@tldraw/mermaid 4.6.0-internal.c7df3c92455a

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 (55) hide show
  1. package/dist-cjs/blueprint.js +17 -0
  2. package/dist-cjs/blueprint.js.map +7 -0
  3. package/dist-cjs/colors.js +173 -0
  4. package/dist-cjs/colors.js.map +7 -0
  5. package/dist-cjs/createMermaidDiagram.js +144 -0
  6. package/dist-cjs/createMermaidDiagram.js.map +7 -0
  7. package/dist-cjs/flowchartDiagram.js +202 -0
  8. package/dist-cjs/flowchartDiagram.js.map +7 -0
  9. package/dist-cjs/index.d.ts +114 -0
  10. package/dist-cjs/index.js +34 -0
  11. package/dist-cjs/index.js.map +7 -0
  12. package/dist-cjs/renderBlueprint.js +314 -0
  13. package/dist-cjs/renderBlueprint.js.map +7 -0
  14. package/dist-cjs/sequenceDiagram.js +686 -0
  15. package/dist-cjs/sequenceDiagram.js.map +7 -0
  16. package/dist-cjs/stateDiagram.js +373 -0
  17. package/dist-cjs/stateDiagram.js.map +7 -0
  18. package/dist-cjs/svgParsing.js +187 -0
  19. package/dist-cjs/svgParsing.js.map +7 -0
  20. package/dist-cjs/utils.js +75 -0
  21. package/dist-cjs/utils.js.map +7 -0
  22. package/dist-esm/blueprint.mjs +1 -0
  23. package/dist-esm/blueprint.mjs.map +7 -0
  24. package/dist-esm/colors.mjs +153 -0
  25. package/dist-esm/colors.mjs.map +7 -0
  26. package/dist-esm/createMermaidDiagram.mjs +114 -0
  27. package/dist-esm/createMermaidDiagram.mjs.map +7 -0
  28. package/dist-esm/flowchartDiagram.mjs +188 -0
  29. package/dist-esm/flowchartDiagram.mjs.map +7 -0
  30. package/dist-esm/index.d.mts +114 -0
  31. package/dist-esm/index.mjs +14 -0
  32. package/dist-esm/index.mjs.map +7 -0
  33. package/dist-esm/renderBlueprint.mjs +298 -0
  34. package/dist-esm/renderBlueprint.mjs.map +7 -0
  35. package/dist-esm/sequenceDiagram.mjs +666 -0
  36. package/dist-esm/sequenceDiagram.mjs.map +7 -0
  37. package/dist-esm/stateDiagram.mjs +359 -0
  38. package/dist-esm/stateDiagram.mjs.map +7 -0
  39. package/dist-esm/svgParsing.mjs +167 -0
  40. package/dist-esm/svgParsing.mjs.map +7 -0
  41. package/dist-esm/utils.mjs +55 -0
  42. package/dist-esm/utils.mjs.map +7 -0
  43. package/package.json +62 -0
  44. package/src/blueprint.ts +75 -0
  45. package/src/colors.ts +215 -0
  46. package/src/createMermaidDiagram.test.ts +31 -0
  47. package/src/createMermaidDiagram.ts +155 -0
  48. package/src/flowchartDiagram.ts +232 -0
  49. package/src/index.ts +18 -0
  50. package/src/mermaidDiagrams.test.ts +880 -0
  51. package/src/renderBlueprint.ts +373 -0
  52. package/src/sequenceDiagram.ts +851 -0
  53. package/src/stateDiagram.ts +477 -0
  54. package/src/svgParsing.ts +240 -0
  55. package/src/utils.ts +73 -0
@@ -0,0 +1,686 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var sequenceDiagram_exports = {};
20
+ __export(sequenceDiagram_exports, {
21
+ countSequenceEvents: () => countSequenceEvents,
22
+ parseSequenceLayout: () => parseSequenceLayout,
23
+ sequenceToBlueprint: () => sequenceToBlueprint
24
+ });
25
+ module.exports = __toCommonJS(sequenceDiagram_exports);
26
+ var import_colors = require("./colors");
27
+ var import_svgParsing = require("./svgParsing");
28
+ const LINETYPE = {
29
+ SOLID: 0,
30
+ DOTTED: 1,
31
+ NOTE: 2,
32
+ SOLID_CROSS: 3,
33
+ DOTTED_CROSS: 4,
34
+ SOLID_OPEN: 5,
35
+ DOTTED_OPEN: 6,
36
+ LOOP_START: 10,
37
+ LOOP_END: 11,
38
+ ALT_START: 12,
39
+ ALT_ELSE: 13,
40
+ ALT_END: 14,
41
+ OPT_START: 15,
42
+ OPT_END: 16,
43
+ ACTIVE_START: 17,
44
+ ACTIVE_END: 18,
45
+ PAR_START: 19,
46
+ PAR_AND: 20,
47
+ PAR_END: 21,
48
+ RECT_START: 22,
49
+ RECT_END: 23,
50
+ SOLID_POINT: 24,
51
+ DOTTED_POINT: 25,
52
+ AUTONUMBER: 26,
53
+ CRITICAL_START: 27,
54
+ CRITICAL_OPTION: 28,
55
+ CRITICAL_END: 29,
56
+ BREAK_START: 30,
57
+ BREAK_END: 31,
58
+ PAR_OVER_START: 32,
59
+ BIDIRECTIONAL_SOLID: 33,
60
+ BIDIRECTIONAL_DOTTED: 34
61
+ };
62
+ const PLACEMENT = {
63
+ LEFTOF: 0,
64
+ RIGHTOF: 1,
65
+ OVER: 2
66
+ };
67
+ const signalTypes = [
68
+ LINETYPE.SOLID,
69
+ LINETYPE.DOTTED,
70
+ LINETYPE.SOLID_CROSS,
71
+ LINETYPE.DOTTED_CROSS,
72
+ LINETYPE.SOLID_OPEN,
73
+ LINETYPE.DOTTED_OPEN,
74
+ LINETYPE.SOLID_POINT,
75
+ LINETYPE.DOTTED_POINT,
76
+ LINETYPE.BIDIRECTIONAL_SOLID,
77
+ LINETYPE.BIDIRECTIONAL_DOTTED
78
+ ];
79
+ function isSignalMessage(type) {
80
+ if (type === void 0) return false;
81
+ return signalTypes.includes(type);
82
+ }
83
+ function isNoteMessage(type) {
84
+ return type === LINETYPE.NOTE;
85
+ }
86
+ function isActiveStart(type) {
87
+ return type === LINETYPE.ACTIVE_START;
88
+ }
89
+ function isActiveEnd(type) {
90
+ return type === LINETYPE.ACTIVE_END;
91
+ }
92
+ function isAutonumber(type) {
93
+ return type === LINETYPE.AUTONUMBER;
94
+ }
95
+ function getFragmentStartKeyword(type) {
96
+ if (type === void 0) return null;
97
+ if (type === LINETYPE.LOOP_START) return "loop";
98
+ if (type === LINETYPE.ALT_START) return "alt";
99
+ if (type === LINETYPE.OPT_START) return "opt";
100
+ if (type === LINETYPE.PAR_START) return "par";
101
+ if (type === LINETYPE.RECT_START) return "rect";
102
+ if (type === LINETYPE.CRITICAL_START) return "critical";
103
+ if (type === LINETYPE.BREAK_START) return "break";
104
+ if (type === LINETYPE.PAR_OVER_START) return "par";
105
+ return null;
106
+ }
107
+ function isFragmentEnd(type) {
108
+ if (type === void 0) return false;
109
+ const endTypes = [
110
+ LINETYPE.LOOP_END,
111
+ LINETYPE.ALT_END,
112
+ LINETYPE.OPT_END,
113
+ LINETYPE.PAR_END,
114
+ LINETYPE.RECT_END,
115
+ LINETYPE.CRITICAL_END,
116
+ LINETYPE.BREAK_END
117
+ ];
118
+ return endTypes.includes(type);
119
+ }
120
+ function getFragmentSeparatorKeyword(type) {
121
+ if (type === LINETYPE.ALT_ELSE) return "else";
122
+ if (type === LINETYPE.PAR_AND) return "and";
123
+ if (type === LINETYPE.CRITICAL_OPTION) return "option";
124
+ return null;
125
+ }
126
+ function mapParticipantTypeToGeo(type) {
127
+ switch (type) {
128
+ case "actor":
129
+ return "ellipse";
130
+ case "database":
131
+ return "oval";
132
+ default:
133
+ return "rectangle";
134
+ }
135
+ }
136
+ function mapLineTypeToArrowProps(type) {
137
+ switch (type) {
138
+ case LINETYPE.SOLID:
139
+ return { dash: "solid", arrowheadEnd: "arrow" };
140
+ case LINETYPE.DOTTED:
141
+ return { dash: "dotted", arrowheadEnd: "arrow" };
142
+ case LINETYPE.SOLID_CROSS:
143
+ return { dash: "solid", arrowheadEnd: "bar" };
144
+ case LINETYPE.DOTTED_CROSS:
145
+ return { dash: "dotted", arrowheadEnd: "bar" };
146
+ case LINETYPE.SOLID_OPEN:
147
+ return { dash: "solid", arrowheadEnd: "none" };
148
+ case LINETYPE.DOTTED_OPEN:
149
+ return { dash: "dotted", arrowheadEnd: "none" };
150
+ case LINETYPE.SOLID_POINT:
151
+ return { dash: "solid", arrowheadEnd: "arrow" };
152
+ case LINETYPE.DOTTED_POINT:
153
+ return { dash: "dotted", arrowheadEnd: "arrow" };
154
+ case LINETYPE.BIDIRECTIONAL_SOLID:
155
+ return { dash: "solid", arrowheadEnd: "arrow" };
156
+ case LINETYPE.BIDIRECTIONAL_DOTTED:
157
+ return { dash: "dotted", arrowheadEnd: "arrow" };
158
+ default:
159
+ return { dash: "solid", arrowheadEnd: "arrow" };
160
+ }
161
+ }
162
+ function isBidirectional(type) {
163
+ return type === LINETYPE.BIDIRECTIONAL_SOLID || type === LINETYPE.BIDIRECTIONAL_DOTTED;
164
+ }
165
+ const TARGET_ACTOR_SPACING = 300;
166
+ const MIN_VERTICAL_GAP = 400;
167
+ const FALLBACK_ACTOR_WIDTH = 200;
168
+ const FALLBACK_ACTOR_HEIGHT = 70;
169
+ const FALLBACK_ACTOR_SPACING = 100;
170
+ const FALLBACK_EVENT_SPACING = 80;
171
+ const FALLBACK_NOTE_WIDTH = 120;
172
+ const FALLBACK_NOTE_HEIGHT = 50;
173
+ const NOTE_PADDING = 5;
174
+ const NOTE_CHAR_WIDTH = 11;
175
+ const NOTE_TEXT_PADDING = 40;
176
+ const FRAGMENT_PADDING_X = 30;
177
+ const FRAGMENT_PADDING_TOP = 50;
178
+ const FRAGMENT_PADDING_BOTTOM = 25;
179
+ const ACTOR_PADDING_WIDTH = 30;
180
+ const ACTOR_PADDING_HEIGHT = 10;
181
+ const SELF_MSG_Y_OFFSET = 0.04;
182
+ const SELF_MSG_BEND = -80;
183
+ const ACTIVATION_BOX_WIDTH = 20;
184
+ const ACTIVATION_NEST_OFFSET = 6;
185
+ const ACTIVATION_PAD_RATIO = 0.15;
186
+ const FRAGMENT_SECTION_LABEL_HEIGHT = 25;
187
+ const FRAGMENT_SECTION_LABEL_PADDING = 5;
188
+ function parseSvgRects(root, selector) {
189
+ const results = [];
190
+ for (const rect of root.querySelectorAll(selector)) {
191
+ const ancestor = (0, import_svgParsing.getAccumulatedTranslate)(rect);
192
+ const x = parseFloat(rect.getAttribute("x") || "0");
193
+ const y = parseFloat(rect.getAttribute("y") || "0");
194
+ const w = parseFloat(rect.getAttribute("width") || "0");
195
+ const h = parseFloat(rect.getAttribute("height") || "0");
196
+ if (w > 0 && h > 0) {
197
+ results.push({
198
+ x: Number.isFinite(ancestor.x + x) ? ancestor.x + x : 0,
199
+ y: Number.isFinite(ancestor.y + y) ? ancestor.y + y : 0,
200
+ w,
201
+ h
202
+ });
203
+ }
204
+ }
205
+ return results;
206
+ }
207
+ function parseActorManRects(root) {
208
+ const results = [];
209
+ for (const group of root.querySelectorAll("g.actor-man")) {
210
+ const ancestor = (0, import_svgParsing.getAccumulatedTranslate)(group);
211
+ let minX = Infinity;
212
+ let minY = Infinity;
213
+ let maxX = -Infinity;
214
+ let maxY = -Infinity;
215
+ for (const line of group.querySelectorAll("line")) {
216
+ for (const attr of ["x1", "x2"]) {
217
+ const coord = parseFloat(line.getAttribute(attr) || "0");
218
+ if (coord < minX) minX = coord;
219
+ if (coord > maxX) maxX = coord;
220
+ }
221
+ for (const attr of ["y1", "y2"]) {
222
+ const coord = parseFloat(line.getAttribute(attr) || "0");
223
+ if (coord < minY) minY = coord;
224
+ if (coord > maxY) maxY = coord;
225
+ }
226
+ }
227
+ if (Number.isFinite(minX) && Number.isFinite(minY)) {
228
+ results.push({
229
+ x: ancestor.x + minX,
230
+ y: ancestor.y + minY,
231
+ w: maxX - minX || FALLBACK_ACTOR_WIDTH,
232
+ h: maxY - minY || FALLBACK_ACTOR_HEIGHT
233
+ });
234
+ }
235
+ }
236
+ return results;
237
+ }
238
+ function computeActorLayouts(root, actorCount, eventCount) {
239
+ const byX = (a, b) => a.x - b.x;
240
+ let top = parseSvgRects(root, "rect.actor-top").sort(byX);
241
+ let bottom = parseSvgRects(root, "rect.actor-bottom").sort(byX);
242
+ const actorManRects = parseActorManRects(root).sort(byX);
243
+ if (actorManRects.length > 0 && (top.length < actorCount || bottom.length < actorCount)) {
244
+ const midY = top.length > 0 && bottom.length > 0 ? (Math.max(...top.map((r) => r.y + r.h)) + Math.min(...bottom.map((r) => r.y))) / 2 : actorManRects.length >= 2 ? (actorManRects[0].y + actorManRects[actorManRects.length - 1].y) / 2 : 0;
245
+ for (const rect of actorManRects) {
246
+ if (rect.y < midY) top.push(rect);
247
+ else bottom.push(rect);
248
+ }
249
+ top.sort(byX);
250
+ bottom.sort(byX);
251
+ }
252
+ if (top.length < actorCount || bottom.length < actorCount) {
253
+ const all = parseSvgRects(root, 'rect[class*="actor"]').sort((a, b) => a.y - b.y);
254
+ if (all.length >= 2 * actorCount) {
255
+ let maxGap = 0;
256
+ let splitAt = actorCount;
257
+ for (let i = 1; i < all.length; i++) {
258
+ const gap = all[i].y - all[i - 1].y;
259
+ if (gap > maxGap) {
260
+ maxGap = gap;
261
+ splitAt = i;
262
+ }
263
+ }
264
+ top = all.slice(0, splitAt).sort(byX).slice(0, actorCount);
265
+ bottom = all.slice(splitAt).sort(byX).slice(0, actorCount);
266
+ } else {
267
+ top = [];
268
+ bottom = [];
269
+ }
270
+ } else {
271
+ top = top.slice(0, actorCount);
272
+ bottom = bottom.slice(0, actorCount);
273
+ }
274
+ if (actorManRects.length > 0) {
275
+ const actorManSet = new Set(actorManRects);
276
+ const regularTops = top.filter((r) => !actorManSet.has(r));
277
+ const regularBottoms = bottom.filter((r) => !actorManSet.has(r));
278
+ const refHeight = regularTops.length > 0 ? Math.max(...regularTops.map((r) => r.h)) : FALLBACK_ACTOR_HEIGHT;
279
+ const refWidth = regularTops.length > 0 ? Math.max(...regularTops.map((r) => r.w)) : FALLBACK_ACTOR_WIDTH;
280
+ const refTopY = regularTops.length > 0 ? Math.min(...regularTops.map((r) => r.y)) : void 0;
281
+ const refBottomEndY = regularBottoms.length > 0 ? Math.max(...regularBottoms.map((r) => r.y + r.h)) : void 0;
282
+ for (const rect of top) {
283
+ if (!actorManSet.has(rect)) continue;
284
+ const centerY = rect.y + rect.h / 2;
285
+ rect.h = refHeight;
286
+ rect.w = Math.max(rect.w, refWidth);
287
+ rect.y = refTopY !== void 0 ? refTopY : centerY - refHeight / 2;
288
+ }
289
+ for (const rect of bottom) {
290
+ if (!actorManSet.has(rect)) continue;
291
+ const centerY = rect.y + rect.h / 2;
292
+ rect.h = refHeight;
293
+ rect.w = Math.max(rect.w, refWidth);
294
+ rect.y = refBottomEndY !== void 0 ? refBottomEndY - refHeight : centerY - refHeight / 2;
295
+ }
296
+ }
297
+ if (top.length >= actorCount && bottom.length >= actorCount) {
298
+ const svgCenters = top.map((r) => r.x + r.w / 2);
299
+ const spacings = [];
300
+ for (let i = 1; i < svgCenters.length; i++) {
301
+ spacings.push(svgCenters[i] - svgCenters[i - 1]);
302
+ }
303
+ const minSpacing = spacings.length > 0 ? Math.min(...spacings) : 1;
304
+ const scale = Math.max(1, TARGET_ACTOR_SPACING / minSpacing);
305
+ const xCenters = svgCenters.map((c) => (c - svgCenters[0]) * scale);
306
+ const totalSpan = xCenters.length > 1 ? xCenters[xCenters.length - 1] : 0;
307
+ const topRowBottom = Math.max(...top.map((r) => r.y + r.h));
308
+ const bottomRowTop = Math.min(...bottom.map((r) => r.y));
309
+ const yStretch = Math.max(0, MIN_VERTICAL_GAP - (bottomRowTop - topRowBottom));
310
+ const topMinY = Math.min(...top.map((r) => r.y));
311
+ const bottomMaxY = Math.max(...bottom.map((r) => r.y + r.h));
312
+ const originY = -(bottomMaxY + yStretch + topMinY) / 2;
313
+ return top.map((topRect, i) => {
314
+ const w = topRect.w + ACTOR_PADDING_WIDTH;
315
+ const h = topRect.h + ACTOR_PADDING_HEIGHT;
316
+ return {
317
+ x: xCenters[i] - totalSpan / 2 - w / 2,
318
+ y: originY + topRect.y,
319
+ w,
320
+ h,
321
+ bottomY: originY + bottom[i].y + yStretch
322
+ };
323
+ });
324
+ }
325
+ const fallbackLifelineHeight = Math.max(300, eventCount * FALLBACK_EVENT_SPACING);
326
+ const totalWidth = actorCount * FALLBACK_ACTOR_WIDTH + (actorCount - 1) * FALLBACK_ACTOR_SPACING;
327
+ const totalHeight = FALLBACK_ACTOR_HEIGHT * 2 + fallbackLifelineHeight;
328
+ const startX = -totalWidth / 2;
329
+ const startY = -totalHeight / 2;
330
+ return Array.from({ length: actorCount }, (_, i) => ({
331
+ x: startX + i * (FALLBACK_ACTOR_WIDTH + FALLBACK_ACTOR_SPACING),
332
+ y: startY,
333
+ w: FALLBACK_ACTOR_WIDTH,
334
+ h: FALLBACK_ACTOR_HEIGHT,
335
+ bottomY: startY + totalHeight - FALLBACK_ACTOR_HEIGHT
336
+ }));
337
+ }
338
+ function getMessageLabel(msg) {
339
+ return typeof msg.message === "string" ? msg.message : void 0;
340
+ }
341
+ function countSequenceEvents(messages) {
342
+ let count = 0;
343
+ for (const msg of messages) {
344
+ if (isAutonumber(msg.type)) continue;
345
+ if (getFragmentStartKeyword(msg.type)) continue;
346
+ if (isFragmentEnd(msg.type)) continue;
347
+ if (getFragmentSeparatorKeyword(msg.type)) continue;
348
+ if (isActiveStart(msg.type) || isActiveEnd(msg.type)) continue;
349
+ const isEvent = isSignalMessage(msg.type) && msg.from && msg.to || isNoteMessage(msg.type) && msg.from;
350
+ if (isEvent) count++;
351
+ }
352
+ return count;
353
+ }
354
+ function parseSequenceLayout(root, actorCount, eventCount) {
355
+ return {
356
+ actorLayouts: computeActorLayouts(root, actorCount, eventCount),
357
+ noteRects: parseSvgRects(root, "rect.note")
358
+ };
359
+ }
360
+ function sequenceToBlueprint(layout, actors, actorKeys, messages, createdActors = /* @__PURE__ */ new Map(), destroyedActors = /* @__PURE__ */ new Map()) {
361
+ const actorCount = actorKeys.length;
362
+ const keyIndex = new Map(actorKeys.map((key, i) => [key, i]));
363
+ const fragments = [];
364
+ const fragmentStack = [];
365
+ const events = [];
366
+ const activationStack = /* @__PURE__ */ new Map();
367
+ const activationSpans = [];
368
+ let autonumberStart = 0;
369
+ let autonumberStep = 0;
370
+ let autonumberVisible = false;
371
+ for (const msg of messages) {
372
+ if (isAutonumber(msg.type)) {
373
+ autonumberStart = 1;
374
+ autonumberStep = 1;
375
+ autonumberVisible = true;
376
+ continue;
377
+ }
378
+ const keyword = getFragmentStartKeyword(msg.type);
379
+ if (keyword) {
380
+ fragmentStack.push({
381
+ keyword,
382
+ sections: [{ title: getMessageLabel(msg) ?? "", firstEventIndex: events.length }],
383
+ firstEventIndex: events.length,
384
+ actorKeys: /* @__PURE__ */ new Set()
385
+ });
386
+ continue;
387
+ }
388
+ if (isFragmentEnd(msg.type)) {
389
+ const frag = fragmentStack.pop();
390
+ if (frag) fragments.push({ ...frag, lastEventIndex: events.length - 1 });
391
+ continue;
392
+ }
393
+ if (getFragmentSeparatorKeyword(msg.type)) {
394
+ const current = fragmentStack[fragmentStack.length - 1];
395
+ if (current) {
396
+ current.sections.push({
397
+ title: getMessageLabel(msg) ?? "",
398
+ firstEventIndex: events.length
399
+ });
400
+ }
401
+ continue;
402
+ }
403
+ if (isActiveStart(msg.type)) {
404
+ const key = msg.from ?? msg.to;
405
+ if (key) {
406
+ if (!activationStack.has(key)) activationStack.set(key, []);
407
+ activationStack.get(key).push(Math.max(0, events.length - 1));
408
+ }
409
+ continue;
410
+ }
411
+ if (isActiveEnd(msg.type)) {
412
+ const key = msg.from ?? msg.to;
413
+ if (key) {
414
+ const startIdx = activationStack.get(key)?.pop();
415
+ if (startIdx !== void 0) {
416
+ activationSpans.push({
417
+ participantKey: key,
418
+ startEventIndex: startIdx,
419
+ endEventIndex: Math.max(events.length - 1, startIdx)
420
+ });
421
+ }
422
+ }
423
+ continue;
424
+ }
425
+ const isEvent = isSignalMessage(msg.type) && msg.from && msg.to || isNoteMessage(msg.type) && msg.from;
426
+ if (!isEvent) continue;
427
+ for (const frag of fragmentStack) {
428
+ if (msg.from) frag.actorKeys.add(msg.from);
429
+ if (msg.to) frag.actorKeys.add(msg.to);
430
+ }
431
+ events.push(msg);
432
+ }
433
+ const layouts = layout.actorLayouts;
434
+ const creationEventIndex = /* @__PURE__ */ new Map();
435
+ const destructionEventIndex = /* @__PURE__ */ new Map();
436
+ for (let i = 0; i < events.length; i++) {
437
+ const ev = events[i];
438
+ if (!isSignalMessage(ev.type)) continue;
439
+ if (ev.to && createdActors.has(ev.to) && !creationEventIndex.has(ev.to)) {
440
+ creationEventIndex.set(ev.to, i);
441
+ }
442
+ if (ev.from && destroyedActors.has(ev.from) && !destructionEventIndex.has(ev.from)) {
443
+ destructionEventIndex.set(ev.from, i);
444
+ }
445
+ }
446
+ const svgNoteRects = layout.noteRects;
447
+ let svgNoteIndex = 0;
448
+ const nodes = [];
449
+ const lines = [];
450
+ const edges = [];
451
+ const { y: firstY, h: firstH, bottomY: firstBottomY } = layouts[0];
452
+ const lifelineTop = firstY + firstH;
453
+ const eventStep = (firstBottomY - lifelineTop) / (events.length + 1);
454
+ for (let i = 0; i < actorCount; i++) {
455
+ const key = actorKeys[i];
456
+ const { x, y, w, h, bottomY } = layouts[i];
457
+ const isCreated = creationEventIndex.has(key);
458
+ const isDestroyed = destructionEventIndex.has(key);
459
+ const eventY = isCreated ? lifelineTop + eventStep * (creationEventIndex.get(key) + 1) : 0;
460
+ const topY = isCreated ? eventY + h / 2 : y + h;
461
+ const botY = isDestroyed ? lifelineTop + eventStep * (destructionEventIndex.get(key) + 1) : bottomY;
462
+ const lifelineHeight = botY - topY;
463
+ if (lifelineHeight > 0) {
464
+ lines.push({ id: `lifeline-${key}`, x: x + w / 2, y: topY, endY: lifelineHeight });
465
+ }
466
+ }
467
+ const activationPad = eventStep * ACTIVATION_PAD_RATIO;
468
+ const sortedSpans = activationSpans.map((span, origIdx) => ({ ...span, origIdx })).sort((a, b) => {
469
+ const sizeA = a.endEventIndex - a.startEventIndex;
470
+ const sizeB = b.endEventIndex - b.startEventIndex;
471
+ return sizeB - sizeA || a.origIdx - b.origIdx;
472
+ });
473
+ for (let i = 0; i < sortedSpans.length; i++) {
474
+ const span = sortedSpans[i];
475
+ const actorIdx = keyIndex.get(span.participantKey);
476
+ if (actorIdx === void 0) continue;
477
+ const spanSize = span.endEventIndex - span.startEventIndex;
478
+ let depth = 0;
479
+ for (const other of sortedSpans) {
480
+ if (other === span) continue;
481
+ const sameParticipant = other.participantKey === span.participantKey;
482
+ const containsSpan = other.startEventIndex <= span.startEventIndex && other.endEventIndex >= span.endEventIndex;
483
+ const strictlyLarger = other.endEventIndex - other.startEventIndex > spanSize;
484
+ if (sameParticipant && containsSpan && strictlyLarger) depth++;
485
+ }
486
+ const layout2 = layouts[actorIdx];
487
+ const lifelineCenterX = layout2.x + layout2.w / 2;
488
+ const boxTop = lifelineTop + eventStep * (span.startEventIndex + 1) - activationPad;
489
+ const boxBottom = lifelineTop + eventStep * (span.endEventIndex + 1) + activationPad;
490
+ nodes.push({
491
+ id: `activation-${span.origIdx}`,
492
+ x: lifelineCenterX - ACTIVATION_BOX_WIDTH / 2 + depth * ACTIVATION_NEST_OFFSET,
493
+ y: boxTop,
494
+ w: ACTIVATION_BOX_WIDTH,
495
+ h: boxBottom - boxTop,
496
+ geo: "rectangle",
497
+ fill: "solid",
498
+ color: "light-violet",
499
+ size: "s"
500
+ });
501
+ }
502
+ for (let fragmentIndex = 0; fragmentIndex < fragments.length; fragmentIndex++) {
503
+ const fragment = fragments[fragmentIndex];
504
+ if (fragment.lastEventIndex < fragment.firstEventIndex) continue;
505
+ const fragTop = lifelineTop + eventStep * (fragment.firstEventIndex + 1) - FRAGMENT_PADDING_TOP;
506
+ const fragBottom = lifelineTop + eventStep * (fragment.lastEventIndex + 1) + FRAGMENT_PADDING_BOTTOM;
507
+ const indices = [...fragment.actorKeys].map((k) => keyIndex.get(k)).filter((idx) => idx >= 0);
508
+ if (indices.length === 0) continue;
509
+ const minIndex = Math.min(...indices);
510
+ const maxIndex = Math.max(...indices);
511
+ const leftX = layouts[minIndex].x - FRAGMENT_PADDING_X;
512
+ const fragW = layouts[maxIndex].x + layouts[maxIndex].w + FRAGMENT_PADDING_X - leftX;
513
+ const fragH = fragBottom - fragTop;
514
+ const rgbColor = fragment.keyword === "rect" ? (0, import_colors.parseRgbToTldrawColor)(fragment.sections[0].title) : null;
515
+ if (rgbColor) {
516
+ nodes.push({
517
+ id: `fragment-${fragmentIndex}`,
518
+ x: leftX,
519
+ y: fragTop,
520
+ w: fragW,
521
+ h: fragH,
522
+ geo: "rectangle",
523
+ fill: rgbColor.hasAlpha ? "semi" : "solid",
524
+ color: rgbColor.color,
525
+ size: "s"
526
+ });
527
+ } else {
528
+ nodes.push({
529
+ id: `fragment-${fragmentIndex}`,
530
+ x: leftX,
531
+ y: fragTop,
532
+ w: fragW,
533
+ h: fragH,
534
+ geo: "rectangle",
535
+ dash: "dashed",
536
+ fill: "none",
537
+ color: "light-blue",
538
+ size: "s",
539
+ align: "start",
540
+ verticalAlign: "start",
541
+ label: `${fragment.keyword} [${fragment.sections[0].title}]`
542
+ });
543
+ for (let s = 1; s < fragment.sections.length; s++) {
544
+ const section = fragment.sections[s];
545
+ const sepY = lifelineTop + eventStep * (section.firstEventIndex + 0.5);
546
+ lines.push({
547
+ id: `fragment-${fragmentIndex}-sep-${s}`,
548
+ x: leftX,
549
+ y: sepY,
550
+ endX: fragW,
551
+ endY: 0,
552
+ dash: "dashed",
553
+ color: "light-blue",
554
+ size: "s"
555
+ });
556
+ nodes.push({
557
+ id: `fragment-${fragmentIndex}-section-${s}`,
558
+ x: leftX + FRAGMENT_SECTION_LABEL_PADDING,
559
+ y: sepY + FRAGMENT_SECTION_LABEL_PADDING,
560
+ w: fragW - FRAGMENT_SECTION_LABEL_PADDING * 2,
561
+ h: FRAGMENT_SECTION_LABEL_HEIGHT,
562
+ geo: "rectangle",
563
+ fill: "none",
564
+ dash: "dashed",
565
+ color: "light-blue",
566
+ size: "s",
567
+ align: "start",
568
+ verticalAlign: "start",
569
+ label: `[${section.title}]`
570
+ });
571
+ }
572
+ }
573
+ }
574
+ for (let i = 0; i < actorCount; i++) {
575
+ const key = actorKeys[i];
576
+ const actor = actors.get(key);
577
+ if (!actor) continue;
578
+ const { x, y, w, h, bottomY } = layouts[i];
579
+ const isCreated = creationEventIndex.has(key);
580
+ const isDestroyed = destructionEventIndex.has(key);
581
+ const shared = {
582
+ geo: mapParticipantTypeToGeo(actor.type),
583
+ label: actor.description || actor.name || key,
584
+ align: "middle",
585
+ verticalAlign: "middle",
586
+ size: "s"
587
+ };
588
+ const creationY = isCreated ? lifelineTop + eventStep * (creationEventIndex.get(key) + 1) : 0;
589
+ const topY = isCreated ? creationY - h / 2 : y;
590
+ nodes.push({ id: `actor-top-${key}`, x, y: topY, w, h, ...shared });
591
+ if (!isDestroyed) {
592
+ nodes.push({ id: `actor-bottom-${key}`, x, y: bottomY, w, h, ...shared });
593
+ }
594
+ }
595
+ const pendingCreations = new Set(createdActors.keys());
596
+ let sequenceNumber = autonumberStart;
597
+ for (let eventIndex = 0; eventIndex < events.length; eventIndex++) {
598
+ const msg = events[eventIndex];
599
+ const anchor = (eventIndex + 1) / (events.length + 1);
600
+ if (isSignalMessage(msg.type)) {
601
+ const fromKey = msg.from;
602
+ const toKey = msg.to;
603
+ if (!keyIndex.has(fromKey) || !keyIndex.has(toKey)) continue;
604
+ const isCreationMessage = pendingCreations.has(toKey);
605
+ if (isCreationMessage) pendingCreations.delete(toKey);
606
+ const msgType = msg.type ?? LINETYPE.SOLID;
607
+ const { dash, arrowheadEnd } = mapLineTypeToArrowProps(msgType);
608
+ const isSelf = fromKey === toKey;
609
+ const bidir = !isSelf && isBidirectional(msgType);
610
+ const edge = {
611
+ startNodeId: `lifeline-${fromKey}`,
612
+ endNodeId: isCreationMessage ? `actor-top-${toKey}` : `lifeline-${toKey}`,
613
+ label: getMessageLabel(msg),
614
+ bend: isSelf ? SELF_MSG_BEND : 0,
615
+ dash,
616
+ arrowheadEnd,
617
+ arrowheadStart: bidir ? "arrow" : "none",
618
+ size: "s",
619
+ anchorStartY: isSelf ? anchor - SELF_MSG_Y_OFFSET : anchor,
620
+ anchorEndY: isCreationMessage ? 0.5 : isSelf ? anchor + SELF_MSG_Y_OFFSET : anchor,
621
+ isExact: true,
622
+ isPrecise: true,
623
+ ...isCreationMessage && { isExactEnd: false, isPreciseEnd: false }
624
+ };
625
+ if (autonumberVisible) {
626
+ edge.decoration = { type: "autonumber", value: String(sequenceNumber) };
627
+ sequenceNumber += autonumberStep;
628
+ }
629
+ edges.push(edge);
630
+ } else if (isNoteMessage(msg.type)) {
631
+ const eventY = lifelineTop + eventStep * (eventIndex + 1);
632
+ const fromKey = msg.from;
633
+ const fromIdx = keyIndex.get(fromKey);
634
+ const toIdx = keyIndex.get(msg.to ?? fromKey);
635
+ if (fromIdx === void 0) continue;
636
+ const label = getMessageLabel(msg);
637
+ const msgPlacement = msg.placement;
638
+ const fromCenterX = layouts[fromIdx].x + layouts[fromIdx].w / 2;
639
+ const toCenterX = toIdx !== void 0 ? layouts[toIdx].x + layouts[toIdx].w / 2 : fromCenterX;
640
+ const isSpanning = msgPlacement === PLACEMENT.OVER && msg.from !== msg.to && toIdx !== void 0;
641
+ const svgNote = svgNoteRects[svgNoteIndex++];
642
+ const noteHeight = svgNote?.h ?? FALLBACK_NOTE_HEIGHT;
643
+ const textWidth = label ? label.length * NOTE_CHAR_WIDTH + NOTE_TEXT_PADDING : 0;
644
+ const baseWidth = Math.max(svgNote?.w ?? FALLBACK_NOTE_WIDTH, textWidth);
645
+ const noteWidth = isSpanning ? Math.max(baseWidth, Math.abs(toCenterX - fromCenterX) + NOTE_PADDING) : baseWidth;
646
+ let noteX;
647
+ if (msgPlacement === PLACEMENT.LEFTOF) {
648
+ noteX = fromCenterX - noteWidth - NOTE_PADDING;
649
+ } else if (msgPlacement === PLACEMENT.RIGHTOF) {
650
+ noteX = fromCenterX + NOTE_PADDING;
651
+ } else if (isSpanning) {
652
+ noteX = (fromCenterX + toCenterX) / 2 - noteWidth / 2;
653
+ } else {
654
+ noteX = fromCenterX - noteWidth / 2;
655
+ }
656
+ nodes.push({
657
+ id: `note-${eventIndex}`,
658
+ x: noteX,
659
+ y: eventY - noteHeight / 2,
660
+ w: noteWidth,
661
+ h: noteHeight,
662
+ geo: "rectangle",
663
+ fill: "solid",
664
+ color: "yellow",
665
+ dash: "draw",
666
+ size: "s",
667
+ align: "middle",
668
+ verticalAlign: "middle",
669
+ label
670
+ });
671
+ }
672
+ }
673
+ return {
674
+ nodes,
675
+ edges,
676
+ lines,
677
+ groups: actorKeys.map((key) => {
678
+ const group = [`actor-top-${key}`, `lifeline-${key}`];
679
+ if (!destructionEventIndex.has(key)) {
680
+ group.push(`actor-bottom-${key}`);
681
+ }
682
+ return group;
683
+ })
684
+ };
685
+ }
686
+ //# sourceMappingURL=sequenceDiagram.js.map