{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "dock",
  "title": "Dock",
  "description": "macOS-style dock whose icons magnify near the pointer.",
  "dependencies": [
    "@vllnt/ui@^0.2.1"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/default/dock/dock.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"@vllnt/ui\";\n\n/** Props for {@link Dock}. */\nexport type DockProps = React.ComponentPropsWithoutRef<\"div\">;\n\n/** Props for {@link DockIcon}. */\nexport type DockIconProps = React.ComponentPropsWithoutRef<\"div\">;\n\nconst DockPointerContext = React.createContext<null | number>(null);\n\nfunction assignRef(\n  ref: React.Ref<HTMLDivElement> | undefined,\n  node: HTMLDivElement | null,\n): void {\n  if (typeof ref === \"function\") {\n    ref(node);\n    return;\n  }\n\n  if (ref) {\n    ref.current = node;\n  }\n}\n\nfunction usePrefersReducedMotion(): boolean {\n  const [reduced, setReduced] = React.useState(false);\n\n  React.useEffect(() => {\n    if (\n      typeof window === \"undefined\" ||\n      typeof window.matchMedia !== \"function\"\n    ) {\n      return;\n    }\n\n    const query = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n    const onChange = (): void => {\n      setReduced(query.matches);\n    };\n\n    onChange();\n    query.addEventListener(\"change\", onChange);\n\n    return () => {\n      query.removeEventListener(\"change\", onChange);\n    };\n  }, []);\n\n  return reduced;\n}\n\nfunction magnify(distance: number): number {\n  const range = 100;\n  const clamped = Math.min(Math.abs(distance), range);\n  return 1 + 0.5 * (1 - clamped / range);\n}\n\n/**\n * macOS-style dock that magnifies its {@link DockIcon} children near the pointer.\n *\n * @example\n * ```tsx\n * <Dock>\n *   <DockIcon>A</DockIcon>\n *   <DockIcon>B</DockIcon>\n * </Dock>\n * ```\n */\nexport const Dock = ({\n  children,\n  className,\n  ref,\n  ...props\n}: DockProps & { ref?: React.Ref<HTMLDivElement> }) => {\n  const [pointerX, setPointerX] = React.useState<null | number>(null);\n\n  return (\n    <DockPointerContext.Provider value={pointerX}>\n      <div\n        className={cn(\n          \"flex items-end gap-2 rounded-2xl border bg-card/60 p-2 backdrop-blur\",\n          className,\n        )}\n        onPointerLeave={() => {\n          setPointerX(null);\n        }}\n        onPointerMove={(event) => {\n          setPointerX(event.clientX);\n        }}\n        ref={ref}\n        {...props}\n      >\n        {children}\n      </div>\n    </DockPointerContext.Provider>\n  );\n};\nDock.displayName = \"Dock\";\n\nfunction useDockScale(\n  reference: React.RefObject<HTMLDivElement | null>,\n  pointerX: null | number,\n  reduced: boolean,\n): number {\n  if (reduced || pointerX === null || reference.current === null) {\n    return 1;\n  }\n\n  const bounds = reference.current.getBoundingClientRect();\n  const center = bounds.left + bounds.width / 2;\n  return magnify(pointerX - center);\n}\n\n/**\n * Single dock entry that scales up as the pointer moves toward its center.\n *\n * Respects `prefers-reduced-motion`: the icon stays at rest size.\n *\n * @example\n * ```tsx\n * <DockIcon>Home</DockIcon>\n * ```\n */\nexport const DockIcon = ({\n  children,\n  className,\n  ref,\n  style,\n  ...props\n}: DockIconProps & { ref?: React.Ref<HTMLDivElement> }) => {\n  const pointerX = React.use(DockPointerContext);\n  const reduced = usePrefersReducedMotion();\n  const reference = React.useRef<HTMLDivElement>(null);\n  const scale = useDockScale(reference, pointerX, reduced);\n\n  const setReferences = React.useCallback(\n    (node: HTMLDivElement | null): void => {\n      reference.current = node;\n      assignRef(ref, node);\n    },\n    [ref],\n  );\n\n  return (\n    <div\n      className={cn(\n        \"flex aspect-square w-12 items-center justify-center rounded-xl bg-accent text-accent-foreground transition-transform\",\n        className,\n      )}\n      ref={setReferences}\n      style={{ transform: `scale(${scale})`, ...style }}\n      {...props}\n    >\n      {children}\n    </div>\n  );\n};\nDockIcon.displayName = \"DockIcon\";\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:component",
  "version": "0.2.1",
  "stability": "stable"
}
