{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "dock",
  "title": "Dock",
  "description": "macOS-style dock with cursor magnification.",
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "src/components/velora/dock.tsx",
      "content": "\"use client\";\n\nimport { createContext, useContext, useRef } from \"react\";\nimport {\n  motion,\n  useMotionValue,\n  useReducedMotion,\n  useSpring,\n  useTransform,\n  type MotionValue,\n} from \"motion/react\";\n\nimport { cn } from \"@/lib/utils\";\n\ninterface DockContextValue {\n  mouseX: MotionValue<number>;\n  baseSize: number;\n  magnification: number;\n  distance: number;\n}\n\nconst DockContext = createContext<DockContextValue | null>(null);\n\ninterface DockProps {\n  children: React.ReactNode;\n  className?: string;\n  /** Icon size at rest, px */\n  baseSize?: number;\n  /** Icon size under the cursor, px */\n  magnification?: number;\n  /** Cursor influence radius, px */\n  distance?: number;\n}\n\nexport function Dock({\n  children,\n  className,\n  baseSize = 40,\n  magnification = 64,\n  distance = 140,\n}: DockProps) {\n  const mouseX = useMotionValue(Infinity);\n\n  return (\n    <DockContext.Provider value={{ mouseX, baseSize, magnification, distance }}>\n      <motion.div\n        data-slot=\"dock\"\n        onMouseMove={(e) => mouseX.set(e.clientX)}\n        onMouseLeave={() => mouseX.set(Infinity)}\n        className={cn(\n          \"mx-auto flex h-16 w-fit items-end gap-2 rounded-2xl border bg-card/70 px-3 pb-2 backdrop-blur-xl\",\n          className\n        )}\n      >\n        {children}\n      </motion.div>\n    </DockContext.Provider>\n  );\n}\n\ninterface DockIconProps {\n  children: React.ReactNode;\n  className?: string;\n  /** Accessible name; also used as the tooltip title */\n  label?: string;\n  /** Render as a link to this URL instead of a button */\n  href?: string;\n  /** Click handler for the button (or link) */\n  onClick?: React.MouseEventHandler<HTMLElement>;\n}\n\nexport function DockIcon({\n  children,\n  className,\n  label,\n  href,\n  onClick,\n}: DockIconProps) {\n  const ref = useRef<HTMLElement>(null);\n  const reducedMotion = useReducedMotion();\n  const fallbackX = useMotionValue(Infinity);\n  const ctx = useContext(DockContext);\n  const mouseX = ctx?.mouseX ?? fallbackX;\n  const baseSize = ctx?.baseSize ?? 40;\n  const magnification = ctx?.magnification ?? 64;\n  const distance = ctx?.distance ?? 140;\n\n  const distanceFromCursor = useTransform(mouseX, (x) => {\n    const bounds = ref.current?.getBoundingClientRect() ?? { x: 0, width: 0 };\n    return x - bounds.x - bounds.width / 2;\n  });\n\n  const sizeTarget = useTransform(\n    distanceFromCursor,\n    [-distance, 0, distance],\n    [baseSize, magnification, baseSize]\n  );\n  const size = useSpring(sizeTarget, {\n    mass: 0.1,\n    stiffness: 160,\n    damping: 13,\n  });\n\n  const shared = {\n    \"data-slot\": \"dock-icon\",\n    \"aria-label\": label,\n    title: label,\n    onClick,\n    // Magnify around the focused icon for keyboard users, like a hover would\n    onFocus: () => {\n      const bounds = ref.current?.getBoundingClientRect();\n      if (bounds) mouseX.set(bounds.x + bounds.width / 2);\n    },\n    onBlur: () => mouseX.set(Infinity),\n    style: reducedMotion\n      ? { width: baseSize, height: baseSize }\n      : { width: size, height: size },\n    className: cn(\n      \"flex aspect-square cursor-pointer items-center justify-center rounded-full bg-muted text-muted-foreground transition-colors hover:text-foreground focus-visible:text-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring\",\n      className\n    ),\n  };\n\n  return href ? (\n    <motion.a\n      ref={ref as React.RefObject<HTMLAnchorElement>}\n      href={href}\n      {...shared}\n    >\n      {children}\n    </motion.a>\n  ) : (\n    <motion.button\n      ref={ref as React.RefObject<HTMLButtonElement>}\n      type=\"button\"\n      {...shared}\n    >\n      {children}\n    </motion.button>\n  );\n}\n",
      "type": "registry:ui",
      "target": "components/velora/dock.tsx"
    }
  ],
  "type": "registry:ui"
}