schematex 0.2.2 → 0.2.4

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 (163) hide show
  1. package/dist/ai/ai-sdk.cjs +85 -0
  2. package/dist/ai/ai-sdk.cjs.map +1 -0
  3. package/dist/ai/ai-sdk.d.cts +30 -0
  4. package/dist/ai/ai-sdk.d.ts +30 -0
  5. package/dist/ai/ai-sdk.js +83 -0
  6. package/dist/ai/ai-sdk.js.map +1 -0
  7. package/dist/ai/index.cjs +60 -0
  8. package/dist/ai/index.cjs.map +1 -0
  9. package/dist/ai/index.d.cts +155 -0
  10. package/dist/ai/index.d.ts +155 -0
  11. package/dist/ai/index.js +23 -0
  12. package/dist/ai/index.js.map +1 -0
  13. package/dist/browser.cjs +16 -15
  14. package/dist/browser.cjs.map +1 -1
  15. package/dist/browser.js +14 -13
  16. package/dist/browser.js.map +1 -1
  17. package/dist/{chunk-ZO77FHBF.cjs → chunk-2JDVJRR3.cjs} +14 -6
  18. package/dist/chunk-2JDVJRR3.cjs.map +1 -0
  19. package/dist/{chunk-QR7VTCI4.cjs → chunk-3YZ6FPQW.cjs} +13 -7
  20. package/dist/chunk-3YZ6FPQW.cjs.map +1 -0
  21. package/dist/{chunk-GEPBET4L.js → chunk-45KP67RR.js} +14 -6
  22. package/dist/chunk-45KP67RR.js.map +1 -0
  23. package/dist/{chunk-LKOBOVNL.cjs → chunk-5AEN2PLB.cjs} +14 -6
  24. package/dist/chunk-5AEN2PLB.cjs.map +1 -0
  25. package/dist/{chunk-7IRT3LOY.cjs → chunk-A5D2IMOX.cjs} +16 -8
  26. package/dist/chunk-A5D2IMOX.cjs.map +1 -0
  27. package/dist/{chunk-XVCAOGFL.cjs → chunk-B37IKTI7.cjs} +221 -44
  28. package/dist/chunk-B37IKTI7.cjs.map +1 -0
  29. package/dist/{chunk-ISACNVFE.cjs → chunk-B6INLQBU.cjs} +15 -9
  30. package/dist/chunk-B6INLQBU.cjs.map +1 -0
  31. package/dist/{chunk-YXIIWLLB.cjs → chunk-COLTVQWR.cjs} +174 -6
  32. package/dist/chunk-COLTVQWR.cjs.map +1 -0
  33. package/dist/chunk-DNZFOCV7.js +796 -0
  34. package/dist/chunk-DNZFOCV7.js.map +1 -0
  35. package/dist/chunk-DPQYGWCT.cjs +1121 -0
  36. package/dist/chunk-DPQYGWCT.cjs.map +1 -0
  37. package/dist/{chunk-XHZ7GXP2.cjs → chunk-E65ITQXV.cjs} +178 -22
  38. package/dist/chunk-E65ITQXV.cjs.map +1 -0
  39. package/dist/{chunk-LCR3KOJV.js → chunk-FCGHV6ZK.js} +16 -8
  40. package/dist/chunk-FCGHV6ZK.js.map +1 -0
  41. package/dist/{chunk-X2BQKXMA.js → chunk-FE6GAUNW.js} +13 -7
  42. package/dist/chunk-FE6GAUNW.js.map +1 -0
  43. package/dist/{chunk-YN467EEQ.js → chunk-H2OEUBPO.js} +547 -101
  44. package/dist/chunk-H2OEUBPO.js.map +1 -0
  45. package/dist/{chunk-Z3WOHHG3.js → chunk-J2LVOWVY.js} +177 -24
  46. package/dist/chunk-J2LVOWVY.js.map +1 -0
  47. package/dist/{chunk-CJ2A3UEQ.js → chunk-LR4X4ZRG.js} +179 -23
  48. package/dist/chunk-LR4X4ZRG.js.map +1 -0
  49. package/dist/{chunk-LXNFVHDT.cjs → chunk-MCFQAUQV.cjs} +21 -13
  50. package/dist/chunk-MCFQAUQV.cjs.map +1 -0
  51. package/dist/{chunk-Z63XPA2V.cjs → chunk-MJGDP3CS.cjs} +546 -100
  52. package/dist/chunk-MJGDP3CS.cjs.map +1 -0
  53. package/dist/chunk-MR5HU5WU.js +1112 -0
  54. package/dist/chunk-MR5HU5WU.js.map +1 -0
  55. package/dist/{chunk-7HKXU7J2.cjs → chunk-MSYBSOU2.cjs} +65 -38
  56. package/dist/chunk-MSYBSOU2.cjs.map +1 -0
  57. package/dist/{chunk-4KYW63IK.js → chunk-OC22GGQN.js} +222 -45
  58. package/dist/chunk-OC22GGQN.js.map +1 -0
  59. package/dist/{chunk-5UV5VQ7J.js → chunk-RP5UATRA.js} +174 -6
  60. package/dist/chunk-RP5UATRA.js.map +1 -0
  61. package/dist/{chunk-ZNZIL244.js → chunk-U6L3FAML.js} +15 -9
  62. package/dist/chunk-U6L3FAML.js.map +1 -0
  63. package/dist/{chunk-CXHPP5BL.cjs → chunk-UAGSCTYI.cjs} +177 -24
  64. package/dist/chunk-UAGSCTYI.cjs.map +1 -0
  65. package/dist/{chunk-5SH5NUDW.js → chunk-UGCUNADI.js} +21 -13
  66. package/dist/chunk-UGCUNADI.js.map +1 -0
  67. package/dist/chunk-ULYRO2KY.cjs +800 -0
  68. package/dist/chunk-ULYRO2KY.cjs.map +1 -0
  69. package/dist/{chunk-UUPYTUGR.js → chunk-VPKCW4PB.js} +54 -27
  70. package/dist/chunk-VPKCW4PB.js.map +1 -0
  71. package/dist/{chunk-6YMQSTFF.js → chunk-ZNDIGQJD.js} +14 -6
  72. package/dist/chunk-ZNDIGQJD.js.map +1 -0
  73. package/dist/diagrams/blockdiagram/index.cjs +5 -5
  74. package/dist/diagrams/blockdiagram/index.d.cts +1 -1
  75. package/dist/diagrams/blockdiagram/index.d.ts +1 -1
  76. package/dist/diagrams/blockdiagram/index.js +1 -1
  77. package/dist/diagrams/circuit/index.d.cts +1 -1
  78. package/dist/diagrams/circuit/index.d.ts +1 -1
  79. package/dist/diagrams/ecomap/index.cjs +7 -6
  80. package/dist/diagrams/ecomap/index.d.cts +2 -2
  81. package/dist/diagrams/ecomap/index.d.ts +2 -2
  82. package/dist/diagrams/ecomap/index.js +2 -1
  83. package/dist/diagrams/entity/index.d.cts +1 -1
  84. package/dist/diagrams/entity/index.d.ts +1 -1
  85. package/dist/diagrams/fishbone/index.cjs +7 -7
  86. package/dist/diagrams/fishbone/index.d.cts +1 -1
  87. package/dist/diagrams/fishbone/index.d.ts +1 -1
  88. package/dist/diagrams/fishbone/index.js +1 -1
  89. package/dist/diagrams/flowchart/index.cjs +7 -7
  90. package/dist/diagrams/flowchart/index.d.cts +2 -2
  91. package/dist/diagrams/flowchart/index.d.ts +2 -2
  92. package/dist/diagrams/flowchart/index.js +1 -1
  93. package/dist/diagrams/genogram/index.cjs +9 -8
  94. package/dist/diagrams/genogram/index.d.cts +1 -1
  95. package/dist/diagrams/genogram/index.d.ts +1 -1
  96. package/dist/diagrams/genogram/index.js +2 -1
  97. package/dist/diagrams/ladder/index.cjs +5 -5
  98. package/dist/diagrams/ladder/index.d.cts +1 -1
  99. package/dist/diagrams/ladder/index.d.ts +1 -1
  100. package/dist/diagrams/ladder/index.js +1 -1
  101. package/dist/diagrams/logic/index.d.cts +1 -1
  102. package/dist/diagrams/logic/index.d.ts +1 -1
  103. package/dist/diagrams/orgchart/index.cjs +6 -6
  104. package/dist/diagrams/orgchart/index.d.cts +5 -2
  105. package/dist/diagrams/orgchart/index.d.ts +5 -2
  106. package/dist/diagrams/orgchart/index.js +1 -1
  107. package/dist/diagrams/pedigree/index.cjs +7 -6
  108. package/dist/diagrams/pedigree/index.d.cts +1 -1
  109. package/dist/diagrams/pedigree/index.d.ts +1 -1
  110. package/dist/diagrams/pedigree/index.js +2 -1
  111. package/dist/diagrams/phylo/index.d.cts +1 -1
  112. package/dist/diagrams/phylo/index.d.ts +1 -1
  113. package/dist/diagrams/sld/index.cjs +5 -5
  114. package/dist/diagrams/sld/index.d.cts +1 -1
  115. package/dist/diagrams/sld/index.d.ts +1 -1
  116. package/dist/diagrams/sld/index.js +1 -1
  117. package/dist/diagrams/sociogram/index.cjs +6 -5
  118. package/dist/diagrams/sociogram/index.d.cts +2 -1
  119. package/dist/diagrams/sociogram/index.d.ts +2 -1
  120. package/dist/diagrams/sociogram/index.js +2 -1
  121. package/dist/diagrams/timing/index.cjs +4 -4
  122. package/dist/diagrams/timing/index.d.cts +1 -1
  123. package/dist/diagrams/timing/index.d.ts +1 -1
  124. package/dist/diagrams/timing/index.js +1 -1
  125. package/dist/diagrams/venn/index.d.cts +1 -1
  126. package/dist/diagrams/venn/index.d.ts +1 -1
  127. package/dist/{index-ga04CTBI.d.ts → index-BTZEka65.d.cts} +11 -2
  128. package/dist/{index-SSGpCggE.d.cts → index-DcU88F9i.d.ts} +11 -2
  129. package/dist/index.cjs +28 -27
  130. package/dist/index.d.cts +2 -2
  131. package/dist/index.d.ts +2 -2
  132. package/dist/index.js +13 -12
  133. package/dist/react.cjs +14 -13
  134. package/dist/react.cjs.map +1 -1
  135. package/dist/react.js +13 -12
  136. package/dist/react.js.map +1 -1
  137. package/dist/{types-BcPhMdHd.d.ts → types-C4LnMEcB.d.cts} +58 -4
  138. package/dist/{types-BcPhMdHd.d.cts → types-C4LnMEcB.d.ts} +58 -4
  139. package/package.json +27 -5
  140. package/dist/chunk-4KYW63IK.js.map +0 -1
  141. package/dist/chunk-5SH5NUDW.js.map +0 -1
  142. package/dist/chunk-5UV5VQ7J.js.map +0 -1
  143. package/dist/chunk-6YMQSTFF.js.map +0 -1
  144. package/dist/chunk-7HKXU7J2.cjs.map +0 -1
  145. package/dist/chunk-7IRT3LOY.cjs.map +0 -1
  146. package/dist/chunk-CJ2A3UEQ.js.map +0 -1
  147. package/dist/chunk-CXHPP5BL.cjs.map +0 -1
  148. package/dist/chunk-GEPBET4L.js.map +0 -1
  149. package/dist/chunk-ISACNVFE.cjs.map +0 -1
  150. package/dist/chunk-LCR3KOJV.js.map +0 -1
  151. package/dist/chunk-LKOBOVNL.cjs.map +0 -1
  152. package/dist/chunk-LXNFVHDT.cjs.map +0 -1
  153. package/dist/chunk-QR7VTCI4.cjs.map +0 -1
  154. package/dist/chunk-UUPYTUGR.js.map +0 -1
  155. package/dist/chunk-X2BQKXMA.js.map +0 -1
  156. package/dist/chunk-XHZ7GXP2.cjs.map +0 -1
  157. package/dist/chunk-XVCAOGFL.cjs.map +0 -1
  158. package/dist/chunk-YN467EEQ.js.map +0 -1
  159. package/dist/chunk-YXIIWLLB.cjs.map +0 -1
  160. package/dist/chunk-Z3WOHHG3.js.map +0 -1
  161. package/dist/chunk-Z63XPA2V.cjs.map +0 -1
  162. package/dist/chunk-ZNZIL244.js.map +0 -1
  163. package/dist/chunk-ZO77FHBF.cjs.map +0 -1
@@ -3,14 +3,16 @@ import { text, title, desc, el, defs, group, svgRoot, rect, path, polygon, circl
3
3
 
4
4
  // src/diagrams/flowchart/parser.ts
5
5
  var FlowchartParseError = class extends Error {
6
- constructor(message, line2, col) {
7
- super(`[line ${line2}:${col}] ${message}`);
6
+ constructor(message, line2, column, source) {
7
+ super(`[line ${line2}:${column}] ${message}`);
8
8
  this.line = line2;
9
- this.col = col;
9
+ this.column = column;
10
+ this.source = source;
10
11
  this.name = "FlowchartParseError";
11
12
  }
12
13
  line;
13
- col;
14
+ column;
15
+ source;
14
16
  };
15
17
  var DIRECTIONS = /* @__PURE__ */ new Set(["TB", "TD", "BT", "LR", "RL"]);
16
18
  function parseShapeSuffix(line2, pos) {
@@ -711,13 +713,53 @@ var FC_CONST = {
711
713
  // flow-direction gap between layers
712
714
  dummyWidth: 1,
713
715
  padding: 24,
716
+ /** Latin/digit avg width at 12px font. CJK uses cjkCharWidth instead. */
714
717
  charWidth: 6.8,
715
- // approx font-size 12 proportional width
718
+ /** Full-width glyph width at 12px (CJK ideograph, kana, hangul, fullwidth). */
719
+ cjkCharWidth: 12.5,
716
720
  labelHPad: 16,
717
721
  minNodeWidth: 72,
718
- maxLabelWidth: 220,
722
+ /**
723
+ * Cap on per-line label width. Until line-wrapping lands, this clamp is
724
+ * a soft contract: nodes never grow past this, and any overflow becomes
725
+ * the caller's problem. Set generously so common CJK sentences (≤30
726
+ * full-width chars) still fit without truncation or text overflow.
727
+ */
728
+ maxLabelWidth: 420,
719
729
  crossingSweepIters: 24
720
730
  };
731
+ var SHAPE_SLANT = {
732
+ parallelogram: 20,
733
+ trapezoid: 16
734
+ };
735
+ var CLUSTER_GEO = {
736
+ pad: 24,
737
+ titleH: 20,
738
+ /** Extra visible separation between two sequential cluster bboxes. */
739
+ gap: 12
740
+ };
741
+ function isFullWidth(code) {
742
+ if (code >= 12288 && code <= 12351) return true;
743
+ if (code >= 12352 && code <= 12447) return true;
744
+ if (code >= 12448 && code <= 12543) return true;
745
+ if (code >= 13312 && code <= 19903) return true;
746
+ if (code >= 19968 && code <= 40959) return true;
747
+ if (code >= 44032 && code <= 55215) return true;
748
+ if (code >= 63744 && code <= 64255) return true;
749
+ if (code >= 65280 && code <= 65376) return true;
750
+ if (code >= 65504 && code <= 65510) return true;
751
+ if (code >= 131072 && code <= 196607) return true;
752
+ return false;
753
+ }
754
+ function measureLabelWidth(label) {
755
+ let w = 0;
756
+ for (const ch of label) {
757
+ const code = ch.codePointAt(0) ?? 0;
758
+ if (isFullWidth(code)) w += FC_CONST.cjkCharWidth;
759
+ else w += FC_CONST.charWidth;
760
+ }
761
+ return w;
762
+ }
721
763
  function greedyFAS(nodeIds, edges) {
722
764
  const outAdj = /* @__PURE__ */ new Map();
723
765
  const inAdj = /* @__PURE__ */ new Map();
@@ -1036,6 +1078,46 @@ function laneBasedXCoords(layerNodes, pathOf, nodeSpacingX, segments) {
1036
1078
  }
1037
1079
  }
1038
1080
  }
1081
+ const clusterLanes = laneOrder.filter((l) => l !== null);
1082
+ if (clusterLanes.length >= 2 && laneOrder.includes(null)) {
1083
+ const tmpPartition = layerNodes.map(
1084
+ (layer) => {
1085
+ const m = /* @__PURE__ */ new Map();
1086
+ for (const n of layer) {
1087
+ if (n.isDummy) continue;
1088
+ const lane = laneOf(n.id);
1089
+ if (!m.has(lane)) m.set(lane, []);
1090
+ m.get(lane).push(n);
1091
+ }
1092
+ return m;
1093
+ }
1094
+ );
1095
+ const clusterOccupiedLayers = /* @__PURE__ */ new Set();
1096
+ for (let li = 0; li < tmpPartition.length; li++) {
1097
+ for (const lane of clusterLanes) {
1098
+ if ((tmpPartition[li].get(lane) ?? []).length > 0) {
1099
+ clusterOccupiedLayers.add(li);
1100
+ }
1101
+ }
1102
+ }
1103
+ let nullIsBoundary = true;
1104
+ for (let li = 0; li < tmpPartition.length; li++) {
1105
+ const nm = tmpPartition[li].get(null) ?? [];
1106
+ if (nm.length > 0 && clusterOccupiedLayers.has(li)) {
1107
+ nullIsBoundary = false;
1108
+ break;
1109
+ }
1110
+ }
1111
+ if (nullIsBoundary) {
1112
+ const mid = Math.floor(clusterLanes.length / 2);
1113
+ laneOrder.length = 0;
1114
+ laneOrder.push(
1115
+ ...clusterLanes.slice(0, mid),
1116
+ null,
1117
+ ...clusterLanes.slice(mid)
1118
+ );
1119
+ }
1120
+ }
1039
1121
  const lanesPerLayer = layerNodes.map(
1040
1122
  (layer) => {
1041
1123
  const m = /* @__PURE__ */ new Map();
@@ -1110,22 +1192,52 @@ function laneBasedXCoords(layerNodes, pathOf, nodeSpacingX, segments) {
1110
1192
  }
1111
1193
  return result;
1112
1194
  }
1195
+ function hasOverlappingTopLevelClusters(ast, layerMap, sgParent) {
1196
+ const topLevel = ast.subgraphs.filter((sg) => !sgParent.get(sg.id));
1197
+ if (topLevel.length < 2) return false;
1198
+ const collect = (sgId) => {
1199
+ const sg = ast.subgraphs.find((s) => s.id === sgId);
1200
+ if (!sg) return [];
1201
+ const ids = [...sg.children];
1202
+ for (const childSgId of sg.subgraphs) ids.push(...collect(childSgId));
1203
+ return ids;
1204
+ };
1205
+ const ranges = topLevel.map((sg) => {
1206
+ const ids = collect(sg.id);
1207
+ if (ids.length === 0) return { min: 0, max: -1 };
1208
+ const layers = ids.map((id) => layerMap.get(id) ?? 0);
1209
+ return { min: Math.min(...layers), max: Math.max(...layers) };
1210
+ });
1211
+ for (let i = 0; i < ranges.length; i++) {
1212
+ for (let j = i + 1; j < ranges.length; j++) {
1213
+ const a = ranges[i];
1214
+ const b = ranges[j];
1215
+ if (a.max < a.min || b.max < b.min) continue;
1216
+ if (a.min <= b.max && b.min <= a.max) return true;
1217
+ }
1218
+ }
1219
+ return false;
1220
+ }
1113
1221
  function layoutFlowchart(ast) {
1114
1222
  const dir = ast.direction;
1115
1223
  const isHorizontalDir = dir === "LR" || dir === "RL";
1116
1224
  const sizeOf = (n) => {
1225
+ const rawTextW = measureLabelWidth(n.label);
1117
1226
  const labelW = Math.min(
1118
1227
  FC_CONST.maxLabelWidth,
1119
- Math.ceil(n.label.length * FC_CONST.charWidth) + FC_CONST.labelHPad * 2
1228
+ Math.ceil(rawTextW) + FC_CONST.labelHPad * 2
1120
1229
  );
1121
1230
  let shapeW = Math.max(FC_CONST.minNodeWidth, labelW);
1122
1231
  let shapeH = FC_CONST.nodeHeight;
1123
1232
  if (n.shape === "diamond") {
1124
- shapeW = Math.max(shapeW, labelW * 1.25);
1233
+ shapeW = Math.max(shapeW, labelW * 1.4);
1125
1234
  shapeH = Math.max(shapeH, 52);
1126
1235
  }
1127
- if (n.shape === "parallelogram" || n.shape === "parallelogram-alt" || n.shape === "trapezoid" || n.shape === "trapezoid-alt") {
1128
- shapeW += 20;
1236
+ if (n.shape === "parallelogram" || n.shape === "parallelogram-alt") {
1237
+ shapeW += 2 * SHAPE_SLANT.parallelogram + 8;
1238
+ }
1239
+ if (n.shape === "trapezoid" || n.shape === "trapezoid-alt") {
1240
+ shapeW += 2 * SHAPE_SLANT.trapezoid + 8;
1129
1241
  }
1130
1242
  if (n.shape === "stadium" || n.shape === "round") {
1131
1243
  shapeW = Math.max(shapeW, shapeH + 20);
@@ -1136,7 +1248,10 @@ function layoutFlowchart(ast) {
1136
1248
  shapeH = side;
1137
1249
  }
1138
1250
  if (n.shape === "hexagon") {
1139
- shapeW = Math.max(shapeW, labelW + 44);
1251
+ shapeW = Math.max(shapeW, labelW + 48);
1252
+ }
1253
+ if (n.shape === "asymmetric") {
1254
+ shapeW += 24;
1140
1255
  }
1141
1256
  if (n.shape === "cylinder") {
1142
1257
  shapeH = Math.max(shapeH, 52);
@@ -1273,8 +1388,9 @@ function layoutFlowchart(ast) {
1273
1388
  const layerNodes = ordered.map(
1274
1389
  (layer) => layer.map((id) => lnodes.get(id))
1275
1390
  );
1391
+ const useLane = ast.subgraphs.length > 0 && hasOverlappingTopLevelClusters(ast, layerMap, sgParent);
1276
1392
  let xMap;
1277
- if (ast.subgraphs.length > 0) {
1393
+ if (useLane) {
1278
1394
  xMap = laneBasedXCoords(
1279
1395
  layerNodes,
1280
1396
  pathOf,
@@ -1288,7 +1404,6 @@ function layoutFlowchart(ast) {
1288
1404
  xMap = bkXCoords(bkLayers, segments, FC_CONST.nodeSpacingX);
1289
1405
  }
1290
1406
  const isHorizontal = dir === "LR" || dir === "RL";
1291
- const layerGap = FC_CONST.layerSpacingY;
1292
1407
  const layerHeights = layerNodes.map((layer) => {
1293
1408
  let maxH = 0;
1294
1409
  for (const n of layer) {
@@ -1298,17 +1413,56 @@ function layoutFlowchart(ast) {
1298
1413
  return maxH > 0 ? maxH : FC_CONST.nodeHeight;
1299
1414
  });
1300
1415
  const hasClusters = ast.subgraphs.length > 0;
1301
- const CLUSTER_OVERHEAD_TITLE = hasClusters ? 44 : 0;
1302
- const CLUSTER_OVERHEAD_SIDE = hasClusters ? 24 : 0;
1416
+ const CLUSTER_OVERHEAD_TITLE = hasClusters ? CLUSTER_GEO.pad + CLUSTER_GEO.titleH : 0;
1417
+ const CLUSTER_OVERHEAD_SIDE = hasClusters ? CLUSTER_GEO.pad : 0;
1303
1418
  const extraTopPad = isHorizontal ? CLUSTER_OVERHEAD_SIDE : CLUSTER_OVERHEAD_TITLE;
1304
1419
  const extraLeftPad = isHorizontal ? CLUSTER_OVERHEAD_TITLE : CLUSTER_OVERHEAD_SIDE;
1420
+ const topLevelOf = (sgId) => {
1421
+ let cur = sgId;
1422
+ let safety = 32;
1423
+ while (safety-- > 0) {
1424
+ const p = sgParent.get(cur);
1425
+ if (!p) return cur;
1426
+ cur = p;
1427
+ }
1428
+ return cur;
1429
+ };
1430
+ const clustersAtLayer = layerNodes.map(() => /* @__PURE__ */ new Set());
1431
+ for (let li = 0; li < layerNodes.length; li++) {
1432
+ for (const n of layerNodes[li]) {
1433
+ if (n.isDummy) continue;
1434
+ const parent = parentOf.get(n.id);
1435
+ if (!parent) continue;
1436
+ clustersAtLayer[li].add(topLevelOf(parent));
1437
+ }
1438
+ }
1439
+ const layerGapAt = (li) => {
1440
+ const a = clustersAtLayer[li] ?? /* @__PURE__ */ new Set();
1441
+ const b = clustersAtLayer[li + 1] ?? /* @__PURE__ */ new Set();
1442
+ let hasExit = false;
1443
+ for (const c of a) if (!b.has(c)) {
1444
+ hasExit = true;
1445
+ break;
1446
+ }
1447
+ let hasEntry = false;
1448
+ for (const c of b) if (!a.has(c)) {
1449
+ hasEntry = true;
1450
+ break;
1451
+ }
1452
+ let required = 0;
1453
+ if (hasExit) required += CLUSTER_GEO.pad;
1454
+ if (hasEntry) required += CLUSTER_GEO.pad + CLUSTER_GEO.titleH;
1455
+ if (hasExit && hasEntry) required += CLUSTER_GEO.gap;
1456
+ return Math.max(FC_CONST.layerSpacingY, required);
1457
+ };
1305
1458
  const layerCenterY = [];
1306
1459
  {
1307
1460
  let y = FC_CONST.padding + extraTopPad;
1308
1461
  for (let li = 0; li < layerHeights.length; li++) {
1309
1462
  y += layerHeights[li] / 2;
1310
1463
  layerCenterY.push(y);
1311
- y += layerHeights[li] / 2 + layerGap;
1464
+ y += layerHeights[li] / 2;
1465
+ if (li < layerHeights.length - 1) y += layerGapAt(li);
1312
1466
  }
1313
1467
  }
1314
1468
  let minX = Infinity;
@@ -1452,8 +1606,7 @@ function layoutFlowchart(ast) {
1452
1606
  }
1453
1607
  return 0;
1454
1608
  }
1455
- const CLUSTER_PAD = 24;
1456
- const CLUSTER_TITLE_H = 20;
1609
+ const { pad: CLUSTER_PAD, titleH: CLUSTER_TITLE_H } = CLUSTER_GEO;
1457
1610
  const clusters = ast.subgraphs.map((sg) => {
1458
1611
  const memberIds = collectDescendantNodeIds(sg.id);
1459
1612
  const members = outNodes.filter((n) => memberIds.includes(n.node.id));
@@ -1554,23 +1707,23 @@ function shapeSVG(shape, w, h) {
1554
1707
  return polygon({ points, class: "sx-fc-node sx-fc-node-diamond" });
1555
1708
  }
1556
1709
  case "parallelogram": {
1557
- const slant = 20;
1710
+ const slant = SHAPE_SLANT.parallelogram;
1558
1711
  const points = `${slant},0 ${w},0 ${w - slant},${h} 0,${h}`;
1559
1712
  return polygon({ points, class: "sx-fc-node" });
1560
1713
  }
1561
1714
  // ── M2 additional shapes ────────────────────────────────────
1562
1715
  case "parallelogram-alt": {
1563
- const slant = 20;
1716
+ const slant = SHAPE_SLANT.parallelogram;
1564
1717
  const points = `0,0 ${w - slant},0 ${w},${h} ${slant},${h}`;
1565
1718
  return polygon({ points, class: "sx-fc-node" });
1566
1719
  }
1567
1720
  case "trapezoid": {
1568
- const slant = 16;
1721
+ const slant = SHAPE_SLANT.trapezoid;
1569
1722
  const points = `0,0 ${w},0 ${w - slant},${h} ${slant},${h}`;
1570
1723
  return polygon({ points, class: "sx-fc-node" });
1571
1724
  }
1572
1725
  case "trapezoid-alt": {
1573
- const slant = 16;
1726
+ const slant = SHAPE_SLANT.trapezoid;
1574
1727
  const points = `${slant},0 ${w - slant},0 ${w},${h} 0,${h}`;
1575
1728
  return polygon({ points, class: "sx-fc-node" });
1576
1729
  }
@@ -1869,5 +2022,5 @@ var flowchart = {
1869
2022
  };
1870
2023
 
1871
2024
  export { FC_CONST, flowchart, layoutFlowchart, parseFlowchart, renderFlowchart, renderFlowchartAST };
1872
- //# sourceMappingURL=chunk-Z3WOHHG3.js.map
1873
- //# sourceMappingURL=chunk-Z3WOHHG3.js.map
2025
+ //# sourceMappingURL=chunk-J2LVOWVY.js.map
2026
+ //# sourceMappingURL=chunk-J2LVOWVY.js.map