@pixerate/editor 0.54.0 → 0.56.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.
Files changed (115) hide show
  1. package/dist/agent/index.cjs +24 -23
  2. package/dist/agent/index.cjs.map +1 -1
  3. package/dist/agent/index.js +9 -8
  4. package/dist/agent/index.js.map +1 -1
  5. package/dist/animation/index.cjs +1 -1
  6. package/dist/animation/index.cjs.map +1 -1
  7. package/dist/animation/index.d.cts +2 -1
  8. package/dist/animation/index.d.ts +2 -1
  9. package/dist/animation/index.js +1 -1
  10. package/dist/animation-editor/index.cjs +2221 -0
  11. package/dist/animation-editor/index.cjs.map +1 -0
  12. package/dist/animation-editor/index.d.cts +1117 -0
  13. package/dist/animation-editor/index.d.ts +1117 -0
  14. package/dist/animation-editor/index.js +2221 -0
  15. package/dist/animation-editor/index.js.map +1 -0
  16. package/dist/bezier-BfwIbVTl.d.cts +548 -0
  17. package/dist/bezier-DYBvLgUH.d.ts +548 -0
  18. package/dist/canvas/index.cjs +2740 -580
  19. package/dist/canvas/index.cjs.map +1 -1
  20. package/dist/canvas/index.d.cts +402 -6
  21. package/dist/canvas/index.d.ts +402 -6
  22. package/dist/canvas/index.js +2735 -575
  23. package/dist/canvas/index.js.map +1 -1
  24. package/dist/chart/index.cjs +33 -31
  25. package/dist/chart/index.cjs.map +1 -1
  26. package/dist/chart/index.d.cts +4 -2
  27. package/dist/chart/index.d.ts +4 -2
  28. package/dist/chart/index.js +21 -19
  29. package/dist/chart/index.js.map +1 -1
  30. package/dist/{chunk-C3JHII3M.cjs → chunk-3I6V7PI4.cjs} +45 -45
  31. package/dist/{chunk-C3JHII3M.cjs.map → chunk-3I6V7PI4.cjs.map} +1 -1
  32. package/dist/{chunk-P43HUQRX.cjs → chunk-AHCENCU4.cjs} +12 -10
  33. package/dist/chunk-AHCENCU4.cjs.map +1 -0
  34. package/dist/{chunk-TO22LX34.js → chunk-GTMJ4Y3S.js} +2208 -2920
  35. package/dist/chunk-GTMJ4Y3S.js.map +1 -0
  36. package/dist/chunk-II77MLHN.cjs +11106 -0
  37. package/dist/chunk-II77MLHN.cjs.map +1 -0
  38. package/dist/{chunk-OIKYP7XC.js → chunk-LMUDHBWR.js} +2 -2
  39. package/dist/chunk-MLREO6J3.cjs +737 -0
  40. package/dist/chunk-MLREO6J3.cjs.map +1 -0
  41. package/dist/chunk-NONDTTH7.js +5979 -0
  42. package/dist/chunk-NONDTTH7.js.map +1 -0
  43. package/dist/{chunk-YNSK4MGT.cjs → chunk-O2UH7LZE.cjs} +1549 -2261
  44. package/dist/chunk-O2UH7LZE.cjs.map +1 -0
  45. package/dist/{chunk-VODBAO32.js → chunk-OEFCLWZ3.js} +4 -1425
  46. package/dist/chunk-OEFCLWZ3.js.map +1 -0
  47. package/dist/{chunk-NK3WL5TJ.cjs → chunk-P2CTDJNF.cjs} +27 -1448
  48. package/dist/chunk-P2CTDJNF.cjs.map +1 -0
  49. package/dist/chunk-TKPPIVW7.cjs +1443 -0
  50. package/dist/chunk-TKPPIVW7.cjs.map +1 -0
  51. package/dist/chunk-VWZB6BCY.js +737 -0
  52. package/dist/chunk-VWZB6BCY.js.map +1 -0
  53. package/dist/chunk-WJSCGBJ2.js +11106 -0
  54. package/dist/chunk-WJSCGBJ2.js.map +1 -0
  55. package/dist/{chunk-RIXTW3C4.js → chunk-WLVZ235X.js} +5 -3
  56. package/dist/{chunk-RIXTW3C4.js.map → chunk-WLVZ235X.js.map} +1 -1
  57. package/dist/chunk-XCXQDPID.cjs +5979 -0
  58. package/dist/chunk-XCXQDPID.cjs.map +1 -0
  59. package/dist/chunk-ZOH6X3VR.js +1443 -0
  60. package/dist/chunk-ZOH6X3VR.js.map +1 -0
  61. package/dist/color-E9pwm--w.d.cts +33 -0
  62. package/dist/color-E9pwm--w.d.ts +33 -0
  63. package/dist/commands/index.cjs +2 -2
  64. package/dist/commands/index.cjs.map +1 -1
  65. package/dist/commands/index.js +3 -3
  66. package/dist/{controller-DscWQbjO.d.ts → controller-D2rj5umx.d.ts} +2 -362
  67. package/dist/{controller-CX0QfSv0.d.cts → controller-R2biKk_E.d.cts} +2 -362
  68. package/dist/diagram/index.cjs +1481 -50
  69. package/dist/diagram/index.cjs.map +1 -1
  70. package/dist/diagram/index.d.cts +1757 -15
  71. package/dist/diagram/index.d.ts +1757 -15
  72. package/dist/diagram/index.js +1469 -38
  73. package/dist/diagram/index.js.map +1 -1
  74. package/dist/extensions/index.cjs +5 -4
  75. package/dist/extensions/index.cjs.map +1 -1
  76. package/dist/extensions/index.d.cts +4 -3
  77. package/dist/extensions/index.d.ts +4 -3
  78. package/dist/extensions/index.js +4 -3
  79. package/dist/{index-DIWB6xMf.d.cts → index-BcHyG0Wq.d.cts} +2 -1
  80. package/dist/{index-CALDD35B.d.ts → index-CTCc3m3C.d.ts} +2 -1
  81. package/dist/index.cjs +10 -9
  82. package/dist/index.cjs.map +1 -1
  83. package/dist/index.d.cts +4 -3
  84. package/dist/index.d.ts +4 -3
  85. package/dist/index.js +4 -3
  86. package/dist/index.js.map +1 -1
  87. package/dist/pathfinder-BZL8aSu0.d.cts +469 -0
  88. package/dist/pathfinder-CNtsbCRK.d.ts +469 -0
  89. package/dist/{player-DSMjdgQ9.d.cts → player-Dg0FT0UI.d.cts} +1 -33
  90. package/dist/{player-DdfVrKWq.d.ts → player-W-5DX3Go.d.ts} +1 -33
  91. package/dist/svg-CLg2zqZA.d.cts +847 -0
  92. package/dist/svg-CPK82TtU.d.ts +847 -0
  93. package/dist/types-BRp-6zkY.d.cts +362 -0
  94. package/dist/types-BRp-6zkY.d.ts +362 -0
  95. package/dist/{types-BULrFyuQ.d.cts → types-DYkjhzdz.d.cts} +1 -1
  96. package/dist/{types-BULrFyuQ.d.ts → types-DYkjhzdz.d.ts} +1 -1
  97. package/dist/vector/index.cjs +1328 -6752
  98. package/dist/vector/index.cjs.map +1 -1
  99. package/dist/vector/index.d.cts +6 -846
  100. package/dist/vector/index.d.ts +6 -846
  101. package/dist/vector/index.js +645 -6069
  102. package/dist/vector/index.js.map +1 -1
  103. package/package.json +6 -1
  104. package/dist/chunk-H5K77C7Y.cjs +0 -3848
  105. package/dist/chunk-H5K77C7Y.cjs.map +0 -1
  106. package/dist/chunk-NK3WL5TJ.cjs.map +0 -1
  107. package/dist/chunk-P43HUQRX.cjs.map +0 -1
  108. package/dist/chunk-TO22LX34.js.map +0 -1
  109. package/dist/chunk-VODBAO32.js.map +0 -1
  110. package/dist/chunk-WWJNC7SX.js +0 -3848
  111. package/dist/chunk-WWJNC7SX.js.map +0 -1
  112. package/dist/chunk-YNSK4MGT.cjs.map +0 -1
  113. package/dist/pathfinder-B9xh_pCZ.d.ts +0 -1013
  114. package/dist/pathfinder-QdG70sr9.d.cts +0 -1013
  115. /package/dist/{chunk-OIKYP7XC.js.map → chunk-LMUDHBWR.js.map} +0 -0
@@ -1,57 +1,132 @@
1
1
  import {
2
- HistoryManager
3
- } from "../chunk-QVZZGT4X.js";
4
- import {
5
- PRESENCE_COLORS,
6
- PerformanceQueue,
7
- PresenceStore,
8
- createInstantPresenceClock,
9
- realPresenceClock,
10
- tweenPresenceCursor
11
- } from "../chunk-B6DSIEXA.js";
12
- import {
2
+ ARCH_METRICS,
3
+ C4_METRICS,
13
4
  CLASS_RELATIONS,
14
5
  ER_CARDINALITIES,
15
6
  ER_PATTERNS,
16
7
  FLOWCHART_SHAPES,
8
+ GANTT_CONFIG_KEYS,
9
+ GANTT_METRICS,
10
+ GANTT_TAGS,
17
11
  META_COMMENT_PREFIX,
18
12
  META_FRONTMATTER_KEY,
13
+ POINT_BOX,
14
+ QUADRANT_METRICS,
15
+ RADAR_CHART_BOX,
16
+ SEQUENCE_METRICS,
19
17
  STATE_SHAPES,
18
+ XY_CHART_BOX,
19
+ afterIds,
20
20
  applyEdit,
21
21
  applyEdits,
22
+ applyStatementEdit,
23
+ architectureAdapter,
24
+ architectureArrow,
25
+ architectureEdgeRoute,
26
+ architectureGrammar,
27
+ architectureLayout,
28
+ c4Adapter,
29
+ c4ArrowHead,
30
+ c4BoundaryText,
31
+ c4ElementGeometry,
32
+ c4ElementType,
33
+ c4Grammar,
34
+ c4Layout,
35
+ c4RelGeometry,
36
+ c4Stereotype,
22
37
  canonicalShape,
23
38
  classGrammar,
24
39
  createLineAdapter,
25
40
  createPassthroughAdapter,
41
+ createStatementAdapter,
26
42
  detectFamily,
27
43
  detectFamilyFromHeader,
44
+ dropMetaKeys,
28
45
  emptyMeta,
29
46
  erGrammar,
47
+ filterInPlace,
30
48
  flowchartAdapter,
49
+ formatAxis,
31
50
  formatChain,
51
+ formatGanttDate,
32
52
  formatLink,
33
53
  formatNode,
54
+ ganttAdapter,
55
+ ganttGeometry,
56
+ ganttGrammar,
34
57
  getDiagramAdapter,
58
+ getFamilyLayout,
59
+ gitGraphAdapter,
60
+ gitGraphGrammar,
61
+ indentOf,
35
62
  isMetaEmpty,
63
+ journeyAdapter,
64
+ journeyGrammar,
65
+ journeyLayout,
36
66
  mergeMeta,
67
+ mindmapAdapter,
68
+ mindmapGrammar,
37
69
  parseAttributes,
38
70
  parseChain,
39
71
  parseFlowchartSource,
72
+ parseGanttDate,
40
73
  parseLink,
41
74
  parseMembers,
42
75
  parseMermaid,
43
76
  parseStatement,
77
+ parseStatementDocument,
78
+ pieAdapter,
79
+ pieGrammar,
80
+ pointCentre,
81
+ pointPosition,
82
+ positionToData,
83
+ quadrantAdapter,
84
+ quadrantGeometry,
85
+ quadrantGrammar,
86
+ quadrantSpace,
87
+ quote,
44
88
  quoteLabelIfNeeded,
89
+ radarAdapter,
90
+ radarGrammar,
45
91
  registerDiagramAdapter,
92
+ registerFamilyLayout,
46
93
  relationFor,
94
+ renameMetaKey,
47
95
  resolveShape,
96
+ sequenceAdapter,
97
+ sequenceGeometry,
98
+ sequenceGrammar,
48
99
  serializeMermaid,
49
100
  serializeMeta,
101
+ serializeStatementDocument,
102
+ serviceLabelLines,
103
+ sharedFrameLayout,
104
+ slugId,
105
+ spaceInput,
106
+ splitOutsideQuotes,
50
107
  splitSource,
51
108
  splitStatements,
52
109
  stateGrammar,
53
- supportTierOf
54
- } from "../chunk-WWJNC7SX.js";
110
+ supportTierOf,
111
+ timelineAdapter,
112
+ timelineGrammar,
113
+ timelineLayout,
114
+ uniqueId,
115
+ unquote,
116
+ xyChartAdapter,
117
+ xyChartGrammar
118
+ } from "../chunk-WJSCGBJ2.js";
119
+ import {
120
+ PRESENCE_COLORS,
121
+ PerformanceQueue,
122
+ PresenceStore,
123
+ createInstantPresenceClock,
124
+ realPresenceClock,
125
+ tweenPresenceCursor
126
+ } from "../chunk-B6DSIEXA.js";
127
+ import {
128
+ HistoryManager
129
+ } from "../chunk-QVZZGT4X.js";
55
130
 
56
131
  // src/diagram/types.ts
57
132
  var DIRECTIONS = ["TB", "TD", "BT", "LR", "RL"];
@@ -114,17 +189,1151 @@ function headingText(line) {
114
189
  return text || void 0;
115
190
  }
116
191
 
192
+ // src/diagram/families/pie.ts
193
+ var pieUI = {
194
+ family: "pie",
195
+ title: "Pie chart",
196
+ shapes: [{ value: "slice", label: "Slice" }],
197
+ edgeKinds: [],
198
+ patterns: [],
199
+ arrowHeads: [],
200
+ groups: { supported: false, label: "Group" },
201
+ labels: true,
202
+ nodeNoun: "Slice",
203
+ nextId: (g) => `slice${g.nodes.length + 1}`,
204
+ canDetach: false,
205
+ styling: false,
206
+ connectable: false,
207
+ directions: false,
208
+ arrange: false,
209
+ preview: false,
210
+ nodeFields: [{ key: "value", label: "Value", type: "number", min: 0 }],
211
+ diagramFields: [{ key: "showData", label: "Show values in legend", type: "boolean" }],
212
+ newNode: () => ({ label: "New slice", data: { value: 10 } })
213
+ };
214
+
215
+ // src/diagram/families/mindmap.ts
216
+ var mindmapUI = {
217
+ family: "mindmap",
218
+ title: "Mind map",
219
+ shapes: [
220
+ { value: "text", label: "Topic" },
221
+ { value: "rounded", label: "Rounded" },
222
+ { value: "rect", label: "Square" },
223
+ { value: "circle", label: "Circle" },
224
+ { value: "odd", label: "Bang" },
225
+ { value: "stadium", label: "Cloud" },
226
+ { value: "hex", label: "Hexagon" }
227
+ ],
228
+ edgeKinds: [
229
+ { value: "branch", label: "Branch", arrowStart: "none", arrowEnd: "none", pattern: "solid" }
230
+ ],
231
+ patterns: [{ value: "solid", label: "Solid" }],
232
+ arrowHeads: [{ value: "none", label: "None" }],
233
+ groups: { supported: false, label: "Group" },
234
+ labels: true,
235
+ nodeNoun: "Topic",
236
+ edgeNoun: "Branch",
237
+ nextId: (g) => `topic${g.nodes.length + 1}`,
238
+ canDetach: false,
239
+ hierarchy: true,
240
+ styling: false,
241
+ connectable: false,
242
+ directions: false,
243
+ arrange: false,
244
+ preview: false,
245
+ nodeFields: [{ key: "icon", label: "Icon", type: "text", placeholder: "fa fa-book" }],
246
+ newNode: () => ({ label: "New topic" })
247
+ };
248
+
249
+ // src/diagram/families/quadrant.ts
250
+ var quadrantUI = {
251
+ family: "quadrant",
252
+ title: "Quadrant chart",
253
+ shapes: [{ value: "point", label: "Point" }],
254
+ edgeKinds: [],
255
+ patterns: [],
256
+ arrowHeads: [],
257
+ groups: { supported: false, label: "Quadrant" },
258
+ labels: true,
259
+ nodeNoun: "Point",
260
+ nextId: (g) => `point${g.nodes.length + 1}`,
261
+ canDetach: false,
262
+ styling: false,
263
+ connectable: false,
264
+ directions: false,
265
+ arrange: false,
266
+ preview: false,
267
+ nodeFields: [
268
+ { key: "x", label: "X", type: "number", min: 0, max: 1, step: 0.05 },
269
+ { key: "y", label: "Y", type: "number", min: 0, max: 1, step: 0.05 },
270
+ { key: "radius", label: "Radius", type: "number", min: 1 },
271
+ { key: "color", label: "Colour", type: "text", placeholder: "#ff9900" }
272
+ ],
273
+ diagramFields: [
274
+ { key: "xAxisLeft", label: "X axis (left)", type: "text" },
275
+ { key: "xAxisRight", label: "X axis (right)", type: "text" },
276
+ { key: "yAxisBottom", label: "Y axis (bottom)", type: "text" },
277
+ { key: "yAxisTop", label: "Y axis (top)", type: "text" }
278
+ ],
279
+ newNode: () => ({ label: "New point", data: { x: 0.5, y: 0.5 } })
280
+ };
281
+
282
+ // src/diagram/families/c4.ts
283
+ var c4UI = {
284
+ family: "c4",
285
+ title: "C4 diagram",
286
+ shapes: [
287
+ { value: "c4-person", label: "Person" },
288
+ { value: "c4-person-ext", label: "External person" },
289
+ { value: "c4-system", label: "System" },
290
+ { value: "c4-system-ext", label: "External system" },
291
+ { value: "c4-container", label: "Container" },
292
+ { value: "c4-container-ext", label: "External container" },
293
+ { value: "c4-component", label: "Component" },
294
+ { value: "c4-component-ext", label: "External component" },
295
+ { value: "c4-db", label: "Database" },
296
+ { value: "c4-queue", label: "Queue" }
297
+ ],
298
+ edgeKinds: [
299
+ {
300
+ value: "Rel",
301
+ label: "Relation",
302
+ arrowStart: "none",
303
+ arrowEnd: "arrow_point",
304
+ pattern: "solid"
305
+ },
306
+ {
307
+ value: "BiRel",
308
+ label: "Bidirectional",
309
+ arrowStart: "arrow_point",
310
+ arrowEnd: "arrow_point",
311
+ pattern: "solid"
312
+ },
313
+ {
314
+ value: "Rel_Back",
315
+ label: "Reverse",
316
+ arrowStart: "arrow_point",
317
+ arrowEnd: "none",
318
+ pattern: "solid"
319
+ }
320
+ ],
321
+ patterns: [{ value: "solid", label: "Solid" }],
322
+ arrowHeads: [
323
+ { value: "none", label: "None" },
324
+ { value: "arrow_point", label: "Arrow" }
325
+ ],
326
+ groups: { supported: true, label: "Boundary" },
327
+ labels: true,
328
+ nodeNoun: "Element",
329
+ edgeNoun: "Relation",
330
+ nextId: (g) => {
331
+ const taken = /* @__PURE__ */ new Set([...g.nodes.map((n) => n.id), ...g.groups.map((x) => x.id)]);
332
+ let i = g.nodes.length + 1;
333
+ while (taken.has(`el${i}`)) i++;
334
+ return `el${i}`;
335
+ },
336
+ canDetach: true,
337
+ styling: false,
338
+ directions: false,
339
+ // Positions are Mermaid's own layout (plus where the user dragged): "Arrange"
340
+ // would pin a dagre layout Mermaid never draws.
341
+ // "Tidy up" resets dragged positions to Mermaid's own layout (the registered family layout).
342
+ arrange: true,
343
+ preview: false,
344
+ connectable: true,
345
+ nodeFields: [
346
+ { key: "tech", label: "Technology", type: "text" },
347
+ { key: "descr", label: "Description", type: "text" }
348
+ ],
349
+ edgeFields: [{ key: "tech", label: "Technology", type: "text" }],
350
+ newNode: () => ({ label: "New element" })
351
+ };
352
+
353
+ // src/diagram/families/architecture.ts
354
+ var SIDE_OPTIONS = [
355
+ { value: "L", label: "Left" },
356
+ { value: "R", label: "Right" },
357
+ { value: "T", label: "Top" },
358
+ { value: "B", label: "Bottom" }
359
+ ];
360
+ var architectureUI = {
361
+ family: "architecture",
362
+ title: "Architecture diagram",
363
+ shapes: [
364
+ { value: "arch-service", label: "Service" },
365
+ { value: "sm-circ", label: "Junction" }
366
+ ],
367
+ edgeKinds: [
368
+ { value: "--", label: "Line", arrowStart: "none", arrowEnd: "none", pattern: "solid" },
369
+ { value: "-->", label: "Arrow", arrowStart: "none", arrowEnd: "arrow_point", pattern: "solid" },
370
+ {
371
+ value: "<-->",
372
+ label: "Bidirectional",
373
+ arrowStart: "arrow_point",
374
+ arrowEnd: "arrow_point",
375
+ pattern: "solid"
376
+ }
377
+ ],
378
+ patterns: [{ value: "solid", label: "Solid" }],
379
+ arrowHeads: [
380
+ { value: "none", label: "None" },
381
+ { value: "arrow_point", label: "Arrow" }
382
+ ],
383
+ groups: { supported: true, label: "Group" },
384
+ labels: true,
385
+ nodeNoun: "Service",
386
+ edgeNoun: "Connection",
387
+ nextId: (g) => {
388
+ const taken = /* @__PURE__ */ new Set([...g.nodes.map((n) => n.id), ...g.groups.map((x) => x.id)]);
389
+ let i = g.nodes.length + 1;
390
+ while (taken.has(`svc${i}`)) i++;
391
+ return `svc${i}`;
392
+ },
393
+ canDetach: true,
394
+ styling: false,
395
+ directions: false,
396
+ // Positions are Mermaid's own layout (plus where the user dragged): "Arrange"
397
+ // would pin a dagre layout Mermaid never draws.
398
+ // "Tidy up" resets dragged positions to Mermaid's own layout (the registered family layout).
399
+ arrange: true,
400
+ preview: false,
401
+ connectable: true,
402
+ nodeFields: [
403
+ {
404
+ key: "icon",
405
+ label: "Icon",
406
+ type: "select",
407
+ options: ["cloud", "database", "disk", "internet", "server"].map((v) => ({
408
+ value: v,
409
+ label: v
410
+ }))
411
+ }
412
+ ],
413
+ edgeFields: [
414
+ { key: "sourceSide", label: "From side", type: "select", options: SIDE_OPTIONS },
415
+ { key: "targetSide", label: "To side", type: "select", options: SIDE_OPTIONS }
416
+ ],
417
+ newNode: () => ({ label: "New service", data: { icon: "server" } })
418
+ };
419
+
420
+ // src/diagram/families/sequence.ts
421
+ function nextParticipantId(graph) {
422
+ const taken = /* @__PURE__ */ new Set([...graph.nodes.map((n) => n.id), ...graph.groups.map((g) => g.id)]);
423
+ let i = 1;
424
+ while (taken.has(`P${i}`)) i++;
425
+ return `P${i}`;
426
+ }
427
+ var kind = (value, label, pattern, arrowEnd, arrowStart = "none") => ({ value, label, pattern, arrowStart, arrowEnd });
428
+ var sequenceUI = {
429
+ family: "sequence",
430
+ title: "Sequence diagram",
431
+ shapes: [
432
+ { value: "rect", label: "Participant" },
433
+ { value: "actor", label: "Actor" }
434
+ ],
435
+ edgeKinds: [
436
+ kind("->>", "Sync", "solid", "arrow_point"),
437
+ kind("-->>", "Reply", "dotted", "arrow_point"),
438
+ kind("->", "Line", "solid", "none"),
439
+ kind("-->", "Dotted line", "dotted", "none"),
440
+ kind("-x", "Lost", "solid", "arrow_cross"),
441
+ kind("--x", "Dotted lost", "dotted", "arrow_cross"),
442
+ kind("-)", "Async", "solid", "arrow_open"),
443
+ kind("--)", "Dotted async", "dotted", "arrow_open"),
444
+ kind("<<->>", "Bidirectional", "solid", "arrow_point", "arrow_point")
445
+ ],
446
+ patterns: [
447
+ { value: "solid", label: "Solid" },
448
+ { value: "dotted", label: "Dotted" }
449
+ ],
450
+ arrowHeads: [
451
+ { value: "none", label: "None" },
452
+ { value: "arrow_point", label: "Arrow" },
453
+ { value: "arrow_cross", label: "Cross" },
454
+ { value: "arrow_open", label: "Open" }
455
+ ],
456
+ groups: { supported: true, label: "Box" },
457
+ labels: true,
458
+ nodeNoun: "Participant",
459
+ edgeNoun: "Message",
460
+ nextId: nextParticipantId,
461
+ canDetach: true,
462
+ styling: false,
463
+ directions: false,
464
+ arrange: false,
465
+ endpoints: true,
466
+ preview: false,
467
+ edgeFields: [
468
+ { key: "activate", label: "Activate target", type: "boolean" },
469
+ { key: "deactivate", label: "Deactivate source", type: "boolean" },
470
+ { key: "index", label: "Position (0 = first)", type: "number", min: 0 }
471
+ ],
472
+ diagramFields: [{ key: "autonumber", label: "Number messages", type: "boolean" }],
473
+ newNode: () => ({ label: "New participant" })
474
+ };
475
+
476
+ // src/diagram/families/gitgraph.ts
477
+ function nextCommitId(graph) {
478
+ const taken = /* @__PURE__ */ new Set([...graph.nodes.map((n) => n.id), ...graph.groups.map((g) => g.id)]);
479
+ let i = graph.nodes.length + 1;
480
+ while (taken.has(`commit${i}`)) i++;
481
+ return `commit${i}`;
482
+ }
483
+ var gitGraphUI = {
484
+ family: "gitGraph",
485
+ title: "Git graph",
486
+ shapes: [{ value: "commit", label: "Commit" }],
487
+ edgeKinds: [
488
+ {
489
+ value: "parent",
490
+ label: "Parent",
491
+ arrowStart: "none",
492
+ arrowEnd: "arrow_point",
493
+ pattern: "solid"
494
+ }
495
+ ],
496
+ patterns: [{ value: "solid", label: "Solid" }],
497
+ arrowHeads: [{ value: "arrow_point", label: "Arrow" }],
498
+ groups: { supported: true, label: "Branch" },
499
+ labels: true,
500
+ nodeNoun: "Commit",
501
+ edgeNoun: "Parent link",
502
+ nextId: nextCommitId,
503
+ canDetach: false,
504
+ styling: false,
505
+ connectable: true,
506
+ directions: true,
507
+ groupDirections: false,
508
+ arrange: false,
509
+ preview: false,
510
+ nodeFields: [
511
+ { key: "tag", label: "Tag", type: "text" },
512
+ {
513
+ key: "type",
514
+ label: "Type",
515
+ type: "select",
516
+ options: [
517
+ { value: "NORMAL", label: "Normal" },
518
+ { value: "REVERSE", label: "Reverse" },
519
+ { value: "HIGHLIGHT", label: "Highlight" }
520
+ ]
521
+ },
522
+ { key: "msg", label: "Message", type: "text" }
523
+ ],
524
+ newNode: () => ({ label: "New commit" })
525
+ };
526
+
527
+ // src/diagram/families/gantt.ts
528
+ function nextTaskId(graph) {
529
+ const taken = /* @__PURE__ */ new Set([...graph.nodes.map((n) => n.id), ...graph.groups.map((g) => g.id)]);
530
+ let i = graph.nodes.length + 1;
531
+ while (taken.has(`task${i}`)) i++;
532
+ return `task${i}`;
533
+ }
534
+ function newTaskStart(graph) {
535
+ const format = typeof graph.data?.dateFormat === "string" ? graph.data.dateFormat : void 0;
536
+ const ends = graph.nodes.map((n) => n.data?.endTime).filter((t) => typeof t === "number" && Number.isFinite(t));
537
+ if (ends.length) return formatGanttDate(Math.max(...ends), format);
538
+ const starts = graph.nodes.map((n) => n.data?.startTime).filter((t) => typeof t === "number" && Number.isFinite(t));
539
+ if (starts.length) return formatGanttDate(Math.min(...starts), format);
540
+ return "2026-01-01";
541
+ }
542
+ var ganttUI = {
543
+ family: "gantt",
544
+ title: "Gantt chart",
545
+ shapes: [
546
+ { value: "task", label: "Task" },
547
+ { value: "milestone", label: "Milestone" }
548
+ ],
549
+ edgeKinds: [
550
+ {
551
+ value: "depends",
552
+ label: "Depends on",
553
+ arrowStart: "none",
554
+ arrowEnd: "arrow_point",
555
+ pattern: "solid"
556
+ }
557
+ ],
558
+ patterns: [],
559
+ arrowHeads: [],
560
+ groups: { supported: true, label: "Section" },
561
+ labels: true,
562
+ nodeNoun: "Task",
563
+ edgeNoun: "Dependency",
564
+ nextId: nextTaskId,
565
+ canDetach: true,
566
+ styling: false,
567
+ // Connecting A → B writes `after A` into B's start.
568
+ connectable: true,
569
+ directions: false,
570
+ arrange: false,
571
+ preview: false,
572
+ nodeFields: [
573
+ { key: "start", label: "Start", type: "text", placeholder: "2026-10-01 or after ds" },
574
+ { key: "end", label: "End or duration", type: "text", placeholder: "14d" },
575
+ {
576
+ key: "tags",
577
+ label: "Tags",
578
+ type: "tags",
579
+ hint: "done, active, crit, milestone, vert",
580
+ options: GANTT_TAGS.map((t) => ({ value: t, label: t }))
581
+ },
582
+ { key: "id", label: "Task id", type: "text" }
583
+ ],
584
+ diagramFields: [
585
+ { key: "dateFormat", label: "Date format", type: "text", placeholder: "YYYY-MM-DD" },
586
+ { key: "axisFormat", label: "Axis format", type: "text", placeholder: "%b %d" },
587
+ { key: "excludes", label: "Excludes", type: "text", placeholder: "weekends" },
588
+ { key: "tickInterval", label: "Tick interval", type: "text", placeholder: "1week" },
589
+ { key: "todayMarker", label: "Today marker", type: "text", placeholder: "off" }
590
+ ],
591
+ newNode: (graph) => ({
592
+ label: "New task",
593
+ shape: "task",
594
+ data: { start: newTaskStart(graph), end: "7d" }
595
+ })
596
+ };
597
+
598
+ // src/diagram/families/timeline.ts
599
+ function nextPeriodId(graph) {
600
+ const taken = /* @__PURE__ */ new Set([...graph.nodes.map((n) => n.id), ...graph.groups.map((g) => g.id)]);
601
+ let i = graph.nodes.length + 1;
602
+ while (taken.has(`period${i}`)) i++;
603
+ return `period${i}`;
604
+ }
605
+ var timelineUI = {
606
+ family: "timeline",
607
+ title: "Timeline",
608
+ shapes: [{ value: "rounded", label: "Period" }],
609
+ edgeKinds: [],
610
+ patterns: [],
611
+ arrowHeads: [],
612
+ groups: { supported: true, label: "Section" },
613
+ labels: true,
614
+ nodeNoun: "Period",
615
+ nextId: nextPeriodId,
616
+ canDetach: true,
617
+ styling: false,
618
+ connectable: false,
619
+ directions: false,
620
+ arrange: false,
621
+ preview: false,
622
+ nodeFields: [{ key: "events", label: "Events (one per line)", type: "lines" }],
623
+ newNode: () => ({ label: "New period", shape: "rounded", data: { events: ["Event"] } })
624
+ };
625
+
626
+ // src/diagram/families/journey.ts
627
+ function nextTaskId2(graph) {
628
+ const taken = /* @__PURE__ */ new Set([...graph.nodes.map((n) => n.id), ...graph.groups.map((g) => g.id)]);
629
+ let i = graph.nodes.length + 1;
630
+ while (taken.has(`task${i}`)) i++;
631
+ return `task${i}`;
632
+ }
633
+ var journeyUI = {
634
+ family: "journey",
635
+ title: "User journey",
636
+ shapes: [{ value: "rect", label: "Task" }],
637
+ edgeKinds: [],
638
+ patterns: [],
639
+ arrowHeads: [],
640
+ groups: { supported: true, label: "Section" },
641
+ labels: true,
642
+ nodeNoun: "Task",
643
+ nextId: nextTaskId2,
644
+ canDetach: true,
645
+ styling: false,
646
+ connectable: false,
647
+ directions: false,
648
+ arrange: false,
649
+ preview: false,
650
+ nodeFields: [
651
+ { key: "score", label: "Score", type: "number", min: 1, max: 5, step: 1 },
652
+ { key: "actors", label: "Actors", type: "tags" }
653
+ ],
654
+ newNode: () => ({ label: "New task", shape: "rect", data: { score: 3, actors: [] } })
655
+ };
656
+
657
+ // src/diagram/families/xychart.ts
658
+ var xyChartUI = {
659
+ family: "xychart",
660
+ title: "XY chart",
661
+ shapes: [
662
+ { value: "bar", label: "Bar" },
663
+ { value: "line", label: "Line" }
664
+ ],
665
+ edgeKinds: [],
666
+ patterns: [],
667
+ arrowHeads: [],
668
+ groups: { supported: false, label: "Group" },
669
+ labels: true,
670
+ nodeNoun: "Series",
671
+ nextId: (g) => `series${g.nodes.length + 1}`,
672
+ canDetach: false,
673
+ styling: false,
674
+ connectable: false,
675
+ directions: false,
676
+ arrange: false,
677
+ preview: false,
678
+ nodeFields: [
679
+ { key: "values", label: "Values", type: "numbers", hint: "One per x-axis category" }
680
+ ],
681
+ diagramFields: [
682
+ { key: "categories", label: "X-axis categories", type: "lines", placeholder: "One per line" },
683
+ { key: "xTitle", label: "X-axis title", type: "text" },
684
+ { key: "yTitle", label: "Y-axis title", type: "text" },
685
+ { key: "yMin", label: "Y-axis min", type: "number" },
686
+ { key: "yMax", label: "Y-axis max", type: "number" },
687
+ { key: "horizontal", label: "Horizontal", type: "boolean" }
688
+ ],
689
+ newNode: () => ({ label: "New series", shape: "bar" })
690
+ };
691
+
692
+ // src/diagram/families/radar.ts
693
+ var radarUI = {
694
+ family: "radar",
695
+ title: "Radar chart",
696
+ shapes: [{ value: "curve", label: "Curve" }],
697
+ edgeKinds: [],
698
+ patterns: [],
699
+ arrowHeads: [],
700
+ groups: { supported: false, label: "Group" },
701
+ labels: true,
702
+ nodeNoun: "Curve",
703
+ nextId: (g) => {
704
+ const taken = new Set(g.nodes.map((n) => n.id));
705
+ let i = g.nodes.length + 1;
706
+ while (taken.has(`curve${i}`)) i++;
707
+ return `curve${i}`;
708
+ },
709
+ canDetach: false,
710
+ styling: false,
711
+ connectable: false,
712
+ directions: false,
713
+ arrange: false,
714
+ preview: false,
715
+ nodeFields: [{ key: "values", label: "Values", type: "numbers", hint: "One per axis" }],
716
+ diagramFields: [
717
+ { key: "axes", label: "Axes", type: "lines", placeholder: "One per line" },
718
+ { key: "max", label: "Max", type: "number" },
719
+ { key: "min", label: "Min", type: "number" },
720
+ { key: "ticks", label: "Ticks", type: "number", min: 1 },
721
+ {
722
+ key: "graticule",
723
+ label: "Grid",
724
+ type: "select",
725
+ options: [
726
+ { value: "circle", label: "Circles" },
727
+ { value: "polygon", label: "Polygons" }
728
+ ]
729
+ },
730
+ { key: "showLegend", label: "Show legend", type: "boolean" }
731
+ ],
732
+ newNode: () => ({ label: "New curve" })
733
+ };
734
+
735
+ // src/diagram/families/fields.ts
736
+ function describeFields(fields) {
737
+ return (fields ?? []).map((f) => ({
738
+ key: f.key,
739
+ label: f.label,
740
+ type: f.type,
741
+ ...f.options ? { options: f.options.map((o) => o.value) } : {},
742
+ ...f.min !== void 0 ? { min: f.min } : {},
743
+ ...f.max !== void 0 ? { max: f.max } : {},
744
+ ...f.hint ? { hint: f.hint } : {},
745
+ ...f.shapes ? { shapes: f.shapes } : {}
746
+ }));
747
+ }
748
+ function pickFieldData(fields, data) {
749
+ const out = {};
750
+ for (const f of fields ?? []) {
751
+ const value = data?.[f.key];
752
+ if (value !== void 0 && value !== null && !(Array.isArray(value) && !value.length)) out[f.key] = value;
753
+ }
754
+ return out;
755
+ }
756
+ var list = (items) => items.map((s) => `"${s}"`).join(", ");
757
+ function checkFieldData(fields, data, what, shape) {
758
+ const all = fields ?? [];
759
+ const usable = all.filter((f) => !f.shapes || shape === void 0 || f.shapes.includes(shape));
760
+ if (!all.length) throw new Error(`${what} has no data fields to set.`);
761
+ const keys = Object.keys(data);
762
+ if (!keys.length) throw new Error(`Give at least one field to set; ${what} has ${list(usable.map((f) => f.key))}.`);
763
+ const out = {};
764
+ for (const key of keys) {
765
+ const field = all.find((f) => f.key === key);
766
+ if (!field) throw new Error(`Unknown field "${key}" for ${what}; use one of ${list(usable.map((f) => f.key))}.`);
767
+ if (!usable.includes(field))
768
+ throw new Error(`Field "${key}" only applies to ${list(field.shapes)} nodes, not "${shape}".`);
769
+ const value = data[key];
770
+ if (value === null || value === "") {
771
+ out[key] = void 0;
772
+ continue;
773
+ }
774
+ const bad = (expected) => new Error(`Field "${key}" (${field.label}) takes ${expected}; got ${JSON.stringify(value)}.`);
775
+ switch (field.type) {
776
+ case "number": {
777
+ if (typeof value !== "number" || !Number.isFinite(value)) throw bad("a number");
778
+ if (field.min !== void 0 && value < field.min) throw bad(`a number of at least ${field.min}`);
779
+ if (field.max !== void 0 && value > field.max) throw bad(`a number of at most ${field.max}`);
780
+ break;
781
+ }
782
+ case "numbers":
783
+ if (!Array.isArray(value) || !value.every((n) => typeof n === "number" && Number.isFinite(n))) throw bad("an array of numbers");
784
+ break;
785
+ case "lines":
786
+ case "tags":
787
+ if (!Array.isArray(value) || !value.every((s) => typeof s === "string")) throw bad("an array of strings");
788
+ break;
789
+ case "boolean":
790
+ if (typeof value !== "boolean") throw bad("true or false");
791
+ break;
792
+ case "select": {
793
+ const options = (field.options ?? []).map((o) => o.value);
794
+ if (typeof value !== "string" || options.length && !options.includes(value)) throw bad(`one of ${list(options)}`);
795
+ break;
796
+ }
797
+ default:
798
+ if (typeof value !== "string") throw bad("a string");
799
+ }
800
+ out[key] = value;
801
+ }
802
+ return out;
803
+ }
804
+
805
+ // src/diagram/families/index.ts
806
+ function counterId(prefix, graph) {
807
+ const taken = /* @__PURE__ */ new Set([...graph.nodes.map((n) => n.id), ...graph.groups.map((g) => g.id)]);
808
+ let i = graph.nodes.length + 1;
809
+ while (taken.has(`${prefix}${i}`)) i++;
810
+ return `${prefix}${i}`;
811
+ }
812
+ var FLOW_HEADS = [
813
+ { value: "none", label: "None" },
814
+ { value: "arrow_point", label: "Arrow" },
815
+ { value: "arrow_circle", label: "Circle" },
816
+ { value: "arrow_cross", label: "Cross" }
817
+ ];
818
+ var IMAGE_FIELDS = [
819
+ {
820
+ key: "img",
821
+ label: "Image URL",
822
+ type: "text",
823
+ placeholder: "https://\u2026/picture.png",
824
+ shapes: ["image"]
825
+ },
826
+ {
827
+ key: "pos",
828
+ label: "Label",
829
+ type: "select",
830
+ options: [
831
+ { value: "b", label: "Below" },
832
+ { value: "t", label: "Above" }
833
+ ],
834
+ shapes: ["image"]
835
+ },
836
+ { key: "w", label: "Width", type: "number", min: 8, step: 1, shapes: ["image"] },
837
+ { key: "h", label: "Height", type: "number", min: 8, step: 1, shapes: ["image"] },
838
+ {
839
+ key: "constraint",
840
+ label: "Keep aspect ratio",
841
+ type: "select",
842
+ options: [
843
+ { value: "on", label: "On" },
844
+ { value: "off", label: "Off" }
845
+ ],
846
+ shapes: ["image"]
847
+ }
848
+ ];
849
+ var flowchartUI = {
850
+ family: "flowchart",
851
+ nodeFields: IMAGE_FIELDS,
852
+ title: "Flowchart",
853
+ shapes: FLOWCHART_SHAPES.map((s) => ({ value: s.name, label: s.title, category: s.category })),
854
+ edgeKinds: [
855
+ {
856
+ value: "arrow",
857
+ label: "Arrow",
858
+ arrowStart: "none",
859
+ arrowEnd: "arrow_point",
860
+ pattern: "solid"
861
+ },
862
+ { value: "open", label: "Line", arrowStart: "none", arrowEnd: "none", pattern: "solid" },
863
+ {
864
+ value: "dotted",
865
+ label: "Dotted arrow",
866
+ arrowStart: "none",
867
+ arrowEnd: "arrow_point",
868
+ pattern: "dotted"
869
+ },
870
+ {
871
+ value: "thick",
872
+ label: "Thick arrow",
873
+ arrowStart: "none",
874
+ arrowEnd: "arrow_point",
875
+ pattern: "thick"
876
+ },
877
+ {
878
+ value: "bidir",
879
+ label: "Bidirectional",
880
+ arrowStart: "arrow_point",
881
+ arrowEnd: "arrow_point",
882
+ pattern: "solid"
883
+ },
884
+ {
885
+ value: "invisible",
886
+ label: "Invisible (layout)",
887
+ arrowStart: "none",
888
+ arrowEnd: "none",
889
+ pattern: "invisible"
890
+ }
891
+ ],
892
+ patterns: [
893
+ { value: "solid", label: "Solid" },
894
+ { value: "dotted", label: "Dotted" },
895
+ { value: "thick", label: "Thick" },
896
+ { value: "invisible", label: "Invisible" }
897
+ ],
898
+ arrowHeads: FLOW_HEADS,
899
+ groups: { supported: true, label: "Subgraph" },
900
+ labels: true,
901
+ nodeNoun: "Node",
902
+ nextId: (g) => counterId("n", g),
903
+ canDetach: false
904
+ };
905
+ var stateUI = {
906
+ family: "state",
907
+ title: "State diagram",
908
+ shapes: [
909
+ { value: "rect", label: "State" },
910
+ { value: "choice", label: "Choice" },
911
+ { value: "fork", label: "Fork" },
912
+ { value: "join", label: "Join" }
913
+ ],
914
+ edgeKinds: [
915
+ {
916
+ value: "transition",
917
+ label: "Transition",
918
+ arrowStart: "none",
919
+ arrowEnd: "arrow_barb",
920
+ pattern: "solid"
921
+ }
922
+ ],
923
+ patterns: [{ value: "solid", label: "Solid" }],
924
+ arrowHeads: [{ value: "arrow_barb", label: "Arrow" }],
925
+ groups: { supported: true, label: "Composite state" },
926
+ labels: true,
927
+ nodeNoun: "State",
928
+ nextId: (g) => counterId("State", g),
929
+ canDetach: true
930
+ };
931
+ var classUI = {
932
+ family: "class",
933
+ title: "Class diagram",
934
+ shapes: [{ value: "classBox", label: "Class" }],
935
+ edgeKinds: CLASS_RELATIONS.filter((r) => !r.title.includes("reversed")).map((r) => ({
936
+ value: r.token,
937
+ label: r.title,
938
+ arrowStart: r.arrowStart,
939
+ arrowEnd: r.arrowEnd,
940
+ pattern: r.pattern
941
+ })),
942
+ patterns: [
943
+ { value: "solid", label: "Solid" },
944
+ { value: "dotted", label: "Dashed" }
945
+ ],
946
+ arrowHeads: [
947
+ { value: "none", label: "None" },
948
+ { value: "extension", label: "Inheritance" },
949
+ { value: "composition", label: "Composition" },
950
+ { value: "aggregation", label: "Aggregation" },
951
+ { value: "dependency", label: "Arrow" },
952
+ { value: "lollipop", label: "Lollipop" }
953
+ ],
954
+ groups: { supported: true, label: "Namespace" },
955
+ labels: true,
956
+ nodeNoun: "Class",
957
+ nextId: (g) => counterId("Class", g),
958
+ canDetach: true
959
+ };
960
+ var erUI = {
961
+ family: "er",
962
+ title: "Entity relationship",
963
+ shapes: [{ value: "erBox", label: "Entity" }],
964
+ edgeKinds: [
965
+ {
966
+ value: "one-many",
967
+ label: "One to many",
968
+ arrowStart: "only_one",
969
+ arrowEnd: "zero_or_more",
970
+ pattern: "solid"
971
+ },
972
+ {
973
+ value: "one-one",
974
+ label: "One to one",
975
+ arrowStart: "only_one",
976
+ arrowEnd: "only_one",
977
+ pattern: "solid"
978
+ },
979
+ {
980
+ value: "many-many",
981
+ label: "Many to many",
982
+ arrowStart: "zero_or_more",
983
+ arrowEnd: "zero_or_more",
984
+ pattern: "solid"
985
+ },
986
+ {
987
+ value: "one-many-ni",
988
+ label: "One to many (non-identifying)",
989
+ arrowStart: "only_one",
990
+ arrowEnd: "zero_or_more",
991
+ pattern: "dotted"
992
+ }
993
+ ],
994
+ patterns: [
995
+ { value: "solid", label: "Identifying" },
996
+ { value: "dotted", label: "Non-identifying" }
997
+ ],
998
+ arrowHeads: Array.from(
999
+ new Map(ER_CARDINALITIES.map((c) => [c.head, { value: c.head, label: c.title }])).values()
1000
+ ),
1001
+ groups: { supported: false, label: "Group" },
1002
+ labels: true,
1003
+ nodeNoun: "Entity",
1004
+ nextId: (g) => counterId("ENTITY_", g),
1005
+ canDetach: true
1006
+ };
1007
+ var FAMILY_UI = {
1008
+ flowchart: flowchartUI,
1009
+ state: stateUI,
1010
+ class: classUI,
1011
+ er: erUI,
1012
+ pie: pieUI,
1013
+ mindmap: mindmapUI,
1014
+ quadrant: quadrantUI,
1015
+ c4: c4UI,
1016
+ architecture: architectureUI,
1017
+ sequence: sequenceUI,
1018
+ gitGraph: gitGraphUI,
1019
+ gantt: ganttUI,
1020
+ timeline: timelineUI,
1021
+ journey: journeyUI,
1022
+ xychart: xyChartUI,
1023
+ radar: radarUI
1024
+ };
1025
+ function familyUI(family) {
1026
+ return FAMILY_UI[family] ?? null;
1027
+ }
1028
+ var FAMILY_TITLES = {
1029
+ flowchart: "Flowchart",
1030
+ state: "State diagram",
1031
+ class: "Class diagram",
1032
+ er: "Entity relationship",
1033
+ requirement: "Requirement diagram",
1034
+ mindmap: "Mind map",
1035
+ sequence: "Sequence diagram",
1036
+ gantt: "Gantt chart",
1037
+ pie: "Pie chart",
1038
+ journey: "User journey",
1039
+ timeline: "Timeline",
1040
+ gitGraph: "Git graph",
1041
+ c4: "C4 diagram",
1042
+ quadrant: "Quadrant chart",
1043
+ sankey: "Sankey diagram",
1044
+ xychart: "XY chart",
1045
+ block: "Block diagram",
1046
+ architecture: "Architecture diagram",
1047
+ packet: "Packet diagram",
1048
+ kanban: "Kanban board",
1049
+ radar: "Radar chart",
1050
+ treemap: "Treemap",
1051
+ info: "Info",
1052
+ unknown: "Unknown diagram"
1053
+ };
1054
+ var FAMILY_TEMPLATES = {
1055
+ flowchart: "flowchart TD\n A[Start] --> B{Decision}\n B -->|Yes| C[Do it]\n B -->|No| D[Skip]\n C --> E[End]\n D --> E\n",
1056
+ state: "stateDiagram-v2\n [*] --> Idle\n Idle --> Active : start\n Active --> Idle : stop\n Active --> [*] : finish\n",
1057
+ class: 'classDiagram\n class Account {\n +String id\n +deposit(amount)\n }\n class Customer\n Customer "1" --> "*" Account : owns\n',
1058
+ er: "erDiagram\n CUSTOMER ||--o{ ORDER : places\n ORDER ||--|{ LINE_ITEM : contains\n CUSTOMER {\n string name PK\n string email\n }\n",
1059
+ sequence: "sequenceDiagram\n participant U as User\n participant S as Service\n U->>S: Request\n S-->>U: Response\n",
1060
+ pie: 'pie showData\n title Share by segment\n "Segment A" : 40\n "Segment B" : 35\n "Segment C" : 25\n',
1061
+ mindmap: "mindmap\n root((Central idea))\n Topic A\n Detail\n Topic B\n Topic C\n",
1062
+ timeline: "timeline\n title Milestones\n 2024 : First release\n 2025 : Second release\n : Expansion\n 2026 : Next chapter\n",
1063
+ journey: "journey\n title Customer journey\n section Discover\n Find the product: 3: Customer\n section Buy\n Check out: 4: Customer\n Confirm order: 5: Customer, Support\n",
1064
+ gantt: "gantt\n title Plan\n dateFormat YYYY-MM-DD\n section Phase 1\n Research :a1, 2026-01-05, 10d\n Design :a2, after a1, 7d\n section Phase 2\n Build :a3, after a2, 14d\n",
1065
+ gitGraph: 'gitGraph\n commit id: "init"\n branch develop\n checkout develop\n commit id: "feature"\n checkout main\n merge develop tag: "v1.0"\n',
1066
+ c4: 'C4Context\n title System context\n Person(user, "User", "Uses the system")\n System(sys, "System", "Does the work")\n System_Ext(ext, "External service", "Provides data")\n Rel(user, sys, "Uses")\n Rel(sys, ext, "Calls")\n',
1067
+ architecture: "architecture-beta\n group app(cloud)[Application]\n service web(server)[Web] in app\n service db(database)[Database] in app\n service edge(internet)[Edge]\n edge:R --> L:web\n web:B --> T:db\n",
1068
+ quadrant: "quadrantChart\n title Prioritisation\n x-axis Low effort --> High effort\n y-axis Low value --> High value\n quadrant-1 Plan\n quadrant-2 Do first\n quadrant-3 Drop\n quadrant-4 Fill-ins\n Idea A: [0.3, 0.8]\n Idea B: [0.7, 0.6]\n Idea C: [0.2, 0.3]\n",
1069
+ xychart: 'xychart-beta\n title "Monthly sales"\n x-axis [Jan, Feb, Mar, Apr]\n y-axis "Units" 0 --> 100\n bar [42, 58, 71, 64]\n line "Target" [50, 55, 60, 65]\n',
1070
+ radar: 'radar-beta\n title Option comparison\n axis cost["Cost"], speed["Speed"], quality["Quality"], risk["Risk"]\n curve a["Option A"]{80, 60, 90, 40}\n curve b["Option B"]{50, 90, 60, 70}\n max 100\n'
1071
+ };
1072
+ var FAMILY_BLANKS = {
1073
+ flowchart: "flowchart TD\n",
1074
+ state: "stateDiagram-v2\n",
1075
+ class: "classDiagram\n direction TB\n",
1076
+ er: "erDiagram\n",
1077
+ sequence: "sequenceDiagram\n",
1078
+ pie: "pie\n",
1079
+ mindmap: "mindmap\n",
1080
+ timeline: "timeline\n",
1081
+ journey: "journey\n",
1082
+ gantt: "gantt\n dateFormat YYYY-MM-DD\n",
1083
+ gitGraph: "gitGraph\n",
1084
+ c4: "C4Context\n title System context\n",
1085
+ architecture: "architecture-beta\n",
1086
+ quadrant: "quadrantChart\n",
1087
+ xychart: "xychart-beta\n",
1088
+ radar: "radar-beta\n"
1089
+ };
1090
+ var FAMILY_DESCRIPTIONS = {
1091
+ flowchart: "Steps, decisions and the paths between them.",
1092
+ state: "The states something moves through and what triggers each change.",
1093
+ class: "Types with their fields and methods, and how they relate.",
1094
+ er: "Entities, their attributes and the relationships between them.",
1095
+ sequence: "Messages exchanged between participants over time.",
1096
+ pie: "Parts of a whole as slices.",
1097
+ mindmap: "Ideas branching out from a central topic.",
1098
+ timeline: "Events grouped by period, in order.",
1099
+ journey: "A user's tasks, section by section, scored by how they feel.",
1100
+ gantt: "Tasks on a calendar with durations and dependencies.",
1101
+ gitGraph: "Branches, commits and merges of a repository.",
1102
+ c4: "People and software systems, and how they interact.",
1103
+ architecture: "Services and infrastructure grouped by where they run.",
1104
+ quadrant: "Items placed on two axes in four quadrants.",
1105
+ xychart: "Bars and lines over categories or a numeric axis.",
1106
+ radar: "Scores across several axes, one curve per item compared."
1107
+ };
1108
+
1109
+ // src/diagram/sankey/index.ts
1110
+ function parseSankey(source) {
1111
+ const split = splitSource(source);
1112
+ if (!/^\s*sankey(?:-beta)?\b/i.test(split.header)) {
1113
+ return { error: "Not a sankey diagram: the first line should be `sankey-beta`." };
1114
+ }
1115
+ const firstLine = split.headerIndex + 2;
1116
+ const kept = [];
1117
+ split.bodyLines.forEach((text, i) => {
1118
+ if (/^\s*%%/.test(text)) return;
1119
+ kept.push({ text: text.trim(), line: firstLine + i });
1120
+ });
1121
+ const records = readRecords(kept);
1122
+ if ("error" in records) return records;
1123
+ const nodes = [];
1124
+ const seen = /* @__PURE__ */ new Set();
1125
+ const add = (name) => {
1126
+ if (!seen.has(name)) {
1127
+ seen.add(name);
1128
+ nodes.push(name);
1129
+ }
1130
+ };
1131
+ const links = [];
1132
+ for (const { fields, line } of records) {
1133
+ if (fields.length !== 3) {
1134
+ return {
1135
+ error: `Expected three fields (source,target,value), found ${fields.length}.`,
1136
+ line
1137
+ };
1138
+ }
1139
+ const [source2, target, raw] = fields;
1140
+ const value = Number.parseFloat(raw);
1141
+ if (!Number.isFinite(value)) {
1142
+ return { error: `"${raw}" is not a number.`, line };
1143
+ }
1144
+ add(source2);
1145
+ add(target);
1146
+ links.push({ source: source2, target, value });
1147
+ }
1148
+ if (!links.length) return { error: "No links: add lines like `A,B,10`." };
1149
+ return { data: { nodes, links } };
1150
+ }
1151
+ function readRecords(lines) {
1152
+ const records = [];
1153
+ let i = 0;
1154
+ while (i < lines.length) {
1155
+ const start = lines[i];
1156
+ if (start.text === "") {
1157
+ i++;
1158
+ continue;
1159
+ }
1160
+ const fields = [];
1161
+ let text = start.text;
1162
+ let pos = 0;
1163
+ let field = "";
1164
+ let quoted = false;
1165
+ for (; ; ) {
1166
+ if (quoted) {
1167
+ const close = text.indexOf('"', pos);
1168
+ if (close < 0) {
1169
+ field += text.slice(pos);
1170
+ i++;
1171
+ if (i >= lines.length)
1172
+ return { error: "A quoted field is never closed.", line: start.line };
1173
+ field += "\n";
1174
+ text = lines[i].text;
1175
+ pos = 0;
1176
+ continue;
1177
+ }
1178
+ field += text.slice(pos, close);
1179
+ if (text[close + 1] === '"') {
1180
+ field += '"';
1181
+ pos = close + 2;
1182
+ continue;
1183
+ }
1184
+ quoted = false;
1185
+ pos = close + 1;
1186
+ const rest = /^[ \t]*/.exec(text.slice(pos))[0].length;
1187
+ pos += rest;
1188
+ if (pos < text.length && text[pos] !== ",") {
1189
+ return { error: "Unexpected text after a quoted field.", line: lines[i].line };
1190
+ }
1191
+ continue;
1192
+ }
1193
+ if (pos >= text.length) {
1194
+ fields.push(field.trim());
1195
+ break;
1196
+ }
1197
+ const ch = text[pos];
1198
+ if (ch === ",") {
1199
+ fields.push(field.trim());
1200
+ field = "";
1201
+ pos++;
1202
+ } else if (ch === '"' && field.trim() === "") {
1203
+ quoted = true;
1204
+ field = "";
1205
+ pos++;
1206
+ } else if (ch === '"') {
1207
+ return { error: "A quote inside an unquoted field.", line: lines[i].line };
1208
+ } else {
1209
+ field += ch;
1210
+ pos++;
1211
+ }
1212
+ }
1213
+ records.push({ fields, line: start.line });
1214
+ i++;
1215
+ }
1216
+ return records;
1217
+ }
1218
+
1219
+ // src/diagram/treemap/index.ts
1220
+ var NAME = String.raw`(?:"([^"]*)"|'([^']*)')`;
1221
+ var CLASS = String.raw`(?:\s*:::\s*([A-Za-z_]\w*))?`;
1222
+ var SECTION_RE = new RegExp(String.raw`^${NAME}${CLASS}$`);
1223
+ var LEAF_RE = new RegExp(String.raw`^${NAME}\s*[:,]\s*([0-9_.,]+)${CLASS}$`);
1224
+ function parseTreemap(source) {
1225
+ const split = splitSource(source);
1226
+ if (!/^\s*treemap(?:-beta)?\b/i.test(split.header)) {
1227
+ return { error: "Not a treemap: the first line should be `treemap-beta`." };
1228
+ }
1229
+ const data = { items: [] };
1230
+ const stack = [];
1231
+ const firstLine = split.headerIndex + 2;
1232
+ const lines = split.bodyLines;
1233
+ for (let i = 0; i < lines.length; i++) {
1234
+ const raw = lines[i];
1235
+ const line = firstLine + i;
1236
+ const indent = /^[ \t]*/.exec(raw)[0].length;
1237
+ const text = stripComment(raw).trim();
1238
+ if (!text) continue;
1239
+ const accBlock = /^accDescr\s*\{(.*)$/.exec(text);
1240
+ if (accBlock) {
1241
+ let body = accBlock[1];
1242
+ while (!body.includes("}") && i + 1 < lines.length) body += `
1243
+ ${lines[++i]}`;
1244
+ if (!body.includes("}")) return { error: "`accDescr {` is never closed.", line };
1245
+ data.accDescr = body.slice(0, body.indexOf("}")).trim();
1246
+ continue;
1247
+ }
1248
+ const acc = /^(accTitle|accDescr)\s*:(.*)$/.exec(text);
1249
+ if (acc) {
1250
+ data[acc[1]] = acc[2].trim();
1251
+ continue;
1252
+ }
1253
+ const title = /^title(?:[ \t]+(.*))?$/.exec(text);
1254
+ if (title) {
1255
+ data.title = (title[1] ?? "").trim() || void 0;
1256
+ continue;
1257
+ }
1258
+ if (/^classDef\s/.test(text)) continue;
1259
+ let item;
1260
+ const leaf = LEAF_RE.exec(text);
1261
+ const section = leaf ? null : SECTION_RE.exec(text);
1262
+ if (leaf) {
1263
+ const value = Number.parseFloat(leaf[3].replace(/,/g, ""));
1264
+ if (!Number.isFinite(value)) return { error: `"${leaf[3]}" is not a number.`, line };
1265
+ item = { name: leaf[1] ?? leaf[2], value };
1266
+ if (leaf[4]) item.className = leaf[4];
1267
+ } else if (section) {
1268
+ item = { name: section[1] ?? section[2], children: [] };
1269
+ if (section[3]) item.className = section[3];
1270
+ } else {
1271
+ return {
1272
+ error: /^["']/.test(text) ? 'Expected `"Name"` for a section or `"Name": value` for a leaf.' : 'Names must be in quotes, e.g. `"Sales": 120`.',
1273
+ line
1274
+ };
1275
+ }
1276
+ while (stack.length && stack[stack.length - 1].indent >= indent) stack.pop();
1277
+ const parent = stack[stack.length - 1]?.item;
1278
+ if (parent) parent.children.push(item);
1279
+ else data.items.push(item);
1280
+ if (item.children) stack.push({ item, indent });
1281
+ }
1282
+ if (!data.items.length) return { error: 'No items: add lines like `"Sales": 120`.' };
1283
+ return { data };
1284
+ }
1285
+ function stripComment(line) {
1286
+ let quote3 = null;
1287
+ for (let i = 0; i < line.length; i++) {
1288
+ const ch = line[i];
1289
+ if (quote3) {
1290
+ if (ch === quote3) quote3 = null;
1291
+ } else if (ch === '"' || ch === "'") {
1292
+ quote3 = ch;
1293
+ } else if (ch === "%" && line[i + 1] === "%") {
1294
+ return line.slice(0, i);
1295
+ }
1296
+ }
1297
+ return line;
1298
+ }
1299
+ function treemapValue(item) {
1300
+ if (!item.children) return item.value ?? 0;
1301
+ return item.children.reduce((sum, child) => sum + treemapValue(child), 0);
1302
+ }
1303
+
117
1304
  // src/diagram/controller.ts
118
- var EDITABLE_DIAGRAM_FAMILIES = ["flowchart", "state", "class", "er"];
1305
+ var EDITABLE_DIAGRAM_FAMILIES = [
1306
+ "flowchart",
1307
+ "state",
1308
+ "class",
1309
+ "er",
1310
+ "pie",
1311
+ "mindmap",
1312
+ "quadrant",
1313
+ "c4",
1314
+ "architecture",
1315
+ "sequence",
1316
+ "gitGraph",
1317
+ "gantt",
1318
+ "timeline",
1319
+ "journey",
1320
+ "xychart",
1321
+ "radar"
1322
+ ];
119
1323
  function diagramShapes(family) {
120
1324
  if (family === "flowchart") return FLOWCHART_SHAPES.map((shape) => shape.name);
121
1325
  if (family === "state") return STATE_SHAPES.map((shape) => shape.name);
122
- return [];
1326
+ if (family === "class" || family === "er") return [];
1327
+ const shapes = familyUI(family)?.shapes ?? [];
1328
+ return shapes.length > 1 ? shapes.map((shape) => shape.value) : [];
123
1329
  }
124
1330
  function diagramSupportsGroups(family) {
125
- return family === "flowchart" || family === "state" || family === "class";
1331
+ return familyUI(family)?.groups.supported ?? false;
126
1332
  }
127
- var quote = (ids) => [...ids].map((id) => `"${id}"`).join(", ");
1333
+ function diagramSupportsDirection(family) {
1334
+ return familyUI(family)?.directions !== false;
1335
+ }
1336
+ var quote2 = (ids) => [...ids].map((id) => `"${id}"`).join(", ");
128
1337
  function validateDiagramEdit(doc, op) {
129
1338
  const { graph, family } = doc;
130
1339
  if (op.type === "replaceSource") return null;
@@ -133,15 +1342,15 @@ function validateDiagramEdit(doc, op) {
133
1342
  const nodes = new Set(graph.nodes.map((n) => n.id));
134
1343
  const groups = new Set(graph.groups.map((g) => g.id));
135
1344
  const edges = new Set(graph.edges.map((e) => e.id));
136
- const anyIds = () => nodes.size ? `existing node ids are ${quote([...nodes].slice(0, 20))}` : "the diagram has no nodes yet";
1345
+ const anyIds = () => nodes.size ? `existing node ids are ${quote2([...nodes].slice(0, 20))}` : "the diagram has no nodes yet";
137
1346
  const node = (id, allowGroup = false) => nodes.has(id) || allowGroup && groups.has(id) ? null : `There is no node "${id}"; ${anyIds()}.`;
138
- const group = (id) => id === void 0 || groups.has(id) ? null : `There is no group "${id}"; ${groups.size ? `existing groups are ${quote(groups)}` : "the diagram has no groups"}.`;
139
- const edge = (id) => edges.has(id) ? null : `There is no edge "${id}"; ${edges.size ? `existing edge ids are ${quote([...edges].slice(0, 20))}` : "the diagram has no edges yet"}.`;
1347
+ const group = (id) => id === void 0 || groups.has(id) ? null : `There is no group "${id}"; ${groups.size ? `existing groups are ${quote2(groups)}` : "the diagram has no groups"}.`;
1348
+ const edge = (id) => edges.has(id) ? null : `There is no edge "${id}"; ${edges.size ? `existing edge ids are ${quote2([...edges].slice(0, 20))}` : "the diagram has no edges yet"}.`;
140
1349
  const shape = (name) => {
141
1350
  if (name === void 0) return null;
142
1351
  const shapes = diagramShapes(family);
143
1352
  if (!shapes.length) return `Nodes of a ${family} diagram have no shapes to choose from.`;
144
- return shapes.includes(name) ? null : `Unknown shape "${name}"; use one of ${quote(shapes)}.`;
1353
+ return shapes.includes(name) ? null : `Unknown shape "${name}"; use one of ${quote2(shapes)}.`;
145
1354
  };
146
1355
  const free = (id) => !/^[A-Za-z0-9_][\w.-]*$/.test(id) ? `Id "${id}" is not a valid Mermaid id; use letters, digits, "_", "-" or ".".` : nodes.has(id) || groups.has(id) ? `Id "${id}" is already used; choose another.` : null;
147
1356
  const first = (...problems) => problems.find((p) => p) ?? null;
@@ -183,7 +1392,8 @@ function validateDiagramEdit(doc, op) {
183
1392
  case "setNodeParent":
184
1393
  return first(...op.ids.map((id) => node(id, true)), group(op.parentId));
185
1394
  case "setDirection":
186
- return DIRECTIONS.includes(op.direction) ? null : `Unknown direction "${op.direction}"; use one of ${quote(DIRECTIONS)}.`;
1395
+ if (!diagramSupportsDirection(family)) return `${family} diagrams have no direction.`;
1396
+ return DIRECTIONS.includes(op.direction) ? null : `Unknown direction "${op.direction}"; use one of ${quote2(DIRECTIONS)}.`;
187
1397
  default:
188
1398
  return null;
189
1399
  }
@@ -309,10 +1519,10 @@ var DiagramController = class {
309
1519
  * document as it stands after the edits before it, and nothing changes when one fails.
310
1520
  */
311
1521
  apply(ops, label = "Edit diagram") {
312
- const list = Array.isArray(ops) ? ops : [ops];
1522
+ const list2 = Array.isArray(ops) ? ops : [ops];
313
1523
  if (this.readOnly) return this.reject("The diagram is read-only.");
314
1524
  let doc = this.doc;
315
- for (const op of list) {
1525
+ for (const op of list2) {
316
1526
  const problem = validateDiagramEdit(doc, op);
317
1527
  if (problem) return this.reject(problem);
318
1528
  doc = applyEdits(doc, [op]);
@@ -382,6 +1592,7 @@ var ID = { type: "string", minLength: 1, description: 'A node id from get_diagra
382
1592
  var IDS = (what) => ({ type: "array", items: { type: "string", minLength: 1 }, minItems: 1, description: what });
383
1593
  var EDGE_ID = { type: "string", minLength: 1, description: 'An edge id from get_diagram (e.g. "L_A_B_0").' };
384
1594
  var LABEL = (what) => ({ type: "string", description: what });
1595
+ var FIELD_VALUE = { type: ["string", "number", "boolean", "array", "null"] };
385
1596
  var object = (properties, required = []) => ({
386
1597
  type: "object",
387
1598
  properties,
@@ -390,6 +1601,8 @@ var object = (properties, required = []) => ({
390
1601
  });
391
1602
  function describeDiagram(doc) {
392
1603
  const { graph } = doc;
1604
+ const ui = familyUI(doc.family);
1605
+ const settings = pickFieldData(ui?.diagramFields, graph.data);
393
1606
  return {
394
1607
  family: doc.family,
395
1608
  editable: doc.tier === "editable",
@@ -402,7 +1615,8 @@ function describeDiagram(doc) {
402
1615
  ...n.parentId ? { parentId: n.parentId } : {},
403
1616
  ...n.classes.length ? { classes: n.classes } : {},
404
1617
  ...n.styles.length ? { styles: n.styles } : {},
405
- ...n.data?.synthetic ? { synthetic: true } : {}
1618
+ ...n.data?.synthetic ? { synthetic: true } : {},
1619
+ ...ui?.nodeFields && Object.keys(pickFieldData(ui.nodeFields, n.data)).length ? { data: pickFieldData(ui.nodeFields, n.data) } : {}
406
1620
  })),
407
1621
  edges: graph.edges.map((e) => ({
408
1622
  id: e.id,
@@ -410,7 +1624,8 @@ function describeDiagram(doc) {
410
1624
  target: e.target,
411
1625
  ...e.label ? { label: e.label } : {},
412
1626
  pattern: e.pattern,
413
- arrowEnd: e.arrowEnd
1627
+ arrowEnd: e.arrowEnd,
1628
+ ...ui?.edgeFields && Object.keys(pickFieldData(ui.edgeFields, e.data)).length ? { data: pickFieldData(ui.edgeFields, e.data) } : {}
414
1629
  })),
415
1630
  groups: graph.groups.map((g) => ({
416
1631
  id: g.id,
@@ -419,6 +1634,14 @@ function describeDiagram(doc) {
419
1634
  ...g.direction ? { direction: g.direction } : {}
420
1635
  })),
421
1636
  shapes: diagramShapes(doc.family),
1637
+ ...Object.keys(settings).length ? { settings } : {},
1638
+ ...ui && (ui.nodeFields?.length || ui.edgeFields?.length || ui.diagramFields?.length) ? {
1639
+ fields: {
1640
+ ...ui.nodeFields?.length ? { node: describeFields(ui.nodeFields) } : {},
1641
+ ...ui.edgeFields?.length ? { edge: describeFields(ui.edgeFields) } : {},
1642
+ ...ui.diagramFields?.length ? { diagram: describeFields(ui.diagramFields) } : {}
1643
+ }
1644
+ } : {},
422
1645
  positions: Object.fromEntries(Object.entries(doc.meta.layout ?? {}).map(([id, [x, y]]) => [id, { x: Math.round(x), y: Math.round(y) }])),
423
1646
  ...doc.diagnostics.length ? { diagnostics: doc.diagnostics.map((d) => ({ severity: d.severity, message: d.message, ...d.line ? { line: d.line } : {} })) } : {}
424
1647
  };
@@ -456,7 +1679,7 @@ function createDiagramToolProvider(controller, options = {}) {
456
1679
  const getDiagram = {
457
1680
  name: "get_diagram",
458
1681
  title: "Read the diagram",
459
- description: "Returns the diagram: its Mermaid family (flowchart, state, class, er; other families are text only), direction, nodes (id, label, shape, parentId), edges (id, source, target, label), groups (subgraphs / composite states), the shapes nodes can take, stored canvas positions, any parse diagnostics and the selection. Use the ids it returns with the write tools.",
1682
+ description: 'Returns the diagram: its Mermaid family (flowchart, state, class, er, pie, mindmap, quadrant, c4, architecture, sequence, gitGraph, gantt, timeline, journey, xychart, radar; sankey, block, packet, kanban and treemap are text only), direction, title, nodes (id, label, shape, parentId, data), edges (id, source, target, label, data), groups (subgraphs, composite states, sections, boxes\u2026), the shapes nodes can take, diagram settings, the data fields each family offers ("fields": node, edge and diagram field keys with their types), stored canvas positions, any parse diagnostics and the selection. Use the ids and field keys it returns with the write tools.',
460
1683
  inputSchema: object({ includeSource: { type: "boolean", description: "Also return the Mermaid text (default false)." } }),
461
1684
  annotations: { title: "Read the diagram", ...READ },
462
1685
  handler: async ({ includeSource = false }) => {
@@ -491,7 +1714,7 @@ function createDiagramToolProvider(controller, options = {}) {
491
1714
  const loadMermaid = {
492
1715
  name: "load_diagram_mermaid",
493
1716
  title: "Replace the diagram with Mermaid",
494
- description: "Replaces the whole diagram with Mermaid text (one undo step). Flowchart, state, class and ER diagrams become editable on the canvas; other families are kept as text. Returns the family, node and edge counts and any parse diagnostics. Prefer the per-operation tools for small changes: they keep the rest of the text as written.",
1717
+ description: "Replaces the whole diagram with Mermaid text (one undo step). Flowchart, state, class, ER, pie, mindmap, quadrant, C4, architecture, sequence, gitGraph, Gantt, timeline, journey, XY and radar diagrams become editable; sankey, block, packet, kanban and treemap are kept as text. Returns the family, node and edge counts and any parse diagnostics. Prefer the per-operation tools for small changes: they keep the rest of the text as written.",
495
1718
  inputSchema: object({ source: { type: "string", minLength: 1, description: 'Mermaid text, starting with a header such as "flowchart LR".' } }, ["source"]),
496
1719
  annotations: { title: "Replace the diagram with Mermaid", ...DESTRUCTIVE },
497
1720
  handler: async ({ source }) => {
@@ -520,8 +1743,9 @@ function createDiagramToolProvider(controller, options = {}) {
520
1743
  inputSchema: object(
521
1744
  {
522
1745
  label: LABEL("Text shown in the node."),
523
- id: { type: "string", pattern: "^[A-Za-z0-9_][\\w.-]*$", description: 'Mermaid id (default: the next free "N<number>").' },
524
- shape: { type: "string", description: 'One of the shapes get_diagram lists (default "rect"). Flowchart and state diagrams only.' },
1746
+ id: { type: "string", pattern: "^[A-Za-z0-9_][\\w.-]*$", description: 'Mermaid id (default: the next free id for the family, e.g. "n3", "slice4", "task2").' },
1747
+ shape: { type: "string", description: `One of the shapes get_diagram lists (default: the family's usual node, e.g. "rect").` },
1748
+ data: { type: "object", additionalProperties: FIELD_VALUE, description: `Values for the family's node fields (get_diagram "fields.node"), e.g. {"value": 40} for a pie slice. Defaults fill in the rest.` },
525
1749
  parentId: { type: "string", description: "Group (subgraph) to add the node to." },
526
1750
  from: { type: "string", description: "An existing node to connect to the new node." },
527
1751
  edgeLabel: LABEL('Label of the edge from "from" (needs "from").'),
@@ -531,14 +1755,22 @@ function createDiagramToolProvider(controller, options = {}) {
531
1755
  ["label"]
532
1756
  ),
533
1757
  annotations: { title: "Add a node", ...WRITE },
534
- handler: async ({ label, id, shape, parentId, from, edgeLabel, x, y }) => {
1758
+ handler: async ({ label, id, shape, parentId, from, edgeLabel, x, y, data }) => {
535
1759
  requireEditable();
536
1760
  if (x === void 0 !== (y === void 0)) throw new Error("Give both x and y, or neither to place the node automatically.");
537
1761
  if (edgeLabel !== void 0 && from === void 0) throw new Error('edgeLabel needs "from", the node the edge starts at.');
538
- const nodeId = id ?? controller.nextId();
1762
+ const ui = familyUI(doc().family);
1763
+ const nodeId = id ?? (ui && !["flowchart", "state", "class", "er"].includes(ui.family) ? ui.nextId(doc().graph) : controller.nextId());
1764
+ const defaults = ui?.newNode?.(doc().graph, parentId) ?? {};
1765
+ const nodeShape = shape ?? defaults.shape;
1766
+ const nodeData = { ...defaults.data ?? {}, ...data ? checkFieldData(ui?.nodeFields, data, `a ${doc().family} node`, nodeShape) : {} };
539
1767
  const before = edgeIds();
540
1768
  const ops = [
541
- { type: "addNode", node: { id: nodeId, label, ...shape ? { shape } : {}, ...parentId ? { parentId } : {} }, ...x !== void 0 ? { position: [x, y] } : {} }
1769
+ {
1770
+ type: "addNode",
1771
+ node: { ...defaults, id: nodeId, label, ...nodeShape ? { shape: nodeShape } : {}, ...parentId ? { parentId } : {}, ...Object.keys(nodeData).length ? { data: nodeData } : {} },
1772
+ ...x !== void 0 ? { position: [x, y] } : {}
1773
+ }
542
1774
  ];
543
1775
  if (from !== void 0) ops.push({ type: "addEdge", edge: { source: from, target: nodeId, ...edgeLabel ? { label: edgeLabel } : {} } });
544
1776
  const d = await apply(ops, "Add node");
@@ -713,9 +1945,9 @@ function createDiagramToolProvider(controller, options = {}) {
713
1945
  ),
714
1946
  annotations: { title: "Move nodes", ...WRITE_IDEMPOTENT },
715
1947
  handler: async ({ moves }) => {
716
- const list = moves;
1948
+ const list2 = moves;
717
1949
  requireEditable();
718
- await apply({ type: "moveNodes", moves: pinned(list.map((m) => ({ id: m.id, position: [m.x, m.y] }))) }, "Move");
1950
+ await apply({ type: "moveNodes", moves: pinned(list2.map((m) => ({ id: m.id, position: [m.x, m.y] }))) }, "Move");
719
1951
  return { moved: moves };
720
1952
  }
721
1953
  };
@@ -743,8 +1975,104 @@ function createDiagramToolProvider(controller, options = {}) {
743
1975
  return { redone, ...redone ? { label } : {} };
744
1976
  }
745
1977
  };
746
- const reads = [getDiagram, exportMermaid, findDiagrams];
747
- const writes = [loadMermaid, addNode, removeElements, renameNode, setShape, setStyle, connect, removeEdges, labelEdge, reconnect, setDirection, group, ungroup, move, undo, redo];
1978
+ const fieldsOf = (kind2) => {
1979
+ const ui = familyUI(doc().family);
1980
+ return kind2 === "node" ? ui?.nodeFields : kind2 === "edge" ? ui?.edgeFields : ui?.diagramFields;
1981
+ };
1982
+ const setNodeData = {
1983
+ name: "set_diagram_node_data",
1984
+ title: "Set a node's data fields",
1985
+ description: `Sets values of a node's data fields: a pie slice's value, a Gantt task's start and end, a quadrant point's x and y, a journey task's score, an XY series' values, a C4 element's technology\u2026 Field keys and types are listed in get_diagram "fields.node"; null clears a field. Returns the node with its data.`,
1986
+ inputSchema: object(
1987
+ {
1988
+ id: ID,
1989
+ data: { type: "object", additionalProperties: FIELD_VALUE, description: 'Field key \u2192 value, e.g. {"value": 40} or {"x": 0.3, "y": 0.8}. null clears the field.' }
1990
+ },
1991
+ ["id", "data"]
1992
+ ),
1993
+ annotations: { title: "Set a node's data fields", ...WRITE_IDEMPOTENT },
1994
+ handler: async ({ id, data }) => {
1995
+ requireEditable();
1996
+ const node = doc().graph.nodes.find((n) => n.id === id);
1997
+ if (!node) throw new Error(`There is no node "${id}"; call get_diagram for the node ids.`);
1998
+ const patch = checkFieldData(fieldsOf("node"), data, `a ${doc().family} node`, node.shape);
1999
+ const d = await apply({ type: "setNodeData", id, data: patch }, "Edit data");
2000
+ const after = d.graph.nodes.find((n) => n.id === id);
2001
+ return { node: { ...nodeOut(d, id), data: pickFieldData(fieldsOf("node"), after?.data) } };
2002
+ }
2003
+ };
2004
+ const setEdgeData = {
2005
+ name: "set_diagram_edge_data",
2006
+ title: "Set an edge's data fields",
2007
+ description: `Sets values of an edge's data fields: a sequence message's activation, a C4 relation's technology, an architecture edge's sides\u2026 Field keys and types are listed in get_diagram "fields.edge"; null clears a field. Returns the edge with its data.`,
2008
+ inputSchema: object(
2009
+ {
2010
+ id: EDGE_ID,
2011
+ data: { type: "object", additionalProperties: FIELD_VALUE, description: "Field key \u2192 value. null clears the field." }
2012
+ },
2013
+ ["id", "data"]
2014
+ ),
2015
+ annotations: { title: "Set an edge's data fields", ...WRITE_IDEMPOTENT },
2016
+ handler: async ({ id, data }) => {
2017
+ requireEditable();
2018
+ if (!doc().graph.edges.some((e) => e.id === id)) throw new Error(`There is no edge "${id}"; call get_diagram for the edge ids.`);
2019
+ const patch = checkFieldData(fieldsOf("edge"), data, `a ${doc().family} edge`);
2020
+ const d = await apply({ type: "setEdgeData", id, data: patch }, "Edit data");
2021
+ const edge = d.graph.edges.find((e) => e.id === id);
2022
+ return { edge: { id, ...edge ? { source: edge.source, target: edge.target } : {}, data: pickFieldData(fieldsOf("edge"), edge?.data) } };
2023
+ }
2024
+ };
2025
+ const setSettings = {
2026
+ name: "set_diagram_settings",
2027
+ title: "Change diagram settings",
2028
+ description: `Sets diagram-level fields: a pie chart's showData, a Gantt chart's dateFormat and excludes, a quadrant chart's axis labels, an XY chart's categories and axis range, sequence autonumbering\u2026 Field keys and types are listed in get_diagram "fields.diagram"; null clears a field. Returns all settings.`,
2029
+ inputSchema: object(
2030
+ { data: { type: "object", additionalProperties: FIELD_VALUE, description: "Field key \u2192 value. null clears the field." } },
2031
+ ["data"]
2032
+ ),
2033
+ annotations: { title: "Change diagram settings", ...WRITE_IDEMPOTENT },
2034
+ handler: async ({ data }) => {
2035
+ requireEditable();
2036
+ const patch = checkFieldData(fieldsOf("diagram"), data, `a ${doc().family} diagram`);
2037
+ const d = await apply({ type: "setGraphData", data: patch }, "Edit settings");
2038
+ return { settings: pickFieldData(fieldsOf("diagram"), d.graph.data) };
2039
+ }
2040
+ };
2041
+ const setTitle = {
2042
+ name: "set_diagram_title",
2043
+ title: "Set the diagram title",
2044
+ description: "Sets the title shown above the diagram (a title statement, or frontmatter for families without one), or removes it with null. Returns the title.",
2045
+ inputSchema: object({ title: { type: ["string", "null"], description: "The new title, or null to remove it." } }, ["title"]),
2046
+ annotations: { title: "Set the diagram title", ...WRITE_IDEMPOTENT },
2047
+ handler: async ({ title }) => {
2048
+ requireEditable();
2049
+ const d = await apply({ type: "setTitle", title: title === null || title === "" ? void 0 : title }, "Set title");
2050
+ return { title: d.graph.title ?? null };
2051
+ }
2052
+ };
2053
+ const renderDiagram = {
2054
+ name: "render_diagram",
2055
+ title: "Render the diagram",
2056
+ description: 'Draws the diagram without changing it, to check it visually: standalone SVG text by default, or a PNG image (format "png") when the host can rasterize. Positions match the canvas.',
2057
+ inputSchema: object({
2058
+ format: { type: "string", enum: ["svg", "png"], description: "svg (default) or png (only when the host supports it)." },
2059
+ maxWidth: { type: "number", minimum: 16, description: "Fit within this width in px (default: natural size)." },
2060
+ maxHeight: { type: "number", minimum: 16, description: "Fit within this height in px (default: natural size)." }
2061
+ }),
2062
+ annotations: { title: "Render the diagram", ...READ },
2063
+ handler: async ({ format = "svg", maxWidth, maxHeight }) => {
2064
+ if (doc().tier !== "editable") throw new Error(`A ${doc().family} diagram is kept as Mermaid text and cannot be drawn here; use export_diagram_mermaid.`);
2065
+ const drawn = options.renderSvg({ maxWidth, maxHeight });
2066
+ if (format === "png") {
2067
+ if (!options.rasterize) throw new Error('This host cannot make PNG images; call render_diagram with format "svg".');
2068
+ const image = await options.rasterize(drawn.svg, { width: drawn.width, height: drawn.height });
2069
+ return { content: [{ type: "image", data: image.data, mimeType: image.mimeType }] };
2070
+ }
2071
+ return { format: "svg", width: drawn.width, height: drawn.height, svg: drawn.svg };
2072
+ }
2073
+ };
2074
+ const reads = [getDiagram, exportMermaid, findDiagrams, ...options.renderSvg ? [renderDiagram] : []];
2075
+ const writes = [loadMermaid, addNode, removeElements, renameNode, setShape, setStyle, setNodeData, connect, removeEdges, labelEdge, setEdgeData, reconnect, setDirection, setTitle, setSettings, group, ungroup, move, undo, redo];
748
2076
  return {
749
2077
  id: options.id ?? "diagram",
750
2078
  namespace: options.namespace,
@@ -1082,6 +2410,8 @@ function planDiagramEdits(source, place, ops, speed = 1) {
1082
2410
  });
1083
2411
  }
1084
2412
  export {
2413
+ ARCH_METRICS,
2414
+ C4_METRICS,
1085
2415
  CLASS_RELATIONS,
1086
2416
  DIRECTIONS,
1087
2417
  DiagramController,
@@ -1089,58 +2419,159 @@ export {
1089
2419
  EDITABLE_DIAGRAM_FAMILIES,
1090
2420
  ER_CARDINALITIES,
1091
2421
  ER_PATTERNS,
2422
+ FAMILY_BLANKS,
2423
+ FAMILY_DESCRIPTIONS,
2424
+ FAMILY_TEMPLATES,
2425
+ FAMILY_TITLES,
1092
2426
  FLOWCHART_SHAPES,
2427
+ GANTT_CONFIG_KEYS,
2428
+ GANTT_METRICS,
2429
+ GANTT_TAGS,
1093
2430
  META_COMMENT_PREFIX,
1094
2431
  META_FRONTMATTER_KEY,
2432
+ POINT_BOX,
1095
2433
  PRESENCE_COLORS,
1096
2434
  PerformanceQueue,
1097
2435
  PresenceStore,
2436
+ QUADRANT_METRICS,
2437
+ RADAR_CHART_BOX,
2438
+ SEQUENCE_METRICS,
1098
2439
  STATE_SHAPES,
2440
+ XY_CHART_BOX,
2441
+ afterIds,
1099
2442
  applyEdit,
1100
2443
  applyEdits,
2444
+ applyStatementEdit,
2445
+ architectureAdapter,
2446
+ architectureArrow,
2447
+ architectureEdgeRoute,
2448
+ architectureGrammar,
2449
+ architectureLayout,
2450
+ architectureUI,
2451
+ c4Adapter,
2452
+ c4ArrowHead,
2453
+ c4BoundaryText,
2454
+ c4ElementGeometry,
2455
+ c4ElementType,
2456
+ c4Grammar,
2457
+ c4Layout,
2458
+ c4RelGeometry,
2459
+ c4Stereotype,
2460
+ c4UI,
1101
2461
  canonicalShape,
1102
2462
  changedItems,
2463
+ checkFieldData,
1103
2464
  classGrammar,
2465
+ classUI,
1104
2466
  createDiagramToolProvider,
1105
2467
  createInstantPresenceClock,
1106
2468
  createLineAdapter,
1107
2469
  createPassthroughAdapter,
2470
+ createStatementAdapter,
1108
2471
  describeDiagram,
2472
+ describeFields,
1109
2473
  detectFamily,
1110
2474
  detectFamilyFromHeader,
1111
2475
  diagramShapes,
2476
+ diagramSupportsDirection,
1112
2477
  diagramSupportsGroups,
1113
2478
  draftFrames,
2479
+ dropMetaKeys,
1114
2480
  emptyMeta,
1115
2481
  erGrammar,
2482
+ erUI,
2483
+ familyUI,
2484
+ filterInPlace,
1116
2485
  findMermaidSources,
1117
2486
  flowchartAdapter,
2487
+ flowchartUI,
2488
+ formatAxis,
1118
2489
  formatChain,
2490
+ formatGanttDate,
1119
2491
  formatLink,
1120
2492
  formatNode,
2493
+ ganttAdapter,
2494
+ ganttGeometry,
2495
+ ganttGrammar,
2496
+ ganttUI,
1121
2497
  getDiagramAdapter,
2498
+ getFamilyLayout,
2499
+ gitGraphAdapter,
2500
+ gitGraphGrammar,
2501
+ gitGraphUI,
2502
+ indentOf,
1122
2503
  isMetaEmpty,
2504
+ journeyAdapter,
2505
+ journeyGrammar,
2506
+ journeyLayout,
2507
+ journeyUI,
1123
2508
  mergeMeta,
2509
+ mindmapAdapter,
2510
+ mindmapGrammar,
2511
+ mindmapUI,
1124
2512
  parseAttributes,
1125
2513
  parseChain,
1126
2514
  parseFlowchartSource,
2515
+ parseGanttDate,
1127
2516
  parseLink,
1128
2517
  parseMembers,
1129
2518
  parseMermaid,
2519
+ parseSankey,
1130
2520
  parseStatement,
2521
+ parseStatementDocument,
2522
+ parseTreemap,
2523
+ pickFieldData,
2524
+ pieAdapter,
2525
+ pieGrammar,
2526
+ pieUI,
1131
2527
  planDiagramEdit,
1132
2528
  planDiagramEdits,
2529
+ pointCentre,
2530
+ pointPosition,
2531
+ positionToData,
2532
+ quadrantAdapter,
2533
+ quadrantGeometry,
2534
+ quadrantGrammar,
2535
+ quadrantSpace,
2536
+ quadrantUI,
2537
+ quote,
1133
2538
  quoteLabelIfNeeded,
2539
+ radarAdapter,
2540
+ radarGrammar,
2541
+ radarUI,
1134
2542
  realPresenceClock,
1135
2543
  registerDiagramAdapter,
2544
+ registerFamilyLayout,
1136
2545
  relationFor,
2546
+ renameMetaKey,
1137
2547
  resolveShape,
2548
+ sequenceAdapter,
2549
+ sequenceGeometry,
2550
+ sequenceGrammar,
2551
+ sequenceUI,
1138
2552
  serializeMermaid,
1139
2553
  serializeMeta,
2554
+ serializeStatementDocument,
2555
+ serviceLabelLines,
2556
+ sharedFrameLayout,
2557
+ slugId,
2558
+ spaceInput,
2559
+ splitOutsideQuotes,
1140
2560
  splitSource,
1141
2561
  splitStatements,
1142
2562
  stateGrammar,
2563
+ stateUI,
1143
2564
  supportTierOf,
1144
- validateDiagramEdit
2565
+ timelineAdapter,
2566
+ timelineGrammar,
2567
+ timelineLayout,
2568
+ timelineUI,
2569
+ treemapValue,
2570
+ uniqueId,
2571
+ unquote,
2572
+ validateDiagramEdit,
2573
+ xyChartAdapter,
2574
+ xyChartGrammar,
2575
+ xyChartUI
1145
2576
  };
1146
2577
  //# sourceMappingURL=index.js.map