@json-render/devtools 0.19.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +21 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +21 -12
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/event-store.ts","../src/prod-guard.ts","../src/panel/dom.ts","../src/picker.ts","../src/panel/styles.ts","../src/panel/shell.ts","../src/panel/types.ts","../src/panel/tabs/spec.ts","../src/panel/tabs/state.ts","../src/panel/tabs/actions.ts","../src/panel/tabs/stream.ts","../src/panel/tabs/catalog.ts","../src/panel/tabs/picker.ts","../src/stream-tap.ts"],"sourcesContent":["import type { DevtoolsEvent } from \"./types\";\n\n/**\n * Options for {@link createEventStore}.\n */\nexport interface EventStoreOptions {\n /** Max events to retain. Older events are dropped. Default: 500. */\n bufferSize?: number;\n}\n\n/**\n * A capped, subscribable ring buffer of {@link DevtoolsEvent}s.\n *\n * Core to every devtools panel — all adapters push into the same store,\n * and panel UIs subscribe for render updates.\n */\nexport interface EventStore {\n /** Append an event. May drop the oldest event if the buffer is full. */\n push: (event: DevtoolsEvent) => void;\n /**\n * Current events in insertion order (oldest first). Returns a fresh\n * array so callers can treat it as immutable.\n */\n snapshot: () => DevtoolsEvent[];\n /**\n * Register a listener invoked after every push (or `clear`). Returns\n * an unsubscribe function. Listeners are invoked synchronously.\n */\n subscribe: (listener: () => void) => () => void;\n /** Remove all events. Notifies listeners. */\n clear: () => void;\n /** Current event count. */\n size: () => number;\n}\n\n/**\n * Create an in-memory ring-buffered event store.\n *\n * @example\n * ```ts\n * const store = createEventStore({ bufferSize: 200 });\n * const unsub = store.subscribe(() => render(store.snapshot()));\n * store.push({ kind: \"state-set\", at: Date.now(), path: \"/x\", prev: 1, next: 2 });\n * ```\n */\nexport function createEventStore(options: EventStoreOptions = {}): EventStore {\n const bufferSize = Math.max(1, options.bufferSize ?? 500);\n const events: DevtoolsEvent[] = [];\n const listeners = new Set<() => void>();\n\n function notify() {\n for (const listener of listeners) {\n try {\n listener();\n } catch (err) {\n if (process.env.NODE_ENV !== \"production\") {\n console.error(\"[json-render devtools] listener threw:\", err);\n }\n }\n }\n }\n\n return {\n push(event) {\n events.push(event);\n if (events.length > bufferSize) {\n events.splice(0, events.length - bufferSize);\n }\n notify();\n },\n snapshot() {\n return events.slice();\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n clear() {\n if (events.length === 0) return;\n events.length = 0;\n notify();\n },\n size() {\n return events.length;\n },\n };\n}\n","/**\n * Production guard. Framework adapters short-circuit to a no-op when this\n * returns true, so dropping `<JsonRenderDevtools />` into an app costs\n * nothing in production builds.\n *\n * Tree-shaken bundlers will fold constant `process.env.NODE_ENV` checks.\n * Consumers that run in browsers without `process` also work because the\n * typeof check guards the access.\n */\nexport function isProduction(): boolean {\n if (typeof process !== \"undefined\" && process.env) {\n return process.env.NODE_ENV === \"production\";\n }\n return false;\n}\n","/**\n * Tiny hyperscript-style helper for building DOM nodes without JSX.\n *\n * Keeps the vanilla-TS panel readable. Supports attributes starting with\n * `on` as event listeners, `className`, inline `style` objects, and a mix\n * of string / node / array children.\n */\n\ntype Child = Node | string | number | null | undefined | false | Child[];\n\ntype Attrs = {\n [key: string]: unknown;\n className?: string;\n style?: Partial<CSSStyleDeclaration>;\n};\n\nfunction appendChild(parent: Node, child: Child): void {\n if (child === null || child === undefined || child === false) return;\n if (Array.isArray(child)) {\n for (const c of child) appendChild(parent, c);\n return;\n }\n if (child instanceof Node) {\n parent.appendChild(child);\n return;\n }\n parent.appendChild(document.createTextNode(String(child)));\n}\n\nexport function h<K extends keyof HTMLElementTagNameMap>(\n tag: K,\n attrs?: Attrs | null,\n ...children: Child[]\n): HTMLElementTagNameMap[K] {\n const el = document.createElement(tag);\n if (attrs) {\n for (const [key, value] of Object.entries(attrs)) {\n if (value === null || value === undefined || value === false) continue;\n if (key === \"className\") {\n el.className = String(value);\n } else if (key === \"style\" && typeof value === \"object\") {\n Object.assign(el.style, value as Partial<CSSStyleDeclaration>);\n } else if (key.startsWith(\"on\") && typeof value === \"function\") {\n el.addEventListener(key.slice(2).toLowerCase(), value as EventListener);\n } else if (key === \"dataset\" && typeof value === \"object\") {\n for (const [dk, dv] of Object.entries(\n value as Record<string, string>,\n )) {\n el.dataset[dk] = String(dv);\n }\n } else if (typeof value === \"boolean\") {\n if (value) el.setAttribute(key, \"\");\n } else {\n el.setAttribute(key, String(value));\n }\n }\n }\n for (const child of children) appendChild(el, child);\n return el;\n}\n\n/** Replace the children of `parent` with `next`, clearing first. */\nexport function replaceChildren(parent: Node, ...next: Child[]): void {\n while (parent.firstChild) parent.removeChild(parent.firstChild);\n for (const n of next) appendChild(parent, n);\n}\n\n/** Render a short JSON preview that truncates long values. */\nexport function jsonPreview(value: unknown, max = 140): string {\n let text: string;\n try {\n text = JSON.stringify(value);\n } catch {\n text = String(value);\n }\n if (text === undefined) return \"undefined\";\n if (text.length > max) return text.slice(0, max - 1) + \"\\u2026\";\n return text;\n}\n\n/** Format an absolute timestamp (ms) as `HH:MM:SS.mmm`. */\nexport function formatTime(at: number): string {\n const d = new Date(at);\n const hh = String(d.getHours()).padStart(2, \"0\");\n const mm = String(d.getMinutes()).padStart(2, \"0\");\n const ss = String(d.getSeconds()).padStart(2, \"0\");\n const ms = String(d.getMilliseconds()).padStart(3, \"0\");\n return `${hh}:${mm}:${ss}.${ms}`;\n}\n","import type { PickerOptions, PickerSession } from \"./types\";\n\n/**\n * Attribute the ElementRenderer (when devtools is active) sets on each\n * rendered element's wrapper. The picker walks up from the hovered node\n * to the nearest ancestor bearing this attribute.\n */\nexport const DEVTOOLS_KEY_ATTR = \"data-jr-key\";\n\nconst PICKER_OVERLAY_ID = \"__jr_devtools_picker_overlay\";\nconst PICKER_LABEL_ID = \"__jr_devtools_picker_label\";\nconst HOVER_OVERLAY_ID = \"__jr_devtools_hover_overlay\";\nconst HOVER_LABEL_ID = \"__jr_devtools_hover_label\";\n\n// ---------------------------------------------------------------------------\n// Shared geometry helper\n// ---------------------------------------------------------------------------\n\n/**\n * Compute a bounding rect for a (possibly `display: contents`) element by\n * falling back to the union of its descendants' client rects.\n *\n * json-render wraps every keyed element in `<span data-jr-key=\"...\" style\n * =\"display:contents\">`, and `display: contents` elements don't generate a\n * CSS box — so their own `getBoundingClientRect()` returns `0 × 0` and a\n * plain CSS outline paints nothing. We recursively widen to child boxes so\n * the overlay tracks the visible extent.\n */\nfunction computeBounds(el: Element): DOMRect | null {\n const own = el.getBoundingClientRect();\n if (own.width > 0 && own.height > 0) return own;\n let left = Infinity;\n let top = Infinity;\n let right = -Infinity;\n let bottom = -Infinity;\n const walker = document.createTreeWalker(el, NodeFilter.SHOW_ELEMENT);\n let node = walker.nextNode() as Element | null;\n while (node) {\n const r = node.getBoundingClientRect();\n if (r.width > 0 && r.height > 0) {\n if (r.left < left) left = r.left;\n if (r.top < top) top = r.top;\n if (r.right > right) right = r.right;\n if (r.bottom > bottom) bottom = r.bottom;\n }\n node = walker.nextNode() as Element | null;\n }\n if (!Number.isFinite(left) || !Number.isFinite(top)) return null;\n return new DOMRect(left, top, right - left, bottom - top);\n}\n\n/**\n * Position an overlay + label pair over a given rect. Both elements are\n * created on demand inside `document.body`; callers pass in the ids so the\n * picker and the tree-hover highlight don't collide.\n */\nfunction paintOverlay(\n rect: DOMRect,\n label: string,\n ids: { overlay: string; label: string },\n): { overlay: HTMLDivElement; label: HTMLDivElement } {\n let ov = document.getElementById(ids.overlay) as HTMLDivElement | null;\n if (!ov) {\n ov = document.createElement(\"div\");\n ov.id = ids.overlay;\n document.body.appendChild(ov);\n }\n ov.style.display = \"block\";\n ov.style.left = `${rect.left}px`;\n ov.style.top = `${rect.top}px`;\n ov.style.width = `${rect.width}px`;\n ov.style.height = `${rect.height}px`;\n\n let lb = document.getElementById(ids.label) as HTMLDivElement | null;\n if (!lb) {\n lb = document.createElement(\"div\");\n lb.id = ids.label;\n document.body.appendChild(lb);\n }\n lb.textContent = label;\n lb.style.display = \"block\";\n const labelLeft = Math.max(4, rect.left);\n // Prefer the label above the overlay, fall back to below when the element\n // is flush against the viewport top.\n const labelTop = rect.top >= 24 ? rect.top - 22 : rect.top + rect.height + 4;\n lb.style.left = `${labelLeft}px`;\n lb.style.top = `${labelTop}px`;\n return { overlay: ov, label: lb };\n}\n\nfunction hideOverlayPair(ids: { overlay: string; label: string }): void {\n const ov = document.getElementById(ids.overlay);\n const lb = document.getElementById(ids.label);\n if (ov) ov.style.display = \"none\";\n if (lb) lb.style.display = \"none\";\n}\n\nfunction removeOverlayPair(ids: { overlay: string; label: string }): void {\n const ov = document.getElementById(ids.overlay);\n const lb = document.getElementById(ids.label);\n if (ov) ov.remove();\n if (lb) lb.remove();\n}\n\n// ---------------------------------------------------------------------------\n// Picker — click-to-pick session started by the toolbar button\n// ---------------------------------------------------------------------------\n\n/**\n * Start an interactive DOM picker. The user hovers or clicks any element\n * in the page; when a click lands on (or inside) a node carrying\n * {@link DEVTOOLS_KEY_ATTR}, `onPick` fires with that key.\n *\n * Returns `null` in environments without a DOM (SSR, tests).\n *\n * The picker paints a translucent overlay + border over the hovered\n * element (Chrome-DevTools style). See {@link computeBounds} for the\n * `display: contents` fallback.\n */\nexport function startPicker(options: PickerOptions): PickerSession | null {\n if (typeof document === \"undefined\") return null;\n\n const IDS = { overlay: PICKER_OVERLAY_ID, label: PICKER_LABEL_ID };\n let currentHover: Element | null = null;\n\n function paint(el: Element) {\n const rect = computeBounds(el);\n if (!rect) {\n hideOverlayPair(IDS);\n return;\n }\n const key = el.getAttribute(DEVTOOLS_KEY_ATTR) ?? \"\";\n paintOverlay(\n rect,\n `${key} ${Math.round(rect.width)} × ${Math.round(rect.height)}`,\n IDS,\n );\n }\n\n const onMove = (ev: MouseEvent) => {\n const target = ev.target as Element | null;\n if (!target || !target.closest) return;\n const host = target.closest(`[${DEVTOOLS_KEY_ATTR}]`);\n if (host !== currentHover) currentHover = host;\n if (host) paint(host);\n else hideOverlayPair(IDS);\n };\n\n const onClick = (ev: MouseEvent) => {\n ev.preventDefault();\n ev.stopPropagation();\n const target = ev.target as Element | null;\n const host = target?.closest?.(`[${DEVTOOLS_KEY_ATTR}]`);\n if (host) {\n const key = host.getAttribute(DEVTOOLS_KEY_ATTR) ?? \"\";\n stop();\n options.onPick(key);\n }\n };\n\n const onKey = (ev: KeyboardEvent) => {\n if (ev.key === \"Escape\") {\n ev.preventDefault();\n stop();\n options.onCancel?.();\n }\n };\n\n // Keep the overlay glued to the element while the user scrolls, the\n // viewport resizes, or the DOM reflows (e.g. streaming patches arrive\n // during pick).\n const onReposition = () => {\n if (currentHover && currentHover.isConnected) {\n paint(currentHover);\n } else if (currentHover) {\n currentHover = null;\n hideOverlayPair(IDS);\n }\n };\n\n function stop() {\n removeOverlayPair(IDS);\n currentHover = null;\n document.documentElement.removeAttribute(\"data-jr-devtools-picking\");\n document.removeEventListener(\"mousemove\", onMove, true);\n document.removeEventListener(\"click\", onClick, true);\n document.removeEventListener(\"keydown\", onKey, true);\n window.removeEventListener(\"scroll\", onReposition, true);\n window.removeEventListener(\"resize\", onReposition);\n }\n\n document.documentElement.setAttribute(\"data-jr-devtools-picking\", \"true\");\n document.addEventListener(\"mousemove\", onMove, true);\n document.addEventListener(\"click\", onClick, true);\n document.addEventListener(\"keydown\", onKey, true);\n window.addEventListener(\"scroll\", onReposition, true);\n window.addEventListener(\"resize\", onReposition);\n\n return { stop };\n}\n\n// ---------------------------------------------------------------------------\n// Hover highlight — persistent overlay driven by spec-tree hover\n// ---------------------------------------------------------------------------\n\nconst HOVER_IDS = { overlay: HOVER_OVERLAY_ID, label: HOVER_LABEL_ID };\n/**\n * Class (not id) used for the *secondary* overlays that paint the extra\n * instances of a repeated element. Styled by HOST_CSS with a dashed amber\n * outline so they're clearly distinguished from the single primary hover.\n */\nconst HOVER_EXTRA_CLASS = \"__jr_devtools_hover_extra\";\nlet hoverKey: string | null = null;\nlet hoverListenersAttached = false;\nlet hoverExtraOverlays: HTMLDivElement[] = [];\n\nfunction ensureExtraOverlay(index: number): HTMLDivElement {\n let ov = hoverExtraOverlays[index];\n if (!ov) {\n ov = document.createElement(\"div\");\n ov.className = HOVER_EXTRA_CLASS;\n document.body.appendChild(ov);\n hoverExtraOverlays[index] = ov;\n }\n return ov;\n}\n\nfunction hideExtrasFrom(index: number): void {\n for (let i = index; i < hoverExtraOverlays.length; i++) {\n const ov = hoverExtraOverlays[i];\n if (ov) ov.style.display = \"none\";\n }\n}\n\nfunction removeAllExtras(): void {\n for (const ov of hoverExtraOverlays) ov.remove();\n hoverExtraOverlays = [];\n}\n\nfunction repositionHover() {\n if (!hoverKey) return;\n const matches = findAllElementsByKey(hoverKey);\n const first = matches[0];\n if (!first) {\n hideOverlayPair(HOVER_IDS);\n hideExtrasFrom(0);\n return;\n }\n\n // Primary overlay + label paints the first match.\n const firstRect = computeBounds(first);\n if (!firstRect) {\n hideOverlayPair(HOVER_IDS);\n hideExtrasFrom(0);\n return;\n }\n const labelSuffix =\n matches.length > 1 ? ` (${matches.length} instances)` : \"\";\n paintOverlay(\n firstRect,\n `${hoverKey} ${Math.round(firstRect.width)} × ${Math.round(firstRect.height)}${labelSuffix}`,\n HOVER_IDS,\n );\n\n // Extra instances (for repeated elements) get their own overlays,\n // styled in amber to distinguish from the primary.\n for (let i = 1; i < matches.length; i++) {\n const el = matches[i];\n if (!el) continue;\n const rect = computeBounds(el);\n const ov = ensureExtraOverlay(i - 1);\n if (!rect) {\n ov.style.display = \"none\";\n continue;\n }\n ov.style.display = \"block\";\n ov.style.left = `${rect.left}px`;\n ov.style.top = `${rect.top}px`;\n ov.style.width = `${rect.width}px`;\n ov.style.height = `${rect.height}px`;\n }\n hideExtrasFrom(Math.max(0, matches.length - 1));\n}\n\nfunction attachHoverListeners() {\n if (hoverListenersAttached || typeof window === \"undefined\") return;\n hoverListenersAttached = true;\n window.addEventListener(\"scroll\", repositionHover, true);\n window.addEventListener(\"resize\", repositionHover);\n}\n\nfunction detachHoverListeners() {\n if (!hoverListenersAttached || typeof window === \"undefined\") return;\n hoverListenersAttached = false;\n window.removeEventListener(\"scroll\", repositionHover, true);\n window.removeEventListener(\"resize\", repositionHover);\n}\n\n/**\n * Show (or hide) a persistent bounding-box overlay over the element\n * identified by `key`. Pass `null` to clear the overlay.\n *\n * Unlike {@link highlightElement}, this does not fade out — callers are\n * expected to clear it explicitly (typically on `mouseleave`). Safe to\n * call repeatedly; each call cheaply repositions the single overlay.\n */\nexport function setHoverHighlight(key: string | null): void {\n if (typeof document === \"undefined\") return;\n if (!key) {\n hoverKey = null;\n removeOverlayPair(HOVER_IDS);\n removeAllExtras();\n detachHoverListeners();\n return;\n }\n hoverKey = key;\n repositionHover();\n attachHoverListeners();\n}\n\n// ---------------------------------------------------------------------------\n// Element lookup + brief flash highlight\n// ---------------------------------------------------------------------------\n\n/**\n * Look up the DOM element carrying `data-jr-key={key}`. Returns `null`\n * when no match (spec exists but hasn't rendered, or the element is\n * currently hidden by a visibility condition).\n *\n * Note: when an element appears inside a `repeat`, each repetition\n * renders its own DOM instance with the same `data-jr-key`. Use\n * {@link findAllElementsByKey} if you need all of them.\n */\nexport function findElementByKey(key: string): Element | null {\n if (typeof document === \"undefined\") return null;\n return document.querySelector(`[${DEVTOOLS_KEY_ATTR}=\"${cssEscape(key)}\"]`);\n}\n\n/**\n * Return every DOM element carrying `data-jr-key={key}`. Intended for\n * repeated spec elements (list items, grid cells…) where a single spec\n * key renders to N DOM instances.\n */\nexport function findAllElementsByKey(key: string): Element[] {\n if (typeof document === \"undefined\") return [];\n const selector = `[${DEVTOOLS_KEY_ATTR}=\"${cssEscape(key)}\"]`;\n return Array.from(document.querySelectorAll(selector));\n}\n\n/**\n * Briefly paint an outline around the DOM element for `key`, so clicking\n * a spec-tree row in the panel flashes its position in the page.\n *\n * The target is often a `display: contents` wrapper, so we build the\n * overlay from `computeBounds` (descendants' client rects) instead of\n * using a CSS outline on the target directly.\n */\nexport function highlightElement(key: string, durationMs = 1200): void {\n if (typeof document === \"undefined\") return;\n const el = findElementByKey(key);\n if (!el) return;\n const rect = computeBounds(el);\n if (!rect) return;\n\n const overlay = document.createElement(\"div\");\n overlay.className = \"__jr_devtools_highlight\";\n overlay.style.cssText = `\n position: fixed;\n left: ${rect.left}px;\n top: ${rect.top}px;\n width: ${rect.width}px;\n height: ${rect.height}px;\n outline: 2px solid #60a5fa;\n outline-offset: 2px;\n pointer-events: none;\n z-index: 2147483645;\n transition: opacity 0.25s ease-out;\n opacity: 1;\n `;\n document.body.appendChild(overlay);\n setTimeout(\n () => {\n overlay.style.opacity = \"0\";\n },\n Math.max(0, durationMs - 250),\n );\n setTimeout(() => {\n overlay.remove();\n }, durationMs);\n}\n\n/** Minimal CSS.escape fallback for environments without it. */\nfunction cssEscape(value: string): string {\n if (typeof CSS !== \"undefined\" && typeof CSS.escape === \"function\") {\n return CSS.escape(value);\n }\n return value.replace(/[\"\\\\]/g, \"\\\\$&\");\n}\n","/**\n * CSS for the devtools panel. Injected into the shadow root so nothing\n * leaks into or out of the host app. Theme values are defined on `:host`\n * so tabs can read them via `var(--jr-*)`.\n *\n * Tokens mirror the json-render playground's visual language: small mono\n * type, muted borders, compact paddings.\n */\nexport const PANEL_CSS = `\n:host {\n /* Light theme — default. Overridden by the dark-mode media query below\n so the panel follows the host OS's \\`prefers-color-scheme\\`. */\n --jr-bg: #ffffff;\n --jr-bg-muted: #f4f4f5;\n --jr-bg-soft: #fafafa;\n --jr-fg: #18181b;\n --jr-fg-muted: #52525b;\n --jr-fg-dim: #71717a;\n --jr-border: #e4e4e7;\n --jr-border-strong: #a1a1aa;\n --jr-accent: #2563eb;\n --jr-green: #16a34a;\n --jr-red: #dc2626;\n --jr-amber: #d97706;\n --jr-font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n --jr-font-ui: system-ui, -apple-system, \"Segoe UI\", sans-serif;\n all: initial;\n color-scheme: light dark;\n font-family: var(--jr-font-ui);\n color: var(--jr-fg);\n position: fixed;\n z-index: 2147483647;\n}\n\n@media (prefers-color-scheme: dark) {\n :host {\n --jr-bg: #09090b;\n --jr-bg-muted: #111113;\n --jr-bg-soft: #17171a;\n --jr-fg: #fafafa;\n --jr-fg-muted: #a1a1aa;\n --jr-fg-dim: #71717a;\n --jr-border: #27272a;\n --jr-border-strong: #3f3f46;\n --jr-accent: #60a5fa;\n --jr-green: #4ade80;\n --jr-red: #f87171;\n --jr-amber: #fbbf24;\n }\n}\n\n* {\n box-sizing: border-box;\n}\n\nbutton {\n font: inherit;\n color: inherit;\n background: transparent;\n border: 0;\n cursor: pointer;\n padding: 0;\n}\n\n/* Floating toggle — frosted dark-glass badge inspired by Next.js Dev Tools.\n Always dark regardless of OS \\`prefers-color-scheme\\` so the affordance\n reads the same on both light and dark hosts. */\n.jr-toggle {\n position: fixed;\n bottom: 20px;\n right: 20px;\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: 0;\n padding: 0;\n background: rgba(0, 0, 0, 0.8);\n -webkit-backdrop-filter: blur(48px);\n backdrop-filter: blur(48px);\n color: #ffffff;\n /* Triple layer: outer hard ring, inner subtle highlight, drop shadow. */\n box-shadow:\n 0 0 0 1px #171717,\n inset 0 0 0 1px hsla(0, 0%, 100%, 0.14),\n 0 16px 32px -8px rgba(0, 0, 0, 0.24);\n display: flex;\n align-items: center;\n justify-content: center;\n will-change: scale, background;\n transition:\n scale 150ms cubic-bezier(0.23, 0.88, 0.26, 0.92),\n background 150ms ease;\n}\n.jr-toggle[data-position=\"bottom-left\"] { right: auto; left: 20px; }\n.jr-toggle[data-position=\"right\"] { bottom: auto; top: 20px; }\n.jr-toggle:hover {\n background: rgba(20, 20, 20, 0.88);\n}\n.jr-toggle:active {\n scale: 0.95;\n}\n.jr-toggle[data-open=\"true\"] {\n box-shadow:\n 0 0 0 1px var(--jr-accent),\n inset 0 0 0 1px hsla(0, 0%, 100%, 0.14),\n 0 16px 32px -8px rgba(0, 0, 0, 0.24);\n}\n\n.jr-panel {\n position: fixed;\n background: var(--jr-bg);\n color: var(--jr-fg);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n font-family: var(--jr-font-ui);\n font-size: 12px;\n}\n\n.jr-panel[data-dock=\"bottom\"] {\n left: 0;\n right: 0;\n bottom: 0;\n height: var(--jr-panel-height, 380px);\n min-height: 180px;\n max-height: 90vh;\n border-top: 1px solid var(--jr-border);\n}\n\n.jr-panel[data-dock=\"right\"] {\n top: 0;\n right: 0;\n bottom: 0;\n width: var(--jr-panel-width, 440px);\n min-width: 260px;\n max-width: 90vw;\n border-left: 1px solid var(--jr-border);\n}\n\n.jr-panel[data-hidden=\"true\"] {\n display: none;\n}\n\n.jr-resize {\n position: absolute;\n z-index: 1;\n}\n.jr-panel[data-dock=\"bottom\"] .jr-resize {\n top: -3px;\n left: 0;\n right: 0;\n height: 6px;\n cursor: ns-resize;\n}\n.jr-panel[data-dock=\"right\"] .jr-resize {\n left: -3px;\n top: 0;\n bottom: 0;\n width: 6px;\n cursor: ew-resize;\n}\n\n.jr-header {\n display: flex;\n align-items: stretch;\n height: 36px;\n border-bottom: 1px solid var(--jr-border);\n flex-shrink: 0;\n background: var(--jr-bg);\n}\n\n.jr-title {\n display: flex;\n align-items: center;\n padding: 0 12px;\n font-family: var(--jr-font-mono);\n font-size: 11px;\n font-weight: 600;\n color: var(--jr-fg);\n border-right: 1px solid var(--jr-border);\n letter-spacing: 0.02em;\n}\n.jr-tabs {\n display: flex;\n flex: 1;\n min-width: 0;\n overflow-x: auto;\n}\n.jr-tab {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 0 12px;\n font-family: var(--jr-font-mono);\n font-size: 11px;\n color: var(--jr-fg-muted);\n background: transparent;\n border-right: 1px solid var(--jr-border);\n white-space: nowrap;\n transition: color 0.1s ease, background 0.1s ease;\n}\n.jr-tab:hover {\n color: var(--jr-fg);\n background: var(--jr-bg-muted);\n}\n.jr-tab[data-active=\"true\"] {\n color: var(--jr-fg);\n background: var(--jr-bg-muted);\n box-shadow: inset 0 -2px 0 var(--jr-accent);\n}\n.jr-tab-count {\n font-size: 10px;\n color: var(--jr-fg-dim);\n background: var(--jr-bg-soft);\n border-radius: 999px;\n padding: 1px 6px;\n}\n\n.jr-actions {\n display: flex;\n align-items: center;\n padding: 0 8px;\n gap: 4px;\n border-left: 1px solid var(--jr-border);\n}\n.jr-icon-btn {\n width: 26px;\n height: 26px;\n border-radius: 6px;\n color: var(--jr-fg-muted);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-size: 14px;\n}\n.jr-icon-btn:hover {\n color: var(--jr-fg);\n background: var(--jr-bg-muted);\n}\n.jr-icon-btn[data-active=\"true\"] {\n color: var(--jr-accent);\n background: var(--jr-bg-muted);\n}\n\n.jr-body {\n flex: 1;\n min-height: 0;\n display: flex;\n overflow: hidden;\n}\n.jr-body > .jr-tab-panel {\n flex: 1;\n min-width: 0;\n min-height: 0;\n overflow: auto;\n padding: 0;\n display: flex;\n flex-direction: column;\n}\n\n.jr-empty {\n flex: 1;\n min-height: 80px;\n padding: 24px;\n color: var(--jr-fg-dim);\n font-size: 12px;\n text-align: center;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n/* --- Rows / list primitives used by tabs --- */\n\n.jr-row {\n display: grid;\n grid-template-columns: auto 1fr auto;\n gap: 8px;\n align-items: center;\n padding: 4px 12px;\n border-bottom: 1px solid var(--jr-border);\n font-family: var(--jr-font-mono);\n font-size: 11px;\n cursor: pointer;\n}\n.jr-row:hover {\n background: var(--jr-bg-muted);\n}\n.jr-row-time {\n color: var(--jr-fg-dim);\n font-size: 10px;\n white-space: nowrap;\n}\n.jr-row-main {\n color: var(--jr-fg);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.jr-row-meta {\n color: var(--jr-fg-muted);\n font-size: 10px;\n white-space: nowrap;\n}\n.jr-row-expanded {\n grid-column: 1 / -1;\n padding: 8px 12px 10px 12px;\n color: var(--jr-fg-muted);\n white-space: pre-wrap;\n word-break: break-all;\n background: var(--jr-bg-soft);\n border-top: 1px solid var(--jr-border);\n}\n\n.jr-badge {\n display: inline-flex;\n align-items: center;\n padding: 1px 6px;\n border-radius: 4px;\n font-family: var(--jr-font-mono);\n font-size: 10px;\n color: var(--jr-fg-muted);\n background: var(--jr-bg-soft);\n border: 1px solid var(--jr-border);\n}\n.jr-badge[data-tone=\"green\"] { color: var(--jr-green); border-color: rgba(74, 222, 128, 0.25); }\n.jr-badge[data-tone=\"red\"] { color: var(--jr-red); border-color: rgba(248, 113, 113, 0.25); }\n.jr-badge[data-tone=\"amber\"] { color: var(--jr-amber); border-color: rgba(251, 191, 36, 0.25); }\n.jr-badge[data-tone=\"accent\"] { color: var(--jr-accent); border-color: rgba(96, 165, 250, 0.25); }\n\n.jr-toolbar {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n border-bottom: 1px solid var(--jr-border);\n background: var(--jr-bg);\n font-family: var(--jr-font-mono);\n font-size: 10px;\n color: var(--jr-fg-muted);\n position: sticky;\n top: 0;\n z-index: 1;\n}\n.jr-toolbar .jr-icon-btn { width: auto; padding: 0 6px; font-size: 10px; }\n.jr-search {\n flex: 1;\n background: var(--jr-bg-soft);\n border: 1px solid var(--jr-border);\n border-radius: 4px;\n padding: 3px 6px;\n color: var(--jr-fg);\n font-family: var(--jr-font-mono);\n font-size: 10px;\n outline: none;\n}\n.jr-search:focus {\n border-color: var(--jr-accent);\n}\n\n/* --- Spec tree --- */\n\n.jr-tree-row {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 2px 12px;\n font-family: var(--jr-font-mono);\n font-size: 11px;\n cursor: pointer;\n white-space: nowrap;\n color: var(--jr-fg);\n}\n.jr-tree-row:hover {\n background: var(--jr-bg-muted);\n}\n.jr-tree-row[data-selected=\"true\"] {\n background: var(--jr-bg-muted);\n box-shadow: inset 2px 0 0 var(--jr-accent);\n}\n.jr-tree-toggle {\n width: 12px;\n color: var(--jr-fg-dim);\n display: inline-block;\n text-align: center;\n}\n.jr-tree-type {\n color: var(--jr-accent);\n font-weight: 500;\n}\n.jr-tree-key {\n color: var(--jr-fg-dim);\n font-size: 10px;\n}\n.jr-tree-summary {\n color: var(--jr-fg-muted);\n font-size: 10px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.jr-tree-hidden {\n opacity: 0.45;\n}\n\n.jr-split {\n display: flex;\n flex: 1;\n min-height: 0;\n width: 100%;\n}\n.jr-split-left {\n flex: 1;\n min-width: 0;\n min-height: 0;\n /* Pane itself no longer scrolls; the inner .jr-tree-rows container does,\n so the breadcrumb bar above stays pinned. */\n overflow: hidden;\n border-right: 1px solid var(--jr-border);\n display: flex;\n flex-direction: column;\n /* Selected row already has its own accent indicator, so no focus ring\n on the container itself. */\n outline: none;\n}\n.jr-tree-rows {\n flex: 1;\n min-height: 0;\n overflow: auto;\n /* Flex-column so .jr-empty inside can stretch + center vertically. */\n display: flex;\n flex-direction: column;\n}\n\n/* Generation switcher — only rendered when >1 specs (e.g. AI chat with\n multiple assistant replies). Sits above the breadcrumbs. */\n.jr-generations {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 8px;\n min-height: 28px;\n border-bottom: 1px solid var(--jr-border);\n background: var(--jr-bg);\n font-family: var(--jr-font-mono);\n font-size: 11px;\n}\n.jr-generations:empty {\n display: none;\n}\n.jr-generation-select {\n background: var(--jr-bg-soft);\n color: var(--jr-fg);\n border: 1px solid var(--jr-border);\n border-radius: 4px;\n padding: 2px 6px;\n font-family: inherit;\n font-size: 11px;\n outline: none;\n cursor: pointer;\n}\n.jr-generation-select:focus-visible {\n border-color: var(--jr-accent);\n}\n.jr-generations-count {\n color: var(--jr-fg-dim);\n font-size: 10px;\n}\n.jr-breadcrumbs {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 4px 8px;\n min-height: 28px;\n border-bottom: 1px solid var(--jr-border);\n background: var(--jr-bg);\n white-space: nowrap;\n font-family: var(--jr-font-mono);\n font-size: 11px;\n}\n.jr-breadcrumbs-trail {\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: center;\n gap: 2px;\n overflow-x: auto;\n scrollbar-width: thin;\n}\n.jr-breadcrumbs-tools {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n gap: 2px;\n padding-left: 4px;\n border-left: 1px solid var(--jr-border);\n margin-left: 4px;\n}\n.jr-view-btn {\n width: 24px;\n height: 22px;\n border-radius: 4px;\n border: 0;\n background: transparent;\n color: var(--jr-fg-muted);\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n.jr-view-btn:hover {\n color: var(--jr-fg);\n background: var(--jr-bg-muted);\n}\n.jr-view-btn[data-active=\"true\"] {\n color: var(--jr-accent);\n background: var(--jr-bg-muted);\n}\n.jr-breadcrumb {\n padding: 2px 6px;\n border-radius: 4px;\n color: var(--jr-fg-muted);\n cursor: pointer;\n background: transparent;\n border: 0;\n font: inherit;\n white-space: nowrap;\n}\n.jr-breadcrumb:hover {\n color: var(--jr-fg);\n background: var(--jr-bg-muted);\n}\n.jr-breadcrumb[data-current=\"true\"] {\n color: var(--jr-accent);\n background: var(--jr-bg-muted);\n}\n.jr-breadcrumb-sep {\n color: var(--jr-fg-dim);\n font-size: 10px;\n padding: 0 1px;\n user-select: none;\n}\n.jr-breadcrumbs-empty {\n color: var(--jr-fg-dim);\n padding: 2px 6px;\n font-style: italic;\n}\n\n/* Raw JSON view — spec pretty-printed, selectable for copy/paste. */\n.jr-raw {\n margin: 0;\n padding: 10px 12px;\n flex: 1;\n min-height: 0;\n font-family: var(--jr-font-mono);\n font-size: 11px;\n line-height: 1.5;\n color: var(--jr-fg);\n white-space: pre;\n overflow: auto;\n -moz-tab-size: 2;\n tab-size: 2;\n}\n.jr-split-right {\n width: 40%;\n min-width: 240px;\n max-width: 60%;\n min-height: 0;\n overflow: auto;\n background: var(--jr-bg);\n display: flex;\n flex-direction: column;\n}\n\n.jr-detail {\n padding: 10px 12px;\n font-family: var(--jr-font-mono);\n font-size: 11px;\n color: var(--jr-fg);\n}\n.jr-detail h4 {\n margin: 0 0 6px 0;\n font-family: var(--jr-font-mono);\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--jr-fg-dim);\n}\n.jr-detail pre {\n margin: 0 0 14px 0;\n padding: 8px;\n background: var(--jr-bg-soft);\n border: 1px solid var(--jr-border);\n border-radius: 4px;\n white-space: pre-wrap;\n word-break: break-all;\n color: var(--jr-fg);\n}\n\n/* --- State editor --- */\n.jr-state-row {\n display: grid;\n grid-template-columns: 1fr 2fr;\n gap: 8px;\n padding: 3px 12px;\n border-bottom: 1px solid var(--jr-border);\n font-family: var(--jr-font-mono);\n font-size: 11px;\n align-items: center;\n}\n.jr-state-path {\n color: var(--jr-fg-muted);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.jr-state-value {\n background: transparent;\n color: var(--jr-fg);\n border: 1px solid transparent;\n border-radius: 3px;\n padding: 2px 4px;\n font-family: var(--jr-font-mono);\n font-size: 11px;\n outline: none;\n width: 100%;\n min-width: 0;\n}\n.jr-state-value:hover {\n border-color: var(--jr-border);\n}\n.jr-state-value:focus {\n border-color: var(--jr-accent);\n background: var(--jr-bg-soft);\n}\n.jr-state-value[data-dirty=\"true\"] {\n border-color: var(--jr-amber);\n}\n\n/* --- Catalog chips --- */\n.jr-chips {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n margin-top: 4px;\n}\n.jr-chip {\n padding: 1px 5px;\n border-radius: 3px;\n font-family: var(--jr-font-mono);\n font-size: 10px;\n background: var(--jr-bg-soft);\n color: var(--jr-fg-muted);\n border: 1px solid var(--jr-border);\n}\n.jr-chip[data-tone=\"prop\"] { color: var(--jr-green); border-color: rgba(74, 222, 128, 0.25); }\n.jr-chip[data-tone=\"event\"] { color: var(--jr-accent); border-color: rgba(96, 165, 250, 0.25); }\n.jr-chip[data-tone=\"param\"] { color: var(--jr-amber); border-color: rgba(251, 191, 36, 0.25); }\n\n.jr-catalog-item {\n padding: 8px 12px;\n border-bottom: 1px solid var(--jr-border);\n}\n.jr-catalog-name {\n font-family: var(--jr-font-mono);\n font-size: 11px;\n color: var(--jr-fg);\n font-weight: 600;\n}\n.jr-catalog-desc {\n font-size: 11px;\n color: var(--jr-fg-muted);\n margin-top: 2px;\n}\n`;\n\n/**\n * CSS injected into the *host* document (not the shadow root). It supports:\n *\n * 1. The picker overlay — paints an outline + label on whichever element the\n * user is hovering while the picker is active.\n * 2. Reserved-space layout — when \\`reserveSpace\\` is enabled the panel writes\n * its size to \\`--jr-devtools-offset-bottom\\` / \\`--jr-devtools-offset-right\\`\n * on \\`:root\\` and we apply matching \\`padding-bottom\\` / \\`padding-right\\` to\n * \\`body\\`, so non-fixed content scrolls into view rather than being hidden.\n * \\`--jr-devtools-offset\\` is kept as an alias for whichever edge is\n * currently active (back-compat).\n *\n * Apps with \\`position: fixed\\` / \\`position: sticky\\` / \\`100vh\\` layouts can\n * opt in per element:\n *\n * \\`\\`\\`css\n * .composer { bottom: var(--jr-devtools-offset-bottom, 0); }\n * .sidebar { right: var(--jr-devtools-offset-right, 0); }\n * .app { height: calc(100vh - var(--jr-devtools-offset-bottom, 0)); }\n * \\`\\`\\`\n */\nexport const HOST_CSS = `\n:root {\n --jr-devtools-offset-bottom: 0px;\n --jr-devtools-offset-right: 0px;\n}\n\nhtml[data-jr-devtools-reserve=\"true\"] body {\n box-sizing: border-box;\n padding-bottom: var(--jr-devtools-offset-bottom, 0);\n padding-right: var(--jr-devtools-offset-right, 0);\n transition: padding-bottom 0.12s ease-out, padding-right 0.12s ease-out;\n}\n\nhtml[data-jr-devtools-picking=\"true\"],\nhtml[data-jr-devtools-picking=\"true\"] * {\n cursor: crosshair !important;\n}\n\n/* Floating overlays + labels used by two features:\n 1. Picker — while the toolbar button is active and the user hovers the page\n 2. Tree hover — while the user hovers a row in the Spec tab tree\n Both use the same visual language. Not rendered with a CSS \\`outline\\` on the\n target because the json-render element wrappers use \\`display: contents\\`\n (no box, no outline). */\n#__jr_devtools_picker_overlay,\n#__jr_devtools_hover_overlay {\n position: fixed;\n z-index: 2147483646;\n pointer-events: none;\n background: rgba(96, 165, 250, 0.15);\n outline: 2px solid #60a5fa;\n outline-offset: 0;\n border-radius: 2px;\n box-shadow: 0 0 0 1px rgba(9, 9, 11, 0.4);\n display: none;\n}\n#__jr_devtools_picker_label,\n#__jr_devtools_hover_label {\n position: fixed;\n z-index: 2147483646;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 11px;\n padding: 3px 7px;\n border-radius: 4px;\n background: #60a5fa;\n color: #09090b;\n pointer-events: none;\n white-space: nowrap;\n display: none;\n}\n/* Secondary overlays painted for the *other* instances of a repeated spec\n element — amber + dashed so they read as \"siblings of the hovered one\". */\n.__jr_devtools_hover_extra {\n position: fixed;\n z-index: 2147483646;\n pointer-events: none;\n background: rgba(251, 191, 36, 0.08);\n outline: 2px dashed #fbbf24;\n outline-offset: 0;\n border-radius: 2px;\n box-shadow: 0 0 0 1px rgba(9, 9, 11, 0.4);\n display: none;\n}\n`;\n","import { h, replaceChildren } from \"./dom\";\nimport { setHoverHighlight } from \"../picker\";\nimport { HOST_CSS, PANEL_CSS } from \"./styles\";\nimport type {\n PanelContext,\n PanelDock,\n PanelHandle,\n PanelOptions,\n PanelPosition,\n TabDef,\n TabInstance,\n} from \"./types\";\n\nconst HOST_ATTR = \"data-jr-devtools-host\";\nconst HOST_STYLE_ID = \"__jr_devtools_host_styles\";\nconst RESERVE_ATTR = \"data-jr-devtools-reserve\";\nconst OFFSET_VAR_BOTTOM = \"--jr-devtools-offset-bottom\";\nconst OFFSET_VAR_RIGHT = \"--jr-devtools-offset-right\";\n/** Back-compat alias: points at whichever edge is currently active. */\nconst OFFSET_VAR_ALIAS = \"--jr-devtools-offset\";\n\nfunction ensureHostStyles() {\n if (document.getElementById(HOST_STYLE_ID)) return;\n const style = document.createElement(\"style\");\n style.id = HOST_STYLE_ID;\n style.textContent = HOST_CSS;\n document.head.appendChild(style);\n}\n\n/**\n * Publish the panel's current size on `:root` as two CSS custom properties:\n * `--jr-devtools-offset-bottom` and `--jr-devtools-offset-right`. Only the\n * one matching the active dock is non-zero at a time. `--jr-devtools-offset`\n * is maintained as an alias for whichever edge is currently active, so older\n * app CSS keeps working.\n */\nfunction setOffset(dock: PanelDock, px: number) {\n const root = document.documentElement;\n const bottom = dock === \"bottom\" ? px : 0;\n const right = dock === \"right\" ? px : 0;\n if (bottom > 0) root.style.setProperty(OFFSET_VAR_BOTTOM, `${bottom}px`);\n else root.style.removeProperty(OFFSET_VAR_BOTTOM);\n if (right > 0) root.style.setProperty(OFFSET_VAR_RIGHT, `${right}px`);\n else root.style.removeProperty(OFFSET_VAR_RIGHT);\n if (px > 0) root.style.setProperty(OFFSET_VAR_ALIAS, `${px}px`);\n else root.style.removeProperty(OFFSET_VAR_ALIAS);\n}\n\n/** Map toggle-button position to the panel dock edge. */\nfunction dockFromPosition(position: PanelPosition): PanelDock {\n return position === \"right\" ? \"right\" : \"bottom\";\n}\n\nconst STORAGE_DOCK = \"__jr_devtools_dock\";\nconst STORAGE_HEIGHT = \"__jr_devtools_height\";\nconst STORAGE_WIDTH = \"__jr_devtools_width\";\n\nfunction readStoredDock(): PanelDock | null {\n if (typeof window === \"undefined\") return null;\n try {\n const raw = window.localStorage?.getItem(STORAGE_DOCK);\n return raw === \"bottom\" || raw === \"right\" ? raw : null;\n } catch {\n return null;\n }\n}\n\nfunction writeStoredDock(dock: PanelDock): void {\n if (typeof window === \"undefined\") return;\n try {\n window.localStorage?.setItem(STORAGE_DOCK, dock);\n } catch {\n // ignore storage errors (private mode, etc.)\n }\n}\n\n/** Per-dock layout constants (storage key, default/min size, CSS var). */\nfunction dockSpec(dock: PanelDock) {\n return dock === \"right\"\n ? {\n key: STORAGE_WIDTH,\n defaultSize: 440,\n minSize: 260,\n cssVar: \"--jr-panel-width\" as const,\n }\n : {\n key: STORAGE_HEIGHT,\n defaultSize: 380,\n minSize: 180,\n cssVar: \"--jr-panel-height\" as const,\n };\n}\n\n/** Inline SVG used for the Pick toolbar button (lucide square-mouse-pointer). */\nconst PICK_ICON_SVG = `\n<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M12.034 12.681a.498.498 0 0 1 .647-.647l9 3.5a.5.5 0 0 1-.033.944l-3.444 1.068a1 1 0 0 0-.66.66l-1.067 3.443a.5.5 0 0 1-.944.033z\"/>\n <path d=\"M21 11V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h6\"/>\n</svg>`;\n\n/**\n * Pixel-style `{}` mark for the floating toggle. Drawn as a 14×14 grid of\n * 2px rects so it's perfectly symmetric on both axes — eliminates the\n * font-glyph-off-centre issue we'd get by rendering live text.\n */\nconst TOGGLE_BRACES_SVG = `\n<svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"currentColor\" aria-hidden=\"true\">\n <rect x=\"2\" y=\"0\" width=\"4\" height=\"2\"/>\n <rect x=\"2\" y=\"2\" width=\"2\" height=\"4\"/>\n <rect x=\"0\" y=\"6\" width=\"2\" height=\"2\"/>\n <rect x=\"2\" y=\"8\" width=\"2\" height=\"4\"/>\n <rect x=\"2\" y=\"12\" width=\"4\" height=\"2\"/>\n <rect x=\"8\" y=\"0\" width=\"4\" height=\"2\"/>\n <rect x=\"10\" y=\"2\" width=\"2\" height=\"4\"/>\n <rect x=\"12\" y=\"6\" width=\"2\" height=\"2\"/>\n <rect x=\"10\" y=\"8\" width=\"2\" height=\"4\"/>\n <rect x=\"8\" y=\"12\" width=\"4\" height=\"2\"/>\n</svg>`;\n\n/** Inline SVGs for the dock-toggle button (lucide panel-bottom / panel-right). */\nconst PANEL_BOTTOM_SVG = `\n<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\"/>\n <path d=\"M3 15h18\"/>\n</svg>`;\nconst PANEL_RIGHT_SVG = `\n<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\"/>\n <path d=\"M15 3v18\"/>\n</svg>`;\n\nfunction matchHotkey(event: KeyboardEvent, hotkey: string): boolean {\n const parts = hotkey\n .toLowerCase()\n .split(\"+\")\n .map((p) => p.trim());\n const isMac =\n typeof navigator !== \"undefined\" &&\n /mac|iphone|ipad/i.test(navigator.platform || navigator.userAgent);\n let needsMod = false;\n let needsShift = false;\n let needsAlt = false;\n let key = \"\";\n for (const p of parts) {\n if (p === \"mod\") needsMod = true;\n else if (p === \"ctrl\") needsMod = true;\n else if (p === \"meta\" || p === \"cmd\") needsMod = true;\n else if (p === \"shift\") needsShift = true;\n else if (p === \"alt\" || p === \"option\") needsAlt = true;\n else key = p;\n }\n const modOk = needsMod ? (isMac ? event.metaKey : event.ctrlKey) : true;\n const shiftOk = needsShift ? event.shiftKey : true;\n const altOk = needsAlt ? event.altKey : true;\n const keyOk = key ? event.key.toLowerCase() === key : true;\n return modOk && shiftOk && altOk && keyOk;\n}\n\n/**\n * Create a devtools panel and mount it to the host document.\n *\n * Idempotent per-host: if a panel is already mounted under the given host,\n * this returns that panel's handle instead of creating a duplicate.\n */\nexport function createPanel(options: PanelOptions): PanelHandle {\n const host =\n options.host ?? (typeof document !== \"undefined\" ? document.body : null);\n if (!host) {\n return {\n open() {},\n close() {},\n toggle() {},\n isOpen: () => false,\n refresh() {},\n destroy() {},\n };\n }\n\n // If a panel root already exists, reuse its handle.\n const existing = host.querySelector(`[${HOST_ATTR}]`);\n if (\n existing &&\n (existing as HTMLElement & { __jrHandle?: PanelHandle }).__jrHandle\n ) {\n return (existing as HTMLElement & { __jrHandle: PanelHandle }).__jrHandle;\n }\n\n ensureHostStyles();\n\n const rootHost = document.createElement(\"div\");\n rootHost.setAttribute(HOST_ATTR, \"\");\n host.appendChild(rootHost);\n\n const shadow = rootHost.attachShadow({ mode: \"open\" });\n const styleEl = document.createElement(\"style\");\n styleEl.textContent = PANEL_CSS;\n shadow.appendChild(styleEl);\n\n const position: PanelPosition = options.position ?? \"bottom-right\";\n const allowDockToggle = options.allowDockToggle ?? true;\n // Initial dock: stored user preference wins (when the user is allowed to\n // toggle), otherwise fall back to whatever `position` implies.\n const initialDock: PanelDock =\n (allowDockToggle ? readStoredDock() : null) ?? dockFromPosition(position);\n let dock: PanelDock = initialDock;\n const reserveSpace = options.reserveSpace ?? true;\n // Opt the host document in to reserved-space padding (HOST_CSS is scoped\n // by this attribute so apps that pass `reserveSpace: false` are untouched).\n if (reserveSpace) {\n document.documentElement.setAttribute(RESERVE_ATTR, \"true\");\n }\n let open = options.initialOpen ?? false;\n let activeTabId = options.tabs[0]?.id ?? \"\";\n\n const ctx: PanelContext = options.context;\n const tabs = options.tabs;\n const tabInstances = new Map<string, TabInstance>();\n\n // --- Toggle button ---\n const toggleBtn = h(\"button\", {\n className: \"jr-toggle\",\n \"data-position\": position,\n \"data-open\": String(open),\n title: \"json-render devtools\",\n \"aria-label\": \"Toggle json-render devtools\",\n onClick: () => toggle(),\n });\n toggleBtn.innerHTML = TOGGLE_BRACES_SVG;\n shadow.appendChild(toggleBtn);\n\n // --- Panel container ---\n const tabsStrip = h(\"div\", { className: \"jr-tabs\" });\n const body = h(\"div\", { className: \"jr-body\" });\n\n // Pick button lives in the header toolbar (Chrome DevTools style) so it is\n // reachable from any tab without stealing a tab slot.\n const pickBtn = h(\"button\", {\n className: \"jr-icon-btn jr-pick-btn\",\n title: \"Select an element in the page (Esc to cancel)\",\n \"aria-label\": \"Select an element in the page\",\n onClick: () => togglePicker(),\n });\n pickBtn.innerHTML = PICK_ICON_SVG;\n\n // Dock-toggle button (only visible when `allowDockToggle` is enabled).\n // Shows the *target* dock icon — click it to move the panel there.\n const dockBtn = h(\"button\", {\n className: \"jr-icon-btn jr-dock-btn\",\n \"aria-label\": \"Toggle devtools dock\",\n onClick: () => toggleDock(),\n });\n function updateDockButton() {\n if (dock === \"bottom\") {\n dockBtn.innerHTML = PANEL_RIGHT_SVG;\n dockBtn.title = \"Dock to right\";\n } else {\n dockBtn.innerHTML = PANEL_BOTTOM_SVG;\n dockBtn.title = \"Dock to bottom\";\n }\n }\n updateDockButton();\n\n const closeBtn = h(\n \"button\",\n {\n className: \"jr-icon-btn\",\n title: \"Close devtools\",\n \"aria-label\": \"Close\",\n onClick: () => close(),\n },\n \"\\u00d7\",\n );\n\n const header = h(\n \"header\",\n { className: \"jr-header\" },\n h(\"div\", { className: \"jr-title\" }, \"json-render devtools\"),\n tabsStrip,\n h(\n \"div\",\n { className: \"jr-actions\" },\n pickBtn,\n allowDockToggle ? dockBtn : null,\n closeBtn,\n ),\n );\n\n const resizeHandle = h(\"div\", {\n className: \"jr-resize\",\n \"aria-label\": \"Resize devtools\",\n });\n\n const panel = h(\n \"section\",\n {\n className: \"jr-panel\",\n \"data-hidden\": String(!open),\n \"data-dock\": dock,\n role: \"complementary\",\n },\n resizeHandle,\n header,\n body,\n );\n shadow.appendChild(panel);\n\n // --- Resize handling ---\n // Bottom-docked panels resize vertically; right-docked panels resize\n // horizontally. Each dock has its own localStorage key so switching\n // docks doesn't inherit the wrong dimension.\n let panelSize = loadSizeFor(dock);\n applyPanelSize(dock, panelSize);\n\n function loadSizeFor(d: PanelDock): number {\n const spec = dockSpec(d);\n const stored =\n typeof window !== \"undefined\"\n ? window.localStorage?.getItem(spec.key)\n : null;\n let size = stored ? parseInt(stored, 10) : spec.defaultSize;\n if (!Number.isFinite(size) || size < spec.minSize) {\n size = spec.defaultSize;\n }\n return size;\n }\n\n function applyPanelSize(d: PanelDock, size: number): void {\n const spec = dockSpec(d);\n // Clear the opposite axis's CSS var so old values don't linger.\n const other = d === \"bottom\" ? \"--jr-panel-width\" : \"--jr-panel-height\";\n panel.style.removeProperty(other);\n panel.style.setProperty(spec.cssVar, `${size}px`);\n }\n\n resizeHandle.addEventListener(\"mousedown\", (ev) => {\n ev.preventDefault();\n const d = dock;\n const startCoord = d === \"right\" ? ev.clientX : ev.clientY;\n const startSize = panelSize;\n const spec = dockSpec(d);\n const onMove = (e: MouseEvent) => {\n // Both axes: dragging *away* from the dock edge (up for bottom, left\n // for right) grows the panel.\n const current = d === \"right\" ? e.clientX : e.clientY;\n const delta = startCoord - current;\n const viewport = d === \"right\" ? window.innerWidth : window.innerHeight;\n panelSize = Math.max(\n spec.minSize,\n Math.min(viewport * 0.9, startSize + delta),\n );\n applyPanelSize(d, panelSize);\n if (open && reserveSpace) setOffset(d, panelSize);\n };\n const onUp = () => {\n document.removeEventListener(\"mousemove\", onMove);\n document.removeEventListener(\"mouseup\", onUp);\n try {\n window.localStorage?.setItem(spec.key, String(panelSize));\n } catch {\n // ignore storage errors (private mode, etc.)\n }\n };\n document.addEventListener(\"mousemove\", onMove);\n document.addEventListener(\"mouseup\", onUp);\n });\n\n // --- Dock toggle ---\n function setDock(next: PanelDock, persist: boolean) {\n if (next === dock) return;\n // Clear the old axis's offset before switching so the host body\n // padding doesn't flash the wrong value during the transition.\n setOffset(dock, 0);\n dock = next;\n panel.dataset.dock = next;\n panelSize = loadSizeFor(next);\n applyPanelSize(next, panelSize);\n if (open && reserveSpace) setOffset(next, panelSize);\n if (persist) writeStoredDock(next);\n updateDockButton();\n }\n\n function toggleDock() {\n if (!allowDockToggle) return;\n setDock(dock === \"bottom\" ? \"right\" : \"bottom\", true);\n }\n\n // --- Picker (toolbar button) ---\n let pickerStop: (() => void) | null = null;\n\n function updatePickButton() {\n const active = !!pickerStop;\n pickBtn.dataset.active = String(active);\n pickBtn.title = active\n ? \"Stop picking (Esc)\"\n : \"Select an element in the page\";\n pickBtn.disabled = typeof document === \"undefined\" || !ctx.startPicker;\n }\n\n function stopPicker() {\n if (pickerStop) pickerStop();\n pickerStop = null;\n updatePickButton();\n }\n\n function startPickerSession() {\n if (pickerStop || !ctx.startPicker) return;\n const session = ctx.startPicker({\n onPick: (key) => {\n pickerStop = null;\n updatePickButton();\n ctx.selection.set(key);\n // Jump to the Spec tab if one is registered so the user sees the\n // matching element right after picking.\n if (tabs.some((t) => t.id === \"spec\")) {\n ctx.activateTab(\"spec\");\n } else {\n openPanel();\n }\n },\n onCancel: () => {\n pickerStop = null;\n updatePickButton();\n },\n });\n if (!session) return;\n pickerStop = session.stop;\n updatePickButton();\n }\n\n function togglePicker() {\n if (pickerStop) stopPicker();\n else startPickerSession();\n }\n\n updatePickButton();\n\n // --- Tab strip ---\n const tabButtons = new Map<string, HTMLButtonElement>();\n\n function renderTabs() {\n replaceChildren(\n tabsStrip,\n tabs.map((tab) => {\n const badgeValue = tab.badge?.(ctx);\n const btn = h(\n \"button\",\n {\n className: \"jr-tab\",\n \"data-active\": String(tab.id === activeTabId),\n \"data-tab\": tab.id,\n onClick: () => setActiveTab(tab.id),\n },\n tab.label,\n badgeValue !== undefined && badgeValue !== \"\" && badgeValue !== 0\n ? h(\"span\", { className: \"jr-tab-count\" }, String(badgeValue))\n : null,\n );\n tabButtons.set(tab.id, btn);\n return btn;\n }),\n );\n }\n\n function activateTab(id: string) {\n const tab = tabs.find((t) => t.id === id);\n if (!tab) return;\n body.textContent = \"\";\n const panelEl = h(\"div\", { className: \"jr-tab-panel\", \"data-tab\": id });\n body.appendChild(panelEl);\n // Destroy previous tab instances (single active tab at a time)\n for (const [prevId, inst] of tabInstances) {\n if (prevId !== id) {\n try {\n inst.destroy?.();\n } catch (err) {\n if (process.env.NODE_ENV !== \"production\") {\n console.error(\"[json-render devtools] tab destroy threw:\", err);\n }\n }\n tabInstances.delete(prevId);\n }\n }\n const instance = tab.mount(panelEl, ctx);\n tabInstances.set(id, instance);\n }\n\n function setActiveTab(id: string) {\n if (activeTabId === id) return;\n activeTabId = id;\n renderTabs();\n activateTab(id);\n }\n\n // Let tabs (and the picker) jump to other tabs programmatically.\n ctx.activateTab = (id: string) => {\n setActiveTab(id);\n openPanel();\n };\n\n renderTabs();\n if (activeTabId) activateTab(activeTabId);\n\n // --- Global refresh on every event ---\n let scheduled = false;\n const runRefresh = () => {\n scheduled = false;\n renderTabs();\n const inst = tabInstances.get(activeTabId);\n inst?.update();\n };\n const scheduleRefresh = () => {\n if (scheduled) return;\n scheduled = true;\n if (\n typeof window !== \"undefined\" &&\n typeof window.requestAnimationFrame === \"function\"\n ) {\n window.requestAnimationFrame(runRefresh);\n } else {\n setTimeout(runRefresh, 16);\n }\n };\n const unsubEvents = ctx.events.subscribe(scheduleRefresh);\n\n // --- Hotkey ---\n const hotkey = options.hotkey === undefined ? \"mod+shift+j\" : options.hotkey;\n const onKey = hotkey\n ? (e: KeyboardEvent) => {\n if (matchHotkey(e, hotkey)) {\n e.preventDefault();\n toggle();\n }\n }\n : null;\n if (onKey) document.addEventListener(\"keydown\", onKey);\n\n // --- Lifecycle ---\n function setOpen(next: boolean) {\n open = next;\n toggleBtn.dataset.open = String(open);\n panel.dataset.hidden = String(!open);\n // Even when `reserveSpace` is false we still publish the CSS var so apps\n // that opt in (e.g. `bottom: var(--jr-devtools-offset-bottom, 0)`) get\n // the right value. HOST_CSS only applies body padding when the host\n // document has `data-jr-devtools-reserve=\"true\"`.\n setOffset(dock, open ? panelSize : 0);\n if (open) {\n const inst = tabInstances.get(activeTabId);\n inst?.update();\n } else {\n // Closing cancels any in-flight picker so the hover outline doesn't\n // linger in the page. Clear the spec-tree hover highlight too — if\n // the user closed via hotkey they never moved the mouse off the row.\n stopPicker();\n setHoverHighlight(null);\n }\n }\n function openPanel() {\n setOpen(true);\n }\n function close() {\n setOpen(false);\n }\n function toggle() {\n setOpen(!open);\n }\n\n // Seed offset on mount so the toggle button doesn't sit over the app when\n // the panel is already open at boot.\n setOffset(dock, open ? panelSize : 0);\n\n const handle: PanelHandle = {\n open: openPanel,\n close,\n toggle,\n isOpen: () => open,\n refresh: scheduleRefresh,\n destroy() {\n unsubEvents();\n if (onKey) document.removeEventListener(\"keydown\", onKey);\n stopPicker();\n setHoverHighlight(null);\n setOffset(dock, 0);\n for (const inst of tabInstances.values()) {\n try {\n inst.destroy?.();\n } catch {\n // ignore\n }\n }\n tabInstances.clear();\n rootHost.remove();\n // Only clear the reserve-space attribute once every panel is gone — in\n // rare HMR / multi-mount scenarios another panel may still be live.\n if (!document.querySelector(`[${HOST_ATTR}]`)) {\n document.documentElement.removeAttribute(RESERVE_ATTR);\n }\n },\n };\n\n (rootHost as HTMLElement & { __jrHandle?: PanelHandle }).__jrHandle = handle;\n return handle;\n}\n\n/**\n * Mount a panel with a minimal placeholder for each tab. Useful for tests\n * or environments where individual tab implementations aren't available.\n *\n * In production, consumers use {@link createPanel} with the full tab set.\n */\nexport function createStubTab(id: string, label: string): TabDef {\n return {\n id,\n label,\n mount(root) {\n const empty = h(\"div\", { className: \"jr-empty\" }, `${label} (stub)`);\n root.appendChild(empty);\n return { update() {} };\n },\n };\n}\n","import type { Catalog, Spec, StateStore } from \"@json-render/core\";\nimport type { EventStore } from \"../event-store\";\nimport type { PickerOptions, PickerSession } from \"../types\";\n\n/**\n * Where the devtools panel docks and where the floating toggle lives.\n *\n * - `bottom-right` (default) — panel docks to the bottom; toggle sits in the\n * bottom-right corner.\n * - `bottom-left` — panel docks to the bottom; toggle sits in the bottom-left\n * corner. Useful when the host app already has something bottom-right.\n * - `right` — panel docks to the right edge (full height); toggle sits in the\n * top-right corner. Best for app-shell layouts that already use `100vh` /\n * `position: fixed` at the bottom — right docking avoids the bottom edge\n * entirely.\n */\nexport type PanelPosition = \"bottom-right\" | \"bottom-left\" | \"right\";\n\n/** @internal Normalized dock edge derived from {@link PanelPosition}. */\nexport type PanelDock = \"bottom\" | \"right\";\n\n/**\n * A single spec available for inspection. When the host app renders one\n * spec at a time (the common single-renderer case) this list has a single\n * entry. Multi-renderer hosts (e.g. an AI chat where each assistant reply\n * produces its own spec) surface every generation so the Spec tab can\n * switch between them.\n */\nexport interface SpecEntry {\n /** Stable id, typically the message id that produced the spec. */\n id: string;\n /** Human-readable label shown in the generation switcher (e.g. \"Generation 2\"). */\n label: string;\n /** The spec itself. */\n spec: Spec;\n}\n\n/**\n * Context shared with every tab. Tabs read live values via getters so they\n * always see the latest spec/state/catalog without needing to re-mount.\n */\nexport interface PanelContext {\n /** Event log shared by all panels. */\n events: EventStore;\n /** Returns the current (usually latest) spec or `null`. */\n getSpec: () => Spec | null;\n /**\n * Optional: returns every inspectable spec on the page.\n * Hosts with multiple concurrent renderers (e.g. a chat with one spec\n * per assistant message) provide this so the Spec tab can offer a\n * generation switcher. When absent, the tab falls back to `getSpec()`\n * alone.\n */\n getSpecs?: () => SpecEntry[];\n /** Returns the current catalog or `null`. */\n getCatalog: () => Catalog | null;\n /** Returns the live `StateStore` or `null` (only set when a provider is mounted). */\n getStateStore: () => StateStore | null;\n /** Start a picker session. Returns `null` if no DOM is available. */\n startPicker?: (options: PickerOptions) => PickerSession | null;\n /** Selection channel shared across tabs (picker <-> Spec tab). */\n selection: SelectionBus;\n /** Activate a specific tab by id. */\n activateTab: (id: string) => void;\n}\n\n/**\n * Bus for syncing the currently focused spec element key across tabs and the\n * picker overlay. Tabs read the current value and subscribe to changes;\n * anything that wants to focus an element (picker, tree click) calls `set`.\n */\nexport interface SelectionBus {\n get: () => string | null;\n set: (key: string | null) => void;\n subscribe: (listener: (key: string | null) => void) => () => void;\n}\n\n/** Create an in-memory {@link SelectionBus}. */\nexport function createSelectionBus(): SelectionBus {\n let value: string | null = null;\n const listeners = new Set<(key: string | null) => void>();\n return {\n get: () => value,\n set(next) {\n if (value === next) return;\n value = next;\n for (const l of listeners) l(next);\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n };\n}\n\n/**\n * A tab registered with the panel. Tabs are rendered lazily — `mount` is\n * called the first time the tab is activated, and `update` is called on\n * every re-render request after that.\n */\nexport interface TabDef {\n /** Stable tab id used in URL hash / storage. */\n id: string;\n /** Short label shown in the tab strip. */\n label: string;\n /** Optional count badge, recomputed on every render. */\n badge?: (ctx: PanelContext) => number | string | undefined;\n /** Create the DOM for this tab. Called once per activation. */\n mount: (root: HTMLElement, ctx: PanelContext) => TabInstance;\n}\n\n/**\n * A live tab. `update` is called whenever an event fires or the host\n * refreshes; `destroy` is called when the tab is unmounted.\n */\nexport interface TabInstance {\n /** Re-render with latest data. */\n update: () => void;\n /** Clean up subscriptions / listeners. */\n destroy?: () => void;\n}\n\n/**\n * Options for {@link createPanel}.\n */\nexport interface PanelOptions {\n /** Shared panel context. */\n context: PanelContext;\n /** Tabs to register. Order is preserved in the tab strip. */\n tabs: TabDef[];\n /** Host-document node to mount under. Default: `document.body`. */\n host?: HTMLElement;\n /** Position of the floating toggle button. */\n position?: PanelPosition;\n /** Start open. Default: `false`. */\n initialOpen?: boolean;\n /**\n * Keyboard shortcut to toggle the panel, or `false` to disable.\n * Syntax: `\"mod+shift+j\"` (`mod` = meta on mac, ctrl elsewhere).\n * Default: `\"mod+shift+j\"`.\n */\n hotkey?: string | false;\n /**\n * Whether the panel should push the host app's content out of the way\n * while open, by applying `padding` on `<body>` matching the panel's size.\n *\n * - `true` (default) — body padding is applied. Works for document-flow\n * layouts and `height: 100%` app shells. Modern apps that use\n * `height: 100vh`, `position: fixed; bottom: 0` etc. are effectively\n * *overlaid* by the panel because CSS can't resize `100vh`. Pair this\n * with `\"right\"` docking or opt those specific elements in via\n * `bottom: var(--jr-devtools-offset-bottom, 0)` /\n * `right: var(--jr-devtools-offset-right, 0)`.\n * - `false` — the panel is a pure overlay. Nothing is pushed; the host\n * app remains visually unchanged. The CSS custom properties\n * `--jr-devtools-offset-bottom` / `--jr-devtools-offset-right` are\n * still published on `:root` so apps can reserve their own space.\n */\n reserveSpace?: boolean;\n /**\n * When `true` (default), show a toolbar button that lets the user flip\n * the panel between bottom-dock and right-dock. The user's choice\n * persists across reloads (localStorage key `__jr_devtools_dock`), and\n * takes precedence over the initial `position` once set.\n *\n * When `false`, the dock follows `position` exactly and the toolbar\n * button is not rendered — useful when the host app's layout only works\n * with one dock.\n */\n allowDockToggle?: boolean;\n}\n\n/**\n * Returned from {@link createPanel}. Controls the panel lifecycle.\n */\nexport interface PanelHandle {\n /** Show the panel. */\n open: () => void;\n /** Hide the panel. */\n close: () => void;\n /** Toggle open/closed. */\n toggle: () => void;\n /** True if the panel is currently open. */\n isOpen: () => boolean;\n /** Request that all visible tabs re-render. */\n refresh: () => void;\n /** Remove the panel from the DOM and clean up. */\n destroy: () => void;\n}\n","import type { Spec, UIElement } from \"@json-render/core\";\nimport { validateSpec, type SpecIssue } from \"@json-render/core\";\nimport { setHoverHighlight } from \"../../picker\";\nimport { h, jsonPreview, replaceChildren } from \"../dom\";\nimport type { PanelContext, SpecEntry, TabDef, TabInstance } from \"../types\";\n\nconst TAB_ID = \"spec\";\n\n/** Tree view icon (lucide list-tree). */\nconst VIEW_TREE_SVG = `\n<svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M21 12h-8\"/>\n <path d=\"M21 6H8\"/>\n <path d=\"M21 18h-8\"/>\n <path d=\"M3 6v4c0 1.1.9 2 2 2h3\"/>\n <path d=\"M3 10v6c0 1.1.9 2 2 2h3\"/>\n</svg>`;\n\n/** Raw JSON view icon (lucide braces). */\nconst VIEW_RAW_SVG = `\n<svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M8 3H7a2 2 0 0 0-2 2v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5a2 2 0 0 0 2 2h1\"/>\n <path d=\"M16 21h1a2 2 0 0 0 2-2v-5a2 2 0 0 1 2-2 2 2 0 0 1-2-2V5a2 2 0 0 0-2-2h-1\"/>\n</svg>`;\n\n/**\n * Spec Tree tab — renders the element tree with expand/collapse, shows a\n * one-line summary per node, and highlights structural issues from\n * `validateSpec`. Selecting a node fills the right-hand detail pane with\n * full props + metadata.\n */\nexport function specTab(): TabDef {\n return {\n id: TAB_ID,\n label: \"Spec\",\n badge(ctx) {\n const spec = ctx.getSpec();\n if (!spec) return undefined;\n return Object.keys(spec.elements).length || undefined;\n },\n mount(root, ctx) {\n return mountSpecTab(root, ctx);\n },\n };\n}\n\nfunction mountSpecTab(root: HTMLElement, ctx: PanelContext): TabInstance {\n const expanded = new Set<string>();\n // Make the tree pane keyboard-navigable (Chrome-DevTools / WAI-ARIA tree\n // behaviour). Arrow keys move/expand/collapse, Enter toggles, Home/End\n // jump to ends.\n const treePane = h(\"div\", {\n className: \"jr-split-left\",\n role: \"tree\",\n tabindex: \"0\",\n });\n // Generation switcher — only rendered when the host exposes >1 spec\n // (typical in AI chats where each assistant message has its own spec).\n //\n // `selectedSpecId` always holds the id of the spec the user is viewing.\n // We track the previously-observed latest id separately so we can keep\n // the tab \"sticky-to-latest\" automatically: if the user is currently on\n // whatever was the newest generation, a newly-arrived generation slides\n // them forward to that one; otherwise their explicit pick is preserved.\n const generationBar = h(\"div\", {\n className: \"jr-generations\",\n \"aria-label\": \"Spec generation\",\n });\n let selectedSpecId: string | null = null;\n let lastSeenLatestId: string | null = null;\n\n // Breadcrumb bar (root → selected) pinned above the scrollable rows so\n // it stays visible while the tree scrolls. The left half is the crumb\n // trail (clickable ancestors); the right half is a toggle between tree\n // and raw-JSON views.\n const breadcrumbs = h(\"nav\", {\n className: \"jr-breadcrumbs\",\n \"aria-label\": \"Selected element ancestors\",\n });\n const crumbTrail = h(\"div\", { className: \"jr-breadcrumbs-trail\" });\n const viewTools = h(\"div\", {\n className: \"jr-breadcrumbs-tools\",\n role: \"group\",\n \"aria-label\": \"Spec view\",\n });\n const treeViewBtn = h(\"button\", {\n className: \"jr-view-btn\",\n type: \"button\",\n title: \"Tree view\",\n \"aria-label\": \"Tree view\",\n \"data-active\": \"true\",\n onClick: () => setView(\"tree\"),\n });\n treeViewBtn.innerHTML = VIEW_TREE_SVG;\n const rawViewBtn = h(\"button\", {\n className: \"jr-view-btn\",\n type: \"button\",\n title: \"Raw JSON view\",\n \"aria-label\": \"Raw JSON view\",\n \"data-active\": \"false\",\n onClick: () => setView(\"raw\"),\n });\n rawViewBtn.innerHTML = VIEW_RAW_SVG;\n viewTools.append(treeViewBtn, rawViewBtn);\n breadcrumbs.append(crumbTrail, viewTools);\n\n const treeRows = h(\"div\", { className: \"jr-tree-rows\" });\n treePane.append(generationBar, breadcrumbs, treeRows);\n const detailPane = h(\"div\", { className: \"jr-split-right\" });\n root.appendChild(h(\"div\", { className: \"jr-split\" }, treePane, detailPane));\n\n let view: \"tree\" | \"raw\" = \"tree\";\n function setView(next: \"tree\" | \"raw\") {\n if (view === next) return;\n view = next;\n treeViewBtn.dataset.active = String(view === \"tree\");\n rawViewBtn.dataset.active = String(view === \"raw\");\n render();\n }\n\n // When the user picks an element that lives in a *different* generation\n // than the one currently being inspected (common in multi-renderer\n // apps), auto-switch the generation so the tree can actually show it.\n const unsubSelection = ctx.selection.subscribe(() => {\n const key = ctx.selection.get();\n if (key) {\n const { spec, generations } = resolveCurrentSpec();\n if (spec && !spec.elements[key] && generations.length > 1) {\n const match = generations.find((g) => g.spec.elements[key]);\n if (match) selectedSpecId = match.id;\n }\n }\n render();\n });\n\n // Safety net: if the whole tree container loses the pointer, clear any\n // lingering hover highlight. Individual row mouseleave handles the\n // common case, but this catches fast tree re-renders where the row the\n // cursor was over has been unmounted without firing its own leave.\n const onTreeLeave = () => setHoverHighlight(null);\n treePane.addEventListener(\"mouseleave\", onTreeLeave);\n\n // Flat list of currently-visible element keys in render order. Populated\n // by `render()` and consumed by the arrow-key navigator.\n let visibleKeys: string[] = [];\n\n function toggleExpanded(key: string) {\n if (expanded.has(key)) expanded.delete(key);\n else expanded.add(key);\n render();\n }\n\n function scrollSelectedIntoView() {\n const el = treePane.querySelector<HTMLElement>(\n '.jr-tree-row[data-selected=\"true\"]',\n );\n el?.scrollIntoView({ block: \"nearest\" });\n }\n\n function moveSelection(nextKey: string | null | undefined) {\n if (!nextKey) return;\n ctx.selection.set(nextKey);\n setHoverHighlight(nextKey);\n // Selection subscriber has already re-rendered at this point.\n scrollSelectedIntoView();\n }\n\n function onKeyDown(ev: KeyboardEvent) {\n // Raw view is just a <pre> — let the browser handle text selection /\n // default keyboard behaviour. Tree nav doesn't apply there.\n if (view === \"raw\") return;\n // Ignore modifier-qualified keypresses so devtools hotkeys still work.\n if (ev.metaKey || ev.ctrlKey || ev.altKey) return;\n const key = ev.key;\n if (\n key !== \"ArrowUp\" &&\n key !== \"ArrowDown\" &&\n key !== \"ArrowLeft\" &&\n key !== \"ArrowRight\" &&\n key !== \"Enter\" &&\n key !== \" \" &&\n key !== \"Home\" &&\n key !== \"End\"\n ) {\n return;\n }\n\n // Keyboard nav must operate on the spec the user is inspecting, not\n // necessarily the latest one.\n const { spec } = resolveCurrentSpec();\n if (!spec || visibleKeys.length === 0) return;\n\n const current = ctx.selection.get();\n const idx = current ? visibleKeys.indexOf(current) : -1;\n ev.preventDefault();\n\n if (key === \"ArrowDown\") {\n if (idx < 0) moveSelection(visibleKeys[0]);\n else\n moveSelection(visibleKeys[Math.min(idx + 1, visibleKeys.length - 1)]);\n return;\n }\n\n if (key === \"ArrowUp\") {\n if (idx < 0) moveSelection(visibleKeys[0]);\n else moveSelection(visibleKeys[Math.max(idx - 1, 0)]);\n return;\n }\n\n if (key === \"Home\") {\n moveSelection(visibleKeys[0]);\n return;\n }\n\n if (key === \"End\") {\n moveSelection(visibleKeys[visibleKeys.length - 1]);\n return;\n }\n\n if (key === \"ArrowRight\") {\n if (!current) {\n moveSelection(visibleKeys[0]);\n return;\n }\n const el = spec.elements[current];\n const hasChildren = !!el?.children?.length;\n if (!hasChildren) return;\n if (!expanded.has(current)) {\n expanded.add(current);\n render();\n // Stay on the same row; the row just became expandable.\n scrollSelectedIntoView();\n } else {\n // Already expanded → step into the first child.\n moveSelection(el.children![0]);\n }\n return;\n }\n\n if (key === \"ArrowLeft\") {\n if (!current) return;\n const el = spec.elements[current];\n const hasChildren = !!el?.children?.length;\n if (hasChildren && expanded.has(current)) {\n expanded.delete(current);\n render();\n scrollSelectedIntoView();\n } else {\n const parent = findParent(spec, current);\n if (parent) moveSelection(parent);\n }\n return;\n }\n\n // Enter / Space\n if (!current) {\n moveSelection(visibleKeys[0]);\n return;\n }\n const el = spec.elements[current];\n if (el?.children?.length) {\n toggleExpanded(current);\n scrollSelectedIntoView();\n }\n }\n\n // Focus the tree pane when the user clicks into it so arrow keys take\n // effect right after a mouse pick. `focus()` without `preventScroll`\n // would jump the body on some browsers, so pass the option.\n const onFocusIn = () => {\n const current = ctx.selection.get();\n if (current) setHoverHighlight(current);\n };\n const onFocusOut = (ev: FocusEvent) => {\n // Only clear when focus leaves the tree entirely (not when moving\n // between rows). Shadow DOM + relatedTarget behaves like a normal\n // document for this check.\n const next = ev.relatedTarget as Node | null;\n if (!next || !treePane.contains(next)) {\n setHoverHighlight(null);\n }\n };\n\n // Focus the tree on mousedown so arrow keys work right after a click.\n // Passing `preventScroll` avoids the browser jumping the page if the\n // pane was off-screen.\n const onMouseDown = () => {\n try {\n treePane.focus({ preventScroll: true });\n } catch {\n // Some environments (tests, ancient browsers) throw on focus().\n }\n };\n treePane.addEventListener(\"mousedown\", onMouseDown);\n treePane.addEventListener(\"keydown\", onKeyDown);\n treePane.addEventListener(\"focusin\", onFocusIn);\n treePane.addEventListener(\"focusout\", onFocusOut);\n\n /**\n * Resolve the spec the tab currently inspects, plus the full generations\n * list. When a new generation arrives and the user had been on what was\n * previously the newest, we slide forward to the new newest (sticky).\n * An explicit older pick is always preserved.\n */\n function resolveCurrentSpec(): {\n spec: Spec | null;\n generations: SpecEntry[];\n } {\n const generations = ctx.getSpecs?.() ?? [];\n if (generations.length === 0) {\n return { spec: ctx.getSpec(), generations };\n }\n const latest = generations[generations.length - 1]!;\n\n // First render, or our pick no longer exists (e.g. chat cleared):\n // default to the newest.\n if (\n selectedSpecId == null ||\n !generations.some((g) => g.id === selectedSpecId)\n ) {\n selectedSpecId = latest.id;\n } else if (\n lastSeenLatestId != null &&\n selectedSpecId === lastSeenLatestId &&\n lastSeenLatestId !== latest.id\n ) {\n // Sticky: we were on \"what was newest last render\"; follow forward.\n selectedSpecId = latest.id;\n }\n lastSeenLatestId = latest.id;\n\n const picked = generations.find((g) => g.id === selectedSpecId)!;\n return { spec: picked.spec, generations };\n }\n\n function renderGenerationBar(generations: SpecEntry[]) {\n if (generations.length < 2) {\n replaceChildren(generationBar, null);\n return;\n }\n const latestId = generations[generations.length - 1]!.id;\n const select = h(\n \"select\",\n {\n className: \"jr-generation-select\",\n \"aria-label\": \"Inspect generation\",\n onChange: (ev: Event) => {\n selectedSpecId = (ev.target as HTMLSelectElement).value;\n render();\n },\n },\n ...generations.map((g, i) =>\n h(\n \"option\",\n {\n value: g.id,\n selected: g.id === selectedSpecId ? \"true\" : undefined,\n },\n g.id === latestId ? `Gen ${i + 1} (latest)` : `Gen ${i + 1}`,\n ),\n ),\n );\n const count = h(\n \"span\",\n { className: \"jr-generations-count\" },\n `${generations.length} generation${generations.length === 1 ? \"\" : \"s\"}`,\n );\n replaceChildren(generationBar, select, count);\n }\n\n function render() {\n const { spec, generations } = resolveCurrentSpec();\n renderGenerationBar(generations);\n if (!spec || !spec.root || Object.keys(spec.elements).length === 0) {\n visibleKeys = [];\n renderBreadcrumbs(null, null);\n replaceChildren(\n treeRows,\n h(\"div\", { className: \"jr-empty\" }, \"No spec attached.\"),\n );\n replaceChildren(detailPane, null);\n return;\n }\n\n const issues = collectIssues(spec);\n const selected = ctx.selection.get();\n\n // Auto-expand the path to the selection so it is always visible.\n // `findPath` returns leaf-first; we'll flip it for the breadcrumb bar.\n const pathLeafFirst = selected ? findPath(spec, selected) : [];\n for (const k of pathLeafFirst) expanded.add(k);\n\n visibleKeys = collectVisibleKeys(spec, expanded);\n\n renderBreadcrumbs(spec, pathLeafFirst);\n\n if (view === \"raw\") {\n renderRaw(spec);\n } else {\n replaceChildren(\n treeRows,\n renderNode(\n spec,\n spec.root,\n 0,\n expanded,\n selected,\n issues,\n ctx,\n toggleExpanded,\n null,\n ),\n );\n }\n\n if (selected && spec.elements[selected]) {\n renderDetail(detailPane, spec, selected, issues);\n } else {\n replaceChildren(\n detailPane,\n h(\"div\", { className: \"jr-empty\" }, \"Select an element to inspect.\"),\n );\n }\n }\n\n /**\n * Render the whole spec as pretty-printed JSON. Useful for copy/paste\n * into issue reports or quick source-level scans.\n */\n function renderRaw(spec: Spec) {\n let text: string;\n try {\n text = JSON.stringify(spec, null, 2);\n } catch {\n text = String(spec);\n }\n replaceChildren(treeRows, h(\"pre\", { className: \"jr-raw\" }, text));\n }\n\n /**\n * Rebuild the crumb trail inside the breadcrumb bar.\n * `pathLeafFirst` is the output of `findPath` (leaf → root); we render\n * it root → leaf. The view-toggle buttons on the right are untouched.\n */\n function renderBreadcrumbs(\n spec: Spec | null,\n pathLeafFirst: string[] | null,\n ) {\n if (!spec || !pathLeafFirst || pathLeafFirst.length === 0) {\n replaceChildren(\n crumbTrail,\n h(\"span\", { className: \"jr-breadcrumbs-empty\" }, \"No element selected\"),\n );\n return;\n }\n const path = [...pathLeafFirst].reverse();\n const parts: Array<HTMLElement | null> = [];\n path.forEach((key, i) => {\n const el = spec.elements[key];\n const label = el?.type ?? \"<missing>\";\n const isCurrent = i === path.length - 1;\n const crumb = h(\n \"button\",\n {\n className: \"jr-breadcrumb\",\n type: \"button\",\n \"data-current\": String(isCurrent),\n title: `#${key}`,\n onClick: (ev: MouseEvent) => {\n ev.stopPropagation();\n ctx.selection.set(key);\n setHoverHighlight(key);\n },\n onMouseEnter: () => setHoverHighlight(key),\n onMouseLeave: () => setHoverHighlight(null),\n },\n label,\n );\n parts.push(crumb);\n if (!isCurrent) {\n parts.push(h(\"span\", { className: \"jr-breadcrumb-sep\" }, \"\\u25b8\"));\n }\n });\n replaceChildren(crumbTrail, parts);\n }\n\n render();\n\n return {\n update: render,\n destroy() {\n unsubSelection();\n treePane.removeEventListener(\"mouseleave\", onTreeLeave);\n treePane.removeEventListener(\"mousedown\", onMouseDown);\n treePane.removeEventListener(\"keydown\", onKeyDown);\n treePane.removeEventListener(\"focusin\", onFocusIn);\n treePane.removeEventListener(\"focusout\", onFocusOut);\n setHoverHighlight(null);\n },\n };\n}\n\n/**\n * Flatten `spec` into the ordered list of element keys currently visible\n * in the tree, respecting the `expanded` set. Used to drive arrow-key\n * navigation.\n */\nfunction collectVisibleKeys(spec: Spec, expanded: Set<string>): string[] {\n const list: string[] = [];\n function walk(key: string) {\n list.push(key);\n const el = spec.elements[key];\n if (!el?.children || el.children.length === 0) return;\n if (!expanded.has(key)) return;\n for (const child of el.children) walk(child);\n }\n walk(spec.root);\n return list;\n}\n\nfunction findParent(spec: Spec, key: string): string | null {\n for (const [parentKey, el] of Object.entries(spec.elements)) {\n if (el.children?.includes(key)) return parentKey;\n }\n return null;\n}\n\ninterface IssueIndex {\n all: SpecIssue[];\n byKey: Map<string, SpecIssue[]>;\n}\n\nfunction collectIssues(spec: Spec): IssueIndex {\n const result = validateSpec(spec, { checkOrphans: true });\n const byKey = new Map<string, SpecIssue[]>();\n for (const issue of result.issues) {\n const k = issue.elementKey ?? \"__spec__\";\n const arr = byKey.get(k) ?? [];\n arr.push(issue);\n byKey.set(k, arr);\n }\n return { all: result.issues, byKey };\n}\n\n/**\n * Walk the tree looking for `key` and return the ancestor path\n * (inclusive) so a caller can expand it.\n */\nfunction findPath(spec: Spec, key: string): string[] {\n const path: string[] = [];\n function walk(current: string): boolean {\n if (current === key) {\n path.push(current);\n return true;\n }\n const el = spec.elements[current];\n if (!el?.children) return false;\n for (const child of el.children) {\n if (walk(child)) {\n path.push(current);\n return true;\n }\n }\n return false;\n }\n walk(spec.root);\n return path;\n}\n\nfunction renderNode(\n spec: Spec,\n key: string,\n depth: number,\n expanded: Set<string>,\n selected: string | null,\n issues: IssueIndex,\n ctx: PanelContext,\n onToggle: (key: string) => void,\n parentHidden: boolean | null,\n): HTMLElement | null {\n const el = spec.elements[key];\n if (!el) {\n return h(\n \"div\",\n {\n className: \"jr-tree-row\",\n style: { paddingLeft: `${12 + depth * 14}px` },\n },\n h(\"span\", { className: \"jr-tree-toggle\" }, \" \"),\n h(\"span\", { className: \"jr-tree-type\" }, \"<missing>\"),\n h(\"span\", { className: \"jr-tree-key\" }, key),\n );\n }\n\n const hasChildren = Array.isArray(el.children) && el.children.length > 0;\n const isExpanded = hasChildren && expanded.has(key);\n const isSelected = selected === key;\n const elementIssues = issues.byKey.get(key) ?? [];\n const hasErrors = elementIssues.some((i) => i.severity === \"error\");\n const summary = makeSummary(el);\n const hiddenHere = el.visible !== undefined ? null : parentHidden;\n\n const row = h(\n \"div\",\n {\n className: `jr-tree-row${hiddenHere === true ? \" jr-tree-hidden\" : \"\"}`,\n \"data-selected\": String(isSelected),\n style: { paddingLeft: `${8 + depth * 14}px` },\n onClick: (ev: MouseEvent) => {\n ev.stopPropagation();\n ctx.selection.set(key);\n },\n // Paint a persistent bounding-box overlay over the matching DOM\n // element while the tree row is hovered — gives the same visual\n // affordance as Chrome DevTools' element picker without needing to\n // enter pick mode.\n onMouseEnter: () => {\n setHoverHighlight(key);\n },\n onMouseLeave: () => {\n setHoverHighlight(null);\n },\n },\n h(\n \"span\",\n {\n className: \"jr-tree-toggle\",\n onClick: (ev: MouseEvent) => {\n ev.stopPropagation();\n if (hasChildren) onToggle(key);\n },\n },\n hasChildren ? (isExpanded ? \"\\u25be\" : \"\\u25b8\") : \" \",\n ),\n h(\"span\", { className: \"jr-tree-type\" }, el.type),\n h(\"span\", { className: \"jr-tree-key\" }, `#${key}`),\n summary ? h(\"span\", { className: \"jr-tree-summary\" }, summary) : null,\n el.visible !== undefined\n ? h(\"span\", { className: \"jr-badge\", \"data-tone\": \"amber\" }, \"visible\")\n : null,\n el.repeat\n ? h(\"span\", { className: \"jr-badge\", \"data-tone\": \"accent\" }, \"repeat\")\n : null,\n hasErrors\n ? h(\n \"span\",\n {\n className: \"jr-badge\",\n \"data-tone\": \"red\",\n title: elementIssues.map((i) => i.message).join(\"\\n\"),\n },\n `${elementIssues.length}`,\n )\n : null,\n );\n\n const container = h(\"div\", null, row);\n\n if (isExpanded && hasChildren) {\n for (const childKey of el.children!) {\n const childNode = renderNode(\n spec,\n childKey,\n depth + 1,\n expanded,\n selected,\n issues,\n ctx,\n onToggle,\n hiddenHere,\n );\n if (childNode) container.appendChild(childNode);\n }\n }\n\n return container;\n}\n\n/**\n * Produce a very short human-readable summary of a node's props. Prefers\n * common fields (\"title\", \"label\", \"text\", \"name\") and falls back to the\n * first scalar prop.\n */\nfunction makeSummary(el: UIElement): string | null {\n const props = el.props as Record<string, unknown> | undefined;\n if (!props) return null;\n const prefer = [\"title\", \"label\", \"text\", \"name\", \"value\", \"status\"];\n for (const p of prefer) {\n const v = props[p];\n if (typeof v === \"string\" && v.length > 0) return shorten(v, 60);\n if (typeof v === \"number\" || typeof v === \"boolean\") return String(v);\n }\n for (const [, v] of Object.entries(props)) {\n if (typeof v === \"string\" && v.length > 0) return shorten(v, 60);\n if (typeof v === \"number\" || typeof v === \"boolean\") return String(v);\n }\n return null;\n}\n\nfunction shorten(text: string, max: number): string {\n if (text.length <= max) return text;\n return text.slice(0, max - 1) + \"\\u2026\";\n}\n\nfunction renderDetail(\n container: HTMLElement,\n spec: Spec,\n key: string,\n issues: IssueIndex,\n) {\n const el = spec.elements[key];\n if (!el) {\n replaceChildren(\n container,\n h(\"div\", { className: \"jr-empty\" }, `Element '${key}' not found.`),\n );\n return;\n }\n\n const elIssues = issues.byKey.get(key) ?? [];\n const children = el.children?.length ?? 0;\n\n replaceChildren(\n container,\n h(\n \"div\",\n { className: \"jr-detail\" },\n h(\"h4\", null, \"Element\"),\n h(\n \"div\",\n { style: { marginBottom: \"10px\" } },\n h(\"span\", { className: \"jr-tree-type\" }, el.type),\n \" \",\n h(\"span\", { className: \"jr-tree-key\" }, `#${key}`),\n \" \",\n h(\n \"span\",\n { className: \"jr-tree-summary\" },\n `${children} child${children === 1 ? \"\" : \"ren\"}`,\n ),\n ),\n elIssues.length > 0\n ? [\n h(\"h4\", null, \"Issues\"),\n ...elIssues.map((issue) =>\n h(\n \"div\",\n {\n className: \"jr-badge\",\n \"data-tone\": issue.severity === \"error\" ? \"red\" : \"amber\",\n style: {\n marginBottom: \"6px\",\n display: \"block\",\n padding: \"4px 8px\",\n },\n },\n `${issue.severity.toUpperCase()}: ${issue.message}`,\n ),\n ),\n ]\n : null,\n el.visible !== undefined\n ? [\n h(\"h4\", null, \"Visibility\"),\n h(\"pre\", null, jsonPreview(el.visible, 2000)),\n ]\n : null,\n el.on && Object.keys(el.on).length > 0\n ? [h(\"h4\", null, \"Events\"), h(\"pre\", null, jsonPreview(el.on, 2000))]\n : null,\n el.watch && Object.keys(el.watch).length > 0\n ? [\n h(\"h4\", null, \"Watchers\"),\n h(\"pre\", null, jsonPreview(el.watch, 2000)),\n ]\n : null,\n el.repeat\n ? [\n h(\"h4\", null, \"Repeat\"),\n h(\"pre\", null, jsonPreview(el.repeat, 2000)),\n ]\n : null,\n h(\"h4\", null, \"Props\"),\n h(\"pre\", null, JSON.stringify(el.props, null, 2)),\n ),\n );\n}\n","import { flattenToPointers } from \"@json-render/core/store-utils\";\nimport { h, jsonPreview, replaceChildren } from \"../dom\";\nimport type { PanelContext, TabDef, TabInstance } from \"../types\";\n\nconst TAB_ID = \"state\";\n\n/**\n * State Inspector tab — lists every leaf path in the state model with an\n * inline editor. Editing a value re-parses it as JSON; if the input\n * doesn't parse, the raw string is used. Reads a snapshot from the\n * underlying StateStore on every render, plus on every state-set event.\n */\nexport function stateTab(): TabDef {\n return {\n id: TAB_ID,\n label: \"State\",\n badge(ctx) {\n const store = ctx.getStateStore();\n if (!store) return undefined;\n try {\n const flat = flattenToPointers(store.getSnapshot());\n const count = Object.keys(flat).length;\n return count || undefined;\n } catch {\n return undefined;\n }\n },\n mount(root, ctx) {\n return mountStateTab(root, ctx);\n },\n };\n}\n\nfunction mountStateTab(root: HTMLElement, ctx: PanelContext): TabInstance {\n const container = h(\"div\", {\n style: { height: \"100%\", display: \"flex\", flexDirection: \"column\" },\n });\n const toolbar = h(\"div\", { className: \"jr-toolbar\" });\n const body = h(\"div\", {\n style: { overflow: \"auto\", flex: \"1\", minHeight: \"0\" },\n });\n container.appendChild(toolbar);\n container.appendChild(body);\n root.appendChild(container);\n\n let filter = \"\";\n // Tracks which paths are being edited so live state-set events don't clobber the input.\n const editing = new Set<string>();\n\n const searchInput = h(\"input\", {\n className: \"jr-search\",\n type: \"text\",\n placeholder: \"Filter paths\\u2026\",\n onInput: (ev: Event) => {\n filter = ((ev.target as HTMLInputElement).value || \"\").toLowerCase();\n renderBody();\n },\n });\n\n function renderToolbar() {\n replaceChildren(\n toolbar,\n searchInput,\n h(\n \"button\",\n {\n className: \"jr-icon-btn\",\n title: \"Refresh state listing\",\n onClick: () => renderBody(),\n },\n \"refresh\",\n ),\n );\n }\n\n function renderBody() {\n const store = ctx.getStateStore();\n if (!store) {\n replaceChildren(\n body,\n h(\n \"div\",\n { className: \"jr-empty\" },\n \"No StateStore attached. Devtools sees state once a provider mounts.\",\n ),\n );\n return;\n }\n\n let flat: Record<string, unknown> = {};\n try {\n flat = flattenToPointers(store.getSnapshot());\n } catch (err) {\n replaceChildren(\n body,\n h(\n \"div\",\n { className: \"jr-empty\" },\n `State read failed: ${String(err)}`,\n ),\n );\n return;\n }\n\n const entries = Object.entries(flat)\n .filter(([path]) => !filter || path.toLowerCase().includes(filter))\n .sort(([a], [b]) => a.localeCompare(b));\n\n if (entries.length === 0) {\n replaceChildren(\n body,\n h(\n \"div\",\n { className: \"jr-empty\" },\n filter ? \"No paths match the filter.\" : \"State is empty.\",\n ),\n );\n return;\n }\n\n replaceChildren(\n body,\n entries.map(([path, value]) =>\n renderStateRow(path, value, store.set, editing),\n ),\n );\n }\n\n renderToolbar();\n renderBody();\n\n return {\n update() {\n // Only rebuild when nothing is actively being edited so focus /\n // caret position is preserved between re-renders.\n if (editing.size === 0) renderBody();\n },\n };\n}\n\nfunction renderStateRow(\n path: string,\n value: unknown,\n setValue: (path: string, value: unknown) => void,\n editing: Set<string>,\n): HTMLElement {\n const input = h(\"input\", {\n className: \"jr-state-value\",\n type: \"text\",\n value: stringifyValue(value),\n spellcheck: \"false\" as unknown as string,\n onFocus: () => {\n editing.add(path);\n },\n onBlur: (ev: FocusEvent) => {\n editing.delete(path);\n const raw = (ev.target as HTMLInputElement).value;\n try {\n const parsed = raw === \"\" ? \"\" : JSON.parse(raw);\n setValue(path, parsed);\n input.dataset.dirty = \"false\";\n } catch {\n setValue(path, raw);\n input.dataset.dirty = \"false\";\n }\n },\n onInput: () => {\n input.dataset.dirty = \"true\";\n },\n onKeyDown: (ev: KeyboardEvent) => {\n if (ev.key === \"Enter\") {\n ev.preventDefault();\n (ev.target as HTMLInputElement).blur();\n }\n if (ev.key === \"Escape\") {\n input.value = stringifyValue(value);\n input.dataset.dirty = \"false\";\n (ev.target as HTMLInputElement).blur();\n }\n },\n }) as HTMLInputElement;\n\n return h(\n \"div\",\n {\n className: \"jr-state-row\",\n title: `${path}\\n${jsonPreview(value, 1000)}`,\n },\n h(\"span\", { className: \"jr-state-path\" }, path),\n input,\n );\n}\n\nfunction stringifyValue(value: unknown): string {\n if (typeof value === \"string\") return JSON.stringify(value);\n if (value === null) return \"null\";\n if (value === undefined) return \"\";\n if (typeof value === \"number\" || typeof value === \"boolean\")\n return String(value);\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n","import { formatTime, h, jsonPreview, replaceChildren } from \"../dom\";\nimport type { DevtoolsEvent } from \"../../types\";\nimport type { PanelContext, TabDef, TabInstance } from \"../types\";\n\nconst TAB_ID = \"actions\";\n\ninterface ActionRow {\n id: string;\n name: string;\n params?: unknown;\n dispatchedAt: number;\n settledAt?: number;\n durationMs?: number;\n ok?: boolean;\n result?: unknown;\n error?: string;\n}\n\n/**\n * Action Log tab — chronologically ordered list of dispatched actions.\n * Each dispatch is paired with its settle event (by `id`) to show\n * duration + success/failure.\n */\nexport function actionsTab(): TabDef {\n return {\n id: TAB_ID,\n label: \"Actions\",\n badge(ctx) {\n const rows = foldActions(ctx.events.snapshot()).length;\n return rows || undefined;\n },\n mount(root, ctx) {\n return mountActionsTab(root, ctx);\n },\n };\n}\n\nfunction mountActionsTab(root: HTMLElement, ctx: PanelContext): TabInstance {\n const container = h(\"div\", {\n style: { height: \"100%\", display: \"flex\", flexDirection: \"column\" },\n });\n const toolbar = h(\"div\", { className: \"jr-toolbar\" });\n const body = h(\"div\", {\n style: { overflow: \"auto\", flex: \"1\", minHeight: \"0\" },\n });\n container.appendChild(toolbar);\n container.appendChild(body);\n root.appendChild(container);\n\n let filter = \"\";\n const expanded = new Set<string>();\n\n // Toolbar nodes are created once so the search input keeps focus + caret\n // position across every re-render. Only the dynamic bits (count badge\n // text) are updated imperatively.\n const searchInput = h(\"input\", {\n className: \"jr-search\",\n type: \"text\",\n placeholder: \"Filter by action name\\u2026\",\n onInput: (ev: Event) => {\n filter = ((ev.target as HTMLInputElement).value || \"\").toLowerCase();\n renderBody();\n },\n }) as HTMLInputElement;\n const countBadge = h(\"span\", { className: \"jr-badge\" }, \"0 actions\");\n const clearBtn = h(\n \"button\",\n {\n className: \"jr-icon-btn\",\n title: \"Clear action log\",\n onClick: () => {\n // Only clears action events to preserve other history.\n const keep = ctx.events\n .snapshot()\n .filter(\n (e) =>\n e.kind !== \"action-dispatched\" && e.kind !== \"action-settled\",\n );\n ctx.events.clear();\n for (const e of keep) ctx.events.push(e);\n },\n },\n \"clear\",\n );\n toolbar.append(searchInput, countBadge, clearBtn);\n\n function renderBody() {\n const rows = foldActions(ctx.events.snapshot())\n .filter((r) => !filter || r.name.toLowerCase().includes(filter))\n .reverse(); // newest first\n\n countBadge.textContent = `${rows.length} action${rows.length === 1 ? \"\" : \"s\"}`;\n\n if (rows.length === 0) {\n replaceChildren(\n body,\n h(\n \"div\",\n { className: \"jr-empty\" },\n filter\n ? \"No actions match the filter.\"\n : \"No actions dispatched yet.\",\n ),\n );\n return;\n }\n\n replaceChildren(\n body,\n rows.map((r) => renderRow(r, expanded, renderBody)),\n );\n }\n\n renderBody();\n\n return { update: renderBody };\n}\n\nfunction foldActions(events: DevtoolsEvent[]): ActionRow[] {\n const byId = new Map<string, ActionRow>();\n const order: string[] = [];\n for (const evt of events) {\n if (evt.kind === \"action-dispatched\") {\n if (byId.has(evt.id)) continue;\n byId.set(evt.id, {\n id: evt.id,\n name: evt.name,\n params: evt.params,\n dispatchedAt: evt.at,\n });\n order.push(evt.id);\n } else if (evt.kind === \"action-settled\") {\n const row = byId.get(evt.id);\n if (!row) continue;\n row.settledAt = evt.at;\n row.durationMs = evt.durationMs;\n row.ok = evt.ok;\n row.result = evt.result;\n row.error = evt.error;\n }\n }\n return order.map((id) => byId.get(id)!).filter(Boolean);\n}\n\nfunction renderRow(\n row: ActionRow,\n expanded: Set<string>,\n refresh: () => void,\n): HTMLElement {\n const isExpanded = expanded.has(row.id);\n const pending = row.settledAt === undefined;\n const tone = pending ? \"amber\" : row.ok ? \"green\" : \"red\";\n const status = pending ? \"pending\" : row.ok ? \"ok\" : \"error\";\n const duration =\n row.durationMs !== undefined ? `${row.durationMs.toFixed(0)}ms` : \"\";\n\n const rowEl = h(\n \"div\",\n {\n className: \"jr-row\",\n onClick: () => {\n if (isExpanded) expanded.delete(row.id);\n else expanded.add(row.id);\n refresh();\n },\n },\n h(\"span\", { className: \"jr-row-time\" }, formatTime(row.dispatchedAt)),\n h(\n \"span\",\n { className: \"jr-row-main\" },\n h(\"strong\", null, row.name),\n row.params !== undefined\n ? h(\n \"span\",\n { className: \"jr-tree-summary\", style: { marginLeft: \"8px\" } },\n jsonPreview(row.params, 80),\n )\n : null,\n ),\n h(\n \"span\",\n { className: \"jr-row-meta\" },\n h(\"span\", { className: \"jr-badge\", \"data-tone\": tone }, status),\n duration ? h(\"span\", { style: { marginLeft: \"6px\" } }, duration) : null,\n ),\n );\n\n if (!isExpanded) return rowEl;\n\n const container = h(\"div\", null, rowEl);\n container.appendChild(\n h(\n \"div\",\n { className: \"jr-row-expanded\" },\n h(\"h4\", null, \"Params\"),\n h(\"pre\", null, JSON.stringify(row.params ?? null, null, 2)),\n row.ok === false\n ? [\n h(\"h4\", null, \"Error\"),\n h(\"pre\", null, row.error ?? \"(unknown error)\"),\n ]\n : null,\n row.result !== undefined && row.ok !== false\n ? [\n h(\"h4\", null, \"Result\"),\n h(\"pre\", null, JSON.stringify(row.result, null, 2)),\n ]\n : null,\n ),\n );\n return container;\n}\n","import { formatTime, h, jsonPreview, replaceChildren } from \"../dom\";\nimport type { DevtoolsEvent, TokenUsage } from \"../../types\";\nimport type { PanelContext, TabDef, TabInstance } from \"../types\";\n\nconst TAB_ID = \"stream\";\n\ninterface Generation {\n startedAt: number;\n endedAt?: number;\n ok?: boolean;\n events: DevtoolsEvent[];\n usage?: TokenUsage;\n}\n\n/**\n * Stream Log tab — shows spec patches, text chunks, lifecycle markers,\n * and token usage grouped by generation (lifecycle start -> end).\n */\nexport function streamTab(): TabDef {\n return {\n id: TAB_ID,\n label: \"Stream\",\n badge(ctx) {\n const gens = groupGenerations(ctx.events.snapshot());\n return gens.length || undefined;\n },\n mount(root, ctx) {\n return mountStreamTab(root, ctx);\n },\n };\n}\n\nfunction mountStreamTab(root: HTMLElement, ctx: PanelContext): TabInstance {\n const container = h(\"div\", {\n style: { height: \"100%\", display: \"flex\", flexDirection: \"column\" },\n });\n const toolbar = h(\"div\", { className: \"jr-toolbar\" });\n const body = h(\"div\", {\n style: { overflow: \"auto\", flex: \"1\", minHeight: \"0\" },\n });\n container.appendChild(toolbar);\n container.appendChild(body);\n root.appendChild(container);\n\n function render() {\n const all = ctx.events.snapshot();\n const gens = groupGenerations(all);\n const orphan = collectOrphanEvents(all);\n\n replaceChildren(\n toolbar,\n h(\n \"span\",\n { className: \"jr-badge\" },\n `${gens.length} generation${gens.length === 1 ? \"\" : \"s\"}`,\n ),\n );\n\n if (gens.length === 0 && orphan.length === 0) {\n replaceChildren(\n body,\n h(\n \"div\",\n { className: \"jr-empty\" },\n \"No stream events yet. Tap a stream or pass messages to capture patches.\",\n ),\n );\n return;\n }\n\n const content: HTMLElement[] = [];\n // Newest first; flatten orphan into a pseudo-generation.\n if (orphan.length > 0) {\n content.push(\n renderGeneration(\n { startedAt: orphan[0]?.at ?? Date.now(), events: orphan },\n \"live\",\n true,\n ),\n );\n }\n for (let i = gens.length - 1; i >= 0; i--) {\n const gen = gens[i]!;\n content.push(renderGeneration(gen, `gen-${i}`, i === gens.length - 1));\n }\n replaceChildren(body, content);\n }\n\n render();\n return { update: render };\n}\n\nfunction groupGenerations(events: DevtoolsEvent[]): Generation[] {\n const gens: Generation[] = [];\n let current: Generation | null = null;\n for (const evt of events) {\n if (evt.kind === \"stream-lifecycle\") {\n if (evt.phase === \"start\") {\n if (current) gens.push(current);\n current = { startedAt: evt.at, events: [] };\n } else {\n if (!current) {\n current = { startedAt: evt.at, events: [] };\n }\n current.endedAt = evt.at;\n current.ok = evt.ok;\n gens.push(current);\n current = null;\n }\n continue;\n }\n if (\n evt.kind === \"stream-patch\" ||\n evt.kind === \"stream-text\" ||\n evt.kind === \"stream-usage\"\n ) {\n if (!current) current = { startedAt: evt.at, events: [] };\n current.events.push(evt);\n if (evt.kind === \"stream-usage\") current.usage = evt.usage;\n }\n }\n if (current) gens.push(current);\n return gens;\n}\n\n/**\n * Stream events recorded outside any lifecycle pair (e.g. when the app taps\n * message parts without emitting explicit start/end markers).\n */\nfunction collectOrphanEvents(events: DevtoolsEvent[]): DevtoolsEvent[] {\n const hasAnyLifecycle = events.some((e) => e.kind === \"stream-lifecycle\");\n if (hasAnyLifecycle) return [];\n return events.filter(\n (e) =>\n e.kind === \"stream-patch\" ||\n e.kind === \"stream-text\" ||\n e.kind === \"stream-usage\",\n );\n}\n\nfunction renderGeneration(\n gen: Generation,\n key: string,\n expandedByDefault: boolean,\n): HTMLElement {\n const patchCount = gen.events.filter((e) => e.kind === \"stream-patch\").length;\n const textCount = gen.events.filter((e) => e.kind === \"stream-text\").length;\n const duration =\n gen.endedAt !== undefined ? gen.endedAt - gen.startedAt : undefined;\n const tone =\n gen.endedAt === undefined ? \"amber\" : gen.ok === false ? \"red\" : \"green\";\n const status =\n gen.endedAt === undefined ? \"live\" : gen.ok === false ? \"error\" : \"done\";\n\n const body = h(\n \"div\",\n {\n style: {\n borderTop: \"1px solid var(--jr-border)\",\n background: \"var(--jr-bg-soft)\",\n display: expandedByDefault ? \"block\" : \"none\",\n },\n },\n ...gen.events.map(renderStreamEvent),\n );\n\n const header = h(\n \"div\",\n {\n className: \"jr-row\",\n style: { cursor: \"pointer\" },\n onClick: () => {\n body.style.display = body.style.display === \"none\" ? \"block\" : \"none\";\n },\n },\n h(\"span\", { className: \"jr-row-time\" }, formatTime(gen.startedAt)),\n h(\n \"span\",\n { className: \"jr-row-main\" },\n h(\"strong\", null, `generation #${key}`),\n h(\n \"span\",\n { className: \"jr-tree-summary\", style: { marginLeft: \"8px\" } },\n `${patchCount} patch${patchCount === 1 ? \"\" : \"es\"}`,\n textCount > 0\n ? `, ${textCount} text chunk${textCount === 1 ? \"\" : \"s\"}`\n : \"\",\n ),\n ),\n h(\n \"span\",\n { className: \"jr-row-meta\" },\n h(\"span\", { className: \"jr-badge\", \"data-tone\": tone }, status),\n duration !== undefined\n ? h(\"span\", { style: { marginLeft: \"6px\" } }, `${duration}ms`)\n : null,\n gen.usage\n ? h(\n \"span\",\n { style: { marginLeft: \"6px\" } },\n `${formatTokens(gen.usage.totalTokens)} tok`,\n )\n : null,\n ),\n );\n\n return h(\"div\", null, header, body);\n}\n\nfunction renderStreamEvent(evt: DevtoolsEvent): HTMLElement {\n if (evt.kind === \"stream-patch\") {\n return h(\n \"div\",\n { className: \"jr-row\" },\n h(\"span\", { className: \"jr-row-time\" }, formatTime(evt.at)),\n h(\n \"span\",\n { className: \"jr-row-main\" },\n h(\n \"span\",\n { className: \"jr-badge\", \"data-tone\": \"accent\" },\n evt.patch.op,\n ),\n h(\n \"span\",\n { className: \"jr-tree-summary\", style: { marginLeft: \"8px\" } },\n evt.patch.path,\n evt.patch.value !== undefined\n ? ` = ${jsonPreview(evt.patch.value, 80)}`\n : \"\",\n ),\n ),\n h(\"span\", { className: \"jr-row-meta\" }, evt.source),\n );\n }\n if (evt.kind === \"stream-text\") {\n return h(\n \"div\",\n { className: \"jr-row\" },\n h(\"span\", { className: \"jr-row-time\" }, formatTime(evt.at)),\n h(\n \"span\",\n { className: \"jr-row-main\", style: { whiteSpace: \"pre-wrap\" } },\n evt.text,\n ),\n h(\n \"span\",\n { className: \"jr-row-meta\" },\n h(\"span\", { className: \"jr-badge\" }, \"text\"),\n ),\n );\n }\n if (evt.kind === \"stream-usage\") {\n return h(\n \"div\",\n { className: \"jr-row\" },\n h(\"span\", { className: \"jr-row-time\" }, formatTime(evt.at)),\n h(\n \"span\",\n { className: \"jr-row-main\" },\n `prompt ${formatTokens(evt.usage.promptTokens)} / completion ${formatTokens(\n evt.usage.completionTokens,\n )} / total ${formatTokens(evt.usage.totalTokens)}`,\n ),\n h(\n \"span\",\n { className: \"jr-row-meta\" },\n h(\"span\", { className: \"jr-badge\", \"data-tone\": \"accent\" }, \"usage\"),\n ),\n );\n }\n return h(\"div\");\n}\n\nfunction formatTokens(n: number): string {\n if (n >= 1000) return `${(n / 1000).toFixed(1).replace(/\\.0$/, \"\")}k`;\n return String(n);\n}\n","import { h, replaceChildren } from \"../dom\";\nimport type { PanelContext, TabDef, TabInstance } from \"../types\";\n\nconst TAB_ID = \"catalog\";\n\ninterface CatalogField {\n name: string;\n type: string;\n}\n\ninterface CatalogComponentInfo {\n name: string;\n description: string;\n props: CatalogField[];\n slots: string[];\n events: string[];\n}\n\ninterface CatalogActionInfo {\n name: string;\n description: string;\n params: CatalogField[];\n}\n\n/**\n * Catalog Browser tab — lists the components and actions declared in the\n * attached catalog with prop/param chips, so developers can see what the\n * AI can use.\n */\nexport function catalogTab(): TabDef {\n return {\n id: TAB_ID,\n label: \"Catalog\",\n badge(ctx) {\n const cat = ctx.getCatalog();\n if (!cat) return undefined;\n const n = cat.componentNames.length + cat.actionNames.length;\n return n || undefined;\n },\n mount(root, ctx) {\n return mountCatalogTab(root, ctx);\n },\n };\n}\n\nfunction mountCatalogTab(root: HTMLElement, ctx: PanelContext): TabInstance {\n const container = h(\"div\", {\n style: { height: \"100%\", display: \"flex\", flexDirection: \"column\" },\n });\n const toolbar = h(\"div\", { className: \"jr-toolbar\" });\n const body = h(\"div\", {\n style: { overflow: \"auto\", flex: \"1\", minHeight: \"0\" },\n });\n container.appendChild(toolbar);\n container.appendChild(body);\n root.appendChild(container);\n\n let view: \"components\" | \"actions\" = \"components\";\n let filter = \"\";\n\n // Toolbar controls are mounted once so their DOM identity (and thus the\n // search input's focus + caret position) survives every re-render —\n // without this, typing into the filter would lose focus after each key.\n const componentsBtn = h(\n \"button\",\n {\n className: \"jr-icon-btn\",\n \"data-active\": \"true\",\n onClick: () => {\n if (view === \"components\") return;\n view = \"components\";\n updateToolbarChrome();\n renderBody();\n },\n },\n \"components\",\n );\n const actionsBtn = h(\n \"button\",\n {\n className: \"jr-icon-btn\",\n \"data-active\": \"false\",\n onClick: () => {\n if (view === \"actions\") return;\n view = \"actions\";\n updateToolbarChrome();\n renderBody();\n },\n },\n \"actions\",\n );\n const searchInput = h(\"input\", {\n className: \"jr-search\",\n type: \"text\",\n placeholder: \"Filter by name\\u2026\",\n onInput: (ev: Event) => {\n filter = ((ev.target as HTMLInputElement).value || \"\").toLowerCase();\n renderBody();\n },\n }) as HTMLInputElement;\n toolbar.append(componentsBtn, actionsBtn, searchInput);\n\n function updateToolbarChrome() {\n const catalog = ctx.getCatalog();\n const display = catalog ? buildCatalogDisplayData(catalog.data) : null;\n const cCount = display?.components.length ?? 0;\n const aCount = display?.actions.length ?? 0;\n componentsBtn.textContent = `components (${cCount})`;\n actionsBtn.textContent = `actions (${aCount})`;\n componentsBtn.dataset.active = String(view === \"components\");\n actionsBtn.dataset.active = String(view === \"actions\");\n }\n\n function renderBody() {\n const catalog = ctx.getCatalog();\n if (!catalog) {\n replaceChildren(\n body,\n h(\n \"div\",\n { className: \"jr-empty\" },\n \"No catalog attached. Pass `catalog` to `<JsonRenderDevtools>` to browse it here.\",\n ),\n );\n return;\n }\n\n const display = buildCatalogDisplayData(catalog.data);\n if (view === \"components\") {\n const items = display.components.filter(\n (c) => !filter || c.name.toLowerCase().includes(filter),\n );\n if (items.length === 0) {\n replaceChildren(\n body,\n h(\"div\", { className: \"jr-empty\" }, \"No components match.\"),\n );\n return;\n }\n replaceChildren(body, items.map(renderComponent));\n } else {\n const items = display.actions.filter(\n (a) => !filter || a.name.toLowerCase().includes(filter),\n );\n if (items.length === 0) {\n replaceChildren(\n body,\n h(\"div\", { className: \"jr-empty\" }, \"No actions match.\"),\n );\n return;\n }\n replaceChildren(body, items.map(renderAction));\n }\n }\n\n function render() {\n updateToolbarChrome();\n renderBody();\n }\n\n render();\n return { update: render };\n}\n\nfunction renderComponent(c: CatalogComponentInfo): HTMLElement {\n return h(\n \"div\",\n { className: \"jr-catalog-item\" },\n h(\"div\", { className: \"jr-catalog-name\" }, c.name),\n c.description\n ? h(\"div\", { className: \"jr-catalog-desc\" }, c.description)\n : null,\n c.props.length > 0 || c.events.length > 0\n ? h(\n \"div\",\n { className: \"jr-chips\" },\n ...c.props.map((p) =>\n h(\n \"span\",\n { className: \"jr-chip\", \"data-tone\": \"prop\" },\n `${p.name}: ${p.type}`,\n ),\n ),\n ...c.events.map((e) =>\n h(\n \"span\",\n { className: \"jr-chip\", \"data-tone\": \"event\" },\n `on.${e}`,\n ),\n ),\n )\n : null,\n );\n}\n\nfunction renderAction(a: CatalogActionInfo): HTMLElement {\n return h(\n \"div\",\n { className: \"jr-catalog-item\" },\n h(\"div\", { className: \"jr-catalog-name\" }, a.name),\n a.description\n ? h(\"div\", { className: \"jr-catalog-desc\" }, a.description)\n : null,\n a.params.length > 0\n ? h(\n \"div\",\n { className: \"jr-chips\" },\n ...a.params.map((p) =>\n h(\n \"span\",\n { className: \"jr-chip\", \"data-tone\": \"param\" },\n `${p.name}: ${p.type}`,\n ),\n ),\n )\n : null,\n );\n}\n\n/**\n * Extract display data from a raw catalog definition. Handles both Zod v3\n * (`_def.shape()`) and v4 (`shape` getter). Resilient to missing fields.\n *\n * Same logic as `apps/web/lib/render/catalog-display.ts` but lives here\n * so framework adapters don't depend on the web app.\n */\nexport function buildCatalogDisplayData(rawCatalogData: unknown): {\n components: CatalogComponentInfo[];\n actions: CatalogActionInfo[];\n} {\n const raw = (rawCatalogData ?? {}) as Record<string, unknown>;\n const componentsRaw = (raw.components ?? {}) as Record<string, unknown>;\n const actionsRaw = (raw.actions ?? {}) as Record<string, unknown>;\n\n const components: CatalogComponentInfo[] = Object.entries(componentsRaw)\n .map(([name, def]) => {\n const d = (def ?? {}) as Record<string, unknown>;\n return {\n name,\n description: (d.description as string) ?? \"\",\n props: extractFields(d.props),\n slots: Array.isArray(d.slots) ? (d.slots as string[]) : [],\n events: Array.isArray(d.events) ? (d.events as string[]) : [],\n };\n })\n .sort((a, b) => a.name.localeCompare(b.name));\n\n const actions: CatalogActionInfo[] = Object.entries(actionsRaw)\n .map(([name, def]) => {\n const d = (def ?? {}) as Record<string, unknown>;\n return {\n name,\n description: (d.description as string) ?? \"\",\n params: extractFields(d.params),\n };\n })\n .sort((a, b) => a.name.localeCompare(b.name));\n\n return { components, actions };\n}\n\nfunction extractFields(zodObj: unknown): CatalogField[] {\n if (!zodObj) return [];\n try {\n const obj = zodObj as Record<string, unknown>;\n const shape =\n typeof obj.shape === \"object\" && obj.shape !== null\n ? (obj.shape as Record<string, unknown>)\n : typeof (obj as { _def?: { shape?: unknown } })._def?.shape ===\n \"function\"\n ? (\n obj as { _def: { shape: () => Record<string, unknown> } }\n )._def.shape()\n : typeof (obj as { _def?: { shape?: unknown } })._def?.shape ===\n \"object\"\n ? (obj as { _def: { shape: Record<string, unknown> } })._def.shape\n : null;\n if (!shape) return [];\n\n return Object.entries(shape).map(([name, schema]) => {\n let type = \"unknown\";\n try {\n const s = schema as {\n _zod?: {\n def?: { type?: string; values?: unknown[]; innerType?: unknown };\n };\n _def?: { typeName?: string; values?: unknown[]; innerType?: unknown };\n };\n const typeName: string = s?._zod?.def?.type ?? s?._def?.typeName ?? \"\";\n if (typeName.includes(\"string\")) type = \"string\";\n else if (typeName.includes(\"number\")) type = \"number\";\n else if (typeName.includes(\"boolean\")) type = \"boolean\";\n else if (typeName.includes(\"array\")) type = \"array\";\n else if (typeName.includes(\"enum\")) {\n const values = s?._zod?.def?.values ?? s?._def?.values;\n type = Array.isArray(values) ? values.join(\" | \") : \"enum\";\n } else if (typeName.includes(\"union\")) type = \"union\";\n else if (typeName.includes(\"nullable\")) {\n const inner = (s?._zod?.def?.innerType ?? s?._def?.innerType) as\n | {\n _zod?: { def?: { type?: string; values?: unknown[] } };\n _def?: { typeName?: string; values?: unknown[] };\n }\n | undefined;\n const innerName: string =\n inner?._zod?.def?.type ?? inner?._def?.typeName ?? \"\";\n if (innerName.includes(\"string\")) type = \"string?\";\n else if (innerName.includes(\"number\")) type = \"number?\";\n else if (innerName.includes(\"boolean\")) type = \"boolean?\";\n else if (innerName.includes(\"array\")) type = \"array?\";\n else if (innerName.includes(\"enum\")) {\n const values = inner?._zod?.def?.values ?? inner?._def?.values;\n type = Array.isArray(values) ? `(${values.join(\" | \")})?` : \"enum?\";\n } else type = \"optional\";\n }\n } catch {\n // ignore\n }\n return { name, type };\n });\n } catch {\n return [];\n }\n}\n","import { h, replaceChildren } from \"../dom\";\nimport { findElementByKey } from \"../../picker\";\nimport type { PanelContext, TabDef, TabInstance } from \"../types\";\n\nconst TAB_ID = \"pick\";\n\n/**\n * Picker tab — explains the DOM picker flow, starts / stops a picker\n * session, and shows the currently selected element key. Selecting a key\n * in the spec tab reflects here; selecting here (via click-to-pick)\n * jumps back to the spec tab.\n */\nexport function pickerTab(): TabDef {\n return {\n id: TAB_ID,\n label: \"Pick\",\n mount(root, ctx) {\n return mountPickerTab(root, ctx);\n },\n };\n}\n\nfunction mountPickerTab(root: HTMLElement, ctx: PanelContext): TabInstance {\n let active = false;\n let stopFn: (() => void) | null = null;\n\n const body = h(\"div\", { style: { padding: \"16px 12px\" } });\n root.appendChild(body);\n\n const unsubSelection = ctx.selection.subscribe(() => render());\n\n function start() {\n if (active) return;\n const session = ctx.startPicker?.({\n onPick: (key) => {\n active = false;\n stopFn = null;\n ctx.selection.set(key);\n ctx.activateTab(\"spec\");\n },\n onCancel: () => {\n active = false;\n stopFn = null;\n render();\n },\n });\n if (!session) {\n render();\n return;\n }\n stopFn = session.stop;\n active = true;\n render();\n }\n\n function stop() {\n if (stopFn) stopFn();\n stopFn = null;\n active = false;\n render();\n }\n\n function render() {\n const selected = ctx.selection.get();\n const canPick = typeof document !== \"undefined\";\n const selectedMounted = selected ? !!findElementByKey(selected) : false;\n\n replaceChildren(\n body,\n h(\n \"div\",\n { style: { marginBottom: \"12px\", color: \"var(--jr-fg-muted)\" } },\n \"Click in the page to pick an element. Hovering paints an outline.\",\n ),\n h(\n \"button\",\n {\n className: \"jr-icon-btn\",\n style: {\n padding: \"6px 12px\",\n width: \"auto\",\n border: \"1px solid var(--jr-border)\",\n borderRadius: \"6px\",\n },\n disabled: !canPick,\n \"data-active\": String(active),\n onClick: () => (active ? stop() : start()),\n },\n active ? \"Stop picking (Esc)\" : \"Start picking\",\n ),\n h(\n \"div\",\n { style: { marginTop: \"18px\" } },\n h(\n \"h4\",\n {\n style: {\n margin: \"0 0 6px 0\",\n fontSize: \"10px\",\n color: \"var(--jr-fg-dim)\",\n textTransform: \"uppercase\",\n letterSpacing: \"0.06em\",\n },\n },\n \"Current selection\",\n ),\n selected\n ? h(\n \"div\",\n {\n className: \"jr-badge\",\n style: { padding: \"4px 8px\", fontSize: \"11px\" },\n },\n `#${selected}`,\n )\n : h(\n \"div\",\n { style: { color: \"var(--jr-fg-dim)\", fontSize: \"11px\" } },\n \"No selection\",\n ),\n selected && !selectedMounted\n ? h(\n \"div\",\n {\n style: {\n marginTop: \"6px\",\n color: \"var(--jr-amber)\",\n fontSize: \"10px\",\n },\n },\n \"This element has no DOM node right now (hidden by visibility, or renderer not wrapping for picker).\",\n )\n : null,\n ),\n !canPick\n ? h(\n \"div\",\n {\n style: {\n marginTop: \"18px\",\n color: \"var(--jr-fg-dim)\",\n fontSize: \"11px\",\n },\n },\n \"Picker requires a DOM environment.\",\n )\n : null,\n );\n }\n\n render();\n return {\n update: render,\n destroy() {\n stop();\n unsubSelection();\n },\n };\n}\n","import {\n SPEC_DATA_PART_TYPE,\n applySpecPatch,\n nestedToFlat,\n type Spec,\n type SpecDataPart,\n type StreamChunk,\n} from \"@json-render/core\";\nimport type { EventStore } from \"./event-store\";\nimport type { DevtoolsEvent, TokenUsage } from \"./types\";\n\n/**\n * A minimal shape compatible with AI SDK `UIMessage.parts[i]`. Defined\n * locally so the devtools package has no dependency on the `ai` package.\n */\ninterface DataPart {\n type: string;\n text?: string;\n data?: unknown;\n state?: string;\n}\n\n/**\n * Wrap a `ReadableStream<StreamChunk>` (e.g. the output of `pipeJsonRender`\n * or any `TransformStream<StreamChunk, StreamChunk>`) so spec patches are\n * mirrored into a devtools `EventStore` as they fly past.\n *\n * Returns the original stream unchanged — the tap just forks a copy.\n *\n * @example\n * ```ts\n * writer.merge(\n * tapJsonRenderStream(\n * pipeJsonRender(result.toUIMessageStream()),\n * devtoolsEventStore,\n * ),\n * );\n * ```\n */\nexport function tapJsonRenderStream(\n stream: ReadableStream<StreamChunk>,\n events: EventStore,\n): ReadableStream<StreamChunk> {\n const [a, b] = stream.tee();\n void consumeToEvents(b, events, \"json\");\n return a;\n}\n\n/** YAML variant — identical behaviour with `source: \"yaml\"`. */\nexport function tapYamlStream(\n stream: ReadableStream<StreamChunk>,\n events: EventStore,\n): ReadableStream<StreamChunk> {\n const [a, b] = stream.tee();\n void consumeToEvents(b, events, \"yaml\");\n return a;\n}\n\nasync function consumeToEvents(\n stream: ReadableStream<StreamChunk>,\n events: EventStore,\n source: \"json\" | \"yaml\",\n): Promise<void> {\n events.push({ kind: \"stream-lifecycle\", at: Date.now(), phase: \"start\" });\n let ok = true;\n try {\n const reader = stream.getReader();\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (!value) continue;\n forwardChunk(value, events, source);\n }\n } catch (err) {\n ok = false;\n events.push({\n kind: \"stream-text\",\n at: Date.now(),\n text: `[stream error: ${String(err)}]`,\n });\n } finally {\n events.push({\n kind: \"stream-lifecycle\",\n at: Date.now(),\n phase: \"end\",\n ok,\n });\n }\n}\n\nfunction forwardChunk(\n chunk: StreamChunk,\n events: EventStore,\n source: \"json\" | \"yaml\",\n) {\n if (chunk.type === SPEC_DATA_PART_TYPE) {\n const data = (chunk as { data?: SpecDataPart }).data;\n if (!data) return;\n if (data.type === \"patch\") {\n events.push({\n kind: \"stream-patch\",\n at: Date.now(),\n patch: data.patch,\n source,\n });\n }\n return;\n }\n if (chunk.type === \"text-delta\") {\n const delta = (chunk as { delta?: string }).delta ?? \"\";\n if (delta) {\n events.push({ kind: \"stream-text\", at: Date.now(), text: delta });\n }\n }\n}\n\n/**\n * Client-side helper: scan a message's `parts` array for spec data parts\n * and push matching events into the store. Use this when rendering chat\n * UIs that use `@ai-sdk/react` `useChat` and pass in `messages`.\n *\n * Idempotent via `seenIds`: only parts not already recorded will emit.\n * Returns the new `seenIds` set so callers can persist it between calls.\n */\nexport function scanMessageParts(\n parts: readonly DataPart[] | undefined,\n events: EventStore,\n seen: WeakSet<object>,\n): void {\n if (!parts) return;\n for (const part of parts) {\n if (!part || typeof part !== \"object\") continue;\n if (seen.has(part)) continue;\n seen.add(part);\n if (part.type === SPEC_DATA_PART_TYPE) {\n const data = part.data as SpecDataPart | undefined;\n if (!data) continue;\n if (data.type === \"patch\") {\n events.push({\n kind: \"stream-patch\",\n at: Date.now(),\n patch: data.patch,\n source: \"json\",\n });\n }\n }\n }\n}\n\n/**\n * Emit a token-usage event. Called by adapters with whatever usage\n * object their framework surfaces (AI SDK `result.usage`).\n */\nexport function recordUsage(events: EventStore, usage: TokenUsage): void {\n events.push({ kind: \"stream-usage\", at: Date.now(), usage });\n}\n\n/**\n * Replay every `SPEC_DATA_PART` in `parts` and return the resulting spec,\n * or `null` if the message has no UI. Mirrors the framework-side\n * `buildSpecFromParts` helper but without a framework dependency — used by\n * the devtools panel's generation switcher to reconstruct each prior\n * assistant message's spec so the user can inspect any of them.\n */\nexport function extractSpecFromParts(\n parts: readonly DataPart[] | undefined,\n): Spec | null {\n if (!parts) return null;\n const spec: Spec = { root: \"\", elements: {} };\n let hasSpec = false;\n for (const part of parts) {\n if (!part || typeof part !== \"object\") continue;\n if (part.type !== SPEC_DATA_PART_TYPE) continue;\n const data = part.data as SpecDataPart | undefined;\n if (!data) continue;\n if (data.type === \"patch\") {\n hasSpec = true;\n applySpecPatch(spec, data.patch);\n } else if (data.type === \"flat\") {\n hasSpec = true;\n Object.assign(spec, data.spec);\n } else if (data.type === \"nested\") {\n hasSpec = true;\n Object.assign(spec, nestedToFlat(data.spec));\n }\n }\n return hasSpec ? spec : null;\n}\n\n/** Emit a pre-built devtools event. Useful for manual instrumentation. */\nexport function recordEvent(events: EventStore, event: DevtoolsEvent): void {\n events.push(event);\n}\n"],"mappings":"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A;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmrBlB,IAAM,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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","names":["el","TAB_ID","TAB_ID","TAB_ID","TAB_ID","TAB_ID"]}
|
|
1
|
+
{"version":3,"sources":["../src/event-store.ts","../src/prod-guard.ts","../src/panel/dom.ts","../src/picker.ts","../src/panel/styles.ts","../src/panel/shell.ts","../src/panel/types.ts","../src/panel/tabs/spec.ts","../src/panel/tabs/state.ts","../src/panel/tabs/actions.ts","../src/panel/tabs/stream.ts","../src/panel/tabs/catalog.ts","../src/panel/tabs/picker.ts","../src/stream-tap.ts"],"sourcesContent":["import type { DevtoolsEvent } from \"./types\";\n\n/**\n * Options for {@link createEventStore}.\n */\nexport interface EventStoreOptions {\n /** Max events to retain. Older events are dropped. Default: 500. */\n bufferSize?: number;\n}\n\n/**\n * A capped, subscribable ring buffer of {@link DevtoolsEvent}s.\n *\n * Core to every devtools panel — all adapters push into the same store,\n * and panel UIs subscribe for render updates.\n */\nexport interface EventStore {\n /** Append an event. May drop the oldest event if the buffer is full. */\n push: (event: DevtoolsEvent) => void;\n /**\n * Current events in insertion order (oldest first). Returns a fresh\n * array so callers can treat it as immutable.\n */\n snapshot: () => DevtoolsEvent[];\n /**\n * Register a listener invoked after every push (or `clear`). Returns\n * an unsubscribe function. Listeners are invoked synchronously.\n */\n subscribe: (listener: () => void) => () => void;\n /** Remove all events. Notifies listeners. */\n clear: () => void;\n /** Current event count. */\n size: () => number;\n}\n\n/**\n * Create an in-memory ring-buffered event store.\n *\n * @example\n * ```ts\n * const store = createEventStore({ bufferSize: 200 });\n * const unsub = store.subscribe(() => render(store.snapshot()));\n * store.push({ kind: \"state-set\", at: Date.now(), path: \"/x\", prev: 1, next: 2 });\n * ```\n */\nexport function createEventStore(options: EventStoreOptions = {}): EventStore {\n const bufferSize = Math.max(1, options.bufferSize ?? 500);\n const events: DevtoolsEvent[] = [];\n const listeners = new Set<() => void>();\n\n function notify() {\n for (const listener of listeners) {\n try {\n listener();\n } catch (err) {\n if (process.env.NODE_ENV !== \"production\") {\n console.error(\"[json-render devtools] listener threw:\", err);\n }\n }\n }\n }\n\n return {\n push(event) {\n events.push(event);\n if (events.length > bufferSize) {\n events.splice(0, events.length - bufferSize);\n }\n notify();\n },\n snapshot() {\n return events.slice();\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n clear() {\n if (events.length === 0) return;\n events.length = 0;\n notify();\n },\n size() {\n return events.length;\n },\n };\n}\n","/**\n * Production guard. Framework adapters short-circuit to a no-op when this\n * returns true, so dropping `<JsonRenderDevtools />` into an app costs\n * nothing in production builds.\n *\n * Tree-shaken bundlers will fold constant `process.env.NODE_ENV` checks.\n * Consumers that run in browsers without `process` also work because the\n * typeof check guards the access.\n */\nexport function isProduction(): boolean {\n if (typeof process !== \"undefined\" && process.env) {\n return process.env.NODE_ENV === \"production\";\n }\n return false;\n}\n","/**\n * Tiny hyperscript-style helper for building DOM nodes without JSX.\n *\n * Keeps the vanilla-TS panel readable. Supports attributes starting with\n * `on` as event listeners, `className`, inline `style` objects, and a mix\n * of string / node / array children.\n */\n\ntype Child = Node | string | number | null | undefined | false | Child[];\n\ntype Attrs = {\n [key: string]: unknown;\n className?: string;\n style?: Partial<CSSStyleDeclaration>;\n};\n\nfunction appendChild(parent: Node, child: Child): void {\n if (child === null || child === undefined || child === false) return;\n if (Array.isArray(child)) {\n for (const c of child) appendChild(parent, c);\n return;\n }\n if (child instanceof Node) {\n parent.appendChild(child);\n return;\n }\n parent.appendChild(document.createTextNode(String(child)));\n}\n\nexport function h<K extends keyof HTMLElementTagNameMap>(\n tag: K,\n attrs?: Attrs | null,\n ...children: Child[]\n): HTMLElementTagNameMap[K] {\n const el = document.createElement(tag);\n if (attrs) {\n for (const [key, value] of Object.entries(attrs)) {\n if (value === null || value === undefined || value === false) continue;\n if (key === \"className\") {\n el.className = String(value);\n } else if (key === \"style\" && typeof value === \"object\") {\n Object.assign(el.style, value as Partial<CSSStyleDeclaration>);\n } else if (key.startsWith(\"on\") && typeof value === \"function\") {\n el.addEventListener(key.slice(2).toLowerCase(), value as EventListener);\n } else if (key === \"dataset\" && typeof value === \"object\") {\n for (const [dk, dv] of Object.entries(\n value as Record<string, string>,\n )) {\n el.dataset[dk] = String(dv);\n }\n } else if (typeof value === \"boolean\") {\n if (value) el.setAttribute(key, \"\");\n } else {\n el.setAttribute(key, String(value));\n }\n }\n }\n for (const child of children) appendChild(el, child);\n return el;\n}\n\n/** Replace the children of `parent` with `next`, clearing first. */\nexport function replaceChildren(parent: Node, ...next: Child[]): void {\n while (parent.firstChild) parent.removeChild(parent.firstChild);\n for (const n of next) appendChild(parent, n);\n}\n\n/** Render a short JSON preview that truncates long values. */\nexport function jsonPreview(value: unknown, max = 140): string {\n let text: string;\n try {\n text = JSON.stringify(value);\n } catch {\n text = String(value);\n }\n if (text === undefined) return \"undefined\";\n if (text.length > max) return text.slice(0, max - 1) + \"\\u2026\";\n return text;\n}\n\n/** Format an absolute timestamp (ms) as `HH:MM:SS.mmm`. */\nexport function formatTime(at: number): string {\n const d = new Date(at);\n const hh = String(d.getHours()).padStart(2, \"0\");\n const mm = String(d.getMinutes()).padStart(2, \"0\");\n const ss = String(d.getSeconds()).padStart(2, \"0\");\n const ms = String(d.getMilliseconds()).padStart(3, \"0\");\n return `${hh}:${mm}:${ss}.${ms}`;\n}\n","import type { PickerOptions, PickerSession } from \"./types\";\n\n/**\n * Attribute the ElementRenderer (when devtools is active) sets on each\n * rendered element's wrapper. The picker walks up from the hovered node\n * to the nearest ancestor bearing this attribute.\n */\nexport const DEVTOOLS_KEY_ATTR = \"data-jr-key\";\n\nconst PICKER_OVERLAY_ID = \"__jr_devtools_picker_overlay\";\nconst PICKER_LABEL_ID = \"__jr_devtools_picker_label\";\nconst HOVER_OVERLAY_ID = \"__jr_devtools_hover_overlay\";\nconst HOVER_LABEL_ID = \"__jr_devtools_hover_label\";\n\n// ---------------------------------------------------------------------------\n// Shared geometry helper\n// ---------------------------------------------------------------------------\n\n/**\n * Compute a bounding rect for a (possibly `display: contents`) element by\n * falling back to the union of its descendants' client rects.\n *\n * json-render wraps every keyed element in `<span data-jr-key=\"...\" style\n * =\"display:contents\">`, and `display: contents` elements don't generate a\n * CSS box — so their own `getBoundingClientRect()` returns `0 × 0` and a\n * plain CSS outline paints nothing. We recursively widen to child boxes so\n * the overlay tracks the visible extent.\n */\nfunction computeBounds(el: Element): DOMRect | null {\n const own = el.getBoundingClientRect();\n if (own.width > 0 && own.height > 0) return own;\n let left = Infinity;\n let top = Infinity;\n let right = -Infinity;\n let bottom = -Infinity;\n const walker = document.createTreeWalker(el, NodeFilter.SHOW_ELEMENT);\n let node = walker.nextNode() as Element | null;\n while (node) {\n const r = node.getBoundingClientRect();\n if (r.width > 0 && r.height > 0) {\n if (r.left < left) left = r.left;\n if (r.top < top) top = r.top;\n if (r.right > right) right = r.right;\n if (r.bottom > bottom) bottom = r.bottom;\n }\n node = walker.nextNode() as Element | null;\n }\n if (!Number.isFinite(left) || !Number.isFinite(top)) return null;\n return new DOMRect(left, top, right - left, bottom - top);\n}\n\n/**\n * Position an overlay + label pair over a given rect. Both elements are\n * created on demand inside `document.body`; callers pass in the ids so the\n * picker and the tree-hover highlight don't collide.\n */\nfunction paintOverlay(\n rect: DOMRect,\n label: string,\n ids: { overlay: string; label: string },\n): { overlay: HTMLDivElement; label: HTMLDivElement } {\n let ov = document.getElementById(ids.overlay) as HTMLDivElement | null;\n if (!ov) {\n ov = document.createElement(\"div\");\n ov.id = ids.overlay;\n document.body.appendChild(ov);\n }\n ov.style.display = \"block\";\n ov.style.left = `${rect.left}px`;\n ov.style.top = `${rect.top}px`;\n ov.style.width = `${rect.width}px`;\n ov.style.height = `${rect.height}px`;\n\n let lb = document.getElementById(ids.label) as HTMLDivElement | null;\n if (!lb) {\n lb = document.createElement(\"div\");\n lb.id = ids.label;\n document.body.appendChild(lb);\n }\n lb.textContent = label;\n lb.style.display = \"block\";\n const labelLeft = Math.max(4, rect.left);\n // Prefer the label above the overlay, fall back to below when the element\n // is flush against the viewport top.\n const labelTop = rect.top >= 24 ? rect.top - 22 : rect.top + rect.height + 4;\n lb.style.left = `${labelLeft}px`;\n lb.style.top = `${labelTop}px`;\n return { overlay: ov, label: lb };\n}\n\nfunction hideOverlayPair(ids: { overlay: string; label: string }): void {\n const ov = document.getElementById(ids.overlay);\n const lb = document.getElementById(ids.label);\n if (ov) ov.style.display = \"none\";\n if (lb) lb.style.display = \"none\";\n}\n\nfunction removeOverlayPair(ids: { overlay: string; label: string }): void {\n const ov = document.getElementById(ids.overlay);\n const lb = document.getElementById(ids.label);\n if (ov) ov.remove();\n if (lb) lb.remove();\n}\n\n// ---------------------------------------------------------------------------\n// Picker — click-to-pick session started by the toolbar button\n// ---------------------------------------------------------------------------\n\n/**\n * Start an interactive DOM picker. The user hovers or clicks any element\n * in the page; when a click lands on (or inside) a node carrying\n * {@link DEVTOOLS_KEY_ATTR}, `onPick` fires with that key.\n *\n * Returns `null` in environments without a DOM (SSR, tests).\n *\n * The picker paints a translucent overlay + border over the hovered\n * element (Chrome-DevTools style). See {@link computeBounds} for the\n * `display: contents` fallback.\n */\nexport function startPicker(options: PickerOptions): PickerSession | null {\n if (typeof document === \"undefined\") return null;\n\n const IDS = { overlay: PICKER_OVERLAY_ID, label: PICKER_LABEL_ID };\n let currentHover: Element | null = null;\n\n function paint(el: Element) {\n const rect = computeBounds(el);\n if (!rect) {\n hideOverlayPair(IDS);\n return;\n }\n const key = el.getAttribute(DEVTOOLS_KEY_ATTR) ?? \"\";\n paintOverlay(\n rect,\n `${key} ${Math.round(rect.width)} × ${Math.round(rect.height)}`,\n IDS,\n );\n }\n\n const onMove = (ev: MouseEvent) => {\n const target = ev.target as Element | null;\n if (!target || !target.closest) return;\n const host = target.closest(`[${DEVTOOLS_KEY_ATTR}]`);\n if (host !== currentHover) currentHover = host;\n if (host) paint(host);\n else hideOverlayPair(IDS);\n };\n\n const onClick = (ev: MouseEvent) => {\n ev.preventDefault();\n ev.stopPropagation();\n const target = ev.target as Element | null;\n const host = target?.closest?.(`[${DEVTOOLS_KEY_ATTR}]`);\n if (host) {\n const key = host.getAttribute(DEVTOOLS_KEY_ATTR) ?? \"\";\n stop();\n options.onPick(key);\n }\n };\n\n const onKey = (ev: KeyboardEvent) => {\n if (ev.key === \"Escape\") {\n ev.preventDefault();\n stop();\n options.onCancel?.();\n }\n };\n\n // Keep the overlay glued to the element while the user scrolls, the\n // viewport resizes, or the DOM reflows (e.g. streaming patches arrive\n // during pick).\n const onReposition = () => {\n if (currentHover && currentHover.isConnected) {\n paint(currentHover);\n } else if (currentHover) {\n currentHover = null;\n hideOverlayPair(IDS);\n }\n };\n\n function stop() {\n removeOverlayPair(IDS);\n currentHover = null;\n document.documentElement.removeAttribute(\"data-jr-devtools-picking\");\n document.removeEventListener(\"mousemove\", onMove, true);\n document.removeEventListener(\"click\", onClick, true);\n document.removeEventListener(\"keydown\", onKey, true);\n window.removeEventListener(\"scroll\", onReposition, true);\n window.removeEventListener(\"resize\", onReposition);\n }\n\n document.documentElement.setAttribute(\"data-jr-devtools-picking\", \"true\");\n document.addEventListener(\"mousemove\", onMove, true);\n document.addEventListener(\"click\", onClick, true);\n document.addEventListener(\"keydown\", onKey, true);\n window.addEventListener(\"scroll\", onReposition, true);\n window.addEventListener(\"resize\", onReposition);\n\n return { stop };\n}\n\n// ---------------------------------------------------------------------------\n// Hover highlight — persistent overlay driven by spec-tree hover\n// ---------------------------------------------------------------------------\n\nconst HOVER_IDS = { overlay: HOVER_OVERLAY_ID, label: HOVER_LABEL_ID };\n/**\n * Class (not id) used for the *secondary* overlays that paint the extra\n * instances of a repeated element. Styled by HOST_CSS with a dashed amber\n * outline so they're clearly distinguished from the single primary hover.\n */\nconst HOVER_EXTRA_CLASS = \"__jr_devtools_hover_extra\";\nlet hoverKey: string | null = null;\nlet hoverListenersAttached = false;\nlet hoverExtraOverlays: HTMLDivElement[] = [];\n\nfunction ensureExtraOverlay(index: number): HTMLDivElement {\n let ov = hoverExtraOverlays[index];\n if (!ov) {\n ov = document.createElement(\"div\");\n ov.className = HOVER_EXTRA_CLASS;\n document.body.appendChild(ov);\n hoverExtraOverlays[index] = ov;\n }\n return ov;\n}\n\nfunction hideExtrasFrom(index: number): void {\n for (let i = index; i < hoverExtraOverlays.length; i++) {\n const ov = hoverExtraOverlays[i];\n if (ov) ov.style.display = \"none\";\n }\n}\n\nfunction removeAllExtras(): void {\n for (const ov of hoverExtraOverlays) ov.remove();\n hoverExtraOverlays = [];\n}\n\nfunction repositionHover() {\n if (!hoverKey) return;\n const matches = findAllElementsByKey(hoverKey);\n const first = matches[0];\n if (!first) {\n hideOverlayPair(HOVER_IDS);\n hideExtrasFrom(0);\n return;\n }\n\n // Primary overlay + label paints the first match.\n const firstRect = computeBounds(first);\n if (!firstRect) {\n hideOverlayPair(HOVER_IDS);\n hideExtrasFrom(0);\n return;\n }\n const labelSuffix =\n matches.length > 1 ? ` (${matches.length} instances)` : \"\";\n paintOverlay(\n firstRect,\n `${hoverKey} ${Math.round(firstRect.width)} × ${Math.round(firstRect.height)}${labelSuffix}`,\n HOVER_IDS,\n );\n\n // Extra instances (for repeated elements) get their own overlays,\n // styled in amber to distinguish from the primary.\n for (let i = 1; i < matches.length; i++) {\n const el = matches[i];\n if (!el) continue;\n const rect = computeBounds(el);\n const ov = ensureExtraOverlay(i - 1);\n if (!rect) {\n ov.style.display = \"none\";\n continue;\n }\n ov.style.display = \"block\";\n ov.style.left = `${rect.left}px`;\n ov.style.top = `${rect.top}px`;\n ov.style.width = `${rect.width}px`;\n ov.style.height = `${rect.height}px`;\n }\n hideExtrasFrom(Math.max(0, matches.length - 1));\n}\n\nfunction attachHoverListeners() {\n if (hoverListenersAttached || typeof window === \"undefined\") return;\n hoverListenersAttached = true;\n window.addEventListener(\"scroll\", repositionHover, true);\n window.addEventListener(\"resize\", repositionHover);\n}\n\nfunction detachHoverListeners() {\n if (!hoverListenersAttached || typeof window === \"undefined\") return;\n hoverListenersAttached = false;\n window.removeEventListener(\"scroll\", repositionHover, true);\n window.removeEventListener(\"resize\", repositionHover);\n}\n\n/**\n * Show (or hide) a persistent bounding-box overlay over the element\n * identified by `key`. Pass `null` to clear the overlay.\n *\n * Unlike {@link highlightElement}, this does not fade out — callers are\n * expected to clear it explicitly (typically on `mouseleave`). Safe to\n * call repeatedly; each call cheaply repositions the single overlay.\n */\nexport function setHoverHighlight(key: string | null): void {\n if (typeof document === \"undefined\") return;\n if (!key) {\n hoverKey = null;\n removeOverlayPair(HOVER_IDS);\n removeAllExtras();\n detachHoverListeners();\n return;\n }\n hoverKey = key;\n repositionHover();\n attachHoverListeners();\n}\n\n// ---------------------------------------------------------------------------\n// Element lookup + brief flash highlight\n// ---------------------------------------------------------------------------\n\n/**\n * Look up the DOM element carrying `data-jr-key={key}`. Returns `null`\n * when no match (spec exists but hasn't rendered, or the element is\n * currently hidden by a visibility condition).\n *\n * Note: when an element appears inside a `repeat`, each repetition\n * renders its own DOM instance with the same `data-jr-key`. Use\n * {@link findAllElementsByKey} if you need all of them.\n */\nexport function findElementByKey(key: string): Element | null {\n if (typeof document === \"undefined\") return null;\n return document.querySelector(`[${DEVTOOLS_KEY_ATTR}=\"${cssEscape(key)}\"]`);\n}\n\n/**\n * Return every DOM element carrying `data-jr-key={key}`. Intended for\n * repeated spec elements (list items, grid cells…) where a single spec\n * key renders to N DOM instances.\n */\nexport function findAllElementsByKey(key: string): Element[] {\n if (typeof document === \"undefined\") return [];\n const selector = `[${DEVTOOLS_KEY_ATTR}=\"${cssEscape(key)}\"]`;\n return Array.from(document.querySelectorAll(selector));\n}\n\n/**\n * Briefly paint an outline around the DOM element for `key`, so clicking\n * a spec-tree row in the panel flashes its position in the page.\n *\n * The target is often a `display: contents` wrapper, so we build the\n * overlay from `computeBounds` (descendants' client rects) instead of\n * using a CSS outline on the target directly.\n */\nexport function highlightElement(key: string, durationMs = 1200): void {\n if (typeof document === \"undefined\") return;\n const el = findElementByKey(key);\n if (!el) return;\n const rect = computeBounds(el);\n if (!rect) return;\n\n const overlay = document.createElement(\"div\");\n overlay.className = \"__jr_devtools_highlight\";\n overlay.style.cssText = `\n position: fixed;\n left: ${rect.left}px;\n top: ${rect.top}px;\n width: ${rect.width}px;\n height: ${rect.height}px;\n outline: 2px solid #60a5fa;\n outline-offset: 2px;\n pointer-events: none;\n z-index: 2147483645;\n transition: opacity 0.25s ease-out;\n opacity: 1;\n `;\n document.body.appendChild(overlay);\n setTimeout(\n () => {\n overlay.style.opacity = \"0\";\n },\n Math.max(0, durationMs - 250),\n );\n setTimeout(() => {\n overlay.remove();\n }, durationMs);\n}\n\n/** Minimal CSS.escape fallback for environments without it. */\nfunction cssEscape(value: string): string {\n if (typeof CSS !== \"undefined\" && typeof CSS.escape === \"function\") {\n return CSS.escape(value);\n }\n return value.replace(/[\"\\\\]/g, \"\\\\$&\");\n}\n","/**\n * CSS for the devtools panel. Injected into the shadow root so nothing\n * leaks into or out of the host app. Theme values are defined on `:host`\n * so tabs can read them via `var(--jr-*)`.\n *\n * Tokens mirror the json-render playground's visual language: small mono\n * type, muted borders, compact paddings.\n */\nexport const PANEL_CSS = `\n:host {\n /* Light theme — default. Overridden by the dark-mode media query below\n so the panel follows the host OS's \\`prefers-color-scheme\\`. */\n --jr-bg: #ffffff;\n --jr-bg-muted: #f4f4f5;\n --jr-bg-soft: #fafafa;\n --jr-fg: #18181b;\n --jr-fg-muted: #52525b;\n --jr-fg-dim: #71717a;\n --jr-border: #e4e4e7;\n --jr-border-strong: #a1a1aa;\n --jr-accent: #2563eb;\n --jr-green: #16a34a;\n --jr-red: #dc2626;\n --jr-amber: #d97706;\n --jr-font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n --jr-font-ui: system-ui, -apple-system, \"Segoe UI\", sans-serif;\n all: initial;\n color-scheme: light dark;\n font-family: var(--jr-font-ui);\n color: var(--jr-fg);\n position: fixed;\n z-index: 2147483647;\n}\n\n@media (prefers-color-scheme: dark) {\n :host {\n --jr-bg: #09090b;\n --jr-bg-muted: #111113;\n --jr-bg-soft: #17171a;\n --jr-fg: #fafafa;\n --jr-fg-muted: #a1a1aa;\n --jr-fg-dim: #71717a;\n --jr-border: #27272a;\n --jr-border-strong: #3f3f46;\n --jr-accent: #60a5fa;\n --jr-green: #4ade80;\n --jr-red: #f87171;\n --jr-amber: #fbbf24;\n }\n}\n\n* {\n box-sizing: border-box;\n}\n\nbutton {\n font: inherit;\n color: inherit;\n background: transparent;\n border: 0;\n cursor: pointer;\n padding: 0;\n}\n\n/* Floating toggle — frosted dark-glass badge inspired by Next.js Dev Tools.\n Always dark regardless of OS \\`prefers-color-scheme\\` so the affordance\n reads the same on both light and dark hosts. */\n.jr-toggle {\n position: fixed;\n bottom: 20px;\n right: 20px;\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: 0;\n padding: 0;\n background: rgba(0, 0, 0, 0.8);\n -webkit-backdrop-filter: blur(48px);\n backdrop-filter: blur(48px);\n color: #ffffff;\n /* Triple layer: outer hard ring, inner subtle highlight, drop shadow. */\n box-shadow:\n 0 0 0 1px #171717,\n inset 0 0 0 1px hsla(0, 0%, 100%, 0.14),\n 0 16px 32px -8px rgba(0, 0, 0, 0.24);\n display: flex;\n align-items: center;\n justify-content: center;\n will-change: scale, background;\n transition:\n scale 150ms cubic-bezier(0.23, 0.88, 0.26, 0.92),\n background 150ms ease;\n}\n.jr-toggle[data-position=\"bottom-left\"] { right: auto; left: 20px; }\n.jr-toggle[data-position=\"right\"] { bottom: auto; top: 20px; }\n.jr-toggle:hover {\n background: rgba(20, 20, 20, 0.88);\n}\n.jr-toggle:active {\n scale: 0.95;\n}\n.jr-toggle[data-open=\"true\"] {\n box-shadow:\n 0 0 0 1px var(--jr-accent),\n inset 0 0 0 1px hsla(0, 0%, 100%, 0.14),\n 0 16px 32px -8px rgba(0, 0, 0, 0.24);\n}\n\n.jr-panel {\n position: fixed;\n background: var(--jr-bg);\n color: var(--jr-fg);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n font-family: var(--jr-font-ui);\n font-size: 12px;\n}\n\n.jr-panel[data-dock=\"bottom\"] {\n left: 0;\n right: 0;\n bottom: 0;\n height: var(--jr-panel-height, 380px);\n min-height: 180px;\n max-height: 90vh;\n border-top: 1px solid var(--jr-border);\n}\n\n.jr-panel[data-dock=\"right\"] {\n top: 0;\n right: 0;\n bottom: 0;\n width: var(--jr-panel-width, 440px);\n min-width: 260px;\n max-width: 90vw;\n border-left: 1px solid var(--jr-border);\n}\n\n.jr-panel[data-hidden=\"true\"] {\n display: none;\n}\n\n.jr-resize {\n position: absolute;\n z-index: 1;\n}\n.jr-panel[data-dock=\"bottom\"] .jr-resize {\n top: -3px;\n left: 0;\n right: 0;\n height: 6px;\n cursor: ns-resize;\n}\n.jr-panel[data-dock=\"right\"] .jr-resize {\n left: -3px;\n top: 0;\n bottom: 0;\n width: 6px;\n cursor: ew-resize;\n}\n\n.jr-header {\n display: flex;\n align-items: stretch;\n height: 36px;\n border-bottom: 1px solid var(--jr-border);\n flex-shrink: 0;\n background: var(--jr-bg);\n}\n\n.jr-title {\n display: flex;\n align-items: center;\n padding: 0 12px;\n font-family: var(--jr-font-mono);\n font-size: 11px;\n font-weight: 600;\n color: var(--jr-fg);\n border-right: 1px solid var(--jr-border);\n letter-spacing: 0.02em;\n}\n.jr-tabs {\n display: flex;\n flex: 1;\n min-width: 0;\n overflow-x: auto;\n}\n.jr-tab {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 0 12px;\n font-family: var(--jr-font-mono);\n font-size: 11px;\n color: var(--jr-fg-muted);\n background: transparent;\n border-right: 1px solid var(--jr-border);\n white-space: nowrap;\n transition: color 0.1s ease, background 0.1s ease;\n}\n.jr-tab:hover {\n color: var(--jr-fg);\n background: var(--jr-bg-muted);\n}\n.jr-tab[data-active=\"true\"] {\n color: var(--jr-fg);\n background: var(--jr-bg-muted);\n box-shadow: inset 0 -2px 0 var(--jr-accent);\n}\n.jr-tab-count {\n font-size: 10px;\n color: var(--jr-fg-dim);\n background: var(--jr-bg-soft);\n border-radius: 999px;\n padding: 1px 6px;\n}\n\n.jr-actions {\n display: flex;\n align-items: center;\n padding: 0 8px;\n gap: 4px;\n border-left: 1px solid var(--jr-border);\n}\n.jr-icon-btn {\n width: 26px;\n height: 26px;\n border-radius: 6px;\n color: var(--jr-fg-muted);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-size: 14px;\n}\n.jr-icon-btn:hover {\n color: var(--jr-fg);\n background: var(--jr-bg-muted);\n}\n.jr-icon-btn[data-active=\"true\"] {\n color: var(--jr-accent);\n background: var(--jr-bg-muted);\n}\n\n.jr-body {\n flex: 1;\n min-height: 0;\n display: flex;\n overflow: hidden;\n}\n.jr-body > .jr-tab-panel {\n flex: 1;\n min-width: 0;\n min-height: 0;\n overflow: auto;\n padding: 0;\n display: flex;\n flex-direction: column;\n}\n\n.jr-empty {\n flex: 1;\n min-height: 80px;\n padding: 24px;\n color: var(--jr-fg-dim);\n font-size: 12px;\n text-align: center;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n/* --- Rows / list primitives used by tabs --- */\n\n.jr-row {\n display: grid;\n grid-template-columns: auto 1fr auto;\n gap: 8px;\n align-items: center;\n padding: 4px 12px;\n border-bottom: 1px solid var(--jr-border);\n font-family: var(--jr-font-mono);\n font-size: 11px;\n cursor: pointer;\n}\n.jr-row:hover {\n background: var(--jr-bg-muted);\n}\n.jr-row-time {\n color: var(--jr-fg-dim);\n font-size: 10px;\n white-space: nowrap;\n}\n.jr-row-main {\n color: var(--jr-fg);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.jr-row-meta {\n color: var(--jr-fg-muted);\n font-size: 10px;\n white-space: nowrap;\n}\n.jr-row-expanded {\n grid-column: 1 / -1;\n padding: 8px 12px 10px 12px;\n color: var(--jr-fg-muted);\n white-space: pre-wrap;\n word-break: break-all;\n background: var(--jr-bg-soft);\n border-top: 1px solid var(--jr-border);\n}\n\n.jr-badge {\n display: inline-flex;\n align-items: center;\n padding: 1px 6px;\n border-radius: 4px;\n font-family: var(--jr-font-mono);\n font-size: 10px;\n color: var(--jr-fg-muted);\n background: var(--jr-bg-soft);\n border: 1px solid var(--jr-border);\n}\n.jr-badge[data-tone=\"green\"] { color: var(--jr-green); border-color: rgba(74, 222, 128, 0.25); }\n.jr-badge[data-tone=\"red\"] { color: var(--jr-red); border-color: rgba(248, 113, 113, 0.25); }\n.jr-badge[data-tone=\"amber\"] { color: var(--jr-amber); border-color: rgba(251, 191, 36, 0.25); }\n.jr-badge[data-tone=\"accent\"] { color: var(--jr-accent); border-color: rgba(96, 165, 250, 0.25); }\n\n.jr-toolbar {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n border-bottom: 1px solid var(--jr-border);\n background: var(--jr-bg);\n font-family: var(--jr-font-mono);\n font-size: 10px;\n color: var(--jr-fg-muted);\n position: sticky;\n top: 0;\n z-index: 1;\n}\n.jr-toolbar .jr-icon-btn { width: auto; padding: 0 6px; font-size: 10px; }\n.jr-search {\n flex: 1;\n background: var(--jr-bg-soft);\n border: 1px solid var(--jr-border);\n border-radius: 4px;\n padding: 3px 6px;\n color: var(--jr-fg);\n font-family: var(--jr-font-mono);\n font-size: 10px;\n outline: none;\n}\n.jr-search:focus {\n border-color: var(--jr-accent);\n}\n\n/* --- Spec tree --- */\n\n.jr-tree-row {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 2px 12px;\n font-family: var(--jr-font-mono);\n font-size: 11px;\n cursor: pointer;\n white-space: nowrap;\n color: var(--jr-fg);\n}\n.jr-tree-row:hover {\n background: var(--jr-bg-muted);\n}\n.jr-tree-row[data-selected=\"true\"] {\n background: var(--jr-bg-muted);\n box-shadow: inset 2px 0 0 var(--jr-accent);\n}\n.jr-tree-toggle {\n width: 12px;\n color: var(--jr-fg-dim);\n display: inline-block;\n text-align: center;\n}\n.jr-tree-type {\n color: var(--jr-accent);\n font-weight: 500;\n}\n.jr-tree-key {\n color: var(--jr-fg-dim);\n font-size: 10px;\n}\n.jr-tree-summary {\n color: var(--jr-fg-muted);\n font-size: 10px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.jr-tree-hidden {\n opacity: 0.45;\n}\n\n.jr-split {\n display: flex;\n flex: 1;\n min-height: 0;\n width: 100%;\n}\n.jr-split-left {\n flex: 1;\n min-width: 0;\n min-height: 0;\n /* Pane itself no longer scrolls; the inner .jr-tree-rows container does,\n so the breadcrumb bar above stays pinned. */\n overflow: hidden;\n border-right: 1px solid var(--jr-border);\n display: flex;\n flex-direction: column;\n /* Selected row already has its own accent indicator, so no focus ring\n on the container itself. */\n outline: none;\n}\n.jr-tree-rows {\n flex: 1;\n min-height: 0;\n overflow: auto;\n /* Flex-column so .jr-empty inside can stretch + center vertically. */\n display: flex;\n flex-direction: column;\n}\n\n/* Generation switcher — only rendered when >1 specs (e.g. AI chat with\n multiple assistant replies). Sits above the breadcrumbs. */\n.jr-generations {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 8px;\n min-height: 28px;\n border-bottom: 1px solid var(--jr-border);\n background: var(--jr-bg);\n font-family: var(--jr-font-mono);\n font-size: 11px;\n}\n.jr-generations:empty {\n display: none;\n}\n.jr-generation-select {\n background: var(--jr-bg-soft);\n color: var(--jr-fg);\n border: 1px solid var(--jr-border);\n border-radius: 4px;\n padding: 2px 6px;\n font-family: inherit;\n font-size: 11px;\n outline: none;\n cursor: pointer;\n}\n.jr-generation-select:focus-visible {\n border-color: var(--jr-accent);\n}\n.jr-generations-count {\n color: var(--jr-fg-dim);\n font-size: 10px;\n}\n.jr-breadcrumbs {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 4px 8px;\n min-height: 28px;\n border-bottom: 1px solid var(--jr-border);\n background: var(--jr-bg);\n white-space: nowrap;\n font-family: var(--jr-font-mono);\n font-size: 11px;\n}\n.jr-breadcrumbs-trail {\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: center;\n gap: 2px;\n overflow-x: auto;\n scrollbar-width: thin;\n}\n.jr-breadcrumbs-tools {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n gap: 2px;\n padding-left: 4px;\n border-left: 1px solid var(--jr-border);\n margin-left: 4px;\n}\n.jr-view-btn {\n width: 24px;\n height: 22px;\n border-radius: 4px;\n border: 0;\n background: transparent;\n color: var(--jr-fg-muted);\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n.jr-view-btn:hover {\n color: var(--jr-fg);\n background: var(--jr-bg-muted);\n}\n.jr-view-btn[data-active=\"true\"] {\n color: var(--jr-accent);\n background: var(--jr-bg-muted);\n}\n.jr-breadcrumb {\n padding: 2px 6px;\n border-radius: 4px;\n color: var(--jr-fg-muted);\n cursor: pointer;\n background: transparent;\n border: 0;\n font: inherit;\n white-space: nowrap;\n}\n.jr-breadcrumb:hover {\n color: var(--jr-fg);\n background: var(--jr-bg-muted);\n}\n.jr-breadcrumb[data-current=\"true\"] {\n color: var(--jr-accent);\n background: var(--jr-bg-muted);\n}\n.jr-breadcrumb-sep {\n color: var(--jr-fg-dim);\n font-size: 10px;\n padding: 0 1px;\n user-select: none;\n}\n.jr-breadcrumbs-empty {\n color: var(--jr-fg-dim);\n padding: 2px 6px;\n font-style: italic;\n}\n\n/* Raw JSON view — spec pretty-printed, selectable for copy/paste. */\n.jr-raw {\n margin: 0;\n padding: 10px 12px;\n flex: 1;\n min-height: 0;\n font-family: var(--jr-font-mono);\n font-size: 11px;\n line-height: 1.5;\n color: var(--jr-fg);\n white-space: pre;\n overflow: auto;\n -moz-tab-size: 2;\n tab-size: 2;\n}\n.jr-split-right {\n width: 40%;\n min-width: 240px;\n max-width: 60%;\n min-height: 0;\n overflow: auto;\n background: var(--jr-bg);\n display: flex;\n flex-direction: column;\n}\n\n.jr-detail {\n padding: 10px 12px;\n font-family: var(--jr-font-mono);\n font-size: 11px;\n color: var(--jr-fg);\n}\n.jr-detail h4 {\n margin: 0 0 6px 0;\n font-family: var(--jr-font-mono);\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--jr-fg-dim);\n}\n.jr-detail pre {\n margin: 0 0 14px 0;\n padding: 8px;\n background: var(--jr-bg-soft);\n border: 1px solid var(--jr-border);\n border-radius: 4px;\n white-space: pre-wrap;\n word-break: break-all;\n color: var(--jr-fg);\n}\n\n/* --- State editor --- */\n.jr-state-row {\n display: grid;\n grid-template-columns: 1fr 2fr;\n gap: 8px;\n padding: 3px 12px;\n border-bottom: 1px solid var(--jr-border);\n font-family: var(--jr-font-mono);\n font-size: 11px;\n align-items: center;\n}\n.jr-state-path {\n color: var(--jr-fg-muted);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.jr-state-value {\n background: transparent;\n color: var(--jr-fg);\n border: 1px solid transparent;\n border-radius: 3px;\n padding: 2px 4px;\n font-family: var(--jr-font-mono);\n font-size: 11px;\n outline: none;\n width: 100%;\n min-width: 0;\n}\n.jr-state-value:hover {\n border-color: var(--jr-border);\n}\n.jr-state-value:focus {\n border-color: var(--jr-accent);\n background: var(--jr-bg-soft);\n}\n.jr-state-value[data-dirty=\"true\"] {\n border-color: var(--jr-amber);\n}\n\n/* --- Catalog chips --- */\n.jr-chips {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n margin-top: 4px;\n}\n.jr-chip {\n padding: 1px 5px;\n border-radius: 3px;\n font-family: var(--jr-font-mono);\n font-size: 10px;\n background: var(--jr-bg-soft);\n color: var(--jr-fg-muted);\n border: 1px solid var(--jr-border);\n}\n.jr-chip[data-tone=\"prop\"] { color: var(--jr-green); border-color: rgba(74, 222, 128, 0.25); }\n.jr-chip[data-tone=\"event\"] { color: var(--jr-accent); border-color: rgba(96, 165, 250, 0.25); }\n.jr-chip[data-tone=\"param\"] { color: var(--jr-amber); border-color: rgba(251, 191, 36, 0.25); }\n\n.jr-catalog-item {\n padding: 8px 12px;\n border-bottom: 1px solid var(--jr-border);\n}\n.jr-catalog-name {\n font-family: var(--jr-font-mono);\n font-size: 11px;\n color: var(--jr-fg);\n font-weight: 600;\n}\n.jr-catalog-desc {\n font-size: 11px;\n color: var(--jr-fg-muted);\n margin-top: 2px;\n}\n`;\n\n/**\n * CSS injected into the *host* document (not the shadow root). It supports:\n *\n * 1. The picker overlay — paints an outline + label on whichever element the\n * user is hovering while the picker is active.\n * 2. Reserved-space layout — when \\`reserveSpace\\` is enabled the panel writes\n * its size to \\`--jr-devtools-offset-bottom\\` / \\`--jr-devtools-offset-right\\`\n * on \\`:root\\` and we apply matching \\`padding-bottom\\` / \\`padding-right\\` to\n * \\`body\\`, so non-fixed content scrolls into view rather than being hidden.\n * \\`--jr-devtools-offset\\` is kept as an alias for whichever edge is\n * currently active (back-compat).\n *\n * Apps with \\`position: fixed\\` / \\`position: sticky\\` / \\`100vh\\` layouts can\n * opt in per element:\n *\n * \\`\\`\\`css\n * .composer { bottom: var(--jr-devtools-offset-bottom, 0); }\n * .sidebar { right: var(--jr-devtools-offset-right, 0); }\n * .app { height: calc(100vh - var(--jr-devtools-offset-bottom, 0)); }\n * \\`\\`\\`\n */\nexport const HOST_CSS = `\n:root {\n --jr-devtools-offset-bottom: 0px;\n --jr-devtools-offset-right: 0px;\n}\n\nhtml[data-jr-devtools-reserve=\"true\"] body {\n box-sizing: border-box;\n padding-bottom: var(--jr-devtools-offset-bottom, 0);\n padding-right: var(--jr-devtools-offset-right, 0);\n transition: padding-bottom 0.12s ease-out, padding-right 0.12s ease-out;\n}\n\nhtml[data-jr-devtools-picking=\"true\"],\nhtml[data-jr-devtools-picking=\"true\"] * {\n cursor: crosshair !important;\n}\n\n/* Floating overlays + labels used by two features:\n 1. Picker — while the toolbar button is active and the user hovers the page\n 2. Tree hover — while the user hovers a row in the Spec tab tree\n Both use the same visual language. Not rendered with a CSS \\`outline\\` on the\n target because the json-render element wrappers use \\`display: contents\\`\n (no box, no outline). */\n#__jr_devtools_picker_overlay,\n#__jr_devtools_hover_overlay {\n position: fixed;\n z-index: 2147483646;\n pointer-events: none;\n background: rgba(96, 165, 250, 0.15);\n outline: 2px solid #60a5fa;\n outline-offset: 0;\n border-radius: 2px;\n box-shadow: 0 0 0 1px rgba(9, 9, 11, 0.4);\n display: none;\n}\n#__jr_devtools_picker_label,\n#__jr_devtools_hover_label {\n position: fixed;\n z-index: 2147483646;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 11px;\n padding: 3px 7px;\n border-radius: 4px;\n background: #60a5fa;\n color: #09090b;\n pointer-events: none;\n white-space: nowrap;\n display: none;\n}\n/* Secondary overlays painted for the *other* instances of a repeated spec\n element — amber + dashed so they read as \"siblings of the hovered one\". */\n.__jr_devtools_hover_extra {\n position: fixed;\n z-index: 2147483646;\n pointer-events: none;\n background: rgba(251, 191, 36, 0.08);\n outline: 2px dashed #fbbf24;\n outline-offset: 0;\n border-radius: 2px;\n box-shadow: 0 0 0 1px rgba(9, 9, 11, 0.4);\n display: none;\n}\n`;\n","import { h, replaceChildren } from \"./dom\";\nimport { setHoverHighlight } from \"../picker\";\nimport { HOST_CSS, PANEL_CSS } from \"./styles\";\nimport type {\n PanelContext,\n PanelDock,\n PanelHandle,\n PanelOptions,\n PanelPosition,\n TabDef,\n TabInstance,\n} from \"./types\";\n\nconst HOST_ATTR = \"data-jr-devtools-host\";\nconst HOST_STYLE_ID = \"__jr_devtools_host_styles\";\nconst RESERVE_ATTR = \"data-jr-devtools-reserve\";\nconst OFFSET_VAR_BOTTOM = \"--jr-devtools-offset-bottom\";\nconst OFFSET_VAR_RIGHT = \"--jr-devtools-offset-right\";\n/** Back-compat alias: points at whichever edge is currently active. */\nconst OFFSET_VAR_ALIAS = \"--jr-devtools-offset\";\n\nfunction ensureHostStyles() {\n if (document.getElementById(HOST_STYLE_ID)) return;\n const style = document.createElement(\"style\");\n style.id = HOST_STYLE_ID;\n style.textContent = HOST_CSS;\n document.head.appendChild(style);\n}\n\n/**\n * Publish the panel's current size on `:root` as two CSS custom properties:\n * `--jr-devtools-offset-bottom` and `--jr-devtools-offset-right`. Only the\n * one matching the active dock is non-zero at a time. `--jr-devtools-offset`\n * is maintained as an alias for whichever edge is currently active, so older\n * app CSS keeps working.\n */\nfunction setOffset(dock: PanelDock, px: number) {\n const root = document.documentElement;\n const bottom = dock === \"bottom\" ? px : 0;\n const right = dock === \"right\" ? px : 0;\n if (bottom > 0) root.style.setProperty(OFFSET_VAR_BOTTOM, `${bottom}px`);\n else root.style.removeProperty(OFFSET_VAR_BOTTOM);\n if (right > 0) root.style.setProperty(OFFSET_VAR_RIGHT, `${right}px`);\n else root.style.removeProperty(OFFSET_VAR_RIGHT);\n if (px > 0) root.style.setProperty(OFFSET_VAR_ALIAS, `${px}px`);\n else root.style.removeProperty(OFFSET_VAR_ALIAS);\n}\n\n/** Map toggle-button position to the panel dock edge. */\nfunction dockFromPosition(position: PanelPosition): PanelDock {\n return position === \"right\" ? \"right\" : \"bottom\";\n}\n\nconst STORAGE_DOCK = \"__jr_devtools_dock\";\nconst STORAGE_HEIGHT = \"__jr_devtools_height\";\nconst STORAGE_WIDTH = \"__jr_devtools_width\";\n\nfunction readStoredDock(): PanelDock | null {\n if (typeof window === \"undefined\") return null;\n try {\n const raw = window.localStorage?.getItem(STORAGE_DOCK);\n return raw === \"bottom\" || raw === \"right\" ? raw : null;\n } catch {\n return null;\n }\n}\n\nfunction writeStoredDock(dock: PanelDock): void {\n if (typeof window === \"undefined\") return;\n try {\n window.localStorage?.setItem(STORAGE_DOCK, dock);\n } catch {\n // ignore storage errors (private mode, etc.)\n }\n}\n\n/** Per-dock layout constants (storage key, default/min size, CSS var). */\nfunction dockSpec(dock: PanelDock) {\n return dock === \"right\"\n ? {\n key: STORAGE_WIDTH,\n defaultSize: 440,\n minSize: 260,\n cssVar: \"--jr-panel-width\" as const,\n }\n : {\n key: STORAGE_HEIGHT,\n defaultSize: 380,\n minSize: 180,\n cssVar: \"--jr-panel-height\" as const,\n };\n}\n\n/** Inline SVG used for the Pick toolbar button (lucide square-mouse-pointer). */\nconst PICK_ICON_SVG = `\n<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M12.034 12.681a.498.498 0 0 1 .647-.647l9 3.5a.5.5 0 0 1-.033.944l-3.444 1.068a1 1 0 0 0-.66.66l-1.067 3.443a.5.5 0 0 1-.944.033z\"/>\n <path d=\"M21 11V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h6\"/>\n</svg>`;\n\n/**\n * Pixel-style `{}` mark for the floating toggle. Drawn as a 14×14 grid of\n * 2px rects so it's perfectly symmetric on both axes — eliminates the\n * font-glyph-off-centre issue we'd get by rendering live text.\n */\nconst TOGGLE_BRACES_SVG = `\n<svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"currentColor\" aria-hidden=\"true\">\n <rect x=\"2\" y=\"0\" width=\"4\" height=\"2\"/>\n <rect x=\"2\" y=\"2\" width=\"2\" height=\"4\"/>\n <rect x=\"0\" y=\"6\" width=\"2\" height=\"2\"/>\n <rect x=\"2\" y=\"8\" width=\"2\" height=\"4\"/>\n <rect x=\"2\" y=\"12\" width=\"4\" height=\"2\"/>\n <rect x=\"8\" y=\"0\" width=\"4\" height=\"2\"/>\n <rect x=\"10\" y=\"2\" width=\"2\" height=\"4\"/>\n <rect x=\"12\" y=\"6\" width=\"2\" height=\"2\"/>\n <rect x=\"10\" y=\"8\" width=\"2\" height=\"4\"/>\n <rect x=\"8\" y=\"12\" width=\"4\" height=\"2\"/>\n</svg>`;\n\n/** Inline SVGs for the dock-toggle button (lucide panel-bottom / panel-right). */\nconst PANEL_BOTTOM_SVG = `\n<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\"/>\n <path d=\"M3 15h18\"/>\n</svg>`;\nconst PANEL_RIGHT_SVG = `\n<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\"/>\n <path d=\"M15 3v18\"/>\n</svg>`;\n\nfunction matchHotkey(event: KeyboardEvent, hotkey: string): boolean {\n const parts = hotkey\n .toLowerCase()\n .split(\"+\")\n .map((p) => p.trim());\n const isMac =\n typeof navigator !== \"undefined\" &&\n /mac|iphone|ipad/i.test(navigator.platform || navigator.userAgent);\n let needsMod = false;\n let needsShift = false;\n let needsAlt = false;\n let key = \"\";\n for (const p of parts) {\n if (p === \"mod\") needsMod = true;\n else if (p === \"ctrl\") needsMod = true;\n else if (p === \"meta\" || p === \"cmd\") needsMod = true;\n else if (p === \"shift\") needsShift = true;\n else if (p === \"alt\" || p === \"option\") needsAlt = true;\n else key = p;\n }\n const modOk = needsMod ? (isMac ? event.metaKey : event.ctrlKey) : true;\n const shiftOk = needsShift ? event.shiftKey : true;\n const altOk = needsAlt ? event.altKey : true;\n const keyOk = key ? event.key.toLowerCase() === key : true;\n return modOk && shiftOk && altOk && keyOk;\n}\n\n/**\n * Create a devtools panel and mount it to the host document.\n *\n * Idempotent per-host: if a panel is already mounted under the given host,\n * this returns that panel's handle instead of creating a duplicate.\n */\nexport function createPanel(options: PanelOptions): PanelHandle {\n const host =\n options.host ?? (typeof document !== \"undefined\" ? document.body : null);\n if (!host) {\n return {\n open() {},\n close() {},\n toggle() {},\n isOpen: () => false,\n refresh() {},\n destroy() {},\n };\n }\n\n // If a panel root already exists, reuse its handle.\n const existing = host.querySelector(`[${HOST_ATTR}]`);\n if (\n existing &&\n (existing as HTMLElement & { __jrHandle?: PanelHandle }).__jrHandle\n ) {\n return (existing as HTMLElement & { __jrHandle: PanelHandle }).__jrHandle;\n }\n\n ensureHostStyles();\n\n const rootHost = document.createElement(\"div\");\n rootHost.setAttribute(HOST_ATTR, \"\");\n host.appendChild(rootHost);\n\n const shadow = rootHost.attachShadow({ mode: \"open\" });\n const styleEl = document.createElement(\"style\");\n styleEl.textContent = PANEL_CSS;\n shadow.appendChild(styleEl);\n\n const position: PanelPosition = options.position ?? \"bottom-right\";\n const allowDockToggle = options.allowDockToggle ?? true;\n // Initial dock: stored user preference wins (when the user is allowed to\n // toggle), otherwise fall back to whatever `position` implies.\n const initialDock: PanelDock =\n (allowDockToggle ? readStoredDock() : null) ?? dockFromPosition(position);\n let dock: PanelDock = initialDock;\n const reserveSpace = options.reserveSpace ?? true;\n // Opt the host document in to reserved-space padding (HOST_CSS is scoped\n // by this attribute so apps that pass `reserveSpace: false` are untouched).\n if (reserveSpace) {\n document.documentElement.setAttribute(RESERVE_ATTR, \"true\");\n }\n let open = options.initialOpen ?? false;\n let activeTabId = options.tabs[0]?.id ?? \"\";\n\n const ctx: PanelContext = options.context;\n const tabs = options.tabs;\n const tabInstances = new Map<string, TabInstance>();\n\n // --- Toggle button ---\n const toggleBtn = h(\"button\", {\n className: \"jr-toggle\",\n \"data-position\": position,\n \"data-open\": String(open),\n title: \"json-render devtools\",\n \"aria-label\": \"Toggle json-render devtools\",\n onClick: () => toggle(),\n });\n toggleBtn.innerHTML = TOGGLE_BRACES_SVG;\n shadow.appendChild(toggleBtn);\n\n // --- Panel container ---\n const tabsStrip = h(\"div\", { className: \"jr-tabs\" });\n const body = h(\"div\", { className: \"jr-body\" });\n\n // Pick button lives in the header toolbar (Chrome DevTools style) so it is\n // reachable from any tab without stealing a tab slot.\n const pickBtn = h(\"button\", {\n className: \"jr-icon-btn jr-pick-btn\",\n title: \"Select an element in the page (Esc to cancel)\",\n \"aria-label\": \"Select an element in the page\",\n onClick: () => togglePicker(),\n });\n pickBtn.innerHTML = PICK_ICON_SVG;\n\n // Dock-toggle button (only visible when `allowDockToggle` is enabled).\n // Shows the *target* dock icon — click it to move the panel there.\n const dockBtn = h(\"button\", {\n className: \"jr-icon-btn jr-dock-btn\",\n \"aria-label\": \"Toggle devtools dock\",\n onClick: () => toggleDock(),\n });\n function updateDockButton() {\n if (dock === \"bottom\") {\n dockBtn.innerHTML = PANEL_RIGHT_SVG;\n dockBtn.title = \"Dock to right\";\n } else {\n dockBtn.innerHTML = PANEL_BOTTOM_SVG;\n dockBtn.title = \"Dock to bottom\";\n }\n }\n updateDockButton();\n\n const closeBtn = h(\n \"button\",\n {\n className: \"jr-icon-btn\",\n title: \"Close devtools\",\n \"aria-label\": \"Close\",\n onClick: () => close(),\n },\n \"\\u00d7\",\n );\n\n const header = h(\n \"header\",\n { className: \"jr-header\" },\n h(\"div\", { className: \"jr-title\" }, \"json-render devtools\"),\n tabsStrip,\n h(\n \"div\",\n { className: \"jr-actions\" },\n pickBtn,\n allowDockToggle ? dockBtn : null,\n closeBtn,\n ),\n );\n\n const resizeHandle = h(\"div\", {\n className: \"jr-resize\",\n \"aria-label\": \"Resize devtools\",\n });\n\n const panel = h(\n \"section\",\n {\n className: \"jr-panel\",\n \"data-hidden\": String(!open),\n \"data-dock\": dock,\n role: \"complementary\",\n },\n resizeHandle,\n header,\n body,\n );\n shadow.appendChild(panel);\n\n // --- Resize handling ---\n // Bottom-docked panels resize vertically; right-docked panels resize\n // horizontally. Each dock has its own localStorage key so switching\n // docks doesn't inherit the wrong dimension.\n let panelSize = loadSizeFor(dock);\n applyPanelSize(dock, panelSize);\n\n function loadSizeFor(d: PanelDock): number {\n const spec = dockSpec(d);\n const stored =\n typeof window !== \"undefined\"\n ? window.localStorage?.getItem(spec.key)\n : null;\n let size = stored ? parseInt(stored, 10) : spec.defaultSize;\n if (!Number.isFinite(size) || size < spec.minSize) {\n size = spec.defaultSize;\n }\n return size;\n }\n\n function applyPanelSize(d: PanelDock, size: number): void {\n const spec = dockSpec(d);\n // Clear the opposite axis's CSS var so old values don't linger.\n const other = d === \"bottom\" ? \"--jr-panel-width\" : \"--jr-panel-height\";\n panel.style.removeProperty(other);\n panel.style.setProperty(spec.cssVar, `${size}px`);\n }\n\n resizeHandle.addEventListener(\"mousedown\", (ev) => {\n ev.preventDefault();\n const d = dock;\n const startCoord = d === \"right\" ? ev.clientX : ev.clientY;\n const startSize = panelSize;\n const spec = dockSpec(d);\n const onMove = (e: MouseEvent) => {\n // Both axes: dragging *away* from the dock edge (up for bottom, left\n // for right) grows the panel.\n const current = d === \"right\" ? e.clientX : e.clientY;\n const delta = startCoord - current;\n const viewport = d === \"right\" ? window.innerWidth : window.innerHeight;\n panelSize = Math.max(\n spec.minSize,\n Math.min(viewport * 0.9, startSize + delta),\n );\n applyPanelSize(d, panelSize);\n if (open && reserveSpace) setOffset(d, panelSize);\n };\n const onUp = () => {\n document.removeEventListener(\"mousemove\", onMove);\n document.removeEventListener(\"mouseup\", onUp);\n try {\n window.localStorage?.setItem(spec.key, String(panelSize));\n } catch {\n // ignore storage errors (private mode, etc.)\n }\n };\n document.addEventListener(\"mousemove\", onMove);\n document.addEventListener(\"mouseup\", onUp);\n });\n\n // --- Dock toggle ---\n function setDock(next: PanelDock, persist: boolean) {\n if (next === dock) return;\n // Clear the old axis's offset before switching so the host body\n // padding doesn't flash the wrong value during the transition.\n setOffset(dock, 0);\n dock = next;\n panel.dataset.dock = next;\n panelSize = loadSizeFor(next);\n applyPanelSize(next, panelSize);\n if (open && reserveSpace) setOffset(next, panelSize);\n if (persist) writeStoredDock(next);\n updateDockButton();\n }\n\n function toggleDock() {\n if (!allowDockToggle) return;\n setDock(dock === \"bottom\" ? \"right\" : \"bottom\", true);\n }\n\n // --- Picker (toolbar button) ---\n let pickerStop: (() => void) | null = null;\n\n function updatePickButton() {\n const active = !!pickerStop;\n pickBtn.dataset.active = String(active);\n pickBtn.title = active\n ? \"Stop picking (Esc)\"\n : \"Select an element in the page\";\n pickBtn.disabled = typeof document === \"undefined\" || !ctx.startPicker;\n }\n\n function stopPicker() {\n if (pickerStop) pickerStop();\n pickerStop = null;\n updatePickButton();\n }\n\n function startPickerSession() {\n if (pickerStop || !ctx.startPicker) return;\n const session = ctx.startPicker({\n onPick: (key) => {\n pickerStop = null;\n updatePickButton();\n ctx.selection.set(key);\n // Jump to the Spec tab if one is registered so the user sees the\n // matching element right after picking.\n if (tabs.some((t) => t.id === \"spec\")) {\n ctx.activateTab(\"spec\");\n } else {\n openPanel();\n }\n },\n onCancel: () => {\n pickerStop = null;\n updatePickButton();\n },\n });\n if (!session) return;\n pickerStop = session.stop;\n updatePickButton();\n }\n\n function togglePicker() {\n if (pickerStop) stopPicker();\n else startPickerSession();\n }\n\n updatePickButton();\n\n // --- Tab strip ---\n const tabButtons = new Map<string, HTMLButtonElement>();\n\n function renderTabs() {\n replaceChildren(\n tabsStrip,\n tabs.map((tab) => {\n const badgeValue = tab.badge?.(ctx);\n const btn = h(\n \"button\",\n {\n className: \"jr-tab\",\n \"data-active\": String(tab.id === activeTabId),\n \"data-tab\": tab.id,\n onClick: () => setActiveTab(tab.id),\n },\n tab.label,\n badgeValue !== undefined && badgeValue !== \"\" && badgeValue !== 0\n ? h(\"span\", { className: \"jr-tab-count\" }, String(badgeValue))\n : null,\n );\n tabButtons.set(tab.id, btn);\n return btn;\n }),\n );\n }\n\n function activateTab(id: string) {\n const tab = tabs.find((t) => t.id === id);\n if (!tab) return;\n body.textContent = \"\";\n const panelEl = h(\"div\", { className: \"jr-tab-panel\", \"data-tab\": id });\n body.appendChild(panelEl);\n // Destroy previous tab instances (single active tab at a time)\n for (const [prevId, inst] of tabInstances) {\n if (prevId !== id) {\n try {\n inst.destroy?.();\n } catch (err) {\n if (process.env.NODE_ENV !== \"production\") {\n console.error(\"[json-render devtools] tab destroy threw:\", err);\n }\n }\n tabInstances.delete(prevId);\n }\n }\n const instance = tab.mount(panelEl, ctx);\n tabInstances.set(id, instance);\n }\n\n function setActiveTab(id: string) {\n if (activeTabId === id) return;\n activeTabId = id;\n renderTabs();\n activateTab(id);\n }\n\n // Let tabs (and the picker) jump to other tabs programmatically.\n ctx.activateTab = (id: string) => {\n setActiveTab(id);\n openPanel();\n };\n\n renderTabs();\n if (activeTabId) activateTab(activeTabId);\n\n // --- Global refresh on every event ---\n let scheduled = false;\n const runRefresh = () => {\n scheduled = false;\n renderTabs();\n const inst = tabInstances.get(activeTabId);\n inst?.update();\n };\n const scheduleRefresh = () => {\n if (scheduled) return;\n scheduled = true;\n if (\n typeof window !== \"undefined\" &&\n typeof window.requestAnimationFrame === \"function\"\n ) {\n window.requestAnimationFrame(runRefresh);\n } else {\n setTimeout(runRefresh, 16);\n }\n };\n const unsubEvents = ctx.events.subscribe(scheduleRefresh);\n\n // --- Hotkey ---\n const hotkey = options.hotkey === undefined ? \"mod+shift+j\" : options.hotkey;\n const onKey = hotkey\n ? (e: KeyboardEvent) => {\n if (matchHotkey(e, hotkey)) {\n e.preventDefault();\n toggle();\n }\n }\n : null;\n if (onKey) document.addEventListener(\"keydown\", onKey);\n\n // --- Lifecycle ---\n function setOpen(next: boolean) {\n open = next;\n toggleBtn.dataset.open = String(open);\n panel.dataset.hidden = String(!open);\n // Even when `reserveSpace` is false we still publish the CSS var so apps\n // that opt in (e.g. `bottom: var(--jr-devtools-offset-bottom, 0)`) get\n // the right value. HOST_CSS only applies body padding when the host\n // document has `data-jr-devtools-reserve=\"true\"`.\n setOffset(dock, open ? panelSize : 0);\n if (open) {\n const inst = tabInstances.get(activeTabId);\n inst?.update();\n } else {\n // Closing cancels any in-flight picker so the hover outline doesn't\n // linger in the page. Clear the spec-tree hover highlight too — if\n // the user closed via hotkey they never moved the mouse off the row.\n stopPicker();\n setHoverHighlight(null);\n }\n }\n function openPanel() {\n setOpen(true);\n }\n function close() {\n setOpen(false);\n }\n function toggle() {\n setOpen(!open);\n }\n\n // Seed offset on mount so the toggle button doesn't sit over the app when\n // the panel is already open at boot.\n setOffset(dock, open ? panelSize : 0);\n\n const handle: PanelHandle = {\n open: openPanel,\n close,\n toggle,\n isOpen: () => open,\n refresh: scheduleRefresh,\n destroy() {\n unsubEvents();\n if (onKey) document.removeEventListener(\"keydown\", onKey);\n stopPicker();\n setHoverHighlight(null);\n setOffset(dock, 0);\n for (const inst of tabInstances.values()) {\n try {\n inst.destroy?.();\n } catch {\n // ignore\n }\n }\n tabInstances.clear();\n rootHost.remove();\n // Only clear the reserve-space attribute once every panel is gone — in\n // rare HMR / multi-mount scenarios another panel may still be live.\n if (!document.querySelector(`[${HOST_ATTR}]`)) {\n document.documentElement.removeAttribute(RESERVE_ATTR);\n }\n },\n };\n\n (rootHost as HTMLElement & { __jrHandle?: PanelHandle }).__jrHandle = handle;\n return handle;\n}\n\n/**\n * Mount a panel with a minimal placeholder for each tab. Useful for tests\n * or environments where individual tab implementations aren't available.\n *\n * In production, consumers use {@link createPanel} with the full tab set.\n */\nexport function createStubTab(id: string, label: string): TabDef {\n return {\n id,\n label,\n mount(root) {\n const empty = h(\"div\", { className: \"jr-empty\" }, `${label} (stub)`);\n root.appendChild(empty);\n return { update() {} };\n },\n };\n}\n","import type { Catalog, Spec, StateStore } from \"@json-render/core\";\nimport type { EventStore } from \"../event-store\";\nimport type { PickerOptions, PickerSession } from \"../types\";\n\n/**\n * Where the devtools panel docks and where the floating toggle lives.\n *\n * - `bottom-right` (default) — panel docks to the bottom; toggle sits in the\n * bottom-right corner.\n * - `bottom-left` — panel docks to the bottom; toggle sits in the bottom-left\n * corner. Useful when the host app already has something bottom-right.\n * - `right` — panel docks to the right edge (full height); toggle sits in the\n * top-right corner. Best for app-shell layouts that already use `100vh` /\n * `position: fixed` at the bottom — right docking avoids the bottom edge\n * entirely.\n */\nexport type PanelPosition = \"bottom-right\" | \"bottom-left\" | \"right\";\n\n/** @internal Normalized dock edge derived from {@link PanelPosition}. */\nexport type PanelDock = \"bottom\" | \"right\";\n\n/**\n * A single spec available for inspection. When the host app renders one\n * spec at a time (the common single-renderer case) this list has a single\n * entry. Multi-renderer hosts (e.g. an AI chat where each assistant reply\n * produces its own spec) surface every generation so the Spec tab can\n * switch between them.\n */\nexport interface SpecEntry {\n /** Stable id, typically the message id that produced the spec. */\n id: string;\n /** Human-readable label shown in the generation switcher (e.g. \"Generation 2\"). */\n label: string;\n /** The spec itself. */\n spec: Spec;\n}\n\n/**\n * Context shared with every tab. Tabs read live values via getters so they\n * always see the latest spec/state/catalog without needing to re-mount.\n */\nexport interface PanelContext {\n /** Event log shared by all panels. */\n events: EventStore;\n /** Returns the current (usually latest) spec or `null`. */\n getSpec: () => Spec | null;\n /**\n * Optional: returns every inspectable spec on the page.\n * Hosts with multiple concurrent renderers (e.g. a chat with one spec\n * per assistant message) provide this so the Spec tab can offer a\n * generation switcher. When absent, the tab falls back to `getSpec()`\n * alone.\n */\n getSpecs?: () => SpecEntry[];\n /** Returns the current catalog or `null`. */\n getCatalog: () => Catalog | null;\n /** Returns the live `StateStore` or `null` (only set when a provider is mounted). */\n getStateStore: () => StateStore | null;\n /** Start a picker session. Returns `null` if no DOM is available. */\n startPicker?: (options: PickerOptions) => PickerSession | null;\n /** Selection channel shared across tabs (picker <-> Spec tab). */\n selection: SelectionBus;\n /** Activate a specific tab by id. */\n activateTab: (id: string) => void;\n}\n\n/**\n * Bus for syncing the currently focused spec element key across tabs and the\n * picker overlay. Tabs read the current value and subscribe to changes;\n * anything that wants to focus an element (picker, tree click) calls `set`.\n */\nexport interface SelectionBus {\n get: () => string | null;\n set: (key: string | null) => void;\n subscribe: (listener: (key: string | null) => void) => () => void;\n}\n\n/** Create an in-memory {@link SelectionBus}. */\nexport function createSelectionBus(): SelectionBus {\n let value: string | null = null;\n const listeners = new Set<(key: string | null) => void>();\n return {\n get: () => value,\n set(next) {\n if (value === next) return;\n value = next;\n for (const l of listeners) l(next);\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n };\n}\n\n/**\n * A tab registered with the panel. Tabs are rendered lazily — `mount` is\n * called the first time the tab is activated, and `update` is called on\n * every re-render request after that.\n */\nexport interface TabDef {\n /** Stable tab id used in URL hash / storage. */\n id: string;\n /** Short label shown in the tab strip. */\n label: string;\n /** Optional count badge, recomputed on every render. */\n badge?: (ctx: PanelContext) => number | string | undefined;\n /** Create the DOM for this tab. Called once per activation. */\n mount: (root: HTMLElement, ctx: PanelContext) => TabInstance;\n}\n\n/**\n * A live tab. `update` is called whenever an event fires or the host\n * refreshes; `destroy` is called when the tab is unmounted.\n */\nexport interface TabInstance {\n /** Re-render with latest data. */\n update: () => void;\n /** Clean up subscriptions / listeners. */\n destroy?: () => void;\n}\n\n/**\n * Options for {@link createPanel}.\n */\nexport interface PanelOptions {\n /** Shared panel context. */\n context: PanelContext;\n /** Tabs to register. Order is preserved in the tab strip. */\n tabs: TabDef[];\n /** Host-document node to mount under. Default: `document.body`. */\n host?: HTMLElement;\n /** Position of the floating toggle button. */\n position?: PanelPosition;\n /** Start open. Default: `false`. */\n initialOpen?: boolean;\n /**\n * Keyboard shortcut to toggle the panel, or `false` to disable.\n * Syntax: `\"mod+shift+j\"` (`mod` = meta on mac, ctrl elsewhere).\n * Default: `\"mod+shift+j\"`.\n */\n hotkey?: string | false;\n /**\n * Whether the panel should push the host app's content out of the way\n * while open, by applying `padding` on `<body>` matching the panel's size.\n *\n * - `true` (default) — body padding is applied. Works for document-flow\n * layouts and `height: 100%` app shells. Modern apps that use\n * `height: 100vh`, `position: fixed; bottom: 0` etc. are effectively\n * *overlaid* by the panel because CSS can't resize `100vh`. Pair this\n * with `\"right\"` docking or opt those specific elements in via\n * `bottom: var(--jr-devtools-offset-bottom, 0)` /\n * `right: var(--jr-devtools-offset-right, 0)`.\n * - `false` — the panel is a pure overlay. Nothing is pushed; the host\n * app remains visually unchanged. The CSS custom properties\n * `--jr-devtools-offset-bottom` / `--jr-devtools-offset-right` are\n * still published on `:root` so apps can reserve their own space.\n */\n reserveSpace?: boolean;\n /**\n * When `true` (default), show a toolbar button that lets the user flip\n * the panel between bottom-dock and right-dock. The user's choice\n * persists across reloads (localStorage key `__jr_devtools_dock`), and\n * takes precedence over the initial `position` once set.\n *\n * When `false`, the dock follows `position` exactly and the toolbar\n * button is not rendered — useful when the host app's layout only works\n * with one dock.\n */\n allowDockToggle?: boolean;\n}\n\n/**\n * Returned from {@link createPanel}. Controls the panel lifecycle.\n */\nexport interface PanelHandle {\n /** Show the panel. */\n open: () => void;\n /** Hide the panel. */\n close: () => void;\n /** Toggle open/closed. */\n toggle: () => void;\n /** True if the panel is currently open. */\n isOpen: () => boolean;\n /** Request that all visible tabs re-render. */\n refresh: () => void;\n /** Remove the panel from the DOM and clean up. */\n destroy: () => void;\n}\n","import type { Spec, UIElement } from \"@json-render/core\";\nimport { validateSpec, type SpecIssue } from \"@json-render/core\";\nimport { setHoverHighlight } from \"../../picker\";\nimport { h, jsonPreview, replaceChildren } from \"../dom\";\nimport type { PanelContext, SpecEntry, TabDef, TabInstance } from \"../types\";\n\nconst TAB_ID = \"spec\";\n\n/** Tree view icon (lucide list-tree). */\nconst VIEW_TREE_SVG = `\n<svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M21 12h-8\"/>\n <path d=\"M21 6H8\"/>\n <path d=\"M21 18h-8\"/>\n <path d=\"M3 6v4c0 1.1.9 2 2 2h3\"/>\n <path d=\"M3 10v6c0 1.1.9 2 2 2h3\"/>\n</svg>`;\n\n/** Raw JSON view icon (lucide braces). */\nconst VIEW_RAW_SVG = `\n<svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M8 3H7a2 2 0 0 0-2 2v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5a2 2 0 0 0 2 2h1\"/>\n <path d=\"M16 21h1a2 2 0 0 0 2-2v-5a2 2 0 0 1 2-2 2 2 0 0 1-2-2V5a2 2 0 0 0-2-2h-1\"/>\n</svg>`;\n\n/**\n * Spec Tree tab — renders the element tree with expand/collapse, shows a\n * one-line summary per node, and highlights structural issues from\n * `validateSpec`. Selecting a node fills the right-hand detail pane with\n * full props + metadata.\n */\nexport function specTab(): TabDef {\n return {\n id: TAB_ID,\n label: \"Spec\",\n badge(ctx) {\n const spec = ctx.getSpec();\n if (!spec) return undefined;\n return Object.keys(spec.elements).length || undefined;\n },\n mount(root, ctx) {\n return mountSpecTab(root, ctx);\n },\n };\n}\n\nfunction mountSpecTab(root: HTMLElement, ctx: PanelContext): TabInstance {\n const expanded = new Set<string>();\n // Make the tree pane keyboard-navigable (Chrome-DevTools / WAI-ARIA tree\n // behaviour). Arrow keys move/expand/collapse, Enter toggles, Home/End\n // jump to ends.\n const treePane = h(\"div\", {\n className: \"jr-split-left\",\n role: \"tree\",\n tabindex: \"0\",\n });\n // Generation switcher — only rendered when the host exposes >1 spec\n // (typical in AI chats where each assistant message has its own spec).\n //\n // `selectedSpecId` always holds the id of the spec the user is viewing.\n // We track the previously-observed latest id separately so we can keep\n // the tab \"sticky-to-latest\" automatically: if the user is currently on\n // whatever was the newest generation, a newly-arrived generation slides\n // them forward to that one; otherwise their explicit pick is preserved.\n const generationBar = h(\"div\", {\n className: \"jr-generations\",\n \"aria-label\": \"Spec generation\",\n });\n let selectedSpecId: string | null = null;\n let lastSeenLatestId: string | null = null;\n\n // Breadcrumb bar (root → selected) pinned above the scrollable rows so\n // it stays visible while the tree scrolls. The left half is the crumb\n // trail (clickable ancestors); the right half is a toggle between tree\n // and raw-JSON views.\n const breadcrumbs = h(\"nav\", {\n className: \"jr-breadcrumbs\",\n \"aria-label\": \"Selected element ancestors\",\n });\n const crumbTrail = h(\"div\", { className: \"jr-breadcrumbs-trail\" });\n const viewTools = h(\"div\", {\n className: \"jr-breadcrumbs-tools\",\n role: \"group\",\n \"aria-label\": \"Spec view\",\n });\n const treeViewBtn = h(\"button\", {\n className: \"jr-view-btn\",\n type: \"button\",\n title: \"Tree view\",\n \"aria-label\": \"Tree view\",\n \"data-active\": \"true\",\n onClick: () => setView(\"tree\"),\n });\n treeViewBtn.innerHTML = VIEW_TREE_SVG;\n const rawViewBtn = h(\"button\", {\n className: \"jr-view-btn\",\n type: \"button\",\n title: \"Raw JSON view\",\n \"aria-label\": \"Raw JSON view\",\n \"data-active\": \"false\",\n onClick: () => setView(\"raw\"),\n });\n rawViewBtn.innerHTML = VIEW_RAW_SVG;\n viewTools.append(treeViewBtn, rawViewBtn);\n breadcrumbs.append(crumbTrail, viewTools);\n\n const treeRows = h(\"div\", { className: \"jr-tree-rows\" });\n treePane.append(generationBar, breadcrumbs, treeRows);\n const detailPane = h(\"div\", { className: \"jr-split-right\" });\n root.appendChild(h(\"div\", { className: \"jr-split\" }, treePane, detailPane));\n\n let view: \"tree\" | \"raw\" = \"tree\";\n function setView(next: \"tree\" | \"raw\") {\n if (view === next) return;\n view = next;\n treeViewBtn.dataset.active = String(view === \"tree\");\n rawViewBtn.dataset.active = String(view === \"raw\");\n render();\n }\n\n // When the user picks an element that lives in a *different* generation\n // than the one currently being inspected (common in multi-renderer\n // apps), auto-switch the generation so the tree can actually show it.\n const unsubSelection = ctx.selection.subscribe(() => {\n const key = ctx.selection.get();\n if (key) {\n const { spec, generations } = resolveCurrentSpec();\n if (spec && !spec.elements[key] && generations.length > 1) {\n const match = generations.find((g) => g.spec.elements[key]);\n if (match) selectedSpecId = match.id;\n }\n }\n render();\n });\n\n // Safety net: if the whole tree container loses the pointer, clear any\n // lingering hover highlight. Individual row mouseleave handles the\n // common case, but this catches fast tree re-renders where the row the\n // cursor was over has been unmounted without firing its own leave.\n const onTreeLeave = () => setHoverHighlight(null);\n treePane.addEventListener(\"mouseleave\", onTreeLeave);\n\n // Flat list of currently-visible element keys in render order. Populated\n // by `render()` and consumed by the arrow-key navigator.\n let visibleKeys: string[] = [];\n\n function toggleExpanded(key: string) {\n if (expanded.has(key)) expanded.delete(key);\n else expanded.add(key);\n render();\n }\n\n function scrollSelectedIntoView() {\n const el = treePane.querySelector<HTMLElement>(\n '.jr-tree-row[data-selected=\"true\"]',\n );\n el?.scrollIntoView({ block: \"nearest\" });\n }\n\n function moveSelection(nextKey: string | null | undefined) {\n if (!nextKey) return;\n ctx.selection.set(nextKey);\n setHoverHighlight(nextKey);\n // Selection subscriber has already re-rendered at this point.\n scrollSelectedIntoView();\n }\n\n function onKeyDown(ev: KeyboardEvent) {\n // Raw view is just a <pre> — let the browser handle text selection /\n // default keyboard behaviour. Tree nav doesn't apply there.\n if (view === \"raw\") return;\n // Ignore modifier-qualified keypresses so devtools hotkeys still work.\n if (ev.metaKey || ev.ctrlKey || ev.altKey) return;\n const key = ev.key;\n if (\n key !== \"ArrowUp\" &&\n key !== \"ArrowDown\" &&\n key !== \"ArrowLeft\" &&\n key !== \"ArrowRight\" &&\n key !== \"Enter\" &&\n key !== \" \" &&\n key !== \"Home\" &&\n key !== \"End\"\n ) {\n return;\n }\n\n // Keyboard nav must operate on the spec the user is inspecting, not\n // necessarily the latest one.\n const { spec } = resolveCurrentSpec();\n if (!spec || visibleKeys.length === 0) return;\n\n const current = ctx.selection.get();\n const idx = current ? visibleKeys.indexOf(current) : -1;\n ev.preventDefault();\n\n if (key === \"ArrowDown\") {\n if (idx < 0) moveSelection(visibleKeys[0]);\n else\n moveSelection(visibleKeys[Math.min(idx + 1, visibleKeys.length - 1)]);\n return;\n }\n\n if (key === \"ArrowUp\") {\n if (idx < 0) moveSelection(visibleKeys[0]);\n else moveSelection(visibleKeys[Math.max(idx - 1, 0)]);\n return;\n }\n\n if (key === \"Home\") {\n moveSelection(visibleKeys[0]);\n return;\n }\n\n if (key === \"End\") {\n moveSelection(visibleKeys[visibleKeys.length - 1]);\n return;\n }\n\n if (key === \"ArrowRight\") {\n if (!current) {\n moveSelection(visibleKeys[0]);\n return;\n }\n const el = spec.elements[current];\n const childKeys = getChildKeys(el);\n const hasChildren = childKeys.length > 0;\n if (!hasChildren) return;\n if (!expanded.has(current)) {\n expanded.add(current);\n render();\n // Stay on the same row; the row just became expandable.\n scrollSelectedIntoView();\n } else {\n // Already expanded → step into the first child.\n moveSelection(childKeys[0]);\n }\n return;\n }\n\n if (key === \"ArrowLeft\") {\n if (!current) return;\n const el = spec.elements[current];\n const hasChildren = getChildKeys(el).length > 0;\n if (hasChildren && expanded.has(current)) {\n expanded.delete(current);\n render();\n scrollSelectedIntoView();\n } else {\n const parent = findParent(spec, current);\n if (parent) moveSelection(parent);\n }\n return;\n }\n\n // Enter / Space\n if (!current) {\n moveSelection(visibleKeys[0]);\n return;\n }\n const el = spec.elements[current];\n if (getChildKeys(el).length > 0) {\n toggleExpanded(current);\n scrollSelectedIntoView();\n }\n }\n\n // Focus the tree pane when the user clicks into it so arrow keys take\n // effect right after a mouse pick. `focus()` without `preventScroll`\n // would jump the body on some browsers, so pass the option.\n const onFocusIn = () => {\n const current = ctx.selection.get();\n if (current) setHoverHighlight(current);\n };\n const onFocusOut = (ev: FocusEvent) => {\n // Only clear when focus leaves the tree entirely (not when moving\n // between rows). Shadow DOM + relatedTarget behaves like a normal\n // document for this check.\n const next = ev.relatedTarget as Node | null;\n if (!next || !treePane.contains(next)) {\n setHoverHighlight(null);\n }\n };\n\n // Focus the tree on mousedown so arrow keys work right after a click.\n // Passing `preventScroll` avoids the browser jumping the page if the\n // pane was off-screen.\n const onMouseDown = () => {\n try {\n treePane.focus({ preventScroll: true });\n } catch {\n // Some environments (tests, ancient browsers) throw on focus().\n }\n };\n treePane.addEventListener(\"mousedown\", onMouseDown);\n treePane.addEventListener(\"keydown\", onKeyDown);\n treePane.addEventListener(\"focusin\", onFocusIn);\n treePane.addEventListener(\"focusout\", onFocusOut);\n\n /**\n * Resolve the spec the tab currently inspects, plus the full generations\n * list. When a new generation arrives and the user had been on what was\n * previously the newest, we slide forward to the new newest (sticky).\n * An explicit older pick is always preserved.\n */\n function resolveCurrentSpec(): {\n spec: Spec | null;\n generations: SpecEntry[];\n } {\n const generations = ctx.getSpecs?.() ?? [];\n if (generations.length === 0) {\n return { spec: ctx.getSpec(), generations };\n }\n const latest = generations[generations.length - 1]!;\n\n // First render, or our pick no longer exists (e.g. chat cleared):\n // default to the newest.\n if (\n selectedSpecId == null ||\n !generations.some((g) => g.id === selectedSpecId)\n ) {\n selectedSpecId = latest.id;\n } else if (\n lastSeenLatestId != null &&\n selectedSpecId === lastSeenLatestId &&\n lastSeenLatestId !== latest.id\n ) {\n // Sticky: we were on \"what was newest last render\"; follow forward.\n selectedSpecId = latest.id;\n }\n lastSeenLatestId = latest.id;\n\n const picked = generations.find((g) => g.id === selectedSpecId)!;\n return { spec: picked.spec, generations };\n }\n\n function renderGenerationBar(generations: SpecEntry[]) {\n if (generations.length < 2) {\n replaceChildren(generationBar, null);\n return;\n }\n const latestId = generations[generations.length - 1]!.id;\n const select = h(\n \"select\",\n {\n className: \"jr-generation-select\",\n \"aria-label\": \"Inspect generation\",\n onChange: (ev: Event) => {\n selectedSpecId = (ev.target as HTMLSelectElement).value;\n render();\n },\n },\n ...generations.map((g, i) =>\n h(\n \"option\",\n {\n value: g.id,\n selected: g.id === selectedSpecId ? \"true\" : undefined,\n },\n g.id === latestId ? `Gen ${i + 1} (latest)` : `Gen ${i + 1}`,\n ),\n ),\n );\n const count = h(\n \"span\",\n { className: \"jr-generations-count\" },\n `${generations.length} generation${generations.length === 1 ? \"\" : \"s\"}`,\n );\n replaceChildren(generationBar, select, count);\n }\n\n function render() {\n const { spec, generations } = resolveCurrentSpec();\n renderGenerationBar(generations);\n if (!spec || !spec.root || Object.keys(spec.elements).length === 0) {\n visibleKeys = [];\n renderBreadcrumbs(null, null);\n replaceChildren(\n treeRows,\n h(\"div\", { className: \"jr-empty\" }, \"No spec attached.\"),\n );\n replaceChildren(detailPane, null);\n return;\n }\n\n const issues = collectIssues(spec);\n const selected = ctx.selection.get();\n\n // Auto-expand the path to the selection so it is always visible.\n // `findPath` returns leaf-first; we'll flip it for the breadcrumb bar.\n const pathLeafFirst = selected ? findPath(spec, selected) : [];\n for (const k of pathLeafFirst) expanded.add(k);\n\n visibleKeys = collectVisibleKeys(spec, expanded);\n\n renderBreadcrumbs(spec, pathLeafFirst);\n\n if (view === \"raw\") {\n renderRaw(spec);\n } else {\n replaceChildren(\n treeRows,\n renderNode(\n spec,\n spec.root,\n 0,\n expanded,\n selected,\n issues,\n ctx,\n toggleExpanded,\n null,\n ),\n );\n }\n\n if (selected && spec.elements[selected]) {\n renderDetail(detailPane, spec, selected, issues);\n } else {\n replaceChildren(\n detailPane,\n h(\"div\", { className: \"jr-empty\" }, \"Select an element to inspect.\"),\n );\n }\n }\n\n /**\n * Render the whole spec as pretty-printed JSON. Useful for copy/paste\n * into issue reports or quick source-level scans.\n */\n function renderRaw(spec: Spec) {\n let text: string;\n try {\n text = JSON.stringify(spec, null, 2);\n } catch {\n text = String(spec);\n }\n replaceChildren(treeRows, h(\"pre\", { className: \"jr-raw\" }, text));\n }\n\n /**\n * Rebuild the crumb trail inside the breadcrumb bar.\n * `pathLeafFirst` is the output of `findPath` (leaf → root); we render\n * it root → leaf. The view-toggle buttons on the right are untouched.\n */\n function renderBreadcrumbs(\n spec: Spec | null,\n pathLeafFirst: string[] | null,\n ) {\n if (!spec || !pathLeafFirst || pathLeafFirst.length === 0) {\n replaceChildren(\n crumbTrail,\n h(\"span\", { className: \"jr-breadcrumbs-empty\" }, \"No element selected\"),\n );\n return;\n }\n const path = [...pathLeafFirst].reverse();\n const parts: Array<HTMLElement | null> = [];\n path.forEach((key, i) => {\n const el = spec.elements[key];\n const label = el?.type ?? \"<missing>\";\n const isCurrent = i === path.length - 1;\n const crumb = h(\n \"button\",\n {\n className: \"jr-breadcrumb\",\n type: \"button\",\n \"data-current\": String(isCurrent),\n title: `#${key}`,\n onClick: (ev: MouseEvent) => {\n ev.stopPropagation();\n ctx.selection.set(key);\n setHoverHighlight(key);\n },\n onMouseEnter: () => setHoverHighlight(key),\n onMouseLeave: () => setHoverHighlight(null),\n },\n label,\n );\n parts.push(crumb);\n if (!isCurrent) {\n parts.push(h(\"span\", { className: \"jr-breadcrumb-sep\" }, \"\\u25b8\"));\n }\n });\n replaceChildren(crumbTrail, parts);\n }\n\n render();\n\n return {\n update: render,\n destroy() {\n unsubSelection();\n treePane.removeEventListener(\"mouseleave\", onTreeLeave);\n treePane.removeEventListener(\"mousedown\", onMouseDown);\n treePane.removeEventListener(\"keydown\", onKeyDown);\n treePane.removeEventListener(\"focusin\", onFocusIn);\n treePane.removeEventListener(\"focusout\", onFocusOut);\n setHoverHighlight(null);\n },\n };\n}\n\n/**\n * Flatten `spec` into the ordered list of element keys currently visible\n * in the tree, respecting the `expanded` set. Used to drive arrow-key\n * navigation.\n */\nfunction collectVisibleKeys(spec: Spec, expanded: Set<string>): string[] {\n const list: string[] = [];\n function walk(key: string) {\n list.push(key);\n const el = spec.elements[key];\n const childKeys = getChildKeys(el);\n if (childKeys.length === 0) return;\n if (!expanded.has(key)) return;\n for (const child of childKeys) walk(child);\n }\n walk(spec.root);\n return list;\n}\n\nfunction findParent(spec: Spec, key: string): string | null {\n for (const [parentKey, el] of Object.entries(spec.elements)) {\n if (getChildKeys(el).includes(key)) return parentKey;\n }\n return null;\n}\n\nfunction getChildKeys(element: UIElement | undefined): string[] {\n if (!element) return [];\n return [\n ...(element.children ?? []),\n ...Object.values(element.slots ?? {}).flat(),\n ];\n}\n\ninterface IssueIndex {\n all: SpecIssue[];\n byKey: Map<string, SpecIssue[]>;\n}\n\nfunction collectIssues(spec: Spec): IssueIndex {\n const result = validateSpec(spec, { checkOrphans: true });\n const byKey = new Map<string, SpecIssue[]>();\n for (const issue of result.issues) {\n const k = issue.elementKey ?? \"__spec__\";\n const arr = byKey.get(k) ?? [];\n arr.push(issue);\n byKey.set(k, arr);\n }\n return { all: result.issues, byKey };\n}\n\n/**\n * Walk the tree looking for `key` and return the ancestor path\n * (inclusive) so a caller can expand it.\n */\nfunction findPath(spec: Spec, key: string): string[] {\n const path: string[] = [];\n function walk(current: string): boolean {\n if (current === key) {\n path.push(current);\n return true;\n }\n const el = spec.elements[current];\n for (const child of getChildKeys(el)) {\n if (walk(child)) {\n path.push(current);\n return true;\n }\n }\n return false;\n }\n walk(spec.root);\n return path;\n}\n\nfunction renderNode(\n spec: Spec,\n key: string,\n depth: number,\n expanded: Set<string>,\n selected: string | null,\n issues: IssueIndex,\n ctx: PanelContext,\n onToggle: (key: string) => void,\n parentHidden: boolean | null,\n): HTMLElement | null {\n const el = spec.elements[key];\n if (!el) {\n return h(\n \"div\",\n {\n className: \"jr-tree-row\",\n style: { paddingLeft: `${12 + depth * 14}px` },\n },\n h(\"span\", { className: \"jr-tree-toggle\" }, \" \"),\n h(\"span\", { className: \"jr-tree-type\" }, \"<missing>\"),\n h(\"span\", { className: \"jr-tree-key\" }, key),\n );\n }\n\n const childKeys = getChildKeys(el);\n const hasChildren = childKeys.length > 0;\n const isExpanded = hasChildren && expanded.has(key);\n const isSelected = selected === key;\n const elementIssues = issues.byKey.get(key) ?? [];\n const hasErrors = elementIssues.some((i) => i.severity === \"error\");\n const summary = makeSummary(el);\n const hiddenHere = el.visible !== undefined ? null : parentHidden;\n\n const row = h(\n \"div\",\n {\n className: `jr-tree-row${hiddenHere === true ? \" jr-tree-hidden\" : \"\"}`,\n \"data-selected\": String(isSelected),\n style: { paddingLeft: `${8 + depth * 14}px` },\n onClick: (ev: MouseEvent) => {\n ev.stopPropagation();\n ctx.selection.set(key);\n },\n // Paint a persistent bounding-box overlay over the matching DOM\n // element while the tree row is hovered — gives the same visual\n // affordance as Chrome DevTools' element picker without needing to\n // enter pick mode.\n onMouseEnter: () => {\n setHoverHighlight(key);\n },\n onMouseLeave: () => {\n setHoverHighlight(null);\n },\n },\n h(\n \"span\",\n {\n className: \"jr-tree-toggle\",\n onClick: (ev: MouseEvent) => {\n ev.stopPropagation();\n if (hasChildren) onToggle(key);\n },\n },\n hasChildren ? (isExpanded ? \"\\u25be\" : \"\\u25b8\") : \" \",\n ),\n h(\"span\", { className: \"jr-tree-type\" }, el.type),\n h(\"span\", { className: \"jr-tree-key\" }, `#${key}`),\n summary ? h(\"span\", { className: \"jr-tree-summary\" }, summary) : null,\n el.visible !== undefined\n ? h(\"span\", { className: \"jr-badge\", \"data-tone\": \"amber\" }, \"visible\")\n : null,\n el.repeat\n ? h(\"span\", { className: \"jr-badge\", \"data-tone\": \"accent\" }, \"repeat\")\n : null,\n hasErrors\n ? h(\n \"span\",\n {\n className: \"jr-badge\",\n \"data-tone\": \"red\",\n title: elementIssues.map((i) => i.message).join(\"\\n\"),\n },\n `${elementIssues.length}`,\n )\n : null,\n );\n\n const container = h(\"div\", null, row);\n\n if (isExpanded && hasChildren) {\n for (const childKey of childKeys) {\n const childNode = renderNode(\n spec,\n childKey,\n depth + 1,\n expanded,\n selected,\n issues,\n ctx,\n onToggle,\n hiddenHere,\n );\n if (childNode) container.appendChild(childNode);\n }\n }\n\n return container;\n}\n\n/**\n * Produce a very short human-readable summary of a node's props. Prefers\n * common fields (\"title\", \"label\", \"text\", \"name\") and falls back to the\n * first scalar prop.\n */\nfunction makeSummary(el: UIElement): string | null {\n const props = el.props as Record<string, unknown> | undefined;\n if (!props) return null;\n const prefer = [\"title\", \"label\", \"text\", \"name\", \"value\", \"status\"];\n for (const p of prefer) {\n const v = props[p];\n if (typeof v === \"string\" && v.length > 0) return shorten(v, 60);\n if (typeof v === \"number\" || typeof v === \"boolean\") return String(v);\n }\n for (const [, v] of Object.entries(props)) {\n if (typeof v === \"string\" && v.length > 0) return shorten(v, 60);\n if (typeof v === \"number\" || typeof v === \"boolean\") return String(v);\n }\n return null;\n}\n\nfunction shorten(text: string, max: number): string {\n if (text.length <= max) return text;\n return text.slice(0, max - 1) + \"\\u2026\";\n}\n\nfunction renderDetail(\n container: HTMLElement,\n spec: Spec,\n key: string,\n issues: IssueIndex,\n) {\n const el = spec.elements[key];\n if (!el) {\n replaceChildren(\n container,\n h(\"div\", { className: \"jr-empty\" }, `Element '${key}' not found.`),\n );\n return;\n }\n\n const elIssues = issues.byKey.get(key) ?? [];\n const children = getChildKeys(el).length;\n\n replaceChildren(\n container,\n h(\n \"div\",\n { className: \"jr-detail\" },\n h(\"h4\", null, \"Element\"),\n h(\n \"div\",\n { style: { marginBottom: \"10px\" } },\n h(\"span\", { className: \"jr-tree-type\" }, el.type),\n \" \",\n h(\"span\", { className: \"jr-tree-key\" }, `#${key}`),\n \" \",\n h(\n \"span\",\n { className: \"jr-tree-summary\" },\n `${children} child${children === 1 ? \"\" : \"ren\"}`,\n ),\n ),\n elIssues.length > 0\n ? [\n h(\"h4\", null, \"Issues\"),\n ...elIssues.map((issue) =>\n h(\n \"div\",\n {\n className: \"jr-badge\",\n \"data-tone\": issue.severity === \"error\" ? \"red\" : \"amber\",\n style: {\n marginBottom: \"6px\",\n display: \"block\",\n padding: \"4px 8px\",\n },\n },\n `${issue.severity.toUpperCase()}: ${issue.message}`,\n ),\n ),\n ]\n : null,\n el.visible !== undefined\n ? [\n h(\"h4\", null, \"Visibility\"),\n h(\"pre\", null, jsonPreview(el.visible, 2000)),\n ]\n : null,\n el.on && Object.keys(el.on).length > 0\n ? [h(\"h4\", null, \"Events\"), h(\"pre\", null, jsonPreview(el.on, 2000))]\n : null,\n el.watch && Object.keys(el.watch).length > 0\n ? [\n h(\"h4\", null, \"Watchers\"),\n h(\"pre\", null, jsonPreview(el.watch, 2000)),\n ]\n : null,\n el.repeat\n ? [\n h(\"h4\", null, \"Repeat\"),\n h(\"pre\", null, jsonPreview(el.repeat, 2000)),\n ]\n : null,\n h(\"h4\", null, \"Props\"),\n h(\"pre\", null, JSON.stringify(el.props, null, 2)),\n ),\n );\n}\n","import { flattenToPointers } from \"@json-render/core/store-utils\";\nimport { h, jsonPreview, replaceChildren } from \"../dom\";\nimport type { PanelContext, TabDef, TabInstance } from \"../types\";\n\nconst TAB_ID = \"state\";\n\n/**\n * State Inspector tab — lists every leaf path in the state model with an\n * inline editor. Editing a value re-parses it as JSON; if the input\n * doesn't parse, the raw string is used. Reads a snapshot from the\n * underlying StateStore on every render, plus on every state-set event.\n */\nexport function stateTab(): TabDef {\n return {\n id: TAB_ID,\n label: \"State\",\n badge(ctx) {\n const store = ctx.getStateStore();\n if (!store) return undefined;\n try {\n const flat = flattenToPointers(store.getSnapshot());\n const count = Object.keys(flat).length;\n return count || undefined;\n } catch {\n return undefined;\n }\n },\n mount(root, ctx) {\n return mountStateTab(root, ctx);\n },\n };\n}\n\nfunction mountStateTab(root: HTMLElement, ctx: PanelContext): TabInstance {\n const container = h(\"div\", {\n style: { height: \"100%\", display: \"flex\", flexDirection: \"column\" },\n });\n const toolbar = h(\"div\", { className: \"jr-toolbar\" });\n const body = h(\"div\", {\n style: { overflow: \"auto\", flex: \"1\", minHeight: \"0\" },\n });\n container.appendChild(toolbar);\n container.appendChild(body);\n root.appendChild(container);\n\n let filter = \"\";\n // Tracks which paths are being edited so live state-set events don't clobber the input.\n const editing = new Set<string>();\n\n const searchInput = h(\"input\", {\n className: \"jr-search\",\n type: \"text\",\n placeholder: \"Filter paths\\u2026\",\n onInput: (ev: Event) => {\n filter = ((ev.target as HTMLInputElement).value || \"\").toLowerCase();\n renderBody();\n },\n });\n\n function renderToolbar() {\n replaceChildren(\n toolbar,\n searchInput,\n h(\n \"button\",\n {\n className: \"jr-icon-btn\",\n title: \"Refresh state listing\",\n onClick: () => renderBody(),\n },\n \"refresh\",\n ),\n );\n }\n\n function renderBody() {\n const store = ctx.getStateStore();\n if (!store) {\n replaceChildren(\n body,\n h(\n \"div\",\n { className: \"jr-empty\" },\n \"No StateStore attached. Devtools sees state once a provider mounts.\",\n ),\n );\n return;\n }\n\n let flat: Record<string, unknown> = {};\n try {\n flat = flattenToPointers(store.getSnapshot());\n } catch (err) {\n replaceChildren(\n body,\n h(\n \"div\",\n { className: \"jr-empty\" },\n `State read failed: ${String(err)}`,\n ),\n );\n return;\n }\n\n const entries = Object.entries(flat)\n .filter(([path]) => !filter || path.toLowerCase().includes(filter))\n .sort(([a], [b]) => a.localeCompare(b));\n\n if (entries.length === 0) {\n replaceChildren(\n body,\n h(\n \"div\",\n { className: \"jr-empty\" },\n filter ? \"No paths match the filter.\" : \"State is empty.\",\n ),\n );\n return;\n }\n\n replaceChildren(\n body,\n entries.map(([path, value]) =>\n renderStateRow(path, value, store.set, editing),\n ),\n );\n }\n\n renderToolbar();\n renderBody();\n\n return {\n update() {\n // Only rebuild when nothing is actively being edited so focus /\n // caret position is preserved between re-renders.\n if (editing.size === 0) renderBody();\n },\n };\n}\n\nfunction renderStateRow(\n path: string,\n value: unknown,\n setValue: (path: string, value: unknown) => void,\n editing: Set<string>,\n): HTMLElement {\n const input = h(\"input\", {\n className: \"jr-state-value\",\n type: \"text\",\n value: stringifyValue(value),\n spellcheck: \"false\" as unknown as string,\n onFocus: () => {\n editing.add(path);\n },\n onBlur: (ev: FocusEvent) => {\n editing.delete(path);\n const raw = (ev.target as HTMLInputElement).value;\n try {\n const parsed = raw === \"\" ? \"\" : JSON.parse(raw);\n setValue(path, parsed);\n input.dataset.dirty = \"false\";\n } catch {\n setValue(path, raw);\n input.dataset.dirty = \"false\";\n }\n },\n onInput: () => {\n input.dataset.dirty = \"true\";\n },\n onKeyDown: (ev: KeyboardEvent) => {\n if (ev.key === \"Enter\") {\n ev.preventDefault();\n (ev.target as HTMLInputElement).blur();\n }\n if (ev.key === \"Escape\") {\n input.value = stringifyValue(value);\n input.dataset.dirty = \"false\";\n (ev.target as HTMLInputElement).blur();\n }\n },\n }) as HTMLInputElement;\n\n return h(\n \"div\",\n {\n className: \"jr-state-row\",\n title: `${path}\\n${jsonPreview(value, 1000)}`,\n },\n h(\"span\", { className: \"jr-state-path\" }, path),\n input,\n );\n}\n\nfunction stringifyValue(value: unknown): string {\n if (typeof value === \"string\") return JSON.stringify(value);\n if (value === null) return \"null\";\n if (value === undefined) return \"\";\n if (typeof value === \"number\" || typeof value === \"boolean\")\n return String(value);\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n","import { formatTime, h, jsonPreview, replaceChildren } from \"../dom\";\nimport type { DevtoolsEvent } from \"../../types\";\nimport type { PanelContext, TabDef, TabInstance } from \"../types\";\n\nconst TAB_ID = \"actions\";\n\ninterface ActionRow {\n id: string;\n name: string;\n params?: unknown;\n dispatchedAt: number;\n settledAt?: number;\n durationMs?: number;\n ok?: boolean;\n result?: unknown;\n error?: string;\n}\n\n/**\n * Action Log tab — chronologically ordered list of dispatched actions.\n * Each dispatch is paired with its settle event (by `id`) to show\n * duration + success/failure.\n */\nexport function actionsTab(): TabDef {\n return {\n id: TAB_ID,\n label: \"Actions\",\n badge(ctx) {\n const rows = foldActions(ctx.events.snapshot()).length;\n return rows || undefined;\n },\n mount(root, ctx) {\n return mountActionsTab(root, ctx);\n },\n };\n}\n\nfunction mountActionsTab(root: HTMLElement, ctx: PanelContext): TabInstance {\n const container = h(\"div\", {\n style: { height: \"100%\", display: \"flex\", flexDirection: \"column\" },\n });\n const toolbar = h(\"div\", { className: \"jr-toolbar\" });\n const body = h(\"div\", {\n style: { overflow: \"auto\", flex: \"1\", minHeight: \"0\" },\n });\n container.appendChild(toolbar);\n container.appendChild(body);\n root.appendChild(container);\n\n let filter = \"\";\n const expanded = new Set<string>();\n\n // Toolbar nodes are created once so the search input keeps focus + caret\n // position across every re-render. Only the dynamic bits (count badge\n // text) are updated imperatively.\n const searchInput = h(\"input\", {\n className: \"jr-search\",\n type: \"text\",\n placeholder: \"Filter by action name\\u2026\",\n onInput: (ev: Event) => {\n filter = ((ev.target as HTMLInputElement).value || \"\").toLowerCase();\n renderBody();\n },\n }) as HTMLInputElement;\n const countBadge = h(\"span\", { className: \"jr-badge\" }, \"0 actions\");\n const clearBtn = h(\n \"button\",\n {\n className: \"jr-icon-btn\",\n title: \"Clear action log\",\n onClick: () => {\n // Only clears action events to preserve other history.\n const keep = ctx.events\n .snapshot()\n .filter(\n (e) =>\n e.kind !== \"action-dispatched\" && e.kind !== \"action-settled\",\n );\n ctx.events.clear();\n for (const e of keep) ctx.events.push(e);\n },\n },\n \"clear\",\n );\n toolbar.append(searchInput, countBadge, clearBtn);\n\n function renderBody() {\n const rows = foldActions(ctx.events.snapshot())\n .filter((r) => !filter || r.name.toLowerCase().includes(filter))\n .reverse(); // newest first\n\n countBadge.textContent = `${rows.length} action${rows.length === 1 ? \"\" : \"s\"}`;\n\n if (rows.length === 0) {\n replaceChildren(\n body,\n h(\n \"div\",\n { className: \"jr-empty\" },\n filter\n ? \"No actions match the filter.\"\n : \"No actions dispatched yet.\",\n ),\n );\n return;\n }\n\n replaceChildren(\n body,\n rows.map((r) => renderRow(r, expanded, renderBody)),\n );\n }\n\n renderBody();\n\n return { update: renderBody };\n}\n\nfunction foldActions(events: DevtoolsEvent[]): ActionRow[] {\n const byId = new Map<string, ActionRow>();\n const order: string[] = [];\n for (const evt of events) {\n if (evt.kind === \"action-dispatched\") {\n if (byId.has(evt.id)) continue;\n byId.set(evt.id, {\n id: evt.id,\n name: evt.name,\n params: evt.params,\n dispatchedAt: evt.at,\n });\n order.push(evt.id);\n } else if (evt.kind === \"action-settled\") {\n const row = byId.get(evt.id);\n if (!row) continue;\n row.settledAt = evt.at;\n row.durationMs = evt.durationMs;\n row.ok = evt.ok;\n row.result = evt.result;\n row.error = evt.error;\n }\n }\n return order.map((id) => byId.get(id)!).filter(Boolean);\n}\n\nfunction renderRow(\n row: ActionRow,\n expanded: Set<string>,\n refresh: () => void,\n): HTMLElement {\n const isExpanded = expanded.has(row.id);\n const pending = row.settledAt === undefined;\n const tone = pending ? \"amber\" : row.ok ? \"green\" : \"red\";\n const status = pending ? \"pending\" : row.ok ? \"ok\" : \"error\";\n const duration =\n row.durationMs !== undefined ? `${row.durationMs.toFixed(0)}ms` : \"\";\n\n const rowEl = h(\n \"div\",\n {\n className: \"jr-row\",\n onClick: () => {\n if (isExpanded) expanded.delete(row.id);\n else expanded.add(row.id);\n refresh();\n },\n },\n h(\"span\", { className: \"jr-row-time\" }, formatTime(row.dispatchedAt)),\n h(\n \"span\",\n { className: \"jr-row-main\" },\n h(\"strong\", null, row.name),\n row.params !== undefined\n ? h(\n \"span\",\n { className: \"jr-tree-summary\", style: { marginLeft: \"8px\" } },\n jsonPreview(row.params, 80),\n )\n : null,\n ),\n h(\n \"span\",\n { className: \"jr-row-meta\" },\n h(\"span\", { className: \"jr-badge\", \"data-tone\": tone }, status),\n duration ? h(\"span\", { style: { marginLeft: \"6px\" } }, duration) : null,\n ),\n );\n\n if (!isExpanded) return rowEl;\n\n const container = h(\"div\", null, rowEl);\n container.appendChild(\n h(\n \"div\",\n { className: \"jr-row-expanded\" },\n h(\"h4\", null, \"Params\"),\n h(\"pre\", null, JSON.stringify(row.params ?? null, null, 2)),\n row.ok === false\n ? [\n h(\"h4\", null, \"Error\"),\n h(\"pre\", null, row.error ?? \"(unknown error)\"),\n ]\n : null,\n row.result !== undefined && row.ok !== false\n ? [\n h(\"h4\", null, \"Result\"),\n h(\"pre\", null, JSON.stringify(row.result, null, 2)),\n ]\n : null,\n ),\n );\n return container;\n}\n","import { formatTime, h, jsonPreview, replaceChildren } from \"../dom\";\nimport type { DevtoolsEvent, TokenUsage } from \"../../types\";\nimport type { PanelContext, TabDef, TabInstance } from \"../types\";\n\nconst TAB_ID = \"stream\";\n\ninterface Generation {\n startedAt: number;\n endedAt?: number;\n ok?: boolean;\n events: DevtoolsEvent[];\n usage?: TokenUsage;\n}\n\n/**\n * Stream Log tab — shows spec patches, text chunks, lifecycle markers,\n * and token usage grouped by generation (lifecycle start -> end).\n */\nexport function streamTab(): TabDef {\n return {\n id: TAB_ID,\n label: \"Stream\",\n badge(ctx) {\n const gens = groupGenerations(ctx.events.snapshot());\n return gens.length || undefined;\n },\n mount(root, ctx) {\n return mountStreamTab(root, ctx);\n },\n };\n}\n\nfunction mountStreamTab(root: HTMLElement, ctx: PanelContext): TabInstance {\n const container = h(\"div\", {\n style: { height: \"100%\", display: \"flex\", flexDirection: \"column\" },\n });\n const toolbar = h(\"div\", { className: \"jr-toolbar\" });\n const body = h(\"div\", {\n style: { overflow: \"auto\", flex: \"1\", minHeight: \"0\" },\n });\n container.appendChild(toolbar);\n container.appendChild(body);\n root.appendChild(container);\n\n function render() {\n const all = ctx.events.snapshot();\n const gens = groupGenerations(all);\n const orphan = collectOrphanEvents(all);\n\n replaceChildren(\n toolbar,\n h(\n \"span\",\n { className: \"jr-badge\" },\n `${gens.length} generation${gens.length === 1 ? \"\" : \"s\"}`,\n ),\n );\n\n if (gens.length === 0 && orphan.length === 0) {\n replaceChildren(\n body,\n h(\n \"div\",\n { className: \"jr-empty\" },\n \"No stream events yet. Tap a stream or pass messages to capture patches.\",\n ),\n );\n return;\n }\n\n const content: HTMLElement[] = [];\n // Newest first; flatten orphan into a pseudo-generation.\n if (orphan.length > 0) {\n content.push(\n renderGeneration(\n { startedAt: orphan[0]?.at ?? Date.now(), events: orphan },\n \"live\",\n true,\n ),\n );\n }\n for (let i = gens.length - 1; i >= 0; i--) {\n const gen = gens[i]!;\n content.push(renderGeneration(gen, `gen-${i}`, i === gens.length - 1));\n }\n replaceChildren(body, content);\n }\n\n render();\n return { update: render };\n}\n\nfunction groupGenerations(events: DevtoolsEvent[]): Generation[] {\n const gens: Generation[] = [];\n let current: Generation | null = null;\n for (const evt of events) {\n if (evt.kind === \"stream-lifecycle\") {\n if (evt.phase === \"start\") {\n if (current) gens.push(current);\n current = { startedAt: evt.at, events: [] };\n } else {\n if (!current) {\n current = { startedAt: evt.at, events: [] };\n }\n current.endedAt = evt.at;\n current.ok = evt.ok;\n gens.push(current);\n current = null;\n }\n continue;\n }\n if (\n evt.kind === \"stream-patch\" ||\n evt.kind === \"stream-text\" ||\n evt.kind === \"stream-usage\"\n ) {\n if (!current) current = { startedAt: evt.at, events: [] };\n current.events.push(evt);\n if (evt.kind === \"stream-usage\") current.usage = evt.usage;\n }\n }\n if (current) gens.push(current);\n return gens;\n}\n\n/**\n * Stream events recorded outside any lifecycle pair (e.g. when the app taps\n * message parts without emitting explicit start/end markers).\n */\nfunction collectOrphanEvents(events: DevtoolsEvent[]): DevtoolsEvent[] {\n const hasAnyLifecycle = events.some((e) => e.kind === \"stream-lifecycle\");\n if (hasAnyLifecycle) return [];\n return events.filter(\n (e) =>\n e.kind === \"stream-patch\" ||\n e.kind === \"stream-text\" ||\n e.kind === \"stream-usage\",\n );\n}\n\nfunction renderGeneration(\n gen: Generation,\n key: string,\n expandedByDefault: boolean,\n): HTMLElement {\n const patchCount = gen.events.filter((e) => e.kind === \"stream-patch\").length;\n const textCount = gen.events.filter((e) => e.kind === \"stream-text\").length;\n const duration =\n gen.endedAt !== undefined ? gen.endedAt - gen.startedAt : undefined;\n const tone =\n gen.endedAt === undefined ? \"amber\" : gen.ok === false ? \"red\" : \"green\";\n const status =\n gen.endedAt === undefined ? \"live\" : gen.ok === false ? \"error\" : \"done\";\n\n const body = h(\n \"div\",\n {\n style: {\n borderTop: \"1px solid var(--jr-border)\",\n background: \"var(--jr-bg-soft)\",\n display: expandedByDefault ? \"block\" : \"none\",\n },\n },\n ...gen.events.map(renderStreamEvent),\n );\n\n const header = h(\n \"div\",\n {\n className: \"jr-row\",\n style: { cursor: \"pointer\" },\n onClick: () => {\n body.style.display = body.style.display === \"none\" ? \"block\" : \"none\";\n },\n },\n h(\"span\", { className: \"jr-row-time\" }, formatTime(gen.startedAt)),\n h(\n \"span\",\n { className: \"jr-row-main\" },\n h(\"strong\", null, `generation #${key}`),\n h(\n \"span\",\n { className: \"jr-tree-summary\", style: { marginLeft: \"8px\" } },\n `${patchCount} patch${patchCount === 1 ? \"\" : \"es\"}`,\n textCount > 0\n ? `, ${textCount} text chunk${textCount === 1 ? \"\" : \"s\"}`\n : \"\",\n ),\n ),\n h(\n \"span\",\n { className: \"jr-row-meta\" },\n h(\"span\", { className: \"jr-badge\", \"data-tone\": tone }, status),\n duration !== undefined\n ? h(\"span\", { style: { marginLeft: \"6px\" } }, `${duration}ms`)\n : null,\n gen.usage\n ? h(\n \"span\",\n { style: { marginLeft: \"6px\" } },\n `${formatTokens(gen.usage.totalTokens)} tok`,\n )\n : null,\n ),\n );\n\n return h(\"div\", null, header, body);\n}\n\nfunction renderStreamEvent(evt: DevtoolsEvent): HTMLElement {\n if (evt.kind === \"stream-patch\") {\n return h(\n \"div\",\n { className: \"jr-row\" },\n h(\"span\", { className: \"jr-row-time\" }, formatTime(evt.at)),\n h(\n \"span\",\n { className: \"jr-row-main\" },\n h(\n \"span\",\n { className: \"jr-badge\", \"data-tone\": \"accent\" },\n evt.patch.op,\n ),\n h(\n \"span\",\n { className: \"jr-tree-summary\", style: { marginLeft: \"8px\" } },\n evt.patch.path,\n evt.patch.value !== undefined\n ? ` = ${jsonPreview(evt.patch.value, 80)}`\n : \"\",\n ),\n ),\n h(\"span\", { className: \"jr-row-meta\" }, evt.source),\n );\n }\n if (evt.kind === \"stream-text\") {\n return h(\n \"div\",\n { className: \"jr-row\" },\n h(\"span\", { className: \"jr-row-time\" }, formatTime(evt.at)),\n h(\n \"span\",\n { className: \"jr-row-main\", style: { whiteSpace: \"pre-wrap\" } },\n evt.text,\n ),\n h(\n \"span\",\n { className: \"jr-row-meta\" },\n h(\"span\", { className: \"jr-badge\" }, \"text\"),\n ),\n );\n }\n if (evt.kind === \"stream-usage\") {\n return h(\n \"div\",\n { className: \"jr-row\" },\n h(\"span\", { className: \"jr-row-time\" }, formatTime(evt.at)),\n h(\n \"span\",\n { className: \"jr-row-main\" },\n `prompt ${formatTokens(evt.usage.promptTokens)} / completion ${formatTokens(\n evt.usage.completionTokens,\n )} / total ${formatTokens(evt.usage.totalTokens)}`,\n ),\n h(\n \"span\",\n { className: \"jr-row-meta\" },\n h(\"span\", { className: \"jr-badge\", \"data-tone\": \"accent\" }, \"usage\"),\n ),\n );\n }\n return h(\"div\");\n}\n\nfunction formatTokens(n: number): string {\n if (n >= 1000) return `${(n / 1000).toFixed(1).replace(/\\.0$/, \"\")}k`;\n return String(n);\n}\n","import { h, replaceChildren } from \"../dom\";\nimport type { PanelContext, TabDef, TabInstance } from \"../types\";\n\nconst TAB_ID = \"catalog\";\n\ninterface CatalogField {\n name: string;\n type: string;\n}\n\ninterface CatalogComponentInfo {\n name: string;\n description: string;\n props: CatalogField[];\n slots: string[];\n events: string[];\n}\n\ninterface CatalogActionInfo {\n name: string;\n description: string;\n params: CatalogField[];\n}\n\n/**\n * Catalog Browser tab — lists the components and actions declared in the\n * attached catalog with prop/param chips, so developers can see what the\n * AI can use.\n */\nexport function catalogTab(): TabDef {\n return {\n id: TAB_ID,\n label: \"Catalog\",\n badge(ctx) {\n const cat = ctx.getCatalog();\n if (!cat) return undefined;\n const n = cat.componentNames.length + cat.actionNames.length;\n return n || undefined;\n },\n mount(root, ctx) {\n return mountCatalogTab(root, ctx);\n },\n };\n}\n\nfunction mountCatalogTab(root: HTMLElement, ctx: PanelContext): TabInstance {\n const container = h(\"div\", {\n style: { height: \"100%\", display: \"flex\", flexDirection: \"column\" },\n });\n const toolbar = h(\"div\", { className: \"jr-toolbar\" });\n const body = h(\"div\", {\n style: { overflow: \"auto\", flex: \"1\", minHeight: \"0\" },\n });\n container.appendChild(toolbar);\n container.appendChild(body);\n root.appendChild(container);\n\n let view: \"components\" | \"actions\" = \"components\";\n let filter = \"\";\n\n // Toolbar controls are mounted once so their DOM identity (and thus the\n // search input's focus + caret position) survives every re-render —\n // without this, typing into the filter would lose focus after each key.\n const componentsBtn = h(\n \"button\",\n {\n className: \"jr-icon-btn\",\n \"data-active\": \"true\",\n onClick: () => {\n if (view === \"components\") return;\n view = \"components\";\n updateToolbarChrome();\n renderBody();\n },\n },\n \"components\",\n );\n const actionsBtn = h(\n \"button\",\n {\n className: \"jr-icon-btn\",\n \"data-active\": \"false\",\n onClick: () => {\n if (view === \"actions\") return;\n view = \"actions\";\n updateToolbarChrome();\n renderBody();\n },\n },\n \"actions\",\n );\n const searchInput = h(\"input\", {\n className: \"jr-search\",\n type: \"text\",\n placeholder: \"Filter by name\\u2026\",\n onInput: (ev: Event) => {\n filter = ((ev.target as HTMLInputElement).value || \"\").toLowerCase();\n renderBody();\n },\n }) as HTMLInputElement;\n toolbar.append(componentsBtn, actionsBtn, searchInput);\n\n function updateToolbarChrome() {\n const catalog = ctx.getCatalog();\n const display = catalog ? buildCatalogDisplayData(catalog.data) : null;\n const cCount = display?.components.length ?? 0;\n const aCount = display?.actions.length ?? 0;\n componentsBtn.textContent = `components (${cCount})`;\n actionsBtn.textContent = `actions (${aCount})`;\n componentsBtn.dataset.active = String(view === \"components\");\n actionsBtn.dataset.active = String(view === \"actions\");\n }\n\n function renderBody() {\n const catalog = ctx.getCatalog();\n if (!catalog) {\n replaceChildren(\n body,\n h(\n \"div\",\n { className: \"jr-empty\" },\n \"No catalog attached. Pass `catalog` to `<JsonRenderDevtools>` to browse it here.\",\n ),\n );\n return;\n }\n\n const display = buildCatalogDisplayData(catalog.data);\n if (view === \"components\") {\n const items = display.components.filter(\n (c) => !filter || c.name.toLowerCase().includes(filter),\n );\n if (items.length === 0) {\n replaceChildren(\n body,\n h(\"div\", { className: \"jr-empty\" }, \"No components match.\"),\n );\n return;\n }\n replaceChildren(body, items.map(renderComponent));\n } else {\n const items = display.actions.filter(\n (a) => !filter || a.name.toLowerCase().includes(filter),\n );\n if (items.length === 0) {\n replaceChildren(\n body,\n h(\"div\", { className: \"jr-empty\" }, \"No actions match.\"),\n );\n return;\n }\n replaceChildren(body, items.map(renderAction));\n }\n }\n\n function render() {\n updateToolbarChrome();\n renderBody();\n }\n\n render();\n return { update: render };\n}\n\nfunction renderComponent(c: CatalogComponentInfo): HTMLElement {\n return h(\n \"div\",\n { className: \"jr-catalog-item\" },\n h(\"div\", { className: \"jr-catalog-name\" }, c.name),\n c.description\n ? h(\"div\", { className: \"jr-catalog-desc\" }, c.description)\n : null,\n c.props.length > 0 || c.events.length > 0\n ? h(\n \"div\",\n { className: \"jr-chips\" },\n ...c.props.map((p) =>\n h(\n \"span\",\n { className: \"jr-chip\", \"data-tone\": \"prop\" },\n `${p.name}: ${p.type}`,\n ),\n ),\n ...c.events.map((e) =>\n h(\n \"span\",\n { className: \"jr-chip\", \"data-tone\": \"event\" },\n `on.${e}`,\n ),\n ),\n )\n : null,\n );\n}\n\nfunction renderAction(a: CatalogActionInfo): HTMLElement {\n return h(\n \"div\",\n { className: \"jr-catalog-item\" },\n h(\"div\", { className: \"jr-catalog-name\" }, a.name),\n a.description\n ? h(\"div\", { className: \"jr-catalog-desc\" }, a.description)\n : null,\n a.params.length > 0\n ? h(\n \"div\",\n { className: \"jr-chips\" },\n ...a.params.map((p) =>\n h(\n \"span\",\n { className: \"jr-chip\", \"data-tone\": \"param\" },\n `${p.name}: ${p.type}`,\n ),\n ),\n )\n : null,\n );\n}\n\n/**\n * Extract display data from a raw catalog definition. Handles both Zod v3\n * (`_def.shape()`) and v4 (`shape` getter). Resilient to missing fields.\n *\n * Same logic as `apps/web/lib/render/catalog-display.ts` but lives here\n * so framework adapters don't depend on the web app.\n */\nexport function buildCatalogDisplayData(rawCatalogData: unknown): {\n components: CatalogComponentInfo[];\n actions: CatalogActionInfo[];\n} {\n const raw = (rawCatalogData ?? {}) as Record<string, unknown>;\n const componentsRaw = (raw.components ?? {}) as Record<string, unknown>;\n const actionsRaw = (raw.actions ?? {}) as Record<string, unknown>;\n\n const components: CatalogComponentInfo[] = Object.entries(componentsRaw)\n .map(([name, def]) => {\n const d = (def ?? {}) as Record<string, unknown>;\n return {\n name,\n description: (d.description as string) ?? \"\",\n props: extractFields(d.props),\n slots: Array.isArray(d.slots) ? (d.slots as string[]) : [],\n events: Array.isArray(d.events) ? (d.events as string[]) : [],\n };\n })\n .sort((a, b) => a.name.localeCompare(b.name));\n\n const actions: CatalogActionInfo[] = Object.entries(actionsRaw)\n .map(([name, def]) => {\n const d = (def ?? {}) as Record<string, unknown>;\n return {\n name,\n description: (d.description as string) ?? \"\",\n params: extractFields(d.params),\n };\n })\n .sort((a, b) => a.name.localeCompare(b.name));\n\n return { components, actions };\n}\n\nfunction extractFields(zodObj: unknown): CatalogField[] {\n if (!zodObj) return [];\n try {\n const obj = zodObj as Record<string, unknown>;\n const shape =\n typeof obj.shape === \"object\" && obj.shape !== null\n ? (obj.shape as Record<string, unknown>)\n : typeof (obj as { _def?: { shape?: unknown } })._def?.shape ===\n \"function\"\n ? (\n obj as { _def: { shape: () => Record<string, unknown> } }\n )._def.shape()\n : typeof (obj as { _def?: { shape?: unknown } })._def?.shape ===\n \"object\"\n ? (obj as { _def: { shape: Record<string, unknown> } })._def.shape\n : null;\n if (!shape) return [];\n\n return Object.entries(shape).map(([name, schema]) => {\n let type = \"unknown\";\n try {\n const s = schema as {\n _zod?: {\n def?: { type?: string; values?: unknown[]; innerType?: unknown };\n };\n _def?: { typeName?: string; values?: unknown[]; innerType?: unknown };\n };\n const typeName: string = s?._zod?.def?.type ?? s?._def?.typeName ?? \"\";\n if (typeName.includes(\"string\")) type = \"string\";\n else if (typeName.includes(\"number\")) type = \"number\";\n else if (typeName.includes(\"boolean\")) type = \"boolean\";\n else if (typeName.includes(\"array\")) type = \"array\";\n else if (typeName.includes(\"enum\")) {\n const values = s?._zod?.def?.values ?? s?._def?.values;\n type = Array.isArray(values) ? values.join(\" | \") : \"enum\";\n } else if (typeName.includes(\"union\")) type = \"union\";\n else if (typeName.includes(\"nullable\")) {\n const inner = (s?._zod?.def?.innerType ?? s?._def?.innerType) as\n | {\n _zod?: { def?: { type?: string; values?: unknown[] } };\n _def?: { typeName?: string; values?: unknown[] };\n }\n | undefined;\n const innerName: string =\n inner?._zod?.def?.type ?? inner?._def?.typeName ?? \"\";\n if (innerName.includes(\"string\")) type = \"string?\";\n else if (innerName.includes(\"number\")) type = \"number?\";\n else if (innerName.includes(\"boolean\")) type = \"boolean?\";\n else if (innerName.includes(\"array\")) type = \"array?\";\n else if (innerName.includes(\"enum\")) {\n const values = inner?._zod?.def?.values ?? inner?._def?.values;\n type = Array.isArray(values) ? `(${values.join(\" | \")})?` : \"enum?\";\n } else type = \"optional\";\n }\n } catch {\n // ignore\n }\n return { name, type };\n });\n } catch {\n return [];\n }\n}\n","import { h, replaceChildren } from \"../dom\";\nimport { findElementByKey } from \"../../picker\";\nimport type { PanelContext, TabDef, TabInstance } from \"../types\";\n\nconst TAB_ID = \"pick\";\n\n/**\n * Picker tab — explains the DOM picker flow, starts / stops a picker\n * session, and shows the currently selected element key. Selecting a key\n * in the spec tab reflects here; selecting here (via click-to-pick)\n * jumps back to the spec tab.\n */\nexport function pickerTab(): TabDef {\n return {\n id: TAB_ID,\n label: \"Pick\",\n mount(root, ctx) {\n return mountPickerTab(root, ctx);\n },\n };\n}\n\nfunction mountPickerTab(root: HTMLElement, ctx: PanelContext): TabInstance {\n let active = false;\n let stopFn: (() => void) | null = null;\n\n const body = h(\"div\", { style: { padding: \"16px 12px\" } });\n root.appendChild(body);\n\n const unsubSelection = ctx.selection.subscribe(() => render());\n\n function start() {\n if (active) return;\n const session = ctx.startPicker?.({\n onPick: (key) => {\n active = false;\n stopFn = null;\n ctx.selection.set(key);\n ctx.activateTab(\"spec\");\n },\n onCancel: () => {\n active = false;\n stopFn = null;\n render();\n },\n });\n if (!session) {\n render();\n return;\n }\n stopFn = session.stop;\n active = true;\n render();\n }\n\n function stop() {\n if (stopFn) stopFn();\n stopFn = null;\n active = false;\n render();\n }\n\n function render() {\n const selected = ctx.selection.get();\n const canPick = typeof document !== \"undefined\";\n const selectedMounted = selected ? !!findElementByKey(selected) : false;\n\n replaceChildren(\n body,\n h(\n \"div\",\n { style: { marginBottom: \"12px\", color: \"var(--jr-fg-muted)\" } },\n \"Click in the page to pick an element. Hovering paints an outline.\",\n ),\n h(\n \"button\",\n {\n className: \"jr-icon-btn\",\n style: {\n padding: \"6px 12px\",\n width: \"auto\",\n border: \"1px solid var(--jr-border)\",\n borderRadius: \"6px\",\n },\n disabled: !canPick,\n \"data-active\": String(active),\n onClick: () => (active ? stop() : start()),\n },\n active ? \"Stop picking (Esc)\" : \"Start picking\",\n ),\n h(\n \"div\",\n { style: { marginTop: \"18px\" } },\n h(\n \"h4\",\n {\n style: {\n margin: \"0 0 6px 0\",\n fontSize: \"10px\",\n color: \"var(--jr-fg-dim)\",\n textTransform: \"uppercase\",\n letterSpacing: \"0.06em\",\n },\n },\n \"Current selection\",\n ),\n selected\n ? h(\n \"div\",\n {\n className: \"jr-badge\",\n style: { padding: \"4px 8px\", fontSize: \"11px\" },\n },\n `#${selected}`,\n )\n : h(\n \"div\",\n { style: { color: \"var(--jr-fg-dim)\", fontSize: \"11px\" } },\n \"No selection\",\n ),\n selected && !selectedMounted\n ? h(\n \"div\",\n {\n style: {\n marginTop: \"6px\",\n color: \"var(--jr-amber)\",\n fontSize: \"10px\",\n },\n },\n \"This element has no DOM node right now (hidden by visibility, or renderer not wrapping for picker).\",\n )\n : null,\n ),\n !canPick\n ? h(\n \"div\",\n {\n style: {\n marginTop: \"18px\",\n color: \"var(--jr-fg-dim)\",\n fontSize: \"11px\",\n },\n },\n \"Picker requires a DOM environment.\",\n )\n : null,\n );\n }\n\n render();\n return {\n update: render,\n destroy() {\n stop();\n unsubSelection();\n },\n };\n}\n","import {\n SPEC_DATA_PART_TYPE,\n applySpecPatch,\n nestedToFlat,\n type Spec,\n type SpecDataPart,\n type StreamChunk,\n} from \"@json-render/core\";\nimport type { EventStore } from \"./event-store\";\nimport type { DevtoolsEvent, TokenUsage } from \"./types\";\n\n/**\n * A minimal shape compatible with AI SDK `UIMessage.parts[i]`. Defined\n * locally so the devtools package has no dependency on the `ai` package.\n */\ninterface DataPart {\n type: string;\n text?: string;\n data?: unknown;\n state?: string;\n}\n\n/**\n * Wrap a `ReadableStream<StreamChunk>` (e.g. the output of `pipeJsonRender`\n * or any `TransformStream<StreamChunk, StreamChunk>`) so spec patches are\n * mirrored into a devtools `EventStore` as they fly past.\n *\n * Returns the original stream unchanged — the tap just forks a copy.\n *\n * @example\n * ```ts\n * writer.merge(\n * tapJsonRenderStream(\n * pipeJsonRender(result.toUIMessageStream()),\n * devtoolsEventStore,\n * ),\n * );\n * ```\n */\nexport function tapJsonRenderStream(\n stream: ReadableStream<StreamChunk>,\n events: EventStore,\n): ReadableStream<StreamChunk> {\n const [a, b] = stream.tee();\n void consumeToEvents(b, events, \"json\");\n return a;\n}\n\n/** YAML variant — identical behaviour with `source: \"yaml\"`. */\nexport function tapYamlStream(\n stream: ReadableStream<StreamChunk>,\n events: EventStore,\n): ReadableStream<StreamChunk> {\n const [a, b] = stream.tee();\n void consumeToEvents(b, events, \"yaml\");\n return a;\n}\n\nasync function consumeToEvents(\n stream: ReadableStream<StreamChunk>,\n events: EventStore,\n source: \"json\" | \"yaml\",\n): Promise<void> {\n events.push({ kind: \"stream-lifecycle\", at: Date.now(), phase: \"start\" });\n let ok = true;\n try {\n const reader = stream.getReader();\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (!value) continue;\n forwardChunk(value, events, source);\n }\n } catch (err) {\n ok = false;\n events.push({\n kind: \"stream-text\",\n at: Date.now(),\n text: `[stream error: ${String(err)}]`,\n });\n } finally {\n events.push({\n kind: \"stream-lifecycle\",\n at: Date.now(),\n phase: \"end\",\n ok,\n });\n }\n}\n\nfunction forwardChunk(\n chunk: StreamChunk,\n events: EventStore,\n source: \"json\" | \"yaml\",\n) {\n if (chunk.type === SPEC_DATA_PART_TYPE) {\n const data = (chunk as { data?: SpecDataPart }).data;\n if (!data) return;\n if (data.type === \"patch\") {\n events.push({\n kind: \"stream-patch\",\n at: Date.now(),\n patch: data.patch,\n source,\n });\n }\n return;\n }\n if (chunk.type === \"text-delta\") {\n const delta = (chunk as { delta?: string }).delta ?? \"\";\n if (delta) {\n events.push({ kind: \"stream-text\", at: Date.now(), text: delta });\n }\n }\n}\n\n/**\n * Client-side helper: scan a message's `parts` array for spec data parts\n * and push matching events into the store. Use this when rendering chat\n * UIs that use `@ai-sdk/react` `useChat` and pass in `messages`.\n *\n * Idempotent via `seenIds`: only parts not already recorded will emit.\n * Returns the new `seenIds` set so callers can persist it between calls.\n */\nexport function scanMessageParts(\n parts: readonly DataPart[] | undefined,\n events: EventStore,\n seen: WeakSet<object>,\n): void {\n if (!parts) return;\n for (const part of parts) {\n if (!part || typeof part !== \"object\") continue;\n if (seen.has(part)) continue;\n seen.add(part);\n if (part.type === SPEC_DATA_PART_TYPE) {\n const data = part.data as SpecDataPart | undefined;\n if (!data) continue;\n if (data.type === \"patch\") {\n events.push({\n kind: \"stream-patch\",\n at: Date.now(),\n patch: data.patch,\n source: \"json\",\n });\n }\n }\n }\n}\n\n/**\n * Emit a token-usage event. Called by adapters with whatever usage\n * object their framework surfaces (AI SDK `result.usage`).\n */\nexport function recordUsage(events: EventStore, usage: TokenUsage): void {\n events.push({ kind: \"stream-usage\", at: Date.now(), usage });\n}\n\n/**\n * Replay every `SPEC_DATA_PART` in `parts` and return the resulting spec,\n * or `null` if the message has no UI. Mirrors the framework-side\n * `buildSpecFromParts` helper but without a framework dependency — used by\n * the devtools panel's generation switcher to reconstruct each prior\n * assistant message's spec so the user can inspect any of them.\n */\nexport function extractSpecFromParts(\n parts: readonly DataPart[] | undefined,\n): Spec | null {\n if (!parts) return null;\n const spec: Spec = { root: \"\", elements: {} };\n let hasSpec = false;\n for (const part of parts) {\n if (!part || typeof part !== \"object\") continue;\n if (part.type !== SPEC_DATA_PART_TYPE) continue;\n const data = part.data as SpecDataPart | undefined;\n if (!data) continue;\n if (data.type === \"patch\") {\n hasSpec = true;\n applySpecPatch(spec, data.patch);\n } else if (data.type === \"flat\") {\n hasSpec = true;\n Object.assign(spec, data.spec);\n } else if (data.type === \"nested\") {\n hasSpec = true;\n Object.assign(spec, nestedToFlat(data.spec));\n }\n }\n return hasSpec ? spec : null;\n}\n\n/** Emit a pre-built devtools event. Useful for manual instrumentation. */\nexport function recordEvent(events: EventStore, event: DevtoolsEvent): void {\n events.push(event);\n}\n"],"mappings":"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A;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmrBlB,IAAM,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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","names":["el","TAB_ID","TAB_ID","TAB_ID","TAB_ID","TAB_ID"]}
|