{"$schema":"https://ui.shadcn.com/schema/registry-item.json","author":"Eduardo Calvo <edu@smoothui.dev>","css":{},"dependencies":["@base-ui/react","motion"],"description":"Animated Slider primitive for SmoothUI with spring thumb press feedback.","devDependencies":[],"files":[{"content":"\"use client\";\n\nimport { Slider as SliderPrimitive } from \"@base-ui/react/slider\";\nimport { cn } from \"@/lib/utils\";\nimport { motion, useReducedMotion } from \"motion/react\";\nimport type { ComponentProps } from \"react\";\nimport { PRESS_TRANSITION, SPRING_SNAPPY } from \"@/components/smoothui/lib/animation\";\n\nexport type SliderRootProps = ComponentProps<typeof SliderPrimitive.Root> & {\n  className?: string;\n};\n\nexport type SliderControlProps = ComponentProps<\n  typeof SliderPrimitive.Control\n> & {\n  className?: string;\n};\n\nexport type SliderTrackProps = ComponentProps<typeof SliderPrimitive.Track> & {\n  className?: string;\n};\n\nexport type SliderIndicatorProps = ComponentProps<\n  typeof SliderPrimitive.Indicator\n> & {\n  className?: string;\n};\n\nexport type SliderThumbProps = ComponentProps<typeof SliderPrimitive.Thumb> & {\n  className?: string;\n};\n\n/** Convenience single-thumb slider props */\nexport interface SliderProps {\n  \"aria-label\"?: string;\n  className?: string;\n  defaultValue?: number;\n  disabled?: boolean;\n  max?: number;\n  min?: number;\n  onValueChange?: (value: number) => void;\n  step?: number;\n  value?: number;\n}\n\nconst MotionThumb = motion.span;\n\n/**\n * SmoothUI Slider — Base UI twin (default).\n * Compound parts + thin convenience default for single value.\n */\nconst SliderRoot = ({ className, ...props }: SliderRootProps) => (\n  <SliderPrimitive.Root\n    className={cn(\n      // Group dims fill/thumb when disabled — avoid root opacity on a faint track\n      \"group/slider relative flex w-full touch-none select-none items-center\",\n      \"data-disabled:cursor-not-allowed\",\n      className\n    )}\n    data-slot=\"slider\"\n    {...props}\n  />\n);\n\nconst SliderControl = ({ className, ...props }: SliderControlProps) => (\n  <SliderPrimitive.Control\n    className={cn(\"relative flex w-full items-center py-2.5\", className)}\n    data-slot=\"slider-control\"\n    {...props}\n  />\n);\n\nconst SliderTrack = ({ className, ...props }: SliderTrackProps) => (\n  <SliderPrimitive.Track\n    className={cn(\n      // Track must read on transparent dark stages — `input` (15% fg) vanishes;\n      // Prefer a stronger fg tint so empty track stays visible on frame-box.\n      \"relative h-1.5 w-full grow rounded-full bg-foreground/40 group-data-disabled/slider:bg-muted-foreground/55\",\n      className\n    )}\n    data-slot=\"slider-track\"\n    {...props}\n  />\n);\n\nconst SliderIndicator = ({ className, ...props }: SliderIndicatorProps) => (\n  <SliderPrimitive.Indicator\n    className={cn(\n      \"h-full rounded-full bg-brand group-data-disabled/slider:bg-muted-foreground\",\n      className\n    )}\n    data-slot=\"slider-indicator\"\n    {...props}\n  />\n);\n\nconst SliderThumb = ({ className, ...props }: SliderThumbProps) => {\n  const shouldReduceMotion = useReducedMotion();\n  return (\n    <SliderPrimitive.Thumb\n      className={cn(\"block outline-none\", className)}\n      data-slot=\"slider-thumb\"\n      render={\n        <MotionThumb\n          className={cn(\n            // Solid fill so the thumb stays visible on dark preview surfaces\n            \"block size-4 rounded-full border-2 border-brand bg-thumb shadow-sm\",\n            // Focus lands on the hidden <input> child, not the thumb itself\n            \"focus-ring-within\",\n            \"data-disabled:pointer-events-none\",\n            // Never `bg-background` when disabled — matches dark frame-box and vanishes\n            \"group-data-disabled/slider:border-muted-foreground group-data-disabled/slider:bg-muted-foreground\"\n          )}\n          transition={shouldReduceMotion ? { duration: 0 } : SPRING_SNAPPY}\n          whileTap={\n            shouldReduceMotion\n              ? undefined\n              : { scale: 1.12, transition: PRESS_TRANSITION }\n          }\n        />\n      }\n      {...props}\n    />\n  );\n};\n\n/** Thin convenience: single-value slider with Track + Indicator + Thumb. */\nconst Slider = ({\n  \"aria-label\": ariaLabel,\n  className,\n  defaultValue = 50,\n  disabled,\n  max = 100,\n  min = 0,\n  onValueChange,\n  step = 1,\n  value,\n}: SliderProps) => (\n  <SliderRoot\n    className={className}\n    defaultValue={defaultValue}\n    disabled={disabled}\n    max={max}\n    min={min}\n    onValueChange={(next) => {\n      if (typeof next === \"number\") {\n        onValueChange?.(next);\n      }\n    }}\n    step={step}\n    value={value}\n  >\n    <SliderControl>\n      <SliderTrack>\n        <SliderIndicator />\n        <SliderThumb aria-label={ariaLabel ?? \"Value\"} />\n      </SliderTrack>\n    </SliderControl>\n  </SliderRoot>\n);\n\nexport { SliderControl, SliderIndicator, SliderRoot, SliderThumb, SliderTrack };\n\nexport default Slider;\n","path":"index.tsx","target":"components/smoothui/slider/index.tsx","type":"registry:ui"}],"name":"slider","registryDependencies":["https://smoothui.dev/r/lib.json","https://smoothui.dev/r/tokens.json"],"title":"Slider","type":"registry:ui"}