{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "slider",
  "title": "Slider",
  "description": "A slider component.",
  "dependencies": [
    "class-variance-authority"
  ],
  "files": [
    {
      "path": "registry/default/slider/slider.tsx",
      "content": "import * as React from \"react\";\nimport { Slider as BaseSlider } from \"@base-ui/react/slider\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst sliderVariants = cva(\n  \"relative w-full touch-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-60 data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col \",\n  {\n    variants: {\n      variant: {\n        default: \"\",\n        contained: \"\",\n        squareThumb: \"\",\n      },\n    },\n    defaultVariants: {\n      variant: \"default\",\n    },\n  },\n);\n\nconst sliderTrackVariants = cva(\n  \"bg-muted flex flex-1 ring-border/60 size-[inherit] min-size-[inherit] ring-1 relative grow rounded-full data-[orientation=horizontal]:h-3 data-[orientation=horizontal]:w-full data-[orientation=vertical]:min-h-full data-[orientation=vertical]:w-3\",\n  {\n    variants: {\n      variant: {\n        default: \"\",\n        contained:\n          \"data-[orientation=horizontal]:h-6 data-[orientation=vertical]:w-6 rounded-full \",\n        squareThumb: \"\",\n      },\n    },\n    defaultVariants: {\n      variant: \"default\",\n    },\n  },\n);\n\nconst sliderIndicatorVariants = cva(\n  \"bg-primary absolute rounded-full shadow-[0_1px_3px_0_oklch(0.18_0_0_/_0.1)] data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full\",\n  {\n    variants: {\n      variant: {\n        default: \"\",\n        contained:\n          \"rounded-full data-[orientation=vertical]:rounded-t-none data-[orientation=horizontal]:rounded-r-none\",\n        squareThumb: \"\",\n      },\n    },\n    defaultVariants: {\n      variant: \"default\",\n    },\n  },\n);\n\nconst sliderThumbVariants = cva(\n  \"bg-background border-primary relative block size-5 shrink-0 rounded-full border-2 shadow-[0_2px_4px_0_oklch(0.18_0_0_/_0.15)] transition-[box-shadow] duration-200 hover:shadow-[0_3px_8px_0_oklch(0.18_0_0_/_0.2)] has-[:focus-visible]:outline-hidden has-[:focus-visible]:z-10 has-[:focus-visible]:ring-2 has-[:focus-visible]:ring-ring has-[:focus-visible]:ring-offset-2 has-[:focus-visible]:ring-offset-background\",\n  {\n    variants: {\n      variant: {\n        default: \"\",\n        contained:\n          \"h-full w-6 bg-primary border-none hover:shadow-none shadow-none rounded-full data-[orientation=vertical]:h-6 data-[orientation=vertical]:w-full after:bg-primary-foreground flex items-center justify-center after:size-[60%]  after:rounded-full  after:origin-center data-[dragging]:after:scale-85 after:transition-transform after:ease-out after:duration-100 after:shadow-[0_2px_4px_0_oklch(0.18_0_0_/_0.15)]\",\n        squareThumb:\n          \"h-5 w-2.5 bg-card border-1 border-border/70 rounded-[.125rem] data-[orientation=vertical]:h-2.5 data-[orientation=vertical]:w-5\",\n      },\n    },\n    defaultVariants: {\n      variant: \"default\",\n    },\n  },\n);\n\nexport interface SliderProps\n  extends\n    React.ComponentProps<typeof BaseSlider.Root>,\n    VariantProps<typeof sliderVariants> {\n  showSteps?: boolean;\n  getAriaLabel?: ((index: number) => string) | null;\n}\n\nfunction Slider({\n  className,\n  children,\n  defaultValue,\n  value,\n  min = 0,\n  max = 100,\n  variant,\n  showSteps = false,\n  getAriaLabel,\n  ...props\n}: SliderProps) {\n  const values = React.useMemo(() => {\n    if (value !== undefined) {\n      return Array.isArray(value) ? value : [value];\n    }\n    if (defaultValue !== undefined) {\n      return Array.isArray(defaultValue) ? defaultValue : [defaultValue];\n    }\n    return [min];\n  }, [value, defaultValue, min]);\n\n  const isRange = values.length > 1;\n\n  const steps = React.useMemo(() => {\n    if (!showSteps) return [];\n    const step = props.step ?? 1;\n    const stepCount = Math.floor((max - min) / step) + 1;\n    return Array.from({ length: stepCount }, (_, i) => min + i * step);\n  }, [showSteps, props.step, min, max]);\n\n  return (\n    <BaseSlider.Root\n      data-slot=\"slider\"\n      defaultValue={defaultValue}\n      value={value}\n      min={min}\n      max={max}\n      className={cn(sliderVariants({ variant }), className)}\n      thumbAlignment={variant === \"contained\" ? \"edge\" : \"center\"}\n      // Drags along the slider's axis are the slider's, so a Base UI drawer\n      // or toast doesn't swipe; across it, a drawer still can.\n      data-base-ui-swipe-ignore={props.orientation === \"vertical\" ? \"y\" : \"x\"}\n      {...props}\n    >\n      {children}\n      <BaseSlider.Control\n        data-slot=\"slider-control\"\n        className=\"flex flex-1 items-center data-[orientation=horizontal]:py-1 data-[orientation=vertical]:min-h-full data-[orientation=vertical]:flex-col data-[orientation=vertical]:justify-center data-[orientation=vertical]:px-1\"\n      >\n        <BaseSlider.Track\n          data-slot=\"slider-track\"\n          className={cn(sliderTrackVariants({ variant }))}\n        >\n          <BaseSlider.Indicator\n            data-slot=\"slider-indicator\"\n            className={cn(\n              sliderIndicatorVariants({ variant }),\n              isRange && \"rounded-none\",\n            )}\n          />\n\n          {showSteps &&\n            steps.map((step, index) => {\n              // Skip first and last step when using center alignment\n              if (\n                variant !== \"contained\" &&\n                (index === 0 || index === steps.length - 1)\n              ) {\n                return null;\n              }\n\n              const percentage = ((step - min) / (max - min)) * 100;\n\n              // Contained variant uses edge alignment, so offset by half the thumb width.\n              const isContained = variant === \"contained\";\n              const thumbWidth = isContained ? 24 : 0; // w-6 = 24px for contained variant\n\n              return (\n                <div\n                  key={step}\n                  className=\"bg-border pointer-events-none absolute size-1.5 rounded-full\"\n                  data-orientation={props.orientation}\n                  style={\n                    props.orientation === \"vertical\"\n                      ? isContained\n                        ? {\n                            bottom: `calc(${thumbWidth / 2}px + ${percentage}% * (100% - ${thumbWidth}px) / 100%)`,\n                            left: \"50%\",\n                            transform: \"translate(-50%, 50%)\",\n                          }\n                        : {\n                            bottom: `${percentage}%`,\n                            left: \"50%\",\n                            transform: \"translate(-50%, 50%)\",\n                          }\n                      : isContained\n                        ? {\n                            left: `calc(${thumbWidth / 2}px + ${percentage}% * (100% - ${thumbWidth}px) / 100%)`,\n                            top: \"50%\",\n                            transform: \"translate(-50%, -50%)\",\n                          }\n                        : {\n                            left: `${percentage}%`,\n                            top: \"50%\",\n                            transform: \"translate(-50%, -50%)\",\n                          }\n                  }\n                />\n              );\n            })}\n\n          {values.map((_, index) => (\n            <BaseSlider.Thumb\n              data-slot=\"slider-thumb\"\n              data-orientation={props.orientation}\n              key={index}\n              index={index}\n              getAriaLabel={getAriaLabel}\n              className={cn(sliderThumbVariants({ variant }))}\n            />\n          ))}\n        </BaseSlider.Track>\n      </BaseSlider.Control>\n    </BaseSlider.Root>\n  );\n}\n\nfunction SliderValue({\n  className,\n  children,\n  ...props\n}: React.ComponentProps<typeof BaseSlider.Value>) {\n  return (\n    <BaseSlider.Value\n      data-slot=\"slider-value\"\n      className={cn(\"text-foreground text-sm font-medium\", className)}\n      {...props}\n    >\n      {children}\n    </BaseSlider.Value>\n  );\n}\n\nfunction SliderLabel({ className, ...props }: BaseSlider.Label.Props) {\n  return (\n    <BaseSlider.Label\n      data-slot=\"slider-label\"\n      className={cn(\n        \"text-foreground text-sm leading-5 font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-60 peer-disabled:cursor-not-allowed peer-disabled:opacity-60\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nexport { Slider, SliderValue, SliderLabel };\n",
      "type": "registry:ui",
      "target": "components/ui/cubby-ui/slider.tsx"
    }
  ],
  "type": "registry:ui"
}