@agent-native/core 0.76.10 → 0.76.12
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/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +13 -0
- package/corpus/core/docs/content/locales/ar-SA/actions.md +7 -7
- package/corpus/core/docs/content/locales/ar-SA/template-plan.md +6 -4
- package/corpus/core/docs/content/locales/de-DE/actions.md +9 -9
- package/corpus/core/docs/content/locales/de-DE/template-plan.md +6 -4
- package/corpus/core/docs/content/locales/es-ES/actions.md +9 -9
- package/corpus/core/docs/content/locales/es-ES/template-plan.md +6 -4
- package/corpus/core/docs/content/locales/fr-FR/actions.md +9 -9
- package/corpus/core/docs/content/locales/fr-FR/template-plan.md +6 -4
- package/corpus/core/docs/content/locales/hi-IN/actions.md +9 -9
- package/corpus/core/docs/content/locales/hi-IN/template-plan.md +4 -4
- package/corpus/core/docs/content/locales/ja-JP/actions.md +9 -9
- package/corpus/core/docs/content/locales/ja-JP/template-plan.md +4 -4
- package/corpus/core/docs/content/locales/ko-KR/actions.md +9 -9
- package/corpus/core/docs/content/locales/ko-KR/template-plan.md +4 -4
- package/corpus/core/docs/content/locales/pt-BR/actions.md +9 -9
- package/corpus/core/docs/content/locales/pt-BR/template-plan.md +6 -4
- package/corpus/core/docs/content/locales/zh-CN/actions.md +9 -9
- package/corpus/core/docs/content/locales/zh-CN/template-plan.md +4 -4
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/client/ErrorBoundary.tsx +151 -10
- package/corpus/core/src/client/FeedbackButton.tsx +162 -18
- package/corpus/core/src/client/blocks/library/AnnotatedCodeBlock.tsx +11 -2
- package/corpus/core/src/client/blocks/library/ApiEndpointBlock.tsx +46 -19
- package/corpus/core/src/client/blocks/library/MermaidBlock.tsx +7 -5
- package/corpus/core/src/client/blocks/library/block-copy.ts +367 -0
- package/corpus/core/src/client/blocks/library/diagram.tsx +8 -6
- package/corpus/core/src/client/blocks/library/wireframe.tsx +7 -2
- package/corpus/core/src/client/i18n.tsx +4 -0
- package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +51 -31
- package/corpus/templates/analytics/app/components/layout/DashboardHeader.tsx +26 -16
- package/corpus/templates/analytics/app/components/layout/Header.tsx +1 -2
- package/corpus/templates/analytics/app/components/layout/HeaderActions.tsx +8 -1
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +2 -5
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +172 -107
- package/corpus/templates/analytics/app/i18n-data.ts +1076 -5
- package/corpus/templates/analytics/app/pages/Settings.tsx +2 -2
- package/corpus/templates/analytics/changelog/2026-06-24-analytics-navigation-command-palette-and-settings-now-honor-.md +6 -0
- package/corpus/templates/assets/app/components/layout/Header.tsx +0 -2
- package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +0 -2
- package/corpus/templates/calendar/app/pages/CalendarView.tsx +0 -2
- package/corpus/templates/chat/app/components/layout/Header.tsx +1 -6
- package/corpus/templates/clips/app/components/layout/Header.tsx +1 -6
- package/corpus/templates/clips/app/hooks/use-library.ts +2 -0
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +3 -1
- package/corpus/templates/clips/changelog/2026-06-24-archive-and-spaces-navigation-is-more-resilient-when-sidebar.md +6 -0
- package/corpus/templates/content/app/components/layout/Header.tsx +0 -2
- package/corpus/templates/design/app/components/layout/Header.tsx +1 -6
- package/corpus/templates/forms/app/components/layout/Header.tsx +1 -6
- package/corpus/templates/macros/app/components/layout/Header.tsx +1 -6
- package/corpus/templates/mail/app/components/email/CodeBlockLangPicker.tsx +4 -2
- package/corpus/templates/mail/app/components/email/ComposeBubbleToolbar.tsx +18 -12
- package/corpus/templates/mail/app/components/email/ComposeEditor.tsx +9 -5
- package/corpus/templates/mail/app/components/email/ComposeModal.tsx +36 -19
- package/corpus/templates/mail/app/components/email/EmailList.tsx +59 -55
- package/corpus/templates/mail/app/components/email/EmailListItem.tsx +7 -3
- package/corpus/templates/mail/app/components/email/EmailThread.tsx +25 -16
- package/corpus/templates/mail/app/components/email/InlineReplyComposer.tsx +25 -19
- package/corpus/templates/mail/app/components/email/IntegrationsSidebar.tsx +32 -17
- package/corpus/templates/mail/app/components/email/RecipientInput.tsx +26 -10
- package/corpus/templates/mail/app/components/email/SendLaterButton.tsx +5 -3
- package/corpus/templates/mail/app/components/email/SnoozeModal.tsx +4 -2
- package/corpus/templates/mail/app/components/email/SnoozePopover.tsx +9 -5
- package/corpus/templates/mail/app/components/email/extensions/ComposeImageBlock.tsx +4 -2
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +168 -86
- package/corpus/templates/mail/app/components/layout/SearchBar.tsx +4 -2
- package/corpus/templates/mail/app/i18n/ar-SA.ts +212 -0
- package/corpus/templates/mail/app/i18n/de-DE.ts +212 -0
- package/corpus/templates/mail/app/i18n/en-US.ts +212 -0
- package/corpus/templates/mail/app/i18n/es-ES.ts +212 -0
- package/corpus/templates/mail/app/i18n/fr-FR.ts +212 -0
- package/corpus/templates/mail/app/i18n/hi-IN.ts +212 -0
- package/corpus/templates/mail/app/i18n/ja-JP.ts +212 -0
- package/corpus/templates/mail/app/i18n/ko-KR.ts +212 -0
- package/corpus/templates/mail/app/i18n/pt-BR.ts +212 -0
- package/corpus/templates/mail/app/i18n/zh-CN.ts +211 -0
- package/corpus/templates/mail/app/root.tsx +90 -6
- package/corpus/templates/mail/changelog/2026-06-24-interface-language-support-now-covers-more-mail-controls-and.md +6 -0
- package/corpus/templates/plan/app/components/layout/Header.tsx +1 -6
- package/corpus/templates/slides/app/components/layout/Header.tsx +1 -6
- package/corpus/templates/videos/app/components/layout/Header.tsx +1 -6
- package/dist/client/ErrorBoundary.d.ts.map +1 -1
- package/dist/client/ErrorBoundary.js +128 -7
- package/dist/client/ErrorBoundary.js.map +1 -1
- package/dist/client/FeedbackButton.d.ts.map +1 -1
- package/dist/client/FeedbackButton.js +142 -14
- package/dist/client/FeedbackButton.js.map +1 -1
- package/dist/client/blocks/library/AnnotatedCodeBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/AnnotatedCodeBlock.js +6 -2
- package/dist/client/blocks/library/AnnotatedCodeBlock.js.map +1 -1
- package/dist/client/blocks/library/ApiEndpointBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/ApiEndpointBlock.js +14 -6
- package/dist/client/blocks/library/ApiEndpointBlock.js.map +1 -1
- package/dist/client/blocks/library/MermaidBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/MermaidBlock.js +6 -4
- package/dist/client/blocks/library/MermaidBlock.js.map +1 -1
- package/dist/client/blocks/library/block-copy.d.ts +33 -0
- package/dist/client/blocks/library/block-copy.d.ts.map +1 -0
- package/dist/client/blocks/library/block-copy.js +329 -0
- package/dist/client/blocks/library/block-copy.js.map +1 -0
- package/dist/client/blocks/library/diagram.d.ts.map +1 -1
- package/dist/client/blocks/library/diagram.js +7 -5
- package/dist/client/blocks/library/diagram.js.map +1 -1
- package/dist/client/blocks/library/wireframe.d.ts.map +1 -1
- package/dist/client/blocks/library/wireframe.js +4 -2
- package/dist/client/blocks/library/wireframe.js.map +1 -1
- package/dist/client/i18n.d.ts +1 -0
- package/dist/client/i18n.d.ts.map +1 -1
- package/dist/client/i18n.js +3 -0
- package/dist/client/i18n.js.map +1 -1
- package/docs/content/locales/ar-SA/actions.md +7 -7
- package/docs/content/locales/ar-SA/template-plan.md +6 -4
- package/docs/content/locales/de-DE/actions.md +9 -9
- package/docs/content/locales/de-DE/template-plan.md +6 -4
- package/docs/content/locales/es-ES/actions.md +9 -9
- package/docs/content/locales/es-ES/template-plan.md +6 -4
- package/docs/content/locales/fr-FR/actions.md +9 -9
- package/docs/content/locales/fr-FR/template-plan.md +6 -4
- package/docs/content/locales/hi-IN/actions.md +9 -9
- package/docs/content/locales/hi-IN/template-plan.md +4 -4
- package/docs/content/locales/ja-JP/actions.md +9 -9
- package/docs/content/locales/ja-JP/template-plan.md +4 -4
- package/docs/content/locales/ko-KR/actions.md +9 -9
- package/docs/content/locales/ko-KR/template-plan.md +4 -4
- package/docs/content/locales/pt-BR/actions.md +9 -9
- package/docs/content/locales/pt-BR/template-plan.md +6 -4
- package/docs/content/locales/zh-CN/actions.md +9 -9
- package/docs/content/locales/zh-CN/template-plan.md +4 -4
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApiEndpointBlock.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/ApiEndpointBlock.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useState } from \"react\";\nimport {\n IconArrowNarrowRight,\n IconChevronRight,\n IconLock,\n IconPlus,\n IconTrash,\n} from \"@tabler/icons-react\";\nimport { cn } from \"../../utils.js\";\nimport { ltrCodeBlockProps } from \"../code-block-direction.js\";\nimport type { BlockEditProps, BlockReadProps } from \"../types.js\";\nimport type {\n ApiEndpointChange,\n ApiEndpointData,\n ApiEndpointMethod,\n ApiEndpointParam,\n ApiEndpointResponse,\n ApiParamLocation,\n} from \"./api-endpoint.config.js\";\nimport {\n API_ENDPOINT_CHANGES,\n API_ENDPOINT_METHODS,\n API_PARAM_LOCATIONS,\n} from \"./api-endpoint.config.js\";\nimport { JsonExplorerSurface } from \"./JsonExplorerBlock.js\";\nimport {\n DevBadge,\n DevInput,\n DevSwitch,\n DevTextarea,\n DevSelect,\n} from \"./dev-doc-ui.js\";\n\n/**\n * Read + Edit renderers for an `api-endpoint` block — a Swagger / Stripe-style\n * API reference. Lives in core so any app can register the dev-doc block (no\n * shadcn import).\n */\n\n/* ── Theme-aware color tokens ──────────────────────────────────────────────── */\n\n/**\n * Method-pill palette. Tinted background + saturated text in BOTH modes (the\n * reference HTML hardcoded a dark-only palette — we deliberately avoid that).\n * Each entry keeps legible contrast against the plan surface under `.dark` and\n * light via Tailwind `dark:` variants.\n */\nconst METHOD_PILL: Record<ApiEndpointMethod, 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};\n\n/** Location-badge palette for the params table `in` column. */\nconst PARAM_IN_BADGE: Record<ApiParamLocation, 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 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 // 3xx and everything else → neutral slate.\n return \"bg-slate-200 text-slate-700 dark:bg-slate-500/20 dark:text-slate-300\";\n}\n\n/* ── Theme-aware change tokens (shared vocabulary with file-tree/data-model) ── */\n\n/**\n * Change-chip palette — IDENTICAL to `FileTreeBlock`'s `CHANGE_BADGE` so a route /\n * param / response chip reads the same as a file or field change chip elsewhere\n * in the recap. Tinted background + saturated text in BOTH the `.dark` plan theme\n * and light mode via Tailwind `dark:` variants (never a dark-only palette).\n */\nconst CHANGE_BADGE: Record<ApiEndpointChange, string> = {\n added:\n \"bg-emerald-100 text-emerald-700 dark:bg-emerald-500/15 dark:text-emerald-300\",\n modified: \"bg-blue-100 text-blue-700 dark:bg-blue-500/15 dark:text-blue-300\",\n removed: \"bg-red-100 text-red-700 dark:bg-red-500/15 dark:text-red-300\",\n renamed:\n \"bg-violet-100 text-violet-700 dark:bg-violet-500/15 dark:text-violet-300\",\n};\n\n/** Single-letter glyph shown in the compact chip (VS Code gutter convention). */\nconst CHANGE_GLYPH: Record<ApiEndpointChange, string> = {\n added: \"A\",\n modified: \"M\",\n removed: \"D\",\n renamed: \"R\",\n};\n\n/** Human label for the chip text + its `title` / `aria-label`. */\nconst CHANGE_LABEL: Record<ApiEndpointChange, string> = {\n added: \"Added\",\n modified: \"Modified\",\n removed: \"Removed\",\n renamed: \"Renamed\",\n};\n\n/** Accent ink echoing a change color, for the name/path it applies to. */\nconst CHANGE_INK: Record<ApiEndpointChange, string> = {\n added: \"text-emerald-700 dark:text-emerald-300\",\n modified: \"text-blue-700 dark:text-blue-300\",\n removed: \"text-red-600 line-through dark:text-red-300\",\n renamed: \"text-violet-700 dark:text-violet-300\",\n};\n\n/**\n * A change chip: compact single-glyph badge (A/M/D/R) by default, or a labeled\n * pill (`variant=\"label\"`) for the endpoint header where there is room. Matches\n * the file-tree change badge so the recap reads consistently.\n */\nfunction ChangeChip({\n change,\n variant = \"glyph\",\n className,\n}: {\n change: ApiEndpointChange;\n variant?: \"glyph\" | \"label\";\n className?: string;\n}) {\n if (variant === \"label\") {\n return (\n <span\n title={CHANGE_LABEL[change]}\n className={cn(\n \"shrink-0 rounded px-1.5 py-0.5 text-[10px] font-bold uppercase tracking-wide\",\n CHANGE_BADGE[change],\n className,\n )}\n >\n {CHANGE_LABEL[change]}\n </span>\n );\n }\n return (\n <span\n title={CHANGE_LABEL[change]}\n aria-label={CHANGE_LABEL[change]}\n className={cn(\n \"flex size-4 shrink-0 items-center justify-center rounded text-[10px] font-bold leading-none\",\n CHANGE_BADGE[change],\n className,\n )}\n >\n {CHANGE_GLYPH[change]}\n </span>\n );\n}\n\n/**\n * Before → after for a modified param: the prior `was` value struck through, a\n * narrow arrow, then the current value (e.g. `optional → required`, or the old\n * type → the new type). When `was` is absent we just show the current value.\n */\nfunction WasArrowCurrent({\n was,\n current,\n}: {\n was?: string;\n current: React.ReactNode;\n}) {\n if (!was) return <>{current}</>;\n return (\n <span className=\"inline-flex items-center gap-1\">\n <span className=\"text-plan-muted line-through\">{was}</span>\n <IconArrowNarrowRight className=\"size-3 shrink-0 text-plan-muted\" />\n {current}\n </span>\n );\n}\n\n/**\n * A param carries a single `was` (prior value) for a `modified` change, but that\n * value may describe either the required flag or the type. Decide which column\n * the before→after belongs to: a `was` of `required`/`optional` is a required\n * flag flip; anything else is treated as the prior type.\n */\nfunction wasIsRequiredFlag(was: string): boolean {\n const v = was.trim().toLowerCase();\n return v === \"required\" || v === \"optional\";\n}\n\n/** Guess a fence language from a content type so examples highlight nicely. */\nfunction fenceLangForContentType(contentType?: string): string {\n const ct = (contentType ?? \"\").toLowerCase();\n if (ct.includes(\"xml\") || ct.includes(\"html\")) return \"html\";\n if (ct.includes(\"yaml\") || ct.includes(\"yml\")) return \"yaml\";\n return \"json\";\n}\n\n/**\n * Strip JSONC niceties so an otherwise-valid-but-commented example still parses\n * as JSON and earns the collapsible JsonExplorer (instead of falling back to a\n * plain code block). Removes `//` line comments and `/* … */` block comments,\n * then trailing commas before `}`/`]`. String contents are preserved: `//`\n * inside a quoted string (e.g. a URL) is NOT treated as a comment.\n */\nfunction stripJsonComments(source: string): string {\n let out = \"\";\n let inString = false;\n let stringQuote = \"\";\n let inLineComment = false;\n let inBlockComment = false;\n\n for (let i = 0; i < source.length; i += 1) {\n const char = source[i];\n const next = source[i + 1];\n\n if (inLineComment) {\n if (char === \"\\n\") {\n inLineComment = false;\n out += char;\n }\n continue;\n }\n\n if (inBlockComment) {\n if (char === \"*\" && next === \"/\") {\n inBlockComment = false;\n i += 1;\n }\n continue;\n }\n\n if (inString) {\n out += char;\n if (char === \"\\\\\") {\n // Copy the escaped char verbatim so an escaped quote can't end the\n // string early.\n if (next !== undefined) {\n out += next;\n i += 1;\n }\n } else if (char === stringQuote) {\n inString = false;\n }\n continue;\n }\n\n if (char === '\"' || char === \"'\") {\n inString = true;\n stringQuote = char;\n out += char;\n continue;\n }\n\n if (char === \"/\" && next === \"/\") {\n inLineComment = true;\n i += 1;\n continue;\n }\n\n if (char === \"/\" && next === \"*\") {\n inBlockComment = true;\n i += 1;\n continue;\n }\n\n // Drop a trailing comma before a closing bracket so the result is strict\n // JSON. Done here (not via a post-pass regex) so it stays string-aware: we\n // only reach this branch outside strings/comments, and the structural comma\n // is the last non-whitespace char already emitted. A comma inside a string\n // value like `\"hello,}\"` is followed by its closing quote, not the bracket,\n // so it is never stripped.\n if (char === \"}\" || char === \"]\") {\n out = out.replace(/,\\s*$/, \"\");\n }\n out += char;\n }\n\n return out;\n}\n\n/**\n * Decide whether an example should render with the collapsible JsonExplorer.\n * Returns the strict-JSON text to feed the explorer (comment-stripped when the\n * raw example was JSONC), or `null` when the example is not parseable as JSON\n * (free-form / XML / YAML text) and should fall back to the styled code surface.\n *\n * Parseability — NOT the declared `contentType` — is the gate, so the REQUEST\n * body example earns the same interactive explorer as the RESPONSE examples\n * whenever it is valid JSON. A request often carries a `contentType` that is not\n * literally `application/json` (e.g. a WebSocket-upgrade body) yet still holds a\n * JSON payload; keying off the content type would wrongly drop those into the\n * static code block. `contentType` now only labels the non-JSON code fallback\n * (via `fenceLangForContentType`), it never suppresses the explorer.\n */\nfunction jsonExplorerSource(example: string): string | null {\n try {\n JSON.parse(example);\n return example;\n } catch {\n // Tolerate JSONC: a commented-but-otherwise-valid body still gets the nice\n // explorer. Feed the explorer the stripped (strict-JSON) text so it parses.\n const stripped = stripJsonComments(example);\n try {\n JSON.parse(stripped);\n return stripped;\n } catch {\n return null;\n }\n }\n}\n\n/**\n * Plain (non-JSON) example fallback. Renders inside the SAME surface chrome as\n * {@link JsonExplorerSurface} — one `rounded-xl border bg-plan-code` box with a\n * label bar and an `overflow-auto` scroll body — so a JSONC / free-form example\n * reads consistently with the JSON-explorer examples instead of as a separate,\n * differently-styled code box (no extra background tint, no clipped overflow).\n * Font-size is inherited from `--plan-code-size` (the same token the global code\n * rule manages); we never hardcode it here.\n */\nfunction ApiCodeExample({\n code,\n label = \"JSON\",\n className,\n}: {\n code: string;\n label?: string;\n className?: string;\n}) {\n return (\n <div\n data-code-surface\n className={cn(\n \"overflow-hidden rounded-xl border border-plan-line bg-plan-code\",\n className,\n )}\n >\n <div className=\"flex items-center gap-2 border-b border-plan-line px-3 py-1.5\">\n <span className=\"font-mono text-xs uppercase tracking-wide text-plan-muted\">\n {label}\n </span>\n </div>\n <pre className=\"overflow-x-auto px-3 py-2.5 font-mono [font-size:var(--plan-doc-code-size)] leading-relaxed text-plan-code-text\">\n {code}\n </pre>\n </div>\n );\n}\n\nfunction ApiExample({\n example,\n contentType,\n className,\n}: {\n example: string;\n contentType?: string;\n className?: string;\n}) {\n const jsonSource = jsonExplorerSource(example);\n if (jsonSource !== null) {\n return (\n <JsonExplorerSurface\n data={{ json: jsonSource, collapsedDepth: 2 }}\n className={className}\n />\n );\n }\n\n return (\n <ApiCodeExample\n code={example}\n label={fenceLangForContentType(contentType).toUpperCase()}\n className={className}\n />\n );\n}\n\n/* ── Read (collapsed-by-default swagger row) ───────────────────────────────── */\n\n/**\n * Read-only renderer for an `api-endpoint` block. Collapsed by default: a single\n * row with a colored method pill, monospace path, muted summary, and a chevron.\n * Clicking the row expands the full reference (description, params table,\n * request body, responses) — the Swagger / Stripe house style. Every colored\n * element is theme-aware (`dark:` variants), so it reads correctly in both the\n * `.dark` plan theme and light mode.\n */\nexport function ApiEndpointRead({\n data,\n blockId,\n title,\n summary,\n ctx,\n}: BlockReadProps<ApiEndpointData>) {\n const [open, setOpen] = useState(false);\n\n const params = data.params ?? [];\n const responses = data.responses ?? [];\n const hasRequest = Boolean(\n data.request?.example || data.request?.contentType,\n );\n const hasBody =\n Boolean(data.description?.trim()) ||\n params.length > 0 ||\n hasRequest ||\n responses.length > 0 ||\n Boolean(data.auth);\n\n return (\n // `data-block-type` lets the document flow detect a RUN of consecutive\n // api-endpoint blocks and collapse the divider + gap between them (see\n // `.plan-document-flow` rules in the plan template's global.css), so a list\n // of endpoints reads as one tight scannable group instead of separate\n // full-width cards. `an-api-endpoint-card` is the flush-able card surface\n // those rules round/merge at the run's edges.\n <section\n {...ltrCodeBlockProps}\n className=\"plan-block\"\n data-block-id={blockId}\n data-block-type=\"api-endpoint\"\n >\n {title && <div className=\"plan-block-label\">{title}</div>}\n <div className=\"an-api-endpoint-card overflow-hidden rounded-xl border border-plan-line bg-plan-block\">\n {/* Collapsed summary row — the whole row toggles. */}\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-3 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[data.method],\n )}\n >\n {data.method}\n </span>\n <span\n className={cn(\n \"min-w-0 truncate font-mono text-sm font-semibold\",\n // `change` ink composes with `deprecated`: a deprecated route\n // still mutes/strikes its path; a changed route tints it (a\n // removed route also strikes via CHANGE_INK).\n data.change ? CHANGE_INK[data.change] : \"text-plan-text\",\n data.deprecated && \"text-plan-muted line-through\",\n )}\n >\n {data.path}\n </span>\n {data.change && <ChangeChip change={data.change} variant=\"label\" />}\n {data.deprecated && (\n <DevBadge className=\"shrink-0 border-amber-500/40 text-amber-600 dark:text-amber-300\">\n Deprecated\n </DevBadge>\n )}\n {(data.summary || summary) && (\n <span className=\"ml-1 min-w-0 flex-1 truncate text-sm text-plan-muted\">\n {data.summary || summary}\n </span>\n )}\n {data.auth && (\n <IconLock\n className=\"size-3.5 shrink-0 text-plan-muted\"\n aria-label=\"Requires authentication\"\n />\n )}\n </button>\n\n {/* Expanded body. No top divider: the title/summary row flows into the\n content separated by padding alone (the user finds mid-card dividers\n distracting; the outer card border + run-flush behavior stay). */}\n {open && hasBody && (\n <div className=\"px-4 pb-4 pt-1\">\n {data.auth && (\n <div className=\"mb-4 flex items-center gap-2 text-xs text-plan-muted\">\n <IconLock className=\"size-3.5 shrink-0\" />\n <span>\n <span className=\"font-medium text-plan-text\">Auth:</span>{\" \"}\n {data.auth}\n </span>\n </div>\n )}\n\n {data.description?.trim() && (\n <div className=\"an-api-endpoint-desc\">\n {ctx.renderMarkdown?.(data.description)}\n </div>\n )}\n\n {params.length > 0 && (\n <div className=\"mt-5\">\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 {params.map((param, index) => {\n const change = param.change;\n // A `modified` `was` describes either the required flag\n // or the prior type; route it to the right column.\n const wasForRequired =\n change === \"modified\" &&\n param.was &&\n wasIsRequiredFlag(param.was)\n ? param.was\n : undefined;\n const wasForType =\n change === \"modified\" &&\n param.was &&\n !wasIsRequiredFlag(param.was)\n ? param.was\n : undefined;\n return (\n <tr\n key={`${param.name}-${index}`}\n className=\"border-t border-plan-line align-top\"\n >\n <td className=\"px-3 py-2 font-mono text-xs font-semibold\">\n <span className=\"flex items-center gap-1.5\">\n <span\n className={cn(\n change\n ? CHANGE_INK[change]\n : \"text-plan-text\",\n )}\n >\n {param.name}\n </span>\n {change && <ChangeChip change={change} />}\n </span>\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 )}\n >\n {param.in}\n </span>\n </td>\n <td className=\"px-3 py-2 font-mono text-xs text-plan-muted\">\n <WasArrowCurrent\n was={wasForType}\n current={\n <span\n className={cn(\n wasForType && \"text-plan-text\",\n )}\n >\n {param.type || \"—\"}\n </span>\n }\n />\n </td>\n <td className=\"px-3 py-2 text-xs\">\n <WasArrowCurrent\n was={wasForRequired}\n current={\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\">\n optional\n </span>\n )\n }\n />\n </td>\n <td className=\"px-3 py-2 text-xs text-plan-muted\">\n {param.description || \"—\"}\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n </div>\n )}\n\n {hasRequest && (\n <div className=\"mt-5\">\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 {data.request?.contentType && (\n <span className=\"rounded bg-accent/40 px-1.5 py-0.5 font-mono text-[11px] text-plan-muted\">\n {data.request.contentType}\n </span>\n )}\n </div>\n {data.request?.example && (\n <ApiExample\n example={data.request.example}\n contentType={data.request.contentType}\n className=\"mt-2 an-api-endpoint-example\"\n />\n )}\n </div>\n )}\n\n {responses.length > 0 && (\n <div className=\"mt-5\">\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 {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\n className={cn(\n \"text-sm\",\n response.change\n ? CHANGE_INK[response.change]\n : \"text-plan-muted\",\n )}\n >\n {response.description}\n </span>\n )}\n {response.change && (\n <ChangeChip\n change={response.change}\n variant=\"label\"\n className=\"ml-auto\"\n />\n )}\n </div>\n {response.example && (\n <div className=\"px-3 pb-3 pt-0 an-api-endpoint-example\">\n <ApiExample\n example={response.example}\n className=\"mt-0\"\n />\n </div>\n )}\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n </section>\n );\n}\n\n/* ── Edit (panel form) ─────────────────────────────────────────────────────── */\n\nconst fieldLabelClass = \"text-xs font-medium text-muted-foreground\";\n\n/**\n * Options for a change `DevSelect` — a leading \"No change\" entry (decodes to\n * `undefined`) plus the four diff states, mirroring the file-tree editor.\n */\nconst CHANGE_SELECT_OPTIONS = [\n { value: \"none\", label: \"No change\" },\n ...API_ENDPOINT_CHANGES.map((change) => ({\n value: change,\n label: CHANGE_LABEL[change],\n })),\n];\n\n/**\n * Panel editor for an `api-endpoint` block. A property form: method (Select),\n * path/summary/auth (Input), description (Textarea), deprecated (Switch), plus\n * repeatable rows for params and responses (add/remove) and a request-body\n * textarea. Renders BARE content (no `<section>`); the registry's panel surface\n * supplies the popover chrome.\n */\nexport function ApiEndpointEdit({\n data,\n onChange,\n editable,\n}: BlockEditProps<ApiEndpointData>) {\n const params = data.params ?? [];\n const responses = data.responses ?? [];\n\n const patch = (next: Partial<ApiEndpointData>) =>\n onChange({ ...data, ...next });\n\n const updateParam = (index: number, next: Partial<ApiEndpointParam>) =>\n patch({\n params: params.map((param, i) =>\n i === index ? { ...param, ...next } : param,\n ),\n });\n\n const removeParam = (index: number) =>\n patch({ params: params.filter((_, i) => i !== index) });\n\n const addParam = () =>\n patch({\n params: [...params, { name: \"param\", in: \"query\" as ApiParamLocation }],\n });\n\n const updateResponse = (index: number, next: Partial<ApiEndpointResponse>) =>\n patch({\n responses: responses.map((response, i) =>\n i === index ? { ...response, ...next } : response,\n ),\n });\n\n const removeResponse = (index: number) =>\n patch({ responses: responses.filter((_, i) => i !== index) });\n\n const addResponse = () =>\n patch({ responses: [...responses, { status: \"200\" }] });\n\n const updateRequest = (next: Partial<ApiEndpointData[\"request\"]>) => {\n const merged = { ...(data.request ?? {}), ...next };\n const empty = !merged.contentType && !merged.example;\n patch({ request: empty ? undefined : merged });\n };\n\n return (\n <div className=\"flex flex-col gap-4\" data-plan-interactive>\n <div className=\"grid grid-cols-[120px_minmax(0,1fr)] gap-2\">\n <label className=\"flex flex-col gap-1.5\">\n <span className={fieldLabelClass}>Method</span>\n <DevSelect\n className=\"h-9\"\n value={data.method}\n disabled={!editable}\n onValueChange={(value) =>\n patch({ method: value as ApiEndpointMethod })\n }\n options={API_ENDPOINT_METHODS.map((method) => ({\n value: method,\n label: method,\n }))}\n />\n </label>\n <label className=\"flex flex-col gap-1.5\">\n <span className={fieldLabelClass}>Path</span>\n <DevInput\n className=\"h-9 font-mono\"\n value={data.path}\n disabled={!editable}\n placeholder=\"/api/resource\"\n onChange={(event) => patch({ path: event.target.value })}\n />\n </label>\n </div>\n\n <label className=\"flex flex-col gap-1.5\">\n <span className={fieldLabelClass}>Summary</span>\n <DevInput\n className=\"h-9\"\n value={data.summary ?? \"\"}\n disabled={!editable}\n placeholder=\"Short one-line description\"\n onChange={(event) =>\n patch({ summary: event.target.value || undefined })\n }\n />\n </label>\n\n <label className=\"flex flex-col gap-1.5\">\n <span className={fieldLabelClass}>Description (markdown)</span>\n <DevTextarea\n className=\"min-h-[80px]\"\n value={data.description ?? \"\"}\n disabled={!editable}\n placeholder=\"Longer description, rendered as markdown\"\n onChange={(event) =>\n patch({ description: event.target.value || undefined })\n }\n />\n </label>\n\n <div className=\"grid grid-cols-[minmax(0,1fr)_120px_auto] items-end gap-3\">\n <label className=\"flex flex-col gap-1.5\">\n <span className={fieldLabelClass}>Auth</span>\n <DevInput\n className=\"h-9\"\n value={data.auth ?? \"\"}\n disabled={!editable}\n placeholder=\"e.g. Bearer token\"\n onChange={(event) =>\n patch({ auth: event.target.value || undefined })\n }\n />\n </label>\n <label className=\"flex flex-col gap-1.5\">\n <span className={fieldLabelClass}>Change</span>\n <DevSelect\n className=\"h-9\"\n value={data.change ?? \"none\"}\n disabled={!editable}\n onValueChange={(value) =>\n patch({\n change:\n value === \"none\" ? undefined : (value as ApiEndpointChange),\n })\n }\n options={CHANGE_SELECT_OPTIONS}\n />\n </label>\n <label className=\"flex items-center gap-2 pb-2\">\n <DevSwitch\n checked={Boolean(data.deprecated)}\n disabled={!editable}\n onCheckedChange={(checked) =>\n patch({ deprecated: checked || undefined })\n }\n />\n <span className={fieldLabelClass}>Deprecated</span>\n </label>\n </div>\n\n {/* Params */}\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex items-center justify-between\">\n <span className={fieldLabelClass}>Parameters</span>\n {editable && (\n <button\n type=\"button\"\n data-plan-interactive\n className=\"flex items-center gap-1 rounded-md px-2 py-1 text-xs text-muted-foreground hover:bg-accent/60 hover:text-foreground\"\n onClick={addParam}\n >\n <IconPlus className=\"size-3.5\" />\n Add\n </button>\n )}\n </div>\n {params.map((param, index) => (\n <div\n key={index}\n className=\"flex flex-col gap-2 rounded-md border border-input p-2\"\n >\n <div className=\"grid grid-cols-[minmax(0,1fr)_96px_auto] gap-2\">\n <DevInput\n className=\"h-8 font-mono text-xs\"\n value={param.name}\n disabled={!editable}\n placeholder=\"name\"\n onChange={(event) =>\n updateParam(index, { name: event.target.value })\n }\n />\n <DevSelect\n className=\"h-8\"\n value={param.in}\n disabled={!editable}\n onValueChange={(value) =>\n updateParam(index, { in: value as ApiParamLocation })\n }\n options={API_PARAM_LOCATIONS.map((location) => ({\n value: location,\n label: location,\n }))}\n />\n {editable && (\n <button\n type=\"button\"\n data-plan-interactive\n aria-label=\"Remove parameter\"\n className=\"flex size-8 items-center justify-center rounded-md text-muted-foreground hover:bg-accent/60 hover:text-foreground\"\n onClick={() => removeParam(index)}\n >\n <IconTrash className=\"size-4\" />\n </button>\n )}\n </div>\n <div className=\"grid grid-cols-[minmax(0,1fr)_auto] items-center gap-2\">\n <DevInput\n className=\"h-8 font-mono text-xs\"\n value={param.type ?? \"\"}\n disabled={!editable}\n placeholder=\"type (e.g. string)\"\n onChange={(event) =>\n updateParam(index, { type: event.target.value || undefined })\n }\n />\n <label className=\"flex items-center gap-1.5 whitespace-nowrap text-xs text-muted-foreground\">\n <input\n type=\"checkbox\"\n className=\"size-3.5 cursor-pointer accent-primary\"\n checked={Boolean(param.required)}\n disabled={!editable}\n onChange={(event) =>\n updateParam(index, {\n required: event.target.checked || undefined,\n })\n }\n />\n Required\n </label>\n </div>\n <DevInput\n className=\"h-8 text-xs\"\n value={param.description ?? \"\"}\n disabled={!editable}\n placeholder=\"description\"\n onChange={(event) =>\n updateParam(index, {\n description: event.target.value || undefined,\n })\n }\n />\n {/* Diff state: change kind + the prior value (`was`) shown\n struck-through before the current one when \"modified\". */}\n <div className=\"grid grid-cols-[120px_minmax(0,1fr)] gap-2\">\n <DevSelect\n className=\"h-8\"\n value={param.change ?? \"none\"}\n disabled={!editable}\n onValueChange={(value) =>\n updateParam(index, {\n change:\n value === \"none\"\n ? undefined\n : (value as ApiEndpointChange),\n })\n }\n options={CHANGE_SELECT_OPTIONS}\n />\n <DevInput\n className=\"h-8 font-mono text-xs\"\n value={param.was ?? \"\"}\n disabled={!editable || param.change !== \"modified\"}\n placeholder=\"was (e.g. optional, or old type)\"\n onChange={(event) =>\n updateParam(index, { was: event.target.value || undefined })\n }\n />\n </div>\n </div>\n ))}\n </div>\n\n {/* Request body */}\n <div className=\"flex flex-col gap-2\">\n <span className={fieldLabelClass}>Request body</span>\n <DevInput\n className=\"h-8 font-mono text-xs\"\n value={data.request?.contentType ?? \"\"}\n disabled={!editable}\n placeholder=\"content type (e.g. application/json)\"\n onChange={(event) =>\n updateRequest({ contentType: event.target.value || undefined })\n }\n />\n <DevTextarea\n className=\"min-h-[80px] font-mono text-xs\"\n value={data.request?.example ?? \"\"}\n disabled={!editable}\n placeholder='{ \"example\": \"request body\" }'\n onChange={(event) =>\n updateRequest({ example: event.target.value || undefined })\n }\n />\n </div>\n\n {/* Responses */}\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex items-center justify-between\">\n <span className={fieldLabelClass}>Responses</span>\n {editable && (\n <button\n type=\"button\"\n data-plan-interactive\n className=\"flex items-center gap-1 rounded-md px-2 py-1 text-xs text-muted-foreground hover:bg-accent/60 hover:text-foreground\"\n onClick={addResponse}\n >\n <IconPlus className=\"size-3.5\" />\n Add\n </button>\n )}\n </div>\n {responses.map((response, index) => (\n <div\n key={index}\n className=\"flex flex-col gap-2 rounded-md border border-input p-2\"\n >\n <div className=\"grid grid-cols-[96px_minmax(0,1fr)_auto] gap-2\">\n <DevInput\n className=\"h-8 font-mono text-xs\"\n value={response.status}\n disabled={!editable}\n placeholder=\"200\"\n onChange={(event) =>\n updateResponse(index, { status: event.target.value })\n }\n />\n <DevInput\n className=\"h-8 text-xs\"\n value={response.description ?? \"\"}\n disabled={!editable}\n placeholder=\"description\"\n onChange={(event) =>\n updateResponse(index, {\n description: event.target.value || undefined,\n })\n }\n />\n {editable && (\n <button\n type=\"button\"\n data-plan-interactive\n aria-label=\"Remove response\"\n className=\"flex size-8 items-center justify-center rounded-md text-muted-foreground hover:bg-accent/60 hover:text-foreground\"\n onClick={() => removeResponse(index)}\n >\n <IconTrash className=\"size-4\" />\n </button>\n )}\n </div>\n <DevTextarea\n className=\"min-h-[64px] font-mono text-xs\"\n value={response.example ?? \"\"}\n disabled={!editable}\n placeholder='{ \"example\": \"response body\" }'\n onChange={(event) =>\n updateResponse(index, {\n example: event.target.value || undefined,\n })\n }\n />\n <label className=\"flex items-center gap-2\">\n <span className={fieldLabelClass}>Change</span>\n <DevSelect\n className=\"h-8 w-[120px]\"\n value={response.change ?? \"none\"}\n disabled={!editable}\n onValueChange={(value) =>\n updateResponse(index, {\n change:\n value === \"none\"\n ? undefined\n : (value as ApiEndpointChange),\n })\n }\n options={CHANGE_SELECT_OPTIONS}\n />\n </label>\n </div>\n ))}\n </div>\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ApiEndpointBlock.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/ApiEndpointBlock.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useState } from \"react\";\nimport {\n IconArrowNarrowRight,\n IconChevronRight,\n IconLock,\n IconPlus,\n IconTrash,\n} from \"@tabler/icons-react\";\nimport { cn } from \"../../utils.js\";\nimport { ltrCodeBlockProps } from \"../code-block-direction.js\";\nimport type { BlockEditProps, BlockReadProps } from \"../types.js\";\nimport type {\n ApiEndpointChange,\n ApiEndpointData,\n ApiEndpointMethod,\n ApiEndpointParam,\n ApiEndpointResponse,\n ApiParamLocation,\n} from \"./api-endpoint.config.js\";\nimport {\n API_ENDPOINT_CHANGES,\n API_ENDPOINT_METHODS,\n API_PARAM_LOCATIONS,\n} from \"./api-endpoint.config.js\";\nimport { useBlockCopy } from \"./block-copy.js\";\nimport { JsonExplorerSurface } from \"./JsonExplorerBlock.js\";\nimport {\n DevBadge,\n DevInput,\n DevSwitch,\n DevTextarea,\n DevSelect,\n} from \"./dev-doc-ui.js\";\n\n/**\n * Read + Edit renderers for an `api-endpoint` block — a Swagger / Stripe-style\n * API reference. Lives in core so any app can register the dev-doc block (no\n * shadcn import).\n */\n\n/* ── Theme-aware color tokens ──────────────────────────────────────────────── */\n\n/**\n * Method-pill palette. Tinted background + saturated text in BOTH modes (the\n * reference HTML hardcoded a dark-only palette — we deliberately avoid that).\n * Each entry keeps legible contrast against the plan surface under `.dark` and\n * light via Tailwind `dark:` variants.\n */\nconst METHOD_PILL: Record<ApiEndpointMethod, 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};\n\n/** Location-badge palette for the params table `in` column. */\nconst PARAM_IN_BADGE: Record<ApiParamLocation, 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 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 // 3xx and everything else → neutral slate.\n return \"bg-slate-200 text-slate-700 dark:bg-slate-500/20 dark:text-slate-300\";\n}\n\n/* ── Theme-aware change tokens (shared vocabulary with file-tree/data-model) ── */\n\n/**\n * Change-chip palette — IDENTICAL to `FileTreeBlock`'s `CHANGE_BADGE` so a route /\n * param / response chip reads the same as a file or field change chip elsewhere\n * in the recap. Tinted background + saturated text in BOTH the `.dark` plan theme\n * and light mode via Tailwind `dark:` variants (never a dark-only palette).\n */\nconst CHANGE_BADGE: Record<ApiEndpointChange, string> = {\n added:\n \"bg-emerald-100 text-emerald-700 dark:bg-emerald-500/15 dark:text-emerald-300\",\n modified: \"bg-blue-100 text-blue-700 dark:bg-blue-500/15 dark:text-blue-300\",\n removed: \"bg-red-100 text-red-700 dark:bg-red-500/15 dark:text-red-300\",\n renamed:\n \"bg-violet-100 text-violet-700 dark:bg-violet-500/15 dark:text-violet-300\",\n};\n\n/** Single-letter glyph shown in the compact chip (VS Code gutter convention). */\nconst CHANGE_GLYPH: Record<ApiEndpointChange, string> = {\n added: \"A\",\n modified: \"M\",\n removed: \"D\",\n renamed: \"R\",\n};\n\n/** Human label for the chip text + its `title` / `aria-label`. */\nconst CHANGE_LABEL: Record<ApiEndpointChange, string> = {\n added: \"Added\",\n modified: \"Modified\",\n removed: \"Removed\",\n renamed: \"Renamed\",\n};\n\n/** Accent ink echoing a change color, for the name/path it applies to. */\nconst CHANGE_INK: Record<ApiEndpointChange, string> = {\n added: \"text-emerald-700 dark:text-emerald-300\",\n modified: \"text-blue-700 dark:text-blue-300\",\n removed: \"text-red-600 line-through dark:text-red-300\",\n renamed: \"text-violet-700 dark:text-violet-300\",\n};\n\n/**\n * A change chip: compact single-glyph badge (A/M/D/R) by default, or a labeled\n * pill (`variant=\"label\"`) for the endpoint header where there is room. Matches\n * the file-tree change badge so the recap reads consistently.\n */\nfunction ChangeChip({\n change,\n label = CHANGE_LABEL[change],\n variant = \"glyph\",\n className,\n}: {\n change: ApiEndpointChange;\n label?: string;\n variant?: \"glyph\" | \"label\";\n className?: string;\n}) {\n if (variant === \"label\") {\n return (\n <span\n title={label}\n className={cn(\n \"shrink-0 rounded px-1.5 py-0.5 text-[10px] font-bold uppercase tracking-wide\",\n CHANGE_BADGE[change],\n className,\n )}\n >\n {label}\n </span>\n );\n }\n return (\n <span\n title={label}\n aria-label={label}\n className={cn(\n \"flex size-4 shrink-0 items-center justify-center rounded text-[10px] font-bold leading-none\",\n CHANGE_BADGE[change],\n className,\n )}\n >\n {CHANGE_GLYPH[change]}\n </span>\n );\n}\n\n/**\n * Before → after for a modified param: the prior `was` value struck through, a\n * narrow arrow, then the current value (e.g. `optional → required`, or the old\n * type → the new type). When `was` is absent we just show the current value.\n */\nfunction WasArrowCurrent({\n was,\n current,\n}: {\n was?: string;\n current: React.ReactNode;\n}) {\n if (!was) return <>{current}</>;\n return (\n <span className=\"inline-flex items-center gap-1\">\n <span className=\"text-plan-muted line-through\">{was}</span>\n <IconArrowNarrowRight className=\"size-3 shrink-0 text-plan-muted\" />\n {current}\n </span>\n );\n}\n\n/**\n * A param carries a single `was` (prior value) for a `modified` change, but that\n * value may describe either the required flag or the type. Decide which column\n * the before→after belongs to: a `was` of `required`/`optional` is a required\n * flag flip; anything else is treated as the prior type.\n */\nfunction wasIsRequiredFlag(was: string): boolean {\n const v = was.trim().toLowerCase();\n return v === \"required\" || v === \"optional\";\n}\n\n/** Guess a fence language from a content type so examples highlight nicely. */\nfunction fenceLangForContentType(contentType?: string): string {\n const ct = (contentType ?? \"\").toLowerCase();\n if (ct.includes(\"xml\") || ct.includes(\"html\")) return \"html\";\n if (ct.includes(\"yaml\") || ct.includes(\"yml\")) return \"yaml\";\n return \"json\";\n}\n\n/**\n * Strip JSONC niceties so an otherwise-valid-but-commented example still parses\n * as JSON and earns the collapsible JsonExplorer (instead of falling back to a\n * plain code block). Removes `//` line comments and `/* … */` block comments,\n * then trailing commas before `}`/`]`. String contents are preserved: `//`\n * inside a quoted string (e.g. a URL) is NOT treated as a comment.\n */\nfunction stripJsonComments(source: string): string {\n let out = \"\";\n let inString = false;\n let stringQuote = \"\";\n let inLineComment = false;\n let inBlockComment = false;\n\n for (let i = 0; i < source.length; i += 1) {\n const char = source[i];\n const next = source[i + 1];\n\n if (inLineComment) {\n if (char === \"\\n\") {\n inLineComment = false;\n out += char;\n }\n continue;\n }\n\n if (inBlockComment) {\n if (char === \"*\" && next === \"/\") {\n inBlockComment = false;\n i += 1;\n }\n continue;\n }\n\n if (inString) {\n out += char;\n if (char === \"\\\\\") {\n // Copy the escaped char verbatim so an escaped quote can't end the\n // string early.\n if (next !== undefined) {\n out += next;\n i += 1;\n }\n } else if (char === stringQuote) {\n inString = false;\n }\n continue;\n }\n\n if (char === '\"' || char === \"'\") {\n inString = true;\n stringQuote = char;\n out += char;\n continue;\n }\n\n if (char === \"/\" && next === \"/\") {\n inLineComment = true;\n i += 1;\n continue;\n }\n\n if (char === \"/\" && next === \"*\") {\n inBlockComment = true;\n i += 1;\n continue;\n }\n\n // Drop a trailing comma before a closing bracket so the result is strict\n // JSON. Done here (not via a post-pass regex) so it stays string-aware: we\n // only reach this branch outside strings/comments, and the structural comma\n // is the last non-whitespace char already emitted. A comma inside a string\n // value like `\"hello,}\"` is followed by its closing quote, not the bracket,\n // so it is never stripped.\n if (char === \"}\" || char === \"]\") {\n out = out.replace(/,\\s*$/, \"\");\n }\n out += char;\n }\n\n return out;\n}\n\n/**\n * Decide whether an example should render with the collapsible JsonExplorer.\n * Returns the strict-JSON text to feed the explorer (comment-stripped when the\n * raw example was JSONC), or `null` when the example is not parseable as JSON\n * (free-form / XML / YAML text) and should fall back to the styled code surface.\n *\n * Parseability — NOT the declared `contentType` — is the gate, so the REQUEST\n * body example earns the same interactive explorer as the RESPONSE examples\n * whenever it is valid JSON. A request often carries a `contentType` that is not\n * literally `application/json` (e.g. a WebSocket-upgrade body) yet still holds a\n * JSON payload; keying off the content type would wrongly drop those into the\n * static code block. `contentType` now only labels the non-JSON code fallback\n * (via `fenceLangForContentType`), it never suppresses the explorer.\n */\nfunction jsonExplorerSource(example: string): string | null {\n try {\n JSON.parse(example);\n return example;\n } catch {\n // Tolerate JSONC: a commented-but-otherwise-valid body still gets the nice\n // explorer. Feed the explorer the stripped (strict-JSON) text so it parses.\n const stripped = stripJsonComments(example);\n try {\n JSON.parse(stripped);\n return stripped;\n } catch {\n return null;\n }\n }\n}\n\n/**\n * Plain (non-JSON) example fallback. Renders inside the SAME surface chrome as\n * {@link JsonExplorerSurface} — one `rounded-xl border bg-plan-code` box with a\n * label bar and an `overflow-auto` scroll body — so a JSONC / free-form example\n * reads consistently with the JSON-explorer examples instead of as a separate,\n * differently-styled code box (no extra background tint, no clipped overflow).\n * Font-size is inherited from `--plan-code-size` (the same token the global code\n * rule manages); we never hardcode it here.\n */\nfunction ApiCodeExample({\n code,\n label = \"JSON\",\n className,\n}: {\n code: string;\n label?: string;\n className?: string;\n}) {\n return (\n <div\n data-code-surface\n className={cn(\n \"overflow-hidden rounded-xl border border-plan-line bg-plan-code\",\n className,\n )}\n >\n <div className=\"flex items-center gap-2 border-b border-plan-line px-3 py-1.5\">\n <span className=\"font-mono text-xs uppercase tracking-wide text-plan-muted\">\n {label}\n </span>\n </div>\n <pre className=\"overflow-x-auto px-3 py-2.5 font-mono [font-size:var(--plan-doc-code-size)] leading-relaxed text-plan-code-text\">\n {code}\n </pre>\n </div>\n );\n}\n\nfunction ApiExample({\n example,\n contentType,\n className,\n}: {\n example: string;\n contentType?: string;\n className?: string;\n}) {\n const jsonSource = jsonExplorerSource(example);\n if (jsonSource !== null) {\n return (\n <JsonExplorerSurface\n data={{ json: jsonSource, collapsedDepth: 2 }}\n className={className}\n />\n );\n }\n\n return (\n <ApiCodeExample\n code={example}\n label={fenceLangForContentType(contentType).toUpperCase()}\n className={className}\n />\n );\n}\n\n/* ── Read (collapsed-by-default swagger row) ───────────────────────────────── */\n\n/**\n * Read-only renderer for an `api-endpoint` block. Collapsed by default: a single\n * row with a colored method pill, monospace path, muted summary, and a chevron.\n * Clicking the row expands the full reference (description, params table,\n * request body, responses) — the Swagger / Stripe house style. Every colored\n * element is theme-aware (`dark:` variants), so it reads correctly in both the\n * `.dark` plan theme and light mode.\n */\nexport function ApiEndpointRead({\n data,\n blockId,\n title,\n summary,\n ctx,\n}: BlockReadProps<ApiEndpointData>) {\n const [open, setOpen] = useState(false);\n const copy = useBlockCopy();\n const changeLabel: Record<ApiEndpointChange, string> = {\n added: copy.added,\n modified: copy.modified,\n removed: copy.removed,\n renamed: copy.renamed,\n };\n\n const params = data.params ?? [];\n const responses = data.responses ?? [];\n const hasRequest = Boolean(\n data.request?.example || data.request?.contentType,\n );\n const hasBody =\n Boolean(data.description?.trim()) ||\n params.length > 0 ||\n hasRequest ||\n responses.length > 0 ||\n Boolean(data.auth);\n\n return (\n // `data-block-type` lets the document flow detect a RUN of consecutive\n // api-endpoint blocks and collapse the divider + gap between them (see\n // `.plan-document-flow` rules in the plan template's global.css), so a list\n // of endpoints reads as one tight scannable group instead of separate\n // full-width cards. `an-api-endpoint-card` is the flush-able card surface\n // those rules round/merge at the run's edges.\n <section\n {...ltrCodeBlockProps}\n className=\"plan-block\"\n data-block-id={blockId}\n data-block-type=\"api-endpoint\"\n >\n {title && <div className=\"plan-block-label\">{title}</div>}\n <div className=\"an-api-endpoint-card overflow-hidden rounded-xl border border-plan-line bg-plan-block\">\n {/* Collapsed summary row — the whole row toggles. */}\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-3 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[data.method],\n )}\n >\n {data.method}\n </span>\n <span\n className={cn(\n \"min-w-0 truncate font-mono text-sm font-semibold\",\n // `change` ink composes with `deprecated`: a deprecated route\n // still mutes/strikes its path; a changed route tints it (a\n // removed route also strikes via CHANGE_INK).\n data.change ? CHANGE_INK[data.change] : \"text-plan-text\",\n data.deprecated && \"text-plan-muted line-through\",\n )}\n >\n {data.path}\n </span>\n {data.change && (\n <ChangeChip\n change={data.change}\n label={changeLabel[data.change]}\n variant=\"label\"\n />\n )}\n {data.deprecated && (\n <DevBadge className=\"shrink-0 border-amber-500/40 text-amber-600 dark:text-amber-300\">\n {copy.deprecated}\n </DevBadge>\n )}\n {(data.summary || summary) && (\n <span className=\"ml-1 min-w-0 flex-1 truncate text-sm text-plan-muted\">\n {data.summary || summary}\n </span>\n )}\n {data.auth && (\n <IconLock\n className=\"size-3.5 shrink-0 text-plan-muted\"\n aria-label={copy.requiresAuthentication}\n />\n )}\n </button>\n\n {/* Expanded body. No top divider: the title/summary row flows into the\n content separated by padding alone (the user finds mid-card dividers\n distracting; the outer card border + run-flush behavior stay). */}\n {open && hasBody && (\n <div className=\"px-4 pb-4 pt-1\">\n {data.auth && (\n <div className=\"mb-4 flex items-center gap-2 text-xs text-plan-muted\">\n <IconLock className=\"size-3.5 shrink-0\" />\n <span>\n <span className=\"font-medium text-plan-text\">\n {copy.auth}:\n </span>{\" \"}\n {data.auth}\n </span>\n </div>\n )}\n\n {data.description?.trim() && (\n <div className=\"an-api-endpoint-desc\">\n {ctx.renderMarkdown?.(data.description)}\n </div>\n )}\n\n {params.length > 0 && (\n <div className=\"mt-5\">\n <div className=\"text-xs font-semibold uppercase tracking-wide text-plan-muted\">\n {copy.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\">{copy.name}</th>\n <th className=\"px-3 py-2 font-medium\">{copy.in}</th>\n <th className=\"px-3 py-2 font-medium\">{copy.type}</th>\n <th className=\"px-3 py-2 font-medium\">\n {copy.requiredColumn}\n </th>\n <th className=\"px-3 py-2 font-medium\">\n {copy.description}\n </th>\n </tr>\n </thead>\n <tbody>\n {params.map((param, index) => {\n const change = param.change;\n // A `modified` `was` describes either the required flag\n // or the prior type; route it to the right column.\n const wasForRequired =\n change === \"modified\" &&\n param.was &&\n wasIsRequiredFlag(param.was)\n ? param.was\n : undefined;\n const wasForType =\n change === \"modified\" &&\n param.was &&\n !wasIsRequiredFlag(param.was)\n ? param.was\n : undefined;\n return (\n <tr\n key={`${param.name}-${index}`}\n className=\"border-t border-plan-line align-top\"\n >\n <td className=\"px-3 py-2 font-mono text-xs font-semibold\">\n <span className=\"flex items-center gap-1.5\">\n <span\n className={cn(\n change\n ? CHANGE_INK[change]\n : \"text-plan-text\",\n )}\n >\n {param.name}\n </span>\n {change && (\n <ChangeChip\n change={change}\n label={changeLabel[change]}\n />\n )}\n </span>\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 )}\n >\n {param.in}\n </span>\n </td>\n <td className=\"px-3 py-2 font-mono text-xs text-plan-muted\">\n <WasArrowCurrent\n was={wasForType}\n current={\n <span\n className={cn(\n wasForType && \"text-plan-text\",\n )}\n >\n {param.type || \"—\"}\n </span>\n }\n />\n </td>\n <td className=\"px-3 py-2 text-xs\">\n <WasArrowCurrent\n was={wasForRequired}\n current={\n param.required ? (\n <span className=\"font-medium text-red-600 dark:text-red-300\">\n {copy.required}\n </span>\n ) : (\n <span className=\"text-plan-muted\">\n {copy.optional}\n </span>\n )\n }\n />\n </td>\n <td className=\"px-3 py-2 text-xs text-plan-muted\">\n {param.description || \"—\"}\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n </div>\n )}\n\n {hasRequest && (\n <div className=\"mt-5\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs font-semibold uppercase tracking-wide text-plan-muted\">\n {copy.requestBody}\n </span>\n {data.request?.contentType && (\n <span className=\"rounded bg-accent/40 px-1.5 py-0.5 font-mono text-[11px] text-plan-muted\">\n {data.request.contentType}\n </span>\n )}\n </div>\n {data.request?.example && (\n <ApiExample\n example={data.request.example}\n contentType={data.request.contentType}\n className=\"mt-2 an-api-endpoint-example\"\n />\n )}\n </div>\n )}\n\n {responses.length > 0 && (\n <div className=\"mt-5\">\n <div className=\"text-xs font-semibold uppercase tracking-wide text-plan-muted\">\n {copy.responses}\n </div>\n <div className=\"mt-2 flex flex-col gap-3\">\n {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\n className={cn(\n \"text-sm\",\n response.change\n ? CHANGE_INK[response.change]\n : \"text-plan-muted\",\n )}\n >\n {response.description}\n </span>\n )}\n {response.change && (\n <ChangeChip\n change={response.change}\n variant=\"label\"\n className=\"ml-auto\"\n />\n )}\n </div>\n {response.example && (\n <div className=\"px-3 pb-3 pt-0 an-api-endpoint-example\">\n <ApiExample\n example={response.example}\n className=\"mt-0\"\n />\n </div>\n )}\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n </section>\n );\n}\n\n/* ── Edit (panel form) ─────────────────────────────────────────────────────── */\n\nconst fieldLabelClass = \"text-xs font-medium text-muted-foreground\";\n\n/**\n * Options for a change `DevSelect` — a leading \"No change\" entry (decodes to\n * `undefined`) plus the four diff states, mirroring the file-tree editor.\n */\nconst CHANGE_SELECT_OPTIONS = [\n { value: \"none\", label: \"No change\" },\n ...API_ENDPOINT_CHANGES.map((change) => ({\n value: change,\n label: CHANGE_LABEL[change],\n })),\n];\n\n/**\n * Panel editor for an `api-endpoint` block. A property form: method (Select),\n * path/summary/auth (Input), description (Textarea), deprecated (Switch), plus\n * repeatable rows for params and responses (add/remove) and a request-body\n * textarea. Renders BARE content (no `<section>`); the registry's panel surface\n * supplies the popover chrome.\n */\nexport function ApiEndpointEdit({\n data,\n onChange,\n editable,\n}: BlockEditProps<ApiEndpointData>) {\n const params = data.params ?? [];\n const responses = data.responses ?? [];\n\n const patch = (next: Partial<ApiEndpointData>) =>\n onChange({ ...data, ...next });\n\n const updateParam = (index: number, next: Partial<ApiEndpointParam>) =>\n patch({\n params: params.map((param, i) =>\n i === index ? { ...param, ...next } : param,\n ),\n });\n\n const removeParam = (index: number) =>\n patch({ params: params.filter((_, i) => i !== index) });\n\n const addParam = () =>\n patch({\n params: [...params, { name: \"param\", in: \"query\" as ApiParamLocation }],\n });\n\n const updateResponse = (index: number, next: Partial<ApiEndpointResponse>) =>\n patch({\n responses: responses.map((response, i) =>\n i === index ? { ...response, ...next } : response,\n ),\n });\n\n const removeResponse = (index: number) =>\n patch({ responses: responses.filter((_, i) => i !== index) });\n\n const addResponse = () =>\n patch({ responses: [...responses, { status: \"200\" }] });\n\n const updateRequest = (next: Partial<ApiEndpointData[\"request\"]>) => {\n const merged = { ...(data.request ?? {}), ...next };\n const empty = !merged.contentType && !merged.example;\n patch({ request: empty ? undefined : merged });\n };\n\n return (\n <div className=\"flex flex-col gap-4\" data-plan-interactive>\n <div className=\"grid grid-cols-[120px_minmax(0,1fr)] gap-2\">\n <label className=\"flex flex-col gap-1.5\">\n <span className={fieldLabelClass}>Method</span>\n <DevSelect\n className=\"h-9\"\n value={data.method}\n disabled={!editable}\n onValueChange={(value) =>\n patch({ method: value as ApiEndpointMethod })\n }\n options={API_ENDPOINT_METHODS.map((method) => ({\n value: method,\n label: method,\n }))}\n />\n </label>\n <label className=\"flex flex-col gap-1.5\">\n <span className={fieldLabelClass}>Path</span>\n <DevInput\n className=\"h-9 font-mono\"\n value={data.path}\n disabled={!editable}\n placeholder=\"/api/resource\"\n onChange={(event) => patch({ path: event.target.value })}\n />\n </label>\n </div>\n\n <label className=\"flex flex-col gap-1.5\">\n <span className={fieldLabelClass}>Summary</span>\n <DevInput\n className=\"h-9\"\n value={data.summary ?? \"\"}\n disabled={!editable}\n placeholder=\"Short one-line description\"\n onChange={(event) =>\n patch({ summary: event.target.value || undefined })\n }\n />\n </label>\n\n <label className=\"flex flex-col gap-1.5\">\n <span className={fieldLabelClass}>Description (markdown)</span>\n <DevTextarea\n className=\"min-h-[80px]\"\n value={data.description ?? \"\"}\n disabled={!editable}\n placeholder=\"Longer description, rendered as markdown\"\n onChange={(event) =>\n patch({ description: event.target.value || undefined })\n }\n />\n </label>\n\n <div className=\"grid grid-cols-[minmax(0,1fr)_120px_auto] items-end gap-3\">\n <label className=\"flex flex-col gap-1.5\">\n <span className={fieldLabelClass}>Auth</span>\n <DevInput\n className=\"h-9\"\n value={data.auth ?? \"\"}\n disabled={!editable}\n placeholder=\"e.g. Bearer token\"\n onChange={(event) =>\n patch({ auth: event.target.value || undefined })\n }\n />\n </label>\n <label className=\"flex flex-col gap-1.5\">\n <span className={fieldLabelClass}>Change</span>\n <DevSelect\n className=\"h-9\"\n value={data.change ?? \"none\"}\n disabled={!editable}\n onValueChange={(value) =>\n patch({\n change:\n value === \"none\" ? undefined : (value as ApiEndpointChange),\n })\n }\n options={CHANGE_SELECT_OPTIONS}\n />\n </label>\n <label className=\"flex items-center gap-2 pb-2\">\n <DevSwitch\n checked={Boolean(data.deprecated)}\n disabled={!editable}\n onCheckedChange={(checked) =>\n patch({ deprecated: checked || undefined })\n }\n />\n <span className={fieldLabelClass}>Deprecated</span>\n </label>\n </div>\n\n {/* Params */}\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex items-center justify-between\">\n <span className={fieldLabelClass}>Parameters</span>\n {editable && (\n <button\n type=\"button\"\n data-plan-interactive\n className=\"flex items-center gap-1 rounded-md px-2 py-1 text-xs text-muted-foreground hover:bg-accent/60 hover:text-foreground\"\n onClick={addParam}\n >\n <IconPlus className=\"size-3.5\" />\n Add\n </button>\n )}\n </div>\n {params.map((param, index) => (\n <div\n key={index}\n className=\"flex flex-col gap-2 rounded-md border border-input p-2\"\n >\n <div className=\"grid grid-cols-[minmax(0,1fr)_96px_auto] gap-2\">\n <DevInput\n className=\"h-8 font-mono text-xs\"\n value={param.name}\n disabled={!editable}\n placeholder=\"name\"\n onChange={(event) =>\n updateParam(index, { name: event.target.value })\n }\n />\n <DevSelect\n className=\"h-8\"\n value={param.in}\n disabled={!editable}\n onValueChange={(value) =>\n updateParam(index, { in: value as ApiParamLocation })\n }\n options={API_PARAM_LOCATIONS.map((location) => ({\n value: location,\n label: location,\n }))}\n />\n {editable && (\n <button\n type=\"button\"\n data-plan-interactive\n aria-label=\"Remove parameter\"\n className=\"flex size-8 items-center justify-center rounded-md text-muted-foreground hover:bg-accent/60 hover:text-foreground\"\n onClick={() => removeParam(index)}\n >\n <IconTrash className=\"size-4\" />\n </button>\n )}\n </div>\n <div className=\"grid grid-cols-[minmax(0,1fr)_auto] items-center gap-2\">\n <DevInput\n className=\"h-8 font-mono text-xs\"\n value={param.type ?? \"\"}\n disabled={!editable}\n placeholder=\"type (e.g. string)\"\n onChange={(event) =>\n updateParam(index, { type: event.target.value || undefined })\n }\n />\n <label className=\"flex items-center gap-1.5 whitespace-nowrap text-xs text-muted-foreground\">\n <input\n type=\"checkbox\"\n className=\"size-3.5 cursor-pointer accent-primary\"\n checked={Boolean(param.required)}\n disabled={!editable}\n onChange={(event) =>\n updateParam(index, {\n required: event.target.checked || undefined,\n })\n }\n />\n Required\n </label>\n </div>\n <DevInput\n className=\"h-8 text-xs\"\n value={param.description ?? \"\"}\n disabled={!editable}\n placeholder=\"description\"\n onChange={(event) =>\n updateParam(index, {\n description: event.target.value || undefined,\n })\n }\n />\n {/* Diff state: change kind + the prior value (`was`) shown\n struck-through before the current one when \"modified\". */}\n <div className=\"grid grid-cols-[120px_minmax(0,1fr)] gap-2\">\n <DevSelect\n className=\"h-8\"\n value={param.change ?? \"none\"}\n disabled={!editable}\n onValueChange={(value) =>\n updateParam(index, {\n change:\n value === \"none\"\n ? undefined\n : (value as ApiEndpointChange),\n })\n }\n options={CHANGE_SELECT_OPTIONS}\n />\n <DevInput\n className=\"h-8 font-mono text-xs\"\n value={param.was ?? \"\"}\n disabled={!editable || param.change !== \"modified\"}\n placeholder=\"was (e.g. optional, or old type)\"\n onChange={(event) =>\n updateParam(index, { was: event.target.value || undefined })\n }\n />\n </div>\n </div>\n ))}\n </div>\n\n {/* Request body */}\n <div className=\"flex flex-col gap-2\">\n <span className={fieldLabelClass}>Request body</span>\n <DevInput\n className=\"h-8 font-mono text-xs\"\n value={data.request?.contentType ?? \"\"}\n disabled={!editable}\n placeholder=\"content type (e.g. application/json)\"\n onChange={(event) =>\n updateRequest({ contentType: event.target.value || undefined })\n }\n />\n <DevTextarea\n className=\"min-h-[80px] font-mono text-xs\"\n value={data.request?.example ?? \"\"}\n disabled={!editable}\n placeholder='{ \"example\": \"request body\" }'\n onChange={(event) =>\n updateRequest({ example: event.target.value || undefined })\n }\n />\n </div>\n\n {/* Responses */}\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex items-center justify-between\">\n <span className={fieldLabelClass}>Responses</span>\n {editable && (\n <button\n type=\"button\"\n data-plan-interactive\n className=\"flex items-center gap-1 rounded-md px-2 py-1 text-xs text-muted-foreground hover:bg-accent/60 hover:text-foreground\"\n onClick={addResponse}\n >\n <IconPlus className=\"size-3.5\" />\n Add\n </button>\n )}\n </div>\n {responses.map((response, index) => (\n <div\n key={index}\n className=\"flex flex-col gap-2 rounded-md border border-input p-2\"\n >\n <div className=\"grid grid-cols-[96px_minmax(0,1fr)_auto] gap-2\">\n <DevInput\n className=\"h-8 font-mono text-xs\"\n value={response.status}\n disabled={!editable}\n placeholder=\"200\"\n onChange={(event) =>\n updateResponse(index, { status: event.target.value })\n }\n />\n <DevInput\n className=\"h-8 text-xs\"\n value={response.description ?? \"\"}\n disabled={!editable}\n placeholder=\"description\"\n onChange={(event) =>\n updateResponse(index, {\n description: event.target.value || undefined,\n })\n }\n />\n {editable && (\n <button\n type=\"button\"\n data-plan-interactive\n aria-label=\"Remove response\"\n className=\"flex size-8 items-center justify-center rounded-md text-muted-foreground hover:bg-accent/60 hover:text-foreground\"\n onClick={() => removeResponse(index)}\n >\n <IconTrash className=\"size-4\" />\n </button>\n )}\n </div>\n <DevTextarea\n className=\"min-h-[64px] font-mono text-xs\"\n value={response.example ?? \"\"}\n disabled={!editable}\n placeholder='{ \"example\": \"response body\" }'\n onChange={(event) =>\n updateResponse(index, {\n example: event.target.value || undefined,\n })\n }\n />\n <label className=\"flex items-center gap-2\">\n <span className={fieldLabelClass}>Change</span>\n <DevSelect\n className=\"h-8 w-[120px]\"\n value={response.change ?? \"none\"}\n disabled={!editable}\n onValueChange={(value) =>\n updateResponse(index, {\n change:\n value === \"none\"\n ? undefined\n : (value as ApiEndpointChange),\n })\n }\n options={CHANGE_SELECT_OPTIONS}\n />\n </label>\n </div>\n ))}\n </div>\n </div>\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MermaidBlock.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/MermaidBlock.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"MermaidBlock.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/MermaidBlock.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAsRvD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,OAAO,EACP,KAAK,EACL,OAAO,GACR,EAAE,cAAc,CAAC,WAAW,CAAC,2CAe7B;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,QAAQ,EACR,QAAQ,GACT,EAAE,cAAc,CAAC,WAAW,CAAC,2CAwC7B"}
|
|
@@ -4,6 +4,7 @@ import { IconArrowsMaximize } from "@tabler/icons-react";
|
|
|
4
4
|
import { ltrCodeBlockProps } from "../code-block-direction.js";
|
|
5
5
|
import { DevInput, DevLabel } from "./dev-doc-ui.js";
|
|
6
6
|
import { DiagramLightbox } from "./diagram.js";
|
|
7
|
+
import { useBlockCopy } from "./block-copy.js";
|
|
7
8
|
function errorMessage(error) {
|
|
8
9
|
return error instanceof Error ? error.message : "Failed to render diagram";
|
|
9
10
|
}
|
|
@@ -86,6 +87,7 @@ function MermaidSvg({ svg, enlarged }) {
|
|
|
86
87
|
}
|
|
87
88
|
function MermaidDiagram({ source, idSeed, }) {
|
|
88
89
|
const isDark = useIsDark();
|
|
90
|
+
const copy = useBlockCopy();
|
|
89
91
|
// Only render the diagram after mount: `mermaid` is client-only and SSR has no
|
|
90
92
|
// DOM for it to measure against.
|
|
91
93
|
const [mounted, setMounted] = useState(false);
|
|
@@ -139,20 +141,20 @@ function MermaidDiagram({ source, idSeed, }) {
|
|
|
139
141
|
// dark/light updates the diagram live.
|
|
140
142
|
}, [mounted, source, isDark, renderId]);
|
|
141
143
|
if (!mounted) {
|
|
142
|
-
return (_jsx("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", children:
|
|
144
|
+
return (_jsx("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", children: copy.loadingDiagram }));
|
|
143
145
|
}
|
|
144
146
|
if (state.error) {
|
|
145
|
-
return (_jsxs("div", { className: "mt-2 space-y-2", children: [_jsx("pre", { className: "overflow-auto rounded-lg border border-plan-line bg-plan-code px-3 py-2 font-mono [font-size:var(--plan-code-size)] text-plan-code-text", children: source }), _jsxs("p", { className: "text-sm text-plan-muted", children: ["
|
|
147
|
+
return (_jsxs("div", { className: "mt-2 space-y-2", children: [_jsx("pre", { className: "overflow-auto rounded-lg border border-plan-line bg-plan-code px-3 py-2 font-mono [font-size:var(--plan-code-size)] text-plan-code-text", children: source }), _jsxs("p", { className: "text-sm text-plan-muted", children: [copy.couldNotRenderDiagram, ": ", state.error] })] }));
|
|
146
148
|
}
|
|
147
149
|
if (!state.svg) {
|
|
148
|
-
return (_jsx("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", children:
|
|
150
|
+
return (_jsx("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", children: copy.addDiagramDefinition }));
|
|
149
151
|
}
|
|
150
152
|
// Hover-revealed top-right expand button + shared lightbox, matching the
|
|
151
153
|
// DiagramBlock affordance exactly (same icon, reveal-on-hover/focus, Escape +
|
|
152
154
|
// backdrop close via the reused `DiagramLightbox`). The enlarged view re-shows
|
|
153
155
|
// the same rendered SVG scaled to fit the wider modal.
|
|
154
156
|
const svg = state.svg;
|
|
155
|
-
return (_jsxs("div", { className: "group/mermaid relative", children: [_jsx(MermaidSvg, { svg: svg }), _jsx("button", { type: "button", "data-plan-interactive": true, onClick: () => setExpanded(true), "aria-label":
|
|
157
|
+
return (_jsxs("div", { className: "group/mermaid relative", children: [_jsx(MermaidSvg, { svg: svg }), _jsx("button", { type: "button", "data-plan-interactive": true, onClick: () => setExpanded(true), "aria-label": copy.expandDiagram, title: copy.expandDiagram, className: "an-diagram-expand-trigger absolute right-2 top-2 z-10 flex size-7 items-center justify-center rounded-md border border-border/60 bg-background/90 text-muted-foreground opacity-0 shadow-sm backdrop-blur transition-[color,opacity] hover:text-foreground focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring group-hover/mermaid:opacity-100", children: _jsx(IconArrowsMaximize, { className: "size-4" }) }), expanded ? (_jsx(DiagramLightbox, { onClose: () => setExpanded(false), children: _jsx(MermaidSvg, { svg: svg, enlarged: true }) })) : null] }));
|
|
156
158
|
}
|
|
157
159
|
/**
|
|
158
160
|
* Read-only renderer for a `mermaid` block. Wraps the diagram in the standard
|
|
@@ -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 { IconArrowsMaximize } from \"@tabler/icons-react\";\nimport { ltrCodeBlockProps } from \"../code-block-direction.js\";\nimport type { BlockEditProps, BlockReadProps } from \"../types.js\";\nimport type { MermaidData } from \"./mermaid.config.js\";\nimport { DevInput, DevLabel } from \"./dev-doc-ui.js\";\nimport { DiagramLightbox } from \"./diagram.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\n/**\n * Inject a rendered Mermaid/Excalidraw SVG string. Shared by the inline render\n * and the expand lightbox so the enlarged view shows the exact same SVG; the\n * lightbox passes `enlarged` so the SVG stretches to fill the wider modal\n * (`max-w-5xl`) instead of staying at its intrinsic inline size.\n */\nfunction MermaidSvg({ svg, enlarged }: { svg: string; enlarged?: boolean }) {\n return (\n <div\n className={\n enlarged\n ? \"flex justify-center overflow-auto [&_svg]:h-auto [&_svg]:w-full [&_svg]:max-w-full\"\n : \"mt-2 flex justify-center overflow-auto [&_svg]:h-auto [&_svg]:max-w-full\"\n }\n // Excalidraw and Mermaid output are sanitized before injection.\n dangerouslySetInnerHTML={{ __html: svg }}\n />\n );\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 const [expanded, setExpanded] = useState(false);\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 [font-size:var(--plan-code-size)] 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 // Hover-revealed top-right expand button + shared lightbox, matching the\n // DiagramBlock affordance exactly (same icon, reveal-on-hover/focus, Escape +\n // backdrop close via the reused `DiagramLightbox`). The enlarged view re-shows\n // the same rendered SVG scaled to fit the wider modal.\n const svg = state.svg;\n return (\n <div className=\"group/mermaid relative\">\n <MermaidSvg svg={svg} />\n <button\n type=\"button\"\n data-plan-interactive\n onClick={() => setExpanded(true)}\n aria-label=\"Expand diagram\"\n title=\"Expand diagram\"\n className=\"an-diagram-expand-trigger absolute right-2 top-2 z-10 flex size-7 items-center justify-center rounded-md border border-border/60 bg-background/90 text-muted-foreground opacity-0 shadow-sm backdrop-blur transition-[color,opacity] hover:text-foreground focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring group-hover/mermaid:opacity-100\"\n >\n <IconArrowsMaximize className=\"size-4\" />\n </button>\n {expanded ? (\n <DiagramLightbox onClose={() => setExpanded(false)}>\n <MermaidSvg svg={svg} enlarged />\n </DiagramLightbox>\n ) : null}\n </div>\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\n {...ltrCodeBlockProps}\n className=\"plan-block\"\n data-block-id={blockId}\n >\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 { IconArrowsMaximize } from \"@tabler/icons-react\";\nimport { ltrCodeBlockProps } from \"../code-block-direction.js\";\nimport type { BlockEditProps, BlockReadProps } from \"../types.js\";\nimport type { MermaidData } from \"./mermaid.config.js\";\nimport { DevInput, DevLabel } from \"./dev-doc-ui.js\";\nimport { DiagramLightbox } from \"./diagram.js\";\nimport { useBlockCopy } from \"./block-copy.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\n/**\n * Inject a rendered Mermaid/Excalidraw SVG string. Shared by the inline render\n * and the expand lightbox so the enlarged view shows the exact same SVG; the\n * lightbox passes `enlarged` so the SVG stretches to fill the wider modal\n * (`max-w-5xl`) instead of staying at its intrinsic inline size.\n */\nfunction MermaidSvg({ svg, enlarged }: { svg: string; enlarged?: boolean }) {\n return (\n <div\n className={\n enlarged\n ? \"flex justify-center overflow-auto [&_svg]:h-auto [&_svg]:w-full [&_svg]:max-w-full\"\n : \"mt-2 flex justify-center overflow-auto [&_svg]:h-auto [&_svg]:max-w-full\"\n }\n // Excalidraw and Mermaid output are sanitized before injection.\n dangerouslySetInnerHTML={{ __html: svg }}\n />\n );\n}\n\nfunction MermaidDiagram({\n source,\n idSeed,\n}: {\n source: string;\n idSeed: string;\n}) {\n const isDark = useIsDark();\n const copy = useBlockCopy();\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 const [expanded, setExpanded] = useState(false);\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 {copy.loadingDiagram}\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 [font-size:var(--plan-code-size)] text-plan-code-text\">\n {source}\n </pre>\n <p className=\"text-sm text-plan-muted\">\n {copy.couldNotRenderDiagram}: {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 {copy.addDiagramDefinition}\n </div>\n );\n }\n\n // Hover-revealed top-right expand button + shared lightbox, matching the\n // DiagramBlock affordance exactly (same icon, reveal-on-hover/focus, Escape +\n // backdrop close via the reused `DiagramLightbox`). The enlarged view re-shows\n // the same rendered SVG scaled to fit the wider modal.\n const svg = state.svg;\n return (\n <div className=\"group/mermaid relative\">\n <MermaidSvg svg={svg} />\n <button\n type=\"button\"\n data-plan-interactive\n onClick={() => setExpanded(true)}\n aria-label={copy.expandDiagram}\n title={copy.expandDiagram}\n className=\"an-diagram-expand-trigger absolute right-2 top-2 z-10 flex size-7 items-center justify-center rounded-md border border-border/60 bg-background/90 text-muted-foreground opacity-0 shadow-sm backdrop-blur transition-[color,opacity] hover:text-foreground focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring group-hover/mermaid:opacity-100\"\n >\n <IconArrowsMaximize className=\"size-4\" />\n </button>\n {expanded ? (\n <DiagramLightbox onClose={() => setExpanded(false)}>\n <MermaidSvg svg={svg} enlarged />\n </DiagramLightbox>\n ) : null}\n </div>\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\n {...ltrCodeBlockProps}\n className=\"plan-block\"\n data-block-id={blockId}\n >\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"]}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export declare function useBlockCopy(): {
|
|
2
|
+
added: string;
|
|
3
|
+
modified: string;
|
|
4
|
+
removed: string;
|
|
5
|
+
renamed: string;
|
|
6
|
+
deprecated: string;
|
|
7
|
+
requiresAuthentication: string;
|
|
8
|
+
auth: string;
|
|
9
|
+
parameters: string;
|
|
10
|
+
name: string;
|
|
11
|
+
in: string;
|
|
12
|
+
type: string;
|
|
13
|
+
requiredColumn: string;
|
|
14
|
+
description: string;
|
|
15
|
+
required: string;
|
|
16
|
+
optional: string;
|
|
17
|
+
requestBody: string;
|
|
18
|
+
responses: string;
|
|
19
|
+
expandDiagram: string;
|
|
20
|
+
loadingDiagram: string;
|
|
21
|
+
couldNotRenderDiagram: string;
|
|
22
|
+
addDiagramDefinition: string;
|
|
23
|
+
switchToCleanDiagrams: string;
|
|
24
|
+
switchToHandDrawnDiagrams: string;
|
|
25
|
+
cleanDiagramsSwitch: string;
|
|
26
|
+
handDrawnDiagramsSwitch: string;
|
|
27
|
+
clean: string;
|
|
28
|
+
sketchy: string;
|
|
29
|
+
switchVisualStyle: string;
|
|
30
|
+
lineAnnotation: string;
|
|
31
|
+
hiddenLinesExpand: string;
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=block-copy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"block-copy.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/block-copy.ts"],"names":[],"mappings":"AA2WA,wBAAgB,YAAY;WAlWjB,MAAM;cACH,MAAM;aACP,MAAM;aACN,MAAM;gBACH,MAAM;4BACM,MAAM;UACxB,MAAM;gBACA,MAAM;UACZ,MAAM;QACR,MAAM;UACJ,MAAM;oBACI,MAAM;iBACT,MAAM;cACT,MAAM;cACN,MAAM;iBACH,MAAM;eACR,MAAM;mBACF,MAAM;oBACL,MAAM;2BACC,MAAM;0BACP,MAAM;2BACL,MAAM;+BACF,MAAM;yBACZ,MAAM;6BACF,MAAM;WACxB,MAAM;aACJ,MAAM;uBACI,MAAM;oBACT,MAAM;uBACH,MAAM;EAwU5B"}
|