{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "slider",
  "type": "registry:ui",
  "title": "Slider",
  "description": "Single-value range control with branded and plain treatments.",
  "dependencies": [
    "@base-ui/react@^1.7.0"
  ],
  "registryDependencies": [
    "https://control-ui.dev/r/core.json"
  ],
  "files": [
    {
      "path": "src/registry/knob-contracts/range-knobs.ts",
      "target": "@components/control-ui/knob-contracts/range-knobs.ts",
      "type": "registry:component",
      "content": "// Generated from src/registry/sources/control-ui/recipes/range.css by scripts/gen-knob-contracts.ts — run `bun run sync:knobs`.\nexport const rangeKnobs = [\n  \"--cui-range-track-radius\",\n  \"--cui-range-track-background\",\n  \"--cui-range-indicator-radius\",\n  \"--cui-range-indicator-background\",\n  \"--cui-range-thumb-radius\",\n  \"--cui-range-thumb-background\",\n  \"--cui-range-thumb-border-color\",\n  \"--cui-range-thumb-shadow\",\n] as const;\nexport type RangeKnobStyle = Partial<Record<(typeof rangeKnobs)[number], string>>;\n"
    },
    {
      "path": "src/registry/sources/control-ui/recipes/range.css",
      "target": "@components/control-ui/styles/recipes/range.css",
      "type": "registry:file",
      "content": "@layer components {\n  :where([data-control-family=\"range\"][data-slot=\"root\"]) {\n    --cui-range-track-radius: 9999px;\n    --cui-range-track-background: var(--muted);\n    --cui-range-indicator-radius: 9999px;\n    --cui-range-indicator-background: var(--primary);\n    --cui-range-thumb-radius: 9999px;\n    --cui-range-thumb-background: var(--background);\n    --cui-range-thumb-border-color: var(--border);\n    --cui-range-thumb-shadow: var(--shadow-sm);\n    --_range-thumb-border-width: 1px;\n  }\n\n  :where([data-control-family=\"range\"][data-range-kind=\"slider\"][data-slot=\"track\"]),\n  :where([data-control-family=\"range\"][data-range-kind=\"progress\"][data-slot=\"track\"]),\n  :where([data-control-family=\"range\"][data-range-kind=\"meter\"][data-slot=\"track\"]) {\n    border-radius: var(--cui-range-track-radius);\n    background: var(--cui-range-track-background);\n  }\n\n  :where([data-control-family=\"range\"][data-range-kind=\"slider\"][data-slot=\"track\"]) {\n    transition: background-color var(--duration-fast) var(--ease-standard);\n  }\n\n  :where([data-control-family=\"range\"][data-range-kind=\"slider\"][data-slot=\"root\"][data-variant=\"plain\"]) {\n    --cui-range-track-radius: 3px;\n    --cui-range-track-background: oklch(from var(--foreground) l c h / 0.06);\n    --cui-range-indicator-radius: 0px;\n    --cui-range-indicator-background: oklch(from var(--foreground) l c h / 0.14);\n    --cui-range-thumb-radius: 1px;\n    --cui-range-thumb-background: oklch(from var(--foreground) l c h / 0.3);\n    --cui-range-thumb-shadow: none;\n    --_range-thumb-border-width: 0px;\n  }\n\n  :where([data-control-family=\"range\"][data-range-kind=\"slider\"][data-slot=\"track\"][data-dragging]) {\n    background: oklch(from var(--foreground) l c h / 0.1);\n  }\n\n  :where([data-control-family=\"range\"][data-range-kind=\"slider\"][data-slot=\"indicator\"]),\n  :where([data-control-family=\"range\"][data-range-kind=\"progress\"][data-slot=\"indicator\"]),\n  :where([data-control-family=\"range\"][data-range-kind=\"meter\"][data-slot=\"indicator\"]) {\n    height: 100%;\n    border-radius: var(--cui-range-indicator-radius);\n    background: var(--cui-range-indicator-background);\n  }\n\n  :where([data-control-family=\"range\"][data-range-kind=\"slider\"][data-slot=\"indicator\"]) {\n    transition: background-color var(--duration-fast) var(--ease-standard);\n  }\n\n  :where([data-control-family=\"range\"][data-range-kind=\"slider\"][data-slot=\"indicator\"][data-dragging]) {\n    --cui-range-indicator-background: var(--primary);\n    background: var(--cui-range-indicator-background);\n  }\n\n  :where([data-control-family=\"range\"][data-range-kind=\"slider\"][data-slot=\"thumb\"]) {\n    position: relative;\n    border: var(--_range-thumb-border-width) solid var(--cui-range-thumb-border-color);\n    border-radius: var(--cui-range-thumb-radius);\n    background: var(--cui-range-thumb-background);\n    box-shadow: var(--cui-range-thumb-shadow);\n    outline: none;\n    transition-property: scale, background-color, box-shadow, height, width;\n    transition-duration: var(--duration-fast);\n  }\n\n  :where([data-control-family=\"range\"][data-range-kind=\"slider\"][data-slot=\"thumb\"]:focus-visible) {\n    --cui-range-thumb-shadow: var(--shadow-sm);\n  }\n\n  :where([data-control-family=\"range\"][data-range-kind=\"slider\"][data-slot=\"thumb\"]:where(:hover, [data-dragging])) {\n    scale: 1.1;\n  }\n\n  :where([data-control-family=\"range\"][data-range-kind=\"slider\"][data-slot=\"thumb\"][data-dragging]) {\n    box-shadow: var(--shadow-md);\n  }\n\n  :where([data-control-family=\"range\"][data-range-kind=\"slider\"][data-slot=\"thumb\"][data-variant=\"plain\"]) {\n    height: 1rem;\n    width: 0.125rem;\n  }\n\n  :where([data-control-family=\"range\"][data-range-kind=\"slider\"][data-slot=\"thumb\"][data-variant=\"plain\"]:where(:hover, [data-dragging])) {\n    --cui-range-thumb-background: oklch(from var(--foreground) l c h / 0.5);\n    scale: 1;\n  }\n\n  :where([data-control-family=\"range\"][data-range-kind=\"slider\"][data-slot=\"thumb\"][data-variant=\"plain\"][data-dragging]) {\n    --cui-range-thumb-background: oklch(from var(--foreground) l c h / 0.7);\n    height: 1.25rem;\n  }\n\n  :where([data-control-family=\"range\"][data-range-kind=\"slider\"][data-slot=\"tick\"]) {\n    background: oklch(from var(--foreground) l c h / 0.15);\n    transition-property: height, background-color;\n    transition-duration: var(--duration-fast);\n    transition-timing-function: var(--ease-standard);\n  }\n\n  :where([data-control-family=\"range\"][data-range-kind=\"slider\"][data-slot=\"root\"][data-dragging] [data-slot=\"tick\"]) {\n    height: 0.75rem;\n    background: oklch(from var(--foreground) l c h / 0.25);\n  }\n\n  :where([data-control-family=\"range\"][data-range-kind=\"slider\"]:is([data-slot=\"label\"], [data-slot=\"value\"])) {\n    color: var(--muted-foreground);\n    transition-property: color, scale, translate;\n    transition-duration: var(--duration-fast);\n    transition-timing-function: var(--ease-standard);\n  }\n\n  :where([data-control-family=\"range\"][data-range-kind=\"slider\"][data-slot=\"root\"][data-dragging] [data-slot=\"label\"]) {\n    translate: -0.25rem -0.375rem;\n    scale: 0.9;\n  }\n\n  :where([data-control-family=\"range\"][data-range-kind=\"slider\"][data-slot=\"root\"][data-dragging] [data-slot=\"value\"]) {\n    translate: 0.125rem -0.375rem;\n    color: var(--foreground);\n  }\n\n  :where([data-control-family=\"range\"][data-range-kind=\"slider\"][data-slot=\"value\"]) {\n    font-size: var(--text-caption);\n    line-height: calc(var(--spacing) * 3.5);\n    letter-spacing: var(--tracking-tight);\n    font-variant-numeric: tabular-nums;\n  }\n\n  :where([data-control-family=\"range\"][data-range-kind=\"slider\"][data-slot=\"label\"]) {\n    font-size: var(--text-caption);\n    line-height: calc(var(--spacing) * 3.5);\n    letter-spacing: var(--tracking-tight);\n  }\n\n  :where([data-control-family=\"range\"][data-range-kind=\"slider\"][data-slot=\"root\"][data-disabled]) {\n    opacity: 50%;\n  }\n\n  :where([data-control-family=\"range\"][data-range-kind=\"progress\"][data-slot=\"indicator\"]) {\n    transition-property: width;\n    transition-duration: var(--duration-slow);\n    transition-timing-function: var(--ease-emphasized);\n  }\n\n  :where([data-control-family=\"range\"][data-range-kind=\"progress\"][data-slot=\"value\"]) {\n    font-size: var(--text-label);\n    color: var(--muted-foreground);\n    font-variant-numeric: tabular-nums;\n  }\n\n  :where([data-control-family=\"range\"][data-range-kind=\"progress\"][data-slot=\"label\"]) {\n    font-size: var(--text-label);\n    font-weight: var(--font-weight-medium);\n    color: var(--foreground);\n  }\n\n  :where([data-control-family=\"range\"][data-range-kind=\"meter\"][data-slot=\"indicator\"]) {\n    transition-property: width;\n    transition-duration: var(--duration-slow);\n    transition-timing-function: var(--ease-emphasized);\n  }\n\n  :where([data-control-family=\"range\"][data-range-kind=\"meter\"][data-slot=\"value\"]) {\n    font-size: var(--text-label);\n    color: var(--muted-foreground);\n    font-variant-numeric: tabular-nums;\n  }\n\n  :where([data-control-family=\"range\"][data-range-kind=\"meter\"][data-slot=\"label\"]) {\n    font-size: var(--text-label);\n    font-weight: var(--font-weight-medium);\n    color: var(--foreground);\n  }\n}\n\n@property --cui-range-track-radius {\n  syntax: \"<length-percentage>\";\n  inherits: true;\n  initial-value: 0px;\n}\n\n@property --cui-range-track-background {\n  syntax: \"<color>\";\n  inherits: true;\n  initial-value: transparent;\n}\n\n@property --cui-range-indicator-radius {\n  syntax: \"<length-percentage>\";\n  inherits: true;\n  initial-value: 0px;\n}\n\n@property --cui-range-indicator-background {\n  syntax: \"<color>\";\n  inherits: true;\n  initial-value: transparent;\n}\n\n@property --cui-range-thumb-radius {\n  syntax: \"<length-percentage>\";\n  inherits: true;\n  initial-value: 0px;\n}\n\n@property --cui-range-thumb-background {\n  syntax: \"*\";\n  inherits: true;\n  initial-value: transparent;\n}\n\n@property --cui-range-thumb-border-color {\n  syntax: \"<color>\";\n  inherits: true;\n  initial-value: transparent;\n}\n\n@property --cui-range-thumb-shadow {\n  syntax: \"*\";\n  inherits: true;\n  initial-value: none;\n}\n"
    },
    {
      "path": "src/registry/sources/control-ui/ui/slider.tsx",
      "target": "@components/control-ui/ui/slider.tsx",
      "type": "registry:ui",
      "content": "\"use client\";\n\nimport { Slider as SliderPrimitive } from \"@base-ui/react/slider\";\nimport type { CSSProperties } from \"react\";\nimport type { RangeKnobStyle } from \"@/components/control-ui/knob-contracts/range-knobs\";\nimport { cn } from \"@/components/control-ui/lib/cn\";\n\nexport type SliderVariant = \"default\" | \"plain\";\n\nexport type SliderProps = Omit<\n  {\n    variant?: SliderVariant;\n    value?: number;\n    defaultValue?: number;\n    onValueChange?: (value: number) => void;\n    min?: number;\n    max?: number;\n    step?: number;\n    disabled?: boolean;\n    label?: string;\n    showValue?: boolean;\n    formatValue?: (value: number) => string;\n    className?: string;\n    \"aria-label\"?: string;\n  },\n  \"style\"\n> & { style?: CSSProperties & RangeKnobStyle };\n\nconst MAX_VISIBLE_STEP_TICKS = 50;\n\n// skipped when steps are too fine or too coarse to read as marks\nfunction tickPositions(min: number, max: number, step: number | undefined): number[] {\n  if (typeof step !== \"number\" || step <= 0 || !Number.isFinite(step)) return [];\n  const range = max - min;\n  if (range <= 0) return [];\n  const stepCount = Math.round(range / step);\n  if (stepCount <= 1 || stepCount > MAX_VISIBLE_STEP_TICKS) return [];\n  return Array.from({ length: stepCount - 1 }, (_, i) => ((i + 1) / stepCount) * 100);\n}\n\nfunction displaySliderValue(values: readonly number[], formatValue?: (value: number) => string): string | number {\n  const value = values[0];\n  if (value === undefined) return \"\";\n  return formatValue ? formatValue(value) : Math.round(value);\n}\n\nexport function Slider({\n  className,\n  variant = \"default\",\n  label,\n  showValue,\n  formatValue,\n  value,\n  defaultValue,\n  onValueChange,\n  min = 0,\n  max = 100,\n  step,\n  disabled,\n  style,\n  ...props\n}: SliderProps) {\n  const showValueResolved = showValue ?? Boolean(label);\n  const labeled = variant === \"plain\" && (label !== undefined || showValue === true);\n  const ticks = labeled ? tickPositions(min, max, step) : [];\n  const trackStyle = style;\n  const indicatorStyle = style;\n  const thumbStyle = style;\n\n  // explicit, never spread: Base UI reads controlled-ness from `value !== undefined`, and spread can carry `undefined` for tick\n  return (\n    <SliderPrimitive.Root\n      data-control-ui=\"slider\"\n      data-range-kind=\"slider\"\n      data-slot=\"root\"\n      data-control-family=\"range\"\n      data-variant={variant}\n      data-labeled={labeled ? \"true\" : undefined}\n      value={value}\n      defaultValue={defaultValue}\n      min={min}\n      max={max}\n      step={step}\n      disabled={disabled}\n      onValueChange={onValueChange ? (next) => onValueChange(Array.isArray(next) ? next[0] : next) : undefined}\n      className={cn(\n        \"group relative flex w-full cursor-pointer touch-none select-none items-center data-[disabled]:cursor-not-allowed\",\n        className,\n      )}\n      style={style}\n      {...props}\n    >\n      <SliderPrimitive.Control\n        data-control-ui=\"slider\"\n        data-control-family=\"range\"\n        data-range-kind=\"slider\"\n        data-slot=\"control\"\n        className={cn(\"flex w-full items-center\", labeled ? \"h-[1.875rem]\" : \"py-1.5\")}\n      >\n        <SliderPrimitive.Track\n          data-control-ui=\"slider\"\n          data-control-family=\"range\"\n          data-range-kind=\"slider\"\n          data-slot=\"track\"\n          data-variant={variant}\n          className={cn(\"relative w-full grow overflow-hidden\", variant === \"default\" ? \"h-1.5\" : \"h-1.5\", labeled && \"h-full\")}\n          style={trackStyle}\n        >\n          <SliderPrimitive.Indicator\n            data-control-ui=\"slider\"\n            data-control-family=\"range\"\n            data-range-kind=\"slider\"\n            data-slot=\"indicator\"\n            data-variant={variant}\n            style={indicatorStyle}\n          />\n          {ticks.map((pct) => (\n            <span\n              key={pct}\n              aria-hidden\n              data-control-ui=\"slider\"\n              data-control-family=\"range\"\n              data-range-kind=\"slider\"\n              data-slot=\"tick\"\n              className=\"pointer-events-none absolute bottom-0 h-1.5 w-px\"\n              style={{ left: `${pct}%` }}\n            />\n          ))}\n          <SliderPrimitive.Thumb\n            data-control-ui=\"slider\"\n            data-control-family=\"range\"\n            data-range-kind=\"slider\"\n            data-slot=\"thumb\"\n            data-variant={variant}\n            className={cn(\"block\", variant === \"default\" ? \"size-3.5\" : \"after:absolute after:-inset-3 after:content-['']\")}\n            style={thumbStyle}\n          />\n        </SliderPrimitive.Track>\n      </SliderPrimitive.Control>\n      {labeled && (\n        <div className=\"pointer-events-none absolute inset-0 z-10 flex items-center justify-between px-3\">\n          {label ? (\n            <SliderPrimitive.Label\n              data-control-ui=\"slider\"\n              data-control-family=\"range\"\n              data-range-kind=\"slider\"\n              data-slot=\"label\"\n              className=\"select-none\"\n            >\n              {label}\n            </SliderPrimitive.Label>\n          ) : (\n            <span />\n          )}\n          {showValueResolved && (\n            <SliderPrimitive.Value\n              data-control-ui=\"slider\"\n              data-control-family=\"range\"\n              data-range-kind=\"slider\"\n              data-slot=\"value\"\n              className=\"select-none\"\n            >\n              {(_, values) => displaySliderValue(values, formatValue)}\n            </SliderPrimitive.Value>\n          )}\n        </div>\n      )}\n    </SliderPrimitive.Root>\n  );\n}\n"
    }
  ],
  "css": {
    "@import \"../components/control-ui/styles/recipes/range.css\"": {}
  },
  "meta": {}
}
