@diagrammo/dgmo 0.75.0 → 0.77.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 (120) hide show
  1. package/dist/advanced.d.ts +181 -12
  2. package/dist/advanced.js +267 -60
  3. package/dist/block.css +20 -3
  4. package/dist/block.d.ts +12 -4
  5. package/dist/block.js +35 -18
  6. package/dist/{chart-meta-lP8Rl19E.d.ts → chart-meta-Cf_jkApJ.d.ts} +2 -2
  7. package/dist/chart-meta.d.ts +3 -3
  8. package/dist/chart-meta.js +6 -6
  9. package/dist/{charts-d3-SQEVMIAM.js → charts-d3-HMEMHSSW.js} +5 -5
  10. package/dist/{chunk-E3BJVEMZ.js → chunk-2MTM4E6M.js} +2 -2
  11. package/dist/{chunk-UBW53CNS.js → chunk-3E4YB6TY.js} +2 -2
  12. package/dist/{chunk-IFC3JXCT.js → chunk-3O7ZYVJV.js} +2 -2
  13. package/dist/{chunk-Q6BAFS7I.js → chunk-43AJKH2U.js} +3 -3
  14. package/dist/{chunk-2NRIGEHZ.js → chunk-46KVXDUJ.js} +10 -3
  15. package/dist/chunk-53SEVJQM.js +9 -0
  16. package/dist/{chunk-UTTRJ6KN.js → chunk-5ZD4DDG7.js} +4 -4
  17. package/dist/{chunk-AFR6GWXD.js → chunk-6BVAW7KI.js} +4 -4
  18. package/dist/{chunk-CLQJAGWL.js → chunk-6IN4F4RH.js} +4 -4
  19. package/dist/{chunk-76IBFEYW.js → chunk-6ZZKEYBS.js} +4 -4
  20. package/dist/{chunk-QUYYL3LP.js → chunk-7CXW6EGX.js} +5 -5
  21. package/dist/chunk-7IATMZSA.js +72 -0
  22. package/dist/{chunk-HOIAQ3P2.js → chunk-B52RL5VV.js} +2 -2
  23. package/dist/{chunk-IGQW7TKM.js → chunk-BH3BQICT.js} +5 -5
  24. package/dist/{chunk-3LJNQ6LR.js → chunk-CF3I5SOG.js} +5 -5
  25. package/dist/{chunk-ZMKCG3FT.js → chunk-CHOK7NCJ.js} +6 -6
  26. package/dist/{chunk-U74EGVOA.js → chunk-CIWFL2LM.js} +4 -4
  27. package/dist/{chunk-OUJG73YJ.js → chunk-CYMYZYLI.js} +5 -5
  28. package/dist/{chunk-BCB24FG7.js → chunk-D3B6YEZK.js} +3 -3
  29. package/dist/{chunk-XHROEQ23.js → chunk-DSXWJAOA.js} +4 -4
  30. package/dist/{chunk-RT7ACF77.js → chunk-EGY3TS62.js} +6 -6
  31. package/dist/{chunk-CQKD6GOC.js → chunk-EUVUOPRC.js} +4 -4
  32. package/dist/{chunk-TDHD3HNO.js → chunk-F4X5NVKY.js} +37 -16
  33. package/dist/{chunk-7G4XMHDB.js → chunk-FF7LRT5L.js} +4 -4
  34. package/dist/{chunk-6DYZ2JM6.js → chunk-FR5EVD2X.js} +206 -32
  35. package/dist/{chunk-R5JPMW2F.js → chunk-FTTB64OJ.js} +5 -5
  36. package/dist/{chunk-U7AO6FRL.js → chunk-H7BYMIVK.js} +312 -118
  37. package/dist/{chunk-M3IVOGZE.js → chunk-HDLRRY3N.js} +61 -55
  38. package/dist/{chunk-F4CPZRG2.js → chunk-J76YDS4V.js} +2 -2
  39. package/dist/{chunk-SUA56ZSB.js → chunk-LTTZX6RD.js} +6 -2
  40. package/dist/{chunk-7EZ5AKBK.js → chunk-LYJ53DBK.js} +8 -6
  41. package/dist/{chunk-JQ575OAK.js → chunk-MZEGUDTA.js} +2 -2
  42. package/dist/{chunk-IHUOYDLN.js → chunk-N5NQIZ56.js} +5 -5
  43. package/dist/{chunk-GE5RO4BS.js → chunk-N6MZSBOL.js} +5 -1
  44. package/dist/{chunk-DU3OIBQE.js → chunk-NWNSXHA5.js} +6 -2
  45. package/dist/{chunk-32MOGTKT.js → chunk-OO2L2LWV.js} +4 -4
  46. package/dist/{chunk-XCAEHWQB.js → chunk-OZOHREFQ.js} +3 -3
  47. package/dist/{chunk-DSH7NJ2G.js → chunk-QBM5BURJ.js} +4 -4
  48. package/dist/{chunk-YVDBBWEP.js → chunk-QXMHBIQG.js} +4 -4
  49. package/dist/{chunk-UWYZIGCB.js → chunk-RGW26UAR.js} +2 -2
  50. package/dist/{chunk-QI4Q5ZZH.js → chunk-RV5A3EGI.js} +4 -4
  51. package/dist/{chunk-HGFKDSKZ.js → chunk-SI3PYDL4.js} +4 -4
  52. package/dist/{chunk-CAPR5DET.js → chunk-SSEAULA5.js} +2 -2
  53. package/dist/{chunk-AYM472K3.js → chunk-SWUQJ5VR.js} +3 -3
  54. package/dist/{chunk-HFCKU73Y.js → chunk-TI4YUUW6.js} +3 -3
  55. package/dist/{chunk-LYLRNAX2.js → chunk-TKIPK5P6.js} +3 -3
  56. package/dist/{chunk-QT5UMFPE.js → chunk-U4DS2ODO.js} +3 -3
  57. package/dist/{chunk-XFLLYY3V.js → chunk-UBDVAHGK.js} +36 -52
  58. package/dist/{chunk-JL7BDLC6.js → chunk-UH5YTZN7.js} +4 -4
  59. package/dist/{chunk-GEURKGZS.js → chunk-V4NHFY22.js} +4 -4
  60. package/dist/{chunk-4SXHMFFP.js → chunk-VRPV6QXR.js} +23 -12
  61. package/dist/{chunk-BFTRW24X.js → chunk-WHWUVDYK.js} +65 -24
  62. package/dist/{chunk-U5B3TUEW.js → chunk-XCFIAGT7.js} +2 -2
  63. package/dist/{chunk-COCMMQXW.js → chunk-XFXJXLK7.js} +2 -2
  64. package/dist/{chunk-YDA46XHI.js → chunk-XPBJVSRY.js} +2 -2
  65. package/dist/{chunk-VV6HZQ5K.js → chunk-YM5RMLFO.js} +2 -2
  66. package/dist/{d3--y67plmW.d.ts → d3-BiaJtaSw.d.ts} +1 -1
  67. package/dist/{dgmo-router-KYNLRE7S.js → dgmo-router-A3LIHT6H.js} +7 -7
  68. package/dist/{dgmo-router-CY5j16Pl.d.ts → dgmo-router-BwXHZ_P3.d.ts} +1 -1
  69. package/dist/{dimensions-NLQ64ED5.js → dimensions-OFF4GRFL.js} +4 -4
  70. package/dist/{flowchart-parser-LY5GGQL2.js → flowchart-parser-NVBP3C5D.js} +2 -2
  71. package/dist/{flowchart-renderer-RIJ5FZKO.js → flowchart-renderer-BBJUPORB.js} +6 -6
  72. package/dist/index.d.ts +7 -7
  73. package/dist/index.js +14 -14
  74. package/dist/{layout-UJ62RQQ3.js → layout-2OJ25STS.js} +2 -2
  75. package/dist/{layout-DAYQ46PS.js → layout-Y2V3LYV7.js} +3 -3
  76. package/dist/{parser-LUOINP6H.js → parser-QYAIFXLP.js} +3 -3
  77. package/dist/{parser-L7RXUKYN.js → parser-WVE6SKB7.js} +2 -2
  78. package/dist/{parser-JYIZEKAS.js → parser-ZYAFHXKQ.js} +2 -2
  79. package/dist/{renderer-FUJNSC5X.js → renderer-2ANDPQWC.js} +3 -3
  80. package/dist/{renderer-UYZSP7MF.js → renderer-2LDT4TUX.js} +5 -5
  81. package/dist/{renderer-4EWGZLJ6.js → renderer-2NYQDW37.js} +3 -3
  82. package/dist/{renderer-LBNVKVO3.js → renderer-2RIIIO34.js} +5 -5
  83. package/dist/{renderer-PKRKLOYR.js → renderer-3HFU3DTO.js} +5 -5
  84. package/dist/{renderer-UUP6OX6F.js → renderer-4BF6ILP6.js} +5 -5
  85. package/dist/{renderer-MUW4G2N6.js → renderer-5E2AH5TO.js} +7 -7
  86. package/dist/{renderer-DKW273R7.js → renderer-62SLWRYF.js} +6 -5
  87. package/dist/{renderer-WDSBFDQ2.js → renderer-ANJUDBOS.js} +6 -6
  88. package/dist/{renderer-OTHBTGBN.js → renderer-CVWQD442.js} +3 -3
  89. package/dist/{renderer-GJDVPXI3.js → renderer-D6GJ6EVK.js} +6 -6
  90. package/dist/{renderer-KMOGGMM7.js → renderer-DNFV2IQI.js} +5 -5
  91. package/dist/{renderer-UYYBJ7OB.js → renderer-EDVCGIQO.js} +10 -10
  92. package/dist/{renderer-73QHYZ2Q.js → renderer-EFQSMHID.js} +6 -6
  93. package/dist/{renderer-EP4GRCDX.js → renderer-FTX67CYZ.js} +3 -3
  94. package/dist/{renderer-GF6S5ZX6.js → renderer-G2DPKJAN.js} +5 -5
  95. package/dist/{renderer-QAMOXOZ2.js → renderer-GHBF5PRH.js} +3 -3
  96. package/dist/{renderer-5W3HWIUL.js → renderer-GZLRX764.js} +5 -5
  97. package/dist/{renderer-CO5O5VR5.js → renderer-H2HYLFN3.js} +3 -3
  98. package/dist/{renderer-JMJ7Q5OC.js → renderer-IR5655M7.js} +5 -5
  99. package/dist/{renderer-4PNVGHVA.js → renderer-L237AOOZ.js} +3 -3
  100. package/dist/{renderer-A2YWSBPY.js → renderer-LSJWYGOL.js} +7 -7
  101. package/dist/{renderer-PR3KLNST.js → renderer-LWXDMZOV.js} +5 -5
  102. package/dist/{renderer-3FB56573.js → renderer-MYSVPERC.js} +5 -5
  103. package/dist/{renderer-FGGDZZFQ.js → renderer-OL5QSZPC.js} +6 -6
  104. package/dist/{renderer-XBL6CLN2.js → renderer-P26HH3NA.js} +5 -5
  105. package/dist/{renderer-D7N7PPB7.js → renderer-R5HIRN2M.js} +3 -3
  106. package/dist/{renderer-BUEFD2IF.js → renderer-RNFECJ5D.js} +5 -5
  107. package/dist/{renderer-F24V3RD3.js → renderer-RPZVNCTF.js} +5 -5
  108. package/dist/{renderer-PIEPRK6M.js → renderer-SDNWZDUY.js} +5 -5
  109. package/dist/{renderer-RUHC6D3B.js → renderer-UKHH4UWV.js} +5 -5
  110. package/dist/{renderer-CGOPX4HW.js → renderer-VF7X66SL.js} +5 -5
  111. package/dist/{renderer-ZAJ5353N.js → renderer-Y3Y7PEUS.js} +3 -3
  112. package/dist/{renderer-radial-MZP3SVTZ.js → renderer-radial-QNGCGKZP.js} +5 -5
  113. package/dist/{state-renderer-454ADT7E.js → state-renderer-ELWDRXD6.js} +7 -7
  114. package/dist/{tag-groups-DrHT2tEc.d.ts → tag-groups-BAtkq0b_.d.ts} +39 -1
  115. package/dist/{themes-GWhsabnx.d.ts → themes-DpsyRSO7.d.ts} +2 -2
  116. package/docs/language-reference.md +3 -3
  117. package/gallery/fixtures/sketch.dgmo +1 -1
  118. package/package.json +5 -4
  119. package/dist/chunk-PDKUANDZ.js +0 -35
  120. package/dist/chunk-UTCPNJND.js +0 -7
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  SKETCH_DIAGNOSTIC_CODES
3
- } from "./chunk-RT7ACF77.js";
3
+ } from "./chunk-EGY3TS62.js";
4
4
  import {
5
5
  makeDgmoError
6
6
  } from "./chunk-5SI6T5A5.js";
@@ -9,7 +9,7 @@ import {
9
9
  var SKETCH_PHI = (1 + Math.sqrt(5)) / 2;
10
10
  var SKETCH_GEOMETRY = {
11
11
  /** px per grid cell (the dot-grid pitch) */
12
- cellPx: 26,
12
+ cellPx: 16,
13
13
  /** universal footprint width, in grid cells */
14
14
  footprintCellsW: 8,
15
15
  /**
@@ -19,9 +19,9 @@ var SKETCH_GEOMETRY = {
19
19
  gapCellsX: 4,
20
20
  gapCellsY: 4,
21
21
  /** box reserved top band, px (spec decision 12) */
22
- bandPx: 44,
22
+ bandPx: 28,
23
23
  /** box frame padding around the children bbox, px */
24
- boxPadPx: 26,
24
+ boxPadPx: 16,
25
25
  /** edge-ring (connect hook) width as a fraction of footprint height */
26
26
  ringFrac: 0.22
27
27
  };
@@ -94,15 +94,85 @@ function resolveAutoFlags(f = {}) {
94
94
  function unitRect(c, r) {
95
95
  return { c, r, w: SKETCH_SEP, h: SKETCH_SEP };
96
96
  }
97
+ var childBoxAt = /* @__PURE__ */ new Map();
98
+ function nearestFreeRect(base, occupied) {
99
+ if (!occupied.hits(base)) return { c: base.c, r: base.r };
100
+ for (let d = 1; d <= 200; d++) {
101
+ const candidates = [];
102
+ for (let dc = -d; dc <= d; dc++) {
103
+ const dr = d - Math.abs(dc);
104
+ candidates.push({ c: base.c + dc, r: base.r + dr });
105
+ if (dr !== 0) candidates.push({ c: base.c + dc, r: base.r - dr });
106
+ }
107
+ candidates.sort((a, b) => {
108
+ const costA = (a.r < base.r ? 2 : 0) + (a.c < base.c ? 1 : 0);
109
+ const costB = (b.r < base.r ? 2 : 0) + (b.c < base.c ? 1 : 0);
110
+ return costA - costB || a.r - b.r || a.c - b.c;
111
+ });
112
+ for (const cand of candidates) {
113
+ if (!occupied.hits({ ...base, c: cand.c, r: cand.r })) return cand;
114
+ }
115
+ }
116
+ return { c: base.c, r: base.r };
117
+ }
97
118
  function rectsOverlap(a, b) {
98
119
  return a.c < b.c + b.w && b.c < a.c + a.w && a.r < b.r + b.h && b.r < a.r + a.h;
99
120
  }
100
- function collidesAny(rect, occupied) {
101
- for (const o of occupied) if (rectsOverlap(rect, o)) return true;
102
- return false;
121
+ var CELL = SKETCH_SEP;
122
+ var OVERSIZED_CELLS = 64;
123
+ function cellRange(rect) {
124
+ return [
125
+ Math.floor(rect.c / CELL),
126
+ Math.floor(rect.r / CELL),
127
+ Math.floor((rect.c + rect.w) / CELL),
128
+ Math.floor((rect.r + rect.h) / CELL)
129
+ ];
130
+ }
131
+ function cellSpan(range) {
132
+ return (range[2] - range[0] + 1) * (range[3] - range[1] + 1);
103
133
  }
134
+ var Occupancy = class {
135
+ grid = /* @__PURE__ */ new Map();
136
+ oversized = [];
137
+ /** Every rect, in insertion order — the extent and flow-origin maths want it. */
138
+ rects = [];
139
+ add(rect) {
140
+ this.rects.push(rect);
141
+ const range = cellRange(rect);
142
+ if (cellSpan(range) > OVERSIZED_CELLS) {
143
+ this.oversized.push(rect);
144
+ return;
145
+ }
146
+ const [c0, r0, c1, r1] = range;
147
+ for (let c = c0; c <= c1; c++) {
148
+ for (let r = r0; r <= r1; r++) {
149
+ const key = `${c},${r}`;
150
+ const bucket = this.grid.get(key);
151
+ if (bucket) bucket.push(rect);
152
+ else this.grid.set(key, [rect]);
153
+ }
154
+ }
155
+ }
156
+ hits(rect) {
157
+ for (const o of this.oversized) if (rectsOverlap(rect, o)) return true;
158
+ const range = cellRange(rect);
159
+ if (cellSpan(range) > OVERSIZED_CELLS) {
160
+ for (const o of this.rects) if (rectsOverlap(rect, o)) return true;
161
+ return false;
162
+ }
163
+ const [c0, r0, c1, r1] = range;
164
+ for (let c = c0; c <= c1; c++) {
165
+ for (let r = r0; r <= r1; r++) {
166
+ const bucket = this.grid.get(`${c},${r}`);
167
+ if (!bucket) continue;
168
+ for (const o of bucket) if (rectsOverlap(rect, o)) return true;
169
+ }
170
+ }
171
+ return false;
172
+ }
173
+ };
104
174
  function nearestFree(base, occupied) {
105
- if (!collidesAny(base, occupied)) return { c: base.c, r: base.r };
175
+ if (!occupied.hits(base)) return { c: base.c, r: base.r };
106
176
  for (let d = 1; d <= 200; d++) {
107
177
  const candidates = [];
108
178
  for (let dc = -d; dc <= d; dc++) {
@@ -116,17 +186,28 @@ function nearestFree(base, occupied) {
116
186
  return costA - costB || a.r - b.r || a.c - b.c;
117
187
  });
118
188
  for (const cand of candidates) {
119
- if (!collidesAny({ ...base, c: cand.c, r: cand.r }, occupied)) {
189
+ if (!occupied.hits({ ...base, c: cand.c, r: cand.r })) {
120
190
  return cand;
121
191
  }
122
192
  }
123
193
  }
124
194
  return { c: base.c, r: base.r };
125
195
  }
126
- function layoutChildren(box, nodesById, warn, flags) {
127
- const occupied = [];
196
+ function layoutChildren(box, nodesById, warn, flags, childBoxRects = /* @__PURE__ */ new Map()) {
197
+ const occupied = new Occupancy();
128
198
  const children = [];
199
+ const localBoxes = [];
129
200
  const pending = [];
201
+ for (const boxId of box.childBoxes) {
202
+ const rect = childBoxRects.get(boxId);
203
+ if (!rect) continue;
204
+ const at = childBoxAt.get(boxId) ?? null;
205
+ const base = at ?? { c: 0, r: 0 };
206
+ const want = { ...rect, c: base.c, r: base.r };
207
+ const spot = flags.resolveOverlap ? nearestFreeRect(want, occupied) : { c: want.c, r: want.r };
208
+ occupied.add({ ...rect, c: spot.c, r: spot.r });
209
+ localBoxes.push({ boxId, c: spot.c, r: spot.r, rect });
210
+ }
130
211
  for (const id of box.children) {
131
212
  const node = nodesById.get(id);
132
213
  if (!node) continue;
@@ -139,25 +220,25 @@ function layoutChildren(box, nodesById, warn, flags) {
139
220
  if (spot.c !== node.at.c || spot.r !== node.at.r) {
140
221
  warn(node.lineNumber, node.label);
141
222
  }
142
- occupied.push(unitRect(spot.c, spot.r));
223
+ occupied.add(unitRect(spot.c, spot.r));
143
224
  children.push({ node, c: spot.c, r: spot.r });
144
225
  }
145
226
  if (!flags.flowPlaceUnpositioned) {
146
227
  for (const node of pending) children.push({ node, c: 0, r: 0 });
147
228
  pending.length = 0;
148
229
  }
149
- let flowRow = occupied.length > 0 ? Math.max(...occupied.map((o) => o.r)) + SKETCH_SEP : 0;
230
+ let flowRow = occupied.rects.length > 0 ? Math.max(...occupied.rects.map((o) => o.r)) + SKETCH_SEP : 0;
150
231
  let flowCol = 0;
151
232
  const wrapAt = Math.max(
152
233
  SKETCH_SEP * 3,
153
- occupied.length > 0 ? Math.max(...occupied.map((o) => o.c)) + SKETCH_SEP : SKETCH_SEP * 3
234
+ occupied.rects.length > 0 ? Math.max(...occupied.rects.map((o) => o.c)) + SKETCH_SEP : SKETCH_SEP * 3
154
235
  );
155
236
  for (const node of pending) {
156
237
  let placed = false;
157
238
  while (!placed) {
158
239
  const rect = unitRect(flowCol, flowRow);
159
- if (!collidesAny(rect, occupied)) {
160
- occupied.push(rect);
240
+ if (!occupied.hits(rect)) {
241
+ occupied.add(rect);
161
242
  children.push({ node, c: flowCol, r: flowRow });
162
243
  placed = true;
163
244
  }
@@ -169,16 +250,16 @@ function layoutChildren(box, nodesById, warn, flags) {
169
250
  }
170
251
  }
171
252
  let extent;
172
- if (occupied.length === 0) {
253
+ if (occupied.rects.length === 0) {
173
254
  extent = { c: 0, r: 0, w: SKETCH_SEP, h: SKETCH_SEP };
174
255
  } else {
175
- const cMin = Math.min(...occupied.map((o) => o.c));
176
- const rMin = Math.min(...occupied.map((o) => o.r));
177
- const cMax = Math.max(...occupied.map((o) => o.c + o.w));
178
- const rMax = Math.max(...occupied.map((o) => o.r + o.h));
256
+ const cMin = Math.min(...occupied.rects.map((o) => o.c));
257
+ const rMin = Math.min(...occupied.rects.map((o) => o.r));
258
+ const cMax = Math.max(...occupied.rects.map((o) => o.c + o.w));
259
+ const rMax = Math.max(...occupied.rects.map((o) => o.r + o.h));
179
260
  extent = { c: cMin, r: rMin, w: cMax - cMin, h: rMax - rMin };
180
261
  }
181
- return { children, extent };
262
+ return { children, boxes: localBoxes, extent };
182
263
  }
183
264
  function layoutSketch(parsed, options = {}) {
184
265
  const diagnostics = [];
@@ -200,11 +281,41 @@ function layoutSketch(parsed, options = {}) {
200
281
  const bandHs = SKETCH_GEOMETRY.bandPx / SKETCH_HALF_SLOT_Y;
201
282
  const boxLocal = /* @__PURE__ */ new Map();
202
283
  const inExpandedBox = /* @__PURE__ */ new Set();
284
+ const boxById = new Map(collapsed.boxes.map((b) => [b.id, b]));
285
+ const nestedBoxIds = new Set(
286
+ collapsed.boxes.filter((b) => b.parentBoxId !== null).map((b) => b.id)
287
+ );
288
+ childBoxAt.clear();
203
289
  for (const box of collapsed.boxes) {
290
+ if (!nestedBoxIds.has(box.id)) continue;
291
+ childBoxAt.set(box.id, box.at);
204
292
  const local = layoutChildren(box, nodesById, overlapWarn, flags);
205
293
  boxLocal.set(box.id, local);
206
294
  for (const child of local.children) inExpandedBox.add(child.node.id);
207
295
  }
296
+ const childBoxRects = /* @__PURE__ */ new Map();
297
+ for (const box of collapsed.boxes) {
298
+ if (!nestedBoxIds.has(box.id)) continue;
299
+ const local = boxLocal.get(box.id);
300
+ childBoxRects.set(box.id, {
301
+ c: 0,
302
+ r: 0,
303
+ w: local.extent.w + 2 * padHsX,
304
+ h: local.extent.h + bandHs + padHsY
305
+ });
306
+ }
307
+ for (const box of collapsed.boxes) {
308
+ if (nestedBoxIds.has(box.id)) continue;
309
+ const local = layoutChildren(
310
+ box,
311
+ nodesById,
312
+ overlapWarn,
313
+ flags,
314
+ childBoxRects
315
+ );
316
+ boxLocal.set(box.id, local);
317
+ for (const child of local.children) inExpandedBox.add(child.node.id);
318
+ }
208
319
  const allNodesById = new Map(parsed.nodes.map((n) => [n.id, n]));
209
320
  const noWarn = () => {
210
321
  };
@@ -242,6 +353,7 @@ function layoutSketch(parsed, options = {}) {
242
353
  rootUnits.push({ kind: "virtual", box });
243
354
  }
244
355
  for (const box of collapsed.boxes) {
356
+ if (nestedBoxIds.has(box.id)) continue;
245
357
  rootUnits.push({ kind: "box", box });
246
358
  }
247
359
  const lineOf = (u) => u.kind === "shape" ? u.node.lineNumber : u.box.lineNumber;
@@ -274,7 +386,7 @@ function layoutSketch(parsed, options = {}) {
274
386
  }
275
387
  return unitRect(c, r);
276
388
  };
277
- const occupied = [];
389
+ const occupied = new Occupancy();
278
390
  const placedAt = /* @__PURE__ */ new Map();
279
391
  const pending = [];
280
392
  for (const unit of rootUnits) {
@@ -285,7 +397,7 @@ function layoutSketch(parsed, options = {}) {
285
397
  }
286
398
  const base = rectFor(unit, at.c, at.r);
287
399
  let spot = { c: at.c, r: at.r };
288
- if (flags.resolveOverlap && unit.kind === "shape" && collidesAny(base, occupied)) {
400
+ if (flags.resolveOverlap && unit.kind === "shape" && occupied.hits(base)) {
289
401
  const freed = nearestFree(base, occupied);
290
402
  spot = {
291
403
  c: at.c + (freed.c - base.c),
@@ -293,28 +405,28 @@ function layoutSketch(parsed, options = {}) {
293
405
  };
294
406
  overlapWarn(unit.node.lineNumber, unit.node.label);
295
407
  }
296
- occupied.push(rectFor(unit, spot.c, spot.r));
408
+ occupied.add(rectFor(unit, spot.c, spot.r));
297
409
  placedAt.set(unit, spot);
298
410
  }
299
411
  if (!flags.flowPlaceUnpositioned) {
300
412
  for (const unit of pending) {
301
- occupied.push(rectFor(unit, 0, 0));
413
+ occupied.add(rectFor(unit, 0, 0));
302
414
  placedAt.set(unit, { c: 0, r: 0 });
303
415
  }
304
416
  pending.length = 0;
305
417
  }
306
- let flowRow = occupied.length > 0 ? Math.ceil(Math.max(...occupied.map((o) => o.r + o.h))) : 0;
418
+ let flowRow = occupied.rects.length > 0 ? Math.ceil(Math.max(...occupied.rects.map((o) => o.r + o.h))) : 0;
307
419
  let flowCol = 0;
308
420
  const wrapAt = Math.max(
309
421
  SKETCH_SEP * 4,
310
- occupied.length > 0 ? Math.ceil(Math.max(...occupied.map((o) => o.c + o.w))) : SKETCH_SEP * 4
422
+ occupied.rects.length > 0 ? Math.ceil(Math.max(...occupied.rects.map((o) => o.c + o.w))) : SKETCH_SEP * 4
311
423
  );
312
424
  for (const unit of pending) {
313
425
  let placed = false;
314
426
  while (!placed) {
315
427
  const rect = rectFor(unit, flowCol, flowRow);
316
- if (!collidesAny(rect, occupied)) {
317
- occupied.push(rect);
428
+ if (!occupied.hits(rect)) {
429
+ occupied.add(rect);
318
430
  placedAt.set(unit, { c: flowCol, r: flowRow });
319
431
  placed = true;
320
432
  }
@@ -409,6 +521,64 @@ function layoutSketch(parsed, options = {}) {
409
521
  maxX = origin.x + SKETCH_FOOT_W;
410
522
  maxY = minY;
411
523
  }
524
+ for (const inner of local.boxes) {
525
+ const innerBox = boxById.get(inner.boxId);
526
+ const innerLocal = boxLocal.get(inner.boxId);
527
+ if (!innerBox || !innerLocal) continue;
528
+ const innerRectOrigin = toPx(spot.c + inner.c, spot.r + inner.r);
529
+ const innerContentX = innerRectOrigin.x + SKETCH_GEOMETRY.boxPadPx - innerLocal.extent.c * SKETCH_HALF_SLOT_X;
530
+ const innerContentY = innerRectOrigin.y + SKETCH_GEOMETRY.bandPx - innerLocal.extent.r * SKETCH_HALF_SLOT_Y;
531
+ let iMinX = Infinity;
532
+ let iMinY = Infinity;
533
+ let iMaxX = -Infinity;
534
+ let iMaxY = -Infinity;
535
+ for (const gc of innerLocal.children) {
536
+ const gx = innerContentX + gc.c * SKETCH_HALF_SLOT_X;
537
+ const gy = innerContentY + gc.r * SKETCH_HALF_SLOT_Y;
538
+ nodes.push({
539
+ id: gc.node.id,
540
+ label: gc.node.label,
541
+ shape: gc.node.shape,
542
+ metadata: gc.node.metadata,
543
+ ...gc.node.description && { description: gc.node.description },
544
+ boxLabel: innerBox.label,
545
+ lineNumber: gc.node.lineNumber,
546
+ slot: { c: spot.c + inner.c, r: spot.r + inner.r },
547
+ x: gx,
548
+ y: gy,
549
+ w: SKETCH_FOOT_W,
550
+ h: SKETCH_FOOT_H
551
+ });
552
+ iMinX = Math.min(iMinX, gx);
553
+ iMinY = Math.min(iMinY, gy);
554
+ iMaxX = Math.max(iMaxX, gx + SKETCH_FOOT_W);
555
+ iMaxY = Math.max(iMaxY, gy + SKETCH_FOOT_H);
556
+ }
557
+ if (iMinX === Infinity) {
558
+ iMinX = innerContentX;
559
+ iMinY = innerContentY + SKETCH_GEOMETRY.bandPx;
560
+ iMaxX = innerContentX + SKETCH_FOOT_W;
561
+ iMaxY = iMinY;
562
+ }
563
+ const iFrame = {
564
+ x: iMinX - SKETCH_GEOMETRY.boxPadPx,
565
+ y: iMinY - SKETCH_GEOMETRY.bandPx,
566
+ w: iMaxX - iMinX + 2 * SKETCH_GEOMETRY.boxPadPx,
567
+ h: iMaxY - iMinY + SKETCH_GEOMETRY.bandPx + SKETCH_GEOMETRY.boxPadPx
568
+ };
569
+ boxes.push({
570
+ id: innerBox.id,
571
+ label: innerBox.label,
572
+ metadata: innerBox.metadata,
573
+ lineNumber: innerBox.lineNumber,
574
+ ...iFrame,
575
+ bandH: SKETCH_GEOMETRY.bandPx
576
+ });
577
+ minX = Math.min(minX, iFrame.x);
578
+ minY = Math.min(minY, iFrame.y);
579
+ maxX = Math.max(maxX, iFrame.x + iFrame.w);
580
+ maxY = Math.max(maxY, iFrame.y + iFrame.h);
581
+ }
412
582
  boxes.push({
413
583
  id: unit.box.id,
414
584
  label: unit.box.label,
@@ -507,9 +677,13 @@ function layoutSketch(parsed, options = {}) {
507
677
  width = Math.max(width, b.x + b.w);
508
678
  height = Math.max(height, b.y + b.h);
509
679
  }
680
+ const orderedBoxes = [
681
+ ...boxes.filter((b) => !nestedBoxIds.has(b.id)),
682
+ ...boxes.filter((b) => nestedBoxIds.has(b.id))
683
+ ];
510
684
  return {
511
685
  nodes,
512
- boxes,
686
+ boxes: orderedBoxes,
513
687
  edges: collapsed.edges,
514
688
  width,
515
689
  height,
@@ -532,4 +706,4 @@ export {
532
706
  SKETCH_AUTO_LAYOUT_DEFAULTS,
533
707
  layoutSketch
534
708
  };
535
- //# sourceMappingURL=chunk-6DYZ2JM6.js.map
709
+ //# sourceMappingURL=chunk-FR5EVD2X.js.map
@@ -51,7 +51,7 @@ import {
51
51
  } from "./chunk-KRTLS3G6.js";
52
52
  import {
53
53
  parseSketch
54
- } from "./chunk-TDHD3HNO.js";
54
+ } from "./chunk-F4X5NVKY.js";
55
55
  import {
56
56
  parseSwimlane
57
57
  } from "./chunk-W7UBPARG.js";
@@ -89,7 +89,7 @@ import {
89
89
  } from "./chunk-ZM27UI5O.js";
90
90
  import {
91
91
  parseInfra
92
- } from "./chunk-2NRIGEHZ.js";
92
+ } from "./chunk-46KVXDUJ.js";
93
93
  import {
94
94
  parseGantt
95
95
  } from "./chunk-TPN7RJOM.js";
@@ -106,7 +106,7 @@ import {
106
106
  import {
107
107
  looksLikeFlowchart,
108
108
  parseFlowchart
109
- } from "./chunk-DU3OIBQE.js";
109
+ } from "./chunk-NWNSXHA5.js";
110
110
  import {
111
111
  looksLikeState,
112
112
  parseState
@@ -114,7 +114,7 @@ import {
114
114
  import {
115
115
  looksLikeClassDiagram,
116
116
  parseClassDiagram
117
- } from "./chunk-SUA56ZSB.js";
117
+ } from "./chunk-LTTZX6RD.js";
118
118
  import {
119
119
  looksLikeERDiagram,
120
120
  parseERDiagram
@@ -1716,4 +1716,4 @@ export {
1716
1716
  knownChartTypeIds,
1717
1717
  parseDgmo
1718
1718
  };
1719
- //# sourceMappingURL=chunk-R5JPMW2F.js.map
1719
+ //# sourceMappingURL=chunk-FTTB64OJ.js.map