{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "world-breadcrumbs",
  "type": "registry:component",
  "title": "World Breadcrumbs",
  "description": "Spatial trail showing the canvas's current location in a hierarchy of worlds, groups, and runs.",
  "dependencies": [
    "@vllnt/ui@^0.2.1"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/default/world-breadcrumbs/world-breadcrumbs.tsx",
      "content": "\"use client\";\n\nimport {\n  type ComponentPropsWithoutRef,\n  forwardRef,\n  type ReactNode,\n} from \"react\";\n\nimport { cn } from \"@vllnt/ui\";\n\n/**\n * One spatial trail crumb.\n *\n * @public\n */\nexport type WorldCrumb = {\n  /** Stable identifier — used as the React key. */\n  id: string;\n  /** Optional kind (drives the leading glyph). */\n  kind?: WorldCrumbKind;\n  /** Display label. */\n  label: ReactNode;\n};\n\n/**\n * Glyph hint for a crumb kind.\n *\n * @public\n */\nexport type WorldCrumbKind =\n  | \"agent\"\n  | \"artifact\"\n  | \"group\"\n  | \"run\"\n  | \"task\"\n  | \"world\";\n\nconst KIND_GLYPH: Record<WorldCrumbKind, string> = {\n  agent: \"◇\",\n  artifact: \"◌\",\n  group: \"▤\",\n  run: \"▶\",\n  task: \"▢\",\n  world: \"✦\",\n};\n\n/**\n * Localizable strings.\n *\n * @public\n */\nexport type WorldBreadcrumbsLabels = {\n  /** Empty-state copy. Defaults to `\"No location\"`. */\n  empty?: string;\n  /** Aria-label override. Defaults to `\"World breadcrumbs\"`. */\n  region?: string;\n};\n\nconst DEFAULT_LABELS = {\n  empty: \"No location\",\n  region: \"World breadcrumbs\",\n} as const satisfies Required<WorldBreadcrumbsLabels>;\n\n/**\n * Props for {@link WorldBreadcrumbs}.\n *\n * @public\n */\nexport type WorldBreadcrumbsProps = {\n  /** Trail in render order — the last crumb represents the active location. */\n  crumbs: WorldCrumb[];\n  /** Localizable strings. */\n  labels?: WorldBreadcrumbsLabels;\n  /** Click handler — receives the activated crumb id. */\n  onSelect?: (id: string) => void;\n} & ComponentPropsWithoutRef<\"nav\">;\n\nconst Crumb = (props: {\n  crumb: WorldCrumb;\n  isLast: boolean;\n  onSelect?: (id: string) => void;\n}): React.ReactElement => {\n  const { crumb, isLast, onSelect } = props;\n  const glyph = crumb.kind ? KIND_GLYPH[crumb.kind] : null;\n  const handleClick = (): void => {\n    onSelect?.(crumb.id);\n  };\n  const text = (\n    <span className=\"inline-flex items-center gap-1\">\n      {glyph ? (\n        <span aria-hidden=\"true\" className=\"text-muted-foreground\">\n          {glyph}\n        </span>\n      ) : null}\n      <span className=\"truncate\">{crumb.label}</span>\n    </span>\n  );\n  if (isLast || !onSelect) {\n    return (\n      <span\n        aria-current={isLast ? \"location\" : undefined}\n        className={cn(\n          \"inline-flex items-center text-xs\",\n          isLast ? \"font-semibold text-foreground\" : \"text-muted-foreground\",\n        )}\n        data-world-breadcrumb={crumb.id}\n        data-world-breadcrumb-active={isLast}\n      >\n        {text}\n      </span>\n    );\n  }\n  return (\n    <button\n      className=\"inline-flex items-center rounded-sm text-xs text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n      data-world-breadcrumb={crumb.id}\n      data-world-breadcrumb-active=\"false\"\n      onClick={handleClick}\n      type=\"button\"\n    >\n      {text}\n    </button>\n  );\n};\n\n/**\n * Spatial trail showing where the viewport sits in a hierarchy of\n * worlds / groups / runs / agents. Distinct from \\`Breadcrumb\\`\n * (route-based, document-tree style) — this primitive describes the\n * canvas's spatial location and supports per-kind glyphs.\n *\n * Pure presentation; the host computes the trail from the active\n * viewport target and the world graph, and resolves \\`onSelect\\` to a\n * camera transition.\n *\n * @example\n * ```tsx\n * <WorldBreadcrumbs\n *   crumbs={[\n *     { id: \"world\", kind: \"world\", label: \"Production\" },\n *     { id: \"group\", kind: \"group\", label: \"Ingest cluster\" },\n *     { id: \"run\",   kind: \"run\",   label: \"research-2025\" },\n *   ]}\n *   onSelect={jumpTo}\n * />\n * ```\n *\n * @public\n */\nexport const WorldBreadcrumbs = forwardRef<HTMLElement, WorldBreadcrumbsProps>(\n  (props, ref) => {\n    const { className, crumbs, labels, onSelect, ...rest } = props;\n    const resolvedLabels = { ...DEFAULT_LABELS, ...labels };\n    if (crumbs.length === 0) {\n      return (\n        <nav\n          aria-label={resolvedLabels.region}\n          className={cn(\n            \"inline-flex items-center text-xs text-muted-foreground\",\n            className,\n          )}\n          data-world-breadcrumbs\n          data-world-breadcrumbs-state=\"empty\"\n          ref={ref}\n          {...rest}\n        >\n          {resolvedLabels.empty}\n        </nav>\n      );\n    }\n    return (\n      <nav\n        aria-label={resolvedLabels.region}\n        className={cn(\n          \"inline-flex items-center gap-1.5 text-xs text-muted-foreground\",\n          className,\n        )}\n        data-world-breadcrumbs\n        ref={ref}\n        {...rest}\n      >\n        {crumbs.map((crumb, index) => (\n          <span className=\"inline-flex items-center gap-1.5\" key={crumb.id}>\n            <Crumb\n              crumb={crumb}\n              isLast={index === crumbs.length - 1}\n              onSelect={onSelect}\n            />\n            {index < crumbs.length - 1 ? (\n              <span\n                aria-hidden=\"true\"\n                className=\"text-muted-foreground/60\"\n                data-world-breadcrumb-sep\n              >\n                ›\n              </span>\n            ) : null}\n          </span>\n        ))}\n      </nav>\n    );\n  },\n);\nWorldBreadcrumbs.displayName = \"WorldBreadcrumbs\";\n",
      "type": "registry:component"
    }
  ],
  "version": "0.2.1",
  "stability": "stable"
}
