@agent-native/core 0.43.0 → 0.44.1

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.
Files changed (124) hide show
  1. package/dist/chat-threads/store.d.ts.map +1 -1
  2. package/dist/chat-threads/store.js +71 -10
  3. package/dist/chat-threads/store.js.map +1 -1
  4. package/dist/cli/pr-visual-recap-workflow.d.ts +1 -1
  5. package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -1
  6. package/dist/cli/pr-visual-recap-workflow.js +1 -1
  7. package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
  8. package/dist/cli/recap.d.ts +23 -0
  9. package/dist/cli/recap.d.ts.map +1 -1
  10. package/dist/cli/recap.js +177 -13
  11. package/dist/cli/recap.js.map +1 -1
  12. package/dist/cli/skills.d.ts +3 -3
  13. package/dist/cli/skills.d.ts.map +1 -1
  14. package/dist/cli/skills.js +67 -20
  15. package/dist/cli/skills.js.map +1 -1
  16. package/dist/client/AssistantChat.d.ts.map +1 -1
  17. package/dist/client/AssistantChat.js +76 -18
  18. package/dist/client/AssistantChat.js.map +1 -1
  19. package/dist/client/blocks/index.d.ts +0 -2
  20. package/dist/client/blocks/index.d.ts.map +1 -1
  21. package/dist/client/blocks/index.js +0 -2
  22. package/dist/client/blocks/index.js.map +1 -1
  23. package/dist/client/blocks/library/AnnotatedCodeBlock.d.ts.map +1 -1
  24. package/dist/client/blocks/library/AnnotatedCodeBlock.js +22 -9
  25. package/dist/client/blocks/library/AnnotatedCodeBlock.js.map +1 -1
  26. package/dist/client/blocks/library/ApiEndpointBlock.d.ts.map +1 -1
  27. package/dist/client/blocks/library/ApiEndpointBlock.js +113 -13
  28. package/dist/client/blocks/library/ApiEndpointBlock.js.map +1 -1
  29. package/dist/client/blocks/library/DiffBlock.d.ts.map +1 -1
  30. package/dist/client/blocks/library/DiffBlock.js +63 -35
  31. package/dist/client/blocks/library/DiffBlock.js.map +1 -1
  32. package/dist/client/blocks/library/FileTreeBlock.d.ts.map +1 -1
  33. package/dist/client/blocks/library/FileTreeBlock.js +4 -0
  34. package/dist/client/blocks/library/FileTreeBlock.js.map +1 -1
  35. package/dist/client/blocks/library/JsonExplorerBlock.d.ts.map +1 -1
  36. package/dist/client/blocks/library/JsonExplorerBlock.js +1 -1
  37. package/dist/client/blocks/library/JsonExplorerBlock.js.map +1 -1
  38. package/dist/client/blocks/library/MermaidBlock.d.ts.map +1 -1
  39. package/dist/client/blocks/library/MermaidBlock.js +22 -3
  40. package/dist/client/blocks/library/MermaidBlock.js.map +1 -1
  41. package/dist/client/blocks/library/annotation-rail.d.ts +85 -19
  42. package/dist/client/blocks/library/annotation-rail.d.ts.map +1 -1
  43. package/dist/client/blocks/library/annotation-rail.js +149 -27
  44. package/dist/client/blocks/library/annotation-rail.js.map +1 -1
  45. package/dist/client/blocks/library/code-tabs.js +1 -1
  46. package/dist/client/blocks/library/code-tabs.js.map +1 -1
  47. package/dist/client/blocks/library/diagram.d.ts +17 -0
  48. package/dist/client/blocks/library/diagram.d.ts.map +1 -1
  49. package/dist/client/blocks/library/diagram.js +47 -2
  50. package/dist/client/blocks/library/diagram.js.map +1 -1
  51. package/dist/client/blocks/library/server-specs.d.ts.map +1 -1
  52. package/dist/client/blocks/library/server-specs.js +0 -10
  53. package/dist/client/blocks/library/server-specs.js.map +1 -1
  54. package/dist/client/blocks/library/specs.d.ts.map +1 -1
  55. package/dist/client/blocks/library/specs.js +0 -2
  56. package/dist/client/blocks/library/specs.js.map +1 -1
  57. package/dist/client/blocks/library/wireframe.config.d.ts.map +1 -1
  58. package/dist/client/blocks/library/wireframe.config.js +19 -2
  59. package/dist/client/blocks/library/wireframe.config.js.map +1 -1
  60. package/dist/client/blocks/mdx.d.ts.map +1 -1
  61. package/dist/client/blocks/mdx.js +11 -0
  62. package/dist/client/blocks/mdx.js.map +1 -1
  63. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  64. package/dist/client/composer/TiptapComposer.js +13 -8
  65. package/dist/client/composer/TiptapComposer.js.map +1 -1
  66. package/dist/client/composer/pasted-text.d.ts +25 -0
  67. package/dist/client/composer/pasted-text.d.ts.map +1 -1
  68. package/dist/client/composer/pasted-text.js +86 -4
  69. package/dist/client/composer/pasted-text.js.map +1 -1
  70. package/dist/client/rich-markdown-editor/DragHandle.d.ts.map +1 -1
  71. package/dist/client/rich-markdown-editor/DragHandle.js +35 -72
  72. package/dist/client/rich-markdown-editor/DragHandle.js.map +1 -1
  73. package/dist/client/rich-markdown-editor/RegistryBlockNode.d.ts.map +1 -1
  74. package/dist/client/rich-markdown-editor/RegistryBlockNode.js +1 -1
  75. package/dist/client/rich-markdown-editor/RegistryBlockNode.js.map +1 -1
  76. package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts +9 -1
  77. package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts.map +1 -1
  78. package/dist/client/rich-markdown-editor/SharedRichEditor.js +3 -1
  79. package/dist/client/rich-markdown-editor/SharedRichEditor.js.map +1 -1
  80. package/dist/client/rich-markdown-editor/extensions.d.ts +13 -1
  81. package/dist/client/rich-markdown-editor/extensions.d.ts.map +1 -1
  82. package/dist/client/rich-markdown-editor/extensions.js +4 -2
  83. package/dist/client/rich-markdown-editor/extensions.js.map +1 -1
  84. package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts.map +1 -1
  85. package/dist/client/rich-markdown-editor/useCollabReconcile.js +11 -1
  86. package/dist/client/rich-markdown-editor/useCollabReconcile.js.map +1 -1
  87. package/dist/db/migrations.d.ts +10 -0
  88. package/dist/db/migrations.d.ts.map +1 -1
  89. package/dist/db/migrations.js +32 -0
  90. package/dist/db/migrations.js.map +1 -1
  91. package/dist/server/og-fonts-data.d.ts +3 -0
  92. package/dist/server/og-fonts-data.d.ts.map +1 -0
  93. package/dist/server/og-fonts-data.js +9 -0
  94. package/dist/server/og-fonts-data.js.map +1 -0
  95. package/dist/server/og-fonts.d.ts +10 -0
  96. package/dist/server/og-fonts.d.ts.map +1 -0
  97. package/dist/server/og-fonts.js +58 -0
  98. package/dist/server/og-fonts.js.map +1 -0
  99. package/dist/server/poll.d.ts.map +1 -1
  100. package/dist/server/poll.js +30 -14
  101. package/dist/server/poll.js.map +1 -1
  102. package/dist/server/social-og-image.d.ts.map +1 -1
  103. package/dist/server/social-og-image.js +16 -5
  104. package/dist/server/social-og-image.js.map +1 -1
  105. package/dist/styles/blocks.css +121 -2
  106. package/dist/templates/default/.agents/skills/storing-data/SKILL.md +2 -0
  107. package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +141 -0
  108. package/dist/templates/workspace-core/.agents/skills/storing-data/SKILL.md +2 -0
  109. package/dist/usage/store.d.ts +12 -0
  110. package/dist/usage/store.d.ts.map +1 -1
  111. package/dist/usage/store.js +35 -5
  112. package/dist/usage/store.js.map +1 -1
  113. package/package.json +1 -1
  114. package/src/templates/default/.agents/skills/storing-data/SKILL.md +2 -0
  115. package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +141 -0
  116. package/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +2 -0
  117. package/dist/client/blocks/library/decision.config.d.ts +0 -37
  118. package/dist/client/blocks/library/decision.config.d.ts.map +0 -1
  119. package/dist/client/blocks/library/decision.config.js +0 -32
  120. package/dist/client/blocks/library/decision.config.js.map +0 -1
  121. package/dist/client/blocks/library/decision.d.ts +0 -19
  122. package/dist/client/blocks/library/decision.d.ts.map +0 -1
  123. package/dist/client/blocks/library/decision.js +0 -119
  124. package/dist/client/blocks/library/decision.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"code-tabs.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/code-tabs.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type ReactNode,\n type UIEvent,\n} from \"react\";\nimport { IconCode, IconPencil, IconPlus, IconTrash } from \"@tabler/icons-react\";\nimport { common, createLowlight } from \"lowlight\";\nimport { cn } from \"../../utils.js\";\nimport { defineBlock } from \"../types.js\";\nimport type { BlockReadProps, BlockEditProps } from \"../types.js\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../../components/ui/popover.js\";\nimport { CodeSurface, DEFAULT_CODE_MAX_LINES } from \"./HighlightedCode.js\";\nimport {\n codeTabsSchema,\n codeTabsMdx,\n type CodeTabsData,\n type CodeTabsTab,\n} from \"./code-tabs.config.js\";\n\n/**\n * Standard `code-tabs` block (STANDARD core library): a vertical file tab rail\n * with Shiki-highlighted code panes. Moved verbatim from the plan\n * `CodeTabsBlock` (`DocumentArea.tsx`) so its rendered output is unchanged, then\n * generalized to the registry `Read`/`Edit` contract. Shareable by any app that\n * registers the core block library.\n *\n * `Edit` is hybrid: each tab's `code` field renders as a code-style monospace\n * text area, while tab metadata (label/language/caption/add/remove) stays in a\n * settings popover so the document surface only exposes authored content.\n */\n\n/* ── Syntax highlighting helpers ──────────────────────────────────────────── */\n\nconst lowlight = createLowlight(common);\n\ntype LowlightNode = {\n type: string;\n value?: string;\n properties?: {\n className?: string[] | string;\n };\n children?: LowlightNode[];\n};\n\nconst LANGUAGE_ALIASES: Record<string, string> = {\n cjs: \"javascript\",\n cts: \"typescript\",\n htm: \"html\",\n js: \"javascript\",\n jsonc: \"json\",\n jsx: \"jsx\",\n md: \"markdown\",\n mdx: \"markdown\",\n mjs: \"javascript\",\n mts: \"typescript\",\n py: \"python\",\n rb: \"ruby\",\n rs: \"rust\",\n sh: \"bash\",\n shell: \"bash\",\n ts: \"typescript\",\n tsx: \"tsx\",\n yml: \"yaml\",\n zsh: \"bash\",\n};\n\nconst TOKEN_CLASS_NAMES: Record<string, string> = {\n \"hljs-addition\": \"text-emerald-700 dark:text-emerald-300\",\n \"hljs-attr\": \"text-sky-700 dark:text-sky-300\",\n \"hljs-attribute\": \"text-sky-700 dark:text-sky-300\",\n \"hljs-built_in\": \"text-amber-700 dark:text-amber-300\",\n \"hljs-bullet\": \"text-primary\",\n \"hljs-comment\": \"text-muted-foreground italic\",\n \"hljs-deletion\": \"text-destructive\",\n \"hljs-doctag\": \"text-destructive\",\n \"hljs-emphasis\": \"italic\",\n \"hljs-formula\": \"text-destructive\",\n \"hljs-keyword\": \"text-rose-700 dark:text-rose-300\",\n \"hljs-link\": \"text-primary underline-offset-2\",\n \"hljs-literal\": \"text-violet-700 dark:text-violet-300\",\n \"hljs-meta\": \"text-primary\",\n \"hljs-meta-string\": \"text-emerald-700 dark:text-emerald-300\",\n \"hljs-name\": \"text-emerald-700 dark:text-emerald-300\",\n \"hljs-number\": \"text-sky-700 dark:text-sky-300\",\n \"hljs-params\": \"text-sky-700 dark:text-sky-300\",\n \"hljs-property\": \"text-sky-700 dark:text-sky-300\",\n \"hljs-quote\": \"text-muted-foreground italic\",\n \"hljs-regexp\": \"text-emerald-700 dark:text-emerald-300\",\n \"hljs-section\": \"text-violet-700 dark:text-violet-300\",\n \"hljs-selector-attr\": \"text-primary\",\n \"hljs-selector-class\": \"text-emerald-700 dark:text-emerald-300\",\n \"hljs-selector-id\": \"text-emerald-700 dark:text-emerald-300\",\n \"hljs-selector-pseudo\": \"text-primary\",\n \"hljs-selector-tag\": \"text-emerald-700 dark:text-emerald-300\",\n \"hljs-string\": \"text-emerald-700 dark:text-emerald-300\",\n \"hljs-strong\": \"font-semibold\",\n \"hljs-subst\": \"text-destructive\",\n \"hljs-symbol\": \"text-primary\",\n \"hljs-tag\": \"text-emerald-700 dark:text-emerald-300\",\n \"hljs-template-variable\": \"text-amber-700 dark:text-amber-300\",\n \"hljs-title\": \"text-violet-700 dark:text-violet-300\",\n \"hljs-type\": \"text-amber-700 dark:text-amber-300\",\n \"hljs-variable\": \"text-amber-700 dark:text-amber-300\",\n language_: \"text-amber-700 dark:text-amber-300\",\n};\n\nfunction normalizeCodeLanguage(value?: string | null): string | null {\n const raw = value\n ?.trim()\n .toLowerCase()\n .replace(/^language-/, \"\");\n if (!raw) return null;\n const normalized = LANGUAGE_ALIASES[raw] ?? raw;\n return lowlight.registered(normalized) ? normalized : null;\n}\n\nfunction inferLanguageFromFilename(filename?: string | null): string | null {\n const basename = filename?.split(\"/\").pop()?.toLowerCase();\n if (!basename) return null;\n if (basename === \"dockerfile\") return normalizeCodeLanguage(\"bash\");\n const extension = basename.includes(\".\")\n ? basename.split(\".\").pop()\n : undefined;\n return normalizeCodeLanguage(extension);\n}\n\nfunction codeTabLanguage(tab?: CodeTabsTab): string | undefined {\n return (\n normalizeCodeLanguage(tab?.language) ??\n inferLanguageFromFilename(tab?.label) ??\n undefined\n );\n}\n\nfunction tokenClassName(value: string[] | string | undefined): string {\n const classes = Array.isArray(value)\n ? value\n : typeof value === \"string\"\n ? value.split(/\\s+/)\n : [];\n return classes\n .map((className) => TOKEN_CLASS_NAMES[className] ?? \"\")\n .filter(Boolean)\n .join(\" \");\n}\n\nfunction hastToReact(children: LowlightNode[], keyPrefix: string): ReactNode[] {\n return children.map((node, index) => {\n if (node.type === \"text\") return node.value ?? \"\";\n if (node.type === \"element\") {\n const key = `${keyPrefix}${index}`;\n const renderedChildren = node.children?.length\n ? hastToReact(node.children, `${key}-`)\n : null;\n const className = tokenClassName(node.properties?.className);\n return (\n <span key={key} className={className || undefined}>\n {renderedChildren}\n </span>\n );\n }\n return null;\n });\n}\n\nfunction highlightCode(code: string, language?: string): ReactNode {\n const normalized = normalizeCodeLanguage(language);\n if (!normalized || normalized === \"plaintext\" || normalized === \"text\") {\n return code;\n }\n try {\n const tree = lowlight.highlight(normalized, code) as LowlightNode;\n return hastToReact(tree.children ?? [], `${normalized}-`);\n } catch {\n return code;\n }\n}\n\n/* ── Read (vertical tab rail + Shiki) ──────────────────────────────────────── */\n\nfunction CodeTabsRead({ data, blockId, title }: BlockReadProps<CodeTabsData>) {\n const [activeId, setActiveId] = useState(data.tabs[0]?.id ?? \"\");\n const active = data.tabs.find((tab) => tab.id === activeId) ?? data.tabs[0];\n return (\n <section className=\"plan-block\" data-block-id={blockId}>\n {title && <div className=\"plan-block-label\">{title}</div>}\n <div className=\"grid overflow-hidden border-y border-plan-line md:grid-cols-[300px_minmax(0,1fr)]\">\n <div className=\"border-plan-line md:border-r\">\n {data.tabs.map((tab) => (\n <button\n key={tab.id}\n type=\"button\"\n data-plan-interactive\n className={cn(\n \"flex w-full items-start gap-3 border-b border-plan-line px-4 py-4 text-left\",\n tab.id === active?.id\n ? \"bg-primary/10 text-plan-text dark:bg-primary/20\"\n : \"text-plan-muted hover:bg-accent/30\",\n )}\n onClick={() => setActiveId(tab.id)}\n >\n <IconCode className=\"mt-0.5 size-4 shrink-0\" />\n <span className=\"min-w-0\">\n <span className=\"block truncate font-mono text-sm font-semibold\">\n {tab.label}\n </span>\n {tab.caption && (\n <span className=\"mt-1 block text-xs leading-5\">\n {tab.caption}\n </span>\n )}\n </span>\n </button>\n ))}\n </div>\n <div className=\"min-w-0 p-5\">\n {active && (\n <>\n <h3 className=\"text-2xl font-semibold tracking-tight\">\n {active.label}\n </h3>\n {active.caption && (\n <p className=\"mt-2 text-plan-muted\">{active.caption}</p>\n )}\n <CodeSurface\n code={active.code}\n language={codeTabLanguage(active)}\n maxLines={active.maxLines}\n />\n </>\n )}\n </div>\n </div>\n </section>\n );\n}\n\n/* ── Edit (code text areas per tab) ────────────────────────────────────────── */\n\nconst inputClass =\n \"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\";\n\n/** Language options for the per-tab picker; \"\" is the Auto-detect sentinel. */\nconst CODE_TAB_LANGUAGES: ReadonlyArray<{ value: string; label: string }> = [\n { value: \"\", label: \"Auto\" },\n { value: \"typescript\", label: \"TypeScript\" },\n { value: \"javascript\", label: \"JavaScript\" },\n { value: \"tsx\", label: \"TSX\" },\n { value: \"jsx\", label: \"JSX\" },\n { value: \"json\", label: \"JSON\" },\n { value: \"html\", label: \"HTML\" },\n { value: \"css\", label: \"CSS\" },\n { value: \"bash\", label: \"Bash\" },\n { value: \"python\", label: \"Python\" },\n { value: \"sql\", label: \"SQL\" },\n { value: \"yaml\", label: \"YAML\" },\n { value: \"markdown\", label: \"Markdown\" },\n { value: \"graphql\", label: \"GraphQL\" },\n { value: \"go\", label: \"Go\" },\n { value: \"rust\", label: \"Rust\" },\n { value: \"diff\", label: \"Diff\" },\n];\n\n/** Mint a reasonably-unique code-tab id without pulling a dep into core. */\nfunction newCodeTabId(): string {\n return `code-tab-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction HighlightedCodeTextarea({\n value,\n language,\n label,\n editable,\n onChange,\n}: {\n value: string;\n language?: string;\n label?: string;\n editable: boolean;\n onChange: (event: ChangeEvent<HTMLTextAreaElement>) => void;\n}) {\n const highlightLayerRef = useRef<HTMLPreElement>(null);\n const resolvedLanguage =\n normalizeCodeLanguage(language) ?? inferLanguageFromFilename(label);\n const highlighted = useMemo(\n () => highlightCode(value, resolvedLanguage ?? undefined),\n [resolvedLanguage, value],\n );\n\n const syncScroll = (event: UIEvent<HTMLTextAreaElement>) => {\n const layer = highlightLayerRef.current;\n if (!layer) return;\n layer.scrollTop = event.currentTarget.scrollTop;\n layer.scrollLeft = event.currentTarget.scrollLeft;\n };\n\n return (\n <div\n className={cn(\n \"relative min-h-[140px] overflow-hidden rounded-md border border-input bg-background text-foreground focus-within:ring-1 focus-within:ring-ring\",\n !editable && \"cursor-not-allowed opacity-50\",\n )}\n data-code-tabs-highlighted-editor\n >\n <pre\n ref={highlightLayerRef}\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute inset-0 m-0 overflow-hidden whitespace-pre px-3 py-2 font-mono text-xs leading-5\"\n data-code-tabs-highlight-layer\n >\n <code>\n {highlighted}\n {value.endsWith(\"\\n\") ? \" \" : null}\n </code>\n </pre>\n <textarea\n data-plan-interactive\n spellCheck={false}\n wrap=\"off\"\n className={cn(\n \"relative z-10 block min-h-[140px] w-full resize-y overflow-auto rounded-md border-0 bg-transparent px-3 py-2 font-mono text-xs leading-5 caret-foreground outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed\",\n value ? \"text-transparent\" : \"text-muted-foreground\",\n )}\n value={value}\n disabled={!editable}\n onChange={onChange}\n onScroll={syncScroll}\n />\n </div>\n );\n}\n\n/**\n * Editor: a file-tab strip (one tab active at a time) with the active tab's code\n * editable inline. Tab metadata is edited from the settings popover, mirroring\n * the standard `tabs` block and keeping schema-ish controls out of the document.\n */\nfunction CodeTabsEdit({\n data,\n onChange,\n editable,\n}: BlockEditProps<CodeTabsData>) {\n const [activeId, setActiveId] = useState(data.tabs[0]?.id ?? \"\");\n const active = data.tabs.find((tab) => tab.id === activeId) ?? data.tabs[0];\n\n const commit = (tabs: CodeTabsTab[]) => onChange({ tabs });\n\n const updateTab = (id: string, patch: Partial<CodeTabsTab>) =>\n commit(\n data.tabs.map((tab) => (tab.id === id ? { ...tab, ...patch } : tab)),\n );\n\n const removeTab = (id: string) => {\n const next = data.tabs.filter((tab) => tab.id !== id);\n if (next.length === 0) return; // tabs must keep at least one (schema min 1)\n commit(next);\n if (activeId === id) setActiveId(next[0]?.id ?? \"\");\n };\n\n const addTab = () => {\n if (data.tabs.length >= 12) return; // schema max\n const id = newCodeTabId();\n commit([\n ...data.tabs,\n { id, label: `file-${data.tabs.length + 1}.ts`, code: \"\" },\n ]);\n setActiveId(id);\n };\n\n return (\n <div className=\"an-code-tabs-editor flex min-w-0 flex-col gap-4\">\n <div className=\"flex w-full min-w-0 items-start gap-2\">\n <div\n className=\"flex w-full min-w-0 flex-1 flex-nowrap items-center gap-1 overflow-x-auto\"\n role=\"tablist\"\n data-plan-interactive\n >\n {data.tabs.map((tab) => {\n const selected = tab.id === active?.id;\n return (\n <button\n key={tab.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={selected}\n onClick={() => setActiveId(tab.id)}\n className={cn(\n \"flex shrink-0 items-center gap-2 whitespace-nowrap rounded-lg border border-transparent px-3 py-2 font-mono text-sm font-semibold transition-colors\",\n selected\n ? \"bg-primary/10 text-plan-text dark:bg-primary/20\"\n : \"text-plan-muted hover:bg-plan-block/60 hover:text-plan-text\",\n )}\n >\n <IconCode className=\"size-4 shrink-0\" />\n {tab.label}\n </button>\n );\n })}\n </div>\n {editable && (\n <CodeTabsSettingsPopover\n active={active}\n tabs={data.tabs}\n onUpdate={updateTab}\n onAdd={addTab}\n onRemove={removeTab}\n />\n )}\n </div>\n {active && (\n <HighlightedCodeTextarea\n value={active.code}\n editable={editable}\n label={active.label}\n language={active.language}\n onChange={(event) =>\n updateTab(active.id, { code: event.target.value })\n }\n />\n )}\n </div>\n );\n}\n\nfunction CodeTabsSettingsPopover({\n active,\n tabs,\n onUpdate,\n onAdd,\n onRemove,\n}: {\n active: CodeTabsTab | undefined;\n tabs: CodeTabsTab[];\n onUpdate: (id: string, patch: Partial<CodeTabsTab>) => void;\n onAdd: () => void;\n onRemove: (id: string) => void;\n}) {\n return (\n <Popover>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n data-plan-interactive\n aria-label=\"Edit code tabs\"\n className=\"flex size-8 shrink-0 items-center justify-center rounded-md text-plan-muted transition-colors hover:text-plan-text focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n >\n <IconPencil className=\"size-4\" />\n </button>\n </PopoverTrigger>\n <PopoverContent\n align=\"end\"\n side=\"bottom\"\n className=\"w-80 p-0\"\n data-plan-interactive\n >\n <div className=\"border-b border-border px-3 py-2\">\n <div className=\"text-sm font-semibold text-foreground\">\n Code tab settings\n </div>\n <div className=\"text-xs text-muted-foreground\">\n Rename the active tab or manage its metadata.\n </div>\n </div>\n <div className=\"grid gap-3 p-3\">\n <label className=\"grid gap-1.5\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n Active tab label\n </span>\n <input\n type=\"text\"\n data-plan-interactive\n className={inputClass}\n value={active?.label ?? \"\"}\n disabled={!active}\n onChange={(event) => {\n if (!active) return;\n onUpdate(active.id, { label: event.target.value });\n }}\n />\n </label>\n <label className=\"grid gap-1.5\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n Language\n </span>\n <select\n data-plan-interactive\n className={inputClass}\n value={active?.language ?? \"\"}\n disabled={!active}\n onChange={(event) => {\n if (!active) return;\n onUpdate(active.id, {\n language: event.target.value || undefined,\n });\n }}\n >\n {CODE_TAB_LANGUAGES.map((option) => (\n <option key={option.value || \"auto\"} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n </label>\n <label className=\"grid gap-1.5\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n Caption\n </span>\n <input\n type=\"text\"\n data-plan-interactive\n className={inputClass}\n value={active?.caption ?? \"\"}\n disabled={!active}\n onChange={(event) => {\n if (!active) return;\n onUpdate(active.id, {\n caption: event.target.value || undefined,\n });\n }}\n />\n </label>\n <label className=\"grid gap-1.5\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n Max lines before expand\n </span>\n <input\n type=\"number\"\n min={0}\n step={1}\n data-plan-interactive\n className={inputClass}\n placeholder={`${DEFAULT_CODE_MAX_LINES} (default) · 0 = no limit`}\n value={active?.maxLines ?? \"\"}\n disabled={!active}\n onChange={(event) => {\n if (!active) return;\n const raw = event.target.value.trim();\n const parsed = raw === \"\" ? undefined : Number(raw);\n onUpdate(active.id, {\n maxLines:\n parsed === undefined || Number.isNaN(parsed)\n ? undefined\n : Math.max(0, Math.min(2000, Math.floor(parsed))),\n });\n }}\n />\n </label>\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n data-plan-interactive\n disabled={tabs.length >= 12}\n onClick={onAdd}\n className=\"inline-flex h-8 items-center gap-1.5 rounded-md border border-border px-2.5 text-xs font-medium text-foreground transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50\"\n >\n <IconPlus className=\"size-3.5\" />\n Add tab\n </button>\n <button\n type=\"button\"\n data-plan-interactive\n disabled={!active || tabs.length <= 1}\n onClick={() => {\n if (!active) return;\n onRemove(active.id);\n }}\n className=\"inline-flex h-8 items-center gap-1.5 rounded-md border border-border px-2.5 text-xs font-medium text-destructive transition-colors hover:bg-destructive/10 disabled:cursor-not-allowed disabled:opacity-50\"\n >\n <IconTrash className=\"size-3.5\" />\n Remove current\n </button>\n </div>\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n\n/* ── Spec ──────────────────────────────────────────────────────────────────── */\n\nexport const codeTabsBlock = defineBlock<CodeTabsData>({\n type: \"code-tabs\",\n schema: codeTabsSchema,\n mdx: codeTabsMdx,\n Read: CodeTabsRead,\n Edit: CodeTabsEdit,\n placement: [\"block\"],\n editSurface: \"inline\",\n label: \"Code tabs\",\n icon: IconCode,\n description:\n \"A vertical file tab rail of syntax-highlighted code snippets, one tab per file with an optional language and caption.\",\n});\n"]}
1
+ {"version":3,"file":"code-tabs.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/code-tabs.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,OAAO,EACP,MAAM,EACN,QAAQ,GAIT,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChF,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EACL,OAAO,EACP,cAAc,EACd,cAAc,GACf,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC3E,OAAO,EACL,cAAc,EACd,WAAW,GAGZ,MAAM,uBAAuB,CAAC;AAE/B;;;;;;;;;;GAUG;AAEH,iFAAiF;AAEjF,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;AAWxC,MAAM,gBAAgB,GAA2B;IAC/C,GAAG,EAAE,YAAY;IACjB,GAAG,EAAE,YAAY;IACjB,GAAG,EAAE,MAAM;IACX,EAAE,EAAE,YAAY;IAChB,KAAK,EAAE,MAAM;IACb,GAAG,EAAE,KAAK;IACV,EAAE,EAAE,UAAU;IACd,GAAG,EAAE,UAAU;IACf,GAAG,EAAE,YAAY;IACjB,GAAG,EAAE,YAAY;IACjB,EAAE,EAAE,QAAQ;IACZ,EAAE,EAAE,MAAM;IACV,EAAE,EAAE,MAAM;IACV,EAAE,EAAE,MAAM;IACV,KAAK,EAAE,MAAM;IACb,EAAE,EAAE,YAAY;IAChB,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,MAAM;IACX,GAAG,EAAE,MAAM;CACZ,CAAC;AAEF,MAAM,iBAAiB,GAA2B;IAChD,eAAe,EAAE,wCAAwC;IACzD,WAAW,EAAE,gCAAgC;IAC7C,gBAAgB,EAAE,gCAAgC;IAClD,eAAe,EAAE,oCAAoC;IACrD,aAAa,EAAE,cAAc;IAC7B,cAAc,EAAE,8BAA8B;IAC9C,eAAe,EAAE,kBAAkB;IACnC,aAAa,EAAE,kBAAkB;IACjC,eAAe,EAAE,QAAQ;IACzB,cAAc,EAAE,kBAAkB;IAClC,cAAc,EAAE,kCAAkC;IAClD,WAAW,EAAE,iCAAiC;IAC9C,cAAc,EAAE,sCAAsC;IACtD,WAAW,EAAE,cAAc;IAC3B,kBAAkB,EAAE,wCAAwC;IAC5D,WAAW,EAAE,wCAAwC;IACrD,aAAa,EAAE,gCAAgC;IAC/C,aAAa,EAAE,gCAAgC;IAC/C,eAAe,EAAE,gCAAgC;IACjD,YAAY,EAAE,8BAA8B;IAC5C,aAAa,EAAE,wCAAwC;IACvD,cAAc,EAAE,sCAAsC;IACtD,oBAAoB,EAAE,cAAc;IACpC,qBAAqB,EAAE,wCAAwC;IAC/D,kBAAkB,EAAE,wCAAwC;IAC5D,sBAAsB,EAAE,cAAc;IACtC,mBAAmB,EAAE,wCAAwC;IAC7D,aAAa,EAAE,wCAAwC;IACvD,aAAa,EAAE,eAAe;IAC9B,YAAY,EAAE,kBAAkB;IAChC,aAAa,EAAE,cAAc;IAC7B,UAAU,EAAE,wCAAwC;IACpD,wBAAwB,EAAE,oCAAoC;IAC9D,YAAY,EAAE,sCAAsC;IACpD,WAAW,EAAE,oCAAoC;IACjD,eAAe,EAAE,oCAAoC;IACrD,SAAS,EAAE,oCAAoC;CAChD,CAAC;AAEF,SAAS,qBAAqB,CAAC,KAAqB;IAClD,MAAM,GAAG,GAAG,KAAK;QACf,EAAE,IAAI,EAAE;SACP,WAAW,EAAE;SACb,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IAC7B,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,MAAM,UAAU,GAAG,gBAAgB,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC;IAChD,OAAO,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7D,CAAC;AAED,SAAS,yBAAyB,CAAC,QAAwB;IACzD,MAAM,QAAQ,GAAG,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,CAAC;IAC3D,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3B,IAAI,QAAQ,KAAK,YAAY;QAAE,OAAO,qBAAqB,CAAC,MAAM,CAAC,CAAC;IACpE,MAAM,SAAS,GAAG,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;QACtC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE;QAC3B,CAAC,CAAC,SAAS,CAAC;IACd,OAAO,qBAAqB,CAAC,SAAS,CAAC,CAAC;AAC1C,CAAC;AAED,SAAS,eAAe,CAAC,GAAiB;IACxC,OAAO,CACL,qBAAqB,CAAC,GAAG,EAAE,QAAQ,CAAC;QACpC,yBAAyB,CAAC,GAAG,EAAE,KAAK,CAAC;QACrC,SAAS,CACV,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,KAAoC;IAC1D,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAClC,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ;YACzB,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC;YACpB,CAAC,CAAC,EAAE,CAAC;IACT,OAAO,OAAO;SACX,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;SACtD,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;AACf,CAAC;AAED,SAAS,WAAW,CAAC,QAAwB,EAAE,SAAiB;IAC9D,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAClC,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;YAAE,OAAO,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;QAClD,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC5B,MAAM,GAAG,GAAG,GAAG,SAAS,GAAG,KAAK,EAAE,CAAC;YACnC,MAAM,gBAAgB,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM;gBAC5C,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,GAAG,GAAG,CAAC;gBACvC,CAAC,CAAC,IAAI,CAAC;YACT,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;YAC7D,OAAO,CACL,eAAgB,SAAS,EAAE,SAAS,IAAI,SAAS,YAC9C,gBAAgB,IADR,GAAG,CAEP,CACR,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,aAAa,CAAC,IAAY,EAAE,QAAiB;IACpD,MAAM,UAAU,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IACnD,IAAI,CAAC,UAAU,IAAI,UAAU,KAAK,WAAW,IAAI,UAAU,KAAK,MAAM,EAAE,CAAC;QACvE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,CAAiB,CAAC;QAClE,OAAO,WAAW,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,EAAE,GAAG,UAAU,GAAG,CAAC,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,kFAAkF;AAElF,SAAS,YAAY,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAgC;IAC1E,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACjE,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,QAAQ,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC5E,OAAO,CACL,mBAAS,SAAS,EAAC,YAAY,mBAAgB,OAAO,aACnD,KAAK,IAAI,cAAK,SAAS,EAAC,kBAAkB,YAAE,KAAK,GAAO,EACzD,eAAK,SAAS,EAAC,mFAAmF,aAChG,cAAK,SAAS,EAAC,8BAA8B,YAC1C,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CACtB,kBAEE,IAAI,EAAC,QAAQ,iCAEb,SAAS,EAAE,EAAE,CACX,6EAA6E,EAC7E,GAAG,CAAC,EAAE,KAAK,MAAM,EAAE,EAAE;gCACnB,CAAC,CAAC,iDAAiD;gCACnD,CAAC,CAAC,oCAAoC,CACzC,EACD,OAAO,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,aAElC,KAAC,QAAQ,IAAC,SAAS,EAAC,wBAAwB,GAAG,EAC/C,gBAAM,SAAS,EAAC,SAAS,aACvB,eAAM,SAAS,EAAC,gDAAgD,YAC7D,GAAG,CAAC,KAAK,GACL,EACN,GAAG,CAAC,OAAO,IAAI,CACd,eAAM,SAAS,EAAC,8BAA8B,YAC3C,GAAG,CAAC,OAAO,GACP,CACR,IACI,KArBF,GAAG,CAAC,EAAE,CAsBJ,CACV,CAAC,GACE,EACN,cAAK,SAAS,EAAC,aAAa,YACzB,MAAM,IAAI,CACT,8BACE,aAAI,SAAS,EAAC,uCAAuC,YAClD,MAAM,CAAC,KAAK,GACV,EACJ,MAAM,CAAC,OAAO,IAAI,CACjB,YAAG,SAAS,EAAC,sBAAsB,YAAE,MAAM,CAAC,OAAO,GAAK,CACzD,EACD,KAAC,WAAW,IACV,IAAI,EAAE,MAAM,CAAC,IAAI,EACjB,QAAQ,EAAE,eAAe,CAAC,MAAM,CAAC,EACjC,QAAQ,EAAE,MAAM,CAAC,QAAQ,GACzB,IACD,CACJ,GACG,IACF,IACE,CACX,CAAC;AACJ,CAAC;AAED,kFAAkF;AAElF,MAAM,UAAU,GACd,6PAA6P,CAAC;AAEhQ,+EAA+E;AAC/E,MAAM,kBAAkB,GAAoD;IAC1E,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE;IAC5B,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE;IAC5C,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE;IAC5C,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE;IAC9B,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE;IAC9B,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;IAChC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;IAChC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE;IAC9B,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;IAChC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;IACpC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE;IAC9B,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;IAChC,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE;IACxC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;IACtC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;IAC5B,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;IAChC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;CACjC,CAAC;AAEF,4EAA4E;AAC5E,SAAS,YAAY;IACnB,OAAO,YAAY,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;AAC/D,CAAC;AAED,SAAS,uBAAuB,CAAC,EAC/B,KAAK,EACL,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,QAAQ,GAOT;IACC,MAAM,iBAAiB,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IACvD,MAAM,gBAAgB,GACpB,qBAAqB,CAAC,QAAQ,CAAC,IAAI,yBAAyB,CAAC,KAAK,CAAC,CAAC;IACtE,MAAM,WAAW,GAAG,OAAO,CACzB,GAAG,EAAE,CAAC,aAAa,CAAC,KAAK,EAAE,gBAAgB,IAAI,SAAS,CAAC,EACzD,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAC1B,CAAC;IAEF,MAAM,UAAU,GAAG,CAAC,KAAmC,EAAE,EAAE;QACzD,MAAM,KAAK,GAAG,iBAAiB,CAAC,OAAO,CAAC;QACxC,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC;QAChD,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC;IACpD,CAAC,CAAC;IAEF,OAAO,CACL,eACE,SAAS,EAAE,EAAE,CACX,gJAAgJ,EAChJ,CAAC,QAAQ,IAAI,+BAA+B,CAC7C,wDAGD,cACE,GAAG,EAAE,iBAAiB,iBACV,MAAM,EAClB,SAAS,EAAC,yIAAyI,oDAGnJ,2BACG,WAAW,EACX,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,IAC7B,GACH,EACN,kDAEE,UAAU,EAAE,KAAK,EACjB,IAAI,EAAC,KAAK,EACV,SAAS,EAAE,EAAE,CACX,gQAAgQ,EAChQ,KAAK,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,uBAAuB,CACrD,EACD,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,CAAC,QAAQ,EACnB,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,UAAU,GACpB,IACE,CACP,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,YAAY,CAAC,EACpB,IAAI,EACJ,QAAQ,EACR,QAAQ,GACqB;IAC7B,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACjE,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,QAAQ,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAE5E,MAAM,MAAM,GAAG,CAAC,IAAmB,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IAE3D,MAAM,SAAS,GAAG,CAAC,EAAU,EAAE,KAA2B,EAAE,EAAE,CAC5D,MAAM,CACJ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CACrE,CAAC;IAEJ,MAAM,SAAS,GAAG,CAAC,EAAU,EAAE,EAAE;QAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QACtD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,CAAC,6CAA6C;QAC5E,MAAM,CAAC,IAAI,CAAC,CAAC;QACb,IAAI,QAAQ,KAAK,EAAE;YAAE,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC,CAAC;IAEF,MAAM,MAAM,GAAG,GAAG,EAAE;QAClB,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE;YAAE,OAAO,CAAC,aAAa;QACjD,MAAM,EAAE,GAAG,YAAY,EAAE,CAAC;QAC1B,MAAM,CAAC;YACL,GAAG,IAAI,CAAC,IAAI;YACZ,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE;SAC3D,CAAC,CAAC;QACH,WAAW,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC,CAAC;IAEF,OAAO,CACL,eAAK,SAAS,EAAC,iDAAiD,aAC9D,eAAK,SAAS,EAAC,uCAAuC,aACpD,cACE,SAAS,EAAC,2EAA2E,EACrF,IAAI,EAAC,SAAS,2CAGb,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;4BACrB,MAAM,QAAQ,GAAG,GAAG,CAAC,EAAE,KAAK,MAAM,EAAE,EAAE,CAAC;4BACvC,OAAO,CACL,kBAEE,IAAI,EAAC,QAAQ,EACb,IAAI,EAAC,KAAK,mBACK,QAAQ,EACvB,OAAO,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,EAClC,SAAS,EAAE,EAAE,CACX,qJAAqJ,EACrJ,QAAQ;oCACN,CAAC,CAAC,iDAAiD;oCACnD,CAAC,CAAC,6DAA6D,CAClE,aAED,KAAC,QAAQ,IAAC,SAAS,EAAC,iBAAiB,GAAG,EACvC,GAAG,CAAC,KAAK,KAbL,GAAG,CAAC,EAAE,CAcJ,CACV,CAAC;wBACJ,CAAC,CAAC,GACE,EACL,QAAQ,IAAI,CACX,KAAC,uBAAuB,IACtB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,IAAI,CAAC,IAAI,EACf,QAAQ,EAAE,SAAS,EACnB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,SAAS,GACnB,CACH,IACG,EACL,MAAM,IAAI,CACT,KAAC,uBAAuB,IACtB,KAAK,EAAE,MAAM,CAAC,IAAI,EAClB,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,MAAM,CAAC,KAAK,EACnB,QAAQ,EAAE,MAAM,CAAC,QAAQ,EACzB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAClB,SAAS,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,GAEpD,CACH,IACG,CACP,CAAC;AACJ,CAAC;AAED,SAAS,uBAAuB,CAAC,EAC/B,MAAM,EACN,IAAI,EACJ,QAAQ,EACR,KAAK,EACL,QAAQ,GAOT;IACC,OAAO,CACL,MAAC,OAAO,eACN,KAAC,cAAc,IAAC,OAAO,kBACrB,iBACE,IAAI,EAAC,QAAQ,+CAEF,gBAAgB,EAC3B,SAAS,EAAC,4LAA4L,YAEtM,KAAC,UAAU,IAAC,SAAS,EAAC,QAAQ,GAAG,GAC1B,GACM,EACjB,MAAC,cAAc,IACb,KAAK,EAAC,KAAK,EACX,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,UAAU,4CAGpB,eAAK,SAAS,EAAC,kCAAkC,aAC/C,cAAK,SAAS,EAAC,uCAAuC,kCAEhD,EACN,cAAK,SAAS,EAAC,+BAA+B,8DAExC,IACF,EACN,eAAK,SAAS,EAAC,gBAAgB,aAC7B,iBAAO,SAAS,EAAC,cAAc,aAC7B,eAAM,SAAS,EAAC,2CAA2C,iCAEpD,EACP,gBACE,IAAI,EAAC,MAAM,iCAEX,SAAS,EAAE,UAAU,EACrB,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,EAAE,EAC1B,QAAQ,EAAE,CAAC,MAAM,EACjB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;4CAClB,IAAI,CAAC,MAAM;gDAAE,OAAO;4CACpB,QAAQ,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;wCACrD,CAAC,GACD,IACI,EACR,iBAAO,SAAS,EAAC,cAAc,aAC7B,eAAM,SAAS,EAAC,2CAA2C,yBAEpD,EACP,gDAEE,SAAS,EAAE,UAAU,EACrB,KAAK,EAAE,MAAM,EAAE,QAAQ,IAAI,EAAE,EAC7B,QAAQ,EAAE,CAAC,MAAM,EACjB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;4CAClB,IAAI,CAAC,MAAM;gDAAE,OAAO;4CACpB,QAAQ,CAAC,MAAM,CAAC,EAAE,EAAE;gDAClB,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,SAAS;6CAC1C,CAAC,CAAC;wCACL,CAAC,YAEA,kBAAkB,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAClC,iBAAqC,KAAK,EAAE,MAAM,CAAC,KAAK,YACrD,MAAM,CAAC,KAAK,IADF,MAAM,CAAC,KAAK,IAAI,MAAM,CAE1B,CACV,CAAC,GACK,IACH,EACR,iBAAO,SAAS,EAAC,cAAc,aAC7B,eAAM,SAAS,EAAC,2CAA2C,wBAEpD,EACP,gBACE,IAAI,EAAC,MAAM,iCAEX,SAAS,EAAE,UAAU,EACrB,KAAK,EAAE,MAAM,EAAE,OAAO,IAAI,EAAE,EAC5B,QAAQ,EAAE,CAAC,MAAM,EACjB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;4CAClB,IAAI,CAAC,MAAM;gDAAE,OAAO;4CACpB,QAAQ,CAAC,MAAM,CAAC,EAAE,EAAE;gDAClB,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,SAAS;6CACzC,CAAC,CAAC;wCACL,CAAC,GACD,IACI,EACR,iBAAO,SAAS,EAAC,cAAc,aAC7B,eAAM,SAAS,EAAC,2CAA2C,wCAEpD,EACP,gBACE,IAAI,EAAC,QAAQ,EACb,GAAG,EAAE,CAAC,EACN,IAAI,EAAE,CAAC,iCAEP,SAAS,EAAE,UAAU,EACrB,WAAW,EAAE,GAAG,sBAAsB,2BAA2B,EACjE,KAAK,EAAE,MAAM,EAAE,QAAQ,IAAI,EAAE,EAC7B,QAAQ,EAAE,CAAC,MAAM,EACjB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;4CAClB,IAAI,CAAC,MAAM;gDAAE,OAAO;4CACpB,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;4CACtC,MAAM,MAAM,GAAG,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;4CACpD,QAAQ,CAAC,MAAM,CAAC,EAAE,EAAE;gDAClB,QAAQ,EACN,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;oDAC1C,CAAC,CAAC,SAAS;oDACX,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;6CACtD,CAAC,CAAC;wCACL,CAAC,GACD,IACI,EACR,eAAK,SAAS,EAAC,yBAAyB,aACtC,kBACE,IAAI,EAAC,QAAQ,iCAEb,QAAQ,EAAE,IAAI,CAAC,MAAM,IAAI,EAAE,EAC3B,OAAO,EAAE,KAAK,EACd,SAAS,EAAC,mMAAmM,aAE7M,KAAC,QAAQ,IAAC,SAAS,EAAC,UAAU,GAAG,eAE1B,EACT,kBACE,IAAI,EAAC,QAAQ,iCAEb,QAAQ,EAAE,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,EACrC,OAAO,EAAE,GAAG,EAAE;4CACZ,IAAI,CAAC,MAAM;gDAAE,OAAO;4CACpB,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;wCACtB,CAAC,EACD,SAAS,EAAC,4MAA4M,aAEtN,KAAC,SAAS,IAAC,SAAS,EAAC,UAAU,GAAG,sBAE3B,IACL,IACF,IACS,IACT,CACX,CAAC;AACJ,CAAC;AAED,kFAAkF;AAElF,MAAM,CAAC,MAAM,aAAa,GAAG,WAAW,CAAe;IACrD,IAAI,EAAE,WAAW;IACjB,MAAM,EAAE,cAAc;IACtB,GAAG,EAAE,WAAW;IAChB,IAAI,EAAE,YAAY;IAClB,IAAI,EAAE,YAAY;IAClB,SAAS,EAAE,CAAC,OAAO,CAAC;IACpB,WAAW,EAAE,QAAQ;IACrB,KAAK,EAAE,WAAW;IAClB,IAAI,EAAE,QAAQ;IACd,WAAW,EACT,uHAAuH;CAC1H,CAAC,CAAC","sourcesContent":["import {\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type ReactNode,\n type UIEvent,\n} from \"react\";\nimport { IconCode, IconPencil, IconPlus, IconTrash } from \"@tabler/icons-react\";\nimport { common, createLowlight } from \"lowlight\";\nimport { cn } from \"../../utils.js\";\nimport { defineBlock } from \"../types.js\";\nimport type { BlockReadProps, BlockEditProps } from \"../types.js\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../../components/ui/popover.js\";\nimport { CodeSurface, DEFAULT_CODE_MAX_LINES } from \"./HighlightedCode.js\";\nimport {\n codeTabsSchema,\n codeTabsMdx,\n type CodeTabsData,\n type CodeTabsTab,\n} from \"./code-tabs.config.js\";\n\n/**\n * Standard `code-tabs` block (STANDARD core library): a vertical file tab rail\n * with Shiki-highlighted code panes. Moved verbatim from the plan\n * `CodeTabsBlock` (`DocumentArea.tsx`) so its rendered output is unchanged, then\n * generalized to the registry `Read`/`Edit` contract. Shareable by any app that\n * registers the core block library.\n *\n * `Edit` is hybrid: each tab's `code` field renders as a code-style monospace\n * text area, while tab metadata (label/language/caption/add/remove) stays in a\n * settings popover so the document surface only exposes authored content.\n */\n\n/* ── Syntax highlighting helpers ──────────────────────────────────────────── */\n\nconst lowlight = createLowlight(common);\n\ntype LowlightNode = {\n type: string;\n value?: string;\n properties?: {\n className?: string[] | string;\n };\n children?: LowlightNode[];\n};\n\nconst LANGUAGE_ALIASES: Record<string, string> = {\n cjs: \"javascript\",\n cts: \"typescript\",\n htm: \"html\",\n js: \"javascript\",\n jsonc: \"json\",\n jsx: \"jsx\",\n md: \"markdown\",\n mdx: \"markdown\",\n mjs: \"javascript\",\n mts: \"typescript\",\n py: \"python\",\n rb: \"ruby\",\n rs: \"rust\",\n sh: \"bash\",\n shell: \"bash\",\n ts: \"typescript\",\n tsx: \"tsx\",\n yml: \"yaml\",\n zsh: \"bash\",\n};\n\nconst TOKEN_CLASS_NAMES: Record<string, string> = {\n \"hljs-addition\": \"text-emerald-700 dark:text-emerald-300\",\n \"hljs-attr\": \"text-sky-700 dark:text-sky-300\",\n \"hljs-attribute\": \"text-sky-700 dark:text-sky-300\",\n \"hljs-built_in\": \"text-amber-700 dark:text-amber-300\",\n \"hljs-bullet\": \"text-primary\",\n \"hljs-comment\": \"text-muted-foreground italic\",\n \"hljs-deletion\": \"text-destructive\",\n \"hljs-doctag\": \"text-destructive\",\n \"hljs-emphasis\": \"italic\",\n \"hljs-formula\": \"text-destructive\",\n \"hljs-keyword\": \"text-rose-700 dark:text-rose-300\",\n \"hljs-link\": \"text-primary underline-offset-2\",\n \"hljs-literal\": \"text-violet-700 dark:text-violet-300\",\n \"hljs-meta\": \"text-primary\",\n \"hljs-meta-string\": \"text-emerald-700 dark:text-emerald-300\",\n \"hljs-name\": \"text-emerald-700 dark:text-emerald-300\",\n \"hljs-number\": \"text-sky-700 dark:text-sky-300\",\n \"hljs-params\": \"text-sky-700 dark:text-sky-300\",\n \"hljs-property\": \"text-sky-700 dark:text-sky-300\",\n \"hljs-quote\": \"text-muted-foreground italic\",\n \"hljs-regexp\": \"text-emerald-700 dark:text-emerald-300\",\n \"hljs-section\": \"text-violet-700 dark:text-violet-300\",\n \"hljs-selector-attr\": \"text-primary\",\n \"hljs-selector-class\": \"text-emerald-700 dark:text-emerald-300\",\n \"hljs-selector-id\": \"text-emerald-700 dark:text-emerald-300\",\n \"hljs-selector-pseudo\": \"text-primary\",\n \"hljs-selector-tag\": \"text-emerald-700 dark:text-emerald-300\",\n \"hljs-string\": \"text-emerald-700 dark:text-emerald-300\",\n \"hljs-strong\": \"font-semibold\",\n \"hljs-subst\": \"text-destructive\",\n \"hljs-symbol\": \"text-primary\",\n \"hljs-tag\": \"text-emerald-700 dark:text-emerald-300\",\n \"hljs-template-variable\": \"text-amber-700 dark:text-amber-300\",\n \"hljs-title\": \"text-violet-700 dark:text-violet-300\",\n \"hljs-type\": \"text-amber-700 dark:text-amber-300\",\n \"hljs-variable\": \"text-amber-700 dark:text-amber-300\",\n language_: \"text-amber-700 dark:text-amber-300\",\n};\n\nfunction normalizeCodeLanguage(value?: string | null): string | null {\n const raw = value\n ?.trim()\n .toLowerCase()\n .replace(/^language-/, \"\");\n if (!raw) return null;\n const normalized = LANGUAGE_ALIASES[raw] ?? raw;\n return lowlight.registered(normalized) ? normalized : null;\n}\n\nfunction inferLanguageFromFilename(filename?: string | null): string | null {\n const basename = filename?.split(\"/\").pop()?.toLowerCase();\n if (!basename) return null;\n if (basename === \"dockerfile\") return normalizeCodeLanguage(\"bash\");\n const extension = basename.includes(\".\")\n ? basename.split(\".\").pop()\n : undefined;\n return normalizeCodeLanguage(extension);\n}\n\nfunction codeTabLanguage(tab?: CodeTabsTab): string | undefined {\n return (\n normalizeCodeLanguage(tab?.language) ??\n inferLanguageFromFilename(tab?.label) ??\n undefined\n );\n}\n\nfunction tokenClassName(value: string[] | string | undefined): string {\n const classes = Array.isArray(value)\n ? value\n : typeof value === \"string\"\n ? value.split(/\\s+/)\n : [];\n return classes\n .map((className) => TOKEN_CLASS_NAMES[className] ?? \"\")\n .filter(Boolean)\n .join(\" \");\n}\n\nfunction hastToReact(children: LowlightNode[], keyPrefix: string): ReactNode[] {\n return children.map((node, index) => {\n if (node.type === \"text\") return node.value ?? \"\";\n if (node.type === \"element\") {\n const key = `${keyPrefix}${index}`;\n const renderedChildren = node.children?.length\n ? hastToReact(node.children, `${key}-`)\n : null;\n const className = tokenClassName(node.properties?.className);\n return (\n <span key={key} className={className || undefined}>\n {renderedChildren}\n </span>\n );\n }\n return null;\n });\n}\n\nfunction highlightCode(code: string, language?: string): ReactNode {\n const normalized = normalizeCodeLanguage(language);\n if (!normalized || normalized === \"plaintext\" || normalized === \"text\") {\n return code;\n }\n try {\n const tree = lowlight.highlight(normalized, code) as LowlightNode;\n return hastToReact(tree.children ?? [], `${normalized}-`);\n } catch {\n return code;\n }\n}\n\n/* ── Read (vertical tab rail + Shiki) ──────────────────────────────────────── */\n\nfunction CodeTabsRead({ data, blockId, title }: BlockReadProps<CodeTabsData>) {\n const [activeId, setActiveId] = useState(data.tabs[0]?.id ?? \"\");\n const active = data.tabs.find((tab) => tab.id === activeId) ?? data.tabs[0];\n return (\n <section className=\"plan-block\" data-block-id={blockId}>\n {title && <div className=\"plan-block-label\">{title}</div>}\n <div className=\"grid overflow-hidden border-y border-plan-line md:grid-cols-[300px_minmax(0,1fr)]\">\n <div className=\"border-plan-line md:border-r\">\n {data.tabs.map((tab) => (\n <button\n key={tab.id}\n type=\"button\"\n data-plan-interactive\n className={cn(\n \"flex w-full items-start gap-3 border-b border-plan-line px-4 py-4 text-left\",\n tab.id === active?.id\n ? \"bg-primary/10 text-plan-text dark:bg-primary/20\"\n : \"text-plan-muted hover:bg-accent/30\",\n )}\n onClick={() => setActiveId(tab.id)}\n >\n <IconCode className=\"mt-0.5 size-4 shrink-0\" />\n <span className=\"min-w-0\">\n <span className=\"block truncate font-mono text-sm font-semibold\">\n {tab.label}\n </span>\n {tab.caption && (\n <span className=\"mt-1 block text-xs leading-5\">\n {tab.caption}\n </span>\n )}\n </span>\n </button>\n ))}\n </div>\n <div className=\"min-w-0 p-5\">\n {active && (\n <>\n <h3 className=\"text-2xl font-semibold tracking-tight\">\n {active.label}\n </h3>\n {active.caption && (\n <p className=\"mt-2 text-plan-muted\">{active.caption}</p>\n )}\n <CodeSurface\n code={active.code}\n language={codeTabLanguage(active)}\n maxLines={active.maxLines}\n />\n </>\n )}\n </div>\n </div>\n </section>\n );\n}\n\n/* ── Edit (code text areas per tab) ────────────────────────────────────────── */\n\nconst inputClass =\n \"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\";\n\n/** Language options for the per-tab picker; \"\" is the Auto-detect sentinel. */\nconst CODE_TAB_LANGUAGES: ReadonlyArray<{ value: string; label: string }> = [\n { value: \"\", label: \"Auto\" },\n { value: \"typescript\", label: \"TypeScript\" },\n { value: \"javascript\", label: \"JavaScript\" },\n { value: \"tsx\", label: \"TSX\" },\n { value: \"jsx\", label: \"JSX\" },\n { value: \"json\", label: \"JSON\" },\n { value: \"html\", label: \"HTML\" },\n { value: \"css\", label: \"CSS\" },\n { value: \"bash\", label: \"Bash\" },\n { value: \"python\", label: \"Python\" },\n { value: \"sql\", label: \"SQL\" },\n { value: \"yaml\", label: \"YAML\" },\n { value: \"markdown\", label: \"Markdown\" },\n { value: \"graphql\", label: \"GraphQL\" },\n { value: \"go\", label: \"Go\" },\n { value: \"rust\", label: \"Rust\" },\n { value: \"diff\", label: \"Diff\" },\n];\n\n/** Mint a reasonably-unique code-tab id without pulling a dep into core. */\nfunction newCodeTabId(): string {\n return `code-tab-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction HighlightedCodeTextarea({\n value,\n language,\n label,\n editable,\n onChange,\n}: {\n value: string;\n language?: string;\n label?: string;\n editable: boolean;\n onChange: (event: ChangeEvent<HTMLTextAreaElement>) => void;\n}) {\n const highlightLayerRef = useRef<HTMLPreElement>(null);\n const resolvedLanguage =\n normalizeCodeLanguage(language) ?? inferLanguageFromFilename(label);\n const highlighted = useMemo(\n () => highlightCode(value, resolvedLanguage ?? undefined),\n [resolvedLanguage, value],\n );\n\n const syncScroll = (event: UIEvent<HTMLTextAreaElement>) => {\n const layer = highlightLayerRef.current;\n if (!layer) return;\n layer.scrollTop = event.currentTarget.scrollTop;\n layer.scrollLeft = event.currentTarget.scrollLeft;\n };\n\n return (\n <div\n className={cn(\n \"relative min-h-[140px] overflow-hidden rounded-md border border-input bg-background text-foreground focus-within:ring-1 focus-within:ring-ring\",\n !editable && \"cursor-not-allowed opacity-50\",\n )}\n data-code-tabs-highlighted-editor\n >\n <pre\n ref={highlightLayerRef}\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute inset-0 m-0 overflow-hidden whitespace-pre px-3 py-2 font-mono [font-size:var(--plan-code-size)] leading-5\"\n data-code-tabs-highlight-layer\n >\n <code>\n {highlighted}\n {value.endsWith(\"\\n\") ? \" \" : null}\n </code>\n </pre>\n <textarea\n data-plan-interactive\n spellCheck={false}\n wrap=\"off\"\n className={cn(\n \"relative z-10 block min-h-[140px] w-full resize-y overflow-auto rounded-md border-0 bg-transparent px-3 py-2 font-mono [font-size:var(--plan-code-size)] leading-5 caret-foreground outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed\",\n value ? \"text-transparent\" : \"text-muted-foreground\",\n )}\n value={value}\n disabled={!editable}\n onChange={onChange}\n onScroll={syncScroll}\n />\n </div>\n );\n}\n\n/**\n * Editor: a file-tab strip (one tab active at a time) with the active tab's code\n * editable inline. Tab metadata is edited from the settings popover, mirroring\n * the standard `tabs` block and keeping schema-ish controls out of the document.\n */\nfunction CodeTabsEdit({\n data,\n onChange,\n editable,\n}: BlockEditProps<CodeTabsData>) {\n const [activeId, setActiveId] = useState(data.tabs[0]?.id ?? \"\");\n const active = data.tabs.find((tab) => tab.id === activeId) ?? data.tabs[0];\n\n const commit = (tabs: CodeTabsTab[]) => onChange({ tabs });\n\n const updateTab = (id: string, patch: Partial<CodeTabsTab>) =>\n commit(\n data.tabs.map((tab) => (tab.id === id ? { ...tab, ...patch } : tab)),\n );\n\n const removeTab = (id: string) => {\n const next = data.tabs.filter((tab) => tab.id !== id);\n if (next.length === 0) return; // tabs must keep at least one (schema min 1)\n commit(next);\n if (activeId === id) setActiveId(next[0]?.id ?? \"\");\n };\n\n const addTab = () => {\n if (data.tabs.length >= 12) return; // schema max\n const id = newCodeTabId();\n commit([\n ...data.tabs,\n { id, label: `file-${data.tabs.length + 1}.ts`, code: \"\" },\n ]);\n setActiveId(id);\n };\n\n return (\n <div className=\"an-code-tabs-editor flex min-w-0 flex-col gap-4\">\n <div className=\"flex w-full min-w-0 items-start gap-2\">\n <div\n className=\"flex w-full min-w-0 flex-1 flex-nowrap items-center gap-1 overflow-x-auto\"\n role=\"tablist\"\n data-plan-interactive\n >\n {data.tabs.map((tab) => {\n const selected = tab.id === active?.id;\n return (\n <button\n key={tab.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={selected}\n onClick={() => setActiveId(tab.id)}\n className={cn(\n \"flex shrink-0 items-center gap-2 whitespace-nowrap rounded-lg border border-transparent px-3 py-2 font-mono text-sm font-semibold transition-colors\",\n selected\n ? \"bg-primary/10 text-plan-text dark:bg-primary/20\"\n : \"text-plan-muted hover:bg-plan-block/60 hover:text-plan-text\",\n )}\n >\n <IconCode className=\"size-4 shrink-0\" />\n {tab.label}\n </button>\n );\n })}\n </div>\n {editable && (\n <CodeTabsSettingsPopover\n active={active}\n tabs={data.tabs}\n onUpdate={updateTab}\n onAdd={addTab}\n onRemove={removeTab}\n />\n )}\n </div>\n {active && (\n <HighlightedCodeTextarea\n value={active.code}\n editable={editable}\n label={active.label}\n language={active.language}\n onChange={(event) =>\n updateTab(active.id, { code: event.target.value })\n }\n />\n )}\n </div>\n );\n}\n\nfunction CodeTabsSettingsPopover({\n active,\n tabs,\n onUpdate,\n onAdd,\n onRemove,\n}: {\n active: CodeTabsTab | undefined;\n tabs: CodeTabsTab[];\n onUpdate: (id: string, patch: Partial<CodeTabsTab>) => void;\n onAdd: () => void;\n onRemove: (id: string) => void;\n}) {\n return (\n <Popover>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n data-plan-interactive\n aria-label=\"Edit code tabs\"\n className=\"flex size-8 shrink-0 items-center justify-center rounded-md text-plan-muted transition-colors hover:text-plan-text focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n >\n <IconPencil className=\"size-4\" />\n </button>\n </PopoverTrigger>\n <PopoverContent\n align=\"end\"\n side=\"bottom\"\n className=\"w-80 p-0\"\n data-plan-interactive\n >\n <div className=\"border-b border-border px-3 py-2\">\n <div className=\"text-sm font-semibold text-foreground\">\n Code tab settings\n </div>\n <div className=\"text-xs text-muted-foreground\">\n Rename the active tab or manage its metadata.\n </div>\n </div>\n <div className=\"grid gap-3 p-3\">\n <label className=\"grid gap-1.5\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n Active tab label\n </span>\n <input\n type=\"text\"\n data-plan-interactive\n className={inputClass}\n value={active?.label ?? \"\"}\n disabled={!active}\n onChange={(event) => {\n if (!active) return;\n onUpdate(active.id, { label: event.target.value });\n }}\n />\n </label>\n <label className=\"grid gap-1.5\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n Language\n </span>\n <select\n data-plan-interactive\n className={inputClass}\n value={active?.language ?? \"\"}\n disabled={!active}\n onChange={(event) => {\n if (!active) return;\n onUpdate(active.id, {\n language: event.target.value || undefined,\n });\n }}\n >\n {CODE_TAB_LANGUAGES.map((option) => (\n <option key={option.value || \"auto\"} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n </label>\n <label className=\"grid gap-1.5\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n Caption\n </span>\n <input\n type=\"text\"\n data-plan-interactive\n className={inputClass}\n value={active?.caption ?? \"\"}\n disabled={!active}\n onChange={(event) => {\n if (!active) return;\n onUpdate(active.id, {\n caption: event.target.value || undefined,\n });\n }}\n />\n </label>\n <label className=\"grid gap-1.5\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n Max lines before expand\n </span>\n <input\n type=\"number\"\n min={0}\n step={1}\n data-plan-interactive\n className={inputClass}\n placeholder={`${DEFAULT_CODE_MAX_LINES} (default) · 0 = no limit`}\n value={active?.maxLines ?? \"\"}\n disabled={!active}\n onChange={(event) => {\n if (!active) return;\n const raw = event.target.value.trim();\n const parsed = raw === \"\" ? undefined : Number(raw);\n onUpdate(active.id, {\n maxLines:\n parsed === undefined || Number.isNaN(parsed)\n ? undefined\n : Math.max(0, Math.min(2000, Math.floor(parsed))),\n });\n }}\n />\n </label>\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n data-plan-interactive\n disabled={tabs.length >= 12}\n onClick={onAdd}\n className=\"inline-flex h-8 items-center gap-1.5 rounded-md border border-border px-2.5 text-xs font-medium text-foreground transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50\"\n >\n <IconPlus className=\"size-3.5\" />\n Add tab\n </button>\n <button\n type=\"button\"\n data-plan-interactive\n disabled={!active || tabs.length <= 1}\n onClick={() => {\n if (!active) return;\n onRemove(active.id);\n }}\n className=\"inline-flex h-8 items-center gap-1.5 rounded-md border border-border px-2.5 text-xs font-medium text-destructive transition-colors hover:bg-destructive/10 disabled:cursor-not-allowed disabled:opacity-50\"\n >\n <IconTrash className=\"size-3.5\" />\n Remove current\n </button>\n </div>\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n\n/* ── Spec ──────────────────────────────────────────────────────────────────── */\n\nexport const codeTabsBlock = defineBlock<CodeTabsData>({\n type: \"code-tabs\",\n schema: codeTabsSchema,\n mdx: codeTabsMdx,\n Read: CodeTabsRead,\n Edit: CodeTabsEdit,\n placement: [\"block\"],\n editSurface: \"inline\",\n label: \"Code tabs\",\n icon: IconCode,\n description:\n \"A vertical file tab rail of syntax-highlighted code snippets, one tab per file with an optional language and caption.\",\n});\n"]}
@@ -1,5 +1,22 @@
1
1
  import type { BlockReadProps, BlockEditProps } from "../types.js";
2
2
  import { type DiagramData } from "./diagram.config.js";
3
+ /**
4
+ * Enlarge overlay for a rendered diagram. Mirrors the image lightbox contract
5
+ * used by the composer's `ImagePreviewLightbox` (PromptComposer.tsx) so the
6
+ * expand affordance feels identical to viewing an image full-size: a fixed
7
+ * `bg-black/80` backdrop, Escape to close, click-the-backdrop to close, and a
8
+ * top-right close button. Unlike the image variant this renders arbitrary
9
+ * children (the diagram body re-rendered larger) rather than an `<img>`, since a
10
+ * diagram is live HTML/SVG/node-graph markup, not an image URL.
11
+ *
12
+ * Exported so the separate Mermaid block (`MermaidBlock.tsx`, which renders its
13
+ * diagram to an SVG through a different runtime) can reuse the exact same
14
+ * lightbox contract — one expand affordance shared across both diagram types.
15
+ */
16
+ export declare function DiagramLightbox({ children, onClose, }: {
17
+ children: React.ReactNode;
18
+ onClose: () => void;
19
+ }): import("react/jsx-runtime").JSX.Element;
3
20
  /** Read-only renderer: the diagram body wrapped in the standard titled block. */
4
21
  export declare function DiagramRead({ data, blockId, title, summary, ctx, }: BlockReadProps<DiagramData>): import("react/jsx-runtime").JSX.Element;
5
22
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"diagram.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/diagram.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EAEf,MAAM,aAAa,CAAC;AAQrB,OAAO,EAGL,KAAK,WAAW,EAGjB,MAAM,qBAAqB,CAAC;AAkX7B,iFAAiF;AACjF,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,OAAO,EACP,KAAK,EACL,OAAO,EACP,GAAG,GACJ,EAAE,cAAc,CAAC,WAAW,CAAC,2CAQ7B;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,KAAK,EACL,OAAO,EACP,GAAG,GACJ,EAAE,cAAc,CAAC,WAAW,CAAC,2CAkL7B;AAED,kFAAkF;AAClF,eAAO,MAAM,YAAY,8CAgBvB,CAAC"}
1
+ {"version":3,"file":"diagram.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/diagram.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EAEf,MAAM,aAAa,CAAC;AAQrB,OAAO,EAGL,KAAK,WAAW,EAGjB,MAAM,qBAAqB,CAAC;AAoX7B;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,OAAO,GACR,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,2CAsCA;AA2CD,iFAAiF;AACjF,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,OAAO,EACP,KAAK,EACL,OAAO,EACP,GAAG,GACJ,EAAE,cAAc,CAAC,WAAW,CAAC,2CAQ7B;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,KAAK,EACL,OAAO,EACP,GAAG,GACJ,EAAE,cAAc,CAAC,WAAW,CAAC,2CAkL7B;AAED,kFAAkF;AAClF,eAAO,MAAM,YAAY,8CAgBvB,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useId, useMemo, useRef, useState } from "react";
3
+ import { IconArrowsMaximize, IconX } from "@tabler/icons-react";
3
4
  import { cn } from "../../utils.js";
4
5
  import { defineBlock } from "../types.js";
5
6
  import { AiEditableFieldLabel } from "../AiEditableField.js";
@@ -147,7 +148,9 @@ function SequenceDiagram({ data, compact, }) {
147
148
  /**
148
149
  * The diagram body. Routes to the preferred HTML/SVG path (when `data.html` is
149
150
  * set) and otherwise to a legacy node-graph path (positioned canvas when nodes
150
- * carry x/y, else an ordered sequence).
151
+ * carry x/y, else an ordered sequence). Used both inline and, scaled up, inside
152
+ * the expand lightbox — so every variant (html/css, positioned, sequence)
153
+ * enlarges through the same code path.
151
154
  */
152
155
  function DiagramBody({ data, ctx, compact, }) {
153
156
  const markerId = useId().replace(/:/g, "");
@@ -160,11 +163,53 @@ function DiagramBody({ data, ctx, compact, }) {
160
163
  return _jsx(SequenceDiagram, { data: data, compact: compact });
161
164
  }
162
165
  /* -------------------------------------------------------------------------- */
166
+ /* Expand / lightbox */
167
+ /* -------------------------------------------------------------------------- */
168
+ /**
169
+ * Enlarge overlay for a rendered diagram. Mirrors the image lightbox contract
170
+ * used by the composer's `ImagePreviewLightbox` (PromptComposer.tsx) so the
171
+ * expand affordance feels identical to viewing an image full-size: a fixed
172
+ * `bg-black/80` backdrop, Escape to close, click-the-backdrop to close, and a
173
+ * top-right close button. Unlike the image variant this renders arbitrary
174
+ * children (the diagram body re-rendered larger) rather than an `<img>`, since a
175
+ * diagram is live HTML/SVG/node-graph markup, not an image URL.
176
+ *
177
+ * Exported so the separate Mermaid block (`MermaidBlock.tsx`, which renders its
178
+ * diagram to an SVG through a different runtime) can reuse the exact same
179
+ * lightbox contract — one expand affordance shared across both diagram types.
180
+ */
181
+ export function DiagramLightbox({ children, onClose, }) {
182
+ useEffect(() => {
183
+ const handler = (e) => {
184
+ if (e.key === "Escape")
185
+ onClose();
186
+ };
187
+ document.addEventListener("keydown", handler);
188
+ document.body.style.overflow = "hidden";
189
+ return () => {
190
+ document.removeEventListener("keydown", handler);
191
+ document.body.style.overflow = "";
192
+ };
193
+ }, [onClose]);
194
+ return (_jsxs("div", { role: "dialog", "aria-modal": "true", "aria-label": "Diagram preview", onClick: onClose, "data-plan-interactive": true, className: "fixed inset-0 z-[300] flex items-center justify-center overflow-auto bg-black/80 p-6 cursor-zoom-out", children: [_jsx("div", { onClick: (e) => e.stopPropagation(), className: "max-h-full w-full max-w-5xl cursor-default overflow-auto rounded-md bg-background p-6 shadow-2xl", children: children }), _jsx("button", { type: "button", onClick: onClose, "aria-label": "Close preview", className: "absolute right-4 top-4 flex h-8 w-8 cursor-pointer items-center justify-center rounded-full border border-white/30 bg-black/40 text-white hover:bg-black/60", children: _jsx(IconX, { className: "h-4 w-4" }) })] }));
195
+ }
196
+ /**
197
+ * The diagram body plus a hover-revealed top-right "expand" button (like the
198
+ * image attachment zoom). Opening the button re-renders the exact same
199
+ * `DiagramBody` inside `DiagramLightbox` at a larger size, so html/css and
200
+ * mermaid/legacy node-graph diagrams alike enlarge through one path. The inline
201
+ * (non-expanded) render is otherwise unchanged.
202
+ */
203
+ function ExpandableDiagramBody({ data, ctx, }) {
204
+ const [expanded, setExpanded] = useState(false);
205
+ return (_jsxs("div", { className: "group/diagram relative", children: [_jsx(DiagramBody, { data: data, ctx: ctx }), _jsx("button", { type: "button", "data-plan-interactive": true, onClick: () => setExpanded(true), "aria-label": "Expand diagram", title: "Expand diagram", className: "an-diagram-expand-trigger absolute right-2 top-2 z-10 flex size-7 items-center justify-center rounded-md border border-border/60 bg-background/90 text-muted-foreground opacity-0 shadow-sm backdrop-blur transition-[color,opacity] hover:text-foreground focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring group-hover/diagram:opacity-100", children: _jsx(IconArrowsMaximize, { className: "size-4" }) }), expanded ? (_jsx(DiagramLightbox, { onClose: () => setExpanded(false), children: _jsx(DiagramBody, { data: data, ctx: ctx }) })) : null] }));
206
+ }
207
+ /* -------------------------------------------------------------------------- */
163
208
  /* Read + Edit */
164
209
  /* -------------------------------------------------------------------------- */
165
210
  /** Read-only renderer: the diagram body wrapped in the standard titled block. */
166
211
  export function DiagramRead({ data, blockId, title, summary, ctx, }) {
167
- return (_jsxs("section", { className: "an-block plan-block", "data-block-id": blockId, children: [title && _jsx("div", { className: "an-block-label plan-block-label", children: title }), _jsx(DiagramBody, { data: data, ctx: ctx }), summary && _jsx("p", { className: "mt-5 text-muted-foreground", children: summary })] }));
212
+ return (_jsxs("section", { className: "an-block plan-block", "data-block-id": blockId, children: [title && _jsx("div", { className: "an-block-label plan-block-label", children: title }), _jsx(ExpandableDiagramBody, { data: data, ctx: ctx }), summary && _jsx("p", { className: "mt-5 text-muted-foreground", children: summary })] }));
168
213
  }
169
214
  /**
170
215
  * Edit form (panel surface). The block can be an HTML/SVG fragment or a legacy
@@ -1 +1 @@
1
- {"version":3,"file":"diagram.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/diagram.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport { cn } from \"../../utils.js\";\nimport { defineBlock } from \"../types.js\";\nimport type {\n BlockReadProps,\n BlockEditProps,\n BlockRenderContext,\n} from \"../types.js\";\nimport { AiEditableFieldLabel } from \"../AiEditableField.js\";\nimport { RoughOverlay, useIsDark, useWireframeStyle } from \"./wireframe-kit.js\";\nimport {\n sanitizeDiagramHtml,\n sanitizeWireframeCss,\n scopeDesignCss,\n} from \"./sanitize-html.js\";\nimport {\n diagramMdx,\n diagramSchema,\n type DiagramData,\n type DiagramEdge,\n type DiagramNode,\n} from \"./diagram.config.js\";\n\n/**\n * Read + Edit renderers for the shared `diagram` block — a flexible inline\n * architecture/code diagram. The preferred authoring path is a scoped, inert\n * HTML/SVG fragment that leans on `.diagram-*` primitives and `--wf-*` tokens;\n * a legacy positional / sequence node-graph path is kept for older/simple plans.\n * Lives in core so any app can register it (it originated in the plan template).\n *\n * DECOUPLING from the plan original (mirrors the sibling `wireframe.tsx` port):\n * - Theme: `useIsDark()` reads `document.documentElement.classList` instead of\n * `next-themes`; `useWireframeStyle()` reads the viewer's sketchy/clean\n * preference from the shared `plan-wireframe-style` localStorage key — both\n * from `./wireframe-kit.js`, so core stays plan-free and shadcn-free.\n * - HTML sanitize: the HTML/SVG fragment + CSS run through the app-injected\n * `ctx.sanitizeHtml` at the render point (defense-in-depth against stored\n * XSS). Without a sanitizer wired, the HTML path emits nothing — core never\n * injects unsanitized author HTML. The React-free `diagramSchema` already\n * rejects active markup before storage.\n * - The rough.js sketch overlay reuses the kit's shared `RoughOverlay`, scoped\n * with the diagram selector and `drawFrame={false}` (the same call the plan\n * `HtmlDiagram` made). The `.plan-diagram-frame` / `.diagram-*` / `data-rough`\n * class contract is preserved exactly so the theme-token CSS in core's\n * `blocks.css` styles it in any app.\n *\n * The section carries the app-neutral `an-block` class plus the legacy\n * `plan-block` class so plan renders byte-identically while any other app gets\n * the theme-token treatment.\n */\n\n/* -------------------------------------------------------------------------- */\n/* HTML/SVG diagram path */\n/* -------------------------------------------------------------------------- */\n\n/** The rough-overlay selector for diagram bordered boxes (mirrors the plan). */\nconst DIAGRAM_ROUGH_SELECTOR =\n \"[data-rough],.diagram-panel,.diagram-node,.diagram-box,.diagram-pill,.diagram-card,[class*='card'],[class*='box'],[class*='panel'],[class*='pill'],[class*='chip'],[class*='badge'],hr\";\n\nfunction HtmlDiagram({\n data,\n ctx,\n compact,\n}: {\n data: DiagramData;\n ctx: BlockRenderContext;\n compact?: boolean;\n}) {\n const ref = useRef<HTMLDivElement>(null);\n const isDark = useIsDark();\n const style = useWireframeStyle();\n const scopeId = useId().replace(/[^a-zA-Z0-9_-]/g, \"\");\n // Sanitize author HTML/CSS at the render point (defense-in-depth against\n // stored XSS). Self-contained in core via the shared block sanitizer (DOM-based\n // in the browser, regex fallback on the server) so diagrams render in any app\n // without the host wiring a sanitizer hook.\n const safeHtml = useMemo(() => sanitizeDiagramHtml(data.html), [data.html]);\n const scopedCss = useMemo(() => {\n const safeCss = sanitizeWireframeCss(data.css);\n // Scope every author selector under this diagram instance so global\n // selectors (body, *, .app-shell, :root) can't escape and restyle the page.\n return safeCss\n ? scopeDesignCss(safeCss, `[data-plan-diagram-scope=\"${scopeId}\"]`)\n : \"\";\n }, [data.css, scopeId]);\n\n return (\n <div\n ref={ref}\n className={cn(\"plan-diagram-shell\", compact && \"plan-diagram-compact\")}\n >\n <div\n className=\"plan-diagram-frame\"\n data-theme={isDark ? \"dark\" : \"light\"}\n data-style={style}\n data-plan-diagram-scope={scopeId}\n >\n {scopedCss && <style>{scopedCss}</style>}\n <div\n className=\"plan-diagram-frame-content\"\n dangerouslySetInnerHTML={{ __html: safeHtml }}\n />\n </div>\n <RoughOverlay\n scopeRef={ref}\n enabled={style === \"sketchy\"}\n drawFrame={false}\n selector={DIAGRAM_ROUGH_SELECTOR}\n />\n {data.caption && !compact && (\n <p className=\"mt-3 text-sm leading-6 text-muted-foreground\">\n {data.caption}\n </p>\n )}\n </div>\n );\n}\n\n/* -------------------------------------------------------------------------- */\n/* Legacy node-graph paths */\n/* -------------------------------------------------------------------------- */\n\nfunction clampDiagramPercent(value: number) {\n if (!Number.isFinite(value)) return 50;\n return Math.max(4, Math.min(96, value));\n}\n\nfunction hasPositionedDiagramNodes(data: DiagramData): boolean {\n return (data.nodes ?? []).some(\n (node) => typeof node.x === \"number\" && typeof node.y === \"number\",\n );\n}\n\nfunction orderDiagramNodes(\n nodes: DiagramNode[],\n edges: DiagramEdge[],\n): DiagramNode[] {\n if (nodes.length === 0) return [];\n const byId = new Map(nodes.map((node) => [node.id, node]));\n const indegree = new Map(nodes.map((node) => [node.id, 0]));\n for (const edge of edges) {\n if (byId.has(edge.from) && byId.has(edge.to)) {\n indegree.set(edge.to, (indegree.get(edge.to) ?? 0) + 1);\n }\n }\n const start = nodes.find((node) => (indegree.get(node.id) ?? 0) === 0);\n if (!start) return nodes;\n const ordered: DiagramNode[] = [];\n const seen = new Set<string>();\n let current: DiagramNode | undefined = start;\n while (current && !seen.has(current.id)) {\n const node: DiagramNode = current;\n ordered.push(node);\n seen.add(node.id);\n const next = edges.find((edge) => edge.from === node.id);\n current = next ? byId.get(next.to) : undefined;\n }\n for (const node of nodes) if (!seen.has(node.id)) ordered.push(node);\n return ordered;\n}\n\nfunction PositionedDiagram({\n data,\n compact,\n markerId,\n}: {\n data: DiagramData;\n compact?: boolean;\n markerId: string;\n}) {\n const nodes = (data.nodes ?? []).map((node) => ({\n ...node,\n x: clampDiagramPercent(node.x ?? 50),\n y: clampDiagramPercent(node.y ?? 50),\n }));\n const edges = data.edges ?? [];\n const nodeById = new Map(nodes.map((node) => [node.id, node]));\n const arrowId = `${markerId}-diagram-arrow`;\n const nodeWidth = compact ? 150 : 190;\n const canvasHeight = compact ? 280 : 430;\n\n return (\n <div className=\"plan-sketch rounded-[16px] border border-border bg-muted p-5\">\n <div\n className=\"relative overflow-hidden rounded-xl border border-border bg-background\"\n style={{ minHeight: canvasHeight }}\n >\n <svg\n className=\"pointer-events-none absolute inset-0 z-0 h-full w-full\"\n viewBox=\"0 0 100 100\"\n preserveAspectRatio=\"none\"\n aria-hidden=\"true\"\n >\n <defs>\n <marker\n id={arrowId}\n viewBox=\"0 0 10 10\"\n refX=\"8\"\n refY=\"5\"\n markerWidth=\"5\"\n markerHeight=\"5\"\n orient=\"auto-start-reverse\"\n >\n <path\n d=\"M 0 0 L 10 5 L 0 10 z\"\n className=\"fill-muted-foreground\"\n />\n </marker>\n </defs>\n {edges.map((edge, index) => {\n const from = nodeById.get(edge.from);\n const to = nodeById.get(edge.to);\n if (!from || !to) return null;\n return (\n <line\n key={`${edge.from}-${edge.to}-${index}`}\n x1={from.x}\n y1={from.y}\n x2={to.x}\n y2={to.y}\n markerEnd={`url(#${arrowId})`}\n vectorEffect=\"non-scaling-stroke\"\n className=\"stroke-border\"\n strokeWidth={2}\n strokeDasharray={edge.label ? \"0\" : \"6 5\"}\n />\n );\n })}\n </svg>\n\n {!compact &&\n edges.map((edge, index) => {\n const from = nodeById.get(edge.from);\n const to = nodeById.get(edge.to);\n if (!edge.label || !from || !to) return null;\n return (\n <span\n key={`${edge.from}-${edge.to}-${index}-label`}\n className=\"absolute z-10 max-w-[130px] -translate-x-1/2 -translate-y-1/2 rounded-full border border-border bg-background px-2 py-0.5 text-center text-[11px] font-semibold text-muted-foreground shadow-sm\"\n style={{\n left: `${(from.x + to.x) / 2}%`,\n top: `${(from.y + to.y) / 2}%`,\n }}\n >\n {edge.label}\n </span>\n );\n })}\n\n {nodes.map((node, index) => (\n <article\n key={node.id}\n className=\"absolute z-20 -translate-x-1/2 -translate-y-1/2 rounded-xl border-2 border-border bg-background p-3 text-foreground shadow-sm\"\n style={{\n left: `${node.x}%`,\n top: `${node.y}%`,\n width: nodeWidth,\n }}\n >\n <p className=\"text-[11px] font-semibold uppercase tracking-[0.12em] text-muted-foreground\">\n {index + 1}\n </p>\n <h3 className=\"mt-2 text-base font-semibold leading-tight\">\n {node.label}\n </h3>\n {node.detail && !compact && (\n <p className=\"mt-2 text-xs leading-5 text-muted-foreground\">\n {node.detail}\n </p>\n )}\n </article>\n ))}\n </div>\n {data.notes && data.notes.length > 0 && !compact && (\n <div className=\"mt-4 grid gap-2 border-t border-border pt-4 text-sm text-muted-foreground md:grid-cols-2\">\n {data.notes.map((note) => (\n <p key={note.id}>{note.text}</p>\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction SequenceDiagram({\n data,\n compact,\n}: {\n data: DiagramData;\n compact?: boolean;\n}) {\n const edges = data.edges ?? [];\n const nodes = orderDiagramNodes(data.nodes ?? [], edges);\n if (nodes.length === 0) {\n return (\n <div className=\"rounded-[12px] border border-border bg-muted p-4 text-sm text-muted-foreground\">\n Diagram content is empty.\n </div>\n );\n }\n return (\n <div className=\"plan-sketch rounded-[16px] border border-border bg-muted p-5\">\n <div\n className={cn(\n \"flex gap-3 overflow-x-auto pb-2\",\n compact ? \"items-center\" : \"items-stretch\",\n )}\n >\n {nodes.map((node, index) => {\n const next = nodes[index + 1];\n const edge = next\n ? edges.find(\n (candidate) =>\n candidate.from === node.id && candidate.to === next.id,\n )\n : undefined;\n return (\n <div key={node.id} className=\"flex min-w-max items-center gap-3\">\n <article\n className={cn(\n \"w-[180px] rounded-xl border-2 border-border bg-background p-3 text-foreground\",\n compact && \"w-[150px]\",\n )}\n >\n <p className=\"text-[11px] font-semibold uppercase tracking-[0.12em] text-muted-foreground\">\n {index + 1}\n </p>\n <h3 className=\"mt-2 text-base font-semibold leading-tight\">\n {node.label}\n </h3>\n {node.detail && !compact && (\n <p className=\"mt-2 text-xs leading-5 text-muted-foreground\">\n {node.detail}\n </p>\n )}\n </article>\n {next && (\n <div className=\"grid min-w-[72px] justify-items-center gap-1 text-muted-foreground\">\n {edge?.label && (\n <span className=\"max-w-[96px] truncate rounded-full border border-border px-2 py-0.5 text-[11px] font-semibold\">\n {edge.label}\n </span>\n )}\n <span className=\"h-0.5 w-full rounded-full border-t-2 border-dashed border-border\" />\n </div>\n )}\n </div>\n );\n })}\n </div>\n {data.notes && data.notes.length > 0 && !compact && (\n <div className=\"mt-4 grid gap-2 border-t border-border pt-4 text-sm text-muted-foreground md:grid-cols-2\">\n {data.notes.map((note) => (\n <p key={note.id}>{note.text}</p>\n ))}\n </div>\n )}\n </div>\n );\n}\n\n/**\n * The diagram body. Routes to the preferred HTML/SVG path (when `data.html` is\n * set) and otherwise to a legacy node-graph path (positioned canvas when nodes\n * carry x/y, else an ordered sequence).\n */\nfunction DiagramBody({\n data,\n ctx,\n compact,\n}: {\n data: DiagramData;\n ctx: BlockRenderContext;\n compact?: boolean;\n}) {\n const markerId = useId().replace(/:/g, \"\");\n if (data.html?.trim()) {\n return <HtmlDiagram data={data} ctx={ctx} compact={compact} />;\n }\n if (hasPositionedDiagramNodes(data)) {\n return (\n <PositionedDiagram data={data} compact={compact} markerId={markerId} />\n );\n }\n return <SequenceDiagram data={data} compact={compact} />;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Read + Edit */\n/* -------------------------------------------------------------------------- */\n\n/** Read-only renderer: the diagram body wrapped in the standard titled block. */\nexport function DiagramRead({\n data,\n blockId,\n title,\n summary,\n ctx,\n}: BlockReadProps<DiagramData>) {\n return (\n <section className=\"an-block plan-block\" data-block-id={blockId}>\n {title && <div className=\"an-block-label plan-block-label\">{title}</div>}\n <DiagramBody data={data} ctx={ctx} />\n {summary && <p className=\"mt-5 text-muted-foreground\">{summary}</p>}\n </section>\n );\n}\n\n/**\n * Edit form (panel surface). The block can be an HTML/SVG fragment or a legacy\n * node/edge/note graph, so this exposes html/css/caption plus a collapsible\n * legacy node-graph JSON editor, each with an AI-edit affordance via\n * `ctx.renderAiFieldAction` (through `AiEditableFieldLabel`). `editSurface:\n * \"panel\"` means the registry renders the `Read` view with a corner edit button\n * that opens this form in the app-provided popover.\n */\nexport function DiagramEdit({\n data,\n onChange,\n editable,\n blockId,\n title,\n summary,\n ctx,\n}: BlockEditProps<DiagramData>) {\n const htmlId = useId();\n const cssId = useId();\n const captionId = useId();\n const legacyId = useId();\n const [html, setHtml] = useState(data.html ?? \"\");\n const [css, setCss] = useState(data.css ?? \"\");\n const [caption, setCaption] = useState(data.caption ?? \"\");\n const [legacyJson, setLegacyJson] = useState(() =>\n JSON.stringify(\n {\n nodes: data.nodes ?? [],\n edges: data.edges ?? [],\n notes: data.notes ?? [],\n },\n null,\n 2,\n ),\n );\n\n useEffect(() => {\n setHtml(data.html ?? \"\");\n setCss(data.css ?? \"\");\n setCaption(data.caption ?? \"\");\n setLegacyJson(\n JSON.stringify(\n {\n nodes: data.nodes ?? [],\n edges: data.edges ?? [],\n notes: data.notes ?? [],\n },\n null,\n 2,\n ),\n );\n }, [data]);\n\n const saveHtmlDiagram = () => {\n onChange({\n html: html.trim() || undefined,\n css: css.trim() || undefined,\n caption: caption.trim() || undefined,\n nodes: data.nodes,\n edges: data.edges,\n notes: data.notes,\n });\n };\n\n const saveLegacyDiagram = () => {\n const parsed = JSON.parse(legacyJson) as Pick<\n DiagramData,\n \"nodes\" | \"edges\" | \"notes\"\n >;\n onChange({\n ...data,\n nodes: parsed.nodes ?? [],\n edges: parsed.edges ?? [],\n notes: parsed.notes ?? [],\n });\n };\n\n const fieldAction = (\n field: \"HTML / SVG fragment\" | \"CSS\" | \"caption\" | \"legacy node graph JSON\",\n value: string,\n ) => ({\n blockId,\n blockType: \"diagram\",\n blockTitle: title,\n blockSummary: summary,\n fieldValue: value,\n draftScope: `block:diagram:${blockId}:${field.toLowerCase().replace(/[^a-z0-9]+/g, \"-\")}`,\n disabled: !editable,\n instructions:\n \"Update the plan with update-visual-plan using a targeted update-block content patch for this diagram block id. Preserve unrelated diagram fields unless the requested edit requires changing them. Keep diagram HTML/CSS on renderer-owned .diagram-* primitives and --wf-* tokens; do not introduce custom font-family or hard-coded hex/rgb/hsl colors.\",\n companionFields: [\n {\n label: \"HTML / SVG fragment\",\n value: html.trim() || \"(empty)\",\n language: \"html\",\n },\n { label: \"CSS\", value: css.trim() || \"(empty)\", language: \"css\" },\n {\n label: \"caption\",\n value: caption.trim() || \"(empty)\",\n language: \"text\",\n },\n ],\n });\n\n return (\n <div className=\"grid gap-4\" data-plan-interactive>\n <button\n type=\"button\"\n className=\"inline-flex h-8 w-fit items-center justify-center rounded-md bg-primary px-3 text-xs font-medium text-primary-foreground disabled:opacity-50\"\n disabled={!editable}\n onClick={saveHtmlDiagram}\n >\n Save diagram\n </button>\n <div className=\"group/field grid gap-1.5\">\n <AiEditableFieldLabel\n htmlFor={htmlId}\n label=\"HTML / SVG fragment\"\n ctx={ctx}\n action={fieldAction(\"HTML / SVG fragment\", html)}\n />\n <textarea\n id={htmlId}\n className=\"min-h-48 w-full rounded-md border border-input bg-background px-3 py-2 font-mono text-xs leading-5 text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n value={html}\n disabled={!editable}\n onChange={(event) => setHtml(event.target.value)}\n placeholder=\"<div class='diagram'>...</div>\"\n />\n </div>\n <div className=\"group/field grid gap-1.5\">\n <AiEditableFieldLabel\n htmlFor={cssId}\n label=\"CSS\"\n ctx={ctx}\n action={fieldAction(\"CSS\", css)}\n />\n <textarea\n id={cssId}\n className=\"min-h-32 w-full rounded-md border border-input bg-background px-3 py-2 font-mono text-xs leading-5 text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n value={css}\n disabled={!editable}\n onChange={(event) => setCss(event.target.value)}\n placeholder=\".diagram { display: grid; }\"\n />\n </div>\n <div className=\"group/field grid gap-1.5\">\n <AiEditableFieldLabel\n htmlFor={captionId}\n label=\"Caption\"\n ctx={ctx}\n action={fieldAction(\"caption\", caption)}\n />\n <input\n id={captionId}\n className=\"h-9 w-full rounded-md border border-input bg-background px-3 text-sm text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n value={caption}\n disabled={!editable}\n onChange={(event) => setCaption(event.target.value)}\n />\n </div>\n {!data.html && (\n <details className=\"rounded-md border border-border p-3\">\n <summary className=\"cursor-pointer text-xs font-semibold text-muted-foreground\">\n Legacy node graph data\n </summary>\n <div className=\"group/field mt-3 grid gap-1.5\">\n <AiEditableFieldLabel\n htmlFor={legacyId}\n label=\"JSON\"\n ctx={ctx}\n action={fieldAction(\"legacy node graph JSON\", legacyJson)}\n />\n <textarea\n id={legacyId}\n className=\"min-h-44 w-full rounded-md border border-input bg-background px-3 py-2 font-mono text-xs leading-5 text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n value={legacyJson}\n disabled={!editable}\n onChange={(event) => setLegacyJson(event.target.value)}\n />\n </div>\n <button\n type=\"button\"\n className=\"mt-3 inline-flex h-8 items-center justify-center rounded-md border border-input px-3 text-xs font-medium text-foreground disabled:opacity-50\"\n disabled={!editable}\n onClick={saveLegacyDiagram}\n >\n Save graph data\n </button>\n </details>\n )}\n </div>\n );\n}\n\n/** Full client spec for the shared `diagram` block (schema + MDX + Read/Edit). */\nexport const diagramBlock = defineBlock<DiagramData>({\n type: \"diagram\",\n schema: diagramSchema,\n mdx: diagramMdx,\n Read: DiagramRead,\n Edit: DiagramEdit,\n placement: [\"block\"],\n // Config-driven: the rendered diagram differs from its raw html/css source, so\n // edit from a corner button + panel rather than inline.\n editSurface: \"panel\",\n label: \"Diagram\",\n description:\n \"A flexible inline architecture/code diagram. Prefer html/css with SVG or semantic HTML for polished two-dimensional layouts; use .diagram-* primitives and --wf-* tokens for theme/sketch compatibility. Legacy nodes/edges are only for simple previews.\",\n // Seed the legacy fallback shape so a fresh block validates while agents can\n // replace it with html/css when layout quality matters.\n empty: () => ({ nodes: [{ id: \"n1\", label: \"Module\" }], edges: [] }),\n});\n"]}
1
+ {"version":3,"file":"diagram.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/diagram.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport { IconArrowsMaximize, IconX } from \"@tabler/icons-react\";\nimport { cn } from \"../../utils.js\";\nimport { defineBlock } from \"../types.js\";\nimport type {\n BlockReadProps,\n BlockEditProps,\n BlockRenderContext,\n} from \"../types.js\";\nimport { AiEditableFieldLabel } from \"../AiEditableField.js\";\nimport { RoughOverlay, useIsDark, useWireframeStyle } from \"./wireframe-kit.js\";\nimport {\n sanitizeDiagramHtml,\n sanitizeWireframeCss,\n scopeDesignCss,\n} from \"./sanitize-html.js\";\nimport {\n diagramMdx,\n diagramSchema,\n type DiagramData,\n type DiagramEdge,\n type DiagramNode,\n} from \"./diagram.config.js\";\n\n/**\n * Read + Edit renderers for the shared `diagram` block — a flexible inline\n * architecture/code diagram. The preferred authoring path is a scoped, inert\n * HTML/SVG fragment that leans on `.diagram-*` primitives and `--wf-*` tokens;\n * a legacy positional / sequence node-graph path is kept for older/simple plans.\n * Lives in core so any app can register it (it originated in the plan template).\n *\n * DECOUPLING from the plan original (mirrors the sibling `wireframe.tsx` port):\n * - Theme: `useIsDark()` reads `document.documentElement.classList` instead of\n * `next-themes`; `useWireframeStyle()` reads the viewer's sketchy/clean\n * preference from the shared `plan-wireframe-style` localStorage key — both\n * from `./wireframe-kit.js`, so core stays plan-free and shadcn-free.\n * - HTML sanitize: the HTML/SVG fragment + CSS run through the app-injected\n * `ctx.sanitizeHtml` at the render point (defense-in-depth against stored\n * XSS). Without a sanitizer wired, the HTML path emits nothing — core never\n * injects unsanitized author HTML. The React-free `diagramSchema` already\n * rejects active markup before storage.\n * - The rough.js sketch overlay reuses the kit's shared `RoughOverlay`, scoped\n * with the diagram selector and `drawFrame={false}` (the same call the plan\n * `HtmlDiagram` made). The `.plan-diagram-frame` / `.diagram-*` / `data-rough`\n * class contract is preserved exactly so the theme-token CSS in core's\n * `blocks.css` styles it in any app.\n *\n * The section carries the app-neutral `an-block` class plus the legacy\n * `plan-block` class so plan renders byte-identically while any other app gets\n * the theme-token treatment.\n */\n\n/* -------------------------------------------------------------------------- */\n/* HTML/SVG diagram path */\n/* -------------------------------------------------------------------------- */\n\n/** The rough-overlay selector for diagram bordered boxes (mirrors the plan). */\nconst DIAGRAM_ROUGH_SELECTOR =\n \"[data-rough],.diagram-panel,.diagram-node,.diagram-box,.diagram-pill,.diagram-card,[class*='card'],[class*='box'],[class*='panel'],[class*='pill'],[class*='chip'],[class*='badge'],hr\";\n\nfunction HtmlDiagram({\n data,\n ctx,\n compact,\n}: {\n data: DiagramData;\n ctx: BlockRenderContext;\n compact?: boolean;\n}) {\n const ref = useRef<HTMLDivElement>(null);\n const isDark = useIsDark();\n const style = useWireframeStyle();\n const scopeId = useId().replace(/[^a-zA-Z0-9_-]/g, \"\");\n // Sanitize author HTML/CSS at the render point (defense-in-depth against\n // stored XSS). Self-contained in core via the shared block sanitizer (DOM-based\n // in the browser, regex fallback on the server) so diagrams render in any app\n // without the host wiring a sanitizer hook.\n const safeHtml = useMemo(() => sanitizeDiagramHtml(data.html), [data.html]);\n const scopedCss = useMemo(() => {\n const safeCss = sanitizeWireframeCss(data.css);\n // Scope every author selector under this diagram instance so global\n // selectors (body, *, .app-shell, :root) can't escape and restyle the page.\n return safeCss\n ? scopeDesignCss(safeCss, `[data-plan-diagram-scope=\"${scopeId}\"]`)\n : \"\";\n }, [data.css, scopeId]);\n\n return (\n <div\n ref={ref}\n className={cn(\"plan-diagram-shell\", compact && \"plan-diagram-compact\")}\n >\n <div\n className=\"plan-diagram-frame\"\n data-theme={isDark ? \"dark\" : \"light\"}\n data-style={style}\n data-plan-diagram-scope={scopeId}\n >\n {scopedCss && <style>{scopedCss}</style>}\n <div\n className=\"plan-diagram-frame-content\"\n dangerouslySetInnerHTML={{ __html: safeHtml }}\n />\n </div>\n <RoughOverlay\n scopeRef={ref}\n enabled={style === \"sketchy\"}\n drawFrame={false}\n selector={DIAGRAM_ROUGH_SELECTOR}\n />\n {data.caption && !compact && (\n <p className=\"mt-3 text-sm leading-6 text-muted-foreground\">\n {data.caption}\n </p>\n )}\n </div>\n );\n}\n\n/* -------------------------------------------------------------------------- */\n/* Legacy node-graph paths */\n/* -------------------------------------------------------------------------- */\n\nfunction clampDiagramPercent(value: number) {\n if (!Number.isFinite(value)) return 50;\n return Math.max(4, Math.min(96, value));\n}\n\nfunction hasPositionedDiagramNodes(data: DiagramData): boolean {\n return (data.nodes ?? []).some(\n (node) => typeof node.x === \"number\" && typeof node.y === \"number\",\n );\n}\n\nfunction orderDiagramNodes(\n nodes: DiagramNode[],\n edges: DiagramEdge[],\n): DiagramNode[] {\n if (nodes.length === 0) return [];\n const byId = new Map(nodes.map((node) => [node.id, node]));\n const indegree = new Map(nodes.map((node) => [node.id, 0]));\n for (const edge of edges) {\n if (byId.has(edge.from) && byId.has(edge.to)) {\n indegree.set(edge.to, (indegree.get(edge.to) ?? 0) + 1);\n }\n }\n const start = nodes.find((node) => (indegree.get(node.id) ?? 0) === 0);\n if (!start) return nodes;\n const ordered: DiagramNode[] = [];\n const seen = new Set<string>();\n let current: DiagramNode | undefined = start;\n while (current && !seen.has(current.id)) {\n const node: DiagramNode = current;\n ordered.push(node);\n seen.add(node.id);\n const next = edges.find((edge) => edge.from === node.id);\n current = next ? byId.get(next.to) : undefined;\n }\n for (const node of nodes) if (!seen.has(node.id)) ordered.push(node);\n return ordered;\n}\n\nfunction PositionedDiagram({\n data,\n compact,\n markerId,\n}: {\n data: DiagramData;\n compact?: boolean;\n markerId: string;\n}) {\n const nodes = (data.nodes ?? []).map((node) => ({\n ...node,\n x: clampDiagramPercent(node.x ?? 50),\n y: clampDiagramPercent(node.y ?? 50),\n }));\n const edges = data.edges ?? [];\n const nodeById = new Map(nodes.map((node) => [node.id, node]));\n const arrowId = `${markerId}-diagram-arrow`;\n const nodeWidth = compact ? 150 : 190;\n const canvasHeight = compact ? 280 : 430;\n\n return (\n <div className=\"plan-sketch rounded-[16px] border border-border bg-muted p-5\">\n <div\n className=\"relative overflow-hidden rounded-xl border border-border bg-background\"\n style={{ minHeight: canvasHeight }}\n >\n <svg\n className=\"pointer-events-none absolute inset-0 z-0 h-full w-full\"\n viewBox=\"0 0 100 100\"\n preserveAspectRatio=\"none\"\n aria-hidden=\"true\"\n >\n <defs>\n <marker\n id={arrowId}\n viewBox=\"0 0 10 10\"\n refX=\"8\"\n refY=\"5\"\n markerWidth=\"5\"\n markerHeight=\"5\"\n orient=\"auto-start-reverse\"\n >\n <path\n d=\"M 0 0 L 10 5 L 0 10 z\"\n className=\"fill-muted-foreground\"\n />\n </marker>\n </defs>\n {edges.map((edge, index) => {\n const from = nodeById.get(edge.from);\n const to = nodeById.get(edge.to);\n if (!from || !to) return null;\n return (\n <line\n key={`${edge.from}-${edge.to}-${index}`}\n x1={from.x}\n y1={from.y}\n x2={to.x}\n y2={to.y}\n markerEnd={`url(#${arrowId})`}\n vectorEffect=\"non-scaling-stroke\"\n className=\"stroke-border\"\n strokeWidth={2}\n strokeDasharray={edge.label ? \"0\" : \"6 5\"}\n />\n );\n })}\n </svg>\n\n {!compact &&\n edges.map((edge, index) => {\n const from = nodeById.get(edge.from);\n const to = nodeById.get(edge.to);\n if (!edge.label || !from || !to) return null;\n return (\n <span\n key={`${edge.from}-${edge.to}-${index}-label`}\n className=\"absolute z-10 max-w-[130px] -translate-x-1/2 -translate-y-1/2 rounded-full border border-border bg-background px-2 py-0.5 text-center text-[11px] font-semibold text-muted-foreground shadow-sm\"\n style={{\n left: `${(from.x + to.x) / 2}%`,\n top: `${(from.y + to.y) / 2}%`,\n }}\n >\n {edge.label}\n </span>\n );\n })}\n\n {nodes.map((node, index) => (\n <article\n key={node.id}\n className=\"absolute z-20 -translate-x-1/2 -translate-y-1/2 rounded-xl border-2 border-border bg-background p-3 text-foreground shadow-sm\"\n style={{\n left: `${node.x}%`,\n top: `${node.y}%`,\n width: nodeWidth,\n }}\n >\n <p className=\"text-[11px] font-semibold uppercase tracking-[0.12em] text-muted-foreground\">\n {index + 1}\n </p>\n <h3 className=\"mt-2 text-base font-semibold leading-tight\">\n {node.label}\n </h3>\n {node.detail && !compact && (\n <p className=\"mt-2 text-xs leading-5 text-muted-foreground\">\n {node.detail}\n </p>\n )}\n </article>\n ))}\n </div>\n {data.notes && data.notes.length > 0 && !compact && (\n <div className=\"mt-4 grid gap-2 border-t border-border pt-4 text-sm text-muted-foreground md:grid-cols-2\">\n {data.notes.map((note) => (\n <p key={note.id}>{note.text}</p>\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction SequenceDiagram({\n data,\n compact,\n}: {\n data: DiagramData;\n compact?: boolean;\n}) {\n const edges = data.edges ?? [];\n const nodes = orderDiagramNodes(data.nodes ?? [], edges);\n if (nodes.length === 0) {\n return (\n <div className=\"rounded-[12px] border border-border bg-muted p-4 text-sm text-muted-foreground\">\n Diagram content is empty.\n </div>\n );\n }\n return (\n <div className=\"plan-sketch rounded-[16px] border border-border bg-muted p-5\">\n <div\n className={cn(\n \"flex gap-3 overflow-x-auto pb-2\",\n compact ? \"items-center\" : \"items-stretch\",\n )}\n >\n {nodes.map((node, index) => {\n const next = nodes[index + 1];\n const edge = next\n ? edges.find(\n (candidate) =>\n candidate.from === node.id && candidate.to === next.id,\n )\n : undefined;\n return (\n <div key={node.id} className=\"flex min-w-max items-center gap-3\">\n <article\n className={cn(\n \"w-[180px] rounded-xl border-2 border-border bg-background p-3 text-foreground\",\n compact && \"w-[150px]\",\n )}\n >\n <p className=\"text-[11px] font-semibold uppercase tracking-[0.12em] text-muted-foreground\">\n {index + 1}\n </p>\n <h3 className=\"mt-2 text-base font-semibold leading-tight\">\n {node.label}\n </h3>\n {node.detail && !compact && (\n <p className=\"mt-2 text-xs leading-5 text-muted-foreground\">\n {node.detail}\n </p>\n )}\n </article>\n {next && (\n <div className=\"grid min-w-[72px] justify-items-center gap-1 text-muted-foreground\">\n {edge?.label && (\n <span className=\"max-w-[96px] truncate rounded-full border border-border px-2 py-0.5 text-[11px] font-semibold\">\n {edge.label}\n </span>\n )}\n <span className=\"h-0.5 w-full rounded-full border-t-2 border-dashed border-border\" />\n </div>\n )}\n </div>\n );\n })}\n </div>\n {data.notes && data.notes.length > 0 && !compact && (\n <div className=\"mt-4 grid gap-2 border-t border-border pt-4 text-sm text-muted-foreground md:grid-cols-2\">\n {data.notes.map((note) => (\n <p key={note.id}>{note.text}</p>\n ))}\n </div>\n )}\n </div>\n );\n}\n\n/**\n * The diagram body. Routes to the preferred HTML/SVG path (when `data.html` is\n * set) and otherwise to a legacy node-graph path (positioned canvas when nodes\n * carry x/y, else an ordered sequence). Used both inline and, scaled up, inside\n * the expand lightbox — so every variant (html/css, positioned, sequence)\n * enlarges through the same code path.\n */\nfunction DiagramBody({\n data,\n ctx,\n compact,\n}: {\n data: DiagramData;\n ctx: BlockRenderContext;\n compact?: boolean;\n}) {\n const markerId = useId().replace(/:/g, \"\");\n if (data.html?.trim()) {\n return <HtmlDiagram data={data} ctx={ctx} compact={compact} />;\n }\n if (hasPositionedDiagramNodes(data)) {\n return (\n <PositionedDiagram data={data} compact={compact} markerId={markerId} />\n );\n }\n return <SequenceDiagram data={data} compact={compact} />;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Expand / lightbox */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Enlarge overlay for a rendered diagram. Mirrors the image lightbox contract\n * used by the composer's `ImagePreviewLightbox` (PromptComposer.tsx) so the\n * expand affordance feels identical to viewing an image full-size: a fixed\n * `bg-black/80` backdrop, Escape to close, click-the-backdrop to close, and a\n * top-right close button. Unlike the image variant this renders arbitrary\n * children (the diagram body re-rendered larger) rather than an `<img>`, since a\n * diagram is live HTML/SVG/node-graph markup, not an image URL.\n *\n * Exported so the separate Mermaid block (`MermaidBlock.tsx`, which renders its\n * diagram to an SVG through a different runtime) can reuse the exact same\n * lightbox contract — one expand affordance shared across both diagram types.\n */\nexport function DiagramLightbox({\n children,\n onClose,\n}: {\n children: React.ReactNode;\n onClose: () => void;\n}) {\n useEffect(() => {\n const handler = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") onClose();\n };\n document.addEventListener(\"keydown\", handler);\n document.body.style.overflow = \"hidden\";\n return () => {\n document.removeEventListener(\"keydown\", handler);\n document.body.style.overflow = \"\";\n };\n }, [onClose]);\n\n return (\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Diagram preview\"\n onClick={onClose}\n data-plan-interactive\n className=\"fixed inset-0 z-[300] flex items-center justify-center overflow-auto bg-black/80 p-6 cursor-zoom-out\"\n >\n <div\n onClick={(e) => e.stopPropagation()}\n className=\"max-h-full w-full max-w-5xl cursor-default overflow-auto rounded-md bg-background p-6 shadow-2xl\"\n >\n {children}\n </div>\n <button\n type=\"button\"\n onClick={onClose}\n aria-label=\"Close preview\"\n className=\"absolute right-4 top-4 flex h-8 w-8 cursor-pointer items-center justify-center rounded-full border border-white/30 bg-black/40 text-white hover:bg-black/60\"\n >\n <IconX className=\"h-4 w-4\" />\n </button>\n </div>\n );\n}\n\n/**\n * The diagram body plus a hover-revealed top-right \"expand\" button (like the\n * image attachment zoom). Opening the button re-renders the exact same\n * `DiagramBody` inside `DiagramLightbox` at a larger size, so html/css and\n * mermaid/legacy node-graph diagrams alike enlarge through one path. The inline\n * (non-expanded) render is otherwise unchanged.\n */\nfunction ExpandableDiagramBody({\n data,\n ctx,\n}: {\n data: DiagramData;\n ctx: BlockRenderContext;\n}) {\n const [expanded, setExpanded] = useState(false);\n return (\n <div className=\"group/diagram relative\">\n <DiagramBody data={data} ctx={ctx} />\n <button\n type=\"button\"\n data-plan-interactive\n onClick={() => setExpanded(true)}\n aria-label=\"Expand diagram\"\n title=\"Expand diagram\"\n className=\"an-diagram-expand-trigger absolute right-2 top-2 z-10 flex size-7 items-center justify-center rounded-md border border-border/60 bg-background/90 text-muted-foreground opacity-0 shadow-sm backdrop-blur transition-[color,opacity] hover:text-foreground focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring group-hover/diagram:opacity-100\"\n >\n <IconArrowsMaximize className=\"size-4\" />\n </button>\n {expanded ? (\n <DiagramLightbox onClose={() => setExpanded(false)}>\n <DiagramBody data={data} ctx={ctx} />\n </DiagramLightbox>\n ) : null}\n </div>\n );\n}\n\n/* -------------------------------------------------------------------------- */\n/* Read + Edit */\n/* -------------------------------------------------------------------------- */\n\n/** Read-only renderer: the diagram body wrapped in the standard titled block. */\nexport function DiagramRead({\n data,\n blockId,\n title,\n summary,\n ctx,\n}: BlockReadProps<DiagramData>) {\n return (\n <section className=\"an-block plan-block\" data-block-id={blockId}>\n {title && <div className=\"an-block-label plan-block-label\">{title}</div>}\n <ExpandableDiagramBody data={data} ctx={ctx} />\n {summary && <p className=\"mt-5 text-muted-foreground\">{summary}</p>}\n </section>\n );\n}\n\n/**\n * Edit form (panel surface). The block can be an HTML/SVG fragment or a legacy\n * node/edge/note graph, so this exposes html/css/caption plus a collapsible\n * legacy node-graph JSON editor, each with an AI-edit affordance via\n * `ctx.renderAiFieldAction` (through `AiEditableFieldLabel`). `editSurface:\n * \"panel\"` means the registry renders the `Read` view with a corner edit button\n * that opens this form in the app-provided popover.\n */\nexport function DiagramEdit({\n data,\n onChange,\n editable,\n blockId,\n title,\n summary,\n ctx,\n}: BlockEditProps<DiagramData>) {\n const htmlId = useId();\n const cssId = useId();\n const captionId = useId();\n const legacyId = useId();\n const [html, setHtml] = useState(data.html ?? \"\");\n const [css, setCss] = useState(data.css ?? \"\");\n const [caption, setCaption] = useState(data.caption ?? \"\");\n const [legacyJson, setLegacyJson] = useState(() =>\n JSON.stringify(\n {\n nodes: data.nodes ?? [],\n edges: data.edges ?? [],\n notes: data.notes ?? [],\n },\n null,\n 2,\n ),\n );\n\n useEffect(() => {\n setHtml(data.html ?? \"\");\n setCss(data.css ?? \"\");\n setCaption(data.caption ?? \"\");\n setLegacyJson(\n JSON.stringify(\n {\n nodes: data.nodes ?? [],\n edges: data.edges ?? [],\n notes: data.notes ?? [],\n },\n null,\n 2,\n ),\n );\n }, [data]);\n\n const saveHtmlDiagram = () => {\n onChange({\n html: html.trim() || undefined,\n css: css.trim() || undefined,\n caption: caption.trim() || undefined,\n nodes: data.nodes,\n edges: data.edges,\n notes: data.notes,\n });\n };\n\n const saveLegacyDiagram = () => {\n const parsed = JSON.parse(legacyJson) as Pick<\n DiagramData,\n \"nodes\" | \"edges\" | \"notes\"\n >;\n onChange({\n ...data,\n nodes: parsed.nodes ?? [],\n edges: parsed.edges ?? [],\n notes: parsed.notes ?? [],\n });\n };\n\n const fieldAction = (\n field: \"HTML / SVG fragment\" | \"CSS\" | \"caption\" | \"legacy node graph JSON\",\n value: string,\n ) => ({\n blockId,\n blockType: \"diagram\",\n blockTitle: title,\n blockSummary: summary,\n fieldValue: value,\n draftScope: `block:diagram:${blockId}:${field.toLowerCase().replace(/[^a-z0-9]+/g, \"-\")}`,\n disabled: !editable,\n instructions:\n \"Update the plan with update-visual-plan using a targeted update-block content patch for this diagram block id. Preserve unrelated diagram fields unless the requested edit requires changing them. Keep diagram HTML/CSS on renderer-owned .diagram-* primitives and --wf-* tokens; do not introduce custom font-family or hard-coded hex/rgb/hsl colors.\",\n companionFields: [\n {\n label: \"HTML / SVG fragment\",\n value: html.trim() || \"(empty)\",\n language: \"html\",\n },\n { label: \"CSS\", value: css.trim() || \"(empty)\", language: \"css\" },\n {\n label: \"caption\",\n value: caption.trim() || \"(empty)\",\n language: \"text\",\n },\n ],\n });\n\n return (\n <div className=\"grid gap-4\" data-plan-interactive>\n <button\n type=\"button\"\n className=\"inline-flex h-8 w-fit items-center justify-center rounded-md bg-primary px-3 text-xs font-medium text-primary-foreground disabled:opacity-50\"\n disabled={!editable}\n onClick={saveHtmlDiagram}\n >\n Save diagram\n </button>\n <div className=\"group/field grid gap-1.5\">\n <AiEditableFieldLabel\n htmlFor={htmlId}\n label=\"HTML / SVG fragment\"\n ctx={ctx}\n action={fieldAction(\"HTML / SVG fragment\", html)}\n />\n <textarea\n id={htmlId}\n className=\"min-h-48 w-full rounded-md border border-input bg-background px-3 py-2 font-mono text-xs leading-5 text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n value={html}\n disabled={!editable}\n onChange={(event) => setHtml(event.target.value)}\n placeholder=\"<div class='diagram'>...</div>\"\n />\n </div>\n <div className=\"group/field grid gap-1.5\">\n <AiEditableFieldLabel\n htmlFor={cssId}\n label=\"CSS\"\n ctx={ctx}\n action={fieldAction(\"CSS\", css)}\n />\n <textarea\n id={cssId}\n className=\"min-h-32 w-full rounded-md border border-input bg-background px-3 py-2 font-mono text-xs leading-5 text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n value={css}\n disabled={!editable}\n onChange={(event) => setCss(event.target.value)}\n placeholder=\".diagram { display: grid; }\"\n />\n </div>\n <div className=\"group/field grid gap-1.5\">\n <AiEditableFieldLabel\n htmlFor={captionId}\n label=\"Caption\"\n ctx={ctx}\n action={fieldAction(\"caption\", caption)}\n />\n <input\n id={captionId}\n className=\"h-9 w-full rounded-md border border-input bg-background px-3 text-sm text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n value={caption}\n disabled={!editable}\n onChange={(event) => setCaption(event.target.value)}\n />\n </div>\n {!data.html && (\n <details className=\"rounded-md border border-border p-3\">\n <summary className=\"cursor-pointer text-xs font-semibold text-muted-foreground\">\n Legacy node graph data\n </summary>\n <div className=\"group/field mt-3 grid gap-1.5\">\n <AiEditableFieldLabel\n htmlFor={legacyId}\n label=\"JSON\"\n ctx={ctx}\n action={fieldAction(\"legacy node graph JSON\", legacyJson)}\n />\n <textarea\n id={legacyId}\n className=\"min-h-44 w-full rounded-md border border-input bg-background px-3 py-2 font-mono text-xs leading-5 text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n value={legacyJson}\n disabled={!editable}\n onChange={(event) => setLegacyJson(event.target.value)}\n />\n </div>\n <button\n type=\"button\"\n className=\"mt-3 inline-flex h-8 items-center justify-center rounded-md border border-input px-3 text-xs font-medium text-foreground disabled:opacity-50\"\n disabled={!editable}\n onClick={saveLegacyDiagram}\n >\n Save graph data\n </button>\n </details>\n )}\n </div>\n );\n}\n\n/** Full client spec for the shared `diagram` block (schema + MDX + Read/Edit). */\nexport const diagramBlock = defineBlock<DiagramData>({\n type: \"diagram\",\n schema: diagramSchema,\n mdx: diagramMdx,\n Read: DiagramRead,\n Edit: DiagramEdit,\n placement: [\"block\"],\n // Config-driven: the rendered diagram differs from its raw html/css source, so\n // edit from a corner button + panel rather than inline.\n editSurface: \"panel\",\n label: \"Diagram\",\n description:\n \"A flexible inline architecture/code diagram. Prefer html/css with SVG or semantic HTML for polished two-dimensional layouts; use .diagram-* primitives and --wf-* tokens for theme/sketch compatibility. Legacy nodes/edges are only for simple previews.\",\n // Seed the legacy fallback shape so a fresh block validates while agents can\n // replace it with html/css when layout quality matters.\n empty: () => ({ nodes: [{ id: \"n1\", label: \"Module\" }], edges: [] }),\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"server-specs.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/server-specs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAkB,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AA4FpE;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,CAAC,GAAG,CAAC,EAsN/C,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,2BAA2B,GAAG,MAAM,CAC9C,MAAM,EACN,OAAO,CACL,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,aAAa,GAAG,kBAAkB,CAAC,CAC5E,CACF,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,aAAa,EACvB,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,2BAA2B,CAAA;CAAO,GACxD,IAAI,CAON"}
1
+ {"version":3,"file":"server-specs.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/server-specs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAkB,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAuFpE;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,CAAC,GAAG,CAAC,EA4M/C,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,2BAA2B,GAAG,MAAM,CAC9C,MAAM,EACN,OAAO,CACL,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,aAAa,GAAG,kBAAkB,CAAC,CAC5E,CACF,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,aAAa,EACvB,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,2BAA2B,CAAA;CAAO,GACxD,IAAI,CAON"}
@@ -11,7 +11,6 @@ import { htmlSchema, htmlMdx } from "./html.config.js";
11
11
  import { tabsSchema, tabsMdx } from "./tabs.config.js";
12
12
  import { columnsSchema, columnsMdx, } from "./columns.config.js";
13
13
  import { calloutSchema, calloutMdx, } from "./callout.config.js";
14
- import { decisionSchema, decisionMdx, } from "./decision.config.js";
15
14
  import { questionFormSchema, questionFormMdx, visualQuestionsSchema, visualQuestionsMdx, } from "./question-form.config.js";
16
15
  import { diagramSchema, diagramMdx, } from "./diagram.config.js";
17
16
  import { wireframeSchema, wireframeMdx, } from "./wireframe.config.js";
@@ -115,15 +114,6 @@ export const libraryBlockConfigs = [
115
114
  label: "Callout",
116
115
  description: "An emphasized note with a tone (info/decision/risk/warning/success) and a markdown body.",
117
116
  }),
118
- defineBlock({
119
- type: "decision",
120
- schema: decisionSchema,
121
- mdx: decisionMdx,
122
- Read: ServerReadStub,
123
- placement: ["block"],
124
- label: "Decision",
125
- description: "A decision prompt with editable option cards and an authored recommended choice.",
126
- }),
127
117
  defineBlock({
128
118
  type: "question-form",
129
119
  schema: questionFormSchema,