{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "dock",
  "title": "Dock",
  "description": "A macOS-style dock with magnification effect on hover.",
  "dependencies": [
    "motion",
    "clsx",
    "tailwind-merge"
  ],
  "files": [
    {
      "path": "registry/wise-ui/components/dock.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport {\n  motion,\n  useMotionValue,\n  useSpring,\n  useTransform,\n  AnimatePresence,\n} from \"motion/react\"\nimport { cn } from \"@/registry/wise-ui/lib/utils\"\n\ninterface DockItem {\n  id: string\n  icon: React.ReactNode\n  label: string\n  href?: string\n}\n\ninterface DockProps {\n  items: DockItem[]\n  onItemClick?: (item: DockItem) => void\n  magnification?: number\n  distance?: number\n  className?: string\n}\n\nfunction Dock({\n  items,\n  onItemClick,\n  magnification = 1.5,\n  distance = 150,\n  className,\n}: DockProps) {\n  const mouseX = useMotionValue(Infinity)\n\n  return (\n    <div\n      className={cn(\n        \"inline-flex items-end gap-2 rounded-2xl border border-border bg-background/80 px-3 py-2 backdrop-blur-md\",\n        className\n      )}\n      onMouseMove={(e) => mouseX.set(e.clientX)}\n      onMouseLeave={() => mouseX.set(Infinity)}\n    >\n      {items.map((item) => (\n        <DockIcon\n          key={item.id}\n          item={item}\n          mouseX={mouseX}\n          magnification={magnification}\n          distance={distance}\n          onClick={() => onItemClick?.(item)}\n        />\n      ))}\n    </div>\n  )\n}\nDock.displayName = \"Dock\"\n\nfunction DockIcon({\n  item,\n  mouseX,\n  magnification,\n  distance,\n  onClick,\n}: {\n  item: DockItem\n  mouseX: ReturnType<typeof useMotionValue<number>>\n  magnification: number\n  distance: number\n  onClick: () => void\n}) {\n  const ref = React.useRef<HTMLButtonElement>(null)\n  const [hovered, setHovered] = React.useState(false)\n\n  const distanceCalc = useTransform(mouseX, (val) => {\n    const el = ref.current\n    if (!el) return distance\n    const rect = el.getBoundingClientRect()\n    const center = rect.left + rect.width / 2\n    return Math.abs(val - center)\n  })\n\n  const baseSize = 40\n  const scaleRaw = useTransform(\n    distanceCalc,\n    [0, distance],\n    [magnification, 1]\n  )\n  const scale = useSpring(scaleRaw, { stiffness: 300, damping: 25 })\n  const size = useTransform(scale, (s) => s * baseSize)\n\n  const Wrapper = item.href ? \"a\" : \"button\"\n  const wrapperProps = item.href\n    ? { href: item.href, target: \"_blank\" as const, rel: \"noopener noreferrer\" }\n    : {}\n\n  return (\n    <div className=\"relative flex flex-col items-center\">\n      <AnimatePresence>\n        {hovered && (\n          <motion.div\n            initial={{ opacity: 0, y: 4 }}\n            animate={{ opacity: 1, y: -4 }}\n            exit={{ opacity: 0, y: 4 }}\n            className=\"absolute -top-8 whitespace-nowrap rounded-md bg-foreground px-2 py-0.5 text-xs text-background shadow\"\n          >\n            {item.label}\n          </motion.div>\n        )}\n      </AnimatePresence>\n      <motion.div style={{ width: size, height: size }}>\n        <Wrapper\n          ref={ref as React.Ref<HTMLButtonElement & HTMLAnchorElement>}\n          className=\"flex h-full w-full cursor-pointer items-center justify-center rounded-xl bg-muted/60 text-foreground transition-colors hover:bg-muted\"\n          onClick={onClick}\n          onMouseEnter={() => setHovered(true)}\n          onMouseLeave={() => setHovered(false)}\n          {...wrapperProps}\n        >\n          {item.icon}\n        </Wrapper>\n      </motion.div>\n    </div>\n  )\n}\n\nexport { Dock }\nexport type { DockProps, DockItem }\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:component"
}