{
  "slug": "mac-slider",
  "name": "Mac Slider",
  "description": "Liquid glass slider with squircle normal map refraction, specular rim sheen, and tactile spring physics.",
  "summary": "A native-feeling macOS slider component built with physics-based liquid glass optics and damped harmonic oscillator springs. Features real-time squircle normal-map displacement, specular edge reflections, and dynamic transparency that shifts from solid white at rest to optical glass when dragged, coupled with responsive track scrubbing, multiple sizes, materials, and keyboard navigation.",
  "category": "sliders-and-toggles",
  "tags": [
    "slider",
    "range",
    "liquid-glass",
    "refraction",
    "macos",
    "physics",
    "spring",
    "apple"
  ],
  "dependencies": [
    "clsx",
    "tailwind-merge",
    "motion"
  ],
  "version": "1.0.0",
  "createdDate": "2026-09-24",
  "updatedDate": "2026-09-24",
  "interactive": true,
  "supportsColor": false,
  "highlights": [
    "Ultra-smooth pointer-capture tracking with zero-latency MotionValue synchronization",
    "Real-time squircle normal-map refraction distortion using SVG feDisplacementMap",
    "Dynamic specular lighting highlights along the 16px convex squircle lens bezel",
    "Damped harmonic spring dynamics (stiffness: 400, damping: 30) for tactile drag expansion",
    "Fluid state morphing from solid white pill at rest to translucent liquid glass under drag",
    "Accurate sub-pixel track fill tracking the exact optical center of the thumb",
    "Three size variants (sm, md, lg) and three glass materials (liquid, frosted, clear)",
    "Seven color themes including macOS System Blue, Emerald, Violet, Amber, Rose, Cyan, and Graphite",
    "Full keyboard accessibility with Arrow keys, PageUp/Down, Home, End, and ARIA slider semantics",
    "Optical props (specularOpacity, specularSaturation, refractionLevel, blurLevel) are synced into MotionValues without re-rendering"
  ],
  "anatomy": [
    "<motion.div> (Track shell with role=\"slider\", ARIA value attributes, and focus ring)",
    "<motion.div> (Active progress fill bar tracking thumb center)",
    "<Filter> (Scoped SVG filter with normal map, feGaussianBlur, feDisplacementMap, feSpecularLighting, feColorMatrix)",
    "<motion.div> (Draggable thumb pill with spring-driven scale, liquid background, and specular sheen)"
  ],
  "physics": {
    "engine": "Harmonic Damped Spring Oscillator & SVG Refraction Shader",
    "description": "Spring-driven thumb scale, backdrop opacity and track seek, coupled with an SVG displacement filter.",
    "parameters": [
      {
        "label": "Rest Scale",
        "value": "0.6 (54px × 36px)"
      },
      {
        "label": "Drag Scale",
        "value": "1.0 (90px × 60px)"
      },
      {
        "label": "Scale Stiffness",
        "value": "400"
      },
      {
        "label": "Scale Damping",
        "value": "30"
      },
      {
        "label": "Seek Stiffness",
        "value": "450"
      },
      {
        "label": "Seek Damping",
        "value": "32"
      },
      {
        "label": "Bezel Width",
        "value": "12px - 20px convex squircle"
      }
    ]
  },
  "accessibility": {
    "role": "slider",
    "aria": "Standard role=\"slider\" with aria-valuenow, aria-valuemin, aria-valuemax, and focus-visible ring.",
    "reducedMotion": "With prefers-reduced-motion, thumb travel and scale changes apply instantly instead of springing.",
    "keyboard": [
      {
        "key": "ArrowLeft / ArrowDown",
        "description": "Decrease value by 1 step."
      },
      {
        "key": "ArrowRight / ArrowUp",
        "description": "Increase value by 1 step."
      },
      {
        "key": "PageDown / PageUp",
        "description": "Decrease or increase value by 10 steps."
      },
      {
        "key": "Home / End",
        "description": "Jump to minimum or maximum value."
      }
    ]
  },
  "guidelines": {
    "recommended": [
      "Audio volume controls, brightness adjustments, and media scrubber interfaces",
      "Control Center style settings panels where authentic macOS tactile feel is desired",
      "Creative tool sliders and shader parameter controllers"
    ],
    "bestPractices": [
      "Position over visually rich backgrounds to showcase the optical refraction effect",
      "Ensure sufficient contrast between the track background and the active fill",
      "Pass min, max, step, value and onChange for controlled use"
    ]
  },
  "props": [
    {
      "name": "value",
      "type": "number",
      "defaultValue": "undefined",
      "description": "Controlled slider value between min and max."
    },
    {
      "name": "defaultValue",
      "type": "number",
      "defaultValue": "10",
      "description": "Initial value for uncontrolled slider usage."
    },
    {
      "name": "min",
      "type": "number",
      "defaultValue": "0",
      "description": "Minimum value of the slider range."
    },
    {
      "name": "max",
      "type": "number",
      "defaultValue": "100",
      "description": "Maximum value of the slider range."
    },
    {
      "name": "step",
      "type": "number",
      "defaultValue": "1",
      "description": "Stepping increment for the slider value."
    },
    {
      "name": "color",
      "type": "\"blue\" | \"emerald\" | \"violet\" | \"amber\" | \"rose\" | \"cyan\" | \"monochrome\"",
      "defaultValue": "\"blue\"",
      "description": "Theme accent color for the active progress bar and ambient glow."
    },
    {
      "name": "size",
      "type": "\"sm\" | \"md\" | \"lg\"",
      "defaultValue": "\"md\"",
      "description": "Size preset controlling track width, height, and thumb scale."
    },
    {
      "name": "material",
      "type": "\"liquid\" | \"frosted\" | \"clear\"",
      "defaultValue": "\"liquid\"",
      "description": "Glass optical material for the thumb lens."
    },
    {
      "name": "forceActive",
      "type": "boolean",
      "defaultValue": "false",
      "description": "Whether the thumb lens is forcefully expanded."
    },
    {
      "name": "specularOpacity",
      "type": "number",
      "defaultValue": "0.4",
      "description": "Intensity of the specular light reflection (0 - 1)."
    },
    {
      "name": "specularSaturation",
      "type": "number",
      "defaultValue": "6",
      "description": "Specular color saturation multiplier (0 - 50)."
    },
    {
      "name": "refractionLevel",
      "type": "number",
      "defaultValue": "0.28",
      "description": "Refractive normal map displacement factor (0 - 1)."
    },
    {
      "name": "blurLevel",
      "type": "number",
      "defaultValue": "0",
      "description": "Gaussian blur standard deviation in pixels (0 - 40)."
    },
    {
      "name": "onChange",
      "type": "(value: number) => void",
      "defaultValue": "undefined",
      "description": "Callback invoked when the slider value changes."
    },
    {
      "name": "disabled",
      "type": "boolean",
      "defaultValue": "false",
      "description": "Disables interaction with the slider."
    },
    {
      "name": "label",
      "type": "string",
      "defaultValue": "\"Value\"",
      "description": "Accessible name announced by screen readers for the slider. Pass a name that describes what the slider controls."
    },
    {
      "name": "className",
      "type": "string",
      "defaultValue": "undefined",
      "description": "Additional CSS class names for outer container."
    }
  ],
  "usage": "\"use client\";\n\nimport { useState } from \"react\";\nimport { MacSlider } from \"@/components/ui/mac-slider\";\n\nexport function MacSliderDemo() {\n  const [volume, setVolume] = useState(40);\n\n  return <MacSlider value={volume} onChange={setVolume} min={0} max={100} label=\"Volume\" />;\n}",
  "files": [
    {
      "name": "mac-slider.tsx",
      "path": "registry/ui/mac-slider.tsx",
      "code": "\"use client\";\n\nimport React, { useEffect, useRef, useId, useCallback, useState } from \"react\";\nimport {\n  motion,\n  useMotionValue,\n  useMotionValueEvent,\n  useReducedMotion,\n  useSpring,\n  useTransform,\n  animate,\n  type MotionValue,\n} from \"motion/react\";\nimport { cn } from \"@/lib/utils\";\n\nexport type MacSliderColor =\n  | \"blue\"\n  | \"emerald\"\n  | \"violet\"\n  | \"amber\"\n  | \"rose\"\n  | \"cyan\"\n  | \"monochrome\";\n\nexport type MacSliderSize = \"sm\" | \"md\" | \"lg\";\nexport type MacSliderMaterial = \"liquid\" | \"frosted\" | \"clear\";\n\nexport interface FilterProps {\n  id?: string;\n  blur?: MotionValue<number> | number;\n  scaleRatio?: MotionValue<number> | number;\n  specularOpacity?: MotionValue<number> | number;\n  specularSaturation?: MotionValue<number> | number;\n  width?: number;\n  height?: number;\n  radius?: number;\n  bezelWidth?: number;\n}\n\nconst COLOR_THEMES: Record<\n  MacSliderColor,\n  { fill: string; dot: string; label: string; glow: string }\n> = {\n  blue: {\n    fill: \"#007AFF\",\n    dot: \"bg-blue-500\",\n    label: \"Blue\",\n    glow: \"rgba(0, 122, 255, 0.35)\",\n  },\n  emerald: {\n    fill: \"#10B981\",\n    dot: \"bg-emerald-400\",\n    label: \"Emerald\",\n    glow: \"rgba(16, 185, 129, 0.35)\",\n  },\n  violet: {\n    fill: \"#8B5CF6\",\n    dot: \"bg-violet-400\",\n    label: \"Violet\",\n    glow: \"rgba(139, 92, 246, 0.35)\",\n  },\n  amber: {\n    fill: \"#F59E0B\",\n    dot: \"bg-amber-400\",\n    label: \"Amber\",\n    glow: \"rgba(245, 158, 11, 0.35)\",\n  },\n  rose: {\n    fill: \"#F43F5E\",\n    dot: \"bg-rose-400\",\n    label: \"Rose\",\n    glow: \"rgba(244, 63, 94, 0.35)\",\n  },\n  cyan: {\n    fill: \"#06B6D4\",\n    dot: \"bg-cyan-400\",\n    label: \"Cyan\",\n    glow: \"rgba(6, 182, 212, 0.35)\",\n  },\n  monochrome: {\n    fill: \"#F4F4F5\",\n    dot: \"bg-zinc-200\",\n    label: \"Graphite\",\n    glow: \"rgba(255, 255, 255, 0.25)\",\n  },\n};\n\nconst SIZE_CONFIGS: Record<\n  MacSliderSize,\n  {\n    sliderWidth: number;\n    sliderHeight: number;\n    thumbWidth: number;\n    thumbHeight: number;\n    thumbRadius: number;\n    bezelWidth: number;\n  }\n> = {\n  sm: {\n    sliderWidth: 260,\n    sliderHeight: 10,\n    thumbWidth: 72,\n    thumbHeight: 48,\n    thumbRadius: 24,\n    bezelWidth: 12,\n  },\n  md: {\n    sliderWidth: 330,\n    sliderHeight: 14,\n    thumbWidth: 90,\n    thumbHeight: 60,\n    thumbRadius: 30,\n    bezelWidth: 16,\n  },\n  lg: {\n    sliderWidth: 400,\n    sliderHeight: 18,\n    thumbWidth: 108,\n    thumbHeight: 72,\n    thumbRadius: 36,\n    bezelWidth: 20,\n  },\n};\n\ntype SpringConfig = Parameters<typeof useSpring>[1];\n\nfunction useReducibleSpring(\n  source: MotionValue<number>,\n  config: SpringConfig,\n  instant: boolean,\n): MotionValue<number> {\n  const spring = useSpring(source, config);\n  return instant ? source : spring;\n}\n\nfunction isMotionValue(val: unknown): val is MotionValue<number> {\n  return typeof val === \"object\" && val !== null && \"get\" in val && \"on\" in val;\n}\n\nfunction getNumericValue(\n  val?: MotionValue<number> | number,\n  fallback = 0,\n): number {\n  if (val === undefined) return fallback;\n  if (isMotionValue(val)) return Number(val.get()) || fallback;\n  return Number(val) || fallback;\n}\n\nexport const Filter: React.FC<FilterProps> = ({\n  id = \"thumb-filter-slider\",\n  blur,\n  scaleRatio,\n  specularOpacity,\n  specularSaturation,\n  width = 90,\n  height = 60,\n  radius = 30,\n  bezelWidth = 16,\n}) => {\n  const feImageRef = useRef<SVGFEImageElement>(null);\n  const blurRef = useRef<SVGFEGaussianBlurElement>(null);\n  const dispRef = useRef<SVGFEDisplacementMapElement>(null);\n  const specRef = useRef<SVGFESpecularLightingElement>(null);\n  const satRef = useRef<SVGFEColorMatrixElement>(null);\n\n  useEffect(() => {\n    if (typeof document === \"undefined\") return;\n\n    const canvas = document.createElement(\"canvas\");\n    canvas.width = width;\n    canvas.height = height;\n    const ctx = canvas.getContext(\"2d\");\n    if (!ctx) return;\n\n    const imgData = ctx.createImageData(width, height);\n    const data = imgData.data;\n    let pos = 0;\n\n    for (let y = 0; y < height; y++) {\n      for (let x = 0; x < width; x++) {\n        const segX = Math.max(radius, Math.min(width - radius, x));\n        const segY = height / 2;\n        const dx = x - segX;\n        const dy = y - segY;\n        const dist = Math.sqrt(dx * dx + dy * dy);\n        const distEdge = radius - dist;\n\n        if (distEdge <= 0 || distEdge >= bezelWidth) {\n          data[pos++] = 128;\n          data[pos++] = 128;\n          data[pos++] = 255;\n          data[pos++] = 255;\n        } else {\n          const u = distEdge / bezelWidth;\n          const slope = Math.cos((u * Math.PI) / 2);\n          const dirX = dist > 0.001 ? dx / dist : 0;\n          const dirY = dist > 0.001 ? dy / dist : 0;\n          const nx = -dirX * slope * 0.85;\n          const ny = -dirY * slope * 0.85;\n          const nz = Math.sqrt(Math.max(0, 1 - nx * nx - ny * ny));\n\n          data[pos++] = Math.round(128 + 127 * nx);\n          data[pos++] = Math.round(128 + 127 * ny);\n          data[pos++] = Math.round(128 + 127 * nz);\n          data[pos++] = 255;\n        }\n      }\n    }\n\n    ctx.putImageData(imgData, 0, 0);\n    const dataUrl = canvas.toDataURL(\"image/png\");\n    feImageRef.current?.setAttribute(\"href\", dataUrl);\n  }, [width, height, radius, bezelWidth]);\n\n  useEffect(() => {\n    const unsubBlur = isMotionValue(blur)\n      ? blur.on(\"change\", (v) => {\n          blurRef.current?.setAttribute(\"stdDeviation\", String(v));\n        })\n      : undefined;\n\n    const unsubDisp = isMotionValue(scaleRatio)\n      ? scaleRatio.on(\"change\", (v) => {\n          dispRef.current?.setAttribute(\"scale\", String(v * 24));\n        })\n      : undefined;\n\n    const unsubSpec = isMotionValue(specularOpacity)\n      ? specularOpacity.on(\"change\", (v) => {\n          specRef.current?.setAttribute(\"specularConstant\", String(v * 1.5));\n        })\n      : undefined;\n\n    const unsubSat = isMotionValue(specularSaturation)\n      ? specularSaturation.on(\"change\", (v) => {\n          satRef.current?.setAttribute(\"values\", String(1 + v * 0.15));\n        })\n      : undefined;\n\n    const currentBlur = getNumericValue(blur, 0);\n    const currentScale = getNumericValue(scaleRatio, 0.4);\n    const currentSpec = getNumericValue(specularOpacity, 0.4);\n    const currentSat = getNumericValue(specularSaturation, 6);\n\n    blurRef.current?.setAttribute(\"stdDeviation\", String(currentBlur));\n    dispRef.current?.setAttribute(\"scale\", String(currentScale * 24));\n    specRef.current?.setAttribute(\n      \"specularConstant\",\n      String(currentSpec * 1.5),\n    );\n    satRef.current?.setAttribute(\"values\", String(1 + currentSat * 0.15));\n\n    return () => {\n      unsubBlur?.();\n      unsubDisp?.();\n      unsubSpec?.();\n      unsubSat?.();\n    };\n  }, [blur, scaleRatio, specularOpacity, specularSaturation]);\n\n  const initialBlur = getNumericValue(blur, 0);\n  const initialDisp = getNumericValue(scaleRatio, 0.4) * 24;\n  const initialSpec = getNumericValue(specularOpacity, 0.4) * 1.5;\n  const initialSat = 1 + getNumericValue(specularSaturation, 6) * 0.15;\n\n  return (\n    <svg\n      width=\"0\"\n      height=\"0\"\n      className=\"pointer-events-none absolute -z-10 opacity-0\"\n      aria-hidden=\"true\"\n    >\n      <defs>\n        <filter\n          id={id}\n          x=\"-20%\"\n          y=\"-20%\"\n          width=\"140%\"\n          height=\"140%\"\n          colorInterpolationFilters=\"sRGB\"\n        >\n          <feImage\n            ref={feImageRef}\n            result=\"normalMap\"\n            x=\"0\"\n            y=\"0\"\n            width={width}\n            height={height}\n            preserveAspectRatio=\"none\"\n          />\n          <feGaussianBlur\n            ref={blurRef}\n            in=\"SourceGraphic\"\n            stdDeviation={initialBlur}\n            result=\"blurred\"\n          />\n          <feDisplacementMap\n            ref={dispRef}\n            in=\"blurred\"\n            in2=\"normalMap\"\n            scale={initialDisp}\n            xChannelSelector=\"R\"\n            yChannelSelector=\"G\"\n            result=\"refracted\"\n          />\n          <feSpecularLighting\n            ref={specRef}\n            in=\"normalMap\"\n            surfaceScale=\"2\"\n            specularConstant={initialSpec}\n            specularExponent=\"24\"\n            result=\"specular\"\n            lightingColor=\"#ffffff\"\n          >\n            <feDistantLight azimuth=\"235\" elevation=\"55\" />\n          </feSpecularLighting>\n          <feColorMatrix\n            ref={satRef}\n            in=\"refracted\"\n            type=\"saturate\"\n            values={String(initialSat)}\n            result=\"saturated\"\n          />\n          <feBlend in=\"saturated\" in2=\"specular\" mode=\"screen\" />\n        </filter>\n      </defs>\n    </svg>\n  );\n};\n\nexport interface MacSliderProps {\n  min?: number;\n  max?: number;\n  step?: number;\n  defaultValue?: number;\n  value?: number;\n  onChange?: (value: number) => void;\n  color?: MacSliderColor;\n  size?: MacSliderSize;\n  material?: MacSliderMaterial;\n  forceActive?: boolean;\n  specularOpacity?: number;\n  specularSaturation?: number;\n  refractionLevel?: number;\n  blurLevel?: number;\n  className?: string;\n  disabled?: boolean;\n  label?: string;\n}\n\nexport const MacSlider: React.FC<MacSliderProps> = ({\n  min = 0,\n  max = 100,\n  step = 1,\n  defaultValue = 10,\n  value: controlledValue,\n  onChange,\n  color = \"blue\",\n  size = \"md\",\n  material = \"liquid\",\n  forceActive = false,\n  specularOpacity: specularOpacityProp = 0.4,\n  specularSaturation: specularSaturationProp = 6,\n  refractionLevel = 0.28,\n  blurLevel = 0,\n  className,\n  disabled = false,\n  label = \"Value\",\n}) => {\n  const generatedId = useId();\n  const filterId = `mac-filter-${generatedId.replace(/:/g, \"\")}`;\n  const reduceMotion = useReducedMotion() ?? false;\n\n  const currentTheme = COLOR_THEMES[color] ?? COLOR_THEMES.blue;\n  const currentSize = SIZE_CONFIGS[size] ?? SIZE_CONFIGS.md;\n  const {\n    sliderWidth,\n    sliderHeight,\n    thumbWidth,\n    thumbHeight,\n    thumbRadius,\n    bezelWidth,\n  } = currentSize;\n\n  const SCALE_REST = 0.6;\n  const SCALE_DRAG = 1;\n  const thumbWidthRest = thumbWidth * SCALE_REST;\n  const trackTravel = sliderWidth - thumbWidthRest;\n  const minX = -thumbWidthRest / 3;\n\n  const initialVal =\n    controlledValue !== undefined ? controlledValue : defaultValue;\n  const valueMotion = useMotionValue(initialVal);\n  const [ariaValue, setAriaValue] = useState(initialVal);\n  useMotionValueEvent(valueMotion, \"change\", setAriaValue);\n  const initialRatio = Math.max(\n    0,\n    Math.min(1, (initialVal - min) / (max - min)),\n  );\n  const thumbX = useMotionValue(minX + initialRatio * trackTravel);\n\n  const pointerDown = useMotionValue(0);\n  const forceActiveMotion = useMotionValue(forceActive ? 1 : 0);\n\n  useEffect(() => {\n    forceActiveMotion.set(forceActive ? 1 : 0);\n  }, [forceActive, forceActiveMotion]);\n\n  const isUp = useTransform((): number =>\n    forceActiveMotion.get() > 0.5 || pointerDown.get() > 0.5 ? 1 : 0,\n  );\n\n  const blur = useMotionValue(blurLevel);\n  const specularOpacity = useMotionValue(specularOpacityProp);\n  const specularSaturation = useMotionValue(specularSaturationProp);\n  const refractionBase = useMotionValue(refractionLevel);\n\n  useEffect(() => {\n    blur.set(blurLevel);\n  }, [blurLevel, blur]);\n\n  useEffect(() => {\n    specularOpacity.set(specularOpacityProp);\n  }, [specularOpacityProp, specularOpacity]);\n\n  useEffect(() => {\n    specularSaturation.set(specularSaturationProp);\n  }, [specularSaturationProp, specularSaturation]);\n\n  useEffect(() => {\n    refractionBase.set(refractionLevel);\n  }, [refractionLevel, refractionBase]);\n\n  const scaleRatio = useReducibleSpring(\n    useTransform((): number => {\n      const press = isUp.get() > 0.5 ? 0.9 : 0.4;\n      return press * (refractionBase.get() || 0);\n    }),\n    {\n      stiffness: 400,\n      damping: 30,\n      mass: 0.8,\n    },\n    reduceMotion,\n  );\n\n  const containerRef = useRef<HTMLDivElement>(null);\n  const trackRef = useRef<HTMLDivElement>(null);\n  const thumbRef = useRef<HTMLDivElement>(null);\n  const isDraggingRef = useRef(false);\n  const trackBoundsRef = useRef<{ left: number; width: number }>({\n    left: 0,\n    width: sliderWidth,\n  });\n\n  const scaleSpring = useReducibleSpring(\n    useTransform(isUp, [0, 1], [SCALE_REST, SCALE_DRAG]),\n    {\n      stiffness: 400,\n      damping: 30,\n      mass: 0.8,\n    },\n    reduceMotion,\n  );\n\n  const backgroundOpacity = useReducibleSpring(\n    useTransform(isUp, [0, 1], [1, 0.1]),\n    {\n      stiffness: 400,\n      damping: 30,\n      mass: 0.8,\n    },\n    reduceMotion,\n  );\n\n  const seekThumb = useCallback(\n    (targetX: number) => {\n      if (reduceMotion) {\n        thumbX.jump(targetX);\n        return;\n      }\n      animate(thumbX, targetX, {\n        type: \"spring\",\n        stiffness: 450,\n        damping: 32,\n        mass: 0.75,\n      });\n    },\n    [reduceMotion, thumbX],\n  );\n\n  const updatePositionFromClientX = useCallback(\n    (clientX: number, animateSpring = false) => {\n      const { left, width } = trackBoundsRef.current;\n      const effectiveTravel = width - thumbWidthRest;\n      if (effectiveTravel <= 0) return;\n\n      const clickX = clientX - left;\n      const ratio = Math.max(\n        0,\n        Math.min(1, (clickX - thumbWidthRest / 2) / effectiveTravel),\n      );\n\n      const rawVal = min + ratio * (max - min);\n      const steppedVal =\n        step > 0 ? Math.round(rawVal / step) * step : Math.round(rawVal);\n      const nextVal = Math.max(min, Math.min(max, steppedVal));\n\n      const normalizedRatio = (nextVal - min) / (max - min);\n      const targetX = minX + normalizedRatio * trackTravel;\n\n      if (animateSpring) {\n        seekThumb(targetX);\n      } else {\n        thumbX.set(targetX);\n      }\n\n      if (valueMotion.get() !== nextVal) {\n        valueMotion.set(nextVal);\n        onChange?.(nextVal);\n      }\n    },\n    [\n      thumbWidthRest,\n      min,\n      max,\n      step,\n      trackTravel,\n      minX,\n      thumbX,\n      seekThumb,\n      valueMotion,\n      onChange,\n    ],\n  );\n\n  useEffect(() => {\n    const curVal =\n      controlledValue !== undefined ? controlledValue : valueMotion.get();\n    const ratio = Math.max(0, Math.min(1, (curVal - min) / (max - min)));\n    thumbX.set(minX + ratio * trackTravel);\n  }, [size, minX, trackTravel, min, max, controlledValue, thumbX, valueMotion]);\n\n  useEffect(() => {\n    if (!isDraggingRef.current && controlledValue !== undefined) {\n      valueMotion.set(controlledValue);\n      const ratio = Math.max(\n        0,\n        Math.min(1, (controlledValue - min) / (max - min)),\n      );\n      seekThumb(minX + ratio * trackTravel);\n    }\n  }, [controlledValue, min, max, minX, trackTravel, seekThumb, valueMotion]);\n\n  const handlePointerDown = (e: React.PointerEvent<HTMLDivElement>) => {\n    if (disabled || !trackRef.current) return;\n\n    const rect = trackRef.current.getBoundingClientRect();\n    trackBoundsRef.current = { left: rect.left, width: rect.width };\n\n    isDraggingRef.current = true;\n    pointerDown.set(1);\n\n    e.currentTarget.setPointerCapture(e.pointerId);\n    updatePositionFromClientX(e.clientX, e.target !== thumbRef.current);\n  };\n\n  const handlePointerMove = (e: React.PointerEvent<HTMLDivElement>) => {\n    if (!isDraggingRef.current || disabled) return;\n    updatePositionFromClientX(e.clientX, false);\n  };\n\n  const handlePointerUp = (e: React.PointerEvent<HTMLDivElement>) => {\n    if (!isDraggingRef.current) return;\n    isDraggingRef.current = false;\n    pointerDown.set(0);\n\n    try {\n      e.currentTarget.releasePointerCapture(e.pointerId);\n    } catch {}\n  };\n\n  const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n    if (disabled) return;\n    let nextVal = valueMotion.get();\n    const jump = step || 1;\n\n    if (e.key === \"ArrowRight\" || e.key === \"ArrowUp\") {\n      e.preventDefault();\n      nextVal = Math.min(max, nextVal + jump);\n    } else if (e.key === \"ArrowLeft\" || e.key === \"ArrowDown\") {\n      e.preventDefault();\n      nextVal = Math.max(min, nextVal - jump);\n    } else if (e.key === \"PageUp\") {\n      e.preventDefault();\n      nextVal = Math.min(max, nextVal + jump * 10);\n    } else if (e.key === \"PageDown\") {\n      e.preventDefault();\n      nextVal = Math.max(min, nextVal - jump * 10);\n    } else if (e.key === \"Home\") {\n      e.preventDefault();\n      nextVal = min;\n    } else if (e.key === \"End\") {\n      e.preventDefault();\n      nextVal = max;\n    } else {\n      return;\n    }\n\n    valueMotion.set(nextVal);\n    onChange?.(nextVal);\n    const ratio = (nextVal - min) / (max - min);\n    seekThumb(minX + ratio * trackTravel);\n  };\n\n  const backdropStyle =\n    material === \"liquid\"\n      ? `url(#${filterId}) blur(14px)`\n      : material === \"frosted\"\n        ? \"blur(24px) saturate(180%)\"\n        : \"blur(8px) saturate(120%)\";\n\n  return (\n    <div\n      className={cn(\n        \"relative flex items-center justify-center select-none py-6\",\n        disabled && \"opacity-50 pointer-events-none\",\n        className,\n      )}\n    >\n      <motion.div\n        ref={containerRef}\n        tabIndex={0}\n        role=\"slider\"\n        aria-valuemin={min}\n        aria-valuemax={max}\n        aria-valuenow={ariaValue}\n        aria-label={label}\n        aria-disabled={disabled || undefined}\n        onKeyDown={handleKeyDown}\n        onPointerDown={handlePointerDown}\n        onPointerMove={handlePointerMove}\n        onPointerUp={handlePointerUp}\n        onPointerCancel={handlePointerUp}\n        className=\"outline-none focus-visible:ring-2 focus-visible:ring-blue-500/50 rounded-full touch-none select-none cursor-pointer\"\n        style={{\n          position: \"relative\",\n          width: sliderWidth,\n          height: thumbHeight,\n        }}\n      >\n        <div\n          ref={trackRef}\n          style={{\n            display: \"inline-block\",\n            width: sliderWidth,\n            height: sliderHeight,\n            left: 0,\n            top: (thumbHeight - sliderHeight) / 2,\n            backgroundColor: \"#89898F66\",\n            borderRadius: sliderHeight / 2,\n            position: \"absolute\",\n          }}\n        >\n          <div className=\"w-full h-full overflow-hidden rounded-full\">\n            <motion.div\n              style={{\n                top: 0,\n                left: 0,\n                height: sliderHeight,\n                width: useTransform(\n                  thumbX,\n                  (x) =>\n                    `${Math.max(\n                      0,\n                      Math.min(sliderWidth, x + thumbWidth / 2),\n                    )}px`,\n                ),\n                borderRadius: sliderHeight / 2,\n                backgroundColor: currentTheme.fill,\n                boxShadow: `0 0 16px ${currentTheme.glow}`,\n              }}\n            />\n          </div>\n        </div>\n\n        {material === \"liquid\" && (\n          <Filter\n            id={filterId}\n            blur={blur}\n            scaleRatio={scaleRatio}\n            specularOpacity={specularOpacity}\n            specularSaturation={specularSaturation}\n            width={thumbWidth}\n            height={thumbHeight}\n            radius={thumbRadius}\n            bezelWidth={bezelWidth}\n          />\n        )}\n\n        <motion.div\n          ref={thumbRef}\n          className=\"absolute pointer-events-none\"\n          style={{\n            height: thumbHeight,\n            width: thumbWidth,\n            top: 0,\n            x: thumbX,\n            borderRadius: thumbRadius,\n            backdropFilter: backdropStyle,\n            WebkitBackdropFilter: backdropStyle,\n            scale: scaleSpring,\n            willChange: \"transform\",\n            backgroundColor: useTransform(\n              backgroundOpacity,\n              (op) => `rgba(255, 255, 255, ${op})`,\n            ),\n            boxShadow:\n              \"0 4px 18px rgba(0, 0, 0, 0.22), inset 0 1px 1.5px rgba(255, 255, 255, 0.8), inset 0 -1px 2px rgba(0, 0, 0, 0.12)\",\n            border: \"1px solid rgba(255, 255, 255, 0.35)\",\n          }}\n        >\n          <div\n            className=\"pointer-events-none absolute inset-x-0 top-0 h-1/2 opacity-40\"\n            style={{\n              borderRadius: `${thumbRadius}px ${thumbRadius}px 0 0`,\n              background:\n                \"linear-gradient(180deg, rgba(255,255,255,0.6) 0%, rgba(255,255,255,0.05) 100%)\",\n            }}\n          />\n        </motion.div>\n      </motion.div>\n    </div>\n  );\n};\n\nexport const Slider = MacSlider;\n",
      "content": "\"use client\";\n\nimport React, { useEffect, useRef, useId, useCallback, useState } from \"react\";\nimport {\n  motion,\n  useMotionValue,\n  useMotionValueEvent,\n  useReducedMotion,\n  useSpring,\n  useTransform,\n  animate,\n  type MotionValue,\n} from \"motion/react\";\nimport { cn } from \"@/lib/utils\";\n\nexport type MacSliderColor =\n  | \"blue\"\n  | \"emerald\"\n  | \"violet\"\n  | \"amber\"\n  | \"rose\"\n  | \"cyan\"\n  | \"monochrome\";\n\nexport type MacSliderSize = \"sm\" | \"md\" | \"lg\";\nexport type MacSliderMaterial = \"liquid\" | \"frosted\" | \"clear\";\n\nexport interface FilterProps {\n  id?: string;\n  blur?: MotionValue<number> | number;\n  scaleRatio?: MotionValue<number> | number;\n  specularOpacity?: MotionValue<number> | number;\n  specularSaturation?: MotionValue<number> | number;\n  width?: number;\n  height?: number;\n  radius?: number;\n  bezelWidth?: number;\n}\n\nconst COLOR_THEMES: Record<\n  MacSliderColor,\n  { fill: string; dot: string; label: string; glow: string }\n> = {\n  blue: {\n    fill: \"#007AFF\",\n    dot: \"bg-blue-500\",\n    label: \"Blue\",\n    glow: \"rgba(0, 122, 255, 0.35)\",\n  },\n  emerald: {\n    fill: \"#10B981\",\n    dot: \"bg-emerald-400\",\n    label: \"Emerald\",\n    glow: \"rgba(16, 185, 129, 0.35)\",\n  },\n  violet: {\n    fill: \"#8B5CF6\",\n    dot: \"bg-violet-400\",\n    label: \"Violet\",\n    glow: \"rgba(139, 92, 246, 0.35)\",\n  },\n  amber: {\n    fill: \"#F59E0B\",\n    dot: \"bg-amber-400\",\n    label: \"Amber\",\n    glow: \"rgba(245, 158, 11, 0.35)\",\n  },\n  rose: {\n    fill: \"#F43F5E\",\n    dot: \"bg-rose-400\",\n    label: \"Rose\",\n    glow: \"rgba(244, 63, 94, 0.35)\",\n  },\n  cyan: {\n    fill: \"#06B6D4\",\n    dot: \"bg-cyan-400\",\n    label: \"Cyan\",\n    glow: \"rgba(6, 182, 212, 0.35)\",\n  },\n  monochrome: {\n    fill: \"#F4F4F5\",\n    dot: \"bg-zinc-200\",\n    label: \"Graphite\",\n    glow: \"rgba(255, 255, 255, 0.25)\",\n  },\n};\n\nconst SIZE_CONFIGS: Record<\n  MacSliderSize,\n  {\n    sliderWidth: number;\n    sliderHeight: number;\n    thumbWidth: number;\n    thumbHeight: number;\n    thumbRadius: number;\n    bezelWidth: number;\n  }\n> = {\n  sm: {\n    sliderWidth: 260,\n    sliderHeight: 10,\n    thumbWidth: 72,\n    thumbHeight: 48,\n    thumbRadius: 24,\n    bezelWidth: 12,\n  },\n  md: {\n    sliderWidth: 330,\n    sliderHeight: 14,\n    thumbWidth: 90,\n    thumbHeight: 60,\n    thumbRadius: 30,\n    bezelWidth: 16,\n  },\n  lg: {\n    sliderWidth: 400,\n    sliderHeight: 18,\n    thumbWidth: 108,\n    thumbHeight: 72,\n    thumbRadius: 36,\n    bezelWidth: 20,\n  },\n};\n\ntype SpringConfig = Parameters<typeof useSpring>[1];\n\nfunction useReducibleSpring(\n  source: MotionValue<number>,\n  config: SpringConfig,\n  instant: boolean,\n): MotionValue<number> {\n  const spring = useSpring(source, config);\n  return instant ? source : spring;\n}\n\nfunction isMotionValue(val: unknown): val is MotionValue<number> {\n  return typeof val === \"object\" && val !== null && \"get\" in val && \"on\" in val;\n}\n\nfunction getNumericValue(\n  val?: MotionValue<number> | number,\n  fallback = 0,\n): number {\n  if (val === undefined) return fallback;\n  if (isMotionValue(val)) return Number(val.get()) || fallback;\n  return Number(val) || fallback;\n}\n\nexport const Filter: React.FC<FilterProps> = ({\n  id = \"thumb-filter-slider\",\n  blur,\n  scaleRatio,\n  specularOpacity,\n  specularSaturation,\n  width = 90,\n  height = 60,\n  radius = 30,\n  bezelWidth = 16,\n}) => {\n  const feImageRef = useRef<SVGFEImageElement>(null);\n  const blurRef = useRef<SVGFEGaussianBlurElement>(null);\n  const dispRef = useRef<SVGFEDisplacementMapElement>(null);\n  const specRef = useRef<SVGFESpecularLightingElement>(null);\n  const satRef = useRef<SVGFEColorMatrixElement>(null);\n\n  useEffect(() => {\n    if (typeof document === \"undefined\") return;\n\n    const canvas = document.createElement(\"canvas\");\n    canvas.width = width;\n    canvas.height = height;\n    const ctx = canvas.getContext(\"2d\");\n    if (!ctx) return;\n\n    const imgData = ctx.createImageData(width, height);\n    const data = imgData.data;\n    let pos = 0;\n\n    for (let y = 0; y < height; y++) {\n      for (let x = 0; x < width; x++) {\n        const segX = Math.max(radius, Math.min(width - radius, x));\n        const segY = height / 2;\n        const dx = x - segX;\n        const dy = y - segY;\n        const dist = Math.sqrt(dx * dx + dy * dy);\n        const distEdge = radius - dist;\n\n        if (distEdge <= 0 || distEdge >= bezelWidth) {\n          data[pos++] = 128;\n          data[pos++] = 128;\n          data[pos++] = 255;\n          data[pos++] = 255;\n        } else {\n          const u = distEdge / bezelWidth;\n          const slope = Math.cos((u * Math.PI) / 2);\n          const dirX = dist > 0.001 ? dx / dist : 0;\n          const dirY = dist > 0.001 ? dy / dist : 0;\n          const nx = -dirX * slope * 0.85;\n          const ny = -dirY * slope * 0.85;\n          const nz = Math.sqrt(Math.max(0, 1 - nx * nx - ny * ny));\n\n          data[pos++] = Math.round(128 + 127 * nx);\n          data[pos++] = Math.round(128 + 127 * ny);\n          data[pos++] = Math.round(128 + 127 * nz);\n          data[pos++] = 255;\n        }\n      }\n    }\n\n    ctx.putImageData(imgData, 0, 0);\n    const dataUrl = canvas.toDataURL(\"image/png\");\n    feImageRef.current?.setAttribute(\"href\", dataUrl);\n  }, [width, height, radius, bezelWidth]);\n\n  useEffect(() => {\n    const unsubBlur = isMotionValue(blur)\n      ? blur.on(\"change\", (v) => {\n          blurRef.current?.setAttribute(\"stdDeviation\", String(v));\n        })\n      : undefined;\n\n    const unsubDisp = isMotionValue(scaleRatio)\n      ? scaleRatio.on(\"change\", (v) => {\n          dispRef.current?.setAttribute(\"scale\", String(v * 24));\n        })\n      : undefined;\n\n    const unsubSpec = isMotionValue(specularOpacity)\n      ? specularOpacity.on(\"change\", (v) => {\n          specRef.current?.setAttribute(\"specularConstant\", String(v * 1.5));\n        })\n      : undefined;\n\n    const unsubSat = isMotionValue(specularSaturation)\n      ? specularSaturation.on(\"change\", (v) => {\n          satRef.current?.setAttribute(\"values\", String(1 + v * 0.15));\n        })\n      : undefined;\n\n    const currentBlur = getNumericValue(blur, 0);\n    const currentScale = getNumericValue(scaleRatio, 0.4);\n    const currentSpec = getNumericValue(specularOpacity, 0.4);\n    const currentSat = getNumericValue(specularSaturation, 6);\n\n    blurRef.current?.setAttribute(\"stdDeviation\", String(currentBlur));\n    dispRef.current?.setAttribute(\"scale\", String(currentScale * 24));\n    specRef.current?.setAttribute(\n      \"specularConstant\",\n      String(currentSpec * 1.5),\n    );\n    satRef.current?.setAttribute(\"values\", String(1 + currentSat * 0.15));\n\n    return () => {\n      unsubBlur?.();\n      unsubDisp?.();\n      unsubSpec?.();\n      unsubSat?.();\n    };\n  }, [blur, scaleRatio, specularOpacity, specularSaturation]);\n\n  const initialBlur = getNumericValue(blur, 0);\n  const initialDisp = getNumericValue(scaleRatio, 0.4) * 24;\n  const initialSpec = getNumericValue(specularOpacity, 0.4) * 1.5;\n  const initialSat = 1 + getNumericValue(specularSaturation, 6) * 0.15;\n\n  return (\n    <svg\n      width=\"0\"\n      height=\"0\"\n      className=\"pointer-events-none absolute -z-10 opacity-0\"\n      aria-hidden=\"true\"\n    >\n      <defs>\n        <filter\n          id={id}\n          x=\"-20%\"\n          y=\"-20%\"\n          width=\"140%\"\n          height=\"140%\"\n          colorInterpolationFilters=\"sRGB\"\n        >\n          <feImage\n            ref={feImageRef}\n            result=\"normalMap\"\n            x=\"0\"\n            y=\"0\"\n            width={width}\n            height={height}\n            preserveAspectRatio=\"none\"\n          />\n          <feGaussianBlur\n            ref={blurRef}\n            in=\"SourceGraphic\"\n            stdDeviation={initialBlur}\n            result=\"blurred\"\n          />\n          <feDisplacementMap\n            ref={dispRef}\n            in=\"blurred\"\n            in2=\"normalMap\"\n            scale={initialDisp}\n            xChannelSelector=\"R\"\n            yChannelSelector=\"G\"\n            result=\"refracted\"\n          />\n          <feSpecularLighting\n            ref={specRef}\n            in=\"normalMap\"\n            surfaceScale=\"2\"\n            specularConstant={initialSpec}\n            specularExponent=\"24\"\n            result=\"specular\"\n            lightingColor=\"#ffffff\"\n          >\n            <feDistantLight azimuth=\"235\" elevation=\"55\" />\n          </feSpecularLighting>\n          <feColorMatrix\n            ref={satRef}\n            in=\"refracted\"\n            type=\"saturate\"\n            values={String(initialSat)}\n            result=\"saturated\"\n          />\n          <feBlend in=\"saturated\" in2=\"specular\" mode=\"screen\" />\n        </filter>\n      </defs>\n    </svg>\n  );\n};\n\nexport interface MacSliderProps {\n  min?: number;\n  max?: number;\n  step?: number;\n  defaultValue?: number;\n  value?: number;\n  onChange?: (value: number) => void;\n  color?: MacSliderColor;\n  size?: MacSliderSize;\n  material?: MacSliderMaterial;\n  forceActive?: boolean;\n  specularOpacity?: number;\n  specularSaturation?: number;\n  refractionLevel?: number;\n  blurLevel?: number;\n  className?: string;\n  disabled?: boolean;\n  label?: string;\n}\n\nexport const MacSlider: React.FC<MacSliderProps> = ({\n  min = 0,\n  max = 100,\n  step = 1,\n  defaultValue = 10,\n  value: controlledValue,\n  onChange,\n  color = \"blue\",\n  size = \"md\",\n  material = \"liquid\",\n  forceActive = false,\n  specularOpacity: specularOpacityProp = 0.4,\n  specularSaturation: specularSaturationProp = 6,\n  refractionLevel = 0.28,\n  blurLevel = 0,\n  className,\n  disabled = false,\n  label = \"Value\",\n}) => {\n  const generatedId = useId();\n  const filterId = `mac-filter-${generatedId.replace(/:/g, \"\")}`;\n  const reduceMotion = useReducedMotion() ?? false;\n\n  const currentTheme = COLOR_THEMES[color] ?? COLOR_THEMES.blue;\n  const currentSize = SIZE_CONFIGS[size] ?? SIZE_CONFIGS.md;\n  const {\n    sliderWidth,\n    sliderHeight,\n    thumbWidth,\n    thumbHeight,\n    thumbRadius,\n    bezelWidth,\n  } = currentSize;\n\n  const SCALE_REST = 0.6;\n  const SCALE_DRAG = 1;\n  const thumbWidthRest = thumbWidth * SCALE_REST;\n  const trackTravel = sliderWidth - thumbWidthRest;\n  const minX = -thumbWidthRest / 3;\n\n  const initialVal =\n    controlledValue !== undefined ? controlledValue : defaultValue;\n  const valueMotion = useMotionValue(initialVal);\n  const [ariaValue, setAriaValue] = useState(initialVal);\n  useMotionValueEvent(valueMotion, \"change\", setAriaValue);\n  const initialRatio = Math.max(\n    0,\n    Math.min(1, (initialVal - min) / (max - min)),\n  );\n  const thumbX = useMotionValue(minX + initialRatio * trackTravel);\n\n  const pointerDown = useMotionValue(0);\n  const forceActiveMotion = useMotionValue(forceActive ? 1 : 0);\n\n  useEffect(() => {\n    forceActiveMotion.set(forceActive ? 1 : 0);\n  }, [forceActive, forceActiveMotion]);\n\n  const isUp = useTransform((): number =>\n    forceActiveMotion.get() > 0.5 || pointerDown.get() > 0.5 ? 1 : 0,\n  );\n\n  const blur = useMotionValue(blurLevel);\n  const specularOpacity = useMotionValue(specularOpacityProp);\n  const specularSaturation = useMotionValue(specularSaturationProp);\n  const refractionBase = useMotionValue(refractionLevel);\n\n  useEffect(() => {\n    blur.set(blurLevel);\n  }, [blurLevel, blur]);\n\n  useEffect(() => {\n    specularOpacity.set(specularOpacityProp);\n  }, [specularOpacityProp, specularOpacity]);\n\n  useEffect(() => {\n    specularSaturation.set(specularSaturationProp);\n  }, [specularSaturationProp, specularSaturation]);\n\n  useEffect(() => {\n    refractionBase.set(refractionLevel);\n  }, [refractionLevel, refractionBase]);\n\n  const scaleRatio = useReducibleSpring(\n    useTransform((): number => {\n      const press = isUp.get() > 0.5 ? 0.9 : 0.4;\n      return press * (refractionBase.get() || 0);\n    }),\n    {\n      stiffness: 400,\n      damping: 30,\n      mass: 0.8,\n    },\n    reduceMotion,\n  );\n\n  const containerRef = useRef<HTMLDivElement>(null);\n  const trackRef = useRef<HTMLDivElement>(null);\n  const thumbRef = useRef<HTMLDivElement>(null);\n  const isDraggingRef = useRef(false);\n  const trackBoundsRef = useRef<{ left: number; width: number }>({\n    left: 0,\n    width: sliderWidth,\n  });\n\n  const scaleSpring = useReducibleSpring(\n    useTransform(isUp, [0, 1], [SCALE_REST, SCALE_DRAG]),\n    {\n      stiffness: 400,\n      damping: 30,\n      mass: 0.8,\n    },\n    reduceMotion,\n  );\n\n  const backgroundOpacity = useReducibleSpring(\n    useTransform(isUp, [0, 1], [1, 0.1]),\n    {\n      stiffness: 400,\n      damping: 30,\n      mass: 0.8,\n    },\n    reduceMotion,\n  );\n\n  const seekThumb = useCallback(\n    (targetX: number) => {\n      if (reduceMotion) {\n        thumbX.jump(targetX);\n        return;\n      }\n      animate(thumbX, targetX, {\n        type: \"spring\",\n        stiffness: 450,\n        damping: 32,\n        mass: 0.75,\n      });\n    },\n    [reduceMotion, thumbX],\n  );\n\n  const updatePositionFromClientX = useCallback(\n    (clientX: number, animateSpring = false) => {\n      const { left, width } = trackBoundsRef.current;\n      const effectiveTravel = width - thumbWidthRest;\n      if (effectiveTravel <= 0) return;\n\n      const clickX = clientX - left;\n      const ratio = Math.max(\n        0,\n        Math.min(1, (clickX - thumbWidthRest / 2) / effectiveTravel),\n      );\n\n      const rawVal = min + ratio * (max - min);\n      const steppedVal =\n        step > 0 ? Math.round(rawVal / step) * step : Math.round(rawVal);\n      const nextVal = Math.max(min, Math.min(max, steppedVal));\n\n      const normalizedRatio = (nextVal - min) / (max - min);\n      const targetX = minX + normalizedRatio * trackTravel;\n\n      if (animateSpring) {\n        seekThumb(targetX);\n      } else {\n        thumbX.set(targetX);\n      }\n\n      if (valueMotion.get() !== nextVal) {\n        valueMotion.set(nextVal);\n        onChange?.(nextVal);\n      }\n    },\n    [\n      thumbWidthRest,\n      min,\n      max,\n      step,\n      trackTravel,\n      minX,\n      thumbX,\n      seekThumb,\n      valueMotion,\n      onChange,\n    ],\n  );\n\n  useEffect(() => {\n    const curVal =\n      controlledValue !== undefined ? controlledValue : valueMotion.get();\n    const ratio = Math.max(0, Math.min(1, (curVal - min) / (max - min)));\n    thumbX.set(minX + ratio * trackTravel);\n  }, [size, minX, trackTravel, min, max, controlledValue, thumbX, valueMotion]);\n\n  useEffect(() => {\n    if (!isDraggingRef.current && controlledValue !== undefined) {\n      valueMotion.set(controlledValue);\n      const ratio = Math.max(\n        0,\n        Math.min(1, (controlledValue - min) / (max - min)),\n      );\n      seekThumb(minX + ratio * trackTravel);\n    }\n  }, [controlledValue, min, max, minX, trackTravel, seekThumb, valueMotion]);\n\n  const handlePointerDown = (e: React.PointerEvent<HTMLDivElement>) => {\n    if (disabled || !trackRef.current) return;\n\n    const rect = trackRef.current.getBoundingClientRect();\n    trackBoundsRef.current = { left: rect.left, width: rect.width };\n\n    isDraggingRef.current = true;\n    pointerDown.set(1);\n\n    e.currentTarget.setPointerCapture(e.pointerId);\n    updatePositionFromClientX(e.clientX, e.target !== thumbRef.current);\n  };\n\n  const handlePointerMove = (e: React.PointerEvent<HTMLDivElement>) => {\n    if (!isDraggingRef.current || disabled) return;\n    updatePositionFromClientX(e.clientX, false);\n  };\n\n  const handlePointerUp = (e: React.PointerEvent<HTMLDivElement>) => {\n    if (!isDraggingRef.current) return;\n    isDraggingRef.current = false;\n    pointerDown.set(0);\n\n    try {\n      e.currentTarget.releasePointerCapture(e.pointerId);\n    } catch {}\n  };\n\n  const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n    if (disabled) return;\n    let nextVal = valueMotion.get();\n    const jump = step || 1;\n\n    if (e.key === \"ArrowRight\" || e.key === \"ArrowUp\") {\n      e.preventDefault();\n      nextVal = Math.min(max, nextVal + jump);\n    } else if (e.key === \"ArrowLeft\" || e.key === \"ArrowDown\") {\n      e.preventDefault();\n      nextVal = Math.max(min, nextVal - jump);\n    } else if (e.key === \"PageUp\") {\n      e.preventDefault();\n      nextVal = Math.min(max, nextVal + jump * 10);\n    } else if (e.key === \"PageDown\") {\n      e.preventDefault();\n      nextVal = Math.max(min, nextVal - jump * 10);\n    } else if (e.key === \"Home\") {\n      e.preventDefault();\n      nextVal = min;\n    } else if (e.key === \"End\") {\n      e.preventDefault();\n      nextVal = max;\n    } else {\n      return;\n    }\n\n    valueMotion.set(nextVal);\n    onChange?.(nextVal);\n    const ratio = (nextVal - min) / (max - min);\n    seekThumb(minX + ratio * trackTravel);\n  };\n\n  const backdropStyle =\n    material === \"liquid\"\n      ? `url(#${filterId}) blur(14px)`\n      : material === \"frosted\"\n        ? \"blur(24px) saturate(180%)\"\n        : \"blur(8px) saturate(120%)\";\n\n  return (\n    <div\n      className={cn(\n        \"relative flex items-center justify-center select-none py-6\",\n        disabled && \"opacity-50 pointer-events-none\",\n        className,\n      )}\n    >\n      <motion.div\n        ref={containerRef}\n        tabIndex={0}\n        role=\"slider\"\n        aria-valuemin={min}\n        aria-valuemax={max}\n        aria-valuenow={ariaValue}\n        aria-label={label}\n        aria-disabled={disabled || undefined}\n        onKeyDown={handleKeyDown}\n        onPointerDown={handlePointerDown}\n        onPointerMove={handlePointerMove}\n        onPointerUp={handlePointerUp}\n        onPointerCancel={handlePointerUp}\n        className=\"outline-none focus-visible:ring-2 focus-visible:ring-blue-500/50 rounded-full touch-none select-none cursor-pointer\"\n        style={{\n          position: \"relative\",\n          width: sliderWidth,\n          height: thumbHeight,\n        }}\n      >\n        <div\n          ref={trackRef}\n          style={{\n            display: \"inline-block\",\n            width: sliderWidth,\n            height: sliderHeight,\n            left: 0,\n            top: (thumbHeight - sliderHeight) / 2,\n            backgroundColor: \"#89898F66\",\n            borderRadius: sliderHeight / 2,\n            position: \"absolute\",\n          }}\n        >\n          <div className=\"w-full h-full overflow-hidden rounded-full\">\n            <motion.div\n              style={{\n                top: 0,\n                left: 0,\n                height: sliderHeight,\n                width: useTransform(\n                  thumbX,\n                  (x) =>\n                    `${Math.max(\n                      0,\n                      Math.min(sliderWidth, x + thumbWidth / 2),\n                    )}px`,\n                ),\n                borderRadius: sliderHeight / 2,\n                backgroundColor: currentTheme.fill,\n                boxShadow: `0 0 16px ${currentTheme.glow}`,\n              }}\n            />\n          </div>\n        </div>\n\n        {material === \"liquid\" && (\n          <Filter\n            id={filterId}\n            blur={blur}\n            scaleRatio={scaleRatio}\n            specularOpacity={specularOpacity}\n            specularSaturation={specularSaturation}\n            width={thumbWidth}\n            height={thumbHeight}\n            radius={thumbRadius}\n            bezelWidth={bezelWidth}\n          />\n        )}\n\n        <motion.div\n          ref={thumbRef}\n          className=\"absolute pointer-events-none\"\n          style={{\n            height: thumbHeight,\n            width: thumbWidth,\n            top: 0,\n            x: thumbX,\n            borderRadius: thumbRadius,\n            backdropFilter: backdropStyle,\n            WebkitBackdropFilter: backdropStyle,\n            scale: scaleSpring,\n            willChange: \"transform\",\n            backgroundColor: useTransform(\n              backgroundOpacity,\n              (op) => `rgba(255, 255, 255, ${op})`,\n            ),\n            boxShadow:\n              \"0 4px 18px rgba(0, 0, 0, 0.22), inset 0 1px 1.5px rgba(255, 255, 255, 0.8), inset 0 -1px 2px rgba(0, 0, 0, 0.12)\",\n            border: \"1px solid rgba(255, 255, 255, 0.35)\",\n          }}\n        >\n          <div\n            className=\"pointer-events-none absolute inset-x-0 top-0 h-1/2 opacity-40\"\n            style={{\n              borderRadius: `${thumbRadius}px ${thumbRadius}px 0 0`,\n              background:\n                \"linear-gradient(180deg, rgba(255,255,255,0.6) 0%, rgba(255,255,255,0.05) 100%)\",\n            }}\n          />\n        </motion.div>\n      </motion.div>\n    </div>\n  );\n};\n\nexport const Slider = MacSlider;\n",
      "type": "registry:ui",
      "target": "@ui/mac-slider.tsx"
    }
  ],
  "type": "registry:ui",
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "title": "Mac Slider"
}
