{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "b-slider",
  "type": "registry:ui",
  "registryDependencies": [],
  "dependencies": ["@base-ui/react", "motion"],
  "devDependencies": [],
  "files": [
    {
      "path": "b-slider.tsx",
      "content": "\"use client\";\n\nimport { Slider as SliderPrimitive } from \"@base-ui/react/slider\";\nimport {\n  animate,\n  type MotionValue,\n  motion,\n  useMotionValue,\n  useReducedMotion,\n  useTransform,\n} from \"motion/react\";\nimport {\n  forwardRef,\n  type ReactNode,\n  useCallback,\n  useEffect,\n  useId,\n  useRef,\n  useState,\n} from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst componentThemeClassName =\n  \"[--ic-background:#ffffff] [--ic-foreground:#111111] [--ic-primary:#111111] [--ic-secondary:#646b75] [--ic-surface-border:#e9edf2] [--ic-border:#e3e7ec] [--ic-card:#ffffff] [--ic-card-foreground:#111111] [--ic-muted:#f5f7fa] [--ic-muted-foreground:#6d7480] [--ic-accent:#f3f5f8] [--color-accent:var(--ic-accent)] [--color-accent-foreground:var(--ic-accent-foreground)] [--ic-accent-foreground:#111111] [--ic-input:#e3e7ec] [--ic-ring:rgba(17,17,17,0.16)] [--ic-destructive:#dc2626] [--ic-paper:#fcfcfd] [--ic-popover-foreground:#111111] [--ic-brand:#0ea5e9] [--ic-brand-soft:#bae6fd] [--ic-shadow-soft:0_18px_38px_-24px_rgba(15,23,42,0.35)] [--ic-chart-1:oklch(0.52_0.19_254)] [--ic-chart-2:oklch(0.74_0.11_232)] [--ic-chart-3:oklch(0.42_0.16_262)] [--ic-chart-4:oklch(0.84_0.07_228)] [--ic-chart-5:oklch(0.62_0.14_240)] [--color-background:var(--ic-background)] [--color-foreground:var(--ic-foreground)] [--color-primary:var(--ic-primary)] [--color-secondary:var(--ic-secondary)] [--color-border:var(--ic-border)] [--color-card:var(--ic-card)] [--color-card-foreground:var(--ic-card-foreground)] [--color-muted:var(--ic-muted)] [--color-muted-foreground:var(--ic-muted-foreground)] [--color-accent:var(--ic-accent)] [--color-accent-foreground:var(--ic-accent-foreground)] [--color-input:var(--ic-input)] [--color-ring:var(--ic-ring)] [--color-destructive:var(--ic-destructive)] [--color-paper:var(--ic-paper)] [--color-popover-foreground:var(--ic-popover-foreground)] [--color-brand:var(--ic-brand)] [--color-brand-soft:var(--ic-brand-soft)] [--color-chart-1:var(--ic-chart-1)] [--color-chart-2:var(--ic-chart-2)] [--color-chart-3:var(--ic-chart-3)] [--color-chart-4:var(--ic-chart-4)] [--color-chart-5:var(--ic-chart-5)] dark:[--ic-background:#111111] dark:[--ic-foreground:#f6f3ec] dark:[--ic-primary:#f6f3ec] dark:[--ic-secondary:#cbc6bb] dark:[--ic-surface-border:#2a2a25] dark:[--ic-border:#2b2a25] dark:[--ic-card:#111111] dark:[--ic-card-foreground:#f6f3ec] dark:[--ic-muted:#171716] dark:[--ic-muted-foreground:#9a958a] dark:[--ic-accent:#1a1a18] [--color-accent:var(--ic-accent)] [--color-accent-foreground:var(--ic-accent-foreground)] dark:[--ic-accent-foreground:#f6f3ec] dark:[--ic-input:#2b2a25] dark:[--ic-ring:rgba(246,243,236,0.18)] dark:[--ic-destructive:#f87171] dark:[--ic-paper:#171716] dark:[--ic-popover-foreground:#f6f3ec] dark:[--ic-brand:#38bdf8] dark:[--ic-brand-soft:#0c4a6e] dark:[--ic-shadow-soft:0_20px_44px_-28px_rgba(0,0,0,0.6)] dark:[--ic-chart-1:oklch(0.68_0.17_250)] dark:[--ic-chart-2:oklch(0.82_0.09_225)] dark:[--ic-chart-3:oklch(0.58_0.15_260)] dark:[--ic-chart-4:oklch(0.75_0.12_235)] dark:[--ic-chart-5:oklch(0.88_0.06_220)]\";\n\nexport interface SliderMark {\n  value: number;\n  label?: string;\n}\n\nexport type SliderSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface SliderProps {\n  value?: number | [number, number];\n  defaultValue?: number | [number, number];\n  min?: number;\n  max?: number;\n  step?: number;\n  onChange?: (value: number | [number, number]) => void;\n  onValueCommit?: (value: number | [number, number]) => void;\n  showValue?: boolean;\n  valueDecimals?: number;\n  formatValue?: (value: number) => string;\n  label?: string;\n  ariaLabel?: string;\n  ariaLabelledBy?: string;\n  marks?: SliderMark[];\n  className?: string;\n  disabled?: boolean;\n  readOnly?: boolean;\n  description?: ReactNode;\n  errorMessage?: ReactNode;\n  invalid?: boolean;\n  ariaDescribedBy?: string;\n  marksInteractive?: boolean;\n  size?: SliderSize;\n  inverted?: boolean;\n  name?: string;\n  id?: string;\n  range?: boolean;\n}\n\nexport const sliderSizeClasses = {\n  sm: {\n    hitAreaHorizontal: \"h-9\",\n    thumb: \"h-3 w-3\",\n    thumbBorder: \"border\",\n    trackInactive: 3,\n    trackActive: 5,\n  },\n  md: {\n    hitAreaHorizontal: \"h-11\",\n    thumb: \"h-4 w-4\",\n    thumbBorder: \"border-[1.5px]\",\n    trackInactive: 4,\n    trackActive: 6,\n  },\n  lg: {\n    hitAreaHorizontal: \"h-14\",\n    thumb: \"h-5 w-5\",\n    thumbBorder: \"border-2\",\n    trackInactive: 5,\n    trackActive: 7,\n  },\n} as const satisfies Record<\n  SliderSize,\n  {\n    hitAreaHorizontal: string;\n    thumb: string;\n    thumbBorder: string;\n    trackInactive: number;\n    trackActive: number;\n  }\n>;\n\nfunction clamp(value: number, min: number, max: number) {\n  return Math.min(Math.max(value, min), max);\n}\n\nfunction getPrecision(value: number) {\n  if (!Number.isFinite(value)) {\n    return 0;\n  }\n\n  const normalized = value.toString().toLowerCase();\n\n  if (normalized.includes(\"e-\")) {\n    const [base, exponent] = normalized.split(\"e-\");\n    return (base.split(\".\")[1]?.length ?? 0) + Number(exponent);\n  }\n\n  return normalized.split(\".\")[1]?.length ?? 0;\n}\n\nfunction snapValue(raw: number, min: number, max: number, step: number) {\n  const safeStep = step > 0 ? step : 1;\n  const precision = Math.max(\n    getPrecision(safeStep),\n    getPrecision(min),\n    getPrecision(max)\n  );\n  const stepped = min + Math.round((raw - min) / safeStep) * safeStep;\n  return clamp(Number(stepped.toFixed(precision)), min, max);\n}\n\nfunction snapRangeValue(\n  raw: readonly [number, number] | number[],\n  min: number,\n  max: number,\n  step: number\n): [number, number] {\n  const first = snapValue(raw[0] ?? min, min, max, step);\n  const second = snapValue(raw[1] ?? max, min, max, step);\n  return first <= second ? [first, second] : [second, first];\n}\n\nfunction formatSliderDisplayValue(\n  value: number | [number, number],\n  options: {\n    formatValue?: (value: number) => string;\n    range?: boolean;\n    valueDecimals?: number;\n  }\n) {\n  const { formatValue, range = false, valueDecimals = 0 } = options;\n\n  if (range && Array.isArray(value)) {\n    const [low, high] = value;\n    const lowText = formatValue ? formatValue(low) : low.toFixed(valueDecimals);\n    const highText = formatValue\n      ? formatValue(high)\n      : high.toFixed(valueDecimals);\n    return `${lowText} – ${highText}`;\n  }\n\n  const numericValue = Array.isArray(value) ? (value[0] ?? 0) : value;\n  return formatValue\n    ? formatValue(numericValue)\n    : numericValue.toFixed(valueDecimals);\n}\n\nfunction resolveSliderAccessibleName({\n  ariaLabel,\n  ariaLabelledBy,\n  label,\n  labelId,\n}: {\n  ariaLabel?: string;\n  ariaLabelledBy?: string;\n  label?: string;\n  labelId?: string;\n}) {\n  if (ariaLabelledBy || label) {\n    return {\n      ariaLabel: undefined,\n      ariaLabelledBy: ariaLabelledBy ?? labelId,\n    };\n  }\n\n  return {\n    ariaLabel: ariaLabel ?? \"Slider\",\n    ariaLabelledBy: undefined,\n  };\n}\n\nfunction resolveSliderFieldMeta({\n  ariaDescribedByProp,\n  description,\n  errorMessage,\n  generatedId,\n  id,\n  invalid,\n}: {\n  ariaDescribedByProp?: string;\n  description?: ReactNode;\n  errorMessage?: ReactNode;\n  generatedId: string;\n  id?: string;\n  invalid?: boolean;\n}) {\n  const sliderId = id ?? generatedId;\n  const descriptionId = description ? `${sliderId}-description` : undefined;\n  const errorId = errorMessage ? `${sliderId}-error` : undefined;\n  const showInvalid = Boolean(invalid) || Boolean(errorMessage);\n\n  return {\n    describedBy: [ariaDescribedByProp, descriptionId, errorId]\n      .filter(Boolean)\n      .join(\" \"),\n    descriptionId,\n    errorId,\n    showInvalid,\n    sliderId,\n  };\n}\n\nfunction resolveBlurTarget(\n  currentTarget: EventTarget & HTMLDivElement,\n  relatedTarget: EventTarget | null\n) {\n  return !currentTarget.contains(relatedTarget as Node | null);\n}\n\nfunction isDocumentRtl() {\n  if (typeof document === \"undefined\") {\n    return false;\n  }\n\n  return document.documentElement.dir === \"rtl\";\n}\n\nfunction valueToProgress(\n  currentValue: number,\n  resolvedMin: number,\n  resolvedMax: number\n) {\n  const span = resolvedMax - resolvedMin;\n  return span === 0 ? 0 : ((currentValue - resolvedMin) / span) * 100;\n}\n\nfunction progressToValue(\n  progress: number,\n  resolvedMin: number,\n  resolvedMax: number,\n  safeStep: number\n) {\n  const span = resolvedMax - resolvedMin;\n  const raw = resolvedMin + (progress / 100) * span;\n  return snapValue(raw, resolvedMin, resolvedMax, safeStep);\n}\n\nfunction resolveInitialSliderValue(\n  controlledValue: number | [number, number] | undefined,\n  defaultValue: number | [number, number] | undefined,\n  range: boolean,\n  resolvedMin: number,\n  resolvedMax: number,\n  safeStep: number,\n  rangeSpan: number\n) {\n  const initial = controlledValue ?? defaultValue ?? (range ? [25, 75] : 50);\n\n  if (range) {\n    const tuple = Array.isArray(initial)\n      ? initial\n      : [resolvedMin + rangeSpan * 0.25, resolvedMin + rangeSpan * 0.75];\n    return snapRangeValue(tuple, resolvedMin, resolvedMax, safeStep);\n  }\n\n  const numeric = Array.isArray(initial) ? (initial[0] ?? 50) : initial;\n  return snapValue(numeric, resolvedMin, resolvedMax, safeStep);\n}\n\nfunction resolveControlledSliderValue(\n  controlledValue: number | [number, number] | undefined,\n  internalValue: number | [number, number],\n  range: boolean,\n  resolvedMin: number,\n  resolvedMax: number,\n  safeStep: number\n) {\n  if (controlledValue === undefined) {\n    return internalValue;\n  }\n\n  if (range) {\n    return snapRangeValue(\n      Array.isArray(controlledValue)\n        ? controlledValue\n        : [controlledValue, controlledValue],\n      resolvedMin,\n      resolvedMax,\n      safeStep\n    );\n  }\n\n  return snapValue(\n    Array.isArray(controlledValue)\n      ? (controlledValue[0] ?? resolvedMin)\n      : controlledValue,\n    resolvedMin,\n    resolvedMax,\n    safeStep\n  );\n}\n\nfunction sliderValuesEqual(\n  current: number | [number, number],\n  next: number | [number, number],\n  range: boolean\n) {\n  if (range) {\n    const currentTuple = Array.isArray(current) ? current : [current, current];\n    const nextTuple = Array.isArray(next) ? next : [next, next];\n    return currentTuple[0] === nextTuple[0] && currentTuple[1] === nextTuple[1];\n  }\n\n  const currentValue = Array.isArray(current) ? (current[0] ?? 0) : current;\n  const nextValue = Array.isArray(next) ? (next[0] ?? 0) : next;\n  return currentValue === nextValue;\n}\n\nfunction invertSliderValue(\n  value: number,\n  resolvedMin: number,\n  resolvedMax: number\n) {\n  return resolvedMin + resolvedMax - value;\n}\n\nfunction toPrimitiveValue(\n  value: number | [number, number],\n  isRange: boolean,\n  inverted: boolean,\n  resolvedMin: number,\n  resolvedMax: number\n): number | [number, number] {\n  if (!inverted) {\n    return value;\n  }\n\n  if (isRange) {\n    const [low, high] = value as [number, number];\n    return [\n      invertSliderValue(high, resolvedMin, resolvedMax),\n      invertSliderValue(low, resolvedMin, resolvedMax),\n    ];\n  }\n\n  return invertSliderValue(value as number, resolvedMin, resolvedMax);\n}\n\nfunction fromPrimitiveValue(\n  nextValue: number | readonly number[],\n  isRange: boolean,\n  inverted: boolean,\n  resolvedMin: number,\n  resolvedMax: number,\n  safeStep: number\n): number | [number, number] {\n  if (!inverted) {\n    if (isRange) {\n      const tuple = Array.isArray(nextValue)\n        ? nextValue\n        : [nextValue, nextValue];\n      return snapRangeValue(tuple, resolvedMin, resolvedMax, safeStep);\n    }\n\n    return snapValue(\n      Array.isArray(nextValue) ? (nextValue[0] ?? resolvedMin) : nextValue,\n      resolvedMin,\n      resolvedMax,\n      safeStep\n    );\n  }\n\n  if (isRange) {\n    const tuple = Array.isArray(nextValue) ? nextValue : [nextValue, nextValue];\n    const low = invertSliderValue(\n      tuple[1] ?? resolvedMax,\n      resolvedMin,\n      resolvedMax\n    );\n    const high = invertSliderValue(\n      tuple[0] ?? resolvedMin,\n      resolvedMin,\n      resolvedMax\n    );\n    return snapRangeValue([low, high], resolvedMin, resolvedMax, safeStep);\n  }\n\n  const numeric = Array.isArray(nextValue)\n    ? (nextValue[0] ?? resolvedMin)\n    : nextValue;\n  return snapValue(\n    invertSliderValue(numeric, resolvedMin, resolvedMax),\n    resolvedMin,\n    resolvedMax,\n    safeStep\n  );\n}\n\nfunction toPrimitiveArray(\n  value: number | [number, number],\n  isRange: boolean,\n  inverted: boolean,\n  resolvedMin: number,\n  resolvedMax: number\n): number[] {\n  const primitive = toPrimitiveValue(\n    value,\n    isRange,\n    inverted,\n    resolvedMin,\n    resolvedMax\n  );\n\n  if (isRange) {\n    const tuple = primitive as [number, number];\n    return [tuple[0], tuple[1]];\n  }\n\n  return [primitive as number];\n}\n\nfunction resolveThumbAccessibleLabel(\n  accessibleName: ReturnType<typeof resolveSliderAccessibleName>,\n  thumbIndex: number,\n  isRange: boolean\n) {\n  if (accessibleName.ariaLabelledBy) {\n    return undefined;\n  }\n\n  const baseLabel = accessibleName.ariaLabel ?? \"Slider\";\n\n  if (!isRange) {\n    return baseLabel;\n  }\n\n  return thumbIndex === 0 ? `${baseLabel}, minimum` : `${baseLabel}, maximum`;\n}\n\nfunction SliderVisualShell({\n  active,\n  activeThumbIndex,\n  fillLeftPercent,\n  fillSizePercent,\n  isDragging,\n  isHovered,\n  isRange,\n  sizeClasses,\n  thumbPercents,\n}: {\n  active: boolean;\n  activeThumbIndex: number;\n  fillLeftPercent: MotionValue<string>;\n  fillSizePercent: MotionValue<string>;\n  isDragging: boolean;\n  isHovered: boolean;\n  isRange: boolean;\n  sizeClasses: (typeof sliderSizeClasses)[SliderSize];\n  thumbPercents: MotionValue<string>[];\n}) {\n  const trackInactive = sizeClasses.trackInactive;\n  const trackActive = sizeClasses.trackActive;\n  const trackSize = active ? trackActive : trackInactive;\n  const springTransition = {\n    type: \"spring\" as const,\n    stiffness: 200,\n    damping: 28,\n    mass: 0.8,\n  };\n  const thumbSpringTransition = {\n    type: \"spring\" as const,\n    stiffness: 220,\n    damping: 22,\n    mass: 0.7,\n  };\n\n  return (\n    <div aria-hidden className=\"pointer-events-none absolute inset-0\">\n      <motion.div\n        animate={{ height: trackSize }}\n        className=\"absolute top-1/2 right-0 left-0 -translate-y-1/2 overflow-hidden rounded-full bg-foreground/15\"\n        transition={springTransition}\n      />\n\n      <motion.div\n        animate={{ height: trackSize }}\n        className=\"absolute top-1/2 left-0 origin-left -translate-y-1/2 overflow-hidden rounded-full bg-foreground\"\n        style={{ left: fillLeftPercent, width: fillSizePercent }}\n        transition={springTransition}\n      />\n\n      {thumbPercents.map((thumbPercent, index) => {\n        const isActiveThumb = isDragging && activeThumbIndex === index;\n\n        return (\n          <motion.div\n            animate={{\n              scale: isActiveThumb ? 1.15 : isHovered ? 1.08 : 1,\n            }}\n            className=\"absolute top-1/2 -translate-x-1/2 -translate-y-1/2\"\n            key={isRange ? `thumb-${index}` : \"thumb\"}\n            style={{ left: thumbPercent }}\n            transition={thumbSpringTransition}\n          >\n            <div\n              className={cn(\n                \"relative rounded-full border-foreground bg-background shadow-sm\",\n                sizeClasses.thumb,\n                sizeClasses.thumbBorder\n              )}\n            />\n          </motion.div>\n        );\n      })}\n    </div>\n  );\n}\n\nfunction SliderMarks({\n  disabled,\n  inverted,\n  isRtl,\n  marks,\n  marksInteractive,\n  onMarkActivate,\n  rangeSpan,\n  readOnly,\n  resolvedMin,\n}: {\n  disabled?: boolean;\n  inverted: boolean;\n  isRtl: boolean;\n  marks: SliderMark[];\n  marksInteractive?: boolean;\n  onMarkActivate: (value: number) => void;\n  rangeSpan: number;\n  readOnly?: boolean;\n  resolvedMin: number;\n}) {\n  if (marks.length === 0) {\n    return null;\n  }\n\n  const hasMarkLabels = marks.some((mark) => mark.label);\n  const interactive = marksInteractive && !disabled && !readOnly;\n\n  return (\n    <div\n      aria-hidden={!interactive}\n      className={cn(\n        \"relative mt-2\",\n        hasMarkLabels ? \"h-8\" : \"h-3\",\n        interactive ? \"\" : \"pointer-events-none\"\n      )}\n    >\n      {marks.map((mark) => {\n        let progress =\n          rangeSpan === 0 ? 0 : ((mark.value - resolvedMin) / rangeSpan) * 100;\n\n        if (isRtl) {\n          progress = 100 - progress;\n        }\n\n        if (inverted) {\n          progress = 100 - progress;\n        }\n\n        const positionStyle = { left: `${progress}%` };\n\n        const content = (\n          <>\n            <span className=\"mx-auto block h-2 w-px rounded-full bg-foreground/25\" />\n            {mark.label ? (\n              <span className=\"mt-1 block whitespace-nowrap font-medium text-[11px] text-muted-foreground\">\n                {mark.label}\n              </span>\n            ) : null}\n          </>\n        );\n\n        if (interactive) {\n          return (\n            <button\n              className=\"absolute top-0 -translate-x-1/2 text-center outline-none focus-visible:outline-2 focus-visible:outline-foreground/35 focus-visible:outline-offset-2\"\n              key={`${mark.value}-${mark.label ?? \"tick\"}`}\n              onClick={() => {\n                onMarkActivate(mark.value);\n              }}\n              style={positionStyle}\n              type=\"button\"\n            >\n              {content}\n            </button>\n          );\n        }\n\n        return (\n          <div\n            className=\"absolute top-0 -translate-x-1/2 text-center\"\n            key={`${mark.value}-${mark.label ?? \"tick\"}`}\n            style={positionStyle}\n          >\n            {content}\n          </div>\n        );\n      })}\n    </div>\n  );\n}\n\nfunction SliderFieldMessages({\n  description,\n  descriptionId,\n  errorId,\n  errorMessage,\n}: {\n  description?: ReactNode;\n  descriptionId?: string;\n  errorId?: string;\n  errorMessage?: ReactNode;\n}) {\n  if (!(description || errorMessage)) {\n    return null;\n  }\n\n  return (\n    <div className=\"mt-2 space-y-1\">\n      {description ? (\n        <p\n          className=\"text-muted-foreground text-xs leading-snug\"\n          id={descriptionId}\n        >\n          {description}\n        </p>\n      ) : null}\n      {errorMessage ? (\n        <p\n          aria-live=\"polite\"\n          className=\"text-destructive text-xs leading-snug\"\n          id={errorId}\n          role=\"alert\"\n        >\n          {errorMessage}\n        </p>\n      ) : null}\n    </div>\n  );\n}\n\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: slider shell coordinates motion, range, pointer, and keyboard state in one place.\nexport const Slider = forwardRef<HTMLDivElement, SliderProps>(function Slider(\n  {\n    value: controlledValue,\n    defaultValue,\n    min = 0,\n    max = 100,\n    step = 1,\n    onChange,\n    onValueCommit,\n    showValue = true,\n    valueDecimals = 0,\n    formatValue,\n    label,\n    ariaLabel,\n    ariaLabelledBy,\n    marks,\n    className,\n    disabled = false,\n    readOnly = false,\n    description,\n    errorMessage,\n    invalid = false,\n    ariaDescribedBy,\n    marksInteractive = false,\n    size = \"md\",\n    inverted = false,\n    name,\n    id,\n    range = false,\n  },\n  ref\n) {\n  const generatedId = useId();\n  const labelId = useId();\n  const activeThumbIndexRef = useRef(0);\n  const resolvedMin = Math.min(min, max);\n  const resolvedMax = Math.max(min, max);\n  const safeStep = step > 0 ? step : 1;\n  const safeValueDecimals = Math.max(0, valueDecimals);\n  const rangeSpan = resolvedMax - resolvedMin;\n  const sizeClasses = sliderSizeClasses[size];\n  const prefersReducedMotion = useReducedMotion() === true;\n  const [isRtl, setIsRtl] = useState(false);\n  const [internalValue, setInternalValue] = useState<number | [number, number]>(\n    () =>\n      resolveInitialSliderValue(\n        controlledValue,\n        defaultValue,\n        range,\n        resolvedMin,\n        resolvedMax,\n        safeStep,\n        rangeSpan\n      )\n  );\n  const [isDragging, setIsDragging] = useState(false);\n  const [isHovered, setIsHovered] = useState(false);\n  const [isFocused, setIsFocused] = useState(false);\n  const [activeThumbIndex, setActiveThumbIndex] = useState(0);\n\n  const fieldMeta = resolveSliderFieldMeta({\n    ariaDescribedByProp: ariaDescribedBy,\n    description,\n    errorMessage,\n    generatedId,\n    id,\n    invalid,\n  });\n  const accessibleName = resolveSliderAccessibleName({\n    ariaLabel,\n    ariaLabelledBy,\n    label,\n    labelId,\n  });\n\n  useEffect(() => {\n    setIsRtl(isDocumentRtl());\n  }, []);\n\n  useEffect(() => {\n    if (controlledValue !== undefined) {\n      return;\n    }\n\n    setInternalValue((current) => {\n      if (range) {\n        const tuple = Array.isArray(current)\n          ? current\n          : [resolvedMin, resolvedMax];\n        const next = snapRangeValue(tuple, resolvedMin, resolvedMax, safeStep);\n        return next[0] === tuple[0] && next[1] === tuple[1] ? current : next;\n      }\n\n      const numeric = Array.isArray(current)\n        ? (current[0] ?? resolvedMin)\n        : current;\n      const next = snapValue(numeric, resolvedMin, resolvedMax, safeStep);\n      return current === next ? current : next;\n    });\n  }, [controlledValue, range, resolvedMin, resolvedMax, safeStep]);\n\n  const value = resolveControlledSliderValue(\n    controlledValue,\n    internalValue,\n    range,\n    resolvedMin,\n    resolvedMax,\n    safeStep\n  );\n\n  const values: [number, number] = range\n    ? (value as [number, number])\n    : [value as number, value as number];\n  const [lowValue, highValue] = values;\n  const lowProgress = valueToProgress(lowValue, resolvedMin, resolvedMax);\n  const highProgress = valueToProgress(highValue, resolvedMin, resolvedMax);\n  const singleProgress = range\n    ? lowProgress\n    : valueToProgress(value as number, resolvedMin, resolvedMax);\n  const fillStartProgress = range ? lowProgress : 0;\n  const fillEndProgress = range ? highProgress : singleProgress;\n\n  const lowProgressMV = useMotionValue(lowProgress);\n  const highProgressMV = useMotionValue(highProgress);\n  const singleProgressMV = useMotionValue(singleProgress);\n  const fillStartMV = useMotionValue(fillStartProgress);\n  const fillEndMV = useMotionValue(fillEndProgress);\n\n  const lowThumbPercent = useTransform(\n    lowProgressMV,\n    (progress) => `${progress}%`\n  );\n  const highThumbPercent = useTransform(\n    highProgressMV,\n    (progress) => `${progress}%`\n  );\n  const singleThumbPercent = useTransform(\n    singleProgressMV,\n    (progress) => `${progress}%`\n  );\n  const thumbPercents = range\n    ? [lowThumbPercent, highThumbPercent]\n    : [singleThumbPercent];\n\n  const fillLeftPercent = useTransform(\n    fillStartMV,\n    (progress) => `${progress}%`\n  );\n  const fillSizePercent = useTransform(\n    [fillStartMV, fillEndMV],\n    ([start, end]: number[]) => `${Math.max(0, end - start)}%`\n  );\n\n  const singleDisplayValue = useTransform(singleProgressMV, (progress) => {\n    const resolved = progressToValue(\n      progress,\n      resolvedMin,\n      resolvedMax,\n      safeStep\n    );\n\n    return formatSliderDisplayValue(resolved, {\n      formatValue,\n      valueDecimals: safeValueDecimals,\n    });\n  });\n  const rangeDisplayValue = useTransform(\n    [lowProgressMV, highProgressMV],\n    ([low, high]: number[]) => {\n      const lowResolved = progressToValue(\n        low,\n        resolvedMin,\n        resolvedMax,\n        safeStep\n      );\n      const highResolved = progressToValue(\n        high,\n        resolvedMin,\n        resolvedMax,\n        safeStep\n      );\n\n      return formatSliderDisplayValue([lowResolved, highResolved], {\n        formatValue,\n        range: true,\n        valueDecimals: safeValueDecimals,\n      });\n    }\n  );\n\n  const progressSpring = prefersReducedMotion\n    ? { duration: 0 }\n    : {\n        type: \"spring\" as const,\n        stiffness: 180,\n        damping: 26,\n        mass: 0.9,\n        restDelta: 0.001,\n      };\n\n  useEffect(() => {\n    activeThumbIndexRef.current = activeThumbIndex;\n  }, [activeThumbIndex]);\n\n  useEffect(() => {\n    const controls = [\n      animate(lowProgressMV, lowProgress, progressSpring),\n      animate(highProgressMV, highProgress, progressSpring),\n      animate(singleProgressMV, singleProgress, progressSpring),\n      animate(fillStartMV, fillStartProgress, progressSpring),\n      animate(fillEndMV, fillEndProgress, progressSpring),\n    ];\n\n    return () => {\n      for (const control of controls) {\n        control.stop();\n      }\n    };\n  }, [\n    fillEndProgress,\n    fillStartProgress,\n    highProgress,\n    highProgressMV,\n    lowProgress,\n    lowProgressMV,\n    progressSpring,\n    singleProgress,\n    singleProgressMV,\n    fillEndMV,\n    fillStartMV,\n  ]);\n\n  const primitiveValue = toPrimitiveArray(\n    value,\n    range,\n    inverted,\n    resolvedMin,\n    resolvedMax\n  );\n\n  const commitValue = useCallback(\n    (\n      nextPrimitiveValue: number | readonly number[],\n      commit?: (resolved: number | [number, number]) => void\n    ) => {\n      if (disabled || readOnly) {\n        return;\n      }\n\n      const resolved = fromPrimitiveValue(\n        nextPrimitiveValue,\n        range,\n        inverted,\n        resolvedMin,\n        resolvedMax,\n        safeStep\n      );\n\n      if (sliderValuesEqual(value, resolved, range)) {\n        return;\n      }\n\n      if (controlledValue === undefined) {\n        setInternalValue(resolved);\n      }\n\n      onChange?.(resolved);\n      commit?.(resolved);\n    },\n    [\n      controlledValue,\n      disabled,\n      inverted,\n      onChange,\n      range,\n      readOnly,\n      resolvedMax,\n      resolvedMin,\n      safeStep,\n      value,\n    ]\n  );\n\n  const handleMarkActivate = useCallback(\n    (markValue: number) => {\n      if (disabled || readOnly) {\n        return;\n      }\n\n      if (range) {\n        const current = value as [number, number];\n        const lowDistance = Math.abs(current[0] - markValue);\n        const highDistance = Math.abs(current[1] - markValue);\n        const thumbIndex = lowDistance <= highDistance ? 0 : 1;\n        setActiveThumbIndex(thumbIndex);\n        activeThumbIndexRef.current = thumbIndex;\n\n        const nextTuple: [number, number] = [...current];\n        nextTuple[thumbIndex] = snapValue(\n          markValue,\n          resolvedMin,\n          resolvedMax,\n          safeStep\n        );\n        const resolved = snapRangeValue(\n          nextTuple,\n          resolvedMin,\n          resolvedMax,\n          safeStep\n        );\n\n        if (sliderValuesEqual(value, resolved, true)) {\n          return;\n        }\n\n        if (controlledValue === undefined) {\n          setInternalValue(resolved);\n        }\n\n        onChange?.(resolved);\n        onValueCommit?.(resolved);\n        return;\n      }\n\n      const resolved = snapValue(markValue, resolvedMin, resolvedMax, safeStep);\n\n      if (sliderValuesEqual(value, resolved, false)) {\n        return;\n      }\n\n      if (controlledValue === undefined) {\n        setInternalValue(resolved);\n      }\n\n      onChange?.(resolved);\n      onValueCommit?.(resolved);\n    },\n    [\n      controlledValue,\n      disabled,\n      onChange,\n      onValueCommit,\n      range,\n      readOnly,\n      resolvedMax,\n      resolvedMin,\n      safeStep,\n      value,\n    ]\n  );\n\n  const normalizedMarks = (marks ?? [])\n    .map((mark) => ({\n      ...mark,\n      value: clamp(mark.value, resolvedMin, resolvedMax),\n    }))\n    .sort((firstMark, secondMark) => firstMark.value - secondMark.value);\n  const active = isDragging || isHovered || isFocused;\n\n  const thumbClassName = cn(\"block opacity-0 outline-none\", sizeClasses.thumb);\n  const getThumbAriaValueText = useCallback(\n    (_formattedValue: string, thumbValue: number) =>\n      formatSliderDisplayValue(thumbValue, {\n        formatValue,\n        valueDecimals: safeValueDecimals,\n      }),\n    [formatValue, safeValueDecimals]\n  );\n  const getThumbAriaLabel = useCallback(\n    (thumbIndex: number) =>\n      resolveThumbAccessibleLabel(accessibleName, thumbIndex, range),\n    [accessibleName, range]\n  );\n\n  return (\n    <div\n      className={cn(\n        componentThemeClassName,\n        \"w-full select-none\",\n        disabled && \"cursor-not-allowed opacity-50\",\n        className\n      )}\n    >\n      {(label || showValue) && (\n        <div className=\"mb-3 flex items-baseline justify-between\">\n          {label ? (\n            <span\n              className=\"font-medium text-muted-foreground text-sm tracking-wide\"\n              id={labelId}\n            >\n              {label}\n            </span>\n          ) : null}\n          {showValue ? (\n            <motion.span className=\"font-semibold text-foreground text-sm tabular-nums\">\n              {range ? rangeDisplayValue : singleDisplayValue}\n            </motion.span>\n          ) : null}\n        </div>\n      )}\n\n      <div className=\"relative\">\n        <SliderPrimitive.Root\n          aria-label={\n            accessibleName.ariaLabelledBy ? undefined : accessibleName.ariaLabel\n          }\n          aria-labelledby={accessibleName.ariaLabelledBy}\n          className=\"relative\"\n          disabled={disabled}\n          max={resolvedMax}\n          min={resolvedMin}\n          onValueChange={(nextValue) => {\n            commitValue(nextValue);\n          }}\n          onValueCommitted={(nextValue) => {\n            commitValue(nextValue, onValueCommit);\n          }}\n          step={safeStep}\n          value={primitiveValue}\n        >\n          <div className=\"relative\">\n            <SliderPrimitive.Control\n              aria-describedby={fieldMeta.describedBy || undefined}\n              aria-invalid={fieldMeta.showInvalid || undefined}\n              aria-orientation=\"horizontal\"\n              aria-readonly={readOnly || undefined}\n              className={cn(\n                \"relative flex w-full cursor-pointer items-center rounded-full outline-none focus-within:outline-2 focus-within:outline-foreground/35 focus-within:outline-offset-4\",\n                sizeClasses.hitAreaHorizontal,\n                (disabled || readOnly) && \"cursor-not-allowed\"\n              )}\n              id={fieldMeta.sliderId}\n              onBlurCapture={(event) => {\n                if (\n                  resolveBlurTarget(event.currentTarget, event.relatedTarget)\n                ) {\n                  setIsFocused(false);\n                }\n              }}\n              onFocusCapture={() => {\n                setIsFocused(true);\n              }}\n              onMouseEnter={() => {\n                setIsHovered(true);\n              }}\n              onMouseLeave={() => {\n                setIsHovered(false);\n              }}\n              onPointerCancelCapture={() => {\n                setIsDragging(false);\n              }}\n              onPointerDownCapture={() => {\n                setIsDragging(true);\n              }}\n              onPointerUpCapture={() => {\n                setIsDragging(false);\n              }}\n              ref={ref}\n              style={{ touchAction: \"pan-y\" }}\n            >\n              <SliderPrimitive.Track className=\"absolute top-1/2 right-0 left-0 h-4 -translate-y-1/2 opacity-0\">\n                <SliderPrimitive.Indicator className=\"absolute inset-0\" />\n              </SliderPrimitive.Track>\n\n              {range ? (\n                <>\n                  <SliderPrimitive.Thumb\n                    className={thumbClassName}\n                    getAriaLabel={\n                      accessibleName.ariaLabelledBy\n                        ? undefined\n                        : () => getThumbAriaLabel(0) ?? \"Slider, minimum\"\n                    }\n                    getAriaValueText={getThumbAriaValueText}\n                    index={0}\n                    onFocus={() => {\n                      setActiveThumbIndex(0);\n                    }}\n                  />\n                  <SliderPrimitive.Thumb\n                    className={thumbClassName}\n                    getAriaLabel={\n                      accessibleName.ariaLabelledBy\n                        ? undefined\n                        : () => getThumbAriaLabel(1) ?? \"Slider, maximum\"\n                    }\n                    getAriaValueText={getThumbAriaValueText}\n                    index={1}\n                    onFocus={() => {\n                      setActiveThumbIndex(1);\n                    }}\n                  />\n                </>\n              ) : (\n                <SliderPrimitive.Thumb\n                  className={thumbClassName}\n                  getAriaLabel={\n                    accessibleName.ariaLabelledBy\n                      ? undefined\n                      : () => getThumbAriaLabel(0) ?? \"Slider\"\n                  }\n                  getAriaValueText={getThumbAriaValueText}\n                  onFocus={() => {\n                    setActiveThumbIndex(0);\n                  }}\n                />\n              )}\n\n              <SliderVisualShell\n                active={active}\n                activeThumbIndex={activeThumbIndex}\n                fillLeftPercent={fillLeftPercent}\n                fillSizePercent={fillSizePercent}\n                isDragging={isDragging}\n                isHovered={isHovered}\n                isRange={range}\n                sizeClasses={sizeClasses}\n                thumbPercents={thumbPercents}\n              />\n            </SliderPrimitive.Control>\n\n            <SliderMarks\n              disabled={disabled}\n              inverted={inverted}\n              isRtl={isRtl}\n              marks={normalizedMarks}\n              marksInteractive={marksInteractive}\n              onMarkActivate={handleMarkActivate}\n              rangeSpan={rangeSpan}\n              readOnly={readOnly}\n              resolvedMin={resolvedMin}\n            />\n          </div>\n        </SliderPrimitive.Root>\n\n        {name ? (\n          range ? (\n            <>\n              <input\n                aria-hidden\n                name={`${name}[0]`}\n                tabIndex={-1}\n                type=\"hidden\"\n                value={lowValue}\n              />\n              <input\n                aria-hidden\n                name={`${name}[1]`}\n                tabIndex={-1}\n                type=\"hidden\"\n                value={highValue}\n              />\n            </>\n          ) : (\n            <input\n              aria-hidden\n              name={name}\n              tabIndex={-1}\n              type=\"hidden\"\n              value={value as number}\n            />\n          )\n        ) : null}\n      </div>\n\n      <SliderFieldMessages\n        description={description}\n        descriptionId={fieldMeta.descriptionId}\n        errorId={fieldMeta.errorId}\n        errorMessage={errorMessage}\n      />\n    </div>\n  );\n});\n\nexport { Slider as slider };\n",
      "type": "registry:ui"
    }
  ],
  "title": "Slider (Base UI)",
  "description": "Slider with the same Iconiq API layered over Base UI primitives, preserving the original spring-settled fill, active track height, and thumb scale motion."
}
