2025-08-04 17:45:44 +02:00
|
|
|
import { Slider as SliderPrimitive } from "radix-ui";
|
2025-08-28 18:27:07 +02:00
|
|
|
import * as React from "react";
|
2025-08-04 17:45:44 +02:00
|
|
|
|
|
|
|
|
import { cn } from "~/lib/utils";
|
|
|
|
|
|
|
|
|
|
interface SliderProps
|
2025-08-28 18:27:07 +02:00
|
|
|
extends React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root> {
|
|
|
|
|
rangeClassName?: string;
|
|
|
|
|
thumbClassName?: string;
|
2025-08-04 17:45:44 +02:00
|
|
|
}
|
|
|
|
|
function Slider({
|
2025-08-28 18:27:07 +02:00
|
|
|
className,
|
|
|
|
|
thumbClassName,
|
|
|
|
|
rangeClassName,
|
|
|
|
|
defaultValue,
|
|
|
|
|
value,
|
|
|
|
|
min = 0,
|
|
|
|
|
max = 100,
|
|
|
|
|
...props
|
2025-08-04 17:45:44 +02:00
|
|
|
}: React.ComponentProps<typeof SliderPrimitive.Root> & SliderProps) {
|
2025-09-01 16:48:03 +02:00
|
|
|
const _values = React.useMemo(() => {
|
|
|
|
|
if (Array.isArray(value)) return value;
|
|
|
|
|
if (Array.isArray(defaultValue)) return defaultValue;
|
|
|
|
|
return [min, max];
|
|
|
|
|
}, [value, defaultValue, min, max]);
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
return (
|
|
|
|
|
<SliderPrimitive.Root
|
|
|
|
|
className={cn(
|
2026-01-16 17:11:53 +01:00
|
|
|
"relative flex w-full touch-none select-none items-center data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col data-disabled:opacity-50",
|
2025-08-28 18:27:07 +02:00
|
|
|
className,
|
|
|
|
|
)}
|
2025-08-29 16:18:32 +02:00
|
|
|
data-slot="slider"
|
|
|
|
|
defaultValue={defaultValue}
|
|
|
|
|
max={max}
|
|
|
|
|
min={min}
|
|
|
|
|
value={value}
|
2025-08-28 18:27:07 +02:00
|
|
|
{...props}
|
|
|
|
|
>
|
|
|
|
|
<SliderPrimitive.Track
|
|
|
|
|
className={cn(
|
2026-01-16 17:11:53 +01:00
|
|
|
"relative grow cursor-pointer overflow-hidden rounded-full bg-muted data-[orientation=horizontal]:h-1.5 data-[orientation=vertical]:h-full data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-1.5",
|
2025-08-28 18:27:07 +02:00
|
|
|
)}
|
2025-08-29 16:18:32 +02:00
|
|
|
data-slot="slider-track"
|
2025-08-28 18:27:07 +02:00
|
|
|
>
|
|
|
|
|
<SliderPrimitive.Range
|
|
|
|
|
className={cn(
|
2025-10-10 16:18:43 +02:00
|
|
|
"absolute bg-primary data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full",
|
2025-08-28 18:27:07 +02:00
|
|
|
rangeClassName,
|
|
|
|
|
)}
|
2025-08-29 16:18:32 +02:00
|
|
|
data-slot="slider-range"
|
2025-08-28 18:27:07 +02:00
|
|
|
/>
|
|
|
|
|
</SliderPrimitive.Track>
|
|
|
|
|
{Array.from({ length: _values.length }, (_, index) => (
|
|
|
|
|
<SliderPrimitive.Thumb
|
|
|
|
|
className={cn(
|
2026-01-16 17:11:53 +01:00
|
|
|
"block size-4 shrink-0 cursor-pointer rounded-full border border-primary bg-background shadow-sm ring-ring/50 transition-[color,box-shadow] hover:ring-4 focus-visible:outline-hidden focus-visible:ring-4 disabled:pointer-events-none disabled:opacity-50",
|
2025-08-28 18:27:07 +02:00
|
|
|
thumbClassName,
|
|
|
|
|
)}
|
2025-08-29 16:18:32 +02:00
|
|
|
data-slot="slider-thumb"
|
2025-10-28 11:55:01 +01:00
|
|
|
// biome-ignore lint/suspicious/noArrayIndexKey: <index is safe here>
|
2025-08-29 16:18:32 +02:00
|
|
|
key={index}
|
2025-08-28 18:27:07 +02:00
|
|
|
/>
|
|
|
|
|
))}
|
|
|
|
|
</SliderPrimitive.Root>
|
|
|
|
|
);
|
2025-08-04 17:45:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export { Slider };
|