{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "slider",
  "title": "Slider",
  "dependencies": [
    "@base-ui/react"
  ],
  "registryDependencies": [
    "https://ui.hotfix.jobs/r/input.json",
    "https://ui.hotfix.jobs/r/tokens.json",
    "https://ui.hotfix.jobs/r/utils.json"
  ],
  "files": [
    {
      "path": "registry/components/ui/slider.tsx",
      "content": "\"use client\";\n\nimport { Slider as SliderPrimitive } from \"@base-ui/react/slider\";\nimport * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport { Input } from \"@/components/ui/input\";\n\nexport interface SliderProps extends SliderPrimitive.Root.Props {\n  /** Show a small numeric Input to the left, wired to values[0]. Range mode only. */\n  showStartInput?: boolean;\n  /** Show a small numeric Input to the right, wired to values[1]. Range mode only. */\n  showEndInput?: boolean;\n  /** Accessible name for one thumb, or one name per range thumb. */\n  ariaLabel?: string | string[];\n}\n\nexport function Slider({\n  className,\n  children,\n  defaultValue,\n  value,\n  min = 0,\n  max = 100,\n  step = 1,\n  disabled,\n  showStartInput,\n  showEndInput,\n  ariaLabel,\n  onValueChange,\n  ...props\n}: SliderProps): React.ReactElement {\n  const arrayFrom = React.useCallback((v: number | readonly number[] | undefined): number[] => {\n    if (v === undefined) return [min];\n    return Array.isArray(v) ? [...v] : [v as number];\n  }, [min]);\n\n  const [uncontrolled, setUncontrolled] = React.useState<number[]>(() =>\n    arrayFrom(defaultValue),\n  );\n  const isControlled = value !== undefined;\n  const values = isControlled ? arrayFrom(value) : uncontrolled;\n  const isRange = values.length >= 2;\n\n  const updateAt = React.useCallback(\n    (index: number, next: number) => {\n      const clamped = Math.max(min, Math.min(max, next));\n      const nextValues = values.slice();\n      nextValues[index] = clamped;\n      if (isRange) {\n        if (index === 0 && nextValues[0] > nextValues[1]) nextValues[0] = nextValues[1];\n        if (index === 1 && nextValues[1] < nextValues[0]) nextValues[1] = nextValues[0];\n      }\n      if (!isControlled) setUncontrolled(nextValues);\n      onValueChange?.(isRange ? nextValues : nextValues[0], {} as never);\n    },\n    [values, min, max, isRange, isControlled, onValueChange],\n  );\n\n  const slider = (\n    <SliderPrimitive.Root\n      className={cn(\n        \"flex flex-col gap-2 data-[orientation=horizontal]:w-full flex-1\",\n        \"data-[orientation=vertical]:flex-row data-[orientation=vertical]:gap-3\",\n        className,\n      )}\n      defaultValue={defaultValue}\n      max={max}\n      min={min}\n      step={step}\n      thumbAlignment=\"edge\"\n      value={value}\n      disabled={disabled}\n      onValueChange={onValueChange}\n      {...props}\n    >\n      {children}\n      <SliderPrimitive.Control\n        className=\"flex touch-none select-none data-disabled:pointer-events-none data-[orientation=horizontal]:w-full data-[orientation=horizontal]:min-w-44 data-disabled:opacity-50 items-center\"\n        data-slot=\"slider-control\"\n      >\n        <SliderPrimitive.Track\n          className=\"relative grow select-none rounded-full bg-fill-2 data-[orientation=horizontal]:h-1.5 data-[orientation=horizontal]:w-full\"\n          data-slot=\"slider-track\"\n        >\n          <SliderPrimitive.Indicator\n            className=\"select-none rounded-full bg-primary\"\n            data-slot=\"slider-indicator\"\n          />\n          {Array.from({ length: values.length }, (_, index) => (\n            <SliderPrimitive.Thumb\n              className={cn(\n                \"block size-3.5 shrink-0 select-none rounded-full bg-primary shadow-[var(--shadow-card)] outline-none\",\n                \"transition-transform duration-[var(--duration-state)] ease-[var(--ease-standard)]\",\n                \"hover:scale-110 data-dragging:scale-110\",\n                \"has-focus-visible:outline has-focus-visible:outline-1 has-focus-visible:outline-[var(--focus-ring-color)] has-focus-visible:outline-offset-2\",\n              )}\n              data-slot=\"slider-thumb\"\n              getAriaLabel={(thumbIndex) =>\n                Array.isArray(ariaLabel)\n                  ? (ariaLabel[thumbIndex] ?? `Value ${thumbIndex + 1}`)\n                  : (ariaLabel ?? (isRange ? `Value ${thumbIndex + 1}` : \"Value\"))\n              }\n              index={index}\n              key={String(index)}\n            />\n          ))}\n        </SliderPrimitive.Track>\n      </SliderPrimitive.Control>\n    </SliderPrimitive.Root>\n  );\n\n  const showAnyInput = isRange && (showStartInput || showEndInput);\n  if (!showAnyInput) return slider;\n\n  return (\n    <div className=\"flex items-center gap-3 w-full\" data-slot=\"slider-with-inputs\">\n      {showStartInput && (\n        <div className=\"w-16 shrink-0\">\n          <Input\n            size=\"sm\"\n            type=\"number\"\n            value={values[0]}\n            min={min}\n            max={max}\n            step={step}\n            disabled={disabled}\n            onChange={(e) => {\n              const n = Number((e.target as HTMLInputElement).value);\n              if (!Number.isNaN(n)) updateAt(0, n);\n            }}\n            aria-label=\"Start value\"\n          />\n        </div>\n      )}\n      {slider}\n      {showEndInput && (\n        <div className=\"w-16 shrink-0\">\n          <Input\n            size=\"sm\"\n            type=\"number\"\n            value={values[1]}\n            min={min}\n            max={max}\n            step={step}\n            disabled={disabled}\n            onChange={(e) => {\n              const n = Number((e.target as HTMLInputElement).value);\n              if (!Number.isNaN(n)) updateAt(1, n);\n            }}\n            aria-label=\"End value\"\n          />\n        </div>\n      )}\n    </div>\n  );\n}\n\nexport function SliderValue({\n  className,\n  ...props\n}: SliderPrimitive.Value.Props): React.ReactElement {\n  return (\n    <SliderPrimitive.Value\n      className={cn(\n        \"block text-end text-small tabular-nums text-ink self-end\",\n        className,\n      )}\n      data-slot=\"slider-value\"\n      {...props}\n    />\n  );\n}\n\nexport { SliderPrimitive };\n",
      "type": "registry:ui",
      "target": "components/ui/slider.tsx"
    }
  ],
  "type": "registry:ui"
}