84 lines
2.0 KiB
TypeScript
84 lines
2.0 KiB
TypeScript
import * as ProgressPrimitive from "@radix-ui/react-progress";
|
|
import { forwardRef, type ComponentPropsWithoutRef, type ElementRef } from "react";
|
|
|
|
import {
|
|
progressIndicatorVariants,
|
|
progressVariants
|
|
} from "./progress.variants";
|
|
import { cn } from "../lib/cn";
|
|
import type { VariantProps } from "../lib/cva";
|
|
import { createDataAttributes, createSlot } from "../lib/contracts";
|
|
|
|
function clampValue(value: number, max: number) {
|
|
return Math.min(Math.max(value, 0), max);
|
|
}
|
|
|
|
function getState(value: number | null | undefined, max: number) {
|
|
if (value == null) {
|
|
return "indeterminate";
|
|
}
|
|
|
|
return clampValue(value, max) >= max ? "complete" : "loading";
|
|
}
|
|
|
|
function getIndicatorWidth(value: number | null | undefined, max: number) {
|
|
if (value == null) {
|
|
return "38%";
|
|
}
|
|
|
|
return `${(clampValue(value, max) / max) * 100}%`;
|
|
}
|
|
|
|
export type ProgressProps = ComponentPropsWithoutRef<typeof ProgressPrimitive.Root> &
|
|
VariantProps<typeof progressVariants> &
|
|
VariantProps<typeof progressIndicatorVariants>;
|
|
|
|
export const Progress = forwardRef<
|
|
ElementRef<typeof ProgressPrimitive.Root>,
|
|
ProgressProps
|
|
>(function Progress(
|
|
{
|
|
className,
|
|
max = 100,
|
|
size,
|
|
tone,
|
|
value,
|
|
variant,
|
|
...props
|
|
},
|
|
ref
|
|
) {
|
|
const resolvedMax = max > 0 ? max : 100;
|
|
const state = getState(value, resolvedMax);
|
|
|
|
return (
|
|
<ProgressPrimitive.Root
|
|
{...props}
|
|
{...createSlot("root")}
|
|
{...createDataAttributes({
|
|
size,
|
|
state,
|
|
tone,
|
|
variant
|
|
})}
|
|
className={cn(progressVariants({ size, tone }), className)}
|
|
max={resolvedMax}
|
|
ref={ref}
|
|
value={value ?? undefined}
|
|
>
|
|
<ProgressPrimitive.Indicator
|
|
{...createSlot("indicator")}
|
|
{...createDataAttributes({
|
|
size,
|
|
state,
|
|
variant
|
|
})}
|
|
className={cn(progressIndicatorVariants({ variant }))}
|
|
style={{
|
|
width: getIndicatorWidth(value, resolvedMax)
|
|
}}
|
|
/>
|
|
</ProgressPrimitive.Root>
|
|
);
|
|
});
|