@agent-native/core 0.41.1 → 0.43.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -56
- package/dist/action.d.ts +13 -1
- package/dist/action.d.ts.map +1 -1
- package/dist/action.js.map +1 -1
- package/dist/agent/production-agent.d.ts +8 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +93 -0
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/cli/app-skill.d.ts +16 -0
- package/dist/cli/app-skill.d.ts.map +1 -1
- package/dist/cli/app-skill.js +33 -3
- package/dist/cli/app-skill.js.map +1 -1
- package/dist/cli/pr-visual-recap-workflow.d.ts +1 -1
- package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -1
- package/dist/cli/pr-visual-recap-workflow.js +1 -1
- package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
- package/dist/cli/recap.d.ts.map +1 -1
- package/dist/cli/recap.js +38 -16
- package/dist/cli/recap.js.map +1 -1
- package/dist/cli/skills.d.ts +30 -3
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +180 -114
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +2 -2
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +172 -5
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/blocks/index.d.ts +11 -0
- package/dist/client/blocks/index.d.ts.map +1 -1
- package/dist/client/blocks/index.js +11 -0
- package/dist/client/blocks/index.js.map +1 -1
- package/dist/client/blocks/library/AnnotatedCodeBlock.d.ts +19 -0
- package/dist/client/blocks/library/AnnotatedCodeBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/AnnotatedCodeBlock.js +6 -58
- 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 +116 -7
- package/dist/client/blocks/library/ApiEndpointBlock.js.map +1 -1
- package/dist/client/blocks/library/DataModelBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/DataModelBlock.js +75 -9
- package/dist/client/blocks/library/DataModelBlock.js.map +1 -1
- package/dist/client/blocks/library/DiffBlock.d.ts +1 -1
- package/dist/client/blocks/library/DiffBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/DiffBlock.js +265 -39
- package/dist/client/blocks/library/DiffBlock.js.map +1 -1
- package/dist/client/blocks/library/FileTreeBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/FileTreeBlock.js +27 -4
- package/dist/client/blocks/library/FileTreeBlock.js.map +1 -1
- package/dist/client/blocks/library/HighlightedCode.d.ts +1 -1
- package/dist/client/blocks/library/HighlightedCode.js +1 -1
- package/dist/client/blocks/library/HighlightedCode.js.map +1 -1
- package/dist/client/blocks/library/JsonExplorerBlock.js +1 -1
- package/dist/client/blocks/library/JsonExplorerBlock.js.map +1 -1
- package/dist/client/blocks/library/MermaidBlock.js +1 -1
- package/dist/client/blocks/library/MermaidBlock.js.map +1 -1
- package/dist/client/blocks/library/annotation-rail.d.ts +115 -0
- package/dist/client/blocks/library/annotation-rail.d.ts.map +1 -0
- package/dist/client/blocks/library/annotation-rail.js +139 -0
- package/dist/client/blocks/library/annotation-rail.js.map +1 -0
- package/dist/client/blocks/library/api-endpoint.config.d.ts +31 -6
- package/dist/client/blocks/library/api-endpoint.config.d.ts.map +1 -1
- package/dist/client/blocks/library/api-endpoint.config.js +30 -6
- package/dist/client/blocks/library/api-endpoint.config.js.map +1 -1
- package/dist/client/blocks/library/callout.config.d.ts +29 -0
- package/dist/client/blocks/library/callout.config.d.ts.map +1 -0
- package/dist/client/blocks/library/callout.config.js +33 -0
- package/dist/client/blocks/library/callout.config.js.map +1 -0
- package/dist/client/blocks/library/callout.d.ts +20 -0
- package/dist/client/blocks/library/callout.d.ts.map +1 -0
- package/dist/client/blocks/library/callout.js +61 -0
- package/dist/client/blocks/library/callout.js.map +1 -0
- package/dist/client/blocks/library/checklist.d.ts.map +1 -1
- package/dist/client/blocks/library/checklist.js +3 -3
- package/dist/client/blocks/library/checklist.js.map +1 -1
- package/dist/client/blocks/library/code.d.ts.map +1 -1
- package/dist/client/blocks/library/code.js +32 -15
- package/dist/client/blocks/library/code.js.map +1 -1
- package/dist/client/blocks/library/columns.d.ts.map +1 -1
- package/dist/client/blocks/library/columns.js +56 -35
- package/dist/client/blocks/library/columns.js.map +1 -1
- package/dist/client/blocks/library/data-model.config.d.ts +17 -0
- package/dist/client/blocks/library/data-model.config.d.ts.map +1 -1
- package/dist/client/blocks/library/data-model.config.js +15 -0
- package/dist/client/blocks/library/data-model.config.js.map +1 -1
- package/dist/client/blocks/library/decision.config.d.ts +37 -0
- package/dist/client/blocks/library/decision.config.d.ts.map +1 -0
- package/dist/client/blocks/library/decision.config.js +32 -0
- package/dist/client/blocks/library/decision.config.js.map +1 -0
- package/dist/client/blocks/library/decision.d.ts +19 -0
- package/dist/client/blocks/library/decision.d.ts.map +1 -0
- package/dist/client/blocks/library/decision.js +119 -0
- package/dist/client/blocks/library/decision.js.map +1 -0
- package/dist/client/blocks/library/diagram.config.d.ts +64 -0
- package/dist/client/blocks/library/diagram.config.d.ts.map +1 -0
- package/dist/client/blocks/library/diagram.config.js +111 -0
- package/dist/client/blocks/library/diagram.config.js.map +1 -0
- package/dist/client/blocks/library/diagram.d.ts +16 -0
- package/dist/client/blocks/library/diagram.d.ts.map +1 -0
- package/dist/client/blocks/library/diagram.js +261 -0
- package/dist/client/blocks/library/diagram.js.map +1 -0
- package/dist/client/blocks/library/diff.config.d.ts +28 -6
- package/dist/client/blocks/library/diff.config.d.ts.map +1 -1
- package/dist/client/blocks/library/diff.config.js +30 -6
- package/dist/client/blocks/library/diff.config.js.map +1 -1
- package/dist/client/blocks/library/question-form.config.d.ts +69 -0
- package/dist/client/blocks/library/question-form.config.d.ts.map +1 -0
- package/dist/client/blocks/library/question-form.config.js +58 -0
- package/dist/client/blocks/library/question-form.config.js.map +1 -0
- package/dist/client/blocks/library/question-form.d.ts +20 -0
- package/dist/client/blocks/library/question-form.d.ts.map +1 -0
- package/dist/client/blocks/library/question-form.js +286 -0
- package/dist/client/blocks/library/question-form.js.map +1 -0
- package/dist/client/blocks/library/sanitize-html.d.ts +5 -0
- package/dist/client/blocks/library/sanitize-html.d.ts.map +1 -0
- package/dist/client/blocks/library/sanitize-html.js +240 -0
- package/dist/client/blocks/library/sanitize-html.js.map +1 -0
- package/dist/client/blocks/library/server-specs.d.ts.map +1 -1
- package/dist/client/blocks/library/server-specs.js +59 -0
- package/dist/client/blocks/library/server-specs.js.map +1 -1
- package/dist/client/blocks/library/specs.d.ts.map +1 -1
- package/dist/client/blocks/library/specs.js +11 -0
- package/dist/client/blocks/library/specs.js.map +1 -1
- package/dist/client/blocks/library/tabs.d.ts.map +1 -1
- package/dist/client/blocks/library/tabs.js +12 -12
- package/dist/client/blocks/library/tabs.js.map +1 -1
- package/dist/client/blocks/library/wireframe-kit.d.ts +260 -0
- package/dist/client/blocks/library/wireframe-kit.d.ts.map +1 -0
- package/dist/client/blocks/library/wireframe-kit.js +920 -0
- package/dist/client/blocks/library/wireframe-kit.js.map +1 -0
- package/dist/client/blocks/library/wireframe.config.d.ts +123 -0
- package/dist/client/blocks/library/wireframe.config.d.ts.map +1 -0
- package/dist/client/blocks/library/wireframe.config.js +294 -0
- package/dist/client/blocks/library/wireframe.config.js.map +1 -0
- package/dist/client/blocks/library/wireframe.d.ts +15 -0
- package/dist/client/blocks/library/wireframe.d.ts.map +1 -0
- package/dist/client/blocks/library/wireframe.js +206 -0
- package/dist/client/blocks/library/wireframe.js.map +1 -0
- package/dist/client/blocks/registry.d.ts +9 -0
- package/dist/client/blocks/registry.d.ts.map +1 -1
- package/dist/client/blocks/registry.js +12 -5
- package/dist/client/blocks/registry.js.map +1 -1
- package/dist/client/blocks/server.d.ts +1 -0
- package/dist/client/blocks/server.d.ts.map +1 -1
- package/dist/client/blocks/server.js +1 -0
- package/dist/client/blocks/server.js.map +1 -1
- package/dist/client/blocks/types.d.ts +10 -2
- package/dist/client/blocks/types.d.ts.map +1 -1
- package/dist/client/blocks/types.js.map +1 -1
- package/dist/client/rich-markdown-editor/DragHandle.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/DragHandle.js +152 -21
- package/dist/client/rich-markdown-editor/DragHandle.js.map +1 -1
- package/dist/client/rich-markdown-editor/RegistryBlockNode.d.ts +25 -1
- package/dist/client/rich-markdown-editor/RegistryBlockNode.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/RegistryBlockNode.js +29 -6
- package/dist/client/rich-markdown-editor/RegistryBlockNode.js.map +1 -1
- package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts +8 -1
- package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/SharedRichEditor.js +5 -1
- package/dist/client/rich-markdown-editor/SharedRichEditor.js.map +1 -1
- package/dist/extensions/actions.d.ts.map +1 -1
- package/dist/extensions/actions.js +159 -12
- package/dist/extensions/actions.js.map +1 -1
- package/dist/extensions/store.d.ts +21 -0
- package/dist/extensions/store.d.ts.map +1 -1
- package/dist/extensions/store.js +33 -1
- package/dist/extensions/store.js.map +1 -1
- package/dist/server/recap-image-route.d.ts.map +1 -1
- package/dist/server/recap-image-route.js +12 -3
- package/dist/server/recap-image-route.js.map +1 -1
- package/dist/styles/agent-native.css +1 -0
- package/dist/styles/blocks.css +1380 -0
- package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +30 -5
- package/docs/content/plan-plugin.md +107 -0
- package/docs/content/pr-visual-recap.md +2 -2
- package/docs/content/skills-guide.md +8 -0
- package/docs/content/template-plan.md +94 -17
- package/package.json +2 -1
- package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +30 -5
- package/docs/content/visual-plans.md +0 -80
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const idSchema = z.string().trim().min(1).max(120);
|
|
3
|
+
const unsafeDiagramHtmlPattern = /(?:<!doctype|<\/?(?:html|head|body|script|style|iframe|object|embed|link|meta|base|form|math|foreignObject|noscript|frame|frameset|applet|portal|marquee)[\s>/]|@(?:import|font-face|keyframes|page|namespace|charset)\b|\b(?:java\s*script|vb\s*script|data\s*:\s*(?:text\/html|image\/svg\+xml))\s*:?\s*|\bsrcdoc\s*=|(?:^|\s)(?:on[a-z][\w:-]*|@[\w:.-]+|x-on:[\w:.-]+|:on[a-z][\w:-]*|x-bind:on[a-z][\w:-]*|:style|x-bind:style)\s*=|expression\s*\(|url\s*\(\s*['"]?\s*(?:java\s*script|vb\s*script|data\s*:\s*(?:text\/html|image\/svg\+xml)))/i;
|
|
4
|
+
const unsafeViewportCssPattern = /(?:^|[;{\s])position\s*:\s*(?:fixed|sticky)\b|(?:^|[;{\s])z-index\s*:\s*[1-9]\d{4,}\b/i;
|
|
5
|
+
function decodeSafetyEntities(value) {
|
|
6
|
+
return value
|
|
7
|
+
.replace(/&#(x[0-9a-f]+|\d+);?/gi, (_, code) => {
|
|
8
|
+
const point = code.toLowerCase().startsWith("x")
|
|
9
|
+
? Number.parseInt(code.slice(1), 16)
|
|
10
|
+
: Number.parseInt(code, 10);
|
|
11
|
+
return Number.isFinite(point) ? String.fromCodePoint(point) : "";
|
|
12
|
+
})
|
|
13
|
+
.replace(/&(colon|tab|newline);/gi, (_, name) => {
|
|
14
|
+
if (name.toLowerCase() === "colon")
|
|
15
|
+
return ":";
|
|
16
|
+
if (name.toLowerCase() === "tab")
|
|
17
|
+
return "\t";
|
|
18
|
+
return "\n";
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
function decodeCssSafetyEscapes(value) {
|
|
22
|
+
return value.replace(/\\([0-9a-fA-F]{1,6}\s?|.)/g, (_match, escaped) => {
|
|
23
|
+
const hex = String(escaped).match(/^[0-9a-fA-F]{1,6}/)?.[0];
|
|
24
|
+
if (hex) {
|
|
25
|
+
const point = Number.parseInt(hex, 16);
|
|
26
|
+
return Number.isFinite(point) ? String.fromCodePoint(point) : "";
|
|
27
|
+
}
|
|
28
|
+
return String(escaped)[0] ?? "";
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function noActiveDiagramText(value) {
|
|
32
|
+
const decoded = decodeCssSafetyEscapes(decodeSafetyEntities(value));
|
|
33
|
+
const compact = decoded.toLowerCase().replace(/[\u0000-\u0020]+/g, "");
|
|
34
|
+
return (!unsafeDiagramHtmlPattern.test(value) &&
|
|
35
|
+
!unsafeDiagramHtmlPattern.test(decoded) &&
|
|
36
|
+
!unsafeViewportCssPattern.test(decoded) &&
|
|
37
|
+
!/(?:javascript|vbscript):|data:(?:text\/html|image\/svg\+xml)|expression\(|url\(['"]?(?:javascript|vbscript|data:(?:text\/html|image\/svg\+xml))/.test(compact));
|
|
38
|
+
}
|
|
39
|
+
const diagramNodeSchema = z.object({
|
|
40
|
+
id: idSchema,
|
|
41
|
+
label: z.string().trim().min(1).max(160),
|
|
42
|
+
detail: z.string().trim().max(500).optional(),
|
|
43
|
+
x: z.number().min(0).max(100).optional(),
|
|
44
|
+
y: z.number().min(0).max(100).optional(),
|
|
45
|
+
});
|
|
46
|
+
const diagramEdgeSchema = z.object({
|
|
47
|
+
from: idSchema,
|
|
48
|
+
to: idSchema,
|
|
49
|
+
label: z.string().trim().max(100).optional(),
|
|
50
|
+
});
|
|
51
|
+
const diagramNoteSchema = z.object({
|
|
52
|
+
id: idSchema,
|
|
53
|
+
text: z.string().trim().min(1).max(500),
|
|
54
|
+
x: z.number().min(0).max(100).optional(),
|
|
55
|
+
y: z.number().min(0).max(100).optional(),
|
|
56
|
+
});
|
|
57
|
+
/**
|
|
58
|
+
* The block can be a flexible HTML/SVG fragment or a legacy positional
|
|
59
|
+
* node/edge/note graph, so it ships a custom `Edit` rather than relying on the
|
|
60
|
+
* schema auto-editor. Editing stays comment/patch-driven.
|
|
61
|
+
*/
|
|
62
|
+
export const diagramSchema = z
|
|
63
|
+
.object({
|
|
64
|
+
html: z
|
|
65
|
+
.string()
|
|
66
|
+
.trim()
|
|
67
|
+
.max(100_000)
|
|
68
|
+
.refine(noActiveDiagramText, {
|
|
69
|
+
message: "Diagram html must be an inert fragment; SVG is allowed, scripts/events are not.",
|
|
70
|
+
})
|
|
71
|
+
.optional(),
|
|
72
|
+
css: z
|
|
73
|
+
.string()
|
|
74
|
+
.max(50_000)
|
|
75
|
+
.refine(noActiveDiagramText, {
|
|
76
|
+
message: "Diagram css must not include document or script tags.",
|
|
77
|
+
})
|
|
78
|
+
.optional(),
|
|
79
|
+
caption: z.string().trim().max(600).optional(),
|
|
80
|
+
nodes: z.array(diagramNodeSchema).max(80).optional(),
|
|
81
|
+
edges: z.array(diagramEdgeSchema).max(120).optional(),
|
|
82
|
+
notes: z.array(diagramNoteSchema).max(40).optional(),
|
|
83
|
+
})
|
|
84
|
+
.superRefine((data, ctx) => {
|
|
85
|
+
if (data.html?.trim() || (data.nodes?.length ?? 0) > 0)
|
|
86
|
+
return;
|
|
87
|
+
ctx.addIssue({
|
|
88
|
+
code: "custom",
|
|
89
|
+
path: ["html"],
|
|
90
|
+
message: "Diagram block requires html or at least one node.",
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
/**
|
|
94
|
+
* MDX config: the entire `data` object is serialized as one JSON `data` prop and
|
|
95
|
+
* the element is self-closing — exactly the legacy `<Diagram id … data={…} />`
|
|
96
|
+
* form. `toAttrs` returns `{ data }`; `fromAttrs` reads the `data` object,
|
|
97
|
+
* mirroring the legacy `dataAttr(node, "data") ?? { nodes: [], edges: [] }`
|
|
98
|
+
* default so plans missing the prop still parse.
|
|
99
|
+
*/
|
|
100
|
+
export const diagramMdx = {
|
|
101
|
+
tag: "Diagram",
|
|
102
|
+
// The whole data object becomes one JSON `data` prop. Cast to the
|
|
103
|
+
// structured-attr member of `MdxAttrValue` — `DiagramData` is a closed
|
|
104
|
+
// interface without an index signature, which the union member requires.
|
|
105
|
+
toAttrs: (data) => ({ data: data }),
|
|
106
|
+
fromAttrs: (attrs) => (attrs.object("data") ?? {
|
|
107
|
+
nodes: [],
|
|
108
|
+
edges: [],
|
|
109
|
+
}),
|
|
110
|
+
};
|
|
111
|
+
//# sourceMappingURL=diagram.config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagram.config.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/diagram.config.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\nimport type { BlockMdxConfig } from \"../types.js\";\n\n/**\n * Pure (React-free) part of the shared `diagram` block: its data schema and MDX\n * round-trip config. Lives in core so BOTH apps' server/shared registries\n * (`plan-block-registry.ts`, `nfm-registry.ts`) and the client spec\n * (`diagram.tsx`) consume one definition. Keeping it React-free means importing\n * it into a server module never pulls React into the Nitro/SSR bundle.\n *\n * The MDX `tag` + attribute shape MUST match the legacy `<Diagram … data={…} />`\n * encoding — the whole `data` object is serialized as one JSON `data` prop — so\n * stored `.mdx` round-trips byte-compatibly (the block originated in the plan\n * template before moving here).\n */\n\nexport interface DiagramNode {\n id: string;\n label: string;\n detail?: string;\n x?: number;\n y?: number;\n}\n\nexport interface DiagramEdge {\n from: string;\n to: string;\n label?: string;\n}\n\nexport interface DiagramNote {\n id: string;\n text: string;\n x?: number;\n y?: number;\n}\n\nexport interface DiagramData {\n /**\n * Preferred authoring path for architecture/code diagrams: a scoped, inert\n * HTML/SVG fragment. Use .diagram-* primitives and --wf-* tokens; the\n * renderer supplies theme-token-backed styling plus sketch/clean style hooks.\n */\n html?: string;\n css?: string;\n caption?: string;\n /**\n * Legacy compatibility path for older/simple node graphs. New plans should use\n * `html`/`css` when layout quality matters.\n */\n nodes?: DiagramNode[];\n edges?: DiagramEdge[];\n notes?: DiagramNote[];\n}\n\nconst idSchema = z.string().trim().min(1).max(120);\nconst unsafeDiagramHtmlPattern =\n /(?:<!doctype|<\\/?(?:html|head|body|script|style|iframe|object|embed|link|meta|base|form|math|foreignObject|noscript|frame|frameset|applet|portal|marquee)[\\s>/]|@(?:import|font-face|keyframes|page|namespace|charset)\\b|\\b(?:java\\s*script|vb\\s*script|data\\s*:\\s*(?:text\\/html|image\\/svg\\+xml))\\s*:?\\s*|\\bsrcdoc\\s*=|(?:^|\\s)(?:on[a-z][\\w:-]*|@[\\w:.-]+|x-on:[\\w:.-]+|:on[a-z][\\w:-]*|x-bind:on[a-z][\\w:-]*|:style|x-bind:style)\\s*=|expression\\s*\\(|url\\s*\\(\\s*['\"]?\\s*(?:java\\s*script|vb\\s*script|data\\s*:\\s*(?:text\\/html|image\\/svg\\+xml)))/i;\nconst unsafeViewportCssPattern =\n /(?:^|[;{\\s])position\\s*:\\s*(?:fixed|sticky)\\b|(?:^|[;{\\s])z-index\\s*:\\s*[1-9]\\d{4,}\\b/i;\n\nfunction decodeSafetyEntities(value: string): string {\n return value\n .replace(/&#(x[0-9a-f]+|\\d+);?/gi, (_, code: string) => {\n const point = code.toLowerCase().startsWith(\"x\")\n ? Number.parseInt(code.slice(1), 16)\n : Number.parseInt(code, 10);\n return Number.isFinite(point) ? String.fromCodePoint(point) : \"\";\n })\n .replace(/&(colon|tab|newline);/gi, (_, name: string) => {\n if (name.toLowerCase() === \"colon\") return \":\";\n if (name.toLowerCase() === \"tab\") return \"\\t\";\n return \"\\n\";\n });\n}\n\nfunction decodeCssSafetyEscapes(value: string): string {\n return value.replace(/\\\\([0-9a-fA-F]{1,6}\\s?|.)/g, (_match, escaped) => {\n const hex = String(escaped).match(/^[0-9a-fA-F]{1,6}/)?.[0];\n if (hex) {\n const point = Number.parseInt(hex, 16);\n return Number.isFinite(point) ? String.fromCodePoint(point) : \"\";\n }\n return String(escaped)[0] ?? \"\";\n });\n}\n\nfunction noActiveDiagramText(value: string) {\n const decoded = decodeCssSafetyEscapes(decodeSafetyEntities(value));\n const compact = decoded.toLowerCase().replace(/[\\u0000-\\u0020]+/g, \"\");\n return (\n !unsafeDiagramHtmlPattern.test(value) &&\n !unsafeDiagramHtmlPattern.test(decoded) &&\n !unsafeViewportCssPattern.test(decoded) &&\n !/(?:javascript|vbscript):|data:(?:text\\/html|image\\/svg\\+xml)|expression\\(|url\\(['\"]?(?:javascript|vbscript|data:(?:text\\/html|image\\/svg\\+xml))/.test(\n compact,\n )\n );\n}\n\nconst diagramNodeSchema = z.object({\n id: idSchema,\n label: z.string().trim().min(1).max(160),\n detail: z.string().trim().max(500).optional(),\n x: z.number().min(0).max(100).optional(),\n y: z.number().min(0).max(100).optional(),\n}) as z.ZodType<DiagramNode>;\n\nconst diagramEdgeSchema = z.object({\n from: idSchema,\n to: idSchema,\n label: z.string().trim().max(100).optional(),\n}) as z.ZodType<DiagramEdge>;\n\nconst diagramNoteSchema = z.object({\n id: idSchema,\n text: z.string().trim().min(1).max(500),\n x: z.number().min(0).max(100).optional(),\n y: z.number().min(0).max(100).optional(),\n}) as z.ZodType<DiagramNote>;\n\n/**\n * The block can be a flexible HTML/SVG fragment or a legacy positional\n * node/edge/note graph, so it ships a custom `Edit` rather than relying on the\n * schema auto-editor. Editing stays comment/patch-driven.\n */\nexport const diagramSchema = z\n .object({\n html: z\n .string()\n .trim()\n .max(100_000)\n .refine(noActiveDiagramText, {\n message:\n \"Diagram html must be an inert fragment; SVG is allowed, scripts/events are not.\",\n })\n .optional(),\n css: z\n .string()\n .max(50_000)\n .refine(noActiveDiagramText, {\n message: \"Diagram css must not include document or script tags.\",\n })\n .optional(),\n caption: z.string().trim().max(600).optional(),\n nodes: z.array(diagramNodeSchema).max(80).optional(),\n edges: z.array(diagramEdgeSchema).max(120).optional(),\n notes: z.array(diagramNoteSchema).max(40).optional(),\n })\n .superRefine((data, ctx) => {\n if (data.html?.trim() || (data.nodes?.length ?? 0) > 0) return;\n ctx.addIssue({\n code: \"custom\",\n path: [\"html\"],\n message: \"Diagram block requires html or at least one node.\",\n });\n }) as unknown as z.ZodType<DiagramData>;\n\n/**\n * MDX config: the entire `data` object is serialized as one JSON `data` prop and\n * the element is self-closing — exactly the legacy `<Diagram id … data={…} />`\n * form. `toAttrs` returns `{ data }`; `fromAttrs` reads the `data` object,\n * mirroring the legacy `dataAttr(node, \"data\") ?? { nodes: [], edges: [] }`\n * default so plans missing the prop still parse.\n */\nexport const diagramMdx: BlockMdxConfig<DiagramData> = {\n tag: \"Diagram\",\n // The whole data object becomes one JSON `data` prop. Cast to the\n // structured-attr member of `MdxAttrValue` — `DiagramData` is a closed\n // interface without an index signature, which the union member requires.\n toAttrs: (data) => ({ data: data as unknown as Record<string, unknown> }),\n fromAttrs: (attrs) =>\n (attrs.object<DiagramData>(\"data\") ?? {\n nodes: [],\n edges: [],\n }) as DiagramData,\n};\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { BlockReadProps, BlockEditProps } from "../types.js";
|
|
2
|
+
import { type DiagramData } from "./diagram.config.js";
|
|
3
|
+
/** Read-only renderer: the diagram body wrapped in the standard titled block. */
|
|
4
|
+
export declare function DiagramRead({ data, blockId, title, summary, ctx, }: BlockReadProps<DiagramData>): import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
/**
|
|
6
|
+
* Edit form (panel surface). The block can be an HTML/SVG fragment or a legacy
|
|
7
|
+
* node/edge/note graph, so this exposes html/css/caption plus a collapsible
|
|
8
|
+
* legacy node-graph JSON editor, each with an AI-edit affordance via
|
|
9
|
+
* `ctx.renderAiFieldAction` (through `AiEditableFieldLabel`). `editSurface:
|
|
10
|
+
* "panel"` means the registry renders the `Read` view with a corner edit button
|
|
11
|
+
* that opens this form in the app-provided popover.
|
|
12
|
+
*/
|
|
13
|
+
export declare function DiagramEdit({ data, onChange, editable, blockId, title, summary, ctx, }: BlockEditProps<DiagramData>): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
/** Full client spec for the shared `diagram` block (schema + MDX + Read/Edit). */
|
|
15
|
+
export declare const diagramBlock: import("../types.js").BlockSpec<DiagramData>;
|
|
16
|
+
//# sourceMappingURL=diagram.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagram.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/diagram.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EAEf,MAAM,aAAa,CAAC;AAQrB,OAAO,EAGL,KAAK,WAAW,EAGjB,MAAM,qBAAqB,CAAC;AAkX7B,iFAAiF;AACjF,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,OAAO,EACP,KAAK,EACL,OAAO,EACP,GAAG,GACJ,EAAE,cAAc,CAAC,WAAW,CAAC,2CAQ7B;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,KAAK,EACL,OAAO,EACP,GAAG,GACJ,EAAE,cAAc,CAAC,WAAW,CAAC,2CAkL7B;AAED,kFAAkF;AAClF,eAAO,MAAM,YAAY,8CAgBvB,CAAC"}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useId, useMemo, useRef, useState } from "react";
|
|
3
|
+
import { cn } from "../../utils.js";
|
|
4
|
+
import { defineBlock } from "../types.js";
|
|
5
|
+
import { AiEditableFieldLabel } from "../AiEditableField.js";
|
|
6
|
+
import { RoughOverlay, useIsDark, useWireframeStyle } from "./wireframe-kit.js";
|
|
7
|
+
import { sanitizeDiagramHtml, sanitizeWireframeCss, scopeDesignCss, } from "./sanitize-html.js";
|
|
8
|
+
import { diagramMdx, diagramSchema, } from "./diagram.config.js";
|
|
9
|
+
/**
|
|
10
|
+
* Read + Edit renderers for the shared `diagram` block — a flexible inline
|
|
11
|
+
* architecture/code diagram. The preferred authoring path is a scoped, inert
|
|
12
|
+
* HTML/SVG fragment that leans on `.diagram-*` primitives and `--wf-*` tokens;
|
|
13
|
+
* a legacy positional / sequence node-graph path is kept for older/simple plans.
|
|
14
|
+
* Lives in core so any app can register it (it originated in the plan template).
|
|
15
|
+
*
|
|
16
|
+
* DECOUPLING from the plan original (mirrors the sibling `wireframe.tsx` port):
|
|
17
|
+
* - Theme: `useIsDark()` reads `document.documentElement.classList` instead of
|
|
18
|
+
* `next-themes`; `useWireframeStyle()` reads the viewer's sketchy/clean
|
|
19
|
+
* preference from the shared `plan-wireframe-style` localStorage key — both
|
|
20
|
+
* from `./wireframe-kit.js`, so core stays plan-free and shadcn-free.
|
|
21
|
+
* - HTML sanitize: the HTML/SVG fragment + CSS run through the app-injected
|
|
22
|
+
* `ctx.sanitizeHtml` at the render point (defense-in-depth against stored
|
|
23
|
+
* XSS). Without a sanitizer wired, the HTML path emits nothing — core never
|
|
24
|
+
* injects unsanitized author HTML. The React-free `diagramSchema` already
|
|
25
|
+
* rejects active markup before storage.
|
|
26
|
+
* - The rough.js sketch overlay reuses the kit's shared `RoughOverlay`, scoped
|
|
27
|
+
* with the diagram selector and `drawFrame={false}` (the same call the plan
|
|
28
|
+
* `HtmlDiagram` made). The `.plan-diagram-frame` / `.diagram-*` / `data-rough`
|
|
29
|
+
* class contract is preserved exactly so the theme-token CSS in core's
|
|
30
|
+
* `blocks.css` styles it in any app.
|
|
31
|
+
*
|
|
32
|
+
* The section carries the app-neutral `an-block` class plus the legacy
|
|
33
|
+
* `plan-block` class so plan renders byte-identically while any other app gets
|
|
34
|
+
* the theme-token treatment.
|
|
35
|
+
*/
|
|
36
|
+
/* -------------------------------------------------------------------------- */
|
|
37
|
+
/* HTML/SVG diagram path */
|
|
38
|
+
/* -------------------------------------------------------------------------- */
|
|
39
|
+
/** The rough-overlay selector for diagram bordered boxes (mirrors the plan). */
|
|
40
|
+
const DIAGRAM_ROUGH_SELECTOR = "[data-rough],.diagram-panel,.diagram-node,.diagram-box,.diagram-pill,.diagram-card,[class*='card'],[class*='box'],[class*='panel'],[class*='pill'],[class*='chip'],[class*='badge'],hr";
|
|
41
|
+
function HtmlDiagram({ data, ctx, compact, }) {
|
|
42
|
+
const ref = useRef(null);
|
|
43
|
+
const isDark = useIsDark();
|
|
44
|
+
const style = useWireframeStyle();
|
|
45
|
+
const scopeId = useId().replace(/[^a-zA-Z0-9_-]/g, "");
|
|
46
|
+
// Sanitize author HTML/CSS at the render point (defense-in-depth against
|
|
47
|
+
// stored XSS). Self-contained in core via the shared block sanitizer (DOM-based
|
|
48
|
+
// in the browser, regex fallback on the server) so diagrams render in any app
|
|
49
|
+
// without the host wiring a sanitizer hook.
|
|
50
|
+
const safeHtml = useMemo(() => sanitizeDiagramHtml(data.html), [data.html]);
|
|
51
|
+
const scopedCss = useMemo(() => {
|
|
52
|
+
const safeCss = sanitizeWireframeCss(data.css);
|
|
53
|
+
// Scope every author selector under this diagram instance so global
|
|
54
|
+
// selectors (body, *, .app-shell, :root) can't escape and restyle the page.
|
|
55
|
+
return safeCss
|
|
56
|
+
? scopeDesignCss(safeCss, `[data-plan-diagram-scope="${scopeId}"]`)
|
|
57
|
+
: "";
|
|
58
|
+
}, [data.css, scopeId]);
|
|
59
|
+
return (_jsxs("div", { ref: ref, className: cn("plan-diagram-shell", compact && "plan-diagram-compact"), children: [_jsxs("div", { className: "plan-diagram-frame", "data-theme": isDark ? "dark" : "light", "data-style": style, "data-plan-diagram-scope": scopeId, children: [scopedCss && _jsx("style", { children: scopedCss }), _jsx("div", { className: "plan-diagram-frame-content", dangerouslySetInnerHTML: { __html: safeHtml } })] }), _jsx(RoughOverlay, { scopeRef: ref, enabled: style === "sketchy", drawFrame: false, selector: DIAGRAM_ROUGH_SELECTOR }), data.caption && !compact && (_jsx("p", { className: "mt-3 text-sm leading-6 text-muted-foreground", children: data.caption }))] }));
|
|
60
|
+
}
|
|
61
|
+
/* -------------------------------------------------------------------------- */
|
|
62
|
+
/* Legacy node-graph paths */
|
|
63
|
+
/* -------------------------------------------------------------------------- */
|
|
64
|
+
function clampDiagramPercent(value) {
|
|
65
|
+
if (!Number.isFinite(value))
|
|
66
|
+
return 50;
|
|
67
|
+
return Math.max(4, Math.min(96, value));
|
|
68
|
+
}
|
|
69
|
+
function hasPositionedDiagramNodes(data) {
|
|
70
|
+
return (data.nodes ?? []).some((node) => typeof node.x === "number" && typeof node.y === "number");
|
|
71
|
+
}
|
|
72
|
+
function orderDiagramNodes(nodes, edges) {
|
|
73
|
+
if (nodes.length === 0)
|
|
74
|
+
return [];
|
|
75
|
+
const byId = new Map(nodes.map((node) => [node.id, node]));
|
|
76
|
+
const indegree = new Map(nodes.map((node) => [node.id, 0]));
|
|
77
|
+
for (const edge of edges) {
|
|
78
|
+
if (byId.has(edge.from) && byId.has(edge.to)) {
|
|
79
|
+
indegree.set(edge.to, (indegree.get(edge.to) ?? 0) + 1);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const start = nodes.find((node) => (indegree.get(node.id) ?? 0) === 0);
|
|
83
|
+
if (!start)
|
|
84
|
+
return nodes;
|
|
85
|
+
const ordered = [];
|
|
86
|
+
const seen = new Set();
|
|
87
|
+
let current = start;
|
|
88
|
+
while (current && !seen.has(current.id)) {
|
|
89
|
+
const node = current;
|
|
90
|
+
ordered.push(node);
|
|
91
|
+
seen.add(node.id);
|
|
92
|
+
const next = edges.find((edge) => edge.from === node.id);
|
|
93
|
+
current = next ? byId.get(next.to) : undefined;
|
|
94
|
+
}
|
|
95
|
+
for (const node of nodes)
|
|
96
|
+
if (!seen.has(node.id))
|
|
97
|
+
ordered.push(node);
|
|
98
|
+
return ordered;
|
|
99
|
+
}
|
|
100
|
+
function PositionedDiagram({ data, compact, markerId, }) {
|
|
101
|
+
const nodes = (data.nodes ?? []).map((node) => ({
|
|
102
|
+
...node,
|
|
103
|
+
x: clampDiagramPercent(node.x ?? 50),
|
|
104
|
+
y: clampDiagramPercent(node.y ?? 50),
|
|
105
|
+
}));
|
|
106
|
+
const edges = data.edges ?? [];
|
|
107
|
+
const nodeById = new Map(nodes.map((node) => [node.id, node]));
|
|
108
|
+
const arrowId = `${markerId}-diagram-arrow`;
|
|
109
|
+
const nodeWidth = compact ? 150 : 190;
|
|
110
|
+
const canvasHeight = compact ? 280 : 430;
|
|
111
|
+
return (_jsxs("div", { className: "plan-sketch rounded-[16px] border border-border bg-muted p-5", children: [_jsxs("div", { className: "relative overflow-hidden rounded-xl border border-border bg-background", style: { minHeight: canvasHeight }, children: [_jsxs("svg", { className: "pointer-events-none absolute inset-0 z-0 h-full w-full", viewBox: "0 0 100 100", preserveAspectRatio: "none", "aria-hidden": "true", children: [_jsx("defs", { children: _jsx("marker", { id: arrowId, viewBox: "0 0 10 10", refX: "8", refY: "5", markerWidth: "5", markerHeight: "5", orient: "auto-start-reverse", children: _jsx("path", { d: "M 0 0 L 10 5 L 0 10 z", className: "fill-muted-foreground" }) }) }), edges.map((edge, index) => {
|
|
112
|
+
const from = nodeById.get(edge.from);
|
|
113
|
+
const to = nodeById.get(edge.to);
|
|
114
|
+
if (!from || !to)
|
|
115
|
+
return null;
|
|
116
|
+
return (_jsx("line", { x1: from.x, y1: from.y, x2: to.x, y2: to.y, markerEnd: `url(#${arrowId})`, vectorEffect: "non-scaling-stroke", className: "stroke-border", strokeWidth: 2, strokeDasharray: edge.label ? "0" : "6 5" }, `${edge.from}-${edge.to}-${index}`));
|
|
117
|
+
})] }), !compact &&
|
|
118
|
+
edges.map((edge, index) => {
|
|
119
|
+
const from = nodeById.get(edge.from);
|
|
120
|
+
const to = nodeById.get(edge.to);
|
|
121
|
+
if (!edge.label || !from || !to)
|
|
122
|
+
return null;
|
|
123
|
+
return (_jsx("span", { className: "absolute z-10 max-w-[130px] -translate-x-1/2 -translate-y-1/2 rounded-full border border-border bg-background px-2 py-0.5 text-center text-[11px] font-semibold text-muted-foreground shadow-sm", style: {
|
|
124
|
+
left: `${(from.x + to.x) / 2}%`,
|
|
125
|
+
top: `${(from.y + to.y) / 2}%`,
|
|
126
|
+
}, children: edge.label }, `${edge.from}-${edge.to}-${index}-label`));
|
|
127
|
+
}), nodes.map((node, index) => (_jsxs("article", { className: "absolute z-20 -translate-x-1/2 -translate-y-1/2 rounded-xl border-2 border-border bg-background p-3 text-foreground shadow-sm", style: {
|
|
128
|
+
left: `${node.x}%`,
|
|
129
|
+
top: `${node.y}%`,
|
|
130
|
+
width: nodeWidth,
|
|
131
|
+
}, children: [_jsx("p", { className: "text-[11px] font-semibold uppercase tracking-[0.12em] text-muted-foreground", children: index + 1 }), _jsx("h3", { className: "mt-2 text-base font-semibold leading-tight", children: node.label }), node.detail && !compact && (_jsx("p", { className: "mt-2 text-xs leading-5 text-muted-foreground", children: node.detail }))] }, node.id)))] }), data.notes && data.notes.length > 0 && !compact && (_jsx("div", { className: "mt-4 grid gap-2 border-t border-border pt-4 text-sm text-muted-foreground md:grid-cols-2", children: data.notes.map((note) => (_jsx("p", { children: note.text }, note.id))) }))] }));
|
|
132
|
+
}
|
|
133
|
+
function SequenceDiagram({ data, compact, }) {
|
|
134
|
+
const edges = data.edges ?? [];
|
|
135
|
+
const nodes = orderDiagramNodes(data.nodes ?? [], edges);
|
|
136
|
+
if (nodes.length === 0) {
|
|
137
|
+
return (_jsx("div", { className: "rounded-[12px] border border-border bg-muted p-4 text-sm text-muted-foreground", children: "Diagram content is empty." }));
|
|
138
|
+
}
|
|
139
|
+
return (_jsxs("div", { className: "plan-sketch rounded-[16px] border border-border bg-muted p-5", children: [_jsx("div", { className: cn("flex gap-3 overflow-x-auto pb-2", compact ? "items-center" : "items-stretch"), children: nodes.map((node, index) => {
|
|
140
|
+
const next = nodes[index + 1];
|
|
141
|
+
const edge = next
|
|
142
|
+
? edges.find((candidate) => candidate.from === node.id && candidate.to === next.id)
|
|
143
|
+
: undefined;
|
|
144
|
+
return (_jsxs("div", { className: "flex min-w-max items-center gap-3", children: [_jsxs("article", { className: cn("w-[180px] rounded-xl border-2 border-border bg-background p-3 text-foreground", compact && "w-[150px]"), children: [_jsx("p", { className: "text-[11px] font-semibold uppercase tracking-[0.12em] text-muted-foreground", children: index + 1 }), _jsx("h3", { className: "mt-2 text-base font-semibold leading-tight", children: node.label }), node.detail && !compact && (_jsx("p", { className: "mt-2 text-xs leading-5 text-muted-foreground", children: node.detail }))] }), next && (_jsxs("div", { className: "grid min-w-[72px] justify-items-center gap-1 text-muted-foreground", children: [edge?.label && (_jsx("span", { className: "max-w-[96px] truncate rounded-full border border-border px-2 py-0.5 text-[11px] font-semibold", children: edge.label })), _jsx("span", { className: "h-0.5 w-full rounded-full border-t-2 border-dashed border-border" })] }))] }, node.id));
|
|
145
|
+
}) }), data.notes && data.notes.length > 0 && !compact && (_jsx("div", { className: "mt-4 grid gap-2 border-t border-border pt-4 text-sm text-muted-foreground md:grid-cols-2", children: data.notes.map((note) => (_jsx("p", { children: note.text }, note.id))) }))] }));
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* The diagram body. Routes to the preferred HTML/SVG path (when `data.html` is
|
|
149
|
+
* set) and otherwise to a legacy node-graph path (positioned canvas when nodes
|
|
150
|
+
* carry x/y, else an ordered sequence).
|
|
151
|
+
*/
|
|
152
|
+
function DiagramBody({ data, ctx, compact, }) {
|
|
153
|
+
const markerId = useId().replace(/:/g, "");
|
|
154
|
+
if (data.html?.trim()) {
|
|
155
|
+
return _jsx(HtmlDiagram, { data: data, ctx: ctx, compact: compact });
|
|
156
|
+
}
|
|
157
|
+
if (hasPositionedDiagramNodes(data)) {
|
|
158
|
+
return (_jsx(PositionedDiagram, { data: data, compact: compact, markerId: markerId }));
|
|
159
|
+
}
|
|
160
|
+
return _jsx(SequenceDiagram, { data: data, compact: compact });
|
|
161
|
+
}
|
|
162
|
+
/* -------------------------------------------------------------------------- */
|
|
163
|
+
/* Read + Edit */
|
|
164
|
+
/* -------------------------------------------------------------------------- */
|
|
165
|
+
/** Read-only renderer: the diagram body wrapped in the standard titled block. */
|
|
166
|
+
export function DiagramRead({ data, blockId, title, summary, ctx, }) {
|
|
167
|
+
return (_jsxs("section", { className: "an-block plan-block", "data-block-id": blockId, children: [title && _jsx("div", { className: "an-block-label plan-block-label", children: title }), _jsx(DiagramBody, { data: data, ctx: ctx }), summary && _jsx("p", { className: "mt-5 text-muted-foreground", children: summary })] }));
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Edit form (panel surface). The block can be an HTML/SVG fragment or a legacy
|
|
171
|
+
* node/edge/note graph, so this exposes html/css/caption plus a collapsible
|
|
172
|
+
* legacy node-graph JSON editor, each with an AI-edit affordance via
|
|
173
|
+
* `ctx.renderAiFieldAction` (through `AiEditableFieldLabel`). `editSurface:
|
|
174
|
+
* "panel"` means the registry renders the `Read` view with a corner edit button
|
|
175
|
+
* that opens this form in the app-provided popover.
|
|
176
|
+
*/
|
|
177
|
+
export function DiagramEdit({ data, onChange, editable, blockId, title, summary, ctx, }) {
|
|
178
|
+
const htmlId = useId();
|
|
179
|
+
const cssId = useId();
|
|
180
|
+
const captionId = useId();
|
|
181
|
+
const legacyId = useId();
|
|
182
|
+
const [html, setHtml] = useState(data.html ?? "");
|
|
183
|
+
const [css, setCss] = useState(data.css ?? "");
|
|
184
|
+
const [caption, setCaption] = useState(data.caption ?? "");
|
|
185
|
+
const [legacyJson, setLegacyJson] = useState(() => JSON.stringify({
|
|
186
|
+
nodes: data.nodes ?? [],
|
|
187
|
+
edges: data.edges ?? [],
|
|
188
|
+
notes: data.notes ?? [],
|
|
189
|
+
}, null, 2));
|
|
190
|
+
useEffect(() => {
|
|
191
|
+
setHtml(data.html ?? "");
|
|
192
|
+
setCss(data.css ?? "");
|
|
193
|
+
setCaption(data.caption ?? "");
|
|
194
|
+
setLegacyJson(JSON.stringify({
|
|
195
|
+
nodes: data.nodes ?? [],
|
|
196
|
+
edges: data.edges ?? [],
|
|
197
|
+
notes: data.notes ?? [],
|
|
198
|
+
}, null, 2));
|
|
199
|
+
}, [data]);
|
|
200
|
+
const saveHtmlDiagram = () => {
|
|
201
|
+
onChange({
|
|
202
|
+
html: html.trim() || undefined,
|
|
203
|
+
css: css.trim() || undefined,
|
|
204
|
+
caption: caption.trim() || undefined,
|
|
205
|
+
nodes: data.nodes,
|
|
206
|
+
edges: data.edges,
|
|
207
|
+
notes: data.notes,
|
|
208
|
+
});
|
|
209
|
+
};
|
|
210
|
+
const saveLegacyDiagram = () => {
|
|
211
|
+
const parsed = JSON.parse(legacyJson);
|
|
212
|
+
onChange({
|
|
213
|
+
...data,
|
|
214
|
+
nodes: parsed.nodes ?? [],
|
|
215
|
+
edges: parsed.edges ?? [],
|
|
216
|
+
notes: parsed.notes ?? [],
|
|
217
|
+
});
|
|
218
|
+
};
|
|
219
|
+
const fieldAction = (field, value) => ({
|
|
220
|
+
blockId,
|
|
221
|
+
blockType: "diagram",
|
|
222
|
+
blockTitle: title,
|
|
223
|
+
blockSummary: summary,
|
|
224
|
+
fieldValue: value,
|
|
225
|
+
draftScope: `block:diagram:${blockId}:${field.toLowerCase().replace(/[^a-z0-9]+/g, "-")}`,
|
|
226
|
+
disabled: !editable,
|
|
227
|
+
instructions: "Update the plan with update-visual-plan using a targeted update-block content patch for this diagram block id. Preserve unrelated diagram fields unless the requested edit requires changing them. Keep diagram HTML/CSS on renderer-owned .diagram-* primitives and --wf-* tokens; do not introduce custom font-family or hard-coded hex/rgb/hsl colors.",
|
|
228
|
+
companionFields: [
|
|
229
|
+
{
|
|
230
|
+
label: "HTML / SVG fragment",
|
|
231
|
+
value: html.trim() || "(empty)",
|
|
232
|
+
language: "html",
|
|
233
|
+
},
|
|
234
|
+
{ label: "CSS", value: css.trim() || "(empty)", language: "css" },
|
|
235
|
+
{
|
|
236
|
+
label: "caption",
|
|
237
|
+
value: caption.trim() || "(empty)",
|
|
238
|
+
language: "text",
|
|
239
|
+
},
|
|
240
|
+
],
|
|
241
|
+
});
|
|
242
|
+
return (_jsxs("div", { className: "grid gap-4", "data-plan-interactive": true, children: [_jsx("button", { type: "button", className: "inline-flex h-8 w-fit items-center justify-center rounded-md bg-primary px-3 text-xs font-medium text-primary-foreground disabled:opacity-50", disabled: !editable, onClick: saveHtmlDiagram, children: "Save diagram" }), _jsxs("div", { className: "group/field grid gap-1.5", children: [_jsx(AiEditableFieldLabel, { htmlFor: htmlId, label: "HTML / SVG fragment", ctx: ctx, action: fieldAction("HTML / SVG fragment", html) }), _jsx("textarea", { id: htmlId, className: "min-h-48 w-full rounded-md border border-input bg-background px-3 py-2 font-mono text-xs leading-5 text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", value: html, disabled: !editable, onChange: (event) => setHtml(event.target.value), placeholder: "<div class='diagram'>...</div>" })] }), _jsxs("div", { className: "group/field grid gap-1.5", children: [_jsx(AiEditableFieldLabel, { htmlFor: cssId, label: "CSS", ctx: ctx, action: fieldAction("CSS", css) }), _jsx("textarea", { id: cssId, className: "min-h-32 w-full rounded-md border border-input bg-background px-3 py-2 font-mono text-xs leading-5 text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", value: css, disabled: !editable, onChange: (event) => setCss(event.target.value), placeholder: ".diagram { display: grid; }" })] }), _jsxs("div", { className: "group/field grid gap-1.5", children: [_jsx(AiEditableFieldLabel, { htmlFor: captionId, label: "Caption", ctx: ctx, action: fieldAction("caption", caption) }), _jsx("input", { id: captionId, className: "h-9 w-full rounded-md border border-input bg-background px-3 text-sm text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", value: caption, disabled: !editable, onChange: (event) => setCaption(event.target.value) })] }), !data.html && (_jsxs("details", { className: "rounded-md border border-border p-3", children: [_jsx("summary", { className: "cursor-pointer text-xs font-semibold text-muted-foreground", children: "Legacy node graph data" }), _jsxs("div", { className: "group/field mt-3 grid gap-1.5", children: [_jsx(AiEditableFieldLabel, { htmlFor: legacyId, label: "JSON", ctx: ctx, action: fieldAction("legacy node graph JSON", legacyJson) }), _jsx("textarea", { id: legacyId, className: "min-h-44 w-full rounded-md border border-input bg-background px-3 py-2 font-mono text-xs leading-5 text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", value: legacyJson, disabled: !editable, onChange: (event) => setLegacyJson(event.target.value) })] }), _jsx("button", { type: "button", className: "mt-3 inline-flex h-8 items-center justify-center rounded-md border border-input px-3 text-xs font-medium text-foreground disabled:opacity-50", disabled: !editable, onClick: saveLegacyDiagram, children: "Save graph data" })] }))] }));
|
|
243
|
+
}
|
|
244
|
+
/** Full client spec for the shared `diagram` block (schema + MDX + Read/Edit). */
|
|
245
|
+
export const diagramBlock = defineBlock({
|
|
246
|
+
type: "diagram",
|
|
247
|
+
schema: diagramSchema,
|
|
248
|
+
mdx: diagramMdx,
|
|
249
|
+
Read: DiagramRead,
|
|
250
|
+
Edit: DiagramEdit,
|
|
251
|
+
placement: ["block"],
|
|
252
|
+
// Config-driven: the rendered diagram differs from its raw html/css source, so
|
|
253
|
+
// edit from a corner button + panel rather than inline.
|
|
254
|
+
editSurface: "panel",
|
|
255
|
+
label: "Diagram",
|
|
256
|
+
description: "A flexible inline architecture/code diagram. Prefer html/css with SVG or semantic HTML for polished two-dimensional layouts; use .diagram-* primitives and --wf-* tokens for theme/sketch compatibility. Legacy nodes/edges are only for simple previews.",
|
|
257
|
+
// Seed the legacy fallback shape so a fresh block validates while agents can
|
|
258
|
+
// replace it with html/css when layout quality matters.
|
|
259
|
+
empty: () => ({ nodes: [{ id: "n1", label: "Module" }], edges: [] }),
|
|
260
|
+
});
|
|
261
|
+
//# sourceMappingURL=diagram.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagram.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/diagram.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport { cn } from \"../../utils.js\";\nimport { defineBlock } from \"../types.js\";\nimport type {\n BlockReadProps,\n BlockEditProps,\n BlockRenderContext,\n} from \"../types.js\";\nimport { AiEditableFieldLabel } from \"../AiEditableField.js\";\nimport { RoughOverlay, useIsDark, useWireframeStyle } from \"./wireframe-kit.js\";\nimport {\n sanitizeDiagramHtml,\n sanitizeWireframeCss,\n scopeDesignCss,\n} from \"./sanitize-html.js\";\nimport {\n diagramMdx,\n diagramSchema,\n type DiagramData,\n type DiagramEdge,\n type DiagramNode,\n} from \"./diagram.config.js\";\n\n/**\n * Read + Edit renderers for the shared `diagram` block — a flexible inline\n * architecture/code diagram. The preferred authoring path is a scoped, inert\n * HTML/SVG fragment that leans on `.diagram-*` primitives and `--wf-*` tokens;\n * a legacy positional / sequence node-graph path is kept for older/simple plans.\n * Lives in core so any app can register it (it originated in the plan template).\n *\n * DECOUPLING from the plan original (mirrors the sibling `wireframe.tsx` port):\n * - Theme: `useIsDark()` reads `document.documentElement.classList` instead of\n * `next-themes`; `useWireframeStyle()` reads the viewer's sketchy/clean\n * preference from the shared `plan-wireframe-style` localStorage key — both\n * from `./wireframe-kit.js`, so core stays plan-free and shadcn-free.\n * - HTML sanitize: the HTML/SVG fragment + CSS run through the app-injected\n * `ctx.sanitizeHtml` at the render point (defense-in-depth against stored\n * XSS). Without a sanitizer wired, the HTML path emits nothing — core never\n * injects unsanitized author HTML. The React-free `diagramSchema` already\n * rejects active markup before storage.\n * - The rough.js sketch overlay reuses the kit's shared `RoughOverlay`, scoped\n * with the diagram selector and `drawFrame={false}` (the same call the plan\n * `HtmlDiagram` made). The `.plan-diagram-frame` / `.diagram-*` / `data-rough`\n * class contract is preserved exactly so the theme-token CSS in core's\n * `blocks.css` styles it in any app.\n *\n * The section carries the app-neutral `an-block` class plus the legacy\n * `plan-block` class so plan renders byte-identically while any other app gets\n * the theme-token treatment.\n */\n\n/* -------------------------------------------------------------------------- */\n/* HTML/SVG diagram path */\n/* -------------------------------------------------------------------------- */\n\n/** The rough-overlay selector for diagram bordered boxes (mirrors the plan). */\nconst DIAGRAM_ROUGH_SELECTOR =\n \"[data-rough],.diagram-panel,.diagram-node,.diagram-box,.diagram-pill,.diagram-card,[class*='card'],[class*='box'],[class*='panel'],[class*='pill'],[class*='chip'],[class*='badge'],hr\";\n\nfunction HtmlDiagram({\n data,\n ctx,\n compact,\n}: {\n data: DiagramData;\n ctx: BlockRenderContext;\n compact?: boolean;\n}) {\n const ref = useRef<HTMLDivElement>(null);\n const isDark = useIsDark();\n const style = useWireframeStyle();\n const scopeId = useId().replace(/[^a-zA-Z0-9_-]/g, \"\");\n // Sanitize author HTML/CSS at the render point (defense-in-depth against\n // stored XSS). Self-contained in core via the shared block sanitizer (DOM-based\n // in the browser, regex fallback on the server) so diagrams render in any app\n // without the host wiring a sanitizer hook.\n const safeHtml = useMemo(() => sanitizeDiagramHtml(data.html), [data.html]);\n const scopedCss = useMemo(() => {\n const safeCss = sanitizeWireframeCss(data.css);\n // Scope every author selector under this diagram instance so global\n // selectors (body, *, .app-shell, :root) can't escape and restyle the page.\n return safeCss\n ? scopeDesignCss(safeCss, `[data-plan-diagram-scope=\"${scopeId}\"]`)\n : \"\";\n }, [data.css, scopeId]);\n\n return (\n <div\n ref={ref}\n className={cn(\"plan-diagram-shell\", compact && \"plan-diagram-compact\")}\n >\n <div\n className=\"plan-diagram-frame\"\n data-theme={isDark ? \"dark\" : \"light\"}\n data-style={style}\n data-plan-diagram-scope={scopeId}\n >\n {scopedCss && <style>{scopedCss}</style>}\n <div\n className=\"plan-diagram-frame-content\"\n dangerouslySetInnerHTML={{ __html: safeHtml }}\n />\n </div>\n <RoughOverlay\n scopeRef={ref}\n enabled={style === \"sketchy\"}\n drawFrame={false}\n selector={DIAGRAM_ROUGH_SELECTOR}\n />\n {data.caption && !compact && (\n <p className=\"mt-3 text-sm leading-6 text-muted-foreground\">\n {data.caption}\n </p>\n )}\n </div>\n );\n}\n\n/* -------------------------------------------------------------------------- */\n/* Legacy node-graph paths */\n/* -------------------------------------------------------------------------- */\n\nfunction clampDiagramPercent(value: number) {\n if (!Number.isFinite(value)) return 50;\n return Math.max(4, Math.min(96, value));\n}\n\nfunction hasPositionedDiagramNodes(data: DiagramData): boolean {\n return (data.nodes ?? []).some(\n (node) => typeof node.x === \"number\" && typeof node.y === \"number\",\n );\n}\n\nfunction orderDiagramNodes(\n nodes: DiagramNode[],\n edges: DiagramEdge[],\n): DiagramNode[] {\n if (nodes.length === 0) return [];\n const byId = new Map(nodes.map((node) => [node.id, node]));\n const indegree = new Map(nodes.map((node) => [node.id, 0]));\n for (const edge of edges) {\n if (byId.has(edge.from) && byId.has(edge.to)) {\n indegree.set(edge.to, (indegree.get(edge.to) ?? 0) + 1);\n }\n }\n const start = nodes.find((node) => (indegree.get(node.id) ?? 0) === 0);\n if (!start) return nodes;\n const ordered: DiagramNode[] = [];\n const seen = new Set<string>();\n let current: DiagramNode | undefined = start;\n while (current && !seen.has(current.id)) {\n const node: DiagramNode = current;\n ordered.push(node);\n seen.add(node.id);\n const next = edges.find((edge) => edge.from === node.id);\n current = next ? byId.get(next.to) : undefined;\n }\n for (const node of nodes) if (!seen.has(node.id)) ordered.push(node);\n return ordered;\n}\n\nfunction PositionedDiagram({\n data,\n compact,\n markerId,\n}: {\n data: DiagramData;\n compact?: boolean;\n markerId: string;\n}) {\n const nodes = (data.nodes ?? []).map((node) => ({\n ...node,\n x: clampDiagramPercent(node.x ?? 50),\n y: clampDiagramPercent(node.y ?? 50),\n }));\n const edges = data.edges ?? [];\n const nodeById = new Map(nodes.map((node) => [node.id, node]));\n const arrowId = `${markerId}-diagram-arrow`;\n const nodeWidth = compact ? 150 : 190;\n const canvasHeight = compact ? 280 : 430;\n\n return (\n <div className=\"plan-sketch rounded-[16px] border border-border bg-muted p-5\">\n <div\n className=\"relative overflow-hidden rounded-xl border border-border bg-background\"\n style={{ minHeight: canvasHeight }}\n >\n <svg\n className=\"pointer-events-none absolute inset-0 z-0 h-full w-full\"\n viewBox=\"0 0 100 100\"\n preserveAspectRatio=\"none\"\n aria-hidden=\"true\"\n >\n <defs>\n <marker\n id={arrowId}\n viewBox=\"0 0 10 10\"\n refX=\"8\"\n refY=\"5\"\n markerWidth=\"5\"\n markerHeight=\"5\"\n orient=\"auto-start-reverse\"\n >\n <path\n d=\"M 0 0 L 10 5 L 0 10 z\"\n className=\"fill-muted-foreground\"\n />\n </marker>\n </defs>\n {edges.map((edge, index) => {\n const from = nodeById.get(edge.from);\n const to = nodeById.get(edge.to);\n if (!from || !to) return null;\n return (\n <line\n key={`${edge.from}-${edge.to}-${index}`}\n x1={from.x}\n y1={from.y}\n x2={to.x}\n y2={to.y}\n markerEnd={`url(#${arrowId})`}\n vectorEffect=\"non-scaling-stroke\"\n className=\"stroke-border\"\n strokeWidth={2}\n strokeDasharray={edge.label ? \"0\" : \"6 5\"}\n />\n );\n })}\n </svg>\n\n {!compact &&\n edges.map((edge, index) => {\n const from = nodeById.get(edge.from);\n const to = nodeById.get(edge.to);\n if (!edge.label || !from || !to) return null;\n return (\n <span\n key={`${edge.from}-${edge.to}-${index}-label`}\n className=\"absolute z-10 max-w-[130px] -translate-x-1/2 -translate-y-1/2 rounded-full border border-border bg-background px-2 py-0.5 text-center text-[11px] font-semibold text-muted-foreground shadow-sm\"\n style={{\n left: `${(from.x + to.x) / 2}%`,\n top: `${(from.y + to.y) / 2}%`,\n }}\n >\n {edge.label}\n </span>\n );\n })}\n\n {nodes.map((node, index) => (\n <article\n key={node.id}\n className=\"absolute z-20 -translate-x-1/2 -translate-y-1/2 rounded-xl border-2 border-border bg-background p-3 text-foreground shadow-sm\"\n style={{\n left: `${node.x}%`,\n top: `${node.y}%`,\n width: nodeWidth,\n }}\n >\n <p className=\"text-[11px] font-semibold uppercase tracking-[0.12em] text-muted-foreground\">\n {index + 1}\n </p>\n <h3 className=\"mt-2 text-base font-semibold leading-tight\">\n {node.label}\n </h3>\n {node.detail && !compact && (\n <p className=\"mt-2 text-xs leading-5 text-muted-foreground\">\n {node.detail}\n </p>\n )}\n </article>\n ))}\n </div>\n {data.notes && data.notes.length > 0 && !compact && (\n <div className=\"mt-4 grid gap-2 border-t border-border pt-4 text-sm text-muted-foreground md:grid-cols-2\">\n {data.notes.map((note) => (\n <p key={note.id}>{note.text}</p>\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction SequenceDiagram({\n data,\n compact,\n}: {\n data: DiagramData;\n compact?: boolean;\n}) {\n const edges = data.edges ?? [];\n const nodes = orderDiagramNodes(data.nodes ?? [], edges);\n if (nodes.length === 0) {\n return (\n <div className=\"rounded-[12px] border border-border bg-muted p-4 text-sm text-muted-foreground\">\n Diagram content is empty.\n </div>\n );\n }\n return (\n <div className=\"plan-sketch rounded-[16px] border border-border bg-muted p-5\">\n <div\n className={cn(\n \"flex gap-3 overflow-x-auto pb-2\",\n compact ? \"items-center\" : \"items-stretch\",\n )}\n >\n {nodes.map((node, index) => {\n const next = nodes[index + 1];\n const edge = next\n ? edges.find(\n (candidate) =>\n candidate.from === node.id && candidate.to === next.id,\n )\n : undefined;\n return (\n <div key={node.id} className=\"flex min-w-max items-center gap-3\">\n <article\n className={cn(\n \"w-[180px] rounded-xl border-2 border-border bg-background p-3 text-foreground\",\n compact && \"w-[150px]\",\n )}\n >\n <p className=\"text-[11px] font-semibold uppercase tracking-[0.12em] text-muted-foreground\">\n {index + 1}\n </p>\n <h3 className=\"mt-2 text-base font-semibold leading-tight\">\n {node.label}\n </h3>\n {node.detail && !compact && (\n <p className=\"mt-2 text-xs leading-5 text-muted-foreground\">\n {node.detail}\n </p>\n )}\n </article>\n {next && (\n <div className=\"grid min-w-[72px] justify-items-center gap-1 text-muted-foreground\">\n {edge?.label && (\n <span className=\"max-w-[96px] truncate rounded-full border border-border px-2 py-0.5 text-[11px] font-semibold\">\n {edge.label}\n </span>\n )}\n <span className=\"h-0.5 w-full rounded-full border-t-2 border-dashed border-border\" />\n </div>\n )}\n </div>\n );\n })}\n </div>\n {data.notes && data.notes.length > 0 && !compact && (\n <div className=\"mt-4 grid gap-2 border-t border-border pt-4 text-sm text-muted-foreground md:grid-cols-2\">\n {data.notes.map((note) => (\n <p key={note.id}>{note.text}</p>\n ))}\n </div>\n )}\n </div>\n );\n}\n\n/**\n * The diagram body. Routes to the preferred HTML/SVG path (when `data.html` is\n * set) and otherwise to a legacy node-graph path (positioned canvas when nodes\n * carry x/y, else an ordered sequence).\n */\nfunction DiagramBody({\n data,\n ctx,\n compact,\n}: {\n data: DiagramData;\n ctx: BlockRenderContext;\n compact?: boolean;\n}) {\n const markerId = useId().replace(/:/g, \"\");\n if (data.html?.trim()) {\n return <HtmlDiagram data={data} ctx={ctx} compact={compact} />;\n }\n if (hasPositionedDiagramNodes(data)) {\n return (\n <PositionedDiagram data={data} compact={compact} markerId={markerId} />\n );\n }\n return <SequenceDiagram data={data} compact={compact} />;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Read + Edit */\n/* -------------------------------------------------------------------------- */\n\n/** Read-only renderer: the diagram body wrapped in the standard titled block. */\nexport function DiagramRead({\n data,\n blockId,\n title,\n summary,\n ctx,\n}: BlockReadProps<DiagramData>) {\n return (\n <section className=\"an-block plan-block\" data-block-id={blockId}>\n {title && <div className=\"an-block-label plan-block-label\">{title}</div>}\n <DiagramBody data={data} ctx={ctx} />\n {summary && <p className=\"mt-5 text-muted-foreground\">{summary}</p>}\n </section>\n );\n}\n\n/**\n * Edit form (panel surface). The block can be an HTML/SVG fragment or a legacy\n * node/edge/note graph, so this exposes html/css/caption plus a collapsible\n * legacy node-graph JSON editor, each with an AI-edit affordance via\n * `ctx.renderAiFieldAction` (through `AiEditableFieldLabel`). `editSurface:\n * \"panel\"` means the registry renders the `Read` view with a corner edit button\n * that opens this form in the app-provided popover.\n */\nexport function DiagramEdit({\n data,\n onChange,\n editable,\n blockId,\n title,\n summary,\n ctx,\n}: BlockEditProps<DiagramData>) {\n const htmlId = useId();\n const cssId = useId();\n const captionId = useId();\n const legacyId = useId();\n const [html, setHtml] = useState(data.html ?? \"\");\n const [css, setCss] = useState(data.css ?? \"\");\n const [caption, setCaption] = useState(data.caption ?? \"\");\n const [legacyJson, setLegacyJson] = useState(() =>\n JSON.stringify(\n {\n nodes: data.nodes ?? [],\n edges: data.edges ?? [],\n notes: data.notes ?? [],\n },\n null,\n 2,\n ),\n );\n\n useEffect(() => {\n setHtml(data.html ?? \"\");\n setCss(data.css ?? \"\");\n setCaption(data.caption ?? \"\");\n setLegacyJson(\n JSON.stringify(\n {\n nodes: data.nodes ?? [],\n edges: data.edges ?? [],\n notes: data.notes ?? [],\n },\n null,\n 2,\n ),\n );\n }, [data]);\n\n const saveHtmlDiagram = () => {\n onChange({\n html: html.trim() || undefined,\n css: css.trim() || undefined,\n caption: caption.trim() || undefined,\n nodes: data.nodes,\n edges: data.edges,\n notes: data.notes,\n });\n };\n\n const saveLegacyDiagram = () => {\n const parsed = JSON.parse(legacyJson) as Pick<\n DiagramData,\n \"nodes\" | \"edges\" | \"notes\"\n >;\n onChange({\n ...data,\n nodes: parsed.nodes ?? [],\n edges: parsed.edges ?? [],\n notes: parsed.notes ?? [],\n });\n };\n\n const fieldAction = (\n field: \"HTML / SVG fragment\" | \"CSS\" | \"caption\" | \"legacy node graph JSON\",\n value: string,\n ) => ({\n blockId,\n blockType: \"diagram\",\n blockTitle: title,\n blockSummary: summary,\n fieldValue: value,\n draftScope: `block:diagram:${blockId}:${field.toLowerCase().replace(/[^a-z0-9]+/g, \"-\")}`,\n disabled: !editable,\n instructions:\n \"Update the plan with update-visual-plan using a targeted update-block content patch for this diagram block id. Preserve unrelated diagram fields unless the requested edit requires changing them. Keep diagram HTML/CSS on renderer-owned .diagram-* primitives and --wf-* tokens; do not introduce custom font-family or hard-coded hex/rgb/hsl colors.\",\n companionFields: [\n {\n label: \"HTML / SVG fragment\",\n value: html.trim() || \"(empty)\",\n language: \"html\",\n },\n { label: \"CSS\", value: css.trim() || \"(empty)\", language: \"css\" },\n {\n label: \"caption\",\n value: caption.trim() || \"(empty)\",\n language: \"text\",\n },\n ],\n });\n\n return (\n <div className=\"grid gap-4\" data-plan-interactive>\n <button\n type=\"button\"\n className=\"inline-flex h-8 w-fit items-center justify-center rounded-md bg-primary px-3 text-xs font-medium text-primary-foreground disabled:opacity-50\"\n disabled={!editable}\n onClick={saveHtmlDiagram}\n >\n Save diagram\n </button>\n <div className=\"group/field grid gap-1.5\">\n <AiEditableFieldLabel\n htmlFor={htmlId}\n label=\"HTML / SVG fragment\"\n ctx={ctx}\n action={fieldAction(\"HTML / SVG fragment\", html)}\n />\n <textarea\n id={htmlId}\n className=\"min-h-48 w-full rounded-md border border-input bg-background px-3 py-2 font-mono text-xs leading-5 text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n value={html}\n disabled={!editable}\n onChange={(event) => setHtml(event.target.value)}\n placeholder=\"<div class='diagram'>...</div>\"\n />\n </div>\n <div className=\"group/field grid gap-1.5\">\n <AiEditableFieldLabel\n htmlFor={cssId}\n label=\"CSS\"\n ctx={ctx}\n action={fieldAction(\"CSS\", css)}\n />\n <textarea\n id={cssId}\n className=\"min-h-32 w-full rounded-md border border-input bg-background px-3 py-2 font-mono text-xs leading-5 text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n value={css}\n disabled={!editable}\n onChange={(event) => setCss(event.target.value)}\n placeholder=\".diagram { display: grid; }\"\n />\n </div>\n <div className=\"group/field grid gap-1.5\">\n <AiEditableFieldLabel\n htmlFor={captionId}\n label=\"Caption\"\n ctx={ctx}\n action={fieldAction(\"caption\", caption)}\n />\n <input\n id={captionId}\n className=\"h-9 w-full rounded-md border border-input bg-background px-3 text-sm text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n value={caption}\n disabled={!editable}\n onChange={(event) => setCaption(event.target.value)}\n />\n </div>\n {!data.html && (\n <details className=\"rounded-md border border-border p-3\">\n <summary className=\"cursor-pointer text-xs font-semibold text-muted-foreground\">\n Legacy node graph data\n </summary>\n <div className=\"group/field mt-3 grid gap-1.5\">\n <AiEditableFieldLabel\n htmlFor={legacyId}\n label=\"JSON\"\n ctx={ctx}\n action={fieldAction(\"legacy node graph JSON\", legacyJson)}\n />\n <textarea\n id={legacyId}\n className=\"min-h-44 w-full rounded-md border border-input bg-background px-3 py-2 font-mono text-xs leading-5 text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n value={legacyJson}\n disabled={!editable}\n onChange={(event) => setLegacyJson(event.target.value)}\n />\n </div>\n <button\n type=\"button\"\n className=\"mt-3 inline-flex h-8 items-center justify-center rounded-md border border-input px-3 text-xs font-medium text-foreground disabled:opacity-50\"\n disabled={!editable}\n onClick={saveLegacyDiagram}\n >\n Save graph data\n </button>\n </details>\n )}\n </div>\n );\n}\n\n/** Full client spec for the shared `diagram` block (schema + MDX + Read/Edit). */\nexport const diagramBlock = defineBlock<DiagramData>({\n type: \"diagram\",\n schema: diagramSchema,\n mdx: diagramMdx,\n Read: DiagramRead,\n Edit: DiagramEdit,\n placement: [\"block\"],\n // Config-driven: the rendered diagram differs from its raw html/css source, so\n // edit from a corner button + panel rather than inline.\n editSurface: \"panel\",\n label: \"Diagram\",\n description:\n \"A flexible inline architecture/code diagram. Prefer html/css with SVG or semantic HTML for polished two-dimensional layouts; use .diagram-* primitives and --wf-* tokens for theme/sketch compatibility. Legacy nodes/edges are only for simple previews.\",\n // Seed the legacy fallback shape so a fresh block validates while agents can\n // replace it with html/css when layout quality matters.\n empty: () => ({ nodes: [{ id: \"n1\", label: \"Module\" }], edges: [] }),\n});\n"]}
|
|
@@ -16,6 +16,23 @@ import type { BlockMdxConfig } from "../types.js";
|
|
|
16
16
|
*/
|
|
17
17
|
/** Rendering layout for the diff body. */
|
|
18
18
|
export type DiffMode = "unified" | "split";
|
|
19
|
+
/**
|
|
20
|
+
* One line-anchored note attached to a diff, mirroring the `annotated-code`
|
|
21
|
+
* annotation shape but adding `side`. The `lines` ref is 1-based against the
|
|
22
|
+
* chosen side's source: `side: "after"` (the default) targets the new file's
|
|
23
|
+
* line numbers, `side: "before"` the old file's. Optional ⇒ a diff without
|
|
24
|
+
* annotations renders exactly as before.
|
|
25
|
+
*/
|
|
26
|
+
export interface DiffAnnotation {
|
|
27
|
+
/** Which side the line ref targets; defaults to "after". */
|
|
28
|
+
side?: "before" | "after";
|
|
29
|
+
/** 1-based line ref against that side's text: "13" or "13-15" (inclusive). */
|
|
30
|
+
lines: string;
|
|
31
|
+
/** Optional short label shown before the note (e.g. "Validation"). */
|
|
32
|
+
label?: string;
|
|
33
|
+
/** The note prose (markdown), rendered through `ctx.renderMarkdown`. */
|
|
34
|
+
note: string;
|
|
35
|
+
}
|
|
19
36
|
export interface DiffData {
|
|
20
37
|
/** Optional file path shown in the header (e.g. `src/add.ts`). */
|
|
21
38
|
filename?: string;
|
|
@@ -27,15 +44,20 @@ export interface DiffData {
|
|
|
27
44
|
after: string;
|
|
28
45
|
/** Layout: unified (default, one column) or split (side-by-side). */
|
|
29
46
|
mode?: DiffMode;
|
|
47
|
+
/** Line-anchored notes over the before/after sides. */
|
|
48
|
+
annotations?: DiffAnnotation[];
|
|
30
49
|
}
|
|
31
50
|
export declare const diffSchema: z.ZodType<DiffData>;
|
|
32
51
|
/**
|
|
33
|
-
* MDX config: `filename`, `language`, `mode`, `before`,
|
|
34
|
-
* attributes — the
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* `
|
|
38
|
-
* attribute
|
|
52
|
+
* MDX config: `filename`, `language`, `mode`, `before`, `after`, and
|
|
53
|
+
* `annotations` are flat attributes — the
|
|
54
|
+
* `<Diff id … filename language mode before after annotations />` self-closing
|
|
55
|
+
* form. Insertion order of `toAttrs` is the on-disk attribute order. `before`/
|
|
56
|
+
* `after` are multiline string attributes (round-trip through the shared `prop()`
|
|
57
|
+
* encoder); `annotations` is a JSON array attribute, encoded the same way as the
|
|
58
|
+
* `annotated-code` block. `fromAttrs` mirrors a forgiving parse (`before ?? ""`,
|
|
59
|
+
* `after ?? ""`, `annotations ?? []`, optional `filename`/`language`/`mode`
|
|
60
|
+
* undefined when absent) so a plan missing an attribute still parses.
|
|
39
61
|
*/
|
|
40
62
|
export declare const diffMdx: BlockMdxConfig<DiffData>;
|
|
41
63
|
//# sourceMappingURL=diff.config.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff.config.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/diff.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD;;;;;;;;;;;;;GAaG;AAEH,0CAA0C;AAC1C,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;AAE3C,MAAM,WAAW,QAAQ;IACvB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,qEAAqE;IACrE,IAAI,CAAC,EAAE,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"diff.config.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/diff.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD;;;;;;;;;;;;;GAaG;AAEH,0CAA0C;AAC1C,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;AAE3C;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,4DAA4D;IAC5D,IAAI,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC1B,8EAA8E;IAC9E,KAAK,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,QAAQ;IACvB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,qEAAqE;IACrE,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,uDAAuD;IACvD,WAAW,CAAC,EAAE,cAAc,EAAE,CAAC;CAChC;AAsBD,eAAO,MAAM,UAAU,EAON,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AAErC;;;;;;;;;;GAUG;AACH,eAAO,MAAM,OAAO,EAAE,cAAc,CAAC,QAAQ,CAkB5C,CAAC"}
|