{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "core-diagnostic-overlay",
  "type": "registry:ui",
  "title": "Diagnostic Overlay",
  "description": "How a developer actually reaches the diagnostic panel: right-click the face, or press Ctrl/Cmd+Shift+D. It owns everything the panel deliberately does not — whether the panel may be shown at all, the context menu (Open diagnostics / Copy runtime report / Reset counters), the resizable drawer docked right or bottom, the per-viewer tab and placement preferences, and the session's open/close lifecycle, so a closed panel costs nothing on the audio thread. The drawer is portalled into the face surface and absolutely positioned, so opening it never reflows the face. Right-clicks on text-editing islands, on module-owned [data-context-menu=\"browser\"] targets and inside nested module context menus keep their own menu.",
  "dependencies": [
    "@base-ui/react",
    "@webgpu/types",
    "maruaudio@>=0.0.3 <0.1.0"
  ],
  "registryDependencies": [
    "https://pluginui.com/r/core-diagnostic-panel.json"
  ],
  "files": [
    {
      "path": "components/ui/diagnostic-overlay.tsx",
      "content": "/**\n * Source: https://maru.audio/ui-kit/diagnostic-overlay\n * Copyright © [Maru](https://maru.audio)\n *\n * Maru UI Kit — https://maru.audio/ui-kit\n *\n * Installed from the Maru UI registry. This file is yours now: edit it\n * freely, it will not be overwritten unless you re-run the add command.\n *\n * Keep this item’s companion files and CSS imports together. Dependencies\n * declared by the registry are installed with the source.\n */\n/**\n * `DiagnosticOverlay` — the way a developer actually reaches the diagnostic\n * panel: right-click the face, or press Ctrl/Cmd+Shift+D.\n *\n * It owns everything the panel deliberately does not: when the panel may be\n * shown at all, the context menu, the keyboard shortcut, the modal's\n * per-viewer preferences, and the session's open/close lifecycle.\n * `DiagnosticPanel` stays a controlled view of a snapshot, so it can also be\n * embedded whole in a docs page or a test.\n *\n * ## When the overlay is shown\n *\n * The rule, in one place so no host has to re-derive it:\n *\n * ```\n * policy !== \"never\" AND (\n *      policy === \"always\"\n *   OR snapshot.identity?.build.mode === \"development\"\n *   OR snapshot.connection === \"dev-runner\"\n *   OR (snapshot.identity === undefined AND snapshot.connection === \"disconnected\")\n * )\n * ```\n *\n * `\"never\"` wins outright — a bundle built with diagnostics off must have no\n * path to the panel, and DIAG-004's production assertion greps for this file's\n * marker attribute to prove the chunk is absent entirely.\n *\n * The last clause is the standalone-dev-preview case: a face rendered with no\n * bridge at all (a docs page, a Vite preview, a unit test) reports no identity\n * and a `disconnected` connection. That is a developer looking at their own\n * face, so the panel is available. It is deliberately *not* the same as a\n * production plugin whose host simply never sent an identity block — that host\n * reports `native`, not `disconnected`, and gets nothing.\n *\n * ## The marker attribute\n *\n * The modal root carries `data-diagnostic-overlay`. `assertProductionBrowserBundle`\n * (DIAG-004) asserts that string is absent from a `\"never\"` bundle, so it must\n * appear literally in this module and nowhere else in a shipped face.\n */\n\nimport {\n  useCallback,\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n  type CSSProperties,\n  type ReactNode,\n} from \"react\"\nimport { Dialog } from \"@base-ui/react/dialog\"\nimport { isTextTarget } from \"maruaudio/ui/shared/computer-keyboard\"\nimport type {\n  DiagnosticSession,\n  DiagnosticSnapshot,\n} from \"maruaudio/ui/shared/maru/diagnostic-session\"\nimport type { AudioModuleLatencyPlan, ParamSchema } from \"maruaudio/ui/shared/maru/contracts\"\n\nimport {\n  ContextMenuTarget,\n  isModuleFaceEditableTarget,\n} from \"maruaudio/ui/shared/maru/module-face-interactions\"\nimport { token } from \"maruaudio/ui/shared/theme\"\nimport { DiagnosticPanel } from \"@/components/ui/diagnostic-panel\"\nimport {\n  resolveDiagnosticTab,\n  type DiagnosticTabId,\n} from \"maruaudio/ui/shared/diagnostic-panel-core\"\nimport { writeClipboard } from \"@/components/ui/diagnostic-tabs-live\"\n\n/** Bundle-level policy, mirrored from `plugin.config.json` `ui.diagnostics`. */\nexport type DiagnosticPolicy = \"development\" | \"always\" | \"never\"\n\n/** @deprecated Diagnostics now use one centered viewport modal. */\nexport type DiagnosticPlacement = \"right\" | \"bottom\"\n\n/** Props `HostedModuleFace` passes when it mounts the overlay. Kept as a named\n * type so DIAG-004's generated template can type its explicit import. */\nexport interface DiagnosticOverlayProps {\n  readonly session: DiagnosticSession\n  readonly snapshot: DiagnosticSnapshot\n  readonly policy?: DiagnosticPolicy\n  /** Package-time graph timing metadata for the optional Latency debugger. */\n  readonly latencyPlan?: AudioModuleLatencyPlan\n  /** The module's authored parameter descriptors; no diagnostic wire copy. */\n  readonly schema?: ParamSchema\n  /** Storage key prefix, so two faces on one page keep separate preferences. */\n  readonly storageKey?: string\n  /** Rendered inside the surface as the menu target. Omit when the overlay is\n   * mounted beside the face rather than around it. */\n  readonly children?: ReactNode\n}\n\nconst STORAGE_PREFIX = \"maru.diagnostics\"\n\n/**\n * The show rule, exported so hosts and tests assert on the same function\n * rather than on a re-implementation. See the module doc comment.\n */\nexport function shouldShowDiagnostics(\n  policy: DiagnosticPolicy,\n  snapshot: Pick<DiagnosticSnapshot, \"identity\" | \"connection\">\n): boolean {\n  if (policy === \"never\") return false\n  if (policy === \"always\") return true\n  if (snapshot.identity?.build.mode === \"development\") return true\n  if (snapshot.connection === \"dev-runner\") return true\n  // Standalone dev preview: no bridge at all, so nobody can be harmed by a\n  // panel and a developer is certainly the one looking.\n  return (\n    snapshot.identity === undefined && snapshot.connection === \"disconnected\"\n  )\n}\n\n/**\n * True for targets whose own context menu must win over the diagnostics one.\n *\n * Text-editing islands keep the platform menu (cut/copy/paste is not something\n * a diagnostics panel should shadow); `[data-context-menu=\"browser\"]` is the\n * face's own opt-out, already honoured by `ModuleFaceInteractionSurface`; and a\n * nested `[data-context-menu-target]` is a module that built its own menu and\n * would otherwise be silently replaced by this one.\n */\nexport function isDiagnosticMenuExempt(\n  target: EventTarget | null,\n  /** The overlay's own menu wrapper, so its own target does not exempt it. */\n  ownMenuRoot?: Element | null\n): boolean {\n  if (isModuleFaceEditableTarget(target)) return true\n  if (!(target instanceof Element)) return false\n  if (target.closest('[data-context-menu=\"browser\"]') !== null) return true\n  // An open menu — this overlay's own included — keeps its own right-click\n  // behaviour rather than re-opening the diagnostics menu on top of itself.\n  if (target.closest(\"[data-module-context-menu]\") !== null) return true\n  const nested = target.closest(\"[data-context-menu-target]\")\n  // A nested target is a module's own menu; the overlay's wrapper is not.\n  return nested !== null && nested !== ownMenuRoot\n}\n\n/** Fallback host for the right-click listener when a bare preview mounts the\n * overlay outside a `[data-module-face-surface]`. This is only the menu host;\n * the visible diagnostics modal always portals to `document.body`. */\nfunction nearestPositionedAncestor(from: HTMLElement): HTMLElement | null {\n  if (typeof getComputedStyle !== \"function\") return null\n  let node: HTMLElement | null = from.parentElement\n  while (node) {\n    if (getComputedStyle(node).position !== \"static\") return node\n    node = node.parentElement\n  }\n  return from.ownerDocument?.documentElement ?? null\n}\n\n/** localStorage read that survives a disabled/absent/corrupt store. */\nfunction readStored(key: string): string | null {\n  try {\n    if (typeof localStorage === \"undefined\") return null\n    return localStorage.getItem(key)\n  } catch {\n    return null\n  }\n}\n\nfunction writeStored(key: string, value: string): void {\n  try {\n    if (typeof localStorage === \"undefined\") return\n    localStorage.setItem(key, value)\n  } catch {\n    // A private window, a blocked store, a quota — none of them are worth\n    // failing a diagnostic panel over.\n  }\n}\n\nexport function DiagnosticOverlay({\n  session,\n  snapshot,\n  policy = \"development\",\n  latencyPlan,\n  schema,\n  storageKey = STORAGE_PREFIX,\n  children,\n}: DiagnosticOverlayProps) {\n  const enabled = shouldShowDiagnostics(policy, snapshot)\n\n  const [open, setOpen] = useState(false)\n  const [tab, setTab] = useState<DiagnosticTabId>(() =>\n    resolveDiagnosticTab(readStored(`${storageKey}.tab`))\n  )\n  const rootRef = useRef<HTMLDivElement>(null)\n  const dialogRef = useRef<HTMLDivElement>(null)\n\n  const show = useCallback(() => setOpen(true), [])\n\n  // Feeds stream only while the modal is visible; close() on hide and on\n  // unmount is what keeps a closed panel free on the audio thread.\n  useEffect(() => {\n    if (!enabled || !open) return\n    session.open()\n    return () => session.close()\n  }, [enabled, open, session])\n\n  useEffect(() => writeStored(`${storageKey}.tab`, tab), [storageKey, tab])\n\n  // Ctrl/Cmd+Shift+D toggles. Document bubble runs after local controls and\n  // before the frame relay; ignored while the policy hides the panel. Escape\n  // belongs to Base UI Dialog while open, which supplies modal-aware dismissal.\n  useEffect(() => {\n    if (!enabled) return\n    const onKeyDown = (event: KeyboardEvent) => {\n      if (event.defaultPrevented || event.isComposing || isTextTarget(event.target)) return\n      if (\n        (event.metaKey || event.ctrlKey) &&\n        event.shiftKey &&\n        (event.key === \"D\" || event.key === \"d\")\n      ) {\n        event.preventDefault()\n        setOpen((current) => !current)\n      }\n    }\n    document.addEventListener(\"keydown\", onKeyDown)\n    return () => document.removeEventListener(\"keydown\", onKeyDown)\n  }, [enabled])\n\n  // Right-click anywhere on the face, including when the overlay wraps nothing.\n  //\n  // `ContextMenuTarget` binds its handler to its own root, which works only\n  // when the overlay wraps the face. Every non-`HostedModuleFace` host mounts\n  // it as a childless SIBLING inside the surface (the website, the dev apps),\n  // so that root contains nothing and no right-click ever reaches it. The\n  // listener below closes that gap generically: it attaches to the enclosing\n  // `[data-module-face-surface]` and re-dispatches the gesture onto the\n  // overlay's own menu root, so both mount shapes end up in\n  // exactly one menu implementation rather than two that can disagree.\n  //\n  // Capture phase, because `ModuleFaceInteractionSurface` preventDefaults the\n  // event on the way back up. A nested ContextMenuTarget is only EXEMPTED here:\n  // the event continues down to that nearest owner, which opens its own menu\n  // and stops the bubble. Stopping during capture would prevent the nested\n  // knob/fader menu from ever seeing the event.\n  useEffect(() => {\n    if (!enabled) return\n    const root = rootRef.current\n    if (!root) return\n    const surface =\n      root.closest<HTMLElement>(\"[data-module-face-surface]\") ??\n      nearestPositionedAncestor(root)\n    if (!surface) return\n\n    const onContextMenu = (event: MouseEvent) => {\n      if (event.defaultPrevented) return\n      const menuRoot = root.querySelector<HTMLElement>(\n        \":scope > [data-context-menu-target]\"\n      )\n      if (!menuRoot) return\n      // The re-dispatch below lands back here; let it through to the menu.\n      if (event.target instanceof Node && menuRoot.contains(event.target))\n        return\n      if (isDiagnosticMenuExempt(event.target, menuRoot)) return\n      event.preventDefault()\n      // Hand the gesture to ContextMenuTarget at the same point. Its own\n      // handler reads clientX/clientY, so the menu opens under the pointer.\n      //\n      // `bubbles: true` is required, not cosmetic: React attaches its\n      // delegated listeners at the root container rather than on the element,\n      // so a non-bubbling event dispatched at the menu root never reaches the\n      // `onContextMenu` prop at all. The guard above lets this re-dispatch\n      // back through untouched.\n      menuRoot.dispatchEvent(\n        new MouseEvent(\"contextmenu\", {\n          bubbles: true,\n          cancelable: true,\n          clientX: event.clientX,\n          clientY: event.clientY,\n        })\n      )\n    }\n    surface.addEventListener(\"contextmenu\", onContextMenu, true)\n    return () => surface.removeEventListener(\"contextmenu\", onContextMenu, true)\n  }, [enabled])\n\n  const copyReport = useCallback(() => {\n    void writeClipboard(JSON.stringify(session.buildLocalReport(), null, 2))\n  }, [session])\n\n  const actions = useMemo(\n    () => [\n      { id: \"open\", label: \"Open diagnostics\", onSelect: show },\n      { id: \"copy\", label: \"Copy runtime report\", onSelect: copyReport },\n      {\n        id: \"reset\",\n        label: \"Reset counters\",\n        onSelect: () => session.stimulate({ kind: \"resetCounters\" }),\n      },\n    ],\n    [copyReport, session, show]\n  )\n\n  if (!enabled) return <>{children}</>\n\n  // Base UI portals to document.body by default, matching the prior modal's\n  // viewport escape from face transforms, clipping and stacking contexts.\n  // All positioning/paint remains inline so native webviews need no stylesheet.\n  const initialFocus = () =>\n    dialogRef.current?.querySelector<HTMLElement>(\n      '[role=\"tab\"][aria-selected=\"true\"]'\n    ) ?? false\n\n  return (\n    <>\n      <div ref={rootRef} style={{ display: \"contents\" }}>\n        <ContextMenuTarget\n          actions={actions}\n          includeAmbientActions\n          style={{ display: \"contents\" }}\n        >\n          {children}\n        </ContextMenuTarget>\n      </div>\n      <Dialog.Root open={open} onOpenChange={setOpen}>\n        <Dialog.Portal>\n          <Dialog.Backdrop\n            style={{\n              position: \"fixed\",\n              inset: 0,\n              zIndex: 2147483000,\n              background: \"rgb(6 8 12 / 0.68)\",\n              backdropFilter: \"blur(8px)\",\n            }}\n          />\n          <Dialog.Popup\n            ref={dialogRef}\n            data-diagnostic-modal\n            data-diagnostic-overlay\n            aria-label=\"Module diagnostics\"\n            initialFocus={initialFocus}\n            finalFocus={true}\n            style={{\n              position: \"fixed\",\n              top: \"50%\",\n              left: \"50%\",\n              zIndex: 2147483001,\n              display: \"flex\",\n              width: \"min(980px, calc(100vw - 32px))\",\n              height: \"min(720px, calc(100dvh - 32px))\",\n              maxHeight: \"calc(100dvh - 32px)\",\n              minWidth: 0,\n              minHeight: 0,\n              transform: \"translate(-50%, -50%)\",\n              overflow: \"hidden\",\n              border: `1px solid ${token.border}`,\n              borderRadius: 12,\n              background: token.surface,\n              boxShadow:\n                \"0 24px 80px rgb(0 0 0 / 0.52), 0 0 0 1px rgb(255 255 255 / 0.04)\",\n            }}\n          >\n            <div\n              style={{\n                flex: \"1 1 auto\",\n                minWidth: 0,\n                minHeight: 0,\n                display: \"flex\",\n              }}\n            >\n              <DiagnosticPanel\n                session={session}\n                snapshot={snapshot}\n                latencyPlan={latencyPlan}\n                schema={schema}\n                tab={tab}\n                onTabChange={setTab}\n                live={open}\n                style={{ flex: \"1 1 auto\", minWidth: 0 }}\n                headerActions={\n                  <Dialog.Close\n                    type=\"button\"\n                    aria-label=\"Close diagnostics\"\n                    style={headerButtonStyle}\n                  >\n                    ✕\n                  </Dialog.Close>\n                }\n              />\n            </div>\n          </Dialog.Popup>\n        </Dialog.Portal>\n      </Dialog.Root>\n    </>\n  )\n}\n\nconst headerButtonStyle: CSSProperties = {\n  appearance: \"none\",\n  border: `1px solid ${token.border}`,\n  borderRadius: 4,\n  background: \"transparent\",\n  color: token.textMuted,\n  cursor: \"pointer\",\n  font: `11px/1 ${token.font}`,\n  padding: \"3px 6px\",\n}\n\nexport default DiagnosticOverlay\n",
      "type": "registry:component",
      "target": "@ui/diagnostic-overlay.tsx"
    }
  ]
}
