@pixerate/editor 0.55.0 → 0.57.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 (75) 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/animation-editor/index.cjs +25 -7
  6. package/dist/animation-editor/index.cjs.map +1 -1
  7. package/dist/animation-editor/index.d.cts +21 -5
  8. package/dist/animation-editor/index.d.ts +21 -5
  9. package/dist/animation-editor/index.js +25 -7
  10. package/dist/animation-editor/index.js.map +1 -1
  11. package/dist/canvas/index.cjs +2105 -172
  12. package/dist/canvas/index.cjs.map +1 -1
  13. package/dist/canvas/index.d.cts +319 -23
  14. package/dist/canvas/index.d.ts +319 -23
  15. package/dist/canvas/index.js +2081 -148
  16. package/dist/canvas/index.js.map +1 -1
  17. package/dist/chart/index.cjs +32 -30
  18. package/dist/chart/index.cjs.map +1 -1
  19. package/dist/chart/index.d.cts +4 -2
  20. package/dist/chart/index.d.ts +4 -2
  21. package/dist/chart/index.js +20 -18
  22. package/dist/chart/index.js.map +1 -1
  23. package/dist/{chunk-C3JHII3M.cjs → chunk-3I6V7PI4.cjs} +45 -45
  24. package/dist/{chunk-C3JHII3M.cjs.map → chunk-3I6V7PI4.cjs.map} +1 -1
  25. package/dist/{chunk-P43HUQRX.cjs → chunk-AHCENCU4.cjs} +12 -10
  26. package/dist/chunk-AHCENCU4.cjs.map +1 -0
  27. package/dist/chunk-II77MLHN.cjs +11106 -0
  28. package/dist/chunk-II77MLHN.cjs.map +1 -0
  29. package/dist/{chunk-OIKYP7XC.js → chunk-LMUDHBWR.js} +2 -2
  30. package/dist/{chunk-VODBAO32.js → chunk-OEFCLWZ3.js} +4 -1425
  31. package/dist/chunk-OEFCLWZ3.js.map +1 -0
  32. package/dist/{chunk-NK3WL5TJ.cjs → chunk-P2CTDJNF.cjs} +27 -1448
  33. package/dist/chunk-P2CTDJNF.cjs.map +1 -0
  34. package/dist/chunk-TKPPIVW7.cjs +1443 -0
  35. package/dist/chunk-TKPPIVW7.cjs.map +1 -0
  36. package/dist/chunk-WJSCGBJ2.js +11106 -0
  37. package/dist/chunk-WJSCGBJ2.js.map +1 -0
  38. package/dist/{chunk-RIXTW3C4.js → chunk-WLVZ235X.js} +5 -3
  39. package/dist/{chunk-RIXTW3C4.js.map → chunk-WLVZ235X.js.map} +1 -1
  40. package/dist/chunk-ZOH6X3VR.js +1443 -0
  41. package/dist/chunk-ZOH6X3VR.js.map +1 -0
  42. package/dist/{controller-DscWQbjO.d.ts → controller-D2rj5umx.d.ts} +2 -362
  43. package/dist/{controller-CX0QfSv0.d.cts → controller-R2biKk_E.d.cts} +2 -362
  44. package/dist/diagram/index.cjs +1457 -47
  45. package/dist/diagram/index.cjs.map +1 -1
  46. package/dist/diagram/index.d.cts +1734 -15
  47. package/dist/diagram/index.d.ts +1734 -15
  48. package/dist/diagram/index.js +1436 -26
  49. package/dist/diagram/index.js.map +1 -1
  50. package/dist/extensions/index.cjs +5 -4
  51. package/dist/extensions/index.cjs.map +1 -1
  52. package/dist/extensions/index.d.cts +4 -3
  53. package/dist/extensions/index.d.ts +4 -3
  54. package/dist/extensions/index.js +4 -3
  55. package/dist/{index-DIWB6xMf.d.cts → index-BcHyG0Wq.d.cts} +2 -1
  56. package/dist/{index-CALDD35B.d.ts → index-CTCc3m3C.d.ts} +2 -1
  57. package/dist/index.cjs +10 -9
  58. package/dist/index.cjs.map +1 -1
  59. package/dist/index.d.cts +4 -3
  60. package/dist/index.d.ts +4 -3
  61. package/dist/index.js +4 -3
  62. package/dist/index.js.map +1 -1
  63. package/dist/types-BRp-6zkY.d.cts +362 -0
  64. package/dist/types-BRp-6zkY.d.ts +362 -0
  65. package/dist/{types-BULrFyuQ.d.cts → types-DYkjhzdz.d.cts} +1 -1
  66. package/dist/{types-BULrFyuQ.d.ts → types-DYkjhzdz.d.ts} +1 -1
  67. package/package.json +1 -1
  68. package/dist/chunk-H5K77C7Y.cjs +0 -3848
  69. package/dist/chunk-H5K77C7Y.cjs.map +0 -1
  70. package/dist/chunk-NK3WL5TJ.cjs.map +0 -1
  71. package/dist/chunk-P43HUQRX.cjs.map +0 -1
  72. package/dist/chunk-VODBAO32.js.map +0 -1
  73. package/dist/chunk-WWJNC7SX.js +0 -3848
  74. package/dist/chunk-WWJNC7SX.js.map +0 -1
  75. /package/dist/{chunk-OIKYP7XC.js.map → chunk-LMUDHBWR.js.map} +0 -0
@@ -15,8 +15,39 @@ import {
15
15
  pathfinder
16
16
  } from "../chunk-VWZB6BCY.js";
17
17
  import {
18
- parseMermaid
19
- } from "../chunk-WWJNC7SX.js";
18
+ ARCH_METRICS,
19
+ GANTT_METRICS,
20
+ GIT_METRICS,
21
+ JOURNEY_METRICS,
22
+ MINDMAP_METRICS,
23
+ PIE_METRICS,
24
+ QUADRANT_METRICS,
25
+ RADAR_CHART_BOX,
26
+ SEQUENCE_METRICS,
27
+ TIMELINE_METRICS,
28
+ XY_CHART_BOX,
29
+ architectureArrow,
30
+ architectureEdgeRoute,
31
+ c4ArrowHead,
32
+ c4BoundaryText,
33
+ c4ElementGeometry,
34
+ c4RelGeometry,
35
+ estimateTextWidth,
36
+ ganttGeometry,
37
+ getFamilyLayout,
38
+ gitGraphGeometry,
39
+ isSide,
40
+ journeyGeometry,
41
+ mindmapGeometry,
42
+ parseMermaid,
43
+ pieGeometry,
44
+ quadrantGeometry,
45
+ sequenceGeometry,
46
+ serviceLabelLines,
47
+ shiftEndpoint,
48
+ textWidth,
49
+ timelineGeometry
50
+ } from "../chunk-WJSCGBJ2.js";
20
51
  import {
21
52
  DEFAULT_NODE_HEIGHT,
22
53
  DEFAULT_NODE_WIDTH,
@@ -36,6 +67,13 @@ import {
36
67
  DEFAULT_ARRANGE_SHORTCUTS,
37
68
  matchArrangeShortcut
38
69
  } from "../chunk-7DWMJCAT.js";
70
+ import {
71
+ layoutChart
72
+ } from "../chunk-OEFCLWZ3.js";
73
+ import {
74
+ createChartSpec
75
+ } from "../chunk-633QC34G.js";
76
+ import "../chunk-EKYHKQPG.js";
39
77
  import {
40
78
  CANVAS_GRADIENT_PRESETS,
41
79
  PIXERATE_BRAND_GRADIENT,
@@ -1321,12 +1359,12 @@ function computeSnapGuides(moving, targets, options = {}) {
1321
1359
  if (useCentres) {
1322
1360
  lines.push({ value: start + size / 2, kind: "centre", axis: horizontal ? index.centreX : index.centreY });
1323
1361
  }
1324
- for (const line3 of lines) {
1325
- const aligned = matches(line3.axis, line3.value, eps);
1362
+ for (const line4 of lines) {
1363
+ const aligned = matches(line4.axis, line4.value, eps);
1326
1364
  if (aligned.length === 0) continue;
1327
1365
  const span = boundsOf([snapped, ...aligned]);
1328
1366
  guides.push(
1329
- horizontal ? { orientation: "vertical", kind: line3.kind, x1: line3.value, y1: span.y, x2: line3.value, y2: span.y + span.height } : { orientation: "horizontal", kind: line3.kind, x1: span.x, y1: line3.value, x2: span.x + span.width, y2: line3.value }
1367
+ horizontal ? { orientation: "vertical", kind: line4.kind, x1: line4.value, y1: span.y, x2: line4.value, y2: span.y + span.height } : { orientation: "horizontal", kind: line4.kind, x1: span.x, y1: line4.value, x2: span.x + span.width, y2: line4.value }
1330
1368
  );
1331
1369
  }
1332
1370
  };
@@ -1547,13 +1585,13 @@ function parseCanvasScenes(input) {
1547
1585
  }
1548
1586
  const list = Array.isArray(value) ? value : typeof value === "object" && value !== null && Array.isArray(value.scenes) ? value.scenes : [];
1549
1587
  const seen = /* @__PURE__ */ new Set();
1550
- const scenes = [];
1588
+ const scenes2 = [];
1551
1589
  for (const entry of list) {
1552
1590
  if (!isValidCanvasScene(entry) || seen.has(entry.id)) continue;
1553
1591
  seen.add(entry.id);
1554
- scenes.push(cloneScene(entry));
1592
+ scenes2.push(cloneScene(entry));
1555
1593
  }
1556
- return scenes;
1594
+ return scenes2;
1557
1595
  }
1558
1596
  var CanvasScenesStore = class {
1559
1597
  scenes;
@@ -1578,9 +1616,9 @@ var CanvasScenesStore = class {
1578
1616
  currentIndex
1579
1617
  };
1580
1618
  }
1581
- commit(scenes = this.scenes) {
1582
- this.scenes = scenes;
1583
- if (this.currentId && !scenes.some((s) => s.id === this.currentId)) this.currentId = null;
1619
+ commit(scenes2 = this.scenes) {
1620
+ this.scenes = scenes2;
1621
+ if (this.currentId && !scenes2.some((s) => s.id === this.currentId)) this.currentId = null;
1584
1622
  this.cached = this.snapshot();
1585
1623
  this.onChange?.(this.cached);
1586
1624
  for (const listener of this.listeners) listener(this.cached);
@@ -1615,11 +1653,11 @@ var CanvasScenesStore = class {
1615
1653
  nodeIds: input.nodeIds
1616
1654
  });
1617
1655
  if (!isValidCanvasScene(scene)) throw new Error("[CanvasScenesStore] Invalid scene viewport.");
1618
- const scenes = [...this.scenes];
1619
- const at = index === void 0 ? scenes.length : Math.max(0, Math.min(scenes.length, index));
1620
- scenes.splice(at, 0, scene);
1656
+ const scenes2 = [...this.scenes];
1657
+ const at = index === void 0 ? scenes2.length : Math.max(0, Math.min(scenes2.length, index));
1658
+ scenes2.splice(at, 0, scene);
1621
1659
  this.currentId = scene.id;
1622
- this.commit(scenes);
1660
+ this.commit(scenes2);
1623
1661
  return scene;
1624
1662
  }
1625
1663
  /** Patches a scene's name, viewport or node ids. Returns the updated scene. */
@@ -1635,9 +1673,9 @@ var CanvasScenesStore = class {
1635
1673
  id
1636
1674
  });
1637
1675
  if (!isValidCanvasScene(next)) throw new Error("[CanvasScenesStore] Invalid scene viewport.");
1638
- const scenes = [...this.scenes];
1639
- scenes[index] = next;
1640
- this.commit(scenes);
1676
+ const scenes2 = [...this.scenes];
1677
+ scenes2[index] = next;
1678
+ this.commit(scenes2);
1641
1679
  return next;
1642
1680
  }
1643
1681
  rename(id, name) {
@@ -1649,10 +1687,10 @@ var CanvasScenesStore = class {
1649
1687
  if (from === -1) return;
1650
1688
  const to = Math.max(0, Math.min(this.scenes.length - 1, Math.trunc(toIndex2)));
1651
1689
  if (from === to) return;
1652
- const scenes = [...this.scenes];
1653
- const [scene] = scenes.splice(from, 1);
1654
- scenes.splice(to, 0, scene);
1655
- this.commit(scenes);
1690
+ const scenes2 = [...this.scenes];
1691
+ const [scene] = scenes2.splice(from, 1);
1692
+ scenes2.splice(to, 0, scene);
1693
+ this.commit(scenes2);
1656
1694
  }
1657
1695
  /** Reorders scenes to match `ids`; unknown ids are ignored and missing scenes keep their relative order at the end. */
1658
1696
  reorder(ids) {
@@ -1867,8 +1905,8 @@ function combineShapeNodes(nodes, ids, operation, options = {}) {
1867
1905
  } else {
1868
1906
  report = { engine: "polygon" };
1869
1907
  const operands = ordered.map((node) => shapeNodeToPolygon(node, lookup, options));
1870
- const write = (polygon) => toBezierPath(
1871
- polygonToSvgPath(polygon, {
1908
+ const write = (polygon2) => toBezierPath(
1909
+ polygonToSvgPath(polygon2, {
1872
1910
  precision: 9,
1873
1911
  simplify: options.simplify,
1874
1912
  curves: options.curves ?? "fit",
@@ -2621,10 +2659,10 @@ function layoutFrameInner(s, frame) {
2621
2659
  } else {
2622
2660
  lines.push(items.map((_, i) => i));
2623
2661
  }
2624
- for (const line3 of lines) {
2625
- const fixed = line3.filter((i) => !items[i].fillMain).reduce((sum, i) => sum + items[i].main, 0);
2626
- const gaps = gap * Math.max(line3.length - 1, 0);
2627
- const fills = line3.filter((i) => items[i].fillMain);
2662
+ for (const line4 of lines) {
2663
+ const fixed = line4.filter((i) => !items[i].fillMain).reduce((sum, i) => sum + items[i].main, 0);
2664
+ const gaps = gap * Math.max(line4.length - 1, 0);
2665
+ const fills = line4.filter((i) => items[i].fillMain);
2628
2666
  if (fills.length > 0) distribute(items, fills, innerMainFixed - fixed - (autoGap ? 0 : gaps));
2629
2667
  }
2630
2668
  for (const it of items) {
@@ -2637,11 +2675,11 @@ function layoutFrameInner(s, frame) {
2637
2675
  for (const it of items) if (!it.fillCross) it.baseline = itemBaseline(s, it.id, 0);
2638
2676
  }
2639
2677
  const extents = [];
2640
- for (const line3 of lines) {
2641
- const gaps = gap * Math.max(line3.length - 1, 0);
2642
- const lineBase = line3.reduce((m, i) => Math.max(m, items[i].baseline ?? 0), 0);
2643
- for (const i of line3) items[i].baseOff = items[i].baseline !== void 0 ? lineBase - items[i].baseline : 0;
2644
- const inLine = line3.map((i) => items[i]);
2678
+ for (const line4 of lines) {
2679
+ const gaps = gap * Math.max(line4.length - 1, 0);
2680
+ const lineBase = line4.reduce((m, i) => Math.max(m, items[i].baseline ?? 0), 0);
2681
+ for (const i of line4) items[i].baseOff = items[i].baseline !== void 0 ? lineBase - items[i].baseline : 0;
2682
+ const inLine = line4.map((i) => items[i]);
2645
2683
  const mainUsed = inLine.reduce((sum, it) => sum + it.main, 0) + gaps;
2646
2684
  const allFill = inLine.every((it) => it.fillCross);
2647
2685
  const cross = inLine.filter((it) => allFill || !it.fillCross).reduce((m, it) => Math.max(m, it.baseOff + it.cross), 0);
@@ -2688,13 +2726,13 @@ function layoutFrameInner(s, frame) {
2688
2726
  }
2689
2727
  }
2690
2728
  }
2691
- lines.forEach((line3, li) => {
2729
+ lines.forEach((line4, li) => {
2692
2730
  const [used, ownCross] = extents[li];
2693
2731
  const lineCross = single ? innerCross : ownCross;
2694
- const total = used - gap * Math.max(line3.length - 1, 0);
2695
- let [pos, step] = mainOffsets(alignMain, innerMain, total, line3.length, gap);
2732
+ const total = used - gap * Math.max(line4.length - 1, 0);
2733
+ let [pos, step] = mainOffsets(alignMain, innerMain, total, line4.length, gap);
2696
2734
  pos += horizontal ? pl : pt;
2697
- for (const i of line3) {
2735
+ for (const i of line4) {
2698
2736
  const it = items[i];
2699
2737
  const crossSize = it.fillCross ? clampLayoutSize(lineCross, it.minCross, it.maxCross) : it.cross;
2700
2738
  let off = 0;
@@ -3672,37 +3710,37 @@ function inside(out, inner, outer) {
3672
3710
  }
3673
3711
  function measureBetween(a, b) {
3674
3712
  const out = [];
3675
- const A = toBox(a);
3713
+ const A2 = toBox(a);
3676
3714
  const B = toBox(b);
3677
- if (!finiteBox(A) || !finiteBox(B)) return out;
3678
- if (contains(B, A)) {
3679
- inside(out, A, B);
3715
+ if (!finiteBox(A2) || !finiteBox(B)) return out;
3716
+ if (contains(B, A2)) {
3717
+ inside(out, A2, B);
3680
3718
  return out;
3681
3719
  }
3682
- if (contains(A, B)) {
3683
- inside(out, B, A);
3720
+ if (contains(A2, B)) {
3721
+ inside(out, B, A2);
3684
3722
  return out;
3685
3723
  }
3686
- const ox = overlapMid(A.x0, A.x1, B.x0, B.x1);
3687
- const oy = overlapMid(A.y0, A.y1, B.y0, B.y1);
3688
- const overlapping = A.x0 < B.x1 && B.x0 < A.x1 && A.y0 < B.y1 && B.y0 < A.y1;
3724
+ const ox = overlapMid(A2.x0, A2.x1, B.x0, B.x1);
3725
+ const oy = overlapMid(A2.y0, A2.y1, B.y0, B.y1);
3726
+ const overlapping = A2.x0 < B.x1 && B.x0 < A2.x1 && A2.y0 < B.y1 && B.y0 < A2.y1;
3689
3727
  if (overlapping && ox !== null && oy !== null) {
3690
- measured(out, A.x0, oy, B.x0, oy);
3691
- measured(out, A.x1, oy, B.x1, oy);
3692
- measured(out, ox, A.y0, ox, B.y0);
3693
- measured(out, ox, A.y1, ox, B.y1);
3728
+ measured(out, A2.x0, oy, B.x0, oy);
3729
+ measured(out, A2.x1, oy, B.x1, oy);
3730
+ measured(out, ox, A2.y0, ox, B.y0);
3731
+ measured(out, ox, A2.y1, ox, B.y1);
3694
3732
  return out;
3695
3733
  }
3696
- const cx = (A.x0 + A.x1) / 2;
3697
- const cy = (A.y0 + A.y1) / 2;
3698
- const gapX = B.x0 >= A.x1 ? [A.x1, B.x0] : B.x1 <= A.x0 ? [A.x0, B.x1] : null;
3734
+ const cx = (A2.x0 + A2.x1) / 2;
3735
+ const cy = (A2.y0 + A2.y1) / 2;
3736
+ const gapX = B.x0 >= A2.x1 ? [A2.x1, B.x0] : B.x1 <= A2.x0 ? [A2.x0, B.x1] : null;
3699
3737
  if (gapX) {
3700
3738
  const [from, to] = gapX;
3701
3739
  const y = oy ?? cy;
3702
3740
  measured(out, from, y, to, y);
3703
3741
  if (oy === null) extension(out, to, y, to, y < B.y0 ? B.y0 : B.y1);
3704
3742
  }
3705
- const gapY = B.y0 >= A.y1 ? [A.y1, B.y0] : B.y1 <= A.y0 ? [A.y0, B.y1] : null;
3743
+ const gapY = B.y0 >= A2.y1 ? [A2.y1, B.y0] : B.y1 <= A2.y0 ? [A2.y0, B.y1] : null;
3706
3744
  if (gapY) {
3707
3745
  const [from, to] = gapY;
3708
3746
  const x = ox ?? cx;
@@ -3713,12 +3751,12 @@ function measureBetween(a, b) {
3713
3751
  }
3714
3752
  function measureToLine(a, orientation, at) {
3715
3753
  const out = [];
3716
- const A = toBox(a);
3717
- if (!finiteBox(A) || !Number.isFinite(at)) return out;
3754
+ const A2 = toBox(a);
3755
+ if (!finiteBox(A2) || !Number.isFinite(at)) return out;
3718
3756
  const vertical = orientation === "vertical";
3719
- const cx = (A.x0 + A.x1) / 2;
3720
- const cy = (A.y0 + A.y1) / 2;
3721
- const [lo, hi] = vertical ? [A.x0, A.x1] : [A.y0, A.y1];
3757
+ const cx = (A2.x0 + A2.x1) / 2;
3758
+ const cy = (A2.y0 + A2.y1) / 2;
3759
+ const [lo, hi] = vertical ? [A2.x0, A2.x1] : [A2.y0, A2.y1];
3722
3760
  const seg = (from, to) => vertical ? measured(out, from, cy, to, cy) : measured(out, cx, from, cx, to);
3723
3761
  if (at >= hi) seg(hi, at);
3724
3762
  else if (at <= lo) seg(at, lo);
@@ -4078,17 +4116,17 @@ function readNodeStyleProperty(style, prop) {
4078
4116
  function writeNodeStyleProperty(style, prop, value, unitless = false) {
4079
4117
  if (typeof style === "string") {
4080
4118
  const name = kebab(prop);
4081
- const text = value === void 0 ? void 0 : typeof value === "number" && !unitless ? `${value}px` : String(value);
4119
+ const text2 = value === void 0 ? void 0 : typeof value === "number" && !unitless ? `${value}px` : String(value);
4082
4120
  const decls = [];
4083
- let placed = text === void 0;
4121
+ let placed = text2 === void 0;
4084
4122
  for (const [key, current] of parseDeclarations(style)) {
4085
4123
  if (key.toLowerCase() !== name) decls.push([key, current]);
4086
4124
  else if (!placed) {
4087
- decls.push([name, text]);
4125
+ decls.push([name, text2]);
4088
4126
  placed = true;
4089
4127
  }
4090
4128
  }
4091
- if (!placed) decls.push([name, text]);
4129
+ if (!placed) decls.push([name, text2]);
4092
4130
  return decls.map(([k, v]) => `${k}: ${v}`).join("; ");
4093
4131
  }
4094
4132
  const next = { ...style ?? {} };
@@ -5331,7 +5369,7 @@ function timing(options, duration) {
5331
5369
  direction: loop === "ping-pong" ? rate < 0 ? "alternate-reverse" : "alternate" : rate < 0 ? "reverse" : "normal"
5332
5370
  };
5333
5371
  }
5334
- var cssIdent = (text) => text.replace(/[^A-Za-z0-9_-]/g, "-").replace(/^(\d)/, "_$1");
5372
+ var cssIdent = (text2) => text2.replace(/[^A-Za-z0-9_-]/g, "-").replace(/^(\d)/, "_$1");
5335
5373
  function exportCssAnimation(nodes, nodeId, options = {}) {
5336
5374
  const duration = options.duration ?? getAnimationDuration(nodes.filter((n3) => n3.id === nodeId));
5337
5375
  const props = getCssPropertyAnimations(nodes, nodeId, { ...options, duration });
@@ -7293,8 +7331,8 @@ function swapCanvasInstance(nodes, ids, componentId, options = {}) {
7293
7331
  if (options.keepTextOverridesOnly) {
7294
7332
  for (const d of g.subtree(id)) {
7295
7333
  const layer = updates.get(d) ?? g.get(d);
7296
- const text = typeof layer.type === "string" && (options.textTypes ?? ["text"]).includes(layer.type);
7297
- const keep = getNodeOverrides(layer).filter((gr) => text || d === id && gr === "size");
7334
+ const text2 = typeof layer.type === "string" && (options.textTypes ?? ["text"]).includes(layer.type);
7335
+ const keep = getNodeOverrides(layer).filter((gr) => text2 || d === id && gr === "size");
7298
7336
  updates.set(d, setOverrides(layer, keep));
7299
7337
  }
7300
7338
  }
@@ -8454,9 +8492,9 @@ function estimateDiagramNodeSize(node) {
8454
8492
  }
8455
8493
  var IMAGE_LABEL_HEIGHT = 24;
8456
8494
  function diagramImageSize(node) {
8457
- const num2 = (v) => typeof v === "number" && v > 0 ? v : void 0;
8458
- const w = num2(node.data?.w);
8459
- const h = num2(node.data?.h);
8495
+ const num4 = (v) => typeof v === "number" && v > 0 ? v : void 0;
8496
+ const w = num4(node.data?.w);
8497
+ const h = num4(node.data?.h);
8460
8498
  return { width: w ?? h ?? 96, height: h ?? w ?? 96 };
8461
8499
  }
8462
8500
  function extraLines(node) {
@@ -8475,6 +8513,8 @@ function rankdir(direction) {
8475
8513
  }
8476
8514
  function autoLayoutDiagram(graph, options = {}) {
8477
8515
  const measure = options.measure ?? estimateDiagramNodeSize;
8516
+ const custom = getFamilyLayout(options.family);
8517
+ if (custom) return custom(graph, { v: 1 }, { ...options, measure });
8478
8518
  const nodeSep = options.nodeSep ?? 48;
8479
8519
  const rankSep = options.rankSep ?? 72;
8480
8520
  const pad = options.groupPadding ?? 24;
@@ -8573,6 +8613,8 @@ function push(map, key, value) {
8573
8613
  }
8574
8614
  function ensureDiagramLayout(graph, meta, options) {
8575
8615
  const measure = options?.measure ?? estimateDiagramNodeSize;
8616
+ const custom = getFamilyLayout(options?.family);
8617
+ if (custom) return custom(graph, meta, { ...options ?? {}, measure });
8576
8618
  const stored = meta.layout ?? {};
8577
8619
  const allIds = [...graph.nodes.map((n3) => n3.id), ...graph.groups.map((g) => g.id)];
8578
8620
  const missing = allIds.filter((id) => !stored[id]);
@@ -8837,14 +8879,14 @@ var DiagramStream = class {
8837
8879
  layout = null;
8838
8880
  /** Reads the source so far. `complete` when nothing more will arrive. */
8839
8881
  update(source, complete = false) {
8840
- const text = streamedDiagramText(source);
8841
- const parsed = parseMermaid(text);
8882
+ const text2 = streamedDiagramText(source);
8883
+ const parsed = parseMermaid(text2);
8842
8884
  const document2 = !complete ? { ...parsed, graph: connectedDiagramOnly(parsed.graph) } : parsed;
8843
8885
  if (document2.tier !== "editable" || !document2.graph.nodes.length) return { document: document2, layout: this.layout && complete ? null : this.layout, relaid: false };
8844
8886
  const key = fingerprint(document2.graph);
8845
8887
  if (key === this.lastKey && this.layout) return { document: document2, layout: this.layout, relaid: false };
8846
8888
  this.lastKey = key;
8847
- this.layout = ensureDiagramLayout(document2.graph, document2.meta, this.options);
8889
+ this.layout = ensureDiagramLayout(document2.graph, document2.meta, { family: document2.family, ...this.options });
8848
8890
  return { document: document2, layout: this.layout, relaid: true };
8849
8891
  }
8850
8892
  /** Forgets the previous layout (a new source). */
@@ -8863,6 +8905,1881 @@ function streamedDiagramText(source) {
8863
8905
  }
8864
8906
  var easeDiagramTween = (t) => 1 - Math.pow(1 - Math.max(0, Math.min(1, t)), 3);
8865
8907
 
8908
+ // src/canvas/mermaid/theme.ts
8909
+ var DIAGRAM_SVG_LIGHT_THEME = {
8910
+ background: "#ffffff",
8911
+ nodeFill: "#ffffff",
8912
+ nodeStroke: "#0f172a",
8913
+ text: "#0f172a",
8914
+ edge: "#64748b",
8915
+ edgeLabelBackground: "#ffffff",
8916
+ groupFill: "#f8fafc",
8917
+ groupStroke: "#cbd5e1",
8918
+ groupText: "#475569",
8919
+ fontFamily: 'system-ui, -apple-system, "Segoe UI", sans-serif',
8920
+ fontSize: 13
8921
+ };
8922
+ var DIAGRAM_SVG_DARK_THEME = {
8923
+ background: "#0f172a",
8924
+ nodeFill: "#1e293b",
8925
+ nodeStroke: "#e2e8f0",
8926
+ text: "#f1f5f9",
8927
+ edge: "#94a3b8",
8928
+ edgeLabelBackground: "#0f172a",
8929
+ groupFill: "#111c33",
8930
+ groupStroke: "#334155",
8931
+ groupText: "#94a3b8",
8932
+ fontFamily: 'system-ui, -apple-system, "Segoe UI", sans-serif',
8933
+ fontSize: 13
8934
+ };
8935
+
8936
+ // src/canvas/mermaid/scene-kit.ts
8937
+ var PALETTE_LIGHT = ["#4e79a7", "#f28e2b", "#59a14f", "#e15759", "#76b7b2", "#edc948", "#b07aa1", "#ff9da7", "#9c755f", "#bab0ac", "#8cd17d", "#86bcb6"];
8938
+ var PALETTE_DARK = ["#7aa6d6", "#ffad5c", "#7fcf73", "#ff8587", "#9fdcd6", "#ffe07a", "#d4a2c6", "#ffc2c9", "#c49a82", "#d9d0cc", "#b0eba3", "#acd8d3"];
8939
+ var DIAGRAM_SCENE_LIGHT_THEME = {
8940
+ ...DIAGRAM_SVG_LIGHT_THEME,
8941
+ palette: PALETTE_LIGHT,
8942
+ paletteText: "#0f172a",
8943
+ grid: "#cbd5e1",
8944
+ mutedText: "#64748b",
8945
+ selection: "#2563eb"
8946
+ };
8947
+ var DIAGRAM_SCENE_DARK_THEME = {
8948
+ ...DIAGRAM_SVG_DARK_THEME,
8949
+ palette: PALETTE_DARK,
8950
+ paletteText: "#0f172a",
8951
+ grid: "#334155",
8952
+ mutedText: "#94a3b8",
8953
+ selection: "#60a5fa"
8954
+ };
8955
+ var DIAGRAM_TITLE_TARGET = "::title";
8956
+ function sceneColor(theme, i) {
8957
+ return theme.palette[(i % theme.palette.length + theme.palette.length) % theme.palette.length];
8958
+ }
8959
+ function estimateTextWidth2(text2, size) {
8960
+ return text2.length * size * 0.58;
8961
+ }
8962
+
8963
+ // src/canvas/mermaid/families/pie.ts
8964
+ var M = PIE_METRICS;
8965
+ var pieScene = ({ graph, theme }) => {
8966
+ const geo = pieGeometry(graph);
8967
+ const marks = [];
8968
+ for (const slice of geo.slices) {
8969
+ if (!slice.drawn) continue;
8970
+ const r = geo.radius;
8971
+ marks.push({
8972
+ kind: "path",
8973
+ key: `wedge:${slice.id}`,
8974
+ role: "slice",
8975
+ target: slice.id,
8976
+ d: slice.path,
8977
+ fill: sceneColor(theme, slice.colorIndex),
8978
+ stroke: theme.background,
8979
+ strokeWidth: 2,
8980
+ box: { x: geo.cx - r, y: geo.cy - r, width: r * 2, height: r * 2 }
8981
+ });
8982
+ }
8983
+ marks.push({ kind: "circle", key: "outer", role: "outline", cx: geo.cx, cy: geo.cy, r: geo.outerRadius, fill: "none", stroke: theme.nodeStroke, strokeWidth: M.outerStrokeWidth });
8984
+ for (const slice of geo.slices) {
8985
+ if (!slice.drawn) continue;
8986
+ marks.push({ kind: "text", key: `percent:${slice.id}`, role: "slice-label", target: slice.id, x: slice.labelX, y: slice.labelY, text: slice.labelText, anchor: "middle", baseline: "bottom", size: 17, fill: theme.paletteText });
8987
+ }
8988
+ for (const entry of geo.legend) {
8989
+ marks.push(
8990
+ { kind: "rect", key: `swatch:${entry.sliceId}`, role: "legend", target: entry.sliceId, x: entry.x, y: entry.y, width: M.legendRectSize, height: M.legendRectSize, fill: sceneColor(theme, entry.colorIndex), stroke: sceneColor(theme, entry.colorIndex) },
8991
+ {
8992
+ kind: "text",
8993
+ key: `legend:${entry.sliceId}`,
8994
+ role: "legend",
8995
+ target: entry.sliceId,
8996
+ x: entry.x + M.legendRectSize + M.legendSpacing,
8997
+ y: entry.y + M.legendRectSize / 2,
8998
+ text: entry.text,
8999
+ anchor: "start",
9000
+ baseline: "middle",
9001
+ size: M.legendFontSize,
9002
+ fill: theme.text
9003
+ }
9004
+ );
9005
+ }
9006
+ if (geo.title)
9007
+ marks.push({ kind: "text", key: "title", role: "title", target: DIAGRAM_TITLE_TARGET, x: geo.title.x, y: geo.title.y, text: geo.title.text, anchor: "middle", baseline: "bottom", size: M.titleFontSize, fill: theme.text });
9008
+ return marks;
9009
+ };
9010
+
9011
+ // src/canvas/mermaid/families/charts.ts
9012
+ var num2 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
9013
+ var numbers = (v) => Array.isArray(v) ? v.map(num2) : [];
9014
+ var text = (v) => typeof v === "string" ? v : "";
9015
+ function chartTheme(theme) {
9016
+ return {
9017
+ background: theme.background,
9018
+ surface: theme.background,
9019
+ text: theme.text,
9020
+ mutedText: theme.mutedText,
9021
+ grid: theme.grid,
9022
+ axis: theme.mutedText,
9023
+ selection: theme.selection,
9024
+ fontFamily: theme.fontFamily
9025
+ };
9026
+ }
9027
+ function xyChartSpec(graph, palette) {
9028
+ const data = graph.data ?? {};
9029
+ const longest = Math.max(0, ...graph.nodes.map((n3) => numbers(n3.data?.values).length));
9030
+ let categories = Array.isArray(data.categories) ? data.categories.map(String) : [];
9031
+ const xMin = num2(data.xMin);
9032
+ const xMax = num2(data.xMax);
9033
+ if (!categories.length && longest) {
9034
+ categories = Array.from(
9035
+ { length: longest },
9036
+ (_, i) => xMin !== null && xMax !== null ? String(Math.round((xMin + (xMax - xMin) * i / Math.max(1, longest - 1)) * 100) / 100) : String(i + 1)
9037
+ );
9038
+ }
9039
+ const bars = graph.nodes.some((n3) => n3.shape === "bar");
9040
+ return createChartSpec({
9041
+ type: bars ? "bar" : "line",
9042
+ title: graph.title ?? "",
9043
+ categories,
9044
+ series: graph.nodes.map((n3) => ({ id: n3.id, name: n3.label, values: numbers(n3.data?.values), type: n3.shape === "line" ? "line" : "bar" })),
9045
+ orientation: data.horizontal ? "horizontal" : "vertical",
9046
+ xAxis: { show: true, title: text(data.xTitle), min: null, max: null, step: null, gridlines: false, format: {} },
9047
+ yAxis: { show: true, title: text(data.yTitle), min: num2(data.yMin), max: num2(data.yMax), step: null, gridlines: true, format: {} },
9048
+ legend: { show: graph.nodes.some((n3) => n3.data?.titled), position: "top" },
9049
+ ...palette ? { palette: [...palette] } : {}
9050
+ });
9051
+ }
9052
+ function radarChartSpec(graph, palette) {
9053
+ const data = graph.data ?? {};
9054
+ return createChartSpec({
9055
+ type: "radar",
9056
+ title: graph.title ?? "",
9057
+ categories: Array.isArray(data.axes) ? data.axes.map(String) : [],
9058
+ series: graph.nodes.map((n3) => ({ id: n3.id, name: n3.label, values: numbers(n3.data?.values) })),
9059
+ yAxis: { show: true, title: "", min: num2(data.min), max: num2(data.max), step: null, gridlines: true, format: {} },
9060
+ legend: { show: data.showLegend !== false, position: "top" },
9061
+ ...palette ? { palette: [...palette] } : {}
9062
+ });
9063
+ }
9064
+ function targetOf(target) {
9065
+ if (!target) return void 0;
9066
+ if (target.kind === "series" || target.kind === "point") return target.seriesId;
9067
+ if (target.kind === "title") return DIAGRAM_TITLE_TARGET;
9068
+ return void 0;
9069
+ }
9070
+ function toDiagramMarks(marks, x, y) {
9071
+ return marks.filter((m) => m.role !== "selection" && m.role !== "drag-readout").map((m) => {
9072
+ const base = { key: m.key, role: m.role, ...targetOf(m.target) ? { target: targetOf(m.target) } : {}, ...m.opacity !== void 0 ? { opacity: m.opacity } : {} };
9073
+ switch (m.kind) {
9074
+ case "rect":
9075
+ return { ...base, kind: "rect", x: m.x + x, y: m.y + y, width: m.width, height: m.height, fill: m.fill, stroke: m.stroke, strokeWidth: m.strokeWidth, radius: m.radius };
9076
+ case "circle":
9077
+ return { ...base, kind: "circle", cx: m.cx + x, cy: m.cy + y, r: m.r, fill: m.fill, stroke: m.stroke, strokeWidth: m.strokeWidth };
9078
+ case "line":
9079
+ return { ...base, kind: "line", x1: m.x1 + x, y1: m.y1 + y, x2: m.x2 + x, y2: m.y2 + y, stroke: m.stroke, strokeWidth: m.strokeWidth, dash: m.dash };
9080
+ case "text":
9081
+ return { ...base, kind: "text", x: m.x + x, y: m.y + y, text: m.text, anchor: m.anchor, baseline: m.baseline, size: m.size, weight: m.weight, fill: m.fill, rotate: m.rotate };
9082
+ case "path":
9083
+ return {
9084
+ ...base,
9085
+ kind: "path",
9086
+ // Chart paths are absolute, so the whole path moves with a translate prefix.
9087
+ d: x || y ? translatePath(m.d, x, y) : m.d,
9088
+ fill: m.fill,
9089
+ stroke: m.stroke,
9090
+ strokeWidth: m.strokeWidth,
9091
+ dash: m.dash
9092
+ };
9093
+ }
9094
+ });
9095
+ }
9096
+ function translatePath(d, dx, dy) {
9097
+ let i = 0;
9098
+ return d.replace(/-?\d*\.?\d+(?:e-?\d+)?/gi, (v) => String(Math.round((Number(v) + (i++ % 2 === 0 ? dx : dy)) * 100) / 100));
9099
+ }
9100
+ var xyChartScene = ({ graph, theme }) => {
9101
+ const box = XY_CHART_BOX;
9102
+ const scene = layoutChart(xyChartSpec(graph, theme.palette), { width: box.width, height: box.height, theme: chartTheme(theme) });
9103
+ return toDiagramMarks(scene.marks, box.x, box.y);
9104
+ };
9105
+ var radarScene = ({ graph, theme }) => {
9106
+ const box = RADAR_CHART_BOX;
9107
+ const scene = layoutChart(radarChartSpec(graph, theme.palette), { width: box.width, height: box.height, theme: chartTheme(theme) });
9108
+ return toDiagramMarks(scene.marks, box.x, box.y);
9109
+ };
9110
+
9111
+ // src/canvas/mermaid/families/sequence.ts
9112
+ var M2 = SEQUENCE_METRICS;
9113
+ var LABEL_SIZE = 14;
9114
+ var LINE_HEIGHT = 1.25;
9115
+ var SMALL_SIZE = 13;
9116
+ var TITLE_SIZE = 18;
9117
+ var NOTE_COLOR = 5;
9118
+ function displayLines(label) {
9119
+ let text2 = label;
9120
+ if (text2.startsWith("`") && text2.endsWith("`")) text2 = text2.slice(1, -1);
9121
+ return text2.replace(/<br\s*\/?>/gi, "\n").replace(/#quot;/g, '"').replace(/#(\d+);/g, (_, n3) => String.fromCharCode(Number(n3))).split("\n");
9122
+ }
9123
+ function dashFor(pattern) {
9124
+ return pattern === "dotted" ? "6 4" : pattern === "invisible" ? "0 1" : void 0;
9125
+ }
9126
+ function markerFor(head) {
9127
+ if (head === "none" || head === "arrow_cross") return void 0;
9128
+ return head === "arrow_open" ? "arrow" : "arrowclosed";
9129
+ }
9130
+ function textLines(lines, base) {
9131
+ const lh = base.size * LINE_HEIGHT;
9132
+ const top = base.cy - (lines.length - 1) * lh / 2;
9133
+ return lines.map((text2, i) => ({
9134
+ kind: "text",
9135
+ key: lines.length === 1 ? base.key : `${base.key}:${i}`,
9136
+ role: base.role,
9137
+ ...base.target ? { target: base.target } : {},
9138
+ x: base.x,
9139
+ y: top + i * lh,
9140
+ text: text2,
9141
+ anchor: base.anchor ?? "middle",
9142
+ baseline: "middle",
9143
+ size: base.size,
9144
+ fill: base.fill,
9145
+ ...base.weight ? { weight: base.weight } : {}
9146
+ }));
9147
+ }
9148
+ function participantMarks(node, box, mirror, theme) {
9149
+ const prefix = mirror ? "mirror" : "participant";
9150
+ const role = mirror ? "participant-mirror" : "participant";
9151
+ const lines = displayLines(node.label || node.id);
9152
+ if (node.shape !== "actor") {
9153
+ return [
9154
+ { kind: "rect", key: `${prefix}:${node.id}`, role, target: node.id, ...box, fill: theme.nodeFill, stroke: theme.nodeStroke, strokeWidth: 1, radius: 3 },
9155
+ ...textLines(lines, { key: `${prefix}-label:${node.id}`, role: `${role}-label`, target: node.id, x: box.x + box.width / 2, cy: box.y + box.height / 2, size: LABEL_SIZE, fill: theme.text })
9156
+ ];
9157
+ }
9158
+ const lh = LABEL_SIZE * LINE_HEIGHT;
9159
+ const labelHeight = lines.length * lh;
9160
+ const scale = Math.min(28 / 40, 34 / 46);
9161
+ const figTop = box.y + box.height - labelHeight - 2 - 34 + (34 - 46 * scale) / 2;
9162
+ const figLeft = box.x + box.width / 2 - 20 * scale;
9163
+ const fx = (v) => figLeft + v * scale;
9164
+ const fy = (v) => figTop + v * scale;
9165
+ const d = `M${fx(20)},${fy(15)} V${fy(31)} M${fx(6)},${fy(21)} H${fx(34)} M${fx(20)},${fy(31)} L${fx(9)},${fy(44)} M${fx(20)},${fy(31)} L${fx(31)},${fy(44)}`;
9166
+ return [
9167
+ { kind: "circle", key: `${prefix}-head:${node.id}`, role: `${role}-figure`, target: node.id, cx: fx(20), cy: fy(8), r: 7 * scale, fill: theme.nodeFill, stroke: theme.nodeStroke, strokeWidth: 1.5 },
9168
+ {
9169
+ kind: "path",
9170
+ key: `${prefix}-body:${node.id}`,
9171
+ role: `${role}-figure`,
9172
+ target: node.id,
9173
+ d,
9174
+ fill: "none",
9175
+ stroke: theme.nodeStroke,
9176
+ strokeWidth: 1.5,
9177
+ box: { x: fx(6), y: fy(15), width: 28 * scale, height: 29 * scale }
9178
+ },
9179
+ ...textLines(lines, {
9180
+ key: `${prefix}-label:${node.id}`,
9181
+ role: `${role}-label`,
9182
+ target: node.id,
9183
+ x: box.x + box.width / 2,
9184
+ cy: box.y + box.height - labelHeight / 2,
9185
+ size: LABEL_SIZE,
9186
+ fill: theme.text
9187
+ })
9188
+ ];
9189
+ }
9190
+ function crossMark(key, target, x, y, dir, stroke) {
9191
+ const cx = x - dir * 2.8;
9192
+ const h = 2.8;
9193
+ return {
9194
+ kind: "path",
9195
+ key,
9196
+ role: "message-head",
9197
+ target,
9198
+ d: `M${cx - h},${y - h} L${cx + h},${y + h} M${cx + h},${y - h} L${cx - h},${y + h}`,
9199
+ stroke,
9200
+ strokeWidth: 1.5
9201
+ };
9202
+ }
9203
+ var sequenceScene = ({ graph, theme }) => {
9204
+ const geo = sequenceGeometry(graph);
9205
+ const marks = [];
9206
+ for (const group of graph.groups) {
9207
+ const box = geo.boxes.get(group.id);
9208
+ if (!box) continue;
9209
+ const color = typeof group.data?.color === "string" ? group.data.color : void 0;
9210
+ marks.push(
9211
+ { kind: "rect", key: `box:${group.id}`, role: "box", target: group.id, ...box, fill: color ?? "none", stroke: theme.groupStroke, strokeWidth: 1 },
9212
+ ...textLines(displayLines(group.label), {
9213
+ key: `box-label:${group.id}`,
9214
+ role: "box-label",
9215
+ target: group.id,
9216
+ x: box.x + box.width / 2,
9217
+ cy: box.y + 4 + LABEL_SIZE * LINE_HEIGHT / 2,
9218
+ size: LABEL_SIZE,
9219
+ weight: 600,
9220
+ fill: theme.groupText
9221
+ })
9222
+ );
9223
+ }
9224
+ if (graph.title) {
9225
+ const lefts = [...[...geo.columns.values()].map((c) => c.x), ...[...geo.boxes.values()].map((b) => b.x)];
9226
+ const rights = [...[...geo.columns.values()].map((c) => c.x + c.width), ...[...geo.boxes.values()].map((b) => b.x + b.width)];
9227
+ const tops = [0, ...[...geo.boxes.values()].map((b) => b.y)];
9228
+ const minX = lefts.length ? Math.min(...lefts) : 0;
9229
+ const maxX = rights.length ? Math.max(...rights) : 240;
9230
+ marks.push({ kind: "text", key: "title", role: "title", target: DIAGRAM_TITLE_TARGET, x: (minX + maxX) / 2, y: Math.min(...tops) - 38, text: graph.title, anchor: "middle", baseline: "middle", size: TITLE_SIZE, weight: 600, fill: theme.text });
9231
+ }
9232
+ [...geo.fragments].map((f, i) => ({ f, i })).sort((a, b) => a.f.depth - b.f.depth || a.i - b.i).forEach(({ f, i }) => {
9233
+ marks.push({ kind: "rect", key: `fragment:${i}`, role: "fragment", x: f.x, y: f.y, width: f.width, height: f.height, fill: "none", stroke: theme.mutedText, strokeWidth: 1.5 });
9234
+ const tabW = estimateTextWidth2(f.keyword, SMALL_SIZE) + 22;
9235
+ const tabH = SMALL_SIZE * LINE_HEIGHT + 4;
9236
+ marks.push(
9237
+ {
9238
+ kind: "path",
9239
+ key: `fragment-tab:${i}`,
9240
+ role: "fragment-tab",
9241
+ d: `M${f.x},${f.y} H${f.x + tabW} V${f.y + tabH * 0.6} L${f.x + tabW - 8},${f.y + tabH} H${f.x} Z`,
9242
+ fill: theme.groupFill,
9243
+ stroke: theme.mutedText,
9244
+ strokeWidth: 1.5
9245
+ },
9246
+ { kind: "text", key: `fragment-keyword:${i}`, role: "fragment-keyword", x: f.x + 8, y: f.y + tabH / 2, text: f.keyword, anchor: "start", baseline: "middle", size: SMALL_SIZE, weight: 600, fill: theme.groupText }
9247
+ );
9248
+ if (f.text)
9249
+ marks.push({ kind: "text", key: `fragment-text:${i}`, role: "fragment-text", x: f.x + f.width / 2, y: f.y + 3, text: `[${f.text}]`, anchor: "middle", baseline: "top", size: SMALL_SIZE, weight: 600, fill: theme.text });
9250
+ f.dividers.forEach((d, j) => {
9251
+ marks.push({ kind: "line", key: `fragment-divider:${i}:${j}`, role: "fragment-divider", x1: f.x, y1: d.y, x2: f.x + f.width, y2: d.y, stroke: theme.mutedText, strokeWidth: 1.5, dash: "6 4" });
9252
+ if (d.text)
9253
+ marks.push({ kind: "text", key: `fragment-divider-text:${i}:${j}`, role: "fragment-text", x: f.x + f.width / 2, y: d.y + 3, text: `[${d.text}]`, anchor: "middle", baseline: "top", size: SMALL_SIZE, weight: 600, fill: theme.text });
9254
+ });
9255
+ });
9256
+ for (const col of geo.columns.values())
9257
+ marks.push({ kind: "line", key: `lifeline:${col.id}`, role: "lifeline", target: col.id, x1: col.center, y1: geo.lifelineTop, x2: col.center, y2: geo.lifelineBottom, stroke: theme.grid, strokeWidth: 1 });
9258
+ geo.activations.forEach(
9259
+ (a, i) => marks.push({ kind: "rect", key: `activation:${i}`, role: "activation", x: a.x, y: a.top, width: M2.activationWidth, height: Math.max(8, a.bottom - a.top), fill: theme.groupFill, stroke: theme.edge, strokeWidth: 1 })
9260
+ );
9261
+ for (const node of graph.nodes) {
9262
+ const col = geo.columns.get(node.id);
9263
+ if (!col) continue;
9264
+ marks.push(...participantMarks(node, { x: col.x, y: 0, width: col.width, height: M2.actorHeight }, false, theme));
9265
+ marks.push(...participantMarks(node, { x: col.x, y: geo.lifelineBottom, width: col.width, height: M2.actorHeight }, true, theme));
9266
+ }
9267
+ const noteColor = sceneColor(theme, NOTE_COLOR);
9268
+ geo.notes.forEach((n3, i) => {
9269
+ const box = { x: n3.x, y: n3.y, width: n3.width, height: n3.height };
9270
+ marks.push(
9271
+ { kind: "rect", key: `note-bg:${i}`, role: "note", ...box, fill: theme.background },
9272
+ { kind: "rect", key: `note-fill:${i}`, role: "note", ...box, fill: noteColor, opacity: 0.3 },
9273
+ { kind: "rect", key: `note:${i}`, role: "note", ...box, fill: "none", stroke: noteColor, strokeWidth: 1 },
9274
+ ...textLines(displayLines(n3.text), { key: `note-text:${i}`, role: "note-text", x: n3.x + n3.width / 2, cy: n3.y + n3.height / 2, size: LABEL_SIZE, fill: theme.text })
9275
+ );
9276
+ });
9277
+ const edges = new Map(graph.edges.map((e) => [e.id, e]));
9278
+ const autonumber = !!graph.data?.autonumber;
9279
+ geo.messages.forEach((row, index) => {
9280
+ const edge = edges.get(row.edgeId);
9281
+ if (!edge) return;
9282
+ const x1 = geo.columns.get(edge.source)?.center ?? 0;
9283
+ const x2 = geo.columns.get(edge.target)?.center ?? 0;
9284
+ const y = row.y;
9285
+ const stroke = theme.edge;
9286
+ const strokeWidth = edge.pattern === "thick" ? 3.5 : 1.5;
9287
+ const dash = dashFor(edge.pattern);
9288
+ const markerEnd = markerFor(edge.arrowEnd);
9289
+ const markerStart = markerFor(edge.arrowStart);
9290
+ const heads = { ...markerEnd ? { markerEnd } : {}, ...markerStart ? { markerStart } : {} };
9291
+ let endX;
9292
+ let endDir;
9293
+ let startDir;
9294
+ let endY = y;
9295
+ let startY = y;
9296
+ if (row.self) {
9297
+ endX = x1 + 4;
9298
+ endDir = -1;
9299
+ startDir = -1;
9300
+ endY = y + 10;
9301
+ startY = y - 10;
9302
+ marks.push({
9303
+ kind: "path",
9304
+ key: `message:${edge.id}`,
9305
+ role: "message",
9306
+ target: edge.id,
9307
+ d: `M${x1},${y - 10} H${x1 + 44} V${y + 10} H${x1 + 4}`,
9308
+ fill: "none",
9309
+ stroke,
9310
+ strokeWidth,
9311
+ ...dash ? { dash } : {},
9312
+ ...heads,
9313
+ box: { x: x1, y: y - 10, width: 44, height: 20 }
9314
+ });
9315
+ } else {
9316
+ endX = x2 + (x2 > x1 ? -2 : 2);
9317
+ endDir = x2 >= x1 ? 1 : -1;
9318
+ startDir = -endDir;
9319
+ marks.push({ kind: "line", key: `message:${edge.id}`, role: "message", target: edge.id, x1, y1: y, x2: endX, y2: y, stroke, strokeWidth, ...dash ? { dash } : {}, ...heads });
9320
+ }
9321
+ if (edge.arrowEnd === "arrow_cross") marks.push(crossMark(`message-cross-end:${edge.id}`, edge.id, endX, endY, endDir, stroke));
9322
+ if (edge.arrowStart === "arrow_cross") marks.push(crossMark(`message-cross-start:${edge.id}`, edge.id, x1, startY, startDir, stroke));
9323
+ if (autonumber)
9324
+ marks.push(
9325
+ { kind: "circle", key: `number-dot:${edge.id}`, role: "message-number", target: edge.id, cx: x1, cy: y, r: 10, fill: stroke },
9326
+ { kind: "text", key: `number:${edge.id}`, role: "message-number", target: edge.id, x: x1, y, text: String(index + 1), anchor: "middle", baseline: "middle", size: 11, weight: 600, fill: theme.background }
9327
+ );
9328
+ const label = edge.label ? displayLines(edge.label).join(" ") : "";
9329
+ if (label)
9330
+ marks.push({
9331
+ kind: "text",
9332
+ key: `message-label:${edge.id}`,
9333
+ role: "message-label",
9334
+ target: edge.id,
9335
+ x: row.self ? x1 + 52 + 4 : (x1 + x2) / 2,
9336
+ y: row.self ? y - 18 : y - 13,
9337
+ text: label,
9338
+ anchor: row.self ? "start" : "middle",
9339
+ baseline: "middle",
9340
+ size: LABEL_SIZE,
9341
+ fill: theme.text
9342
+ });
9343
+ });
9344
+ return marks;
9345
+ };
9346
+
9347
+ // src/canvas/mermaid/families/journey.ts
9348
+ var M3 = JOURNEY_METRICS;
9349
+ var TITLE_SIZE2 = 32;
9350
+ function actorColor(theme, slot) {
9351
+ return sceneColor(theme, M3.sectionColours + slot);
9352
+ }
9353
+ function wrapLines(text2, size, max) {
9354
+ const lines = [];
9355
+ for (const para of text2.replace(/<br\s*\/?>/gi, "\n").split("\n")) {
9356
+ let line4 = "";
9357
+ for (const word of para.split(/\s+/).filter(Boolean)) {
9358
+ const next = line4 ? `${line4} ${word}` : word;
9359
+ if (line4 && estimateTextWidth2(next, size) > max) {
9360
+ lines.push(line4);
9361
+ line4 = word;
9362
+ } else line4 = next;
9363
+ }
9364
+ lines.push(line4);
9365
+ }
9366
+ return lines;
9367
+ }
9368
+ function boxLabel(key, role, target, text2, box, fill) {
9369
+ let size = M3.fontSize;
9370
+ let lines = wrapLines(text2, size, box.width - 10);
9371
+ if (lines.length > 2) {
9372
+ size = 13;
9373
+ lines = wrapLines(text2, size, box.width - 8);
9374
+ }
9375
+ const lineHeight = size * 1.15;
9376
+ const max = Math.max(1, Math.floor(box.height / lineHeight));
9377
+ if (lines.length > max) lines = [...lines.slice(0, max - 1), `${lines[max - 1]}\u2026`];
9378
+ const top = box.y + box.height / 2 - lines.length * lineHeight / 2 + lineHeight / 2;
9379
+ return lines.map((line4, i) => ({
9380
+ kind: "text",
9381
+ key: `${key}:${i}`,
9382
+ role,
9383
+ target,
9384
+ x: box.x + box.width / 2,
9385
+ y: top + i * lineHeight,
9386
+ text: line4,
9387
+ anchor: "middle",
9388
+ baseline: "middle",
9389
+ size,
9390
+ fill
9391
+ }));
9392
+ }
9393
+ var journeyScene = ({ graph, theme }) => {
9394
+ const geo = journeyGeometry(graph);
9395
+ const marks = [];
9396
+ const ink = theme.mutedText;
9397
+ if (graph.title)
9398
+ marks.push({
9399
+ kind: "text",
9400
+ key: "title",
9401
+ role: "title",
9402
+ target: DIAGRAM_TITLE_TARGET,
9403
+ x: geo.title.x,
9404
+ y: geo.title.baseline + 7,
9405
+ text: graph.title,
9406
+ anchor: "start",
9407
+ baseline: "bottom",
9408
+ size: TITLE_SIZE2,
9409
+ weight: 700,
9410
+ fill: theme.text
9411
+ });
9412
+ for (const t of geo.tasks.values())
9413
+ marks.push({ kind: "line", key: `task-line:${t.id}`, role: "task-line", x1: t.face.x, y1: t.y, x2: t.face.x, y2: M3.lineBottom, stroke: theme.grid, strokeWidth: 1, dash: "4 2" });
9414
+ marks.push({
9415
+ kind: "line",
9416
+ key: "axis",
9417
+ role: "axis",
9418
+ x1: geo.axis.x1,
9419
+ y1: geo.axis.y,
9420
+ x2: geo.axis.x2,
9421
+ y2: geo.axis.y,
9422
+ stroke: theme.edge,
9423
+ strokeWidth: M3.axisWidth,
9424
+ markerEnd: "arrowclosed"
9425
+ });
9426
+ for (const l of geo.legend)
9427
+ marks.push(
9428
+ { kind: "circle", key: `legend-dot:${l.name}`, role: "legend", cx: l.x, cy: l.y, r: M3.actorRadius, fill: actorColor(theme, l.colour), stroke: theme.nodeStroke, strokeWidth: 1 },
9429
+ { kind: "text", key: `legend:${l.name}`, role: "legend", x: l.labelX, y: l.y, text: l.name, anchor: "start", baseline: "middle", size: M3.fontSize, fill: theme.text }
9430
+ );
9431
+ for (const t of geo.tasks.values()) {
9432
+ const { x, y } = t.face;
9433
+ const r = M3.faceRadius;
9434
+ marks.push(
9435
+ { kind: "circle", key: `face:${t.id}`, role: "face", target: t.id, cx: x, cy: y, r, fill: theme.nodeFill, stroke: ink, strokeWidth: 2 },
9436
+ { kind: "circle", key: `eye-l:${t.id}`, role: "face-eye", cx: x - r / 3, cy: y - r / 3, r: 1.5, fill: ink, stroke: ink, strokeWidth: 2 },
9437
+ { kind: "circle", key: `eye-r:${t.id}`, role: "face-eye", cx: x + r / 3, cy: y - r / 3, r: 1.5, fill: ink, stroke: ink, strokeWidth: 2 }
9438
+ );
9439
+ if (t.score > 3)
9440
+ marks.push({ kind: "path", key: `mouth:${t.id}`, role: "face-mouth", d: `M${x + 7},${y + 2} A7,7 0 0 1 ${x - 7},${y + 2}`, fill: "none", stroke: ink, strokeWidth: 1, box: { x: x - 7, y: y + 2, width: 14, height: 7 } });
9441
+ else if (t.score < 3)
9442
+ marks.push({ kind: "path", key: `mouth:${t.id}`, role: "face-mouth", d: `M${x - 7},${y + 7} A7,7 0 0 1 ${x + 7},${y + 7}`, fill: "none", stroke: ink, strokeWidth: 1, box: { x: x - 7, y, width: 14, height: 7 } });
9443
+ else marks.push({ kind: "line", key: `mouth:${t.id}`, role: "face-mouth", x1: x - 5, y1: y + 7, x2: x + 5, y2: y + 7, stroke: ink, strokeWidth: 1 });
9444
+ }
9445
+ for (const group of graph.groups) {
9446
+ const s = geo.sections.get(group.id);
9447
+ if (!s) continue;
9448
+ marks.push({
9449
+ kind: "rect",
9450
+ key: `section:${s.id}`,
9451
+ role: "section",
9452
+ target: s.id,
9453
+ x: s.x,
9454
+ y: s.y,
9455
+ width: s.width,
9456
+ height: s.height,
9457
+ fill: sceneColor(theme, s.colour),
9458
+ stroke: theme.nodeStroke,
9459
+ strokeWidth: 1,
9460
+ radius: 3,
9461
+ // Mermaid draws no bar for an empty section; it is parked after the tasks, faded.
9462
+ ...s.empty ? { dash: "4 3", opacity: 0.6 } : {}
9463
+ });
9464
+ marks.push(...boxLabel(`section-label:${s.id}`, "section-label", s.id, group.label, s, theme.paletteText).map((m) => s.empty ? { ...m, opacity: 0.6 } : m));
9465
+ }
9466
+ for (const node of graph.nodes) {
9467
+ const t = geo.tasks.get(node.id);
9468
+ if (!t) continue;
9469
+ marks.push({
9470
+ kind: "rect",
9471
+ key: `task:${t.id}`,
9472
+ role: "task",
9473
+ target: t.id,
9474
+ x: t.x,
9475
+ y: t.y,
9476
+ width: t.width,
9477
+ height: t.height,
9478
+ fill: sceneColor(theme, t.colour),
9479
+ stroke: theme.nodeStroke,
9480
+ strokeWidth: 1,
9481
+ radius: 3
9482
+ });
9483
+ marks.push(...boxLabel(`task-label:${t.id}`, "task-label", t.id, node.label ?? node.id, t, theme.paletteText));
9484
+ for (const a of t.actors)
9485
+ marks.push({ kind: "circle", key: `actor:${t.id}:${a.name}`, role: "actor", target: t.id, cx: a.x, cy: a.y, r: M3.actorRadius, fill: actorColor(theme, a.colour), stroke: theme.nodeStroke, strokeWidth: 1 });
9486
+ }
9487
+ return marks;
9488
+ };
9489
+
9490
+ // src/canvas/mermaid/families/quadrant.ts
9491
+ var M4 = QUADRANT_METRICS;
9492
+ var QUADRANT_TINT = 0.18;
9493
+ var quadrantScene = ({ graph, theme }) => {
9494
+ const geo = quadrantGeometry(graph);
9495
+ const marks = [];
9496
+ const groups = new Map(graph.groups.map((g) => [g.id, g]));
9497
+ for (const q of geo.quadrants) {
9498
+ const group = groups.get(q.id);
9499
+ marks.push({ kind: "rect", key: `quadrant-fill:${q.id}`, role: "quadrant-fill", x: q.x, y: q.y, width: q.width, height: q.height, fill: sceneColor(theme, q.n - 1), opacity: QUADRANT_TINT });
9500
+ marks.push({ kind: "rect", key: `quadrant:${q.id}`, role: "quadrant", ...group ? { target: q.id } : {}, x: q.x, y: q.y, width: q.width, height: q.height, fill: "transparent" });
9501
+ }
9502
+ for (const q of geo.quadrants) {
9503
+ const group = groups.get(q.id);
9504
+ if (!group || group.data?.placeholder || !group.label) continue;
9505
+ marks.push({
9506
+ kind: "text",
9507
+ key: `quadrant-label:${q.id}`,
9508
+ role: "quadrant-label",
9509
+ target: q.id,
9510
+ x: q.labelX,
9511
+ y: q.labelY,
9512
+ text: group.label,
9513
+ anchor: "middle",
9514
+ baseline: q.labelBaseline,
9515
+ size: M4.quadrantLabelFontSize,
9516
+ fill: theme.text
9517
+ });
9518
+ }
9519
+ geo.borders.forEach(
9520
+ (b, i) => marks.push({
9521
+ kind: "line",
9522
+ key: `border:${i}`,
9523
+ role: b.external ? "border" : "divider",
9524
+ x1: b.x1,
9525
+ y1: b.y1,
9526
+ x2: b.x2,
9527
+ y2: b.y2,
9528
+ stroke: theme.nodeStroke,
9529
+ strokeWidth: b.external ? M4.externalBorderWidth : M4.internalBorderWidth
9530
+ })
9531
+ );
9532
+ for (const l of geo.axisLabels)
9533
+ marks.push({
9534
+ kind: "text",
9535
+ key: `axis:${l.key}`,
9536
+ role: "axis-label",
9537
+ x: l.x,
9538
+ y: l.y,
9539
+ text: l.text,
9540
+ anchor: l.anchor,
9541
+ baseline: "top",
9542
+ size: l.rotation ? M4.yAxisLabelFontSize : M4.xAxisLabelFontSize,
9543
+ fill: theme.text,
9544
+ ...l.rotation ? { rotate: l.rotation } : {}
9545
+ });
9546
+ if (geo.title)
9547
+ marks.push({ kind: "text", key: "title", role: "title", target: DIAGRAM_TITLE_TARGET, x: geo.title.x, y: geo.title.y, text: geo.title.text, anchor: "middle", baseline: "top", size: M4.titleFontSize, fill: theme.text });
9548
+ for (const p of geo.points) {
9549
+ const fill = p.color ?? sceneColor(theme, 0);
9550
+ const strokeWidth = p.strokeWidth ? parseFloat(p.strokeWidth) : 0;
9551
+ marks.push({
9552
+ kind: "circle",
9553
+ key: `point:${p.id}`,
9554
+ role: "point",
9555
+ target: p.id,
9556
+ cx: p.cx,
9557
+ cy: p.cy,
9558
+ r: p.radius,
9559
+ fill,
9560
+ ...Number.isFinite(strokeWidth) && strokeWidth > 0 ? { stroke: p.strokeColor ?? fill, strokeWidth } : {}
9561
+ });
9562
+ marks.push({
9563
+ kind: "text",
9564
+ key: `point-label:${p.id}`,
9565
+ role: "point-label",
9566
+ target: p.id,
9567
+ x: p.cx,
9568
+ y: p.cy + M4.pointTextPadding,
9569
+ text: p.label.replace(/<br\s*\/?>/gi, " "),
9570
+ anchor: "middle",
9571
+ baseline: "top",
9572
+ size: M4.pointLabelFontSize,
9573
+ fill: theme.text
9574
+ });
9575
+ }
9576
+ return marks;
9577
+ };
9578
+
9579
+ // src/canvas/mermaid/families/gitgraph.ts
9580
+ var M5 = GIT_METRICS;
9581
+ function rot([dx, dy], deg) {
9582
+ const a = deg * Math.PI / 180;
9583
+ const c = Math.cos(a);
9584
+ const s = Math.sin(a);
9585
+ return [dx * c - dy * s, dx * s + dy * c];
9586
+ }
9587
+ var polygon = (points) => `M${points.map(([x, y]) => `${round2(x)},${round2(y)}`).join(" L")} Z`;
9588
+ var round2 = (v) => Math.round(v * 100) / 100;
9589
+ function boxOf(points) {
9590
+ const xs = points.map((p) => p[0]);
9591
+ const ys = points.map((p) => p[1]);
9592
+ const x = Math.min(...xs);
9593
+ const y = Math.min(...ys);
9594
+ return { x, y, width: Math.max(...xs) - x, height: Math.max(...ys) - y };
9595
+ }
9596
+ function arrowBox(d) {
9597
+ const points = [];
9598
+ for (const [, cmd, args] of d.matchAll(/([MLA])([^MLA]*)/g)) {
9599
+ const nums = (args.match(/-?\d+(?:\.\d+)?(?:e-?\d+)?/gi) ?? []).map(Number);
9600
+ if (cmd === "A") {
9601
+ for (let i = 0; i + 6 < nums.length; i += 7) points.push([nums[i + 5], nums[i + 6]]);
9602
+ } else for (let i = 0; i + 1 < nums.length; i += 2) points.push([nums[i], nums[i + 1]]);
9603
+ }
9604
+ return points.length ? boxOf(points) : { x: 0, y: 0, width: 0, height: 0 };
9605
+ }
9606
+ function commitSymbol(c, theme) {
9607
+ const color = sceneColor(theme, c.color);
9608
+ const base = { target: c.id };
9609
+ switch (c.symbol) {
9610
+ case "HIGHLIGHT":
9611
+ return [
9612
+ { kind: "rect", key: `commit:${c.id}`, role: "commit", ...base, x: c.x - 10, y: c.y - 10, width: 20, height: 20, fill: theme.text, stroke: theme.text },
9613
+ { kind: "rect", key: `commit-inner:${c.id}`, role: "commit-inner", ...base, x: c.x - 6, y: c.y - 6, width: 12, height: 12, fill: color, stroke: color }
9614
+ ];
9615
+ case "CHERRY_PICK":
9616
+ return [
9617
+ { kind: "circle", key: `commit:${c.id}`, role: "commit", ...base, cx: c.x, cy: c.y, r: M5.commitRadius, fill: theme.text },
9618
+ { kind: "circle", key: `cherry-l:${c.id}`, role: "cherry", ...base, cx: c.x - 3, cy: c.y + 2, r: 2.75, fill: theme.background },
9619
+ { kind: "circle", key: `cherry-r:${c.id}`, role: "cherry", ...base, cx: c.x + 3, cy: c.y + 2, r: 2.75, fill: theme.background },
9620
+ {
9621
+ kind: "path",
9622
+ key: `cherry-stem:${c.id}`,
9623
+ role: "cherry-stem",
9624
+ ...base,
9625
+ d: `M${c.x + 3},${c.y + 1} L${c.x},${c.y - 5} M${c.x - 3},${c.y + 1} L${c.x},${c.y - 5}`,
9626
+ fill: "none",
9627
+ stroke: theme.background
9628
+ }
9629
+ ];
9630
+ default: {
9631
+ const marks = [{ kind: "circle", key: `commit:${c.id}`, role: "commit", ...base, cx: c.x, cy: c.y, r: M5.commitRadius, fill: color, stroke: color }];
9632
+ if (c.symbol === "MERGE")
9633
+ marks.push({ kind: "circle", key: `commit-inner:${c.id}`, role: "commit-inner", ...base, cx: c.x, cy: c.y, r: 6, fill: theme.background, stroke: theme.background });
9634
+ if (c.symbol === "REVERSE")
9635
+ marks.push({
9636
+ kind: "path",
9637
+ key: `commit-reverse:${c.id}`,
9638
+ role: "commit-reverse",
9639
+ ...base,
9640
+ d: `M${c.x - 5},${c.y - 5} L${c.x + 5},${c.y + 5} M${c.x - 5},${c.y + 5} L${c.x + 5},${c.y - 5}`,
9641
+ fill: "none",
9642
+ stroke: theme.background,
9643
+ strokeWidth: 3
9644
+ });
9645
+ return marks;
9646
+ }
9647
+ }
9648
+ }
9649
+ function commitLabel(c, text2, direction, theme) {
9650
+ const w = estimateTextWidth(text2, M5.labelFontSize);
9651
+ const anchor = direction === "LR" ? [1 - 0.026 * w, 18.1 - 0.0136 * w] : [-14.9, 9.2];
9652
+ const ax = c.x + anchor[0];
9653
+ const ay = c.y + anchor[1];
9654
+ const corners = [[-w - 4, -7], [0, -7], [0, 7], [-w - 4, 7]].map((p) => {
9655
+ const [dx, dy] = rot(p, -45);
9656
+ return [ax + dx, ay + dy];
9657
+ });
9658
+ const [tx, ty] = rot([-2, 0], -45);
9659
+ return [
9660
+ { kind: "path", key: `label-bg:${c.id}`, role: "commit-label-bg", target: c.id, d: polygon(corners), fill: theme.edgeLabelBackground, opacity: 0.5 },
9661
+ { kind: "text", key: `label:${c.id}`, role: "commit-label", target: c.id, x: ax + tx, y: ay + ty, text: text2, anchor: "end", baseline: "middle", size: M5.labelFontSize, fill: theme.text, rotate: -45 }
9662
+ ];
9663
+ }
9664
+ function commitTag(c, text2, index, direction, theme) {
9665
+ const w = estimateTextWidth(text2, M5.labelFontSize);
9666
+ const h2 = M5.labelTextHeight / 2;
9667
+ const key = `${c.id}:${index}`;
9668
+ let points;
9669
+ let hole;
9670
+ let label;
9671
+ let rotate;
9672
+ if (direction === "LR") {
9673
+ const ly = -19.2 - index * 20;
9674
+ const local = [
9675
+ [-w / 2 - 12, ly + 2],
9676
+ [-w / 2 - 12, ly - 2],
9677
+ [-w / 2 - 4, ly - h2 - 2],
9678
+ [w / 2 + 4, ly - h2 - 2],
9679
+ [w / 2 + 4, ly + h2 + 2],
9680
+ [-w / 2 - 4, ly + h2 + 2]
9681
+ ];
9682
+ points = local.map(([x, y]) => [c.x + x, c.y + y]);
9683
+ hole = [c.x - w / 2 - 8, c.y + ly];
9684
+ label = [c.x, c.y + ly];
9685
+ } else {
9686
+ const ox = c.x + 12;
9687
+ const oy = c.y + 2 + index * 20;
9688
+ const place2 = (p) => {
9689
+ const [dx, dy] = rot(p, 45);
9690
+ return [ox + dx, oy + dy];
9691
+ };
9692
+ points = [[0, 2], [0, -2], [10, -h2 - 2], [14 + w, -h2 - 2], [14 + w, h2 + 2], [10, h2 + 2]].map(place2);
9693
+ hole = place2([2, 0]);
9694
+ label = place2([12 + w / 2, 0]);
9695
+ rotate = 45;
9696
+ }
9697
+ return [
9698
+ { kind: "path", key: `tag:${key}`, role: "tag", target: c.id, d: polygon(points), fill: theme.groupFill, stroke: theme.groupStroke },
9699
+ { kind: "circle", key: `tag-hole:${key}`, role: "tag-hole", target: c.id, cx: hole[0], cy: hole[1], r: 1.5, fill: theme.text },
9700
+ {
9701
+ kind: "text",
9702
+ key: `tag-label:${key}`,
9703
+ role: "tag-label",
9704
+ target: c.id,
9705
+ x: label[0],
9706
+ y: label[1],
9707
+ text: text2,
9708
+ anchor: "middle",
9709
+ baseline: "middle",
9710
+ size: M5.labelFontSize,
9711
+ fill: theme.text,
9712
+ ...rotate !== void 0 ? { rotate } : {}
9713
+ }
9714
+ ];
9715
+ }
9716
+ var gitGraphScene = ({ graph, theme }) => {
9717
+ const geo = gitGraphGeometry(graph);
9718
+ const marks = [];
9719
+ for (const lane of geo.lanes) {
9720
+ const { x1, y1, x2, y2 } = lane.line;
9721
+ marks.push({ kind: "line", key: `lane:${lane.branch}`, role: "lane", x1, y1, x2, y2, stroke: theme.grid, strokeWidth: 1, dash: "2 2" });
9722
+ }
9723
+ for (const edge of graph.edges) {
9724
+ const arrow = geo.arrows.get(edge.id);
9725
+ if (!arrow) continue;
9726
+ marks.push({
9727
+ kind: "path",
9728
+ key: `arrow:${edge.id}`,
9729
+ role: "parent-link",
9730
+ target: edge.id,
9731
+ d: arrow.path,
9732
+ fill: "none",
9733
+ stroke: sceneColor(theme, arrow.color),
9734
+ strokeWidth: 8,
9735
+ box: arrowBox(arrow.path)
9736
+ });
9737
+ }
9738
+ const groups = new Map(graph.groups.map((g) => [g.id, g]));
9739
+ for (const lane of geo.lanes) {
9740
+ const group = groups.get(lane.branch);
9741
+ if (!group) continue;
9742
+ const { x, y, width, height } = lane.label;
9743
+ const color = sceneColor(theme, lane.color);
9744
+ marks.push(
9745
+ { kind: "rect", key: `branch:${lane.branch}`, role: "branch", target: lane.branch, x, y, width, height, fill: color, radius: 4 },
9746
+ {
9747
+ kind: "text",
9748
+ key: `branch-label:${lane.branch}`,
9749
+ role: "branch-label",
9750
+ target: lane.branch,
9751
+ x: x + width / 2,
9752
+ y: y + height / 2,
9753
+ text: group.label || group.id,
9754
+ anchor: "middle",
9755
+ baseline: "middle",
9756
+ size: M5.branchFontSize,
9757
+ fill: theme.paletteText
9758
+ }
9759
+ );
9760
+ }
9761
+ for (const node of graph.nodes) {
9762
+ const c = geo.commits.get(node.id);
9763
+ if (!c) continue;
9764
+ marks.push(...commitSymbol(c, theme));
9765
+ if (c.label !== void 0) marks.push(...commitLabel(c, c.label, geo.direction, theme));
9766
+ c.tags.forEach((t, i) => marks.push(...commitTag(c, t, i, geo.direction, theme)));
9767
+ }
9768
+ return marks;
9769
+ };
9770
+
9771
+ // src/canvas/mermaid/families/mindmap.ts
9772
+ var M6 = MINDMAP_METRICS;
9773
+ var round3 = (v) => Math.round(v * 100) / 100;
9774
+ function displayLabel(label) {
9775
+ let text2 = label;
9776
+ if (text2.startsWith("`") && text2.endsWith("`")) text2 = text2.slice(1, -1);
9777
+ return text2.replace(/<br\s*\/?>/gi, "\n").replace(/#quot;/g, '"').replace(/#(\d+);/g, (_, n3) => String.fromCharCode(Number(n3)));
9778
+ }
9779
+ function arcOutline(x, y, arcs) {
9780
+ let px2 = x;
9781
+ let py = y;
9782
+ const xs = [x];
9783
+ const ys = [y];
9784
+ const parts = [`M${round3(x)},${round3(y)}`];
9785
+ for (const a of arcs) {
9786
+ parts.push(`a${round3(a.rx)},${round3(a.ry)} ${a.rotation} ${a.large},${a.sweep} ${round3(a.dx)},${round3(a.dy)}`);
9787
+ for (const [sx, sy] of sampleArc(px2, py, a)) {
9788
+ xs.push(sx);
9789
+ ys.push(sy);
9790
+ }
9791
+ px2 += a.dx;
9792
+ py += a.dy;
9793
+ }
9794
+ parts.push(`H${round3(x)} V${round3(y)} Z`);
9795
+ const bx = Math.min(...xs);
9796
+ const by = Math.min(...ys);
9797
+ return { d: parts.join(" "), box: { x: bx, y: by, width: Math.max(...xs) - bx, height: Math.max(...ys) - by } };
9798
+ }
9799
+ function sampleArc(x1, y1, a) {
9800
+ const x2 = x1 + a.dx;
9801
+ const y2 = y1 + a.dy;
9802
+ let rx = Math.abs(a.rx);
9803
+ let ry = Math.abs(a.ry);
9804
+ if (!rx || !ry || a.dx === 0 && a.dy === 0) return [[x2, y2]];
9805
+ const phi = a.rotation * Math.PI / 180;
9806
+ const cos = Math.cos(phi);
9807
+ const sin = Math.sin(phi);
9808
+ const hx = (x1 - x2) / 2;
9809
+ const hy = (y1 - y2) / 2;
9810
+ const x1p = cos * hx + sin * hy;
9811
+ const y1p = -sin * hx + cos * hy;
9812
+ const lambda = x1p * x1p / (rx * rx) + y1p * y1p / (ry * ry);
9813
+ if (lambda > 1) {
9814
+ rx *= Math.sqrt(lambda);
9815
+ ry *= Math.sqrt(lambda);
9816
+ }
9817
+ const num4 = rx * rx * ry * ry - rx * rx * y1p * y1p - ry * ry * x1p * x1p;
9818
+ const den = rx * rx * y1p * y1p + ry * ry * x1p * x1p;
9819
+ const k = (a.large === a.sweep ? -1 : 1) * Math.sqrt(Math.max(0, num4 / den));
9820
+ const cxp = k * rx * y1p / ry;
9821
+ const cyp = -k * ry * x1p / rx;
9822
+ const cx = cos * cxp - sin * cyp + (x1 + x2) / 2;
9823
+ const cy = sin * cxp + cos * cyp + (y1 + y2) / 2;
9824
+ const angle = (ux, uy, vx, vy) => Math.atan2(ux * vy - uy * vx, ux * vx + uy * vy);
9825
+ const t1 = angle(1, 0, (x1p - cxp) / rx, (y1p - cyp) / ry);
9826
+ let dt = angle((x1p - cxp) / rx, (y1p - cyp) / ry, (-x1p - cxp) / rx, (-y1p - cyp) / ry);
9827
+ if (!a.sweep && dt > 0) dt -= 2 * Math.PI;
9828
+ if (a.sweep && dt < 0) dt += 2 * Math.PI;
9829
+ const out = [];
9830
+ const steps = 24;
9831
+ for (let i = 1; i <= steps; i++) {
9832
+ const t = t1 + dt * i / steps;
9833
+ out.push([cx + rx * Math.cos(t) * cos - ry * Math.sin(t) * sin, cy + rx * Math.cos(t) * sin + ry * Math.sin(t) * cos]);
9834
+ }
9835
+ return out;
9836
+ }
9837
+ var arc = (rx, ry, rotation, sweep, dx, dy) => ({ rx, ry, rotation, large: 0, sweep, dx, dy });
9838
+ function topicShape(t, x0, y0, fill, underline) {
9839
+ const { width: w, height: h } = t;
9840
+ const base = { target: t.id, role: "topic" };
9841
+ const key = `topic:${t.id}`;
9842
+ switch (t.form) {
9843
+ case "circle":
9844
+ return [{ kind: "circle", key, ...base, cx: x0 + w / 2, cy: y0 + h / 2, r: w / 2, fill }];
9845
+ case "square":
9846
+ return [{ kind: "rect", key, ...base, x: x0, y: y0, width: w, height: h, fill }];
9847
+ case "rounded":
9848
+ return [{ kind: "rect", key, ...base, x: x0, y: y0, width: w, height: h, fill, radius: 5 }];
9849
+ case "hexagon": {
9850
+ const m = h / 4;
9851
+ const pts = [
9852
+ [m, h],
9853
+ [w - m, h],
9854
+ [w, h / 2],
9855
+ [w - m, 0],
9856
+ [m, 0],
9857
+ [0, h / 2]
9858
+ ];
9859
+ return [{ kind: "path", key, ...base, d: `M${pts.map(([x, y]) => `${round3(x0 + x)},${round3(y0 + y)}`).join(" L")} Z`, fill }];
9860
+ }
9861
+ case "cloud": {
9862
+ const r1 = 0.15 * w;
9863
+ const r22 = 0.25 * w;
9864
+ const r3 = 0.35 * w;
9865
+ const r4 = 0.2 * w;
9866
+ const { d, box } = arcOutline(x0, y0, [
9867
+ arc(r1, r1, 0, 1, w * 0.25, -w * 0.1),
9868
+ arc(r3, r3, 1, 1, w * 0.4, -w * 0.1),
9869
+ arc(r22, r22, 1, 1, w * 0.35, w * 0.2),
9870
+ arc(r1, r1, 1, 1, w * 0.15, h * 0.35),
9871
+ arc(r4, r4, 1, 1, -w * 0.15, h * 0.65),
9872
+ arc(r22, r1, 1, 1, -w * 0.25, w * 0.15),
9873
+ arc(r3, r3, 1, 1, -w * 0.5, 0),
9874
+ arc(r1, r1, 1, 1, -w * 0.25, -w * 0.15),
9875
+ arc(r1, r1, 1, 1, -w * 0.1, -h * 0.35),
9876
+ arc(r4, r4, 1, 1, w * 0.1, -h * 0.65)
9877
+ ]);
9878
+ return [{ kind: "path", key, ...base, d, fill, box }];
9879
+ }
9880
+ case "bang": {
9881
+ const r = 0.15 * w;
9882
+ const { d, box } = arcOutline(x0, y0, [
9883
+ arc(r, r, 1, 0, w * 0.25, -h * 0.1),
9884
+ arc(r, r, 1, 0, w * 0.25, 0),
9885
+ arc(r, r, 1, 0, w * 0.25, 0),
9886
+ arc(r, r, 1, 0, w * 0.25, h * 0.1),
9887
+ arc(r, r, 1, 0, w * 0.15, h * 0.33),
9888
+ arc(r * 0.8, r * 0.8, 1, 0, 0, h * 0.34),
9889
+ arc(r, r, 1, 0, -w * 0.15, h * 0.33),
9890
+ arc(r, r, 1, 0, -w * 0.25, h * 0.15),
9891
+ arc(r, r, 1, 0, -w * 0.25, 0),
9892
+ arc(r, r, 1, 0, -w * 0.25, 0),
9893
+ arc(r, r, 1, 0, -w * 0.25, -h * 0.15),
9894
+ arc(r, r, 1, 0, -w * 0.1, -h * 0.33),
9895
+ arc(r * 0.8, r * 0.8, 1, 0, 0, -h * 0.34),
9896
+ arc(r, r, 1, 0, w * 0.1, -h * 0.33)
9897
+ ]);
9898
+ return [{ kind: "path", key, ...base, d, fill, box }];
9899
+ }
9900
+ default:
9901
+ return [
9902
+ { kind: "rect", key, ...base, x: x0, y: y0, width: w, height: h, fill, radius: 5 },
9903
+ { kind: "line", key: `underline:${t.id}`, role: "topic-underline", target: t.id, x1: x0, y1: y0 + h, x2: x0 + w, y2: y0 + h, stroke: underline, strokeWidth: 3 }
9904
+ ];
9905
+ }
9906
+ }
9907
+ function topicColors(t, theme) {
9908
+ const underline = sceneColor(theme, t.section + Math.floor(theme.palette.length / 2));
9909
+ if (t.section < 0) return { fill: theme.nodeStroke, label: theme.background, underline };
9910
+ return { fill: sceneColor(theme, t.section), label: theme.paletteText, underline };
9911
+ }
9912
+ function iconGlyph(icon) {
9913
+ const name = icon.trim().split(/\s+/).pop() ?? "";
9914
+ const word = name.replace(/^(fa[a-z]?|mdi|bi|icon)-/, "");
9915
+ return (word[0] ?? "?").toUpperCase();
9916
+ }
9917
+ var mindmapScene = ({ graph, theme }) => {
9918
+ const geo = mindmapGeometry(graph);
9919
+ const marks = [];
9920
+ for (const e of geo.edges) {
9921
+ const a = geo.topics.get(e.source);
9922
+ const b = geo.topics.get(e.target);
9923
+ if (!a || !b) continue;
9924
+ marks.push({ kind: "line", key: `branch:${e.edgeId}`, role: "branch", x1: a.x, y1: a.y, x2: b.x, y2: b.y, stroke: sceneColor(theme, e.section), strokeWidth: e.width });
9925
+ }
9926
+ for (const node of graph.nodes) {
9927
+ const t = geo.topics.get(node.id);
9928
+ if (!t) continue;
9929
+ const x0 = t.x - t.width / 2;
9930
+ const y0 = t.y - t.height / 2;
9931
+ const colors = topicColors(t, theme);
9932
+ marks.push(...topicShape(t, x0, y0, colors.fill, colors.underline));
9933
+ const top = t.y - t.lines.length * M6.lineHeight / 2;
9934
+ t.lines.forEach((line4, i) => {
9935
+ const text2 = displayLabel(line4);
9936
+ if (!text2) return;
9937
+ marks.push({
9938
+ kind: "text",
9939
+ key: `label:${t.id}:${i}`,
9940
+ role: "topic-label",
9941
+ target: t.id,
9942
+ x: t.x,
9943
+ y: top + (i + 0.5) * M6.lineHeight,
9944
+ text: text2,
9945
+ anchor: "middle",
9946
+ baseline: "middle",
9947
+ size: M6.fontSize,
9948
+ fill: colors.label
9949
+ });
9950
+ });
9951
+ const icon = typeof node.data?.icon === "string" ? node.data.icon : void 0;
9952
+ if (icon) {
9953
+ marks.push(
9954
+ { kind: "circle", key: `icon:${t.id}`, role: "icon", target: t.id, cx: x0, cy: y0, r: 11, fill: colors.fill, stroke: theme.background, strokeWidth: 2 },
9955
+ { kind: "text", key: `icon-glyph:${t.id}`, role: "icon", target: t.id, x: x0, y: y0, text: iconGlyph(icon), anchor: "middle", baseline: "middle", size: 12, fill: colors.label }
9956
+ );
9957
+ }
9958
+ }
9959
+ return marks;
9960
+ };
9961
+
9962
+ // src/canvas/mermaid/families/c4.ts
9963
+ var C4_COLORS = {
9964
+ person: { bg: "#08427b", border: "#073b6f" },
9965
+ system: { bg: "#1168bd", border: "#3c7fc0" },
9966
+ container: { bg: "#438dd5", border: "#3c7fc0" },
9967
+ component: { bg: "#85bbf0", border: "#78a8d8" },
9968
+ external_person: { bg: "#686868", border: "#8a8a8a" },
9969
+ external_system: { bg: "#999999", border: "#8a8a8a" },
9970
+ external_container: { bg: "#b3b3b3", border: "#a6a6a6" },
9971
+ external_component: { bg: "#cccccc", border: "#bfbfbf" }
9972
+ };
9973
+ var C4_ELEMENT_FG = "#ffffff";
9974
+ var NAME_SIZE = 14;
9975
+ var TYPE_SIZE = 10.5;
9976
+ var DESCR_SIZE = 11.48;
9977
+ var LINE_HEIGHT2 = 1.15;
9978
+ var SECTION_GAP = 3;
9979
+ var REL_FONT = 12;
9980
+ var REL_LINE = 14;
9981
+ var REL_GAP = 3;
9982
+ function colorsOf(type) {
9983
+ return C4_COLORS[`${type.external ? "external_" : ""}${type.base}`] ?? C4_COLORS.container;
9984
+ }
9985
+ var styleOf = (data) => data?.c4Style ?? {};
9986
+ function titleMark(graph, layout2, theme) {
9987
+ if (!graph.title) return null;
9988
+ const groupIds = new Set(graph.groups.map((g) => g.id));
9989
+ const roots = [...graph.nodes, ...graph.groups].filter((n3) => !(n3.parentId && groupIds.has(n3.parentId)) && layout2.positions[n3.id] && layout2.sizes[n3.id]);
9990
+ const minX = roots.length ? Math.min(...roots.map((n3) => layout2.positions[n3.id][0])) : 0;
9991
+ const maxX = roots.length ? Math.max(...roots.map((n3) => layout2.positions[n3.id][0] + layout2.sizes[n3.id].width)) : 240;
9992
+ const minY = roots.length ? Math.min(...roots.map((n3) => layout2.positions[n3.id][1])) : 0;
9993
+ return { kind: "text", key: "title", role: "title", target: DIAGRAM_TITLE_TARGET, x: (minX + maxX) / 2, y: minY - 56 + 18, text: graph.title, anchor: "middle", baseline: "middle", size: 18, weight: 600, fill: theme.text };
9994
+ }
9995
+ var c4Scene = ({ graph, layout: layout2, theme }) => {
9996
+ const marks = [];
9997
+ const box = (id) => {
9998
+ const p = layout2.positions[id];
9999
+ const s = layout2.sizes[id];
10000
+ return p && s ? { x: p[0], y: p[1], width: s.width, height: s.height } : null;
10001
+ };
10002
+ const groupIds = new Set(graph.groups.map((g) => g.id));
10003
+ const depth2 = (id) => {
10004
+ let d = 0;
10005
+ const seen = /* @__PURE__ */ new Set();
10006
+ let p = graph.groups.find((g) => g.id === id)?.parentId;
10007
+ while (p && groupIds.has(p) && !seen.has(p)) {
10008
+ seen.add(p);
10009
+ d++;
10010
+ p = graph.groups.find((g) => g.id === p)?.parentId;
10011
+ }
10012
+ return d;
10013
+ };
10014
+ for (const group of [...graph.groups].sort((a, b) => depth2(a.id) - depth2(b.id))) {
10015
+ const b = box(group.id);
10016
+ if (!b) continue;
10017
+ const text2 = c4BoundaryText(group);
10018
+ const cx = b.x + b.width / 2;
10019
+ marks.push({ kind: "rect", key: `boundary:${group.id}`, role: "boundary", target: group.id, ...b, radius: 2.5, fill: "none", stroke: theme.groupStroke, strokeWidth: 1, dash: text2.solid ? void 0 : "7 7" });
10020
+ marks.push({ kind: "text", key: `boundary-label:${group.id}`, role: "boundary-label", target: group.id, x: cx, y: b.y + text2.labelY, text: text2.label, anchor: "middle", baseline: "middle", size: 16, weight: 700, fill: theme.groupText });
10021
+ marks.push({ kind: "text", key: `boundary-type:${group.id}`, role: "boundary-type", target: group.id, x: cx, y: b.y + text2.typeY, text: text2.type, anchor: "middle", baseline: "middle", size: 14, fill: theme.groupText });
10022
+ if (text2.descr && text2.descrY !== void 0)
10023
+ marks.push({ kind: "text", key: `boundary-descr:${group.id}`, role: "boundary-descr", target: group.id, x: cx, y: b.y + text2.descrY, text: text2.descr, anchor: "middle", baseline: "middle", size: 12, fill: theme.groupText });
10024
+ }
10025
+ const labels = [];
10026
+ const dynamic = graph.data?.c4Type === "C4Dynamic";
10027
+ graph.edges.forEach((edge, index) => {
10028
+ const from = box(edge.source);
10029
+ const to = box(edge.target);
10030
+ if (!from || !to) return;
10031
+ const geo = c4RelGeometry(from, to, index);
10032
+ const { start, end, control } = geo;
10033
+ const style = styleOf(edge.data);
10034
+ const line4 = style.lineColor || theme.edge;
10035
+ marks.push({
10036
+ kind: "path",
10037
+ key: `relation:${edge.id}`,
10038
+ role: "relation",
10039
+ target: edge.id,
10040
+ d: control ? `M${start.x},${start.y} Q${control.x},${control.y} ${end.x},${end.y}` : `M${start.x},${start.y} L${end.x},${end.y}`,
10041
+ fill: "none",
10042
+ stroke: line4,
10043
+ strokeWidth: 1
10044
+ });
10045
+ const head = (key, points) => marks.push({ kind: "path", key, role: "arrow", target: edge.id, d: `M${points.split(" ").join(" L")} Z`, fill: line4 });
10046
+ if (edge.arrowEnd !== "none") head(`arrow-end:${edge.id}`, c4ArrowHead(end, control ?? start));
10047
+ if (edge.arrowStart !== "none") head(`arrow-start:${edge.id}`, c4ArrowHead(start, control ?? end));
10048
+ const offsetX = parseInt(style.offsetX ?? "0", 10) || 0;
10049
+ const offsetY = parseInt(style.offsetY ?? "0", 10) || 0;
10050
+ const left = geo.label.x + offsetX;
10051
+ const top = geo.label.y + offsetY - 7;
10052
+ const textFill = style.textColor || theme.text;
10053
+ const label = `${dynamic ? `${index + 1}: ` : ""}${edge.label ?? ""}`;
10054
+ const tech = typeof edge.data?.tech === "string" && edge.data.tech ? `[${edge.data.tech}]` : "";
10055
+ const gridWidth = Math.max(label ? estimateTextWidth2(label, REL_FONT) : 0, tech ? estimateTextWidth2(tech, REL_FONT) : 0);
10056
+ if (label)
10057
+ labels.push({ kind: "text", key: `relation-label:${edge.id}`, role: "relation-label", target: edge.id, x: left, y: top + REL_LINE / 2, text: label, anchor: "start", baseline: "middle", size: REL_FONT, fill: textFill });
10058
+ if (tech)
10059
+ labels.push({
10060
+ kind: "text",
10061
+ key: `relation-tech:${edge.id}`,
10062
+ role: "relation-tech",
10063
+ target: edge.id,
10064
+ x: left + gridWidth / 2,
10065
+ y: top + (label ? REL_LINE + REL_GAP : 0) + REL_LINE / 2,
10066
+ text: tech,
10067
+ anchor: "middle",
10068
+ baseline: "middle",
10069
+ size: REL_FONT,
10070
+ italic: true,
10071
+ fill: style.textColor || theme.mutedText
10072
+ });
10073
+ });
10074
+ for (const node of graph.nodes) {
10075
+ const b = box(node.id);
10076
+ if (!b) continue;
10077
+ const geo = c4ElementGeometry(node);
10078
+ const style = styleOf(node.data);
10079
+ const colors = colorsOf(geo.type);
10080
+ const fill = style.bgColor || colors.bg;
10081
+ const stroke = style.borderColor || colors.border;
10082
+ const fg = style.fontColor || C4_ELEMENT_FG;
10083
+ const { x, y } = b;
10084
+ const w = geo.width;
10085
+ const h = geo.height;
10086
+ const common = { target: node.id, fill, stroke, strokeWidth: 2 };
10087
+ if (geo.person) {
10088
+ const { headRadius: r, bodyTop, bodyRadius } = geo.person;
10089
+ marks.push(
10090
+ { kind: "rect", key: `element:${node.id}`, role: "element", ...common, x, y: y + bodyTop, width: w, height: h - bodyTop, radius: bodyRadius },
10091
+ { kind: "circle", key: `element-head:${node.id}`, role: "element", ...common, cx: x + w / 2, cy: y + r, r }
10092
+ );
10093
+ } else if (geo.shape === "cylinder" && geo.cylinder) {
10094
+ const { rx, ry } = geo.cylinder;
10095
+ const body = h - 2 * ry;
10096
+ marks.push({
10097
+ kind: "path",
10098
+ key: `element:${node.id}`,
10099
+ role: "element",
10100
+ ...common,
10101
+ d: `M${x},${y + ry} a${rx},${ry} 0,0,0 ${w},0 a${rx},${ry} 0,0,0 ${-w},0 l0,${body} a${rx},${ry} 0,0,0 ${w},0 l0,${-body}`,
10102
+ box: { x, y, width: w, height: h }
10103
+ });
10104
+ } else if (geo.shape === "h-cyl" && geo.cylinder) {
10105
+ const { rx, ry } = geo.cylinder;
10106
+ const body = w - 2 * rx;
10107
+ marks.push({
10108
+ kind: "path",
10109
+ key: `element:${node.id}`,
10110
+ role: "element",
10111
+ ...common,
10112
+ d: `M${x + rx},${y + h} a${rx},${ry} 0,0,1 0,${-h} l${body},0 a${rx},${ry} 0,0,1 0,${h} M${x + rx + body},${y} a${rx},${ry} 0,0,0 0,${h} l${-body},0`,
10113
+ box: { x, y, width: w, height: h }
10114
+ });
10115
+ } else marks.push({ kind: "rect", key: `element:${node.id}`, role: "element", ...common, x, y, width: w, height: h, radius: 12 });
10116
+ let top = y + geo.textCenter.y - geo.textHeight / 2;
10117
+ for (const section of geo.sections) {
10118
+ const size = section.part === "label" ? NAME_SIZE : section.part === "tech" ? TYPE_SIZE : DESCR_SIZE;
10119
+ const lh = section.fontSize * LINE_HEIGHT2;
10120
+ section.lines.forEach((line4, i) => {
10121
+ if (!line4) return;
10122
+ marks.push({
10123
+ kind: "text",
10124
+ key: `element-${section.part}:${node.id}:${i}`,
10125
+ role: section.part === "label" ? "element-name" : section.part === "tech" ? "element-type" : "element-descr",
10126
+ target: node.id,
10127
+ x: x + geo.textCenter.x,
10128
+ y: top + (i + 0.5) * lh,
10129
+ text: line4,
10130
+ anchor: "middle",
10131
+ baseline: "middle",
10132
+ size,
10133
+ weight: section.bold ? 700 : void 0,
10134
+ fill: fg
10135
+ });
10136
+ });
10137
+ top += section.height + SECTION_GAP;
10138
+ }
10139
+ }
10140
+ marks.push(...labels);
10141
+ const title = titleMark(graph, layout2, theme);
10142
+ if (title) marks.push(title);
10143
+ return marks;
10144
+ };
10145
+
10146
+ // src/canvas/mermaid/families/architecture.ts
10147
+ var A = ARCH_METRICS;
10148
+ var ICON_BG = "#087ebf";
10149
+ var ICON_FG = "#ffffff";
10150
+ var r2 = (n3) => Math.round(n3 * 100) / 100;
10151
+ function placePath(d, s, ox, oy) {
10152
+ const tokens = d.match(/[MmLlHhVvCcSsQqZz]|-?(?:\d*\.\d+|\d+\.?)(?:e[-+]?\d+)?/g) ?? [];
10153
+ const out = [];
10154
+ const P = (x2, y2) => `${r2(ox + x2 * s)},${r2(oy + y2 * s)}`;
10155
+ let i = 0;
10156
+ let cmd = "";
10157
+ let x = 0, y = 0, sx = 0, sy = 0;
10158
+ let lastC = null;
10159
+ const num4 = () => Number(tokens[i++]);
10160
+ while (i < tokens.length) {
10161
+ if (/[A-Za-z]/.test(tokens[i])) cmd = tokens[i++];
10162
+ const rel = cmd === cmd.toLowerCase();
10163
+ const bx = rel ? x : 0;
10164
+ const by = rel ? y : 0;
10165
+ switch (cmd.toUpperCase()) {
10166
+ case "M":
10167
+ x = bx + num4();
10168
+ y = by + num4();
10169
+ sx = x;
10170
+ sy = y;
10171
+ out.push(`M${P(x, y)}`);
10172
+ cmd = rel ? "l" : "L";
10173
+ lastC = null;
10174
+ break;
10175
+ case "L":
10176
+ x = bx + num4();
10177
+ y = by + num4();
10178
+ out.push(`L${P(x, y)}`);
10179
+ lastC = null;
10180
+ break;
10181
+ case "H":
10182
+ x = bx + num4();
10183
+ out.push(`L${P(x, y)}`);
10184
+ lastC = null;
10185
+ break;
10186
+ case "V":
10187
+ y = (rel ? y : 0) + num4();
10188
+ out.push(`L${P(x, y)}`);
10189
+ lastC = null;
10190
+ break;
10191
+ case "C": {
10192
+ const c1x = bx + num4(), c1y = by + num4(), c2x = bx + num4(), c2y = by + num4();
10193
+ x = bx + num4();
10194
+ y = by + num4();
10195
+ out.push(`C${P(c1x, c1y)} ${P(c2x, c2y)} ${P(x, y)}`);
10196
+ lastC = [c2x, c2y];
10197
+ break;
10198
+ }
10199
+ case "S": {
10200
+ const c1x = lastC ? 2 * x - lastC[0] : x;
10201
+ const c1y = lastC ? 2 * y - lastC[1] : y;
10202
+ const c2x = bx + num4(), c2y = by + num4();
10203
+ x = bx + num4();
10204
+ y = by + num4();
10205
+ out.push(`C${P(c1x, c1y)} ${P(c2x, c2y)} ${P(x, y)}`);
10206
+ lastC = [c2x, c2y];
10207
+ break;
10208
+ }
10209
+ case "Q": {
10210
+ const cx = bx + num4(), cy = by + num4();
10211
+ x = bx + num4();
10212
+ y = by + num4();
10213
+ out.push(`Q${P(cx, cy)} ${P(x, y)}`);
10214
+ lastC = null;
10215
+ break;
10216
+ }
10217
+ case "Z":
10218
+ x = sx;
10219
+ y = sy;
10220
+ out.push("Z");
10221
+ lastC = null;
10222
+ break;
10223
+ default:
10224
+ i++;
10225
+ }
10226
+ }
10227
+ return out.join(" ");
10228
+ }
10229
+ function ellipse(cx, cy, rx, ry) {
10230
+ const k = 0.5523;
10231
+ return `M${cx - rx},${cy} C${cx - rx},${cy - ry * k} ${cx - rx * k},${cy - ry} ${cx},${cy - ry} C${cx + rx * k},${cy - ry} ${cx + rx},${cy - ry * k} ${cx + rx},${cy} C${cx + rx},${cy + ry * k} ${cx + rx * k},${cy + ry} ${cx},${cy + ry} C${cx - rx * k},${cy + ry} ${cx - rx},${cy + ry * k} ${cx - rx},${cy} Z`;
10232
+ }
10233
+ function roundRect(x, y, w, h, r) {
10234
+ return `M${x + r},${y} H${x + w - r} Q${x + w},${y} ${x + w},${y + r} V${y + h - r} Q${x + w},${y + h} ${x + w - r},${y + h} H${x + r} Q${x},${y + h} ${x},${y + h - r} V${y + r} Q${x},${y} ${x + r},${y} Z`;
10235
+ }
10236
+ var line2 = (x1, y1, x2, y2) => `M${x1},${y1} L${x2},${y2}`;
10237
+ var BAR = (y) => ({ d: `m56.25,${y}c0,.27-.45.5-1,.5h-10.5c-.55,0-1-.23-1-.5s.45-.5,1-.5h10.5c.55,0,1,.23,1,.5Z`, paint: "both", width: 1 });
10238
+ var DOTS = (y) => [32.5, 27.5, 22.5].map((x) => ({ d: ellipse(x, y, 0.75, 0.75), paint: "both", width: 1 }));
10239
+ var ARCH_GLYPHS = {
10240
+ database: [
10241
+ { d: "m20,57.86c0,3.94,8.95,7.14,20,7.14s20-3.2,20-7.14", paint: "stroke" },
10242
+ { d: "m20,45.95c0,3.94,8.95,7.14,20,7.14s20-3.2,20-7.14", paint: "stroke" },
10243
+ { d: "m20,34.05c0,3.94,8.95,7.14,20,7.14s20-3.2,20-7.14", paint: "stroke" },
10244
+ { d: ellipse(40, 22.14, 20, 7.14), paint: "stroke" },
10245
+ { d: line2(20, 57.86, 20, 22.14), paint: "stroke" },
10246
+ { d: line2(60, 57.86, 60, 22.14), paint: "stroke" }
10247
+ ],
10248
+ server: [
10249
+ { d: roundRect(17.5, 17.5, 45, 45, 2), paint: "stroke" },
10250
+ { d: line2(17.5, 32.5, 62.5, 32.5), paint: "stroke" },
10251
+ { d: line2(17.5, 47.5, 62.5, 47.5), paint: "stroke" },
10252
+ BAR(25),
10253
+ BAR(40),
10254
+ BAR(55),
10255
+ ...DOTS(25),
10256
+ ...DOTS(40),
10257
+ ...DOTS(55)
10258
+ ],
10259
+ disk: [
10260
+ { d: roundRect(20, 15, 40, 50, 1), paint: "stroke" },
10261
+ { d: ellipse(24, 19.17, 0.8, 0.83), paint: "stroke" },
10262
+ { d: ellipse(56, 19.17, 0.8, 0.83), paint: "stroke" },
10263
+ { d: ellipse(24, 60.83, 0.8, 0.83), paint: "stroke" },
10264
+ { d: ellipse(56, 60.83, 0.8, 0.83), paint: "stroke" },
10265
+ { d: ellipse(40, 33.75, 14, 14.58), paint: "stroke" },
10266
+ { d: ellipse(40, 33.75, 4, 4.17), paint: "both" },
10267
+ { d: "m37.51,42.52l-4.83,13.22c-.26.71-1.1,1.02-1.76.64l-4.18-2.42c-.66-.38-.81-1.26-.33-1.84l9.01-10.8c.88-1.05,2.56-.08,2.09,1.2Z", paint: "fill" }
10268
+ ],
10269
+ internet: [
10270
+ { d: ellipse(40, 40, 22.5, 22.5), paint: "stroke" },
10271
+ { d: line2(40, 17.5, 40, 62.5), paint: "stroke" },
10272
+ { d: line2(17.5, 40, 62.5, 40), paint: "stroke" },
10273
+ { d: "m39.99,17.51c-15.28,11.1-15.28,33.88,0,44.98", paint: "stroke" },
10274
+ { d: "m40.01,17.51c15.28,11.1,15.28,33.88,0,44.98", paint: "stroke" },
10275
+ { d: line2(19.75, 30.1, 60.25, 30.1), paint: "stroke" },
10276
+ { d: line2(19.75, 49.9, 60.25, 49.9), paint: "stroke" }
10277
+ ],
10278
+ cloud: [
10279
+ {
10280
+ d: "m65,47.5c0,2.76-2.24,5-5,5H20c-2.76,0-5-2.24-5-5,0-1.87,1.03-3.51,2.56-4.36-.04-.21-.06-.42-.06-.64,0-2.6,2.48-4.74,5.65-4.97,1.65-4.51,6.34-7.76,11.85-7.76.86,0,1.69.08,2.5.23,2.09-1.57,4.69-2.5,7.5-2.5,6.1,0,11.19,4.38,12.28,10.17,2.14.56,3.72,2.51,3.72,4.83,0,.03,0,.07-.01.1,2.29.46,4.01,2.48,4.01,4.9Z",
10281
+ paint: "stroke"
10282
+ }
10283
+ ],
10284
+ blank: []
10285
+ };
10286
+ function iconMarks(key, target, icon, x, y, size, theme) {
10287
+ const s = size / 80;
10288
+ if (!icon)
10289
+ return [
10290
+ {
10291
+ kind: "path",
10292
+ key: `icon:${key}`,
10293
+ role: "icon",
10294
+ target,
10295
+ d: placePath("M0,80 V5 Q0,0 5,0 H75 Q80,0 80,5 V80 Z", s, x, y),
10296
+ fill: "none",
10297
+ stroke: theme.groupStroke,
10298
+ strokeWidth: 2,
10299
+ dash: "8"
10300
+ }
10301
+ ];
10302
+ const marks = [{ kind: "rect", key: `icon:${key}`, role: "icon", target, x, y, width: size, height: size, fill: ICON_BG }];
10303
+ const glyph = ARCH_GLYPHS[icon];
10304
+ if (glyph) {
10305
+ glyph.forEach(
10306
+ (part, i) => marks.push({
10307
+ kind: "path",
10308
+ key: `icon-glyph:${key}:${i}`,
10309
+ role: "icon-glyph",
10310
+ target,
10311
+ d: placePath(part.d, s, x, y),
10312
+ fill: part.paint === "stroke" ? "none" : ICON_FG,
10313
+ stroke: part.paint === "fill" ? void 0 : ICON_FG,
10314
+ strokeWidth: (part.width ?? 2) * s
10315
+ })
10316
+ );
10317
+ return marks;
10318
+ }
10319
+ const font = 11 * s;
10320
+ const perLine = Math.max(1, Math.floor(72 * s / estimateTextWidth2("m", font)));
10321
+ const lines = [];
10322
+ for (let i = 0; i < icon.length; i += perLine) lines.push(icon.slice(i, i + perLine));
10323
+ const shown = lines.slice(0, Math.max(1, Math.floor(72 * s / (font * 1.2))));
10324
+ const lh = font * 1.2;
10325
+ shown.forEach(
10326
+ (text2, i) => marks.push({ kind: "text", key: `icon-name:${key}:${i}`, role: "icon-name", target, x: x + size / 2, y: y + size / 2 + (i - (shown.length - 1) / 2) * lh, text: text2, anchor: "middle", baseline: "middle", size: font, fill: ICON_FG })
10327
+ );
10328
+ return marks;
10329
+ }
10330
+ var isJunction = (n3) => n3.shape === "sm-circ" || !!n3.data?.junction;
10331
+ var iconOf = (data) => typeof data?.icon === "string" && data.icon ? data.icon : void 0;
10332
+ function titleMark2(graph, layout2, theme) {
10333
+ if (!graph.title) return null;
10334
+ const groupIds = new Set(graph.groups.map((g) => g.id));
10335
+ const roots = [...graph.nodes, ...graph.groups].filter((n3) => !(n3.parentId && groupIds.has(n3.parentId)) && layout2.positions[n3.id] && layout2.sizes[n3.id]);
10336
+ const minX = roots.length ? Math.min(...roots.map((n3) => layout2.positions[n3.id][0])) : 0;
10337
+ const maxX = roots.length ? Math.max(...roots.map((n3) => layout2.positions[n3.id][0] + layout2.sizes[n3.id].width)) : 240;
10338
+ const minY = roots.length ? Math.min(...roots.map((n3) => layout2.positions[n3.id][1])) : 0;
10339
+ return { kind: "text", key: "title", role: "title", target: DIAGRAM_TITLE_TARGET, x: (minX + maxX) / 2, y: minY - 56 + 18, text: graph.title, anchor: "middle", baseline: "middle", size: 18, weight: 600, fill: theme.text };
10340
+ }
10341
+ var architectureScene = ({ graph, layout: layout2, theme }) => {
10342
+ const marks = [];
10343
+ const box = (id) => {
10344
+ const p = layout2.positions[id];
10345
+ const s = layout2.sizes[id];
10346
+ return p && s ? { x: p[0], y: p[1], width: s.width, height: s.height } : null;
10347
+ };
10348
+ const groupIds = new Set(graph.groups.map((g) => g.id));
10349
+ const parentOf = new Map(graph.groups.map((g) => [g.id, g.parentId]));
10350
+ const depth2 = (id) => {
10351
+ let d = 0;
10352
+ const seen = /* @__PURE__ */ new Set();
10353
+ let p = parentOf.get(id);
10354
+ while (p && groupIds.has(p) && !seen.has(p)) {
10355
+ seen.add(p);
10356
+ d++;
10357
+ p = parentOf.get(p);
10358
+ }
10359
+ return d;
10360
+ };
10361
+ for (const group of [...graph.groups].sort((a, b) => depth2(a.id) - depth2(b.id))) {
10362
+ const b = box(group.id);
10363
+ if (!b) continue;
10364
+ const icon = iconOf(group.data);
10365
+ marks.push({ kind: "rect", key: `group:${group.id}`, role: "group", target: group.id, ...b, fill: "none", stroke: theme.groupStroke, strokeWidth: 2, dash: "8" });
10366
+ if (icon) marks.push(...iconMarks(`group:${group.id}`, group.id, icon, b.x + 1, b.y + 1, A.groupIconSize, theme));
10367
+ const label = group.data?.untitled ? "" : group.label;
10368
+ if (label)
10369
+ marks.push({ kind: "text", key: `group-label:${group.id}`, role: "group-label", target: group.id, x: b.x + (icon ? A.groupIconSize + 4 : 4), y: b.y + 7 + 19 / 2, text: label, anchor: "start", baseline: "middle", size: A.fontSize, fill: theme.groupText });
10370
+ }
10371
+ const labels = [];
10372
+ const junctions = new Set(graph.nodes.filter(isJunction).map((n3) => n3.id));
10373
+ const port = (b, side) => side === "L" ? { x: b.x, y: b.y + b.height / 2 } : side === "R" ? { x: b.x + b.width, y: b.y + b.height / 2 } : side === "T" ? { x: b.x + b.width / 2, y: b.y } : { x: b.x + b.width / 2, y: b.y + b.height };
10374
+ for (const edge of graph.edges) {
10375
+ const from = box(edge.source);
10376
+ const to = box(edge.target);
10377
+ if (!from || !to) continue;
10378
+ const d = edge.data ?? {};
10379
+ const sourceSide = isSide(d.sourceSide) ? d.sourceSide : "R";
10380
+ const targetSide = isSide(d.targetSide) ? d.targetSide : "L";
10381
+ const s = shiftEndpoint(port(from, sourceSide), sourceSide, { group: !!d.sourceGroup, junction: junctions.has(edge.source) });
10382
+ const t = shiftEndpoint(port(to, targetSide), targetSide, { group: !!d.targetGroup, junction: junctions.has(edge.target) });
10383
+ const route = architectureEdgeRoute(s, sourceSide, t, targetSide);
10384
+ marks.push({ kind: "path", key: `edge:${edge.id}`, role: "edge", target: edge.id, d: route.points.map((p, i) => `${i ? "L" : "M"}${p.x},${p.y}`).join(" "), fill: "none", stroke: theme.edge, strokeWidth: 3 });
10385
+ const head = (key, points) => marks.push({ kind: "path", key, role: "arrow", target: edge.id, d: `M${points.split(" ").join(" L")} Z`, fill: theme.edge });
10386
+ if (edge.arrowStart !== "none") head(`arrow-start:${edge.id}`, architectureArrow(s, sourceSide));
10387
+ if (edge.arrowEnd !== "none") head(`arrow-end:${edge.id}`, architectureArrow(t, targetSide));
10388
+ if (edge.label)
10389
+ labels.push({ kind: "text", key: `edge-label:${edge.id}`, role: "edge-label", target: edge.id, x: route.label.x, y: route.label.y, text: edge.label, anchor: "middle", baseline: "middle", size: A.fontSize, rotate: route.rotate || void 0, fill: theme.text });
10390
+ }
10391
+ for (const node of graph.nodes) {
10392
+ const b = box(node.id);
10393
+ if (!b) continue;
10394
+ if (isJunction(node)) {
10395
+ const cx = b.x + b.width / 2;
10396
+ const cy = b.y + b.height / 2;
10397
+ marks.push(
10398
+ { kind: "circle", key: `junction:${node.id}`, role: "junction", target: node.id, cx, cy, r: b.width / 2, fill: "transparent" },
10399
+ { kind: "circle", key: `junction-dot:${node.id}`, role: "junction", target: node.id, cx, cy, r: Math.max(1, b.width / 2 - 3), fill: theme.edge }
10400
+ );
10401
+ continue;
10402
+ }
10403
+ marks.push(...iconMarks(`service:${node.id}`, node.id, iconOf(node.data), b.x, b.y, b.width, theme));
10404
+ if (node.data?.untitled) continue;
10405
+ serviceLabelLines(node.label ?? "").forEach(
10406
+ (text2, i) => marks.push({ kind: "text", key: `service-label:${node.id}:${i}`, role: "service-label", target: node.id, x: b.x + b.width / 2, y: b.y + b.height + (i + 0.5) * A.lineHeight, text: text2, anchor: "middle", baseline: "middle", size: A.fontSize, fill: theme.text })
10407
+ );
10408
+ }
10409
+ marks.push(...labels);
10410
+ const title = titleMark2(graph, layout2, theme);
10411
+ if (title) marks.push(title);
10412
+ return marks;
10413
+ };
10414
+
10415
+ // src/canvas/mermaid/families/gantt.ts
10416
+ var M7 = GANTT_METRICS;
10417
+ var CRIT = 3;
10418
+ function statusOf(node) {
10419
+ const tags = Array.isArray(node?.data?.tags) ? node.data.tags.map(String) : [];
10420
+ const done2 = tags.includes("done");
10421
+ const active = tags.includes("active");
10422
+ const crit = tags.includes("crit");
10423
+ if (crit && done2) return "done-crit";
10424
+ if (crit && active) return "active-crit";
10425
+ if (crit) return "crit";
10426
+ if (done2) return "done";
10427
+ if (active) return "active";
10428
+ return "";
10429
+ }
10430
+ function barColours(theme, status) {
10431
+ const task = sceneColor(theme, 0);
10432
+ const crit = sceneColor(theme, CRIT);
10433
+ switch (status) {
10434
+ case "active":
10435
+ return { fill: theme.background, stroke: task, text: theme.text };
10436
+ case "done":
10437
+ return { fill: theme.grid, stroke: theme.mutedText, text: theme.text };
10438
+ case "crit":
10439
+ return { fill: crit, stroke: crit, text: theme.paletteText };
10440
+ case "active-crit":
10441
+ return { fill: theme.background, stroke: crit, text: theme.text };
10442
+ case "done-crit":
10443
+ return { fill: theme.grid, stroke: crit, text: theme.text };
10444
+ default:
10445
+ return { fill: task, stroke: task, text: theme.paletteText };
10446
+ }
10447
+ }
10448
+ function bandFill(theme, index) {
10449
+ const slot = (index % 4 + 4) % 4;
10450
+ if (slot === 1 || slot === 3) return theme.background;
10451
+ return sceneColor(theme, slot === 0 ? 0 : 2);
10452
+ }
10453
+ var labelWidth = (text2) => text2.length * 6.8 + 16;
10454
+ function stepPath(from, to) {
10455
+ const offset = 12;
10456
+ const sx = from.x + from.width;
10457
+ const sy = from.y + from.height / 2;
10458
+ const tx = to.x;
10459
+ const ty = to.y + to.height / 2;
10460
+ if (tx >= sx + 2 * offset) {
10461
+ const mx = (sx + tx) / 2;
10462
+ return `M ${sx} ${sy} L ${mx} ${sy} L ${mx} ${ty} L ${tx} ${ty}`;
10463
+ }
10464
+ const my = (sy + ty) / 2;
10465
+ return `M ${sx} ${sy} L ${sx + offset} ${sy} L ${sx + offset} ${my} L ${tx - offset} ${my} L ${tx - offset} ${ty} L ${tx} ${ty}`;
10466
+ }
10467
+ var ganttScene = ({ graph, selection, theme }) => {
10468
+ const geo = ganttGeometry(graph);
10469
+ const nodes = new Map(graph.nodes.map((n3) => [n3.id, n3]));
10470
+ const marks = [];
10471
+ const left = geo.chartX - M7.labelWidth;
10472
+ const fullWidth = M7.labelWidth + geo.chartWidth + M7.rightPadding;
10473
+ for (const band of geo.bands) {
10474
+ const key = band.id ?? "::loose";
10475
+ marks.push({
10476
+ kind: "rect",
10477
+ key: `band:${key}`,
10478
+ role: "section",
10479
+ target: band.id,
10480
+ x: left,
10481
+ y: band.y,
10482
+ width: fullWidth,
10483
+ height: band.height,
10484
+ fill: bandFill(theme, band.id ? band.index : 0),
10485
+ opacity: 0.2
10486
+ });
10487
+ if (band.label !== void 0)
10488
+ marks.push({ kind: "text", key: `section:${key}`, role: "section-label", target: band.id, x: left + 8, y: band.y + 4, text: band.label, anchor: "start", baseline: "top", size: 12, fill: theme.groupText });
10489
+ }
10490
+ for (const tick of geo.ticks) {
10491
+ marks.push(
10492
+ { kind: "line", key: `tick:${tick.time}`, role: "grid", x1: tick.x, y1: geo.top, x2: tick.x, y2: geo.bottom, stroke: theme.grid, opacity: 0.8 },
10493
+ { kind: "text", key: `tick-label:${tick.time}`, role: "axis", x: tick.x, y: geo.bottom + 6, text: tick.label, anchor: "middle", baseline: "top", size: 11, fill: theme.mutedText }
10494
+ );
10495
+ }
10496
+ if (geo.today !== void 0)
10497
+ marks.push({ kind: "line", key: "today", role: "today", x1: geo.today, y1: geo.top, x2: geo.today, y2: geo.bottom, stroke: sceneColor(theme, CRIT), strokeWidth: 2 });
10498
+ for (const edge of graph.edges) {
10499
+ if (!selection.has(edge.id) && !selection.has(edge.source) && !selection.has(edge.target)) continue;
10500
+ const from = geo.rowById.get(edge.source);
10501
+ const to = geo.rowById.get(edge.target);
10502
+ if (!from || !to) continue;
10503
+ marks.push({ kind: "path", key: `dependency:${edge.id}`, role: "dependency", target: edge.id, d: stepPath(from, to), stroke: theme.selection, strokeWidth: 1.5, dash: "5 4", markerEnd: "arrowclosed" });
10504
+ }
10505
+ for (const row of geo.rows) {
10506
+ const node = nodes.get(row.id);
10507
+ const status = statusOf(node);
10508
+ const colours2 = barColours(theme, status);
10509
+ const label = (node?.label ?? row.id).replace(/<br\s*\/?>/gi, " ");
10510
+ if (row.milestone) {
10511
+ const cx = row.x + row.width / 2;
10512
+ const cy = row.y + row.height / 2;
10513
+ const h = row.width * 0.8 * Math.SQRT2 / 2;
10514
+ const crit = status.includes("crit");
10515
+ marks.push({
10516
+ kind: "path",
10517
+ key: `milestone:${row.id}`,
10518
+ role: "milestone",
10519
+ target: row.id,
10520
+ d: `M ${cx} ${cy - h} L ${cx + h} ${cy} L ${cx} ${cy + h} L ${cx - h} ${cy} Z`,
10521
+ fill: status.startsWith("done") ? theme.grid : sceneColor(theme, 0),
10522
+ stroke: crit ? sceneColor(theme, CRIT) : status.startsWith("done") ? theme.mutedText : sceneColor(theme, 0),
10523
+ strokeWidth: 2
10524
+ });
10525
+ } else {
10526
+ marks.push({ kind: "rect", key: `bar:${row.id}`, role: "bar", target: row.id, x: row.x, y: row.y, width: row.width, height: row.height, fill: colours2.fill, stroke: colours2.stroke, strokeWidth: 2, radius: 3 });
10527
+ }
10528
+ const outside = row.milestone || labelWidth(label) > row.width;
10529
+ marks.push({
10530
+ kind: "text",
10531
+ key: `label:${row.id}`,
10532
+ role: "task-label",
10533
+ target: row.id,
10534
+ x: outside ? row.x + row.width + 6 : row.x + row.width / 2,
10535
+ y: row.y + row.height / 2,
10536
+ text: label,
10537
+ anchor: outside ? "start" : "middle",
10538
+ baseline: "middle",
10539
+ size: 12,
10540
+ fill: outside ? theme.text : colours2.text,
10541
+ ...row.milestone ? { italic: true } : {}
10542
+ });
10543
+ }
10544
+ if (graph.title)
10545
+ marks.push({ kind: "text", key: "title", role: "title", target: DIAGRAM_TITLE_TARGET, x: left + fullWidth / 2, y: geo.top - 38, text: graph.title, anchor: "middle", baseline: "middle", size: 18, weight: 600, fill: theme.text });
10546
+ return marks;
10547
+ };
10548
+
10549
+ // src/canvas/mermaid/families/timeline.ts
10550
+ var M8 = TIMELINE_METRICS;
10551
+ var RADIUS = 5;
10552
+ var TEXT_TOP = 17;
10553
+ var TEXT_LINE = M8.fontSize * 1.1;
10554
+ function colours(theme, colour) {
10555
+ if (colour === "root") return { fill: theme.nodeStroke, text: theme.background };
10556
+ return { fill: sceneColor(theme, colour), text: theme.paletteText, line: sceneColor(theme, colour + 6) };
10557
+ }
10558
+ function boxPath({ x, y, width: w, height: h }) {
10559
+ const r = Math.min(RADIUS, w / 2, h / 2);
10560
+ return `M ${x} ${y + r} Q ${x} ${y} ${x + r} ${y} L ${x + w - r} ${y} Q ${x + w} ${y} ${x + w} ${y + r} L ${x + w} ${y + h} L ${x} ${y + h} Z`;
10561
+ }
10562
+ function wrap(text2, width) {
10563
+ const out = [];
10564
+ for (const part of String(text2).split(/<br\s*\/?>|\n/i)) {
10565
+ let line4 = "";
10566
+ for (const word of part.split(/\s+/).filter(Boolean)) {
10567
+ const next = line4 ? `${line4} ${word}` : word;
10568
+ if (line4 && textWidth(next) > width) {
10569
+ out.push(line4);
10570
+ line4 = word;
10571
+ } else line4 = next;
10572
+ }
10573
+ out.push(line4);
10574
+ }
10575
+ return out.length ? out : [""];
10576
+ }
10577
+ function arrowLine(key, x1, y1, x2, y2, width, dashed, colour) {
10578
+ const len = Math.hypot(x2 - x1, y2 - y1) || 1;
10579
+ const ux = (x2 - x1) / len;
10580
+ const uy = (y2 - y1) / len;
10581
+ const bx = x2 - ux * 5 * width;
10582
+ const by = y2 - uy * 5 * width;
10583
+ const tx = x2 + ux * width;
10584
+ const ty = y2 + uy * width;
10585
+ return [
10586
+ { kind: "line", key, role: dashed ? "event-line" : "axis", x1, y1, x2, y2, stroke: colour, strokeWidth: width, ...dashed ? { dash: "5,5" } : {} },
10587
+ {
10588
+ kind: "path",
10589
+ key: `${key}:head`,
10590
+ role: dashed ? "event-line" : "axis",
10591
+ d: `M ${bx - uy * 2 * width} ${by + ux * 2 * width} L ${tx} ${ty} L ${bx + uy * 2 * width} ${by - ux * 2 * width} Z`,
10592
+ fill: colour
10593
+ }
10594
+ ];
10595
+ }
10596
+ var timelineScene = ({ graph, theme }) => {
10597
+ const geo = timelineGeometry(graph);
10598
+ const marks = [];
10599
+ const nodes = new Map(graph.nodes.map((n3) => [n3.id, n3]));
10600
+ const groups = new Map(graph.groups.map((g) => [g.id, g]));
10601
+ const line4 = theme.text;
10602
+ const box = (key, role, target, b, colour, text2, opacity, brighten = false) => {
10603
+ const c = colours(theme, colour);
10604
+ marks.push({ kind: "path", key, role, target, d: boxPath(b), fill: c.fill, ...opacity !== void 0 ? { opacity } : {} });
10605
+ if (brighten) marks.push({ kind: "path", key: `${key}:wash`, role, target, d: boxPath(b), fill: theme.background, opacity: 0.2 });
10606
+ if (c.line) marks.push({ kind: "line", key: `${key}:line`, role, target, x1: b.x, y1: b.y + b.height, x2: b.x + b.width, y2: b.y + b.height, stroke: c.line, strokeWidth: 3 });
10607
+ wrap(text2, b.width - 2 * M8.padding).forEach(
10608
+ (t, i) => marks.push({ kind: "text", key: `${key}:text:${i}`, role: `${role}-label`, target, x: b.x + b.width / 2, y: b.y + TEXT_TOP + TEXT_LINE * (i + 0.5), text: t, anchor: "middle", baseline: "middle", size: M8.fontSize, fill: c.text })
10609
+ );
10610
+ };
10611
+ for (const l of geo.eventLines) marks.push(...arrowLine(`event-line:${l.periodId}`, l.x, l.y1, l.x, l.y2, M8.eventLineWidth, true, line4));
10612
+ marks.push(...arrowLine("axis", geo.axis.x1, geo.axis.y, geo.axis.x2, geo.axis.y, M8.axisWidth, false, line4));
10613
+ for (const e of geo.events) box(`event:${e.periodId}:${e.index}`, "event", e.periodId, e, e.colour, e.text, void 0, true);
10614
+ for (const s of geo.sections.values()) box(`section:${s.id}`, "section", s.id, s, s.colour, groups.get(s.id)?.label ?? s.id, s.empty ? 0.6 : void 0);
10615
+ for (const p of geo.periods.values()) {
10616
+ const node = nodes.get(p.id);
10617
+ box(`period:${p.id}`, "period", p.id, p, p.colour, node?.label ?? p.id);
10618
+ }
10619
+ if (graph.title)
10620
+ marks.push({ kind: "text", key: "title", role: "title", target: DIAGRAM_TITLE_TARGET, x: geo.title.x, y: geo.title.baseline, text: graph.title, anchor: "start", baseline: "bottom", size: 32, weight: 700, fill: theme.text });
10621
+ return marks;
10622
+ };
10623
+
10624
+ // src/canvas/mermaid/families/index.ts
10625
+ var BUILTIN_FAMILY_SCENES = {
10626
+ pie: pieScene,
10627
+ xychart: xyChartScene,
10628
+ radar: radarScene,
10629
+ sequence: sequenceScene,
10630
+ journey: journeyScene,
10631
+ quadrant: quadrantScene,
10632
+ gitGraph: gitGraphScene,
10633
+ mindmap: mindmapScene,
10634
+ c4: c4Scene,
10635
+ architecture: architectureScene,
10636
+ gantt: ganttScene,
10637
+ timeline: timelineScene
10638
+ };
10639
+
10640
+ // src/canvas/mermaid/scene.ts
10641
+ var scenes = new Map(Object.entries(BUILTIN_FAMILY_SCENES));
10642
+ function registerFamilyScene(family, scene) {
10643
+ scenes.set(family, scene);
10644
+ }
10645
+ function getFamilyScene(family) {
10646
+ return scenes.get(family);
10647
+ }
10648
+ function hasFamilyScene(family) {
10649
+ return scenes.has(family);
10650
+ }
10651
+ function markBounds(mark) {
10652
+ switch (mark.kind) {
10653
+ case "rect":
10654
+ return [mark.x, mark.y, mark.x + mark.width, mark.y + mark.height];
10655
+ case "circle":
10656
+ return [mark.cx - mark.r, mark.cy - mark.r, mark.cx + mark.r, mark.cy + mark.r];
10657
+ case "line":
10658
+ return [Math.min(mark.x1, mark.x2), Math.min(mark.y1, mark.y2), Math.max(mark.x1, mark.x2), Math.max(mark.y1, mark.y2)];
10659
+ case "text": {
10660
+ const w = estimateTextWidth2(mark.text, mark.size);
10661
+ const x0 = mark.anchor === "start" ? mark.x : mark.anchor === "end" ? mark.x - w : mark.x - w / 2;
10662
+ const y0 = mark.baseline === "top" ? mark.y : mark.baseline === "bottom" ? mark.y - mark.size * 1.2 : mark.y - mark.size * 0.6;
10663
+ if (mark.rotate) {
10664
+ const r = Math.max(w, mark.size * 1.2);
10665
+ return [mark.x - r, mark.y - r, mark.x + r, mark.y + r];
10666
+ }
10667
+ return [x0, y0, x0 + w, y0 + mark.size * 1.2];
10668
+ }
10669
+ case "path": {
10670
+ if (mark.box) return [mark.box.x, mark.box.y, mark.box.x + mark.box.width, mark.box.y + mark.box.height];
10671
+ const nums = mark.d.match(/-?\d*\.?\d+(?:e-?\d+)?/gi)?.map(Number) ?? [];
10672
+ if (nums.length < 2) return null;
10673
+ let x0 = Infinity, y0 = Infinity, x1 = -Infinity, y1 = -Infinity;
10674
+ for (let i = 0; i + 1 < nums.length; i += 2) {
10675
+ x0 = Math.min(x0, nums[i]);
10676
+ y0 = Math.min(y0, nums[i + 1]);
10677
+ x1 = Math.max(x1, nums[i]);
10678
+ y1 = Math.max(y1, nums[i + 1]);
10679
+ }
10680
+ return [x0, y0, x1, y1];
10681
+ }
10682
+ }
10683
+ }
10684
+ function diagramMarksBounds(marks) {
10685
+ let x0 = Infinity, y0 = Infinity, x1 = -Infinity, y1 = -Infinity;
10686
+ for (const mark of marks) {
10687
+ const b = markBounds(mark);
10688
+ if (!b) continue;
10689
+ x0 = Math.min(x0, b[0]);
10690
+ y0 = Math.min(y0, b[1]);
10691
+ x1 = Math.max(x1, b[2]);
10692
+ y1 = Math.max(y1, b[3]);
10693
+ }
10694
+ if (x0 === Infinity) return { x: 0, y: 0, width: 0, height: 0 };
10695
+ return { x: x0, y: y0, width: x1 - x0, height: y1 - y0 };
10696
+ }
10697
+ function mermaidToScene(doc, options = {}) {
10698
+ const scene = scenes.get(doc.family);
10699
+ if (!scene || doc.tier !== "editable") return null;
10700
+ const layout2 = options.layout ?? ensureDiagramLayout(doc.graph, doc.meta, { family: doc.family, ...options });
10701
+ return familySceneFromLayout(doc.family, doc.graph, layout2, options);
10702
+ }
10703
+ function familySceneFromLayout(family, graph, layout2, options = {}) {
10704
+ const scene = scenes.get(family);
10705
+ if (!scene) return null;
10706
+ const theme = { ...DIAGRAM_SCENE_LIGHT_THEME, ...options.theme };
10707
+ const selection = new Set(options.selection ?? []);
10708
+ const marks = scene({ graph, layout: layout2, theme, selection }).map((m) => m.target && selection.has(m.target) ? { ...m, selected: true } : m);
10709
+ return { family, ...diagramMarksBounds(marks), marks };
10710
+ }
10711
+ var esc = (text2) => text2.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
10712
+ var num3 = (v) => String(Math.round(v * 100) / 100);
10713
+ function diagramTextBaseline(baseline) {
10714
+ return baseline === "top" ? "hanging" : baseline === "bottom" ? "text-after-edge" : "central";
10715
+ }
10716
+ var DIAGRAM_MARKER_IDS = { arrow: "pd-arrow-open", arrowclosed: "pd-arrow-closed" };
10717
+ function diagramMarksToSvg(marks, theme = DIAGRAM_SCENE_LIGHT_THEME) {
10718
+ const out = [];
10719
+ for (const m of marks) {
10720
+ const common = `${m.target ? ` data-target="${esc(m.target)}"` : ""}${m.opacity !== void 0 ? ` opacity="${num3(m.opacity)}"` : ""}`;
10721
+ const sel = m.selected ? ` stroke="${esc(theme.selection)}" stroke-width="2"` : "";
10722
+ const markers = (mk) => `${mk.markerEnd ? ` marker-end="url(#${DIAGRAM_MARKER_IDS[mk.markerEnd]})"` : ""}${mk.markerStart ? ` marker-start="url(#${DIAGRAM_MARKER_IDS[mk.markerStart]})"` : ""}`;
10723
+ switch (m.kind) {
10724
+ case "rect":
10725
+ out.push(
10726
+ `<rect x="${num3(m.x)}" y="${num3(m.y)}" width="${num3(Math.max(0, m.width))}" height="${num3(Math.max(0, m.height))}"${m.radius ? ` rx="${num3(m.radius)}"` : ""} fill="${esc(m.fill)}"${sel || (m.stroke ? ` stroke="${esc(m.stroke)}" stroke-width="${num3(m.strokeWidth ?? 1)}"` : "")}${m.dash ? ` stroke-dasharray="${m.dash}"` : ""}${common}/>`
10727
+ );
10728
+ break;
10729
+ case "circle":
10730
+ out.push(
10731
+ `<circle cx="${num3(m.cx)}" cy="${num3(m.cy)}" r="${num3(m.r)}" fill="${esc(m.fill)}"${sel || (m.stroke ? ` stroke="${esc(m.stroke)}" stroke-width="${num3(m.strokeWidth ?? 1)}"` : "")}${common}/>`
10732
+ );
10733
+ break;
10734
+ case "line":
10735
+ out.push(
10736
+ `<line x1="${num3(m.x1)}" y1="${num3(m.y1)}" x2="${num3(m.x2)}" y2="${num3(m.y2)}" stroke="${esc(m.selected ? theme.selection : m.stroke)}" stroke-width="${num3(m.strokeWidth ?? 1)}"${m.dash ? ` stroke-dasharray="${m.dash}"` : ""}${markers(m)}${common}/>`
10737
+ );
10738
+ break;
10739
+ case "path":
10740
+ out.push(
10741
+ `<path d="${m.d}" fill="${esc(m.fill ?? "none")}"${sel || (m.stroke ? ` stroke="${esc(m.stroke)}" stroke-width="${num3(m.strokeWidth ?? 1)}"` : "")}${m.dash ? ` stroke-dasharray="${m.dash}"` : ""}${markers(m)}${common}/>`
10742
+ );
10743
+ break;
10744
+ case "text":
10745
+ out.push(
10746
+ `<text x="${num3(m.x)}" y="${num3(m.y)}" text-anchor="${m.anchor}" dominant-baseline="${diagramTextBaseline(m.baseline)}" font-size="${num3(m.size)}"${m.weight ? ` font-weight="${m.weight}"` : ""}${m.italic ? ' font-style="italic"' : ""} fill="${esc(m.fill)}"${m.rotate ? ` transform="rotate(${num3(m.rotate)} ${num3(m.x)} ${num3(m.y)})"` : ""}${common}>${esc(m.text)}</text>`
10747
+ );
10748
+ break;
10749
+ }
10750
+ }
10751
+ return out.join("");
10752
+ }
10753
+ var CSS_VARIABLE_DIAGRAM_SCENE_THEME = {
10754
+ ...DIAGRAM_SCENE_LIGHT_THEME,
10755
+ background: "var(--background, #ffffff)",
10756
+ nodeFill: "var(--background, #ffffff)",
10757
+ nodeStroke: "var(--foreground, #0f172a)",
10758
+ text: "var(--foreground, #0f172a)",
10759
+ edge: "var(--muted-foreground, #64748b)",
10760
+ edgeLabelBackground: "var(--background, #ffffff)",
10761
+ groupFill: "var(--muted, #f8fafc)",
10762
+ groupStroke: "var(--border, #cbd5e1)",
10763
+ groupText: "var(--muted-foreground, #475569)",
10764
+ grid: "var(--border, #cbd5e1)",
10765
+ mutedText: "var(--muted-foreground, #64748b)",
10766
+ selection: "var(--primary, #2563eb)",
10767
+ fontFamily: "inherit"
10768
+ };
10769
+ function diagramRenameOp(doc, target, label) {
10770
+ const { graph } = doc;
10771
+ if (target === DIAGRAM_TITLE_TARGET) return { type: "setTitle", title: label.trim() || void 0 };
10772
+ if (graph.groups.some((g) => g.id === target)) return { type: "renameGroup", id: target, label };
10773
+ if (graph.edges.some((e) => e.id === target)) return { type: "setEdgeLabel", id: target, label };
10774
+ if (graph.nodes.some((n3) => n3.id === target)) return { type: "renameNode", id: target, label };
10775
+ return null;
10776
+ }
10777
+ function diagramTargetLabel(doc, target) {
10778
+ const { graph } = doc;
10779
+ if (target === DIAGRAM_TITLE_TARGET) return graph.title ?? "";
10780
+ return graph.groups.find((g) => g.id === target)?.label ?? graph.edges.find((e) => e.id === target)?.label ?? graph.nodes.find((n3) => n3.id === target)?.label ?? null;
10781
+ }
10782
+
8866
10783
  // src/canvas/mermaid/shapes.ts
8867
10784
  var n = (v) => Math.round(v * 100) / 100;
8868
10785
  var poly = (points) => `M${points.map(([x, y]) => `${n(x)},${n(y)}`).join(" L")} Z`;
@@ -8871,8 +10788,8 @@ var rect = (x, y, w, h, r = 0) => {
8871
10788
  const rr = Math.min(r, w / 2, h / 2);
8872
10789
  return `M${n(x + rr)},${n(y)} H${n(x + w - rr)} A${n(rr)},${n(rr)} 0 0 1 ${n(x + w)},${n(y + rr)} V${n(y + h - rr)} A${n(rr)},${n(rr)} 0 0 1 ${n(x + w - rr)},${n(y + h)} H${n(x + rr)} A${n(rr)},${n(rr)} 0 0 1 ${n(x)},${n(y + h - rr)} V${n(y + rr)} A${n(rr)},${n(rr)} 0 0 1 ${n(x + rr)},${n(y)} Z`;
8873
10790
  };
8874
- var ellipse = (cx, cy, rx, ry) => `M${n(cx - rx)},${n(cy)} A${n(rx)},${n(ry)} 0 1 0 ${n(cx + rx)},${n(cy)} A${n(rx)},${n(ry)} 0 1 0 ${n(cx - rx)},${n(cy)} Z`;
8875
- var line2 = (x1, y1, x2, y2) => `M${n(x1)},${n(y1)} L${n(x2)},${n(y2)}`;
10791
+ var ellipse2 = (cx, cy, rx, ry) => `M${n(cx - rx)},${n(cy)} A${n(rx)},${n(ry)} 0 1 0 ${n(cx + rx)},${n(cy)} A${n(rx)},${n(ry)} 0 1 0 ${n(cx - rx)},${n(cy)} Z`;
10792
+ var line3 = (x1, y1, x2, y2) => `M${n(x1)},${n(y1)} L${n(x2)},${n(y2)}`;
8876
10793
  function mermaidShapePaths(shape, width, height, inset = 1) {
8877
10794
  const s = inset;
8878
10795
  const W = Math.max(0, width - 2 * s);
@@ -8895,7 +10812,7 @@ function mermaidShapePaths(shape, width, height, inset = 1) {
8895
10812
  case "subproc":
8896
10813
  case "subroutine": {
8897
10814
  const i = Math.min(10, W / 8);
8898
- return [fill(rect(x0, y0, W, H)), stroke(line2(x0 + i, y0, x0 + i, y1)), stroke(line2(x1 - i, y0, x1 - i, y1))];
10815
+ return [fill(rect(x0, y0, W, H)), stroke(line3(x0 + i, y0, x0 + i, y1)), stroke(line3(x1 - i, y0, x1 - i, y1))];
8899
10816
  }
8900
10817
  case "cyl":
8901
10818
  case "cylinder": {
@@ -8910,28 +10827,28 @@ function mermaidShapePaths(shape, width, height, inset = 1) {
8910
10827
  const rx = Math.min(W / 6, 14);
8911
10828
  const paths = [
8912
10829
  fill(`M${n(x0 + rx)},${n(y0)} L${n(x1 - rx)},${n(y0)} A${n(rx)},${n(H / 2)} 0 0 1 ${n(x1 - rx)},${n(y1)} L${n(x0 + rx)},${n(y1)} A${n(rx)},${n(H / 2)} 0 0 1 ${n(x0 + rx)},${n(y0)} Z`),
8913
- stroke(ellipse(x1 - rx, cy, rx, H / 2))
10830
+ stroke(ellipse2(x1 - rx, cy, rx, H / 2))
8914
10831
  ];
8915
- if (shape === "lin-cyl") paths.push(stroke(line2(x0 + rx * 2, y0, x0 + rx * 2, y1)));
10832
+ if (shape === "lin-cyl") paths.push(stroke(line3(x0 + rx * 2, y0, x0 + rx * 2, y1)));
8916
10833
  return paths;
8917
10834
  }
8918
10835
  case "circle":
8919
10836
  case "circ":
8920
- return [fill(ellipse(cx, cy, W / 2, H / 2))];
10837
+ return [fill(ellipse2(cx, cy, W / 2, H / 2))];
8921
10838
  case "dbl-circ":
8922
- return [fill(ellipse(cx, cy, W / 2, H / 2)), stroke(ellipse(cx, cy, Math.max(0, W / 2 - 5), Math.max(0, H / 2 - 5)))];
10839
+ return [fill(ellipse2(cx, cy, W / 2, H / 2)), stroke(ellipse2(cx, cy, Math.max(0, W / 2 - 5), Math.max(0, H / 2 - 5)))];
8923
10840
  case "sm-circ":
8924
10841
  case "f-circ":
8925
10842
  case "stateStart":
8926
- return [solid(ellipse(cx, cy, W / 2, H / 2))];
10843
+ return [solid(ellipse2(cx, cy, W / 2, H / 2))];
8927
10844
  case "fr-circ":
8928
10845
  case "stateEnd":
8929
- return [fill(ellipse(cx, cy, W / 2, H / 2)), solid(ellipse(cx, cy, Math.max(0, W / 2 - 5), Math.max(0, H / 2 - 5)))];
10846
+ return [fill(ellipse2(cx, cy, W / 2, H / 2)), solid(ellipse2(cx, cy, Math.max(0, W / 2 - 5), Math.max(0, H / 2 - 5)))];
8930
10847
  case "cross-circ":
8931
10848
  return [
8932
- fill(ellipse(cx, cy, W / 2, H / 2)),
8933
- stroke(line2(cx - W / 2.83, cy - H / 2.83, cx + W / 2.83, cy + H / 2.83)),
8934
- stroke(line2(cx + W / 2.83, cy - H / 2.83, cx - W / 2.83, cy + H / 2.83))
10849
+ fill(ellipse2(cx, cy, W / 2, H / 2)),
10850
+ stroke(line3(cx - W / 2.83, cy - H / 2.83, cx + W / 2.83, cy + H / 2.83)),
10851
+ stroke(line3(cx + W / 2.83, cy - H / 2.83, cx - W / 2.83, cy + H / 2.83))
8935
10852
  ];
8936
10853
  case "odd":
8937
10854
  case "asymmetric": {
@@ -8973,7 +10890,7 @@ function mermaidShapePaths(shape, width, height, inset = 1) {
8973
10890
  }
8974
10891
  case "lin-rect":
8975
10892
  case "shaded-process":
8976
- return [fill(rect(x0, y0, W, H)), stroke(line2(x0 + 8, y0, x0 + 8, y1))];
10893
+ return [fill(rect(x0, y0, W, H)), stroke(line3(x0 + 8, y0, x0 + 8, y1))];
8977
10894
  case "fork":
8978
10895
  case "join":
8979
10896
  return [solid(rect(x0, y0, W, H, 2))];
@@ -8986,8 +10903,8 @@ function mermaidShapePaths(shape, width, height, inset = 1) {
8986
10903
  case "tag-doc": {
8987
10904
  const wave = Math.min(12, H / 5);
8988
10905
  const paths = [fill(`M${n(x0)},${n(y0)} L${n(x1)},${n(y0)} L${n(x1)},${n(y1 - wave)} Q${n(x1 - W / 4)},${n(y1 - wave * 2.2)} ${n(cx)},${n(y1 - wave)} T${n(x0)},${n(y1 - wave)} Z`)];
8989
- if (shape === "lin-doc") paths.push(stroke(line2(x0 + 8, y0, x0 + 8, y1 - wave)));
8990
- if (shape === "tag-doc") paths.push(stroke(line2(x1 - 12, y1 - wave * 1.6, x1, y1 - wave * 2.6)));
10906
+ if (shape === "lin-doc") paths.push(stroke(line3(x0 + 8, y0, x0 + 8, y1 - wave)));
10907
+ if (shape === "tag-doc") paths.push(stroke(line3(x1 - 12, y1 - wave * 1.6, x1, y1 - wave * 2.6)));
8991
10908
  return paths;
8992
10909
  }
8993
10910
  case "docs": {
@@ -9003,14 +10920,14 @@ function mermaidShapePaths(shape, width, height, inset = 1) {
9003
10920
  }
9004
10921
  case "div-rect": {
9005
10922
  const d = Math.min(24, H / 3);
9006
- return [fill(rect(x0, y0, W, H)), stroke(line2(x0, y0 + d, x1, y0 + d))];
10923
+ return [fill(rect(x0, y0, W, H)), stroke(line3(x0, y0 + d, x1, y0 + d))];
9007
10924
  }
9008
10925
  case "tri":
9009
10926
  return [fill(poly([[cx, y0], [x1, y1], [x0, y1]]))];
9010
10927
  case "flip-tri":
9011
10928
  return [fill(poly([[x0, y0], [x1, y0], [cx, y1]]))];
9012
10929
  case "win-pane":
9013
- return [fill(rect(x0, y0, W, H)), stroke(line2(x0 + 10, y0, x0 + 10, y1)), stroke(line2(x0, y0 + 10, x1, y0 + 10))];
10930
+ return [fill(rect(x0, y0, W, H)), stroke(line3(x0 + 10, y0, x0 + 10, y1)), stroke(line3(x0, y0 + 10, x1, y0 + 10))];
9014
10931
  case "flag": {
9015
10932
  const wave = Math.min(10, H / 5);
9016
10933
  return [fill(`M${n(x0)},${n(y0 + wave)} Q${n(x0 + W / 4)},${n(y0 - wave)} ${n(cx)},${n(y0 + wave)} T${n(x1)},${n(y0 + wave)} L${n(x1)},${n(y1 - wave)} Q${n(x1 - W / 4)},${n(y1 + wave)} ${n(cx)},${n(y1 - wave)} T${n(x0)},${n(y1 - wave)} Z`)];
@@ -9022,7 +10939,7 @@ function mermaidShapePaths(shape, width, height, inset = 1) {
9022
10939
  return [fill(`M${n(x0)},${n(y0)} Q${n(x0 + d)},${n(cy)} ${n(x0)},${n(y1)} L${n(x1)},${n(y1)} Q${n(x1 - d)},${n(cy)} ${n(x1)},${n(y0)} Z`)];
9023
10940
  }
9024
10941
  case "tag-rect":
9025
- return [fill(rect(x0, y0, W, H)), stroke(line2(x1 - 14, y1, x1, y1 - 14))];
10942
+ return [fill(rect(x0, y0, W, H)), stroke(line3(x1 - 14, y1, x1, y1 - 14))];
9026
10943
  case "notch-pent": {
9027
10944
  const d = Math.min(W / 6, H / 3);
9028
10945
  return [fill(poly([[x0 + d, y0], [x1 - d, y0], [x1, y0 + d], [x1, y1], [x0, y1], [x0, y0 + d]]))];
@@ -9075,7 +10992,7 @@ var MERMAID_SHAPE_PAINT = {
9075
10992
  hidden: { fill: "transparent", stroke: "none" }
9076
10993
  };
9077
10994
  function mermaidLabelLines(label) {
9078
- return String(label).replace(/^"`?|`?"$/g, "").split(/<br\s*\/?>|\n/i).map((line3) => line3.replace(/<[^>]+>/g, ""));
10995
+ return String(label).replace(/^"`?|`?"$/g, "").split(/<br\s*\/?>|\n/i).map((line4) => line4.replace(/<[^>]+>/g, ""));
9079
10996
  }
9080
10997
  function mermaidNodeMembers(data) {
9081
10998
  const list = [...data?.members ?? [], ...data?.attributes ?? []];
@@ -9083,33 +11000,7 @@ function mermaidNodeMembers(data) {
9083
11000
  }
9084
11001
 
9085
11002
  // src/canvas/mermaid/export.ts
9086
- var DIAGRAM_SVG_LIGHT_THEME = {
9087
- background: "#ffffff",
9088
- nodeFill: "#ffffff",
9089
- nodeStroke: "#0f172a",
9090
- text: "#0f172a",
9091
- edge: "#64748b",
9092
- edgeLabelBackground: "#ffffff",
9093
- groupFill: "#f8fafc",
9094
- groupStroke: "#cbd5e1",
9095
- groupText: "#475569",
9096
- fontFamily: 'system-ui, -apple-system, "Segoe UI", sans-serif',
9097
- fontSize: 13
9098
- };
9099
- var DIAGRAM_SVG_DARK_THEME = {
9100
- background: "#0f172a",
9101
- nodeFill: "#1e293b",
9102
- nodeStroke: "#e2e8f0",
9103
- text: "#f1f5f9",
9104
- edge: "#94a3b8",
9105
- edgeLabelBackground: "#0f172a",
9106
- groupFill: "#111c33",
9107
- groupStroke: "#334155",
9108
- groupText: "#94a3b8",
9109
- fontFamily: 'system-ui, -apple-system, "Segoe UI", sans-serif',
9110
- fontSize: 13
9111
- };
9112
- var esc = (text) => text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
11003
+ var esc2 = (text2) => text2.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
9113
11004
  var n2 = (v) => String(Math.round(v * 100) / 100);
9114
11005
  function exitPoint(box, to) {
9115
11006
  const cx = box.x + box.width / 2;
@@ -9126,19 +11017,25 @@ function mermaidToSvg(doc, options = {}) {
9126
11017
  const theme = { ...DIAGRAM_SVG_LIGHT_THEME, ...options.theme };
9127
11018
  const pad = options.padding ?? 16;
9128
11019
  const graph = doc.graph;
9129
- const layout2 = options.layout ?? ensureDiagramLayout(graph, doc.meta, options);
9130
- const boxOf = (id) => {
11020
+ const layout2 = options.layout ?? ensureDiagramLayout(graph, doc.meta, { family: doc.family, ...options });
11021
+ const boxOf2 = (id) => {
9131
11022
  const p = layout2.positions[id];
9132
11023
  if (!p) return null;
9133
11024
  const s = layout2.sizes[id] ?? { width: 160, height: 56 };
9134
11025
  return { x: p[0], y: p[1], width: s.width, height: s.height };
9135
11026
  };
11027
+ const scene = doc.tier === "editable" ? familySceneFromLayout(doc.family, graph, layout2, { theme: { ...DIAGRAM_SCENE_LIGHT_THEME, ...theme } }) : null;
9136
11028
  let minX = Infinity;
9137
11029
  let minY = Infinity;
9138
11030
  let maxX = -Infinity;
9139
11031
  let maxY = -Infinity;
9140
- for (const id of Object.keys(layout2.positions)) {
9141
- const b = boxOf(id);
11032
+ if (scene && scene.marks.length) {
11033
+ minX = scene.x;
11034
+ minY = scene.y;
11035
+ maxX = scene.x + scene.width;
11036
+ maxY = scene.y + scene.height;
11037
+ } else for (const id of Object.keys(layout2.positions)) {
11038
+ const b = boxOf2(id);
9142
11039
  minX = Math.min(minX, b.x);
9143
11040
  minY = Math.min(minY, b.y);
9144
11041
  maxX = Math.max(maxX, b.x + b.width);
@@ -9156,15 +11053,19 @@ function mermaidToSvg(doc, options = {}) {
9156
11053
  const title = options.title ?? graph.title ?? `${doc.family} diagram`;
9157
11054
  const out = [];
9158
11055
  out.push(
9159
- `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${naturalWidth} ${naturalHeight}" role="img" aria-label="${esc(title)}" font-family="${esc(theme.fontFamily)}" font-size="${fs}">`,
9160
- `<title>${esc(title)}</title>`,
11056
+ `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${naturalWidth} ${naturalHeight}" role="img" aria-label="${esc2(title)}" font-family="${esc2(theme.fontFamily)}" font-size="${fs}">`,
11057
+ `<title>${esc2(title)}</title>`,
9161
11058
  "<defs>",
9162
- `<marker id="pd-arrow-closed" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 Z" fill="${esc(theme.edge)}"/></marker>`,
9163
- `<marker id="pd-arrow-open" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10" fill="none" stroke="${esc(theme.edge)}" stroke-width="1.5"/></marker>`,
11059
+ `<marker id="pd-arrow-closed" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 Z" fill="${esc2(theme.edge)}"/></marker>`,
11060
+ `<marker id="pd-arrow-open" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10" fill="none" stroke="${esc2(theme.edge)}" stroke-width="1.5"/></marker>`,
9164
11061
  "</defs>"
9165
11062
  );
9166
- if (!options.transparent) out.push(`<rect width="${naturalWidth}" height="${naturalHeight}" fill="${esc(theme.background)}"/>`);
11063
+ if (!options.transparent) out.push(`<rect width="${naturalWidth}" height="${naturalHeight}" fill="${esc2(theme.background)}"/>`);
9167
11064
  out.push(`<g transform="translate(${n2(ox)} ${n2(oy)})">`);
11065
+ if (scene) {
11066
+ out.push(diagramMarksToSvg(scene.marks, { ...DIAGRAM_SCENE_LIGHT_THEME, ...theme }), "</g></svg>");
11067
+ return { svg: out.join(""), width, height, naturalWidth, naturalHeight };
11068
+ }
9168
11069
  const depth2 = (id) => {
9169
11070
  let d = 0;
9170
11071
  let cur = graph.groups.find((g) => g.id === id)?.parentId;
@@ -9175,17 +11076,17 @@ function mermaidToSvg(doc, options = {}) {
9175
11076
  return d;
9176
11077
  };
9177
11078
  for (const g of [...graph.groups].sort((a, b) => depth2(a.id) - depth2(b.id))) {
9178
- const b = boxOf(g.id);
11079
+ const b = boxOf2(g.id);
9179
11080
  if (!b) continue;
9180
11081
  const st = resolveMermaidStyles(g.classes, g.styles, graph.classDefs);
9181
11082
  out.push(
9182
- `<g data-group="${esc(g.id)}"><rect x="${n2(b.x)}" y="${n2(b.y)}" width="${n2(b.width)}" height="${n2(b.height)}" rx="8" fill="${esc(st.fill ?? theme.groupFill)}" stroke="${esc(st.stroke ?? theme.groupStroke)}" stroke-dasharray="4 3"/>`,
9183
- `<text x="${n2(b.x + 10)}" y="${n2(b.y + 18)}" fill="${esc(st.color ?? theme.groupText)}" font-size="${fs - 1}" font-weight="600">${esc(mermaidLabelLines(g.label).join(" "))}</text></g>`
11083
+ `<g data-group="${esc2(g.id)}"><rect x="${n2(b.x)}" y="${n2(b.y)}" width="${n2(b.width)}" height="${n2(b.height)}" rx="8" fill="${esc2(st.fill ?? theme.groupFill)}" stroke="${esc2(st.stroke ?? theme.groupStroke)}" stroke-dasharray="4 3"/>`,
11084
+ `<text x="${n2(b.x + 10)}" y="${n2(b.y + 18)}" fill="${esc2(st.color ?? theme.groupText)}" font-size="${fs - 1}" font-weight="600">${esc2(mermaidLabelLines(g.label).join(" "))}</text></g>`
9184
11085
  );
9185
11086
  }
9186
11087
  for (const e of graph.edges) {
9187
- const a = boxOf(e.source);
9188
- const b = boxOf(e.target);
11088
+ const a = boxOf2(e.source);
11089
+ const b = boxOf2(e.target);
9189
11090
  if (!a || !b || e.pattern === "invisible") continue;
9190
11091
  const ca = { x: a.x + a.width / 2, y: a.y + a.height / 2 };
9191
11092
  const cb = { x: b.x + b.width / 2, y: b.y + b.height / 2 };
@@ -9197,41 +11098,41 @@ function mermaidToSvg(doc, options = {}) {
9197
11098
  const marker = (m) => m === "arrow" ? "url(#pd-arrow-open)" : m ? "url(#pd-arrow-closed)" : "";
9198
11099
  const dash = mermaidEdgeDash(e.pattern);
9199
11100
  out.push(
9200
- `<line data-edge="${esc(e.id)}" x1="${n2(p.x)}" y1="${n2(p.y)}" x2="${n2(q.x)}" y2="${n2(q.y)}" stroke="${esc(st.stroke ?? theme.edge)}" stroke-width="${e.pattern === "thick" ? 3 : 1.5}"${dash ? ` stroke-dasharray="${dash}"` : ""}${end ? ` marker-end="${marker(end)}"` : ""}${start ? ` marker-start="${marker(start)}"` : ""}/>`
11101
+ `<line data-edge="${esc2(e.id)}" x1="${n2(p.x)}" y1="${n2(p.y)}" x2="${n2(q.x)}" y2="${n2(q.y)}" stroke="${esc2(st.stroke ?? theme.edge)}" stroke-width="${e.pattern === "thick" ? 3 : 1.5}"${dash ? ` stroke-dasharray="${dash}"` : ""}${end ? ` marker-end="${marker(end)}"` : ""}${start ? ` marker-start="${marker(start)}"` : ""}/>`
9201
11102
  );
9202
11103
  if (e.label) {
9203
- const text = mermaidLabelLines(e.label).join(" ");
9204
- const w = text.length * fs * 0.55 + 10;
11104
+ const text2 = mermaidLabelLines(e.label).join(" ");
11105
+ const w = text2.length * fs * 0.55 + 10;
9205
11106
  const mx = (p.x + q.x) / 2;
9206
11107
  const my = (p.y + q.y) / 2;
9207
11108
  out.push(
9208
- `<rect x="${n2(mx - w / 2)}" y="${n2(my - fs * 0.75)}" width="${n2(w)}" height="${n2(fs * 1.5)}" rx="3" fill="${esc(theme.edgeLabelBackground)}"/>`,
9209
- `<text x="${n2(mx)}" y="${n2(my)}" text-anchor="middle" dominant-baseline="central" fill="${esc(st.color ?? theme.text)}" font-size="${fs - 1}">${esc(text)}</text>`
11109
+ `<rect x="${n2(mx - w / 2)}" y="${n2(my - fs * 0.75)}" width="${n2(w)}" height="${n2(fs * 1.5)}" rx="3" fill="${esc2(theme.edgeLabelBackground)}"/>`,
11110
+ `<text x="${n2(mx)}" y="${n2(my)}" text-anchor="middle" dominant-baseline="central" fill="${esc2(st.color ?? theme.text)}" font-size="${fs - 1}">${esc2(text2)}</text>`
9210
11111
  );
9211
11112
  }
9212
11113
  }
9213
11114
  for (const node of graph.nodes) {
9214
- const b = boxOf(node.id);
11115
+ const b = boxOf2(node.id);
9215
11116
  if (!b) continue;
9216
11117
  const st = resolveMermaidStyles(node.classes, node.styles, graph.classDefs);
9217
11118
  const fill = st.fill ?? theme.nodeFill;
9218
11119
  const stroke = st.stroke ?? theme.nodeStroke;
9219
11120
  const color = st.color ?? theme.text;
9220
11121
  const strokeWidth = st["stroke-width"]?.replace("px", "") ?? "1.25";
9221
- const paint = (kind) => kind === "shape" ? `fill="${esc(fill)}" stroke="${esc(stroke)}" stroke-width="${esc(strokeWidth)}"` : kind === "line" ? `fill="none" stroke="${esc(stroke)}" stroke-width="${esc(strokeWidth)}"` : kind === "filled" ? `fill="${esc(stroke)}" stroke="${esc(stroke)}"` : 'fill="none" stroke="none"';
9222
- out.push(`<g data-node="${esc(node.id)}" transform="translate(${n2(b.x)} ${n2(b.y)})">`);
11122
+ const paint = (kind) => kind === "shape" ? `fill="${esc2(fill)}" stroke="${esc2(stroke)}" stroke-width="${esc2(strokeWidth)}"` : kind === "line" ? `fill="none" stroke="${esc2(stroke)}" stroke-width="${esc2(strokeWidth)}"` : kind === "filled" ? `fill="${esc2(stroke)}" stroke="${esc2(stroke)}"` : 'fill="none" stroke="none"';
11123
+ out.push(`<g data-node="${esc2(node.id)}" transform="translate(${n2(b.x)} ${n2(b.y)})">`);
9223
11124
  for (const path of mermaidShapePaths(node.shape, b.width, b.height)) out.push(`<path d="${path.d}" ${paint(path.paint)}/>`);
9224
11125
  const lines = mermaidLabelLines(node.label).filter((l, i, all) => l || all.length === 1);
9225
11126
  const members = mermaidNodeMembers(node.data);
9226
11127
  const lh = fs * 1.3;
9227
11128
  if (members.length) {
9228
- lines.forEach((line3, i) => out.push(`<text x="${n2(b.width / 2)}" y="${n2(14 + lh * i)}" text-anchor="middle" dominant-baseline="central" fill="${esc(color)}" font-weight="600">${esc(line3)}</text>`));
11129
+ lines.forEach((line4, i) => out.push(`<text x="${n2(b.width / 2)}" y="${n2(14 + lh * i)}" text-anchor="middle" dominant-baseline="central" fill="${esc2(color)}" font-weight="600">${esc2(line4)}</text>`));
9229
11130
  const top = 14 + lh * lines.length - lh / 2 + 4;
9230
- out.push(`<line x1="0" y1="${n2(top)}" x2="${n2(b.width)}" y2="${n2(top)}" stroke="${esc(stroke)}" stroke-width="1"/>`);
9231
- members.forEach((m, i) => out.push(`<text x="8" y="${n2(top + 4 + lh * (i + 0.5))}" dominant-baseline="central" fill="${esc(color)}" font-size="${fs - 1}">${esc(m)}</text>`));
11131
+ out.push(`<line x1="0" y1="${n2(top)}" x2="${n2(b.width)}" y2="${n2(top)}" stroke="${esc2(stroke)}" stroke-width="1"/>`);
11132
+ members.forEach((m, i) => out.push(`<text x="8" y="${n2(top + 4 + lh * (i + 0.5))}" dominant-baseline="central" fill="${esc2(color)}" font-size="${fs - 1}">${esc2(m)}</text>`));
9232
11133
  } else {
9233
11134
  const first = b.height / 2 - (lines.length - 1) * lh / 2;
9234
- lines.forEach((line3, i) => out.push(`<text x="${n2(b.width / 2)}" y="${n2(first + lh * i)}" text-anchor="middle" dominant-baseline="central" fill="${esc(color)}">${esc(line3)}</text>`));
11135
+ lines.forEach((line4, i) => out.push(`<text x="${n2(b.width / 2)}" y="${n2(first + lh * i)}" text-anchor="middle" dominant-baseline="central" fill="${esc2(color)}">${esc2(line4)}</text>`));
9235
11136
  }
9236
11137
  out.push("</g>");
9237
11138
  }
@@ -9300,7 +11201,7 @@ async function downloadDiagramPng(doc, options = {}) {
9300
11201
 
9301
11202
  // src/canvas/mermaid/index.ts
9302
11203
  function mermaidToCanvas(doc, options = {}) {
9303
- const layout2 = options.layout ?? ensureDiagramLayout(doc.graph, doc.meta, options);
11204
+ const layout2 = options.layout ?? ensureDiagramLayout(doc.graph, doc.meta, { family: doc.family, ...options });
9304
11205
  return {
9305
11206
  nodes: mermaidFlowNodes(doc.graph, layout2, { editable: options.editable }),
9306
11207
  edges: mermaidFlowEdges(doc.graph, { editable: options.editable }),
@@ -9375,10 +11276,10 @@ function calculateCurvedPath(fromX, fromY, toX, toY, progress, options) {
9375
11276
  const p = Math.max(0, Math.min(1, progress));
9376
11277
  const arcHeight = options?.arcHeight ?? -30;
9377
11278
  const wobble = options?.wobble ?? 0;
9378
- const arc = Math.sin(p * Math.PI) * arcHeight;
11279
+ const arc2 = Math.sin(p * Math.PI) * arcHeight;
9379
11280
  const sway = Math.sin(p * Math.PI * 2) * wobble;
9380
11281
  const currentX = fromX + (toX - fromX) * p + sway;
9381
- const currentY = fromY + (toY - fromY) * p + arc;
11282
+ const currentY = fromY + (toY - fromY) * p + arc2;
9382
11283
  return { x: currentX, y: currentY };
9383
11284
  }
9384
11285
  function getNaturalMovementTiming(distance, seedStr = "drag") {
@@ -9460,6 +11361,7 @@ export {
9460
11361
  AUTO_LAYOUT_DATA_KEY,
9461
11362
  AnimationEditError,
9462
11363
  AnimationPlayer,
11364
+ BUILTIN_FAMILY_SCENES,
9463
11365
  CANVAS_COMPONENT_DRAG_TYPE,
9464
11366
  CANVAS_GRADIENT_PRESETS,
9465
11367
  CANVAS_TOKEN_PROPERTIES,
@@ -9472,6 +11374,7 @@ export {
9472
11374
  COMPONENT_SOURCE_DATA_KEY,
9473
11375
  CONNECTION_LINE_TYPES,
9474
11376
  CSS_ANIMATION_PROPERTIES,
11377
+ CSS_VARIABLE_DIAGRAM_SCENE_THEME,
9475
11378
  CUBIC_BEZIER_PRESETS,
9476
11379
  CanvasScenesStore,
9477
11380
  DEFAULT_ARRANGE_SHORTCUTS,
@@ -9481,9 +11384,13 @@ export {
9481
11384
  DEFAULT_NODE_HEIGHT,
9482
11385
  DEFAULT_NODE_WIDTH,
9483
11386
  DEFAULT_PLACEMENT_GAP,
11387
+ DIAGRAM_MARKER_IDS,
9484
11388
  DIAGRAM_RASTER_MAX_SIZE,
11389
+ DIAGRAM_SCENE_DARK_THEME,
11390
+ DIAGRAM_SCENE_LIGHT_THEME,
9485
11391
  DIAGRAM_SVG_DARK_THEME,
9486
11392
  DIAGRAM_SVG_LIGHT_THEME,
11393
+ DIAGRAM_TITLE_TARGET,
9487
11394
  DiagramStream,
9488
11395
  INSTANCE_DATA_KEY,
9489
11396
  LOCKED_DATA_KEY,
@@ -9515,6 +11422,7 @@ export {
9515
11422
  applyShapeCombination,
9516
11423
  applyShapeReplacement,
9517
11424
  arcToCubics,
11425
+ architectureScene,
9518
11426
  autoLayoutDiagram,
9519
11427
  bezierPathArea,
9520
11428
  bezierPathBounds,
@@ -9527,6 +11435,7 @@ export {
9527
11435
  blendDiagramLayout,
9528
11436
  blendLayout,
9529
11437
  boundsOf,
11438
+ c4Scene,
9530
11439
  calculateCursorArrowRotation,
9531
11440
  calculateCurvedPath,
9532
11441
  calculateDagreReflowDisplacement,
@@ -9581,6 +11490,11 @@ export {
9581
11490
  diagramGroupSize,
9582
11491
  diagramImageSize,
9583
11492
  diagramLayoutBounds,
11493
+ diagramMarksBounds,
11494
+ diagramMarksToSvg,
11495
+ diagramRenameOp,
11496
+ diagramTargetLabel,
11497
+ diagramTextBaseline,
9584
11498
  diffOverrideGroups,
9585
11499
  distanceToBezierPath,
9586
11500
  distributeNodes,
@@ -9598,11 +11512,13 @@ export {
9598
11512
  estimateDiagramCanvasHeight,
9599
11513
  estimateDiagramNodeSize,
9600
11514
  estimateNodeSize,
11515
+ estimateTextWidth2 as estimateTextWidth,
9601
11516
  evaluateAnimation,
9602
11517
  evaluateEasing,
9603
11518
  evaluateTrack,
9604
11519
  excludePaths,
9605
11520
  exportCssAnimation,
11521
+ familySceneFromLayout,
9606
11522
  findConnectorSnap,
9607
11523
  findStrokesAtPoint,
9608
11524
  findVariant,
@@ -9620,6 +11536,7 @@ export {
9620
11536
  formatNumber,
9621
11537
  formatOklab,
9622
11538
  formatVariantName,
11539
+ ganttScene,
9623
11540
  getAbsolutePosition,
9624
11541
  getAgentCardAnchor,
9625
11542
  getAnimatableProperty,
@@ -9644,6 +11561,7 @@ export {
9644
11561
  getCursorTransitionDuration,
9645
11562
  getDefaultVariant,
9646
11563
  getEffectiveTokenModes,
11564
+ getFamilyScene,
9647
11565
  getFlowChildren,
9648
11566
  getInstanceData,
9649
11567
  getInstanceProperties,
@@ -9676,8 +11594,10 @@ export {
9676
11594
  getVariantOptions,
9677
11595
  getVariantSet,
9678
11596
  getVariantValues,
11597
+ gitGraphScene,
9679
11598
  gradientToSvgDef,
9680
11599
  handlePoint,
11600
+ hasFamilyScene,
9681
11601
  hasVisibleStroke,
9682
11602
  hashString,
9683
11603
  hatchPath,
@@ -9711,6 +11631,7 @@ export {
9711
11631
  isValidCanvasNode,
9712
11632
  isValidCanvasScene,
9713
11633
  isValidUrl,
11634
+ journeyScene,
9714
11635
  layoutAll,
9715
11636
  layoutBounds,
9716
11637
  layoutFrame,
@@ -9741,7 +11662,9 @@ export {
9741
11662
  mermaidShapePaths,
9742
11663
  mermaidThumbnailSvg,
9743
11664
  mermaidToCanvas,
11665
+ mermaidToScene,
9744
11666
  mermaidToSvg,
11667
+ mindmapScene,
9745
11668
  mixColorsOklab,
9746
11669
  moveKeyframes,
9747
11670
  moveLayoutChild,
@@ -9773,6 +11696,7 @@ export {
9773
11696
  pathBooleanSelect,
9774
11697
  pathToContours,
9775
11698
  pathfinder,
11699
+ pieScene,
9776
11700
  placeBeside,
9777
11701
  planarSplit,
9778
11702
  playWebAnimations,
@@ -9785,6 +11709,9 @@ export {
9785
11709
  positionToSide,
9786
11710
  pruneCanvasTokenModes,
9787
11711
  pushCanvasInstanceOverrides,
11712
+ quadrantScene,
11713
+ radarChartSpec,
11714
+ radarScene,
9788
11715
  rasterSize,
9789
11716
  rasterizeSvg,
9790
11717
  readAnimatableValue,
@@ -9793,6 +11720,7 @@ export {
9793
11720
  readStyleSize,
9794
11721
  realClock,
9795
11722
  recordAnimationChanges,
11723
+ registerFamilyScene,
9796
11724
  relayoutUpdates,
9797
11725
  remapPastedNodes,
9798
11726
  removeCanvasVariant,
@@ -9815,6 +11743,7 @@ export {
9815
11743
  runMultiNodeTransition,
9816
11744
  sampleAnimationFrames,
9817
11745
  scaleKeyframes,
11746
+ sceneColor,
9818
11747
  segmentBounds,
9819
11748
  segmentCurvature,
9820
11749
  segmentDerivative,
@@ -9825,6 +11754,7 @@ export {
9825
11754
  segmentParamAtLength,
9826
11755
  segmentPoint,
9827
11756
  segmentTangent,
11757
+ sequenceScene,
9828
11758
  serializeCanvasNodes,
9829
11759
  setCanvasComponentProperty,
9830
11760
  setCanvasInstanceProperties,
@@ -9862,6 +11792,7 @@ export {
9862
11792
  syncCanvasComponents,
9863
11793
  syncCanvasInstance,
9864
11794
  timeToX,
11795
+ timelineScene,
9865
11796
  toBezierPath,
9866
11797
  toWebAnimations,
9867
11798
  toggleLockNodes,
@@ -9880,6 +11811,8 @@ export {
9880
11811
  writeNodeStyleProperty,
9881
11812
  writeOverrideGroup,
9882
11813
  xToTime,
9883
- xorPolygons
11814
+ xorPolygons,
11815
+ xyChartScene,
11816
+ xyChartSpec
9884
11817
  };
9885
11818
  //# sourceMappingURL=index.js.map