{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "dock",
  "title": "Dock",
  "type": "registry:ui",
  "files": [
    {
      "path": "packages/registry-svelte/components/dock/Dock.svelte",
      "content": "<script lang=\"ts\" module>\n  import type { Component } from 'svelte'\n  import type { HTMLAttributes } from 'svelte/elements'\n\n  export interface DockItem {\n    /** Unique id for the item. */\n    id: string\n    /** Lucide icon component to render. */\n    icon: Component\n    /** Label shown in the tooltip on hover. */\n    label: string\n    /** Click handler. */\n    handler?: () => void\n    /** Whether this item is the active one. */\n    active?: boolean\n  }\n\n  export interface DockProps extends HTMLAttributes<HTMLDivElement> {\n    /** Dock items. */\n    items: DockItem[]\n    /** Base icon size in pixels. Default 48. */\n    baseSize?: number\n    /** Peak magnification scale as the cursor hovers directly over an item. Default 1.6. */\n    magnification?: number\n    /** Pixel radius within which items magnify. Default 120. */\n    distance?: number\n    /** Orientation. Only 'horizontal' (bottom dock) is supported. */\n    orientation?: 'horizontal'\n    /** Show the tooltip label on hover. Default true. */\n    showTooltips?: boolean\n    ref?: HTMLDivElement | null\n  }\n</script>\n\n<script lang=\"ts\">\n  import { cn } from '$lib/utils'\n\n  let {\n    class: className,\n    items,\n    baseSize = 48,\n    magnification = 1.6,\n    distance = 120,\n    orientation = 'horizontal',\n    showTooltips = true,\n    ref = $bindable(null),\n    ...restProps\n  }: DockProps = $props()\n\n  let mouseX = $state<number | null>(null)\n  let hoveredId = $state<string | null>(null)\n  let itemEls: (HTMLElement | undefined)[] = $state([])\n\n  function registerItem(el: HTMLElement, index: number) {\n    itemEls[index] = el\n    return {\n      destroy() {\n        itemEls[index] = undefined\n      },\n    }\n  }\n\n  function sizeFor(index: number): number {\n    if (mouseX === null) return baseSize\n    const el = itemEls[index]\n    if (!el) return baseSize\n    const rect = el.getBoundingClientRect()\n    const center = rect.left + rect.width / 2\n    const dist = Math.abs(mouseX - center)\n    if (dist > distance) return baseSize\n    // Cosine bell curve so magnification falls off smoothly.\n    const t = 1 - dist / distance\n    const scale = 1 + (magnification - 1) * t\n    return baseSize * scale\n  }\n\n  const sizes = $derived(items.map((_, i) => sizeFor(i)))\n</script>\n\n<div\n  bind:this={ref}\n  data-uipkge\n  data-slot=\"dock\"\n  data-orientation={orientation}\n  class={cn(\n    'border-border/60 bg-background/60 flex items-end justify-center gap-3 rounded-2xl border px-3 py-2 backdrop-blur-md',\n    className,\n  )}\n  onmousemove={(e) => (mouseX = e.clientX)}\n  onmouseleave={() => {\n    mouseX = null\n    hoveredId = null\n  }}\n  {...restProps}\n>\n  {#each items as item, index (item.id)}\n    {@const Icon = item.icon}\n    {@const size = sizes[index] ?? baseSize}\n    <div\n      use:registerItem={index}\n      data-slot=\"dock-item\"\n      data-active={item.active ? '' : undefined}\n      role=\"button\"\n      tabindex=\"0\"\n      aria-label={item.label}\n      aria-current={item.active ? 'true' : undefined}\n      class=\"group focus-visible:ring-ring/50 relative flex shrink-0 cursor-pointer items-end justify-center rounded-xl outline-none focus-visible:ring-[3px]\"\n      onmouseenter={() => (hoveredId = item.id)}\n      onmouseleave={() => (hoveredId = null)}\n      onclick={() => item.handler?.()}\n      onkeydown={(e) => {\n        if (e.key === 'Enter') item.handler?.()\n        if (e.key === ' ') {\n          e.preventDefault()\n          item.handler?.()\n        }\n      }}\n    >\n      <!-- Tooltip -->\n      {#if showTooltips && hoveredId === item.id}\n        <span\n          class=\"border-border bg-popover text-popover-foreground pointer-events-none absolute -top-10 left-1/2 -translate-x-1/2 rounded-md border px-2 py-1 text-xs whitespace-nowrap shadow-md\"\n        >\n          {item.label}\n        </span>\n      {/if}\n\n      <!-- Icon tile -->\n      <span\n        class={cn(\n          'flex items-center justify-center rounded-xl border transition-[width,height] duration-100 ease-out will-change-[width,height]',\n          item.active\n            ? 'border-primary/40 bg-primary/10 text-primary'\n            : 'border-border/50 bg-muted/40 text-foreground hover:bg-muted',\n        )}\n        style=\"width: {size}px; height: {size}px\"\n      >\n        <Icon style=\"width: {size * 0.5}px; height: {size * 0.5}px\" />\n      </span>\n\n      <!-- Active indicator dot -->\n      {#if item.active}\n        <span class=\"bg-primary absolute -bottom-2 size-1 rounded-full\" aria-hidden=\"true\"></span>\n      {/if}\n    </div>\n  {/each}\n</div>\n",
      "type": "registry:ui",
      "target": "~/src/lib/components/ui/dock/Dock.svelte"
    },
    {
      "path": "packages/registry-svelte/components/dock/index.ts",
      "content": "export { default as Dock, type DockItem, type DockProps } from './Dock.svelte'\n",
      "type": "registry:ui",
      "target": "~/src/lib/components/ui/dock/index.ts"
    }
  ],
  "dependencies": [],
  "devDependencies": [],
  "registryDependencies": [],
  "description": "macOS-style dock menu with magnification on hover. Items expand as the cursor approaches using a cosine bell curve. Supports an items array (icon + label + handler), magnification scale, base size, tooltips on hover, click handlers, and an active state indicator.",
  "categories": [
    "navigation"
  ]
}