@elabs-ai/components-editor 4.2.0 → 5.0.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/lib/editor-completions-monaco.ts","../../src/markdown-editor/slash/monaco-slash-menu.tsx","../../src/markdown-toolbar/markdown-commands.ts","../../src/markdown-workspace/markdown-workspace.tsx","../../src/calc-block/calc-editor-monaco.ts","../../src/lib/markdown/diff.ts","../../src/lib/markdown/merge.ts","../../src/markdown-editor/slash/source-slash-trigger.ts","../../src/markdown-editor/slash/shortcut-monaco.ts","../../src/markdown-preview/markdown-preview.tsx","../../src/lib/markdown/directives.ts","../../src/calc-block/calc-block.tsx","../../src/calc-block/calc-inline.tsx","../../src/mermaid-diagram/mermaid-diagram.tsx","../../src/mermaid-diagram/mermaid-viewer.tsx","../../src/mermaid-diagram/remediate.ts","../../src/prose/prose.tsx","../../src/timeline/index.ts","../../src/markdown-preview/code-fence.tsx","../../src/markdown-academic/citations.tsx","../../src/markdown-academic/footnotes.tsx","../../src/markdown-academic/math.tsx","../../src/markdown-academic/toc.tsx","../../src/markdown-iteration/directive.tsx","../../src/markdown-toolbar/markdown-toolbar.tsx","../../src/markdown-workspace/focus-writing.ts","../../src/markdown/parse.ts","../../src/mermaid-workspace/mermaid-workspace.tsx","../../src/ai-objects/decision-card.tsx","../../src/ai-objects/entity.tsx","../../src/ai-objects/knowledge-card.tsx","../../src/ai-objects/directives.ts","../../src/markdown-iteration/template-dialog.tsx","../../src/markdown-iteration/iteration-builder-dialog.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * Monaco registration lifecycle for the declarative completion-provider API\n * (#283) — the engine that backs the `completions` prop on `MarkdownWorkspace`.\n *\n * `monaco.languages.registerCompletionItemProvider` is GLOBAL PER LANGUAGE, not\n * per editor instance (the root cause #283 exists to fix — see the issue). So\n * this module owns a single, REFCOUNTED registration for the \"markdown\"\n * language: the first `attachCompletionsMonaco` call registers it, each\n * subsequent call (a second mounted `MarkdownWorkspace`) bumps the refcount,\n * and the registration is disposed ONLY when the LAST attached editor's\n * disposer runs — no leak, no double-registration (#283 acceptance).\n *\n * Suggestions are scoped to the models THIS module attached (a `REGISTRY` keyed\n * by `ITextModel`) — any other \"markdown\" model in the app (one the host built\n * itself, outside `@elabs-ai/components-editor`) is ignored, never suggested into.\n *\n * `getProviders` is read fresh from the registry on every `provideCompletionItems`\n * call — NOT captured as a closure at registration time — so a rebuilt provider\n * list (a new `completions` array identity from React state/props) is picked up\n * WITHOUT re-registering (#283 acceptance). Mirrors the calc layer's\n * `REGISTRY`/`getHooks` pattern in `calc-block/calc-editor-monaco.ts`.\n */\nimport * as monaco from \"monaco-editor\";\n\nimport {\n collectCompletions,\n resolveReplaceRange,\n type EditorCompletionProvider,\n} from \"./editor-completions\";\n\n/** Resolver of the latest provider list for a model (read fresh on every call). */\ntype ProvidersGetter = () => EditorCompletionProvider[] | undefined;\n\n/** Per-model provider registry — scopes suggestions to OUR editor instances. */\nconst REGISTRY = new Map<monaco.editor.ITextModel, ProvidersGetter>();\n\nlet refCount = 0;\nlet registration: monaco.IDisposable | null = null;\n\n/** Register the \"markdown\" completion provider once (idempotent while refs > 0). */\nfunction ensureRegistered(): void {\n if (registration) return;\n registration = monaco.languages.registerCompletionItemProvider(\"markdown\", {\n provideCompletionItems(model, position) {\n const getProviders = REGISTRY.get(model);\n if (!getProviders) return { suggestions: [] };\n const providers = getProviders();\n if (!providers || providers.length === 0) return { suggestions: [] };\n const lineText = model.getLineContent(position.lineNumber);\n const ctx = {\n source: model.getValue(),\n line: position.lineNumber,\n column: position.column,\n lineText,\n };\n return collectCompletions(providers, ctx).then((matches) => ({\n suggestions: matches.map(({ provider, item }) => ({\n label: item.label,\n kind: monaco.languages.CompletionItemKind.Text,\n insertText: item.insertText,\n detail: item.detail,\n range: resolveReplaceRange(item, position, lineText, provider.triggerCharacters),\n })),\n }));\n },\n });\n}\n\n/**\n * Attach the declarative completion providers to a Monaco editor instance.\n * `getProviders` is read live on every suggestion request (see module doc) —\n * pass a ref-backed getter so a fresh `completions` array identity on every\n * render never forces a re-attach.\n *\n * Also force-opens Monaco's native suggest widget (`editor.action.triggerSuggest`)\n * whenever the user types a character matching one of the CURRENTLY-configured\n * providers' `triggerCharacters` — read live, so changing that set never needs a\n * re-registration either. Markdown punctuation like `[` doesn't extend a \"word\",\n * so without this Monaco's own quick-suggestions heuristic would never invoke a\n * provider on it.\n *\n * Returns a disposer. Call it on unmount / when `completions` is removed —\n * refcounted, so the GLOBAL \"markdown\" registration is only torn down once the\n * LAST attached editor calls its disposer (#283 acceptance: no leak, no\n * double-registration with two workspaces mounted).\n */\nexport function attachCompletionsMonaco(\n editor: monaco.editor.IStandaloneCodeEditor,\n getProviders: ProvidersGetter,\n): () => void {\n ensureRegistered();\n refCount++;\n\n let model = editor.getModel();\n if (model) REGISTRY.set(model, getProviders);\n\n const contentSub = editor.onDidChangeModelContent((e) => {\n const providers = getProviders();\n if (!providers || providers.length === 0) return;\n for (const change of e.changes) {\n if (change.text.length !== 1) continue;\n if (providers.some((p) => p.triggerCharacters?.includes(change.text))) {\n editor.trigger(\"brand-completions\", \"editor.action.triggerSuggest\", {});\n return;\n }\n }\n });\n\n const modelSub = editor.onDidChangeModel(() => {\n if (model) REGISTRY.delete(model);\n model = editor.getModel();\n if (model) REGISTRY.set(model, getProviders);\n });\n\n return () => {\n contentSub.dispose();\n modelSub.dispose();\n if (model) REGISTRY.delete(model);\n refCount = Math.max(0, refCount - 1);\n if (refCount === 0) {\n registration?.dispose();\n registration = null;\n }\n };\n}\n","\"use client\";\n\n/**\n * MonacoSlashMenu — a caret-anchored slash command popup for the Monaco source\n * pane (#271).\n *\n * The workspace owns the open/closed state (via a `CodeEditor` action keybinding\n * registered through `CodeEditor.actions`). This component is the POSITIONING\n * CONTROLLER + KEYBOARD HANDLER that wraps the shared `SlashMenu` body — it does\n * NOT re-implement the listbox (no duplication, tokens only, same look as the\n * WYSIWYG widget).\n *\n * a11y: the `SlashMenu` already provides `role=\"listbox\"` / `role=\"option\"` /\n * `aria-selected`; this wrapper wires `aria-activedescendant` on the editor's\n * textarea so AT can follow the active row. Esc closes and refocuses the editor.\n */\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport type { IRange } from \"monaco-editor\";\nimport { useEffect, useRef, useState } from \"react\";\n\nimport type { MonacoCodeEditor } from \"../../code-editor\";\nimport { monacoContentAccess } from \"../../lib/editor-content-access\";\nimport { insertDirective } from \"../../markdown-toolbar/markdown-commands\";\nimport { filterSlashCommands, type SlashCommand } from \"./brand-slash-commands\";\nimport { SlashMenu, slashOptionId } from \"./slash-menu\";\n\nexport interface MonacoSlashMenuProps {\n /** The live Monaco editor instance (source pane). */\n editor: MonacoCodeEditor;\n /**\n * Commands to show in the source pane — filtered by the workspace to\n * `snippet != null || typeof runInSource === \"function\"` (#299): a command\n * needs a text snippet, a source-pane handler, or both to appear here (a\n * run-only WYSIWYG command with neither is Milkdown-only and stays excluded).\n */\n commands: SlashCommand[];\n /** Controlled open state — the workspace toggles it via the Layer-1 action. */\n open: boolean;\n onOpenChange: (open: boolean) => void;\n /**\n * Insert the selected snippet at the Monaco caret + refocus.\n * Defaults to `insertDirective` from `markdown-commands.ts`.\n */\n onInsert?: (editor: MonacoCodeEditor, snippet: string) => void;\n /**\n * When the menu was opened by typing `/` (not the hotkey), the model range of\n * that `/`. On select the `/` is REPLACED by the inserted block; on cancel\n * (Escape / Backspace past the trigger) it is removed. `null`/omitted = the\n * hotkey path, which inserts via `onInsert`/`insertDirective` and leaves the\n * document otherwise untouched.\n */\n triggerRange?: IRange | null;\n /** Merged onto the positioned popup container (the inline `position:fixed` anchor stays). */\n className?: string;\n}\n\nconst ID_PREFIX = \"brand-monaco-slash\";\nconst LISTBOX_ID = `${ID_PREFIX}-listbox`;\n\n/** Fixed/absolute coords of the popup anchor. */\ninterface Coords {\n top: number;\n left: number;\n}\n\nfunction getCaretCoords(editor: MonacoCodeEditor): Coords | null {\n const pos = editor.getPosition();\n if (!pos) return null;\n const scrolled = editor.getScrolledVisiblePosition(pos);\n if (!scrolled) return null;\n const domNode = editor.getDomNode();\n if (!domNode) return null;\n const rect = domNode.getBoundingClientRect();\n return {\n top: rect.top + scrolled.top + (scrolled.height ?? 20),\n left: rect.left + scrolled.left,\n };\n}\n\nexport function MonacoSlashMenu({\n editor,\n commands,\n open,\n onOpenChange,\n onInsert,\n triggerRange,\n className,\n}: MonacoSlashMenuProps) {\n const [query, setQuery] = useState(\"\");\n const [activeIndex, setActiveIndex] = useState(0);\n const [coords, setCoords] = useState<Coords | null>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n\n // Insert the chosen snippet. Typed-`/` mode REPLACES the `/` (triggerRange) with\n // the block; hotkey mode inserts via insertDirective at the caret/line. Always\n // refocus the editor and close.\n const commitSnippet = (snippet: string) => {\n if (triggerRange) {\n editor.executeEdits(\"brand-slash-typed\", [\n { range: triggerRange, text: snippet, forceMoveMarkers: true },\n ]);\n } else {\n (onInsert ?? insertDirective)(editor, snippet);\n }\n onOpenChange(false);\n editor.focus();\n };\n\n // Run a source-pane handler (#299): strip the typed `/query` trigger FIRST\n // (the same edit `cancel` uses, so the doc is clean whether the handler\n // opens a dialog, schedules async work, or inserts nothing), then call it\n // with the live editor + the (now-stale) trigger range + content access.\n const commitRunInSource = (command: SlashCommand) => {\n if (triggerRange) {\n editor.executeEdits(\"brand-slash-typed\", [{ range: triggerRange, text: \"\" }]);\n }\n command.runInSource?.({\n editor,\n range: triggerRange ?? null,\n content: monacoContentAccess(editor),\n });\n onOpenChange(false);\n editor.focus();\n };\n\n // Select a command: `runInSource` (when present) wins over `snippet` — it's\n // the more capable handler and is the ONLY option for a run-only command.\n const selectCommand = (command: SlashCommand) => {\n if (typeof command.runInSource === \"function\") {\n commitRunInSource(command);\n } else if (command.snippet) {\n commitSnippet(command.snippet);\n }\n };\n\n // Dismiss without inserting. In typed-`/` mode the stray `/` is removed so the\n // document is left exactly as it was before the trigger.\n const cancel = () => {\n if (triggerRange) {\n editor.executeEdits(\"brand-slash-cancel\", [{ range: triggerRange, text: \"\" }]);\n }\n onOpenChange(false);\n editor.focus();\n };\n\n // Latest select/cancel via refs so the capture-phase keydown listener can stay\n // attached across renders (its effect deps don't need these closures).\n const selectRef = useRef(selectCommand);\n selectRef.current = selectCommand;\n const cancelRef = useRef(cancel);\n cancelRef.current = cancel;\n\n // Reset query + active index whenever the menu opens.\n useEffect(() => {\n if (open) {\n setQuery(\"\");\n setActiveIndex(0);\n }\n }, [open]);\n\n // Compute and track caret position.\n useEffect(() => {\n if (!open) return;\n\n const update = () => {\n setCoords(getCaretCoords(editor));\n };\n\n update();\n\n const scrollSub = editor.onDidScrollChange(update);\n const cursorSub = editor.onDidChangeCursorPosition(update);\n\n const onResize = () => update();\n window.addEventListener(\"resize\", onResize);\n\n return () => {\n scrollSub.dispose();\n cursorSub.dispose();\n window.removeEventListener(\"resize\", onResize);\n };\n }, [open, editor]);\n\n // Close on editor blur.\n useEffect(() => {\n if (!open) return;\n const blurSub = editor.onDidBlurEditorText(() => {\n // Small delay — if focus moved to the menu itself (mousedown), don't close.\n setTimeout(() => {\n if (!menuRef.current?.contains(document.activeElement)) {\n onOpenChange(false);\n }\n }, 100);\n });\n return () => blurSub.dispose();\n }, [open, editor, onOpenChange]);\n\n // Wire keyboard navigation into the editor while the menu is open.\n useEffect(() => {\n if (!open) return;\n\n const keydown = (e: KeyboardEvent) => {\n const filtered = filterSlashCommands(commands, query);\n\n if (e.key === \"Escape\") {\n e.preventDefault();\n e.stopPropagation();\n cancelRef.current();\n return;\n }\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n e.stopPropagation();\n setActiveIndex((i) => (i + 1) % Math.max(filtered.length, 1));\n return;\n }\n if (e.key === \"ArrowUp\") {\n e.preventDefault();\n e.stopPropagation();\n setActiveIndex(\n (i) => (i - 1 + Math.max(filtered.length, 1)) % Math.max(filtered.length, 1),\n );\n return;\n }\n // Enter AND Tab select the active command (the cmdk / Notion command-menu\n // convention) — kept identical to the WYSIWYG slash menu so the cross-pane\n // shortcut behaves the same in both panes (the goal of #271). Tab does NOT\n // move browser focus here by design; Esc dismisses without inserting.\n if (e.key === \"Enter\" || e.key === \"Tab\") {\n // Always swallow while the popup is open — even with no match — so the key\n // never leaks a newline/tab into the document behind the popup.\n e.preventDefault();\n e.stopPropagation();\n const command = filtered[Math.min(activeIndex, filtered.length - 1)];\n if (command) selectRef.current(command);\n return;\n }\n // Printable characters update the query — intercept so they filter the\n // menu instead of being typed into the Monaco document (the menu was\n // opened by shortcut, so there is no `/query` run in the doc to absorb them).\n if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {\n e.preventDefault();\n e.stopPropagation();\n setQuery((q) => q + e.key);\n setActiveIndex(0);\n return;\n }\n // Backspace trims the query (and closes when empty) — intercept so it\n // never deletes document text behind the popup.\n if (e.key === \"Backspace\") {\n e.preventDefault();\n e.stopPropagation();\n if (query.length === 0) {\n // Backspacing past the trigger dismisses (and removes the typed `/`).\n cancelRef.current();\n return;\n }\n setQuery((q) => q.slice(0, -1));\n setActiveIndex(0);\n }\n };\n\n // Capture phase — intercept before Monaco's own key handlers.\n const domNode = editor.getDomNode();\n domNode?.addEventListener(\"keydown\", keydown, true);\n return () => domNode?.removeEventListener(\"keydown\", keydown, true);\n }, [open, editor, commands, query, activeIndex]);\n\n // Keep the highlighted option scrolled into view as ↑/↓ moves it — the listbox\n // is overflow-y-auto, so without this the active row can move off-screen while\n // the keyboard selection advances (the same fix slash-widget.tsx applies).\n useEffect(() => {\n if (!open) return;\n const filtered = filterSlashCommands(commands, query);\n const active = filtered[Math.min(activeIndex, Math.max(filtered.length - 1, 0))];\n if (!active) return;\n const el = menuRef.current?.querySelector<HTMLElement>(\n `#${CSS.escape(slashOptionId(ID_PREFIX, active.id))}`,\n );\n el?.scrollIntoView({ block: \"nearest\" });\n }, [open, commands, query, activeIndex]);\n\n // Mirror the listbox relationship onto the Monaco textbox while open, so AT is\n // told a popup appeared (aria-expanded), where it is (aria-controls), and which\n // option is active (aria-activedescendant) — the same wiring the WYSIWYG path\n // applies in slash-widget.tsx. All three are cleaned up on close.\n useEffect(() => {\n if (!open) return;\n const filtered = filterSlashCommands(commands, query);\n const activeCommand = filtered[Math.min(activeIndex, Math.max(filtered.length - 1, 0))];\n const textarea = editor.getDomNode()?.querySelector(\"textarea\");\n if (!textarea) return;\n textarea.setAttribute(\"aria-expanded\", \"true\");\n textarea.setAttribute(\"aria-controls\", LISTBOX_ID);\n if (activeCommand) {\n textarea.setAttribute(\"aria-activedescendant\", slashOptionId(ID_PREFIX, activeCommand.id));\n } else {\n textarea.removeAttribute(\"aria-activedescendant\");\n }\n return () => {\n textarea.removeAttribute(\"aria-expanded\");\n textarea.removeAttribute(\"aria-controls\");\n textarea.removeAttribute(\"aria-activedescendant\");\n };\n }, [open, editor, commands, query, activeIndex]);\n\n if (!open || !coords) return null;\n\n const filtered = filterSlashCommands(commands, query);\n const activeCommand = filtered[Math.min(activeIndex, Math.max(filtered.length - 1, 0))];\n\n const handleSelect = (command: SlashCommand) => {\n selectCommand(command);\n };\n\n const resultCount = filtered.length;\n const statusText =\n resultCount === 0\n ? \"No matching blocks\"\n : query\n ? `${resultCount} result${resultCount === 1 ? \"\" : \"s\"} for “${query}”`\n : `${resultCount} block${resultCount === 1 ? \"\" : \"s\"}`;\n\n return (\n <div\n ref={menuRef}\n className={cn(className)}\n // Fixed positioning so it overlays the editor regardless of scroll.\n style={{ position: \"fixed\", top: coords.top, left: coords.left, zIndex: 50 }}\n // Prevent the mousedown from stealing focus from the editor.\n onMouseDown={(e) => e.preventDefault()}\n >\n {/* One polite live region — focus stays in the editor, so AT learns the\n filter result count (and the empty state) only from here. The visual\n chip below is aria-hidden to avoid a double announcement. */}\n <span role=\"status\" aria-live=\"polite\" className=\"sr-only\">\n {statusText}\n </span>\n {query && (\n <div\n aria-hidden=\"true\"\n className=\"mb-0.5 rounded-sm border border-border bg-popover px-2 py-1 text-caption text-muted-foreground\"\n >\n Filter: <span className=\"font-medium text-foreground\">{query}</span>\n </div>\n )}\n <SlashMenu\n id={LISTBOX_ID}\n commands={filtered}\n activeId={activeCommand?.id}\n onSelect={handleSelect}\n idPrefix={ID_PREFIX}\n />\n </div>\n );\n}\n","/**\n * Markdown editing commands that operate on a Monaco editor instance (the source\n * pane). Pure functions over the editor — the toolbar UI wires buttons to these.\n */\nimport * as monaco from \"monaco-editor\";\n\nimport type { MonacoCodeEditor } from \"../code-editor\";\n\n/** Wrap the current selection (or insert a placeholder) with `before`/`after`. */\nexport function wrapSelection(\n editor: MonacoCodeEditor,\n before: string,\n after: string = before,\n placeholder = \"text\",\n): void {\n const model = editor.getModel();\n const selection = editor.getSelection();\n if (!model || !selection) return;\n\n const selected = model.getValueInRange(selection) || placeholder;\n editor.executeEdits(\"markdown-toolbar\", [\n { range: selection, text: `${before}${selected}${after}`, forceMoveMarkers: true },\n ]);\n // Re-select the inner text so the user can keep typing over the placeholder.\n const startCol = selection.startColumn + before.length;\n editor.setSelection(\n new monaco.Selection(\n selection.startLineNumber,\n startCol,\n selection.startLineNumber,\n startCol + selected.length,\n ),\n );\n editor.focus();\n}\n\n/** Toggle a line prefix (`# `, `> `, `- `, `1. `) on every selected line. */\nexport function toggleLinePrefix(editor: MonacoCodeEditor, prefix: string): void {\n const model = editor.getModel();\n const selection = editor.getSelection();\n if (!model || !selection) return;\n\n const edits: monaco.editor.IIdentifiedSingleEditOperation[] = [];\n const allPrefixed = (() => {\n for (let line = selection.startLineNumber; line <= selection.endLineNumber; line++) {\n if (!model.getLineContent(line).startsWith(prefix)) return false;\n }\n return true;\n })();\n\n for (let line = selection.startLineNumber; line <= selection.endLineNumber; line++) {\n const content = model.getLineContent(line);\n if (allPrefixed) {\n edits.push({\n range: new monaco.Range(line, 1, line, prefix.length + 1),\n text: \"\",\n });\n } else if (!content.startsWith(prefix)) {\n edits.push({ range: new monaco.Range(line, 1, line, 1), text: prefix });\n }\n }\n editor.executeEdits(\"markdown-toolbar\", edits);\n editor.focus();\n}\n\n/** Insert `[selection](url)` (or a placeholder link). */\nexport function insertLink(editor: MonacoCodeEditor): void {\n const model = editor.getModel();\n const selection = editor.getSelection();\n if (!model || !selection) return;\n const label = model.getValueInRange(selection) || \"label\";\n editor.executeEdits(\"markdown-toolbar\", [\n { range: selection, text: `[${label}](https://)`, forceMoveMarkers: true },\n ]);\n editor.focus();\n}\n\n/** Insert a horizontal rule on its own line below the cursor. */\nexport function insertHorizontalRule(editor: MonacoCodeEditor): void {\n const selection = editor.getSelection();\n if (!selection) return;\n const line = selection.endLineNumber;\n const col = editor.getModel()?.getLineMaxColumn(line) ?? 1;\n editor.executeEdits(\"markdown-toolbar\", [\n { range: new monaco.Range(line, col, line, col), text: `\\n\\n---\\n`, forceMoveMarkers: true },\n ]);\n editor.focus();\n}\n\n/** Insert a brand directive block at the cursor (e.g. card/callout/metric/timeline). */\nexport function insertDirective(editor: MonacoCodeEditor, snippet: string): void {\n const selection = editor.getSelection();\n if (!selection) return;\n const line = selection.endLineNumber;\n const col = editor.getModel()?.getLineMaxColumn(line) ?? 1;\n editor.executeEdits(\"markdown-toolbar\", [\n {\n range: new monaco.Range(line, col, line, col),\n text: `\\n\\n${snippet}\\n`,\n forceMoveMarkers: true,\n },\n ]);\n editor.focus();\n}\n","\"use client\";\n\n/**\n * MarkdownWorkspace — the hybrid markdown authoring surface for the Workbench.\n *\n * One markdown value, three modes (a @elabs-ai/components-ui ToggleGroup):\n * - \"source\" : Monaco CodeEditor(markdown) + the MarkdownToolbar\n * - \"wysiwyg\" : the Milkdown MarkdownEditor (direct manipulation)\n * - \"split\" : source ↔ the branded MarkdownPreview (drag-resizable)\n *\n * The value is shared across modes, so switching is lossless. Controlled\n * (`value`/`onChange`) or uncontrolled (`defaultValue`); same for `mode`.\n */\nimport {\n ResizableHandle,\n ResizablePanel,\n ResizablePanelGroup,\n Toggle,\n ToggleGroup,\n ToggleGroupItem,\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n useLocale,\n} from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { Columns2, Eye, Focus, SquareCode } from \"lucide-react\";\nimport {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type HTMLAttributes,\n type ReactNode,\n} from \"react\";\n\nimport { attachCalcMonaco } from \"../calc-block/calc-editor-monaco\";\nimport type { CalcEditorHooks } from \"../calc-block/types\";\nimport { CodeEditor, type EditorAction, type MonacoCodeEditor } from \"../code-editor\";\nimport { attachCompletionsMonaco } from \"../lib/editor-completions-monaco\";\nimport type { EditorCompletionProvider } from \"../lib/editor-completions\";\nimport {\n monacoContentAccess,\n type EditorContentAccess,\n type EditorSelection,\n} from \"../lib/editor-content-access\";\nimport { parseFrontmatter } from \"../lib/markdown/frontmatter\";\nimport { mergeNormalizedEdit } from \"../lib/markdown/merge\";\nimport { MarkdownEditor, type MarkdownEditorHandle, type EmbedAssetFn } from \"../markdown-editor\";\nimport { parseMarkdownOutline } from \"../markdown-outline\";\nimport { BRAND_SLASH_COMMANDS, type SlashCommand } from \"../markdown-editor/slash\";\n// MonacoSlashMenu + parseShortcut are imported from their files (NOT the slash\n// barrel), which pull the Monaco runtime — the workspace already does too. Keeps\n// the Milkdown-facing slash barrel Monaco-free. The pure `shortcut.ts` holds the\n// default; `shortcut-monaco.ts` holds the Monaco-keybinding parser.\nimport { MonacoSlashMenu } from \"../markdown-editor/slash/monaco-slash-menu\";\nimport {\n slashTriggerRange,\n type SlashTriggerRange,\n} from \"../markdown-editor/slash/source-slash-trigger\";\nimport { DEFAULT_SLASH_SHORTCUT } from \"../markdown-editor/slash/shortcut\";\nimport { parseShortcut } from \"../markdown-editor/slash/shortcut-monaco\";\nimport { MarkdownPreview } from \"../markdown-preview\";\nimport { MarkdownToolbar } from \"../markdown-toolbar\";\nimport { topLevelBlockOf, typewriterDelta } from \"./focus-writing\";\n\nexport type MarkdownWorkspaceMode = \"source\" | \"wysiwyg\" | \"split\";\n\n/**\n * Imperative handle exposed via `MarkdownWorkspace`'s `ref` (#273, DECISION A).\n *\n * Migration note: the forwarded ref type changed from `HTMLDivElement` to this\n * handle. Replace any `ref.current` DOM access with `ref.current?.getElement()`.\n *\n * Extends {@link EditorContentAccess} — all AI content-access methods delegate to\n * the active engine: Monaco (source/split) or the Milkdown WYSIWYG handle.\n *\n * **`onSelectionChange` caveat:** the subscription is scoped to the engine active at\n * call time. A mode switch (source ↔ wysiwyg) does NOT auto-rebind the listener —\n * re-subscribe from an effect whose deps include the mode. A self-rebinding v2 is a\n * noted future enhancement, out of v1 scope.\n */\nexport interface MarkdownWorkspaceHandle extends EditorContentAccess {\n /**\n * Scroll the active editor so FULL-SOURCE 1-based `line` is visible (Monaco\n * coordinates). No-op (never throws) while the engine is booting or `line` is\n * out of range. In WYSIWYG it is best-effort: resolves the nearest preceding\n * heading via `parseMarkdownOutline` + `fmOffset`, then delegates to\n * `scrollToHeading`. No-op if no preceding heading found.\n */\n revealLine(line: number, opts?: { center?: boolean }): void;\n /**\n * Scroll to a heading by its outline slug (same slugs as `DocumentOutline` /\n * `useMarkdownOutline` / `parseMarkdownOutline`). In Source/Split mode\n * resolves the line via `parseMarkdownOutline` then calls `revealLine`. In\n * WYSIWYG delegates to the `MarkdownEditorHandle.scrollToHeading`.\n */\n scrollToHeading(slug: string): void;\n /**\n * The live Monaco source editor instance, or `null` when not mounted or when\n * the active mode is `\"wysiwyg\"` (source pane not rendered).\n */\n getEditor(): MonacoCodeEditor | null;\n /**\n * The workspace root DOM element. Preserves the old `HTMLDivElement` ref\n * access that existed before DECISION A (ref type change in #273).\n */\n getElement(): HTMLDivElement | null;\n}\n\nexport interface MarkdownWorkspaceProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n \"onChange\" | \"defaultValue\"\n> {\n value?: string;\n defaultValue?: string;\n onChange?: (markdown: string) => void;\n mode?: MarkdownWorkspaceMode;\n defaultMode?: MarkdownWorkspaceMode;\n onModeChange?: (mode: MarkdownWorkspaceMode) => void;\n /**\n * Start with FOCUS WRITING on (wysiwyg mode): typewriter scrolling keeps\n * the caret vertically centered and inactive paragraphs dim. Toggleable in\n * the editor's mode row.\n */\n defaultFocusWriting?: boolean;\n /**\n * The `/` command menu in the WYSIWYG (preview-edit) pane AND the Monaco source\n * pane. `true` (default) uses the built-in brand commands; pass a config to\n * extend/replace them, or `false` to disable. Forwarded to {@link MarkdownEditor}.\n *\n * `shortcut` (default `\"Mod-Shift-O\"`) opens the menu at the caret in BOTH panes —\n * in the WYSIWYG pane via the ProseMirror plugin's `handleKeyDown`, and in the\n * source/split pane via a `CodeEditor` action (no `/` is inserted into the\n * doc). (#271)\n */\n slashMenu?: boolean | { commands?: SlashCommand[]; trigger?: string; shortcut?: string };\n /**\n * Customize the source / split toolbar's **Insert** menu (A4). Defaults to the\n * same commands as the WYSIWYG slash menu (so `/calc`, `/iterate`, `/pivot` and\n * any consumer commands are insertable in source mode too). Only commands with\n * a `snippet` appear; pass your own list to override.\n */\n insertCommands?: SlashCommand[];\n /**\n * Opt-in calc authoring inside ```calc fences (off by default). Wired to BOTH\n * surfaces: the Monaco source pane (highlight + autocomplete + result inlays)\n * and the WYSIWYG pane (highlight + result inlays). Supply the consumer's\n * `tokenize` / `evaluate` / `complete` hooks; the library bundles no calc engine.\n */\n calc?: CalcEditorHooks;\n /**\n * Declarative completion providers (#283) — e.g. `[[wikilink]]` autocomplete.\n * Off by default; mirrors the `slashMenu`/`calc` opt-in pattern. The library\n * owns the Monaco `registerCompletionItemProvider` registration lifecycle\n * (registered once, refcounted across mounted workspaces, disposed with the\n * last one — see `lib/editor-completions-monaco.ts`) for the Source/Split\n * panes, and mirrors providers into the WYSIWYG pane via `MarkdownEditor`'s\n * `completions` prop (a deliberately minimal mirror — see\n * `markdown-editor/completions/completions-prose.ts` for the exact gaps).\n * Zero `monaco-editor` imports needed in consumer code.\n */\n completions?: EditorCompletionProvider[];\n /**\n * Host-provided callback for image paste/drop embedding in the WYSIWYG pane.\n * Forwarded to {@link MarkdownEditor}. See `MarkdownEditorProps.onEmbedAsset`\n * for the full contract.\n */\n onEmbedAsset?: EmbedAssetFn;\n /**\n * Show the built-in \"Focus writing\" toggle in the WYSIWYG (preview-edit)\n * toolbar row. `false` HIDES and DISABLES it (no keyboard path) and forces\n * focus-writing OFF. `undefined`/`true` keep current behavior. The INITIAL\n * on/off state still comes from `defaultFocusWriting`. (#270)\n */\n focusWriting?: boolean;\n /**\n * Show the built-in Source / Split / Preview-edit mode switch. `false` hides\n * it in both toolbar branches so the host owns the view switch (controlled\n * `mode`/`onModeChange` still drive the panes). Default `true`. (#272)\n */\n modeSwitch?: boolean;\n /**\n * Host-supplied controls rendered in the toolbar's trailing slot (where the\n * built-in mode switch sits). Use with `modeSwitch={false}` to supply your\n * own switch / actions. (#272)\n */\n toolbarActions?: ReactNode;\n}\n\nconst MODES: { value: MarkdownWorkspaceMode; label: string; icon: typeof Eye }[] = [\n { value: \"source\", label: \"Source\", icon: SquareCode },\n { value: \"split\", label: \"Split\", icon: Columns2 },\n { value: \"wysiwyg\", label: \"Preview-edit\", icon: Eye },\n];\n\nexport const MarkdownWorkspace = forwardRef<MarkdownWorkspaceHandle, MarkdownWorkspaceProps>(\n function MarkdownWorkspace(\n {\n value,\n defaultValue,\n onChange,\n mode,\n defaultMode = \"split\",\n onModeChange,\n defaultFocusWriting = false,\n focusWriting,\n modeSwitch = true,\n toolbarActions,\n slashMenu = true,\n insertCommands,\n calc,\n completions,\n onEmbedAsset,\n className,\n ...props\n },\n ref,\n ) {\n const { t } = useLocale();\n // The source/split Insert menu defaults to the SAME commands as the WYSIWYG\n // slash menu, so both surfaces insert the same blocks (A4).\n const slashCommandList =\n typeof slashMenu === \"object\" && slashMenu.commands\n ? slashMenu.commands\n : BRAND_SLASH_COMMANDS;\n const toolbarInsertCommands = insertCommands ?? slashCommandList;\n const isControlled = value !== undefined;\n const [internalValue, setInternalValue] = useState(value ?? defaultValue ?? \"\");\n const markdown = isControlled ? value : internalValue;\n\n const [internalMode, setInternalMode] = useState<MarkdownWorkspaceMode>(defaultMode);\n const activeMode = mode ?? internalMode;\n\n const [monaco, setMonaco] = useState<MonacoCodeEditor | null>(null);\n // Stable set of onSelectionChange listeners (engine-agnostic). The handle adds\n // here; a binding effect forwards the active engine's selection events. (#AI)\n const [selectionListeners] = useState(() => new Set<(sel: EditorSelection) => void>());\n\n /* ------------------------- calc authoring (#220) ------------------------ */\n // Read the calc hooks through a ref so a fresh `calc` object identity never\n // re-attaches the Monaco layer; only toggling the feature on/off does.\n const calcRef = useRef<CalcEditorHooks | undefined>(calc);\n calcRef.current = calc;\n const calcEnabled = calc != null;\n\n useEffect(() => {\n if (!monaco || !calcEnabled) return;\n // Let calc completions surface as you type inside the fence (markdown\n // otherwise suppresses quick suggestions outside comments/strings).\n monaco.updateOptions({\n quickSuggestions: { other: true, comments: false, strings: false },\n });\n return attachCalcMonaco(monaco, () => calcRef.current);\n }, [monaco, calcEnabled]);\n\n /* --------------------- completion providers (#283) ----------------------- */\n // Read through a ref so a fresh `completions` array identity (a re-render)\n // never re-attaches — the Monaco lifecycle (`attachCompletionsMonaco`) reads\n // the LIVE list on every suggestion request; only mount/unmount and\n // enabling/disabling the feature touch the effect.\n const completionsRef = useRef<EditorCompletionProvider[] | undefined>(completions);\n completionsRef.current = completions;\n const completionsEnabled = completions != null;\n\n useEffect(() => {\n if (!monaco || !completionsEnabled) return;\n return attachCompletionsMonaco(monaco, () => completionsRef.current);\n }, [monaco, completionsEnabled]);\n\n // The source CodeEditor unmounts when the active mode becomes WYSIWYG, but its\n // `onMount` only fires on (re)mount — nothing clears the held instance. Drop it\n // here so `getEditor()` honors its documented `null` contract in WYSIWYG and\n // `revealLine`/`scrollToHeading` delegate to the WYSIWYG handle instead of\n // acting on a disposed Monaco editor. (#271 review)\n useEffect(() => {\n if (activeMode === \"wysiwyg\") setMonaco(null);\n }, [activeMode]);\n\n /* --------- source-pane slash menu (#271) -------------------------------- */\n const slashEnabled = slashMenu !== false;\n // Honor an explicitly disabled shortcut (`shortcut: \"\"` / `shortcut: undefined`)\n // the SAME way the WYSIWYG plugin does (`\"shortcut\" in options`), so both panes\n // agree: only fall back to the default when the key is absent entirely. (#271 review)\n const shortcut =\n typeof slashMenu === \"object\" && \"shortcut\" in slashMenu\n ? slashMenu.shortcut\n : DEFAULT_SLASH_SHORTCUT;\n\n const [sourceSlashOpen, setSourceSlashOpen] = useState(false);\n // The model range of a typed `/` when the menu was opened by typing (not the\n // hotkey). null for the hotkey path. Drives MonacoSlashMenu's `triggerRange`:\n // on select the `/` is replaced by the block; on cancel it is removed.\n const [typedTrigger, setTypedTrigger] = useState<SlashTriggerRange | null>(null);\n\n // Close handler: clear the typed-trigger whenever the menu closes so a later\n // hotkey-open doesn't inherit a stale range.\n const handleSourceSlashOpenChange = (next: boolean) => {\n setSourceSlashOpen(next);\n if (!next) setTypedTrigger(null);\n };\n\n // Typing `/` at a line start (or after whitespace) opens the menu in the\n // source pane — the conflict-free trigger that mirrors the WYSIWYG `/`. We\n // watch model edits for a lone `/` insertion at a valid spot; our own\n // insert/cancel edits are multi-char or empty, so they never re-trigger.\n useEffect(() => {\n if (!monaco || !slashEnabled) return;\n const sub = monaco.onDidChangeModelContent((e) => {\n if (sourceSlashOpen || e.changes.length !== 1) return;\n const change = e.changes[0];\n if (!change || change.text !== \"/\") return;\n const model = monaco.getModel();\n if (!model) return;\n const line = change.range.startLineNumber;\n const range = slashTriggerRange(line, model.getLineContent(line), change.range.startColumn);\n if (!range) return;\n setTypedTrigger(range);\n setSourceSlashOpen(true);\n });\n return () => sub.dispose();\n }, [monaco, slashEnabled, sourceSlashOpen]);\n\n // A command works in the source pane when it has a text snippet OR an\n // explicit source-pane handler (#299) — a run-only command whose ONLY\n // handler is Milkdown's `run` (needs a Ctx unavailable in Monaco) is\n // excluded; `runInSource` is exactly the escape hatch for that case.\n const sourceCommands = useMemo(\n () =>\n slashCommandList.filter((c) => c.snippet != null || typeof c.runInSource === \"function\"),\n [slashCommandList],\n );\n\n // A Layer-1 CodeEditor action that opens the source slash popup when fired\n // (via its keybinding or the command palette). All KeyMod/KeyCode references\n // live inside parseShortcut (slash/shortcut.ts) — NEVER reference a bare\n // monaco.KeyMod here, because `monaco` is a state variable (the editor\n // instance), not the namespace.\n const sourceActions = useMemo<EditorAction[]>(\n () =>\n slashEnabled && shortcut\n ? [\n {\n id: \"brand.openSlashMenu\",\n label: \"Insert block…\",\n keybindings: [parseShortcut(shortcut)],\n // Hotkey open inserts at the caret (no typed `/` to replace).\n run: () => {\n setTypedTrigger(null);\n setSourceSlashOpen(true);\n },\n },\n ]\n : [],\n [slashEnabled, shortcut],\n );\n\n /* ------------------- split-view scroll synchronization ------------------ */\n // Line-accurate (not percentage) sync: preview blocks carry\n // `data-sourcepos` in frontmatter-STRIPPED coordinates; Monaco lines are\n // full-source — bridge with the stripped-line offset.\n const previewPaneRef = useRef<HTMLDivElement | null>(null);\n const scrollLock = useRef<\"editor\" | \"preview\" | null>(null);\n const lockTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const fmOffset = useMemo(() => {\n try {\n const body = parseFrontmatter(markdown).content;\n return markdown.split(\"\\n\").length - body.split(\"\\n\").length;\n } catch {\n return 0;\n }\n }, [markdown]);\n\n const lock = (owner: \"editor\" | \"preview\") => {\n scrollLock.current = owner;\n if (lockTimer.current) clearTimeout(lockTimer.current);\n lockTimer.current = setTimeout(() => {\n scrollLock.current = null;\n }, 150);\n };\n\n // Editor → preview.\n useEffect(() => {\n if (!monaco || activeMode !== \"split\") return;\n const disposable = monaco.onDidScrollChange(() => {\n if (scrollLock.current === \"preview\") return;\n const range = monaco.getVisibleRanges()[0];\n const host = previewPaneRef.current;\n if (!range || !host) return;\n const line = range.startLineNumber - fmOffset;\n let target: HTMLElement | null = null;\n for (const el of host.querySelectorAll<HTMLElement>(\"[data-sourcepos]\")) {\n const end = Number(el.dataset.sourcepos?.split(\":\")[1]);\n if (end >= line) {\n target = el;\n break;\n }\n }\n if (!target) return;\n lock(\"editor\");\n host.scrollTop =\n target.getBoundingClientRect().top -\n host.getBoundingClientRect().top +\n host.scrollTop -\n 12;\n });\n return () => disposable.dispose();\n }, [monaco, activeMode, fmOffset]);\n\n // Preview → editor.\n const onPreviewScroll = () => {\n if (scrollLock.current === \"editor\" || !monaco || activeMode !== \"split\") return;\n const host = previewPaneRef.current;\n if (!host) return;\n const hostTop = host.getBoundingClientRect().top;\n for (const el of host.querySelectorAll<HTMLElement>(\"[data-sourcepos]\")) {\n if (el.getBoundingClientRect().bottom >= hostTop) {\n const start = Number(el.dataset.sourcepos?.split(\":\")[0]);\n if (!Number.isNaN(start)) {\n lock(\"preview\");\n monaco.setScrollTop(monaco.getTopForLineNumber(Math.max(1, start + fmOffset)));\n }\n return;\n }\n }\n };\n\n const setMarkdown = (next: string) => {\n if (!isControlled) setInternalValue(next);\n onChange?.(next);\n };\n\n /* ------------------ lossless WYSIWYG editing (WI-1) ------------------ */\n // Milkdown re-serializes the WHOLE document on every edit, normalizing\n // formatting the user never touched — a one-line edit became a whole-file\n // diff. Capture the editor's pre-edit serialization as a BASELINE and\n // merge each emission back onto the byte-exact original: unedited blocks\n // keep their original bytes.\n const wysiwygRef = useRef<MarkdownEditorHandle | null>(null);\n const wysiwygBase = useRef<{ original: string; baseline: string | null } | null>(null);\n\n useEffect(() => {\n if (activeMode !== \"wysiwyg\") {\n wysiwygBase.current = null;\n return;\n }\n // Capture at mode entry; the editor is uncontrolled while in wysiwyg,\n // so the workspace buffer is the only writer.\n const original = markdown;\n wysiwygBase.current = { original, baseline: null };\n const poll = setInterval(() => {\n const base = wysiwygBase.current;\n if (!base || base.baseline !== null) {\n clearInterval(poll);\n return;\n }\n const s = wysiwygRef.current?.serialized();\n if (s != null) {\n base.baseline = s;\n clearInterval(poll);\n }\n }, 50);\n const stop = setTimeout(() => clearInterval(poll), 5000);\n return () => {\n clearInterval(poll);\n clearTimeout(stop);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- capture markdown at ENTRY only\n }, [activeMode]);\n\n const onWysiwygChange = (emitted: string) => {\n const base = wysiwygBase.current;\n // Baseline captured before the first keystroke → merge; otherwise fall\n // back to the raw emission (rare boot race — old behavior, never worse).\n const next =\n base && base.baseline !== null\n ? mergeNormalizedEdit(base.original, base.baseline, emitted)\n : emitted;\n setMarkdown(next);\n };\n\n /* ---------------- focus writing (Ulysses Phase A, wysiwyg) ---------------- */\n // Typewriter scrolling + paragraph focus, driven from OUTSIDE the engine:\n // selectionchange marks the active top-level block (CSS dims the rest);\n // right after typing, the pane re-centers the caret into a middle band.\n const focusWritingEnabled = focusWriting !== false;\n const [focusWritingOn, setFocusWritingOn] = useState(\n focusWritingEnabled ? defaultFocusWriting : false,\n );\n const wysiwygPaneRef = useRef<HTMLDivElement | null>(null);\n const lastInputAt = useRef(0);\n\n useEffect(() => {\n if (!(focusWritingEnabled && focusWritingOn && activeMode === \"wysiwyg\")) return;\n const pane = wysiwygPaneRef.current;\n if (!pane) return;\n let active: Element | null = null;\n\n const onSelectionChange = () => {\n const root = pane.querySelector<HTMLElement>(\".ProseMirror\");\n if (!root) return;\n const sel = document.getSelection();\n const node = sel?.anchorNode ?? null;\n if (!node || !root.contains(node)) return;\n const block = topLevelBlockOf(root, node);\n if (block !== active) {\n active?.classList.remove(\"wb-fw-active\");\n block?.classList.add(\"wb-fw-active\");\n active = block;\n }\n // Re-center only right after typing — a mouse click must not yank\n // the viewport (Ulysses recenters while WRITING, not while aiming).\n if (Date.now() - lastInputAt.current < 200 && sel && sel.rangeCount > 0) {\n const range = sel.getRangeAt(0).getBoundingClientRect();\n const caret = range.height > 0 ? range : (active?.getBoundingClientRect() ?? range);\n const host = pane.getBoundingClientRect();\n const delta = typewriterDelta(caret.top, caret.height, host.top, host.height);\n if (delta !== 0) pane.scrollTop += delta;\n }\n };\n const onInput = () => {\n lastInputAt.current = Date.now();\n };\n\n document.addEventListener(\"selectionchange\", onSelectionChange);\n pane.addEventListener(\"input\", onInput, true);\n onSelectionChange();\n return () => {\n document.removeEventListener(\"selectionchange\", onSelectionChange);\n pane.removeEventListener(\"input\", onInput, true);\n active?.classList.remove(\"wb-fw-active\");\n };\n }, [focusWritingEnabled, focusWritingOn, activeMode]);\n\n /* ------------------- imperative handle (#273, DECISION A) --------------- */\n // The forwarded ref is now a MarkdownWorkspaceHandle (not the div).\n // The root <div> gets rootRef; getElement() returns rootRef.current.\n const rootRef = useRef<HTMLDivElement | null>(null);\n\n useImperativeHandle(\n ref,\n () => {\n const revealLine = (n: number, opts?: { center?: boolean }) => {\n if (monaco) {\n // Source / Split: Monaco exact-line reveal.\n const max = monaco.getModel()?.getLineCount() ?? 0;\n if (n < 1 || n > max) return;\n if (opts?.center === false) {\n monaco.revealLine(n);\n } else {\n monaco.revealLineInCenter(n);\n }\n } else {\n // WYSIWYG: best-effort — find the nearest preceding heading whose\n // (stripped) line + fmOffset ≤ n, then delegate to scrollToHeading.\n const items = parseMarkdownOutline(markdown);\n // items.line is frontmatter-stripped (1-based); full-source = line + fmOffset\n const preceding = items.filter((item) => item.line + fmOffset <= n).at(-1);\n if (!preceding) return;\n wysiwygRef.current?.scrollToHeading(preceding.id);\n }\n };\n\n const scrollToHeading = (slug: string) => {\n if (monaco) {\n // Source / Split: resolve stripped line via outline, lift to full-source.\n const item = parseMarkdownOutline(markdown).find((i) => i.id === slug);\n if (!item) return;\n revealLine(item.line + fmOffset, { center: true });\n } else {\n // WYSIWYG: delegate to the Milkdown handle.\n wysiwygRef.current?.scrollToHeading(slug);\n }\n };\n\n // Content-access delegation: monaco (source/split) → monacoContentAccess;\n // wysiwyg → the MarkdownEditorHandle (which now IS an EditorContentAccess).\n // If both are null (booting), fall back to best-effort no-ops (never throw).\n const getAccess = (): EditorContentAccess | null => {\n if (monaco) return monacoContentAccess(monaco);\n if (wysiwygRef.current) return wysiwygRef.current;\n return null;\n };\n\n return {\n revealLine,\n scrollToHeading,\n getEditor: () => monaco,\n getElement: () => rootRef.current,\n\n // EditorContentAccess — read/write delegate to the active engine at call\n // time (the AI acts after mount, so a call-time snapshot is correct here).\n getText: () => getAccess()?.getText() ?? \"\",\n getSelection: () => getAccess()?.getSelection() ?? { text: \"\", empty: true },\n replaceSelection: (text: string) => getAccess()?.replaceSelection(text),\n insertAtCursor: (text: string) => getAccess()?.insertAtCursor(text),\n focus: () => getAccess()?.focus(),\n // onSelectionChange uses the STABLE listener set (not getAccess()) so a\n // subscribe-in-mount-effect survives the editor's async mount + mode\n // switches; the binding effect below forwards the active engine's events.\n onSelectionChange: (listener) => {\n selectionListeners.add(listener);\n return () => selectionListeners.delete(listener);\n },\n };\n },\n // Re-create when the things the methods close over change.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [monaco, markdown, fmOffset, activeMode, selectionListeners],\n );\n\n // Forward the ACTIVE engine's selection changes into the stable listener set,\n // re-binding when the engine (monaco/wysiwyg) or mode changes. This is what\n // makes the handle's onSelectionChange robust to the editor's async mount.\n useEffect(() => {\n let unsub: (() => void) | undefined;\n if (monaco) {\n unsub = monacoContentAccess(monaco).onSelectionChange((sel) =>\n selectionListeners.forEach((l) => l(sel)),\n );\n } else if (activeMode === \"wysiwyg\" && wysiwygRef.current) {\n unsub = wysiwygRef.current.onSelectionChange((sel) =>\n selectionListeners.forEach((l) => l(sel)),\n );\n }\n return () => unsub?.();\n }, [monaco, activeMode, selectionListeners]);\n\n const setMode = (next: string) => {\n if (next !== \"source\" && next !== \"split\" && next !== \"wysiwyg\") return;\n if (!mode) setInternalMode(next);\n onModeChange?.(next);\n };\n\n const modeToggle = (\n <TooltipProvider delayDuration={300}>\n {/* Segmented mode switch — same recessed-track / raised-segment\n grammar as every other mode control (Tabs, Read/Write). */}\n <ToggleGroup\n type=\"single\"\n value={activeMode}\n onValueChange={setMode}\n variant=\"segmented\"\n size=\"sm\"\n className=\"rounded-md p-0.5\"\n >\n {MODES.map(({ value: m, label, icon: Icon }) => (\n <Tooltip key={m}>\n <TooltipTrigger asChild>\n <ToggleGroupItem\n value={m}\n aria-label={label}\n className=\"h-6 min-w-7 rounded-[5px] px-2\"\n >\n <Icon className=\"size-4\" />\n </ToggleGroupItem>\n </TooltipTrigger>\n <TooltipContent>{label}</TooltipContent>\n </Tooltip>\n ))}\n </ToggleGroup>\n </TooltipProvider>\n );\n\n const trailing = (\n <>\n {modeSwitch ? modeToggle : null}\n {toolbarActions}\n </>\n );\n\n const sourcePane = (\n <CodeEditor\n language=\"markdown\"\n value={markdown}\n onChange={setMarkdown}\n actions={sourceActions}\n onMount={(editor) => {\n // Markdown is prose: soft-wrap so the source pane lays out like the\n // preview (line-based scroll sync stays accurate either way, but\n // matching layouts keep the two panes visually in step).\n editor.updateOptions({ wordWrap: \"on\" });\n setMonaco(editor);\n }}\n />\n );\n\n return (\n <div\n ref={rootRef}\n data-testid=\"markdown-workspace\"\n className={cn(\"flex h-full min-h-0 flex-col overflow-hidden\", className)}\n {...props}\n >\n {activeMode === \"wysiwyg\" ? (\n <div className=\"flex h-10 shrink-0 items-center justify-end gap-2 border-b border-border bg-surface px-2\">\n {focusWritingEnabled ? (\n <TooltipProvider delayDuration={300}>\n <Tooltip>\n <TooltipTrigger asChild>\n <Toggle\n size=\"sm\"\n pressed={focusWritingOn}\n onPressedChange={setFocusWritingOn}\n aria-label={t(\"editor.markdownWorkspace.focusWriting\")}\n className=\"h-6 gap-1.5 px-2 text-caption\"\n >\n <Focus className=\"size-3.5\" aria-hidden=\"true\" />{\" \"}\n {t(\"editor.markdownWorkspace.focus\")}\n </Toggle>\n </TooltipTrigger>\n <TooltipContent>{t(\"editor.markdownWorkspace.focusWritingHint\")}</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n ) : null}\n {trailing}\n </div>\n ) : (\n <MarkdownToolbar\n editor={monaco}\n actions={trailing}\n insertCommands={toolbarInsertCommands}\n />\n )}\n\n <div className=\"min-h-0 flex-1\">\n {activeMode === \"source\" ? sourcePane : null}\n\n {activeMode === \"wysiwyg\" ? (\n <div\n ref={wysiwygPaneRef}\n data-focus-writing={focusWritingEnabled && focusWritingOn ? \"\" : undefined}\n className=\"h-full overflow-auto p-4\"\n >\n {/* UNCONTROLLED while in wysiwyg: feeding the merged buffer back\n would replaceAll on every keystroke (cursor loss + echo\n loops). The buffer receives merged text via onWysiwygChange;\n mode switches remount the editor from the buffer. */}\n <MarkdownEditor\n ref={wysiwygRef}\n defaultValue={markdown}\n onChange={onWysiwygChange}\n slashMenu={slashMenu}\n calc={calc}\n completions={completions}\n onEmbedAsset={onEmbedAsset}\n className=\"border-0\"\n />\n </div>\n ) : null}\n\n {activeMode === \"split\" ? (\n <ResizablePanelGroup direction=\"horizontal\">\n <ResizablePanel defaultSize={50} minSize={25}>\n {sourcePane}\n </ResizablePanel>\n <ResizableHandle withHandle />\n <ResizablePanel defaultSize={50} minSize={25}>\n <div\n ref={previewPaneRef}\n onScroll={onPreviewScroll}\n className=\"h-full overflow-auto p-5\"\n >\n <MarkdownPreview>{markdown}</MarkdownPreview>\n </div>\n </ResizablePanel>\n </ResizablePanelGroup>\n ) : null}\n </div>\n\n {/* Source-pane slash popup (#271): shown when the Layer-1 action fires\n in source or split mode. Uses fixed positioning anchored to the caret\n via getScrolledVisiblePosition, so it works in both layouts. */}\n {monaco && (activeMode === \"source\" || activeMode === \"split\") && slashEnabled ? (\n <MonacoSlashMenu\n editor={monaco}\n commands={sourceCommands}\n open={sourceSlashOpen}\n onOpenChange={handleSourceSlashOpenChange}\n triggerRange={typedTrigger}\n />\n ) : null}\n </div>\n );\n },\n);\n","\"use client\";\n\n/**\n * Monaco calc layer (#220) — live highlighting + autocomplete + result inlays for\n * ```calc fences inside a markdown Monaco model.\n *\n * - HIGHLIGHT is a decoration pass (not a Monarch language): the model is markdown,\n * so we tokenize each calc fence body via the consumer's `tokenize` hook and apply\n * `inlineClassName` decorations colored from the `--calc-*` tokens (calc-editor.css).\n * - COMPLETIONS come from a markdown `CompletionItemProvider` scoped to calc fences,\n * delegating to the consumer's `complete` hook.\n * - INLAYS are Monaco inlay hints (themed via the theme bridge's `editorInlayHint.*`\n * colors, so they re-apply on theme change), built from the consumer's `evaluate`.\n *\n * The providers register ONCE per language and look the active hooks up per-model via\n * a registry, so any number of markdown editors can be wired independently. All the\n * column/position math lives in `calc-editor.ts` (engine-neutral + unit-tested);\n * this module only maps those specs to Monaco objects and owns the lifecycle.\n */\nimport * as monaco from \"monaco-editor\";\n\nimport \"./calc-editor.css\";\n\nimport {\n calcDecorationSpecs,\n calcInlaySpecs,\n findCalcFences,\n identifierPrefix,\n type CalcFence,\n} from \"./calc-editor\";\nimport type { CalcCompletionKind, CalcEditorHooks } from \"./types\";\n\n/** Resolver of the latest hooks for a model (read through a ref so prop-identity churn is free). */\ntype HooksGetter = () => CalcEditorHooks | undefined;\n\n/** Per-model hook registry the global providers consult. */\nconst REGISTRY = new Map<monaco.editor.ITextModel, HooksGetter>();\n\nlet providersRegistered = false;\nlet inlayEmitter: monaco.Emitter<void> | null = null;\n\n/** Read a fence body's EOL-free line texts straight from the model (CRLF-safe). */\nfunction bodyLineTexts(model: monaco.editor.ITextModel, fence: CalcFence): string[] {\n const out: string[] = [];\n for (let ln = fence.bodyStartLine; ln <= fence.bodyEndLine; ln++) {\n out.push(model.getLineContent(ln));\n }\n return out;\n}\n\n/** All ```calc fences in the model, scanned from LF-normalized text. */\nfunction modelFences(model: monaco.editor.ITextModel): CalcFence[] {\n return findCalcFences(model.getValue(monaco.editor.EndOfLinePreference.LF));\n}\n\n/** Highlight decorations for every calc fence in the model. */\nfunction buildDecorations(\n model: monaco.editor.ITextModel,\n hooks: CalcEditorHooks,\n): monaco.editor.IModelDeltaDecoration[] {\n const decorations: monaco.editor.IModelDeltaDecoration[] = [];\n for (const fence of modelFences(model)) {\n if (fence.bodyEndLine < fence.bodyStartLine) continue;\n const specs = calcDecorationSpecs(hooks, fence.bodyStartLine, bodyLineTexts(model, fence));\n for (const s of specs) {\n decorations.push({\n range: new monaco.Range(s.lineNumber, s.startColumn, s.lineNumber, s.endColumn),\n options: { inlineClassName: s.className },\n });\n }\n }\n return decorations;\n}\n\nconst COMPLETION_KIND: Record<CalcCompletionKind, () => monaco.languages.CompletionItemKind> = {\n variable: () => monaco.languages.CompletionItemKind.Variable,\n function: () => monaco.languages.CompletionItemKind.Function,\n unit: () => monaco.languages.CompletionItemKind.Unit,\n currency: () => monaco.languages.CompletionItemKind.Unit,\n constant: () => monaco.languages.CompletionItemKind.Constant,\n reference: () => monaco.languages.CompletionItemKind.Reference,\n keyword: () => monaco.languages.CompletionItemKind.Keyword,\n snippet: () => monaco.languages.CompletionItemKind.Snippet,\n};\n\nfunction mapCompletionKind(kind?: CalcCompletionKind): monaco.languages.CompletionItemKind {\n return (COMPLETION_KIND[kind ?? \"variable\"] ?? COMPLETION_KIND.variable)();\n}\n\n/** Register the per-language providers once (idempotent). */\nfunction ensureProviders(): void {\n if (providersRegistered) return;\n providersRegistered = true;\n inlayEmitter = new monaco.Emitter<void>();\n\n monaco.languages.registerInlayHintsProvider(\"markdown\", {\n onDidChangeInlayHints: inlayEmitter.event,\n provideInlayHints(model, range) {\n const empty = { hints: [] as monaco.languages.InlayHint[], dispose() {} };\n const hooks = REGISTRY.get(model)?.();\n if (!hooks?.evaluate) return empty;\n const hints: monaco.languages.InlayHint[] = [];\n for (const fence of modelFences(model)) {\n if (fence.bodyEndLine < fence.bodyStartLine) continue;\n if (\n fence.bodyEndLine < range.startLineNumber ||\n fence.bodyStartLine > range.endLineNumber\n ) {\n continue;\n }\n for (const inlay of calcInlaySpecs(\n hooks,\n fence.bodyStartLine,\n bodyLineTexts(model, fence),\n )) {\n hints.push({\n position: { lineNumber: inlay.lineNumber, column: inlay.column },\n label: inlay.text,\n kind: monaco.languages.InlayHintKind.Type,\n paddingLeft: true,\n });\n }\n }\n return { hints, dispose() {} };\n },\n });\n\n monaco.languages.registerCompletionItemProvider(\"markdown\", {\n provideCompletionItems(model, position) {\n const hooks = REGISTRY.get(model)?.();\n if (!hooks?.complete) return { suggestions: [] };\n const fence = modelFences(model).find(\n (f) => position.lineNumber >= f.bodyStartLine && position.lineNumber <= f.bodyEndLine,\n );\n if (!fence) return { suggestions: [] };\n const lines = bodyLineTexts(model, fence);\n const line = lines[position.lineNumber - fence.bodyStartLine] ?? \"\";\n const column = position.column - 1; // 0-based caret within the line\n const prefix = identifierPrefix(line, column);\n let completions;\n try {\n completions = hooks.complete({\n source: lines.join(\"\\n\"),\n line,\n lineNumber: position.lineNumber - fence.bodyStartLine + 1,\n column,\n prefix,\n });\n } catch {\n return { suggestions: [] };\n }\n const replace = new monaco.Range(\n position.lineNumber,\n position.column - prefix.length,\n position.lineNumber,\n position.column,\n );\n return {\n suggestions: completions.map((c) => ({\n label: c.label,\n insertText: c.insert,\n detail: c.detail,\n kind: mapCompletionKind(c.kind),\n range: replace,\n })),\n };\n },\n });\n}\n\n/**\n * Wire calc highlighting + completion + inlays onto a markdown Monaco editor.\n * `getHooks` is read fresh on each update, so changing the `calc` prop's identity\n * never forces a re-attach. Returns a disposer; call it on unmount / when `calc`\n * is removed.\n */\nexport function attachCalcMonaco(\n editor: monaco.editor.IStandaloneCodeEditor,\n getHooks: HooksGetter,\n): () => void {\n ensureProviders();\n const collection = editor.createDecorationsCollection();\n const subs: monaco.IDisposable[] = [];\n let model = editor.getModel();\n if (model) REGISTRY.set(model, getHooks);\n\n const refresh = () => {\n const current = editor.getModel();\n const hooks = getHooks();\n if (!current || !hooks) {\n collection.clear();\n return;\n }\n REGISTRY.set(current, getHooks);\n collection.set(buildDecorations(current, hooks));\n inlayEmitter?.fire();\n };\n\n refresh();\n subs.push(editor.onDidChangeModelContent(refresh));\n subs.push(\n editor.onDidChangeModel(() => {\n if (model) REGISTRY.delete(model);\n model = editor.getModel();\n refresh();\n }),\n );\n\n return () => {\n for (const s of subs) s.dispose();\n collection.clear();\n if (model) REGISTRY.delete(model);\n };\n}\n","/**\n * Line-level markdown diff → block annotations for `MarkdownPreview` (#L18).\n *\n * `computeMarkdownAnnotations(before, after)` diffs two markdown sources and\n * returns the annotation set the preview renders as a \"ghost diff\": added /\n * modified blocks get a wash + accent rail, pure deletions become a slim\n * \"removed here\" marker before the next surviving block.\n *\n * Lines are 1-based and refer to the AFTER source **including** any YAML\n * frontmatter — `MarkdownPreview` shifts them when it strips frontmatter, so\n * callers never have to think about the offset.\n *\n * The diff is a classic LCS (O(n·m) DP) — markdown documents are\n * authoring-sized. Inputs beyond {@link MAX_DIFF_LINES} lines fall back to an\n * empty annotation set (the UI simply shows no wash) instead of freezing.\n */\n\nexport type MarkdownAnnotationKind = \"added\" | \"modified\" | \"removed-before\";\n\nexport interface MarkdownAnnotation {\n kind: MarkdownAnnotationKind;\n /**\n * For `added`/`modified`: the 1-based inclusive line range in the AFTER\n * source. For `removed-before`: `startLine === endLine` is the line in the\n * AFTER source that now sits where the removed content used to be.\n */\n startLine: number;\n endLine: number;\n /** For `removed-before`: how many lines were removed. */\n removedCount?: number;\n}\n\n/** Above this many lines on either side the diff degrades to \"no annotations\". */\nexport const MAX_DIFF_LINES = 5000;\n\nconst splitLines = (s: string): string[] => s.split(\"\\n\");\n\n/**\n * LCS keep-table via dynamic programming. Returns pairs of kept (before-index,\n * after-index) in ascending order. Indices are 0-based.\n *\n * Exported for the normalization-aware merge (`merge.ts`) — not public API.\n */\nexport function lcsPairs(a: string[], b: string[]): [number, number][] {\n const n = a.length;\n const m = b.length;\n // dp rows as typed arrays to keep memory flat.\n const dp: Uint32Array[] = Array.from({ length: n + 1 }, () => new Uint32Array(m + 1));\n for (let i = n - 1; i >= 0; i--) {\n const row = dp[i]!;\n const next = dp[i + 1]!;\n for (let j = m - 1; j >= 0; j--) {\n row[j] = a[i] === b[j] ? next[j + 1]! + 1 : Math.max(next[j]!, row[j + 1]!);\n }\n }\n const pairs: [number, number][] = [];\n let i = 0;\n let j = 0;\n while (i < n && j < m) {\n if (a[i] === b[j]) {\n pairs.push([i, j]);\n i++;\n j++;\n } else if (dp[i + 1]![j]! >= dp[i]![j + 1]!) {\n i++;\n } else {\n j++;\n }\n }\n return pairs;\n}\n\n/**\n * Diff two markdown sources into preview annotations.\n *\n * Hunk semantics: a run of only-added lines → `added`; a run that replaces\n * removed lines → `modified`; a run of only-removed lines → `removed-before`\n * anchored on the first surviving AFTER line at-or-after the removal.\n */\nexport function computeMarkdownAnnotations(before: string, after: string): MarkdownAnnotation[] {\n if (before === after) return [];\n const a = splitLines(before);\n const b = splitLines(after);\n if (a.length > MAX_DIFF_LINES || b.length > MAX_DIFF_LINES) return [];\n\n const pairs = lcsPairs(a, b);\n const annotations: MarkdownAnnotation[] = [];\n\n let prevA = -1;\n let prevB = -1;\n // Sentinel pair past the end flushes the trailing hunk.\n const walk: [number, number][] = [...pairs, [a.length, b.length]];\n for (const [ai, bi] of walk) {\n const removed = ai - prevA - 1;\n const added = bi - prevB - 1;\n if (added > 0 && removed > 0) {\n annotations.push({ kind: \"modified\", startLine: prevB + 2, endLine: bi });\n } else if (added > 0) {\n annotations.push({ kind: \"added\", startLine: prevB + 2, endLine: bi });\n } else if (removed > 0) {\n // Anchor on the next surviving AFTER line (1-based); clamp into range.\n const anchor = Math.min(bi + 1, b.length);\n annotations.push({\n kind: \"removed-before\",\n startLine: anchor,\n endLine: anchor,\n removedCount: removed,\n });\n }\n prevA = ai;\n prevB = bi;\n }\n return mergeAdjacent(annotations);\n}\n\n/** Honest \"+a −r\" totals for an annotation set (commit churn, drift rows). */\nexport function summarizeAnnotations(annotations: MarkdownAnnotation[]): {\n added: number;\n removed: number;\n} {\n let added = 0;\n let removed = 0;\n for (const a of annotations) {\n const span = a.endLine - a.startLine + 1;\n if (a.kind === \"added\") added += span;\n else if (a.kind === \"modified\") {\n added += span;\n removed += span;\n } else if (a.kind === \"removed-before\") removed += a.removedCount ?? 1;\n }\n return { added, removed };\n}\n\n/** Merge touching/overlapping wash hunks of the same kind (keeps the DOM quiet). */\nfunction mergeAdjacent(annotations: MarkdownAnnotation[]): MarkdownAnnotation[] {\n const out: MarkdownAnnotation[] = [];\n for (const ann of annotations) {\n const last = out[out.length - 1];\n if (\n last &&\n last.kind !== \"removed-before\" &&\n last.kind === ann.kind &&\n ann.startLine <= last.endLine + 1\n ) {\n last.endLine = Math.max(last.endLine, ann.endLine);\n } else {\n out.push({ ...ann });\n }\n }\n return out;\n}\n\n/**\n * Shift annotation lines by `-offset` (used when frontmatter is stripped before\n * rendering). Annotations that fall entirely inside the stripped region drop out.\n */\nexport function shiftAnnotations(\n annotations: MarkdownAnnotation[],\n offset: number,\n): MarkdownAnnotation[] {\n if (offset === 0) return annotations;\n const out: MarkdownAnnotation[] = [];\n for (const ann of annotations) {\n const startLine = ann.startLine - offset;\n const endLine = ann.endLine - offset;\n if (endLine < 1) continue;\n out.push({ ...ann, startLine: Math.max(1, startLine), endLine });\n }\n return out;\n}\n\n/** Does the annotation set wash the given block line range? Most specific wins. */\nexport function annotationForRange(\n annotations: MarkdownAnnotation[],\n startLine: number,\n endLine: number,\n): MarkdownAnnotation | undefined {\n let hit: MarkdownAnnotation | undefined;\n for (const ann of annotations) {\n if (ann.kind === \"removed-before\") continue;\n if (ann.startLine <= endLine && ann.endLine >= startLine) {\n if (!hit || ann.endLine - ann.startLine < hit.endLine - hit.startLine) hit = ann;\n }\n }\n return hit;\n}\n\n/** The removed-marker (if any) anchored exactly at this block's first line. */\nexport function removedMarkerAt(\n annotations: MarkdownAnnotation[],\n startLine: number,\n): MarkdownAnnotation | undefined {\n return annotations.find((a) => a.kind === \"removed-before\" && a.startLine === startLine);\n}\n","/**\n * Normalization-aware merge for WYSIWYG markdown editing (review WI-1).\n *\n * Problem: Milkdown serializes the WHOLE document on every edit, normalizing\n * formatting it never touched (list markers, wrapping, spacing). Feeding that\n * back into the buffer turns a one-line edit into a whole-file rewrite —\n * destroying git blame and making PR review impossible.\n *\n * Fix: three-way line merge.\n * - `original` — the byte-exact source the editor was opened with.\n * - `baseline` — the editor's serialization of `original` BEFORE any edit\n * (pure normalization drift).\n * - `edited` — the editor's serialization after user edits.\n *\n * `diff(baseline, edited)` isolates what the USER changed; an\n * `original ↔ baseline` alignment maps those hunks back onto `original`.\n * Everything the user didn't touch keeps its original bytes. Granularity is\n * the contiguous normalized run — markdown's blank lines survive\n * serialization byte-exact, so in practice that's a single block.\n *\n * Guarantees:\n * - no user edit (`baseline === edited`) → returns `original` byte-exact;\n * - no normalization drift (`original === baseline`) → returns `edited`;\n * - a user hunk inside a normalized block replaces exactly that block;\n * - oversized inputs (> {@link MAX_DIFF_LINES}) fall back to `edited`.\n */\n\nimport { lcsPairs, MAX_DIFF_LINES } from \"./diff\";\n\n/** A contiguous span of the baseline mapped to a span of the original. */\ninterface Region {\n /** Baseline range [bStart, bEnd) — may be empty (pure original deletion). */\n bStart: number;\n bEnd: number;\n /** Original lines this region carries. */\n oLines: string[];\n /** True when the region is a 1:1 byte-equal line pair. */\n exact: boolean;\n}\n\n/** Build the ordered original↔baseline region list (covers both fully). */\nfunction alignRegions(o: string[], b: string[]): Region[] {\n const pairs = lcsPairs(o, b);\n const regions: Region[] = [];\n let prevO = -1;\n let prevB = -1;\n const walk: [number, number][] = [...pairs, [o.length, b.length]];\n for (const [oi, bi] of walk) {\n if (oi - prevO > 1 || bi - prevB > 1) {\n // Normalization-changed run (possibly empty on one side).\n regions.push({\n bStart: prevB + 1,\n bEnd: bi,\n oLines: o.slice(prevO + 1, oi),\n exact: false,\n });\n }\n if (oi < o.length && bi < b.length) {\n regions.push({ bStart: bi, bEnd: bi + 1, oLines: [o[oi]!], exact: true });\n }\n prevO = oi;\n prevB = bi;\n }\n return regions;\n}\n\n/**\n * Merge a WYSIWYG serialization back onto the original source, keeping\n * original bytes for everything the user didn't touch.\n */\nexport function mergeNormalizedEdit(original: string, baseline: string, edited: string): string {\n if (baseline === edited) return original;\n if (original === baseline) return edited;\n\n const o = original.split(\"\\n\");\n const b = baseline.split(\"\\n\");\n const n = edited.split(\"\\n\");\n if (o.length > MAX_DIFF_LINES || b.length > MAX_DIFF_LINES || n.length > MAX_DIFF_LINES) {\n return edited;\n }\n\n // Which baseline lines did the user keep, and where do their insertions go?\n const keptB = new Uint8Array(b.length);\n /** N-lines the user inserted, anchored BEFORE baseline index `atB`. */\n const inserts = new Map<number, string[]>();\n {\n const pairs = lcsPairs(b, n);\n let prevB = -1;\n let prevN = -1;\n const walk: [number, number][] = [...pairs, [b.length, n.length]];\n for (const [bi, ni] of walk) {\n if (ni - prevN > 1) inserts.set(bi, n.slice(prevN + 1, ni));\n if (bi < b.length) keptB[bi] = 1;\n prevB = bi;\n prevN = ni;\n }\n void prevB;\n }\n\n const regions = alignRegions(o, b);\n const out: string[] = [];\n\n const flushInsertsBefore = (bIndex: number, pendingFrom: number): number => {\n for (let at = pendingFrom; at <= bIndex; at++) {\n const ins = inserts.get(at);\n if (ins) out.push(...ins);\n }\n return bIndex + 1;\n };\n\n let insertCursor = 0;\n for (const region of regions) {\n if (region.bStart === region.bEnd) {\n // Pure original deletion by normalization (no baseline lines). Keep the\n // original lines when the surrounding context is untouched by the user.\n const before = region.bStart - 1;\n const contextKept =\n (before < 0 || keptB[before] === 1) &&\n (region.bStart >= b.length || keptB[region.bStart] === 1);\n insertCursor = flushInsertsBefore(region.bStart - 1, insertCursor);\n if (contextKept) out.push(...region.oLines);\n continue;\n }\n\n let allKept = true;\n for (let bi = region.bStart; bi < region.bEnd; bi++) {\n if (keptB[bi] !== 1) {\n allKept = false;\n break;\n }\n }\n\n if (region.exact || allKept) {\n // Untouched by the user → original bytes win. (For exact regions the\n // texts are identical anyway; for normalized runs this UNDOES the\n // serializer's drift.) Emit interleaved insertions at their anchors.\n for (let bi = region.bStart; bi < region.bEnd; bi++) {\n insertCursor = flushInsertsBefore(bi, insertCursor);\n if (keptB[bi] === 1) {\n if (region.exact) out.push(...region.oLines);\n }\n }\n if (!region.exact) out.push(...region.oLines);\n } else {\n // The user edited inside this region → the edited serialization wins\n // for the whole region (locally normalized; the rest of the document\n // stays byte-exact). Kept lines inside it come from the baseline text.\n for (let bi = region.bStart; bi < region.bEnd; bi++) {\n insertCursor = flushInsertsBefore(bi, insertCursor);\n if (keptB[bi] === 1) out.push(b[bi]!);\n }\n }\n }\n // Trailing insertions (anchored at b.length).\n flushInsertsBefore(b.length, insertCursor);\n\n return out.join(\"\\n\");\n}\n","/**\n * Typed-`/` trigger detection for the Monaco source pane (the conflict-free way\n * to open the brand block menu — no keybinding, mirrors the WYSIWYG `/` trigger).\n *\n * Pure + Monaco-free so it unit-tests without the engine. The workspace feeds it\n * the just-edited line + the column the `/` landed on (from a Monaco content\n * change) and, when it's a valid trigger spot, gets back the model range of that\n * `/` so the menu can replace it with the inserted block (or delete it on cancel).\n *\n * A `/` is a valid trigger only at a textblock start (column 1) or right after\n * whitespace — so a `/` inside a word, a URL, or a path (`a/b`, `http://`) never\n * hijacks typing, matching the WYSIWYG `triggerAllowed` rule.\n */\n\n/** A Monaco `IRange`-shaped span (kept structural so this module imports no monaco). */\nexport interface SlashTriggerRange {\n startLineNumber: number;\n startColumn: number;\n endLineNumber: number;\n endColumn: number;\n}\n\n/**\n * Given the 1-based `line` number, the FULL line content AFTER the `/` was typed,\n * and the 1-based `slashColumn` the `/` now occupies, return the range covering\n * that `/` when it is a valid trigger — otherwise `null`.\n */\nexport function slashTriggerRange(\n line: number,\n lineContent: string,\n slashColumn: number,\n): SlashTriggerRange | null {\n // Sanity: the character at the reported column must actually be the `/`.\n if (lineContent.charAt(slashColumn - 1) !== \"/\") return null;\n // Allowed at the very start of the line, or immediately after whitespace.\n if (slashColumn > 1) {\n const before = lineContent.charAt(slashColumn - 2);\n if (!/\\s/.test(before)) return null;\n }\n return {\n startLineNumber: line,\n startColumn: slashColumn,\n endLineNumber: line,\n endColumn: slashColumn + 1,\n };\n}\n","/**\n * Shortcut helpers for the cross-pane slash menu (#271) — the MONACO half.\n *\n * Converts a shortcut string (e.g. `\"Mod-/\"`) into a Monaco keybinding bitmask.\n * This is the ONLY slash module that imports `monaco-editor`; it is imported only\n * by the Monaco-side surfaces (the source pane action in `MarkdownWorkspace`), so\n * the pure `./shortcut.ts` — imported by the Milkdown plugin — stays Monaco-free.\n *\n * INTERNAL — not exported from package barrels.\n */\nimport * as monaco from \"monaco-editor\";\n\n/** Supported letter key names (A-Z, case-insensitive in shortcut strings). */\nconst LETTER_KEY_MAP: Record<string, number> = (() => {\n const map: Record<string, number> = {};\n const kc = monaco.KeyCode as unknown as Record<string, number>;\n for (let i = 0; i < 26; i++) {\n const letter = String.fromCharCode(65 + i); // \"A\"..\"Z\"\n const code = kc[`Key${letter}`];\n if (code !== undefined) map[letter.toLowerCase()] = code;\n }\n return map;\n})();\n\nconst NAMED_KEY_MAP: Record<string, number> = {\n \"/\": monaco.KeyCode.Slash,\n backspace: monaco.KeyCode.Backspace,\n delete: monaco.KeyCode.Delete,\n escape: monaco.KeyCode.Escape,\n enter: monaco.KeyCode.Enter,\n tab: monaco.KeyCode.Tab,\n arrowup: monaco.KeyCode.UpArrow,\n arrowdown: monaco.KeyCode.DownArrow,\n arrowleft: monaco.KeyCode.LeftArrow,\n arrowright: monaco.KeyCode.RightArrow,\n};\n\n/**\n * Parse a shortcut string (e.g. `\"Mod-/\"`, `\"Mod-Shift-K\"`) into a Monaco\n * keybinding bitmask. Supports `Mod` (CtrlCmd), `Shift`, `Alt` modifiers and\n * a final key that is either a letter (A-Z) or one of the named keys in\n * `NAMED_KEY_MAP`. Throws for unrecognized final keys.\n *\n * The shipped default is `\"Mod-/\"` → `KeyMod.CtrlCmd | KeyCode.Slash`.\n */\nexport function parseShortcut(shortcut: string): number {\n const parts = shortcut.split(\"-\");\n let binding = 0;\n const keyPart = parts[parts.length - 1] ?? \"\";\n const modifiers = parts.slice(0, -1).map((m) => m.toLowerCase());\n\n for (const mod of modifiers) {\n if (mod === \"mod\") binding |= monaco.KeyMod.CtrlCmd;\n else if (mod === \"shift\") binding |= monaco.KeyMod.Shift;\n else if (mod === \"alt\") binding |= monaco.KeyMod.Alt;\n // Ctrl/Meta can also be named explicitly\n else if (mod === \"ctrl\") binding |= monaco.KeyMod.WinCtrl;\n }\n\n const key = keyPart.toLowerCase();\n const keyCode =\n NAMED_KEY_MAP[key] ??\n LETTER_KEY_MAP[key] ??\n (() => {\n throw new Error(`[@elabs-ai/components-editor] parseShortcut: unrecognized key \"${keyPart}\"`);\n })();\n\n return binding | keyCode;\n}\n","\"use client\";\n\n/**\n * MarkdownPreview — renders markdown to REAL @brand components (not default HTML).\n *\n * Built on Streamdown (the same react-markdown + remark engine @elabs-ai/components-ai uses), with\n * a branded `components` map: `#` → Heading, paragraph → Text, link → Link, list →\n * List, table → @elabs-ai/components-ui Table, `---` → Separator, blockquote → Blockquote, and the\n * `:::card`/`:::callout`/`::metric`/`:::timeline` directives → Card / Alert /\n * MetricBlock / Timeline. The directive plugins come from the SHARED\n * `buildMarkdownPlugins()` array, so the preview and the Milkdown editor parse the\n * brand dialect identically. Unknown directives render an explicit error block.\n *\n * Five production seams (#L1 / #L4 / #L18 / #L-wikilink / #L-transclusion):\n * - ```mermaid fences render through the branded `MermaidDiagram`;\n * - `resolveUrl` rewrites image/link targets (private-repo assets, relative paths);\n * - every block carries `data-sourcepos=\"start:end\"` (1-based source lines), and an\n * `annotations` prop washes changed blocks / marks removals — the \"ghost diff\";\n * - `resolveWikilink` rewrites `[[target]]` / `[[target|alias]]` /\n * `[[target#anchor|alias]]` into normal mdast LINK nodes (Obsidian-vault style);\n * - `resolveTransclusion` embeds `![[target]]` / `![[target#section]]` as a\n * visually-nested, labelled block (recursion capped at 3 levels).\n */\nimport {\n Alert,\n AlertDescription,\n AlertTitle,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n Separator,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport {\n createContext,\n forwardRef,\n isValidElement,\n useContext,\n useMemo,\n type HTMLAttributes,\n type ReactElement,\n type ReactNode,\n} from \"react\";\nimport {\n Streamdown,\n defaultRehypePlugins,\n defaultRemarkPlugins,\n type Components,\n} from \"streamdown\";\nimport type { PluggableList } from \"unified\";\nimport { visit } from \"unist-util-visit\";\n\nimport {\n BRAND_DIRECTIVE_ATTR,\n BRAND_DIRECTIVE_INLINE_TAG,\n BRAND_DIRECTIVE_PROP,\n BRAND_DIRECTIVE_TAG,\n buildMarkdownPlugins,\n type BrandDirectivePayload,\n type MarkdownDirectiveRenderer,\n type MarkdownExtensions,\n type MarkdownFenceRenderer,\n} from \"../lib/markdown/directives\";\nimport {\n annotationForRange,\n removedMarkerAt,\n shiftAnnotations,\n type MarkdownAnnotation,\n} from \"../lib/markdown/diff\";\nimport { parseFrontmatter } from \"../lib/markdown/frontmatter\";\nimport { CalcBlock, CalcInline, type EvaluateCalc } from \"../calc-block\";\nimport { MermaidDiagram } from \"../mermaid-diagram\";\nimport { MetricBlock } from \"../metric-block\";\nimport { Blockquote, Heading, Link, List, ListItem, Text, type HeadingLevel } from \"../prose\";\nimport { Timeline, type TimelineStatus } from \"../timeline\";\nimport { CodeFence, fenceLanguage } from \"./code-fence\";\nimport { parseMarkdownOutline } from \"../markdown-outline\";\nimport remarkMath from \"remark-math\";\nimport {\n Bibliography,\n CITE_TAG,\n CITE_PROP,\n CitationProvider,\n collectCitations,\n InlineCite,\n remarkBrandCitations,\n type CitationStyle,\n type CollectedCitations,\n type ResolveCitation,\n} from \"../markdown-academic/citations\";\nimport {\n FOOTNOTE_ITEM_TAG,\n FOOTNOTE_LIST_TAG,\n FOOTNOTE_PROP,\n FOOTNOTE_REF_TAG,\n FootnoteItem,\n FootnoteList,\n FootnoteRef,\n remarkBrandFootnotes,\n} from \"../markdown-academic/footnotes\";\nimport {\n MATH_BLOCK_TAG,\n MATH_INLINE_TAG,\n MATH_PROP,\n MathBlockTag,\n MathInlineTag,\n remarkBrandMath,\n} from \"../markdown-academic/math\";\nimport { TableOfContents, TocProvider, useHeadingId } from \"../markdown-academic/toc\";\nimport {\n IterationDirective,\n specFromDirective,\n type EvaluateIteration,\n type InterpolateTemplate,\n} from \"../markdown-iteration\";\n\n// Streamdown's own default remark plugins (gfm etc.). The brand directive\n// plugins are appended PER-INSTANCE inside the component, because the known\n// directive-name set depends on the consumer's `extensions` (see the `plugins`\n// memo below).\nconst baseRemarkPlugins = Object.values(defaultRemarkPlugins);\n\n/**\n * Custom element for inline transclusion embeds (`![[target]]`). A SEPARATE tag\n * from the brand-directive tags so the sanitize schema stays narrow. The JSON\n * payload property is `data-transclusion` (hast: `dataTransclusion`).\n */\nconst BRAND_TRANSCLUSION_TAG = \"brand-transclusion\";\nconst BRAND_TRANSCLUSION_ATTR = \"data-transclusion\";\nconst BRAND_TRANSCLUSION_PROP = \"dataTransclusion\";\n\n// Allow-list uses the hast PROPERTY name (camelCase), which is what survives\n// Streamdown's sanitization — not the rendered `data-brand` attribute name.\n// Both directive tags (block/leaf + inline) carry the same JSON payload property.\nconst allowedTags = {\n [BRAND_DIRECTIVE_TAG]: [BRAND_DIRECTIVE_PROP],\n [BRAND_DIRECTIVE_INLINE_TAG]: [BRAND_DIRECTIVE_PROP],\n [BRAND_TRANSCLUSION_TAG]: [BRAND_TRANSCLUSION_PROP],\n // Academic layer (footnotes / math / citations) — opt-in via props, but the\n // tags are always allow-listed (harmless when the feature is off).\n [FOOTNOTE_REF_TAG]: [FOOTNOTE_PROP],\n [FOOTNOTE_ITEM_TAG]: [FOOTNOTE_PROP],\n [FOOTNOTE_LIST_TAG]: [],\n [MATH_BLOCK_TAG]: [MATH_PROP],\n [MATH_INLINE_TAG]: [MATH_PROP],\n [CITE_TAG]: [CITE_PROP],\n};\n\n/** All academic custom tags + their payload props, for the sanitize schema. */\nconst ACADEMIC_TAGS = [\n FOOTNOTE_REF_TAG,\n FOOTNOTE_ITEM_TAG,\n FOOTNOTE_LIST_TAG,\n MATH_BLOCK_TAG,\n MATH_INLINE_TAG,\n CITE_TAG,\n];\nconst ACADEMIC_TAG_ATTRS: Record<string, string[]> = {\n [FOOTNOTE_REF_TAG]: [FOOTNOTE_PROP],\n [FOOTNOTE_ITEM_TAG]: [FOOTNOTE_PROP],\n [FOOTNOTE_LIST_TAG]: [],\n [MATH_BLOCK_TAG]: [MATH_PROP],\n [MATH_INLINE_TAG]: [MATH_PROP],\n [CITE_TAG]: [CITE_PROP],\n};\n\n/**\n * Streamdown's default sanitize schema only lets http(s) image `src` through,\n * which kills the `resolveUrl` story (#L4): authenticated repo assets arrive\n * as `data:`/`blob:` URLs. Extend the SAME default pipeline (raw → sanitize →\n * harden) with those protocols — harden itself already validates them.\n */\nconst rehypePlugins = (() => {\n const defaults = defaultRehypePlugins as Record<string, unknown>;\n const sanitize = defaults.sanitize as [\n unknown,\n {\n protocols?: Record<string, unknown[]>;\n tagNames?: string[];\n attributes?: Record<string, unknown[]>;\n },\n ];\n const schema = sanitize[1] ?? {};\n const protocols = (schema.protocols ?? {}) as Record<string, unknown[]>;\n const extendedSanitize = [\n sanitize[0],\n {\n ...schema,\n protocols: { ...protocols, src: [...(protocols.src ?? [\"http\", \"https\"]), \"data\", \"blob\"] },\n // Custom rehypePlugins bypass Streamdown's `allowedTags` merge — so the brand-directive\n // tags, the transclusion tag, and their JSON payload properties all go into the schema here.\n tagNames: [\n ...(schema.tagNames ?? []),\n BRAND_DIRECTIVE_TAG,\n BRAND_DIRECTIVE_INLINE_TAG,\n BRAND_TRANSCLUSION_TAG,\n ...ACADEMIC_TAGS,\n ],\n attributes: {\n ...(schema.attributes ?? {}),\n [BRAND_DIRECTIVE_TAG]: [BRAND_DIRECTIVE_PROP],\n [BRAND_DIRECTIVE_INLINE_TAG]: [BRAND_DIRECTIVE_PROP],\n [BRAND_TRANSCLUSION_TAG]: [BRAND_TRANSCLUSION_PROP],\n ...ACADEMIC_TAG_ATTRS,\n },\n },\n ];\n return [defaults.raw, extendedSanitize, defaults.harden] as PluggableList;\n})();\n\n/** Treat the whole document as one block (keeps multi-line directives intact). */\nconst singleBlock = (md: string): string[] => [md];\n\n/** react-markdown passes `node` to every component — strip it before spreading. */\ntype MdProps = { node?: unknown; children?: ReactNode } & Record<string, unknown>;\n\n/* ------------------------------------------------------------------ */\n/* Contexts (keep the `components` map static across renders) */\n/* ------------------------------------------------------------------ */\n\nconst AnnotationsContext = createContext<MarkdownAnnotation[]>([]);\n\n/**\n * In-document search state (term + the active hit's line), threaded to the\n * blocks: the active block gets a primary wash; mermaid fences mark matching\n * nodes. Lines are 1-based relative to the STRIPPED markdown (the provider\n * shifts the public prop).\n */\ninterface SearchState {\n term?: string;\n activeLine?: number;\n /** Stripped source lines — used to hand the active line's text to diagrams. */\n lines: readonly string[];\n}\n\nconst SearchContext = createContext<SearchState>({ lines: [] });\n\n/**\n * Hover affordances beside headings (#L6 companion): a generic render-prop —\n * the preview knows nothing about what the action does (pinning, anchors,\n * copy-link…). Revealed on heading hover / focus, and kept visible while the\n * slot contains a pressed toggle (`aria-pressed=\"true\"`).\n */\nexport interface MarkdownHeadingInfo {\n level: HeadingLevel;\n /** Plain text content of the heading. */\n text: string;\n /** 1-based start line in the frontmatter-STRIPPED source (= `data-sourcepos`). */\n line?: number;\n}\n\nconst HeadingActionsContext = createContext<((heading: MarkdownHeadingInfo) => ReactNode) | null>(\n null,\n);\n\n/**\n * The resolved render registry for this preview instance: directive renderers by\n * name + fence renderers by language (the `extensions` prop, plus the calc fence\n * synthesized from `evaluate`). Consulted by `BrandDirective` /\n * `BrandInlineDirective` (directives) and `PreBlock` (fences).\n */\ninterface PreviewRegistry {\n directives: Map<string, MarkdownDirectiveRenderer>;\n fences: Map<string, MarkdownFenceRenderer>;\n}\n\nconst EMPTY_REGISTRY: PreviewRegistry = { directives: new Map(), fences: new Map() };\nconst RegistryContext = createContext<PreviewRegistry>(EMPTY_REGISTRY);\n\n/**\n * Consumer-supplied link-preview render slot. When supplied, every rendered `<a>`\n * is wrapped via this function; the consumer attaches its own hover card /\n * popover. The library never fetches — the consumer owns the preview content.\n * Default (not supplied) → the plain `Link` component.\n */\nconst LinkPreviewContext = createContext<((href: string, children: ReactNode) => ReactNode) | null>(\n null,\n);\n\n/**\n * Transclusion resolver — threaded into `TransclusionBlock` so recursive\n * `MarkdownPreview` renders can access the same hook without prop-drilling.\n */\nconst TransclusionResolverContext = createContext<\n ((target: string, opts: TransclusionResolveOptions) => string | null) | null\n>(null);\n\n/** Maximum nesting depth for `![[transclusion]]` embeds (prevents cycles). */\nconst TRANSCLUSION_MAX_DEPTH = 3;\n\n/** Tracks the current embed depth; 0 = top-level document. */\nconst TransclusionDepthContext = createContext<number>(0);\n\n/** Flatten a rendered heading's children to plain text (descends elements). */\nfunction flattenNodeText(node: ReactNode): string {\n if (typeof node === \"string\" || typeof node === \"number\") return String(node);\n if (Array.isArray(node)) return node.map((n) => flattenNodeText(n as ReactNode)).join(\"\");\n if (isValidElement(node)) {\n return flattenNodeText((node.props as { children?: ReactNode }).children);\n }\n return \"\";\n}\n\nexport type MarkdownUrlKind = \"image\" | \"link\";\ntype UrlResolver = (url: string, kind: MarkdownUrlKind) => string;\n\n/**\n * URL rewriting must happen at the REMARK stage: Streamdown's sanitizer\n * (harden-react-markdown) runs on the hast and blocks unresolvable relative\n * URLs before any React component sees them — so the resolver maps them to\n * absolute (or protocol-carrying) URLs first.\n */\ninterface MdUrlNode {\n type: string;\n url?: string;\n}\n\nfunction remarkResolveUrls(resolve: UrlResolver) {\n // Unified plugin shape: an ATTACHER that returns the transformer.\n return function attacher() {\n return (tree: unknown) => {\n visit(tree as Parameters<typeof visit>[0], (node) => {\n const n = node as MdUrlNode;\n if (n.type === \"image\" || n.type === \"imageReference\") {\n if (typeof n.url === \"string\") n.url = resolve(n.url, \"image\");\n } else if (n.type === \"link\" || n.type === \"definition\") {\n if (typeof n.url === \"string\") n.url = resolve(n.url, \"link\");\n }\n });\n };\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Wikilink resolver types (exported for consumers) */\n/* ------------------------------------------------------------------ */\n\n/**\n * Options passed to `resolveWikilink` for each wikilink found in the document.\n */\nexport interface WikilinkResolveOptions {\n /** The `#anchor` fragment, if present — e.g. `[[target#Section 1]]` → `\"Section 1\"`. */\n anchor?: string;\n}\n\n/**\n * Options passed to `resolveTransclusion` for each transclusion embed found.\n */\nexport interface TransclusionResolveOptions {\n /**\n * A `#section` heading, if present — e.g. `![[target#Introduction]]` → `\"Introduction\"`.\n * The consumer can use this to extract only that section from the document.\n */\n section?: string;\n}\n\n/* ------------------------------------------------------------------ */\n/* remarkResolveWikilinks — `[[target]]` → mdast link node */\n/* ------------------------------------------------------------------ */\n\n/**\n * Wikilink syntax supported:\n * `[[target]]` → link text = target, href from resolveWikilink(target, {})\n * `[[target|alias]]` → link text = alias, href from resolveWikilink(target, {})\n * `[[target#anchor]]` → link text = target, href from resolveWikilink(target, { anchor })\n * `[[target#anchor|alias]]` → link text = alias, href from resolveWikilink(target, { anchor })\n * (Obsidian style: anchor is on the TARGET side, before the `|` separator)\n *\n * Unresolvable wikilinks (hook returns null) render as plain text `[[original]]`.\n * The produced link flows through the existing `a:` renderer (resolveUrl + renderLinkPreview apply).\n */\nfunction remarkResolveWikilinks(\n resolve: (target: string, opts: WikilinkResolveOptions) => string | null,\n) {\n // Match `[[...]]` but NOT `![[...]]` (transclusion is handled separately).\n // Lookbehind `(?<!!)` ensures we don't consume transclusion prefixes.\n const WIKILINK_RE = /(?<!!)\\[\\[([^\\]]+)\\]\\]/g;\n\n return function attacher() {\n return (tree: unknown) => {\n visit(tree as Parameters<typeof visit>[0], \"text\", (node, index, parent) => {\n const n = node as { type: string; value: string };\n const p = parent as { children?: unknown[] } | undefined;\n if (!p?.children || index == null || typeof n.value !== \"string\") return;\n\n const text = n.value;\n // Fast path: no wikilinks in this text node.\n if (!text.includes(\"[[\")) return;\n\n const newChildren: unknown[] = [];\n let lastIndex = 0;\n WIKILINK_RE.lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = WIKILINK_RE.exec(text)) !== null) {\n // Text before this wikilink.\n if (match.index > lastIndex) {\n newChildren.push({ type: \"text\", value: text.slice(lastIndex, match.index) });\n }\n\n const inner = match[1]!;\n // Split on FIRST `|` for alias — anchor lives on the target side (before `|`).\n const pipeIdx = inner.indexOf(\"|\");\n const targetPart = pipeIdx !== -1 ? inner.slice(0, pipeIdx) : inner;\n const alias = pipeIdx !== -1 ? inner.slice(pipeIdx + 1) : undefined;\n\n // Split target on FIRST `#` for anchor.\n const hashIdx = targetPart.indexOf(\"#\");\n const target = hashIdx !== -1 ? targetPart.slice(0, hashIdx) : targetPart;\n const anchor = hashIdx !== -1 ? targetPart.slice(hashIdx + 1) : undefined;\n\n const opts: WikilinkResolveOptions = anchor ? { anchor } : {};\n const href = resolve(target.trim(), opts);\n const linkText = alias?.trim() || target.trim();\n\n if (href === null) {\n // Unresolvable → plain text, preserving the original `[[…]]` literal.\n newChildren.push({ type: \"text\", value: match[0] });\n } else {\n // A normal mdast link — flows through the existing `a:` renderer.\n newChildren.push({\n type: \"link\",\n url: href,\n title: null,\n children: [{ type: \"text\", value: linkText }],\n });\n }\n\n lastIndex = match.index + match[0].length;\n }\n\n // Remaining text after the last wikilink.\n if (lastIndex < text.length) {\n newChildren.push({ type: \"text\", value: text.slice(lastIndex) });\n }\n\n // Only splice if we actually found wikilinks.\n if (newChildren.length > 0) {\n p.children.splice(index, 1, ...newChildren);\n // Return the next index to skip past the newly inserted nodes.\n return index + newChildren.length;\n }\n });\n };\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* remarkResolveTransclusions — `![[target]]` → brand-transclusion */\n/* ------------------------------------------------------------------ */\n\ninterface TransclusionPayload {\n target: string;\n section?: string;\n}\n\n/**\n * Rewrites standalone `![[target]]` / `![[target#section]]` lines into a custom\n * `<brand-transclusion>` element carrying a JSON payload. The React component\n * (`TransclusionBlock`) resolves + renders the content recursively, with a\n * depth cap to prevent infinite loops.\n *\n * \"Standalone\" means the wikilink embed appears as its own paragraph (the most\n * common Obsidian authoring pattern). Embeds mid-sentence are also caught via\n * the text-node transform but are treated as paragraph-level blocks by inserting\n * a paragraph wrapper — this keeps valid mdast structure.\n */\nfunction remarkResolveTransclusions() {\n // A STANDALONE transclusion: a paragraph whose only content is `![[target]]`\n // (the Obsidian authoring pattern). Transclusion is a BLOCK embed, so we\n // rewrite the whole PARAGRAPH (not an inline text node — a figure inside <p>\n // would be invalid HTML) and use `data.hName`/`hProperties` (the same reliable\n // mechanism the brand directives use) rather than a raw `html` node, which does\n // not round-trip through Streamdown's rehype pipeline.\n const STANDALONE_RE = /^!\\[\\[([^\\]]+)\\]\\]$/;\n\n return function attacher() {\n return (tree: unknown) => {\n visit(tree as Parameters<typeof visit>[0], \"paragraph\", (node) => {\n const n = node as {\n children?: { type: string; value?: string }[];\n data?: { hName?: string; hProperties?: Record<string, unknown> };\n };\n if (!n.children || n.children.length !== 1) return;\n const child = n.children[0]!;\n if (child.type !== \"text\" || typeof child.value !== \"string\") return;\n\n const match = child.value.trim().match(STANDALONE_RE);\n if (!match) return;\n\n const inner = match[1]!;\n const hashIdx = inner.indexOf(\"#\");\n const target = (hashIdx !== -1 ? inner.slice(0, hashIdx) : inner).trim();\n const section = hashIdx !== -1 ? inner.slice(hashIdx + 1).trim() : undefined;\n const payload: TransclusionPayload = section ? { target, section } : { target };\n\n const data = n.data ?? (n.data = {});\n data.hName = BRAND_TRANSCLUSION_TAG;\n data.hProperties = { [BRAND_TRANSCLUSION_PROP]: JSON.stringify(payload) };\n n.children = []; // consumed into the payload; TransclusionBlock renders it\n });\n };\n };\n}\n\ninterface SourcePos {\n start: number;\n end: number;\n}\n\n/** Does a DESCENDANT list item already contain this line? (innermost li wins) */\nfunction nestedItemContains(node: unknown, line: number): boolean {\n const kids = (node as { children?: unknown[] } | undefined)?.children ?? [];\n for (const kid of kids) {\n const el = kid as { tagName?: string };\n if (el.tagName === \"li\") {\n const pos = getSourcePos(kid);\n if (pos && line >= pos.start && line <= pos.end) return true;\n }\n if (nestedItemContains(kid, line)) return true;\n }\n return false;\n}\n\nfunction getSourcePos(node: unknown): SourcePos | undefined {\n const pos = (\n node as { position?: { start?: { line?: number }; end?: { line?: number } } } | undefined\n )?.position;\n if (typeof pos?.start?.line !== \"number\") return undefined;\n return { start: pos.start.line, end: pos.end?.line ?? pos.start.line };\n}\n\nfunction RemovedMarker({ count }: { count: number }) {\n return (\n <div\n role=\"note\"\n aria-label={`${count} ${count === 1 ? \"line\" : \"lines\"} removed here`}\n className=\"flex items-center gap-2 text-meta text-destructive-text\"\n >\n <span aria-hidden=\"true\" className=\"font-mono\">\n −\n </span>\n <span aria-hidden=\"true\" className=\"flex-1 border-t border-dashed border-destructive/40\" />\n <span>\n {count} {count === 1 ? \"line\" : \"lines\"} removed\n </span>\n <span aria-hidden=\"true\" className=\"flex-1 border-t border-dashed border-destructive/40\" />\n </div>\n );\n}\n\n/**\n * Wrap a block renderer with the sourcepos + annotation layer: stamps\n * `data-sourcepos`, washes added/modified blocks (accent rail + tint), washes\n * the active search hit's block (primary tint), and renders the\n * removed-content marker anchored to this block.\n *\n * `searchWash: false` opts a block out of the active-search wash — `pre`\n * fences (incl. mermaid) carry their own treatment.\n */\nfunction annotated(render: (props: MdProps) => ReactNode, searchWash = true) {\n return function AnnotatedBlock(props: MdProps) {\n const annotations = useContext(AnnotationsContext);\n const search = useContext(SearchContext);\n const pos = getSourcePos(props.node);\n const enriched = pos ? { ...props, \"data-sourcepos\": `${pos.start}:${pos.end}` } : props;\n\n const wash =\n pos && annotations.length > 0\n ? annotationForRange(annotations, pos.start, pos.end)\n : undefined;\n const removed =\n pos && annotations.length > 0 ? removedMarkerAt(annotations, pos.start) : undefined;\n const activeSearch =\n searchWash &&\n pos != null &&\n search.activeLine != null &&\n search.activeLine >= pos.start &&\n search.activeLine <= pos.end;\n\n let content = render(enriched);\n if (!wash && !removed && !activeSearch) return content;\n\n if (wash) {\n content = (\n <div\n data-annotation={wash.kind}\n className=\"border-s-2 border-s-success bg-success/10 py-1.5 pe-2 ps-3\"\n >\n {content}\n </div>\n );\n }\n if (activeSearch) {\n content = (\n <div data-search-active=\"\" className=\"-mx-2 rounded-md bg-primary/10 px-2 py-1\">\n {content}\n </div>\n );\n }\n return (\n <>\n {removed ? <RemovedMarker count={removed.removedCount ?? 1} /> : null}\n {content}\n </>\n );\n };\n}\n\nfunction heading(level: HeadingLevel) {\n return function HeadingMd({ node: _n, children, ...rest }: MdProps) {\n const headingActions = useContext(HeadingActionsContext);\n const start = (rest[\"data-sourcepos\"] as string | undefined)?.split(\":\")[0];\n const line = start ? Number(start) : undefined;\n // Stable slug id (only when TOC is enabled) so `::toc` anchors resolve.\n const headingId = useHeadingId(line);\n const slot = headingActions?.({\n level,\n text: flattenNodeText(children),\n line,\n });\n return (\n <Heading\n level={level}\n id={headingId}\n {...(rest as HTMLAttributes<HTMLHeadingElement>)}\n className={cn(\n slot ? \"group/heading\" : undefined,\n headingId ? \"scroll-mt-4\" : undefined,\n rest.className as string | undefined,\n )}\n >\n {children}\n {slot ? (\n <span\n // GitHub-anchor grammar: revealed on hover/focus; stays visible\n // while a contained toggle is pressed (a pinned section keeps its pin).\n className=\"ms-1.5 inline-flex align-middle opacity-0 transition-opacity duration-fast ease-standard focus-within:opacity-100 group-hover/heading:opacity-100 has-[[aria-pressed=true]]:opacity-100 motion-reduce:transition-none\"\n >\n {slot}\n </span>\n ) : null}\n </Heading>\n );\n };\n}\n\nconst CALLOUT_VARIANT: Record<string, \"default\" | \"info\" | \"success\" | \"warning\" | \"destructive\"> =\n {\n info: \"info\",\n note: \"info\",\n tip: \"success\",\n success: \"success\",\n warning: \"warning\",\n caution: \"warning\",\n danger: \"destructive\",\n error: \"destructive\",\n destructive: \"destructive\",\n };\n\nconst TIMELINE_STATUS: Record<string, TimelineStatus> = {\n done: \"done\",\n complete: \"done\",\n completed: \"done\",\n active: \"active\",\n current: \"active\",\n pending: \"pending\",\n todo: \"pending\",\n};\n\nfunction UnknownBlock({ name }: { name: string }) {\n return (\n <Alert variant=\"destructive\">\n <AlertTitle>Unknown block: {name}</AlertTitle>\n <AlertDescription>\n No renderer is mapped for <code>:::{name}</code>. Add it to the brand directive registry, or\n fix the directive name.\n </AlertDescription>\n </Alert>\n );\n}\n\n/** Parse the JSON payload off a `<brand-directive*>` element's props. */\nfunction readDirectivePayload(rest: MdProps): BrandDirectivePayload | \"malformed\" | null {\n const raw =\n (rest[BRAND_DIRECTIVE_ATTR] as string | undefined) ?? (rest.dataBrand as string | undefined);\n if (!raw) return null;\n try {\n return JSON.parse(raw) as BrandDirectivePayload;\n } catch {\n return \"malformed\";\n }\n}\n\nfunction BrandDirective({ node: _n, children, ...rest }: MdProps) {\n const registry = useContext(RegistryContext);\n const payload = readDirectivePayload(rest);\n if (payload === null) return null;\n if (payload === \"malformed\") return <UnknownBlock name=\"malformed\" />;\n\n if (!payload.known) return <UnknownBlock name={payload.name} />;\n\n const attrs = payload.attributes ?? {};\n switch (payload.name) {\n case \"card\":\n return (\n <Card>\n {attrs.title ? (\n <CardHeader>\n <CardTitle>{attrs.title}</CardTitle>\n </CardHeader>\n ) : null}\n <CardContent className={cn(!attrs.title && \"pt-6\")}>{children}</CardContent>\n </Card>\n );\n case \"callout\":\n return (\n <Alert variant={CALLOUT_VARIANT[attrs.type ?? \"\"] ?? \"default\"}>\n {/* Callout title is a label, NOT a document section heading — a callout is\n inserted INTO the content flow, so an <h5> (AlertTitle's default for a\n standalone banner) would break the document heading outline. Render the\n same visual as a non-heading <div> instead (see #21). */}\n {attrs.title ? (\n <div className=\"mb-1 font-medium leading-none tracking-tight\">{attrs.title}</div>\n ) : null}\n <AlertDescription>{children}</AlertDescription>\n </Alert>\n );\n case \"metric\":\n return (\n <MetricBlock\n label={attrs.label ?? \"\"}\n value={attrs.value ?? \"\"}\n description={attrs.description}\n delta={attrs.delta}\n deltaDirection={\n attrs.delta?.startsWith(\"+\") ? \"up\" : attrs.delta?.startsWith(\"-\") ? \"down\" : \"neutral\"\n }\n />\n );\n case \"timeline\":\n return (\n <Timeline\n items={(payload.items ?? []).map((it) => ({\n title: it.title,\n status: TIMELINE_STATUS[it.status] ?? \"pending\",\n }))}\n />\n );\n default: {\n // Not a built-in → a consumer-registered directive (`extensions`). The\n // name reached `known: true` only because it was registered, so a renderer\n // should exist; if somehow missing, surface the unknown-block error.\n const renderer = registry.directives.get(payload.name);\n if (renderer && (!renderer.kinds || renderer.kinds.includes(payload.kind))) {\n return (\n <>\n {renderer.render({\n name: payload.name,\n kind: payload.kind,\n attributes: attrs,\n children,\n textValue: payload.label,\n rawBody: payload.body,\n })}\n </>\n );\n }\n return <UnknownBlock name={payload.name} />;\n }\n }\n}\n\n/**\n * Inline (`:name[label]{attrs}`) directives. Rendered via a SEPARATE tag so it\n * stays in the text flow (no block wrapper / annotation layer). Only registered\n * inline names reach here (unregistered ones were restored to literal text by\n * the parser); a registered name with no inline renderer falls back to its label.\n */\nfunction BrandInlineDirective({ node: _n, children, ...rest }: MdProps) {\n const registry = useContext(RegistryContext);\n const payload = readDirectivePayload(rest);\n if (payload === null || payload === \"malformed\") return <>{children}</>;\n\n const renderer = registry.directives.get(payload.name);\n if (!renderer || (renderer.kinds && !renderer.kinds.includes(\"inline\"))) {\n return <>{children}</>;\n }\n return (\n <>\n {renderer.render({\n name: payload.name,\n kind: \"inline\",\n attributes: payload.attributes ?? {},\n children,\n textValue: payload.label,\n })}\n </>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Mermaid fences + resolved images/links */\n/* ------------------------------------------------------------------ */\n\n/** Flatten react-markdown `children` (string | array) into the raw fence text. */\nfunction fenceText(children: ReactNode): string {\n if (typeof children === \"string\") return children;\n if (Array.isArray(children)) return children.map((c) => fenceText(c as ReactNode)).join(\"\");\n return \"\";\n}\n\nfunction isMermaidCodeElement(child: unknown): child is ReactElement<{\n className?: string;\n children?: ReactNode;\n}> {\n return (\n isValidElement(child) &&\n /\\blanguage-mermaid\\b/.test((child.props as { className?: string } | null)?.className ?? \"\")\n );\n}\n\nfunction PreBlock({ node, children, ...rest }: MdProps) {\n const search = useContext(SearchContext);\n const registry = useContext(RegistryContext);\n const pos = getSourcePos(node);\n const activeInBlock =\n pos != null &&\n search.activeLine != null &&\n search.activeLine >= pos.start &&\n search.activeLine <= pos.end;\n\n const list = Array.isArray(children) ? children : [children];\n // Mermaid stays a PRIVILEGED built-in: it carries search-highlight + active-line\n // coupling that the generic `{ source, lang }` fence contract deliberately omits.\n const mermaidChild = list.find(isMermaidCodeElement);\n if (mermaidChild) {\n const chart = fenceText((mermaidChild.props as { children?: ReactNode }).children).replace(\n /\\n$/,\n \"\",\n );\n return (\n <MermaidDiagram\n chart={chart}\n // The diagram must stay addressable by source line (outline/search jumps).\n data-sourcepos={pos ? `${pos.start}:${pos.end}` : undefined}\n highlightTerm={search.term}\n activeText={\n activeInBlock && search.activeLine != null\n ? search.lines[search.activeLine - 1]\n : undefined\n }\n />\n );\n }\n // Registered fences (the seam): calc is registered from the `evaluate` prop;\n // consumers register their own via `extensions.fences`. The library renders the\n // result; the consumer's renderer owns any domain hook. Stamp `data-sourcepos`\n // so the block stays addressable by outline/search jumps.\n const codeEl = list.find(isValidElement) as\n | ReactElement<{ className?: string; children?: ReactNode }>\n | undefined;\n const fenceLang = fenceLanguage(codeEl?.props.className);\n const fenceRenderer = fenceLang ? registry.fences.get(fenceLang) : undefined;\n if (fenceLang && fenceRenderer && codeEl) {\n const source = fenceText(codeEl.props.children).replace(/\\n$/, \"\");\n const rendered = fenceRenderer.render({ source, lang: fenceLang });\n return pos ? <div data-sourcepos={`${pos.start}:${pos.end}`}>{rendered}</div> : <>{rendered}</>;\n }\n // Non-mermaid, unregistered fences: tokenized highlighting + language chip + hover copy.\n // The fence keeps its source-line address (`data-sourcepos` arrives via\n // `rest` onto the wrapper) and the active-search wash on the inner pre.\n const codeText = fenceText(codeEl ? codeEl.props.children : (children as ReactNode)).replace(\n /\\n$/,\n \"\",\n );\n return (\n <CodeFence\n {...(rest as HTMLAttributes<HTMLElement>)}\n codeText={codeText}\n language={fenceLang}\n searchActive={activeInBlock}\n >\n {children}\n </CodeFence>\n );\n}\n\nfunction ImageMd({ node: _n, src, alt, ...rest }: MdProps) {\n return (\n <img\n src={src as string}\n alt={(alt as string) ?? \"\"}\n loading=\"lazy\"\n className=\"max-w-full rounded-md border border-border\"\n {...(rest as HTMLAttributes<HTMLImageElement>)}\n />\n );\n}\n\nfunction LinkMd({ node: _n, href, children, ...rest }: MdProps) {\n const renderLinkPreview = useContext(LinkPreviewContext);\n const anchor = (\n <Link href={href as string} {...(rest as HTMLAttributes<HTMLAnchorElement>)}>\n {children}\n </Link>\n );\n if (renderLinkPreview && typeof href === \"string\") {\n return <>{renderLinkPreview(href, anchor)}</>;\n }\n return anchor;\n}\n\n/**\n * Renders a `![[target]]` / `![[target#section]]` transclusion embed.\n *\n * - Reads the payload from the `data-transclusion` attribute (JSON).\n * - Calls `resolveTransclusion(target, { section })` to get markdown text.\n * - If null → renders the literal `![[target]]` as plain text.\n * - If at the depth cap → renders a \"transclusion too deep\" notice.\n * - Otherwise → recursively renders the returned markdown via `MarkdownPreview`\n * inside a visually-nested, semantically-labelled block.\n *\n * The block uses a quiet inset separation: border-start rail + muted ground\n * (no redundant border over the fill; satisfies the separation grammar).\n */\nfunction TransclusionBlock({ node: _n, ...rest }: MdProps) {\n const resolveTransclusion = useContext(TransclusionResolverContext);\n const depth = useContext(TransclusionDepthContext);\n const linkPreview = useContext(LinkPreviewContext);\n\n // Parse the JSON payload from the hast attribute.\n const rawAttr =\n (rest[BRAND_TRANSCLUSION_ATTR] as string | undefined) ??\n (rest.dataTransclusion as string | undefined);\n\n if (!rawAttr || !resolveTransclusion) {\n // No resolver or malformed — render as literal fallback.\n return (\n <span>{rawAttr ? `![[${(JSON.parse(rawAttr) as TransclusionPayload).target}]]` : null}</span>\n );\n }\n\n let payload: TransclusionPayload;\n try {\n payload = JSON.parse(rawAttr) as TransclusionPayload;\n } catch {\n return null;\n }\n\n const { target, section } = payload;\n const label = section ? `${target}#${section}` : target;\n\n if (depth >= TRANSCLUSION_MAX_DEPTH) {\n return (\n <figure\n aria-label={`Embedded: ${label}`}\n className=\"my-3 rounded-md border-s-2 border-s-muted bg-muted/40 px-4 py-3\"\n data-testid=\"transclusion-block\"\n data-transclusion-depth={depth}\n >\n <figcaption className=\"mb-1 text-meta text-muted-foreground\">{label}</figcaption>\n <p className=\"text-meta text-muted-foreground italic\">\n Transclusion too deep — embed skipped.\n </p>\n </figure>\n );\n }\n\n const content = resolveTransclusion(target, section ? { section } : {});\n\n if (content === null) {\n // Unresolvable → plain text, never a broken element.\n return <span>{`![[${label}]]`}</span>;\n }\n\n // Recursive render: inner MarkdownPreview reads depth+1 from context.\n // We thread the SAME linkPreview context so consumer hooks propagate.\n // NOTE: We render a plain MarkdownPreview without frontmatter strip by default.\n // We must not import MarkdownPreview here (circular ref) — instead we render the\n // Streamdown directly with the same plugin set. We solve this by rendering a\n // lightweight recursive wrapper that bypasses the outer forwardRef. We achieve\n // this by reading the current plugin array from the outer `plugins` memo (not\n // possible here) — so instead we compose a separate inner pipeline with the same\n // base plugins. The new contexts (depth + resolver + linkPreview) are provided by\n // the outer MarkdownPreview render tree and inherited by RecursiveTransclusion.\n return (\n <TransclusionDepthContext.Provider value={depth + 1}>\n <LinkPreviewContext.Provider value={linkPreview}>\n <RecursiveTransclusionContent target={target} label={label} content={content} />\n </LinkPreviewContext.Provider>\n </TransclusionDepthContext.Provider>\n );\n}\n\n/** Inner render for a resolved transclusion — used by TransclusionBlock. */\nfunction RecursiveTransclusionContent({\n target: _target,\n label,\n content,\n}: {\n target: string;\n label: string;\n content: string;\n}) {\n const plugins = useMemo<PluggableList>(() => {\n return [...baseRemarkPlugins, ...buildMarkdownPlugins()];\n }, []);\n\n return (\n <figure\n aria-label={`Embedded: ${label}`}\n className=\"my-3 rounded-md border-s-2 border-s-muted bg-muted/40 px-4 py-2\"\n data-testid=\"transclusion-block\"\n >\n <figcaption className=\"mb-1.5 text-meta text-muted-foreground\">{label}</figcaption>\n <div className=\"text-body text-foreground\">\n <Streamdown\n parseMarkdownIntoBlocksFn={singleBlock}\n remarkPlugins={plugins}\n rehypePlugins={rehypePlugins}\n allowedTags={allowedTags}\n components={components}\n >\n {content}\n </Streamdown>\n </div>\n </figure>\n );\n}\n\nconst components = {\n h1: annotated(heading(1)),\n h2: annotated(heading(2)),\n h3: annotated(heading(3)),\n h4: annotated(heading(4)),\n h5: annotated(heading(5)),\n h6: annotated(heading(6)),\n p: annotated(({ node: _n, ...p }: MdProps) => (\n <Text {...(p as HTMLAttributes<HTMLParagraphElement>)} />\n )),\n a: LinkMd,\n img: ImageMd,\n // Lists wash at ITEM granularity (a whole-list wash drowns the page), so the\n // ul/ol wrappers opt out of the search wash and the li carries it inline\n // (no wrapper div — that would break list semantics).\n ul: annotated(\n ({ node: _n, ...p }: MdProps) => <List {...(p as HTMLAttributes<HTMLElement>)} />,\n false,\n ),\n ol: annotated(\n ({ node: _n, ...p }: MdProps) => <List ordered {...(p as HTMLAttributes<HTMLElement>)} />,\n false,\n ),\n li: function ListItemMd({ node, ...p }: MdProps) {\n const search = useContext(SearchContext);\n const pos = getSourcePos(node);\n const active =\n pos != null &&\n search.activeLine != null &&\n search.activeLine >= pos.start &&\n search.activeLine <= pos.end &&\n !nestedItemContains(node, search.activeLine);\n return (\n <ListItem\n data-sourcepos={pos ? `${pos.start}:${pos.end}` : undefined}\n data-search-active={active ? \"\" : undefined}\n {...(p as HTMLAttributes<HTMLLIElement>)}\n className={cn(active && \"-mx-1 rounded-sm bg-primary/10 px-1\", p.className as string)}\n />\n );\n },\n blockquote: annotated(({ node: _n, ...p }: MdProps) => (\n <Blockquote {...(p as HTMLAttributes<HTMLQuoteElement>)} />\n )),\n hr: annotated(() => <Separator className=\"my-4\" />),\n pre: annotated(PreBlock, false),\n table: annotated(({ node: _n, ...p }: MdProps) => (\n <Table {...(p as HTMLAttributes<HTMLTableElement>)} />\n )),\n thead: ({ node: _n, ...p }: MdProps) => <TableHeader {...(p as object)} />,\n tbody: ({ node: _n, ...p }: MdProps) => <TableBody {...(p as object)} />,\n tr: ({ node: _n, ...p }: MdProps) => <TableRow {...(p as object)} />,\n th: ({ node: _n, ...p }: MdProps) => <TableHead {...(p as object)} />,\n td: ({ node: _n, ...p }: MdProps) => <TableCell {...(p as object)} />,\n [BRAND_DIRECTIVE_TAG]: annotated(BrandDirective),\n // Inline directives render un-`annotated` (no block wrapper) to stay in the text flow.\n [BRAND_DIRECTIVE_INLINE_TAG]: BrandInlineDirective,\n // Transclusion embeds (`![[target]]`) — resolved + recursively rendered by TransclusionBlock.\n [BRAND_TRANSCLUSION_TAG]: TransclusionBlock,\n // Academic layer — footnotes, math, citations (inline tags stay in the text flow;\n // the footnote section is a generated block).\n [FOOTNOTE_REF_TAG]: FootnoteRef,\n [FOOTNOTE_ITEM_TAG]: FootnoteItem,\n [FOOTNOTE_LIST_TAG]: ({ node: _n, children, ...rest }: MdProps) => (\n <FootnoteList {...(rest as HTMLAttributes<HTMLElement>)}>{children}</FootnoteList>\n ),\n [MATH_INLINE_TAG]: MathInlineTag,\n [MATH_BLOCK_TAG]: MathBlockTag,\n [CITE_TAG]: InlineCite,\n} as unknown as Components;\n\nexport interface MarkdownPreviewProps extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n /** Markdown source. */\n children: string;\n /** Strip a leading YAML frontmatter block before rendering. Default true. */\n stripFrontmatter?: boolean;\n /**\n * Ghost-diff annotations (#L18) — typically from `computeMarkdownAnnotations`.\n * Lines are 1-based relative to the FULL `children` source (frontmatter\n * included); the preview shifts them when `stripFrontmatter` removes lines.\n */\n annotations?: MarkdownAnnotation[];\n /**\n * Rewrite image/link URLs (#L4) — e.g. resolve repo-relative paths or swap\n * private-repo asset URLs for authenticated blob URLs. Synchronous by design:\n * async consumers cache upstream and re-render when the URL is ready.\n */\n resolveUrl?: (url: string, kind: MarkdownUrlKind) => string;\n /**\n * In-document search term (≥2 chars): mermaid diagrams mark matching nodes.\n * Pair with an app-side text highlighter (CSS Custom Highlight API) for the\n * prose occurrences.\n */\n searchTerm?: string;\n /**\n * 1-based line of the ACTIVE search hit, relative to the FULL `children`\n * source (same convention as `annotations`). Its block gets a primary wash;\n * in a mermaid fence the matching node gets the active stroke.\n */\n activeSearchLine?: number;\n /**\n * Render hover affordances beside each heading (pin/anchor/copy-link…).\n * Presentational slot — revealed on heading hover/focus and kept visible\n * while it contains a pressed toggle. `line` is in frontmatter-STRIPPED\n * coordinates (the same space as `data-sourcepos` / `parseMarkdownOutline`).\n */\n headingActions?: (heading: MarkdownHeadingInfo) => ReactNode;\n /**\n * Evaluate a ```calc fence to a `CalcSheet` (the library renders, the app\n * computes — mirrors `resolveUrl`). With no `evaluate`, a ```calc fence renders\n * as a normal code block; the math engine stays in the consumer.\n *\n * Sugar over `extensions.fences`: it registers a built-in `calc` fence renderer.\n * Register your own `calc` fence via `extensions` to override it.\n */\n evaluate?: EvaluateCalc;\n /**\n * Extend the markdown dialect without forking the engine: register custom\n * `:::`/`::`/`:` directive renderers and ```lang fence renderers. Registered\n * directive names are also fed to the parser (so `:entity[…]` is recognized\n * while an unregistered prose colon stays literal). Domain logic stays in the\n * consumer's renderer (the library renders; the app computes).\n */\n extensions?: MarkdownExtensions;\n /**\n * Resolve an Obsidian-style wikilink (`[[target]]`, `[[target|alias]]`,\n * `[[target#anchor]]`, `[[target#anchor|alias]]`) to a URL.\n *\n * - Return a string href to produce a real `<a>` (flows through `resolveUrl`\n * and `renderLinkPreview` like any other link).\n * - Return `null` to leave the wikilink as literal plain text `[[target]]`\n * (graceful — never a broken link).\n *\n * Supported forms:\n * - `[[target]]` → `resolveWikilink(\"target\", {})`\n * - `[[target|alias]]` → `resolveWikilink(\"target\", {})`, link text = alias\n * - `[[target#anchor]]` → `resolveWikilink(\"target\", { anchor: \"anchor\" })`\n * - `[[target#anchor|alias]]` → `resolveWikilink(\"target\", { anchor: \"anchor\" })`, text = alias\n */\n resolveWikilink?: (target: string, opts: WikilinkResolveOptions) => string | null;\n /**\n * Resolve an Obsidian-style transclusion embed (`![[target]]`,\n * `![[target#section]]`) to the markdown TEXT to embed.\n *\n * - Return the markdown string to embed; it will be recursively rendered as a\n * visually-nested, AT-labelled block (depth cap: 3 levels).\n * - Return `null` to leave the embed as literal plain text `![[target]]`.\n *\n * The library never fetches — the consumer owns the vault index and resolution.\n */\n resolveTransclusion?: (target: string, opts: TransclusionResolveOptions) => string | null;\n /**\n * Wrap every rendered `<a>` to attach a hover/inline link preview (e.g. a\n * `@elabs-ai/components-ui` HoverCard showing metadata). The library does NOT fetch; the\n * consumer owns the preview content.\n *\n * Return `children` unchanged if the href should not trigger a preview.\n * Default (not supplied) → the plain `Link` component.\n */\n renderLinkPreview?: (href: string, children: ReactNode) => ReactNode;\n /**\n * Branded GFM footnotes (`[^1]` … `[^1]: definition`) — quiet superscript refs\n * + a footnote section at the document end with working same-page back-refs.\n * Default `false` (footnotes parse but render with the plain GFM treatment).\n */\n footnotes?: boolean;\n /**\n * Math via `remark-math` + KaTeX — `$inline$` and `$$block$$` (on their own\n * lines). KaTeX runs untrusted-safe (`trust:false`, bounded macro expansion);\n * MathML is emitted for assistive tech. **The consumer must load KaTeX CSS once**\n * (`import \"katex/dist/katex.min.css\"`). Default `false`.\n */\n math?: boolean;\n /**\n * Resolve a Pandoc / Better-BibTeX citation key (`[@smith2020]`,\n * `[@a; @b]`, `[@a, p. 5]`, `[-@a]`) to {@link CitationData}, or `null` when\n * unknown. The BibTeX/CSL database + any CSL formatting live in the app — the\n * library renders inline cites + the `::bibliography` / `::references` block with\n * consistent numbering. Setting this enables citations (the same way `evaluate`\n * enables calc).\n */\n resolveCitation?: ResolveCitation;\n /** Inline citation style: `\"numeric\"` `[1]` (default) or `\"author-year\"` `(Smith 2020)`. */\n citationStyle?: CitationStyle;\n /**\n * Enable the generated `::toc` block (a quiet in-flow table of contents) and\n * stamp stable slug `id`s on headings so the anchors resolve. Reuses the same\n * heading extractor as `DocumentOutline`. Default `false`.\n */\n toc?: boolean;\n /**\n * Resolve a `:::iterate` / `:::pivot` block's {@link IterationSpec} (parsed from\n * the directive's attributes + body template) to its data. The data source +\n * any query live in the app — the library renders the repeated/cross-tabbed\n * cells. Setting this enables the `iterate` + `pivot` directives (the way\n * `evaluate` enables calc).\n */\n evaluateIteration?: EvaluateIteration;\n /**\n * Fill a `:::iterate` cell template with its row/cell context. Default: a\n * minimal `{{path}}` substitution — pass your own engine for anything richer.\n */\n interpolate?: InterpolateTemplate;\n}\n\nexport const MarkdownPreview = forwardRef<HTMLDivElement, MarkdownPreviewProps>(\n function MarkdownPreview(\n {\n children,\n stripFrontmatter = true,\n annotations,\n resolveUrl,\n searchTerm,\n activeSearchLine,\n headingActions,\n evaluate,\n extensions,\n resolveWikilink,\n resolveTransclusion,\n renderLinkPreview,\n footnotes,\n math,\n resolveCitation,\n citationStyle = \"numeric\",\n toc,\n evaluateIteration,\n interpolate,\n className,\n ...props\n },\n ref,\n ) {\n const markdown = stripFrontmatter ? parseFrontmatter(children).content : children;\n const fmOffset = stripFrontmatter\n ? children.split(\"\\n\").length - markdown.split(\"\\n\").length\n : 0;\n\n const shifted = useMemo(() => {\n if (!annotations?.length) return [];\n return fmOffset ? shiftAnnotations(annotations, fmOffset) : annotations;\n }, [annotations, fmOffset]);\n\n const search = useMemo<SearchState>(() => {\n const term = searchTerm?.trim();\n const activeLine =\n activeSearchLine != null && activeSearchLine - fmOffset >= 1\n ? activeSearchLine - fmOffset\n : undefined;\n return {\n term: term && term.length >= 2 ? term : undefined,\n activeLine,\n lines: markdown.split(\"\\n\"),\n };\n }, [searchTerm, activeSearchLine, fmOffset, markdown]);\n\n // Citation numbering authority — a single pre-pass so inline `[1]` and the\n // bibliography agree (only when a resolver is supplied).\n const citations = useMemo<CollectedCitations | null>(() => {\n if (!resolveCitation) return null;\n return collectCitations(markdown, resolveCitation);\n }, [markdown, resolveCitation]);\n\n // Heading outline for the `::toc` block + heading-id stamping (only when on).\n const outline = useMemo(() => (toc ? parseMarkdownOutline(markdown) : null), [toc, markdown]);\n\n // Resolve the render registry (directives + fences) for this instance. The\n // `evaluate` prop is sugar that registers the built-in `calc` fence.\n const registry = useMemo<PreviewRegistry>(() => {\n const directives = new Map<string, MarkdownDirectiveRenderer>();\n for (const d of extensions?.directives ?? []) directives.set(d.name, d);\n const fences = new Map<string, MarkdownFenceRenderer>();\n for (const f of extensions?.fences ?? []) fences.set(f.lang, f);\n // `::toc` + `::bibliography` / `::references` — internal directives whose\n // renderers read the outline / citation context (provided below).\n if (toc) {\n directives.set(\"toc\", {\n name: \"toc\",\n kinds: [\"leaf\", \"container\"],\n render: ({ attributes }) => <TableOfContents title={attributes.title || undefined} />,\n });\n }\n if (resolveCitation) {\n const renderBibliography: MarkdownDirectiveRenderer[\"render\"] = ({ attributes }) => (\n <Bibliography title={attributes.title || undefined} />\n );\n directives.set(\"bibliography\", {\n name: \"bibliography\",\n kinds: [\"leaf\", \"container\"],\n render: renderBibliography,\n });\n directives.set(\"references\", {\n name: \"references\",\n kinds: [\"leaf\", \"container\"],\n render: renderBibliography,\n });\n }\n if (evaluateIteration) {\n // `:::iterate` / `:::pivot` — the body is the per-cell TEMPLATE (captured\n // raw via `rawBodyNames`); cells render through a nested `MarkdownPreview`\n // that inherits the dialect features (depth-capped against runaway loops).\n const iterationDirective = (name: \"iterate\" | \"pivot\"): MarkdownDirectiveRenderer => ({\n name,\n kinds: [\"container\"],\n render: ({ attributes, rawBody }) => (\n <IterationDirective\n spec={specFromDirective(name, attributes, rawBody)}\n evaluate={evaluateIteration}\n interpolate={interpolate}\n // Cells render through a nested preview that inherits the dialect\n // features. Extracted to `IterationCell` so `MarkdownPreview` isn't\n // referenced inside its own initializer (TS2786 / forwardRef cycle).\n renderCell={(md) => (\n <IterationCell\n markdown={md}\n config={{\n evaluateIteration,\n interpolate,\n evaluate,\n extensions,\n footnotes,\n math,\n resolveCitation,\n citationStyle,\n }}\n />\n )}\n />\n ),\n });\n directives.set(\"iterate\", iterationDirective(\"iterate\"));\n directives.set(\"pivot\", iterationDirective(\"pivot\"));\n }\n if (evaluate && !fences.has(\"calc\")) {\n fences.set(\"calc\", {\n lang: \"calc\",\n render: ({ source }) => <CalcBlock source={source} evaluate={evaluate} />,\n });\n }\n if (evaluate && !directives.has(\"calc\")) {\n directives.set(\"calc\", {\n name: \"calc\",\n kinds: [\"inline\"],\n // `textValue` is the verbatim expression (markdown chars preserved);\n // fall back to the rendered label only if positions were unavailable.\n render: ({ textValue, children }) => (\n <CalcInline source={textValue ?? flattenNodeText(children)} evaluate={evaluate} />\n ),\n });\n }\n return { directives, fences };\n }, [\n extensions,\n evaluate,\n toc,\n resolveCitation,\n citationStyle,\n evaluateIteration,\n interpolate,\n footnotes,\n math,\n ]);\n\n // Stable key over the registered directive NAMES (space-joined): the parser only\n // needs the known-set, so the plugin array rebuilds on name changes, not on a\n // new `extensions` identity each render.\n // `calc` joins the set when `evaluate` is supplied (so `:calc[…]` parses);\n // `toc` / `bibliography` / `references` join when those features are enabled.\n const directiveNamesKey = [\n ...(extensions?.directives ?? []).map((d) => d.name),\n ...(evaluate ? [\"calc\"] : []),\n ...(toc ? [\"toc\"] : []),\n ...(resolveCitation ? [\"bibliography\", \"references\"] : []),\n ...(evaluateIteration ? [\"iterate\", \"pivot\"] : []),\n ].join(\" \");\n\n const plugins = useMemo<PluggableList>(() => {\n const directiveNames = directiveNamesKey ? directiveNamesKey.split(\" \") : [];\n // `:::iterate`/`:::pivot` bodies are captured RAW (as templates) rather than\n // pre-rendered — so they don't render their `{{token}}` source before interpolation.\n const rawBodyNames = evaluateIteration ? [\"iterate\", \"pivot\"] : [];\n let list: PluggableList = [\n ...baseRemarkPlugins,\n ...buildMarkdownPlugins({ directiveNames, rawBodyNames }),\n ];\n // Academic transforms run after the directive pipeline. `remarkMath` must\n // precede `remarkBrandMath` (it produces the math nodes the latter rewrites).\n if (math) list = [...list, remarkMath, remarkBrandMath];\n if (footnotes) list = [...list, remarkBrandFootnotes];\n if (resolveCitation) list = [...list, remarkBrandCitations];\n // Wikilinks and transclusions are added BEFORE resolveUrl so any href they\n // produce (wikilinks) flows through the URL resolver as a normal link would.\n // Transclusion embeds produce raw HTML nodes (not mdast links) so order\n // relative to resolveUrl is irrelevant, but we keep them together for clarity.\n if (resolveWikilink) list = [...list, remarkResolveWikilinks(resolveWikilink)];\n if (resolveTransclusion) list = [...list, remarkResolveTransclusions()];\n if (resolveUrl) list = [...list, remarkResolveUrls(resolveUrl)];\n return list;\n // `directiveNamesKey` already folds in `calc`/`toc`/`bibliography` when those\n // are set, so the plugin array tracks them without depending on identities.\n }, [\n resolveUrl,\n resolveWikilink,\n resolveTransclusion,\n directiveNamesKey,\n math,\n footnotes,\n resolveCitation,\n evaluateIteration,\n ]);\n\n const streamdown = (\n <Streamdown\n // Render as ONE block. Streamdown's default block-splitter (a streaming\n // optimization) severs a multi-line `:::` container directive from its\n // child content (e.g. a `:::timeline` from its list), so the directive\n // arrives empty. The preview re-renders the whole doc anyway, so a single\n // block is both correct and fine for authoring-sized documents.\n parseMarkdownIntoBlocksFn={singleBlock}\n remarkPlugins={plugins}\n rehypePlugins={rehypePlugins}\n allowedTags={allowedTags}\n components={components}\n >\n {markdown}\n </Streamdown>\n );\n // Academic contexts wrap the renderer only when their feature is on, so inline\n // cites + the bibliography share numbering and `::toc` reads the heading slugs.\n const withCitations = citations ? (\n <CitationProvider order={citations.order} byKey={citations.byKey} style={citationStyle}>\n {streamdown}\n </CitationProvider>\n ) : (\n streamdown\n );\n const body = outline ? (\n <TocProvider items={outline}>{withCitations}</TocProvider>\n ) : (\n withCitations\n );\n\n return (\n <div\n ref={ref}\n data-testid=\"markdown-preview\"\n // Reading rhythm (proximity grammar): headings carry 2–2.5× the space\n // ABOVE vs below — uniform block spacing reads like a teleprinter. The\n // `!` beats Streamdown's internal space-y sibling rule.\n className={cn(\n \"text-body text-foreground [&_pre]:my-3\",\n \"[&_h1]:!mt-10 [&_h2]:!mt-9 [&_h3]:!mt-7 [&_h4]:!mt-6\",\n \"[&_:is(h1,h2,h3,h4)+*]:!mt-3 [&_:is(h1,h2,h3,h4):first-child]:!mt-0\",\n className,\n )}\n {...props}\n >\n <AnnotationsContext.Provider value={shifted}>\n <SearchContext.Provider value={search}>\n <HeadingActionsContext.Provider value={headingActions ?? null}>\n <RegistryContext.Provider value={registry}>\n <LinkPreviewContext.Provider value={renderLinkPreview ?? null}>\n <TransclusionResolverContext.Provider value={resolveTransclusion ?? null}>\n <TransclusionDepthContext.Provider value={0}>\n {body}\n </TransclusionDepthContext.Provider>\n </TransclusionResolverContext.Provider>\n </LinkPreviewContext.Provider>\n </RegistryContext.Provider>\n </HeadingActionsContext.Provider>\n </SearchContext.Provider>\n </AnnotationsContext.Provider>\n </div>\n );\n },\n);\n\n/** The dialect features an iterated cell's nested preview inherits. */\ninterface IterationCellConfig {\n evaluateIteration?: EvaluateIteration;\n interpolate?: InterpolateTemplate;\n evaluate?: EvaluateCalc;\n extensions?: MarkdownExtensions;\n footnotes?: boolean;\n math?: boolean;\n resolveCitation?: ResolveCitation;\n citationStyle: CitationStyle;\n}\n\n/**\n * Renders one `:::iterate` cell's resolved markdown via a nested `MarkdownPreview`.\n * Defined OUTSIDE `MarkdownPreview` so the component isn't referenced inside its\n * own initializer (the forwardRef self-reference TS2786 — same reason transclusion\n * renders its own pipeline).\n */\nfunction IterationCell({ markdown, config }: { markdown: string; config: IterationCellConfig }) {\n return (\n <MarkdownPreview stripFrontmatter={false} {...config}>\n {markdown}\n </MarkdownPreview>\n );\n}\n\nexport type { MarkdownAnnotation, MarkdownAnnotationKind } from \"../lib/markdown/diff\";\n","/**\n * Shared remark pipeline for the brand markdown dialect.\n *\n * `remark-directive` parses generic container/leaf/text directives (`:::name`,\n * `::name`, `:name`). `remarkBrandDirectives` then rewrites the four brand blocks\n * — :::card / :::callout / ::metric / :::timeline — into a single `<brand-directive>`\n * element carrying a JSON `data-brand` payload, which the preview's components map\n * turns into real @brand components. Unknown directive names are preserved + flagged\n * so the preview can surface an \"unknown block\" error instead of silently dropping.\n *\n * One JSON attribute (not many) keeps it robust against Streamdown's HTML\n * sanitization (we only need to allow a single attribute through). The SAME plugin\n * array is fed to Streamdown (preview) and can be fed to Milkdown via `$remark`\n * (editor), so both sides parse `:::card` identically.\n */\nimport type { ReactNode } from \"react\";\nimport remarkDirective from \"remark-directive\";\nimport type { PluggableList } from \"unified\";\nimport { visit } from \"unist-util-visit\";\n\nexport const BRAND_DIRECTIVES = [\"card\", \"callout\", \"metric\", \"timeline\"] as const;\nexport type BrandDirectiveName = (typeof BRAND_DIRECTIVES)[number];\n\n/** Custom element BLOCK / LEAF directives are rewritten to. */\nexport const BRAND_DIRECTIVE_TAG = \"brand-directive\";\n/**\n * Custom element INLINE (text) directives are rewritten to. A SEPARATE tag (not\n * {@link BRAND_DIRECTIVE_TAG}) so the preview can render inline directives without\n * the block `<div>` wrappers the annotation/search layer adds to block tags —\n * keeping `:entity[name]` inside the text flow.\n */\nexport const BRAND_DIRECTIVE_INLINE_TAG = \"brand-directive-inline\";\n/** Rendered HTML attribute carrying the JSON payload (allow-list this in Streamdown). */\nexport const BRAND_DIRECTIVE_ATTR = \"data-brand\";\n/**\n * hast PROPERTY name (camelCase) for {@link BRAND_DIRECTIVE_ATTR}. This — not the\n * rendered `data-brand` — is what Streamdown's `allowedTags` must list to let the\n * payload survive sanitization.\n */\nexport const BRAND_DIRECTIVE_PROP = \"dataBrand\";\n\n/** Which directive syntax produced a node: `:::block`, `::leaf`, or `:inline`. */\nexport type MarkdownDirectiveKind = \"container\" | \"leaf\" | \"inline\";\n\nexport interface BrandDirectivePayload {\n name: string;\n known: boolean;\n kind: MarkdownDirectiveKind;\n attributes: Record<string, string>;\n items?: { title: string; status: string }[];\n /**\n * RAW label source for inline/leaf directives (`:calc[85 * 32]` → `85 * 32`).\n * Captured from source positions so markdown-significant characters in the\n * label (`*`, `_`, `[`) survive intact — the rendered children would mangle\n * them. Renderers that need the verbatim expression (calc) read this.\n */\n label?: string;\n /**\n * RAW container body source (the markdown between the `:::name` fences),\n * captured only for the directive names passed in `rawBodyNames` — e.g. the\n * per-cell TEMPLATE of an `:::iterate` block, which must be interpolated then\n * rendered, NOT shown pre-rendered. Captured from source positions.\n */\n body?: string;\n}\n\n/* ------------------------------------------------------------------ */\n/* Extension registry — the consumer-supplied render seam (the library */\n/* RENDERS; the consumer brings the renderer + any domain hook). One */\n/* registry feeds BOTH the parse-side known-set and the render dispatch. */\n/* ------------------------------------------------------------------ */\n\n/** Context handed to a consumer directive renderer. */\nexport interface MarkdownDirectiveContext {\n name: string;\n /** Which syntax matched — a renderer can branch (e.g. inline chip vs block card). */\n kind: MarkdownDirectiveKind;\n /** Directive attributes (`{key=value}`), strings only. */\n attributes: Record<string, string>;\n /** Rendered body (container), label (inline), or empty (leaf). */\n children: ReactNode;\n /**\n * RAW label text for inline/leaf directives (markdown-significant characters\n * preserved). Use this — not `children` — when you need the verbatim source\n * (e.g. a calc expression `85 * 32`). `undefined` for container directives.\n */\n textValue?: string;\n /**\n * RAW container body markdown (the source between the `:::name` fences). Only\n * populated for directives registered with `rawBodyNames` (e.g. `iterate` /\n * `pivot`), where the body is a TEMPLATE to interpolate + render per cell, not\n * to display pre-rendered. `undefined` otherwise.\n */\n rawBody?: string;\n}\n\n/** Register a custom `:::name` / `::name` / `:name` directive renderer. */\nexport interface MarkdownDirectiveRenderer {\n /** Directive name, e.g. `\"decision\"`, `\"entity\"`. */\n name: string;\n /** Accepted syntaxes. Default: all three. */\n kinds?: readonly MarkdownDirectiveKind[];\n render: (ctx: MarkdownDirectiveContext) => ReactNode;\n}\n\n/** Context handed to a consumer fence renderer. */\nexport interface MarkdownFenceContext {\n /** The fence body (trailing newline stripped). */\n source: string;\n /** The info-string language, e.g. `\"calc\"`. */\n lang: string;\n}\n\n/** Register a custom ```lang fenced-block renderer (the mermaid/calc seam). */\nexport interface MarkdownFenceRenderer {\n /** Info-string this renderer claims, e.g. `\"calc\"`. */\n lang: string;\n render: (ctx: MarkdownFenceContext) => ReactNode;\n}\n\n/**\n * Consumer extensions to the brand markdown dialect — passed to `MarkdownPreview`\n * via the `extensions` prop. Registered directive NAMES are also fed to the parser\n * (so `:entity[…]` is rewritten, while an unregistered `:foo` in prose stays\n * literal text), and the renderers drive the preview's dispatch. The engine is\n * never forked: new blocks register here.\n */\nexport interface MarkdownExtensions {\n directives?: readonly MarkdownDirectiveRenderer[];\n fences?: readonly MarkdownFenceRenderer[];\n}\n\ninterface MdNode {\n type: string;\n name?: string;\n value?: string;\n attributes?: Record<string, string | null | undefined>;\n children?: MdNode[];\n position?: { start?: { offset?: number }; end?: { offset?: number } };\n data?: { hName?: string; hProperties?: Record<string, unknown> };\n}\n\nconst DIRECTIVE_TYPES = new Set([\"containerDirective\", \"leafDirective\", \"textDirective\"]);\n\nfunction mdastText(node: MdNode): string {\n if (typeof node.value === \"string\") return node.value;\n if (node.children) return node.children.map(mdastText).join(\"\");\n return \"\";\n}\n\nfunction extractTimelineItems(node: MdNode): { title: string; status: string }[] {\n const list = node.children?.find((c) => c.type === \"list\");\n if (!list?.children) return [];\n // Status marker is a leading `(done)` / `(active)` / `(pending)` — parentheses\n // avoid markdown's `[ref]` link-reference collision. Default: pending.\n const MARKER = /^\\((done|complete|completed|active|current|pending|todo)\\)\\s*/i;\n return list.children\n .filter((c) => c.type === \"listItem\")\n .map((li) => {\n let title = mdastText(li).trim();\n let status = \"pending\";\n const marker = title.match(MARKER);\n if (marker) {\n status = marker[1]!.toLowerCase();\n title = title.slice(marker[0].length).trim();\n }\n return { title, status };\n });\n}\n\nfunction cleanAttributes(attrs: MdNode[\"attributes\"]): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(attrs ?? {})) {\n if (typeof v === \"string\") out[k] = v;\n }\n return out;\n}\n\n/**\n * Reconstruct a directive's ORIGINAL source text. Prose colons routinely\n * pattern-match remark-directive's text/leaf forms (`qwen3:0.6b` parses as a\n * `:0` text directive and swallows the \"0\") — restoring the source slice is\n * the only faithful undo.\n */\nfunction originalText(node: MdNode, source: string | undefined): string {\n const start = node.position?.start?.offset;\n const end = node.position?.end?.offset;\n if (source != null && typeof start === \"number\" && typeof end === \"number\") {\n return source.slice(start, end);\n }\n // Position unavailable — best-effort reconstruction.\n const colons = node.type === \"leafDirective\" ? \"::\" : \":\";\n const label = node.children?.length ? `[${mdastText(node)}]` : \"\";\n return `${colons}${node.name ?? \"\"}${label}`;\n}\n\n/** mdast node type → the directive kind it represents. */\nfunction directiveKind(type: string): MarkdownDirectiveKind {\n if (type === \"containerDirective\") return \"container\";\n if (type === \"leafDirective\") return \"leaf\";\n return \"inline\";\n}\n\n/**\n * The RAW label source of a directive (`:name[label]`) — sliced from the original\n * source via the label children's positions, so markdown-significant characters\n * (`*`, `_`, `[`) survive instead of being parsed into emphasis/links.\n */\nfunction rawLabel(node: MdNode, source: string | undefined): string | undefined {\n const kids = node.children;\n if (!source || !kids || kids.length === 0) return undefined;\n const start = kids[0]?.position?.start?.offset;\n const end = kids[kids.length - 1]?.position?.end?.offset;\n if (typeof start === \"number\" && typeof end === \"number\") return source.slice(start, end);\n return undefined;\n}\n\n/**\n * The RAW body source of a CONTAINER directive — the markdown between the\n * `:::name{…}` opening and the closing `:::`. Skips a leading directive label\n * (`:::name[label]`) child. Used for templated containers (`:::iterate`) whose\n * body must be interpolated then rendered, not shown pre-rendered.\n */\nfunction rawContainerBody(node: MdNode, source: string | undefined): string | undefined {\n const kids = node.children;\n if (!source || !kids || kids.length === 0) return undefined;\n const body = kids.filter(\n (c) => !(c.data as { directiveLabel?: boolean } | undefined)?.directiveLabel,\n );\n if (body.length === 0) return undefined;\n const start = body[0]?.position?.start?.offset;\n const end = body[body.length - 1]?.position?.end?.offset;\n if (typeof start === \"number\" && typeof end === \"number\") return source.slice(start, end).trim();\n return undefined;\n}\n\n/**\n * remark transform: brand directives → `<brand-directive data-brand=\"{json}\">`\n * (block/leaf) or `<brand-directive-inline …>` (inline).\n *\n * `knownNames` is the set of directive names to TREAT AS KNOWN — i.e. rewrite\n * rather than restore. It defaults to the four built-ins; `MarkdownPreview`\n * extends it with the names a consumer registered via `extensions`, so a\n * registered `:entity[…]` is rewritten while an unregistered `:foo` (or a stray\n * prose colon) is still restored to literal text.\n */\nexport function remarkBrandDirectives(\n knownNames: readonly string[] = BRAND_DIRECTIVES,\n rawBodyNames: readonly string[] = [],\n) {\n return (tree: unknown, file?: { value?: unknown }) => {\n const source = typeof file?.value === \"string\" ? file.value : undefined;\n visit(tree as never, (node: MdNode, index: number | undefined, parent: MdNode | undefined) => {\n if (!DIRECTIVE_TYPES.has(node.type) || !node.name) return undefined;\n\n const name = node.name;\n const known = knownNames.includes(name);\n const kind = directiveKind(node.type);\n\n // Unknown text/leaf directives are almost always FALSE POSITIVES from\n // ordinary colons in prose — restore them as literal text. Only an\n // unknown CONTAINER (`:::name`, deliberately authored) keeps the\n // explicit unknown-block error.\n if (!known && node.type !== \"containerDirective\" && parent?.children && index != null) {\n const literal: MdNode = { type: \"text\", value: originalText(node, source) };\n parent.children.splice(\n index,\n 1,\n node.type === \"leafDirective\"\n ? ({ type: \"paragraph\", children: [literal] } as MdNode)\n : literal,\n );\n return index + 1; // continue after the replacement\n }\n\n const payload: BrandDirectivePayload = {\n name,\n known,\n kind,\n attributes: cleanAttributes(node.attributes),\n };\n\n // Inline/leaf directives carry a verbatim label (e.g. a calc expression).\n if (kind !== \"container\") {\n const label = rawLabel(node, source);\n if (label != null) payload.label = label;\n }\n\n // Templated containers (`:::iterate`/`:::pivot`) carry their RAW body so the\n // renderer can interpolate + render it per cell. Clear the children so the\n // template is NOT also rendered pre-interpolated (mirrors timeline).\n if (kind === \"container\" && rawBodyNames.includes(name)) {\n const body = rawContainerBody(node, source);\n if (body != null) payload.body = body;\n node.children = [];\n }\n\n if (name === \"timeline\") {\n payload.items = extractTimelineItems(node);\n node.children = []; // consumed into payload.items\n }\n\n const data = node.data ?? (node.data = {});\n // Inline directives keep their children (the label) and use a SEPARATE tag\n // so the preview renders them inline (no block wrapper).\n data.hName = kind === \"inline\" ? BRAND_DIRECTIVE_INLINE_TAG : BRAND_DIRECTIVE_TAG;\n // camelCase hast property → renders as the `data-brand` attribute.\n data.hProperties = { [BRAND_DIRECTIVE_PROP]: JSON.stringify(payload) };\n });\n };\n}\n\n/** Options for {@link buildMarkdownPlugins}. */\nexport interface BuildMarkdownPluginsOptions {\n /**\n * Extra directive names to treat as known (rewritten, not restored as literal\n * text). The four built-ins are always known; pass the names a consumer\n * registered via `extensions.directives`.\n */\n directiveNames?: readonly string[];\n /**\n * Container directive names whose RAW body should be captured (as\n * `payload.body` / `ctx.rawBody`) instead of pre-rendered — for templated\n * blocks like `iterate` / `pivot` whose body is interpolated per cell.\n */\n rawBodyNames?: readonly string[];\n}\n\n/**\n * The shared remark plugin array (directive parsing + brand mapping). Pass\n * `directiveNames` to recognize consumer-registered directives without forking\n * the engine; with no options it parses exactly the four built-ins (backward\n * compatible).\n */\nexport function buildMarkdownPlugins(options: BuildMarkdownPluginsOptions = {}): PluggableList {\n const known =\n options.directiveNames && options.directiveNames.length > 0\n ? [...BRAND_DIRECTIVES, ...options.directiveNames]\n : BRAND_DIRECTIVES;\n const rawBodyNames = options.rawBodyNames ?? [];\n return [remarkDirective, [remarkBrandDirectives, known, rawBodyNames]];\n}\n","\"use client\";\n\n/**\n * CalcBlock — render a ```calc fence as a two-column \"sheet\" (#L1).\n *\n * The Soulver/Notes-Calculator model: expressions on the left, computed answers\n * on the right (`tabular-nums`), a running-total footer. The library RENDERS and\n * the consumer EVALUATES: the math engine is app/domain logic, so CalcBlock takes\n * an `evaluate(source) => CalcSheet` hook (mirroring `MarkdownPreview`'s\n * `resolveUrl`) and bundles no calculator. Per-line errors render inline; a bad\n * block never throws or blanks the document. The mermaid fence is the precedent.\n *\n * Title: a leading `# Heading` becomes the block title (header bar); with none,\n * the header shows the neutral `calc` code-label.\n *\n * Row presentation — a per-row `rule` divider (dotted / single / double) and a\n * semantic `tint` wash — comes from two sources, both pure presentation:\n * 1. the evaluator, as `rule`/`tint` fields on a `CalcLineResult` (app-driven); or\n * 2. a trailing author **marker** the WRITER types in the calc text, which\n * CalcBlock strips before calling `evaluate` (so the math engine never sees\n * it) — the same way it strips `# ` off a heading. Tints: `@primary`,\n * `@success`, `@warning`, `@danger`, `@info`, `@muted`/`@note`. Rules:\n * `@line`, `@line2`/`@double`, `@dotted`. Multiple markers per line compose\n * (`subtotal = a + b @success @line`); an evaluator field wins over a marker.\n * Disable parsing with `markers={false}`. Unknown trailing `@words` are left\n * as literal text (never silently dropped).\n *\n * The footer total defaults to `sheet.total` but can be overridden via the\n * `total` / `totalLabel` props.\n *\n * Syntax highlighting uses the dedicated `--calc-*` tokens (#221) via `text-calc-*`;\n * color is never the only signal (var-def = weight, unresolved = dotted underline),\n * so roles stay distinct in the high-contrast theme.\n */\nimport { useLocale } from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { TriangleAlert } from \"lucide-react\";\nimport { forwardRef, useId, useMemo, type HTMLAttributes, type ReactNode } from \"react\";\n\nimport type {\n CalcLineResult,\n CalcRule,\n CalcTint,\n CalcToken,\n CalcTokenKind,\n CalcValue,\n EvaluateCalc,\n} from \"./types\";\n// Carry the `.brand-calc-tok--<role>` role colours, so the RENDERED block reads\n// identically to the editor authoring surfaces (which import the same stylesheet).\nimport \"./calc-editor.css\";\n\nexport interface CalcBlockProps extends Omit<HTMLAttributes<HTMLElement>, \"children\" | \"title\"> {\n /** The ```calc fence body. */\n source: string;\n /** Consumer-supplied evaluator (sync). The library bundles no math engine. */\n evaluate: EvaluateCalc;\n /**\n * Block title shown in the header bar. By default a leading `# Heading` line in\n * `source` is lifted here; with neither prop nor heading the header shows the\n * neutral `calc` code-label. Pass `title` to override the displayed text.\n */\n title?: ReactNode;\n /** Show the running-total footer. Default true. */\n showTotal?: boolean;\n /**\n * Override the footer total. Defaults to `sheet.total`. Pass a `CalcValue`\n * (rendered tabular via its `.display`) or any ReactNode to replace the\n * computed total — e.g. a different aggregate the evaluator didn't surface.\n */\n total?: CalcValue | ReactNode;\n /** Footer label. Default `Total`. */\n totalLabel?: ReactNode;\n /**\n * Parse trailing author markers (`@success`, `@line`, …) out of each source\n * line — applying the row's tint/rule and stripping the marker from the\n * rendered text. Default `true`. Set `false` if your calc dialect uses a\n * trailing `@token` for something else.\n */\n markers?: boolean;\n /** Reserved for the editing variant (CalcWorkspace); preview is read-only. */\n readOnly?: boolean;\n}\n\n/** Author marker keyword → semantic tint (friendly words; `@danger` = destructive). */\nconst TINT_MARKERS: Record<string, CalcTint> = {\n primary: \"primary\",\n success: \"success\",\n warning: \"warning\",\n danger: \"destructive\",\n destructive: \"destructive\",\n info: \"info\",\n muted: \"muted\",\n note: \"muted\",\n};\n\n/** Author marker keyword → rule (divider) style. */\nconst RULE_MARKERS: Record<string, CalcRule> = {\n line: \"single\",\n rule: \"single\",\n line2: \"double\",\n double: \"double\",\n dotted: \"dotted\",\n};\n\n/** A line's parsed presentation, after author markers are stripped from the text. */\ninterface LineMarkers {\n text: string;\n tint?: CalcTint;\n rule?: CalcRule;\n}\n\n/**\n * Strip recognized trailing `@marker`s off a line (right-to-left), returning the\n * cleaned text plus the tint/rule they request. An unrecognized trailing `@word`\n * halts stripping and is kept as literal text — markers only ever bind at the end.\n */\nfunction parseMarkers(line: string): LineMarkers {\n let text = line;\n let tint: CalcTint | undefined;\n let rule: CalcRule | undefined;\n for (;;) {\n const m = /\\s+@([A-Za-z][A-Za-z0-9]*)\\s*$/.exec(text);\n if (!m) break;\n const key = (m[1] ?? \"\").toLowerCase();\n if (key in TINT_MARKERS) {\n tint ??= TINT_MARKERS[key];\n } else if (key in RULE_MARKERS) {\n rule ??= RULE_MARKERS[key];\n } else {\n break; // unknown trailing @word — leave it (and everything before) as text\n }\n text = text.slice(0, m.index);\n }\n return { text, tint, rule };\n}\n\n/** Per-row rule (divider) presentation. `border-strong` is the sole same-surface cue. */\nconst RULE_CLASS: Record<CalcRule, string> = {\n dotted: \"border-b border-dotted border-border-strong pb-1\",\n single: \"border-b border-border-strong pb-1\",\n double: \"border-b-4 border-double border-border-strong pb-1\",\n};\n\n/** Per-row background tint — semantic status washes (theme-safe), `muted` neutral. */\nconst TINT_CLASS: Record<CalcTint, string> = {\n primary: \"bg-primary/10\",\n success: \"bg-success/10\",\n warning: \"bg-warning/10\",\n destructive: \"bg-destructive/10\",\n info: \"bg-info/10\",\n muted: \"bg-muted\",\n};\n\n/** Narrow a `total` override to a `CalcValue` (vs a plain ReactNode like a string). */\nfunction isCalcValue(x: unknown): x is CalcValue {\n return typeof x === \"object\" && x !== null && !(\"$$typeof\" in x) && \"kind\" in x && \"display\" in x;\n}\n\n/**\n * Token kind → highlight class. Color comes from the dedicated `--calc-*` syntax\n * tokens (#221) via the `text-calc-*` utilities; the `brand-calc-tok--<role>`\n * class carries a role-specific, color-independent cue (weight / style / underline)\n * in low-chroma themes (#226) — so in high-contrast, where every inline calc token\n * collapses to one ink, number / unit / currency / var-ref / line-ref / unknown\n * stay distinguishable. The SAME classes drive the editor decorations\n * (calc-editor.css), so both surfaces read identically.\n */\nfunction tokenClass(kind: CalcTokenKind, resolved: boolean): string {\n let base: string;\n let role: string;\n switch (kind) {\n case \"comment\":\n base = \"text-calc-comment italic\";\n role = \"brand-calc-tok--comment\";\n break;\n case \"operator\":\n base = \"text-calc-operator\";\n role = \"brand-calc-tok--operator\";\n break;\n case \"unit\":\n base = \"text-calc-unit\";\n role = \"brand-calc-tok--unit\";\n break;\n case \"currency\":\n base = \"text-calc-currency\";\n role = \"brand-calc-tok--currency\";\n break;\n case \"function\":\n base = \"text-calc-function\";\n role = \"brand-calc-tok--function\";\n break;\n case \"var-ref\":\n base = \"text-calc-variable\";\n role = \"brand-calc-tok--var-ref\";\n break;\n case \"line-ref\":\n base = \"text-calc-reference tabular-nums\";\n role = \"brand-calc-tok--line-ref\";\n break;\n case \"var-def\":\n base = \"text-calc-variable font-medium\";\n role = \"brand-calc-tok--var-def\";\n break;\n case \"unknown\":\n base = \"text-calc-warning\";\n role = \"brand-calc-tok--unknown\";\n break;\n default: // number, constant\n base = \"text-calc-number\";\n role = \"brand-calc-tok--number\";\n }\n return cn(\n \"brand-calc-tok\",\n role,\n base,\n !resolved && \"underline decoration-dotted decoration-1 underline-offset-2\",\n );\n}\n\n/** Paint one source line: tokenized spans with plain text in the gaps. */\nfunction renderSource(text: string, tokens: CalcToken[]): ReactNode {\n const out: ReactNode[] = [];\n let cursor = 0;\n for (const [i, t] of tokens.entries()) {\n if (t.start > cursor) {\n out.push(<span key={`gap-${String(i)}`}>{text.slice(cursor, t.start)}</span>);\n }\n out.push(\n <span key={`tok-${String(i)}`} className={tokenClass(t.kind, t.resolved)}>\n {text.slice(t.start, t.end)}\n </span>,\n );\n cursor = t.end;\n }\n if (cursor < text.length) out.push(<span key=\"tail\">{text.slice(cursor)}</span>);\n if (out.length === 0) out.push(<span key=\"empty\">{text || \" \"}</span>);\n return out;\n}\n\n/** The right-hand cell: a value, a calm error marker, or nothing. */\nfunction ResultCell({ result }: { result: CalcLineResult }): ReactNode {\n const { t } = useLocale();\n if (result.error) {\n // Native `title` (not a Radix Tooltip) so CalcBlock is self-contained — it\n // renders inside MarkdownPreview / a story with no TooltipProvider ancestor.\n return (\n <span\n className=\"inline-flex shrink-0 text-calc-warning\"\n title={result.error.message}\n aria-label={t(\"editor.calcBlock.error\", { message: result.error.message })}\n >\n <TriangleAlert className=\"size-3.5\" aria-hidden=\"true\" />\n </span>\n );\n }\n if (result.value) {\n return (\n <div className=\"brand-calc-tok--result shrink-0 tabular-nums text-calc-result\">\n <span className=\"sr-only\">{t(\"editor.calcBlock.equals\")}</span>\n <span>{result.value.display}</span>\n </div>\n );\n }\n return null;\n}\n\nexport const CalcBlock = forwardRef<HTMLDivElement, CalcBlockProps>(function CalcBlock(\n {\n source,\n evaluate,\n title,\n showTotal = true,\n total,\n totalLabel: totalLabelProp,\n markers = true,\n readOnly: _readOnly,\n className,\n ...props\n },\n ref,\n) {\n const { t } = useLocale();\n const totalLabel = totalLabelProp ?? t(\"editor.calcBlock.total\");\n // Author markers are stripped BEFORE evaluation: the math engine sees clean\n // lines, and because markers are trailing, token columns stay aligned with the\n // rendered (cleaned) text. `lines`/`evalSource` are the marker-free versions.\n const { lines, evalSource, hints } = useMemo(() => {\n const raw = source.split(\"\\n\");\n if (!markers) return { lines: raw, evalSource: source, hints: [] as LineMarkers[] };\n const parsed = raw.map(parseMarkers);\n return {\n lines: parsed.map((p) => p.text),\n evalSource: parsed.map((p) => p.text).join(\"\\n\"),\n hints: parsed,\n };\n }, [source, markers]);\n\n const sheet = useMemo(() => evaluate(evalSource), [evaluate, evalSource]);\n const empty = evalSource.trim() === \"\";\n const titleId = useId();\n\n // A leading `# Heading` is the block title (lifted to the header bar) and is not\n // repeated in the body. Later `#` lines stay as in-body section headings.\n const { titleLine, derivedTitle } = useMemo(() => {\n const idx = lines.findIndex((l) => l.trim() !== \"\");\n const first = (lines[idx] ?? \"\").trim();\n return /^#+\\s+/.test(first)\n ? { titleLine: idx + 1, derivedTitle: first.replace(/^#+\\s*/, \"\") }\n : { titleLine: 0, derivedTitle: undefined as string | undefined };\n }, [lines]);\n\n const hasTitle = title != null || derivedTitle != null;\n const resolvedTitle = title ?? derivedTitle ?? \"calc\";\n\n const resolvedTotal = total ?? sheet.total;\n const totalDisplay = isCalcValue(resolvedTotal) ? resolvedTotal.display : resolvedTotal;\n\n const rows: ReactNode[] = [];\n for (const result of sheet.results) {\n if (result.line === titleLine) continue; // lifted to the header bar\n const text = lines[result.line - 1] ?? \"\";\n const key = `row-${String(result.line)}`;\n if (text.trim() === \"\") {\n rows.push(<div key={key} className=\"h-1.5\" aria-hidden=\"true\" />);\n continue;\n }\n if (text.trim().startsWith(\"#\")) {\n rows.push(\n <div key={key} className=\"pt-1 font-semibold text-foreground first:pt-0\">\n {text.replace(/^#+\\s*/, \"\")}\n </div>,\n );\n continue;\n }\n // An evaluator-set field wins over an author marker; otherwise the marker applies.\n const hint = hints[result.line - 1];\n const rule = result.rule ?? hint?.rule;\n const tint = result.tint ?? hint?.tint;\n rows.push(\n <div\n key={key}\n data-rule={rule}\n data-tint={tint}\n className={cn(\n \"flex items-baseline justify-between gap-x-6\",\n rule && RULE_CLASS[rule],\n tint != null && cn(\"-mx-2 rounded-sm px-2\", TINT_CLASS[tint]),\n )}\n >\n <div className=\"min-w-0 whitespace-pre-wrap break-words text-foreground\">\n {renderSource(text, result.tokens)}\n </div>\n <ResultCell result={result} />\n </div>,\n );\n }\n\n return (\n <div\n ref={ref}\n data-testid=\"calc-block\"\n role=\"group\"\n aria-labelledby={titleId}\n className={cn(\"my-4 overflow-hidden rounded-md border border-border bg-card\", className)}\n {...props}\n >\n <div className=\"border-b border-border px-4 py-1.5\">\n <span\n id={titleId}\n className={cn(\n \"text-meta\",\n hasTitle\n ? \"font-medium text-foreground\"\n : \"font-mono uppercase tracking-wide text-muted-foreground\",\n )}\n >\n {resolvedTitle}\n </span>\n </div>\n\n {empty ? (\n <p className=\"px-4 py-6 text-body text-muted-foreground\">\n {t(\"editor.calcBlock.emptyBlock\")}\n </p>\n ) : (\n <div className=\"flex flex-col gap-y-1 px-4 py-3 font-mono text-code leading-relaxed\">\n {rows}\n </div>\n )}\n\n {showTotal && resolvedTotal != null && !empty ? (\n <div className=\"flex items-center justify-between border-t border-border px-4 py-2\">\n <span className=\"text-meta font-medium uppercase tracking-wide text-muted-foreground\">\n {totalLabel}\n </span>\n <span className=\"font-mono text-code font-medium tabular-nums text-foreground\">\n {totalDisplay}\n </span>\n </div>\n ) : null}\n </div>\n );\n});\n","\"use client\";\n\n/**\n * CalcInline — an inline `:calc[expr]` directive rendered as a result chip (#L).\n *\n * The inline sibling of {@link CalcBlock}, same contract: the library RENDERS, the\n * consumer EVALUATES. `evaluate(expr)` returns a `CalcSheet`; the chip shows the\n * first line's value (the expression's result) with the verbatim source as a\n * native hover `title` and in the accessible name (`\"85 USD * 32 = 2,720 USD\"`). A\n * bad expression renders a calm inline warning — it never throws or blanks the\n * sentence. A native `title` (not a Radix Tooltip) keeps the chip self-contained,\n * so it drops into rendered prose with no `TooltipProvider` ancestor.\n *\n * Color comes from the shared `--calc-*` tokens (#221): the result reads in\n * `text-calc-result`; the warning cue is the icon + dotted underline, never hue\n * alone (so it survives the high-contrast theme).\n */\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { TriangleAlert } from \"lucide-react\";\nimport { forwardRef, useMemo, type HTMLAttributes } from \"react\";\n\nimport type { EvaluateCalc } from \"./types\";\n\nexport interface CalcInlineProps extends Omit<HTMLAttributes<HTMLElement>, \"children\"> {\n /** The inline expression, e.g. `85 USD * 32`. */\n source: string;\n /** Consumer-supplied evaluator (sync). The library bundles no math engine. */\n evaluate: EvaluateCalc;\n}\n\nexport const CalcInline = forwardRef<HTMLSpanElement, CalcInlineProps>(function CalcInline(\n { source, evaluate, className, ...props },\n ref,\n) {\n const sheet = useMemo(() => evaluate(source), [evaluate, source]);\n const first = sheet.results[0];\n const display = first?.value?.display;\n const error = first?.error ?? (display == null ? { message: \"No result\" } : undefined);\n\n if (error) {\n return (\n <span\n ref={ref}\n data-testid=\"calc-inline\"\n data-calc-error=\"\"\n title={error.message}\n aria-label={`${source}: ${error.message}`}\n className={cn(\n \"inline-flex items-center gap-0.5 align-baseline font-mono text-calc-warning underline decoration-dotted decoration-1 underline-offset-2\",\n className,\n )}\n {...props}\n >\n <TriangleAlert className=\"size-3\" aria-hidden=\"true\" />\n <span>{source}</span>\n </span>\n );\n }\n\n return (\n <span\n ref={ref}\n data-testid=\"calc-inline\"\n title={source}\n aria-label={`${source} = ${display}`}\n className={cn(\n \"inline-flex items-center rounded-sm bg-calc-result/10 px-1 align-baseline font-mono tabular-nums text-calc-result\",\n className,\n )}\n {...props}\n >\n {display}\n </span>\n );\n});\n","\"use client\";\n\n/**\n * MermaidDiagram — the branded Mermaid renderer (#L1).\n *\n * Renders a ```mermaid source string as an SVG diagram, themed from the active\n * semantic tokens (no raw colors here): the mermaid engine is initialized with\n * `theme: \"base\"` + `themeVariables` resolved at render time from the CSS\n * variables in scope, so the diagram follows every `data-theme` — including\n * runtime switches (a MutationObserver re-renders on theme change).\n *\n * The `mermaid` package is loaded lazily on first render, so consumers that\n * never show a diagram never download the engine. Invalid sources render an\n * inline error block (message + source), never a thrown render.\n */\nimport { Button, Dialog, DialogContent, DialogTitle, useLocale } from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { Download, Maximize2 } from \"lucide-react\";\nimport { forwardRef, useEffect, useRef, useState, type HTMLAttributes } from \"react\";\n\nimport { oklchToHex } from \"@elabs-ai/components-tokens\";\n\nimport { CopyButton } from \"../copy-button\";\nimport { MermaidViewer } from \"./mermaid-viewer\";\nimport { offendingToken, remediateReservedIds } from \"./remediate\";\n\nexport interface MermaidDiagramProps extends HTMLAttributes<HTMLDivElement> {\n /** Mermaid source (the fence body). */\n chart: string;\n /** Accessible name for the rendered diagram. Default \"Diagram\". */\n label?: string;\n /** Show the hover copy-source button. Default true. */\n copyable?: boolean;\n /** Show the hover expand-to-modal button. Default true. */\n expandable?: boolean;\n /**\n * In-document search term (≥2 chars): nodes/edge labels whose text contains\n * it get the hit stroke — the diagram participates in document search.\n */\n highlightTerm?: string;\n /**\n * Source text of the ACTIVE search hit (the clicked finding's line). The\n * matching hit is promoted to the primary \"active\" stroke.\n */\n activeText?: string;\n}\n\n/** Semantic token → mermaid `themeVariables` mapping (resolved per render). */\nconst TOKEN_VARS: Record<string, string> = {\n background: \"--background\",\n mainBkg: \"--card\",\n primaryColor: \"--muted\",\n primaryTextColor: \"--foreground\",\n primaryBorderColor: \"--border-strong\",\n secondaryColor: \"--secondary\",\n tertiaryColor: \"--muted\",\n lineColor: \"--muted-foreground\",\n textColor: \"--foreground\",\n nodeBorder: \"--border-strong\",\n clusterBkg: \"--surface-muted\",\n clusterBorder: \"--border\",\n titleColor: \"--foreground\",\n edgeLabelBackground: \"--background\",\n errorBkgColor: \"--destructive\",\n errorTextColor: \"--destructive-foreground\",\n};\n\nlet renderSeq = 0;\n\n/**\n * Serializes every `mermaid.initialize()` + `mermaid.render()` pair across\n * every `MermaidDiagram` instance on the page.\n *\n * The `mermaid` package configures itself through ONE module-level global\n * (`mermaid.initialize`/`setConfig`) — `render()` takes no per-call config —\n * so two diagrams rendering concurrently (e.g. under different `data-theme`\n * scopes, or just two diagrams mounting together) can interleave: instance A\n * calls `initialize({theme: A})`, then before A's `render()` finishes reading\n * it, instance B calls `initialize({theme: B})` and A's diagram comes out\n * themed as B. Routing every render through this queue makes \"initialize,\n * then render\" atomic with respect to every other instance.\n */\nlet mermaidRenderQueue: Promise<unknown> = Promise.resolve();\n\nfunction withMermaidLock<T>(task: () => Promise<T>): Promise<T> {\n const result = mermaidRenderQueue.then(task, task);\n // Never let a failed render break the chain for the next caller.\n mermaidRenderQueue = result.then(\n () => undefined,\n () => undefined,\n );\n return result;\n}\n\n/**\n * How long to let `chart` sit unchanged before actually rendering it — a\n * source streamed in token-by-token (an LLM authoring one live) would\n * otherwise trigger a full mermaid parse + layout on every partial,\n * malformed intermediate string.\n */\nconst RENDER_DEBOUNCE_MS = 300;\n\n/**\n * Search-hit strokes for rendered nodes — token-driven, shared by the inline\n * render and the expanded viewer (a `<style>` is document-global wherever it\n * mounts, so one copy per diagram instance is enough).\n */\nconst HIT_CSS = `\n .wb-dg-hit :is(rect, polygon, circle, ellipse, path.basic) { stroke: var(--warning) !important; stroke-width: 2.5px !important; }\n .wb-dg-hit-active :is(rect, polygon, circle, ellipse, path.basic) { stroke: var(--primary) !important; stroke-width: 3px !important; }\n .wb-dg-hit.edgeLabel { outline: 2px solid var(--warning); border-radius: 2px; }\n .wb-dg-hit-active.edgeLabel { outline: 2px solid var(--primary); border-radius: 2px; }\n`;\n\n/** Does mermaid's color lib (khroma) understand this format already? */\nconst KHROMA_SAFE_RE = /^(#|rgba?\\(|hsla?\\()/i;\n\n/**\n * Normalize any CSS color (incl. oklch tokens) to a hex/rgb string the mermaid\n * engine (khroma) can manipulate. oklch converts mathematically (browsers do\n * NOT re-serialize it to rgb — Chromium's canvas keeps the oklch string);\n * anything else unknown falls back to canvas serialization, then raw.\n */\nfunction normalizeColor(value: string, ctx: CanvasRenderingContext2D | null): string {\n const v = value.trim();\n if (!v || KHROMA_SAFE_RE.test(v)) return v;\n const fromOklch = oklchToHex(v);\n if (fromOklch) return fromOklch;\n if (ctx) {\n try {\n ctx.fillStyle = \"#000\";\n ctx.fillStyle = v;\n if (KHROMA_SAFE_RE.test(ctx.fillStyle)) return ctx.fillStyle;\n } catch {\n // fall through to raw\n }\n }\n return v;\n}\n\nfunction resolveThemeVariables(el: HTMLElement): Record<string, string> {\n const styles = getComputedStyle(el);\n let ctx: CanvasRenderingContext2D | null = null;\n try {\n ctx = document.createElement(\"canvas\").getContext(\"2d\");\n } catch {\n ctx = null;\n }\n const vars: Record<string, string> = {\n fontFamily: styles.getPropertyValue(\"--font-sans\").trim() || \"inherit\",\n };\n for (const [mermaidVar, token] of Object.entries(TOKEN_VARS)) {\n const raw = styles.getPropertyValue(token).trim();\n if (raw) vars[mermaidVar] = normalizeColor(raw, ctx);\n }\n return vars;\n}\n\nexport const MermaidDiagram = forwardRef<HTMLDivElement, MermaidDiagramProps>(\n function MermaidDiagram(\n {\n chart,\n label: labelProp,\n copyable = true,\n expandable = true,\n highlightTerm,\n activeText,\n className,\n ...props\n },\n ref,\n ) {\n const { t } = useLocale();\n const label = labelProp ?? t(\"editor.mermaidDiagram.label\");\n const hostRef = useRef<HTMLDivElement | null>(null);\n const svgHostRef = useRef<HTMLDivElement | null>(null);\n const [svg, setSvg] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [expanded, setExpanded] = useState(false);\n\n const downloadSvg = () => {\n if (!svg) return;\n const blob = new Blob([svg], { type: \"image/svg+xml\" });\n const url = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = `${label.toLowerCase().replace(/[^a-z0-9]+/g, \"-\") || \"diagram\"}.svg`;\n a.click();\n // Defer the revoke past the current task: some browsers (Safari) start\n // the save asynchronously off the click and cancel it if the object URL\n // is invalidated too early.\n setTimeout(() => URL.revokeObjectURL(url), 0);\n };\n // Bumped by the observer when the governing data-theme changes.\n const [themeVersion, setThemeVersion] = useState(0);\n\n useEffect(() => {\n const host = hostRef.current;\n if (!host) return;\n const scope = host.closest(\"[data-theme]\") ?? document.documentElement;\n const observer = new MutationObserver(() => setThemeVersion((v) => v + 1));\n observer.observe(scope, { attributes: true, attributeFilter: [\"data-theme\"] });\n return () => observer.disconnect();\n }, []);\n\n useEffect(() => {\n let cancelled = false;\n const host = hostRef.current;\n if (!host || !chart.trim()) {\n setSvg(null);\n setError(null);\n return;\n }\n // Debounce: a `chart` fed from a streaming source changes on every\n // token, and a mermaid parse + layout is not cheap enough to run on\n // every one of those partial, often-invalid intermediate strings — wait\n // for the source to sit still for RENDER_DEBOUNCE_MS first.\n const timer = setTimeout(() => {\n void withMermaidLock(async () => {\n if (cancelled) return;\n try {\n const mermaid = (await import(\"mermaid\")).default;\n if (cancelled) return;\n mermaid.initialize({\n startOnLoad: false,\n securityLevel: \"strict\",\n suppressErrorRendering: true,\n theme: \"base\",\n themeVariables: resolveThemeVariables(host),\n });\n const render = (source: string) =>\n mermaid.render(`brand-mermaid-${++renderSeq}`, source);\n let out;\n try {\n out = await render(chart);\n } catch (firstErr) {\n // Reserved-keyword node ids (\"graph[...]\", \"end[...]\") are the\n // most common authoring mistake — remediate the id (labels stay)\n // and retry once instead of failing the reader.\n const token = offendingToken(\n firstErr instanceof Error ? firstErr.message : String(firstErr),\n );\n const fixed = token ? remediateReservedIds(chart, token) : null;\n if (!fixed) throw firstErr;\n out = await render(fixed);\n }\n if (cancelled) return;\n setSvg(out.svg);\n setError(null);\n } catch (err) {\n if (cancelled) return;\n setSvg(null);\n setError(err instanceof Error ? err.message : String(err));\n }\n });\n }, RENDER_DEBOUNCE_MS);\n return () => {\n cancelled = true;\n clearTimeout(timer);\n };\n }, [chart, themeVersion]);\n\n // Mark search hits on the rendered nodes (class toggles only — the SVG\n // markup is mermaid's; we never rebuild it for a highlight change).\n useEffect(() => {\n const root = svgHostRef.current;\n if (!root) return;\n const term = (highlightTerm ?? \"\").trim().toLowerCase();\n const active = (activeText ?? \"\").trim().toLowerCase();\n for (const node of root.querySelectorAll<SVGGElement>(\"g.node, g.edgeLabel\")) {\n const text = (node.textContent ?? \"\").trim().toLowerCase();\n const hit = term.length >= 2 && text.length > 0 && text.includes(term);\n node.classList.toggle(\"wb-dg-hit\", hit);\n node.classList.toggle(\n \"wb-dg-hit-active\",\n hit && active.length > 0 && (active.includes(text) || text.includes(active)),\n );\n }\n }, [svg, highlightTerm, activeText]);\n\n return (\n <div\n ref={(el) => {\n hostRef.current = el;\n if (typeof ref === \"function\") ref(el);\n else if (ref) ref.current = el;\n }}\n data-testid=\"mermaid-diagram\"\n className={cn(\"group/mermaid relative\", className)}\n {...props}\n >\n {svg && (copyable || expandable) ? (\n <div className=\"absolute end-2 top-2 z-10 flex gap-1 opacity-0 transition-opacity duration-fast ease-standard focus-within:opacity-100 group-hover/mermaid:opacity-100 motion-reduce:transition-none\">\n {expandable ? (\n <Button\n variant=\"outline\"\n size=\"icon-sm\"\n aria-label={t(\"editor.mermaidDiagram.expand\")}\n onClick={() => setExpanded(true)}\n >\n <Maximize2 className=\"size-3.5\" />\n </Button>\n ) : null}\n <Button\n variant=\"outline\"\n size=\"icon-sm\"\n aria-label={t(\"editor.mermaidDiagram.downloadSvg\")}\n onClick={downloadSvg}\n >\n <Download className=\"size-3.5\" />\n </Button>\n {copyable ? (\n <CopyButton\n value={chart}\n label={false}\n aria-label={t(\"editor.mermaidDiagram.copySource\")}\n size=\"icon-sm\"\n />\n ) : null}\n </div>\n ) : null}\n {error ? (\n <div\n role=\"alert\"\n className=\"space-y-2 border-s-2 border-s-destructive bg-destructive/10 p-3 text-body\"\n >\n <p className=\"font-medium text-destructive-text\">\n {t(\"editor.mermaidDiagram.renderFailed\")}\n </p>\n <p className=\"text-muted-foreground\">{error}</p>\n <pre className=\"overflow-x-auto rounded bg-muted p-2 font-mono text-code text-foreground\">\n {chart}\n </pre>\n </div>\n ) : svg ? (\n <>\n <style>{HIT_CSS}</style>\n <div\n ref={svgHostRef}\n role=\"img\"\n aria-label={label}\n className=\"overflow-x-auto rounded-md bg-card p-3 [&_svg]:mx-auto [&_svg]:h-auto [&_svg]:max-w-full\"\n // Mermaid output; securityLevel \"strict\" sanitizes the source.\n dangerouslySetInnerHTML={{ __html: svg }}\n />\n </>\n ) : (\n <div\n role=\"status\"\n aria-label={t(\"editor.mermaidDiagram.rendering\")}\n className=\"h-24 animate-pulse rounded-md bg-surface-muted motion-reduce:animate-none\"\n />\n )}\n\n {expandable ? (\n <Dialog open={expanded} onOpenChange={setExpanded}>\n <DialogContent className=\"flex h-[88dvh] w-[92vw] max-w-[92vw] flex-col p-4 sm:max-w-[92vw]\">\n <DialogTitle className=\"sr-only\">{label}</DialogTitle>\n {/* Hit strokes ship via the shared HIT_CSS <style> above. */}\n {svg ? <MermaidViewer svg={svg} label={label} /> : null}\n </DialogContent>\n </Dialog>\n ) : null}\n </div>\n );\n },\n);\n","\"use client\";\n\n/**\n * MermaidViewer — the expanded diagram surface: wheel-zoom at the cursor,\n * drag-pan, fit/100% controls, and a left search panel that filters the\n * RENDERED nodes, highlights every hit and zooms to the selected one.\n */\nimport { Button, Input, useLocale } from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { Maximize, Minus, Plus } from \"lucide-react\";\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type PointerEvent as ReactPointerEvent,\n type WheelEvent as ReactWheelEvent,\n} from \"react\";\n\ninterface DiagramHit {\n id: string;\n label: string;\n}\n\ninterface Transform {\n scale: number;\n tx: number;\n ty: number;\n}\n\nconst MIN_SCALE = 0.2;\nconst MAX_SCALE = 6;\nconst HIT_CLASS = \"wb-dg-hit\";\nconst HIT_ACTIVE_CLASS = \"wb-dg-hit-active\";\n\nconst clampScale = (s: number) => Math.min(MAX_SCALE, Math.max(MIN_SCALE, s));\n\n/**\n * Fit-to-viewport transform (centered), or `null` while either box is\n * unmeasured. Guarding here is what fixes the \"opens at MIN_SCALE pinned\n * top-left\" defect: the dialog mounts BEFORE layout, so a 0-sized container\n * used to produce a negative → clamped-to-minimum scale.\n */\nexport function fitTransform(\n container: { width: number; height: number },\n natural: { width: number; height: number },\n pad = 24,\n): Transform | null {\n if (container.width <= pad || container.height <= pad) return null;\n if (!natural.width || !natural.height) return null;\n // Fit means \"make it all visible\", never \"blow it up\": small diagrams stay\n // at natural size (100%), centered — upscaling reads as a broken zoom.\n const scale = clampScale(\n Math.min(1, (container.width - pad) / natural.width, (container.height - pad) / natural.height),\n );\n return {\n scale,\n tx: (container.width - natural.width * scale) / 2,\n ty: (container.height - natural.height * scale) / 2,\n };\n}\n\n/**\n * Human-readable label for a rendered diagram node. Mermaid renders multi-line\n * labels as sibling text containers (`tspan` lines, or `p`/`span` inside the\n * htmlLabels foreignObject); raw `textContent` concatenates them WITHOUT\n * separators (\"Microsoft Graph APIOutlook / C…\"). Join the leaf segments with\n * a \"·\" instead.\n */\nexport function diagramNodeLabel(node: Element): string {\n const candidates = Array.from(node.querySelectorAll(\"tspan, p, span\"));\n const leaves = candidates.filter((el) => !el.querySelector(\"tspan, p, span\"));\n const parts = leaves\n .map((el) => (el.textContent ?? \"\").trim().replace(/\\s+/g, \" \"))\n .filter(Boolean);\n if (parts.length === 0) return (node.textContent ?? \"\").trim().replace(/\\s+/g, \" \");\n return parts.join(\" · \");\n}\n\nexport function MermaidViewer({ svg, label }: { svg: string; label: string }) {\n const { t } = useLocale();\n const containerRef = useRef<HTMLDivElement | null>(null);\n const stageRef = useRef<HTMLDivElement | null>(null);\n const [transform, setTransform] = useState<Transform>({ scale: 1, tx: 0, ty: 0 });\n const [hits, setHits] = useState<DiagramHit[]>([]);\n const [query, setQuery] = useState(\"\");\n const [activeHit, setActiveHit] = useState<string | null>(null);\n const dragRef = useRef<{ x: number; y: number; tx: number; ty: number } | null>(null);\n /** The user took over (zoom/pan) — stop auto-fitting on container resize. */\n const userDrivenRef = useRef(false);\n\n /** Natural (untransformed) svg size in px. */\n const naturalSize = useRef<{ w: number; h: number }>({ w: 0, h: 0 });\n\n const fit = useCallback((): boolean => {\n const container = containerRef.current;\n const { w, h } = naturalSize.current;\n if (!container) return false;\n const next = fitTransform(\n { width: container.clientWidth, height: container.clientHeight },\n { width: w, height: h },\n );\n if (next) setTransform(next);\n return next !== null;\n }, []);\n\n // Mount: size the svg naturally, collect searchable nodes, fit to view.\n useEffect(() => {\n const stage = stageRef.current;\n const svgEl = stage?.querySelector(\"svg\");\n if (!stage || !svgEl) return;\n const viewBox = svgEl.viewBox?.baseVal;\n const w = viewBox?.width || svgEl.getBoundingClientRect().width || 800;\n const h = viewBox?.height || svgEl.getBoundingClientRect().height || 600;\n // Replace mermaid's inline style WHOLESALE (it ships `max-width: Xpx`\n // which silently beat per-property overrides — the fit math then used the\n // viewBox size while the svg rendered capped: the \"26% blob\" defect).\n svgEl.setAttribute(\"style\", `max-width:none;width:${w}px;height:${h}px;`);\n svgEl.setAttribute(\"width\", String(w));\n svgEl.setAttribute(\"height\", String(h));\n // Trust the PIXELS, not the assumption: measure the rendered box (the\n // stage transform is still identity at mount). Fall back to viewBox.\n const rect = svgEl.getBoundingClientRect();\n naturalSize.current = {\n w: rect.width > 0 ? rect.width : w,\n h: rect.height > 0 ? rect.height : h,\n };\n\n const found: DiagramHit[] = [];\n const seen = new Set<string>();\n for (const node of svgEl.querySelectorAll<SVGGElement>(\"g.node, g.edgeLabel\")) {\n const text = diagramNodeLabel(node);\n if (!text || !node.id) continue;\n if (seen.has(node.id)) continue;\n seen.add(node.id);\n found.push({ id: node.id, label: text });\n }\n setHits(found);\n // The dialog animates open — retry across the first frames until the\n // container has real dimensions (belt to the ResizeObserver's braces).\n if (!fit()) {\n let tries = 0;\n let raf = 0;\n const attempt = () => {\n if (userDrivenRef.current) return;\n if (!fit() && ++tries < 30) raf = requestAnimationFrame(attempt);\n };\n raf = requestAnimationFrame(attempt);\n return () => cancelAnimationFrame(raf);\n }\n }, [svg, fit]);\n\n // The dialog mounts before layout settles, so the mount-time fit() can see a\n // 0-sized container (fitTransform skips it). Re-fit when the container gains\n // or changes size — until the user zooms/pans, after which their view wins.\n useEffect(() => {\n const container = containerRef.current;\n if (!container || typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(() => {\n if (!userDrivenRef.current) fit();\n });\n observer.observe(container);\n return () => observer.disconnect();\n }, [fit]);\n\n // Highlight matching nodes as the query changes.\n const q = query.trim().toLowerCase();\n const matches = useMemo(\n () => (q.length >= 2 ? hits.filter((hit) => hit.label.toLowerCase().includes(q)) : []),\n [hits, q],\n );\n\n useEffect(() => {\n const svgEl = stageRef.current?.querySelector(\"svg\");\n if (!svgEl) return;\n const matchIds = new Set(matches.map((m) => m.id));\n for (const node of svgEl.querySelectorAll<SVGGElement>(\"g.node, g.edgeLabel\")) {\n node.classList.toggle(HIT_CLASS, matchIds.has(node.id));\n // The ACTIVE highlight is independent of the query filter: after the\n // user clicks a result (and the query changes or clears), the found\n // node must stay visibly marked.\n node.classList.toggle(HIT_ACTIVE_CLASS, node.id === activeHit);\n }\n }, [matches, activeHit]);\n\n const zoomAt = useCallback((clientX: number, clientY: number, factor: number) => {\n const container = containerRef.current;\n if (!container) return;\n userDrivenRef.current = true;\n const rect = container.getBoundingClientRect();\n setTransform((prev) => {\n const scale = clampScale(prev.scale * factor);\n const px = (clientX - rect.left - prev.tx) / prev.scale;\n const py = (clientY - rect.top - prev.ty) / prev.scale;\n return { scale, tx: clientX - rect.left - px * scale, ty: clientY - rect.top - py * scale };\n });\n }, []);\n\n const zoomCenter = (factor: number) => {\n const container = containerRef.current;\n if (!container) return;\n const rect = container.getBoundingClientRect();\n zoomAt(rect.left + rect.width / 2, rect.top + rect.height / 2, factor);\n };\n\n const zoomToHit = useCallback((id: string) => {\n const container = containerRef.current;\n const svgEl = stageRef.current?.querySelector(\"svg\");\n const node = svgEl?.querySelector<SVGGElement>(`[id=\"${CSS.escape(id)}\"]`);\n if (!container || !svgEl || !node) return;\n userDrivenRef.current = true;\n setActiveHit(id);\n setTransform((prev) => {\n const nodeRect = node.getBoundingClientRect();\n const containerRect = container.getBoundingClientRect();\n // Node center in svg-space (invert the current transform).\n const cx = (nodeRect.left + nodeRect.width / 2 - containerRect.left - prev.tx) / prev.scale;\n const cy = (nodeRect.top + nodeRect.height / 2 - containerRect.top - prev.ty) / prev.scale;\n const scale = clampScale(Math.max(prev.scale, 1.25));\n return {\n scale,\n tx: containerRect.width / 2 - cx * scale,\n ty: containerRect.height / 2 - cy * scale,\n };\n });\n }, []);\n\n const onWheel = (e: ReactWheelEvent) => {\n e.preventDefault();\n zoomAt(e.clientX, e.clientY, e.deltaY < 0 ? 1.12 : 1 / 1.12);\n };\n\n const onPointerDown = (e: ReactPointerEvent<HTMLDivElement>) => {\n if (e.button !== 0) return;\n userDrivenRef.current = true;\n dragRef.current = { x: e.clientX, y: e.clientY, tx: transform.tx, ty: transform.ty };\n (e.currentTarget as HTMLDivElement).setPointerCapture(e.pointerId);\n };\n const onPointerMove = (e: ReactPointerEvent<HTMLDivElement>) => {\n const drag = dragRef.current;\n if (!drag) return;\n setTransform((prev) => ({\n ...prev,\n tx: drag.tx + (e.clientX - drag.x),\n ty: drag.ty + (e.clientY - drag.y),\n }));\n };\n const onPointerUp = () => {\n dragRef.current = null;\n };\n\n return (\n <div className=\"flex min-h-0 flex-1 gap-3\">\n {/* Search rail */}\n <div className=\"flex w-60 shrink-0 flex-col border-e border-border pe-3\">\n <Input\n autoFocus\n type=\"search\"\n placeholder={t(\"editor.mermaidViewer.findPlaceholder\")}\n aria-label={t(\"editor.mermaidViewer.findLabel\")}\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n spellCheck={false}\n className=\"h-8 text-body\"\n />\n <p aria-live=\"polite\" className=\"px-1 pt-1.5 text-meta text-muted-foreground tabular-nums\">\n {q.length >= 2\n ? t(\"editor.mermaidViewer.matchCount\", { count: matches.length })\n : t(\"editor.mermaidViewer.nodeCountHint\", { count: hits.length })}\n </p>\n <ul className=\"m-0 mt-1 min-h-0 flex-1 list-none overflow-auto p-0\">\n {(q.length >= 2 ? matches : hits).map((hit) => (\n <li key={hit.id}>\n <button\n type=\"button\"\n onClick={() => zoomToHit(hit.id)}\n aria-pressed={activeHit === hit.id}\n className={cn(\n \"w-full truncate rounded-md px-2 py-1.5 text-start text-caption transition-colors duration-fast ease-standard motion-reduce:transition-none\",\n \"hover:bg-accent hover:text-accent-foreground\",\n \"focus-ring-inset\",\n activeHit === hit.id\n ? \"bg-accent font-medium text-foreground\"\n : \"text-muted-foreground\",\n )}\n >\n {hit.label}\n </button>\n </li>\n ))}\n </ul>\n </div>\n\n {/* Stage */}\n <div className=\"relative min-h-0 min-w-0 flex-1\">\n <div className=\"absolute end-2 top-2 z-10 flex gap-1\">\n <Button\n variant=\"outline\"\n size=\"icon-sm\"\n aria-label={t(\"editor.mermaidViewer.zoomOut\")}\n onClick={() => zoomCenter(1 / 1.25)}\n >\n <Minus className=\"size-3.5\" />\n </Button>\n <Button\n variant=\"outline\"\n size=\"icon-sm\"\n aria-label={t(\"editor.mermaidViewer.zoomIn\")}\n onClick={() => zoomCenter(1.25)}\n >\n <Plus className=\"size-3.5\" />\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"h-7 px-2 font-mono text-meta tabular-nums\"\n aria-label={t(\"editor.mermaidViewer.resetZoom\")}\n onClick={() => {\n userDrivenRef.current = true;\n setTransform((prev) => ({ ...prev, scale: 1 }));\n }}\n >\n {Math.round(transform.scale * 100)}%\n </Button>\n <Button\n variant=\"outline\"\n size=\"icon-sm\"\n aria-label={t(\"editor.mermaidViewer.fitDiagram\")}\n onClick={() => {\n // An explicit fit hands control back: keep fitting on resize.\n userDrivenRef.current = false;\n fit();\n }}\n >\n <Maximize className=\"size-3.5\" />\n </Button>\n </div>\n\n <div\n ref={containerRef}\n role=\"img\"\n aria-label={label}\n className={cn(\n \"h-full w-full touch-none select-none overflow-hidden rounded-md bg-surface-muted/50\",\n dragRef.current ? \"cursor-grabbing\" : \"cursor-grab\",\n )}\n onWheel={onWheel}\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n onPointerCancel={onPointerUp}\n onDoubleClick={(e) => zoomAt(e.clientX, e.clientY, 1.5)}\n >\n <div\n ref={stageRef}\n style={{\n transform: `translate(${transform.tx}px, ${transform.ty}px) scale(${transform.scale})`,\n transformOrigin: \"0 0\",\n }}\n // Same sanitized engine output as the inline rendering.\n dangerouslySetInnerHTML={{ __html: svg }}\n />\n </div>\n </div>\n </div>\n );\n}\n","/**\n * Mermaid reserved-identifier remediation.\n *\n * Authors routinely use flowchart KEYWORDS as node ids (`graph[Microsoft\n * Graph]`, `end[End]`, `class[...]`) — mermaid hard-fails (\"got 'GRAPH'\")\n * even though the intent is unambiguous. Instead of punting the error to the\n * reader, the diagram component extracts the offending token from the parse\n * error, rewrites that identifier with a trailing underscore, and retries\n * once. Labels, quoted strings and edge text (`|…|`) are never touched —\n * only the invisible id changes.\n */\n\nexport const FLOWCHART_RESERVED = new Set([\n \"graph\",\n \"flowchart\",\n \"subgraph\",\n \"end\",\n \"style\",\n \"linkstyle\",\n \"classdef\",\n \"class\",\n \"click\",\n \"direction\",\n \"default\",\n \"state\",\n]);\n\n/** Pull the offending token out of a mermaid parse error (\"… got 'GRAPH'\"). */\nexport function offendingToken(errorMessage: string): string | null {\n const m = /got '([A-Za-z_]+)'/.exec(errorMessage);\n return m ? m[1]!.toLowerCase() : null;\n}\n\n/** A true diagram declaration line: keyword + direction and nothing else. */\nconst DECLARATION_RE = /^(graph|flowchart)\\s+(tb|td|bt|rl|lr)\\s*;?\\s*$/;\n\n/**\n * Replace `re` matches only OUTSIDE label/quote/edge-text segments:\n * `[...]`, `(...)`, `{...}`, `\"...\"` and `|...|` contents stay verbatim.\n */\nfunction replaceOutsideLabels(line: string, re: RegExp, repl: string): string {\n let out = \"\";\n let buf = \"\";\n let depth = 0;\n let inQuote = false;\n let inPipe = false;\n\n const flush = () => {\n out += buf.replace(re, repl);\n buf = \"\";\n };\n\n for (const ch of line) {\n if (inQuote) {\n out += ch;\n if (ch === '\"') inQuote = false;\n continue;\n }\n if (depth === 0 && ch === \"|\") {\n if (!inPipe) flush();\n inPipe = !inPipe;\n out += ch;\n continue;\n }\n if (inPipe) {\n out += ch;\n continue;\n }\n if (ch === '\"') {\n flush();\n out += ch;\n inQuote = true;\n continue;\n }\n if (ch === \"[\" || ch === \"(\" || ch === \"{\") {\n if (depth === 0) flush();\n depth++;\n out += ch;\n continue;\n }\n if (ch === \"]\" || ch === \")\" || ch === \"}\") {\n if (depth > 0) depth--;\n if (depth === 0) {\n out += ch;\n continue;\n }\n out += ch;\n continue;\n }\n if (depth === 0) buf += ch;\n else out += ch;\n }\n flush();\n return out;\n}\n\n/**\n * Rewrite a reserved word used as a node id to `<word>_`. Structural keyword\n * positions are preserved: declaration lines (`flowchart TD`), `subgraph`\n * keyword lines and lone `end` terminators stay intact. Returns the\n * rewritten source, or null when nothing remediable changed.\n */\nexport function remediateReservedIds(chart: string, token: string): string | null {\n const t = token.toLowerCase();\n if (!FLOWCHART_RESERVED.has(t)) return null;\n const re = new RegExp(`\\\\b${t}\\\\b`, \"gi\");\n let changed = false;\n const repl = `${t}_`;\n\n const out = chart\n .split(\"\\n\")\n .map((line) => {\n const trimmed = line.trim().toLowerCase();\n if (trimmed === t) return line; // lone keyword (e.g. subgraph terminator `end`)\n if (DECLARATION_RE.test(trimmed)) return line; // `graph TD` / `flowchart LR`\n if (t === \"subgraph\" && trimmed.startsWith(\"subgraph\")) return line;\n const next = replaceOutsideLabels(line, re, repl);\n if (next !== line) changed = true;\n return next;\n })\n .join(\"\\n\");\n\n return changed ? out : null;\n}\n","/**\n * Prose primitives — re-exported from @elabs-ai/components-ui (#188; ADR-0012 own/re-export\n * model: @elabs-ai/components-ui owns the canonical prose source in\n * `components/typography/prose.tsx`; this package derives). The\n * `@elabs-ai/components-editor/markdown` public surface keeps the original names\n * (Heading, Text, Link, List, ListItem, Blockquote, InlineCode).\n *\n * These must stay the SAME objects, not lookalikes: that identity is the whole\n * reason a `Prose*` change cannot drift the editor away from the chat view or\n * the file viewer. `prose.test.ts` asserts it against the package barrel — if\n * you replace a line below with a local component, that test goes red while the\n * behaviour tests in `prose.test.tsx` stay green, which is exactly the failure\n * it exists to catch.\n */\nexport {\n ProseHeading as Heading,\n ProseText as Text,\n ProseLink as Link,\n ProseList as List,\n ProseListItem as ListItem,\n ProseBlockquote as Blockquote,\n ProseInlineCode as InlineCode,\n type ProseHeadingProps as HeadingProps,\n type ProseHeadingLevel as HeadingLevel,\n type ProseTextProps as TextProps,\n type ProseLinkProps as LinkProps,\n type ProseListProps as ListProps,\n} from \"@elabs-ai/components-ui\";\n","/**\n * Timeline — MOVED to `@elabs-ai/components-ui` (#190, research 10 §B.2; the ADR-0012\n * own/re-export model). `@elabs-ai/components-ui` owns the canonical rail; this shim keeps\n * the editor-facing surface byte-compatible — `markdown/index.ts` and the\n * `:::timeline` preview keep importing from `../timeline` unchanged.\n *\n * `TimelineItem` here is the ARRAY-item data shape (named `TimelineEntry` in\n * `@elabs-ai/components-ui`, where `TimelineItem` is the compound `<li>` part); the alias\n * preserves the editor's original public type name. `TimelineStatus`\n * (`done|active|pending`) now lives with its `fromTimelineStatus` mapper in\n * status-badge and reaches the `@elabs-ai/components-ui` barrel from there.\n */\nexport {\n Timeline,\n type TimelineEntry as TimelineItem,\n type TimelineProps,\n type TimelineStatus,\n} from \"@elabs-ai/components-ui\";\n","\"use client\";\n\n/**\n * CodeFence — the highlighted non-mermaid code fence inside MarkdownPreview.\n *\n * Highlighting rides on the SAME engine the rest of the workspace already\n * ships (`@streamdown/code`, Streamdown's shiki plugin — cached highlighters,\n * sync-after-first-tokenize), but the theme is a shiki **CSS-variables theme**:\n * every token color resolves to a `var(--md-code-*)` reference that this\n * component maps onto the semantic tokens below. One theme, correct in every\n * `data-theme` (light, dark, …) — no per-theme shiki theme, no raw\n * colors, and a runtime theme switch recolors already-tokenized code for free.\n *\n * Until shiki finishes loading (or for a fence with no language tag) the raw\n * fence text renders as before — highlighting is a progressive enhancement.\n */\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { code as codeHighlighter } from \"@streamdown/code\";\nimport {\n useEffect,\n useRef,\n useState,\n type CSSProperties,\n type HTMLAttributes,\n type ReactNode,\n} from \"react\";\nimport type { BundledLanguage, ThemedToken, TokensResult } from \"shiki\";\nimport { createCssVariablesTheme } from \"shiki\";\n\nimport { CopyButton } from \"../copy-button\";\n\n/** Extract the fence language from react-markdown's `language-*` className. */\nexport function fenceLanguage(className?: string): string | undefined {\n return /\\blanguage-([\\w+#.-]+)\\b/.exec(className ?? \"\")?.[1];\n}\n\n/**\n * One shiki theme for BOTH slots (the plugin API is [light, dark]): colors are\n * pure CSS-variable references, so the active `data-theme` decides the actual\n * values — both slots resolve identically by construction.\n */\nconst cssVariablesTheme = createCssVariablesTheme({\n name: \"brand-tokens\",\n variablePrefix: \"--md-code-\",\n fontStyle: true,\n});\nconst SHIKI_THEMES: [typeof cssVariablesTheme, typeof cssVariablesTheme] = [\n cssVariablesTheme,\n cssVariablesTheme,\n];\n\n/**\n * The `--md-code-*` seams mapped onto semantic tokens (scoped to the fence, so\n * nothing leaks into `themes.css`). Chart tokens carry the categorical hues —\n * they are the only themed accent ramp guaranteed to exist in every theme.\n */\nconst SHIKI_TOKEN_VARS = cn(\n \"[--md-code-foreground:var(--foreground)]\",\n \"[--md-code-background:transparent]\",\n \"[--md-code-token-comment:var(--muted-foreground)]\",\n \"[--md-code-token-constant:var(--chart-1)]\",\n \"[--md-code-token-function:var(--chart-3)]\",\n \"[--md-code-token-keyword:var(--chart-4)]\",\n \"[--md-code-token-link:var(--primary)]\",\n \"[--md-code-token-parameter:var(--chart-5)]\",\n \"[--md-code-token-punctuation:var(--muted-foreground)]\",\n \"[--md-code-token-string-expression:var(--chart-2)]\",\n \"[--md-code-token-string:var(--chart-2)]\",\n);\n\n// Shiki encodes font style as bitflags: 1 = italic, 2 = bold, 4 = underline.\nconst hasFontFlag = (fontStyle: number | undefined, flag: number) =>\n ((fontStyle ?? 0) & flag) === flag;\n\nfunction tokenStyle(token: ThemedToken): CSSProperties {\n return {\n // htmlStyle.color carries the theme var; token.color is the fallback path.\n color: (token.htmlStyle as Record<string, string> | undefined)?.color ?? token.color,\n fontStyle: hasFontFlag(token.fontStyle, 1) ? \"italic\" : undefined,\n fontWeight: hasFontFlag(token.fontStyle, 2) ? \"bold\" : undefined,\n textDecoration: hasFontFlag(token.fontStyle, 4) ? \"underline\" : undefined,\n };\n}\n\n/**\n * Tokenize via the shared plugin. Returns `null` until the highlighter is\n * ready (first render of a language) — cached fences resolve synchronously.\n */\nfunction useHighlightedTokens(codeText: string, language: string | undefined) {\n const [result, setResult] = useState<TokensResult | null>(null);\n const keyRef = useRef({ codeText, language });\n\n // Invalidate stale tokens synchronously during render (no flash of the\n // previous fence's tokens when the source changes).\n if (keyRef.current.codeText !== codeText || keyRef.current.language !== language) {\n keyRef.current = { codeText, language };\n setResult(null);\n }\n\n useEffect(() => {\n if (!language) return undefined; // no language tag — keep the plain text\n let cancelled = false;\n const sync = codeHighlighter.highlight(\n // Unknown languages fall back to \"text\" inside the plugin.\n { code: codeText, language: language as BundledLanguage, themes: SHIKI_THEMES },\n (r) => {\n if (!cancelled) setResult(r);\n },\n );\n if (sync && !cancelled) setResult(sync);\n return () => {\n cancelled = true;\n };\n }, [codeText, language]);\n\n return result;\n}\n\nexport interface CodeFenceProps extends HTMLAttributes<HTMLElement> {\n /** Raw fence text (trailing newline already stripped). */\n codeText: string;\n /** The fence's language tag (` ```ts `), if any. */\n language?: string;\n /** This fence contains the active in-document search hit. */\n searchActive?: boolean;\n /** Fallback content (the un-highlighted fence) while shiki loads. */\n children?: ReactNode;\n}\n\nexport function CodeFence({\n codeText,\n language,\n searchActive,\n className,\n children,\n ...props\n}: CodeFenceProps) {\n const tokens = useHighlightedTokens(codeText, language)?.tokens ?? null;\n\n return (\n <div\n data-code-fence={language ?? \"\"}\n className={cn(\"group/code-fence relative my-3\", className)}\n {...props}\n >\n <pre\n data-search-active={searchActive ? \"\" : undefined}\n className={cn(\n \"!my-0 overflow-x-auto rounded-md p-3 font-mono text-code\",\n SHIKI_TOKEN_VARS,\n searchActive ? \"bg-primary/10\" : \"bg-surface-muted\",\n )}\n >\n {tokens ? (\n <code>\n {tokens.map((line, lineIdx) => (\n // Lines are positionally stable for a given source string (the\n // whole list is rebuilt when `codeText` changes).\n <span key={`line-${lineIdx}`} className=\"block\">\n {line.length === 0\n ? \"\\n\"\n : line.map((token, tokenIdx) => (\n <span key={`token-${lineIdx}-${tokenIdx}`} style={tokenStyle(token)}>\n {token.content}\n </span>\n ))}\n </span>\n ))}\n </code>\n ) : (\n children\n )}\n </pre>\n\n <div className=\"absolute end-2 top-2 flex items-center gap-1\">\n <CopyButton\n value={codeText}\n label={false}\n size=\"icon-sm\"\n className=\"opacity-0 transition-opacity duration-fast ease-standard focus-visible:opacity-100 group-hover/code-fence:opacity-100 motion-reduce:transition-none\"\n />\n {language ? (\n <span\n aria-hidden=\"true\"\n className=\"pointer-events-none select-none rounded-sm bg-surface-muted px-1.5 py-0.5 font-mono text-meta text-muted-foreground\"\n >\n {language}\n </span>\n ) : null}\n </div>\n </div>\n );\n}\n","\"use client\";\n\n/**\n * Citations — Pandoc / Better-BibTeX keys (`[@smith2020]`) resolved through a\n * consumer hook (`resolveCitation(key) => CitationData | null`).\n *\n * The library NEVER owns the bibliography database or CSL formatting — that lives\n * in the app (pass `formatted` for a citeproc-rendered reference, or the lightweight\n * `author`/`year`/`title` bits for the built-in assembler). The library renders:\n * inline cites (numeric `[1]` or author-year `(Smith 2020)`) and a generated\n * bibliography, with consistent numbering shared between them.\n *\n * `[@key]` stays a plain text node in mdast (it is NOT markdown link syntax), so a\n * text-node transform (`remarkBrandCitations`) rewrites the spans — the same shape\n * as the wikilink resolver. Numbering is owned by `collectCitations` (a single\n * pre-pass over the source) so an inline `[1]` and bibliography entry 1 always agree.\n */\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { Separator, useLocale } from \"@elabs-ai/components-ui\";\nimport {\n createContext,\n forwardRef,\n useContext,\n useId,\n type HTMLAttributes,\n type ReactNode,\n} from \"react\";\nimport { visit } from \"unist-util-visit\";\n\n/* ------------------------------------------------------------------ */\n/* Public contract */\n/* ------------------------------------------------------------------ */\n\n/**\n * Resolved citation data, returned by the consumer's `resolveCitation` hook.\n * Provide `formatted` (your CSL/citeproc output) for a verbatim bibliography\n * entry; otherwise the built-in assembler uses `author` / `year` / `title` /\n * `container`. The library does NOT format CSL.\n */\nexport interface CitationData {\n /** The citation key (echoed back; optional). */\n key?: string;\n /** Inline author label for author-year + bibliography lead (e.g. `\"Smith et al.\"`). */\n author?: string;\n /** Publication year. */\n year?: string | number;\n /** Work title. */\n title?: string;\n /** Container — journal, book, publisher, or site. */\n container?: string;\n /** Canonical URL (the bibliography link). */\n url?: string;\n /** DOI — linked as `https://doi.org/<doi>` when no `url` is given. */\n doi?: string;\n /** Fully-formatted reference (app's CSL output) — rendered verbatim when set. */\n formatted?: string;\n}\n\n/** Consumer hook: citation key → data, or `null` when unknown (renders `[?]`). */\nexport type ResolveCitation = (key: string) => CitationData | null;\n\n/** Inline citation rendering style. */\nexport type CitationStyle = \"numeric\" | \"author-year\";\n\n/** One resolved citation with its assigned number (numbers skip unresolved keys). */\nexport interface ResolvedCitation {\n key: string;\n /** 1-based number (numeric style + bibliography); `undefined` when unresolved. */\n n?: number;\n data: CitationData | null;\n}\n\n/** A single `@key` reference inside a citation bracket. */\nexport interface CiteItem {\n key: string;\n /** Locator text after the key, e.g. `\"p. 5\"`. */\n locator?: string;\n /** `-@key` → suppress the author in author-year style. */\n suppressAuthor?: boolean;\n /** Prose before the key, e.g. `\"see\"`. */\n prefix?: string;\n}\n\n/* ------------------------------------------------------------------ */\n/* Parsing (shared by the transform AND the numbering pre-pass) */\n/* ------------------------------------------------------------------ */\n\n// A key char-class wide enough for Better-BibTeX / CSL keys without swallowing\n// trailing punctuation: letters, digits, and `_:.#$%&+?<>~/-` (no whitespace).\nconst ITEM_RE = /^\\s*([^@]*?)\\s*(-)?@([\\p{L}\\d][\\w:.#$%&+?<>~/-]*)\\s*(.*)$/u;\n\n/** Parse one `;`-separated cite item; `null` if it has no `@key`. */\nfunction parseItem(raw: string): CiteItem | null {\n const m = ITEM_RE.exec(raw);\n if (!m) return null;\n const [, prefix, suppress, key, rest] = m;\n if (!key) return null;\n const locator = (rest ?? \"\").replace(/^\\s*,\\s*/, \"\").trim();\n const item: CiteItem = { key };\n if (suppress) item.suppressAuthor = true;\n if (prefix?.trim()) item.prefix = prefix.trim();\n if (locator) item.locator = locator;\n return item;\n}\n\n/**\n * Parse a bracket's inner text into cite items, or `null` if it is not a citation\n * (no `@key` token) — so ordinary `[bracketed]` prose is left untouched.\n */\nexport function parseCitationBracket(inner: string): CiteItem[] | null {\n if (!inner.includes(\"@\")) return null;\n const items: CiteItem[] = [];\n for (const part of inner.split(\";\")) {\n const item = parseItem(part);\n if (!item) return null; // every `;`-part must be a valid cite, else it's prose\n items.push(item);\n }\n return items.length > 0 ? items : null;\n}\n\n// Find candidate citation brackets in a text node. Excludes a preceding `]` or `!`\n// (reference-link / image syntax) and a following `(`/`[` (inline / reference link).\nconst BRACKET_RE = /(?<![\\]!])\\[([^[\\]]+)\\](?![([])/g;\n\n/* ------------------------------------------------------------------ */\n/* collectCitations — the single numbering authority */\n/* ------------------------------------------------------------------ */\n\nexport interface CollectedCitations {\n /** Resolved citations in first-appearance order (the bibliography list). */\n order: ResolvedCitation[];\n /** Lookup by key — both resolved and unresolved keys. */\n byKey: Map<string, ResolvedCitation>;\n}\n\n/**\n * Scan the markdown body once, in document order, resolving each unique citation\n * key and numbering the resolved ones. The inline transform stays numbering-free\n * and reads back from `byKey`, so inline `[1]` and bibliography entry 1 agree.\n */\nexport function collectCitations(markdown: string, resolve: ResolveCitation): CollectedCitations {\n const byKey = new Map<string, ResolvedCitation>();\n const order: ResolvedCitation[] = [];\n let m: RegExpExecArray | null;\n BRACKET_RE.lastIndex = 0;\n while ((m = BRACKET_RE.exec(markdown)) !== null) {\n const items = parseCitationBracket(m[1]!);\n if (!items) continue;\n for (const { key } of items) {\n if (byKey.has(key)) continue;\n const data = resolve(key);\n const entry: ResolvedCitation = { key, data };\n if (data) {\n entry.n = order.length + 1;\n order.push(entry);\n }\n byKey.set(key, entry);\n }\n }\n return { order, byKey };\n}\n\n/* ------------------------------------------------------------------ */\n/* remark transform: `[@key]` → <brand-cite> */\n/* ------------------------------------------------------------------ */\n\nexport const CITE_TAG = \"brand-cite\";\nexport const CITE_PROP = \"dataCite\";\nconst CITE_ATTR = \"data-cite\";\n\ninterface CitePayload {\n items: CiteItem[];\n /** Original bracket text, for the graceful all-unresolved fallback. */\n original: string;\n}\n\ninterface MdTextNode {\n type: string;\n value?: string;\n}\n\n/** Rewrite `[@key]` citation spans in text nodes into `<brand-cite>` elements. */\nexport function remarkBrandCitations() {\n return (tree: unknown) => {\n visit(tree as never, \"text\", (node: MdTextNode, index: number | undefined, parent) => {\n const p = parent as { children?: unknown[] } | undefined;\n const text = node.value;\n if (!p?.children || index == null || typeof text !== \"string\" || !text.includes(\"@\")) return;\n\n const next: unknown[] = [];\n let last = 0;\n BRACKET_RE.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = BRACKET_RE.exec(text)) !== null) {\n const items = parseCitationBracket(m[1]!);\n if (!items) continue;\n if (m.index > last) next.push({ type: \"text\", value: text.slice(last, m.index) });\n const payload: CitePayload = { items, original: m[0] };\n next.push({\n type: \"brandCite\",\n data: { hName: CITE_TAG, hProperties: { [CITE_PROP]: JSON.stringify(payload) } },\n });\n last = m.index + m[0].length;\n }\n if (next.length === 0) return;\n if (last < text.length) next.push({ type: \"text\", value: text.slice(last) });\n p.children.splice(index, 1, ...next);\n return index + next.length;\n });\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Context (numbering shared by inline cites + bibliography) */\n/* ------------------------------------------------------------------ */\n\ninterface CitationState {\n byKey: Map<string, ResolvedCitation>;\n order: ResolvedCitation[];\n style: CitationStyle;\n}\n\nconst CitationContext = createContext<CitationState | null>(null);\n\nexport interface CitationProviderProps extends CollectedCitations {\n style: CitationStyle;\n children: ReactNode;\n}\n\nexport function CitationProvider({ byKey, order, style, children }: CitationProviderProps) {\n return (\n <CitationContext.Provider value={{ byKey, order, style }}>{children}</CitationContext.Provider>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Rendering helpers */\n/* ------------------------------------------------------------------ */\n\nfunction hoverTitle(data: CitationData): string {\n if (data.formatted) return data.formatted;\n const parts = [\n data.author,\n data.year != null ? `(${data.year})` : undefined,\n data.title,\n data.container,\n ].filter(Boolean);\n return parts.join(\". \");\n}\n\nfunction CiteLink({ entry, label }: { entry: ResolvedCitation; label: string }) {\n const { t } = useLocale();\n // For numeric style the visible label is a bare \"[1]\" — give AT a real name\n // (the `title` tooltip is for mouse users and is not reliably announced).\n const name = entry.data ? hoverTitle(entry.data) : entry.key;\n return (\n <a\n href={`#ref-${cssId(entry.key)}`}\n title={entry.data ? hoverTitle(entry.data) : undefined}\n aria-label={t(\"editor.citations.citationLabel\", { name })}\n // #317/#399 — the on-surface `-text` rung, NOT the `--primary` FILL: an\n // inline cite is body text inside a paragraph and owes WCAG 1.4.3 AA\n // (4.5:1), which `--primary` missed at 4.29-4.31:1 in light. The\n // resting `underline` is the separate 1.4.1 non-colour cue (#317's\n // link-in-text-block half) — keep both.\n className=\"text-link underline hover:underline focus-visible:rounded-sm focus-ring\"\n >\n {label}\n </a>\n );\n}\n\n/** Make a citation key safe for use in an element id / fragment. */\nfunction cssId(key: string): string {\n return key.replace(/[^\\w-]/g, \"-\");\n}\n\n/* ------------------------------------------------------------------ */\n/* InlineCite — the <brand-cite> renderer */\n/* ------------------------------------------------------------------ */\n\ntype TagProps = { node?: unknown; children?: ReactNode } & Record<string, unknown>;\n\nfunction readCite(rest: TagProps): CitePayload | null {\n const raw = (rest[CITE_ATTR] as string | undefined) ?? (rest[CITE_PROP] as string | undefined);\n if (!raw) return null;\n try {\n return JSON.parse(raw) as CitePayload;\n } catch {\n return null;\n }\n}\n\n/** Renderer for the inline `<brand-cite>` element produced by the transform. */\nexport function InlineCite({ node: _n, children: _c, ...rest }: TagProps) {\n const { t } = useLocale();\n const ctx = useContext(CitationContext);\n const payload = readCite(rest);\n if (!payload) return null;\n if (!ctx) return <span>{payload.original}</span>;\n\n const resolved = payload.items.map((it) => ({ it, entry: ctx.byKey.get(it.key) }));\n const anyResolved = resolved.some((r) => r.entry?.data);\n if (!anyResolved) {\n // Graceful: nothing resolved → keep the literal, marked for sighted + AT.\n return (\n <span className=\"text-muted-foreground\" title={t(\"editor.citations.unresolvedCitation\")}>\n {payload.original}\n </span>\n );\n }\n\n const numeric = ctx.style === \"numeric\";\n const open = numeric ? \"[\" : \"(\";\n const close = numeric ? \"]\" : \")\";\n const sep = numeric ? \", \" : \"; \";\n\n return (\n <span className=\"whitespace-nowrap text-meta tabular-nums\">\n {open}\n {resolved.map(({ it, entry }, i) => {\n const label = numeric ? numericLabel(it, entry) : authorYearLabel(it, entry);\n return (\n <span key={`${it.key}-${i}`}>\n {i > 0 ? sep : null}\n {entry?.data ? (\n <CiteLink entry={entry} label={label} />\n ) : (\n <span\n className=\"text-muted-foreground\"\n title={t(\"editor.citations.unresolvedKey\", { key: it.key })}\n >\n {label}\n </span>\n )}\n </span>\n );\n })}\n {close}\n </span>\n );\n}\n\nfunction numericLabel(it: CiteItem, entry?: ResolvedCitation): string {\n if (!entry?.data || entry.n == null) return \"?\";\n return it.locator ? `${entry.n}, ${it.locator}` : String(entry.n);\n}\n\nfunction authorYearLabel(it: CiteItem, entry?: ResolvedCitation): string {\n if (!entry?.data) return `@${it.key}?`;\n const d = entry.data;\n const head = it.suppressAuthor ? \"\" : d.author ? `${d.author} ` : \"\";\n const year = d.year != null ? String(d.year) : \"\";\n const core = `${head}${year}`.trim() || d.title || it.key;\n const prefixed = it.prefix ? `${it.prefix} ${core}` : core;\n return it.locator ? `${prefixed}, ${it.locator}` : prefixed;\n}\n\n/* ------------------------------------------------------------------ */\n/* Bibliography */\n/* ------------------------------------------------------------------ */\n\nfunction assembledReference(data: CitationData): string {\n if (data.formatted) return data.formatted;\n const parts = [\n data.author,\n data.year != null ? `(${data.year}).` : undefined,\n data.title ? `${data.title}.` : undefined,\n data.container ? `${data.container}.` : undefined,\n ].filter(Boolean);\n return parts.join(\" \");\n}\n\nfunction referenceHref(data: CitationData): string | undefined {\n if (data.url) return data.url;\n if (data.doi) return `https://doi.org/${data.doi}`;\n return undefined;\n}\n\nexport interface BibliographyProps extends Omit<HTMLAttributes<HTMLElement>, \"children\" | \"style\"> {\n /** Resolved citations; defaults to the citations collected by `MarkdownPreview`. */\n entries?: ResolvedCitation[];\n /** Numbering style; defaults to the preview's `citationStyle`. */\n style?: CitationStyle;\n /** Section heading label. Default `\"References\"`. */\n title?: string;\n}\n\n/**\n * The generated reference list. Reads the preview's collected citations by default\n * (the `::bibliography` block), or accepts an explicit `entries` array standalone.\n * One focal separation gesture — a top `Separator` — over a quiet label + list.\n */\nexport const Bibliography = forwardRef<HTMLElement, BibliographyProps>(function Bibliography(\n { entries, style, title: titleProp, className, ...props },\n ref,\n) {\n const { t } = useLocale();\n const title = titleProp ?? t(\"editor.citations.references\");\n const ctx = useContext(CitationContext);\n const labelId = useId();\n const list = entries ?? ctx?.order ?? [];\n const resolvedStyle = style ?? ctx?.style ?? \"numeric\";\n const numeric = resolvedStyle === \"numeric\";\n\n if (list.length === 0) return null;\n\n return (\n <section ref={ref} aria-labelledby={labelId} className={cn(\"mt-8\", className)} {...props}>\n <Separator className=\"mb-3\" />\n <p id={labelId} className=\"mb-2 text-meta font-medium text-muted-foreground\">\n {title}\n </p>\n <ol className=\"space-y-2\">\n {list.map((entry) => {\n const data = entry.data;\n if (!data) return null;\n const href = referenceHref(data);\n return (\n <li\n key={entry.key}\n id={`ref-${cssId(entry.key)}`}\n className=\"flex gap-2 text-caption text-foreground scroll-mt-4\"\n >\n {numeric && entry.n != null ? (\n <span className=\"shrink-0 tabular-nums text-muted-foreground\">[{entry.n}]</span>\n ) : null}\n <span className=\"min-w-0\">\n {assembledReference(data)}{\" \"}\n {href ? (\n <a\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n // #317/#399 — bibliography DOI/URL is body text: `-text` rung\n // + resting underline (the non-colour cue).\n className=\"break-words text-link underline underline-offset-2 hover:underline focus-visible:rounded-sm focus-ring\"\n >\n {data.url ?? `doi:${data.doi}`}\n </a>\n ) : null}\n </span>\n </li>\n );\n })}\n </ol>\n </section>\n );\n});\n","\"use client\";\n\n/**\n * Branded GFM footnotes (`[^1]` … `[^1]: definition`).\n *\n * GFM footnotes already PARSE (remark-gfm is always on), but Streamdown's default\n * hast handlers render them with broken in-page anchors (a doubled `user-content-`\n * id prefix so ref/backref hrefs don't resolve) and `target=\"_blank\"` on what are\n * same-page jumps. So we OWN the render: `remarkBrandFootnotes` rewrites the\n * `footnoteReference` / `footnoteDefinition` mdast nodes into our own `brand-*`\n * elements BEFORE mdast→hast runs, giving consistent ids, real same-page links,\n * and quiet branded chrome.\n *\n * Why replace the node TYPE (not just set `data.hName`): mdast-util-to-hast has\n * built-in handlers for `footnoteReference` / `footnoteDefinition` that ignore\n * `data.hName`. Only a node type with NO handler falls through to the unknown\n * handler, which honors `hName` / `hProperties`. So we swap in fresh custom-typed\n * nodes — and we keep every `id`/`href` on our React output (post-sanitization),\n * never on raw hast the sanitizer could strip.\n */\nimport { Separator } from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { forwardRef, useId, type HTMLAttributes, type ReactNode } from \"react\";\nimport { visit } from \"unist-util-visit\";\n\n/** Inline footnote marker (`<sup><a>…</a></sup>`). */\nexport const FOOTNOTE_REF_TAG = \"brand-footnote-ref\";\n/** The branded footnote-definition section appended at document end. */\nexport const FOOTNOTE_LIST_TAG = \"brand-footnote-list\";\n/** A single footnote definition row (`<li>` + backref). */\nexport const FOOTNOTE_ITEM_TAG = \"brand-footnote-item\";\n/** hast property carrying the JSON payload (rendered as `data-fn`). */\nexport const FOOTNOTE_PROP = \"dataFn\";\nconst FOOTNOTE_ATTR = \"data-fn\";\n\ninterface FootnotePayload {\n /** Footnote identifier (the `1` / `longname` in `[^1]`). */\n id: string;\n /** Display number, assigned in first-reference order. */\n n: number;\n /** Unique element id for this reference occurrence (the backref target). */\n refId?: string;\n /** All reference element ids for this footnote — one back-ref per occurrence. */\n refs?: string[];\n}\n\n/* ------------------------------------------------------------------ */\n/* remark transform */\n/* ------------------------------------------------------------------ */\n\ninterface MdNode {\n type: string;\n identifier?: string;\n value?: string;\n children?: MdNode[];\n data?: { hName?: string; hProperties?: Record<string, unknown> };\n}\n\nfunction payloadProps(payload: FootnotePayload) {\n return { [FOOTNOTE_PROP]: JSON.stringify(payload) };\n}\n\n/**\n * Rewrite footnote refs + definitions into branded elements. Numbering follows\n * first-reference order (GFM behavior); repeated references reuse the number but\n * get a unique element id. Unreferenced definitions are dropped (also GFM).\n */\nexport function remarkBrandFootnotes() {\n return (tree: unknown) => {\n const root = tree as MdNode;\n\n // Pass 1 — collect definitions (and remove them; re-emitted at the end).\n const defs = new Map<string, MdNode>();\n visit(\n root as never,\n \"footnoteDefinition\",\n (node: MdNode, index, parent: MdNode | undefined) => {\n if (!node.identifier || !parent?.children || index == null) return;\n defs.set(node.identifier, node);\n parent.children.splice(index, 1);\n return index; // re-visit the now-shifted index\n },\n );\n\n // Pass 2 — number references in document order + replace with branded refs.\n const numberOf = new Map<string, number>();\n const refsOf = new Map<string, string[]>();\n const order: string[] = [];\n visit(root as never, \"footnoteReference\", (node: MdNode, index, parent: MdNode | undefined) => {\n if (!node.identifier || !parent?.children || index == null) return;\n const id = node.identifier;\n let n = numberOf.get(id);\n if (n == null) {\n n = order.length + 1;\n numberOf.set(id, n);\n order.push(id);\n }\n const refs = refsOf.get(id) ?? [];\n const refId = refs.length === 0 ? `fnref-${id}` : `fnref-${id}-${refs.length + 1}`;\n refs.push(refId);\n refsOf.set(id, refs);\n parent.children[index] = {\n type: \"brandFootnoteRef\",\n data: { hName: FOOTNOTE_REF_TAG, hProperties: payloadProps({ id, n, refId }) },\n };\n });\n\n if (order.length === 0) return;\n\n // Pass 3 — emit the branded definition section at the document end. Each item\n // is a custom element; the definition BODY stays real mdast (rendered + safely\n // sanitized as normal prose), while every id/anchor lives on our React output.\n // Carry every occurrence's ref id so the item renders one back-ref per mention.\n const items: MdNode[] = order.map((id, i) => {\n const def = defs.get(id);\n const body: MdNode[] = def?.children\n ? def.children.map((c) => structuredClone(c))\n : [{ type: \"paragraph\", children: [{ type: \"text\", value: \"Missing footnote.\" }] }];\n return {\n type: \"brandFootnoteItem\",\n data: {\n hName: FOOTNOTE_ITEM_TAG,\n hProperties: payloadProps({ id, n: i + 1, refs: refsOf.get(id) ?? [`fnref-${id}`] }),\n },\n children: body,\n };\n });\n\n root.children = root.children ?? [];\n root.children.push({\n type: \"brandFootnoteList\",\n data: { hName: FOOTNOTE_LIST_TAG },\n children: items,\n });\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* React renderers (registered on MarkdownPreview's components map) */\n/* ------------------------------------------------------------------ */\n\ntype TagProps = { node?: unknown; children?: ReactNode } & Record<string, unknown>;\n\nfunction readPayload(rest: TagProps): FootnotePayload | null {\n const raw =\n (rest[FOOTNOTE_ATTR] as string | undefined) ?? (rest[FOOTNOTE_PROP] as string | undefined);\n if (!raw) return null;\n try {\n return JSON.parse(raw) as FootnotePayload;\n } catch {\n return null;\n }\n}\n\n/** Inline footnote marker — a quiet superscript same-page link. */\nexport function FootnoteRef({ node: _n, children: _c, ...rest }: TagProps) {\n const payload = readPayload(rest);\n if (!payload) return null;\n const { id, n, refId } = payload;\n return (\n <sup className=\"leading-none\">\n <a\n id={refId ?? `fnref-${id}`}\n href={`#fn-${id}`}\n data-footnote-ref=\"\"\n aria-label={`Footnote ${n}`}\n // #399 — a footnote marker is superscript body text: `-text` rung.\n className=\"px-0.5 font-medium text-link underline tabular-nums hover:underline focus-visible:rounded-sm focus-ring\"\n >\n {n}\n </a>\n </sup>\n );\n}\n\n/** A single footnote definition row — the `<li>` + one \"↩\" back-ref per mention. */\nexport function FootnoteItem({ node: _n, children, ...rest }: TagProps) {\n const payload = readPayload(rest);\n if (!payload) return null;\n const { id, n, refs } = payload;\n // One back-ref per occurrence (GFM behavior); a single mention → a lone \"↩\".\n const refList = refs && refs.length > 0 ? refs : [`fnref-${id}`];\n return (\n <li\n id={`fn-${id}`}\n className=\"scroll-mt-4 ps-1 [&>p]:m-0 [&>p]:inline [&>p]:text-caption [&>p]:text-muted-foreground\"\n >\n {children}{\" \"}\n {refList.map((refId, i) => (\n <a\n key={refId}\n href={`#${refId}`}\n data-footnote-backref=\"\"\n aria-label={\n refList.length > 1\n ? `Back to reference ${n}, mention ${i + 1}`\n : `Back to reference ${n}`\n }\n className=\"ms-0.5 inline-flex items-center text-muted-foreground no-underline hover:text-foreground focus-visible:rounded-sm focus-ring\"\n >\n <span aria-hidden=\"true\">↩</span>\n {refList.length > 1 ? (\n <sub className=\"ms-0.5 leading-none tabular-nums\">{i + 1}</sub>\n ) : null}\n </a>\n ))}\n </li>\n );\n}\n\nexport type FootnoteListProps = HTMLAttributes<HTMLElement>;\n\n/**\n * The branded footnote-definition section. One focal separation gesture — a top\n * `Separator` (the classic footnote rule) — over a quiet label + the definition\n * list; no fill, no border box. The label id is per-instance (`useId`) so two\n * previews on one page don't collide.\n */\nexport const FootnoteList = forwardRef<HTMLElement, FootnoteListProps>(function FootnoteList(\n { className, children, ...props },\n ref,\n) {\n const labelId = useId();\n return (\n <section ref={ref} aria-labelledby={labelId} className={cn(\"mt-8\", className)} {...props}>\n <Separator className=\"mb-3\" />\n <p id={labelId} className=\"mb-2 text-meta font-medium text-muted-foreground\">\n Footnotes\n </p>\n <ol className=\"list-decimal space-y-1.5 ps-6 text-caption text-muted-foreground marker:text-muted-foreground\">\n {children}\n </ol>\n </section>\n );\n});\n","\"use client\";\n\n/**\n * Math via `remark-math` + KaTeX (`$inline$`, and `$$block$$` on its own lines).\n *\n * `remark-math` parses `$…$` / `$$…$$` into `inlineMath` / `math` mdast nodes,\n * which have NO mdast→hast handler (they'd otherwise degrade to literal text). So\n * `remarkBrandMath` rewrites them into our own `brand-math` / `brand-math-inline`\n * elements carrying the raw TeX, and the React renderers turn that into KaTeX.\n *\n * SECURITY: the TeX is untrusted input, so KaTeX runs with `trust: false` (blocks\n * `\\href`/`\\url`/class injection), a bounded `maxExpand` (caps macro expansion —\n * the `\\def`-bomb DoS guard), and `throwOnError: false` (a bad expression renders\n * a contained error, never crashes the page). a11y: `output: \"htmlAndMathml\"`\n * emits MathML (read by assistive tech) alongside the visual HTML.\n */\nimport { useLocale } from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport katex from \"katex\";\nimport { useMemo, type HTMLAttributes } from \"react\";\nimport { visit } from \"unist-util-visit\";\n\n/** Block math element (`$$…$$`). */\nexport const MATH_BLOCK_TAG = \"brand-math\";\n/** Inline math element (`$…$`). */\nexport const MATH_INLINE_TAG = \"brand-math-inline\";\n/** hast property carrying the raw TeX (rendered as `data-tex`). */\nexport const MATH_PROP = \"dataTex\";\nconst MATH_ATTR = \"data-tex\";\n\n/** Cap macro expansion — bounds `\\def`-style expansion against untrusted input. */\nconst MAX_EXPAND = 1000;\n\ninterface MdNode {\n type: string;\n value?: string;\n children?: MdNode[];\n data?: { hName?: string; hProperties?: Record<string, unknown> };\n}\n\n/**\n * Rewrite `inlineMath` / `math` (from remark-math) into branded elements carrying\n * the raw TeX. Runs AFTER `remarkMath` in the plugin array.\n */\nexport function remarkBrandMath() {\n return (tree: unknown) => {\n visit(tree as never, (node: MdNode, index: number | undefined, parent: MdNode | undefined) => {\n if (node.type !== \"inlineMath\" && node.type !== \"math\") return;\n if (!parent?.children || index == null) return;\n const display = node.type === \"math\";\n const tex = typeof node.value === \"string\" ? node.value : \"\";\n parent.children[index] = {\n type: display ? \"brandMathBlock\" : \"brandMathInline\",\n data: {\n hName: display ? MATH_BLOCK_TAG : MATH_INLINE_TAG,\n hProperties: { [MATH_PROP]: tex },\n },\n };\n });\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* React renderers */\n/* ------------------------------------------------------------------ */\n\ntype TagProps = { node?: unknown; children?: React.ReactNode } & Record<string, unknown>;\n\nfunction readTex(rest: TagProps): string {\n return (rest[MATH_ATTR] as string | undefined) ?? (rest[MATH_PROP] as string | undefined) ?? \"\";\n}\n\n/** Render TeX to a KaTeX HTML string (safe options); never throws. */\nfunction renderKatex(tex: string, displayMode: boolean): { html: string; error: boolean } {\n try {\n return {\n html: katex.renderToString(tex, {\n displayMode,\n throwOnError: false,\n errorColor: \"var(--destructive)\",\n trust: false,\n maxExpand: MAX_EXPAND,\n strict: \"ignore\",\n output: \"htmlAndMathml\",\n }),\n error: false,\n };\n } catch {\n return { html: \"\", error: true };\n }\n}\n\nexport interface MathProps extends Omit<HTMLAttributes<HTMLElement>, \"children\"> {\n /** Raw TeX source. */\n tex: string;\n}\n\n/** Inline math (`$…$`) → KaTeX, in the text flow. */\nexport function MathInline({ tex, className, ...props }: MathProps) {\n const { t } = useLocale();\n const { html, error } = useMemo(() => renderKatex(tex, false), [tex]);\n if (error) {\n return (\n <code\n className={cn(\"text-destructive-text\", className)}\n aria-label={t(\"editor.math.renderErrorLabel\", { tex })}\n title={t(\"editor.math.renderError\")}\n {...props}\n >\n {tex}\n </code>\n );\n }\n return (\n <span\n role=\"math\"\n // The raw TeX is a universally-readable fallback name for AT that does not\n // process the embedded MathML; MathML-capable AT reads the MathML instead.\n aria-label={tex}\n className={cn(\"inline-block align-middle\", className)}\n // KaTeX output is generated with trust:false + bounded maxExpand (safe).\n dangerouslySetInnerHTML={{ __html: html }}\n {...props}\n />\n );\n}\n\n/** Block math (`$$…$$`) → centered display KaTeX. */\nexport function MathBlock({ tex, className, ...props }: MathProps) {\n const { t } = useLocale();\n const { html, error } = useMemo(() => renderKatex(tex, true), [tex]);\n if (error) {\n return (\n <pre\n className={cn(\n \"overflow-x-auto rounded-md bg-surface-muted p-3 text-destructive-text\",\n className,\n )}\n aria-label={t(\"editor.math.renderErrorLabel\", { tex })}\n title={t(\"editor.math.renderError\")}\n {...props}\n >\n <code>{tex}</code>\n </pre>\n );\n }\n return (\n <div\n role=\"math\"\n aria-label={tex}\n className={cn(\"my-3 overflow-x-auto text-center\", className)}\n dangerouslySetInnerHTML={{ __html: html }}\n {...props}\n />\n );\n}\n\n/** Components-map renderer for the inline math element. */\nexport function MathInlineTag({ node: _n, children: _c, ...rest }: TagProps) {\n return <MathInline tex={readTex(rest)} />;\n}\n\n/** Components-map renderer for the block math element. */\nexport function MathBlockTag({ node: _n, children: _c, ...rest }: TagProps) {\n return <MathBlock tex={readTex(rest)} />;\n}\n","\"use client\";\n\n/**\n * Generated table of contents — an in-flow `::toc` block.\n *\n * Reuses `parseMarkdownOutline` (the same heading extractor `DocumentOutline`\n * uses — no second parser) for slugs + levels, and renders a quiet nav list of\n * same-page anchor links. `MarkdownPreview` provides the outline through\n * `TocProvider`; it also stamps the matching `id` on each rendered heading\n * (`useHeadingId`) so the links resolve.\n */\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { createContext, forwardRef, useContext, type HTMLAttributes } from \"react\";\n\nimport type { MarkdownOutlineItem } from \"../markdown-outline\";\n\n// Per-depth indent on the standard spacing scale (statically scannable so Tailwind\n// keeps the classes). Index = heading depth relative to the shallowest in view.\nconst INDENT = [\"ps-0\", \"ps-3\", \"ps-6\", \"ps-9\", \"ps-12\", \"ps-12\"] as const;\n\ninterface TocState {\n items: MarkdownOutlineItem[];\n /** Heading slug keyed by 1-based start line (frontmatter-stripped coords). */\n idByLine: Map<number, string>;\n}\n\nconst TocContext = createContext<TocState | null>(null);\n\nexport interface TocProviderProps {\n items: MarkdownOutlineItem[];\n children: React.ReactNode;\n}\n\nexport function TocProvider({ items, children }: TocProviderProps) {\n const idByLine = new Map<number, string>();\n for (const it of items) idByLine.set(it.line, it.id);\n return <TocContext.Provider value={{ items, idByLine }}>{children}</TocContext.Provider>;\n}\n\n/** The heading `id` for a 1-based source line, or `undefined`. */\nexport function useHeadingId(line: number | undefined): string | undefined {\n const ctx = useContext(TocContext);\n if (line == null || !ctx) return undefined;\n return ctx.idByLine.get(line);\n}\n\nexport interface TableOfContentsProps extends Omit<HTMLAttributes<HTMLElement>, \"children\"> {\n /** Heading outline; defaults to the outline collected by `MarkdownPreview`. */\n items?: MarkdownOutlineItem[];\n /** Section heading label. Default `\"Contents\"`. */\n title?: string;\n /** Deepest heading level to include (1–6). Default 3. */\n maxLevel?: 1 | 2 | 3 | 4 | 5 | 6;\n}\n\n/**\n * Quiet generated TOC. Standalone with an explicit `items` array, or fed from the\n * preview context inside a `::toc` block. Indentation tracks heading depth; no\n * fill or border — the indent + links are the only gestures.\n */\nexport const TableOfContents = forwardRef<HTMLElement, TableOfContentsProps>(\n function TableOfContents({ items, title = \"Contents\", maxLevel = 3, className, ...props }, ref) {\n const ctx = useContext(TocContext);\n const source = items ?? ctx?.items ?? [];\n const list = source.filter((it) => it.level <= maxLevel);\n if (list.length === 0) return null;\n\n const minLevel = Math.min(...list.map((it) => it.level));\n\n return (\n <nav ref={ref} aria-label={title} className={cn(\"my-4 text-meta\", className)} {...props}>\n <p className=\"mb-2 font-medium text-muted-foreground\">{title}</p>\n <ol className=\"space-y-1\">\n {list.map((it) => (\n <li key={it.id} className={INDENT[Math.min(it.level - minLevel, INDENT.length - 1)]}>\n <a\n href={`#${it.id}`}\n className=\"text-muted-foreground underline hover:text-foreground hover:underline focus-visible:rounded-sm focus-ring\"\n >\n {it.text}\n </a>\n </li>\n ))}\n </ol>\n </nav>\n );\n },\n);\n","\"use client\";\n\n/**\n * The `:::iterate` / `:::pivot` directive bridge — turns a directive context\n * (attributes + the captured raw body template) into an `IterationSpec`, and\n * renders an `IterationBlock` with a recursion guard so a self-referential\n * template can't loop forever (the transclusion depth-cap precedent).\n */\nimport { createContext, useContext, type ReactNode } from \"react\";\n\nimport {\n IterationBlock,\n type EvaluateIteration,\n type InterpolateTemplate,\n type IterationLayout,\n type IterationSpec,\n} from \"./iteration\";\n\n/** Max nesting depth for `:::iterate` inside an iterated cell. */\nexport const MAX_ITERATION_DEPTH = 3;\n\n/** Current iteration nesting depth; 0 = top-level document. */\nconst IterationDepthContext = createContext(0);\n\nconst DEFAULT_LAYOUT: Record<\"iterate\" | \"pivot\", IterationLayout> = {\n iterate: \"stacked\",\n pivot: \"matrix\",\n};\n\nconst LAYOUTS = new Set<IterationLayout>([\"stacked\", \"grid\", \"matrix\", \"bento\"]);\n\n/** Build an `IterationSpec` from a directive's name + attributes + raw body. */\nexport function specFromDirective(\n name: \"iterate\" | \"pivot\",\n attributes: Record<string, string>,\n rawBody: string | undefined,\n): IterationSpec {\n const kind = name;\n const layoutAttr = attributes.layout as IterationLayout | undefined;\n const layout = layoutAttr && LAYOUTS.has(layoutAttr) ? layoutAttr : DEFAULT_LAYOUT[kind];\n const columns = attributes.columns ? Number(attributes.columns) || undefined : undefined;\n return {\n kind,\n layout,\n template: rawBody ?? \"\",\n as: attributes.as?.trim() || \"item\",\n source: attributes.source,\n rows: attributes.rows,\n cols: attributes.cols,\n columns,\n attributes,\n };\n}\n\nexport interface IterationDirectiveProps {\n spec: IterationSpec;\n evaluate: EvaluateIteration;\n interpolate?: InterpolateTemplate;\n /** Render one cell's resolved markdown → node (a nested `MarkdownPreview`). */\n renderCell: (markdown: string) => ReactNode;\n}\n\n/**\n * Renders an `IterationBlock` one nesting level deeper, refusing to recurse past\n * {@link MAX_ITERATION_DEPTH}. Cells (which mount nested `MarkdownPreview`s) read\n * the incremented depth, so a nested `:::iterate` is bounded.\n */\nexport function IterationDirective({\n spec,\n evaluate,\n interpolate,\n renderCell,\n}: IterationDirectiveProps) {\n const depth = useContext(IterationDepthContext);\n if (depth >= MAX_ITERATION_DEPTH) {\n return (\n <div className=\"my-4 text-meta text-muted-foreground italic\" data-iteration-too-deep=\"\">\n Iteration nested too deep — skipped.\n </div>\n );\n }\n return (\n <IterationDepthContext.Provider value={depth + 1}>\n <IterationBlock\n spec={spec}\n evaluate={evaluate}\n interpolate={interpolate}\n render={renderCell}\n />\n </IterationDepthContext.Provider>\n );\n}\n","\"use client\";\n\n/**\n * MarkdownToolbar — formatting chrome for the markdown SOURCE pane, composed\n * entirely from @elabs-ai/components-ui (Button, Tooltip, Separator, DropdownMenu). Actions run\n * against a Monaco editor instance via the pure commands in markdown-commands.ts.\n * Buttons disable when no editor is mounted.\n */\nimport {\n Button,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n Separator,\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n useLocale,\n} from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport {\n Bold,\n ChevronDown,\n Code2,\n Heading,\n Italic,\n Link2,\n List,\n ListOrdered,\n Minus,\n Quote,\n SquarePlus,\n} from \"lucide-react\";\nimport { forwardRef, Fragment, type HTMLAttributes, type ReactNode } from \"react\";\n\nimport type { MonacoCodeEditor } from \"../code-editor\";\nimport { groupSlashCommands, type SlashCommand } from \"../markdown-editor/slash\";\nimport {\n insertDirective,\n insertHorizontalRule,\n insertLink,\n toggleLinePrefix,\n wrapSelection,\n} from \"./markdown-commands\";\n\nexport interface MarkdownToolbarProps extends HTMLAttributes<HTMLDivElement> {\n /** The Monaco editor instance to act on (from CodeEditor ref/onMount). */\n editor: MonacoCodeEditor | null;\n /** Extra controls rendered on the right (e.g. a mode switch). */\n actions?: ReactNode;\n /**\n * Drives the **Insert** menu. When set, the menu lists every command that\n * carries a `snippet` (grouped by `group`), inserting that markdown at the\n * caret — so the source / split pane reaches the SAME blocks as the WYSIWYG\n * slash menu (`/calc`, `/iterate`, `/pivot`, plus any consumer commands).\n * When omitted, the menu falls back to the four built-in directive snippets.\n * (A4)\n */\n insertCommands?: SlashCommand[];\n}\n\n/** A command that actually carries a source-mode snippet. */\ntype InsertableCommand = SlashCommand & { snippet: string };\n\n// The `title=`/`label=` values below are example CONTENT dropped into the user's\n// document (the same seeds `brand-slash-commands.ts` uses), not UI chrome — left\n// as literal English placeholder text the author overwrites.\nconst DIRECTIVE_SNIPPETS: { labelKey: string; snippet: string }[] = [\n {\n labelKey: \"editor.markdownToolbar.directiveCard\",\n snippet: `:::card{title=\"Title\"}\\nContent\\n:::`, // i18n-exempt: example document content\n },\n {\n labelKey: \"editor.markdownToolbar.directiveCallout\",\n snippet: `:::callout{type=\"info\" title=\"Note\"}\\nMessage\\n:::`, // i18n-exempt: example document content\n },\n {\n labelKey: \"editor.markdownToolbar.directiveMetric\",\n snippet: `::metric{label=\"Label\" value=\"0\" description=\"detail\"}`, // i18n-exempt: example document content\n },\n {\n labelKey: \"editor.markdownToolbar.directiveTimeline\",\n snippet: `:::timeline\\n- (done) Step one\\n- (active) Step two\\n- (pending) Step three\\n:::`, // i18n-exempt: example document content\n },\n];\n\nexport const MarkdownToolbar = forwardRef<HTMLDivElement, MarkdownToolbarProps>(\n function MarkdownToolbar({ editor, actions, insertCommands, className, ...props }, ref) {\n const { t } = useLocale();\n const disabled = !editor;\n const run = (fn: (e: MonacoCodeEditor) => void) => () => {\n if (editor) fn(editor);\n };\n\n // The Insert menu is driven by the slash registry when provided (A4): only\n // commands that carry a source-mode `snippet`, grouped by `group`.\n const insertGroups = insertCommands\n ? groupSlashCommands(\n insertCommands.filter((c): c is InsertableCommand => typeof c.snippet === \"string\"),\n )\n : null;\n\n const IconButton = ({\n label,\n icon,\n onClick,\n }: {\n label: string;\n icon: ReactNode;\n onClick: () => void;\n }) => (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n disabled={disabled}\n onClick={onClick}\n aria-label={label}\n >\n {icon}\n </Button>\n </TooltipTrigger>\n <TooltipContent>{label}</TooltipContent>\n </Tooltip>\n );\n\n return (\n <TooltipProvider delayDuration={300}>\n <div\n ref={ref}\n role=\"toolbar\"\n aria-label={t(\"editor.markdownToolbar.label\")}\n className={cn(\n \"flex h-10 shrink-0 items-center gap-0.5 border-b border-border bg-surface px-2\",\n className,\n )}\n {...props}\n >\n <IconButton\n label={t(\"editor.markdownToolbar.bold\")}\n icon={<Bold className=\"size-4\" />}\n onClick={run((e) => wrapSelection(e, \"**\"))}\n />\n <IconButton\n label={t(\"editor.markdownToolbar.italic\")}\n icon={<Italic className=\"size-4\" />}\n onClick={run((e) => wrapSelection(e, \"*\"))}\n />\n <IconButton\n label={t(\"editor.markdownToolbar.inlineCode\")}\n icon={<Code2 className=\"size-4\" />}\n onClick={run((e) => wrapSelection(e, \"`\"))}\n />\n <IconButton\n label={t(\"editor.markdownToolbar.link\")}\n icon={<Link2 className=\"size-4\" />}\n onClick={run(insertLink)}\n />\n\n <Separator orientation=\"vertical\" className=\"mx-1 h-5\" />\n\n <DropdownMenu>\n <Tooltip>\n <TooltipTrigger asChild>\n <DropdownMenuTrigger asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n disabled={disabled}\n className=\"gap-1\"\n aria-label={t(\"editor.markdownToolbar.headingLevel\")}\n >\n <Heading className=\"size-4\" />\n <ChevronDown className=\"size-3\" />\n </Button>\n </DropdownMenuTrigger>\n </TooltipTrigger>\n <TooltipContent>{t(\"editor.markdownToolbar.heading\")}</TooltipContent>\n </Tooltip>\n <DropdownMenuContent align=\"start\">\n {([1, 2, 3] as const).map((level) => (\n <DropdownMenuItem\n key={level}\n onSelect={run((e) => toggleLinePrefix(e, `${\"#\".repeat(level)} `))}\n >\n {t(\"editor.markdownToolbar.headingLevelItem\", { level })}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n\n <IconButton\n label={t(\"editor.markdownToolbar.quote\")}\n icon={<Quote className=\"size-4\" />}\n onClick={run((e) => toggleLinePrefix(e, \"> \"))}\n />\n <IconButton\n label={t(\"editor.markdownToolbar.bulletList\")}\n icon={<List className=\"size-4\" />}\n onClick={run((e) => toggleLinePrefix(e, \"- \"))}\n />\n <IconButton\n label={t(\"editor.markdownToolbar.numberedList\")}\n icon={<ListOrdered className=\"size-4\" />}\n onClick={run((e) => toggleLinePrefix(e, \"1. \"))}\n />\n <IconButton\n label={t(\"editor.markdownToolbar.divider\")}\n icon={<Minus className=\"size-4\" />}\n onClick={run(insertHorizontalRule)}\n />\n\n <Separator orientation=\"vertical\" className=\"mx-1 h-5\" />\n\n <DropdownMenu>\n <Tooltip>\n <TooltipTrigger asChild>\n <DropdownMenuTrigger asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n disabled={disabled}\n className=\"gap-1\"\n aria-label={t(\"editor.markdownToolbar.insertBlock\")}\n >\n <SquarePlus className=\"size-4\" />\n <span className=\"text-xs\">{t(\"editor.markdownToolbar.insert\")}</span>\n </Button>\n </DropdownMenuTrigger>\n </TooltipTrigger>\n <TooltipContent>{t(\"editor.markdownToolbar.insertBrandBlock\")}</TooltipContent>\n </Tooltip>\n <DropdownMenuContent align=\"start\">\n {insertGroups && insertGroups.length > 0\n ? insertGroups.map(({ group, commands }, gi) => (\n <Fragment key={group}>\n {gi > 0 ? <DropdownMenuSeparator /> : null}\n <DropdownMenuLabel className=\"text-meta font-medium text-muted-foreground\">\n {group}\n </DropdownMenuLabel>\n {(commands as InsertableCommand[]).map((cmd) => (\n <DropdownMenuItem\n key={cmd.id}\n className=\"gap-2\"\n onSelect={run((e) => insertDirective(e, cmd.snippet))}\n >\n {cmd.icon ? (\n <span className=\"flex size-4 shrink-0 items-center justify-center text-muted-foreground [&_svg]:size-4\">\n {cmd.icon}\n </span>\n ) : null}\n {cmd.label}\n </DropdownMenuItem>\n ))}\n </Fragment>\n ))\n : DIRECTIVE_SNIPPETS.map(({ labelKey, snippet }) => (\n <DropdownMenuItem\n key={labelKey}\n onSelect={run((e) => insertDirective(e, snippet))}\n >\n {t(labelKey)}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n\n {actions ? <div className=\"ml-auto flex items-center gap-1.5\">{actions}</div> : null}\n </div>\n </TooltipProvider>\n );\n },\n);\n","/**\n * Focus-writing helpers (Ulysses Phase A) — the pure half of the workspace's\n * \"Focus\" toggle: paragraph focus (mark the top-level block that owns the\n * selection) and typewriter scrolling (keep the caret in a vertical band\n * around the scroller's center). Engine-agnostic: plain DOM walking, no\n * ProseMirror plugin surface — testable in jsdom without booting Milkdown.\n */\n\n/** The editor-root CHILD that contains `node` (the active top-level block). */\nexport function topLevelBlockOf(editorRoot: Element, node: Node | null): Element | null {\n let current: Node | null = node;\n while (current && current.parentNode !== editorRoot) {\n current = current.parentNode;\n }\n return current instanceof Element ? current : null;\n}\n\n/**\n * Typewriter scroll adjustment: how far the scroller must move so the caret\n * sits back in the center band. Returns 0 while the caret is inside the band\n * (no jitter on every keystroke — only re-center when it drifts out).\n *\n * @param band fraction of the scroller height treated as \"centered enough\".\n */\nexport function typewriterDelta(\n caretTop: number,\n caretHeight: number,\n hostTop: number,\n hostHeight: number,\n band = 0.22,\n): number {\n if (hostHeight <= 0) return 0;\n const center = hostTop + hostHeight / 2;\n const caretMid = caretTop + caretHeight / 2;\n const tolerance = (hostHeight * band) / 2;\n const off = caretMid - center;\n return Math.abs(off) <= tolerance ? 0 : off;\n}\n","/**\n * `@elabs-ai/components-editor/markdown/parse` — a Monaco-free markdown parser.\n *\n * `parseMarkdown(md)` returns the mdast `Root` for the SAME dialect the branded\n * preview parses: GitHub-flavored markdown + `:::`/`::`/`:` directives + YAML\n * frontmatter. Split onto its own leaf subpath (like `./markdown/frontmatter`) so\n * SERVER, RSC, and unit-test consumers can parse markdown WITHOUT pulling the\n * editor engines (Milkdown, Monaco, Streamdown) into their bundle — the whole\n * reason the `.` vs `./markdown` split exists. Depends only on `unified` +\n * `remark-*` (no React, no Monaco).\n *\n * It returns RAW directive mdast (`containerDirective` / `leafDirective` /\n * `textDirective` nodes) — it does NOT run `remarkBrandDirectives` (that rewrites\n * directives into the `<brand-directive>` hast tag, which is a RENDER concern).\n * Walk the tree by `node.type` + `node.name` yourself. The match is at the\n * DIALECT level (same plugins/extensions); it is not byte-identical to the tree\n * Streamdown builds internally (which also applies a streaming block-splitter).\n */\nimport type { Root } from \"mdast\";\nimport remarkDirective from \"remark-directive\";\nimport remarkFrontmatter from \"remark-frontmatter\";\nimport remarkGfm from \"remark-gfm\";\nimport remarkParse from \"remark-parse\";\nimport { unified } from \"unified\";\n\n// Built once: a frozen parser-only processor (gfm + frontmatter + directive\n// syntax extensions). `parse()` is stateless per call, so one instance is safe.\nconst processor = unified()\n .use(remarkParse)\n .use(remarkGfm)\n .use(remarkFrontmatter, [\"yaml\"])\n .use(remarkDirective)\n .freeze();\n\n/** Parse markdown to mdast (gfm + directives + frontmatter). Monaco-free. */\nexport function parseMarkdown(md: string): Root {\n return processor.parse(md) as Root;\n}\n","\"use client\";\n\n/**\n * MermaidWorkspace (#L2) — the source ⇄ diagram editing surface.\n *\n * Same compound pattern as `MarkdownWorkspace`: one mermaid source string,\n * Monaco on the left, the live branded `MermaidDiagram` on the right\n * (debounced so keystrokes don't thrash the engine). Controlled\n * (`value`/`onChange`) or uncontrolled (`defaultValue`).\n */\nimport { ResizableHandle, ResizablePanel, ResizablePanelGroup } from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { forwardRef, useEffect, useState, type HTMLAttributes } from \"react\";\n\nimport { CodeEditor } from \"../code-editor\";\nimport { MermaidDiagram } from \"../mermaid-diagram\";\n\nexport interface MermaidWorkspaceProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n \"onChange\" | \"defaultValue\"\n> {\n value?: string;\n defaultValue?: string;\n onChange?: (source: string) => void;\n /** Debounce (ms) before the diagram re-renders while typing. Default 350. */\n debounceMs?: number;\n}\n\nexport const MermaidWorkspace = forwardRef<HTMLDivElement, MermaidWorkspaceProps>(\n function MermaidWorkspace(\n { value, defaultValue, onChange, debounceMs = 350, className, ...props },\n ref,\n ) {\n const isControlled = value !== undefined;\n const [internal, setInternal] = useState(value ?? defaultValue ?? \"\");\n const source = isControlled ? value : internal;\n\n const [debounced, setDebounced] = useState(source);\n useEffect(() => {\n const t = setTimeout(() => setDebounced(source), debounceMs);\n return () => clearTimeout(t);\n }, [source, debounceMs]);\n\n const setSource = (next: string) => {\n if (!isControlled) setInternal(next);\n onChange?.(next);\n };\n\n return (\n <div\n ref={ref}\n data-testid=\"mermaid-workspace\"\n className={cn(\"h-full min-h-0 overflow-hidden\", className)}\n {...props}\n >\n <ResizablePanelGroup direction=\"horizontal\">\n <ResizablePanel defaultSize={45} minSize={25}>\n {/* Monaco has no mermaid grammar — plaintext keeps it honest (no wrong colors). */}\n <CodeEditor language=\"plaintext\" value={source} onChange={setSource} />\n </ResizablePanel>\n <ResizableHandle withHandle />\n <ResizablePanel defaultSize={55} minSize={25}>\n <div className=\"h-full overflow-auto p-4\">\n <MermaidDiagram chart={debounced} label=\"Diagram preview\" />\n </div>\n </ResizablePanel>\n </ResizablePanelGroup>\n </div>\n );\n },\n);\n","\"use client\";\n\n/**\n * DecisionCard — renders a `:::decision{status=accepted date=2026-06-15}` directive\n * as a decision-record card.\n *\n * Anatomy:\n * - Status badge (accepted | rejected | proposed | superseded) in a header rail.\n * - Date (ISO or human-readable) rendered as a `<time>` element.\n * - Rationale body (the directive body text, rendered children).\n * - Optional \"Alternatives considered\" section (comma-separated `alternatives=`\n * attribute). The attribute shape is intentional: alternatives are typically\n * short phrases, and keeping them out of the body lets the body stay prose.\n *\n * Status → Badge variant mapping:\n * accepted → success · rejected → destructive · proposed → info ·\n * superseded → secondary (neutral — de-emphasized, not a failure).\n *\n * The card is a `<section aria-label>` for landmark navigation.\n */\nimport {\n Badge,\n Card,\n CardContent,\n CardHeader,\n Separator,\n useLocale,\n type BadgeProps,\n} from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { cva } from \"class-variance-authority\";\nimport { CheckCircle2, CircleDashed, Clock, RefreshCw } from \"lucide-react\";\nimport {\n forwardRef,\n type ComponentType,\n type HTMLAttributes,\n type ReactNode,\n type SVGProps,\n} from \"react\";\n\n/* ------------------------------------------------------------------ */\n/* Status vocabulary */\n/* ------------------------------------------------------------------ */\n\nexport const DECISION_STATUSES = [\"accepted\", \"rejected\", \"proposed\", \"superseded\"] as const;\nexport type DecisionStatus = (typeof DECISION_STATUSES)[number];\n\nconst STATUS_BADGE_VARIANT: Record<DecisionStatus, BadgeProps[\"variant\"]> = {\n accepted: \"success\",\n rejected: \"destructive\",\n proposed: \"info\",\n superseded: \"secondary\",\n};\n\n/** Status → translation key (see `editor.decisionCard.status.*` in messages.ts). */\nconst STATUS_LABEL_KEYS: Record<DecisionStatus, string> = {\n accepted: \"editor.decisionCard.statusAccepted\",\n rejected: \"editor.decisionCard.statusRejected\",\n proposed: \"editor.decisionCard.statusProposed\",\n superseded: \"editor.decisionCard.statusSuperseded\",\n};\n\nconst STATUS_ICONS: Record<DecisionStatus, ComponentType<SVGProps<SVGSVGElement>>> = {\n accepted: CheckCircle2,\n rejected: CircleDashed,\n proposed: Clock,\n superseded: RefreshCw,\n};\n\nfunction isDecisionStatus(s: string): s is DecisionStatus {\n return DECISION_STATUSES.includes(s as DecisionStatus);\n}\n\n/* ------------------------------------------------------------------ */\n/* cva (status rail accent) */\n/* ------------------------------------------------------------------ */\n\nexport const decisionCardVariants = cva(\"border-s-4\", {\n variants: {\n status: {\n accepted: \"border-s-success\",\n rejected: \"border-s-destructive\",\n proposed: \"border-s-info\",\n superseded: \"border-s-border\",\n },\n },\n defaultVariants: { status: \"proposed\" },\n});\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport interface DecisionCardProps extends HTMLAttributes<HTMLElement> {\n /**\n * Decision outcome. One of the four canonical states; anything unrecognised\n * renders as \"proposed\".\n */\n status?: string;\n /**\n * ISO date or human-readable date of the decision\n * (e.g. `\"2026-06-15\"` or `\"June 2026\"`).\n */\n date?: string;\n /**\n * Comma-separated alternative options considered before this decision.\n * E.g. `\"Redis cache, in-memory map, SQLite\"`.\n */\n alternatives?: string;\n /** The rationale body (rendered markdown children of the directive). */\n children?: ReactNode;\n}\n\nexport const DecisionCard = forwardRef<HTMLElement, DecisionCardProps>(function DecisionCard(\n { status: rawStatus, date, alternatives, children, className, ...props },\n ref,\n) {\n const { t } = useLocale();\n const status: DecisionStatus = isDecisionStatus(rawStatus ?? \"\")\n ? (rawStatus as DecisionStatus)\n : \"proposed\";\n const badgeVariant = STATUS_BADGE_VARIANT[status];\n const label = t(STATUS_LABEL_KEYS[status]);\n const Icon = STATUS_ICONS[status];\n\n const altItems = alternatives\n ? alternatives\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean)\n : [];\n\n return (\n <section\n ref={ref}\n aria-label={t(\"editor.decisionCard.label\", { label })}\n className={cn(\"not-prose\", className)}\n {...props}\n >\n <Card className={cn(decisionCardVariants({ status }))}>\n <CardHeader className=\"pb-3\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <Badge variant={badgeVariant} className=\"gap-1.5\">\n <Icon className=\"size-3\" aria-hidden=\"true\" />\n {label}\n </Badge>\n {date ? (\n <time dateTime={date} className=\"text-meta text-muted-foreground tabular-nums\">\n {date}\n </time>\n ) : null}\n </div>\n </CardHeader>\n\n {children ? (\n <CardContent className=\"text-body text-foreground\">{children}</CardContent>\n ) : null}\n\n {altItems.length > 0 ? (\n <>\n <Separator />\n <div className=\"px-6 py-4\">\n <p className=\"mb-2 text-meta font-medium text-muted-foreground\">\n {t(\"editor.decisionCard.alternativesConsidered\")}\n </p>\n <ul\n className=\"flex flex-wrap gap-1.5\"\n aria-label={t(\"editor.decisionCard.alternativesConsidered\")}\n >\n {altItems.map((alt) => (\n <li key={alt}>\n <Badge variant=\"outline\" className=\"text-meta\">\n {alt}\n </Badge>\n </li>\n ))}\n </ul>\n </div>\n </>\n ) : null}\n </Card>\n </section>\n );\n});\n","\"use client\";\n\n/**\n * EntityCard + EntityChip — renders `:::entity{kind=org name=\"Acme\"}` (block card)\n * and `:entity[Acme]{kind=org}` (inline chip) directives.\n *\n * One component handles both syntaxes; the renderer factory branches on `ctx.kind`.\n *\n * Entity kinds and their icon/tone:\n * org → Building2 / secondary (companies, organisations)\n * person → User / primary (people, authors)\n * place → MapPin / info (locations, regions)\n * product → Box / success (products, services)\n * concept → Lightbulb / warning (ideas, topics)\n * default → Tag / outline (anything else)\n *\n * The inline chip is a `<span>` — no block wrapper — so it stays inside `<p>` without\n * creating invalid HTML. A11y: kind is conveyed via `aria-label` (not icon alone).\n */\nimport { Card, CardContent, CardHeader, CardTitle } from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { Box, Building2, Lightbulb, MapPin, Tag, User } from \"lucide-react\";\nimport {\n forwardRef,\n type ComponentType,\n type HTMLAttributes,\n type ReactNode,\n type SVGProps,\n} from \"react\";\n\n/* ------------------------------------------------------------------ */\n/* Kind vocabulary */\n/* ------------------------------------------------------------------ */\n\nexport const ENTITY_KINDS = [\"org\", \"person\", \"place\", \"product\", \"concept\"] as const;\nexport type EntityKind = (typeof ENTITY_KINDS)[number];\n\ntype KindMeta = {\n Icon: ComponentType<SVGProps<SVGSVGElement>>;\n label: string;\n};\n\nconst KIND_META: Record<string, KindMeta> = {\n org: { Icon: Building2, label: \"Organisation\" },\n person: { Icon: User, label: \"Person\" },\n place: { Icon: MapPin, label: \"Place\" },\n product: { Icon: Box, label: \"Product\" },\n concept: { Icon: Lightbulb, label: \"Concept\" },\n};\n\nconst DEFAULT_KIND_META: KindMeta = { Icon: Tag, label: \"Entity\" };\n\nfunction kindMeta(kind: string | undefined): KindMeta {\n return KIND_META[kind ?? \"\"] ?? DEFAULT_KIND_META;\n}\n\n/* ------------------------------------------------------------------ */\n/* cva */\n/* ------------------------------------------------------------------ */\n\nexport const entityChipVariants = cva(\n // inline-flex + align-middle keeps the chip in the text baseline;\n // no `block` wrapper so it is valid inside <p>.\n \"inline-flex items-center gap-1 rounded-sm border px-1.5 py-0.5 text-meta font-medium align-middle focus-ring\",\n {\n variants: {\n kind: {\n org: \"border-border bg-secondary/60 text-secondary-foreground\",\n // #399 — same reasoning as `concept` below: a 10% WASH is not a plate\n // and not a mark, so the LABEL takes the on-surface `-text` rung. This\n // is the row that had no `-text` rung to reach for until #399 minted it.\n person: \"border-primary/30 bg-primary/10 text-primary-text\",\n place: \"border-info/30 bg-info/10 text-info-text\",\n product: \"border-success/30 bg-success/10 text-success-text\",\n // `-text`, not `-foreground`: the chip is a 10% WASH on the page surface,\n // not a solid `--warning` plate, so it needs the on-surface rung its\n // place/product siblings use (#381 flipped `--warning-foreground` to\n // light ink for the now-deep fill).\n concept: \"border-warning/30 bg-warning/10 text-warning-text\",\n default: \"border-border text-foreground\",\n },\n },\n defaultVariants: { kind: \"default\" },\n },\n);\n\nfunction chipKind(kind: string | undefined): VariantProps<typeof entityChipVariants>[\"kind\"] {\n if (!kind) return \"default\";\n const known: Array<VariantProps<typeof entityChipVariants>[\"kind\"]> = [\n \"org\",\n \"person\",\n \"place\",\n \"product\",\n \"concept\",\n \"default\",\n ];\n return known.includes(kind as never)\n ? (kind as VariantProps<typeof entityChipVariants>[\"kind\"])\n : \"default\";\n}\n\n/* ------------------------------------------------------------------ */\n/* EntityChip (inline) */\n/* ------------------------------------------------------------------ */\n\nexport interface EntityChipProps extends HTMLAttributes<HTMLSpanElement> {\n /** Entity kind — drives icon and tone. */\n kind?: string;\n /** Display label (the directive's label text or `name` attribute). */\n children?: ReactNode;\n}\n\nexport const EntityChip = forwardRef<HTMLSpanElement, EntityChipProps>(function EntityChip(\n { kind: rawKind, children, className, ...props },\n ref,\n) {\n const { Icon, label } = kindMeta(rawKind);\n const resolvedKind = chipKind(rawKind);\n return (\n <span\n ref={ref}\n role=\"mark\"\n aria-label={children ? `${String(children)} (${label})` : label}\n className={cn(entityChipVariants({ kind: resolvedKind }), className)}\n {...props}\n >\n <Icon className=\"size-3 shrink-0\" aria-hidden=\"true\" />\n <span>{children}</span>\n </span>\n );\n});\n\n/* ------------------------------------------------------------------ */\n/* EntityCard (block) */\n/* ------------------------------------------------------------------ */\n\nexport interface EntityCardProps extends HTMLAttributes<HTMLElement> {\n /** Entity kind — drives the icon and header tone. */\n kind?: string;\n /** Entity name. Falls back to children when absent. */\n name?: string;\n /** Description body (rendered markdown children of the directive). */\n children?: ReactNode;\n}\n\nexport const EntityCard = forwardRef<HTMLElement, EntityCardProps>(function EntityCard(\n { kind: rawKind, name, children, className, ...props },\n ref,\n) {\n const { Icon, label } = kindMeta(rawKind);\n\n return (\n <section\n ref={ref}\n aria-label={name ? `${label}: ${name}` : label}\n className={cn(\"not-prose\", className)}\n {...props}\n >\n <Card>\n <CardHeader className=\"pb-3\">\n <div className=\"flex items-center gap-2\">\n <span\n className=\"flex size-7 shrink-0 items-center justify-center rounded-md bg-muted\"\n aria-hidden=\"true\"\n >\n <Icon className=\"size-4 text-muted-foreground\" />\n </span>\n <div className=\"min-w-0\">\n {name ? <CardTitle className=\"truncate\">{name}</CardTitle> : null}\n <p className=\"text-meta text-muted-foreground\">{label}</p>\n </div>\n </div>\n </CardHeader>\n {children ? (\n <CardContent className=\"text-body text-foreground\">{children}</CardContent>\n ) : null}\n </Card>\n </section>\n );\n});\n","\"use client\";\n\n/**\n * KnowledgeCard — renders a `:::knowledge{sources=\"notes/a.md, notes/b.md\"}` directive\n * as a sourced-fact card.\n *\n * Anatomy:\n * - Fact body (rendered markdown children of the directive).\n * - Sources section: each comma-split path is handed to the consumer's `resolve`\n * hook (`resolve(path) => { href, title } | null`). Resolved paths render as\n * `<a>` links; unresolved paths render as plain `<span>` labels — graceful\n * degradation, no errors thrown.\n *\n * The library never reads files. Domain logic (vault index, file system, API) lives\n * entirely in the consumer's `resolve` hook — the same principle as `resolveUrl` on\n * `MarkdownPreview` and `evaluate` on calc blocks.\n *\n * `KnowledgeCard` is standalone (no `resolve` → sources rendered as plain labels).\n * The `knowledgeDirective({ resolve })` factory wires the hook for directive use.\n */\nimport { Card, CardContent, CardFooter, useLocale } from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { BookOpen, FileText } from \"lucide-react\";\nimport { forwardRef, type HTMLAttributes, type ReactNode } from \"react\";\n\n/* ------------------------------------------------------------------ */\n/* Resolver type (consumer-supplied; never bundled) */\n/* ------------------------------------------------------------------ */\n\nexport interface KnowledgeSourceResolved {\n href: string;\n title?: string;\n}\n\n/**\n * Consumer-supplied resolver: path → link data, or `null` when the path cannot\n * be resolved (stale vault link, missing file, etc.). The card degrades\n * gracefully — the source renders as a plain label rather than a broken link.\n */\nexport type KnowledgeSourceResolver = (path: string) => KnowledgeSourceResolved | null;\n\n/* ------------------------------------------------------------------ */\n/* Sub-component: a single resolved/unresolved source row */\n/* ------------------------------------------------------------------ */\n\ninterface SourceRowProps {\n path: string;\n resolve?: KnowledgeSourceResolver;\n}\n\nfunction SourceRow({ path, resolve }: SourceRowProps) {\n const { t } = useLocale();\n const resolved = resolve ? resolve(path) : null;\n const display = resolved?.title ?? path;\n\n if (resolved) {\n return (\n <a\n href={resolved.href}\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n // #399 — a source link is TEXT: the `--link` ink, not the fill.\n className=\"flex min-w-0 items-center gap-1.5 text-meta text-link underline-offset-2 hover:underline focus-ring\"\n aria-label={t(\"editor.knowledgeCard.source\", { name: display })}\n >\n <FileText className=\"size-3 shrink-0\" aria-hidden=\"true\" />\n <span className=\"truncate\">{display}</span>\n </a>\n );\n }\n\n return (\n <span\n className=\"flex min-w-0 items-center gap-1.5 text-meta text-muted-foreground\"\n aria-label={t(\"editor.knowledgeCard.sourceUnresolved\", { name: display })}\n >\n <FileText className=\"size-3 shrink-0\" aria-hidden=\"true\" />\n <span className=\"truncate\">{display}</span>\n </span>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* KnowledgeCard */\n/* ------------------------------------------------------------------ */\n\nexport interface KnowledgeCardProps extends HTMLAttributes<HTMLElement> {\n /**\n * Comma-separated source paths (e.g. `\"notes/a.md, notes/b.md\"`).\n * Each path is handed to `resolve`; unresolved paths render as plain labels.\n */\n sources?: string;\n /**\n * Consumer-supplied resolver. `undefined` → all sources render as plain labels\n * (safe default — never throws, never reads files).\n */\n resolve?: KnowledgeSourceResolver;\n /** The fact body (rendered markdown children of the directive). */\n children?: ReactNode;\n}\n\nexport const KnowledgeCard = forwardRef<HTMLElement, KnowledgeCardProps>(function KnowledgeCard(\n { sources, resolve, children, className, ...props },\n ref,\n) {\n const { t } = useLocale();\n const sourcePaths = sources\n ? sources\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean)\n : [];\n\n return (\n <section\n ref={ref}\n aria-label={t(\"editor.knowledgeCard.label\")}\n className={cn(\"not-prose\", className)}\n {...props}\n >\n <Card className=\"border-s-4 border-s-info\">\n <CardContent className=\"pt-4\">\n <div className=\"mb-2 flex items-center gap-1.5\">\n <BookOpen className=\"size-3.5 shrink-0 text-info-text\" aria-hidden=\"true\" />\n <span className=\"text-meta font-medium text-info-text\">\n {t(\"editor.knowledgeCard.heading\")}\n </span>\n </div>\n <div className=\"text-body text-foreground\">{children}</div>\n </CardContent>\n\n {sourcePaths.length > 0 ? (\n <CardFooter className=\"flex-col items-start gap-1 border-t border-border pt-3\">\n <p className=\"text-meta font-medium text-muted-foreground\">\n {t(\"editor.knowledgeCard.sources\")}\n </p>\n <ul\n className=\"flex w-full flex-col gap-1\"\n aria-label={t(\"editor.knowledgeCard.sources\")}\n >\n {sourcePaths.map((path) => (\n <li key={path} className=\"min-w-0\">\n <SourceRow path={path} resolve={resolve} />\n </li>\n ))}\n </ul>\n </CardFooter>\n ) : null}\n </Card>\n </section>\n );\n});\n","/**\n * Directive renderer factories for the ai-objects trio.\n *\n * Each factory returns a `MarkdownDirectiveRenderer` for registration on\n * `MarkdownPreview` via the `extensions.directives` prop. The factories are\n * thin wrappers: they pass directive context into the standalone presentational\n * components — the library renders, the consumer computes.\n *\n * Usage:\n * import { aiObjectDirectives } from \"@elabs-ai/components-editor/markdown\";\n *\n * <MarkdownPreview\n * extensions={{ directives: aiObjectDirectives({ resolveKnowledge }) }}\n * />\n */\nimport { createElement } from \"react\";\n\nimport type { MarkdownDirectiveRenderer } from \"../lib/markdown/directives\";\nimport { DecisionCard } from \"./decision-card\";\nimport { EntityCard, EntityChip } from \"./entity\";\nimport { KnowledgeCard, type KnowledgeSourceResolver } from \"./knowledge-card\";\n\n/* ------------------------------------------------------------------ */\n/* Individual factories */\n/* ------------------------------------------------------------------ */\n\n/**\n * `decisionDirective()` — registers the `:::decision` container renderer.\n *\n * Authoring shape:\n * :::decision{status=accepted date=2026-06-15 alternatives=\"Redis, SQLite\"}\n * We chose PostgreSQL because it already runs in prod.\n * :::\n */\nexport function decisionDirective(): MarkdownDirectiveRenderer {\n return {\n name: \"decision\",\n kinds: [\"container\"],\n render({ attributes, children }) {\n return createElement(DecisionCard, {\n status: attributes.status,\n date: attributes.date,\n alternatives: attributes.alternatives,\n children,\n });\n },\n };\n}\n\n/**\n * `entityDirective()` — registers the `entity` directive for BOTH container\n * (block card) and inline (chip) syntaxes.\n *\n * Authoring shapes:\n * Container: :::entity{kind=org name=\"Acme Corp\"}\n * Acme Corp is the primary vendor.\n * :::\n * Inline: :entity[Acme Corp]{kind=org}\n */\nexport function entityDirective(): MarkdownDirectiveRenderer {\n return {\n name: \"entity\",\n kinds: [\"container\", \"inline\"],\n render({ kind, attributes, children, textValue }) {\n if (kind === \"inline\") {\n // `textValue` is the verbatim label text (markdown chars preserved);\n // fall back to rendered children when positions were unavailable.\n const label = textValue ?? (typeof children === \"string\" ? children : undefined);\n return createElement(EntityChip, { kind: attributes.kind, children: label ?? children });\n }\n // Container → EntityCard (block)\n return createElement(EntityCard, {\n kind: attributes.kind,\n name: attributes.name,\n children,\n });\n },\n };\n}\n\n/**\n * `knowledgeDirective({ resolve })` — registers the `:::knowledge` container\n * renderer. The `resolve` hook is consumer-supplied; omitting it causes all\n * sources to render as plain unlinked labels (safe default).\n *\n * Authoring shape:\n * :::knowledge{sources=\"notes/a.md, notes/b.md\"}\n * PostgreSQL was chosen because …\n * :::\n */\nexport function knowledgeDirective(options?: {\n resolve?: KnowledgeSourceResolver;\n}): MarkdownDirectiveRenderer {\n return {\n name: \"knowledge\",\n kinds: [\"container\"],\n render({ attributes, children }) {\n return createElement(KnowledgeCard, {\n sources: attributes.sources,\n resolve: options?.resolve,\n children,\n });\n },\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Convenience bundle */\n/* ------------------------------------------------------------------ */\n\nexport interface AiObjectDirectivesOptions {\n /** Consumer-supplied resolver for `:::knowledge` source paths. */\n resolveKnowledge?: KnowledgeSourceResolver;\n}\n\n/**\n * `aiObjectDirectives(options)` — returns all three directive renderers as an\n * array ready to pass to `extensions.directives`:\n * - `decisionDirective()`\n * - `entityDirective()`\n * - `knowledgeDirective({ resolve: options.resolveKnowledge })`\n *\n * @example\n * <MarkdownPreview\n * extensions={{ directives: aiObjectDirectives({ resolveKnowledge }) }}\n * />\n */\nexport function aiObjectDirectives(\n options: AiObjectDirectivesOptions = {},\n): MarkdownDirectiveRenderer[] {\n return [\n decisionDirective(),\n entityDirective(),\n knowledgeDirective({ resolve: options.resolveKnowledge }),\n ];\n}\n","\"use client\";\n\n/**\n * IterationTemplateDialog — author a `:::iterate` / `:::pivot` per-cell TEMPLATE\n * in a focused modal (the #223 template modal). Composes `@elabs-ai/components-ui` `Dialog`\n * with the existing `MarkdownWorkspace` (source / split / preview-edit), so the\n * template is edited with the same toolbar + live preview as any document.\n *\n * Controlled: drive `open` / `onOpenChange`; seed `template`; receive the edited\n * markdown via `onSave`. The library does not own where the template is stored —\n * the caller (a slash command, or the node-view `⋯` re-edit menu) wires it back.\n */\nimport {\n Button,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n useLocale,\n} from \"@elabs-ai/components-ui\";\nimport { useEffect, useState, type ReactNode } from \"react\";\n\nimport { MarkdownWorkspace, type MarkdownWorkspaceMode } from \"../markdown-workspace\";\nimport { IterationEditContext, type IterationEditRequest } from \"./edit-context\";\n\nexport interface IterationTemplateDialogProps {\n /** Whether the dialog is open. */\n open: boolean;\n /** Open-state change handler (Radix Dialog contract). */\n onOpenChange: (open: boolean) => void;\n /** The initial template markdown (the directive body). */\n template: string;\n /** Called with the edited template when the user saves. */\n onSave: (template: string) => void;\n /** Tunes the title + helper copy. Default `\"iterate\"`. */\n kind?: \"iterate\" | \"pivot\";\n /** Initial workspace mode. Default `\"split\"`. */\n mode?: MarkdownWorkspaceMode;\n}\n\nexport function IterationTemplateDialog({\n open,\n onOpenChange,\n template,\n onSave,\n kind = \"iterate\",\n mode = \"split\",\n}: IterationTemplateDialogProps) {\n const { t } = useLocale();\n const [draft, setDraft] = useState(template);\n\n // Re-seed the draft whenever the dialog (re)opens against a new template.\n useEffect(() => {\n if (open) setDraft(template);\n }, [open, template]);\n\n const unit = kind === \"pivot\" ? \"cell\" : \"row\";\n\n const save = () => {\n onSave(draft);\n onOpenChange(false);\n };\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent\n className=\"flex max-h-[85vh] w-[min(48rem,92vw)] max-w-none flex-col\"\n // Radix autofocuses the first tabbable element — the toolbar's Bold button —\n // and its Tooltip opens on focus, so the dialog opened with a stray tooltip.\n // Focus the dialog itself instead; Tab still reaches the toolbar first.\n onOpenAutoFocus={(event) => {\n event.preventDefault();\n (event.currentTarget as HTMLElement | null)?.focus();\n }}\n >\n <DialogHeader>\n <DialogTitle>\n {kind === \"pivot\"\n ? t(\"editor.templateDialog.editPivotTitle\")\n : t(\"editor.templateDialog.editIterationTitle\")}\n </DialogTitle>\n <DialogDescription>\n {t(\"editor.templateDialog.descriptionPrefix\", { unit })}\n <code>{\"{{token}}\"}</code>\n {t(\"editor.templateDialog.descriptionMiddle\")}\n <code>{\"{{item.name}}\"}</code>\n {t(\"editor.templateDialog.descriptionSuffix\", { unit })}\n </DialogDescription>\n </DialogHeader>\n <div className=\"min-h-0 flex-1\">\n <MarkdownWorkspace\n value={draft}\n onChange={setDraft}\n defaultMode={mode}\n className=\"h-full\"\n aria-label={t(\"editor.templateDialog.editorLabel\")}\n />\n </div>\n <DialogFooter>\n <Button variant=\"ghost\" onClick={() => onOpenChange(false)}>\n {t(\"editor.templateDialog.cancel\")}\n </Button>\n <Button onClick={save}>{t(\"editor.templateDialog.saveTemplate\")}</Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n\n/**\n * One-liner wiring for the node-view `⋯` re-edit: provides the\n * {@link IterationEditContext} handler AND renders the `IterationTemplateDialog`\n * it opens. Wrap your `MarkdownEditor` / `MarkdownWorkspace` in it to enable the\n * `⋯` \"Edit template…\" affordance on `:::iterate` / `:::pivot` node-views.\n */\nexport function IterationTemplateProvider({ children }: { children: ReactNode }) {\n const [request, setRequest] = useState<IterationEditRequest | null>(null);\n return (\n <IterationEditContext.Provider value={setRequest}>\n {children}\n <IterationTemplateDialog\n open={request != null}\n onOpenChange={(next) => {\n if (!next) setRequest(null);\n }}\n template={request?.template ?? \"\"}\n kind={request?.kind ?? \"iterate\"}\n onSave={(template) => request?.onSave(template)}\n />\n </IterationEditContext.Provider>\n );\n}\n","\"use client\";\n\n/**\n * IterationBuilderDialog (A5) — GUIDED `:::iterate` / `:::pivot` authoring.\n *\n * Where `IterationTemplateDialog` edits only the per-cell template, the builder\n * also collects the DATA — the value list (iterate) or the two value lists\n * (pivot), the bind name, and the layout — and shows a LIVE preview of the\n * populated block as you type. On save it writes a fully-bound directive\n * (`serializeIterationDirective`) whose value lists live in its attributes, so the\n * block renders populated via the built-in `evaluateEmbedded` and the `⋯` re-edit\n * can reopen it losslessly (`parseIterationDirective` / `builderValueFromParts`).\n *\n * Controlled (`open` / `onOpenChange`); seed via `value` (re-edit) or `kind` +\n * `initialValues` (fresh insert, e.g. a selection split to one value per line).\n */\nimport {\n Button,\n Dialog,\n DialogBody,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n Input,\n Label,\n TagInput,\n ToggleGroup,\n ToggleGroupItem,\n useLocale,\n} from \"@elabs-ai/components-ui\";\nimport { useEffect, useId, useMemo, useState, type ReactNode } from \"react\";\n\nimport { type EvaluateCalc } from \"../calc-block\";\nimport { MarkdownPreview } from \"../markdown-preview\";\nimport { MarkdownWorkspace } from \"../markdown-workspace\";\nimport { IterationEditContext, type IterationEditRequest } from \"./edit-context\";\nimport { type InterpolateTemplate, type IterationLayout } from \"./iteration\";\nimport {\n builderValueFromParts,\n directivePartsFromValue,\n emptyBuilderValue,\n evaluateEmbedded,\n ITERATION_LAYOUTS,\n parseIterationDirective,\n serializeIterationDirective,\n type IterationBuilderValue,\n} from \"./iteration-builder\";\n\nexport interface IterationBuilderDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n /** Which block to author. Default `\"iterate\"`. Ignored when `value` is set. */\n kind?: \"iterate\" | \"pivot\";\n /** Seed the whole builder (the `⋯` re-edit path). */\n value?: IterationBuilderValue;\n /** Seed the value list of a fresh block (e.g. a selection split to lines). */\n initialValues?: string[];\n /** Receives the fully-bound directive markdown when the user saves. */\n onSave: (directiveMarkdown: string) => void;\n /**\n * Resolve a ```calc fence to a `CalcSheet` so calc cells COMPUTE in the live\n * preview (the same hook `MarkdownPreview` takes — the library renders, the app\n * computes). Without it a calc cell still renders as a code block; with it, the\n * preview matches production. Pass your app's calc engine.\n */\n evaluate?: EvaluateCalc;\n /** Fill a cell template with its context. Defaults to `{{path}}` substitution. */\n interpolate?: InterpolateTemplate;\n}\n\nexport function IterationBuilderDialog({\n open,\n onOpenChange,\n kind: kindProp = \"iterate\",\n value,\n initialValues,\n onSave,\n evaluate,\n interpolate,\n}: IterationBuilderDialogProps) {\n const { t } = useLocale();\n const kind = value?.kind ?? kindProp;\n const isPivot = kind === \"pivot\";\n const ids = useId();\n\n // Working draft. Value lists are arrays (chip entry via TagInput); the per-cell\n // template stays raw text.\n const [asName, setAsName] = useState(\"item\");\n const [layout, setLayout] = useState<IterationLayout>(ITERATION_LAYOUTS[kind][0] ?? \"stacked\");\n const [values, setValues] = useState<string[]>([]);\n const [cols, setCols] = useState<string[]>([]);\n const [template, setTemplate] = useState(\"\");\n\n // (Re)seed whenever the dialog opens against a new value / kind.\n useEffect(() => {\n if (!open) return;\n const seed = value ?? {\n ...emptyBuilderValue(kind),\n values: initialValues ?? [],\n };\n setAsName(seed.as);\n setLayout(seed.layout);\n setValues(seed.values);\n setCols(seed.cols ?? []);\n setTemplate(seed.template);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open]);\n\n const draft: IterationBuilderValue = useMemo(\n () => ({\n kind,\n as: asName.trim() || \"item\",\n layout,\n values,\n cols: isPivot ? cols : undefined,\n template,\n }),\n [kind, asName, layout, values, cols, template, isPivot],\n );\n\n // Live preview — render the SERIALIZED directive through MarkdownPreview, the\n // exact path the saved block renders through. That resolves the iteration via\n // the built-in `evaluateEmbedded` AND each cell's objects (a ```calc fence,\n // nested directives, formatting) — in stacked, grid and matrix alike — instead\n // of dumping the raw cell text.\n const previewMarkdown = useMemo(() => serializeIterationDirective(draft), [draft]);\n\n const save = () => {\n onSave(serializeIterationDirective(draft));\n onOpenChange(false);\n };\n\n const noun = isPivot\n ? t(\"editor.iterationBuilder.pivotNoun\")\n : t(\"editor.iterationBuilder.iterationNoun\");\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"flex max-h-[88vh] w-[min(56rem,94vw)] max-w-none flex-col\">\n <DialogHeader>\n <DialogTitle>\n {t(\n value ? \"editor.iterationBuilder.editTitle\" : \"editor.iterationBuilder.insertTitle\",\n {\n noun,\n },\n )}\n </DialogTitle>\n <DialogDescription>\n {isPivot\n ? t(\"editor.iterationBuilder.pivotDescription\")\n : t(\"editor.iterationBuilder.iterationDescription\")}\n </DialogDescription>\n </DialogHeader>\n\n <DialogBody className=\"grid gap-4 md:grid-cols-2\">\n {/* Left column — the DATA the block iterates over. */}\n <div className=\"flex min-w-0 flex-col gap-4\">\n {!isPivot ? (\n <div className=\"flex flex-col gap-1.5\">\n <Label htmlFor={`${ids}-as`}>{t(\"editor.iterationBuilder.bindName\")}</Label>\n <Input\n id={`${ids}-as`}\n value={asName}\n spellCheck={false}\n autoComplete=\"off\"\n placeholder={t(\"editor.iterationBuilder.bindNamePlaceholder\")}\n onChange={(e) => setAsName(e.target.value)}\n />\n <p className=\"text-meta text-muted-foreground\">\n {t(\"editor.iterationBuilder.bindNameHintPrefix\")}\n <code>{`{{${asName.trim() || \"item\"}.name}}`}</code>\n {t(\"editor.iterationBuilder.bindNameHintSuffix\")}\n </p>\n </div>\n ) : null}\n\n <div className=\"flex flex-col gap-1.5\">\n <Label htmlFor={`${ids}-values`}>\n {isPivot\n ? t(\"editor.iterationBuilder.rowValues\")\n : t(\"editor.iterationBuilder.values\")}\n </Label>\n <TagInput\n id={`${ids}-values`}\n value={values}\n onValueChange={setValues}\n delimiter={[\",\", \"\\n\"]}\n placeholder={t(\"editor.iterationBuilder.valuePlaceholder\")}\n />\n </div>\n\n {isPivot ? (\n <div className=\"flex flex-col gap-1.5\">\n <Label htmlFor={`${ids}-cols`}>{t(\"editor.iterationBuilder.columnValues\")}</Label>\n <TagInput\n id={`${ids}-cols`}\n value={cols}\n onValueChange={setCols}\n delimiter={[\",\", \"\\n\"]}\n placeholder={t(\"editor.iterationBuilder.valuePlaceholder\")}\n />\n </div>\n ) : null}\n\n <div className=\"flex flex-col gap-1.5\">\n <Label id={`${ids}-layout`}>{t(\"editor.iterationBuilder.layout\")}</Label>\n <ToggleGroup\n type=\"single\"\n variant=\"segmented\"\n value={layout}\n onValueChange={(next) => {\n // Single-select: ignore the empty value Radix emits when the active\n // item is re-pressed, so a layout is always selected.\n if (next) setLayout(next as IterationLayout);\n }}\n aria-labelledby={`${ids}-layout`}\n className=\"w-fit\"\n >\n {ITERATION_LAYOUTS[kind].map((l) => (\n <ToggleGroupItem key={l} value={l} className=\"capitalize\">\n {l}\n </ToggleGroupItem>\n ))}\n </ToggleGroup>\n </div>\n </div>\n\n {/* Right column — the per-cell TEMPLATE + the live populated preview. */}\n <div className=\"flex min-h-0 min-w-0 flex-col gap-4\">\n <div className=\"flex min-h-0 flex-col gap-1.5\">\n <Label>\n {isPivot\n ? t(\"editor.iterationBuilder.perCellTemplate\")\n : t(\"editor.iterationBuilder.perRowTemplate\")}\n </Label>\n <div className=\"h-44 min-h-0 overflow-hidden rounded-md border border-border\">\n <MarkdownWorkspace\n value={template}\n onChange={setTemplate}\n defaultMode=\"source\"\n className=\"h-full\"\n aria-label={t(\"editor.iterationBuilder.perCellTemplate\")}\n />\n </div>\n </div>\n\n <div className=\"flex min-h-0 flex-col gap-1.5\">\n <Label>{t(\"editor.iterationBuilder.livePreview\")}</Label>\n <div\n role=\"region\"\n aria-label={t(\"editor.iterationBuilder.livePreview\")}\n className=\"min-h-0 flex-1 overflow-auto rounded-md border border-border bg-card p-3\"\n >\n <MarkdownPreview\n evaluateIteration={evaluateEmbedded}\n evaluate={evaluate}\n interpolate={interpolate}\n >\n {previewMarkdown}\n </MarkdownPreview>\n </div>\n </div>\n </div>\n </DialogBody>\n\n <DialogFooter>\n <Button variant=\"ghost\" onClick={() => onOpenChange(false)}>\n {t(\"editor.iterationBuilder.cancel\")}\n </Button>\n <Button onClick={save}>\n {value ? t(\"editor.iterationBuilder.save\") : t(\"editor.iterationBuilder.insert\")}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n\n/**\n * One-liner wiring for the node-view `⋯` re-edit using the GUIDED builder (A5).\n * Drop it above a `MarkdownEditor` / `MarkdownWorkspace` to make the `⋯` on a\n * `:::iterate` / `:::pivot` reopen the full builder seeded with the block's DATA\n * (value lists + bind name + layout) and template, writing both back losslessly.\n *\n * Prefer this over {@link IterationTemplateProvider} when the consumer authors\n * blocks with embedded value lists (the builder flow); the template-only provider\n * remains for the lighter \"edit just the template\" affordance.\n */\nexport function IterationBuilderProvider({\n children,\n evaluate,\n interpolate,\n}: {\n children: ReactNode;\n /** Forwarded to the builder's live preview so calc cells COMPUTE on re-edit. */\n evaluate?: EvaluateCalc;\n /** Forwarded to the builder's live preview cell interpolation. */\n interpolate?: InterpolateTemplate;\n}) {\n const [request, setRequest] = useState<IterationEditRequest | null>(null);\n\n const seed = request\n ? builderValueFromParts(request.kind, request.attributes ?? {}, request.template)\n : undefined;\n\n return (\n <IterationEditContext.Provider value={setRequest}>\n {children}\n <IterationBuilderDialog\n open={request != null}\n onOpenChange={(next) => {\n if (!next) setRequest(null);\n }}\n kind={request?.kind ?? \"iterate\"}\n value={seed}\n evaluate={evaluate}\n interpolate={interpolate}\n onSave={(directiveMarkdown) => {\n const parsed = parseIterationDirective(directiveMarkdown);\n if (!parsed) return;\n const { attributes, template } = directivePartsFromValue(parsed);\n // Prefer the data-aware writer (rewrites attributes + body); fall back to\n // the template-only writer for older node-views.\n if (request?.onSaveData) request.onSaveData({ attributes, template });\n else request?.onSave(template);\n }}\n />\n </IterationEditContext.Provider>\n );\n}\n"],"mappings":"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","names":["editor","monaco","editor","editor","filtered","activeCommand","Tooltip","TooltipContent","TooltipProvider","TooltipTrigger","useLocale","cn","forwardRef","useEffect","useMemo","useRef","useState","monaco","REGISTRY","editor","i","j","monaco","Separator","cn","createContext","forwardRef","useContext","useMemo","visit","cn","jsx","jsxs","cn","CalcBlock","cn","TriangleAlert","forwardRef","useMemo","jsx","jsxs","CalcInline","Button","useLocale","cn","forwardRef","useEffect","useRef","useState","useLocale","cn","useEffect","useMemo","useRef","useState","jsx","jsxs","jsx","jsxs","forwardRef","MermaidDiagram","useLocale","useRef","useState","useEffect","cn","Button","cn","useEffect","useRef","useState","jsx","jsxs","cn","useState","useRef","useEffect","cn","useLocale","forwardRef","useId","visit","jsx","jsxs","Bibliography","Separator","cn","forwardRef","useId","visit","jsx","jsxs","FootnoteList","useLocale","cn","useMemo","visit","jsx","cn","createContext","forwardRef","useContext","jsx","jsxs","TableOfContents","createContext","useContext","jsx","createContext","useContext","Fragment","jsx","jsxs","createContext","visit","useContext","cn","useMemo","Separator","forwardRef","MarkdownPreview","children","Button","Separator","useLocale","cn","Minus","forwardRef","Fragment","jsx","jsxs","forwardRef","MarkdownToolbar","editor","useLocale","Button","cn","Separator","Minus","Fragment","Fragment","jsx","jsxs","forwardRef","MarkdownWorkspace","useLocale","useState","monaco","useRef","useEffect","useMemo","TooltipProvider","Tooltip","TooltipTrigger","TooltipContent","editor","cn","remarkDirective","ResizableHandle","ResizablePanel","ResizablePanelGroup","cn","forwardRef","useEffect","useState","jsx","jsxs","forwardRef","MermaidWorkspace","useState","useEffect","cn","ResizablePanelGroup","ResizablePanel","ResizableHandle","Card","CardContent","CardHeader","Separator","useLocale","cn","forwardRef","Fragment","jsx","jsxs","DecisionCard","Card","CardContent","CardHeader","CardTitle","cn","cva","forwardRef","jsx","jsxs","EntityChip","EntityCard","Card","CardContent","useLocale","cn","forwardRef","jsx","jsxs","KnowledgeCard","Button","Dialog","DialogContent","DialogTitle","useLocale","useEffect","useState","jsx","jsxs","useLocale","useState","useEffect","Dialog","DialogContent","DialogTitle","Button","Button","Dialog","DialogContent","DialogDescription","DialogFooter","DialogHeader","DialogTitle","Input","ToggleGroup","ToggleGroupItem","useLocale","useEffect","useId","useMemo","useState","jsx","jsxs","useLocale","useId","useState","useEffect","useMemo","Dialog","DialogContent","DialogHeader","DialogTitle","DialogDescription","Input","ToggleGroup","ToggleGroupItem","DialogFooter","Button"]}
1
+ {"version":3,"sources":["../../src/lib/editor-completions-monaco.ts","../../src/markdown-editor/slash/monaco-slash-menu.tsx","../../src/markdown-toolbar/markdown-commands.ts","../../src/markdown-workspace/markdown-workspace.tsx","../../src/calc-block/calc-editor-monaco.ts","../../src/lib/markdown/diff.ts","../../src/lib/markdown/merge.ts","../../src/markdown-editor/slash/source-slash-trigger.ts","../../src/markdown-editor/slash/shortcut-monaco.ts","../../src/markdown-preview/markdown-preview.tsx","../../src/lib/markdown/directives.ts","../../src/calc-block/calc-block.tsx","../../src/calc-block/calc-inline.tsx","../../src/mermaid-diagram/mermaid-diagram.tsx","../../src/mermaid-diagram/mermaid-viewer.tsx","../../src/mermaid-diagram/remediate.ts","../../src/prose/prose.tsx","../../src/timeline/index.ts","../../src/markdown-preview/code-fence.tsx","../../src/markdown-academic/citations.tsx","../../src/markdown-academic/footnotes.tsx","../../src/markdown-academic/math.tsx","../../src/markdown-academic/toc.tsx","../../src/markdown-iteration/directive.tsx","../../src/markdown-toolbar/markdown-toolbar.tsx","../../src/markdown-workspace/focus-writing.ts","../../src/markdown/parse.ts","../../src/mermaid-workspace/mermaid-workspace.tsx","../../src/ai-objects/decision-card.tsx","../../src/ai-objects/entity.tsx","../../src/ai-objects/knowledge-card.tsx","../../src/ai-objects/directives.ts","../../src/markdown-iteration/template-dialog.tsx","../../src/markdown-iteration/iteration-builder-dialog.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * Monaco registration lifecycle for the declarative completion-provider API\n * (#283) — the engine that backs the `completions` prop on `MarkdownWorkspace`.\n *\n * `monaco.languages.registerCompletionItemProvider` is GLOBAL PER LANGUAGE, not\n * per editor instance (the root cause #283 exists to fix — see the issue). So\n * this module owns a single, REFCOUNTED registration for the \"markdown\"\n * language: the first `attachCompletionsMonaco` call registers it, each\n * subsequent call (a second mounted `MarkdownWorkspace`) bumps the refcount,\n * and the registration is disposed ONLY when the LAST attached editor's\n * disposer runs — no leak, no double-registration (#283 acceptance).\n *\n * Suggestions are scoped to the models THIS module attached (a `REGISTRY` keyed\n * by `ITextModel`) — any other \"markdown\" model in the app (one the host built\n * itself, outside `@elabs-ai/components-editor`) is ignored, never suggested into.\n *\n * `getProviders` is read fresh from the registry on every `provideCompletionItems`\n * call — NOT captured as a closure at registration time — so a rebuilt provider\n * list (a new `completions` array identity from React state/props) is picked up\n * WITHOUT re-registering (#283 acceptance). Mirrors the calc layer's\n * `REGISTRY`/`getHooks` pattern in `calc-block/calc-editor-monaco.ts`.\n */\nimport * as monaco from \"monaco-editor\";\n\nimport {\n collectCompletions,\n resolveReplaceRange,\n type EditorCompletionProvider,\n} from \"./editor-completions\";\n\n/** Resolver of the latest provider list for a model (read fresh on every call). */\ntype ProvidersGetter = () => EditorCompletionProvider[] | undefined;\n\n/** Per-model provider registry — scopes suggestions to OUR editor instances. */\nconst REGISTRY = new Map<monaco.editor.ITextModel, ProvidersGetter>();\n\nlet refCount = 0;\nlet registration: monaco.IDisposable | null = null;\n\n/** Register the \"markdown\" completion provider once (idempotent while refs > 0). */\nfunction ensureRegistered(): void {\n if (registration) return;\n registration = monaco.languages.registerCompletionItemProvider(\"markdown\", {\n provideCompletionItems(model, position) {\n const getProviders = REGISTRY.get(model);\n if (!getProviders) return { suggestions: [] };\n const providers = getProviders();\n if (!providers || providers.length === 0) return { suggestions: [] };\n const lineText = model.getLineContent(position.lineNumber);\n const ctx = {\n source: model.getValue(),\n line: position.lineNumber,\n column: position.column,\n lineText,\n };\n return collectCompletions(providers, ctx).then((matches) => ({\n suggestions: matches.map(({ provider, item }) => ({\n label: item.label,\n kind: monaco.languages.CompletionItemKind.Text,\n insertText: item.insertText,\n detail: item.detail,\n range: resolveReplaceRange(item, position, lineText, provider.triggerCharacters),\n })),\n }));\n },\n });\n}\n\n/**\n * Attach the declarative completion providers to a Monaco editor instance.\n * `getProviders` is read live on every suggestion request (see module doc) —\n * pass a ref-backed getter so a fresh `completions` array identity on every\n * render never forces a re-attach.\n *\n * Also force-opens Monaco's native suggest widget (`editor.action.triggerSuggest`)\n * whenever the user types a character matching one of the CURRENTLY-configured\n * providers' `triggerCharacters` — read live, so changing that set never needs a\n * re-registration either. Markdown punctuation like `[` doesn't extend a \"word\",\n * so without this Monaco's own quick-suggestions heuristic would never invoke a\n * provider on it.\n *\n * Returns a disposer. Call it on unmount / when `completions` is removed —\n * refcounted, so the GLOBAL \"markdown\" registration is only torn down once the\n * LAST attached editor calls its disposer (#283 acceptance: no leak, no\n * double-registration with two workspaces mounted).\n */\nexport function attachCompletionsMonaco(\n editor: monaco.editor.IStandaloneCodeEditor,\n getProviders: ProvidersGetter,\n): () => void {\n ensureRegistered();\n refCount++;\n\n let model = editor.getModel();\n if (model) REGISTRY.set(model, getProviders);\n\n const contentSub = editor.onDidChangeModelContent((e) => {\n const providers = getProviders();\n if (!providers || providers.length === 0) return;\n for (const change of e.changes) {\n if (change.text.length !== 1) continue;\n if (providers.some((p) => p.triggerCharacters?.includes(change.text))) {\n editor.trigger(\"brand-completions\", \"editor.action.triggerSuggest\", {});\n return;\n }\n }\n });\n\n const modelSub = editor.onDidChangeModel(() => {\n if (model) REGISTRY.delete(model);\n model = editor.getModel();\n if (model) REGISTRY.set(model, getProviders);\n });\n\n return () => {\n contentSub.dispose();\n modelSub.dispose();\n if (model) REGISTRY.delete(model);\n refCount = Math.max(0, refCount - 1);\n if (refCount === 0) {\n registration?.dispose();\n registration = null;\n }\n };\n}\n","\"use client\";\n\n/**\n * MonacoSlashMenu — a caret-anchored slash command popup for the Monaco source\n * pane (#271).\n *\n * The workspace owns the open/closed state (via a `CodeEditor` action keybinding\n * registered through `CodeEditor.actions`). This component is the POSITIONING\n * CONTROLLER + KEYBOARD HANDLER that wraps the shared `SlashMenu` body — it does\n * NOT re-implement the listbox (no duplication, tokens only, same look as the\n * WYSIWYG widget).\n *\n * a11y: the `SlashMenu` already provides `role=\"listbox\"` / `role=\"option\"` /\n * `aria-selected`; this wrapper wires `aria-activedescendant` on the editor's\n * textarea so AT can follow the active row. Esc closes and refocuses the editor.\n */\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport type { IRange } from \"monaco-editor\";\nimport { useEffect, useRef, useState } from \"react\";\n\nimport type { MonacoCodeEditor } from \"../../code-editor\";\nimport { monacoContentAccess } from \"../../lib/editor-content-access\";\nimport { insertDirective } from \"../../markdown-toolbar/markdown-commands\";\nimport { filterSlashCommands, type SlashCommand } from \"./brand-slash-commands\";\nimport { SlashMenu, slashOptionId } from \"./slash-menu\";\n\nexport interface MonacoSlashMenuProps {\n /** The live Monaco editor instance (source pane). */\n editor: MonacoCodeEditor;\n /**\n * Commands to show in the source pane — filtered by the workspace to\n * `snippet != null || typeof runInSource === \"function\"` (#299): a command\n * needs a text snippet, a source-pane handler, or both to appear here (a\n * run-only WYSIWYG command with neither is Milkdown-only and stays excluded).\n */\n commands: SlashCommand[];\n /** Controlled open state — the workspace toggles it via the Layer-1 action. */\n open: boolean;\n onOpenChange: (open: boolean) => void;\n /**\n * Insert the selected snippet at the Monaco caret + refocus.\n * Defaults to `insertDirective` from `markdown-commands.ts`.\n */\n onInsert?: (editor: MonacoCodeEditor, snippet: string) => void;\n /**\n * When the menu was opened by typing `/` (not the hotkey), the model range of\n * that `/`. On select the `/` is REPLACED by the inserted block; on cancel\n * (Escape / Backspace past the trigger) it is removed. `null`/omitted = the\n * hotkey path, which inserts via `onInsert`/`insertDirective` and leaves the\n * document otherwise untouched.\n */\n triggerRange?: IRange | null;\n /** Merged onto the positioned popup container (the inline `position:fixed` anchor stays). */\n className?: string;\n}\n\nconst ID_PREFIX = \"brand-monaco-slash\";\nconst LISTBOX_ID = `${ID_PREFIX}-listbox`;\n\n/** Fixed/absolute coords of the popup anchor. */\ninterface Coords {\n top: number;\n left: number;\n}\n\nfunction getCaretCoords(editor: MonacoCodeEditor): Coords | null {\n const pos = editor.getPosition();\n if (!pos) return null;\n const scrolled = editor.getScrolledVisiblePosition(pos);\n if (!scrolled) return null;\n const domNode = editor.getDomNode();\n if (!domNode) return null;\n const rect = domNode.getBoundingClientRect();\n return {\n top: rect.top + scrolled.top + (scrolled.height ?? 20),\n left: rect.left + scrolled.left,\n };\n}\n\nexport function MonacoSlashMenu({\n editor,\n commands,\n open,\n onOpenChange,\n onInsert,\n triggerRange,\n className,\n}: MonacoSlashMenuProps) {\n const [query, setQuery] = useState(\"\");\n const [activeIndex, setActiveIndex] = useState(0);\n const [coords, setCoords] = useState<Coords | null>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n\n // Insert the chosen snippet. Typed-`/` mode REPLACES the `/` (triggerRange) with\n // the block; hotkey mode inserts via insertDirective at the caret/line. Always\n // refocus the editor and close.\n const commitSnippet = (snippet: string) => {\n if (triggerRange) {\n editor.executeEdits(\"brand-slash-typed\", [\n { range: triggerRange, text: snippet, forceMoveMarkers: true },\n ]);\n } else {\n (onInsert ?? insertDirective)(editor, snippet);\n }\n onOpenChange(false);\n editor.focus();\n };\n\n // Run a source-pane handler (#299): strip the typed `/query` trigger FIRST\n // (the same edit `cancel` uses, so the doc is clean whether the handler\n // opens a dialog, schedules async work, or inserts nothing), then call it\n // with the live editor + the (now-stale) trigger range + content access.\n const commitRunInSource = (command: SlashCommand) => {\n if (triggerRange) {\n editor.executeEdits(\"brand-slash-typed\", [{ range: triggerRange, text: \"\" }]);\n }\n command.runInSource?.({\n editor,\n range: triggerRange ?? null,\n content: monacoContentAccess(editor),\n });\n onOpenChange(false);\n editor.focus();\n };\n\n // Select a command: `runInSource` (when present) wins over `snippet` — it's\n // the more capable handler and is the ONLY option for a run-only command.\n const selectCommand = (command: SlashCommand) => {\n if (typeof command.runInSource === \"function\") {\n commitRunInSource(command);\n } else if (command.snippet) {\n commitSnippet(command.snippet);\n }\n };\n\n // Dismiss without inserting. In typed-`/` mode the stray `/` is removed so the\n // document is left exactly as it was before the trigger.\n const cancel = () => {\n if (triggerRange) {\n editor.executeEdits(\"brand-slash-cancel\", [{ range: triggerRange, text: \"\" }]);\n }\n onOpenChange(false);\n editor.focus();\n };\n\n // Latest select/cancel via refs so the capture-phase keydown listener can stay\n // attached across renders (its effect deps don't need these closures).\n const selectRef = useRef(selectCommand);\n selectRef.current = selectCommand;\n const cancelRef = useRef(cancel);\n cancelRef.current = cancel;\n\n // Reset query + active index whenever the menu opens.\n useEffect(() => {\n if (open) {\n setQuery(\"\");\n setActiveIndex(0);\n }\n }, [open]);\n\n // Compute and track caret position.\n useEffect(() => {\n if (!open) return;\n\n const update = () => {\n setCoords(getCaretCoords(editor));\n };\n\n update();\n\n const scrollSub = editor.onDidScrollChange(update);\n const cursorSub = editor.onDidChangeCursorPosition(update);\n\n const onResize = () => update();\n window.addEventListener(\"resize\", onResize);\n\n return () => {\n scrollSub.dispose();\n cursorSub.dispose();\n window.removeEventListener(\"resize\", onResize);\n };\n }, [open, editor]);\n\n // Close on editor blur.\n useEffect(() => {\n if (!open) return;\n const blurSub = editor.onDidBlurEditorText(() => {\n // Small delay — if focus moved to the menu itself (mousedown), don't close.\n setTimeout(() => {\n if (!menuRef.current?.contains(document.activeElement)) {\n onOpenChange(false);\n }\n }, 100);\n });\n return () => blurSub.dispose();\n }, [open, editor, onOpenChange]);\n\n // Wire keyboard navigation into the editor while the menu is open.\n useEffect(() => {\n if (!open) return;\n\n const keydown = (e: KeyboardEvent) => {\n const filtered = filterSlashCommands(commands, query);\n\n if (e.key === \"Escape\") {\n e.preventDefault();\n e.stopPropagation();\n cancelRef.current();\n return;\n }\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n e.stopPropagation();\n setActiveIndex((i) => (i + 1) % Math.max(filtered.length, 1));\n return;\n }\n if (e.key === \"ArrowUp\") {\n e.preventDefault();\n e.stopPropagation();\n setActiveIndex(\n (i) => (i - 1 + Math.max(filtered.length, 1)) % Math.max(filtered.length, 1),\n );\n return;\n }\n // Enter AND Tab select the active command (the cmdk / Notion command-menu\n // convention) — kept identical to the WYSIWYG slash menu so the cross-pane\n // shortcut behaves the same in both panes (the goal of #271). Tab does NOT\n // move browser focus here by design; Esc dismisses without inserting.\n if (e.key === \"Enter\" || e.key === \"Tab\") {\n // Always swallow while the popup is open — even with no match — so the key\n // never leaks a newline/tab into the document behind the popup.\n e.preventDefault();\n e.stopPropagation();\n const command = filtered[Math.min(activeIndex, filtered.length - 1)];\n if (command) selectRef.current(command);\n return;\n }\n // Printable characters update the query — intercept so they filter the\n // menu instead of being typed into the Monaco document (the menu was\n // opened by shortcut, so there is no `/query` run in the doc to absorb them).\n if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {\n e.preventDefault();\n e.stopPropagation();\n setQuery((q) => q + e.key);\n setActiveIndex(0);\n return;\n }\n // Backspace trims the query (and closes when empty) — intercept so it\n // never deletes document text behind the popup.\n if (e.key === \"Backspace\") {\n e.preventDefault();\n e.stopPropagation();\n if (query.length === 0) {\n // Backspacing past the trigger dismisses (and removes the typed `/`).\n cancelRef.current();\n return;\n }\n setQuery((q) => q.slice(0, -1));\n setActiveIndex(0);\n }\n };\n\n // Capture phase — intercept before Monaco's own key handlers.\n const domNode = editor.getDomNode();\n domNode?.addEventListener(\"keydown\", keydown, true);\n return () => domNode?.removeEventListener(\"keydown\", keydown, true);\n }, [open, editor, commands, query, activeIndex]);\n\n // Keep the highlighted option scrolled into view as ↑/↓ moves it — the listbox\n // is overflow-y-auto, so without this the active row can move off-screen while\n // the keyboard selection advances (the same fix slash-widget.tsx applies).\n useEffect(() => {\n if (!open) return;\n const filtered = filterSlashCommands(commands, query);\n const active = filtered[Math.min(activeIndex, Math.max(filtered.length - 1, 0))];\n if (!active) return;\n const el = menuRef.current?.querySelector<HTMLElement>(\n `#${CSS.escape(slashOptionId(ID_PREFIX, active.id))}`,\n );\n el?.scrollIntoView({ block: \"nearest\" });\n }, [open, commands, query, activeIndex]);\n\n // Mirror the listbox relationship onto the Monaco textbox while open, so AT is\n // told a popup appeared (aria-expanded), where it is (aria-controls), and which\n // option is active (aria-activedescendant) — the same wiring the WYSIWYG path\n // applies in slash-widget.tsx. All three are cleaned up on close.\n useEffect(() => {\n if (!open) return;\n const filtered = filterSlashCommands(commands, query);\n const activeCommand = filtered[Math.min(activeIndex, Math.max(filtered.length - 1, 0))];\n const textarea = editor.getDomNode()?.querySelector(\"textarea\");\n if (!textarea) return;\n textarea.setAttribute(\"aria-expanded\", \"true\");\n textarea.setAttribute(\"aria-controls\", LISTBOX_ID);\n if (activeCommand) {\n textarea.setAttribute(\"aria-activedescendant\", slashOptionId(ID_PREFIX, activeCommand.id));\n } else {\n textarea.removeAttribute(\"aria-activedescendant\");\n }\n return () => {\n textarea.removeAttribute(\"aria-expanded\");\n textarea.removeAttribute(\"aria-controls\");\n textarea.removeAttribute(\"aria-activedescendant\");\n };\n }, [open, editor, commands, query, activeIndex]);\n\n if (!open || !coords) return null;\n\n const filtered = filterSlashCommands(commands, query);\n const activeCommand = filtered[Math.min(activeIndex, Math.max(filtered.length - 1, 0))];\n\n const handleSelect = (command: SlashCommand) => {\n selectCommand(command);\n };\n\n const resultCount = filtered.length;\n const statusText =\n resultCount === 0\n ? \"No matching blocks\"\n : query\n ? `${resultCount} result${resultCount === 1 ? \"\" : \"s\"} for “${query}”`\n : `${resultCount} block${resultCount === 1 ? \"\" : \"s\"}`;\n\n return (\n <div\n ref={menuRef}\n className={cn(className)}\n // Fixed positioning so it overlays the editor regardless of scroll.\n style={{ position: \"fixed\", top: coords.top, left: coords.left, zIndex: 50 }}\n // Prevent the mousedown from stealing focus from the editor.\n onMouseDown={(e) => e.preventDefault()}\n >\n {/* One polite live region — focus stays in the editor, so AT learns the\n filter result count (and the empty state) only from here. The visual\n chip below is aria-hidden to avoid a double announcement. */}\n <span role=\"status\" aria-live=\"polite\" className=\"sr-only\">\n {statusText}\n </span>\n {query && (\n <div\n aria-hidden=\"true\"\n className=\"mb-0.5 rounded-sm border border-border bg-popover px-2 py-1 text-caption text-muted-foreground\"\n >\n Filter: <span className=\"font-medium text-foreground\">{query}</span>\n </div>\n )}\n <SlashMenu\n id={LISTBOX_ID}\n commands={filtered}\n activeId={activeCommand?.id}\n onSelect={handleSelect}\n idPrefix={ID_PREFIX}\n />\n </div>\n );\n}\n","/**\n * Markdown editing commands that operate on a Monaco editor instance (the source\n * pane). Pure functions over the editor — the toolbar UI wires buttons to these.\n */\nimport * as monaco from \"monaco-editor\";\n\nimport type { MonacoCodeEditor } from \"../code-editor\";\n\n/** Wrap the current selection (or insert a placeholder) with `before`/`after`. */\nexport function wrapSelection(\n editor: MonacoCodeEditor,\n before: string,\n after: string = before,\n placeholder = \"text\",\n): void {\n const model = editor.getModel();\n const selection = editor.getSelection();\n if (!model || !selection) return;\n\n const selected = model.getValueInRange(selection) || placeholder;\n editor.executeEdits(\"markdown-toolbar\", [\n { range: selection, text: `${before}${selected}${after}`, forceMoveMarkers: true },\n ]);\n // Re-select the inner text so the user can keep typing over the placeholder.\n const startCol = selection.startColumn + before.length;\n editor.setSelection(\n new monaco.Selection(\n selection.startLineNumber,\n startCol,\n selection.startLineNumber,\n startCol + selected.length,\n ),\n );\n editor.focus();\n}\n\n/** Toggle a line prefix (`# `, `> `, `- `, `1. `) on every selected line. */\nexport function toggleLinePrefix(editor: MonacoCodeEditor, prefix: string): void {\n const model = editor.getModel();\n const selection = editor.getSelection();\n if (!model || !selection) return;\n\n const edits: monaco.editor.IIdentifiedSingleEditOperation[] = [];\n const allPrefixed = (() => {\n for (let line = selection.startLineNumber; line <= selection.endLineNumber; line++) {\n if (!model.getLineContent(line).startsWith(prefix)) return false;\n }\n return true;\n })();\n\n for (let line = selection.startLineNumber; line <= selection.endLineNumber; line++) {\n const content = model.getLineContent(line);\n if (allPrefixed) {\n edits.push({\n range: new monaco.Range(line, 1, line, prefix.length + 1),\n text: \"\",\n });\n } else if (!content.startsWith(prefix)) {\n edits.push({ range: new monaco.Range(line, 1, line, 1), text: prefix });\n }\n }\n editor.executeEdits(\"markdown-toolbar\", edits);\n editor.focus();\n}\n\n/** Insert `[selection](url)` (or a placeholder link). */\nexport function insertLink(editor: MonacoCodeEditor): void {\n const model = editor.getModel();\n const selection = editor.getSelection();\n if (!model || !selection) return;\n const label = model.getValueInRange(selection) || \"label\";\n editor.executeEdits(\"markdown-toolbar\", [\n { range: selection, text: `[${label}](https://)`, forceMoveMarkers: true },\n ]);\n editor.focus();\n}\n\n/** Insert a horizontal rule on its own line below the cursor. */\nexport function insertHorizontalRule(editor: MonacoCodeEditor): void {\n const selection = editor.getSelection();\n if (!selection) return;\n const line = selection.endLineNumber;\n const col = editor.getModel()?.getLineMaxColumn(line) ?? 1;\n editor.executeEdits(\"markdown-toolbar\", [\n { range: new monaco.Range(line, col, line, col), text: `\\n\\n---\\n`, forceMoveMarkers: true },\n ]);\n editor.focus();\n}\n\n/** Insert a brand directive block at the cursor (e.g. card/callout/metric/timeline). */\nexport function insertDirective(editor: MonacoCodeEditor, snippet: string): void {\n const selection = editor.getSelection();\n if (!selection) return;\n const line = selection.endLineNumber;\n const col = editor.getModel()?.getLineMaxColumn(line) ?? 1;\n editor.executeEdits(\"markdown-toolbar\", [\n {\n range: new monaco.Range(line, col, line, col),\n text: `\\n\\n${snippet}\\n`,\n forceMoveMarkers: true,\n },\n ]);\n editor.focus();\n}\n","\"use client\";\n\n/**\n * MarkdownWorkspace — the hybrid markdown authoring surface for the Workbench.\n *\n * One markdown value, three modes (a @elabs-ai/components-ui ToggleGroup):\n * - \"source\" : Monaco CodeEditor(markdown) + the MarkdownToolbar\n * - \"wysiwyg\" : the Milkdown MarkdownEditor (direct manipulation)\n * - \"split\" : source ↔ the branded MarkdownPreview (drag-resizable)\n *\n * The value is shared across modes, so switching is lossless. Controlled\n * (`value`/`onChange`) or uncontrolled (`defaultValue`); same for `mode`.\n */\nimport {\n ResizableHandle,\n ResizablePanel,\n ResizablePanelGroup,\n Toggle,\n ToggleGroup,\n ToggleGroupItem,\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n useLocale,\n} from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { Columns2, Eye, Focus, SquareCode } from \"lucide-react\";\nimport {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type HTMLAttributes,\n type ReactNode,\n} from \"react\";\n\nimport { attachCalcMonaco } from \"../calc-block/calc-editor-monaco\";\nimport type { CalcEditorHooks } from \"../calc-block/types\";\nimport { CodeEditor, type EditorAction, type MonacoCodeEditor } from \"../code-editor\";\nimport { attachCompletionsMonaco } from \"../lib/editor-completions-monaco\";\nimport type { EditorCompletionProvider } from \"../lib/editor-completions\";\nimport {\n monacoContentAccess,\n type EditorContentAccess,\n type EditorSelection,\n} from \"../lib/editor-content-access\";\nimport { parseFrontmatter } from \"../lib/markdown/frontmatter\";\nimport { mergeNormalizedEdit } from \"../lib/markdown/merge\";\nimport { MarkdownEditor, type MarkdownEditorHandle, type EmbedAssetFn } from \"../markdown-editor\";\nimport { parseMarkdownOutline } from \"../markdown-outline\";\nimport { BRAND_SLASH_COMMANDS, type SlashCommand } from \"../markdown-editor/slash\";\n// MonacoSlashMenu + parseShortcut are imported from their files (NOT the slash\n// barrel), which pull the Monaco runtime — the workspace already does too. Keeps\n// the Milkdown-facing slash barrel Monaco-free. The pure `shortcut.ts` holds the\n// default; `shortcut-monaco.ts` holds the Monaco-keybinding parser.\nimport { MonacoSlashMenu } from \"../markdown-editor/slash/monaco-slash-menu\";\nimport {\n slashTriggerRange,\n type SlashTriggerRange,\n} from \"../markdown-editor/slash/source-slash-trigger\";\nimport { DEFAULT_SLASH_SHORTCUT } from \"../markdown-editor/slash/shortcut\";\nimport { parseShortcut } from \"../markdown-editor/slash/shortcut-monaco\";\nimport { MarkdownPreview } from \"../markdown-preview\";\nimport { MarkdownToolbar } from \"../markdown-toolbar\";\nimport { topLevelBlockOf, typewriterDelta } from \"./focus-writing\";\n\nexport type MarkdownWorkspaceMode = \"source\" | \"wysiwyg\" | \"split\";\n\n/**\n * Imperative handle exposed via `MarkdownWorkspace`'s `ref` (#273, DECISION A).\n *\n * Migration note: the forwarded ref type changed from `HTMLDivElement` to this\n * handle. Replace any `ref.current` DOM access with `ref.current?.getElement()`.\n *\n * Extends {@link EditorContentAccess} — all AI content-access methods delegate to\n * the active engine: Monaco (source/split) or the Milkdown WYSIWYG handle.\n *\n * **`onSelectionChange` caveat:** the subscription is scoped to the engine active at\n * call time. A mode switch (source ↔ wysiwyg) does NOT auto-rebind the listener —\n * re-subscribe from an effect whose deps include the mode. A self-rebinding v2 is a\n * noted future enhancement, out of v1 scope.\n */\nexport interface MarkdownWorkspaceHandle extends EditorContentAccess {\n /**\n * Scroll the active editor so FULL-SOURCE 1-based `line` is visible (Monaco\n * coordinates). No-op (never throws) while the engine is booting or `line` is\n * out of range. In WYSIWYG it is best-effort: resolves the nearest preceding\n * heading via `parseMarkdownOutline` + `fmOffset`, then delegates to\n * `scrollToHeading`. No-op if no preceding heading found.\n */\n revealLine(line: number, opts?: { center?: boolean }): void;\n /**\n * Scroll to a heading by its outline slug (same slugs as `DocumentOutline` /\n * `useMarkdownOutline` / `parseMarkdownOutline`). In Source/Split mode\n * resolves the line via `parseMarkdownOutline` then calls `revealLine`. In\n * WYSIWYG delegates to the `MarkdownEditorHandle.scrollToHeading`.\n */\n scrollToHeading(slug: string): void;\n /**\n * The live Monaco source editor instance, or `null` when not mounted or when\n * the active mode is `\"wysiwyg\"` (source pane not rendered).\n */\n getEditor(): MonacoCodeEditor | null;\n /**\n * The workspace root DOM element. Preserves the old `HTMLDivElement` ref\n * access that existed before DECISION A (ref type change in #273).\n */\n getElement(): HTMLDivElement | null;\n}\n\nexport interface MarkdownWorkspaceProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n \"onChange\" | \"defaultValue\"\n> {\n value?: string;\n defaultValue?: string;\n onChange?: (markdown: string) => void;\n mode?: MarkdownWorkspaceMode;\n defaultMode?: MarkdownWorkspaceMode;\n onModeChange?: (mode: MarkdownWorkspaceMode) => void;\n /**\n * Start with FOCUS WRITING on (wysiwyg mode): typewriter scrolling keeps\n * the caret vertically centered and inactive paragraphs dim. Toggleable in\n * the editor's mode row.\n */\n defaultFocusWriting?: boolean;\n /**\n * The `/` command menu in the WYSIWYG (preview-edit) pane AND the Monaco source\n * pane. `true` (default) uses the built-in brand commands; pass a config to\n * extend/replace them, or `false` to disable. Forwarded to {@link MarkdownEditor}.\n *\n * `shortcut` (default `\"Mod-Shift-O\"`) opens the menu at the caret in BOTH panes —\n * in the WYSIWYG pane via the ProseMirror plugin's `handleKeyDown`, and in the\n * source/split pane via a `CodeEditor` action (no `/` is inserted into the\n * doc). (#271)\n */\n slashMenu?: boolean | { commands?: SlashCommand[]; trigger?: string; shortcut?: string };\n /**\n * Customize the source / split toolbar's **Insert** menu (A4). Defaults to the\n * same commands as the WYSIWYG slash menu (so `/calc`, `/iterate`, `/pivot` and\n * any consumer commands are insertable in source mode too). Only commands with\n * a `snippet` appear; pass your own list to override.\n */\n insertCommands?: SlashCommand[];\n /**\n * Opt-in calc authoring inside ```calc fences (off by default). Wired to BOTH\n * surfaces: the Monaco source pane (highlight + autocomplete + result inlays)\n * and the WYSIWYG pane (highlight + result inlays). Supply the consumer's\n * `tokenize` / `evaluate` / `complete` hooks; the library bundles no calc engine.\n */\n calc?: CalcEditorHooks;\n /**\n * Declarative completion providers (#283) — e.g. `[[wikilink]]` autocomplete.\n * Off by default; mirrors the `slashMenu`/`calc` opt-in pattern. The library\n * owns the Monaco `registerCompletionItemProvider` registration lifecycle\n * (registered once, refcounted across mounted workspaces, disposed with the\n * last one — see `lib/editor-completions-monaco.ts`) for the Source/Split\n * panes, and mirrors providers into the WYSIWYG pane via `MarkdownEditor`'s\n * `completions` prop (a deliberately minimal mirror — see\n * `markdown-editor/completions/completions-prose.ts` for the exact gaps).\n * Zero `monaco-editor` imports needed in consumer code.\n */\n completions?: EditorCompletionProvider[];\n /**\n * Host-provided callback for image paste/drop embedding in the WYSIWYG pane.\n * Forwarded to {@link MarkdownEditor}. See `MarkdownEditorProps.onEmbedAsset`\n * for the full contract.\n */\n onEmbedAsset?: EmbedAssetFn;\n /**\n * Show the built-in \"Focus writing\" toggle in the WYSIWYG (preview-edit)\n * toolbar row. `false` HIDES and DISABLES it (no keyboard path) and forces\n * focus-writing OFF. `undefined`/`true` keep current behavior. The INITIAL\n * on/off state still comes from `defaultFocusWriting`. (#270)\n */\n focusWriting?: boolean;\n /**\n * Show the built-in Source / Split / Preview-edit mode switch. `false` hides\n * it in both toolbar branches so the host owns the view switch (controlled\n * `mode`/`onModeChange` still drive the panes). Default `true`. (#272)\n */\n modeSwitch?: boolean;\n /**\n * Host-supplied controls rendered in the toolbar's trailing slot (where the\n * built-in mode switch sits). Use with `modeSwitch={false}` to supply your\n * own switch / actions. (#272)\n */\n toolbarActions?: ReactNode;\n}\n\nconst MODES: { value: MarkdownWorkspaceMode; label: string; icon: typeof Eye }[] = [\n { value: \"source\", label: \"Source\", icon: SquareCode },\n { value: \"split\", label: \"Split\", icon: Columns2 },\n { value: \"wysiwyg\", label: \"Preview-edit\", icon: Eye },\n];\n\nexport const MarkdownWorkspace = forwardRef<MarkdownWorkspaceHandle, MarkdownWorkspaceProps>(\n function MarkdownWorkspace(\n {\n value,\n defaultValue,\n onChange,\n mode,\n defaultMode = \"split\",\n onModeChange,\n defaultFocusWriting = false,\n focusWriting,\n modeSwitch = true,\n toolbarActions,\n slashMenu = true,\n insertCommands,\n calc,\n completions,\n onEmbedAsset,\n className,\n ...props\n },\n ref,\n ) {\n const { t } = useLocale();\n // The source/split Insert menu defaults to the SAME commands as the WYSIWYG\n // slash menu, so both surfaces insert the same blocks (A4).\n const slashCommandList =\n typeof slashMenu === \"object\" && slashMenu.commands\n ? slashMenu.commands\n : BRAND_SLASH_COMMANDS;\n const toolbarInsertCommands = insertCommands ?? slashCommandList;\n const isControlled = value !== undefined;\n const [internalValue, setInternalValue] = useState(value ?? defaultValue ?? \"\");\n const markdown = isControlled ? value : internalValue;\n\n const [internalMode, setInternalMode] = useState<MarkdownWorkspaceMode>(defaultMode);\n const activeMode = mode ?? internalMode;\n\n const [monaco, setMonaco] = useState<MonacoCodeEditor | null>(null);\n // Stable set of onSelectionChange listeners (engine-agnostic). The handle adds\n // here; a binding effect forwards the active engine's selection events. (#AI)\n const [selectionListeners] = useState(() => new Set<(sel: EditorSelection) => void>());\n\n /* ------------------------- calc authoring (#220) ------------------------ */\n // Read the calc hooks through a ref so a fresh `calc` object identity never\n // re-attaches the Monaco layer; only toggling the feature on/off does.\n const calcRef = useRef<CalcEditorHooks | undefined>(calc);\n calcRef.current = calc;\n const calcEnabled = calc != null;\n\n useEffect(() => {\n if (!monaco || !calcEnabled) return;\n // Let calc completions surface as you type inside the fence (markdown\n // otherwise suppresses quick suggestions outside comments/strings).\n monaco.updateOptions({\n quickSuggestions: { other: true, comments: false, strings: false },\n });\n return attachCalcMonaco(monaco, () => calcRef.current);\n }, [monaco, calcEnabled]);\n\n /* --------------------- completion providers (#283) ----------------------- */\n // Read through a ref so a fresh `completions` array identity (a re-render)\n // never re-attaches — the Monaco lifecycle (`attachCompletionsMonaco`) reads\n // the LIVE list on every suggestion request; only mount/unmount and\n // enabling/disabling the feature touch the effect.\n const completionsRef = useRef<EditorCompletionProvider[] | undefined>(completions);\n completionsRef.current = completions;\n const completionsEnabled = completions != null;\n\n useEffect(() => {\n if (!monaco || !completionsEnabled) return;\n return attachCompletionsMonaco(monaco, () => completionsRef.current);\n }, [monaco, completionsEnabled]);\n\n // The source CodeEditor unmounts when the active mode becomes WYSIWYG, but its\n // `onMount` only fires on (re)mount — nothing clears the held instance. Drop it\n // here so `getEditor()` honors its documented `null` contract in WYSIWYG and\n // `revealLine`/`scrollToHeading` delegate to the WYSIWYG handle instead of\n // acting on a disposed Monaco editor. (#271 review)\n useEffect(() => {\n if (activeMode === \"wysiwyg\") setMonaco(null);\n }, [activeMode]);\n\n /* --------- source-pane slash menu (#271) -------------------------------- */\n const slashEnabled = slashMenu !== false;\n // Honor an explicitly disabled shortcut (`shortcut: \"\"` / `shortcut: undefined`)\n // the SAME way the WYSIWYG plugin does (`\"shortcut\" in options`), so both panes\n // agree: only fall back to the default when the key is absent entirely. (#271 review)\n const shortcut =\n typeof slashMenu === \"object\" && \"shortcut\" in slashMenu\n ? slashMenu.shortcut\n : DEFAULT_SLASH_SHORTCUT;\n\n const [sourceSlashOpen, setSourceSlashOpen] = useState(false);\n // The model range of a typed `/` when the menu was opened by typing (not the\n // hotkey). null for the hotkey path. Drives MonacoSlashMenu's `triggerRange`:\n // on select the `/` is replaced by the block; on cancel it is removed.\n const [typedTrigger, setTypedTrigger] = useState<SlashTriggerRange | null>(null);\n\n // Close handler: clear the typed-trigger whenever the menu closes so a later\n // hotkey-open doesn't inherit a stale range.\n const handleSourceSlashOpenChange = (next: boolean) => {\n setSourceSlashOpen(next);\n if (!next) setTypedTrigger(null);\n };\n\n // Typing `/` at a line start (or after whitespace) opens the menu in the\n // source pane — the conflict-free trigger that mirrors the WYSIWYG `/`. We\n // watch model edits for a lone `/` insertion at a valid spot; our own\n // insert/cancel edits are multi-char or empty, so they never re-trigger.\n useEffect(() => {\n if (!monaco || !slashEnabled) return;\n const sub = monaco.onDidChangeModelContent((e) => {\n if (sourceSlashOpen || e.changes.length !== 1) return;\n const change = e.changes[0];\n if (!change || change.text !== \"/\") return;\n const model = monaco.getModel();\n if (!model) return;\n const line = change.range.startLineNumber;\n const range = slashTriggerRange(line, model.getLineContent(line), change.range.startColumn);\n if (!range) return;\n setTypedTrigger(range);\n setSourceSlashOpen(true);\n });\n return () => sub.dispose();\n }, [monaco, slashEnabled, sourceSlashOpen]);\n\n // A command works in the source pane when it has a text snippet OR an\n // explicit source-pane handler (#299) — a run-only command whose ONLY\n // handler is Milkdown's `run` (needs a Ctx unavailable in Monaco) is\n // excluded; `runInSource` is exactly the escape hatch for that case.\n const sourceCommands = useMemo(\n () =>\n slashCommandList.filter((c) => c.snippet != null || typeof c.runInSource === \"function\"),\n [slashCommandList],\n );\n\n // A Layer-1 CodeEditor action that opens the source slash popup when fired\n // (via its keybinding or the command palette). All KeyMod/KeyCode references\n // live inside parseShortcut (slash/shortcut.ts) — NEVER reference a bare\n // monaco.KeyMod here, because `monaco` is a state variable (the editor\n // instance), not the namespace.\n const sourceActions = useMemo<EditorAction[]>(\n () =>\n slashEnabled && shortcut\n ? [\n {\n id: \"brand.openSlashMenu\",\n label: \"Insert block…\",\n keybindings: [parseShortcut(shortcut)],\n // Hotkey open inserts at the caret (no typed `/` to replace).\n run: () => {\n setTypedTrigger(null);\n setSourceSlashOpen(true);\n },\n },\n ]\n : [],\n [slashEnabled, shortcut],\n );\n\n /* ------------------- split-view scroll synchronization ------------------ */\n // Line-accurate (not percentage) sync: preview blocks carry\n // `data-sourcepos` in frontmatter-STRIPPED coordinates; Monaco lines are\n // full-source — bridge with the stripped-line offset.\n const previewPaneRef = useRef<HTMLDivElement | null>(null);\n const scrollLock = useRef<\"editor\" | \"preview\" | null>(null);\n const lockTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const fmOffset = useMemo(() => {\n try {\n const body = parseFrontmatter(markdown).content;\n return markdown.split(\"\\n\").length - body.split(\"\\n\").length;\n } catch {\n return 0;\n }\n }, [markdown]);\n\n const lock = (owner: \"editor\" | \"preview\") => {\n scrollLock.current = owner;\n if (lockTimer.current) clearTimeout(lockTimer.current);\n lockTimer.current = setTimeout(() => {\n scrollLock.current = null;\n }, 150);\n };\n\n // Editor → preview.\n useEffect(() => {\n if (!monaco || activeMode !== \"split\") return;\n const disposable = monaco.onDidScrollChange(() => {\n if (scrollLock.current === \"preview\") return;\n const range = monaco.getVisibleRanges()[0];\n const host = previewPaneRef.current;\n if (!range || !host) return;\n const line = range.startLineNumber - fmOffset;\n let target: HTMLElement | null = null;\n for (const el of host.querySelectorAll<HTMLElement>(\"[data-sourcepos]\")) {\n const end = Number(el.dataset.sourcepos?.split(\":\")[1]);\n if (end >= line) {\n target = el;\n break;\n }\n }\n if (!target) return;\n lock(\"editor\");\n host.scrollTop =\n target.getBoundingClientRect().top -\n host.getBoundingClientRect().top +\n host.scrollTop -\n 12;\n });\n return () => disposable.dispose();\n }, [monaco, activeMode, fmOffset]);\n\n // Preview → editor.\n const onPreviewScroll = () => {\n if (scrollLock.current === \"editor\" || !monaco || activeMode !== \"split\") return;\n const host = previewPaneRef.current;\n if (!host) return;\n const hostTop = host.getBoundingClientRect().top;\n for (const el of host.querySelectorAll<HTMLElement>(\"[data-sourcepos]\")) {\n if (el.getBoundingClientRect().bottom >= hostTop) {\n const start = Number(el.dataset.sourcepos?.split(\":\")[0]);\n if (!Number.isNaN(start)) {\n lock(\"preview\");\n monaco.setScrollTop(monaco.getTopForLineNumber(Math.max(1, start + fmOffset)));\n }\n return;\n }\n }\n };\n\n const setMarkdown = (next: string) => {\n if (!isControlled) setInternalValue(next);\n onChange?.(next);\n };\n\n /* ------------------ lossless WYSIWYG editing (WI-1) ------------------ */\n // Milkdown re-serializes the WHOLE document on every edit, normalizing\n // formatting the user never touched — a one-line edit became a whole-file\n // diff. Capture the editor's pre-edit serialization as a BASELINE and\n // merge each emission back onto the byte-exact original: unedited blocks\n // keep their original bytes.\n const wysiwygRef = useRef<MarkdownEditorHandle | null>(null);\n const wysiwygBase = useRef<{ original: string; baseline: string | null } | null>(null);\n\n useEffect(() => {\n if (activeMode !== \"wysiwyg\") {\n wysiwygBase.current = null;\n return;\n }\n // Capture at mode entry; the editor is uncontrolled while in wysiwyg,\n // so the workspace buffer is the only writer.\n const original = markdown;\n wysiwygBase.current = { original, baseline: null };\n const poll = setInterval(() => {\n const base = wysiwygBase.current;\n if (!base || base.baseline !== null) {\n clearInterval(poll);\n return;\n }\n const s = wysiwygRef.current?.serialized();\n if (s != null) {\n base.baseline = s;\n clearInterval(poll);\n }\n }, 50);\n const stop = setTimeout(() => clearInterval(poll), 5000);\n return () => {\n clearInterval(poll);\n clearTimeout(stop);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- capture markdown at ENTRY only\n }, [activeMode]);\n\n const onWysiwygChange = (emitted: string) => {\n const base = wysiwygBase.current;\n // Baseline captured before the first keystroke → merge; otherwise fall\n // back to the raw emission (rare boot race — old behavior, never worse).\n const next =\n base && base.baseline !== null\n ? mergeNormalizedEdit(base.original, base.baseline, emitted)\n : emitted;\n setMarkdown(next);\n };\n\n /* ---------------- focus writing (Ulysses Phase A, wysiwyg) ---------------- */\n // Typewriter scrolling + paragraph focus, driven from OUTSIDE the engine:\n // selectionchange marks the active top-level block (CSS dims the rest);\n // right after typing, the pane re-centers the caret into a middle band.\n const focusWritingEnabled = focusWriting !== false;\n const [focusWritingOn, setFocusWritingOn] = useState(\n focusWritingEnabled ? defaultFocusWriting : false,\n );\n const wysiwygPaneRef = useRef<HTMLDivElement | null>(null);\n const lastInputAt = useRef(0);\n\n useEffect(() => {\n if (!(focusWritingEnabled && focusWritingOn && activeMode === \"wysiwyg\")) return;\n const pane = wysiwygPaneRef.current;\n if (!pane) return;\n let active: Element | null = null;\n\n const onSelectionChange = () => {\n const root = pane.querySelector<HTMLElement>(\".ProseMirror\");\n if (!root) return;\n const sel = document.getSelection();\n const node = sel?.anchorNode ?? null;\n if (!node || !root.contains(node)) return;\n const block = topLevelBlockOf(root, node);\n if (block !== active) {\n active?.classList.remove(\"wb-fw-active\");\n block?.classList.add(\"wb-fw-active\");\n active = block;\n }\n // Re-center only right after typing — a mouse click must not yank\n // the viewport (Ulysses recenters while WRITING, not while aiming).\n if (Date.now() - lastInputAt.current < 200 && sel && sel.rangeCount > 0) {\n const range = sel.getRangeAt(0).getBoundingClientRect();\n const caret = range.height > 0 ? range : (active?.getBoundingClientRect() ?? range);\n const host = pane.getBoundingClientRect();\n const delta = typewriterDelta(caret.top, caret.height, host.top, host.height);\n if (delta !== 0) pane.scrollTop += delta;\n }\n };\n const onInput = () => {\n lastInputAt.current = Date.now();\n };\n\n document.addEventListener(\"selectionchange\", onSelectionChange);\n pane.addEventListener(\"input\", onInput, true);\n onSelectionChange();\n return () => {\n document.removeEventListener(\"selectionchange\", onSelectionChange);\n pane.removeEventListener(\"input\", onInput, true);\n active?.classList.remove(\"wb-fw-active\");\n };\n }, [focusWritingEnabled, focusWritingOn, activeMode]);\n\n /* ------------------- imperative handle (#273, DECISION A) --------------- */\n // The forwarded ref is now a MarkdownWorkspaceHandle (not the div).\n // The root <div> gets rootRef; getElement() returns rootRef.current.\n const rootRef = useRef<HTMLDivElement | null>(null);\n\n useImperativeHandle(\n ref,\n () => {\n const revealLine = (n: number, opts?: { center?: boolean }) => {\n if (monaco) {\n // Source / Split: Monaco exact-line reveal.\n const max = monaco.getModel()?.getLineCount() ?? 0;\n if (n < 1 || n > max) return;\n if (opts?.center === false) {\n monaco.revealLine(n);\n } else {\n monaco.revealLineInCenter(n);\n }\n } else {\n // WYSIWYG: best-effort — find the nearest preceding heading whose\n // (stripped) line + fmOffset ≤ n, then delegate to scrollToHeading.\n const items = parseMarkdownOutline(markdown);\n // items.line is frontmatter-stripped (1-based); full-source = line + fmOffset\n const preceding = items.filter((item) => item.line + fmOffset <= n).at(-1);\n if (!preceding) return;\n wysiwygRef.current?.scrollToHeading(preceding.id);\n }\n };\n\n const scrollToHeading = (slug: string) => {\n if (monaco) {\n // Source / Split: resolve stripped line via outline, lift to full-source.\n const item = parseMarkdownOutline(markdown).find((i) => i.id === slug);\n if (!item) return;\n revealLine(item.line + fmOffset, { center: true });\n } else {\n // WYSIWYG: delegate to the Milkdown handle.\n wysiwygRef.current?.scrollToHeading(slug);\n }\n };\n\n // Content-access delegation: monaco (source/split) → monacoContentAccess;\n // wysiwyg → the MarkdownEditorHandle (which now IS an EditorContentAccess).\n // If both are null (booting), fall back to best-effort no-ops (never throw).\n const getAccess = (): EditorContentAccess | null => {\n if (monaco) return monacoContentAccess(monaco);\n if (wysiwygRef.current) return wysiwygRef.current;\n return null;\n };\n\n return {\n revealLine,\n scrollToHeading,\n getEditor: () => monaco,\n getElement: () => rootRef.current,\n\n // EditorContentAccess — read/write delegate to the active engine at call\n // time (the AI acts after mount, so a call-time snapshot is correct here).\n getText: () => getAccess()?.getText() ?? \"\",\n getSelection: () => getAccess()?.getSelection() ?? { text: \"\", empty: true },\n replaceSelection: (text: string) => getAccess()?.replaceSelection(text),\n insertAtCursor: (text: string) => getAccess()?.insertAtCursor(text),\n focus: () => getAccess()?.focus(),\n // onSelectionChange uses the STABLE listener set (not getAccess()) so a\n // subscribe-in-mount-effect survives the editor's async mount + mode\n // switches; the binding effect below forwards the active engine's events.\n onSelectionChange: (listener) => {\n selectionListeners.add(listener);\n return () => selectionListeners.delete(listener);\n },\n };\n },\n // Re-create when the things the methods close over change.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [monaco, markdown, fmOffset, activeMode, selectionListeners],\n );\n\n // Forward the ACTIVE engine's selection changes into the stable listener set,\n // re-binding when the engine (monaco/wysiwyg) or mode changes. This is what\n // makes the handle's onSelectionChange robust to the editor's async mount.\n useEffect(() => {\n let unsub: (() => void) | undefined;\n if (monaco) {\n unsub = monacoContentAccess(monaco).onSelectionChange((sel) =>\n selectionListeners.forEach((l) => l(sel)),\n );\n } else if (activeMode === \"wysiwyg\" && wysiwygRef.current) {\n unsub = wysiwygRef.current.onSelectionChange((sel) =>\n selectionListeners.forEach((l) => l(sel)),\n );\n }\n return () => unsub?.();\n }, [monaco, activeMode, selectionListeners]);\n\n const setMode = (next: string) => {\n if (next !== \"source\" && next !== \"split\" && next !== \"wysiwyg\") return;\n if (!mode) setInternalMode(next);\n onModeChange?.(next);\n };\n\n const modeToggle = (\n <TooltipProvider delayDuration={300}>\n {/* Segmented mode switch — same recessed-track / raised-segment\n grammar as every other mode control (Tabs, Read/Write). */}\n <ToggleGroup\n type=\"single\"\n value={activeMode}\n onValueChange={setMode}\n variant=\"segmented\"\n size=\"sm\"\n className=\"rounded-md p-0.5\"\n >\n {MODES.map(({ value: m, label, icon: Icon }) => (\n <Tooltip key={m}>\n <TooltipTrigger asChild>\n <ToggleGroupItem\n value={m}\n aria-label={label}\n className=\"h-6 min-w-7 rounded-[5px] px-2\"\n >\n <Icon className=\"size-4\" />\n </ToggleGroupItem>\n </TooltipTrigger>\n <TooltipContent>{label}</TooltipContent>\n </Tooltip>\n ))}\n </ToggleGroup>\n </TooltipProvider>\n );\n\n const trailing = (\n <>\n {modeSwitch ? modeToggle : null}\n {toolbarActions}\n </>\n );\n\n const sourcePane = (\n <CodeEditor\n language=\"markdown\"\n value={markdown}\n onChange={setMarkdown}\n actions={sourceActions}\n onMount={(editor) => {\n // Markdown is prose: soft-wrap so the source pane lays out like the\n // preview (line-based scroll sync stays accurate either way, but\n // matching layouts keep the two panes visually in step).\n editor.updateOptions({ wordWrap: \"on\" });\n setMonaco(editor);\n }}\n />\n );\n\n return (\n <div\n ref={rootRef}\n data-testid=\"markdown-workspace\"\n className={cn(\"flex h-full min-h-0 flex-col overflow-hidden\", className)}\n {...props}\n >\n {activeMode === \"wysiwyg\" ? (\n <div className=\"flex h-10 shrink-0 items-center justify-end gap-2 border-b border-border bg-surface px-2\">\n {focusWritingEnabled ? (\n <TooltipProvider delayDuration={300}>\n <Tooltip>\n <TooltipTrigger asChild>\n <Toggle\n size=\"sm\"\n pressed={focusWritingOn}\n onPressedChange={setFocusWritingOn}\n aria-label={t(\"editor.markdownWorkspace.focusWriting\")}\n className=\"h-6 gap-1.5 px-2 text-caption\"\n >\n <Focus className=\"size-3.5\" aria-hidden=\"true\" />{\" \"}\n {t(\"editor.markdownWorkspace.focus\")}\n </Toggle>\n </TooltipTrigger>\n <TooltipContent>{t(\"editor.markdownWorkspace.focusWritingHint\")}</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n ) : null}\n {trailing}\n </div>\n ) : (\n <MarkdownToolbar\n editor={monaco}\n actions={trailing}\n insertCommands={toolbarInsertCommands}\n />\n )}\n\n <div className=\"min-h-0 flex-1\">\n {activeMode === \"source\" ? sourcePane : null}\n\n {activeMode === \"wysiwyg\" ? (\n <div\n ref={wysiwygPaneRef}\n data-focus-writing={focusWritingEnabled && focusWritingOn ? \"\" : undefined}\n className=\"h-full overflow-auto p-4\"\n >\n {/* UNCONTROLLED while in wysiwyg: feeding the merged buffer back\n would replaceAll on every keystroke (cursor loss + echo\n loops). The buffer receives merged text via onWysiwygChange;\n mode switches remount the editor from the buffer. */}\n <MarkdownEditor\n ref={wysiwygRef}\n defaultValue={markdown}\n onChange={onWysiwygChange}\n slashMenu={slashMenu}\n calc={calc}\n completions={completions}\n onEmbedAsset={onEmbedAsset}\n className=\"border-0\"\n />\n </div>\n ) : null}\n\n {activeMode === \"split\" ? (\n <ResizablePanelGroup direction=\"horizontal\">\n <ResizablePanel defaultSize={50} minSize={25}>\n {sourcePane}\n </ResizablePanel>\n <ResizableHandle withHandle />\n <ResizablePanel defaultSize={50} minSize={25}>\n <div\n ref={previewPaneRef}\n onScroll={onPreviewScroll}\n className=\"h-full overflow-auto p-5\"\n >\n <MarkdownPreview>{markdown}</MarkdownPreview>\n </div>\n </ResizablePanel>\n </ResizablePanelGroup>\n ) : null}\n </div>\n\n {/* Source-pane slash popup (#271): shown when the Layer-1 action fires\n in source or split mode. Uses fixed positioning anchored to the caret\n via getScrolledVisiblePosition, so it works in both layouts. */}\n {monaco && (activeMode === \"source\" || activeMode === \"split\") && slashEnabled ? (\n <MonacoSlashMenu\n editor={monaco}\n commands={sourceCommands}\n open={sourceSlashOpen}\n onOpenChange={handleSourceSlashOpenChange}\n triggerRange={typedTrigger}\n />\n ) : null}\n </div>\n );\n },\n);\n","\"use client\";\n\n/**\n * Monaco calc layer (#220) — live highlighting + autocomplete + result inlays for\n * ```calc fences inside a markdown Monaco model.\n *\n * - HIGHLIGHT is a decoration pass (not a Monarch language): the model is markdown,\n * so we tokenize each calc fence body via the consumer's `tokenize` hook and apply\n * `inlineClassName` decorations colored from the `--calc-*` tokens (calc-editor.css).\n * - COMPLETIONS come from a markdown `CompletionItemProvider` scoped to calc fences,\n * delegating to the consumer's `complete` hook.\n * - INLAYS are Monaco inlay hints (themed via the theme bridge's `editorInlayHint.*`\n * colors, so they re-apply on theme change), built from the consumer's `evaluate`.\n *\n * The providers register ONCE per language and look the active hooks up per-model via\n * a registry, so any number of markdown editors can be wired independently. All the\n * column/position math lives in `calc-editor.ts` (engine-neutral + unit-tested);\n * this module only maps those specs to Monaco objects and owns the lifecycle.\n */\nimport * as monaco from \"monaco-editor\";\n\nimport \"./calc-editor.css\";\n\nimport {\n calcDecorationSpecs,\n calcInlaySpecs,\n findCalcFences,\n identifierPrefix,\n type CalcFence,\n} from \"./calc-editor\";\nimport type { CalcCompletionKind, CalcEditorHooks } from \"./types\";\n\n/** Resolver of the latest hooks for a model (read through a ref so prop-identity churn is free). */\ntype HooksGetter = () => CalcEditorHooks | undefined;\n\n/** Per-model hook registry the global providers consult. */\nconst REGISTRY = new Map<monaco.editor.ITextModel, HooksGetter>();\n\nlet providersRegistered = false;\nlet inlayEmitter: monaco.Emitter<void> | null = null;\n\n/** Read a fence body's EOL-free line texts straight from the model (CRLF-safe). */\nfunction bodyLineTexts(model: monaco.editor.ITextModel, fence: CalcFence): string[] {\n const out: string[] = [];\n for (let ln = fence.bodyStartLine; ln <= fence.bodyEndLine; ln++) {\n out.push(model.getLineContent(ln));\n }\n return out;\n}\n\n/** All ```calc fences in the model, scanned from LF-normalized text. */\nfunction modelFences(model: monaco.editor.ITextModel): CalcFence[] {\n return findCalcFences(model.getValue(monaco.editor.EndOfLinePreference.LF));\n}\n\n/** Highlight decorations for every calc fence in the model. */\nfunction buildDecorations(\n model: monaco.editor.ITextModel,\n hooks: CalcEditorHooks,\n): monaco.editor.IModelDeltaDecoration[] {\n const decorations: monaco.editor.IModelDeltaDecoration[] = [];\n for (const fence of modelFences(model)) {\n if (fence.bodyEndLine < fence.bodyStartLine) continue;\n const specs = calcDecorationSpecs(hooks, fence.bodyStartLine, bodyLineTexts(model, fence));\n for (const s of specs) {\n decorations.push({\n range: new monaco.Range(s.lineNumber, s.startColumn, s.lineNumber, s.endColumn),\n options: { inlineClassName: s.className },\n });\n }\n }\n return decorations;\n}\n\nconst COMPLETION_KIND: Record<CalcCompletionKind, () => monaco.languages.CompletionItemKind> = {\n variable: () => monaco.languages.CompletionItemKind.Variable,\n function: () => monaco.languages.CompletionItemKind.Function,\n unit: () => monaco.languages.CompletionItemKind.Unit,\n currency: () => monaco.languages.CompletionItemKind.Unit,\n constant: () => monaco.languages.CompletionItemKind.Constant,\n reference: () => monaco.languages.CompletionItemKind.Reference,\n keyword: () => monaco.languages.CompletionItemKind.Keyword,\n snippet: () => monaco.languages.CompletionItemKind.Snippet,\n};\n\nfunction mapCompletionKind(kind?: CalcCompletionKind): monaco.languages.CompletionItemKind {\n return (COMPLETION_KIND[kind ?? \"variable\"] ?? COMPLETION_KIND.variable)();\n}\n\n/** Register the per-language providers once (idempotent). */\nfunction ensureProviders(): void {\n if (providersRegistered) return;\n providersRegistered = true;\n inlayEmitter = new monaco.Emitter<void>();\n\n monaco.languages.registerInlayHintsProvider(\"markdown\", {\n onDidChangeInlayHints: inlayEmitter.event,\n provideInlayHints(model, range) {\n const empty = { hints: [] as monaco.languages.InlayHint[], dispose() {} };\n const hooks = REGISTRY.get(model)?.();\n if (!hooks?.evaluate) return empty;\n const hints: monaco.languages.InlayHint[] = [];\n for (const fence of modelFences(model)) {\n if (fence.bodyEndLine < fence.bodyStartLine) continue;\n if (\n fence.bodyEndLine < range.startLineNumber ||\n fence.bodyStartLine > range.endLineNumber\n ) {\n continue;\n }\n for (const inlay of calcInlaySpecs(\n hooks,\n fence.bodyStartLine,\n bodyLineTexts(model, fence),\n )) {\n hints.push({\n position: { lineNumber: inlay.lineNumber, column: inlay.column },\n label: inlay.text,\n kind: monaco.languages.InlayHintKind.Type,\n paddingLeft: true,\n });\n }\n }\n return { hints, dispose() {} };\n },\n });\n\n monaco.languages.registerCompletionItemProvider(\"markdown\", {\n provideCompletionItems(model, position) {\n const hooks = REGISTRY.get(model)?.();\n if (!hooks?.complete) return { suggestions: [] };\n const fence = modelFences(model).find(\n (f) => position.lineNumber >= f.bodyStartLine && position.lineNumber <= f.bodyEndLine,\n );\n if (!fence) return { suggestions: [] };\n const lines = bodyLineTexts(model, fence);\n const line = lines[position.lineNumber - fence.bodyStartLine] ?? \"\";\n const column = position.column - 1; // 0-based caret within the line\n const prefix = identifierPrefix(line, column);\n let completions;\n try {\n completions = hooks.complete({\n source: lines.join(\"\\n\"),\n line,\n lineNumber: position.lineNumber - fence.bodyStartLine + 1,\n column,\n prefix,\n });\n } catch {\n return { suggestions: [] };\n }\n const replace = new monaco.Range(\n position.lineNumber,\n position.column - prefix.length,\n position.lineNumber,\n position.column,\n );\n return {\n suggestions: completions.map((c) => ({\n label: c.label,\n insertText: c.insert,\n detail: c.detail,\n kind: mapCompletionKind(c.kind),\n range: replace,\n })),\n };\n },\n });\n}\n\n/**\n * Wire calc highlighting + completion + inlays onto a markdown Monaco editor.\n * `getHooks` is read fresh on each update, so changing the `calc` prop's identity\n * never forces a re-attach. Returns a disposer; call it on unmount / when `calc`\n * is removed.\n */\nexport function attachCalcMonaco(\n editor: monaco.editor.IStandaloneCodeEditor,\n getHooks: HooksGetter,\n): () => void {\n ensureProviders();\n const collection = editor.createDecorationsCollection();\n const subs: monaco.IDisposable[] = [];\n let model = editor.getModel();\n if (model) REGISTRY.set(model, getHooks);\n\n const refresh = () => {\n const current = editor.getModel();\n const hooks = getHooks();\n if (!current || !hooks) {\n collection.clear();\n return;\n }\n REGISTRY.set(current, getHooks);\n collection.set(buildDecorations(current, hooks));\n inlayEmitter?.fire();\n };\n\n refresh();\n subs.push(editor.onDidChangeModelContent(refresh));\n subs.push(\n editor.onDidChangeModel(() => {\n if (model) REGISTRY.delete(model);\n model = editor.getModel();\n refresh();\n }),\n );\n\n return () => {\n for (const s of subs) s.dispose();\n collection.clear();\n if (model) REGISTRY.delete(model);\n };\n}\n","/**\n * Line-level markdown diff → block annotations for `MarkdownPreview` (#L18).\n *\n * `computeMarkdownAnnotations(before, after)` diffs two markdown sources and\n * returns the annotation set the preview renders as a \"ghost diff\": added /\n * modified blocks get a wash + accent rail, pure deletions become a slim\n * \"removed here\" marker before the next surviving block.\n *\n * Lines are 1-based and refer to the AFTER source **including** any YAML\n * frontmatter — `MarkdownPreview` shifts them when it strips frontmatter, so\n * callers never have to think about the offset.\n *\n * The diff is a classic LCS (O(n·m) DP) — markdown documents are\n * authoring-sized. Inputs beyond {@link MAX_DIFF_LINES} lines fall back to an\n * empty annotation set (the UI simply shows no wash) instead of freezing.\n */\n\nexport type MarkdownAnnotationKind = \"added\" | \"modified\" | \"removed-before\";\n\nexport interface MarkdownAnnotation {\n kind: MarkdownAnnotationKind;\n /**\n * For `added`/`modified`: the 1-based inclusive line range in the AFTER\n * source. For `removed-before`: `startLine === endLine` is the line in the\n * AFTER source that now sits where the removed content used to be.\n */\n startLine: number;\n endLine: number;\n /** For `removed-before`: how many lines were removed. */\n removedCount?: number;\n}\n\n/** Above this many lines on either side the diff degrades to \"no annotations\". */\nexport const MAX_DIFF_LINES = 5000;\n\nconst splitLines = (s: string): string[] => s.split(\"\\n\");\n\n/**\n * LCS keep-table via dynamic programming. Returns pairs of kept (before-index,\n * after-index) in ascending order. Indices are 0-based.\n *\n * Exported for the normalization-aware merge (`merge.ts`) — not public API.\n */\nexport function lcsPairs(a: string[], b: string[]): [number, number][] {\n const n = a.length;\n const m = b.length;\n // dp rows as typed arrays to keep memory flat.\n const dp: Uint32Array[] = Array.from({ length: n + 1 }, () => new Uint32Array(m + 1));\n for (let i = n - 1; i >= 0; i--) {\n const row = dp[i]!;\n const next = dp[i + 1]!;\n for (let j = m - 1; j >= 0; j--) {\n row[j] = a[i] === b[j] ? next[j + 1]! + 1 : Math.max(next[j]!, row[j + 1]!);\n }\n }\n const pairs: [number, number][] = [];\n let i = 0;\n let j = 0;\n while (i < n && j < m) {\n if (a[i] === b[j]) {\n pairs.push([i, j]);\n i++;\n j++;\n } else if (dp[i + 1]![j]! >= dp[i]![j + 1]!) {\n i++;\n } else {\n j++;\n }\n }\n return pairs;\n}\n\n/**\n * Diff two markdown sources into preview annotations.\n *\n * Hunk semantics: a run of only-added lines → `added`; a run that replaces\n * removed lines → `modified`; a run of only-removed lines → `removed-before`\n * anchored on the first surviving AFTER line at-or-after the removal.\n */\nexport function computeMarkdownAnnotations(before: string, after: string): MarkdownAnnotation[] {\n if (before === after) return [];\n const a = splitLines(before);\n const b = splitLines(after);\n if (a.length > MAX_DIFF_LINES || b.length > MAX_DIFF_LINES) return [];\n\n const pairs = lcsPairs(a, b);\n const annotations: MarkdownAnnotation[] = [];\n\n let prevA = -1;\n let prevB = -1;\n // Sentinel pair past the end flushes the trailing hunk.\n const walk: [number, number][] = [...pairs, [a.length, b.length]];\n for (const [ai, bi] of walk) {\n const removed = ai - prevA - 1;\n const added = bi - prevB - 1;\n if (added > 0 && removed > 0) {\n annotations.push({ kind: \"modified\", startLine: prevB + 2, endLine: bi });\n } else if (added > 0) {\n annotations.push({ kind: \"added\", startLine: prevB + 2, endLine: bi });\n } else if (removed > 0) {\n // Anchor on the next surviving AFTER line (1-based); clamp into range.\n const anchor = Math.min(bi + 1, b.length);\n annotations.push({\n kind: \"removed-before\",\n startLine: anchor,\n endLine: anchor,\n removedCount: removed,\n });\n }\n prevA = ai;\n prevB = bi;\n }\n return mergeAdjacent(annotations);\n}\n\n/** Honest \"+a −r\" totals for an annotation set (commit churn, drift rows). */\nexport function summarizeAnnotations(annotations: MarkdownAnnotation[]): {\n added: number;\n removed: number;\n} {\n let added = 0;\n let removed = 0;\n for (const a of annotations) {\n const span = a.endLine - a.startLine + 1;\n if (a.kind === \"added\") added += span;\n else if (a.kind === \"modified\") {\n added += span;\n removed += span;\n } else if (a.kind === \"removed-before\") removed += a.removedCount ?? 1;\n }\n return { added, removed };\n}\n\n/** Merge touching/overlapping wash hunks of the same kind (keeps the DOM quiet). */\nfunction mergeAdjacent(annotations: MarkdownAnnotation[]): MarkdownAnnotation[] {\n const out: MarkdownAnnotation[] = [];\n for (const ann of annotations) {\n const last = out[out.length - 1];\n if (\n last &&\n last.kind !== \"removed-before\" &&\n last.kind === ann.kind &&\n ann.startLine <= last.endLine + 1\n ) {\n last.endLine = Math.max(last.endLine, ann.endLine);\n } else {\n out.push({ ...ann });\n }\n }\n return out;\n}\n\n/**\n * Shift annotation lines by `-offset` (used when frontmatter is stripped before\n * rendering). Annotations that fall entirely inside the stripped region drop out.\n */\nexport function shiftAnnotations(\n annotations: MarkdownAnnotation[],\n offset: number,\n): MarkdownAnnotation[] {\n if (offset === 0) return annotations;\n const out: MarkdownAnnotation[] = [];\n for (const ann of annotations) {\n const startLine = ann.startLine - offset;\n const endLine = ann.endLine - offset;\n if (endLine < 1) continue;\n out.push({ ...ann, startLine: Math.max(1, startLine), endLine });\n }\n return out;\n}\n\n/** Does the annotation set wash the given block line range? Most specific wins. */\nexport function annotationForRange(\n annotations: MarkdownAnnotation[],\n startLine: number,\n endLine: number,\n): MarkdownAnnotation | undefined {\n let hit: MarkdownAnnotation | undefined;\n for (const ann of annotations) {\n if (ann.kind === \"removed-before\") continue;\n if (ann.startLine <= endLine && ann.endLine >= startLine) {\n if (!hit || ann.endLine - ann.startLine < hit.endLine - hit.startLine) hit = ann;\n }\n }\n return hit;\n}\n\n/** The removed-marker (if any) anchored exactly at this block's first line. */\nexport function removedMarkerAt(\n annotations: MarkdownAnnotation[],\n startLine: number,\n): MarkdownAnnotation | undefined {\n return annotations.find((a) => a.kind === \"removed-before\" && a.startLine === startLine);\n}\n","/**\n * Normalization-aware merge for WYSIWYG markdown editing (review WI-1).\n *\n * Problem: Milkdown serializes the WHOLE document on every edit, normalizing\n * formatting it never touched (list markers, wrapping, spacing). Feeding that\n * back into the buffer turns a one-line edit into a whole-file rewrite —\n * destroying git blame and making PR review impossible.\n *\n * Fix: three-way line merge.\n * - `original` — the byte-exact source the editor was opened with.\n * - `baseline` — the editor's serialization of `original` BEFORE any edit\n * (pure normalization drift).\n * - `edited` — the editor's serialization after user edits.\n *\n * `diff(baseline, edited)` isolates what the USER changed; an\n * `original ↔ baseline` alignment maps those hunks back onto `original`.\n * Everything the user didn't touch keeps its original bytes. Granularity is\n * the contiguous normalized run — markdown's blank lines survive\n * serialization byte-exact, so in practice that's a single block.\n *\n * Guarantees:\n * - no user edit (`baseline === edited`) → returns `original` byte-exact;\n * - no normalization drift (`original === baseline`) → returns `edited`;\n * - a user hunk inside a normalized block replaces exactly that block;\n * - oversized inputs (> {@link MAX_DIFF_LINES}) fall back to `edited`.\n */\n\nimport { lcsPairs, MAX_DIFF_LINES } from \"./diff\";\n\n/** A contiguous span of the baseline mapped to a span of the original. */\ninterface Region {\n /** Baseline range [bStart, bEnd) — may be empty (pure original deletion). */\n bStart: number;\n bEnd: number;\n /** Original lines this region carries. */\n oLines: string[];\n /** True when the region is a 1:1 byte-equal line pair. */\n exact: boolean;\n}\n\n/** Build the ordered original↔baseline region list (covers both fully). */\nfunction alignRegions(o: string[], b: string[]): Region[] {\n const pairs = lcsPairs(o, b);\n const regions: Region[] = [];\n let prevO = -1;\n let prevB = -1;\n const walk: [number, number][] = [...pairs, [o.length, b.length]];\n for (const [oi, bi] of walk) {\n if (oi - prevO > 1 || bi - prevB > 1) {\n // Normalization-changed run (possibly empty on one side).\n regions.push({\n bStart: prevB + 1,\n bEnd: bi,\n oLines: o.slice(prevO + 1, oi),\n exact: false,\n });\n }\n if (oi < o.length && bi < b.length) {\n regions.push({ bStart: bi, bEnd: bi + 1, oLines: [o[oi]!], exact: true });\n }\n prevO = oi;\n prevB = bi;\n }\n return regions;\n}\n\n/**\n * Merge a WYSIWYG serialization back onto the original source, keeping\n * original bytes for everything the user didn't touch.\n */\nexport function mergeNormalizedEdit(original: string, baseline: string, edited: string): string {\n if (baseline === edited) return original;\n if (original === baseline) return edited;\n\n const o = original.split(\"\\n\");\n const b = baseline.split(\"\\n\");\n const n = edited.split(\"\\n\");\n if (o.length > MAX_DIFF_LINES || b.length > MAX_DIFF_LINES || n.length > MAX_DIFF_LINES) {\n return edited;\n }\n\n // Which baseline lines did the user keep, and where do their insertions go?\n const keptB = new Uint8Array(b.length);\n /** N-lines the user inserted, anchored BEFORE baseline index `atB`. */\n const inserts = new Map<number, string[]>();\n {\n const pairs = lcsPairs(b, n);\n let prevB = -1;\n let prevN = -1;\n const walk: [number, number][] = [...pairs, [b.length, n.length]];\n for (const [bi, ni] of walk) {\n if (ni - prevN > 1) inserts.set(bi, n.slice(prevN + 1, ni));\n if (bi < b.length) keptB[bi] = 1;\n prevB = bi;\n prevN = ni;\n }\n void prevB;\n }\n\n const regions = alignRegions(o, b);\n const out: string[] = [];\n\n const flushInsertsBefore = (bIndex: number, pendingFrom: number): number => {\n for (let at = pendingFrom; at <= bIndex; at++) {\n const ins = inserts.get(at);\n if (ins) out.push(...ins);\n }\n return bIndex + 1;\n };\n\n let insertCursor = 0;\n for (const region of regions) {\n if (region.bStart === region.bEnd) {\n // Pure original deletion by normalization (no baseline lines). Keep the\n // original lines when the surrounding context is untouched by the user.\n const before = region.bStart - 1;\n const contextKept =\n (before < 0 || keptB[before] === 1) &&\n (region.bStart >= b.length || keptB[region.bStart] === 1);\n insertCursor = flushInsertsBefore(region.bStart - 1, insertCursor);\n if (contextKept) out.push(...region.oLines);\n continue;\n }\n\n let allKept = true;\n for (let bi = region.bStart; bi < region.bEnd; bi++) {\n if (keptB[bi] !== 1) {\n allKept = false;\n break;\n }\n }\n\n if (region.exact || allKept) {\n // Untouched by the user → original bytes win. (For exact regions the\n // texts are identical anyway; for normalized runs this UNDOES the\n // serializer's drift.) Emit interleaved insertions at their anchors.\n for (let bi = region.bStart; bi < region.bEnd; bi++) {\n insertCursor = flushInsertsBefore(bi, insertCursor);\n if (keptB[bi] === 1) {\n if (region.exact) out.push(...region.oLines);\n }\n }\n if (!region.exact) out.push(...region.oLines);\n } else {\n // The user edited inside this region → the edited serialization wins\n // for the whole region (locally normalized; the rest of the document\n // stays byte-exact). Kept lines inside it come from the baseline text.\n for (let bi = region.bStart; bi < region.bEnd; bi++) {\n insertCursor = flushInsertsBefore(bi, insertCursor);\n if (keptB[bi] === 1) out.push(b[bi]!);\n }\n }\n }\n // Trailing insertions (anchored at b.length).\n flushInsertsBefore(b.length, insertCursor);\n\n return out.join(\"\\n\");\n}\n","/**\n * Typed-`/` trigger detection for the Monaco source pane (the conflict-free way\n * to open the brand block menu — no keybinding, mirrors the WYSIWYG `/` trigger).\n *\n * Pure + Monaco-free so it unit-tests without the engine. The workspace feeds it\n * the just-edited line + the column the `/` landed on (from a Monaco content\n * change) and, when it's a valid trigger spot, gets back the model range of that\n * `/` so the menu can replace it with the inserted block (or delete it on cancel).\n *\n * A `/` is a valid trigger only at a textblock start (column 1) or right after\n * whitespace — so a `/` inside a word, a URL, or a path (`a/b`, `http://`) never\n * hijacks typing, matching the WYSIWYG `triggerAllowed` rule.\n */\n\n/** A Monaco `IRange`-shaped span (kept structural so this module imports no monaco). */\nexport interface SlashTriggerRange {\n startLineNumber: number;\n startColumn: number;\n endLineNumber: number;\n endColumn: number;\n}\n\n/**\n * Given the 1-based `line` number, the FULL line content AFTER the `/` was typed,\n * and the 1-based `slashColumn` the `/` now occupies, return the range covering\n * that `/` when it is a valid trigger — otherwise `null`.\n */\nexport function slashTriggerRange(\n line: number,\n lineContent: string,\n slashColumn: number,\n): SlashTriggerRange | null {\n // Sanity: the character at the reported column must actually be the `/`.\n if (lineContent.charAt(slashColumn - 1) !== \"/\") return null;\n // Allowed at the very start of the line, or immediately after whitespace.\n if (slashColumn > 1) {\n const before = lineContent.charAt(slashColumn - 2);\n if (!/\\s/.test(before)) return null;\n }\n return {\n startLineNumber: line,\n startColumn: slashColumn,\n endLineNumber: line,\n endColumn: slashColumn + 1,\n };\n}\n","/**\n * Shortcut helpers for the cross-pane slash menu (#271) — the MONACO half.\n *\n * Converts a shortcut string (e.g. `\"Mod-/\"`) into a Monaco keybinding bitmask.\n * This is the ONLY slash module that imports `monaco-editor`; it is imported only\n * by the Monaco-side surfaces (the source pane action in `MarkdownWorkspace`), so\n * the pure `./shortcut.ts` — imported by the Milkdown plugin — stays Monaco-free.\n *\n * INTERNAL — not exported from package barrels.\n */\nimport * as monaco from \"monaco-editor\";\n\n/** Supported letter key names (A-Z, case-insensitive in shortcut strings). */\nconst LETTER_KEY_MAP: Record<string, number> = (() => {\n const map: Record<string, number> = {};\n const kc = monaco.KeyCode as unknown as Record<string, number>;\n for (let i = 0; i < 26; i++) {\n const letter = String.fromCharCode(65 + i); // \"A\"..\"Z\"\n const code = kc[`Key${letter}`];\n if (code !== undefined) map[letter.toLowerCase()] = code;\n }\n return map;\n})();\n\nconst NAMED_KEY_MAP: Record<string, number> = {\n \"/\": monaco.KeyCode.Slash,\n backspace: monaco.KeyCode.Backspace,\n delete: monaco.KeyCode.Delete,\n escape: monaco.KeyCode.Escape,\n enter: monaco.KeyCode.Enter,\n tab: monaco.KeyCode.Tab,\n arrowup: monaco.KeyCode.UpArrow,\n arrowdown: monaco.KeyCode.DownArrow,\n arrowleft: monaco.KeyCode.LeftArrow,\n arrowright: monaco.KeyCode.RightArrow,\n};\n\n/**\n * Parse a shortcut string (e.g. `\"Mod-/\"`, `\"Mod-Shift-K\"`) into a Monaco\n * keybinding bitmask. Supports `Mod` (CtrlCmd), `Shift`, `Alt` modifiers and\n * a final key that is either a letter (A-Z) or one of the named keys in\n * `NAMED_KEY_MAP`. Throws for unrecognized final keys.\n *\n * The shipped default is `\"Mod-/\"` → `KeyMod.CtrlCmd | KeyCode.Slash`.\n */\nexport function parseShortcut(shortcut: string): number {\n const parts = shortcut.split(\"-\");\n let binding = 0;\n const keyPart = parts[parts.length - 1] ?? \"\";\n const modifiers = parts.slice(0, -1).map((m) => m.toLowerCase());\n\n for (const mod of modifiers) {\n if (mod === \"mod\") binding |= monaco.KeyMod.CtrlCmd;\n else if (mod === \"shift\") binding |= monaco.KeyMod.Shift;\n else if (mod === \"alt\") binding |= monaco.KeyMod.Alt;\n // Ctrl/Meta can also be named explicitly\n else if (mod === \"ctrl\") binding |= monaco.KeyMod.WinCtrl;\n }\n\n const key = keyPart.toLowerCase();\n const keyCode =\n NAMED_KEY_MAP[key] ??\n LETTER_KEY_MAP[key] ??\n (() => {\n throw new Error(`[@elabs-ai/components-editor] parseShortcut: unrecognized key \"${keyPart}\"`);\n })();\n\n return binding | keyCode;\n}\n","\"use client\";\n\n/**\n * MarkdownPreview — renders markdown to REAL @brand components (not default HTML).\n *\n * Built on Streamdown (the same react-markdown + remark engine @elabs-ai/components-ai uses), with\n * a branded `components` map: `#` → Heading, paragraph → Text, link → Link, list →\n * List, table → @elabs-ai/components-ui Table, `---` → Separator, blockquote → Blockquote, and the\n * `:::card`/`:::callout`/`::metric`/`:::timeline` directives → Card / Alert /\n * MetricBlock / Timeline. The directive plugins come from the SHARED\n * `buildMarkdownPlugins()` array, so the preview and the Milkdown editor parse the\n * brand dialect identically. Unknown directives render an explicit error block.\n *\n * Five production seams (#L1 / #L4 / #L18 / #L-wikilink / #L-transclusion):\n * - ```mermaid fences render through the branded `MermaidDiagram`;\n * - `resolveUrl` rewrites image/link targets (private-repo assets, relative paths);\n * - every block carries `data-sourcepos=\"start:end\"` (1-based source lines), and an\n * `annotations` prop washes changed blocks / marks removals — the \"ghost diff\";\n * - `resolveWikilink` rewrites `[[target]]` / `[[target|alias]]` /\n * `[[target#anchor|alias]]` into normal mdast LINK nodes (Obsidian-vault style);\n * - `resolveTransclusion` embeds `![[target]]` / `![[target#section]]` as a\n * visually-nested, labelled block (recursion capped at 3 levels).\n */\nimport {\n Alert,\n AlertDescription,\n AlertTitle,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n Separator,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport {\n createContext,\n forwardRef,\n isValidElement,\n useContext,\n useMemo,\n type HTMLAttributes,\n type ReactElement,\n type ReactNode,\n} from \"react\";\nimport {\n Streamdown,\n defaultRehypePlugins,\n defaultRemarkPlugins,\n type Components,\n} from \"streamdown\";\nimport type { PluggableList } from \"unified\";\nimport { visit } from \"unist-util-visit\";\n\nimport {\n BRAND_DIRECTIVE_ATTR,\n BRAND_DIRECTIVE_INLINE_TAG,\n BRAND_DIRECTIVE_PROP,\n BRAND_DIRECTIVE_TAG,\n buildMarkdownPlugins,\n type BrandDirectivePayload,\n type MarkdownDirectiveRenderer,\n type MarkdownExtensions,\n type MarkdownFenceRenderer,\n} from \"../lib/markdown/directives\";\nimport {\n annotationForRange,\n removedMarkerAt,\n shiftAnnotations,\n type MarkdownAnnotation,\n} from \"../lib/markdown/diff\";\nimport { parseFrontmatter } from \"../lib/markdown/frontmatter\";\nimport { CalcBlock, CalcInline, type EvaluateCalc } from \"../calc-block\";\nimport { MermaidDiagram } from \"../mermaid-diagram\";\nimport { MetricBlock } from \"../metric-block\";\nimport { Blockquote, Heading, Link, List, ListItem, Text, type HeadingLevel } from \"../prose\";\nimport { Timeline, type TimelineStatus } from \"../timeline\";\nimport { CodeFence, fenceLanguage } from \"./code-fence\";\nimport { parseMarkdownOutline } from \"../markdown-outline\";\nimport remarkMath from \"remark-math\";\nimport {\n Bibliography,\n CITE_TAG,\n CITE_PROP,\n CitationProvider,\n collectCitations,\n InlineCite,\n remarkBrandCitations,\n type CitationStyle,\n type CollectedCitations,\n type ResolveCitation,\n} from \"../markdown-academic/citations\";\nimport {\n FOOTNOTE_ITEM_TAG,\n FOOTNOTE_LIST_TAG,\n FOOTNOTE_PROP,\n FOOTNOTE_REF_TAG,\n FootnoteItem,\n FootnoteList,\n FootnoteRef,\n remarkBrandFootnotes,\n} from \"../markdown-academic/footnotes\";\nimport {\n MATH_BLOCK_TAG,\n MATH_INLINE_TAG,\n MATH_PROP,\n MathBlockTag,\n MathInlineTag,\n remarkBrandMath,\n} from \"../markdown-academic/math\";\nimport { TableOfContents, TocProvider, useHeadingId } from \"../markdown-academic/toc\";\nimport {\n IterationDirective,\n specFromDirective,\n type EvaluateIteration,\n type InterpolateTemplate,\n} from \"../markdown-iteration\";\n\n// Streamdown's own default remark plugins (gfm etc.). The brand directive\n// plugins are appended PER-INSTANCE inside the component, because the known\n// directive-name set depends on the consumer's `extensions` (see the `plugins`\n// memo below).\nconst baseRemarkPlugins = Object.values(defaultRemarkPlugins);\n\n/**\n * Custom element for inline transclusion embeds (`![[target]]`). A SEPARATE tag\n * from the brand-directive tags so the sanitize schema stays narrow. The JSON\n * payload property is `data-transclusion` (hast: `dataTransclusion`).\n */\nconst BRAND_TRANSCLUSION_TAG = \"brand-transclusion\";\nconst BRAND_TRANSCLUSION_ATTR = \"data-transclusion\";\nconst BRAND_TRANSCLUSION_PROP = \"dataTransclusion\";\n\n// Allow-list uses the hast PROPERTY name (camelCase), which is what survives\n// Streamdown's sanitization — not the rendered `data-brand` attribute name.\n// Both directive tags (block/leaf + inline) carry the same JSON payload property.\nconst allowedTags = {\n [BRAND_DIRECTIVE_TAG]: [BRAND_DIRECTIVE_PROP],\n [BRAND_DIRECTIVE_INLINE_TAG]: [BRAND_DIRECTIVE_PROP],\n [BRAND_TRANSCLUSION_TAG]: [BRAND_TRANSCLUSION_PROP],\n // Academic layer (footnotes / math / citations) — opt-in via props, but the\n // tags are always allow-listed (harmless when the feature is off).\n [FOOTNOTE_REF_TAG]: [FOOTNOTE_PROP],\n [FOOTNOTE_ITEM_TAG]: [FOOTNOTE_PROP],\n [FOOTNOTE_LIST_TAG]: [],\n [MATH_BLOCK_TAG]: [MATH_PROP],\n [MATH_INLINE_TAG]: [MATH_PROP],\n [CITE_TAG]: [CITE_PROP],\n};\n\n/** All academic custom tags + their payload props, for the sanitize schema. */\nconst ACADEMIC_TAGS = [\n FOOTNOTE_REF_TAG,\n FOOTNOTE_ITEM_TAG,\n FOOTNOTE_LIST_TAG,\n MATH_BLOCK_TAG,\n MATH_INLINE_TAG,\n CITE_TAG,\n];\nconst ACADEMIC_TAG_ATTRS: Record<string, string[]> = {\n [FOOTNOTE_REF_TAG]: [FOOTNOTE_PROP],\n [FOOTNOTE_ITEM_TAG]: [FOOTNOTE_PROP],\n [FOOTNOTE_LIST_TAG]: [],\n [MATH_BLOCK_TAG]: [MATH_PROP],\n [MATH_INLINE_TAG]: [MATH_PROP],\n [CITE_TAG]: [CITE_PROP],\n};\n\n/**\n * Streamdown's default sanitize schema only lets http(s) image `src` through,\n * which kills the `resolveUrl` story (#L4): authenticated repo assets arrive\n * as `data:`/`blob:` URLs. Extend the SAME default pipeline (raw → sanitize →\n * harden) with those protocols — harden itself already validates them.\n */\nconst rehypePlugins = (() => {\n const defaults = defaultRehypePlugins as Record<string, unknown>;\n const sanitize = defaults.sanitize as [\n unknown,\n {\n protocols?: Record<string, unknown[]>;\n tagNames?: string[];\n attributes?: Record<string, unknown[]>;\n },\n ];\n const schema = sanitize[1] ?? {};\n const protocols = (schema.protocols ?? {}) as Record<string, unknown[]>;\n const extendedSanitize = [\n sanitize[0],\n {\n ...schema,\n protocols: { ...protocols, src: [...(protocols.src ?? [\"http\", \"https\"]), \"data\", \"blob\"] },\n // Custom rehypePlugins bypass Streamdown's `allowedTags` merge — so the brand-directive\n // tags, the transclusion tag, and their JSON payload properties all go into the schema here.\n tagNames: [\n ...(schema.tagNames ?? []),\n BRAND_DIRECTIVE_TAG,\n BRAND_DIRECTIVE_INLINE_TAG,\n BRAND_TRANSCLUSION_TAG,\n ...ACADEMIC_TAGS,\n ],\n attributes: {\n ...(schema.attributes ?? {}),\n [BRAND_DIRECTIVE_TAG]: [BRAND_DIRECTIVE_PROP],\n [BRAND_DIRECTIVE_INLINE_TAG]: [BRAND_DIRECTIVE_PROP],\n [BRAND_TRANSCLUSION_TAG]: [BRAND_TRANSCLUSION_PROP],\n ...ACADEMIC_TAG_ATTRS,\n },\n },\n ];\n return [defaults.raw, extendedSanitize, defaults.harden] as PluggableList;\n})();\n\n/** Treat the whole document as one block (keeps multi-line directives intact). */\nconst singleBlock = (md: string): string[] => [md];\n\n/** react-markdown passes `node` to every component — strip it before spreading. */\ntype MdProps = { node?: unknown; children?: ReactNode } & Record<string, unknown>;\n\n/* ------------------------------------------------------------------ */\n/* Contexts (keep the `components` map static across renders) */\n/* ------------------------------------------------------------------ */\n\nconst AnnotationsContext = createContext<MarkdownAnnotation[]>([]);\n\n/**\n * In-document search state (term + the active hit's line), threaded to the\n * blocks: the active block gets a primary wash; mermaid fences mark matching\n * nodes. Lines are 1-based relative to the STRIPPED markdown (the provider\n * shifts the public prop).\n */\ninterface SearchState {\n term?: string;\n activeLine?: number;\n /** Stripped source lines — used to hand the active line's text to diagrams. */\n lines: readonly string[];\n}\n\nconst SearchContext = createContext<SearchState>({ lines: [] });\n\n/**\n * Hover affordances beside headings (#L6 companion): a generic render-prop —\n * the preview knows nothing about what the action does (pinning, anchors,\n * copy-link…). Revealed on heading hover / focus, and kept visible while the\n * slot contains a pressed toggle (`aria-pressed=\"true\"`).\n */\nexport interface MarkdownHeadingInfo {\n level: HeadingLevel;\n /** Plain text content of the heading. */\n text: string;\n /** 1-based start line in the frontmatter-STRIPPED source (= `data-sourcepos`). */\n line?: number;\n}\n\nconst HeadingActionsContext = createContext<((heading: MarkdownHeadingInfo) => ReactNode) | null>(\n null,\n);\n\n/**\n * The resolved render registry for this preview instance: directive renderers by\n * name + fence renderers by language (the `extensions` prop, plus the calc fence\n * synthesized from `evaluate`). Consulted by `BrandDirective` /\n * `BrandInlineDirective` (directives) and `PreBlock` (fences).\n */\ninterface PreviewRegistry {\n directives: Map<string, MarkdownDirectiveRenderer>;\n fences: Map<string, MarkdownFenceRenderer>;\n}\n\nconst EMPTY_REGISTRY: PreviewRegistry = { directives: new Map(), fences: new Map() };\nconst RegistryContext = createContext<PreviewRegistry>(EMPTY_REGISTRY);\n\n/**\n * Consumer-supplied link-preview render slot. When supplied, every rendered `<a>`\n * is wrapped via this function; the consumer attaches its own hover card /\n * popover. The library never fetches — the consumer owns the preview content.\n * Default (not supplied) → the plain `Link` component.\n */\nconst LinkPreviewContext = createContext<((href: string, children: ReactNode) => ReactNode) | null>(\n null,\n);\n\n/**\n * Transclusion resolver — threaded into `TransclusionBlock` so recursive\n * `MarkdownPreview` renders can access the same hook without prop-drilling.\n */\nconst TransclusionResolverContext = createContext<\n ((target: string, opts: TransclusionResolveOptions) => string | null) | null\n>(null);\n\n/** Maximum nesting depth for `![[transclusion]]` embeds (prevents cycles). */\nconst TRANSCLUSION_MAX_DEPTH = 3;\n\n/** Tracks the current embed depth; 0 = top-level document. */\nconst TransclusionDepthContext = createContext<number>(0);\n\n/** Flatten a rendered heading's children to plain text (descends elements). */\nfunction flattenNodeText(node: ReactNode): string {\n if (typeof node === \"string\" || typeof node === \"number\") return String(node);\n if (Array.isArray(node)) return node.map((n) => flattenNodeText(n as ReactNode)).join(\"\");\n if (isValidElement(node)) {\n return flattenNodeText((node.props as { children?: ReactNode }).children);\n }\n return \"\";\n}\n\nexport type MarkdownUrlKind = \"image\" | \"link\";\ntype UrlResolver = (url: string, kind: MarkdownUrlKind) => string;\n\n/**\n * URL rewriting must happen at the REMARK stage: Streamdown's sanitizer\n * (harden-react-markdown) runs on the hast and blocks unresolvable relative\n * URLs before any React component sees them — so the resolver maps them to\n * absolute (or protocol-carrying) URLs first.\n */\ninterface MdUrlNode {\n type: string;\n url?: string;\n}\n\nfunction remarkResolveUrls(resolve: UrlResolver) {\n // Unified plugin shape: an ATTACHER that returns the transformer.\n return function attacher() {\n return (tree: unknown) => {\n visit(tree as Parameters<typeof visit>[0], (node) => {\n const n = node as MdUrlNode;\n if (n.type === \"image\" || n.type === \"imageReference\") {\n if (typeof n.url === \"string\") n.url = resolve(n.url, \"image\");\n } else if (n.type === \"link\" || n.type === \"definition\") {\n if (typeof n.url === \"string\") n.url = resolve(n.url, \"link\");\n }\n });\n };\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Wikilink resolver types (exported for consumers) */\n/* ------------------------------------------------------------------ */\n\n/**\n * Options passed to `resolveWikilink` for each wikilink found in the document.\n */\nexport interface WikilinkResolveOptions {\n /** The `#anchor` fragment, if present — e.g. `[[target#Section 1]]` → `\"Section 1\"`. */\n anchor?: string;\n}\n\n/**\n * Options passed to `resolveTransclusion` for each transclusion embed found.\n */\nexport interface TransclusionResolveOptions {\n /**\n * A `#section` heading, if present — e.g. `![[target#Introduction]]` → `\"Introduction\"`.\n * The consumer can use this to extract only that section from the document.\n */\n section?: string;\n}\n\n/* ------------------------------------------------------------------ */\n/* remarkResolveWikilinks — `[[target]]` → mdast link node */\n/* ------------------------------------------------------------------ */\n\n/**\n * Wikilink syntax supported:\n * `[[target]]` → link text = target, href from resolveWikilink(target, {})\n * `[[target|alias]]` → link text = alias, href from resolveWikilink(target, {})\n * `[[target#anchor]]` → link text = target, href from resolveWikilink(target, { anchor })\n * `[[target#anchor|alias]]` → link text = alias, href from resolveWikilink(target, { anchor })\n * (Obsidian style: anchor is on the TARGET side, before the `|` separator)\n *\n * Unresolvable wikilinks (hook returns null) render as plain text `[[original]]`.\n * The produced link flows through the existing `a:` renderer (resolveUrl + renderLinkPreview apply).\n */\nfunction remarkResolveWikilinks(\n resolve: (target: string, opts: WikilinkResolveOptions) => string | null,\n) {\n // Match `[[...]]` but NOT `![[...]]` (transclusion is handled separately).\n // Lookbehind `(?<!!)` ensures we don't consume transclusion prefixes.\n const WIKILINK_RE = /(?<!!)\\[\\[([^\\]]+)\\]\\]/g;\n\n return function attacher() {\n return (tree: unknown) => {\n visit(tree as Parameters<typeof visit>[0], \"text\", (node, index, parent) => {\n const n = node as { type: string; value: string };\n const p = parent as { children?: unknown[] } | undefined;\n if (!p?.children || index == null || typeof n.value !== \"string\") return;\n\n const text = n.value;\n // Fast path: no wikilinks in this text node.\n if (!text.includes(\"[[\")) return;\n\n const newChildren: unknown[] = [];\n let lastIndex = 0;\n WIKILINK_RE.lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = WIKILINK_RE.exec(text)) !== null) {\n // Text before this wikilink.\n if (match.index > lastIndex) {\n newChildren.push({ type: \"text\", value: text.slice(lastIndex, match.index) });\n }\n\n const inner = match[1]!;\n // Split on FIRST `|` for alias — anchor lives on the target side (before `|`).\n const pipeIdx = inner.indexOf(\"|\");\n const targetPart = pipeIdx !== -1 ? inner.slice(0, pipeIdx) : inner;\n const alias = pipeIdx !== -1 ? inner.slice(pipeIdx + 1) : undefined;\n\n // Split target on FIRST `#` for anchor.\n const hashIdx = targetPart.indexOf(\"#\");\n const target = hashIdx !== -1 ? targetPart.slice(0, hashIdx) : targetPart;\n const anchor = hashIdx !== -1 ? targetPart.slice(hashIdx + 1) : undefined;\n\n const opts: WikilinkResolveOptions = anchor ? { anchor } : {};\n const href = resolve(target.trim(), opts);\n const linkText = alias?.trim() || target.trim();\n\n if (href === null) {\n // Unresolvable → plain text, preserving the original `[[…]]` literal.\n newChildren.push({ type: \"text\", value: match[0] });\n } else {\n // A normal mdast link — flows through the existing `a:` renderer.\n newChildren.push({\n type: \"link\",\n url: href,\n title: null,\n children: [{ type: \"text\", value: linkText }],\n });\n }\n\n lastIndex = match.index + match[0].length;\n }\n\n // Remaining text after the last wikilink.\n if (lastIndex < text.length) {\n newChildren.push({ type: \"text\", value: text.slice(lastIndex) });\n }\n\n // Only splice if we actually found wikilinks.\n if (newChildren.length > 0) {\n p.children.splice(index, 1, ...newChildren);\n // Return the next index to skip past the newly inserted nodes.\n return index + newChildren.length;\n }\n });\n };\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* remarkResolveTransclusions — `![[target]]` → brand-transclusion */\n/* ------------------------------------------------------------------ */\n\ninterface TransclusionPayload {\n target: string;\n section?: string;\n}\n\n/**\n * Rewrites standalone `![[target]]` / `![[target#section]]` lines into a custom\n * `<brand-transclusion>` element carrying a JSON payload. The React component\n * (`TransclusionBlock`) resolves + renders the content recursively, with a\n * depth cap to prevent infinite loops.\n *\n * \"Standalone\" means the wikilink embed appears as its own paragraph (the most\n * common Obsidian authoring pattern). Embeds mid-sentence are also caught via\n * the text-node transform but are treated as paragraph-level blocks by inserting\n * a paragraph wrapper — this keeps valid mdast structure.\n */\nfunction remarkResolveTransclusions() {\n // A STANDALONE transclusion: a paragraph whose only content is `![[target]]`\n // (the Obsidian authoring pattern). Transclusion is a BLOCK embed, so we\n // rewrite the whole PARAGRAPH (not an inline text node — a figure inside <p>\n // would be invalid HTML) and use `data.hName`/`hProperties` (the same reliable\n // mechanism the brand directives use) rather than a raw `html` node, which does\n // not round-trip through Streamdown's rehype pipeline.\n const STANDALONE_RE = /^!\\[\\[([^\\]]+)\\]\\]$/;\n\n return function attacher() {\n return (tree: unknown) => {\n visit(tree as Parameters<typeof visit>[0], \"paragraph\", (node) => {\n const n = node as {\n children?: { type: string; value?: string }[];\n data?: { hName?: string; hProperties?: Record<string, unknown> };\n };\n if (!n.children || n.children.length !== 1) return;\n const child = n.children[0]!;\n if (child.type !== \"text\" || typeof child.value !== \"string\") return;\n\n const match = child.value.trim().match(STANDALONE_RE);\n if (!match) return;\n\n const inner = match[1]!;\n const hashIdx = inner.indexOf(\"#\");\n const target = (hashIdx !== -1 ? inner.slice(0, hashIdx) : inner).trim();\n const section = hashIdx !== -1 ? inner.slice(hashIdx + 1).trim() : undefined;\n const payload: TransclusionPayload = section ? { target, section } : { target };\n\n const data = n.data ?? (n.data = {});\n data.hName = BRAND_TRANSCLUSION_TAG;\n data.hProperties = { [BRAND_TRANSCLUSION_PROP]: JSON.stringify(payload) };\n n.children = []; // consumed into the payload; TransclusionBlock renders it\n });\n };\n };\n}\n\ninterface SourcePos {\n start: number;\n end: number;\n}\n\n/** Does a DESCENDANT list item already contain this line? (innermost li wins) */\nfunction nestedItemContains(node: unknown, line: number): boolean {\n const kids = (node as { children?: unknown[] } | undefined)?.children ?? [];\n for (const kid of kids) {\n const el = kid as { tagName?: string };\n if (el.tagName === \"li\") {\n const pos = getSourcePos(kid);\n if (pos && line >= pos.start && line <= pos.end) return true;\n }\n if (nestedItemContains(kid, line)) return true;\n }\n return false;\n}\n\nfunction getSourcePos(node: unknown): SourcePos | undefined {\n const pos = (\n node as { position?: { start?: { line?: number }; end?: { line?: number } } } | undefined\n )?.position;\n if (typeof pos?.start?.line !== \"number\") return undefined;\n return { start: pos.start.line, end: pos.end?.line ?? pos.start.line };\n}\n\nfunction RemovedMarker({ count }: { count: number }) {\n return (\n <div\n role=\"note\"\n aria-label={`${count} ${count === 1 ? \"line\" : \"lines\"} removed here`}\n className=\"flex items-center gap-2 text-meta text-destructive-text\"\n >\n <span aria-hidden=\"true\" className=\"font-mono\">\n −\n </span>\n <span aria-hidden=\"true\" className=\"flex-1 border-t border-dashed border-destructive/40\" />\n <span>\n {count} {count === 1 ? \"line\" : \"lines\"} removed\n </span>\n <span aria-hidden=\"true\" className=\"flex-1 border-t border-dashed border-destructive/40\" />\n </div>\n );\n}\n\n/**\n * Wrap a block renderer with the sourcepos + annotation layer: stamps\n * `data-sourcepos`, washes added/modified blocks (accent rail + tint), washes\n * the active search hit's block (primary tint), and renders the\n * removed-content marker anchored to this block.\n *\n * `searchWash: false` opts a block out of the active-search wash — `pre`\n * fences (incl. mermaid) carry their own treatment.\n */\nfunction annotated(render: (props: MdProps) => ReactNode, searchWash = true) {\n return function AnnotatedBlock(props: MdProps) {\n const annotations = useContext(AnnotationsContext);\n const search = useContext(SearchContext);\n const pos = getSourcePos(props.node);\n const enriched = pos ? { ...props, \"data-sourcepos\": `${pos.start}:${pos.end}` } : props;\n\n const wash =\n pos && annotations.length > 0\n ? annotationForRange(annotations, pos.start, pos.end)\n : undefined;\n const removed =\n pos && annotations.length > 0 ? removedMarkerAt(annotations, pos.start) : undefined;\n const activeSearch =\n searchWash &&\n pos != null &&\n search.activeLine != null &&\n search.activeLine >= pos.start &&\n search.activeLine <= pos.end;\n\n let content = render(enriched);\n if (!wash && !removed && !activeSearch) return content;\n\n if (wash) {\n content = (\n <div\n data-annotation={wash.kind}\n className=\"border-s-2 border-s-success bg-success/10 py-1.5 pe-2 ps-3\"\n >\n {content}\n </div>\n );\n }\n if (activeSearch) {\n content = (\n <div data-search-active=\"\" className=\"-mx-2 rounded-md bg-primary/10 px-2 py-1\">\n {content}\n </div>\n );\n }\n return (\n <>\n {removed ? <RemovedMarker count={removed.removedCount ?? 1} /> : null}\n {content}\n </>\n );\n };\n}\n\nfunction heading(level: HeadingLevel) {\n return function HeadingMd({ node: _n, children, ...rest }: MdProps) {\n const headingActions = useContext(HeadingActionsContext);\n const start = (rest[\"data-sourcepos\"] as string | undefined)?.split(\":\")[0];\n const line = start ? Number(start) : undefined;\n // Stable slug id (only when TOC is enabled) so `::toc` anchors resolve.\n const headingId = useHeadingId(line);\n const slot = headingActions?.({\n level,\n text: flattenNodeText(children),\n line,\n });\n return (\n <Heading\n level={level}\n id={headingId}\n {...(rest as HTMLAttributes<HTMLHeadingElement>)}\n className={cn(\n slot ? \"group/heading\" : undefined,\n headingId ? \"scroll-mt-4\" : undefined,\n rest.className as string | undefined,\n )}\n >\n {children}\n {slot ? (\n <span\n // GitHub-anchor grammar: revealed on hover/focus; stays visible\n // while a contained toggle is pressed (a pinned section keeps its pin).\n className=\"ms-1.5 inline-flex align-middle opacity-0 transition-opacity duration-fast ease-standard focus-within:opacity-100 group-hover/heading:opacity-100 has-[[aria-pressed=true]]:opacity-100 motion-reduce:transition-none\"\n >\n {slot}\n </span>\n ) : null}\n </Heading>\n );\n };\n}\n\nconst CALLOUT_VARIANT: Record<string, \"default\" | \"info\" | \"success\" | \"warning\" | \"destructive\"> =\n {\n info: \"info\",\n note: \"info\",\n tip: \"success\",\n success: \"success\",\n warning: \"warning\",\n caution: \"warning\",\n danger: \"destructive\",\n error: \"destructive\",\n destructive: \"destructive\",\n };\n\nconst TIMELINE_STATUS: Record<string, TimelineStatus> = {\n done: \"done\",\n complete: \"done\",\n completed: \"done\",\n active: \"active\",\n current: \"active\",\n pending: \"pending\",\n todo: \"pending\",\n};\n\nfunction UnknownBlock({ name }: { name: string }) {\n return (\n <Alert variant=\"destructive\">\n <AlertTitle>Unknown block: {name}</AlertTitle>\n <AlertDescription>\n No renderer is mapped for <code>:::{name}</code>. Add it to the brand directive registry, or\n fix the directive name.\n </AlertDescription>\n </Alert>\n );\n}\n\n/** Parse the JSON payload off a `<brand-directive*>` element's props. */\nfunction readDirectivePayload(rest: MdProps): BrandDirectivePayload | \"malformed\" | null {\n const raw =\n (rest[BRAND_DIRECTIVE_ATTR] as string | undefined) ?? (rest.dataBrand as string | undefined);\n if (!raw) return null;\n try {\n return JSON.parse(raw) as BrandDirectivePayload;\n } catch {\n return \"malformed\";\n }\n}\n\nfunction BrandDirective({ node: _n, children, ...rest }: MdProps) {\n const registry = useContext(RegistryContext);\n const payload = readDirectivePayload(rest);\n if (payload === null) return null;\n if (payload === \"malformed\") return <UnknownBlock name=\"malformed\" />;\n\n if (!payload.known) return <UnknownBlock name={payload.name} />;\n\n const attrs = payload.attributes ?? {};\n switch (payload.name) {\n case \"card\":\n return (\n <Card>\n {attrs.title ? (\n <CardHeader>\n <CardTitle>{attrs.title}</CardTitle>\n </CardHeader>\n ) : null}\n <CardContent className={cn(!attrs.title && \"pt-6\")}>{children}</CardContent>\n </Card>\n );\n case \"callout\":\n return (\n <Alert variant={CALLOUT_VARIANT[attrs.type ?? \"\"] ?? \"default\"}>\n {/* Callout title is a label, NOT a document section heading — a callout is\n inserted INTO the content flow, so an <h5> (AlertTitle's default for a\n standalone banner) would break the document heading outline. Render the\n same visual as a non-heading <div> instead (see #21). */}\n {attrs.title ? (\n <div className=\"mb-1 font-medium leading-none tracking-tight\">{attrs.title}</div>\n ) : null}\n <AlertDescription>{children}</AlertDescription>\n </Alert>\n );\n case \"metric\":\n return (\n <MetricBlock\n label={attrs.label ?? \"\"}\n value={attrs.value ?? \"\"}\n description={attrs.description}\n delta={attrs.delta}\n deltaDirection={\n attrs.delta?.startsWith(\"+\") ? \"up\" : attrs.delta?.startsWith(\"-\") ? \"down\" : \"neutral\"\n }\n />\n );\n case \"timeline\":\n return (\n <Timeline\n items={(payload.items ?? []).map((it) => ({\n title: it.title,\n status: TIMELINE_STATUS[it.status] ?? \"pending\",\n }))}\n />\n );\n default: {\n // Not a built-in → a consumer-registered directive (`extensions`). The\n // name reached `known: true` only because it was registered, so a renderer\n // should exist; if somehow missing, surface the unknown-block error.\n const renderer = registry.directives.get(payload.name);\n if (renderer && (!renderer.kinds || renderer.kinds.includes(payload.kind))) {\n return (\n <>\n {renderer.render({\n name: payload.name,\n kind: payload.kind,\n attributes: attrs,\n children,\n textValue: payload.label,\n rawBody: payload.body,\n })}\n </>\n );\n }\n return <UnknownBlock name={payload.name} />;\n }\n }\n}\n\n/**\n * Inline (`:name[label]{attrs}`) directives. Rendered via a SEPARATE tag so it\n * stays in the text flow (no block wrapper / annotation layer). Only registered\n * inline names reach here (unregistered ones were restored to literal text by\n * the parser); a registered name with no inline renderer falls back to its label.\n */\nfunction BrandInlineDirective({ node: _n, children, ...rest }: MdProps) {\n const registry = useContext(RegistryContext);\n const payload = readDirectivePayload(rest);\n if (payload === null || payload === \"malformed\") return <>{children}</>;\n\n const renderer = registry.directives.get(payload.name);\n if (!renderer || (renderer.kinds && !renderer.kinds.includes(\"inline\"))) {\n return <>{children}</>;\n }\n return (\n <>\n {renderer.render({\n name: payload.name,\n kind: \"inline\",\n attributes: payload.attributes ?? {},\n children,\n textValue: payload.label,\n })}\n </>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Mermaid fences + resolved images/links */\n/* ------------------------------------------------------------------ */\n\n/** Flatten react-markdown `children` (string | array) into the raw fence text. */\nfunction fenceText(children: ReactNode): string {\n if (typeof children === \"string\") return children;\n if (Array.isArray(children)) return children.map((c) => fenceText(c as ReactNode)).join(\"\");\n return \"\";\n}\n\nfunction isMermaidCodeElement(child: unknown): child is ReactElement<{\n className?: string;\n children?: ReactNode;\n}> {\n return (\n isValidElement(child) &&\n /\\blanguage-mermaid\\b/.test((child.props as { className?: string } | null)?.className ?? \"\")\n );\n}\n\nfunction PreBlock({ node, children, ...rest }: MdProps) {\n const search = useContext(SearchContext);\n const registry = useContext(RegistryContext);\n const pos = getSourcePos(node);\n const activeInBlock =\n pos != null &&\n search.activeLine != null &&\n search.activeLine >= pos.start &&\n search.activeLine <= pos.end;\n\n const list = Array.isArray(children) ? children : [children];\n // Mermaid stays a PRIVILEGED built-in: it carries search-highlight + active-line\n // coupling that the generic `{ source, lang }` fence contract deliberately omits.\n const mermaidChild = list.find(isMermaidCodeElement);\n if (mermaidChild) {\n const chart = fenceText((mermaidChild.props as { children?: ReactNode }).children).replace(\n /\\n$/,\n \"\",\n );\n return (\n <MermaidDiagram\n chart={chart}\n // The diagram must stay addressable by source line (outline/search jumps).\n data-sourcepos={pos ? `${pos.start}:${pos.end}` : undefined}\n highlightTerm={search.term}\n activeText={\n activeInBlock && search.activeLine != null\n ? search.lines[search.activeLine - 1]\n : undefined\n }\n />\n );\n }\n // Registered fences (the seam): calc is registered from the `evaluate` prop;\n // consumers register their own via `extensions.fences`. The library renders the\n // result; the consumer's renderer owns any domain hook. Stamp `data-sourcepos`\n // so the block stays addressable by outline/search jumps.\n const codeEl = list.find(isValidElement) as\n | ReactElement<{ className?: string; children?: ReactNode }>\n | undefined;\n const fenceLang = fenceLanguage(codeEl?.props.className);\n const fenceRenderer = fenceLang ? registry.fences.get(fenceLang) : undefined;\n if (fenceLang && fenceRenderer && codeEl) {\n const source = fenceText(codeEl.props.children).replace(/\\n$/, \"\");\n const rendered = fenceRenderer.render({ source, lang: fenceLang });\n return pos ? <div data-sourcepos={`${pos.start}:${pos.end}`}>{rendered}</div> : <>{rendered}</>;\n }\n // Non-mermaid, unregistered fences: tokenized highlighting + language chip + hover copy.\n // The fence keeps its source-line address (`data-sourcepos` arrives via\n // `rest` onto the wrapper) and the active-search wash on the inner pre.\n const codeText = fenceText(codeEl ? codeEl.props.children : (children as ReactNode)).replace(\n /\\n$/,\n \"\",\n );\n return (\n <CodeFence\n {...(rest as HTMLAttributes<HTMLElement>)}\n codeText={codeText}\n language={fenceLang}\n searchActive={activeInBlock}\n >\n {children}\n </CodeFence>\n );\n}\n\nfunction ImageMd({ node: _n, src, alt, ...rest }: MdProps) {\n return (\n <img\n src={src as string}\n alt={(alt as string) ?? \"\"}\n loading=\"lazy\"\n className=\"max-w-full rounded-md border border-border\"\n {...(rest as HTMLAttributes<HTMLImageElement>)}\n />\n );\n}\n\nfunction LinkMd({ node: _n, href, children, ...rest }: MdProps) {\n const renderLinkPreview = useContext(LinkPreviewContext);\n const anchor = (\n <Link href={href as string} {...(rest as HTMLAttributes<HTMLAnchorElement>)}>\n {children}\n </Link>\n );\n if (renderLinkPreview && typeof href === \"string\") {\n return <>{renderLinkPreview(href, anchor)}</>;\n }\n return anchor;\n}\n\n/**\n * Renders a `![[target]]` / `![[target#section]]` transclusion embed.\n *\n * - Reads the payload from the `data-transclusion` attribute (JSON).\n * - Calls `resolveTransclusion(target, { section })` to get markdown text.\n * - If null → renders the literal `![[target]]` as plain text.\n * - If at the depth cap → renders a \"transclusion too deep\" notice.\n * - Otherwise → recursively renders the returned markdown via `MarkdownPreview`\n * inside a visually-nested, semantically-labelled block.\n *\n * The block uses a quiet inset separation: border-start rail + muted ground\n * (no redundant border over the fill; satisfies the separation grammar).\n */\nfunction TransclusionBlock({ node: _n, ...rest }: MdProps) {\n const resolveTransclusion = useContext(TransclusionResolverContext);\n const depth = useContext(TransclusionDepthContext);\n const linkPreview = useContext(LinkPreviewContext);\n\n // Parse the JSON payload from the hast attribute.\n const rawAttr =\n (rest[BRAND_TRANSCLUSION_ATTR] as string | undefined) ??\n (rest.dataTransclusion as string | undefined);\n\n if (!rawAttr || !resolveTransclusion) {\n // No resolver or malformed — render as literal fallback.\n return (\n <span>{rawAttr ? `![[${(JSON.parse(rawAttr) as TransclusionPayload).target}]]` : null}</span>\n );\n }\n\n let payload: TransclusionPayload;\n try {\n payload = JSON.parse(rawAttr) as TransclusionPayload;\n } catch {\n return null;\n }\n\n const { target, section } = payload;\n const label = section ? `${target}#${section}` : target;\n\n if (depth >= TRANSCLUSION_MAX_DEPTH) {\n return (\n <figure\n aria-label={`Embedded: ${label}`}\n className=\"my-3 rounded-md border-s-2 border-s-muted bg-muted/40 px-4 py-3\"\n data-testid=\"transclusion-block\"\n data-transclusion-depth={depth}\n >\n <figcaption className=\"mb-1 text-meta text-muted-foreground\">{label}</figcaption>\n <p className=\"text-meta text-muted-foreground italic\">\n Transclusion too deep — embed skipped.\n </p>\n </figure>\n );\n }\n\n const content = resolveTransclusion(target, section ? { section } : {});\n\n if (content === null) {\n // Unresolvable → plain text, never a broken element.\n return <span>{`![[${label}]]`}</span>;\n }\n\n // Recursive render: inner MarkdownPreview reads depth+1 from context.\n // We thread the SAME linkPreview context so consumer hooks propagate.\n // NOTE: We render a plain MarkdownPreview without frontmatter strip by default.\n // We must not import MarkdownPreview here (circular ref) — instead we render the\n // Streamdown directly with the same plugin set. We solve this by rendering a\n // lightweight recursive wrapper that bypasses the outer forwardRef. We achieve\n // this by reading the current plugin array from the outer `plugins` memo (not\n // possible here) — so instead we compose a separate inner pipeline with the same\n // base plugins. The new contexts (depth + resolver + linkPreview) are provided by\n // the outer MarkdownPreview render tree and inherited by RecursiveTransclusion.\n return (\n <TransclusionDepthContext.Provider value={depth + 1}>\n <LinkPreviewContext.Provider value={linkPreview}>\n <RecursiveTransclusionContent target={target} label={label} content={content} />\n </LinkPreviewContext.Provider>\n </TransclusionDepthContext.Provider>\n );\n}\n\n/** Inner render for a resolved transclusion — used by TransclusionBlock. */\nfunction RecursiveTransclusionContent({\n target: _target,\n label,\n content,\n}: {\n target: string;\n label: string;\n content: string;\n}) {\n const plugins = useMemo<PluggableList>(() => {\n return [...baseRemarkPlugins, ...buildMarkdownPlugins()];\n }, []);\n\n return (\n <figure\n aria-label={`Embedded: ${label}`}\n className=\"my-3 rounded-md border-s-2 border-s-muted bg-muted/40 px-4 py-2\"\n data-testid=\"transclusion-block\"\n >\n <figcaption className=\"mb-1.5 text-meta text-muted-foreground\">{label}</figcaption>\n <div className=\"text-body text-foreground\">\n <Streamdown\n parseMarkdownIntoBlocksFn={singleBlock}\n remarkPlugins={plugins}\n rehypePlugins={rehypePlugins}\n allowedTags={allowedTags}\n components={components}\n >\n {content}\n </Streamdown>\n </div>\n </figure>\n );\n}\n\nconst components = {\n h1: annotated(heading(1)),\n h2: annotated(heading(2)),\n h3: annotated(heading(3)),\n h4: annotated(heading(4)),\n h5: annotated(heading(5)),\n h6: annotated(heading(6)),\n p: annotated(({ node: _n, ...p }: MdProps) => (\n <Text {...(p as HTMLAttributes<HTMLParagraphElement>)} />\n )),\n a: LinkMd,\n img: ImageMd,\n // Lists wash at ITEM granularity (a whole-list wash drowns the page), so the\n // ul/ol wrappers opt out of the search wash and the li carries it inline\n // (no wrapper div — that would break list semantics).\n ul: annotated(\n ({ node: _n, ...p }: MdProps) => <List {...(p as HTMLAttributes<HTMLElement>)} />,\n false,\n ),\n ol: annotated(\n ({ node: _n, ...p }: MdProps) => <List ordered {...(p as HTMLAttributes<HTMLElement>)} />,\n false,\n ),\n li: function ListItemMd({ node, ...p }: MdProps) {\n const search = useContext(SearchContext);\n const pos = getSourcePos(node);\n const active =\n pos != null &&\n search.activeLine != null &&\n search.activeLine >= pos.start &&\n search.activeLine <= pos.end &&\n !nestedItemContains(node, search.activeLine);\n return (\n <ListItem\n data-sourcepos={pos ? `${pos.start}:${pos.end}` : undefined}\n data-search-active={active ? \"\" : undefined}\n {...(p as HTMLAttributes<HTMLLIElement>)}\n className={cn(active && \"-mx-1 rounded-sm bg-primary/10 px-1\", p.className as string)}\n />\n );\n },\n blockquote: annotated(({ node: _n, ...p }: MdProps) => (\n <Blockquote {...(p as HTMLAttributes<HTMLQuoteElement>)} />\n )),\n hr: annotated(() => <Separator className=\"my-4\" />),\n pre: annotated(PreBlock, false),\n table: annotated(({ node: _n, ...p }: MdProps) => (\n <Table {...(p as HTMLAttributes<HTMLTableElement>)} />\n )),\n thead: ({ node: _n, ...p }: MdProps) => <TableHeader {...(p as object)} />,\n tbody: ({ node: _n, ...p }: MdProps) => <TableBody {...(p as object)} />,\n tr: ({ node: _n, ...p }: MdProps) => <TableRow {...(p as object)} />,\n th: ({ node: _n, ...p }: MdProps) => <TableHead {...(p as object)} />,\n td: ({ node: _n, ...p }: MdProps) => <TableCell {...(p as object)} />,\n [BRAND_DIRECTIVE_TAG]: annotated(BrandDirective),\n // Inline directives render un-`annotated` (no block wrapper) to stay in the text flow.\n [BRAND_DIRECTIVE_INLINE_TAG]: BrandInlineDirective,\n // Transclusion embeds (`![[target]]`) — resolved + recursively rendered by TransclusionBlock.\n [BRAND_TRANSCLUSION_TAG]: TransclusionBlock,\n // Academic layer — footnotes, math, citations (inline tags stay in the text flow;\n // the footnote section is a generated block).\n [FOOTNOTE_REF_TAG]: FootnoteRef,\n [FOOTNOTE_ITEM_TAG]: FootnoteItem,\n [FOOTNOTE_LIST_TAG]: ({ node: _n, children, ...rest }: MdProps) => (\n <FootnoteList {...(rest as HTMLAttributes<HTMLElement>)}>{children}</FootnoteList>\n ),\n [MATH_INLINE_TAG]: MathInlineTag,\n [MATH_BLOCK_TAG]: MathBlockTag,\n [CITE_TAG]: InlineCite,\n} as unknown as Components;\n\nexport interface MarkdownPreviewProps extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n /** Markdown source. */\n children: string;\n /** Strip a leading YAML frontmatter block before rendering. Default true. */\n stripFrontmatter?: boolean;\n /**\n * Ghost-diff annotations (#L18) — typically from `computeMarkdownAnnotations`.\n * Lines are 1-based relative to the FULL `children` source (frontmatter\n * included); the preview shifts them when `stripFrontmatter` removes lines.\n */\n annotations?: MarkdownAnnotation[];\n /**\n * Rewrite image/link URLs (#L4) — e.g. resolve repo-relative paths or swap\n * private-repo asset URLs for authenticated blob URLs. Synchronous by design:\n * async consumers cache upstream and re-render when the URL is ready.\n */\n resolveUrl?: (url: string, kind: MarkdownUrlKind) => string;\n /**\n * In-document search term (≥2 chars): mermaid diagrams mark matching nodes.\n * Pair with an app-side text highlighter (CSS Custom Highlight API) for the\n * prose occurrences.\n */\n searchTerm?: string;\n /**\n * 1-based line of the ACTIVE search hit, relative to the FULL `children`\n * source (same convention as `annotations`). Its block gets a primary wash;\n * in a mermaid fence the matching node gets the active stroke.\n */\n activeSearchLine?: number;\n /**\n * Render hover affordances beside each heading (pin/anchor/copy-link…).\n * Presentational slot — revealed on heading hover/focus and kept visible\n * while it contains a pressed toggle. `line` is in frontmatter-STRIPPED\n * coordinates (the same space as `data-sourcepos` / `parseMarkdownOutline`).\n */\n headingActions?: (heading: MarkdownHeadingInfo) => ReactNode;\n /**\n * Evaluate a ```calc fence to a `CalcSheet` (the library renders, the app\n * computes — mirrors `resolveUrl`). With no `evaluate`, a ```calc fence renders\n * as a normal code block; the math engine stays in the consumer.\n *\n * Sugar over `extensions.fences`: it registers a built-in `calc` fence renderer.\n * Register your own `calc` fence via `extensions` to override it.\n */\n evaluate?: EvaluateCalc;\n /**\n * Extend the markdown dialect without forking the engine: register custom\n * `:::`/`::`/`:` directive renderers and ```lang fence renderers. Registered\n * directive names are also fed to the parser (so `:entity[…]` is recognized\n * while an unregistered prose colon stays literal). Domain logic stays in the\n * consumer's renderer (the library renders; the app computes).\n */\n extensions?: MarkdownExtensions;\n /**\n * Resolve an Obsidian-style wikilink (`[[target]]`, `[[target|alias]]`,\n * `[[target#anchor]]`, `[[target#anchor|alias]]`) to a URL.\n *\n * - Return a string href to produce a real `<a>` (flows through `resolveUrl`\n * and `renderLinkPreview` like any other link).\n * - Return `null` to leave the wikilink as literal plain text `[[target]]`\n * (graceful — never a broken link).\n *\n * Supported forms:\n * - `[[target]]` → `resolveWikilink(\"target\", {})`\n * - `[[target|alias]]` → `resolveWikilink(\"target\", {})`, link text = alias\n * - `[[target#anchor]]` → `resolveWikilink(\"target\", { anchor: \"anchor\" })`\n * - `[[target#anchor|alias]]` → `resolveWikilink(\"target\", { anchor: \"anchor\" })`, text = alias\n */\n resolveWikilink?: (target: string, opts: WikilinkResolveOptions) => string | null;\n /**\n * Resolve an Obsidian-style transclusion embed (`![[target]]`,\n * `![[target#section]]`) to the markdown TEXT to embed.\n *\n * - Return the markdown string to embed; it will be recursively rendered as a\n * visually-nested, AT-labelled block (depth cap: 3 levels).\n * - Return `null` to leave the embed as literal plain text `![[target]]`.\n *\n * The library never fetches — the consumer owns the vault index and resolution.\n */\n resolveTransclusion?: (target: string, opts: TransclusionResolveOptions) => string | null;\n /**\n * Wrap every rendered `<a>` to attach a hover/inline link preview (e.g. a\n * `@elabs-ai/components-ui` HoverCard showing metadata). The library does NOT fetch; the\n * consumer owns the preview content.\n *\n * Return `children` unchanged if the href should not trigger a preview.\n * Default (not supplied) → the plain `Link` component.\n */\n renderLinkPreview?: (href: string, children: ReactNode) => ReactNode;\n /**\n * Branded GFM footnotes (`[^1]` … `[^1]: definition`) — quiet superscript refs\n * + a footnote section at the document end with working same-page back-refs.\n * Default `false` (footnotes parse but render with the plain GFM treatment).\n */\n footnotes?: boolean;\n /**\n * Math via `remark-math` + KaTeX — `$inline$` and `$$block$$` (on their own\n * lines). KaTeX runs untrusted-safe (`trust:false`, bounded macro expansion);\n * MathML is emitted for assistive tech. **The consumer must load KaTeX CSS once**\n * (`import \"katex/dist/katex.min.css\"`). Default `false`.\n */\n math?: boolean;\n /**\n * Resolve a Pandoc / Better-BibTeX citation key (`[@smith2020]`,\n * `[@a; @b]`, `[@a, p. 5]`, `[-@a]`) to {@link CitationData}, or `null` when\n * unknown. The BibTeX/CSL database + any CSL formatting live in the app — the\n * library renders inline cites + the `::bibliography` / `::references` block with\n * consistent numbering. Setting this enables citations (the same way `evaluate`\n * enables calc).\n */\n resolveCitation?: ResolveCitation;\n /** Inline citation style: `\"numeric\"` `[1]` (default) or `\"author-year\"` `(Smith 2020)`. */\n citationStyle?: CitationStyle;\n /**\n * Enable the generated `::toc` block (a quiet in-flow table of contents) and\n * stamp stable slug `id`s on headings so the anchors resolve. Reuses the same\n * heading extractor as `DocumentOutline`. Default `false`.\n */\n toc?: boolean;\n /**\n * Resolve a `:::iterate` / `:::pivot` block's {@link IterationSpec} (parsed from\n * the directive's attributes + body template) to its data. The data source +\n * any query live in the app — the library renders the repeated/cross-tabbed\n * cells. Setting this enables the `iterate` + `pivot` directives (the way\n * `evaluate` enables calc).\n */\n evaluateIteration?: EvaluateIteration;\n /**\n * Fill a `:::iterate` cell template with its row/cell context. Default: a\n * minimal `{{path}}` substitution — pass your own engine for anything richer.\n */\n interpolate?: InterpolateTemplate;\n}\n\nexport const MarkdownPreview = forwardRef<HTMLDivElement, MarkdownPreviewProps>(\n function MarkdownPreview(\n {\n children,\n stripFrontmatter = true,\n annotations,\n resolveUrl,\n searchTerm,\n activeSearchLine,\n headingActions,\n evaluate,\n extensions,\n resolveWikilink,\n resolveTransclusion,\n renderLinkPreview,\n footnotes,\n math,\n resolveCitation,\n citationStyle = \"numeric\",\n toc,\n evaluateIteration,\n interpolate,\n className,\n ...props\n },\n ref,\n ) {\n const markdown = stripFrontmatter ? parseFrontmatter(children).content : children;\n const fmOffset = stripFrontmatter\n ? children.split(\"\\n\").length - markdown.split(\"\\n\").length\n : 0;\n\n const shifted = useMemo(() => {\n if (!annotations?.length) return [];\n return fmOffset ? shiftAnnotations(annotations, fmOffset) : annotations;\n }, [annotations, fmOffset]);\n\n const search = useMemo<SearchState>(() => {\n const term = searchTerm?.trim();\n const activeLine =\n activeSearchLine != null && activeSearchLine - fmOffset >= 1\n ? activeSearchLine - fmOffset\n : undefined;\n return {\n term: term && term.length >= 2 ? term : undefined,\n activeLine,\n lines: markdown.split(\"\\n\"),\n };\n }, [searchTerm, activeSearchLine, fmOffset, markdown]);\n\n // Citation numbering authority — a single pre-pass so inline `[1]` and the\n // bibliography agree (only when a resolver is supplied).\n const citations = useMemo<CollectedCitations | null>(() => {\n if (!resolveCitation) return null;\n return collectCitations(markdown, resolveCitation);\n }, [markdown, resolveCitation]);\n\n // Heading outline for the `::toc` block + heading-id stamping (only when on).\n const outline = useMemo(() => (toc ? parseMarkdownOutline(markdown) : null), [toc, markdown]);\n\n // Resolve the render registry (directives + fences) for this instance. The\n // `evaluate` prop is sugar that registers the built-in `calc` fence.\n const registry = useMemo<PreviewRegistry>(() => {\n const directives = new Map<string, MarkdownDirectiveRenderer>();\n for (const d of extensions?.directives ?? []) directives.set(d.name, d);\n const fences = new Map<string, MarkdownFenceRenderer>();\n for (const f of extensions?.fences ?? []) fences.set(f.lang, f);\n // `::toc` + `::bibliography` / `::references` — internal directives whose\n // renderers read the outline / citation context (provided below).\n if (toc) {\n directives.set(\"toc\", {\n name: \"toc\",\n kinds: [\"leaf\", \"container\"],\n render: ({ attributes }) => <TableOfContents title={attributes.title || undefined} />,\n });\n }\n if (resolveCitation) {\n const renderBibliography: MarkdownDirectiveRenderer[\"render\"] = ({ attributes }) => (\n <Bibliography title={attributes.title || undefined} />\n );\n directives.set(\"bibliography\", {\n name: \"bibliography\",\n kinds: [\"leaf\", \"container\"],\n render: renderBibliography,\n });\n directives.set(\"references\", {\n name: \"references\",\n kinds: [\"leaf\", \"container\"],\n render: renderBibliography,\n });\n }\n if (evaluateIteration) {\n // `:::iterate` / `:::pivot` — the body is the per-cell TEMPLATE (captured\n // raw via `rawBodyNames`); cells render through a nested `MarkdownPreview`\n // that inherits the dialect features (depth-capped against runaway loops).\n const iterationDirective = (name: \"iterate\" | \"pivot\"): MarkdownDirectiveRenderer => ({\n name,\n kinds: [\"container\"],\n render: ({ attributes, rawBody }) => (\n <IterationDirective\n spec={specFromDirective(name, attributes, rawBody)}\n evaluate={evaluateIteration}\n interpolate={interpolate}\n // Cells render through a nested preview that inherits the dialect\n // features. Extracted to `IterationCell` so `MarkdownPreview` isn't\n // referenced inside its own initializer (TS2786 / forwardRef cycle).\n renderCell={(md) => (\n <IterationCell\n markdown={md}\n config={{\n evaluateIteration,\n interpolate,\n evaluate,\n extensions,\n footnotes,\n math,\n resolveCitation,\n citationStyle,\n }}\n />\n )}\n />\n ),\n });\n directives.set(\"iterate\", iterationDirective(\"iterate\"));\n directives.set(\"pivot\", iterationDirective(\"pivot\"));\n }\n if (evaluate && !fences.has(\"calc\")) {\n fences.set(\"calc\", {\n lang: \"calc\",\n render: ({ source }) => <CalcBlock source={source} evaluate={evaluate} />,\n });\n }\n if (evaluate && !directives.has(\"calc\")) {\n directives.set(\"calc\", {\n name: \"calc\",\n kinds: [\"inline\"],\n // `textValue` is the verbatim expression (markdown chars preserved);\n // fall back to the rendered label only if positions were unavailable.\n render: ({ textValue, children }) => (\n <CalcInline source={textValue ?? flattenNodeText(children)} evaluate={evaluate} />\n ),\n });\n }\n return { directives, fences };\n }, [\n extensions,\n evaluate,\n toc,\n resolveCitation,\n citationStyle,\n evaluateIteration,\n interpolate,\n footnotes,\n math,\n ]);\n\n // Stable key over the registered directive NAMES (space-joined): the parser only\n // needs the known-set, so the plugin array rebuilds on name changes, not on a\n // new `extensions` identity each render.\n // `calc` joins the set when `evaluate` is supplied (so `:calc[…]` parses);\n // `toc` / `bibliography` / `references` join when those features are enabled.\n const directiveNamesKey = [\n ...(extensions?.directives ?? []).map((d) => d.name),\n ...(evaluate ? [\"calc\"] : []),\n ...(toc ? [\"toc\"] : []),\n ...(resolveCitation ? [\"bibliography\", \"references\"] : []),\n ...(evaluateIteration ? [\"iterate\", \"pivot\"] : []),\n ].join(\" \");\n\n const plugins = useMemo<PluggableList>(() => {\n const directiveNames = directiveNamesKey ? directiveNamesKey.split(\" \") : [];\n // `:::iterate`/`:::pivot` bodies are captured RAW (as templates) rather than\n // pre-rendered — so they don't render their `{{token}}` source before interpolation.\n const rawBodyNames = evaluateIteration ? [\"iterate\", \"pivot\"] : [];\n let list: PluggableList = [\n ...baseRemarkPlugins,\n ...buildMarkdownPlugins({ directiveNames, rawBodyNames }),\n ];\n // Academic transforms run after the directive pipeline. `remarkMath` must\n // precede `remarkBrandMath` (it produces the math nodes the latter rewrites).\n if (math) list = [...list, remarkMath, remarkBrandMath];\n if (footnotes) list = [...list, remarkBrandFootnotes];\n if (resolveCitation) list = [...list, remarkBrandCitations];\n // Wikilinks and transclusions are added BEFORE resolveUrl so any href they\n // produce (wikilinks) flows through the URL resolver as a normal link would.\n // Transclusion embeds produce raw HTML nodes (not mdast links) so order\n // relative to resolveUrl is irrelevant, but we keep them together for clarity.\n if (resolveWikilink) list = [...list, remarkResolveWikilinks(resolveWikilink)];\n if (resolveTransclusion) list = [...list, remarkResolveTransclusions()];\n if (resolveUrl) list = [...list, remarkResolveUrls(resolveUrl)];\n return list;\n // `directiveNamesKey` already folds in `calc`/`toc`/`bibliography` when those\n // are set, so the plugin array tracks them without depending on identities.\n }, [\n resolveUrl,\n resolveWikilink,\n resolveTransclusion,\n directiveNamesKey,\n math,\n footnotes,\n resolveCitation,\n evaluateIteration,\n ]);\n\n const streamdown = (\n <Streamdown\n // Render as ONE block. Streamdown's default block-splitter (a streaming\n // optimization) severs a multi-line `:::` container directive from its\n // child content (e.g. a `:::timeline` from its list), so the directive\n // arrives empty. The preview re-renders the whole doc anyway, so a single\n // block is both correct and fine for authoring-sized documents.\n parseMarkdownIntoBlocksFn={singleBlock}\n remarkPlugins={plugins}\n rehypePlugins={rehypePlugins}\n allowedTags={allowedTags}\n components={components}\n >\n {markdown}\n </Streamdown>\n );\n // Academic contexts wrap the renderer only when their feature is on, so inline\n // cites + the bibliography share numbering and `::toc` reads the heading slugs.\n const withCitations = citations ? (\n <CitationProvider order={citations.order} byKey={citations.byKey} style={citationStyle}>\n {streamdown}\n </CitationProvider>\n ) : (\n streamdown\n );\n const body = outline ? (\n <TocProvider items={outline}>{withCitations}</TocProvider>\n ) : (\n withCitations\n );\n\n return (\n <div\n ref={ref}\n data-testid=\"markdown-preview\"\n // Reading rhythm (proximity grammar): headings carry 2–2.5× the space\n // ABOVE vs below — uniform block spacing reads like a teleprinter. The\n // `!` beats Streamdown's internal space-y sibling rule.\n className={cn(\n \"text-body text-foreground [&_pre]:my-3\",\n \"[&_h1]:!mt-10 [&_h2]:!mt-9 [&_h3]:!mt-7 [&_h4]:!mt-6\",\n \"[&_:is(h1,h2,h3,h4)+*]:!mt-3 [&_:is(h1,h2,h3,h4):first-child]:!mt-0\",\n className,\n )}\n {...props}\n >\n <AnnotationsContext.Provider value={shifted}>\n <SearchContext.Provider value={search}>\n <HeadingActionsContext.Provider value={headingActions ?? null}>\n <RegistryContext.Provider value={registry}>\n <LinkPreviewContext.Provider value={renderLinkPreview ?? null}>\n <TransclusionResolverContext.Provider value={resolveTransclusion ?? null}>\n <TransclusionDepthContext.Provider value={0}>\n {body}\n </TransclusionDepthContext.Provider>\n </TransclusionResolverContext.Provider>\n </LinkPreviewContext.Provider>\n </RegistryContext.Provider>\n </HeadingActionsContext.Provider>\n </SearchContext.Provider>\n </AnnotationsContext.Provider>\n </div>\n );\n },\n);\n\n/** The dialect features an iterated cell's nested preview inherits. */\ninterface IterationCellConfig {\n evaluateIteration?: EvaluateIteration;\n interpolate?: InterpolateTemplate;\n evaluate?: EvaluateCalc;\n extensions?: MarkdownExtensions;\n footnotes?: boolean;\n math?: boolean;\n resolveCitation?: ResolveCitation;\n citationStyle: CitationStyle;\n}\n\n/**\n * Renders one `:::iterate` cell's resolved markdown via a nested `MarkdownPreview`.\n * Defined OUTSIDE `MarkdownPreview` so the component isn't referenced inside its\n * own initializer (the forwardRef self-reference TS2786 — same reason transclusion\n * renders its own pipeline).\n */\nfunction IterationCell({ markdown, config }: { markdown: string; config: IterationCellConfig }) {\n return (\n <MarkdownPreview stripFrontmatter={false} {...config}>\n {markdown}\n </MarkdownPreview>\n );\n}\n\nexport type { MarkdownAnnotation, MarkdownAnnotationKind } from \"../lib/markdown/diff\";\n","/**\n * Shared remark pipeline for the brand markdown dialect.\n *\n * `remark-directive` parses generic container/leaf/text directives (`:::name`,\n * `::name`, `:name`). `remarkBrandDirectives` then rewrites the four brand blocks\n * — :::card / :::callout / ::metric / :::timeline — into a single `<brand-directive>`\n * element carrying a JSON `data-brand` payload, which the preview's components map\n * turns into real @brand components. Unknown directive names are preserved + flagged\n * so the preview can surface an \"unknown block\" error instead of silently dropping.\n *\n * One JSON attribute (not many) keeps it robust against Streamdown's HTML\n * sanitization (we only need to allow a single attribute through). The SAME plugin\n * array is fed to Streamdown (preview) and can be fed to Milkdown via `$remark`\n * (editor), so both sides parse `:::card` identically.\n */\nimport type { ReactNode } from \"react\";\nimport remarkDirective from \"remark-directive\";\nimport type { PluggableList } from \"unified\";\nimport { visit } from \"unist-util-visit\";\n\nexport const BRAND_DIRECTIVES = [\"card\", \"callout\", \"metric\", \"timeline\"] as const;\nexport type BrandDirectiveName = (typeof BRAND_DIRECTIVES)[number];\n\n/** Custom element BLOCK / LEAF directives are rewritten to. */\nexport const BRAND_DIRECTIVE_TAG = \"brand-directive\";\n/**\n * Custom element INLINE (text) directives are rewritten to. A SEPARATE tag (not\n * {@link BRAND_DIRECTIVE_TAG}) so the preview can render inline directives without\n * the block `<div>` wrappers the annotation/search layer adds to block tags —\n * keeping `:entity[name]` inside the text flow.\n */\nexport const BRAND_DIRECTIVE_INLINE_TAG = \"brand-directive-inline\";\n/** Rendered HTML attribute carrying the JSON payload (allow-list this in Streamdown). */\nexport const BRAND_DIRECTIVE_ATTR = \"data-brand\";\n/**\n * hast PROPERTY name (camelCase) for {@link BRAND_DIRECTIVE_ATTR}. This — not the\n * rendered `data-brand` — is what Streamdown's `allowedTags` must list to let the\n * payload survive sanitization.\n */\nexport const BRAND_DIRECTIVE_PROP = \"dataBrand\";\n\n/** Which directive syntax produced a node: `:::block`, `::leaf`, or `:inline`. */\nexport type MarkdownDirectiveKind = \"container\" | \"leaf\" | \"inline\";\n\nexport interface BrandDirectivePayload {\n name: string;\n known: boolean;\n kind: MarkdownDirectiveKind;\n attributes: Record<string, string>;\n items?: { title: string; status: string }[];\n /**\n * RAW label source for inline/leaf directives (`:calc[85 * 32]` → `85 * 32`).\n * Captured from source positions so markdown-significant characters in the\n * label (`*`, `_`, `[`) survive intact — the rendered children would mangle\n * them. Renderers that need the verbatim expression (calc) read this.\n */\n label?: string;\n /**\n * RAW container body source (the markdown between the `:::name` fences),\n * captured only for the directive names passed in `rawBodyNames` — e.g. the\n * per-cell TEMPLATE of an `:::iterate` block, which must be interpolated then\n * rendered, NOT shown pre-rendered. Captured from source positions.\n */\n body?: string;\n}\n\n/* ------------------------------------------------------------------ */\n/* Extension registry — the consumer-supplied render seam (the library */\n/* RENDERS; the consumer brings the renderer + any domain hook). One */\n/* registry feeds BOTH the parse-side known-set and the render dispatch. */\n/* ------------------------------------------------------------------ */\n\n/** Context handed to a consumer directive renderer. */\nexport interface MarkdownDirectiveContext {\n name: string;\n /** Which syntax matched — a renderer can branch (e.g. inline chip vs block card). */\n kind: MarkdownDirectiveKind;\n /** Directive attributes (`{key=value}`), strings only. */\n attributes: Record<string, string>;\n /** Rendered body (container), label (inline), or empty (leaf). */\n children: ReactNode;\n /**\n * RAW label text for inline/leaf directives (markdown-significant characters\n * preserved). Use this — not `children` — when you need the verbatim source\n * (e.g. a calc expression `85 * 32`). `undefined` for container directives.\n */\n textValue?: string;\n /**\n * RAW container body markdown (the source between the `:::name` fences). Only\n * populated for directives registered with `rawBodyNames` (e.g. `iterate` /\n * `pivot`), where the body is a TEMPLATE to interpolate + render per cell, not\n * to display pre-rendered. `undefined` otherwise.\n */\n rawBody?: string;\n}\n\n/** Register a custom `:::name` / `::name` / `:name` directive renderer. */\nexport interface MarkdownDirectiveRenderer {\n /** Directive name, e.g. `\"decision\"`, `\"entity\"`. */\n name: string;\n /** Accepted syntaxes. Default: all three. */\n kinds?: readonly MarkdownDirectiveKind[];\n render: (ctx: MarkdownDirectiveContext) => ReactNode;\n}\n\n/** Context handed to a consumer fence renderer. */\nexport interface MarkdownFenceContext {\n /** The fence body (trailing newline stripped). */\n source: string;\n /** The info-string language, e.g. `\"calc\"`. */\n lang: string;\n}\n\n/** Register a custom ```lang fenced-block renderer (the mermaid/calc seam). */\nexport interface MarkdownFenceRenderer {\n /** Info-string this renderer claims, e.g. `\"calc\"`. */\n lang: string;\n render: (ctx: MarkdownFenceContext) => ReactNode;\n}\n\n/**\n * Consumer extensions to the brand markdown dialect — passed to `MarkdownPreview`\n * via the `extensions` prop. Registered directive NAMES are also fed to the parser\n * (so `:entity[…]` is rewritten, while an unregistered `:foo` in prose stays\n * literal text), and the renderers drive the preview's dispatch. The engine is\n * never forked: new blocks register here.\n */\nexport interface MarkdownExtensions {\n directives?: readonly MarkdownDirectiveRenderer[];\n fences?: readonly MarkdownFenceRenderer[];\n}\n\ninterface MdNode {\n type: string;\n name?: string;\n value?: string;\n attributes?: Record<string, string | null | undefined>;\n children?: MdNode[];\n position?: { start?: { offset?: number }; end?: { offset?: number } };\n data?: { hName?: string; hProperties?: Record<string, unknown> };\n}\n\nconst DIRECTIVE_TYPES = new Set([\"containerDirective\", \"leafDirective\", \"textDirective\"]);\n\nfunction mdastText(node: MdNode): string {\n if (typeof node.value === \"string\") return node.value;\n if (node.children) return node.children.map(mdastText).join(\"\");\n return \"\";\n}\n\nfunction extractTimelineItems(node: MdNode): { title: string; status: string }[] {\n const list = node.children?.find((c) => c.type === \"list\");\n if (!list?.children) return [];\n // Status marker is a leading `(done)` / `(active)` / `(pending)` — parentheses\n // avoid markdown's `[ref]` link-reference collision. Default: pending.\n const MARKER = /^\\((done|complete|completed|active|current|pending|todo)\\)\\s*/i;\n return list.children\n .filter((c) => c.type === \"listItem\")\n .map((li) => {\n let title = mdastText(li).trim();\n let status = \"pending\";\n const marker = title.match(MARKER);\n if (marker) {\n status = marker[1]!.toLowerCase();\n title = title.slice(marker[0].length).trim();\n }\n return { title, status };\n });\n}\n\nfunction cleanAttributes(attrs: MdNode[\"attributes\"]): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(attrs ?? {})) {\n if (typeof v === \"string\") out[k] = v;\n }\n return out;\n}\n\n/**\n * Reconstruct a directive's ORIGINAL source text. Prose colons routinely\n * pattern-match remark-directive's text/leaf forms (`qwen3:0.6b` parses as a\n * `:0` text directive and swallows the \"0\") — restoring the source slice is\n * the only faithful undo.\n */\nfunction originalText(node: MdNode, source: string | undefined): string {\n const start = node.position?.start?.offset;\n const end = node.position?.end?.offset;\n if (source != null && typeof start === \"number\" && typeof end === \"number\") {\n return source.slice(start, end);\n }\n // Position unavailable — best-effort reconstruction.\n const colons = node.type === \"leafDirective\" ? \"::\" : \":\";\n const label = node.children?.length ? `[${mdastText(node)}]` : \"\";\n return `${colons}${node.name ?? \"\"}${label}`;\n}\n\n/** mdast node type → the directive kind it represents. */\nfunction directiveKind(type: string): MarkdownDirectiveKind {\n if (type === \"containerDirective\") return \"container\";\n if (type === \"leafDirective\") return \"leaf\";\n return \"inline\";\n}\n\n/**\n * The RAW label source of a directive (`:name[label]`) — sliced from the original\n * source via the label children's positions, so markdown-significant characters\n * (`*`, `_`, `[`) survive instead of being parsed into emphasis/links.\n */\nfunction rawLabel(node: MdNode, source: string | undefined): string | undefined {\n const kids = node.children;\n if (!source || !kids || kids.length === 0) return undefined;\n const start = kids[0]?.position?.start?.offset;\n const end = kids[kids.length - 1]?.position?.end?.offset;\n if (typeof start === \"number\" && typeof end === \"number\") return source.slice(start, end);\n return undefined;\n}\n\n/**\n * The RAW body source of a CONTAINER directive — the markdown between the\n * `:::name{…}` opening and the closing `:::`. Skips a leading directive label\n * (`:::name[label]`) child. Used for templated containers (`:::iterate`) whose\n * body must be interpolated then rendered, not shown pre-rendered.\n */\nfunction rawContainerBody(node: MdNode, source: string | undefined): string | undefined {\n const kids = node.children;\n if (!source || !kids || kids.length === 0) return undefined;\n const body = kids.filter(\n (c) => !(c.data as { directiveLabel?: boolean } | undefined)?.directiveLabel,\n );\n if (body.length === 0) return undefined;\n const start = body[0]?.position?.start?.offset;\n const end = body[body.length - 1]?.position?.end?.offset;\n if (typeof start === \"number\" && typeof end === \"number\") return source.slice(start, end).trim();\n return undefined;\n}\n\n/**\n * remark transform: brand directives → `<brand-directive data-brand=\"{json}\">`\n * (block/leaf) or `<brand-directive-inline …>` (inline).\n *\n * `knownNames` is the set of directive names to TREAT AS KNOWN — i.e. rewrite\n * rather than restore. It defaults to the four built-ins; `MarkdownPreview`\n * extends it with the names a consumer registered via `extensions`, so a\n * registered `:entity[…]` is rewritten while an unregistered `:foo` (or a stray\n * prose colon) is still restored to literal text.\n */\nexport function remarkBrandDirectives(\n knownNames: readonly string[] = BRAND_DIRECTIVES,\n rawBodyNames: readonly string[] = [],\n) {\n return (tree: unknown, file?: { value?: unknown }) => {\n const source = typeof file?.value === \"string\" ? file.value : undefined;\n visit(tree as never, (node: MdNode, index: number | undefined, parent: MdNode | undefined) => {\n if (!DIRECTIVE_TYPES.has(node.type) || !node.name) return undefined;\n\n const name = node.name;\n const known = knownNames.includes(name);\n const kind = directiveKind(node.type);\n\n // Unknown text/leaf directives are almost always FALSE POSITIVES from\n // ordinary colons in prose — restore them as literal text. Only an\n // unknown CONTAINER (`:::name`, deliberately authored) keeps the\n // explicit unknown-block error.\n if (!known && node.type !== \"containerDirective\" && parent?.children && index != null) {\n const literal: MdNode = { type: \"text\", value: originalText(node, source) };\n parent.children.splice(\n index,\n 1,\n node.type === \"leafDirective\"\n ? ({ type: \"paragraph\", children: [literal] } as MdNode)\n : literal,\n );\n return index + 1; // continue after the replacement\n }\n\n const payload: BrandDirectivePayload = {\n name,\n known,\n kind,\n attributes: cleanAttributes(node.attributes),\n };\n\n // Inline/leaf directives carry a verbatim label (e.g. a calc expression).\n if (kind !== \"container\") {\n const label = rawLabel(node, source);\n if (label != null) payload.label = label;\n }\n\n // Templated containers (`:::iterate`/`:::pivot`) carry their RAW body so the\n // renderer can interpolate + render it per cell. Clear the children so the\n // template is NOT also rendered pre-interpolated (mirrors timeline).\n if (kind === \"container\" && rawBodyNames.includes(name)) {\n const body = rawContainerBody(node, source);\n if (body != null) payload.body = body;\n node.children = [];\n }\n\n if (name === \"timeline\") {\n payload.items = extractTimelineItems(node);\n node.children = []; // consumed into payload.items\n }\n\n const data = node.data ?? (node.data = {});\n // Inline directives keep their children (the label) and use a SEPARATE tag\n // so the preview renders them inline (no block wrapper).\n data.hName = kind === \"inline\" ? BRAND_DIRECTIVE_INLINE_TAG : BRAND_DIRECTIVE_TAG;\n // camelCase hast property → renders as the `data-brand` attribute.\n data.hProperties = { [BRAND_DIRECTIVE_PROP]: JSON.stringify(payload) };\n });\n };\n}\n\n/** Options for {@link buildMarkdownPlugins}. */\nexport interface BuildMarkdownPluginsOptions {\n /**\n * Extra directive names to treat as known (rewritten, not restored as literal\n * text). The four built-ins are always known; pass the names a consumer\n * registered via `extensions.directives`.\n */\n directiveNames?: readonly string[];\n /**\n * Container directive names whose RAW body should be captured (as\n * `payload.body` / `ctx.rawBody`) instead of pre-rendered — for templated\n * blocks like `iterate` / `pivot` whose body is interpolated per cell.\n */\n rawBodyNames?: readonly string[];\n}\n\n/**\n * The shared remark plugin array (directive parsing + brand mapping). Pass\n * `directiveNames` to recognize consumer-registered directives without forking\n * the engine; with no options it parses exactly the four built-ins (backward\n * compatible).\n */\nexport function buildMarkdownPlugins(options: BuildMarkdownPluginsOptions = {}): PluggableList {\n const known =\n options.directiveNames && options.directiveNames.length > 0\n ? [...BRAND_DIRECTIVES, ...options.directiveNames]\n : BRAND_DIRECTIVES;\n const rawBodyNames = options.rawBodyNames ?? [];\n return [remarkDirective, [remarkBrandDirectives, known, rawBodyNames]];\n}\n","\"use client\";\n\n/**\n * CalcBlock — render a ```calc fence as a two-column \"sheet\" (#L1).\n *\n * The Soulver/Notes-Calculator model: expressions on the left, computed answers\n * on the right (`tabular-nums`), a running-total footer. The library RENDERS and\n * the consumer EVALUATES: the math engine is app/domain logic, so CalcBlock takes\n * an `evaluate(source) => CalcSheet` hook (mirroring `MarkdownPreview`'s\n * `resolveUrl`) and bundles no calculator. Per-line errors render inline; a bad\n * block never throws or blanks the document. The mermaid fence is the precedent.\n *\n * Title: a leading `# Heading` becomes the block title (header bar); with none,\n * the header shows the neutral `calc` code-label.\n *\n * Row presentation — a per-row `rule` divider (dotted / single / double) and a\n * semantic `tint` wash — comes from two sources, both pure presentation:\n * 1. the evaluator, as `rule`/`tint` fields on a `CalcLineResult` (app-driven); or\n * 2. a trailing author **marker** the WRITER types in the calc text, which\n * CalcBlock strips before calling `evaluate` (so the math engine never sees\n * it) — the same way it strips `# ` off a heading. Tints: `@primary`,\n * `@success`, `@warning`, `@danger`, `@info`, `@muted`/`@note`. Rules:\n * `@line`, `@line2`/`@double`, `@dotted`. Multiple markers per line compose\n * (`subtotal = a + b @success @line`); an evaluator field wins over a marker.\n * Disable parsing with `markers={false}`. Unknown trailing `@words` are left\n * as literal text (never silently dropped).\n *\n * The footer total defaults to `sheet.total` but can be overridden via the\n * `total` / `totalLabel` props.\n *\n * Syntax highlighting uses the dedicated `--calc-*` tokens (#221) via `text-calc-*`;\n * color is never the only signal (var-def = weight, unresolved = dotted underline),\n * so roles stay distinct in the high-contrast theme.\n */\nimport { useLocale } from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { TriangleAlert } from \"lucide-react\";\nimport { forwardRef, useId, useMemo, type HTMLAttributes, type ReactNode } from \"react\";\n\nimport type {\n CalcLineResult,\n CalcRule,\n CalcTint,\n CalcToken,\n CalcTokenKind,\n CalcValue,\n EvaluateCalc,\n} from \"./types\";\n// Carry the `.brand-calc-tok--<role>` role colours, so the RENDERED block reads\n// identically to the editor authoring surfaces (which import the same stylesheet).\nimport \"./calc-editor.css\";\n\nexport interface CalcBlockProps extends Omit<HTMLAttributes<HTMLElement>, \"children\" | \"title\"> {\n /** The ```calc fence body. */\n source: string;\n /** Consumer-supplied evaluator (sync). The library bundles no math engine. */\n evaluate: EvaluateCalc;\n /**\n * Block title shown in the header bar. By default a leading `# Heading` line in\n * `source` is lifted here; with neither prop nor heading the header shows the\n * neutral `calc` code-label. Pass `title` to override the displayed text.\n */\n title?: ReactNode;\n /** Show the running-total footer. Default true. */\n showTotal?: boolean;\n /**\n * Override the footer total. Defaults to `sheet.total`. Pass a `CalcValue`\n * (rendered tabular via its `.display`) or any ReactNode to replace the\n * computed total — e.g. a different aggregate the evaluator didn't surface.\n */\n total?: CalcValue | ReactNode;\n /** Footer label. Default `Total`. */\n totalLabel?: ReactNode;\n /**\n * Parse trailing author markers (`@success`, `@line`, …) out of each source\n * line — applying the row's tint/rule and stripping the marker from the\n * rendered text. Default `true`. Set `false` if your calc dialect uses a\n * trailing `@token` for something else.\n */\n markers?: boolean;\n /** Reserved for the editing variant (CalcWorkspace); preview is read-only. */\n readOnly?: boolean;\n}\n\n/** Author marker keyword → semantic tint (friendly words; `@danger` = destructive). */\nconst TINT_MARKERS: Record<string, CalcTint> = {\n primary: \"primary\",\n success: \"success\",\n warning: \"warning\",\n danger: \"destructive\",\n destructive: \"destructive\",\n info: \"info\",\n muted: \"muted\",\n note: \"muted\",\n};\n\n/** Author marker keyword → rule (divider) style. */\nconst RULE_MARKERS: Record<string, CalcRule> = {\n line: \"single\",\n rule: \"single\",\n line2: \"double\",\n double: \"double\",\n dotted: \"dotted\",\n};\n\n/** A line's parsed presentation, after author markers are stripped from the text. */\ninterface LineMarkers {\n text: string;\n tint?: CalcTint;\n rule?: CalcRule;\n}\n\n/**\n * Strip recognized trailing `@marker`s off a line (right-to-left), returning the\n * cleaned text plus the tint/rule they request. An unrecognized trailing `@word`\n * halts stripping and is kept as literal text — markers only ever bind at the end.\n */\nfunction parseMarkers(line: string): LineMarkers {\n let text = line;\n let tint: CalcTint | undefined;\n let rule: CalcRule | undefined;\n for (;;) {\n const m = /\\s+@([A-Za-z][A-Za-z0-9]*)\\s*$/.exec(text);\n if (!m) break;\n const key = (m[1] ?? \"\").toLowerCase();\n if (key in TINT_MARKERS) {\n tint ??= TINT_MARKERS[key];\n } else if (key in RULE_MARKERS) {\n rule ??= RULE_MARKERS[key];\n } else {\n break; // unknown trailing @word — leave it (and everything before) as text\n }\n text = text.slice(0, m.index);\n }\n return { text, tint, rule };\n}\n\n/** Per-row rule (divider) presentation. `border-strong` is the sole same-surface cue. */\nconst RULE_CLASS: Record<CalcRule, string> = {\n dotted: \"border-b border-dotted border-border-strong pb-1\",\n single: \"border-b border-border-strong pb-1\",\n double: \"border-b-4 border-double border-border-strong pb-1\",\n};\n\n/** Per-row background tint — semantic status washes (theme-safe), `muted` neutral. */\nconst TINT_CLASS: Record<CalcTint, string> = {\n primary: \"bg-primary/10\",\n success: \"bg-success/10\",\n warning: \"bg-warning/10\",\n destructive: \"bg-destructive/10\",\n info: \"bg-info/10\",\n muted: \"bg-muted\",\n};\n\n/** Narrow a `total` override to a `CalcValue` (vs a plain ReactNode like a string). */\nfunction isCalcValue(x: unknown): x is CalcValue {\n return typeof x === \"object\" && x !== null && !(\"$$typeof\" in x) && \"kind\" in x && \"display\" in x;\n}\n\n/**\n * Token kind → highlight class. Color comes from the dedicated `--calc-*` syntax\n * tokens (#221) via the `text-calc-*` utilities; the `brand-calc-tok--<role>`\n * class carries a role-specific, color-independent cue (weight / style / underline)\n * in low-chroma themes (#226) — so in high-contrast, where every inline calc token\n * collapses to one ink, number / unit / currency / var-ref / line-ref / unknown\n * stay distinguishable. The SAME classes drive the editor decorations\n * (calc-editor.css), so both surfaces read identically.\n */\nfunction tokenClass(kind: CalcTokenKind, resolved: boolean): string {\n let base: string;\n let role: string;\n switch (kind) {\n case \"comment\":\n base = \"text-calc-comment italic\";\n role = \"brand-calc-tok--comment\";\n break;\n case \"operator\":\n base = \"text-calc-operator\";\n role = \"brand-calc-tok--operator\";\n break;\n case \"unit\":\n base = \"text-calc-unit\";\n role = \"brand-calc-tok--unit\";\n break;\n case \"currency\":\n base = \"text-calc-currency\";\n role = \"brand-calc-tok--currency\";\n break;\n case \"function\":\n base = \"text-calc-function\";\n role = \"brand-calc-tok--function\";\n break;\n case \"var-ref\":\n base = \"text-calc-variable\";\n role = \"brand-calc-tok--var-ref\";\n break;\n case \"line-ref\":\n base = \"text-calc-reference tabular-nums\";\n role = \"brand-calc-tok--line-ref\";\n break;\n case \"var-def\":\n base = \"text-calc-variable font-medium\";\n role = \"brand-calc-tok--var-def\";\n break;\n case \"unknown\":\n base = \"text-calc-warning\";\n role = \"brand-calc-tok--unknown\";\n break;\n default: // number, constant\n base = \"text-calc-number\";\n role = \"brand-calc-tok--number\";\n }\n return cn(\n \"brand-calc-tok\",\n role,\n base,\n !resolved && \"underline decoration-dotted decoration-1 underline-offset-2\",\n );\n}\n\n/** Paint one source line: tokenized spans with plain text in the gaps. */\nfunction renderSource(text: string, tokens: CalcToken[]): ReactNode {\n const out: ReactNode[] = [];\n let cursor = 0;\n for (const [i, t] of tokens.entries()) {\n if (t.start > cursor) {\n out.push(<span key={`gap-${String(i)}`}>{text.slice(cursor, t.start)}</span>);\n }\n out.push(\n <span key={`tok-${String(i)}`} className={tokenClass(t.kind, t.resolved)}>\n {text.slice(t.start, t.end)}\n </span>,\n );\n cursor = t.end;\n }\n if (cursor < text.length) out.push(<span key=\"tail\">{text.slice(cursor)}</span>);\n if (out.length === 0) out.push(<span key=\"empty\">{text || \" \"}</span>);\n return out;\n}\n\n/** The right-hand cell: a value, a calm error marker, or nothing. */\nfunction ResultCell({ result }: { result: CalcLineResult }): ReactNode {\n const { t } = useLocale();\n if (result.error) {\n // Native `title` (not a Radix Tooltip) so CalcBlock is self-contained — it\n // renders inside MarkdownPreview / a story with no TooltipProvider ancestor.\n return (\n <span\n className=\"inline-flex shrink-0 text-calc-warning\"\n title={result.error.message}\n aria-label={t(\"editor.calcBlock.error\", { message: result.error.message })}\n >\n <TriangleAlert className=\"size-3.5\" aria-hidden=\"true\" />\n </span>\n );\n }\n if (result.value) {\n return (\n <div className=\"brand-calc-tok--result shrink-0 tabular-nums text-calc-result\">\n <span className=\"sr-only\">{t(\"editor.calcBlock.equals\")}</span>\n <span>{result.value.display}</span>\n </div>\n );\n }\n return null;\n}\n\nexport const CalcBlock = forwardRef<HTMLDivElement, CalcBlockProps>(function CalcBlock(\n {\n source,\n evaluate,\n title,\n showTotal = true,\n total,\n totalLabel: totalLabelProp,\n markers = true,\n readOnly: _readOnly,\n className,\n ...props\n },\n ref,\n) {\n const { t } = useLocale();\n const totalLabel = totalLabelProp ?? t(\"editor.calcBlock.total\");\n // Author markers are stripped BEFORE evaluation: the math engine sees clean\n // lines, and because markers are trailing, token columns stay aligned with the\n // rendered (cleaned) text. `lines`/`evalSource` are the marker-free versions.\n const { lines, evalSource, hints } = useMemo(() => {\n const raw = source.split(\"\\n\");\n if (!markers) return { lines: raw, evalSource: source, hints: [] as LineMarkers[] };\n const parsed = raw.map(parseMarkers);\n return {\n lines: parsed.map((p) => p.text),\n evalSource: parsed.map((p) => p.text).join(\"\\n\"),\n hints: parsed,\n };\n }, [source, markers]);\n\n const sheet = useMemo(() => evaluate(evalSource), [evaluate, evalSource]);\n const empty = evalSource.trim() === \"\";\n const titleId = useId();\n\n // A leading `# Heading` is the block title (lifted to the header bar) and is not\n // repeated in the body. Later `#` lines stay as in-body section headings.\n const { titleLine, derivedTitle } = useMemo(() => {\n const idx = lines.findIndex((l) => l.trim() !== \"\");\n const first = (lines[idx] ?? \"\").trim();\n return /^#+\\s+/.test(first)\n ? { titleLine: idx + 1, derivedTitle: first.replace(/^#+\\s*/, \"\") }\n : { titleLine: 0, derivedTitle: undefined as string | undefined };\n }, [lines]);\n\n const hasTitle = title != null || derivedTitle != null;\n const resolvedTitle = title ?? derivedTitle ?? \"calc\";\n\n const resolvedTotal = total ?? sheet.total;\n const totalDisplay = isCalcValue(resolvedTotal) ? resolvedTotal.display : resolvedTotal;\n\n const rows: ReactNode[] = [];\n for (const result of sheet.results) {\n if (result.line === titleLine) continue; // lifted to the header bar\n const text = lines[result.line - 1] ?? \"\";\n const key = `row-${String(result.line)}`;\n if (text.trim() === \"\") {\n rows.push(<div key={key} className=\"h-1.5\" aria-hidden=\"true\" />);\n continue;\n }\n if (text.trim().startsWith(\"#\")) {\n rows.push(\n <div key={key} className=\"pt-1 font-semibold text-foreground first:pt-0\">\n {text.replace(/^#+\\s*/, \"\")}\n </div>,\n );\n continue;\n }\n // An evaluator-set field wins over an author marker; otherwise the marker applies.\n const hint = hints[result.line - 1];\n const rule = result.rule ?? hint?.rule;\n const tint = result.tint ?? hint?.tint;\n rows.push(\n <div\n key={key}\n data-rule={rule}\n data-tint={tint}\n className={cn(\n \"flex items-baseline justify-between gap-x-6\",\n rule && RULE_CLASS[rule],\n tint != null && cn(\"-mx-2 rounded-sm px-2\", TINT_CLASS[tint]),\n )}\n >\n <div className=\"min-w-0 whitespace-pre-wrap break-words text-foreground\">\n {renderSource(text, result.tokens)}\n </div>\n <ResultCell result={result} />\n </div>,\n );\n }\n\n return (\n <div\n ref={ref}\n data-testid=\"calc-block\"\n role=\"group\"\n aria-labelledby={titleId}\n className={cn(\"my-4 overflow-hidden rounded-md border border-border bg-card\", className)}\n {...props}\n >\n <div className=\"border-b border-border px-4 py-1.5\">\n <span\n id={titleId}\n className={cn(\n \"text-meta\",\n hasTitle\n ? \"font-medium text-foreground\"\n : \"font-mono uppercase tracking-wide text-muted-foreground\",\n )}\n >\n {resolvedTitle}\n </span>\n </div>\n\n {empty ? (\n <p className=\"px-4 py-6 text-body text-muted-foreground\">\n {t(\"editor.calcBlock.emptyBlock\")}\n </p>\n ) : (\n <div className=\"flex flex-col gap-y-1 px-4 py-3 font-mono text-code leading-relaxed\">\n {rows}\n </div>\n )}\n\n {showTotal && resolvedTotal != null && !empty ? (\n <div className=\"flex items-center justify-between border-t border-border px-4 py-2\">\n <span className=\"text-eyebrow uppercase text-muted-foreground\">{totalLabel}</span>\n <span className=\"font-mono text-code font-medium tabular-nums text-foreground\">\n {totalDisplay}\n </span>\n </div>\n ) : null}\n </div>\n );\n});\n","\"use client\";\n\n/**\n * CalcInline — an inline `:calc[expr]` directive rendered as a result chip (#L).\n *\n * The inline sibling of {@link CalcBlock}, same contract: the library RENDERS, the\n * consumer EVALUATES. `evaluate(expr)` returns a `CalcSheet`; the chip shows the\n * first line's value (the expression's result) with the verbatim source as a\n * native hover `title` and in the accessible name (`\"85 USD * 32 = 2,720 USD\"`). A\n * bad expression renders a calm inline warning — it never throws or blanks the\n * sentence. A native `title` (not a Radix Tooltip) keeps the chip self-contained,\n * so it drops into rendered prose with no `TooltipProvider` ancestor.\n *\n * Color comes from the shared `--calc-*` tokens (#221): the result reads in\n * `text-calc-result`; the warning cue is the icon + dotted underline, never hue\n * alone (so it survives the high-contrast theme).\n */\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { TriangleAlert } from \"lucide-react\";\nimport { forwardRef, useMemo, type HTMLAttributes } from \"react\";\n\nimport type { EvaluateCalc } from \"./types\";\n\nexport interface CalcInlineProps extends Omit<HTMLAttributes<HTMLElement>, \"children\"> {\n /** The inline expression, e.g. `85 USD * 32`. */\n source: string;\n /** Consumer-supplied evaluator (sync). The library bundles no math engine. */\n evaluate: EvaluateCalc;\n}\n\nexport const CalcInline = forwardRef<HTMLSpanElement, CalcInlineProps>(function CalcInline(\n { source, evaluate, className, ...props },\n ref,\n) {\n const sheet = useMemo(() => evaluate(source), [evaluate, source]);\n const first = sheet.results[0];\n const display = first?.value?.display;\n const error = first?.error ?? (display == null ? { message: \"No result\" } : undefined);\n\n if (error) {\n return (\n <span\n ref={ref}\n data-testid=\"calc-inline\"\n data-calc-error=\"\"\n title={error.message}\n aria-label={`${source}: ${error.message}`}\n className={cn(\n \"inline-flex items-center gap-0.5 align-baseline font-mono text-calc-warning underline decoration-dotted decoration-1 underline-offset-2\",\n className,\n )}\n {...props}\n >\n <TriangleAlert className=\"size-3\" aria-hidden=\"true\" />\n <span>{source}</span>\n </span>\n );\n }\n\n return (\n <span\n ref={ref}\n data-testid=\"calc-inline\"\n title={source}\n aria-label={`${source} = ${display}`}\n className={cn(\n \"inline-flex items-center rounded-sm bg-calc-result/10 px-1 align-baseline font-mono tabular-nums text-calc-result\",\n className,\n )}\n {...props}\n >\n {display}\n </span>\n );\n});\n","\"use client\";\n\n/**\n * MermaidDiagram — the branded Mermaid renderer (#L1).\n *\n * Renders a ```mermaid source string as an SVG diagram, themed from the active\n * semantic tokens (no raw colors here): the mermaid engine is initialized with\n * `theme: \"base\"` + `themeVariables` resolved at render time from the CSS\n * variables in scope, so the diagram follows every `data-theme` — including\n * runtime switches (a MutationObserver re-renders on theme change).\n *\n * The `mermaid` package is loaded lazily on first render, so consumers that\n * never show a diagram never download the engine. Invalid sources render an\n * inline error block (message + source), never a thrown render.\n */\nimport { Button, Dialog, DialogContent, DialogTitle, useLocale } from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { Download, Maximize2 } from \"lucide-react\";\nimport { forwardRef, useEffect, useRef, useState, type HTMLAttributes } from \"react\";\n\nimport { oklchToHex } from \"@elabs-ai/components-tokens\";\n\nimport { CopyButton } from \"../copy-button\";\nimport { MermaidViewer } from \"./mermaid-viewer\";\nimport { offendingToken, remediateReservedIds } from \"./remediate\";\n\nexport interface MermaidDiagramProps extends HTMLAttributes<HTMLDivElement> {\n /** Mermaid source (the fence body). */\n chart: string;\n /** Accessible name for the rendered diagram. Default \"Diagram\". */\n label?: string;\n /** Show the hover copy-source button. Default true. */\n copyable?: boolean;\n /** Show the hover expand-to-modal button. Default true. */\n expandable?: boolean;\n /**\n * In-document search term (≥2 chars): nodes/edge labels whose text contains\n * it get the hit stroke — the diagram participates in document search.\n */\n highlightTerm?: string;\n /**\n * Source text of the ACTIVE search hit (the clicked finding's line). The\n * matching hit is promoted to the primary \"active\" stroke.\n */\n activeText?: string;\n}\n\n/** Semantic token → mermaid `themeVariables` mapping (resolved per render). */\nconst TOKEN_VARS: Record<string, string> = {\n background: \"--background\",\n mainBkg: \"--card\",\n primaryColor: \"--muted\",\n primaryTextColor: \"--foreground\",\n primaryBorderColor: \"--border-strong\",\n secondaryColor: \"--secondary\",\n tertiaryColor: \"--muted\",\n lineColor: \"--muted-foreground\",\n textColor: \"--foreground\",\n nodeBorder: \"--border-strong\",\n clusterBkg: \"--surface-muted\",\n clusterBorder: \"--border\",\n titleColor: \"--foreground\",\n edgeLabelBackground: \"--background\",\n errorBkgColor: \"--destructive\",\n errorTextColor: \"--destructive-foreground\",\n};\n\nlet renderSeq = 0;\n\n/**\n * Serializes every `mermaid.initialize()` + `mermaid.render()` pair across\n * every `MermaidDiagram` instance on the page.\n *\n * The `mermaid` package configures itself through ONE module-level global\n * (`mermaid.initialize`/`setConfig`) — `render()` takes no per-call config —\n * so two diagrams rendering concurrently (e.g. under different `data-theme`\n * scopes, or just two diagrams mounting together) can interleave: instance A\n * calls `initialize({theme: A})`, then before A's `render()` finishes reading\n * it, instance B calls `initialize({theme: B})` and A's diagram comes out\n * themed as B. Routing every render through this queue makes \"initialize,\n * then render\" atomic with respect to every other instance.\n */\nlet mermaidRenderQueue: Promise<unknown> = Promise.resolve();\n\nfunction withMermaidLock<T>(task: () => Promise<T>): Promise<T> {\n const result = mermaidRenderQueue.then(task, task);\n // Never let a failed render break the chain for the next caller.\n mermaidRenderQueue = result.then(\n () => undefined,\n () => undefined,\n );\n return result;\n}\n\n/**\n * How long to let `chart` sit unchanged before actually rendering it — a\n * source streamed in token-by-token (an LLM authoring one live) would\n * otherwise trigger a full mermaid parse + layout on every partial,\n * malformed intermediate string.\n */\nconst RENDER_DEBOUNCE_MS = 300;\n\n/**\n * Search-hit strokes for rendered nodes — token-driven, shared by the inline\n * render and the expanded viewer (a `<style>` is document-global wherever it\n * mounts, so one copy per diagram instance is enough).\n */\nconst HIT_CSS = `\n .wb-dg-hit :is(rect, polygon, circle, ellipse, path.basic) { stroke: var(--warning) !important; stroke-width: 2.5px !important; }\n .wb-dg-hit-active :is(rect, polygon, circle, ellipse, path.basic) { stroke: var(--primary) !important; stroke-width: 3px !important; }\n .wb-dg-hit.edgeLabel { outline: 2px solid var(--warning); border-radius: 2px; }\n .wb-dg-hit-active.edgeLabel { outline: 2px solid var(--primary); border-radius: 2px; }\n`;\n\n/** Does mermaid's color lib (khroma) understand this format already? */\nconst KHROMA_SAFE_RE = /^(#|rgba?\\(|hsla?\\()/i;\n\n/**\n * Normalize any CSS color (incl. oklch tokens) to a hex/rgb string the mermaid\n * engine (khroma) can manipulate. oklch converts mathematically (browsers do\n * NOT re-serialize it to rgb — Chromium's canvas keeps the oklch string);\n * anything else unknown falls back to canvas serialization, then raw.\n */\nfunction normalizeColor(value: string, ctx: CanvasRenderingContext2D | null): string {\n const v = value.trim();\n if (!v || KHROMA_SAFE_RE.test(v)) return v;\n const fromOklch = oklchToHex(v);\n if (fromOklch) return fromOklch;\n if (ctx) {\n try {\n ctx.fillStyle = \"#000\";\n ctx.fillStyle = v;\n if (KHROMA_SAFE_RE.test(ctx.fillStyle)) return ctx.fillStyle;\n } catch {\n // fall through to raw\n }\n }\n return v;\n}\n\nfunction resolveThemeVariables(el: HTMLElement): Record<string, string> {\n const styles = getComputedStyle(el);\n let ctx: CanvasRenderingContext2D | null = null;\n try {\n ctx = document.createElement(\"canvas\").getContext(\"2d\");\n } catch {\n ctx = null;\n }\n const vars: Record<string, string> = {\n fontFamily: styles.getPropertyValue(\"--font-sans\").trim() || \"inherit\",\n };\n for (const [mermaidVar, token] of Object.entries(TOKEN_VARS)) {\n const raw = styles.getPropertyValue(token).trim();\n if (raw) vars[mermaidVar] = normalizeColor(raw, ctx);\n }\n return vars;\n}\n\nexport const MermaidDiagram = forwardRef<HTMLDivElement, MermaidDiagramProps>(\n function MermaidDiagram(\n {\n chart,\n label: labelProp,\n copyable = true,\n expandable = true,\n highlightTerm,\n activeText,\n className,\n ...props\n },\n ref,\n ) {\n const { t } = useLocale();\n const label = labelProp ?? t(\"editor.mermaidDiagram.label\");\n const hostRef = useRef<HTMLDivElement | null>(null);\n const svgHostRef = useRef<HTMLDivElement | null>(null);\n const [svg, setSvg] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [expanded, setExpanded] = useState(false);\n\n const downloadSvg = () => {\n if (!svg) return;\n const blob = new Blob([svg], { type: \"image/svg+xml\" });\n const url = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = `${label.toLowerCase().replace(/[^a-z0-9]+/g, \"-\") || \"diagram\"}.svg`;\n a.click();\n // Defer the revoke past the current task: some browsers (Safari) start\n // the save asynchronously off the click and cancel it if the object URL\n // is invalidated too early.\n setTimeout(() => URL.revokeObjectURL(url), 0);\n };\n // Bumped by the observer when the governing data-theme changes.\n const [themeVersion, setThemeVersion] = useState(0);\n\n useEffect(() => {\n const host = hostRef.current;\n if (!host) return;\n const scope = host.closest(\"[data-theme]\") ?? document.documentElement;\n const observer = new MutationObserver(() => setThemeVersion((v) => v + 1));\n observer.observe(scope, { attributes: true, attributeFilter: [\"data-theme\"] });\n return () => observer.disconnect();\n }, []);\n\n useEffect(() => {\n let cancelled = false;\n const host = hostRef.current;\n if (!host || !chart.trim()) {\n setSvg(null);\n setError(null);\n return;\n }\n // Debounce: a `chart` fed from a streaming source changes on every\n // token, and a mermaid parse + layout is not cheap enough to run on\n // every one of those partial, often-invalid intermediate strings — wait\n // for the source to sit still for RENDER_DEBOUNCE_MS first.\n const timer = setTimeout(() => {\n void withMermaidLock(async () => {\n if (cancelled) return;\n try {\n const mermaid = (await import(\"mermaid\")).default;\n if (cancelled) return;\n mermaid.initialize({\n startOnLoad: false,\n securityLevel: \"strict\",\n suppressErrorRendering: true,\n theme: \"base\",\n themeVariables: resolveThemeVariables(host),\n });\n const render = (source: string) =>\n mermaid.render(`brand-mermaid-${++renderSeq}`, source);\n let out;\n try {\n out = await render(chart);\n } catch (firstErr) {\n // Reserved-keyword node ids (\"graph[...]\", \"end[...]\") are the\n // most common authoring mistake — remediate the id (labels stay)\n // and retry once instead of failing the reader.\n const token = offendingToken(\n firstErr instanceof Error ? firstErr.message : String(firstErr),\n );\n const fixed = token ? remediateReservedIds(chart, token) : null;\n if (!fixed) throw firstErr;\n out = await render(fixed);\n }\n if (cancelled) return;\n setSvg(out.svg);\n setError(null);\n } catch (err) {\n if (cancelled) return;\n setSvg(null);\n setError(err instanceof Error ? err.message : String(err));\n }\n });\n }, RENDER_DEBOUNCE_MS);\n return () => {\n cancelled = true;\n clearTimeout(timer);\n };\n }, [chart, themeVersion]);\n\n // Mark search hits on the rendered nodes (class toggles only — the SVG\n // markup is mermaid's; we never rebuild it for a highlight change).\n useEffect(() => {\n const root = svgHostRef.current;\n if (!root) return;\n const term = (highlightTerm ?? \"\").trim().toLowerCase();\n const active = (activeText ?? \"\").trim().toLowerCase();\n for (const node of root.querySelectorAll<SVGGElement>(\"g.node, g.edgeLabel\")) {\n const text = (node.textContent ?? \"\").trim().toLowerCase();\n const hit = term.length >= 2 && text.length > 0 && text.includes(term);\n node.classList.toggle(\"wb-dg-hit\", hit);\n node.classList.toggle(\n \"wb-dg-hit-active\",\n hit && active.length > 0 && (active.includes(text) || text.includes(active)),\n );\n }\n }, [svg, highlightTerm, activeText]);\n\n return (\n <div\n ref={(el) => {\n hostRef.current = el;\n if (typeof ref === \"function\") ref(el);\n else if (ref) ref.current = el;\n }}\n data-testid=\"mermaid-diagram\"\n className={cn(\"group/mermaid relative\", className)}\n {...props}\n >\n {svg && (copyable || expandable) ? (\n <div className=\"absolute end-2 top-2 z-10 flex gap-1 opacity-0 transition-opacity duration-fast ease-standard focus-within:opacity-100 group-hover/mermaid:opacity-100 motion-reduce:transition-none\">\n {expandable ? (\n <Button\n variant=\"outline\"\n size=\"icon-sm\"\n aria-label={t(\"editor.mermaidDiagram.expand\")}\n onClick={() => setExpanded(true)}\n >\n <Maximize2 className=\"size-3.5\" />\n </Button>\n ) : null}\n <Button\n variant=\"outline\"\n size=\"icon-sm\"\n aria-label={t(\"editor.mermaidDiagram.downloadSvg\")}\n onClick={downloadSvg}\n >\n <Download className=\"size-3.5\" />\n </Button>\n {copyable ? (\n <CopyButton\n value={chart}\n label={false}\n aria-label={t(\"editor.mermaidDiagram.copySource\")}\n size=\"icon-sm\"\n />\n ) : null}\n </div>\n ) : null}\n {error ? (\n <div\n role=\"alert\"\n className=\"space-y-2 border-s-2 border-s-destructive bg-destructive/10 p-3 text-body\"\n >\n <p className=\"font-medium text-destructive-text\">\n {t(\"editor.mermaidDiagram.renderFailed\")}\n </p>\n <p className=\"text-muted-foreground\">{error}</p>\n <pre className=\"overflow-x-auto rounded bg-muted p-2 font-mono text-code text-foreground\">\n {chart}\n </pre>\n </div>\n ) : svg ? (\n <>\n <style>{HIT_CSS}</style>\n <div\n ref={svgHostRef}\n role=\"img\"\n aria-label={label}\n className=\"overflow-x-auto rounded-md bg-card p-3 [&_svg]:mx-auto [&_svg]:h-auto [&_svg]:max-w-full\"\n // Mermaid output; securityLevel \"strict\" sanitizes the source.\n dangerouslySetInnerHTML={{ __html: svg }}\n />\n </>\n ) : (\n <div\n role=\"status\"\n aria-label={t(\"editor.mermaidDiagram.rendering\")}\n className=\"h-24 animate-pulse rounded-md bg-surface-muted motion-reduce:animate-none\"\n />\n )}\n\n {expandable ? (\n <Dialog open={expanded} onOpenChange={setExpanded}>\n <DialogContent className=\"flex h-[88dvh] w-[92vw] max-w-[92vw] flex-col p-4 sm:max-w-[92vw]\">\n <DialogTitle className=\"sr-only\">{label}</DialogTitle>\n {/* Hit strokes ship via the shared HIT_CSS <style> above. */}\n {svg ? <MermaidViewer svg={svg} label={label} /> : null}\n </DialogContent>\n </Dialog>\n ) : null}\n </div>\n );\n },\n);\n","\"use client\";\n\n/**\n * MermaidViewer — the expanded diagram surface: wheel-zoom at the cursor,\n * drag-pan, fit/100% controls, and a left search panel that filters the\n * RENDERED nodes, highlights every hit and zooms to the selected one.\n */\nimport { Button, Input, useLocale } from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { Maximize, Minus, Plus } from \"lucide-react\";\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type PointerEvent as ReactPointerEvent,\n type WheelEvent as ReactWheelEvent,\n} from \"react\";\n\ninterface DiagramHit {\n id: string;\n label: string;\n}\n\ninterface Transform {\n scale: number;\n tx: number;\n ty: number;\n}\n\nconst MIN_SCALE = 0.2;\nconst MAX_SCALE = 6;\nconst HIT_CLASS = \"wb-dg-hit\";\nconst HIT_ACTIVE_CLASS = \"wb-dg-hit-active\";\n\nconst clampScale = (s: number) => Math.min(MAX_SCALE, Math.max(MIN_SCALE, s));\n\n/**\n * Fit-to-viewport transform (centered), or `null` while either box is\n * unmeasured. Guarding here is what fixes the \"opens at MIN_SCALE pinned\n * top-left\" defect: the dialog mounts BEFORE layout, so a 0-sized container\n * used to produce a negative → clamped-to-minimum scale.\n */\nexport function fitTransform(\n container: { width: number; height: number },\n natural: { width: number; height: number },\n pad = 24,\n): Transform | null {\n if (container.width <= pad || container.height <= pad) return null;\n if (!natural.width || !natural.height) return null;\n // Fit means \"make it all visible\", never \"blow it up\": small diagrams stay\n // at natural size (100%), centered — upscaling reads as a broken zoom.\n const scale = clampScale(\n Math.min(1, (container.width - pad) / natural.width, (container.height - pad) / natural.height),\n );\n return {\n scale,\n tx: (container.width - natural.width * scale) / 2,\n ty: (container.height - natural.height * scale) / 2,\n };\n}\n\n/**\n * Human-readable label for a rendered diagram node. Mermaid renders multi-line\n * labels as sibling text containers (`tspan` lines, or `p`/`span` inside the\n * htmlLabels foreignObject); raw `textContent` concatenates them WITHOUT\n * separators (\"Microsoft Graph APIOutlook / C…\"). Join the leaf segments with\n * a \"·\" instead.\n */\nexport function diagramNodeLabel(node: Element): string {\n const candidates = Array.from(node.querySelectorAll(\"tspan, p, span\"));\n const leaves = candidates.filter((el) => !el.querySelector(\"tspan, p, span\"));\n const parts = leaves\n .map((el) => (el.textContent ?? \"\").trim().replace(/\\s+/g, \" \"))\n .filter(Boolean);\n if (parts.length === 0) return (node.textContent ?? \"\").trim().replace(/\\s+/g, \" \");\n return parts.join(\" · \");\n}\n\nexport function MermaidViewer({ svg, label }: { svg: string; label: string }) {\n const { t } = useLocale();\n const containerRef = useRef<HTMLDivElement | null>(null);\n const stageRef = useRef<HTMLDivElement | null>(null);\n const [transform, setTransform] = useState<Transform>({ scale: 1, tx: 0, ty: 0 });\n const [hits, setHits] = useState<DiagramHit[]>([]);\n const [query, setQuery] = useState(\"\");\n const [activeHit, setActiveHit] = useState<string | null>(null);\n const dragRef = useRef<{ x: number; y: number; tx: number; ty: number } | null>(null);\n /** The user took over (zoom/pan) — stop auto-fitting on container resize. */\n const userDrivenRef = useRef(false);\n\n /** Natural (untransformed) svg size in px. */\n const naturalSize = useRef<{ w: number; h: number }>({ w: 0, h: 0 });\n\n const fit = useCallback((): boolean => {\n const container = containerRef.current;\n const { w, h } = naturalSize.current;\n if (!container) return false;\n const next = fitTransform(\n { width: container.clientWidth, height: container.clientHeight },\n { width: w, height: h },\n );\n if (next) setTransform(next);\n return next !== null;\n }, []);\n\n // Mount: size the svg naturally, collect searchable nodes, fit to view.\n useEffect(() => {\n const stage = stageRef.current;\n const svgEl = stage?.querySelector(\"svg\");\n if (!stage || !svgEl) return;\n const viewBox = svgEl.viewBox?.baseVal;\n const w = viewBox?.width || svgEl.getBoundingClientRect().width || 800;\n const h = viewBox?.height || svgEl.getBoundingClientRect().height || 600;\n // Replace mermaid's inline style WHOLESALE (it ships `max-width: Xpx`\n // which silently beat per-property overrides — the fit math then used the\n // viewBox size while the svg rendered capped: the \"26% blob\" defect).\n svgEl.setAttribute(\"style\", `max-width:none;width:${w}px;height:${h}px;`);\n svgEl.setAttribute(\"width\", String(w));\n svgEl.setAttribute(\"height\", String(h));\n // Trust the PIXELS, not the assumption: measure the rendered box (the\n // stage transform is still identity at mount). Fall back to viewBox.\n const rect = svgEl.getBoundingClientRect();\n naturalSize.current = {\n w: rect.width > 0 ? rect.width : w,\n h: rect.height > 0 ? rect.height : h,\n };\n\n const found: DiagramHit[] = [];\n const seen = new Set<string>();\n for (const node of svgEl.querySelectorAll<SVGGElement>(\"g.node, g.edgeLabel\")) {\n const text = diagramNodeLabel(node);\n if (!text || !node.id) continue;\n if (seen.has(node.id)) continue;\n seen.add(node.id);\n found.push({ id: node.id, label: text });\n }\n setHits(found);\n // The dialog animates open — retry across the first frames until the\n // container has real dimensions (belt to the ResizeObserver's braces).\n if (!fit()) {\n let tries = 0;\n let raf = 0;\n const attempt = () => {\n if (userDrivenRef.current) return;\n if (!fit() && ++tries < 30) raf = requestAnimationFrame(attempt);\n };\n raf = requestAnimationFrame(attempt);\n return () => cancelAnimationFrame(raf);\n }\n }, [svg, fit]);\n\n // The dialog mounts before layout settles, so the mount-time fit() can see a\n // 0-sized container (fitTransform skips it). Re-fit when the container gains\n // or changes size — until the user zooms/pans, after which their view wins.\n useEffect(() => {\n const container = containerRef.current;\n if (!container || typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(() => {\n if (!userDrivenRef.current) fit();\n });\n observer.observe(container);\n return () => observer.disconnect();\n }, [fit]);\n\n // Highlight matching nodes as the query changes.\n const q = query.trim().toLowerCase();\n const matches = useMemo(\n () => (q.length >= 2 ? hits.filter((hit) => hit.label.toLowerCase().includes(q)) : []),\n [hits, q],\n );\n\n useEffect(() => {\n const svgEl = stageRef.current?.querySelector(\"svg\");\n if (!svgEl) return;\n const matchIds = new Set(matches.map((m) => m.id));\n for (const node of svgEl.querySelectorAll<SVGGElement>(\"g.node, g.edgeLabel\")) {\n node.classList.toggle(HIT_CLASS, matchIds.has(node.id));\n // The ACTIVE highlight is independent of the query filter: after the\n // user clicks a result (and the query changes or clears), the found\n // node must stay visibly marked.\n node.classList.toggle(HIT_ACTIVE_CLASS, node.id === activeHit);\n }\n }, [matches, activeHit]);\n\n const zoomAt = useCallback((clientX: number, clientY: number, factor: number) => {\n const container = containerRef.current;\n if (!container) return;\n userDrivenRef.current = true;\n const rect = container.getBoundingClientRect();\n setTransform((prev) => {\n const scale = clampScale(prev.scale * factor);\n const px = (clientX - rect.left - prev.tx) / prev.scale;\n const py = (clientY - rect.top - prev.ty) / prev.scale;\n return { scale, tx: clientX - rect.left - px * scale, ty: clientY - rect.top - py * scale };\n });\n }, []);\n\n const zoomCenter = (factor: number) => {\n const container = containerRef.current;\n if (!container) return;\n const rect = container.getBoundingClientRect();\n zoomAt(rect.left + rect.width / 2, rect.top + rect.height / 2, factor);\n };\n\n const zoomToHit = useCallback((id: string) => {\n const container = containerRef.current;\n const svgEl = stageRef.current?.querySelector(\"svg\");\n const node = svgEl?.querySelector<SVGGElement>(`[id=\"${CSS.escape(id)}\"]`);\n if (!container || !svgEl || !node) return;\n userDrivenRef.current = true;\n setActiveHit(id);\n setTransform((prev) => {\n const nodeRect = node.getBoundingClientRect();\n const containerRect = container.getBoundingClientRect();\n // Node center in svg-space (invert the current transform).\n const cx = (nodeRect.left + nodeRect.width / 2 - containerRect.left - prev.tx) / prev.scale;\n const cy = (nodeRect.top + nodeRect.height / 2 - containerRect.top - prev.ty) / prev.scale;\n const scale = clampScale(Math.max(prev.scale, 1.25));\n return {\n scale,\n tx: containerRect.width / 2 - cx * scale,\n ty: containerRect.height / 2 - cy * scale,\n };\n });\n }, []);\n\n const onWheel = (e: ReactWheelEvent) => {\n e.preventDefault();\n zoomAt(e.clientX, e.clientY, e.deltaY < 0 ? 1.12 : 1 / 1.12);\n };\n\n const onPointerDown = (e: ReactPointerEvent<HTMLDivElement>) => {\n if (e.button !== 0) return;\n userDrivenRef.current = true;\n dragRef.current = { x: e.clientX, y: e.clientY, tx: transform.tx, ty: transform.ty };\n (e.currentTarget as HTMLDivElement).setPointerCapture(e.pointerId);\n };\n const onPointerMove = (e: ReactPointerEvent<HTMLDivElement>) => {\n const drag = dragRef.current;\n if (!drag) return;\n setTransform((prev) => ({\n ...prev,\n tx: drag.tx + (e.clientX - drag.x),\n ty: drag.ty + (e.clientY - drag.y),\n }));\n };\n const onPointerUp = () => {\n dragRef.current = null;\n };\n\n return (\n <div className=\"flex min-h-0 flex-1 gap-3\">\n {/* Search rail */}\n <div className=\"flex w-60 shrink-0 flex-col border-e border-border pe-3\">\n <Input\n autoFocus\n type=\"search\"\n placeholder={t(\"editor.mermaidViewer.findPlaceholder\")}\n aria-label={t(\"editor.mermaidViewer.findLabel\")}\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n spellCheck={false}\n className=\"h-8 text-body\"\n />\n <p aria-live=\"polite\" className=\"px-1 pt-1.5 text-meta text-muted-foreground tabular-nums\">\n {q.length >= 2\n ? t(\"editor.mermaidViewer.matchCount\", { count: matches.length })\n : t(\"editor.mermaidViewer.nodeCountHint\", { count: hits.length })}\n </p>\n <ul className=\"m-0 mt-1 min-h-0 flex-1 list-none overflow-auto p-0\">\n {(q.length >= 2 ? matches : hits).map((hit) => (\n <li key={hit.id}>\n <button\n type=\"button\"\n onClick={() => zoomToHit(hit.id)}\n aria-pressed={activeHit === hit.id}\n className={cn(\n \"w-full truncate rounded-md px-2 py-1.5 text-start text-caption transition-colors duration-fast ease-standard motion-reduce:transition-none\",\n \"hover:bg-accent hover:text-accent-foreground\",\n \"focus-ring-inset\",\n activeHit === hit.id\n ? \"bg-accent font-medium text-foreground\"\n : \"text-muted-foreground\",\n )}\n >\n {hit.label}\n </button>\n </li>\n ))}\n </ul>\n </div>\n\n {/* Stage */}\n <div className=\"relative min-h-0 min-w-0 flex-1\">\n <div className=\"absolute end-2 top-2 z-10 flex gap-1\">\n <Button\n variant=\"outline\"\n size=\"icon-sm\"\n aria-label={t(\"editor.mermaidViewer.zoomOut\")}\n onClick={() => zoomCenter(1 / 1.25)}\n >\n <Minus className=\"size-3.5\" />\n </Button>\n <Button\n variant=\"outline\"\n size=\"icon-sm\"\n aria-label={t(\"editor.mermaidViewer.zoomIn\")}\n onClick={() => zoomCenter(1.25)}\n >\n <Plus className=\"size-3.5\" />\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"h-7 px-2 font-mono text-meta tabular-nums\"\n aria-label={t(\"editor.mermaidViewer.resetZoom\")}\n onClick={() => {\n userDrivenRef.current = true;\n setTransform((prev) => ({ ...prev, scale: 1 }));\n }}\n >\n {Math.round(transform.scale * 100)}%\n </Button>\n <Button\n variant=\"outline\"\n size=\"icon-sm\"\n aria-label={t(\"editor.mermaidViewer.fitDiagram\")}\n onClick={() => {\n // An explicit fit hands control back: keep fitting on resize.\n userDrivenRef.current = false;\n fit();\n }}\n >\n <Maximize className=\"size-3.5\" />\n </Button>\n </div>\n\n <div\n ref={containerRef}\n role=\"img\"\n aria-label={label}\n className={cn(\n \"h-full w-full touch-none select-none overflow-hidden rounded-md bg-surface-muted/50\",\n dragRef.current ? \"cursor-grabbing\" : \"cursor-grab\",\n )}\n onWheel={onWheel}\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n onPointerCancel={onPointerUp}\n onDoubleClick={(e) => zoomAt(e.clientX, e.clientY, 1.5)}\n >\n <div\n ref={stageRef}\n style={{\n transform: `translate(${transform.tx}px, ${transform.ty}px) scale(${transform.scale})`,\n transformOrigin: \"0 0\",\n }}\n // Same sanitized engine output as the inline rendering.\n dangerouslySetInnerHTML={{ __html: svg }}\n />\n </div>\n </div>\n </div>\n );\n}\n","/**\n * Mermaid reserved-identifier remediation.\n *\n * Authors routinely use flowchart KEYWORDS as node ids (`graph[Microsoft\n * Graph]`, `end[End]`, `class[...]`) — mermaid hard-fails (\"got 'GRAPH'\")\n * even though the intent is unambiguous. Instead of punting the error to the\n * reader, the diagram component extracts the offending token from the parse\n * error, rewrites that identifier with a trailing underscore, and retries\n * once. Labels, quoted strings and edge text (`|…|`) are never touched —\n * only the invisible id changes.\n */\n\nexport const FLOWCHART_RESERVED = new Set([\n \"graph\",\n \"flowchart\",\n \"subgraph\",\n \"end\",\n \"style\",\n \"linkstyle\",\n \"classdef\",\n \"class\",\n \"click\",\n \"direction\",\n \"default\",\n \"state\",\n]);\n\n/** Pull the offending token out of a mermaid parse error (\"… got 'GRAPH'\"). */\nexport function offendingToken(errorMessage: string): string | null {\n const m = /got '([A-Za-z_]+)'/.exec(errorMessage);\n return m ? m[1]!.toLowerCase() : null;\n}\n\n/** A true diagram declaration line: keyword + direction and nothing else. */\nconst DECLARATION_RE = /^(graph|flowchart)\\s+(tb|td|bt|rl|lr)\\s*;?\\s*$/;\n\n/**\n * Replace `re` matches only OUTSIDE label/quote/edge-text segments:\n * `[...]`, `(...)`, `{...}`, `\"...\"` and `|...|` contents stay verbatim.\n */\nfunction replaceOutsideLabels(line: string, re: RegExp, repl: string): string {\n let out = \"\";\n let buf = \"\";\n let depth = 0;\n let inQuote = false;\n let inPipe = false;\n\n const flush = () => {\n out += buf.replace(re, repl);\n buf = \"\";\n };\n\n for (const ch of line) {\n if (inQuote) {\n out += ch;\n if (ch === '\"') inQuote = false;\n continue;\n }\n if (depth === 0 && ch === \"|\") {\n if (!inPipe) flush();\n inPipe = !inPipe;\n out += ch;\n continue;\n }\n if (inPipe) {\n out += ch;\n continue;\n }\n if (ch === '\"') {\n flush();\n out += ch;\n inQuote = true;\n continue;\n }\n if (ch === \"[\" || ch === \"(\" || ch === \"{\") {\n if (depth === 0) flush();\n depth++;\n out += ch;\n continue;\n }\n if (ch === \"]\" || ch === \")\" || ch === \"}\") {\n if (depth > 0) depth--;\n if (depth === 0) {\n out += ch;\n continue;\n }\n out += ch;\n continue;\n }\n if (depth === 0) buf += ch;\n else out += ch;\n }\n flush();\n return out;\n}\n\n/**\n * Rewrite a reserved word used as a node id to `<word>_`. Structural keyword\n * positions are preserved: declaration lines (`flowchart TD`), `subgraph`\n * keyword lines and lone `end` terminators stay intact. Returns the\n * rewritten source, or null when nothing remediable changed.\n */\nexport function remediateReservedIds(chart: string, token: string): string | null {\n const t = token.toLowerCase();\n if (!FLOWCHART_RESERVED.has(t)) return null;\n const re = new RegExp(`\\\\b${t}\\\\b`, \"gi\");\n let changed = false;\n const repl = `${t}_`;\n\n const out = chart\n .split(\"\\n\")\n .map((line) => {\n const trimmed = line.trim().toLowerCase();\n if (trimmed === t) return line; // lone keyword (e.g. subgraph terminator `end`)\n if (DECLARATION_RE.test(trimmed)) return line; // `graph TD` / `flowchart LR`\n if (t === \"subgraph\" && trimmed.startsWith(\"subgraph\")) return line;\n const next = replaceOutsideLabels(line, re, repl);\n if (next !== line) changed = true;\n return next;\n })\n .join(\"\\n\");\n\n return changed ? out : null;\n}\n","/**\n * Prose primitives — re-exported from @elabs-ai/components-ui (#188; ADR-0012 own/re-export\n * model: @elabs-ai/components-ui owns the canonical prose source in\n * `components/typography/prose.tsx`; this package derives). The\n * `@elabs-ai/components-editor/markdown` public surface keeps the original names\n * (Heading, Text, Link, List, ListItem, Blockquote, InlineCode).\n *\n * These must stay the SAME objects, not lookalikes: that identity is the whole\n * reason a `Prose*` change cannot drift the editor away from the chat view or\n * the file viewer. `prose.test.ts` asserts it against the package barrel — if\n * you replace a line below with a local component, that test goes red while the\n * behaviour tests in `prose.test.tsx` stay green, which is exactly the failure\n * it exists to catch.\n */\nexport {\n ProseHeading as Heading,\n ProseText as Text,\n ProseLink as Link,\n ProseList as List,\n ProseListItem as ListItem,\n ProseBlockquote as Blockquote,\n ProseInlineCode as InlineCode,\n type ProseHeadingProps as HeadingProps,\n type ProseHeadingLevel as HeadingLevel,\n type ProseTextProps as TextProps,\n type ProseLinkProps as LinkProps,\n type ProseListProps as ListProps,\n} from \"@elabs-ai/components-ui\";\n","/**\n * Timeline — MOVED to `@elabs-ai/components-ui` (#190, research 10 §B.2; the ADR-0012\n * own/re-export model). `@elabs-ai/components-ui` owns the canonical rail; this shim keeps\n * the editor-facing surface byte-compatible — `markdown/index.ts` and the\n * `:::timeline` preview keep importing from `../timeline` unchanged.\n *\n * `TimelineItem` here is the ARRAY-item data shape (named `TimelineEntry` in\n * `@elabs-ai/components-ui`, where `TimelineItem` is the compound `<li>` part); the alias\n * preserves the editor's original public type name. `TimelineStatus`\n * (`done|active|pending`) now lives with its `fromTimelineStatus` mapper in\n * status-badge and reaches the `@elabs-ai/components-ui` barrel from there.\n */\nexport {\n Timeline,\n type TimelineEntry as TimelineItem,\n type TimelineProps,\n type TimelineStatus,\n} from \"@elabs-ai/components-ui\";\n","\"use client\";\n\n/**\n * CodeFence — the highlighted non-mermaid code fence inside MarkdownPreview.\n *\n * Highlighting rides on the SAME engine the rest of the workspace already\n * ships (`@streamdown/code`, Streamdown's shiki plugin — cached highlighters,\n * sync-after-first-tokenize), but the theme is a shiki **CSS-variables theme**:\n * every token color resolves to a `var(--md-code-*)` reference that this\n * component maps onto the semantic tokens below. One theme, correct in every\n * `data-theme` (light, dark, …) — no per-theme shiki theme, no raw\n * colors, and a runtime theme switch recolors already-tokenized code for free.\n *\n * Until shiki finishes loading (or for a fence with no language tag) the raw\n * fence text renders as before — highlighting is a progressive enhancement.\n */\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { code as codeHighlighter } from \"@streamdown/code\";\nimport {\n useEffect,\n useRef,\n useState,\n type CSSProperties,\n type HTMLAttributes,\n type ReactNode,\n} from \"react\";\nimport type { BundledLanguage, ThemedToken, TokensResult } from \"shiki\";\nimport { createCssVariablesTheme } from \"shiki\";\n\nimport { CopyButton } from \"../copy-button\";\n\n/** Extract the fence language from react-markdown's `language-*` className. */\nexport function fenceLanguage(className?: string): string | undefined {\n return /\\blanguage-([\\w+#.-]+)\\b/.exec(className ?? \"\")?.[1];\n}\n\n/**\n * One shiki theme for BOTH slots (the plugin API is [light, dark]): colors are\n * pure CSS-variable references, so the active `data-theme` decides the actual\n * values — both slots resolve identically by construction.\n */\nconst cssVariablesTheme = createCssVariablesTheme({\n name: \"brand-tokens\",\n variablePrefix: \"--md-code-\",\n fontStyle: true,\n});\nconst SHIKI_THEMES: [typeof cssVariablesTheme, typeof cssVariablesTheme] = [\n cssVariablesTheme,\n cssVariablesTheme,\n];\n\n/**\n * The `--md-code-*` seams mapped onto semantic tokens (scoped to the fence, so\n * nothing leaks into `themes.css`). Chart tokens carry the categorical hues —\n * they are the only themed accent ramp guaranteed to exist in every theme.\n */\nconst SHIKI_TOKEN_VARS = cn(\n \"[--md-code-foreground:var(--foreground)]\",\n \"[--md-code-background:transparent]\",\n \"[--md-code-token-comment:var(--muted-foreground)]\",\n \"[--md-code-token-constant:var(--chart-1)]\",\n \"[--md-code-token-function:var(--chart-3)]\",\n \"[--md-code-token-keyword:var(--chart-4)]\",\n \"[--md-code-token-link:var(--primary)]\",\n \"[--md-code-token-parameter:var(--chart-5)]\",\n \"[--md-code-token-punctuation:var(--muted-foreground)]\",\n \"[--md-code-token-string-expression:var(--chart-2)]\",\n \"[--md-code-token-string:var(--chart-2)]\",\n);\n\n// Shiki encodes font style as bitflags: 1 = italic, 2 = bold, 4 = underline.\nconst hasFontFlag = (fontStyle: number | undefined, flag: number) =>\n ((fontStyle ?? 0) & flag) === flag;\n\nfunction tokenStyle(token: ThemedToken): CSSProperties {\n return {\n // htmlStyle.color carries the theme var; token.color is the fallback path.\n color: (token.htmlStyle as Record<string, string> | undefined)?.color ?? token.color,\n fontStyle: hasFontFlag(token.fontStyle, 1) ? \"italic\" : undefined,\n fontWeight: hasFontFlag(token.fontStyle, 2) ? \"bold\" : undefined,\n textDecoration: hasFontFlag(token.fontStyle, 4) ? \"underline\" : undefined,\n };\n}\n\n/**\n * Tokenize via the shared plugin. Returns `null` until the highlighter is\n * ready (first render of a language) — cached fences resolve synchronously.\n */\nfunction useHighlightedTokens(codeText: string, language: string | undefined) {\n const [result, setResult] = useState<TokensResult | null>(null);\n const keyRef = useRef({ codeText, language });\n\n // Invalidate stale tokens synchronously during render (no flash of the\n // previous fence's tokens when the source changes).\n if (keyRef.current.codeText !== codeText || keyRef.current.language !== language) {\n keyRef.current = { codeText, language };\n setResult(null);\n }\n\n useEffect(() => {\n if (!language) return undefined; // no language tag — keep the plain text\n let cancelled = false;\n const sync = codeHighlighter.highlight(\n // Unknown languages fall back to \"text\" inside the plugin.\n { code: codeText, language: language as BundledLanguage, themes: SHIKI_THEMES },\n (r) => {\n if (!cancelled) setResult(r);\n },\n );\n if (sync && !cancelled) setResult(sync);\n return () => {\n cancelled = true;\n };\n }, [codeText, language]);\n\n return result;\n}\n\nexport interface CodeFenceProps extends HTMLAttributes<HTMLElement> {\n /** Raw fence text (trailing newline already stripped). */\n codeText: string;\n /** The fence's language tag (` ```ts `), if any. */\n language?: string;\n /** This fence contains the active in-document search hit. */\n searchActive?: boolean;\n /** Fallback content (the un-highlighted fence) while shiki loads. */\n children?: ReactNode;\n}\n\nexport function CodeFence({\n codeText,\n language,\n searchActive,\n className,\n children,\n ...props\n}: CodeFenceProps) {\n const tokens = useHighlightedTokens(codeText, language)?.tokens ?? null;\n\n return (\n <div\n data-code-fence={language ?? \"\"}\n className={cn(\"group/code-fence relative my-3\", className)}\n {...props}\n >\n <pre\n data-search-active={searchActive ? \"\" : undefined}\n className={cn(\n \"!my-0 overflow-x-auto rounded-md p-3 font-mono text-code\",\n SHIKI_TOKEN_VARS,\n searchActive ? \"bg-primary/10\" : \"bg-surface-muted\",\n )}\n >\n {tokens ? (\n <code>\n {tokens.map((line, lineIdx) => (\n // Lines are positionally stable for a given source string (the\n // whole list is rebuilt when `codeText` changes).\n <span key={`line-${lineIdx}`} className=\"block\">\n {line.length === 0\n ? \"\\n\"\n : line.map((token, tokenIdx) => (\n <span key={`token-${lineIdx}-${tokenIdx}`} style={tokenStyle(token)}>\n {token.content}\n </span>\n ))}\n </span>\n ))}\n </code>\n ) : (\n children\n )}\n </pre>\n\n <div className=\"absolute end-2 top-2 flex items-center gap-1\">\n <CopyButton\n value={codeText}\n label={false}\n size=\"icon-sm\"\n className=\"opacity-0 transition-opacity duration-fast ease-standard focus-visible:opacity-100 group-hover/code-fence:opacity-100 motion-reduce:transition-none\"\n />\n {language ? (\n <span\n aria-hidden=\"true\"\n className=\"pointer-events-none select-none rounded-sm bg-surface-muted px-1.5 py-0.5 font-mono text-meta text-muted-foreground\"\n >\n {language}\n </span>\n ) : null}\n </div>\n </div>\n );\n}\n","\"use client\";\n\n/**\n * Citations — Pandoc / Better-BibTeX keys (`[@smith2020]`) resolved through a\n * consumer hook (`resolveCitation(key) => CitationData | null`).\n *\n * The library NEVER owns the bibliography database or CSL formatting — that lives\n * in the app (pass `formatted` for a citeproc-rendered reference, or the lightweight\n * `author`/`year`/`title` bits for the built-in assembler). The library renders:\n * inline cites (numeric `[1]` or author-year `(Smith 2020)`) and a generated\n * bibliography, with consistent numbering shared between them.\n *\n * `[@key]` stays a plain text node in mdast (it is NOT markdown link syntax), so a\n * text-node transform (`remarkBrandCitations`) rewrites the spans — the same shape\n * as the wikilink resolver. Numbering is owned by `collectCitations` (a single\n * pre-pass over the source) so an inline `[1]` and bibliography entry 1 always agree.\n */\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { Separator, useLocale } from \"@elabs-ai/components-ui\";\nimport {\n createContext,\n forwardRef,\n useContext,\n useId,\n type HTMLAttributes,\n type ReactNode,\n} from \"react\";\nimport { visit } from \"unist-util-visit\";\n\n/* ------------------------------------------------------------------ */\n/* Public contract */\n/* ------------------------------------------------------------------ */\n\n/**\n * Resolved citation data, returned by the consumer's `resolveCitation` hook.\n * Provide `formatted` (your CSL/citeproc output) for a verbatim bibliography\n * entry; otherwise the built-in assembler uses `author` / `year` / `title` /\n * `container`. The library does NOT format CSL.\n */\nexport interface CitationData {\n /** The citation key (echoed back; optional). */\n key?: string;\n /** Inline author label for author-year + bibliography lead (e.g. `\"Smith et al.\"`). */\n author?: string;\n /** Publication year. */\n year?: string | number;\n /** Work title. */\n title?: string;\n /** Container — journal, book, publisher, or site. */\n container?: string;\n /** Canonical URL (the bibliography link). */\n url?: string;\n /** DOI — linked as `https://doi.org/<doi>` when no `url` is given. */\n doi?: string;\n /** Fully-formatted reference (app's CSL output) — rendered verbatim when set. */\n formatted?: string;\n}\n\n/** Consumer hook: citation key → data, or `null` when unknown (renders `[?]`). */\nexport type ResolveCitation = (key: string) => CitationData | null;\n\n/** Inline citation rendering style. */\nexport type CitationStyle = \"numeric\" | \"author-year\";\n\n/** One resolved citation with its assigned number (numbers skip unresolved keys). */\nexport interface ResolvedCitation {\n key: string;\n /** 1-based number (numeric style + bibliography); `undefined` when unresolved. */\n n?: number;\n data: CitationData | null;\n}\n\n/** A single `@key` reference inside a citation bracket. */\nexport interface CiteItem {\n key: string;\n /** Locator text after the key, e.g. `\"p. 5\"`. */\n locator?: string;\n /** `-@key` → suppress the author in author-year style. */\n suppressAuthor?: boolean;\n /** Prose before the key, e.g. `\"see\"`. */\n prefix?: string;\n}\n\n/* ------------------------------------------------------------------ */\n/* Parsing (shared by the transform AND the numbering pre-pass) */\n/* ------------------------------------------------------------------ */\n\n// A key char-class wide enough for Better-BibTeX / CSL keys without swallowing\n// trailing punctuation: letters, digits, and `_:.#$%&+?<>~/-` (no whitespace).\nconst ITEM_RE = /^\\s*([^@]*?)\\s*(-)?@([\\p{L}\\d][\\w:.#$%&+?<>~/-]*)\\s*(.*)$/u;\n\n/** Parse one `;`-separated cite item; `null` if it has no `@key`. */\nfunction parseItem(raw: string): CiteItem | null {\n const m = ITEM_RE.exec(raw);\n if (!m) return null;\n const [, prefix, suppress, key, rest] = m;\n if (!key) return null;\n const locator = (rest ?? \"\").replace(/^\\s*,\\s*/, \"\").trim();\n const item: CiteItem = { key };\n if (suppress) item.suppressAuthor = true;\n if (prefix?.trim()) item.prefix = prefix.trim();\n if (locator) item.locator = locator;\n return item;\n}\n\n/**\n * Parse a bracket's inner text into cite items, or `null` if it is not a citation\n * (no `@key` token) — so ordinary `[bracketed]` prose is left untouched.\n */\nexport function parseCitationBracket(inner: string): CiteItem[] | null {\n if (!inner.includes(\"@\")) return null;\n const items: CiteItem[] = [];\n for (const part of inner.split(\";\")) {\n const item = parseItem(part);\n if (!item) return null; // every `;`-part must be a valid cite, else it's prose\n items.push(item);\n }\n return items.length > 0 ? items : null;\n}\n\n// Find candidate citation brackets in a text node. Excludes a preceding `]` or `!`\n// (reference-link / image syntax) and a following `(`/`[` (inline / reference link).\nconst BRACKET_RE = /(?<![\\]!])\\[([^[\\]]+)\\](?![([])/g;\n\n/* ------------------------------------------------------------------ */\n/* collectCitations — the single numbering authority */\n/* ------------------------------------------------------------------ */\n\nexport interface CollectedCitations {\n /** Resolved citations in first-appearance order (the bibliography list). */\n order: ResolvedCitation[];\n /** Lookup by key — both resolved and unresolved keys. */\n byKey: Map<string, ResolvedCitation>;\n}\n\n/**\n * Scan the markdown body once, in document order, resolving each unique citation\n * key and numbering the resolved ones. The inline transform stays numbering-free\n * and reads back from `byKey`, so inline `[1]` and bibliography entry 1 agree.\n */\nexport function collectCitations(markdown: string, resolve: ResolveCitation): CollectedCitations {\n const byKey = new Map<string, ResolvedCitation>();\n const order: ResolvedCitation[] = [];\n let m: RegExpExecArray | null;\n BRACKET_RE.lastIndex = 0;\n while ((m = BRACKET_RE.exec(markdown)) !== null) {\n const items = parseCitationBracket(m[1]!);\n if (!items) continue;\n for (const { key } of items) {\n if (byKey.has(key)) continue;\n const data = resolve(key);\n const entry: ResolvedCitation = { key, data };\n if (data) {\n entry.n = order.length + 1;\n order.push(entry);\n }\n byKey.set(key, entry);\n }\n }\n return { order, byKey };\n}\n\n/* ------------------------------------------------------------------ */\n/* remark transform: `[@key]` → <brand-cite> */\n/* ------------------------------------------------------------------ */\n\nexport const CITE_TAG = \"brand-cite\";\nexport const CITE_PROP = \"dataCite\";\nconst CITE_ATTR = \"data-cite\";\n\ninterface CitePayload {\n items: CiteItem[];\n /** Original bracket text, for the graceful all-unresolved fallback. */\n original: string;\n}\n\ninterface MdTextNode {\n type: string;\n value?: string;\n}\n\n/** Rewrite `[@key]` citation spans in text nodes into `<brand-cite>` elements. */\nexport function remarkBrandCitations() {\n return (tree: unknown) => {\n visit(tree as never, \"text\", (node: MdTextNode, index: number | undefined, parent) => {\n const p = parent as { children?: unknown[] } | undefined;\n const text = node.value;\n if (!p?.children || index == null || typeof text !== \"string\" || !text.includes(\"@\")) return;\n\n const next: unknown[] = [];\n let last = 0;\n BRACKET_RE.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = BRACKET_RE.exec(text)) !== null) {\n const items = parseCitationBracket(m[1]!);\n if (!items) continue;\n if (m.index > last) next.push({ type: \"text\", value: text.slice(last, m.index) });\n const payload: CitePayload = { items, original: m[0] };\n next.push({\n type: \"brandCite\",\n data: { hName: CITE_TAG, hProperties: { [CITE_PROP]: JSON.stringify(payload) } },\n });\n last = m.index + m[0].length;\n }\n if (next.length === 0) return;\n if (last < text.length) next.push({ type: \"text\", value: text.slice(last) });\n p.children.splice(index, 1, ...next);\n return index + next.length;\n });\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Context (numbering shared by inline cites + bibliography) */\n/* ------------------------------------------------------------------ */\n\ninterface CitationState {\n byKey: Map<string, ResolvedCitation>;\n order: ResolvedCitation[];\n style: CitationStyle;\n}\n\nconst CitationContext = createContext<CitationState | null>(null);\n\nexport interface CitationProviderProps extends CollectedCitations {\n style: CitationStyle;\n children: ReactNode;\n}\n\nexport function CitationProvider({ byKey, order, style, children }: CitationProviderProps) {\n return (\n <CitationContext.Provider value={{ byKey, order, style }}>{children}</CitationContext.Provider>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Rendering helpers */\n/* ------------------------------------------------------------------ */\n\nfunction hoverTitle(data: CitationData): string {\n if (data.formatted) return data.formatted;\n const parts = [\n data.author,\n data.year != null ? `(${data.year})` : undefined,\n data.title,\n data.container,\n ].filter(Boolean);\n return parts.join(\". \");\n}\n\nfunction CiteLink({ entry, label }: { entry: ResolvedCitation; label: string }) {\n const { t } = useLocale();\n // For numeric style the visible label is a bare \"[1]\" — give AT a real name\n // (the `title` tooltip is for mouse users and is not reliably announced).\n const name = entry.data ? hoverTitle(entry.data) : entry.key;\n return (\n <a\n href={`#ref-${cssId(entry.key)}`}\n title={entry.data ? hoverTitle(entry.data) : undefined}\n aria-label={t(\"editor.citations.citationLabel\", { name })}\n // #317/#399 — the on-surface `-text` rung, NOT the `--primary` FILL: an\n // inline cite is body text inside a paragraph and owes WCAG 1.4.3 AA\n // (4.5:1), which `--primary` missed at 4.29-4.31:1 in light. The\n // resting `underline` is the separate 1.4.1 non-colour cue (#317's\n // link-in-text-block half) — keep both.\n className=\"text-link underline hover:underline focus-visible:rounded-sm focus-ring\"\n >\n {label}\n </a>\n );\n}\n\n/** Make a citation key safe for use in an element id / fragment. */\nfunction cssId(key: string): string {\n return key.replace(/[^\\w-]/g, \"-\");\n}\n\n/* ------------------------------------------------------------------ */\n/* InlineCite — the <brand-cite> renderer */\n/* ------------------------------------------------------------------ */\n\ntype TagProps = { node?: unknown; children?: ReactNode } & Record<string, unknown>;\n\nfunction readCite(rest: TagProps): CitePayload | null {\n const raw = (rest[CITE_ATTR] as string | undefined) ?? (rest[CITE_PROP] as string | undefined);\n if (!raw) return null;\n try {\n return JSON.parse(raw) as CitePayload;\n } catch {\n return null;\n }\n}\n\n/** Renderer for the inline `<brand-cite>` element produced by the transform. */\nexport function InlineCite({ node: _n, children: _c, ...rest }: TagProps) {\n const { t } = useLocale();\n const ctx = useContext(CitationContext);\n const payload = readCite(rest);\n if (!payload) return null;\n if (!ctx) return <span>{payload.original}</span>;\n\n const resolved = payload.items.map((it) => ({ it, entry: ctx.byKey.get(it.key) }));\n const anyResolved = resolved.some((r) => r.entry?.data);\n if (!anyResolved) {\n // Graceful: nothing resolved → keep the literal, marked for sighted + AT.\n return (\n <span className=\"text-muted-foreground\" title={t(\"editor.citations.unresolvedCitation\")}>\n {payload.original}\n </span>\n );\n }\n\n const numeric = ctx.style === \"numeric\";\n const open = numeric ? \"[\" : \"(\";\n const close = numeric ? \"]\" : \")\";\n const sep = numeric ? \", \" : \"; \";\n\n return (\n <span className=\"whitespace-nowrap text-meta tabular-nums\">\n {open}\n {resolved.map(({ it, entry }, i) => {\n const label = numeric ? numericLabel(it, entry) : authorYearLabel(it, entry);\n return (\n <span key={`${it.key}-${i}`}>\n {i > 0 ? sep : null}\n {entry?.data ? (\n <CiteLink entry={entry} label={label} />\n ) : (\n <span\n className=\"text-muted-foreground\"\n title={t(\"editor.citations.unresolvedKey\", { key: it.key })}\n >\n {label}\n </span>\n )}\n </span>\n );\n })}\n {close}\n </span>\n );\n}\n\nfunction numericLabel(it: CiteItem, entry?: ResolvedCitation): string {\n if (!entry?.data || entry.n == null) return \"?\";\n return it.locator ? `${entry.n}, ${it.locator}` : String(entry.n);\n}\n\nfunction authorYearLabel(it: CiteItem, entry?: ResolvedCitation): string {\n if (!entry?.data) return `@${it.key}?`;\n const d = entry.data;\n const head = it.suppressAuthor ? \"\" : d.author ? `${d.author} ` : \"\";\n const year = d.year != null ? String(d.year) : \"\";\n const core = `${head}${year}`.trim() || d.title || it.key;\n const prefixed = it.prefix ? `${it.prefix} ${core}` : core;\n return it.locator ? `${prefixed}, ${it.locator}` : prefixed;\n}\n\n/* ------------------------------------------------------------------ */\n/* Bibliography */\n/* ------------------------------------------------------------------ */\n\nfunction assembledReference(data: CitationData): string {\n if (data.formatted) return data.formatted;\n const parts = [\n data.author,\n data.year != null ? `(${data.year}).` : undefined,\n data.title ? `${data.title}.` : undefined,\n data.container ? `${data.container}.` : undefined,\n ].filter(Boolean);\n return parts.join(\" \");\n}\n\nfunction referenceHref(data: CitationData): string | undefined {\n if (data.url) return data.url;\n if (data.doi) return `https://doi.org/${data.doi}`;\n return undefined;\n}\n\nexport interface BibliographyProps extends Omit<HTMLAttributes<HTMLElement>, \"children\" | \"style\"> {\n /** Resolved citations; defaults to the citations collected by `MarkdownPreview`. */\n entries?: ResolvedCitation[];\n /** Numbering style; defaults to the preview's `citationStyle`. */\n style?: CitationStyle;\n /** Section heading label. Default `\"References\"`. */\n title?: string;\n}\n\n/**\n * The generated reference list. Reads the preview's collected citations by default\n * (the `::bibliography` block), or accepts an explicit `entries` array standalone.\n * One focal separation gesture — a top `Separator` — over a quiet label + list.\n */\nexport const Bibliography = forwardRef<HTMLElement, BibliographyProps>(function Bibliography(\n { entries, style, title: titleProp, className, ...props },\n ref,\n) {\n const { t } = useLocale();\n const title = titleProp ?? t(\"editor.citations.references\");\n const ctx = useContext(CitationContext);\n const labelId = useId();\n const list = entries ?? ctx?.order ?? [];\n const resolvedStyle = style ?? ctx?.style ?? \"numeric\";\n const numeric = resolvedStyle === \"numeric\";\n\n if (list.length === 0) return null;\n\n return (\n <section ref={ref} aria-labelledby={labelId} className={cn(\"mt-8\", className)} {...props}>\n <Separator className=\"mb-3\" />\n <p id={labelId} className=\"mb-2 text-meta font-medium text-muted-foreground\">\n {title}\n </p>\n <ol className=\"space-y-2\">\n {list.map((entry) => {\n const data = entry.data;\n if (!data) return null;\n const href = referenceHref(data);\n return (\n <li\n key={entry.key}\n id={`ref-${cssId(entry.key)}`}\n className=\"flex gap-2 text-caption text-foreground scroll-mt-4\"\n >\n {numeric && entry.n != null ? (\n <span className=\"shrink-0 tabular-nums text-muted-foreground\">[{entry.n}]</span>\n ) : null}\n <span className=\"min-w-0\">\n {assembledReference(data)}{\" \"}\n {href ? (\n <a\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n // #317/#399 — bibliography DOI/URL is body text: `-text` rung\n // + resting underline (the non-colour cue).\n className=\"break-words text-link underline underline-offset-2 hover:underline focus-visible:rounded-sm focus-ring\"\n >\n {data.url ?? `doi:${data.doi}`}\n </a>\n ) : null}\n </span>\n </li>\n );\n })}\n </ol>\n </section>\n );\n});\n","\"use client\";\n\n/**\n * Branded GFM footnotes (`[^1]` … `[^1]: definition`).\n *\n * GFM footnotes already PARSE (remark-gfm is always on), but Streamdown's default\n * hast handlers render them with broken in-page anchors (a doubled `user-content-`\n * id prefix so ref/backref hrefs don't resolve) and `target=\"_blank\"` on what are\n * same-page jumps. So we OWN the render: `remarkBrandFootnotes` rewrites the\n * `footnoteReference` / `footnoteDefinition` mdast nodes into our own `brand-*`\n * elements BEFORE mdast→hast runs, giving consistent ids, real same-page links,\n * and quiet branded chrome.\n *\n * Why replace the node TYPE (not just set `data.hName`): mdast-util-to-hast has\n * built-in handlers for `footnoteReference` / `footnoteDefinition` that ignore\n * `data.hName`. Only a node type with NO handler falls through to the unknown\n * handler, which honors `hName` / `hProperties`. So we swap in fresh custom-typed\n * nodes — and we keep every `id`/`href` on our React output (post-sanitization),\n * never on raw hast the sanitizer could strip.\n */\nimport { Separator } from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { forwardRef, useId, type HTMLAttributes, type ReactNode } from \"react\";\nimport { visit } from \"unist-util-visit\";\n\n/** Inline footnote marker (`<sup><a>…</a></sup>`). */\nexport const FOOTNOTE_REF_TAG = \"brand-footnote-ref\";\n/** The branded footnote-definition section appended at document end. */\nexport const FOOTNOTE_LIST_TAG = \"brand-footnote-list\";\n/** A single footnote definition row (`<li>` + backref). */\nexport const FOOTNOTE_ITEM_TAG = \"brand-footnote-item\";\n/** hast property carrying the JSON payload (rendered as `data-fn`). */\nexport const FOOTNOTE_PROP = \"dataFn\";\nconst FOOTNOTE_ATTR = \"data-fn\";\n\ninterface FootnotePayload {\n /** Footnote identifier (the `1` / `longname` in `[^1]`). */\n id: string;\n /** Display number, assigned in first-reference order. */\n n: number;\n /** Unique element id for this reference occurrence (the backref target). */\n refId?: string;\n /** All reference element ids for this footnote — one back-ref per occurrence. */\n refs?: string[];\n}\n\n/* ------------------------------------------------------------------ */\n/* remark transform */\n/* ------------------------------------------------------------------ */\n\ninterface MdNode {\n type: string;\n identifier?: string;\n value?: string;\n children?: MdNode[];\n data?: { hName?: string; hProperties?: Record<string, unknown> };\n}\n\nfunction payloadProps(payload: FootnotePayload) {\n return { [FOOTNOTE_PROP]: JSON.stringify(payload) };\n}\n\n/**\n * Rewrite footnote refs + definitions into branded elements. Numbering follows\n * first-reference order (GFM behavior); repeated references reuse the number but\n * get a unique element id. Unreferenced definitions are dropped (also GFM).\n */\nexport function remarkBrandFootnotes() {\n return (tree: unknown) => {\n const root = tree as MdNode;\n\n // Pass 1 — collect definitions (and remove them; re-emitted at the end).\n const defs = new Map<string, MdNode>();\n visit(\n root as never,\n \"footnoteDefinition\",\n (node: MdNode, index, parent: MdNode | undefined) => {\n if (!node.identifier || !parent?.children || index == null) return;\n defs.set(node.identifier, node);\n parent.children.splice(index, 1);\n return index; // re-visit the now-shifted index\n },\n );\n\n // Pass 2 — number references in document order + replace with branded refs.\n const numberOf = new Map<string, number>();\n const refsOf = new Map<string, string[]>();\n const order: string[] = [];\n visit(root as never, \"footnoteReference\", (node: MdNode, index, parent: MdNode | undefined) => {\n if (!node.identifier || !parent?.children || index == null) return;\n const id = node.identifier;\n let n = numberOf.get(id);\n if (n == null) {\n n = order.length + 1;\n numberOf.set(id, n);\n order.push(id);\n }\n const refs = refsOf.get(id) ?? [];\n const refId = refs.length === 0 ? `fnref-${id}` : `fnref-${id}-${refs.length + 1}`;\n refs.push(refId);\n refsOf.set(id, refs);\n parent.children[index] = {\n type: \"brandFootnoteRef\",\n data: { hName: FOOTNOTE_REF_TAG, hProperties: payloadProps({ id, n, refId }) },\n };\n });\n\n if (order.length === 0) return;\n\n // Pass 3 — emit the branded definition section at the document end. Each item\n // is a custom element; the definition BODY stays real mdast (rendered + safely\n // sanitized as normal prose), while every id/anchor lives on our React output.\n // Carry every occurrence's ref id so the item renders one back-ref per mention.\n const items: MdNode[] = order.map((id, i) => {\n const def = defs.get(id);\n const body: MdNode[] = def?.children\n ? def.children.map((c) => structuredClone(c))\n : [{ type: \"paragraph\", children: [{ type: \"text\", value: \"Missing footnote.\" }] }];\n return {\n type: \"brandFootnoteItem\",\n data: {\n hName: FOOTNOTE_ITEM_TAG,\n hProperties: payloadProps({ id, n: i + 1, refs: refsOf.get(id) ?? [`fnref-${id}`] }),\n },\n children: body,\n };\n });\n\n root.children = root.children ?? [];\n root.children.push({\n type: \"brandFootnoteList\",\n data: { hName: FOOTNOTE_LIST_TAG },\n children: items,\n });\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* React renderers (registered on MarkdownPreview's components map) */\n/* ------------------------------------------------------------------ */\n\ntype TagProps = { node?: unknown; children?: ReactNode } & Record<string, unknown>;\n\nfunction readPayload(rest: TagProps): FootnotePayload | null {\n const raw =\n (rest[FOOTNOTE_ATTR] as string | undefined) ?? (rest[FOOTNOTE_PROP] as string | undefined);\n if (!raw) return null;\n try {\n return JSON.parse(raw) as FootnotePayload;\n } catch {\n return null;\n }\n}\n\n/** Inline footnote marker — a quiet superscript same-page link. */\nexport function FootnoteRef({ node: _n, children: _c, ...rest }: TagProps) {\n const payload = readPayload(rest);\n if (!payload) return null;\n const { id, n, refId } = payload;\n return (\n <sup className=\"leading-none\">\n <a\n id={refId ?? `fnref-${id}`}\n href={`#fn-${id}`}\n data-footnote-ref=\"\"\n aria-label={`Footnote ${n}`}\n // #399 — a footnote marker is superscript body text: `-text` rung.\n className=\"px-0.5 font-medium text-link underline tabular-nums hover:underline focus-visible:rounded-sm focus-ring\"\n >\n {n}\n </a>\n </sup>\n );\n}\n\n/** A single footnote definition row — the `<li>` + one \"↩\" back-ref per mention. */\nexport function FootnoteItem({ node: _n, children, ...rest }: TagProps) {\n const payload = readPayload(rest);\n if (!payload) return null;\n const { id, n, refs } = payload;\n // One back-ref per occurrence (GFM behavior); a single mention → a lone \"↩\".\n const refList = refs && refs.length > 0 ? refs : [`fnref-${id}`];\n return (\n <li\n id={`fn-${id}`}\n className=\"scroll-mt-4 ps-1 [&>p]:m-0 [&>p]:inline [&>p]:text-caption [&>p]:text-muted-foreground\"\n >\n {children}{\" \"}\n {refList.map((refId, i) => (\n <a\n key={refId}\n href={`#${refId}`}\n data-footnote-backref=\"\"\n aria-label={\n refList.length > 1\n ? `Back to reference ${n}, mention ${i + 1}`\n : `Back to reference ${n}`\n }\n className=\"ms-0.5 inline-flex items-center text-muted-foreground no-underline hover:text-foreground focus-visible:rounded-sm focus-ring\"\n >\n <span aria-hidden=\"true\">↩</span>\n {refList.length > 1 ? (\n <sub className=\"ms-0.5 leading-none tabular-nums\">{i + 1}</sub>\n ) : null}\n </a>\n ))}\n </li>\n );\n}\n\nexport type FootnoteListProps = HTMLAttributes<HTMLElement>;\n\n/**\n * The branded footnote-definition section. One focal separation gesture — a top\n * `Separator` (the classic footnote rule) — over a quiet label + the definition\n * list; no fill, no border box. The label id is per-instance (`useId`) so two\n * previews on one page don't collide.\n */\nexport const FootnoteList = forwardRef<HTMLElement, FootnoteListProps>(function FootnoteList(\n { className, children, ...props },\n ref,\n) {\n const labelId = useId();\n return (\n <section ref={ref} aria-labelledby={labelId} className={cn(\"mt-8\", className)} {...props}>\n <Separator className=\"mb-3\" />\n <p id={labelId} className=\"mb-2 text-meta font-medium text-muted-foreground\">\n Footnotes\n </p>\n <ol className=\"list-decimal space-y-1.5 ps-6 text-caption text-muted-foreground marker:text-muted-foreground\">\n {children}\n </ol>\n </section>\n );\n});\n","\"use client\";\n\n/**\n * Math via `remark-math` + KaTeX (`$inline$`, and `$$block$$` on its own lines).\n *\n * `remark-math` parses `$…$` / `$$…$$` into `inlineMath` / `math` mdast nodes,\n * which have NO mdast→hast handler (they'd otherwise degrade to literal text). So\n * `remarkBrandMath` rewrites them into our own `brand-math` / `brand-math-inline`\n * elements carrying the raw TeX, and the React renderers turn that into KaTeX.\n *\n * SECURITY: the TeX is untrusted input, so KaTeX runs with `trust: false` (blocks\n * `\\href`/`\\url`/class injection), a bounded `maxExpand` (caps macro expansion —\n * the `\\def`-bomb DoS guard), and `throwOnError: false` (a bad expression renders\n * a contained error, never crashes the page). a11y: `output: \"htmlAndMathml\"`\n * emits MathML (read by assistive tech) alongside the visual HTML.\n */\nimport { useLocale } from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport katex from \"katex\";\nimport { useMemo, type HTMLAttributes } from \"react\";\nimport { visit } from \"unist-util-visit\";\n\n/** Block math element (`$$…$$`). */\nexport const MATH_BLOCK_TAG = \"brand-math\";\n/** Inline math element (`$…$`). */\nexport const MATH_INLINE_TAG = \"brand-math-inline\";\n/** hast property carrying the raw TeX (rendered as `data-tex`). */\nexport const MATH_PROP = \"dataTex\";\nconst MATH_ATTR = \"data-tex\";\n\n/** Cap macro expansion — bounds `\\def`-style expansion against untrusted input. */\nconst MAX_EXPAND = 1000;\n\ninterface MdNode {\n type: string;\n value?: string;\n children?: MdNode[];\n data?: { hName?: string; hProperties?: Record<string, unknown> };\n}\n\n/**\n * Rewrite `inlineMath` / `math` (from remark-math) into branded elements carrying\n * the raw TeX. Runs AFTER `remarkMath` in the plugin array.\n */\nexport function remarkBrandMath() {\n return (tree: unknown) => {\n visit(tree as never, (node: MdNode, index: number | undefined, parent: MdNode | undefined) => {\n if (node.type !== \"inlineMath\" && node.type !== \"math\") return;\n if (!parent?.children || index == null) return;\n const display = node.type === \"math\";\n const tex = typeof node.value === \"string\" ? node.value : \"\";\n parent.children[index] = {\n type: display ? \"brandMathBlock\" : \"brandMathInline\",\n data: {\n hName: display ? MATH_BLOCK_TAG : MATH_INLINE_TAG,\n hProperties: { [MATH_PROP]: tex },\n },\n };\n });\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* React renderers */\n/* ------------------------------------------------------------------ */\n\ntype TagProps = { node?: unknown; children?: React.ReactNode } & Record<string, unknown>;\n\nfunction readTex(rest: TagProps): string {\n return (rest[MATH_ATTR] as string | undefined) ?? (rest[MATH_PROP] as string | undefined) ?? \"\";\n}\n\n/** Render TeX to a KaTeX HTML string (safe options); never throws. */\nfunction renderKatex(tex: string, displayMode: boolean): { html: string; error: boolean } {\n try {\n return {\n html: katex.renderToString(tex, {\n displayMode,\n throwOnError: false,\n errorColor: \"var(--destructive)\",\n trust: false,\n maxExpand: MAX_EXPAND,\n strict: \"ignore\",\n output: \"htmlAndMathml\",\n }),\n error: false,\n };\n } catch {\n return { html: \"\", error: true };\n }\n}\n\nexport interface MathProps extends Omit<HTMLAttributes<HTMLElement>, \"children\"> {\n /** Raw TeX source. */\n tex: string;\n}\n\n/** Inline math (`$…$`) → KaTeX, in the text flow. */\nexport function MathInline({ tex, className, ...props }: MathProps) {\n const { t } = useLocale();\n const { html, error } = useMemo(() => renderKatex(tex, false), [tex]);\n if (error) {\n return (\n <code\n className={cn(\"text-destructive-text\", className)}\n aria-label={t(\"editor.math.renderErrorLabel\", { tex })}\n title={t(\"editor.math.renderError\")}\n {...props}\n >\n {tex}\n </code>\n );\n }\n return (\n <span\n role=\"math\"\n // The raw TeX is a universally-readable fallback name for AT that does not\n // process the embedded MathML; MathML-capable AT reads the MathML instead.\n aria-label={tex}\n className={cn(\"inline-block align-middle\", className)}\n // KaTeX output is generated with trust:false + bounded maxExpand (safe).\n dangerouslySetInnerHTML={{ __html: html }}\n {...props}\n />\n );\n}\n\n/** Block math (`$$…$$`) → centered display KaTeX. */\nexport function MathBlock({ tex, className, ...props }: MathProps) {\n const { t } = useLocale();\n const { html, error } = useMemo(() => renderKatex(tex, true), [tex]);\n if (error) {\n return (\n <pre\n className={cn(\n \"overflow-x-auto rounded-md bg-surface-muted p-3 text-destructive-text\",\n className,\n )}\n aria-label={t(\"editor.math.renderErrorLabel\", { tex })}\n title={t(\"editor.math.renderError\")}\n {...props}\n >\n <code>{tex}</code>\n </pre>\n );\n }\n return (\n <div\n role=\"math\"\n aria-label={tex}\n className={cn(\"my-3 overflow-x-auto text-center\", className)}\n dangerouslySetInnerHTML={{ __html: html }}\n {...props}\n />\n );\n}\n\n/** Components-map renderer for the inline math element. */\nexport function MathInlineTag({ node: _n, children: _c, ...rest }: TagProps) {\n return <MathInline tex={readTex(rest)} />;\n}\n\n/** Components-map renderer for the block math element. */\nexport function MathBlockTag({ node: _n, children: _c, ...rest }: TagProps) {\n return <MathBlock tex={readTex(rest)} />;\n}\n","\"use client\";\n\n/**\n * Generated table of contents — an in-flow `::toc` block.\n *\n * Reuses `parseMarkdownOutline` (the same heading extractor `DocumentOutline`\n * uses — no second parser) for slugs + levels, and renders a quiet nav list of\n * same-page anchor links. `MarkdownPreview` provides the outline through\n * `TocProvider`; it also stamps the matching `id` on each rendered heading\n * (`useHeadingId`) so the links resolve.\n */\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { createContext, forwardRef, useContext, type HTMLAttributes } from \"react\";\n\nimport type { MarkdownOutlineItem } from \"../markdown-outline\";\n\n// Per-depth indent on the standard spacing scale (statically scannable so Tailwind\n// keeps the classes). Index = heading depth relative to the shallowest in view.\nconst INDENT = [\"ps-0\", \"ps-3\", \"ps-6\", \"ps-9\", \"ps-12\", \"ps-12\"] as const;\n\ninterface TocState {\n items: MarkdownOutlineItem[];\n /** Heading slug keyed by 1-based start line (frontmatter-stripped coords). */\n idByLine: Map<number, string>;\n}\n\nconst TocContext = createContext<TocState | null>(null);\n\nexport interface TocProviderProps {\n items: MarkdownOutlineItem[];\n children: React.ReactNode;\n}\n\nexport function TocProvider({ items, children }: TocProviderProps) {\n const idByLine = new Map<number, string>();\n for (const it of items) idByLine.set(it.line, it.id);\n return <TocContext.Provider value={{ items, idByLine }}>{children}</TocContext.Provider>;\n}\n\n/** The heading `id` for a 1-based source line, or `undefined`. */\nexport function useHeadingId(line: number | undefined): string | undefined {\n const ctx = useContext(TocContext);\n if (line == null || !ctx) return undefined;\n return ctx.idByLine.get(line);\n}\n\nexport interface TableOfContentsProps extends Omit<HTMLAttributes<HTMLElement>, \"children\"> {\n /** Heading outline; defaults to the outline collected by `MarkdownPreview`. */\n items?: MarkdownOutlineItem[];\n /** Section heading label. Default `\"Contents\"`. */\n title?: string;\n /** Deepest heading level to include (1–6). Default 3. */\n maxLevel?: 1 | 2 | 3 | 4 | 5 | 6;\n}\n\n/**\n * Quiet generated TOC. Standalone with an explicit `items` array, or fed from the\n * preview context inside a `::toc` block. Indentation tracks heading depth; no\n * fill or border — the indent + links are the only gestures.\n */\nexport const TableOfContents = forwardRef<HTMLElement, TableOfContentsProps>(\n function TableOfContents({ items, title = \"Contents\", maxLevel = 3, className, ...props }, ref) {\n const ctx = useContext(TocContext);\n const source = items ?? ctx?.items ?? [];\n const list = source.filter((it) => it.level <= maxLevel);\n if (list.length === 0) return null;\n\n const minLevel = Math.min(...list.map((it) => it.level));\n\n return (\n <nav ref={ref} aria-label={title} className={cn(\"my-4 text-meta\", className)} {...props}>\n <p className=\"mb-2 font-medium text-muted-foreground\">{title}</p>\n <ol className=\"space-y-1\">\n {list.map((it) => (\n <li key={it.id} className={INDENT[Math.min(it.level - minLevel, INDENT.length - 1)]}>\n <a\n href={`#${it.id}`}\n className=\"text-muted-foreground underline hover:text-foreground hover:underline focus-visible:rounded-sm focus-ring\"\n >\n {it.text}\n </a>\n </li>\n ))}\n </ol>\n </nav>\n );\n },\n);\n","\"use client\";\n\n/**\n * The `:::iterate` / `:::pivot` directive bridge — turns a directive context\n * (attributes + the captured raw body template) into an `IterationSpec`, and\n * renders an `IterationBlock` with a recursion guard so a self-referential\n * template can't loop forever (the transclusion depth-cap precedent).\n */\nimport { createContext, useContext, type ReactNode } from \"react\";\n\nimport {\n IterationBlock,\n type EvaluateIteration,\n type InterpolateTemplate,\n type IterationLayout,\n type IterationSpec,\n} from \"./iteration\";\n\n/** Max nesting depth for `:::iterate` inside an iterated cell. */\nexport const MAX_ITERATION_DEPTH = 3;\n\n/** Current iteration nesting depth; 0 = top-level document. */\nconst IterationDepthContext = createContext(0);\n\nconst DEFAULT_LAYOUT: Record<\"iterate\" | \"pivot\", IterationLayout> = {\n iterate: \"stacked\",\n pivot: \"matrix\",\n};\n\nconst LAYOUTS = new Set<IterationLayout>([\"stacked\", \"grid\", \"matrix\", \"bento\"]);\n\n/** Build an `IterationSpec` from a directive's name + attributes + raw body. */\nexport function specFromDirective(\n name: \"iterate\" | \"pivot\",\n attributes: Record<string, string>,\n rawBody: string | undefined,\n): IterationSpec {\n const kind = name;\n const layoutAttr = attributes.layout as IterationLayout | undefined;\n const layout = layoutAttr && LAYOUTS.has(layoutAttr) ? layoutAttr : DEFAULT_LAYOUT[kind];\n const columns = attributes.columns ? Number(attributes.columns) || undefined : undefined;\n return {\n kind,\n layout,\n template: rawBody ?? \"\",\n as: attributes.as?.trim() || \"item\",\n source: attributes.source,\n rows: attributes.rows,\n cols: attributes.cols,\n columns,\n attributes,\n };\n}\n\nexport interface IterationDirectiveProps {\n spec: IterationSpec;\n evaluate: EvaluateIteration;\n interpolate?: InterpolateTemplate;\n /** Render one cell's resolved markdown → node (a nested `MarkdownPreview`). */\n renderCell: (markdown: string) => ReactNode;\n}\n\n/**\n * Renders an `IterationBlock` one nesting level deeper, refusing to recurse past\n * {@link MAX_ITERATION_DEPTH}. Cells (which mount nested `MarkdownPreview`s) read\n * the incremented depth, so a nested `:::iterate` is bounded.\n */\nexport function IterationDirective({\n spec,\n evaluate,\n interpolate,\n renderCell,\n}: IterationDirectiveProps) {\n const depth = useContext(IterationDepthContext);\n if (depth >= MAX_ITERATION_DEPTH) {\n return (\n <div className=\"my-4 text-meta text-muted-foreground italic\" data-iteration-too-deep=\"\">\n Iteration nested too deep — skipped.\n </div>\n );\n }\n return (\n <IterationDepthContext.Provider value={depth + 1}>\n <IterationBlock\n spec={spec}\n evaluate={evaluate}\n interpolate={interpolate}\n render={renderCell}\n />\n </IterationDepthContext.Provider>\n );\n}\n","\"use client\";\n\n/**\n * MarkdownToolbar — formatting chrome for the markdown SOURCE pane, composed\n * entirely from @elabs-ai/components-ui (Button, Tooltip, Separator, DropdownMenu). Actions run\n * against a Monaco editor instance via the pure commands in markdown-commands.ts.\n * Buttons disable when no editor is mounted.\n */\nimport {\n Button,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n Separator,\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n useLocale,\n} from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport {\n Bold,\n ChevronDown,\n Code2,\n Heading,\n Italic,\n Link2,\n List,\n ListOrdered,\n Minus,\n Quote,\n SquarePlus,\n} from \"lucide-react\";\nimport { forwardRef, Fragment, type HTMLAttributes, type ReactNode } from \"react\";\n\nimport type { MonacoCodeEditor } from \"../code-editor\";\nimport { groupSlashCommands, type SlashCommand } from \"../markdown-editor/slash\";\nimport {\n insertDirective,\n insertHorizontalRule,\n insertLink,\n toggleLinePrefix,\n wrapSelection,\n} from \"./markdown-commands\";\n\nexport interface MarkdownToolbarProps extends HTMLAttributes<HTMLDivElement> {\n /** The Monaco editor instance to act on (from CodeEditor ref/onMount). */\n editor: MonacoCodeEditor | null;\n /** Extra controls rendered on the right (e.g. a mode switch). */\n actions?: ReactNode;\n /**\n * Drives the **Insert** menu. When set, the menu lists every command that\n * carries a `snippet` (grouped by `group`), inserting that markdown at the\n * caret — so the source / split pane reaches the SAME blocks as the WYSIWYG\n * slash menu (`/calc`, `/iterate`, `/pivot`, plus any consumer commands).\n * When omitted, the menu falls back to the four built-in directive snippets.\n * (A4)\n */\n insertCommands?: SlashCommand[];\n}\n\n/** A command that actually carries a source-mode snippet. */\ntype InsertableCommand = SlashCommand & { snippet: string };\n\n// The `title=`/`label=` values below are example CONTENT dropped into the user's\n// document (the same seeds `brand-slash-commands.ts` uses), not UI chrome — left\n// as literal English placeholder text the author overwrites.\nconst DIRECTIVE_SNIPPETS: { labelKey: string; snippet: string }[] = [\n {\n labelKey: \"editor.markdownToolbar.directiveCard\",\n snippet: `:::card{title=\"Title\"}\\nContent\\n:::`, // i18n-exempt: example document content\n },\n {\n labelKey: \"editor.markdownToolbar.directiveCallout\",\n snippet: `:::callout{type=\"info\" title=\"Note\"}\\nMessage\\n:::`, // i18n-exempt: example document content\n },\n {\n labelKey: \"editor.markdownToolbar.directiveMetric\",\n snippet: `::metric{label=\"Label\" value=\"0\" description=\"detail\"}`, // i18n-exempt: example document content\n },\n {\n labelKey: \"editor.markdownToolbar.directiveTimeline\",\n snippet: `:::timeline\\n- (done) Step one\\n- (active) Step two\\n- (pending) Step three\\n:::`, // i18n-exempt: example document content\n },\n];\n\nexport const MarkdownToolbar = forwardRef<HTMLDivElement, MarkdownToolbarProps>(\n function MarkdownToolbar({ editor, actions, insertCommands, className, ...props }, ref) {\n const { t } = useLocale();\n const disabled = !editor;\n const run = (fn: (e: MonacoCodeEditor) => void) => () => {\n if (editor) fn(editor);\n };\n\n // The Insert menu is driven by the slash registry when provided (A4): only\n // commands that carry a source-mode `snippet`, grouped by `group`.\n const insertGroups = insertCommands\n ? groupSlashCommands(\n insertCommands.filter((c): c is InsertableCommand => typeof c.snippet === \"string\"),\n )\n : null;\n\n const IconButton = ({\n label,\n icon,\n onClick,\n }: {\n label: string;\n icon: ReactNode;\n onClick: () => void;\n }) => (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n disabled={disabled}\n onClick={onClick}\n aria-label={label}\n >\n {icon}\n </Button>\n </TooltipTrigger>\n <TooltipContent>{label}</TooltipContent>\n </Tooltip>\n );\n\n return (\n <TooltipProvider delayDuration={300}>\n <div\n ref={ref}\n role=\"toolbar\"\n aria-label={t(\"editor.markdownToolbar.label\")}\n className={cn(\n \"flex h-10 shrink-0 items-center gap-0.5 border-b border-border bg-surface px-2\",\n className,\n )}\n {...props}\n >\n <IconButton\n label={t(\"editor.markdownToolbar.bold\")}\n icon={<Bold className=\"size-4\" />}\n onClick={run((e) => wrapSelection(e, \"**\"))}\n />\n <IconButton\n label={t(\"editor.markdownToolbar.italic\")}\n icon={<Italic className=\"size-4\" />}\n onClick={run((e) => wrapSelection(e, \"*\"))}\n />\n <IconButton\n label={t(\"editor.markdownToolbar.inlineCode\")}\n icon={<Code2 className=\"size-4\" />}\n onClick={run((e) => wrapSelection(e, \"`\"))}\n />\n <IconButton\n label={t(\"editor.markdownToolbar.link\")}\n icon={<Link2 className=\"size-4\" />}\n onClick={run(insertLink)}\n />\n\n <Separator orientation=\"vertical\" className=\"mx-1 h-5\" />\n\n <DropdownMenu>\n <Tooltip>\n <TooltipTrigger asChild>\n <DropdownMenuTrigger asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n disabled={disabled}\n className=\"gap-1\"\n aria-label={t(\"editor.markdownToolbar.headingLevel\")}\n >\n <Heading className=\"size-4\" />\n <ChevronDown className=\"size-3\" />\n </Button>\n </DropdownMenuTrigger>\n </TooltipTrigger>\n <TooltipContent>{t(\"editor.markdownToolbar.heading\")}</TooltipContent>\n </Tooltip>\n <DropdownMenuContent align=\"start\">\n {([1, 2, 3] as const).map((level) => (\n <DropdownMenuItem\n key={level}\n onSelect={run((e) => toggleLinePrefix(e, `${\"#\".repeat(level)} `))}\n >\n {t(\"editor.markdownToolbar.headingLevelItem\", { level })}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n\n <IconButton\n label={t(\"editor.markdownToolbar.quote\")}\n icon={<Quote className=\"size-4\" />}\n onClick={run((e) => toggleLinePrefix(e, \"> \"))}\n />\n <IconButton\n label={t(\"editor.markdownToolbar.bulletList\")}\n icon={<List className=\"size-4\" />}\n onClick={run((e) => toggleLinePrefix(e, \"- \"))}\n />\n <IconButton\n label={t(\"editor.markdownToolbar.numberedList\")}\n icon={<ListOrdered className=\"size-4\" />}\n onClick={run((e) => toggleLinePrefix(e, \"1. \"))}\n />\n <IconButton\n label={t(\"editor.markdownToolbar.divider\")}\n icon={<Minus className=\"size-4\" />}\n onClick={run(insertHorizontalRule)}\n />\n\n <Separator orientation=\"vertical\" className=\"mx-1 h-5\" />\n\n <DropdownMenu>\n <Tooltip>\n <TooltipTrigger asChild>\n <DropdownMenuTrigger asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n disabled={disabled}\n className=\"gap-1\"\n aria-label={t(\"editor.markdownToolbar.insertBlock\")}\n >\n <SquarePlus className=\"size-4\" />\n <span className=\"text-xs\">{t(\"editor.markdownToolbar.insert\")}</span>\n </Button>\n </DropdownMenuTrigger>\n </TooltipTrigger>\n <TooltipContent>{t(\"editor.markdownToolbar.insertBrandBlock\")}</TooltipContent>\n </Tooltip>\n <DropdownMenuContent align=\"start\">\n {insertGroups && insertGroups.length > 0\n ? insertGroups.map(({ group, commands }, gi) => (\n <Fragment key={group}>\n {gi > 0 ? <DropdownMenuSeparator /> : null}\n <DropdownMenuLabel className=\"text-meta font-medium text-muted-foreground\">\n {group}\n </DropdownMenuLabel>\n {(commands as InsertableCommand[]).map((cmd) => (\n <DropdownMenuItem\n key={cmd.id}\n className=\"gap-2\"\n onSelect={run((e) => insertDirective(e, cmd.snippet))}\n >\n {cmd.icon ? (\n <span className=\"flex size-4 shrink-0 items-center justify-center text-muted-foreground [&_svg]:size-4\">\n {cmd.icon}\n </span>\n ) : null}\n {cmd.label}\n </DropdownMenuItem>\n ))}\n </Fragment>\n ))\n : DIRECTIVE_SNIPPETS.map(({ labelKey, snippet }) => (\n <DropdownMenuItem\n key={labelKey}\n onSelect={run((e) => insertDirective(e, snippet))}\n >\n {t(labelKey)}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n\n {actions ? <div className=\"ml-auto flex items-center gap-1.5\">{actions}</div> : null}\n </div>\n </TooltipProvider>\n );\n },\n);\n","/**\n * Focus-writing helpers (Ulysses Phase A) — the pure half of the workspace's\n * \"Focus\" toggle: paragraph focus (mark the top-level block that owns the\n * selection) and typewriter scrolling (keep the caret in a vertical band\n * around the scroller's center). Engine-agnostic: plain DOM walking, no\n * ProseMirror plugin surface — testable in jsdom without booting Milkdown.\n */\n\n/** The editor-root CHILD that contains `node` (the active top-level block). */\nexport function topLevelBlockOf(editorRoot: Element, node: Node | null): Element | null {\n let current: Node | null = node;\n while (current && current.parentNode !== editorRoot) {\n current = current.parentNode;\n }\n return current instanceof Element ? current : null;\n}\n\n/**\n * Typewriter scroll adjustment: how far the scroller must move so the caret\n * sits back in the center band. Returns 0 while the caret is inside the band\n * (no jitter on every keystroke — only re-center when it drifts out).\n *\n * @param band fraction of the scroller height treated as \"centered enough\".\n */\nexport function typewriterDelta(\n caretTop: number,\n caretHeight: number,\n hostTop: number,\n hostHeight: number,\n band = 0.22,\n): number {\n if (hostHeight <= 0) return 0;\n const center = hostTop + hostHeight / 2;\n const caretMid = caretTop + caretHeight / 2;\n const tolerance = (hostHeight * band) / 2;\n const off = caretMid - center;\n return Math.abs(off) <= tolerance ? 0 : off;\n}\n","/**\n * `@elabs-ai/components-editor/markdown/parse` — a Monaco-free markdown parser.\n *\n * `parseMarkdown(md)` returns the mdast `Root` for the SAME dialect the branded\n * preview parses: GitHub-flavored markdown + `:::`/`::`/`:` directives + YAML\n * frontmatter. Split onto its own leaf subpath (like `./markdown/frontmatter`) so\n * SERVER, RSC, and unit-test consumers can parse markdown WITHOUT pulling the\n * editor engines (Milkdown, Monaco, Streamdown) into their bundle — the whole\n * reason the `.` vs `./markdown` split exists. Depends only on `unified` +\n * `remark-*` (no React, no Monaco).\n *\n * It returns RAW directive mdast (`containerDirective` / `leafDirective` /\n * `textDirective` nodes) — it does NOT run `remarkBrandDirectives` (that rewrites\n * directives into the `<brand-directive>` hast tag, which is a RENDER concern).\n * Walk the tree by `node.type` + `node.name` yourself. The match is at the\n * DIALECT level (same plugins/extensions); it is not byte-identical to the tree\n * Streamdown builds internally (which also applies a streaming block-splitter).\n */\nimport type { Root } from \"mdast\";\nimport remarkDirective from \"remark-directive\";\nimport remarkFrontmatter from \"remark-frontmatter\";\nimport remarkGfm from \"remark-gfm\";\nimport remarkParse from \"remark-parse\";\nimport { unified } from \"unified\";\n\n// Built once: a frozen parser-only processor (gfm + frontmatter + directive\n// syntax extensions). `parse()` is stateless per call, so one instance is safe.\nconst processor = unified()\n .use(remarkParse)\n .use(remarkGfm)\n .use(remarkFrontmatter, [\"yaml\"])\n .use(remarkDirective)\n .freeze();\n\n/** Parse markdown to mdast (gfm + directives + frontmatter). Monaco-free. */\nexport function parseMarkdown(md: string): Root {\n return processor.parse(md) as Root;\n}\n","\"use client\";\n\n/**\n * MermaidWorkspace (#L2) — the source ⇄ diagram editing surface.\n *\n * Same compound pattern as `MarkdownWorkspace`: one mermaid source string,\n * Monaco on the left, the live branded `MermaidDiagram` on the right\n * (debounced so keystrokes don't thrash the engine). Controlled\n * (`value`/`onChange`) or uncontrolled (`defaultValue`).\n */\nimport { ResizableHandle, ResizablePanel, ResizablePanelGroup } from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { forwardRef, useEffect, useState, type HTMLAttributes } from \"react\";\n\nimport { CodeEditor } from \"../code-editor\";\nimport { MermaidDiagram } from \"../mermaid-diagram\";\n\nexport interface MermaidWorkspaceProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n \"onChange\" | \"defaultValue\"\n> {\n value?: string;\n defaultValue?: string;\n onChange?: (source: string) => void;\n /** Debounce (ms) before the diagram re-renders while typing. Default 350. */\n debounceMs?: number;\n}\n\nexport const MermaidWorkspace = forwardRef<HTMLDivElement, MermaidWorkspaceProps>(\n function MermaidWorkspace(\n { value, defaultValue, onChange, debounceMs = 350, className, ...props },\n ref,\n ) {\n const isControlled = value !== undefined;\n const [internal, setInternal] = useState(value ?? defaultValue ?? \"\");\n const source = isControlled ? value : internal;\n\n const [debounced, setDebounced] = useState(source);\n useEffect(() => {\n const t = setTimeout(() => setDebounced(source), debounceMs);\n return () => clearTimeout(t);\n }, [source, debounceMs]);\n\n const setSource = (next: string) => {\n if (!isControlled) setInternal(next);\n onChange?.(next);\n };\n\n return (\n <div\n ref={ref}\n data-testid=\"mermaid-workspace\"\n className={cn(\"h-full min-h-0 overflow-hidden\", className)}\n {...props}\n >\n <ResizablePanelGroup direction=\"horizontal\">\n <ResizablePanel defaultSize={45} minSize={25}>\n {/* Monaco has no mermaid grammar — plaintext keeps it honest (no wrong colors). */}\n <CodeEditor language=\"plaintext\" value={source} onChange={setSource} />\n </ResizablePanel>\n <ResizableHandle withHandle />\n <ResizablePanel defaultSize={55} minSize={25}>\n <div className=\"h-full overflow-auto p-4\">\n <MermaidDiagram chart={debounced} label=\"Diagram preview\" />\n </div>\n </ResizablePanel>\n </ResizablePanelGroup>\n </div>\n );\n },\n);\n","\"use client\";\n\n/**\n * DecisionCard — renders a `:::decision{status=accepted date=2026-06-15}` directive\n * as a decision-record card.\n *\n * Anatomy:\n * - Status badge (accepted | rejected | proposed | superseded) in a header rail.\n * - Date (ISO or human-readable) rendered as a `<time>` element.\n * - Rationale body (the directive body text, rendered children).\n * - Optional \"Alternatives considered\" section (comma-separated `alternatives=`\n * attribute). The attribute shape is intentional: alternatives are typically\n * short phrases, and keeping them out of the body lets the body stay prose.\n *\n * Status → Badge variant mapping:\n * accepted → success · rejected → destructive · proposed → info ·\n * superseded → secondary (neutral — de-emphasized, not a failure).\n *\n * The card is a `<section aria-label>` for landmark navigation.\n */\nimport {\n Badge,\n Card,\n CardContent,\n CardHeader,\n Separator,\n useLocale,\n type BadgeProps,\n} from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { cva } from \"class-variance-authority\";\nimport { CheckCircle2, CircleDashed, Clock, RefreshCw } from \"lucide-react\";\nimport {\n forwardRef,\n type ComponentType,\n type HTMLAttributes,\n type ReactNode,\n type SVGProps,\n} from \"react\";\n\n/* ------------------------------------------------------------------ */\n/* Status vocabulary */\n/* ------------------------------------------------------------------ */\n\nexport const DECISION_STATUSES = [\"accepted\", \"rejected\", \"proposed\", \"superseded\"] as const;\nexport type DecisionStatus = (typeof DECISION_STATUSES)[number];\n\nconst STATUS_BADGE_VARIANT: Record<DecisionStatus, BadgeProps[\"variant\"]> = {\n accepted: \"success\",\n rejected: \"destructive\",\n proposed: \"info\",\n superseded: \"secondary\",\n};\n\n/** Status → translation key (see `editor.decisionCard.status.*` in messages.ts). */\nconst STATUS_LABEL_KEYS: Record<DecisionStatus, string> = {\n accepted: \"editor.decisionCard.statusAccepted\",\n rejected: \"editor.decisionCard.statusRejected\",\n proposed: \"editor.decisionCard.statusProposed\",\n superseded: \"editor.decisionCard.statusSuperseded\",\n};\n\nconst STATUS_ICONS: Record<DecisionStatus, ComponentType<SVGProps<SVGSVGElement>>> = {\n accepted: CheckCircle2,\n rejected: CircleDashed,\n proposed: Clock,\n superseded: RefreshCw,\n};\n\nfunction isDecisionStatus(s: string): s is DecisionStatus {\n return DECISION_STATUSES.includes(s as DecisionStatus);\n}\n\n/* ------------------------------------------------------------------ */\n/* cva (status rail accent) */\n/* ------------------------------------------------------------------ */\n\nexport const decisionCardVariants = cva(\"border-s-4\", {\n variants: {\n status: {\n accepted: \"border-s-success\",\n rejected: \"border-s-destructive\",\n proposed: \"border-s-info\",\n superseded: \"border-s-border\",\n },\n },\n defaultVariants: { status: \"proposed\" },\n});\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport interface DecisionCardProps extends HTMLAttributes<HTMLElement> {\n /**\n * Decision outcome. One of the four canonical states; anything unrecognised\n * renders as \"proposed\".\n */\n status?: string;\n /**\n * ISO date or human-readable date of the decision\n * (e.g. `\"2026-06-15\"` or `\"June 2026\"`).\n */\n date?: string;\n /**\n * Comma-separated alternative options considered before this decision.\n * E.g. `\"Redis cache, in-memory map, SQLite\"`.\n */\n alternatives?: string;\n /** The rationale body (rendered markdown children of the directive). */\n children?: ReactNode;\n}\n\nexport const DecisionCard = forwardRef<HTMLElement, DecisionCardProps>(function DecisionCard(\n { status: rawStatus, date, alternatives, children, className, ...props },\n ref,\n) {\n const { t } = useLocale();\n const status: DecisionStatus = isDecisionStatus(rawStatus ?? \"\")\n ? (rawStatus as DecisionStatus)\n : \"proposed\";\n const badgeVariant = STATUS_BADGE_VARIANT[status];\n const label = t(STATUS_LABEL_KEYS[status]);\n const Icon = STATUS_ICONS[status];\n\n const altItems = alternatives\n ? alternatives\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean)\n : [];\n\n return (\n <section\n ref={ref}\n aria-label={t(\"editor.decisionCard.label\", { label })}\n className={cn(\"not-prose\", className)}\n {...props}\n >\n <Card className={cn(decisionCardVariants({ status }))}>\n <CardHeader className=\"pb-3\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <Badge variant={badgeVariant} className=\"gap-1.5\">\n <Icon className=\"size-3\" aria-hidden=\"true\" />\n {label}\n </Badge>\n {date ? (\n <time dateTime={date} className=\"text-meta text-muted-foreground tabular-nums\">\n {date}\n </time>\n ) : null}\n </div>\n </CardHeader>\n\n {children ? (\n <CardContent className=\"text-body text-foreground\">{children}</CardContent>\n ) : null}\n\n {altItems.length > 0 ? (\n <>\n <Separator />\n <div className=\"px-6 py-4\">\n <p className=\"mb-2 text-meta font-medium text-muted-foreground\">\n {t(\"editor.decisionCard.alternativesConsidered\")}\n </p>\n <ul\n className=\"flex flex-wrap gap-1.5\"\n aria-label={t(\"editor.decisionCard.alternativesConsidered\")}\n >\n {altItems.map((alt) => (\n <li key={alt}>\n <Badge variant=\"outline\" className=\"text-meta\">\n {alt}\n </Badge>\n </li>\n ))}\n </ul>\n </div>\n </>\n ) : null}\n </Card>\n </section>\n );\n});\n","\"use client\";\n\n/**\n * EntityCard + EntityChip — renders `:::entity{kind=org name=\"Acme\"}` (block card)\n * and `:entity[Acme]{kind=org}` (inline chip) directives.\n *\n * One component handles both syntaxes; the renderer factory branches on `ctx.kind`.\n *\n * Entity kinds and their icon/tone:\n * org → Building2 / secondary (companies, organisations)\n * person → User / primary (people, authors)\n * place → MapPin / info (locations, regions)\n * product → Box / success (products, services)\n * concept → Lightbulb / warning (ideas, topics)\n * default → Tag / outline (anything else)\n *\n * The inline chip is a `<span>` — no block wrapper — so it stays inside `<p>` without\n * creating invalid HTML. A11y: kind is conveyed via `aria-label` (not icon alone).\n */\nimport { Card, CardContent, CardHeader, CardTitle } from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { Box, Building2, Lightbulb, MapPin, Tag, User } from \"lucide-react\";\nimport {\n forwardRef,\n type ComponentType,\n type HTMLAttributes,\n type ReactNode,\n type SVGProps,\n} from \"react\";\n\n/* ------------------------------------------------------------------ */\n/* Kind vocabulary */\n/* ------------------------------------------------------------------ */\n\nexport const ENTITY_KINDS = [\"org\", \"person\", \"place\", \"product\", \"concept\"] as const;\nexport type EntityKind = (typeof ENTITY_KINDS)[number];\n\ntype KindMeta = {\n Icon: ComponentType<SVGProps<SVGSVGElement>>;\n label: string;\n};\n\nconst KIND_META: Record<string, KindMeta> = {\n org: { Icon: Building2, label: \"Organisation\" },\n person: { Icon: User, label: \"Person\" },\n place: { Icon: MapPin, label: \"Place\" },\n product: { Icon: Box, label: \"Product\" },\n concept: { Icon: Lightbulb, label: \"Concept\" },\n};\n\nconst DEFAULT_KIND_META: KindMeta = { Icon: Tag, label: \"Entity\" };\n\nfunction kindMeta(kind: string | undefined): KindMeta {\n return KIND_META[kind ?? \"\"] ?? DEFAULT_KIND_META;\n}\n\n/* ------------------------------------------------------------------ */\n/* cva */\n/* ------------------------------------------------------------------ */\n\nexport const entityChipVariants = cva(\n // inline-flex + align-middle keeps the chip in the text baseline;\n // no `block` wrapper so it is valid inside <p>.\n \"inline-flex items-center gap-1 rounded-sm border px-1.5 py-0.5 text-meta font-medium align-middle focus-ring\",\n {\n variants: {\n kind: {\n org: \"border-border bg-secondary/60 text-secondary-foreground\",\n // #399 — same reasoning as `concept` below: a 10% WASH is not a plate\n // and not a mark, so the LABEL takes the on-surface `-text` rung. This\n // is the row that had no `-text` rung to reach for until #399 minted it.\n person: \"border-primary/30 bg-primary/10 text-primary-text\",\n place: \"border-info/30 bg-info/10 text-info-text\",\n product: \"border-success/30 bg-success/10 text-success-text\",\n // `-text`, not `-foreground`: the chip is a 10% WASH on the page surface,\n // not a solid `--warning` plate, so it needs the on-surface rung its\n // place/product siblings use (#381 flipped `--warning-foreground` to\n // light ink for the now-deep fill).\n concept: \"border-warning/30 bg-warning/10 text-warning-text\",\n default: \"border-border text-foreground\",\n },\n },\n defaultVariants: { kind: \"default\" },\n },\n);\n\nfunction chipKind(kind: string | undefined): VariantProps<typeof entityChipVariants>[\"kind\"] {\n if (!kind) return \"default\";\n const known: Array<VariantProps<typeof entityChipVariants>[\"kind\"]> = [\n \"org\",\n \"person\",\n \"place\",\n \"product\",\n \"concept\",\n \"default\",\n ];\n return known.includes(kind as never)\n ? (kind as VariantProps<typeof entityChipVariants>[\"kind\"])\n : \"default\";\n}\n\n/* ------------------------------------------------------------------ */\n/* EntityChip (inline) */\n/* ------------------------------------------------------------------ */\n\nexport interface EntityChipProps extends HTMLAttributes<HTMLSpanElement> {\n /** Entity kind — drives icon and tone. */\n kind?: string;\n /** Display label (the directive's label text or `name` attribute). */\n children?: ReactNode;\n}\n\nexport const EntityChip = forwardRef<HTMLSpanElement, EntityChipProps>(function EntityChip(\n { kind: rawKind, children, className, ...props },\n ref,\n) {\n const { Icon, label } = kindMeta(rawKind);\n const resolvedKind = chipKind(rawKind);\n return (\n <span\n ref={ref}\n role=\"mark\"\n aria-label={children ? `${String(children)} (${label})` : label}\n className={cn(entityChipVariants({ kind: resolvedKind }), className)}\n {...props}\n >\n <Icon className=\"size-3 shrink-0\" aria-hidden=\"true\" />\n <span>{children}</span>\n </span>\n );\n});\n\n/* ------------------------------------------------------------------ */\n/* EntityCard (block) */\n/* ------------------------------------------------------------------ */\n\nexport interface EntityCardProps extends HTMLAttributes<HTMLElement> {\n /** Entity kind — drives the icon and header tone. */\n kind?: string;\n /** Entity name. Falls back to children when absent. */\n name?: string;\n /** Description body (rendered markdown children of the directive). */\n children?: ReactNode;\n}\n\nexport const EntityCard = forwardRef<HTMLElement, EntityCardProps>(function EntityCard(\n { kind: rawKind, name, children, className, ...props },\n ref,\n) {\n const { Icon, label } = kindMeta(rawKind);\n\n return (\n <section\n ref={ref}\n aria-label={name ? `${label}: ${name}` : label}\n className={cn(\"not-prose\", className)}\n {...props}\n >\n <Card>\n <CardHeader className=\"pb-3\">\n <div className=\"flex items-center gap-2\">\n <span\n className=\"flex size-7 shrink-0 items-center justify-center rounded-md bg-muted\"\n aria-hidden=\"true\"\n >\n <Icon className=\"size-4 text-muted-foreground\" />\n </span>\n <div className=\"min-w-0\">\n {name ? <CardTitle className=\"truncate\">{name}</CardTitle> : null}\n <p className=\"text-meta text-muted-foreground\">{label}</p>\n </div>\n </div>\n </CardHeader>\n {children ? (\n <CardContent className=\"text-body text-foreground\">{children}</CardContent>\n ) : null}\n </Card>\n </section>\n );\n});\n","\"use client\";\n\n/**\n * KnowledgeCard — renders a `:::knowledge{sources=\"notes/a.md, notes/b.md\"}` directive\n * as a sourced-fact card.\n *\n * Anatomy:\n * - Fact body (rendered markdown children of the directive).\n * - Sources section: each comma-split path is handed to the consumer's `resolve`\n * hook (`resolve(path) => { href, title } | null`). Resolved paths render as\n * `<a>` links; unresolved paths render as plain `<span>` labels — graceful\n * degradation, no errors thrown.\n *\n * The library never reads files. Domain logic (vault index, file system, API) lives\n * entirely in the consumer's `resolve` hook — the same principle as `resolveUrl` on\n * `MarkdownPreview` and `evaluate` on calc blocks.\n *\n * `KnowledgeCard` is standalone (no `resolve` → sources rendered as plain labels).\n * The `knowledgeDirective({ resolve })` factory wires the hook for directive use.\n */\nimport { Card, CardContent, CardFooter, useLocale } from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { BookOpen, FileText } from \"lucide-react\";\nimport { forwardRef, type HTMLAttributes, type ReactNode } from \"react\";\n\n/* ------------------------------------------------------------------ */\n/* Resolver type (consumer-supplied; never bundled) */\n/* ------------------------------------------------------------------ */\n\nexport interface KnowledgeSourceResolved {\n href: string;\n title?: string;\n}\n\n/**\n * Consumer-supplied resolver: path → link data, or `null` when the path cannot\n * be resolved (stale vault link, missing file, etc.). The card degrades\n * gracefully — the source renders as a plain label rather than a broken link.\n */\nexport type KnowledgeSourceResolver = (path: string) => KnowledgeSourceResolved | null;\n\n/* ------------------------------------------------------------------ */\n/* Sub-component: a single resolved/unresolved source row */\n/* ------------------------------------------------------------------ */\n\ninterface SourceRowProps {\n path: string;\n resolve?: KnowledgeSourceResolver;\n}\n\nfunction SourceRow({ path, resolve }: SourceRowProps) {\n const { t } = useLocale();\n const resolved = resolve ? resolve(path) : null;\n const display = resolved?.title ?? path;\n\n if (resolved) {\n return (\n <a\n href={resolved.href}\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n // #399 — a source link is TEXT: the `--link` ink, not the fill.\n className=\"flex min-w-0 items-center gap-1.5 text-meta text-link underline-offset-2 hover:underline focus-ring\"\n aria-label={t(\"editor.knowledgeCard.source\", { name: display })}\n >\n <FileText className=\"size-3 shrink-0\" aria-hidden=\"true\" />\n <span className=\"truncate\">{display}</span>\n </a>\n );\n }\n\n return (\n <span\n className=\"flex min-w-0 items-center gap-1.5 text-meta text-muted-foreground\"\n aria-label={t(\"editor.knowledgeCard.sourceUnresolved\", { name: display })}\n >\n <FileText className=\"size-3 shrink-0\" aria-hidden=\"true\" />\n <span className=\"truncate\">{display}</span>\n </span>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* KnowledgeCard */\n/* ------------------------------------------------------------------ */\n\nexport interface KnowledgeCardProps extends HTMLAttributes<HTMLElement> {\n /**\n * Comma-separated source paths (e.g. `\"notes/a.md, notes/b.md\"`).\n * Each path is handed to `resolve`; unresolved paths render as plain labels.\n */\n sources?: string;\n /**\n * Consumer-supplied resolver. `undefined` → all sources render as plain labels\n * (safe default — never throws, never reads files).\n */\n resolve?: KnowledgeSourceResolver;\n /** The fact body (rendered markdown children of the directive). */\n children?: ReactNode;\n}\n\nexport const KnowledgeCard = forwardRef<HTMLElement, KnowledgeCardProps>(function KnowledgeCard(\n { sources, resolve, children, className, ...props },\n ref,\n) {\n const { t } = useLocale();\n const sourcePaths = sources\n ? sources\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean)\n : [];\n\n return (\n <section\n ref={ref}\n aria-label={t(\"editor.knowledgeCard.label\")}\n className={cn(\"not-prose\", className)}\n {...props}\n >\n <Card className=\"border-s-4 border-s-info\">\n <CardContent className=\"pt-4\">\n <div className=\"mb-2 flex items-center gap-1.5\">\n <BookOpen className=\"size-3.5 shrink-0 text-info-text\" aria-hidden=\"true\" />\n <span className=\"text-meta font-medium text-info-text\">\n {t(\"editor.knowledgeCard.heading\")}\n </span>\n </div>\n <div className=\"text-body text-foreground\">{children}</div>\n </CardContent>\n\n {sourcePaths.length > 0 ? (\n <CardFooter className=\"flex-col items-start gap-1 border-t border-border pt-3\">\n <p className=\"text-meta font-medium text-muted-foreground\">\n {t(\"editor.knowledgeCard.sources\")}\n </p>\n <ul\n className=\"flex w-full flex-col gap-1\"\n aria-label={t(\"editor.knowledgeCard.sources\")}\n >\n {sourcePaths.map((path) => (\n <li key={path} className=\"min-w-0\">\n <SourceRow path={path} resolve={resolve} />\n </li>\n ))}\n </ul>\n </CardFooter>\n ) : null}\n </Card>\n </section>\n );\n});\n","/**\n * Directive renderer factories for the ai-objects trio.\n *\n * Each factory returns a `MarkdownDirectiveRenderer` for registration on\n * `MarkdownPreview` via the `extensions.directives` prop. The factories are\n * thin wrappers: they pass directive context into the standalone presentational\n * components — the library renders, the consumer computes.\n *\n * Usage:\n * import { aiObjectDirectives } from \"@elabs-ai/components-editor/markdown\";\n *\n * <MarkdownPreview\n * extensions={{ directives: aiObjectDirectives({ resolveKnowledge }) }}\n * />\n */\nimport { createElement } from \"react\";\n\nimport type { MarkdownDirectiveRenderer } from \"../lib/markdown/directives\";\nimport { DecisionCard } from \"./decision-card\";\nimport { EntityCard, EntityChip } from \"./entity\";\nimport { KnowledgeCard, type KnowledgeSourceResolver } from \"./knowledge-card\";\n\n/* ------------------------------------------------------------------ */\n/* Individual factories */\n/* ------------------------------------------------------------------ */\n\n/**\n * `decisionDirective()` — registers the `:::decision` container renderer.\n *\n * Authoring shape:\n * :::decision{status=accepted date=2026-06-15 alternatives=\"Redis, SQLite\"}\n * We chose PostgreSQL because it already runs in prod.\n * :::\n */\nexport function decisionDirective(): MarkdownDirectiveRenderer {\n return {\n name: \"decision\",\n kinds: [\"container\"],\n render({ attributes, children }) {\n return createElement(DecisionCard, {\n status: attributes.status,\n date: attributes.date,\n alternatives: attributes.alternatives,\n children,\n });\n },\n };\n}\n\n/**\n * `entityDirective()` — registers the `entity` directive for BOTH container\n * (block card) and inline (chip) syntaxes.\n *\n * Authoring shapes:\n * Container: :::entity{kind=org name=\"Acme Corp\"}\n * Acme Corp is the primary vendor.\n * :::\n * Inline: :entity[Acme Corp]{kind=org}\n */\nexport function entityDirective(): MarkdownDirectiveRenderer {\n return {\n name: \"entity\",\n kinds: [\"container\", \"inline\"],\n render({ kind, attributes, children, textValue }) {\n if (kind === \"inline\") {\n // `textValue` is the verbatim label text (markdown chars preserved);\n // fall back to rendered children when positions were unavailable.\n const label = textValue ?? (typeof children === \"string\" ? children : undefined);\n return createElement(EntityChip, { kind: attributes.kind, children: label ?? children });\n }\n // Container → EntityCard (block)\n return createElement(EntityCard, {\n kind: attributes.kind,\n name: attributes.name,\n children,\n });\n },\n };\n}\n\n/**\n * `knowledgeDirective({ resolve })` — registers the `:::knowledge` container\n * renderer. The `resolve` hook is consumer-supplied; omitting it causes all\n * sources to render as plain unlinked labels (safe default).\n *\n * Authoring shape:\n * :::knowledge{sources=\"notes/a.md, notes/b.md\"}\n * PostgreSQL was chosen because …\n * :::\n */\nexport function knowledgeDirective(options?: {\n resolve?: KnowledgeSourceResolver;\n}): MarkdownDirectiveRenderer {\n return {\n name: \"knowledge\",\n kinds: [\"container\"],\n render({ attributes, children }) {\n return createElement(KnowledgeCard, {\n sources: attributes.sources,\n resolve: options?.resolve,\n children,\n });\n },\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Convenience bundle */\n/* ------------------------------------------------------------------ */\n\nexport interface AiObjectDirectivesOptions {\n /** Consumer-supplied resolver for `:::knowledge` source paths. */\n resolveKnowledge?: KnowledgeSourceResolver;\n}\n\n/**\n * `aiObjectDirectives(options)` — returns all three directive renderers as an\n * array ready to pass to `extensions.directives`:\n * - `decisionDirective()`\n * - `entityDirective()`\n * - `knowledgeDirective({ resolve: options.resolveKnowledge })`\n *\n * @example\n * <MarkdownPreview\n * extensions={{ directives: aiObjectDirectives({ resolveKnowledge }) }}\n * />\n */\nexport function aiObjectDirectives(\n options: AiObjectDirectivesOptions = {},\n): MarkdownDirectiveRenderer[] {\n return [\n decisionDirective(),\n entityDirective(),\n knowledgeDirective({ resolve: options.resolveKnowledge }),\n ];\n}\n","\"use client\";\n\n/**\n * IterationTemplateDialog — author a `:::iterate` / `:::pivot` per-cell TEMPLATE\n * in a focused modal (the #223 template modal). Composes `@elabs-ai/components-ui` `Dialog`\n * with the existing `MarkdownWorkspace` (source / split / preview-edit), so the\n * template is edited with the same toolbar + live preview as any document.\n *\n * Controlled: drive `open` / `onOpenChange`; seed `template`; receive the edited\n * markdown via `onSave`. The library does not own where the template is stored —\n * the caller (a slash command, or the node-view `⋯` re-edit menu) wires it back.\n */\nimport {\n Button,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n useLocale,\n} from \"@elabs-ai/components-ui\";\nimport { useEffect, useState, type ReactNode } from \"react\";\n\nimport { MarkdownWorkspace, type MarkdownWorkspaceMode } from \"../markdown-workspace\";\nimport { IterationEditContext, type IterationEditRequest } from \"./edit-context\";\n\nexport interface IterationTemplateDialogProps {\n /** Whether the dialog is open. */\n open: boolean;\n /** Open-state change handler (Radix Dialog contract). */\n onOpenChange: (open: boolean) => void;\n /** The initial template markdown (the directive body). */\n template: string;\n /** Called with the edited template when the user saves. */\n onSave: (template: string) => void;\n /** Tunes the title + helper copy. Default `\"iterate\"`. */\n kind?: \"iterate\" | \"pivot\";\n /** Initial workspace mode. Default `\"split\"`. */\n mode?: MarkdownWorkspaceMode;\n}\n\nexport function IterationTemplateDialog({\n open,\n onOpenChange,\n template,\n onSave,\n kind = \"iterate\",\n mode = \"split\",\n}: IterationTemplateDialogProps) {\n const { t } = useLocale();\n const [draft, setDraft] = useState(template);\n\n // Re-seed the draft whenever the dialog (re)opens against a new template.\n useEffect(() => {\n if (open) setDraft(template);\n }, [open, template]);\n\n const unit = kind === \"pivot\" ? \"cell\" : \"row\";\n\n const save = () => {\n onSave(draft);\n onOpenChange(false);\n };\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent\n className=\"flex max-h-[85vh] w-[min(48rem,92vw)] max-w-none flex-col\"\n // Radix autofocuses the first tabbable element — the toolbar's Bold button —\n // and its Tooltip opens on focus, so the dialog opened with a stray tooltip.\n // Focus the dialog itself instead; Tab still reaches the toolbar first.\n onOpenAutoFocus={(event) => {\n event.preventDefault();\n (event.currentTarget as HTMLElement | null)?.focus();\n }}\n >\n <DialogHeader>\n <DialogTitle>\n {kind === \"pivot\"\n ? t(\"editor.templateDialog.editPivotTitle\")\n : t(\"editor.templateDialog.editIterationTitle\")}\n </DialogTitle>\n <DialogDescription>\n {t(\"editor.templateDialog.descriptionPrefix\", { unit })}\n <code>{\"{{token}}\"}</code>\n {t(\"editor.templateDialog.descriptionMiddle\")}\n <code>{\"{{item.name}}\"}</code>\n {t(\"editor.templateDialog.descriptionSuffix\", { unit })}\n </DialogDescription>\n </DialogHeader>\n <div className=\"min-h-0 flex-1\">\n <MarkdownWorkspace\n value={draft}\n onChange={setDraft}\n defaultMode={mode}\n className=\"h-full\"\n aria-label={t(\"editor.templateDialog.editorLabel\")}\n />\n </div>\n <DialogFooter>\n <Button variant=\"ghost\" onClick={() => onOpenChange(false)}>\n {t(\"editor.templateDialog.cancel\")}\n </Button>\n <Button onClick={save}>{t(\"editor.templateDialog.saveTemplate\")}</Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n\n/**\n * One-liner wiring for the node-view `⋯` re-edit: provides the\n * {@link IterationEditContext} handler AND renders the `IterationTemplateDialog`\n * it opens. Wrap your `MarkdownEditor` / `MarkdownWorkspace` in it to enable the\n * `⋯` \"Edit template…\" affordance on `:::iterate` / `:::pivot` node-views.\n */\nexport function IterationTemplateProvider({ children }: { children: ReactNode }) {\n const [request, setRequest] = useState<IterationEditRequest | null>(null);\n return (\n <IterationEditContext.Provider value={setRequest}>\n {children}\n <IterationTemplateDialog\n open={request != null}\n onOpenChange={(next) => {\n if (!next) setRequest(null);\n }}\n template={request?.template ?? \"\"}\n kind={request?.kind ?? \"iterate\"}\n onSave={(template) => request?.onSave(template)}\n />\n </IterationEditContext.Provider>\n );\n}\n","\"use client\";\n\n/**\n * IterationBuilderDialog (A5) — GUIDED `:::iterate` / `:::pivot` authoring.\n *\n * Where `IterationTemplateDialog` edits only the per-cell template, the builder\n * also collects the DATA — the value list (iterate) or the two value lists\n * (pivot), the bind name, and the layout — and shows a LIVE preview of the\n * populated block as you type. On save it writes a fully-bound directive\n * (`serializeIterationDirective`) whose value lists live in its attributes, so the\n * block renders populated via the built-in `evaluateEmbedded` and the `⋯` re-edit\n * can reopen it losslessly (`parseIterationDirective` / `builderValueFromParts`).\n *\n * Controlled (`open` / `onOpenChange`); seed via `value` (re-edit) or `kind` +\n * `initialValues` (fresh insert, e.g. a selection split to one value per line).\n */\nimport {\n Button,\n Dialog,\n DialogBody,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n Input,\n Label,\n TagInput,\n ToggleGroup,\n ToggleGroupItem,\n useLocale,\n} from \"@elabs-ai/components-ui\";\nimport { useEffect, useId, useMemo, useState, type ReactNode } from \"react\";\n\nimport { type EvaluateCalc } from \"../calc-block\";\nimport { MarkdownPreview } from \"../markdown-preview\";\nimport { MarkdownWorkspace } from \"../markdown-workspace\";\nimport { IterationEditContext, type IterationEditRequest } from \"./edit-context\";\nimport { type InterpolateTemplate, type IterationLayout } from \"./iteration\";\nimport {\n builderValueFromParts,\n directivePartsFromValue,\n emptyBuilderValue,\n evaluateEmbedded,\n ITERATION_LAYOUTS,\n parseIterationDirective,\n serializeIterationDirective,\n type IterationBuilderValue,\n} from \"./iteration-builder\";\n\nexport interface IterationBuilderDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n /** Which block to author. Default `\"iterate\"`. Ignored when `value` is set. */\n kind?: \"iterate\" | \"pivot\";\n /** Seed the whole builder (the `⋯` re-edit path). */\n value?: IterationBuilderValue;\n /** Seed the value list of a fresh block (e.g. a selection split to lines). */\n initialValues?: string[];\n /** Receives the fully-bound directive markdown when the user saves. */\n onSave: (directiveMarkdown: string) => void;\n /**\n * Resolve a ```calc fence to a `CalcSheet` so calc cells COMPUTE in the live\n * preview (the same hook `MarkdownPreview` takes — the library renders, the app\n * computes). Without it a calc cell still renders as a code block; with it, the\n * preview matches production. Pass your app's calc engine.\n */\n evaluate?: EvaluateCalc;\n /** Fill a cell template with its context. Defaults to `{{path}}` substitution. */\n interpolate?: InterpolateTemplate;\n}\n\nexport function IterationBuilderDialog({\n open,\n onOpenChange,\n kind: kindProp = \"iterate\",\n value,\n initialValues,\n onSave,\n evaluate,\n interpolate,\n}: IterationBuilderDialogProps) {\n const { t } = useLocale();\n const kind = value?.kind ?? kindProp;\n const isPivot = kind === \"pivot\";\n const ids = useId();\n\n // Working draft. Value lists are arrays (chip entry via TagInput); the per-cell\n // template stays raw text.\n const [asName, setAsName] = useState(\"item\");\n const [layout, setLayout] = useState<IterationLayout>(ITERATION_LAYOUTS[kind][0] ?? \"stacked\");\n const [values, setValues] = useState<string[]>([]);\n const [cols, setCols] = useState<string[]>([]);\n const [template, setTemplate] = useState(\"\");\n\n // (Re)seed whenever the dialog opens against a new value / kind.\n useEffect(() => {\n if (!open) return;\n const seed = value ?? {\n ...emptyBuilderValue(kind),\n values: initialValues ?? [],\n };\n setAsName(seed.as);\n setLayout(seed.layout);\n setValues(seed.values);\n setCols(seed.cols ?? []);\n setTemplate(seed.template);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open]);\n\n const draft: IterationBuilderValue = useMemo(\n () => ({\n kind,\n as: asName.trim() || \"item\",\n layout,\n values,\n cols: isPivot ? cols : undefined,\n template,\n }),\n [kind, asName, layout, values, cols, template, isPivot],\n );\n\n // Live preview — render the SERIALIZED directive through MarkdownPreview, the\n // exact path the saved block renders through. That resolves the iteration via\n // the built-in `evaluateEmbedded` AND each cell's objects (a ```calc fence,\n // nested directives, formatting) — in stacked, grid and matrix alike — instead\n // of dumping the raw cell text.\n const previewMarkdown = useMemo(() => serializeIterationDirective(draft), [draft]);\n\n const save = () => {\n onSave(serializeIterationDirective(draft));\n onOpenChange(false);\n };\n\n const noun = isPivot\n ? t(\"editor.iterationBuilder.pivotNoun\")\n : t(\"editor.iterationBuilder.iterationNoun\");\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"flex max-h-[88vh] w-[min(56rem,94vw)] max-w-none flex-col\">\n <DialogHeader>\n <DialogTitle>\n {t(\n value ? \"editor.iterationBuilder.editTitle\" : \"editor.iterationBuilder.insertTitle\",\n {\n noun,\n },\n )}\n </DialogTitle>\n <DialogDescription>\n {isPivot\n ? t(\"editor.iterationBuilder.pivotDescription\")\n : t(\"editor.iterationBuilder.iterationDescription\")}\n </DialogDescription>\n </DialogHeader>\n\n <DialogBody className=\"grid gap-4 md:grid-cols-2\">\n {/* Left column — the DATA the block iterates over. */}\n <div className=\"flex min-w-0 flex-col gap-4\">\n {!isPivot ? (\n <div className=\"flex flex-col gap-1.5\">\n <Label htmlFor={`${ids}-as`}>{t(\"editor.iterationBuilder.bindName\")}</Label>\n <Input\n id={`${ids}-as`}\n value={asName}\n spellCheck={false}\n autoComplete=\"off\"\n placeholder={t(\"editor.iterationBuilder.bindNamePlaceholder\")}\n onChange={(e) => setAsName(e.target.value)}\n />\n <p className=\"text-meta text-muted-foreground\">\n {t(\"editor.iterationBuilder.bindNameHintPrefix\")}\n <code>{`{{${asName.trim() || \"item\"}.name}}`}</code>\n {t(\"editor.iterationBuilder.bindNameHintSuffix\")}\n </p>\n </div>\n ) : null}\n\n <div className=\"flex flex-col gap-1.5\">\n <Label htmlFor={`${ids}-values`}>\n {isPivot\n ? t(\"editor.iterationBuilder.rowValues\")\n : t(\"editor.iterationBuilder.values\")}\n </Label>\n <TagInput\n id={`${ids}-values`}\n value={values}\n onValueChange={setValues}\n delimiter={[\",\", \"\\n\"]}\n placeholder={t(\"editor.iterationBuilder.valuePlaceholder\")}\n />\n </div>\n\n {isPivot ? (\n <div className=\"flex flex-col gap-1.5\">\n <Label htmlFor={`${ids}-cols`}>{t(\"editor.iterationBuilder.columnValues\")}</Label>\n <TagInput\n id={`${ids}-cols`}\n value={cols}\n onValueChange={setCols}\n delimiter={[\",\", \"\\n\"]}\n placeholder={t(\"editor.iterationBuilder.valuePlaceholder\")}\n />\n </div>\n ) : null}\n\n <div className=\"flex flex-col gap-1.5\">\n <Label id={`${ids}-layout`}>{t(\"editor.iterationBuilder.layout\")}</Label>\n <ToggleGroup\n type=\"single\"\n variant=\"segmented\"\n value={layout}\n onValueChange={(next) => {\n // Single-select: ignore the empty value Radix emits when the active\n // item is re-pressed, so a layout is always selected.\n if (next) setLayout(next as IterationLayout);\n }}\n aria-labelledby={`${ids}-layout`}\n className=\"w-fit\"\n >\n {ITERATION_LAYOUTS[kind].map((l) => (\n <ToggleGroupItem key={l} value={l} className=\"capitalize\">\n {l}\n </ToggleGroupItem>\n ))}\n </ToggleGroup>\n </div>\n </div>\n\n {/* Right column — the per-cell TEMPLATE + the live populated preview. */}\n <div className=\"flex min-h-0 min-w-0 flex-col gap-4\">\n <div className=\"flex min-h-0 flex-col gap-1.5\">\n <Label>\n {isPivot\n ? t(\"editor.iterationBuilder.perCellTemplate\")\n : t(\"editor.iterationBuilder.perRowTemplate\")}\n </Label>\n <div className=\"h-44 min-h-0 overflow-hidden rounded-md border border-border\">\n <MarkdownWorkspace\n value={template}\n onChange={setTemplate}\n defaultMode=\"source\"\n className=\"h-full\"\n aria-label={t(\"editor.iterationBuilder.perCellTemplate\")}\n />\n </div>\n </div>\n\n <div className=\"flex min-h-0 flex-col gap-1.5\">\n <Label>{t(\"editor.iterationBuilder.livePreview\")}</Label>\n <div\n role=\"region\"\n aria-label={t(\"editor.iterationBuilder.livePreview\")}\n className=\"min-h-0 flex-1 overflow-auto rounded-md border border-border bg-card p-3\"\n >\n <MarkdownPreview\n evaluateIteration={evaluateEmbedded}\n evaluate={evaluate}\n interpolate={interpolate}\n >\n {previewMarkdown}\n </MarkdownPreview>\n </div>\n </div>\n </div>\n </DialogBody>\n\n <DialogFooter>\n <Button variant=\"ghost\" onClick={() => onOpenChange(false)}>\n {t(\"editor.iterationBuilder.cancel\")}\n </Button>\n <Button onClick={save}>\n {value ? t(\"editor.iterationBuilder.save\") : t(\"editor.iterationBuilder.insert\")}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n\n/**\n * One-liner wiring for the node-view `⋯` re-edit using the GUIDED builder (A5).\n * Drop it above a `MarkdownEditor` / `MarkdownWorkspace` to make the `⋯` on a\n * `:::iterate` / `:::pivot` reopen the full builder seeded with the block's DATA\n * (value lists + bind name + layout) and template, writing both back losslessly.\n *\n * Prefer this over {@link IterationTemplateProvider} when the consumer authors\n * blocks with embedded value lists (the builder flow); the template-only provider\n * remains for the lighter \"edit just the template\" affordance.\n */\nexport function IterationBuilderProvider({\n children,\n evaluate,\n interpolate,\n}: {\n children: ReactNode;\n /** Forwarded to the builder's live preview so calc cells COMPUTE on re-edit. */\n evaluate?: EvaluateCalc;\n /** Forwarded to the builder's live preview cell interpolation. */\n interpolate?: InterpolateTemplate;\n}) {\n const [request, setRequest] = useState<IterationEditRequest | null>(null);\n\n const seed = request\n ? builderValueFromParts(request.kind, request.attributes ?? {}, request.template)\n : undefined;\n\n return (\n <IterationEditContext.Provider value={setRequest}>\n {children}\n <IterationBuilderDialog\n open={request != null}\n onOpenChange={(next) => {\n if (!next) setRequest(null);\n }}\n kind={request?.kind ?? \"iterate\"}\n value={seed}\n evaluate={evaluate}\n interpolate={interpolate}\n onSave={(directiveMarkdown) => {\n const parsed = parseIterationDirective(directiveMarkdown);\n if (!parsed) return;\n const { attributes, template } = directivePartsFromValue(parsed);\n // Prefer the data-aware writer (rewrites attributes + body); fall back to\n // the template-only writer for older node-views.\n if (request?.onSaveData) request.onSaveData({ attributes, template });\n else request?.onSave(template);\n }}\n />\n </IterationEditContext.Provider>\n );\n}\n"],"mappings":"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","names":["editor","monaco","editor","editor","filtered","activeCommand","Tooltip","TooltipContent","TooltipProvider","TooltipTrigger","useLocale","cn","forwardRef","useEffect","useMemo","useRef","useState","monaco","REGISTRY","editor","i","j","monaco","Separator","cn","createContext","forwardRef","useContext","useMemo","visit","cn","jsx","jsxs","cn","CalcBlock","cn","TriangleAlert","forwardRef","useMemo","jsx","jsxs","CalcInline","Button","useLocale","cn","forwardRef","useEffect","useRef","useState","useLocale","cn","useEffect","useMemo","useRef","useState","jsx","jsxs","jsx","jsxs","forwardRef","MermaidDiagram","useLocale","useRef","useState","useEffect","cn","Button","cn","useEffect","useRef","useState","jsx","jsxs","cn","useState","useRef","useEffect","cn","useLocale","forwardRef","useId","visit","jsx","jsxs","Bibliography","Separator","cn","forwardRef","useId","visit","jsx","jsxs","FootnoteList","useLocale","cn","useMemo","visit","jsx","cn","createContext","forwardRef","useContext","jsx","jsxs","TableOfContents","createContext","useContext","jsx","createContext","useContext","Fragment","jsx","jsxs","createContext","visit","useContext","cn","useMemo","Separator","forwardRef","MarkdownPreview","children","Button","Separator","useLocale","cn","Minus","forwardRef","Fragment","jsx","jsxs","forwardRef","MarkdownToolbar","editor","useLocale","Button","cn","Separator","Minus","Fragment","Fragment","jsx","jsxs","forwardRef","MarkdownWorkspace","useLocale","useState","monaco","useRef","useEffect","useMemo","TooltipProvider","Tooltip","TooltipTrigger","TooltipContent","editor","cn","remarkDirective","ResizableHandle","ResizablePanel","ResizablePanelGroup","cn","forwardRef","useEffect","useState","jsx","jsxs","forwardRef","MermaidWorkspace","useState","useEffect","cn","ResizablePanelGroup","ResizablePanel","ResizableHandle","Card","CardContent","CardHeader","Separator","useLocale","cn","forwardRef","Fragment","jsx","jsxs","DecisionCard","Card","CardContent","CardHeader","CardTitle","cn","cva","forwardRef","jsx","jsxs","EntityChip","EntityCard","Card","CardContent","useLocale","cn","forwardRef","jsx","jsxs","KnowledgeCard","Button","Dialog","DialogContent","DialogTitle","useLocale","useEffect","useState","jsx","jsxs","useLocale","useState","useEffect","Dialog","DialogContent","DialogTitle","Button","Button","Dialog","DialogContent","DialogDescription","DialogFooter","DialogHeader","DialogTitle","Input","ToggleGroup","ToggleGroupItem","useLocale","useEffect","useId","useMemo","useState","jsx","jsxs","useLocale","useId","useState","useEffect","useMemo","Dialog","DialogContent","DialogHeader","DialogTitle","DialogDescription","Input","ToggleGroup","ToggleGroupItem","DialogFooter","Button"]}