You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
87 lines
2.1 KiB
87 lines
2.1 KiB
import { useId, useState } from "react";
|
|
import * as SliderPrimitive from "@radix-ui/react-slider";
|
|
import { cn } from "@core/utils/cn.ts";
|
|
|
|
export interface SliderProps {
|
|
value: number[];
|
|
step?: number;
|
|
min?: number;
|
|
max: number;
|
|
onValueChange?: (value: number[]) => void;
|
|
onValueCommit?: (value: number[]) => void;
|
|
disabled?: boolean;
|
|
className?: string;
|
|
trackClassName?: string;
|
|
rangeClassName?: string;
|
|
thumbClassName?: string;
|
|
}
|
|
|
|
export function Slider({
|
|
value,
|
|
step = 1,
|
|
min = 0,
|
|
max,
|
|
onValueChange,
|
|
onValueCommit,
|
|
disabled = false,
|
|
className,
|
|
trackClassName,
|
|
rangeClassName,
|
|
thumbClassName,
|
|
...props
|
|
}: SliderProps) {
|
|
const [internalValue, setInternalValue] = useState<number[]>(value);
|
|
const isControlled = value !== undefined;
|
|
const currentValue = isControlled ? value! : internalValue;
|
|
const id = useId();
|
|
|
|
const handleValueChange = (newValue: number[]) => {
|
|
if (!isControlled) setInternalValue(newValue);
|
|
onValueChange?.(newValue);
|
|
};
|
|
|
|
const handleValueCommit = (newValue: number[]) => {
|
|
onValueCommit?.(newValue);
|
|
};
|
|
|
|
return (
|
|
<SliderPrimitive.Root
|
|
className={cn(
|
|
"relative flex items-center select-none touch-none",
|
|
className,
|
|
)}
|
|
value={currentValue}
|
|
step={step}
|
|
min={min}
|
|
max={max}
|
|
disabled={disabled}
|
|
onValueChange={handleValueChange}
|
|
onValueCommit={handleValueCommit}
|
|
{...props}
|
|
>
|
|
<SliderPrimitive.Track
|
|
className={cn(
|
|
"relative h-2 flex-1 rounded-full bg-slate-200",
|
|
trackClassName,
|
|
)}
|
|
>
|
|
<SliderPrimitive.Range
|
|
className={cn(
|
|
"absolute h-full rounded-full bg-blue-500",
|
|
rangeClassName,
|
|
)}
|
|
/>
|
|
</SliderPrimitive.Track>
|
|
{currentValue.map((_, i) => (
|
|
<SliderPrimitive.Thumb
|
|
key={`${id}-thumb-${i}`}
|
|
className={cn(
|
|
"block w-4 h-4 rounded-full bg-white border border-slate-400 shadow-md",
|
|
thumbClassName,
|
|
)}
|
|
aria-label={`Thumb ${i + 1}`}
|
|
/>
|
|
))}
|
|
</SliderPrimitive.Root>
|
|
);
|
|
}
|
|
|