{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"slider","type":"registry:ui","title":"Slider","description":"Pick a value or a range by dragging a thumb.","dependencies":["radix-ui"],"registryDependencies":["https://dashral.com/r/utils.json","https://dashral.com/r/field.json"],"files":[{"path":"registry/dashral/slider.tsx","type":"registry:file","target":"components/dashral/slider.tsx","content":"\"use client\"\n\nimport * as React from \"react\"\nimport { Slider as SliderPrimitive } from \"radix-ui\"\n\nimport { cn } from \"./lib/utils\"\nimport { FieldWrapper, splitFieldProps, useFieldControl, type FieldClassNames, type FieldOwnProps } from \"./field\"\n\ntype ControlColor = \"primary\" | \"neutral\" | \"info\" | \"success\" | \"warning\" | \"destructive\" | \"highlight\"\n\n// Track, filled range, and the thumb's border and halo (on hover and focus), all in the slider's color. Every class is\n// written out in full so Tailwind finds it.\nconst colors: Record<ControlColor, { track: string; range: string; thumb: string }> = {\n  primary: { track: \"bg-primary/15\", range: \"bg-primary\", thumb: \"border-primary hover:ring-primary/20 focus-visible:ring-primary/30\" },\n  neutral: { track: \"bg-foreground/10\", range: \"bg-foreground\", thumb: \"border-foreground hover:ring-foreground/15 focus-visible:ring-foreground/25\" },\n  info: { track: \"bg-info/15\", range: \"bg-info\", thumb: \"border-info hover:ring-info/20 focus-visible:ring-info/30\" },\n  success: { track: \"bg-success/15\", range: \"bg-success\", thumb: \"border-success hover:ring-success/20 focus-visible:ring-success/30\" },\n  warning: { track: \"bg-warning/20\", range: \"bg-warning\", thumb: \"border-warning hover:ring-warning/25 focus-visible:ring-warning/35\" },\n  destructive: { track: \"bg-destructive/15\", range: \"bg-destructive\", thumb: \"border-destructive hover:ring-destructive/20 focus-visible:ring-destructive/30\" },\n  highlight: { track: \"bg-highlight/15\", range: \"bg-highlight\", thumb: \"border-highlight hover:ring-highlight/20 focus-visible:ring-highlight/30\" },\n}\n\ntype SliderProps = Omit<React.ComponentProps<typeof SliderPrimitive.Root>, \"color\"> &\n  FieldOwnProps & {\n    /** The filled part and the thumbs. */\n    color?: ControlColor\n    /** Each thumb's accessible name, e.g. [\"Minimum price\", \"Maximum price\"] for a range. */\n    thumbLabels?: string[]\n    classNames?: FieldClassNames & { track?: string; range?: string; thumb?: string }\n  }\n\n/** A value (or, with two values, a range) picked by dragging. Give it a label and it becomes a whole field. */\nfunction Slider(props: SliderProps) {\n  const [field, control] = splitFieldProps(props)\n  return (\n    <FieldWrapper {...field} group>\n      <SliderControl {...control} />\n    </FieldWrapper>\n  )\n}\n\nfunction SliderControl({\n  className,\n  classNames,\n  color = \"primary\",\n  thumbLabels,\n  defaultValue,\n  value,\n  min = 0,\n  max = 100,\n  ...rest\n}: Omit<SliderProps, keyof FieldOwnProps>) {\n  const { \"aria-label\": ariaLabel, \"aria-labelledby\": labelledBy, \"aria-describedby\": describedBy, \"aria-invalid\": _invalid, ...props } =\n    useFieldControl(rest)\n  // One thumb per value — pass two values for a range slider.\n  const thumbs = React.useMemo(\n    () => (Array.isArray(value) ? value : Array.isArray(defaultValue) ? defaultValue : [min]),\n    [value, defaultValue, min]\n  )\n  const tone = colors[color]\n\n  return (\n    <SliderPrimitive.Root\n      data-slot=\"slider\"\n      defaultValue={defaultValue}\n      value={value}\n      min={min}\n      max={max}\n      className={cn(\n        \"relative flex w-full touch-none items-center select-none data-[disabled]:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col\",\n        className\n      )}\n      {...props}\n    >\n      <SliderPrimitive.Track\n        data-slot=\"slider-track\"\n        className={cn(\n          \"relative grow overflow-hidden rounded-full data-[orientation=horizontal]:h-1.5 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5\",\n          tone.track,\n          classNames?.track\n        )}\n      >\n        <SliderPrimitive.Range\n          data-slot=\"slider-range\"\n          className={cn(\"absolute data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full\", tone.range, classNames?.range)}\n        />\n      </SliderPrimitive.Track>\n      {thumbs.map((_, index) => (\n        <SliderPrimitive.Thumb\n          data-slot=\"slider-thumb\"\n          key={index}\n          // The thumbs are what's focused, so they carry the name: thumbLabels for a range, else the label or aria-label.\n          aria-label={thumbLabels?.[index] ?? (labelledBy ? undefined : ariaLabel)}\n          aria-labelledby={thumbLabels?.[index] ? undefined : labelledBy}\n          aria-describedby={describedBy}\n          className={cn(\n            \"block size-4 shrink-0 rounded-full border bg-background shadow-sm transition-[color,box-shadow,scale] duration-(--duration-fast) ease-spring active:scale-115 motion-reduce:active:scale-100 hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50\",\n            tone.thumb,\n            classNames?.thumb\n          )}\n        />\n      ))}\n    </SliderPrimitive.Root>\n  )\n}\n\nexport { Slider, type SliderProps }\n"}],"cssVars":{"theme":{"color-info":"var(--info)","color-info-foreground":"var(--info-foreground)","color-info-text":"var(--info-text)","color-success":"var(--success)","color-success-foreground":"var(--success-foreground)","color-success-text":"var(--success-text)","color-warning":"var(--warning)","color-warning-foreground":"var(--warning-foreground)","color-warning-text":"var(--warning-text)","color-highlight":"var(--highlight)","color-highlight-foreground":"var(--highlight-foreground)","color-highlight-text":"var(--highlight-text)","ease-standard":"var(--ease-standard)","ease-enter":"var(--ease-enter)","ease-exit":"var(--ease-exit)","ease-spring":"var(--ease-spring)"},"light":{"info":"oklch(0.5 0.134 242.749)","info-foreground":"oklch(0.985 0 0)","info-text":"oklch(0.443 0.11 240.79)","success":"oklch(0.508 0.118 165.612)","success-foreground":"oklch(0.985 0 0)","success-text":"oklch(0.432 0.095 166.913)","warning":"#f59200","warning-foreground":"oklch(0.3 0.07 60)","warning-text":"#964e00","highlight":"#b8008c","highlight-foreground":"oklch(0.985 0 0)","highlight-text":"#a3007b","duration-fast":"160ms","duration-standard":"240ms","duration-considered":"480ms","ease-standard":"cubic-bezier(0.2, 0, 0, 1)","ease-enter":"cubic-bezier(0, 0, 0, 1)","ease-exit":"cubic-bezier(0.3, 0, 1, 1)","ease-spring":"linear(0, 0.071 4%, 0.234 8%, 0.433 12%, 0.626 17%, 0.791 21%, 0.917 25%, 1.004 29%, 1.055 33%, 1.079 38%, 1.083 42%, 1.075 46%, 1.06 50%, 1.043 54%, 1.027 58%, 1.015 62%, 1.005 67%, 0.998 71%, 0.995 75%, 0.993 79%, 0.993 83%, 0.994 88%, 0.995 92%, 0.997 96%, 1)"},"dark":{"info":"oklch(0.685 0.169 237.323)","info-foreground":"oklch(0.2 0 0)","info-text":"oklch(0.746 0.16 232.661)","success":"oklch(0.696 0.17 162.48)","success-foreground":"oklch(0.2 0.04 160)","success-text":"oklch(0.765 0.177 163.223)","warning":"#f59200","warning-foreground":"oklch(0.25 0.06 60)","warning-text":"#ffba42","highlight":"#ff2ecf","highlight-foreground":"oklch(0.2 0 0)","highlight-text":"#ff75df"}}}