@agent-native/core 0.39.2 → 0.40.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.
- package/README.md +1 -1
- package/dist/action.js +12 -0
- package/dist/action.js.map +1 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +5 -1
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/skills.d.ts +4 -3
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +756 -694
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/blocks/AiEditableField.d.ts +8 -0
- package/dist/client/blocks/AiEditableField.d.ts.map +1 -0
- package/dist/client/blocks/AiEditableField.js +10 -0
- package/dist/client/blocks/AiEditableField.js.map +1 -0
- package/dist/client/blocks/BlockView.d.ts +3 -3
- package/dist/client/blocks/BlockView.d.ts.map +1 -1
- package/dist/client/blocks/BlockView.js +15 -3
- package/dist/client/blocks/BlockView.js.map +1 -1
- package/dist/client/blocks/SchemaBlockEditor.js +2 -2
- package/dist/client/blocks/SchemaBlockEditor.js.map +1 -1
- package/dist/client/blocks/index.d.ts +5 -2
- package/dist/client/blocks/index.d.ts.map +1 -1
- package/dist/client/blocks/index.js +6 -3
- package/dist/client/blocks/index.js.map +1 -1
- package/dist/client/blocks/library/ApiEndpointBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/ApiEndpointBlock.js +20 -6
- package/dist/client/blocks/library/ApiEndpointBlock.js.map +1 -1
- package/dist/client/blocks/library/DiffBlock.d.ts +29 -0
- package/dist/client/blocks/library/DiffBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/DiffBlock.js +190 -30
- package/dist/client/blocks/library/DiffBlock.js.map +1 -1
- package/dist/client/blocks/library/FileTreeBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/FileTreeBlock.js +46 -7
- package/dist/client/blocks/library/FileTreeBlock.js.map +1 -1
- package/dist/client/blocks/library/HighlightedCode.d.ts +10 -0
- package/dist/client/blocks/library/HighlightedCode.d.ts.map +1 -0
- package/dist/client/blocks/library/HighlightedCode.js +92 -0
- package/dist/client/blocks/library/HighlightedCode.js.map +1 -0
- package/dist/client/blocks/library/JsonExplorerBlock.d.ts +9 -4
- package/dist/client/blocks/library/JsonExplorerBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/JsonExplorerBlock.js +66 -30
- package/dist/client/blocks/library/JsonExplorerBlock.js.map +1 -1
- package/dist/client/blocks/library/MermaidBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/MermaidBlock.js +73 -44
- package/dist/client/blocks/library/MermaidBlock.js.map +1 -1
- package/dist/client/blocks/library/OpenApiSpecBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/OpenApiSpecBlock.js +3 -2
- package/dist/client/blocks/library/OpenApiSpecBlock.js.map +1 -1
- package/dist/client/blocks/library/checklist.d.ts.map +1 -1
- package/dist/client/blocks/library/checklist.js +1 -0
- package/dist/client/blocks/library/checklist.js.map +1 -1
- package/dist/client/blocks/library/code-tabs.d.ts.map +1 -1
- package/dist/client/blocks/library/code-tabs.js +183 -102
- package/dist/client/blocks/library/code-tabs.js.map +1 -1
- package/dist/client/blocks/library/columns.config.d.ts +60 -0
- package/dist/client/blocks/library/columns.config.d.ts.map +1 -0
- package/dist/client/blocks/library/columns.config.js +37 -0
- package/dist/client/blocks/library/columns.config.js.map +1 -0
- package/dist/client/blocks/library/columns.d.ts +25 -0
- package/dist/client/blocks/library/columns.d.ts.map +1 -0
- package/dist/client/blocks/library/columns.js +199 -0
- package/dist/client/blocks/library/columns.js.map +1 -0
- package/dist/client/blocks/library/dev-doc-ui.d.ts +2 -1
- package/dist/client/blocks/library/dev-doc-ui.d.ts.map +1 -1
- package/dist/client/blocks/library/dev-doc-ui.js +2 -1
- package/dist/client/blocks/library/dev-doc-ui.js.map +1 -1
- package/dist/client/blocks/library/html.d.ts +1 -1
- package/dist/client/blocks/library/html.d.ts.map +1 -1
- package/dist/client/blocks/library/html.js +34 -4
- package/dist/client/blocks/library/html.js.map +1 -1
- package/dist/client/blocks/library/json-explorer.config.d.ts +3 -1
- package/dist/client/blocks/library/json-explorer.config.d.ts.map +1 -1
- package/dist/client/blocks/library/json-explorer.config.js +30 -1
- package/dist/client/blocks/library/json-explorer.config.js.map +1 -1
- package/dist/client/blocks/library/server-specs.d.ts.map +1 -1
- package/dist/client/blocks/library/server-specs.js +13 -3
- package/dist/client/blocks/library/server-specs.js.map +1 -1
- package/dist/client/blocks/library/specs.d.ts +4 -4
- package/dist/client/blocks/library/specs.d.ts.map +1 -1
- package/dist/client/blocks/library/specs.js +21 -16
- package/dist/client/blocks/library/specs.js.map +1 -1
- package/dist/client/blocks/library/table.config.d.ts +3 -0
- package/dist/client/blocks/library/table.config.d.ts.map +1 -1
- package/dist/client/blocks/library/table.config.js +13 -1
- package/dist/client/blocks/library/table.config.js.map +1 -1
- package/dist/client/blocks/library/table.d.ts.map +1 -1
- package/dist/client/blocks/library/table.js +90 -9
- package/dist/client/blocks/library/table.js.map +1 -1
- package/dist/client/blocks/library/tabs.config.d.ts +16 -8
- package/dist/client/blocks/library/tabs.config.d.ts.map +1 -1
- package/dist/client/blocks/library/tabs.config.js +10 -4
- package/dist/client/blocks/library/tabs.config.js.map +1 -1
- package/dist/client/blocks/library/tabs.d.ts.map +1 -1
- package/dist/client/blocks/library/tabs.js +146 -21
- package/dist/client/blocks/library/tabs.js.map +1 -1
- package/dist/client/blocks/server.d.ts +2 -1
- package/dist/client/blocks/server.d.ts.map +1 -1
- package/dist/client/blocks/server.js +1 -0
- package/dist/client/blocks/server.js.map +1 -1
- package/dist/client/blocks/types.d.ts +99 -9
- package/dist/client/blocks/types.d.ts.map +1 -1
- package/dist/client/blocks/types.js.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +2 -2
- package/dist/client/index.js.map +1 -1
- package/dist/client/rich-markdown-editor/BubbleToolbar.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/BubbleToolbar.js +13 -3
- package/dist/client/rich-markdown-editor/BubbleToolbar.js.map +1 -1
- package/dist/client/rich-markdown-editor/DragHandle.d.ts +49 -4
- package/dist/client/rich-markdown-editor/DragHandle.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/DragHandle.js +656 -88
- package/dist/client/rich-markdown-editor/DragHandle.js.map +1 -1
- package/dist/client/rich-markdown-editor/RegistryBlockNode.d.ts +10 -1
- package/dist/client/rich-markdown-editor/RegistryBlockNode.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/RegistryBlockNode.js +180 -15
- package/dist/client/rich-markdown-editor/RegistryBlockNode.js.map +1 -1
- package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts +2 -1
- package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/SharedRichEditor.js +3 -1
- package/dist/client/rich-markdown-editor/SharedRichEditor.js.map +1 -1
- package/dist/client/rich-markdown-editor/SlashCommandMenu.d.ts +5 -0
- package/dist/client/rich-markdown-editor/SlashCommandMenu.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/SlashCommandMenu.js +33 -5
- package/dist/client/rich-markdown-editor/SlashCommandMenu.js.map +1 -1
- package/dist/client/rich-markdown-editor/index.d.ts +3 -3
- package/dist/client/rich-markdown-editor/index.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/index.js +2 -2
- package/dist/client/rich-markdown-editor/index.js.map +1 -1
- package/dist/client/rich-markdown-editor/registrySlashCommands.d.ts +14 -0
- package/dist/client/rich-markdown-editor/registrySlashCommands.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/registrySlashCommands.js +38 -0
- package/dist/client/rich-markdown-editor/registrySlashCommands.js.map +1 -1
- package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts +1 -0
- package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/useCollabReconcile.js +4 -0
- package/dist/client/rich-markdown-editor/useCollabReconcile.js.map +1 -1
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +17 -1
- package/dist/db/client.js.map +1 -1
- package/dist/deploy/build.js +68 -0
- package/dist/deploy/build.js.map +1 -1
- package/dist/sharing/access.d.ts +4 -2
- package/dist/sharing/access.d.ts.map +1 -1
- package/dist/sharing/access.js +8 -3
- package/dist/sharing/access.js.map +1 -1
- package/dist/sharing/actions/set-resource-visibility.d.ts.map +1 -1
- package/dist/sharing/actions/set-resource-visibility.js +2 -3
- package/dist/sharing/actions/set-resource-visibility.js.map +1 -1
- package/dist/sharing/registry.d.ts +13 -0
- package/dist/sharing/registry.d.ts.map +1 -1
- package/dist/sharing/registry.js.map +1 -1
- package/dist/styles/rich-markdown-editor.css +15 -0
- package/package.json +16 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MermaidBlock.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/MermaidBlock.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useId, useMemo, useState } from \"react\";\nimport type { BlockEditProps, BlockReadProps } from \"../types.js\";\nimport type { MermaidData } from \"./mermaid.config.js\";\nimport { DevInput, DevLabel } from \"./dev-doc-ui.js\";\n\n/**\n * Read + Edit renderers for a `mermaid` block — a Mermaid diagram definition\n * (flowchart, sequence, etc.) edited as raw text and rendered with Mermaid's\n * `handDrawn` look so it matches the plan's hand-drawn / sketchy house style.\n * Lives in core so any app can register the dev-doc block; it stays app-agnostic\n * (no shadcn / next-themes import).\n *\n * `mermaid` is a browser-only runtime (it touches `document`/DOM measurement),\n * so the Read renderer SSR-guards: it renders a lightweight placeholder until a\n * `useEffect` confirms it is mounted, then dynamically imports `mermaid` and\n * injects the rendered SVG. Parse errors never throw — they fall back to the raw\n * source in a styled monospace block plus the error message. (The dynamic import\n * uses a runtime specifier so this module never forces `mermaid` into the core\n * package's own dependency graph — the host app provides it.)\n *\n * Dark mode: the plan editor toggles a `.dark` class on <html>. The Read renderer\n * reads `document.documentElement.classList.contains(\"dark\")` (re-checking on a\n * `MutationObserver` of the html class) and re-renders the diagram with Mermaid's\n * `dark` theme (vs `neutral` in light) — the resolved theme is in the render\n * effect's deps so toggling dark/light updates the SVG live.\n */\n\n/** Module specifier kept in a variable so the bundler/tsc treats it as a runtime\n * import (core does not depend on `mermaid`; the host app provides it). */\nconst MERMAID_MODULE = \"mermaid\";\n\ninterface MermaidRenderState {\n svg?: string;\n error?: string;\n}\n\n/** Read the live dark-mode flag from the document root (next-themes-free). */\nfunction useIsDark(): boolean {\n const [isDark, setIsDark] = useState(false);\n useEffect(() => {\n if (typeof document === \"undefined\") return;\n const root = document.documentElement;\n const read = () => setIsDark(root.classList.contains(\"dark\"));\n read();\n const observer = new MutationObserver(read);\n observer.observe(root, { attributes: true, attributeFilter: [\"class\"] });\n return () => observer.disconnect();\n }, []);\n return isDark;\n}\n\nfunction MermaidDiagram({\n source,\n idSeed,\n}: {\n source: string;\n idSeed: string;\n}) {\n const isDark = useIsDark();\n // Only render the diagram after mount: `mermaid` is client-only and SSR has no\n // DOM for it to measure against.\n const [mounted, setMounted] = useState(false);\n const [state, setState] = useState<MermaidRenderState>({});\n\n // A DOM-id-safe, stable-per-block render id. Mermaid requires a valid CSS id.\n const renderId = useMemo(\n () => `mermaid-${idSeed.replace(/[^a-zA-Z0-9_-]/g, \"-\")}`,\n [idSeed],\n );\n\n useEffect(() => {\n setMounted(true);\n }, []);\n\n useEffect(() => {\n if (!mounted) return;\n let cancelled = false;\n const trimmed = source.trim();\n if (!trimmed) {\n setState({});\n return;\n }\n (async () => {\n try {\n const mermaid = ((await import(MERMAID_MODULE)) as { default: any })\n .default;\n mermaid.initialize({\n startOnLoad: false,\n securityLevel: \"strict\",\n look: \"handDrawn\",\n theme: isDark ? \"dark\" : \"neutral\",\n });\n // Unique id per render pass so re-renders (theme/source change) never\n // collide with a stale, still-mounted SVG node id.\n const { svg } = await mermaid.render(\n `${renderId}-${isDark ? \"d\" : \"l\"}`,\n trimmed,\n );\n if (!cancelled) setState({ svg });\n } catch (error) {\n if (!cancelled) {\n setState({\n error:\n error instanceof Error\n ? error.message\n : \"Failed to render diagram\",\n });\n }\n }\n })();\n return () => {\n cancelled = true;\n };\n // Re-render when the source OR the resolved theme changes so toggling\n // dark/light updates the diagram live.\n }, [mounted, source, isDark, renderId]);\n\n if (!mounted) {\n return (\n <div className=\"mt-2 flex min-h-24 items-center justify-center rounded-lg border border-plan-line bg-plan-code text-sm text-plan-muted\">\n Loading diagram…\n </div>\n );\n }\n\n if (state.error) {\n return (\n <div className=\"mt-2 space-y-2\">\n <pre className=\"overflow-auto rounded-lg border border-plan-line bg-plan-code px-3 py-2 font-mono text-sm text-plan-code-text\">\n {source}\n </pre>\n <p className=\"text-sm text-plan-muted\">\n Could not render diagram: {state.error}\n </p>\n </div>\n );\n }\n\n if (!state.svg) {\n return (\n <div className=\"mt-2 flex min-h-24 items-center justify-center rounded-lg border border-plan-line bg-plan-code text-sm text-plan-muted\">\n Add a diagram definition to render it.\n </div>\n );\n }\n\n return (\n <div\n className=\"mt-2 flex justify-center overflow-auto [&_svg]:max-w-full [&_svg]:h-auto\"\n // Mermaid output is already sanitized under `securityLevel: \"strict\"`.\n dangerouslySetInnerHTML={{ __html: state.svg }}\n />\n );\n}\n\n/**\n * Read-only renderer for a `mermaid` block. Wraps the diagram in the standard\n * titled `plan-block` section + an optional muted caption, matching the plan\n * house style.\n */\nexport function MermaidRead({\n data,\n blockId,\n title,\n summary,\n}: BlockReadProps<MermaidData>) {\n return (\n <section className=\"plan-block\" data-block-id={blockId}>\n {title && <div className=\"plan-block-label\">{title}</div>}\n <MermaidDiagram source={data.source} idSeed={blockId} />\n {data.caption && (\n <p className=\"mt-3 text-sm text-plan-muted\">{data.caption}</p>\n )}\n {summary && <p className=\"mt-5 text-plan-muted\">{summary}</p>}\n </section>\n );\n}\n\n/**\n * Edit renderer (panel surface) for a `mermaid` block: a monospace textarea for\n * the diagram source plus an optional caption input. Both commit immediately via\n * `onChange`. `editSurface: \"panel\"` means the registry renders the `Read` view\n * with a corner edit button that opens this form in the plan's shared popover, so\n * this renders only the form (the popover supplies the chrome and title).\n */\nexport function MermaidEdit({\n data,\n onChange,\n editable,\n}: BlockEditProps<MermaidData>) {\n const sourceId = useId();\n const captionId = useId();\n\n return (\n <div className=\"grid gap-3\" data-plan-interactive>\n <div className=\"grid gap-1.5\">\n <DevLabel htmlFor={sourceId}>Diagram source</DevLabel>\n <textarea\n id={sourceId}\n value={data.source}\n readOnly={!editable}\n spellCheck={false}\n onChange={(event) =>\n onChange({ ...data, source: event.target.value })\n }\n className=\"flex min-h-56 w-full rounded-md border border-input bg-transparent px-3 py-2 font-mono text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\"\n placeholder={\"flowchart TD\\n A[Start] --> B{Decision}\"}\n />\n <p className=\"text-xs text-muted-foreground\">\n Mermaid syntax — flowcharts, sequence diagrams, and more.\n </p>\n </div>\n <div className=\"grid gap-1.5\">\n <DevLabel htmlFor={captionId}>Caption</DevLabel>\n <DevInput\n id={captionId}\n value={data.caption ?? \"\"}\n readOnly={!editable}\n onChange={(event) =>\n onChange({\n ...data,\n caption: event.target.value || undefined,\n })\n }\n placeholder=\"Optional caption\"\n />\n </div>\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"MermaidBlock.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/MermaidBlock.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useId, useMemo, useState } from \"react\";\nimport type { BlockEditProps, BlockReadProps } from \"../types.js\";\nimport type { MermaidData } from \"./mermaid.config.js\";\nimport { DevInput, DevLabel } from \"./dev-doc-ui.js\";\n\n/**\n * Read + Edit renderers for a `mermaid` block — a Mermaid diagram definition\n * (flowchart, sequence, etc.) edited as raw text and rendered as an\n * Excalidraw-style SVG so it matches the plan's hand-drawn / sketchy house\n * style.\n * Lives in core so any app can register the dev-doc block; it stays app-agnostic\n * (no shadcn / next-themes import).\n *\n * The Mermaid and Excalidraw runtimes are browser-only,\n * so the Read renderer SSR-guards: it renders a lightweight placeholder until a\n * `useEffect` confirms it is mounted, then dynamically imports\n * `@excalidraw/mermaid-to-excalidraw` + `@excalidraw/excalidraw` and injects\n * the exported SVG. If Excalidraw conversion fails, it falls back to Mermaid's\n * hand-drawn renderer. Parse errors never throw; they show the raw source and\n * the error message.\n *\n * Dark mode: the plan editor toggles a `.dark` class on <html>. The Read renderer\n * reads `document.documentElement.classList.contains(\"dark\")` (re-checking on a\n * `MutationObserver` of the html class) and re-renders the diagram with matching\n * light/dark export settings.\n */\n\ninterface MermaidRenderState {\n svg?: string;\n error?: string;\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : \"Failed to render diagram\";\n}\n\nfunction sanitizeSvgMarkup(svg: string): string {\n if (typeof DOMParser === \"undefined\") return svg;\n const doc = new DOMParser().parseFromString(svg, \"image/svg+xml\");\n doc\n .querySelectorAll(\"script, foreignObject\")\n .forEach((node) => node.remove());\n for (const element of Array.from(doc.querySelectorAll(\"*\"))) {\n for (const attr of Array.from(element.attributes)) {\n const name = attr.name.toLowerCase();\n const value = attr.value.trim().toLowerCase();\n if (\n name.startsWith(\"on\") ||\n ((name === \"href\" || name.endsWith(\":href\")) &&\n value.startsWith(\"javascript:\"))\n ) {\n element.removeAttribute(attr.name);\n }\n }\n }\n return doc.documentElement.outerHTML;\n}\n\nasync function renderExcalidrawSvg(\n source: string,\n isDark: boolean,\n): Promise<string> {\n const [{ parseMermaidToExcalidraw }, excalidraw] = await Promise.all([\n import(\"@excalidraw/mermaid-to-excalidraw\") as Promise<{\n parseMermaidToExcalidraw: (source: string) => Promise<{\n elements: unknown[];\n files?: Record<string, unknown>;\n }>;\n }>,\n import(\"@excalidraw/excalidraw\") as Promise<{\n convertToExcalidrawElements: (elements: unknown[]) => unknown[];\n exportToSvg: (options: {\n elements: unknown[];\n appState: {\n theme: \"dark\" | \"light\";\n viewBackgroundColor: string;\n exportWithDarkMode: boolean;\n };\n files: Record<string, unknown>;\n }) => Promise<{ outerHTML: string }>;\n }>,\n ]);\n const { elements, files } = await parseMermaidToExcalidraw(source);\n const excalidrawElements = excalidraw.convertToExcalidrawElements(elements);\n const svg = await excalidraw.exportToSvg({\n elements: excalidrawElements,\n appState: {\n theme: isDark ? \"dark\" : \"light\",\n viewBackgroundColor: \"transparent\",\n exportWithDarkMode: isDark,\n },\n files: files ?? {},\n });\n return sanitizeSvgMarkup(svg.outerHTML);\n}\n\nasync function renderMermaidSvg(\n source: string,\n id: string,\n isDark: boolean,\n): Promise<string> {\n const mermaid = (\n (await import(\"mermaid\")) as {\n default: {\n initialize: (config: Record<string, unknown>) => void;\n render: (id: string, source: string) => Promise<{ svg: string }>;\n };\n }\n ).default;\n mermaid.initialize({\n startOnLoad: false,\n securityLevel: \"strict\",\n look: \"handDrawn\",\n theme: isDark ? \"dark\" : \"neutral\",\n });\n const { svg } = await mermaid.render(id, source);\n return sanitizeSvgMarkup(svg);\n}\n\n/** Read the live dark-mode flag from the document root (next-themes-free). */\nfunction useIsDark(): boolean {\n const [isDark, setIsDark] = useState(false);\n useEffect(() => {\n if (typeof document === \"undefined\") return;\n const root = document.documentElement;\n const read = () => setIsDark(root.classList.contains(\"dark\"));\n read();\n const observer = new MutationObserver(read);\n observer.observe(root, { attributes: true, attributeFilter: [\"class\"] });\n return () => observer.disconnect();\n }, []);\n return isDark;\n}\n\nfunction MermaidDiagram({\n source,\n idSeed,\n}: {\n source: string;\n idSeed: string;\n}) {\n const isDark = useIsDark();\n // Only render the diagram after mount: `mermaid` is client-only and SSR has no\n // DOM for it to measure against.\n const [mounted, setMounted] = useState(false);\n const [state, setState] = useState<MermaidRenderState>({});\n\n // A DOM-id-safe, stable-per-block render id. Mermaid requires a valid CSS id.\n const renderId = useMemo(\n () => `mermaid-${idSeed.replace(/[^a-zA-Z0-9_-]/g, \"-\")}`,\n [idSeed],\n );\n\n useEffect(() => {\n setMounted(true);\n }, []);\n\n useEffect(() => {\n if (!mounted) return;\n let cancelled = false;\n const trimmed = source.trim();\n if (!trimmed) {\n setState({});\n return;\n }\n (async () => {\n try {\n const svg = await renderExcalidrawSvg(trimmed, isDark);\n if (!cancelled) setState({ svg });\n } catch (excalidrawError) {\n try {\n // Fallback keeps diagrams usable if a Mermaid feature is not supported\n // by the Excalidraw converter in a given host app.\n const svg = await renderMermaidSvg(\n trimmed,\n `${renderId}-${isDark ? \"d\" : \"l\"}`,\n isDark,\n );\n if (!cancelled) setState({ svg });\n } catch (mermaidError) {\n const excalidrawMessage = errorMessage(excalidrawError);\n const mermaidMessage = errorMessage(mermaidError);\n if (!cancelled) {\n setState({\n error:\n excalidrawMessage === mermaidMessage\n ? mermaidMessage\n : `Excalidraw: ${excalidrawMessage}; Mermaid fallback: ${mermaidMessage}`,\n });\n }\n }\n }\n })();\n return () => {\n cancelled = true;\n };\n // Re-render when the source OR the resolved theme changes so toggling\n // dark/light updates the diagram live.\n }, [mounted, source, isDark, renderId]);\n\n if (!mounted) {\n return (\n <div className=\"mt-2 flex min-h-24 items-center justify-center rounded-lg border border-plan-line bg-plan-code text-sm text-plan-muted\">\n Loading diagram…\n </div>\n );\n }\n\n if (state.error) {\n return (\n <div className=\"mt-2 space-y-2\">\n <pre className=\"overflow-auto rounded-lg border border-plan-line bg-plan-code px-3 py-2 font-mono text-sm text-plan-code-text\">\n {source}\n </pre>\n <p className=\"text-sm text-plan-muted\">\n Could not render diagram: {state.error}\n </p>\n </div>\n );\n }\n\n if (!state.svg) {\n return (\n <div className=\"mt-2 flex min-h-24 items-center justify-center rounded-lg border border-plan-line bg-plan-code text-sm text-plan-muted\">\n Add a diagram definition to render it.\n </div>\n );\n }\n\n return (\n <div\n className=\"mt-2 flex justify-center overflow-auto [&_svg]:h-auto [&_svg]:max-w-full\"\n // Excalidraw and Mermaid output are sanitized before injection.\n dangerouslySetInnerHTML={{ __html: state.svg }}\n />\n );\n}\n\n/**\n * Read-only renderer for a `mermaid` block. Wraps the diagram in the standard\n * titled `plan-block` section + an optional muted caption, matching the plan\n * house style.\n */\nexport function MermaidRead({\n data,\n blockId,\n title,\n summary,\n}: BlockReadProps<MermaidData>) {\n return (\n <section className=\"plan-block\" data-block-id={blockId}>\n {title && <div className=\"plan-block-label\">{title}</div>}\n <MermaidDiagram source={data.source} idSeed={blockId} />\n {data.caption && (\n <p className=\"mt-3 text-sm text-plan-muted\">{data.caption}</p>\n )}\n {summary && <p className=\"mt-5 text-plan-muted\">{summary}</p>}\n </section>\n );\n}\n\n/**\n * Edit renderer (panel surface) for a `mermaid` block: a monospace textarea for\n * the diagram source plus an optional caption input. Both commit immediately via\n * `onChange`. `editSurface: \"panel\"` means the registry renders the `Read` view\n * with a corner edit button that opens this form in the plan's shared popover, so\n * this renders only the form (the popover supplies the chrome and title).\n */\nexport function MermaidEdit({\n data,\n onChange,\n editable,\n}: BlockEditProps<MermaidData>) {\n const sourceId = useId();\n const captionId = useId();\n\n return (\n <div className=\"grid gap-3\" data-plan-interactive>\n <div className=\"grid gap-1.5\">\n <DevLabel htmlFor={sourceId}>Diagram source</DevLabel>\n <textarea\n id={sourceId}\n value={data.source}\n readOnly={!editable}\n spellCheck={false}\n onChange={(event) =>\n onChange({ ...data, source: event.target.value })\n }\n className=\"flex min-h-56 w-full rounded-md border border-input bg-transparent px-3 py-2 font-mono text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\"\n placeholder={\"flowchart TD\\n A[Start] --> B{Decision}\"}\n />\n <p className=\"text-xs text-muted-foreground\">\n Mermaid syntax — flowcharts, sequence diagrams, and more.\n </p>\n </div>\n <div className=\"grid gap-1.5\">\n <DevLabel htmlFor={captionId}>Caption</DevLabel>\n <DevInput\n id={captionId}\n value={data.caption ?? \"\"}\n readOnly={!editable}\n onChange={(event) =>\n onChange({\n ...data,\n caption: event.target.value || undefined,\n })\n }\n placeholder=\"Optional caption\"\n />\n </div>\n </div>\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OpenApiSpecBlock.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/OpenApiSpecBlock.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"OpenApiSpecBlock.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/OpenApiSpecBlock.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAqyBhE;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,OAAO,EACP,KAAK,EACL,OAAO,EACP,GAAG,GACJ,EAAE,cAAc,CAAC,eAAe,CAAC,2CAkFjC;AAID;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,QAAQ,EACR,QAAQ,GACT,EAAE,cAAc,CAAC,eAAe,CAAC,2CAwEjC"}
|
|
@@ -3,6 +3,7 @@ import { useId, useMemo, useState } from "react";
|
|
|
3
3
|
import { IconChevronRight, IconLock } from "@tabler/icons-react";
|
|
4
4
|
import { cn } from "../../utils.js";
|
|
5
5
|
import { DevInput, DevLabel, DevTextarea } from "./dev-doc-ui.js";
|
|
6
|
+
import { CodeSurface } from "./HighlightedCode.js";
|
|
6
7
|
/**
|
|
7
8
|
* Read + Edit renderers for an `openapi-spec` block — a Redoc / Swagger-UI-style
|
|
8
9
|
* API reference rendered from a whole OpenAPI 3 / Swagger 2 document. The raw
|
|
@@ -440,7 +441,7 @@ function OperationRow({ operation, renderMarkdown, }) {
|
|
|
440
441
|
operation.responses.length > 0;
|
|
441
442
|
return (_jsxs("div", { className: "overflow-hidden border-t border-plan-line first:border-t-0", children: [_jsxs("button", { type: "button", "data-plan-interactive": true, "aria-expanded": open, onClick: () => setOpen((value) => !value), className: cn("flex w-full items-center gap-3 px-4 py-2.5 text-left transition-colors", "hover:bg-accent/40"), children: [_jsx(IconChevronRight, { className: cn("size-4 shrink-0 text-plan-muted transition-transform", open && "rotate-90") }), _jsx("span", { className: cn("shrink-0 rounded-md px-2 py-1 font-mono text-xs font-bold uppercase tracking-wide", METHOD_PILL[operation.method] ??
|
|
442
443
|
"bg-slate-200 text-slate-700 dark:bg-slate-500/20 dark:text-slate-300"), children: operation.method }), _jsx("span", { className: cn("min-w-0 truncate font-mono text-sm font-semibold text-plan-text", operation.deprecated && "text-plan-muted line-through"), children: operation.path }), operation.summary && (_jsx("span", { className: "ml-1 min-w-0 flex-1 truncate text-sm text-plan-muted", children: operation.summary })), operation.secured && (_jsx(IconLock, { className: "size-3.5 shrink-0 text-plan-muted", "aria-label": "Requires authentication" }))] }), open && hasBody && (_jsxs("div", { className: "border-t border-plan-line bg-plan-block px-4 py-4", children: [operation.description?.trim() && (_jsx("div", { className: "an-api-endpoint-desc", children: renderMarkdown ? (renderMarkdown(operation.description)) : (_jsx("p", { className: "text-sm text-plan-muted", children: operation.description })) })), operation.params.length > 0 && (_jsxs("div", { className: "mt-4", children: [_jsx("div", { className: "text-xs font-semibold uppercase tracking-wide text-plan-muted", children: "Parameters" }), _jsx("div", { className: "mt-2 overflow-hidden rounded-lg border border-plan-line", children: _jsxs("table", { className: "w-full border-collapse text-sm", children: [_jsx("thead", { children: _jsxs("tr", { className: "bg-accent/30 text-left text-xs uppercase tracking-wide text-plan-muted", children: [_jsx("th", { className: "px-3 py-2 font-medium", children: "Name" }), _jsx("th", { className: "px-3 py-2 font-medium", children: "In" }), _jsx("th", { className: "px-3 py-2 font-medium", children: "Type" }), _jsx("th", { className: "px-3 py-2 font-medium", children: "Required" }), _jsx("th", { className: "px-3 py-2 font-medium", children: "Description" })] }) }), _jsx("tbody", { children: operation.params.map((param, index) => (_jsxs("tr", { className: "border-t border-plan-line align-top", children: [_jsx("td", { className: "px-3 py-2 font-mono text-xs font-semibold text-plan-text", children: param.name }), _jsx("td", { className: "px-3 py-2", children: _jsx("span", { className: cn("rounded px-1.5 py-0.5 font-mono text-[11px] font-semibold", PARAM_IN_BADGE[param.in] ??
|
|
443
|
-
"bg-slate-200 text-slate-700 dark:bg-slate-500/20 dark:text-slate-300"), children: param.in }) }), _jsx("td", { className: "px-3 py-2 font-mono text-xs text-plan-muted", children: param.type || "—" }), _jsx("td", { className: "px-3 py-2 text-xs", children: param.required ? (_jsx("span", { className: "font-medium text-red-600 dark:text-red-300", children: "required" })) : (_jsx("span", { className: "text-plan-muted", children: "optional" })) }), _jsx("td", { className: "px-3 py-2 text-xs text-plan-muted", children: param.description || "—" })] }, `${param.name}-${param.in}-${index}`))) })] }) })] })), (operation.requestExample || operation.requestContentType) && (_jsxs("div", { className: "mt-4", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-xs font-semibold uppercase tracking-wide text-plan-muted", children: "Request body" }), operation.requestContentType && (_jsx("span", { className: "rounded bg-accent/40 px-1.5 py-0.5 font-mono text-[11px] text-plan-muted", children: operation.requestContentType }))] }), operation.requestExample && (_jsx(
|
|
444
|
+
"bg-slate-200 text-slate-700 dark:bg-slate-500/20 dark:text-slate-300"), children: param.in }) }), _jsx("td", { className: "px-3 py-2 font-mono text-xs text-plan-muted", children: param.type || "—" }), _jsx("td", { className: "px-3 py-2 text-xs", children: param.required ? (_jsx("span", { className: "font-medium text-red-600 dark:text-red-300", children: "required" })) : (_jsx("span", { className: "text-plan-muted", children: "optional" })) }), _jsx("td", { className: "px-3 py-2 text-xs text-plan-muted", children: param.description || "—" })] }, `${param.name}-${param.in}-${index}`))) })] }) })] })), (operation.requestExample || operation.requestContentType) && (_jsxs("div", { className: "mt-4", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-xs font-semibold uppercase tracking-wide text-plan-muted", children: "Request body" }), operation.requestContentType && (_jsx("span", { className: "rounded bg-accent/40 px-1.5 py-0.5 font-mono text-[11px] text-plan-muted", children: operation.requestContentType }))] }), operation.requestExample && (_jsx(CodeSurface, { code: operation.requestExample, language: "json", className: "mt-2" }))] })), operation.responses.length > 0 && (_jsxs("div", { className: "mt-4", children: [_jsx("div", { className: "text-xs font-semibold uppercase tracking-wide text-plan-muted", children: "Responses" }), _jsx("div", { className: "mt-2 flex flex-col gap-3", children: operation.responses.map((response, index) => (_jsxs("div", { className: "rounded-lg border border-plan-line", children: [_jsxs("div", { className: "flex items-center gap-2 px-3 py-2", children: [_jsx("span", { className: cn("rounded px-2 py-0.5 font-mono text-xs font-bold", statusPillClass(response.status)), children: response.status }), response.description && (_jsx("span", { className: "text-sm text-plan-muted", children: response.description }))] }), response.example && (_jsx("div", { className: "border-t border-plan-line px-3 pb-3 pt-3", children: _jsx(CodeSurface, { code: response.example, language: "json", className: "mt-0" }) }))] }, `${response.status}-${index}`))) })] }))] }))] }));
|
|
444
445
|
}
|
|
445
446
|
/* ── Tag group (collapsed-by-default) ──────────────────────────────────────── */
|
|
446
447
|
function TagGroup({ group, defaultOpen, renderMarkdown, }) {
|
|
@@ -462,7 +463,7 @@ export function OpenApiSpecRead({ data, blockId, title, summary, ctx, }) {
|
|
|
462
463
|
return (_jsxs("section", { className: "plan-block", "data-block-id": blockId, children: [heading && _jsx("div", { className: "plan-block-label", children: heading }), parsed.ok && parsed.spec ? (_jsxs("div", { className: "flex flex-col gap-3", children: [_jsxs("div", { className: "overflow-hidden rounded-xl border border-plan-line bg-plan-block px-4 py-3", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx("span", { className: "font-semibold text-plan-text", children: parsed.spec.title || "API reference" }), parsed.spec.version && (_jsxs("span", { className: "rounded bg-accent/40 px-1.5 py-0.5 font-mono text-[11px] text-plan-muted", children: ["v", parsed.spec.version] })), _jsx("span", { className: "rounded-full border border-plan-line px-2 py-0.5 text-[11px] font-medium text-plan-muted", children: parsed.spec.format }), _jsxs("span", { className: "text-xs text-plan-muted", children: [parsed.spec.operationCount, " ", parsed.spec.operationCount === 1 ? "operation" : "operations"] })] }), parsed.spec.description?.trim() && (_jsx("div", { className: "mt-2 an-api-endpoint-desc", children: renderMarkdown ? (renderMarkdown(parsed.spec.description)) : (_jsx("p", { className: "text-sm text-plan-muted", children: parsed.spec.description })) }))] }), parsed.spec.groups.length === 0 ? (_jsx("div", { className: "rounded-xl border border-plan-line bg-plan-block px-4 py-6 text-center text-sm text-plan-muted", children: "No operations found in this spec." })) : (parsed.spec.groups.map((group, index) => (_jsx(TagGroup, { group: group,
|
|
463
464
|
// Open the first group by default so the reference is not a wall
|
|
464
465
|
// of collapsed accordions on first paint.
|
|
465
|
-
defaultOpen: index === 0, renderMarkdown: renderMarkdown }, group.tag))))] })) : (_jsxs("div", { className: "overflow-hidden rounded-xl border border-plan-line bg-plan-
|
|
466
|
+
defaultOpen: index === 0, renderMarkdown: renderMarkdown }, group.tag))))] })) : (_jsxs("div", { className: "overflow-hidden rounded-xl border border-plan-line bg-plan-block", children: [_jsx("div", { className: "border-b border-plan-line px-3 py-1.5", children: _jsx("span", { className: "font-mono text-xs uppercase tracking-wide text-plan-muted", children: "OpenAPI" }) }), _jsxs("div", { className: "space-y-2 px-3 py-2.5", children: [_jsxs("p", { className: "text-xs text-red-600 dark:text-red-300", children: ["Could not parse spec: ", parsed.error] }), _jsx(CodeSurface, { code: data.spec || "—", language: "json", className: "mt-0" })] })] })), summary && _jsx("p", { className: "mt-5 text-plan-muted", children: summary })] }));
|
|
466
467
|
}
|
|
467
468
|
/* ── Edit (panel form) ─────────────────────────────────────────────────────── */
|
|
468
469
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OpenApiSpecBlock.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/OpenApiSpecBlock.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AAGpC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,mFAAmF;AAEnF,MAAM,WAAW,GAA2B;IAC1C,GAAG,EAAE,8EAA8E;IACnF,IAAI,EAAE,kEAAkE;IACxE,GAAG,EAAE,sEAAsE;IAC3E,KAAK,EACH,0EAA0E;IAC5E,MAAM,EAAE,8DAA8D;IACtE,IAAI,EAAE,sEAAsE;IAC5E,OAAO,EACL,sEAAsE;IACxE,KAAK,EAAE,sEAAsE;CAC9E,CAAC;AAEF,MAAM,cAAc,GAA2B;IAC7C,IAAI,EAAE,0EAA0E;IAChF,KAAK,EAAE,kEAAkE;IACzE,MAAM,EACJ,sEAAsE;IACxE,MAAM,EACJ,8EAA8E;IAChF,IAAI,EAAE,8EAA8E;CACrF,CAAC;AAEF,+EAA+E;AAC/E,SAAS,eAAe,CAAC,MAAc;IACrC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACrC,IAAI,IAAI,KAAK,GAAG;QACd,OAAO,8EAA8E,CAAC;IACxF,IAAI,IAAI,KAAK,GAAG;QACd,OAAO,sEAAsE,CAAC;IAChF,IAAI,IAAI,KAAK,GAAG;QACd,OAAO,8DAA8D,CAAC;IACxE,OAAO,sEAAsE,CAAC;AAChF,CAAC;AAOD,MAAM,YAAY,GAAG;IACnB,KAAK;IACL,MAAM;IACN,KAAK;IACL,OAAO;IACP,QAAQ;IACR,MAAM;IACN,SAAS;IACT,OAAO;CACC,CAAC;AAqDX,SAAS,QAAQ,CAAC,KAAW;IAC3B,OAAO,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,QAAQ,CAAC,KAAW;IAC3B,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACvD,CAAC;AAED;;;;GAIG;AACH,SAAS,SAAS,CAAC,GAAW;IAC5B,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,uDAAuD;SAC/D,CAAC;IACJ,CAAC;IACD,IAAI,GAAS,CAAC;IACd,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,GACR,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC;YAC9D,CAAC,CAAC,yEAAyE;YAC3E,CAAC,CAAC,EAAE,CAAC;QACT,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,GAAG,IAAI,EAAE;SAC3E,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACnB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,6BAA6B,EAAE,CAAC;IAC7D,CAAC;IACD,IAAI,CAAC;QACH,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;IAChD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EACH,KAAK,YAAY,KAAK;gBACpB,CAAC,CAAC,KAAK,CAAC,OAAO;gBACf,CAAC,CAAC,wCAAwC;SAC/C,CAAC;IACJ,CAAC;AACH,CAAC;AAED,kFAAkF;AAClF,SAAS,UAAU,CACjB,IAAgB,EAChB,GAAW,EACX,IAAiB;IAEjB,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IAC5C,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC,CAAC,cAAc;IACnD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACd,MAAM,QAAQ,GAAG,GAAG;SACjB,KAAK,CAAC,CAAC,CAAC;SACR,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;IAC7D,IAAI,OAAO,GAAS,IAAI,CAAC;IACzB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,OAAO,SAAS,CAAC;QACzC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,sEAAsE;AACtE,SAAS,KAAK,CAAC,IAAgB,EAAE,KAAW,EAAE,IAAiB;IAC7D,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,OAAO,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,GAAG,EAAE,EAAE,CAAC;QAC3E,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACtD,IAAI,QAAQ,KAAK,SAAS;YAAE,OAAO,OAAO,CAAC;QAC3C,OAAO,GAAG,QAAQ,CAAC;QACnB,KAAK,IAAI,CAAC,CAAC;IACb,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,4DAA4D;AAC5D,SAAS,eAAe,CACtB,IAAgB,EAChB,MAAY,EACZ,IAAiB;IAEjB,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IACpD,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,SAAS,CAAC;IAC1C,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtC,IAAI,QAAQ,CAAC,IAAI,KAAK,OAAO,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;YAChD,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,EAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YAC1D,OAAO,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;QACxC,CAAC;QACD,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IACD,IAAI,QAAQ,CAAC,IAAI,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACvD,OAAO,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;IACxC,CAAC;IACD,IAAI,QAAQ,CAAC,IAAI;QAAE,OAAO,MAAM,CAAC;IACjC,IAAI,QAAQ,CAAC,UAAU;QAAE,OAAO,QAAQ,CAAC;IACzC,IAAI,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK;QAAE,OAAO,QAAQ,CAAC;IACxE,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,SAAS,aAAa,CACpB,IAAgB,EAChB,MAAY,EACZ,IAAiB,EACjB,KAAa;IAEb,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC;IAC1B,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IACpD,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,QAAQ,IAAI,IAAI,CAAC;IACjD,IAAI,QAAQ,CAAC,OAAO,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC,OAAO,CAAC;IAC5D,IAAI,QAAQ,CAAC,OAAO,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC,OAAO,CAAC;IAC5D,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7D,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC;IAED,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IACpE,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,MAAM,GAAe,EAAE,CAAC;QAC9B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;YACzD,IAAI,QAAQ,CAAC,KAAK,CAAC;gBAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,MAAM,CAAC;IACpD,CAAC;IACD,MAAM,KAAK,GACT,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC;QACjD,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC;QACjD,IAAI,CAAC;IACP,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,OAAO,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;IACxD,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;IAC3B,IAAI,IAAI,KAAK,QAAQ,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;QAC7C,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;QACvE,MAAM,GAAG,GAAe,EAAE,CAAC;QAC3B,KAAK,MAAM,CAAC,GAAG,EAAE,UAAU,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;YACnE,GAAG,CAAC,GAAG,CAAC,GAAG,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;QAC9D,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IACD,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,OAAO,CAAC,aAAa,CAAC,IAAI,EAAE,QAAQ,CAAC,KAAK,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;IACtE,CAAC;IACD,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,CAAC,CAAC;IACtD,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACpC,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,IAAI,QAAQ,CAAC,MAAM,KAAK,WAAW;YAAE,OAAO,sBAAsB,CAAC;QACnE,IAAI,QAAQ,CAAC,MAAM,KAAK,MAAM;YAC5B,OAAO,sCAAsC,CAAC;QAChD,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,wEAAwE;AACxE,SAAS,gBAAgB,CAAC,KAAW;IACnC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI;YAC5D,OAAO,SAAS,CAAC;QACnB,OAAO,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CACrB,IAAgB,EAChB,GAAS,EACT,IAAiB;IAEjB,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9C,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACvC,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACpC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ;QAAE,OAAO,SAAS,CAAC;IACzC,uEAAuE;IACvE,MAAM,IAAI,GACR,eAAe,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACpE,OAAO;QACL,IAAI;QACJ,EAAE,EAAE,QAAQ;QACZ,IAAI;QACJ,QAAQ,EAAE,KAAK,CAAC,QAAQ,KAAK,IAAI;QACjC,WAAW,EAAE,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC;KACzC,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CACzB,IAAgB,EAChB,IAAY,EACZ,MAAc,EACd,KAAW,EACX,eAAkC,EAClC,IAAiB;IAEjB,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAEvC,MAAM,MAAM,GAAsB,CAAC,GAAG,eAAe,CAAC,CAAC;IACvD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;QACpC,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;YACxC,MAAM,UAAU,GAAG,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;YACxD,IAAI,UAAU;gBAAE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;IAED,mFAAmF;IACnF,IAAI,kBAAsC,CAAC;IAC3C,IAAI,cAAkC,CAAC;IACvC,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,WAAW,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAClE,IAAI,QAAQ,CAAC,WAAW,CAAC,IAAI,QAAQ,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3D,MAAM,CAAC,WAAW,EAAE,KAAK,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC1E,kBAAkB,GAAG,WAAW,CAAC;QACjC,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACpB,cAAc;gBACZ,gBAAgB,CAAC,KAAK,CAAC,OAAO,CAAC;oBAC/B,gBAAgB,CAAC,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC;QACtD,IAAI,SAAS,EAAE,CAAC;YACd,gEAAgE;YAChE,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC;gBAC7C,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CACnB,CAAC,CAAC,EAAE,EAAE,CACJ,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;oBACvC,QAAQ,CAAE,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,CAAgB,CAAC,EAAE,CAAC;wBACxD,MAAM,CACX;gBACH,CAAC,CAAC,SAAS,CAAC;YACd,MAAM,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;gBAChE,CAAC,CAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,CAAgB;gBACrD,CAAC,CAAC,SAAS,CAAC;YACd,kBAAkB,GAAG,kBAAkB,CAAC;YACxC,cAAc,GAAG,gBAAgB,CAC/B,aAAa,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CACnD,CAAC;QACJ,CAAC;IACH,CAAC;IACD,2EAA2E;IAC3E,4DAA4D;IAC5D,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC;IAE5D,MAAM,SAAS,GAAyB,EAAE,CAAC;IAC3C,IAAI,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,KAAK,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;YACpE,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;YACzD,IAAI,OAA2B,CAAC;YAChC,IAAI,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACvB,qEAAqE;gBACrE,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;oBAC/B,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;oBACjD,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;wBACpB,OAAO;4BACL,gBAAgB,CAAC,KAAK,CAAC,OAAO,CAAC;gCAC/B,gBAAgB,CAAC,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;oBACjE,CAAC;gBACH,CAAC;qBAAM,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;oBAC3B,OAAO,GAAG,gBAAgB,CACxB,aAAa,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAC9C,CAAC;gBACJ,CAAC;YACH,CAAC;YACD,SAAS,CAAC,IAAI,CAAC;gBACb,MAAM;gBACN,WAAW,EAAE,QAAQ,CAAC,QAAQ,CAAC;oBAC7B,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC;oBAChC,CAAC,CAAC,SAAS;gBACb,OAAO;aACR,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,MAAM,IAAI,GACR,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC;QAChD,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC;QAC9D,CAAC,CAAC,EAAE,CAAC;IAET,MAAM,OAAO,GACX,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;QACxD,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CACjB,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CACtD;QACH,CAAC,CAAC,SAAS,CAAC;IAEhB,OAAO;QACL,EAAE,EAAE,GAAG,MAAM,IAAI,IAAI,EAAE;QACvB,MAAM,EAAE,MAAM,CAAC,WAAW,EAAE;QAC5B,IAAI;QACJ,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC;QAChC,WAAW,EAAE,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC;QACxC,UAAU,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI;QACrC,OAAO;QACP,IAAI,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC1C,MAAM,EAAE,aAAa;QACrB,kBAAkB;QAClB,cAAc;QACd,SAAS,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;KACtE,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,GAAe;IACpC,MAAM,MAAM,GACV,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;QAC7B,CAAC,CAAC,WAAW;QACb,CAAC,CAAC,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;YAC/B,CAAC,CAAC,WAAW;YACb,CAAC,CAAC,SAAS,CAAC;IAElB,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IAEvD,4EAA4E;IAC5E,8EAA8E;IAC9E,8BAA8B;IAC9B,MAAM,aAAa,GACjB,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;QAC3B,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAE3E,iEAAiE;IACjE,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,eAAe,GAAG,IAAI,GAAG,EAAkB,CAAC;IAClD,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5B,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;YAC3B,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAClD,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBACxB,IAAI,OAAO,GAAG,CAAC,WAAW,KAAK,QAAQ,EAAE,CAAC;oBACxC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC;gBACjD,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,GAAG,EAAiC,CAAC;IACxD,IAAI,cAAc,GAAG,CAAC,CAAC;IAEvB,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IACnD,KAAK,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACxD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC;QAC/C,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAAE,SAAS;QAElC,MAAM,eAAe,GAAsB,EAAE,CAAC;QAC9C,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YACvC,KAAK,MAAM,QAAQ,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;gBAC3C,MAAM,UAAU,GAAG,cAAc,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;gBAC5D,IAAI,UAAU;oBAAE,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;QAED,KAAK,MAAM,MAAM,IAAI,YAAY,EAAE,CAAC;YAClC,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC/B,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,SAAS;YAC/B,MAAM,SAAS,GAAG,kBAAkB,CAClC,GAAG,EACH,IAAI,EACJ,MAAM,EACN,KAAK,EACL,eAAe,EACf,IAAI,GAAG,EAAE,CACV,CAAC;YACF,IAAI,CAAC,SAAS;gBAAE,SAAS;YACzB,IAAI,SAAS,CAAC,OAAO,KAAK,SAAS,IAAI,aAAa,EAAE,CAAC;gBACrD,SAAS,CAAC,OAAO,GAAG,IAAI,CAAC;YAC3B,CAAC;YACD,cAAc,IAAI,CAAC,CAAC;YACpB,KAAK,MAAM,GAAG,IAAI,SAAS,CAAC,IAAI,EAAE,CAAC;gBACjC,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;gBACnC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBACrB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;IACH,CAAC;IAED,6EAA6E;IAC7E,uBAAuB;IACvB,MAAM,eAAe,GAAG;QACtB,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5C,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;aAClB,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;aACxC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;KACtC,CAAC;IAEF,MAAM,SAAS,GAAyB,eAAe,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACpE,GAAG;QACH,WAAW,EAAE,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC;QACrC,UAAU,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE;KAClC,CAAC,CAAC,CAAC;IAEJ,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS;QAC9C,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS;QAClD,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS;QAC1D,MAAM;QACN,MAAM,EAAE,SAAS;QACjB,cAAc;KACf,CAAC;AACJ,CAAC;AAED,mFAAmF;AAEnF,SAAS,YAAY,CAAC,EACpB,SAAS,EACT,cAAc,GAIf;IACC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAExC,MAAM,OAAO,GACX,OAAO,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC;QACtC,SAAS,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;QAC3B,OAAO,CAAC,SAAS,CAAC,cAAc,IAAI,SAAS,CAAC,kBAAkB,CAAC;QACjE,SAAS,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;IAEjC,OAAO,CACL,eAAK,SAAS,EAAC,4DAA4D,aACzE,kBACE,IAAI,EAAC,QAAQ,kDAEE,IAAI,EACnB,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,EACzC,SAAS,EAAE,EAAE,CACX,wEAAwE,EACxE,oBAAoB,CACrB,aAED,KAAC,gBAAgB,IACf,SAAS,EAAE,EAAE,CACX,sDAAsD,EACtD,IAAI,IAAI,WAAW,CACpB,GACD,EACF,eACE,SAAS,EAAE,EAAE,CACX,mFAAmF,EACnF,WAAW,CAAC,SAAS,CAAC,MAAM,CAAC;4BAC3B,sEAAsE,CACzE,YAEA,SAAS,CAAC,MAAM,GACZ,EACP,eACE,SAAS,EAAE,EAAE,CACX,iEAAiE,EACjE,SAAS,CAAC,UAAU,IAAI,8BAA8B,CACvD,YAEA,SAAS,CAAC,IAAI,GACV,EACN,SAAS,CAAC,OAAO,IAAI,CACpB,eAAM,SAAS,EAAC,sDAAsD,YACnE,SAAS,CAAC,OAAO,GACb,CACR,EACA,SAAS,CAAC,OAAO,IAAI,CACpB,KAAC,QAAQ,IACP,SAAS,EAAC,mCAAmC,gBAClC,yBAAyB,GACpC,CACH,IACM,EAER,IAAI,IAAI,OAAO,IAAI,CAClB,eAAK,SAAS,EAAC,mDAAmD,aAC/D,SAAS,CAAC,WAAW,EAAE,IAAI,EAAE,IAAI,CAChC,cAAK,SAAS,EAAC,sBAAsB,YAClC,cAAc,CAAC,CAAC,CAAC,CAChB,cAAc,CAAC,SAAS,CAAC,WAAW,CAAC,CACtC,CAAC,CAAC,CAAC,CACF,YAAG,SAAS,EAAC,yBAAyB,YACnC,SAAS,CAAC,WAAW,GACpB,CACL,GACG,CACP,EAEA,SAAS,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,CAC9B,eAAK,SAAS,EAAC,MAAM,aACnB,cAAK,SAAS,EAAC,+DAA+D,2BAExE,EACN,cAAK,SAAS,EAAC,yDAAyD,YACtE,iBAAO,SAAS,EAAC,gCAAgC,aAC/C,0BACE,cAAI,SAAS,EAAC,wEAAwE,aACpF,aAAI,SAAS,EAAC,uBAAuB,qBAAU,EAC/C,aAAI,SAAS,EAAC,uBAAuB,mBAAQ,EAC7C,aAAI,SAAS,EAAC,uBAAuB,qBAAU,EAC/C,aAAI,SAAS,EAAC,uBAAuB,yBAAc,EACnD,aAAI,SAAS,EAAC,uBAAuB,4BAAiB,IACnD,GACC,EACR,0BACG,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CACtC,cAEE,SAAS,EAAC,qCAAqC,aAE/C,aAAI,SAAS,EAAC,0DAA0D,YACrE,KAAK,CAAC,IAAI,GACR,EACL,aAAI,SAAS,EAAC,WAAW,YACvB,eACE,SAAS,EAAE,EAAE,CACX,2DAA2D,EAC3D,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;gEACtB,sEAAsE,CACzE,YAEA,KAAK,CAAC,EAAE,GACJ,GACJ,EACL,aAAI,SAAS,EAAC,6CAA6C,YACxD,KAAK,CAAC,IAAI,IAAI,GAAG,GACf,EACL,aAAI,SAAS,EAAC,mBAAmB,YAC9B,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAChB,eAAM,SAAS,EAAC,4CAA4C,yBAErD,CACR,CAAC,CAAC,CAAC,CACF,eAAM,SAAS,EAAC,iBAAiB,yBAAgB,CAClD,GACE,EACL,aAAI,SAAS,EAAC,mCAAmC,YAC9C,KAAK,CAAC,WAAW,IAAI,GAAG,GACtB,KA/BA,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,EAAE,IAAI,KAAK,EAAE,CAgCtC,CACN,CAAC,GACI,IACF,GACJ,IACF,CACP,EAEA,CAAC,SAAS,CAAC,cAAc,IAAI,SAAS,CAAC,kBAAkB,CAAC,IAAI,CAC7D,eAAK,SAAS,EAAC,MAAM,aACnB,eAAK,SAAS,EAAC,yBAAyB,aACtC,eAAM,SAAS,EAAC,+DAA+D,6BAExE,EACN,SAAS,CAAC,kBAAkB,IAAI,CAC/B,eAAM,SAAS,EAAC,0EAA0E,YACvF,SAAS,CAAC,kBAAkB,GACxB,CACR,IACG,EACL,SAAS,CAAC,cAAc,IAAI,CAC3B,cAAK,SAAS,EAAC,oHAAoH,YAChI,SAAS,CAAC,cAAc,GACrB,CACP,IACG,CACP,EAEA,SAAS,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,CACjC,eAAK,SAAS,EAAC,MAAM,aACnB,cAAK,SAAS,EAAC,+DAA+D,0BAExE,EACN,cAAK,SAAS,EAAC,0BAA0B,YACtC,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAC,CAC5C,eAEE,SAAS,EAAC,oCAAoC,aAE9C,eAAK,SAAS,EAAC,mCAAmC,aAChD,eACE,SAAS,EAAE,EAAE,CACX,iDAAiD,EACjD,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,CACjC,YAEA,QAAQ,CAAC,MAAM,GACX,EACN,QAAQ,CAAC,WAAW,IAAI,CACvB,eAAM,SAAS,EAAC,yBAAyB,YACtC,QAAQ,CAAC,WAAW,GAChB,CACR,IACG,EACL,QAAQ,CAAC,OAAO,IAAI,CACnB,cAAK,SAAS,EAAC,sGAAsG,YAClH,QAAQ,CAAC,OAAO,GACb,CACP,KAtBI,GAAG,QAAQ,CAAC,MAAM,IAAI,KAAK,EAAE,CAuB9B,CACP,CAAC,GACE,IACF,CACP,IACG,CACP,IACG,CACP,CAAC;AACJ,CAAC;AAED,kFAAkF;AAElF,SAAS,QAAQ,CAAC,EAChB,KAAK,EACL,WAAW,EACX,cAAc,GAKf;IACC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC9C,OAAO,CACL,eAAK,SAAS,EAAC,kEAAkE,aAC/E,kBACE,IAAI,EAAC,QAAQ,kDAEE,IAAI,EACnB,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,EACzC,SAAS,EAAC,yFAAyF,aAEnG,KAAC,gBAAgB,IACf,SAAS,EAAE,EAAE,CACX,sDAAsD,EACtD,IAAI,IAAI,WAAW,CACpB,GACD,EACF,eAAM,SAAS,EAAC,8BAA8B,YAAE,KAAK,CAAC,GAAG,GAAQ,EACjE,eAAM,SAAS,EAAC,+EAA+E,YAC5F,KAAK,CAAC,UAAU,CAAC,MAAM,GACnB,EACN,KAAK,CAAC,WAAW,IAAI,CACpB,eAAM,SAAS,EAAC,sDAAsD,YACnE,KAAK,CAAC,WAAW,GACb,CACR,IACM,EACR,IAAI,IAAI,CACP,cAAK,SAAS,EAAC,2BAA2B,YACvC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CACnC,KAAC,YAAY,IAEX,SAAS,EAAE,SAAS,EACpB,cAAc,EAAE,cAAc,IAFzB,SAAS,CAAC,EAAE,CAGjB,CACH,CAAC,GACE,CACP,IACG,CACP,CAAC;AACJ,CAAC;AAED,kFAAkF;AAElF;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,EAC9B,IAAI,EACJ,OAAO,EACP,KAAK,EACL,OAAO,EACP,GAAG,GAC6B;IAChC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAChE,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC;IACpC,MAAM,cAAc,GAAG,GAAG,CAAC,cAAc,CAAC;IAE1C,OAAO,CACL,mBAAS,SAAS,EAAC,YAAY,mBAAgB,OAAO,aACnD,OAAO,IAAI,cAAK,SAAS,EAAC,kBAAkB,YAAE,OAAO,GAAO,EAE5D,MAAM,CAAC,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAC1B,eAAK,SAAS,EAAC,qBAAqB,aAClC,eAAK,SAAS,EAAC,4EAA4E,aACzF,eAAK,SAAS,EAAC,mCAAmC,aAChD,eAAM,SAAS,EAAC,8BAA8B,YAC3C,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,eAAe,GAChC,EACN,MAAM,CAAC,IAAI,CAAC,OAAO,IAAI,CACtB,gBAAM,SAAS,EAAC,0EAA0E,kBACtF,MAAM,CAAC,IAAI,CAAC,OAAO,IAChB,CACR,EACD,eAAM,SAAS,EAAC,0FAA0F,YACvG,MAAM,CAAC,IAAI,CAAC,MAAM,GACd,EACP,gBAAM,SAAS,EAAC,yBAAyB,aACtC,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,GAAG,EAC/B,MAAM,CAAC,IAAI,CAAC,cAAc,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,IACzD,IACH,EACL,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,EAAE,IAAI,CAClC,cAAK,SAAS,EAAC,2BAA2B,YACvC,cAAc,CAAC,CAAC,CAAC,CAChB,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CACxC,CAAC,CAAC,CAAC,CACF,YAAG,SAAS,EAAC,yBAAyB,YACnC,MAAM,CAAC,IAAI,CAAC,WAAW,GACtB,CACL,GACG,CACP,IACG,EAEL,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CACjC,cAAK,SAAS,EAAC,gGAAgG,kDAEzG,CACP,CAAC,CAAC,CAAC,CACF,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CACvC,KAAC,QAAQ,IAEP,KAAK,EAAE,KAAK;wBACZ,iEAAiE;wBACjE,0CAA0C;wBAC1C,WAAW,EAAE,KAAK,KAAK,CAAC,EACxB,cAAc,EAAE,cAAc,IALzB,KAAK,CAAC,GAAG,CAMd,CACH,CAAC,CACH,IACG,CACP,CAAC,CAAC,CAAC,CACF,eAAK,SAAS,EAAC,iEAAiE,aAC9E,cAAK,SAAS,EAAC,uCAAuC,YACpD,eAAM,SAAS,EAAC,2DAA2D,wBAEpE,GACH,EACN,eAAK,SAAS,EAAC,uBAAuB,aACpC,aAAG,SAAS,EAAC,wCAAwC,uCAC5B,MAAM,CAAC,KAAK,IACjC,EACJ,cAAK,SAAS,EAAC,qFAAqF,YACjG,IAAI,CAAC,IAAI,IAAI,GAAG,GACb,IACF,IACF,CACP,EAEA,OAAO,IAAI,YAAG,SAAS,EAAC,sBAAsB,YAAE,OAAO,GAAK,IACrD,CACX,CAAC;AACJ,CAAC;AAED,kFAAkF;AAElF;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,EAC9B,IAAI,EACJ,QAAQ,EACR,QAAQ,GACwB;IAChC,MAAM,OAAO,GAAG,KAAK,EAAE,CAAC;IACxB,MAAM,MAAM,GAAG,KAAK,EAAE,CAAC;IACvB,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAEpE,MAAM,YAAY,GAAG,GAAG,EAAE;QACxB,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YACjE,cAAc,CAAC,IAAI,CAAC,CAAC;YACrB,QAAQ,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;QACzC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,cAAc,CACZ,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,8BAA8B,CACxE,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,CACL,eAAK,SAAS,EAAC,YAAY,4CACzB,eAAK,SAAS,EAAC,cAAc,aAC3B,KAAC,QAAQ,IAAC,OAAO,EAAE,OAAO,sBAAkB,EAC5C,KAAC,QAAQ,IACP,EAAE,EAAE,OAAO,EACX,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE,EACvB,QAAQ,EAAE,CAAC,QAAQ,EACnB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAClB,QAAQ,CAAC,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,SAAS,EAAE,CAAC,EAE/D,WAAW,EAAC,kBAAkB,GAC9B,IACE,EAEN,eAAK,SAAS,EAAC,cAAc,aAC3B,eAAK,SAAS,EAAC,mCAAmC,aAChD,KAAC,QAAQ,IAAC,OAAO,EAAE,MAAM,uCAAmC,EAC3D,QAAQ,IAAI,CACX,iBACE,IAAI,EAAC,QAAQ,iCAEb,OAAO,EAAE,YAAY,EACrB,SAAS,EAAC,qYAAqY,uBAGxY,CACV,IACG,EACN,KAAC,WAAW,IACV,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,IAAI,CAAC,IAAI,EAChB,QAAQ,EAAE,CAAC,QAAQ,EACnB,UAAU,EAAE,KAAK,EACjB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;4BAClB,cAAc,CAAC,IAAI,CAAC,CAAC;4BACrB,QAAQ,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;wBAClD,CAAC,EACD,SAAS,EAAC,4BAA4B,EACtC,WAAW,EACT,kGAAkG,GAEpG,EACD,WAAW,IAAI,CACd,YAAG,SAAS,EAAC,wCAAwC,YAClD,WAAW,GACV,CACL,EACD,YAAG,SAAS,EAAC,+BAA+B,iIAGxC,IACA,IACF,CACP,CAAC;AACJ,CAAC","sourcesContent":["import { useId, useMemo, useState } from \"react\";\nimport { IconChevronRight, IconLock } from \"@tabler/icons-react\";\nimport { cn } from \"../../utils.js\";\nimport type { BlockEditProps, BlockReadProps } from \"../types.js\";\nimport type { OpenApiSpecData } from \"./openapi-spec.config.js\";\nimport { DevInput, DevLabel, DevTextarea } from \"./dev-doc-ui.js\";\n\n/**\n * Read + Edit renderers for an `openapi-spec` block — a Redoc / Swagger-UI-style\n * API reference rendered from a whole OpenAPI 3 / Swagger 2 document. The raw\n * `spec` TEXT (`data.spec`) is the source of truth; the Read renderer parses it\n * defensively and, on any parse error, falls back to the raw text plus the error\n * message (it never throws). Lives in core so any app can register the dev-doc\n * block (no shadcn import).\n *\n * Operations are grouped by tag; each operation is a collapsed-by-default row\n * (colored method pill + monospace path + summary) that expands to its\n * description, params table, request body, and per-status responses — the SAME\n * per-operation house style as the single-endpoint `api-endpoint` block. `$ref`\n * model references are resolved against `components.schemas` (OpenAPI 3) or\n * top-level `definitions` (Swagger 2), with a cycle guard.\n *\n * v1 parses JSON specs only (no `yaml` dependency is declared). `parseSpec` is\n * the single seam to extend when a YAML parser is added.\n *\n * DARK/LIGHT: the plan editor toggles a `.dark` class on <html>. Every color\n * token (method/status/location pills, chrome) uses Tailwind `dark:` variants or\n * the theme-aware plan CSS-var utilities, so the reference reads correctly in\n * BOTH modes (no hardcoded dark-only palette). SSR-safe: rendering derives only\n * from props (no window/document access at module or render time).\n */\n\n/* ── Theme-aware color tokens (mirrors ApiEndpointBlock) ────────────────────── */\n\nconst METHOD_PILL: Record<string, string> = {\n GET: \"bg-emerald-100 text-emerald-700 dark:bg-emerald-500/15 dark:text-emerald-300\",\n POST: \"bg-blue-100 text-blue-700 dark:bg-blue-500/15 dark:text-blue-300\",\n PUT: \"bg-amber-100 text-amber-700 dark:bg-amber-500/15 dark:text-amber-300\",\n PATCH:\n \"bg-violet-100 text-violet-700 dark:bg-violet-500/15 dark:text-violet-300\",\n DELETE: \"bg-red-100 text-red-700 dark:bg-red-500/15 dark:text-red-300\",\n HEAD: \"bg-slate-200 text-slate-700 dark:bg-slate-500/20 dark:text-slate-300\",\n OPTIONS:\n \"bg-slate-200 text-slate-700 dark:bg-slate-500/20 dark:text-slate-300\",\n TRACE: \"bg-slate-200 text-slate-700 dark:bg-slate-500/20 dark:text-slate-300\",\n};\n\nconst PARAM_IN_BADGE: Record<string, string> = {\n path: \"bg-violet-100 text-violet-700 dark:bg-violet-500/15 dark:text-violet-300\",\n query: \"bg-blue-100 text-blue-700 dark:bg-blue-500/15 dark:text-blue-300\",\n header:\n \"bg-amber-100 text-amber-700 dark:bg-amber-500/15 dark:text-amber-300\",\n cookie:\n \"bg-emerald-100 text-emerald-700 dark:bg-emerald-500/15 dark:text-emerald-300\",\n body: \"bg-emerald-100 text-emerald-700 dark:bg-emerald-500/15 dark:text-emerald-300\",\n};\n\n/** Status-pill palette keyed by the leading status digit (2xx/3xx/4xx/5xx). */\nfunction statusPillClass(status: string): string {\n const lead = status.trim().charAt(0);\n if (lead === \"2\")\n return \"bg-emerald-100 text-emerald-700 dark:bg-emerald-500/15 dark:text-emerald-300\";\n if (lead === \"4\")\n return \"bg-amber-100 text-amber-700 dark:bg-amber-500/15 dark:text-amber-300\";\n if (lead === \"5\")\n return \"bg-red-100 text-red-700 dark:bg-red-500/15 dark:text-red-300\";\n return \"bg-slate-200 text-slate-700 dark:bg-slate-500/20 dark:text-slate-300\";\n}\n\n/* ── Defensive spec parsing + normalization ────────────────────────────────── */\n\ntype Json = unknown;\ntype JsonObject = Record<string, Json>;\n\nconst HTTP_METHODS = [\n \"get\",\n \"post\",\n \"put\",\n \"patch\",\n \"delete\",\n \"head\",\n \"options\",\n \"trace\",\n] as const;\n\ninterface NormalizedParam {\n name: string;\n in: string;\n type?: string;\n required?: boolean;\n description?: string;\n}\n\ninterface NormalizedResponse {\n status: string;\n description?: string;\n /** Inline JSON example/schema preview, when derivable. */\n example?: string;\n}\n\ninterface NormalizedOperation {\n id: string;\n method: string;\n path: string;\n summary?: string;\n description?: string;\n deprecated?: boolean;\n secured?: boolean;\n tags: string[];\n params: NormalizedParam[];\n requestContentType?: string;\n requestExample?: string;\n responses: NormalizedResponse[];\n}\n\ninterface NormalizedTagGroup {\n tag: string;\n description?: string;\n operations: NormalizedOperation[];\n}\n\ninterface NormalizedSpec {\n title?: string;\n version?: string;\n description?: string;\n format: \"OpenAPI 3\" | \"Swagger 2\" | \"Unknown\";\n groups: NormalizedTagGroup[];\n operationCount: number;\n}\n\ninterface ParseResult {\n ok: boolean;\n spec?: NormalizedSpec;\n error?: string;\n}\n\nfunction isObject(value: Json): value is JsonObject {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction asString(value: Json): string | undefined {\n return typeof value === \"string\" ? value : undefined;\n}\n\n/**\n * Parse the raw spec text into a JSON object. v1 supports JSON only — a YAML\n * parser is not a declared dependency. This is the single seam to extend with\n * YAML once `yaml` is a real dependency.\n */\nfunction parseSpec(raw: string): ParseResult {\n const trimmed = raw.trim();\n if (!trimmed) {\n return {\n ok: false,\n error: \"Empty spec — paste an OpenAPI 3 / Swagger 2 document.\",\n };\n }\n let doc: Json;\n try {\n doc = JSON.parse(trimmed);\n } catch (error) {\n const hint =\n /^[A-Za-z][\\w-]*\\s*:/.test(trimmed) || trimmed.startsWith(\"---\")\n ? \" (YAML is not supported yet — paste JSON, or convert the spec to JSON.)\"\n : \"\";\n return {\n ok: false,\n error: `${error instanceof Error ? error.message : \"Invalid JSON\"}${hint}`,\n };\n }\n if (!isObject(doc)) {\n return { ok: false, error: \"Spec must be a JSON object.\" };\n }\n try {\n return { ok: true, spec: normalizeSpec(doc) };\n } catch (error) {\n return {\n ok: false,\n error:\n error instanceof Error\n ? error.message\n : \"Could not interpret the spec document.\",\n };\n }\n}\n\n/** Resolve a local `$ref` (e.g. `#/components/schemas/User`) against the root. */\nfunction resolveRef(\n root: JsonObject,\n ref: string,\n seen: Set<string>,\n): Json | undefined {\n if (!ref.startsWith(\"#/\")) return undefined;\n if (seen.has(ref)) return undefined; // cycle guard\n seen.add(ref);\n const segments = ref\n .slice(2)\n .split(\"/\")\n .map((seg) => seg.replace(/~1/g, \"/\").replace(/~0/g, \"~\"));\n let current: Json = root;\n for (const segment of segments) {\n if (!isObject(current)) return undefined;\n current = current[segment];\n }\n return current;\n}\n\n/** Follow a single `$ref` hop on a schema/param object if present. */\nfunction deref(root: JsonObject, value: Json, seen: Set<string>): Json {\n let current = value;\n let guard = 0;\n while (isObject(current) && typeof current.$ref === \"string\" && guard < 20) {\n const resolved = resolveRef(root, current.$ref, seen);\n if (resolved === undefined) return current;\n current = resolved;\n guard += 1;\n }\n return current;\n}\n\n/** Short human type label for a (deref'd) schema object. */\nfunction schemaTypeLabel(\n root: JsonObject,\n schema: Json,\n seen: Set<string>,\n): string | undefined {\n const resolved = deref(root, schema, new Set(seen));\n if (!isObject(resolved)) return undefined;\n if (typeof resolved.type === \"string\") {\n if (resolved.type === \"array\" && resolved.items) {\n const inner = schemaTypeLabel(root, resolved.items, seen);\n return inner ? `${inner}[]` : \"array\";\n }\n return resolved.type;\n }\n if (resolved.$ref && typeof resolved.$ref === \"string\") {\n return resolved.$ref.split(\"/\").pop();\n }\n if (resolved.enum) return \"enum\";\n if (resolved.properties) return \"object\";\n if (resolved.oneOf || resolved.anyOf || resolved.allOf) return \"object\";\n return undefined;\n}\n\n/**\n * Build a compact JSON skeleton from a (resolved) schema so the request/response\n * panels can show a Swagger-UI-style model preview. Bounded depth + a cycle\n * guard keep it safe on recursive models.\n */\nfunction schemaExample(\n root: JsonObject,\n schema: Json,\n seen: Set<string>,\n depth: number,\n): Json {\n if (depth > 6) return \"…\";\n const resolved = deref(root, schema, new Set(seen));\n if (!isObject(resolved)) return resolved ?? null;\n if (resolved.example !== undefined) return resolved.example;\n if (resolved.default !== undefined) return resolved.default;\n if (Array.isArray(resolved.enum) && resolved.enum.length > 0) {\n return resolved.enum[0];\n }\n\n const allOf = Array.isArray(resolved.allOf) ? resolved.allOf : null;\n if (allOf) {\n const merged: JsonObject = {};\n for (const part of allOf) {\n const value = schemaExample(root, part, seen, depth + 1);\n if (isObject(value)) Object.assign(merged, value);\n }\n if (Object.keys(merged).length > 0) return merged;\n }\n const oneOf =\n (Array.isArray(resolved.oneOf) && resolved.oneOf) ||\n (Array.isArray(resolved.anyOf) && resolved.anyOf) ||\n null;\n if (oneOf && oneOf.length > 0) {\n return schemaExample(root, oneOf[0], seen, depth + 1);\n }\n\n const type = resolved.type;\n if (type === \"object\" || resolved.properties) {\n const props = isObject(resolved.properties) ? resolved.properties : {};\n const out: JsonObject = {};\n for (const [key, propSchema] of Object.entries(props).slice(0, 30)) {\n out[key] = schemaExample(root, propSchema, seen, depth + 1);\n }\n return out;\n }\n if (type === \"array\") {\n return [schemaExample(root, resolved.items ?? {}, seen, depth + 1)];\n }\n if (type === \"integer\" || type === \"number\") return 0;\n if (type === \"boolean\") return true;\n if (type === \"string\") {\n if (resolved.format === \"date-time\") return \"2020-01-01T00:00:00Z\";\n if (resolved.format === \"uuid\")\n return \"00000000-0000-0000-0000-000000000000\";\n return \"string\";\n }\n return null;\n}\n\n/** Stringify a derived example, guarding against oversized payloads. */\nfunction stringifyExample(value: Json): string | undefined {\n try {\n const text = JSON.stringify(value, null, 2);\n if (!text || text === \"null\" || text === \"{}\" || text === \"[]\")\n return undefined;\n return text.length > 8_000 ? `${text.slice(0, 8_000)}\\n…` : text;\n } catch {\n return undefined;\n }\n}\n\nfunction normalizeParam(\n root: JsonObject,\n raw: Json,\n seen: Set<string>,\n): NormalizedParam | undefined {\n const param = deref(root, raw, new Set(seen));\n if (!isObject(param)) return undefined;\n const name = asString(param.name);\n const location = asString(param.in);\n if (!name || !location) return undefined;\n // OpenAPI 3 nests type under `schema`; Swagger 2 puts it on the param.\n const type =\n schemaTypeLabel(root, param.schema, seen) ?? asString(param.type);\n return {\n name,\n in: location,\n type,\n required: param.required === true,\n description: asString(param.description),\n };\n}\n\nfunction normalizeOperation(\n root: JsonObject,\n path: string,\n method: string,\n rawOp: Json,\n pathLevelParams: NormalizedParam[],\n seen: Set<string>,\n): NormalizedOperation | undefined {\n if (!isObject(rawOp)) return undefined;\n\n const params: NormalizedParam[] = [...pathLevelParams];\n if (Array.isArray(rawOp.parameters)) {\n for (const rawParam of rawOp.parameters) {\n const normalized = normalizeParam(root, rawParam, seen);\n if (normalized) params.push(normalized);\n }\n }\n\n // Request body: OpenAPI 3 `requestBody.content[*].schema`; Swagger 2 `body` param.\n let requestContentType: string | undefined;\n let requestExample: string | undefined;\n const requestBody = deref(root, rawOp.requestBody, new Set(seen));\n if (isObject(requestBody) && isObject(requestBody.content)) {\n const [contentType, media] = Object.entries(requestBody.content)[0] ?? [];\n requestContentType = contentType;\n if (isObject(media)) {\n requestExample =\n stringifyExample(media.example) ??\n stringifyExample(schemaExample(root, media.schema, seen, 0));\n }\n } else {\n const bodyParam = params.find((p) => p.in === \"body\");\n if (bodyParam) {\n // Swagger 2 body param carries its schema on the raw parameter.\n const rawBody = Array.isArray(rawOp.parameters)\n ? rawOp.parameters.find(\n (p) =>\n isObject(deref(root, p, new Set(seen))) &&\n asString((deref(root, p, new Set(seen)) as JsonObject).in) ===\n \"body\",\n )\n : undefined;\n const resolvedBody = isObject(deref(root, rawBody, new Set(seen)))\n ? (deref(root, rawBody, new Set(seen)) as JsonObject)\n : undefined;\n requestContentType = \"application/json\";\n requestExample = stringifyExample(\n schemaExample(root, resolvedBody?.schema, seen, 0),\n );\n }\n }\n // Swagger 2 `body` params are represented via requestBody above; drop them\n // from the visible param table so they don't double-render.\n const visibleParams = params.filter((p) => p.in !== \"body\");\n\n const responses: NormalizedResponse[] = [];\n if (isObject(rawOp.responses)) {\n for (const [status, rawResponse] of Object.entries(rawOp.responses)) {\n const response = deref(root, rawResponse, new Set(seen));\n let example: string | undefined;\n if (isObject(response)) {\n // OpenAPI 3: response.content[*].schema; Swagger 2: response.schema.\n if (isObject(response.content)) {\n const media = Object.values(response.content)[0];\n if (isObject(media)) {\n example =\n stringifyExample(media.example) ??\n stringifyExample(schemaExample(root, media.schema, seen, 0));\n }\n } else if (response.schema) {\n example = stringifyExample(\n schemaExample(root, response.schema, seen, 0),\n );\n }\n }\n responses.push({\n status,\n description: isObject(response)\n ? asString(response.description)\n : undefined,\n example,\n });\n }\n }\n\n const tags =\n Array.isArray(rawOp.tags) && rawOp.tags.length > 0\n ? rawOp.tags.filter((t): t is string => typeof t === \"string\")\n : [];\n\n const secured =\n Array.isArray(rawOp.security) && rawOp.security.length > 0\n ? rawOp.security.some(\n (req) => isObject(req) && Object.keys(req).length > 0,\n )\n : undefined;\n\n return {\n id: `${method}-${path}`,\n method: method.toUpperCase(),\n path,\n summary: asString(rawOp.summary),\n description: asString(rawOp.description),\n deprecated: rawOp.deprecated === true,\n secured,\n tags: tags.length > 0 ? tags : [\"default\"],\n params: visibleParams,\n requestContentType,\n requestExample,\n responses: responses.sort((a, b) => a.status.localeCompare(b.status)),\n };\n}\n\nfunction normalizeSpec(doc: JsonObject): NormalizedSpec {\n const format: NormalizedSpec[\"format\"] =\n typeof doc.openapi === \"string\"\n ? \"OpenAPI 3\"\n : typeof doc.swagger === \"string\"\n ? \"Swagger 2\"\n : \"Unknown\";\n\n const info = isObject(doc.info) ? doc.info : undefined;\n\n // Global security requirement → every operation without its own override is\n // secured. Operation-level `security: []` opts out; we treat presence here as\n // the default-secured signal.\n const globalSecured =\n Array.isArray(doc.security) &&\n doc.security.some((req) => isObject(req) && Object.keys(req).length > 0);\n\n // Tag order + descriptions from the document's top-level `tags`.\n const tagOrder: string[] = [];\n const tagDescriptions = new Map<string, string>();\n if (Array.isArray(doc.tags)) {\n for (const tag of doc.tags) {\n if (isObject(tag) && typeof tag.name === \"string\") {\n tagOrder.push(tag.name);\n if (typeof tag.description === \"string\") {\n tagDescriptions.set(tag.name, tag.description);\n }\n }\n }\n }\n\n const groups = new Map<string, NormalizedOperation[]>();\n let operationCount = 0;\n\n const paths = isObject(doc.paths) ? doc.paths : {};\n for (const [path, rawPathItem] of Object.entries(paths)) {\n const seen = new Set<string>();\n const pathItem = deref(doc, rawPathItem, seen);\n if (!isObject(pathItem)) continue;\n\n const pathLevelParams: NormalizedParam[] = [];\n if (Array.isArray(pathItem.parameters)) {\n for (const rawParam of pathItem.parameters) {\n const normalized = normalizeParam(doc, rawParam, new Set());\n if (normalized) pathLevelParams.push(normalized);\n }\n }\n\n for (const method of HTTP_METHODS) {\n const rawOp = pathItem[method];\n if (!isObject(rawOp)) continue;\n const operation = normalizeOperation(\n doc,\n path,\n method,\n rawOp,\n pathLevelParams,\n new Set(),\n );\n if (!operation) continue;\n if (operation.secured === undefined && globalSecured) {\n operation.secured = true;\n }\n operationCount += 1;\n for (const tag of operation.tags) {\n const list = groups.get(tag) ?? [];\n list.push(operation);\n groups.set(tag, list);\n }\n }\n }\n\n // Order: documented tags first (in their declared order), then any remaining\n // tags alphabetically.\n const orderedTagNames = [\n ...tagOrder.filter((tag) => groups.has(tag)),\n ...[...groups.keys()]\n .filter((tag) => !tagOrder.includes(tag))\n .sort((a, b) => a.localeCompare(b)),\n ];\n\n const groupList: NormalizedTagGroup[] = orderedTagNames.map((tag) => ({\n tag,\n description: tagDescriptions.get(tag),\n operations: groups.get(tag) ?? [],\n }));\n\n return {\n title: info ? asString(info.title) : undefined,\n version: info ? asString(info.version) : undefined,\n description: info ? asString(info.description) : undefined,\n format,\n groups: groupList,\n operationCount,\n };\n}\n\n/* ── Operation row (collapsed-by-default, mirrors api-endpoint) ─────────────── */\n\nfunction OperationRow({\n operation,\n renderMarkdown,\n}: {\n operation: NormalizedOperation;\n renderMarkdown?: (markdown: string) => React.ReactNode;\n}) {\n const [open, setOpen] = useState(false);\n\n const hasBody =\n Boolean(operation.description?.trim()) ||\n operation.params.length > 0 ||\n Boolean(operation.requestExample || operation.requestContentType) ||\n operation.responses.length > 0;\n\n return (\n <div className=\"overflow-hidden border-t border-plan-line first:border-t-0\">\n <button\n type=\"button\"\n data-plan-interactive\n aria-expanded={open}\n onClick={() => setOpen((value) => !value)}\n className={cn(\n \"flex w-full items-center gap-3 px-4 py-2.5 text-left transition-colors\",\n \"hover:bg-accent/40\",\n )}\n >\n <IconChevronRight\n className={cn(\n \"size-4 shrink-0 text-plan-muted transition-transform\",\n open && \"rotate-90\",\n )}\n />\n <span\n className={cn(\n \"shrink-0 rounded-md px-2 py-1 font-mono text-xs font-bold uppercase tracking-wide\",\n METHOD_PILL[operation.method] ??\n \"bg-slate-200 text-slate-700 dark:bg-slate-500/20 dark:text-slate-300\",\n )}\n >\n {operation.method}\n </span>\n <span\n className={cn(\n \"min-w-0 truncate font-mono text-sm font-semibold text-plan-text\",\n operation.deprecated && \"text-plan-muted line-through\",\n )}\n >\n {operation.path}\n </span>\n {operation.summary && (\n <span className=\"ml-1 min-w-0 flex-1 truncate text-sm text-plan-muted\">\n {operation.summary}\n </span>\n )}\n {operation.secured && (\n <IconLock\n className=\"size-3.5 shrink-0 text-plan-muted\"\n aria-label=\"Requires authentication\"\n />\n )}\n </button>\n\n {open && hasBody && (\n <div className=\"border-t border-plan-line bg-plan-block px-4 py-4\">\n {operation.description?.trim() && (\n <div className=\"an-api-endpoint-desc\">\n {renderMarkdown ? (\n renderMarkdown(operation.description)\n ) : (\n <p className=\"text-sm text-plan-muted\">\n {operation.description}\n </p>\n )}\n </div>\n )}\n\n {operation.params.length > 0 && (\n <div className=\"mt-4\">\n <div className=\"text-xs font-semibold uppercase tracking-wide text-plan-muted\">\n Parameters\n </div>\n <div className=\"mt-2 overflow-hidden rounded-lg border border-plan-line\">\n <table className=\"w-full border-collapse text-sm\">\n <thead>\n <tr className=\"bg-accent/30 text-left text-xs uppercase tracking-wide text-plan-muted\">\n <th className=\"px-3 py-2 font-medium\">Name</th>\n <th className=\"px-3 py-2 font-medium\">In</th>\n <th className=\"px-3 py-2 font-medium\">Type</th>\n <th className=\"px-3 py-2 font-medium\">Required</th>\n <th className=\"px-3 py-2 font-medium\">Description</th>\n </tr>\n </thead>\n <tbody>\n {operation.params.map((param, index) => (\n <tr\n key={`${param.name}-${param.in}-${index}`}\n className=\"border-t border-plan-line align-top\"\n >\n <td className=\"px-3 py-2 font-mono text-xs font-semibold text-plan-text\">\n {param.name}\n </td>\n <td className=\"px-3 py-2\">\n <span\n className={cn(\n \"rounded px-1.5 py-0.5 font-mono text-[11px] font-semibold\",\n PARAM_IN_BADGE[param.in] ??\n \"bg-slate-200 text-slate-700 dark:bg-slate-500/20 dark:text-slate-300\",\n )}\n >\n {param.in}\n </span>\n </td>\n <td className=\"px-3 py-2 font-mono text-xs text-plan-muted\">\n {param.type || \"—\"}\n </td>\n <td className=\"px-3 py-2 text-xs\">\n {param.required ? (\n <span className=\"font-medium text-red-600 dark:text-red-300\">\n required\n </span>\n ) : (\n <span className=\"text-plan-muted\">optional</span>\n )}\n </td>\n <td className=\"px-3 py-2 text-xs text-plan-muted\">\n {param.description || \"—\"}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n )}\n\n {(operation.requestExample || operation.requestContentType) && (\n <div className=\"mt-4\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs font-semibold uppercase tracking-wide text-plan-muted\">\n Request body\n </span>\n {operation.requestContentType && (\n <span className=\"rounded bg-accent/40 px-1.5 py-0.5 font-mono text-[11px] text-plan-muted\">\n {operation.requestContentType}\n </span>\n )}\n </div>\n {operation.requestExample && (\n <pre className=\"mt-2 overflow-auto rounded-lg border border-plan-line bg-plan-code px-3 py-2 font-mono text-xs text-plan-code-text\">\n {operation.requestExample}\n </pre>\n )}\n </div>\n )}\n\n {operation.responses.length > 0 && (\n <div className=\"mt-4\">\n <div className=\"text-xs font-semibold uppercase tracking-wide text-plan-muted\">\n Responses\n </div>\n <div className=\"mt-2 flex flex-col gap-3\">\n {operation.responses.map((response, index) => (\n <div\n key={`${response.status}-${index}`}\n className=\"rounded-lg border border-plan-line\"\n >\n <div className=\"flex items-center gap-2 px-3 py-2\">\n <span\n className={cn(\n \"rounded px-2 py-0.5 font-mono text-xs font-bold\",\n statusPillClass(response.status),\n )}\n >\n {response.status}\n </span>\n {response.description && (\n <span className=\"text-sm text-plan-muted\">\n {response.description}\n </span>\n )}\n </div>\n {response.example && (\n <pre className=\"overflow-auto border-t border-plan-line bg-plan-code px-3 py-2 font-mono text-xs text-plan-code-text\">\n {response.example}\n </pre>\n )}\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n );\n}\n\n/* ── Tag group (collapsed-by-default) ──────────────────────────────────────── */\n\nfunction TagGroup({\n group,\n defaultOpen,\n renderMarkdown,\n}: {\n group: NormalizedTagGroup;\n defaultOpen: boolean;\n renderMarkdown?: (markdown: string) => React.ReactNode;\n}) {\n const [open, setOpen] = useState(defaultOpen);\n return (\n <div className=\"overflow-hidden rounded-xl border border-plan-line bg-plan-block\">\n <button\n type=\"button\"\n data-plan-interactive\n aria-expanded={open}\n onClick={() => setOpen((value) => !value)}\n className=\"flex w-full items-center gap-2 px-4 py-3 text-left transition-colors hover:bg-accent/40\"\n >\n <IconChevronRight\n className={cn(\n \"size-4 shrink-0 text-plan-muted transition-transform\",\n open && \"rotate-90\",\n )}\n />\n <span className=\"font-semibold text-plan-text\">{group.tag}</span>\n <span className=\"rounded-full bg-accent/40 px-2 py-0.5 text-[11px] font-medium text-plan-muted\">\n {group.operations.length}\n </span>\n {group.description && (\n <span className=\"ml-1 min-w-0 flex-1 truncate text-sm text-plan-muted\">\n {group.description}\n </span>\n )}\n </button>\n {open && (\n <div className=\"border-t border-plan-line\">\n {group.operations.map((operation) => (\n <OperationRow\n key={operation.id}\n operation={operation}\n renderMarkdown={renderMarkdown}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\n/* ── Read (Redoc / Swagger-UI-style reference) ─────────────────────────────── */\n\n/**\n * Read-only renderer for an `openapi-spec` block. Parses `data.spec` defensively\n * and renders a Redoc / Swagger-UI-style reference: a header (title + version +\n * format badge), then operations grouped by tag, each a collapsed-by-default row\n * that expands to the full per-operation reference. On a parse error it shows the\n * error plus the raw payload (never throws).\n */\nexport function OpenApiSpecRead({\n data,\n blockId,\n title,\n summary,\n ctx,\n}: BlockReadProps<OpenApiSpecData>) {\n const parsed = useMemo(() => parseSpec(data.spec), [data.spec]);\n const heading = data.title ?? title;\n const renderMarkdown = ctx.renderMarkdown;\n\n return (\n <section className=\"plan-block\" data-block-id={blockId}>\n {heading && <div className=\"plan-block-label\">{heading}</div>}\n\n {parsed.ok && parsed.spec ? (\n <div className=\"flex flex-col gap-3\">\n <div className=\"overflow-hidden rounded-xl border border-plan-line bg-plan-block px-4 py-3\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"font-semibold text-plan-text\">\n {parsed.spec.title || \"API reference\"}\n </span>\n {parsed.spec.version && (\n <span className=\"rounded bg-accent/40 px-1.5 py-0.5 font-mono text-[11px] text-plan-muted\">\n v{parsed.spec.version}\n </span>\n )}\n <span className=\"rounded-full border border-plan-line px-2 py-0.5 text-[11px] font-medium text-plan-muted\">\n {parsed.spec.format}\n </span>\n <span className=\"text-xs text-plan-muted\">\n {parsed.spec.operationCount}{\" \"}\n {parsed.spec.operationCount === 1 ? \"operation\" : \"operations\"}\n </span>\n </div>\n {parsed.spec.description?.trim() && (\n <div className=\"mt-2 an-api-endpoint-desc\">\n {renderMarkdown ? (\n renderMarkdown(parsed.spec.description)\n ) : (\n <p className=\"text-sm text-plan-muted\">\n {parsed.spec.description}\n </p>\n )}\n </div>\n )}\n </div>\n\n {parsed.spec.groups.length === 0 ? (\n <div className=\"rounded-xl border border-plan-line bg-plan-block px-4 py-6 text-center text-sm text-plan-muted\">\n No operations found in this spec.\n </div>\n ) : (\n parsed.spec.groups.map((group, index) => (\n <TagGroup\n key={group.tag}\n group={group}\n // Open the first group by default so the reference is not a wall\n // of collapsed accordions on first paint.\n defaultOpen={index === 0}\n renderMarkdown={renderMarkdown}\n />\n ))\n )}\n </div>\n ) : (\n <div className=\"overflow-hidden rounded-xl border border-plan-line bg-plan-code\">\n <div className=\"border-b border-plan-line px-3 py-1.5\">\n <span className=\"font-mono text-xs uppercase tracking-wide text-plan-muted\">\n OpenAPI\n </span>\n </div>\n <div className=\"space-y-2 px-3 py-2.5\">\n <p className=\"text-xs text-red-600 dark:text-red-300\">\n Could not parse spec: {parsed.error}\n </p>\n <pre className=\"overflow-auto whitespace-pre-wrap break-words font-mono text-xs text-plan-code-text\">\n {data.spec || \"—\"}\n </pre>\n </div>\n </div>\n )}\n\n {summary && <p className=\"mt-5 text-plan-muted\">{summary}</p>}\n </section>\n );\n}\n\n/* ── Edit (panel form) ─────────────────────────────────────────────────────── */\n\n/**\n * Panel editor for an `openapi-spec` block: a `title` input plus a monospace\n * textarea bound to the raw `spec`, with a \"Format\" button that pretty-prints via\n * `JSON.parse` → `JSON.stringify(_, null, 2)` (guarded — shows an INLINE error,\n * never `window.alert`). Renders BARE content (no `<section>`); the registry's\n * panel surface supplies the popover chrome.\n */\nexport function OpenApiSpecEdit({\n data,\n onChange,\n editable,\n}: BlockEditProps<OpenApiSpecData>) {\n const titleId = useId();\n const specId = useId();\n const [formatError, setFormatError] = useState<string | null>(null);\n\n const handleFormat = () => {\n try {\n const formatted = JSON.stringify(JSON.parse(data.spec), null, 2);\n setFormatError(null);\n onChange({ ...data, spec: formatted });\n } catch (error) {\n setFormatError(\n error instanceof Error ? error.message : \"Invalid JSON — cannot format\",\n );\n }\n };\n\n return (\n <div className=\"grid gap-3\" data-plan-interactive>\n <div className=\"grid gap-1.5\">\n <DevLabel htmlFor={titleId}>Title</DevLabel>\n <DevInput\n id={titleId}\n value={data.title ?? \"\"}\n readOnly={!editable}\n onChange={(event) =>\n onChange({ ...data, title: event.target.value || undefined })\n }\n placeholder=\"Optional heading\"\n />\n </div>\n\n <div className=\"grid gap-1.5\">\n <div className=\"flex items-center justify-between\">\n <DevLabel htmlFor={specId}>OpenAPI / Swagger spec</DevLabel>\n {editable && (\n <button\n type=\"button\"\n data-plan-interactive\n onClick={handleFormat}\n className=\"inline-flex h-7 cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md border border-input bg-background px-2 text-xs font-medium ring-offset-background transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50\"\n >\n Format\n </button>\n )}\n </div>\n <DevTextarea\n id={specId}\n value={data.spec}\n readOnly={!editable}\n spellCheck={false}\n onChange={(event) => {\n setFormatError(null);\n onChange({ ...data, spec: event.target.value });\n }}\n className=\"min-h-72 font-mono text-xs\"\n placeholder={\n '{\\n \"openapi\": \"3.0.0\",\\n \"info\": { \"title\": \"My API\", \"version\": \"1.0.0\" },\\n \"paths\": {}\\n}'\n }\n />\n {formatError && (\n <p className=\"text-xs text-red-600 dark:text-red-300\">\n {formatError}\n </p>\n )}\n <p className=\"text-xs text-muted-foreground\">\n Paste a complete OpenAPI 3 or Swagger 2 document. v1 supports JSON\n specs only — convert YAML to JSON first.\n </p>\n </div>\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"OpenApiSpecBlock.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/OpenApiSpecBlock.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useId, useMemo, useState } from \"react\";\nimport { IconChevronRight, IconLock } from \"@tabler/icons-react\";\nimport { cn } from \"../../utils.js\";\nimport type { BlockEditProps, BlockReadProps } from \"../types.js\";\nimport type { OpenApiSpecData } from \"./openapi-spec.config.js\";\nimport { DevInput, DevLabel, DevTextarea } from \"./dev-doc-ui.js\";\nimport { CodeSurface } from \"./HighlightedCode.js\";\n\n/**\n * Read + Edit renderers for an `openapi-spec` block — a Redoc / Swagger-UI-style\n * API reference rendered from a whole OpenAPI 3 / Swagger 2 document. The raw\n * `spec` TEXT (`data.spec`) is the source of truth; the Read renderer parses it\n * defensively and, on any parse error, falls back to the raw text plus the error\n * message (it never throws). Lives in core so any app can register the dev-doc\n * block (no shadcn import).\n *\n * Operations are grouped by tag; each operation is a collapsed-by-default row\n * (colored method pill + monospace path + summary) that expands to its\n * description, params table, request body, and per-status responses — the SAME\n * per-operation house style as the single-endpoint `api-endpoint` block. `$ref`\n * model references are resolved against `components.schemas` (OpenAPI 3) or\n * top-level `definitions` (Swagger 2), with a cycle guard.\n *\n * v1 parses JSON specs only (no `yaml` dependency is declared). `parseSpec` is\n * the single seam to extend when a YAML parser is added.\n *\n * DARK/LIGHT: the plan editor toggles a `.dark` class on <html>. Every color\n * token (method/status/location pills, chrome) uses Tailwind `dark:` variants or\n * the theme-aware plan CSS-var utilities, so the reference reads correctly in\n * BOTH modes (no hardcoded dark-only palette). SSR-safe: rendering derives only\n * from props (no window/document access at module or render time).\n */\n\n/* ── Theme-aware color tokens (mirrors ApiEndpointBlock) ────────────────────── */\n\nconst METHOD_PILL: Record<string, string> = {\n GET: \"bg-emerald-100 text-emerald-700 dark:bg-emerald-500/15 dark:text-emerald-300\",\n POST: \"bg-blue-100 text-blue-700 dark:bg-blue-500/15 dark:text-blue-300\",\n PUT: \"bg-amber-100 text-amber-700 dark:bg-amber-500/15 dark:text-amber-300\",\n PATCH:\n \"bg-violet-100 text-violet-700 dark:bg-violet-500/15 dark:text-violet-300\",\n DELETE: \"bg-red-100 text-red-700 dark:bg-red-500/15 dark:text-red-300\",\n HEAD: \"bg-slate-200 text-slate-700 dark:bg-slate-500/20 dark:text-slate-300\",\n OPTIONS:\n \"bg-slate-200 text-slate-700 dark:bg-slate-500/20 dark:text-slate-300\",\n TRACE: \"bg-slate-200 text-slate-700 dark:bg-slate-500/20 dark:text-slate-300\",\n};\n\nconst PARAM_IN_BADGE: Record<string, string> = {\n path: \"bg-violet-100 text-violet-700 dark:bg-violet-500/15 dark:text-violet-300\",\n query: \"bg-blue-100 text-blue-700 dark:bg-blue-500/15 dark:text-blue-300\",\n header:\n \"bg-amber-100 text-amber-700 dark:bg-amber-500/15 dark:text-amber-300\",\n cookie:\n \"bg-emerald-100 text-emerald-700 dark:bg-emerald-500/15 dark:text-emerald-300\",\n body: \"bg-emerald-100 text-emerald-700 dark:bg-emerald-500/15 dark:text-emerald-300\",\n};\n\n/** Status-pill palette keyed by the leading status digit (2xx/3xx/4xx/5xx). */\nfunction statusPillClass(status: string): string {\n const lead = status.trim().charAt(0);\n if (lead === \"2\")\n return \"bg-emerald-100 text-emerald-700 dark:bg-emerald-500/15 dark:text-emerald-300\";\n if (lead === \"4\")\n return \"bg-amber-100 text-amber-700 dark:bg-amber-500/15 dark:text-amber-300\";\n if (lead === \"5\")\n return \"bg-red-100 text-red-700 dark:bg-red-500/15 dark:text-red-300\";\n return \"bg-slate-200 text-slate-700 dark:bg-slate-500/20 dark:text-slate-300\";\n}\n\n/* ── Defensive spec parsing + normalization ────────────────────────────────── */\n\ntype Json = unknown;\ntype JsonObject = Record<string, Json>;\n\nconst HTTP_METHODS = [\n \"get\",\n \"post\",\n \"put\",\n \"patch\",\n \"delete\",\n \"head\",\n \"options\",\n \"trace\",\n] as const;\n\ninterface NormalizedParam {\n name: string;\n in: string;\n type?: string;\n required?: boolean;\n description?: string;\n}\n\ninterface NormalizedResponse {\n status: string;\n description?: string;\n /** Inline JSON example/schema preview, when derivable. */\n example?: string;\n}\n\ninterface NormalizedOperation {\n id: string;\n method: string;\n path: string;\n summary?: string;\n description?: string;\n deprecated?: boolean;\n secured?: boolean;\n tags: string[];\n params: NormalizedParam[];\n requestContentType?: string;\n requestExample?: string;\n responses: NormalizedResponse[];\n}\n\ninterface NormalizedTagGroup {\n tag: string;\n description?: string;\n operations: NormalizedOperation[];\n}\n\ninterface NormalizedSpec {\n title?: string;\n version?: string;\n description?: string;\n format: \"OpenAPI 3\" | \"Swagger 2\" | \"Unknown\";\n groups: NormalizedTagGroup[];\n operationCount: number;\n}\n\ninterface ParseResult {\n ok: boolean;\n spec?: NormalizedSpec;\n error?: string;\n}\n\nfunction isObject(value: Json): value is JsonObject {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction asString(value: Json): string | undefined {\n return typeof value === \"string\" ? value : undefined;\n}\n\n/**\n * Parse the raw spec text into a JSON object. v1 supports JSON only — a YAML\n * parser is not a declared dependency. This is the single seam to extend with\n * YAML once `yaml` is a real dependency.\n */\nfunction parseSpec(raw: string): ParseResult {\n const trimmed = raw.trim();\n if (!trimmed) {\n return {\n ok: false,\n error: \"Empty spec — paste an OpenAPI 3 / Swagger 2 document.\",\n };\n }\n let doc: Json;\n try {\n doc = JSON.parse(trimmed);\n } catch (error) {\n const hint =\n /^[A-Za-z][\\w-]*\\s*:/.test(trimmed) || trimmed.startsWith(\"---\")\n ? \" (YAML is not supported yet — paste JSON, or convert the spec to JSON.)\"\n : \"\";\n return {\n ok: false,\n error: `${error instanceof Error ? error.message : \"Invalid JSON\"}${hint}`,\n };\n }\n if (!isObject(doc)) {\n return { ok: false, error: \"Spec must be a JSON object.\" };\n }\n try {\n return { ok: true, spec: normalizeSpec(doc) };\n } catch (error) {\n return {\n ok: false,\n error:\n error instanceof Error\n ? error.message\n : \"Could not interpret the spec document.\",\n };\n }\n}\n\n/** Resolve a local `$ref` (e.g. `#/components/schemas/User`) against the root. */\nfunction resolveRef(\n root: JsonObject,\n ref: string,\n seen: Set<string>,\n): Json | undefined {\n if (!ref.startsWith(\"#/\")) return undefined;\n if (seen.has(ref)) return undefined; // cycle guard\n seen.add(ref);\n const segments = ref\n .slice(2)\n .split(\"/\")\n .map((seg) => seg.replace(/~1/g, \"/\").replace(/~0/g, \"~\"));\n let current: Json = root;\n for (const segment of segments) {\n if (!isObject(current)) return undefined;\n current = current[segment];\n }\n return current;\n}\n\n/** Follow a single `$ref` hop on a schema/param object if present. */\nfunction deref(root: JsonObject, value: Json, seen: Set<string>): Json {\n let current = value;\n let guard = 0;\n while (isObject(current) && typeof current.$ref === \"string\" && guard < 20) {\n const resolved = resolveRef(root, current.$ref, seen);\n if (resolved === undefined) return current;\n current = resolved;\n guard += 1;\n }\n return current;\n}\n\n/** Short human type label for a (deref'd) schema object. */\nfunction schemaTypeLabel(\n root: JsonObject,\n schema: Json,\n seen: Set<string>,\n): string | undefined {\n const resolved = deref(root, schema, new Set(seen));\n if (!isObject(resolved)) return undefined;\n if (typeof resolved.type === \"string\") {\n if (resolved.type === \"array\" && resolved.items) {\n const inner = schemaTypeLabel(root, resolved.items, seen);\n return inner ? `${inner}[]` : \"array\";\n }\n return resolved.type;\n }\n if (resolved.$ref && typeof resolved.$ref === \"string\") {\n return resolved.$ref.split(\"/\").pop();\n }\n if (resolved.enum) return \"enum\";\n if (resolved.properties) return \"object\";\n if (resolved.oneOf || resolved.anyOf || resolved.allOf) return \"object\";\n return undefined;\n}\n\n/**\n * Build a compact JSON skeleton from a (resolved) schema so the request/response\n * panels can show a Swagger-UI-style model preview. Bounded depth + a cycle\n * guard keep it safe on recursive models.\n */\nfunction schemaExample(\n root: JsonObject,\n schema: Json,\n seen: Set<string>,\n depth: number,\n): Json {\n if (depth > 6) return \"…\";\n const resolved = deref(root, schema, new Set(seen));\n if (!isObject(resolved)) return resolved ?? null;\n if (resolved.example !== undefined) return resolved.example;\n if (resolved.default !== undefined) return resolved.default;\n if (Array.isArray(resolved.enum) && resolved.enum.length > 0) {\n return resolved.enum[0];\n }\n\n const allOf = Array.isArray(resolved.allOf) ? resolved.allOf : null;\n if (allOf) {\n const merged: JsonObject = {};\n for (const part of allOf) {\n const value = schemaExample(root, part, seen, depth + 1);\n if (isObject(value)) Object.assign(merged, value);\n }\n if (Object.keys(merged).length > 0) return merged;\n }\n const oneOf =\n (Array.isArray(resolved.oneOf) && resolved.oneOf) ||\n (Array.isArray(resolved.anyOf) && resolved.anyOf) ||\n null;\n if (oneOf && oneOf.length > 0) {\n return schemaExample(root, oneOf[0], seen, depth + 1);\n }\n\n const type = resolved.type;\n if (type === \"object\" || resolved.properties) {\n const props = isObject(resolved.properties) ? resolved.properties : {};\n const out: JsonObject = {};\n for (const [key, propSchema] of Object.entries(props).slice(0, 30)) {\n out[key] = schemaExample(root, propSchema, seen, depth + 1);\n }\n return out;\n }\n if (type === \"array\") {\n return [schemaExample(root, resolved.items ?? {}, seen, depth + 1)];\n }\n if (type === \"integer\" || type === \"number\") return 0;\n if (type === \"boolean\") return true;\n if (type === \"string\") {\n if (resolved.format === \"date-time\") return \"2020-01-01T00:00:00Z\";\n if (resolved.format === \"uuid\")\n return \"00000000-0000-0000-0000-000000000000\";\n return \"string\";\n }\n return null;\n}\n\n/** Stringify a derived example, guarding against oversized payloads. */\nfunction stringifyExample(value: Json): string | undefined {\n try {\n const text = JSON.stringify(value, null, 2);\n if (!text || text === \"null\" || text === \"{}\" || text === \"[]\")\n return undefined;\n return text.length > 8_000 ? `${text.slice(0, 8_000)}\\n…` : text;\n } catch {\n return undefined;\n }\n}\n\nfunction normalizeParam(\n root: JsonObject,\n raw: Json,\n seen: Set<string>,\n): NormalizedParam | undefined {\n const param = deref(root, raw, new Set(seen));\n if (!isObject(param)) return undefined;\n const name = asString(param.name);\n const location = asString(param.in);\n if (!name || !location) return undefined;\n // OpenAPI 3 nests type under `schema`; Swagger 2 puts it on the param.\n const type =\n schemaTypeLabel(root, param.schema, seen) ?? asString(param.type);\n return {\n name,\n in: location,\n type,\n required: param.required === true,\n description: asString(param.description),\n };\n}\n\nfunction normalizeOperation(\n root: JsonObject,\n path: string,\n method: string,\n rawOp: Json,\n pathLevelParams: NormalizedParam[],\n seen: Set<string>,\n): NormalizedOperation | undefined {\n if (!isObject(rawOp)) return undefined;\n\n const params: NormalizedParam[] = [...pathLevelParams];\n if (Array.isArray(rawOp.parameters)) {\n for (const rawParam of rawOp.parameters) {\n const normalized = normalizeParam(root, rawParam, seen);\n if (normalized) params.push(normalized);\n }\n }\n\n // Request body: OpenAPI 3 `requestBody.content[*].schema`; Swagger 2 `body` param.\n let requestContentType: string | undefined;\n let requestExample: string | undefined;\n const requestBody = deref(root, rawOp.requestBody, new Set(seen));\n if (isObject(requestBody) && isObject(requestBody.content)) {\n const [contentType, media] = Object.entries(requestBody.content)[0] ?? [];\n requestContentType = contentType;\n if (isObject(media)) {\n requestExample =\n stringifyExample(media.example) ??\n stringifyExample(schemaExample(root, media.schema, seen, 0));\n }\n } else {\n const bodyParam = params.find((p) => p.in === \"body\");\n if (bodyParam) {\n // Swagger 2 body param carries its schema on the raw parameter.\n const rawBody = Array.isArray(rawOp.parameters)\n ? rawOp.parameters.find(\n (p) =>\n isObject(deref(root, p, new Set(seen))) &&\n asString((deref(root, p, new Set(seen)) as JsonObject).in) ===\n \"body\",\n )\n : undefined;\n const resolvedBody = isObject(deref(root, rawBody, new Set(seen)))\n ? (deref(root, rawBody, new Set(seen)) as JsonObject)\n : undefined;\n requestContentType = \"application/json\";\n requestExample = stringifyExample(\n schemaExample(root, resolvedBody?.schema, seen, 0),\n );\n }\n }\n // Swagger 2 `body` params are represented via requestBody above; drop them\n // from the visible param table so they don't double-render.\n const visibleParams = params.filter((p) => p.in !== \"body\");\n\n const responses: NormalizedResponse[] = [];\n if (isObject(rawOp.responses)) {\n for (const [status, rawResponse] of Object.entries(rawOp.responses)) {\n const response = deref(root, rawResponse, new Set(seen));\n let example: string | undefined;\n if (isObject(response)) {\n // OpenAPI 3: response.content[*].schema; Swagger 2: response.schema.\n if (isObject(response.content)) {\n const media = Object.values(response.content)[0];\n if (isObject(media)) {\n example =\n stringifyExample(media.example) ??\n stringifyExample(schemaExample(root, media.schema, seen, 0));\n }\n } else if (response.schema) {\n example = stringifyExample(\n schemaExample(root, response.schema, seen, 0),\n );\n }\n }\n responses.push({\n status,\n description: isObject(response)\n ? asString(response.description)\n : undefined,\n example,\n });\n }\n }\n\n const tags =\n Array.isArray(rawOp.tags) && rawOp.tags.length > 0\n ? rawOp.tags.filter((t): t is string => typeof t === \"string\")\n : [];\n\n const secured =\n Array.isArray(rawOp.security) && rawOp.security.length > 0\n ? rawOp.security.some(\n (req) => isObject(req) && Object.keys(req).length > 0,\n )\n : undefined;\n\n return {\n id: `${method}-${path}`,\n method: method.toUpperCase(),\n path,\n summary: asString(rawOp.summary),\n description: asString(rawOp.description),\n deprecated: rawOp.deprecated === true,\n secured,\n tags: tags.length > 0 ? tags : [\"default\"],\n params: visibleParams,\n requestContentType,\n requestExample,\n responses: responses.sort((a, b) => a.status.localeCompare(b.status)),\n };\n}\n\nfunction normalizeSpec(doc: JsonObject): NormalizedSpec {\n const format: NormalizedSpec[\"format\"] =\n typeof doc.openapi === \"string\"\n ? \"OpenAPI 3\"\n : typeof doc.swagger === \"string\"\n ? \"Swagger 2\"\n : \"Unknown\";\n\n const info = isObject(doc.info) ? doc.info : undefined;\n\n // Global security requirement → every operation without its own override is\n // secured. Operation-level `security: []` opts out; we treat presence here as\n // the default-secured signal.\n const globalSecured =\n Array.isArray(doc.security) &&\n doc.security.some((req) => isObject(req) && Object.keys(req).length > 0);\n\n // Tag order + descriptions from the document's top-level `tags`.\n const tagOrder: string[] = [];\n const tagDescriptions = new Map<string, string>();\n if (Array.isArray(doc.tags)) {\n for (const tag of doc.tags) {\n if (isObject(tag) && typeof tag.name === \"string\") {\n tagOrder.push(tag.name);\n if (typeof tag.description === \"string\") {\n tagDescriptions.set(tag.name, tag.description);\n }\n }\n }\n }\n\n const groups = new Map<string, NormalizedOperation[]>();\n let operationCount = 0;\n\n const paths = isObject(doc.paths) ? doc.paths : {};\n for (const [path, rawPathItem] of Object.entries(paths)) {\n const seen = new Set<string>();\n const pathItem = deref(doc, rawPathItem, seen);\n if (!isObject(pathItem)) continue;\n\n const pathLevelParams: NormalizedParam[] = [];\n if (Array.isArray(pathItem.parameters)) {\n for (const rawParam of pathItem.parameters) {\n const normalized = normalizeParam(doc, rawParam, new Set());\n if (normalized) pathLevelParams.push(normalized);\n }\n }\n\n for (const method of HTTP_METHODS) {\n const rawOp = pathItem[method];\n if (!isObject(rawOp)) continue;\n const operation = normalizeOperation(\n doc,\n path,\n method,\n rawOp,\n pathLevelParams,\n new Set(),\n );\n if (!operation) continue;\n if (operation.secured === undefined && globalSecured) {\n operation.secured = true;\n }\n operationCount += 1;\n for (const tag of operation.tags) {\n const list = groups.get(tag) ?? [];\n list.push(operation);\n groups.set(tag, list);\n }\n }\n }\n\n // Order: documented tags first (in their declared order), then any remaining\n // tags alphabetically.\n const orderedTagNames = [\n ...tagOrder.filter((tag) => groups.has(tag)),\n ...[...groups.keys()]\n .filter((tag) => !tagOrder.includes(tag))\n .sort((a, b) => a.localeCompare(b)),\n ];\n\n const groupList: NormalizedTagGroup[] = orderedTagNames.map((tag) => ({\n tag,\n description: tagDescriptions.get(tag),\n operations: groups.get(tag) ?? [],\n }));\n\n return {\n title: info ? asString(info.title) : undefined,\n version: info ? asString(info.version) : undefined,\n description: info ? asString(info.description) : undefined,\n format,\n groups: groupList,\n operationCount,\n };\n}\n\n/* ── Operation row (collapsed-by-default, mirrors api-endpoint) ─────────────── */\n\nfunction OperationRow({\n operation,\n renderMarkdown,\n}: {\n operation: NormalizedOperation;\n renderMarkdown?: (markdown: string) => React.ReactNode;\n}) {\n const [open, setOpen] = useState(false);\n\n const hasBody =\n Boolean(operation.description?.trim()) ||\n operation.params.length > 0 ||\n Boolean(operation.requestExample || operation.requestContentType) ||\n operation.responses.length > 0;\n\n return (\n <div className=\"overflow-hidden border-t border-plan-line first:border-t-0\">\n <button\n type=\"button\"\n data-plan-interactive\n aria-expanded={open}\n onClick={() => setOpen((value) => !value)}\n className={cn(\n \"flex w-full items-center gap-3 px-4 py-2.5 text-left transition-colors\",\n \"hover:bg-accent/40\",\n )}\n >\n <IconChevronRight\n className={cn(\n \"size-4 shrink-0 text-plan-muted transition-transform\",\n open && \"rotate-90\",\n )}\n />\n <span\n className={cn(\n \"shrink-0 rounded-md px-2 py-1 font-mono text-xs font-bold uppercase tracking-wide\",\n METHOD_PILL[operation.method] ??\n \"bg-slate-200 text-slate-700 dark:bg-slate-500/20 dark:text-slate-300\",\n )}\n >\n {operation.method}\n </span>\n <span\n className={cn(\n \"min-w-0 truncate font-mono text-sm font-semibold text-plan-text\",\n operation.deprecated && \"text-plan-muted line-through\",\n )}\n >\n {operation.path}\n </span>\n {operation.summary && (\n <span className=\"ml-1 min-w-0 flex-1 truncate text-sm text-plan-muted\">\n {operation.summary}\n </span>\n )}\n {operation.secured && (\n <IconLock\n className=\"size-3.5 shrink-0 text-plan-muted\"\n aria-label=\"Requires authentication\"\n />\n )}\n </button>\n\n {open && hasBody && (\n <div className=\"border-t border-plan-line bg-plan-block px-4 py-4\">\n {operation.description?.trim() && (\n <div className=\"an-api-endpoint-desc\">\n {renderMarkdown ? (\n renderMarkdown(operation.description)\n ) : (\n <p className=\"text-sm text-plan-muted\">\n {operation.description}\n </p>\n )}\n </div>\n )}\n\n {operation.params.length > 0 && (\n <div className=\"mt-4\">\n <div className=\"text-xs font-semibold uppercase tracking-wide text-plan-muted\">\n Parameters\n </div>\n <div className=\"mt-2 overflow-hidden rounded-lg border border-plan-line\">\n <table className=\"w-full border-collapse text-sm\">\n <thead>\n <tr className=\"bg-accent/30 text-left text-xs uppercase tracking-wide text-plan-muted\">\n <th className=\"px-3 py-2 font-medium\">Name</th>\n <th className=\"px-3 py-2 font-medium\">In</th>\n <th className=\"px-3 py-2 font-medium\">Type</th>\n <th className=\"px-3 py-2 font-medium\">Required</th>\n <th className=\"px-3 py-2 font-medium\">Description</th>\n </tr>\n </thead>\n <tbody>\n {operation.params.map((param, index) => (\n <tr\n key={`${param.name}-${param.in}-${index}`}\n className=\"border-t border-plan-line align-top\"\n >\n <td className=\"px-3 py-2 font-mono text-xs font-semibold text-plan-text\">\n {param.name}\n </td>\n <td className=\"px-3 py-2\">\n <span\n className={cn(\n \"rounded px-1.5 py-0.5 font-mono text-[11px] font-semibold\",\n PARAM_IN_BADGE[param.in] ??\n \"bg-slate-200 text-slate-700 dark:bg-slate-500/20 dark:text-slate-300\",\n )}\n >\n {param.in}\n </span>\n </td>\n <td className=\"px-3 py-2 font-mono text-xs text-plan-muted\">\n {param.type || \"—\"}\n </td>\n <td className=\"px-3 py-2 text-xs\">\n {param.required ? (\n <span className=\"font-medium text-red-600 dark:text-red-300\">\n required\n </span>\n ) : (\n <span className=\"text-plan-muted\">optional</span>\n )}\n </td>\n <td className=\"px-3 py-2 text-xs text-plan-muted\">\n {param.description || \"—\"}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n )}\n\n {(operation.requestExample || operation.requestContentType) && (\n <div className=\"mt-4\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs font-semibold uppercase tracking-wide text-plan-muted\">\n Request body\n </span>\n {operation.requestContentType && (\n <span className=\"rounded bg-accent/40 px-1.5 py-0.5 font-mono text-[11px] text-plan-muted\">\n {operation.requestContentType}\n </span>\n )}\n </div>\n {operation.requestExample && (\n <CodeSurface\n code={operation.requestExample}\n language=\"json\"\n className=\"mt-2\"\n />\n )}\n </div>\n )}\n\n {operation.responses.length > 0 && (\n <div className=\"mt-4\">\n <div className=\"text-xs font-semibold uppercase tracking-wide text-plan-muted\">\n Responses\n </div>\n <div className=\"mt-2 flex flex-col gap-3\">\n {operation.responses.map((response, index) => (\n <div\n key={`${response.status}-${index}`}\n className=\"rounded-lg border border-plan-line\"\n >\n <div className=\"flex items-center gap-2 px-3 py-2\">\n <span\n className={cn(\n \"rounded px-2 py-0.5 font-mono text-xs font-bold\",\n statusPillClass(response.status),\n )}\n >\n {response.status}\n </span>\n {response.description && (\n <span className=\"text-sm text-plan-muted\">\n {response.description}\n </span>\n )}\n </div>\n {response.example && (\n <div className=\"border-t border-plan-line px-3 pb-3 pt-3\">\n <CodeSurface\n code={response.example}\n language=\"json\"\n className=\"mt-0\"\n />\n </div>\n )}\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n );\n}\n\n/* ── Tag group (collapsed-by-default) ──────────────────────────────────────── */\n\nfunction TagGroup({\n group,\n defaultOpen,\n renderMarkdown,\n}: {\n group: NormalizedTagGroup;\n defaultOpen: boolean;\n renderMarkdown?: (markdown: string) => React.ReactNode;\n}) {\n const [open, setOpen] = useState(defaultOpen);\n return (\n <div className=\"overflow-hidden rounded-xl border border-plan-line bg-plan-block\">\n <button\n type=\"button\"\n data-plan-interactive\n aria-expanded={open}\n onClick={() => setOpen((value) => !value)}\n className=\"flex w-full items-center gap-2 px-4 py-3 text-left transition-colors hover:bg-accent/40\"\n >\n <IconChevronRight\n className={cn(\n \"size-4 shrink-0 text-plan-muted transition-transform\",\n open && \"rotate-90\",\n )}\n />\n <span className=\"font-semibold text-plan-text\">{group.tag}</span>\n <span className=\"rounded-full bg-accent/40 px-2 py-0.5 text-[11px] font-medium text-plan-muted\">\n {group.operations.length}\n </span>\n {group.description && (\n <span className=\"ml-1 min-w-0 flex-1 truncate text-sm text-plan-muted\">\n {group.description}\n </span>\n )}\n </button>\n {open && (\n <div className=\"border-t border-plan-line\">\n {group.operations.map((operation) => (\n <OperationRow\n key={operation.id}\n operation={operation}\n renderMarkdown={renderMarkdown}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\n/* ── Read (Redoc / Swagger-UI-style reference) ─────────────────────────────── */\n\n/**\n * Read-only renderer for an `openapi-spec` block. Parses `data.spec` defensively\n * and renders a Redoc / Swagger-UI-style reference: a header (title + version +\n * format badge), then operations grouped by tag, each a collapsed-by-default row\n * that expands to the full per-operation reference. On a parse error it shows the\n * error plus the raw payload (never throws).\n */\nexport function OpenApiSpecRead({\n data,\n blockId,\n title,\n summary,\n ctx,\n}: BlockReadProps<OpenApiSpecData>) {\n const parsed = useMemo(() => parseSpec(data.spec), [data.spec]);\n const heading = data.title ?? title;\n const renderMarkdown = ctx.renderMarkdown;\n\n return (\n <section className=\"plan-block\" data-block-id={blockId}>\n {heading && <div className=\"plan-block-label\">{heading}</div>}\n\n {parsed.ok && parsed.spec ? (\n <div className=\"flex flex-col gap-3\">\n <div className=\"overflow-hidden rounded-xl border border-plan-line bg-plan-block px-4 py-3\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"font-semibold text-plan-text\">\n {parsed.spec.title || \"API reference\"}\n </span>\n {parsed.spec.version && (\n <span className=\"rounded bg-accent/40 px-1.5 py-0.5 font-mono text-[11px] text-plan-muted\">\n v{parsed.spec.version}\n </span>\n )}\n <span className=\"rounded-full border border-plan-line px-2 py-0.5 text-[11px] font-medium text-plan-muted\">\n {parsed.spec.format}\n </span>\n <span className=\"text-xs text-plan-muted\">\n {parsed.spec.operationCount}{\" \"}\n {parsed.spec.operationCount === 1 ? \"operation\" : \"operations\"}\n </span>\n </div>\n {parsed.spec.description?.trim() && (\n <div className=\"mt-2 an-api-endpoint-desc\">\n {renderMarkdown ? (\n renderMarkdown(parsed.spec.description)\n ) : (\n <p className=\"text-sm text-plan-muted\">\n {parsed.spec.description}\n </p>\n )}\n </div>\n )}\n </div>\n\n {parsed.spec.groups.length === 0 ? (\n <div className=\"rounded-xl border border-plan-line bg-plan-block px-4 py-6 text-center text-sm text-plan-muted\">\n No operations found in this spec.\n </div>\n ) : (\n parsed.spec.groups.map((group, index) => (\n <TagGroup\n key={group.tag}\n group={group}\n // Open the first group by default so the reference is not a wall\n // of collapsed accordions on first paint.\n defaultOpen={index === 0}\n renderMarkdown={renderMarkdown}\n />\n ))\n )}\n </div>\n ) : (\n <div className=\"overflow-hidden rounded-xl border border-plan-line bg-plan-block\">\n <div className=\"border-b border-plan-line px-3 py-1.5\">\n <span className=\"font-mono text-xs uppercase tracking-wide text-plan-muted\">\n OpenAPI\n </span>\n </div>\n <div className=\"space-y-2 px-3 py-2.5\">\n <p className=\"text-xs text-red-600 dark:text-red-300\">\n Could not parse spec: {parsed.error}\n </p>\n <CodeSurface\n code={data.spec || \"—\"}\n language=\"json\"\n className=\"mt-0\"\n />\n </div>\n </div>\n )}\n\n {summary && <p className=\"mt-5 text-plan-muted\">{summary}</p>}\n </section>\n );\n}\n\n/* ── Edit (panel form) ─────────────────────────────────────────────────────── */\n\n/**\n * Panel editor for an `openapi-spec` block: a `title` input plus a monospace\n * textarea bound to the raw `spec`, with a \"Format\" button that pretty-prints via\n * `JSON.parse` → `JSON.stringify(_, null, 2)` (guarded — shows an INLINE error,\n * never `window.alert`). Renders BARE content (no `<section>`); the registry's\n * panel surface supplies the popover chrome.\n */\nexport function OpenApiSpecEdit({\n data,\n onChange,\n editable,\n}: BlockEditProps<OpenApiSpecData>) {\n const titleId = useId();\n const specId = useId();\n const [formatError, setFormatError] = useState<string | null>(null);\n\n const handleFormat = () => {\n try {\n const formatted = JSON.stringify(JSON.parse(data.spec), null, 2);\n setFormatError(null);\n onChange({ ...data, spec: formatted });\n } catch (error) {\n setFormatError(\n error instanceof Error ? error.message : \"Invalid JSON — cannot format\",\n );\n }\n };\n\n return (\n <div className=\"grid gap-3\" data-plan-interactive>\n <div className=\"grid gap-1.5\">\n <DevLabel htmlFor={titleId}>Title</DevLabel>\n <DevInput\n id={titleId}\n value={data.title ?? \"\"}\n readOnly={!editable}\n onChange={(event) =>\n onChange({ ...data, title: event.target.value || undefined })\n }\n placeholder=\"Optional heading\"\n />\n </div>\n\n <div className=\"grid gap-1.5\">\n <div className=\"flex items-center justify-between\">\n <DevLabel htmlFor={specId}>OpenAPI / Swagger spec</DevLabel>\n {editable && (\n <button\n type=\"button\"\n data-plan-interactive\n onClick={handleFormat}\n className=\"inline-flex h-7 cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md border border-input bg-background px-2 text-xs font-medium ring-offset-background transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50\"\n >\n Format\n </button>\n )}\n </div>\n <DevTextarea\n id={specId}\n value={data.spec}\n readOnly={!editable}\n spellCheck={false}\n onChange={(event) => {\n setFormatError(null);\n onChange({ ...data, spec: event.target.value });\n }}\n className=\"min-h-72 font-mono text-xs\"\n placeholder={\n '{\\n \"openapi\": \"3.0.0\",\\n \"info\": { \"title\": \"My API\", \"version\": \"1.0.0\" },\\n \"paths\": {}\\n}'\n }\n />\n {formatError && (\n <p className=\"text-xs text-red-600 dark:text-red-300\">\n {formatError}\n </p>\n )}\n <p className=\"text-xs text-muted-foreground\">\n Paste a complete OpenAPI 3 or Swagger 2 document. v1 supports JSON\n specs only — convert YAML to JSON first.\n </p>\n </div>\n </div>\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checklist.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/checklist.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAGL,KAAK,aAAa,EAEnB,MAAM,uBAAuB,CAAC;AAsB/B;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,OAAO,EACP,KAAK,EACL,QAAQ,GACT,EAAE,cAAc,CAAC,aAAa,CAAC,GAAG;IACjC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC,2CA8BA;AA0BD,6DAA6D;AAC7D,wBAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,QAAQ,EACR,QAAQ,GACT,EAAE,cAAc,CAAC,aAAa,CAAC,2CAuE/B;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc,
|
|
1
|
+
{"version":3,"file":"checklist.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/checklist.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAGL,KAAK,aAAa,EAEnB,MAAM,uBAAuB,CAAC;AAsB/B;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,OAAO,EACP,KAAK,EACL,QAAQ,GACT,EAAE,cAAc,CAAC,aAAa,CAAC,GAAG;IACjC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC,2CA8BA;AA0BD,6DAA6D;AAC7D,wBAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,QAAQ,EACR,QAAQ,GACT,EAAE,cAAc,CAAC,aAAa,CAAC,2CAuE/B;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc,gDAezB,CAAC"}
|
|
@@ -68,6 +68,7 @@ export const checklistBlock = defineBlock({
|
|
|
68
68
|
Read: ChecklistBlock,
|
|
69
69
|
Edit: ChecklistEditor,
|
|
70
70
|
placement: ["block"],
|
|
71
|
+
editSurface: "inline",
|
|
71
72
|
// A checklist maps to NFM to-do items, so it round-trips to Notion.
|
|
72
73
|
notionCompatible: true,
|
|
73
74
|
label: "Checklist",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checklist.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/checklist.tsx"],"names":[],"mappings":"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","sourcesContent":["import { IconCheck, IconPlus, IconX } from \"@tabler/icons-react\";\nimport { cn } from \"../../utils.js\";\nimport { defineBlock } from \"../types.js\";\nimport type { BlockReadProps, BlockEditProps } from \"../types.js\";\nimport {\n checklistSchema,\n checklistMdx,\n type ChecklistData,\n type ChecklistItem,\n} from \"./checklist.config.js\";\n\n/**\n * Standard `checklist` block. A list of toggleable items, each with a label and\n * an optional note. Lives in core so any app can register it.\n *\n * `Read` mirrors the legacy plan `PlanBlockView` checklist branch byte-for-byte\n * (same `plan-block` section, toggle buttons, `IconCheck` marker, and the\n * existing toggle-via-`onChange` behavior) so converting the block to the\n * registry does not change rendered output. The plan CSS classes\n * (`plan-block`, `text-plan-*`, `border-plan-line`) resolve against the plan\n * app's stylesheet at render time, exactly as before.\n *\n * `Edit` is a custom editor (the schema auto-editor can't edit an array of\n * objects): it lets you add, remove, toggle, and relabel items inline.\n */\n\n/** Mint a reasonably-unique item id without pulling a dep into core. */\nfunction newItemId(): string {\n return `item-${Math.random().toString(36).slice(2, 10)}`;\n}\n\n/**\n * Read renderer. Note `onToggle` is supplied by the block dispatcher for the\n * historical click-to-toggle behavior; in pure read contexts it is omitted and\n * the markers render statically.\n */\nexport function ChecklistBlock({\n data,\n blockId,\n title,\n onToggle,\n}: BlockReadProps<ChecklistData> & {\n onToggle?: (itemId: string) => void;\n}) {\n return (\n <section className=\"plan-block\" data-block-id={blockId}>\n {title && <div className=\"plan-block-label\">{title}</div>}\n <div className=\"grid gap-3\">\n {data.items.map((item) =>\n onToggle ? (\n <button\n key={item.id}\n type=\"button\"\n data-plan-interactive\n className=\"flex items-start gap-3 text-left text-plan-muted\"\n onClick={() => onToggle(item.id)}\n >\n <ChecklistMarker checked={item.checked} />\n <ChecklistItemBody item={item} />\n </button>\n ) : (\n <div\n key={item.id}\n className=\"flex items-start gap-3 text-left text-plan-muted\"\n >\n <ChecklistMarker checked={item.checked} />\n <ChecklistItemBody item={item} />\n </div>\n ),\n )}\n </div>\n </section>\n );\n}\n\nfunction ChecklistMarker({ checked }: { checked?: boolean }) {\n return (\n <span\n className={cn(\n \"mt-1 flex size-5 items-center justify-center rounded border\",\n checked\n ? \"border-primary bg-primary text-primary-foreground\"\n : \"border-plan-line\",\n )}\n >\n {checked && <IconCheck className=\"size-3.5\" />}\n </span>\n );\n}\n\nfunction ChecklistItemBody({ item }: { item: ChecklistItem }) {\n return (\n <span>\n <span className=\"block text-plan-text\">{item.label}</span>\n {item.note && <span className=\"block text-sm\">{item.note}</span>}\n </span>\n );\n}\n\n/** Custom editor: toggle, relabel, add, and remove items. */\nexport function ChecklistEditor({\n data,\n onChange,\n editable,\n}: BlockEditProps<ChecklistData>) {\n const items = data.items;\n\n const update = (next: ChecklistItem[]) => onChange({ items: next });\n\n const toggle = (id: string) =>\n update(\n items.map((item) =>\n item.id === id ? { ...item, checked: !item.checked } : item,\n ),\n );\n\n const setLabel = (id: string, label: string) =>\n update(items.map((item) => (item.id === id ? { ...item, label } : item)));\n\n const remove = (id: string) => update(items.filter((item) => item.id !== id));\n\n const add = () =>\n update([...items, { id: newItemId(), label: \"\", checked: false }]);\n\n return (\n <div className=\"grid gap-2\">\n {items.map((item) => (\n <div key={item.id} className=\"flex items-start gap-2\">\n <button\n type=\"button\"\n data-plan-interactive\n aria-label={item.checked ? \"Mark incomplete\" : \"Mark complete\"}\n className={cn(\n \"mt-1 flex size-5 shrink-0 items-center justify-center rounded border\",\n item.checked\n ? \"border-primary bg-primary text-primary-foreground\"\n : \"border-plan-line\",\n )}\n onClick={() => toggle(item.id)}\n >\n {item.checked && <IconCheck className=\"size-3.5\" />}\n </button>\n <input\n type=\"text\"\n data-plan-interactive\n className=\"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-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 placeholder=\"Checklist item\"\n value={item.label}\n disabled={!editable}\n onChange={(event) => setLabel(item.id, event.target.value)}\n />\n <button\n type=\"button\"\n data-plan-interactive\n aria-label=\"Remove item\"\n className=\"mt-1 flex size-7 shrink-0 items-center justify-center rounded text-muted-foreground hover:bg-muted hover:text-foreground disabled:opacity-50\"\n disabled={!editable}\n onClick={() => remove(item.id)}\n >\n <IconX className=\"size-4\" />\n </button>\n </div>\n ))}\n <button\n type=\"button\"\n data-plan-interactive\n className=\"flex items-center gap-1.5 self-start rounded-md px-2 py-1 text-sm text-muted-foreground hover:bg-muted hover:text-foreground disabled:opacity-50\"\n disabled={!editable}\n onClick={add}\n >\n <IconPlus className=\"size-4\" />\n Add item\n </button>\n </div>\n );\n}\n\n/**\n * The standard checklist block spec (with React `Read`/`Edit`). Apps register\n * this in their browser registry. The schema + MDX config come from\n * `./checklist.config.ts`, the exact same object server / agent code registers,\n * so rendering and source round-trip never drift.\n *\n * `Read` is typed against `BlockReadProps<ChecklistData>`; the optional\n * `onToggle` the dispatcher injects for the legacy click-to-toggle behavior is\n * an extra prop the registry's `BlockView` passes through harmlessly when\n * present (it lives outside `BlockReadProps`, so it's wired by the app's block\n * dispatch rather than the generic `BlockView`).\n */\nexport const checklistBlock = defineBlock<ChecklistData>({\n type: \"checklist\",\n schema: checklistSchema,\n mdx: checklistMdx,\n Read: ChecklistBlock as never,\n Edit: ChecklistEditor,\n placement: [\"block\"],\n // A checklist maps to NFM to-do items, so it round-trips to Notion.\n notionCompatible: true,\n label: \"Checklist\",\n icon: IconCheck,\n description:\n \"A list of toggleable items, each with a label and an optional note.\",\n empty: () => ({ items: [] }),\n});\n"]}
|
|
1
|
+
{"version":3,"file":"checklist.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/checklist.tsx"],"names":[],"mappings":"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","sourcesContent":["import { IconCheck, IconPlus, IconX } from \"@tabler/icons-react\";\nimport { cn } from \"../../utils.js\";\nimport { defineBlock } from \"../types.js\";\nimport type { BlockReadProps, BlockEditProps } from \"../types.js\";\nimport {\n checklistSchema,\n checklistMdx,\n type ChecklistData,\n type ChecklistItem,\n} from \"./checklist.config.js\";\n\n/**\n * Standard `checklist` block. A list of toggleable items, each with a label and\n * an optional note. Lives in core so any app can register it.\n *\n * `Read` mirrors the legacy plan `PlanBlockView` checklist branch byte-for-byte\n * (same `plan-block` section, toggle buttons, `IconCheck` marker, and the\n * existing toggle-via-`onChange` behavior) so converting the block to the\n * registry does not change rendered output. The plan CSS classes\n * (`plan-block`, `text-plan-*`, `border-plan-line`) resolve against the plan\n * app's stylesheet at render time, exactly as before.\n *\n * `Edit` is a custom editor (the schema auto-editor can't edit an array of\n * objects): it lets you add, remove, toggle, and relabel items inline.\n */\n\n/** Mint a reasonably-unique item id without pulling a dep into core. */\nfunction newItemId(): string {\n return `item-${Math.random().toString(36).slice(2, 10)}`;\n}\n\n/**\n * Read renderer. Note `onToggle` is supplied by the block dispatcher for the\n * historical click-to-toggle behavior; in pure read contexts it is omitted and\n * the markers render statically.\n */\nexport function ChecklistBlock({\n data,\n blockId,\n title,\n onToggle,\n}: BlockReadProps<ChecklistData> & {\n onToggle?: (itemId: string) => void;\n}) {\n return (\n <section className=\"plan-block\" data-block-id={blockId}>\n {title && <div className=\"plan-block-label\">{title}</div>}\n <div className=\"grid gap-3\">\n {data.items.map((item) =>\n onToggle ? (\n <button\n key={item.id}\n type=\"button\"\n data-plan-interactive\n className=\"flex items-start gap-3 text-left text-plan-muted\"\n onClick={() => onToggle(item.id)}\n >\n <ChecklistMarker checked={item.checked} />\n <ChecklistItemBody item={item} />\n </button>\n ) : (\n <div\n key={item.id}\n className=\"flex items-start gap-3 text-left text-plan-muted\"\n >\n <ChecklistMarker checked={item.checked} />\n <ChecklistItemBody item={item} />\n </div>\n ),\n )}\n </div>\n </section>\n );\n}\n\nfunction ChecklistMarker({ checked }: { checked?: boolean }) {\n return (\n <span\n className={cn(\n \"mt-1 flex size-5 items-center justify-center rounded border\",\n checked\n ? \"border-primary bg-primary text-primary-foreground\"\n : \"border-plan-line\",\n )}\n >\n {checked && <IconCheck className=\"size-3.5\" />}\n </span>\n );\n}\n\nfunction ChecklistItemBody({ item }: { item: ChecklistItem }) {\n return (\n <span>\n <span className=\"block text-plan-text\">{item.label}</span>\n {item.note && <span className=\"block text-sm\">{item.note}</span>}\n </span>\n );\n}\n\n/** Custom editor: toggle, relabel, add, and remove items. */\nexport function ChecklistEditor({\n data,\n onChange,\n editable,\n}: BlockEditProps<ChecklistData>) {\n const items = data.items;\n\n const update = (next: ChecklistItem[]) => onChange({ items: next });\n\n const toggle = (id: string) =>\n update(\n items.map((item) =>\n item.id === id ? { ...item, checked: !item.checked } : item,\n ),\n );\n\n const setLabel = (id: string, label: string) =>\n update(items.map((item) => (item.id === id ? { ...item, label } : item)));\n\n const remove = (id: string) => update(items.filter((item) => item.id !== id));\n\n const add = () =>\n update([...items, { id: newItemId(), label: \"\", checked: false }]);\n\n return (\n <div className=\"grid gap-2\">\n {items.map((item) => (\n <div key={item.id} className=\"flex items-start gap-2\">\n <button\n type=\"button\"\n data-plan-interactive\n aria-label={item.checked ? \"Mark incomplete\" : \"Mark complete\"}\n className={cn(\n \"mt-1 flex size-5 shrink-0 items-center justify-center rounded border\",\n item.checked\n ? \"border-primary bg-primary text-primary-foreground\"\n : \"border-plan-line\",\n )}\n onClick={() => toggle(item.id)}\n >\n {item.checked && <IconCheck className=\"size-3.5\" />}\n </button>\n <input\n type=\"text\"\n data-plan-interactive\n className=\"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-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 placeholder=\"Checklist item\"\n value={item.label}\n disabled={!editable}\n onChange={(event) => setLabel(item.id, event.target.value)}\n />\n <button\n type=\"button\"\n data-plan-interactive\n aria-label=\"Remove item\"\n className=\"mt-1 flex size-7 shrink-0 items-center justify-center rounded text-muted-foreground hover:bg-muted hover:text-foreground disabled:opacity-50\"\n disabled={!editable}\n onClick={() => remove(item.id)}\n >\n <IconX className=\"size-4\" />\n </button>\n </div>\n ))}\n <button\n type=\"button\"\n data-plan-interactive\n className=\"flex items-center gap-1.5 self-start rounded-md px-2 py-1 text-sm text-muted-foreground hover:bg-muted hover:text-foreground disabled:opacity-50\"\n disabled={!editable}\n onClick={add}\n >\n <IconPlus className=\"size-4\" />\n Add item\n </button>\n </div>\n );\n}\n\n/**\n * The standard checklist block spec (with React `Read`/`Edit`). Apps register\n * this in their browser registry. The schema + MDX config come from\n * `./checklist.config.ts`, the exact same object server / agent code registers,\n * so rendering and source round-trip never drift.\n *\n * `Read` is typed against `BlockReadProps<ChecklistData>`; the optional\n * `onToggle` the dispatcher injects for the legacy click-to-toggle behavior is\n * an extra prop the registry's `BlockView` passes through harmlessly when\n * present (it lives outside `BlockReadProps`, so it's wired by the app's block\n * dispatch rather than the generic `BlockView`).\n */\nexport const checklistBlock = defineBlock<ChecklistData>({\n type: \"checklist\",\n schema: checklistSchema,\n mdx: checklistMdx,\n Read: ChecklistBlock as never,\n Edit: ChecklistEditor,\n placement: [\"block\"],\n editSurface: \"inline\",\n // A checklist maps to NFM to-do items, so it round-trips to Notion.\n notionCompatible: true,\n label: \"Checklist\",\n icon: IconCheck,\n description:\n \"A list of toggleable items, each with a label and an optional note.\",\n empty: () => ({ items: [] }),\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code-tabs.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/code-tabs.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"code-tabs.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/code-tabs.tsx"],"names":[],"mappings":"AAmBA,OAAO,EAGL,KAAK,YAAY,EAElB,MAAM,uBAAuB,CAAC;AAmgB/B,eAAO,MAAM,aAAa,+CAYxB,CAAC"}
|