@pixerate/editor 0.55.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 (69) hide show
  1. package/dist/agent/index.cjs +18 -17
  2. package/dist/agent/index.cjs.map +1 -1
  3. package/dist/agent/index.js +3 -2
  4. package/dist/agent/index.js.map +1 -1
  5. package/dist/canvas/index.cjs +2105 -172
  6. package/dist/canvas/index.cjs.map +1 -1
  7. package/dist/canvas/index.d.cts +319 -23
  8. package/dist/canvas/index.d.ts +319 -23
  9. package/dist/canvas/index.js +2081 -148
  10. package/dist/canvas/index.js.map +1 -1
  11. package/dist/chart/index.cjs +32 -30
  12. package/dist/chart/index.cjs.map +1 -1
  13. package/dist/chart/index.d.cts +4 -2
  14. package/dist/chart/index.d.ts +4 -2
  15. package/dist/chart/index.js +20 -18
  16. package/dist/chart/index.js.map +1 -1
  17. package/dist/{chunk-C3JHII3M.cjs → chunk-3I6V7PI4.cjs} +45 -45
  18. package/dist/{chunk-C3JHII3M.cjs.map → chunk-3I6V7PI4.cjs.map} +1 -1
  19. package/dist/{chunk-P43HUQRX.cjs → chunk-AHCENCU4.cjs} +12 -10
  20. package/dist/chunk-AHCENCU4.cjs.map +1 -0
  21. package/dist/chunk-II77MLHN.cjs +11106 -0
  22. package/dist/chunk-II77MLHN.cjs.map +1 -0
  23. package/dist/{chunk-OIKYP7XC.js → chunk-LMUDHBWR.js} +2 -2
  24. package/dist/{chunk-VODBAO32.js → chunk-OEFCLWZ3.js} +4 -1425
  25. package/dist/chunk-OEFCLWZ3.js.map +1 -0
  26. package/dist/{chunk-NK3WL5TJ.cjs → chunk-P2CTDJNF.cjs} +27 -1448
  27. package/dist/chunk-P2CTDJNF.cjs.map +1 -0
  28. package/dist/chunk-TKPPIVW7.cjs +1443 -0
  29. package/dist/chunk-TKPPIVW7.cjs.map +1 -0
  30. package/dist/chunk-WJSCGBJ2.js +11106 -0
  31. package/dist/chunk-WJSCGBJ2.js.map +1 -0
  32. package/dist/{chunk-RIXTW3C4.js → chunk-WLVZ235X.js} +5 -3
  33. package/dist/{chunk-RIXTW3C4.js.map → chunk-WLVZ235X.js.map} +1 -1
  34. package/dist/chunk-ZOH6X3VR.js +1443 -0
  35. package/dist/chunk-ZOH6X3VR.js.map +1 -0
  36. package/dist/{controller-DscWQbjO.d.ts → controller-D2rj5umx.d.ts} +2 -362
  37. package/dist/{controller-CX0QfSv0.d.cts → controller-R2biKk_E.d.cts} +2 -362
  38. package/dist/diagram/index.cjs +1457 -47
  39. package/dist/diagram/index.cjs.map +1 -1
  40. package/dist/diagram/index.d.cts +1734 -15
  41. package/dist/diagram/index.d.ts +1734 -15
  42. package/dist/diagram/index.js +1436 -26
  43. package/dist/diagram/index.js.map +1 -1
  44. package/dist/extensions/index.cjs +5 -4
  45. package/dist/extensions/index.cjs.map +1 -1
  46. package/dist/extensions/index.d.cts +4 -3
  47. package/dist/extensions/index.d.ts +4 -3
  48. package/dist/extensions/index.js +4 -3
  49. package/dist/{index-DIWB6xMf.d.cts → index-BcHyG0Wq.d.cts} +2 -1
  50. package/dist/{index-CALDD35B.d.ts → index-CTCc3m3C.d.ts} +2 -1
  51. package/dist/index.cjs +10 -9
  52. package/dist/index.cjs.map +1 -1
  53. package/dist/index.d.cts +4 -3
  54. package/dist/index.d.ts +4 -3
  55. package/dist/index.js +4 -3
  56. package/dist/index.js.map +1 -1
  57. package/dist/types-BRp-6zkY.d.cts +362 -0
  58. package/dist/types-BRp-6zkY.d.ts +362 -0
  59. package/dist/{types-BULrFyuQ.d.cts → types-DYkjhzdz.d.cts} +1 -1
  60. package/dist/{types-BULrFyuQ.d.ts → types-DYkjhzdz.d.ts} +1 -1
  61. package/package.json +1 -1
  62. package/dist/chunk-H5K77C7Y.cjs +0 -3848
  63. package/dist/chunk-H5K77C7Y.cjs.map +0 -1
  64. package/dist/chunk-NK3WL5TJ.cjs.map +0 -1
  65. package/dist/chunk-P43HUQRX.cjs.map +0 -1
  66. package/dist/chunk-VODBAO32.js.map +0 -1
  67. package/dist/chunk-WWJNC7SX.js +0 -3848
  68. package/dist/chunk-WWJNC7SX.js.map +0 -1
  69. /package/dist/{chunk-OIKYP7XC.js.map → chunk-LMUDHBWR.js.map} +0 -0
@@ -1,46 +1,121 @@
1
1
  import {
2
+ ARCH_METRICS,
3
+ C4_METRICS,
2
4
  CLASS_RELATIONS,
3
5
  ER_CARDINALITIES,
4
6
  ER_PATTERNS,
5
7
  FLOWCHART_SHAPES,
8
+ GANTT_CONFIG_KEYS,
9
+ GANTT_METRICS,
10
+ GANTT_TAGS,
6
11
  META_COMMENT_PREFIX,
7
12
  META_FRONTMATTER_KEY,
13
+ POINT_BOX,
14
+ QUADRANT_METRICS,
15
+ RADAR_CHART_BOX,
16
+ SEQUENCE_METRICS,
8
17
  STATE_SHAPES,
18
+ XY_CHART_BOX,
19
+ afterIds,
9
20
  applyEdit,
10
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,
11
37
  canonicalShape,
12
38
  classGrammar,
13
39
  createLineAdapter,
14
40
  createPassthroughAdapter,
41
+ createStatementAdapter,
15
42
  detectFamily,
16
43
  detectFamilyFromHeader,
44
+ dropMetaKeys,
17
45
  emptyMeta,
18
46
  erGrammar,
47
+ filterInPlace,
19
48
  flowchartAdapter,
49
+ formatAxis,
20
50
  formatChain,
51
+ formatGanttDate,
21
52
  formatLink,
22
53
  formatNode,
54
+ ganttAdapter,
55
+ ganttGeometry,
56
+ ganttGrammar,
23
57
  getDiagramAdapter,
58
+ getFamilyLayout,
59
+ gitGraphAdapter,
60
+ gitGraphGrammar,
61
+ indentOf,
24
62
  isMetaEmpty,
63
+ journeyAdapter,
64
+ journeyGrammar,
65
+ journeyLayout,
25
66
  mergeMeta,
67
+ mindmapAdapter,
68
+ mindmapGrammar,
26
69
  parseAttributes,
27
70
  parseChain,
28
71
  parseFlowchartSource,
72
+ parseGanttDate,
29
73
  parseLink,
30
74
  parseMembers,
31
75
  parseMermaid,
32
76
  parseStatement,
77
+ parseStatementDocument,
78
+ pieAdapter,
79
+ pieGrammar,
80
+ pointCentre,
81
+ pointPosition,
82
+ positionToData,
83
+ quadrantAdapter,
84
+ quadrantGeometry,
85
+ quadrantGrammar,
86
+ quadrantSpace,
87
+ quote,
33
88
  quoteLabelIfNeeded,
89
+ radarAdapter,
90
+ radarGrammar,
34
91
  registerDiagramAdapter,
92
+ registerFamilyLayout,
35
93
  relationFor,
94
+ renameMetaKey,
36
95
  resolveShape,
96
+ sequenceAdapter,
97
+ sequenceGeometry,
98
+ sequenceGrammar,
37
99
  serializeMermaid,
38
100
  serializeMeta,
101
+ serializeStatementDocument,
102
+ serviceLabelLines,
103
+ sharedFrameLayout,
104
+ slugId,
105
+ spaceInput,
106
+ splitOutsideQuotes,
39
107
  splitSource,
40
108
  splitStatements,
41
109
  stateGrammar,
42
- supportTierOf
43
- } 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";
44
119
  import {
45
120
  PRESENCE_COLORS,
46
121
  PerformanceQueue,
@@ -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,6 +1975,81 @@ function createDiagramToolProvider(controller, options = {}) {
743
1975
  return { redone, ...redone ? { label } : {} };
744
1976
  }
745
1977
  };
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
+ };
746
2053
  const renderDiagram = {
747
2054
  name: "render_diagram",
748
2055
  title: "Render the diagram",
@@ -765,7 +2072,7 @@ function createDiagramToolProvider(controller, options = {}) {
765
2072
  }
766
2073
  };
767
2074
  const reads = [getDiagram, exportMermaid, findDiagrams, ...options.renderSvg ? [renderDiagram] : []];
768
- const writes = [loadMermaid, addNode, removeElements, renameNode, setShape, setStyle, connect, removeEdges, labelEdge, reconnect, setDirection, group, ungroup, move, undo, redo];
2075
+ const writes = [loadMermaid, addNode, removeElements, renameNode, setShape, setStyle, setNodeData, connect, removeEdges, labelEdge, setEdgeData, reconnect, setDirection, setTitle, setSettings, group, ungroup, move, undo, redo];
769
2076
  return {
770
2077
  id: options.id ?? "diagram",
771
2078
  namespace: options.namespace,
@@ -1103,6 +2410,8 @@ function planDiagramEdits(source, place, ops, speed = 1) {
1103
2410
  });
1104
2411
  }
1105
2412
  export {
2413
+ ARCH_METRICS,
2414
+ C4_METRICS,
1106
2415
  CLASS_RELATIONS,
1107
2416
  DIRECTIONS,
1108
2417
  DiagramController,
@@ -1110,58 +2419,159 @@ export {
1110
2419
  EDITABLE_DIAGRAM_FAMILIES,
1111
2420
  ER_CARDINALITIES,
1112
2421
  ER_PATTERNS,
2422
+ FAMILY_BLANKS,
2423
+ FAMILY_DESCRIPTIONS,
2424
+ FAMILY_TEMPLATES,
2425
+ FAMILY_TITLES,
1113
2426
  FLOWCHART_SHAPES,
2427
+ GANTT_CONFIG_KEYS,
2428
+ GANTT_METRICS,
2429
+ GANTT_TAGS,
1114
2430
  META_COMMENT_PREFIX,
1115
2431
  META_FRONTMATTER_KEY,
2432
+ POINT_BOX,
1116
2433
  PRESENCE_COLORS,
1117
2434
  PerformanceQueue,
1118
2435
  PresenceStore,
2436
+ QUADRANT_METRICS,
2437
+ RADAR_CHART_BOX,
2438
+ SEQUENCE_METRICS,
1119
2439
  STATE_SHAPES,
2440
+ XY_CHART_BOX,
2441
+ afterIds,
1120
2442
  applyEdit,
1121
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,
1122
2461
  canonicalShape,
1123
2462
  changedItems,
2463
+ checkFieldData,
1124
2464
  classGrammar,
2465
+ classUI,
1125
2466
  createDiagramToolProvider,
1126
2467
  createInstantPresenceClock,
1127
2468
  createLineAdapter,
1128
2469
  createPassthroughAdapter,
2470
+ createStatementAdapter,
1129
2471
  describeDiagram,
2472
+ describeFields,
1130
2473
  detectFamily,
1131
2474
  detectFamilyFromHeader,
1132
2475
  diagramShapes,
2476
+ diagramSupportsDirection,
1133
2477
  diagramSupportsGroups,
1134
2478
  draftFrames,
2479
+ dropMetaKeys,
1135
2480
  emptyMeta,
1136
2481
  erGrammar,
2482
+ erUI,
2483
+ familyUI,
2484
+ filterInPlace,
1137
2485
  findMermaidSources,
1138
2486
  flowchartAdapter,
2487
+ flowchartUI,
2488
+ formatAxis,
1139
2489
  formatChain,
2490
+ formatGanttDate,
1140
2491
  formatLink,
1141
2492
  formatNode,
2493
+ ganttAdapter,
2494
+ ganttGeometry,
2495
+ ganttGrammar,
2496
+ ganttUI,
1142
2497
  getDiagramAdapter,
2498
+ getFamilyLayout,
2499
+ gitGraphAdapter,
2500
+ gitGraphGrammar,
2501
+ gitGraphUI,
2502
+ indentOf,
1143
2503
  isMetaEmpty,
2504
+ journeyAdapter,
2505
+ journeyGrammar,
2506
+ journeyLayout,
2507
+ journeyUI,
1144
2508
  mergeMeta,
2509
+ mindmapAdapter,
2510
+ mindmapGrammar,
2511
+ mindmapUI,
1145
2512
  parseAttributes,
1146
2513
  parseChain,
1147
2514
  parseFlowchartSource,
2515
+ parseGanttDate,
1148
2516
  parseLink,
1149
2517
  parseMembers,
1150
2518
  parseMermaid,
2519
+ parseSankey,
1151
2520
  parseStatement,
2521
+ parseStatementDocument,
2522
+ parseTreemap,
2523
+ pickFieldData,
2524
+ pieAdapter,
2525
+ pieGrammar,
2526
+ pieUI,
1152
2527
  planDiagramEdit,
1153
2528
  planDiagramEdits,
2529
+ pointCentre,
2530
+ pointPosition,
2531
+ positionToData,
2532
+ quadrantAdapter,
2533
+ quadrantGeometry,
2534
+ quadrantGrammar,
2535
+ quadrantSpace,
2536
+ quadrantUI,
2537
+ quote,
1154
2538
  quoteLabelIfNeeded,
2539
+ radarAdapter,
2540
+ radarGrammar,
2541
+ radarUI,
1155
2542
  realPresenceClock,
1156
2543
  registerDiagramAdapter,
2544
+ registerFamilyLayout,
1157
2545
  relationFor,
2546
+ renameMetaKey,
1158
2547
  resolveShape,
2548
+ sequenceAdapter,
2549
+ sequenceGeometry,
2550
+ sequenceGrammar,
2551
+ sequenceUI,
1159
2552
  serializeMermaid,
1160
2553
  serializeMeta,
2554
+ serializeStatementDocument,
2555
+ serviceLabelLines,
2556
+ sharedFrameLayout,
2557
+ slugId,
2558
+ spaceInput,
2559
+ splitOutsideQuotes,
1161
2560
  splitSource,
1162
2561
  splitStatements,
1163
2562
  stateGrammar,
2563
+ stateUI,
1164
2564
  supportTierOf,
1165
- validateDiagramEdit
2565
+ timelineAdapter,
2566
+ timelineGrammar,
2567
+ timelineLayout,
2568
+ timelineUI,
2569
+ treemapValue,
2570
+ uniqueId,
2571
+ unquote,
2572
+ validateDiagramEdit,
2573
+ xyChartAdapter,
2574
+ xyChartGrammar,
2575
+ xyChartUI
1166
2576
  };
1167
2577
  //# sourceMappingURL=index.js.map