{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "jarvis-dock",
  "title": "Jarvis Dock",
  "description": "Floating bottom dock with quick-action buttons + a command-palette trigger.",
  "dependencies": [
    "@vllnt/ui@^0.3.0"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/default/jarvis-dock/jarvis-dock.tsx",
      "content": "\"use client\";\n\nimport type { ComponentPropsWithoutRef, ReactNode } from \"react\";\n\nimport { cn } from \"@vllnt/ui\";\n\n/**\n * Tone of a dock action — drives its accent color.\n *\n * @public\n */\nexport type JarvisDockTone = \"danger\" | \"neutral\" | \"primary\" | \"success\";\n\nconst TONE_CLASS: Record<JarvisDockTone, string> = {\n  danger: \"text-red-600 dark:text-red-400\",\n  neutral: \"text-foreground\",\n  primary: \"text-blue-600 dark:text-blue-400\",\n  success: \"text-emerald-600 dark:text-emerald-400\",\n};\n\n/**\n * One action button slotted in the dock.\n *\n * @public\n */\nexport type JarvisDockAction = {\n  /** Optional badge value rendered as a small dot or count. */\n  badge?: ReactNode;\n  /** Glyph rendered above the label (single character or icon). */\n  glyph: ReactNode;\n  /** Stable identifier — used as the React key + analytics hook. */\n  id: string;\n  /** Short label shown beneath the glyph. */\n  label: ReactNode;\n  /** Click handler. */\n  onActivate: () => void;\n  /** Optional tone. Defaults to `\"neutral\"`. */\n  tone?: JarvisDockTone;\n};\n\n/**\n * Localizable strings.\n *\n * @public\n */\nexport type JarvisDockLabels = {\n  /** Aria-label for the command-palette trigger. Defaults to `\"Open command palette\"`. */\n  paletteTrigger?: string;\n  /** Aria-label for the dock. Defaults to `\"Jarvis dock\"`. */\n  region?: string;\n};\n\nconst DEFAULT_LABELS = {\n  paletteTrigger: \"Open command palette\",\n  region: \"Jarvis dock\",\n} as const satisfies Required<JarvisDockLabels>;\n\n/**\n * Props for {@link JarvisDock}.\n *\n * @public\n */\nexport type JarvisDockProps = {\n  /** Action buttons in render order. */\n  actions: JarvisDockAction[];\n  /** Localizable strings. */\n  labels?: JarvisDockLabels;\n  /** Optional handler for the \"...\" command-palette trigger. */\n  onOpenPalette?: () => void;\n} & ComponentPropsWithoutRef<\"nav\">;\n\nconst ActionButton = (props: {\n  action: JarvisDockAction;\n}): React.ReactElement => {\n  const { action } = props;\n  const tone = action.tone ?? \"neutral\";\n  const handleActivateAction = (): void => {\n    action.onActivate();\n  };\n  return (\n    <button\n      className=\"group relative flex size-12 flex-col items-center justify-center gap-0.5 rounded-md border border-transparent text-[10px] uppercase tracking-wide text-muted-foreground transition-colors hover:border-border hover:bg-muted/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n      data-jarvis-action={action.id}\n      data-jarvis-tone={tone}\n      onClick={handleActivateAction}\n      type=\"button\"\n    >\n      <span\n        aria-hidden=\"true\"\n        className={cn(\n          \"text-base leading-none transition-transform group-hover:scale-110\",\n          TONE_CLASS[tone],\n        )}\n      >\n        {action.glyph}\n      </span>\n      <span className=\"truncate\">{action.label}</span>\n      {action.badge ? (\n        <span\n          className=\"absolute right-1 top-1 inline-flex min-h-[14px] min-w-[14px] items-center justify-center rounded-full bg-foreground px-1 text-[9px] font-medium text-background\"\n          data-jarvis-badge\n        >\n          {action.badge}\n        </span>\n      ) : null}\n    </button>\n  );\n};\n\n/**\n * Floating bottom dock for the spatial canvas. Renders a compact row\n * of agent / quick-action buttons plus a trailing command-palette\n * trigger. Pure presentation; the host wires `onActivate` per action\n * and `onOpenPalette` for the palette button.\n *\n * @example\n * ```tsx\n * <JarvisDock\n *   actions={[\n *     { id: \"summon\", glyph: \"+\", label: \"Summon\", tone: \"primary\",\n *       onActivate: () => spawnAgent() },\n *     { id: \"review\", glyph: \"✓\", label: \"Review\", tone: \"success\",\n *       onActivate: () => openReview() },\n *   ]}\n *   onOpenPalette={() => openCommandPalette()}\n * />\n * ```\n *\n * @public\n */\nexport const JarvisDock = ({\n  ref,\n  ...props\n}: JarvisDockProps & { ref?: React.Ref<HTMLElement> }) => {\n  const { actions, className, labels, onOpenPalette, ...rest } = props;\n  const resolvedLabels = { ...DEFAULT_LABELS, ...labels };\n  const handlePalette = (): void => {\n    onOpenPalette?.();\n  };\n  return (\n    <nav\n      aria-label={resolvedLabels.region}\n      className={cn(\n        \"inline-flex items-center gap-1 rounded-2xl border bg-background/90 p-1.5 shadow-md backdrop-blur\",\n        className,\n      )}\n      data-jarvis-dock\n      ref={ref}\n      {...rest}\n    >\n      {actions.map((action) => (\n        <ActionButton action={action} key={action.id} />\n      ))}\n      {onOpenPalette ? (\n        <>\n          <span aria-hidden=\"true\" className=\"mx-1 h-8 w-px bg-border\" />\n          <button\n            aria-label={resolvedLabels.paletteTrigger}\n            className=\"flex size-12 items-center justify-center rounded-md border border-transparent text-base text-muted-foreground transition-colors hover:border-border hover:bg-muted/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n            data-jarvis-palette-trigger\n            onClick={handlePalette}\n            type=\"button\"\n          >\n            <span aria-hidden=\"true\">⌘</span>\n          </button>\n        </>\n      ) : null}\n    </nav>\n  );\n};\nJarvisDock.displayName = \"JarvisDock\";\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:component",
  "version": "0.3.0",
  "stability": "stable"
}
