@aranzatech/diagrams-bpmn 0.3.4 → 0.3.6
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.
- package/dist/{catalog-DNIyjHbl.d.ts → catalog-CYZHikuU.d.ts} +1 -1
- package/dist/{catalog-DG-sz0VM.d.cts → catalog-C_S9hyyn.d.cts} +1 -1
- package/dist/{chunk-CPFUQM6H.js → chunk-EMTO53AN.js} +54 -73
- package/dist/chunk-EMTO53AN.js.map +1 -0
- package/dist/chunk-G22XQD6H.js +64 -0
- package/dist/chunk-G22XQD6H.js.map +1 -0
- package/dist/{chunk-NYIYQUGX.js → chunk-OFOTX3LA.js} +124 -20
- package/dist/chunk-OFOTX3LA.js.map +1 -0
- package/dist/{chunk-YAYZW45I.js → chunk-SRUWPELT.js} +80 -3
- package/dist/chunk-SRUWPELT.js.map +1 -0
- package/dist/edges/index.cjs +75 -35
- package/dist/edges/index.cjs.map +1 -1
- package/dist/edges/index.js +2 -1
- package/dist/elements/index.d.cts +3 -3
- package/dist/elements/index.d.ts +3 -3
- package/dist/extensions/index.d.cts +2 -2
- package/dist/extensions/index.d.ts +2 -2
- package/dist/index.cjs +196 -53
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/layout/index.cjs +1280 -889
- package/dist/layout/index.cjs.map +1 -1
- package/dist/layout/index.d.cts +4 -4
- package/dist/layout/index.d.ts +4 -4
- package/dist/layout/index.js +694 -106
- package/dist/layout/index.js.map +1 -1
- package/dist/modeling/index.cjs +78 -0
- package/dist/modeling/index.cjs.map +1 -1
- package/dist/modeling/index.d.cts +10 -5
- package/dist/modeling/index.d.ts +10 -5
- package/dist/modeling/index.js +1 -1
- package/dist/{types-nvF59RGF.d.cts → types--x9aoecw.d.cts} +5 -0
- package/dist/{types-nvF59RGF.d.ts → types--x9aoecw.d.ts} +5 -0
- package/dist/{types-dQUuSnV5.d.cts → types-CrFDTGo9.d.cts} +1 -1
- package/dist/{types-CuDL2YGL.d.ts → types-DoPv3m7u.d.ts} +2 -2
- package/dist/{types-X5FyP8oS.d.ts → types-DteJykQG.d.ts} +1 -1
- package/dist/{types-CDp9kWQ4.d.cts → types-YZ4sj3Ih.d.cts} +2 -2
- package/dist/validation/index.d.cts +3 -3
- package/dist/validation/index.d.ts +3 -3
- package/dist/xml/index.cjs +162 -18
- package/dist/xml/index.cjs.map +1 -1
- package/dist/xml/index.d.cts +4 -4
- package/dist/xml/index.d.ts +4 -4
- package/dist/xml/index.js +2 -1
- package/package.json +1 -1
- package/dist/chunk-CPFUQM6H.js.map +0 -1
- package/dist/chunk-FFWJA5BV.js +0 -163
- package/dist/chunk-FFWJA5BV.js.map +0 -1
- package/dist/chunk-NYIYQUGX.js.map +0 -1
- package/dist/chunk-YAYZW45I.js.map +0 -1
- package/dist/elk-QT7H4252.js +0 -6
- package/dist/elk-QT7H4252.js.map +0 -1
package/dist/layout/index.js
CHANGED
|
@@ -1,10 +1,166 @@
|
|
|
1
|
-
|
|
2
|
-
import { getBpmnNodeSize } from '../chunk-YAYZW45I.js';
|
|
1
|
+
import { getBpmnNodeSize } from '../chunk-SRUWPELT.js';
|
|
3
2
|
import '../chunk-RLAJNRF2.js';
|
|
4
3
|
import '../chunk-L5Z22RLX.js';
|
|
5
|
-
import { dagreLayout, applyLayoutResultToDiagram } from '@aranzatech/diagrams-core/layout';
|
|
4
|
+
import { elkLayout, dagreLayout, applyLayoutResultToDiagram } from '@aranzatech/diagrams-core/layout';
|
|
6
5
|
export { applyLayoutResultToDiagram } from '@aranzatech/diagrams-core/layout';
|
|
7
6
|
|
|
7
|
+
var BPMN_CONTAINER_TYPES = /* @__PURE__ */ new Set([
|
|
8
|
+
"Pool",
|
|
9
|
+
"Lane",
|
|
10
|
+
"SubProcess",
|
|
11
|
+
"Transaction",
|
|
12
|
+
"EventSubProcess",
|
|
13
|
+
"AdHocSubProcess"
|
|
14
|
+
]);
|
|
15
|
+
var CONTAINER_MIN_SIZE = {
|
|
16
|
+
Pool: { w: 720, h: 200 },
|
|
17
|
+
Lane: { w: 600, h: 160 },
|
|
18
|
+
SubProcess: { w: 240, h: 140 },
|
|
19
|
+
Transaction: { w: 240, h: 140 },
|
|
20
|
+
EventSubProcess: { w: 240, h: 140 },
|
|
21
|
+
AdHocSubProcess: { w: 240, h: 140 }
|
|
22
|
+
};
|
|
23
|
+
var CONTAINER_PADDING = {
|
|
24
|
+
Pool: "[top=30,left=60,bottom=30,right=50]",
|
|
25
|
+
Lane: "[top=40,left=70,bottom=40,right=50]",
|
|
26
|
+
SubProcess: "[top=30,left=40,bottom=30,right=40]",
|
|
27
|
+
Transaction: "[top=30,left=40,bottom=30,right=40]",
|
|
28
|
+
EventSubProcess: "[top=30,left=40,bottom=30,right=40]",
|
|
29
|
+
AdHocSubProcess: "[top=30,left=40,bottom=30,right=40]"
|
|
30
|
+
};
|
|
31
|
+
async function bpmnElkLayout(nodes, edges) {
|
|
32
|
+
const poolsWithLanes = /* @__PURE__ */ new Set();
|
|
33
|
+
for (const node of nodes) {
|
|
34
|
+
if (node.data.elementType === "Lane" && node.parentId) {
|
|
35
|
+
poolsWithLanes.add(node.parentId);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const result = await elkLayout(
|
|
39
|
+
nodes,
|
|
40
|
+
edges,
|
|
41
|
+
{
|
|
42
|
+
direction: "LR",
|
|
43
|
+
getNodeSize: (node) => {
|
|
44
|
+
const bNode = node;
|
|
45
|
+
if (BPMN_CONTAINER_TYPES.has(bNode.data.elementType)) return void 0;
|
|
46
|
+
return getBpmnNodeSize(bNode);
|
|
47
|
+
},
|
|
48
|
+
isContainerNode: (node) => BPMN_CONTAINER_TYPES.has(node.data.elementType),
|
|
49
|
+
getNodeLayoutOptions: (node) => {
|
|
50
|
+
const bNode = node;
|
|
51
|
+
const type = bNode.data.elementType;
|
|
52
|
+
if (!BPMN_CONTAINER_TYPES.has(type)) return void 0;
|
|
53
|
+
const min = CONTAINER_MIN_SIZE[type];
|
|
54
|
+
const isPoolWithLanes = type === "Pool" && poolsWithLanes.has(node.id);
|
|
55
|
+
const dir = isPoolWithLanes ? "DOWN" : "RIGHT";
|
|
56
|
+
return {
|
|
57
|
+
"elk.direction": dir,
|
|
58
|
+
"elk.nodeSize.constraints": "MINIMUM_SIZE",
|
|
59
|
+
// Each container handles its own layout pass so cross-lane edges
|
|
60
|
+
// participate in the internal layout without the global direction
|
|
61
|
+
// forcing Lane containers to align sideways.
|
|
62
|
+
"elk.hierarchyHandling": "INCLUDE_CHILDREN",
|
|
63
|
+
// Lanes within a Pool share a border — zero gap between them.
|
|
64
|
+
// Other containers keep the tighter inner spacing.
|
|
65
|
+
...isPoolWithLanes ? { "elk.spacing.nodeNode": "0", "elk.spacing.componentComponent": "0" } : {
|
|
66
|
+
"elk.layered.spacing.nodeNodeBetweenLayers": "100",
|
|
67
|
+
"elk.layered.spacing.edgeNodeBetweenLayers": "45",
|
|
68
|
+
"elk.spacing.nodeNode": "50"
|
|
69
|
+
},
|
|
70
|
+
...min ? { "elk.nodeSize.minimum": `[w=${min.w},h=${min.h}]` } : {},
|
|
71
|
+
...CONTAINER_PADDING[type] ? { "elk.padding": CONTAINER_PADDING[type] } : {}
|
|
72
|
+
};
|
|
73
|
+
},
|
|
74
|
+
elk: {
|
|
75
|
+
"elk.algorithm": "layered",
|
|
76
|
+
"elk.direction": "RIGHT",
|
|
77
|
+
// INHERIT: each container handles its own INCLUDE_CHILDREN pass so
|
|
78
|
+
// the global RIGHT direction does not force Lane containers sideways.
|
|
79
|
+
"elk.hierarchyHandling": "INHERIT",
|
|
80
|
+
"elk.edgeRouting": "ORTHOGONAL",
|
|
81
|
+
// Global spacing — generous values for visual breathing room.
|
|
82
|
+
"elk.layered.spacing.nodeNodeBetweenLayers": "120",
|
|
83
|
+
"elk.layered.spacing.edgeNodeBetweenLayers": "50",
|
|
84
|
+
"elk.spacing.nodeNode": "70",
|
|
85
|
+
"elk.spacing.componentComponent": "100"
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
);
|
|
89
|
+
const nodeMap = new Map(result.nodes.map((n) => [n.id, n]));
|
|
90
|
+
const edgeMap = new Map(result.edges.map((e) => [e.id, e]));
|
|
91
|
+
const COMPONENT_GAP = 100;
|
|
92
|
+
const rootNodeOrder = nodes.filter((n) => !n.parentId).map((n) => n.id);
|
|
93
|
+
const rootHeights = /* @__PURE__ */ new Map();
|
|
94
|
+
for (const id of rootNodeOrder) {
|
|
95
|
+
const laid = nodeMap.get(id);
|
|
96
|
+
const orig = nodes.find((n) => n.id === id);
|
|
97
|
+
rootHeights.set(id, laid?.height ?? orig?.height ?? 200);
|
|
98
|
+
}
|
|
99
|
+
let stackY = 0;
|
|
100
|
+
const rootY = /* @__PURE__ */ new Map();
|
|
101
|
+
for (const id of rootNodeOrder) {
|
|
102
|
+
rootY.set(id, stackY);
|
|
103
|
+
stackY += (rootHeights.get(id) ?? 200) + COMPONENT_GAP;
|
|
104
|
+
}
|
|
105
|
+
const updatedNodes = nodes.map((node) => {
|
|
106
|
+
const laid = nodeMap.get(node.id);
|
|
107
|
+
if (!laid) return node;
|
|
108
|
+
const pos = node.parentId ? laid.position : { x: laid.position.x, y: rootY.get(node.id) ?? laid.position.y };
|
|
109
|
+
return { ...node, position: pos, width: laid.width, height: laid.height };
|
|
110
|
+
});
|
|
111
|
+
const lanesByPool = /* @__PURE__ */ new Map();
|
|
112
|
+
for (const node of updatedNodes) {
|
|
113
|
+
if (node.data.elementType === "Lane" && node.parentId) {
|
|
114
|
+
const arr = lanesByPool.get(node.parentId) ?? [];
|
|
115
|
+
arr.push(node.id);
|
|
116
|
+
lanesByPool.set(node.parentId, arr);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
const nodeIndex = new Map(updatedNodes.map((n, i) => [n.id, i]));
|
|
120
|
+
for (const laneIds of lanesByPool.values()) {
|
|
121
|
+
const widths = laneIds.map((id) => updatedNodes[nodeIndex.get(id)]?.width ?? 0);
|
|
122
|
+
const maxWidth = Math.max(...widths);
|
|
123
|
+
if (maxWidth <= 0) continue;
|
|
124
|
+
for (const id of laneIds) {
|
|
125
|
+
const idx = nodeIndex.get(id);
|
|
126
|
+
if (idx !== void 0) {
|
|
127
|
+
updatedNodes[idx] = { ...updatedNodes[idx], width: maxWidth };
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
const nodeRootContainer = /* @__PURE__ */ new Map();
|
|
132
|
+
for (const node of updatedNodes) {
|
|
133
|
+
nodeRootContainer.set(node.id, node.parentId ?? null);
|
|
134
|
+
}
|
|
135
|
+
const getRootContainer = (nodeId) => {
|
|
136
|
+
let current = nodeId;
|
|
137
|
+
const visited = /* @__PURE__ */ new Set();
|
|
138
|
+
while (current) {
|
|
139
|
+
if (visited.has(current)) break;
|
|
140
|
+
visited.add(current);
|
|
141
|
+
const parent = nodeRootContainer.get(current);
|
|
142
|
+
if (!parent) return current;
|
|
143
|
+
current = parent;
|
|
144
|
+
}
|
|
145
|
+
return null;
|
|
146
|
+
};
|
|
147
|
+
const updatedEdges = edges.map((edge) => {
|
|
148
|
+
const laid = edgeMap.get(edge.id);
|
|
149
|
+
if (!laid) return edge;
|
|
150
|
+
const nextData = { ...edge.data };
|
|
151
|
+
const sourceRoot = getRootContainer(edge.source);
|
|
152
|
+
const targetRoot = getRootContainer(edge.target);
|
|
153
|
+
const isCrossPool = sourceRoot !== targetRoot;
|
|
154
|
+
if (!isCrossPool && laid.points && laid.points.length > 0) {
|
|
155
|
+
nextData.routingPoints = laid.points;
|
|
156
|
+
} else {
|
|
157
|
+
delete nextData.routingPoints;
|
|
158
|
+
}
|
|
159
|
+
return { ...edge, data: nextData };
|
|
160
|
+
});
|
|
161
|
+
return { nodes: updatedNodes, edges: updatedEdges };
|
|
162
|
+
}
|
|
163
|
+
|
|
8
164
|
// src/layout/bpmn-layout-graph.ts
|
|
9
165
|
var LAYOUT_CONTAINER_TYPES = /* @__PURE__ */ new Set([
|
|
10
166
|
"Pool",
|
|
@@ -22,15 +178,21 @@ var LAYOUT_GATEWAY_TYPES = /* @__PURE__ */ new Set([
|
|
|
22
178
|
"ComplexGateway"
|
|
23
179
|
]);
|
|
24
180
|
function detectBackEdges(nodeIds, seqEdges) {
|
|
181
|
+
const sortedIds = [...nodeIds].sort();
|
|
25
182
|
const backEdgeIds = /* @__PURE__ */ new Set();
|
|
26
183
|
const state = /* @__PURE__ */ new Map();
|
|
27
|
-
for (const id of
|
|
184
|
+
for (const id of sortedIds) state.set(id, 0);
|
|
28
185
|
const adj = /* @__PURE__ */ new Map();
|
|
29
|
-
for (const id of
|
|
186
|
+
for (const id of sortedIds) adj.set(id, []);
|
|
30
187
|
for (const e of seqEdges) {
|
|
31
188
|
adj.get(e.source)?.push({ target: e.target, edgeId: e.id });
|
|
32
189
|
}
|
|
33
|
-
for (const
|
|
190
|
+
for (const list of adj.values()) {
|
|
191
|
+
list.sort(
|
|
192
|
+
(a, b) => a.target < b.target ? -1 : a.target > b.target ? 1 : a.edgeId < b.edgeId ? -1 : a.edgeId > b.edgeId ? 1 : 0
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
for (const startId of sortedIds) {
|
|
34
196
|
if (state.get(startId) !== 0) continue;
|
|
35
197
|
const stack = [{ id: startId, idx: 0 }];
|
|
36
198
|
state.set(startId, 1);
|
|
@@ -107,9 +269,7 @@ function detectGatewayPairs(nodes, forwardEdges) {
|
|
|
107
269
|
}
|
|
108
270
|
const order = topologicalSort(nodeIds, forwardEdges);
|
|
109
271
|
const topoPos = new Map(order.map((id, i) => [id, i]));
|
|
110
|
-
const splits = nodes.filter(
|
|
111
|
-
(n) => LAYOUT_GATEWAY_TYPES.has(n.data.elementType) && (succs.get(n.id)?.length ?? 0) > 1
|
|
112
|
-
);
|
|
272
|
+
const splits = nodes.filter((n) => (succs.get(n.id)?.length ?? 0) > 1);
|
|
113
273
|
for (const split of splits) {
|
|
114
274
|
const branches = succs.get(split.id) ?? [];
|
|
115
275
|
if (branches.length < 2) continue;
|
|
@@ -161,12 +321,18 @@ function buildHandleMap(edges) {
|
|
|
161
321
|
}
|
|
162
322
|
return map;
|
|
163
323
|
}
|
|
324
|
+
function branchPullBias(nodeIds, nodeBias) {
|
|
325
|
+
if (!nodeBias) return null;
|
|
326
|
+
let sum = 0;
|
|
327
|
+
for (const id of nodeIds) sum += nodeBias.get(id) ?? 0;
|
|
328
|
+
if (sum === 0) return null;
|
|
329
|
+
return sum > 0 ? 1 : -1;
|
|
330
|
+
}
|
|
164
331
|
function pickMainBranch(branchData) {
|
|
165
332
|
if (branchData.length === 0) return void 0;
|
|
166
333
|
return [...branchData].sort((a, b) => {
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
if (aRight !== bRight) return bRight - aRight;
|
|
334
|
+
const rank = (branch) => branch.bias === 0 ? 2 : branch.bias === null ? 1 : 0;
|
|
335
|
+
if (rank(a) !== rank(b)) return rank(b) - rank(a);
|
|
170
336
|
if (a.nodeIds.length !== b.nodeIds.length) return b.nodeIds.length - a.nodeIds.length;
|
|
171
337
|
return a.start.localeCompare(b.start);
|
|
172
338
|
})[0]?.start;
|
|
@@ -207,7 +373,7 @@ function assignBranchRowsAroundMain(branchData, splitRow) {
|
|
|
207
373
|
}
|
|
208
374
|
return assigned;
|
|
209
375
|
}
|
|
210
|
-
function assignRows(nodes, forwardEdges, columns, gatewayPairs) {
|
|
376
|
+
function assignRows(nodes, forwardEdges, columns, gatewayPairs, nodeBias) {
|
|
211
377
|
const rows = new Map(nodes.map((n) => [n.id, 0]));
|
|
212
378
|
const succs = new Map(nodes.map((n) => [n.id, []]));
|
|
213
379
|
for (const e of forwardEdges) {
|
|
@@ -215,7 +381,7 @@ function assignRows(nodes, forwardEdges, columns, gatewayPairs) {
|
|
|
215
381
|
}
|
|
216
382
|
const handleMap = buildHandleMap(forwardEdges);
|
|
217
383
|
const sortedPairs = [...gatewayPairs.entries()].sort(
|
|
218
|
-
(a, b) => (columns.get(
|
|
384
|
+
(a, b) => (columns.get(a[0]) ?? 0) - (columns.get(b[0]) ?? 0)
|
|
219
385
|
);
|
|
220
386
|
for (const [splitId, mergeId] of sortedPairs) {
|
|
221
387
|
const branches = succs.get(splitId) ?? [];
|
|
@@ -235,11 +401,14 @@ function assignRows(nodes, forwardEdges, columns, gatewayPairs) {
|
|
|
235
401
|
return result;
|
|
236
402
|
};
|
|
237
403
|
const splitHandles = handleMap.get(splitId);
|
|
238
|
-
const branchData = branches.map((start) =>
|
|
239
|
-
start
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
404
|
+
const branchData = branches.map((start) => {
|
|
405
|
+
const nodeIds = getBranchNodes(start);
|
|
406
|
+
return {
|
|
407
|
+
start,
|
|
408
|
+
nodeIds,
|
|
409
|
+
bias: handleToRowBias(splitHandles?.get(start) ?? null) ?? branchPullBias(nodeIds, nodeBias)
|
|
410
|
+
};
|
|
411
|
+
});
|
|
243
412
|
const assigned = assignBranchRowsAroundMain(branchData, splitRow);
|
|
244
413
|
for (const b of branchData) {
|
|
245
414
|
const row = assigned.get(b.start) ?? splitRow;
|
|
@@ -251,7 +420,7 @@ function assignRows(nodes, forwardEdges, columns, gatewayPairs) {
|
|
|
251
420
|
}
|
|
252
421
|
const pairedSplits = new Set(gatewayPairs.keys());
|
|
253
422
|
const unpairedSplits = nodes.filter(
|
|
254
|
-
(n) =>
|
|
423
|
+
(n) => !pairedSplits.has(n.id) && (succs.get(n.id)?.length ?? 0) > 1
|
|
255
424
|
);
|
|
256
425
|
for (const split of unpairedSplits) {
|
|
257
426
|
const branches = succs.get(split.id) ?? [];
|
|
@@ -271,11 +440,14 @@ function assignRows(nodes, forwardEdges, columns, gatewayPairs) {
|
|
|
271
440
|
return result;
|
|
272
441
|
};
|
|
273
442
|
const splitHandles2 = handleMap.get(split.id);
|
|
274
|
-
const branchData = branches.map((start) =>
|
|
275
|
-
start
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
443
|
+
const branchData = branches.map((start) => {
|
|
444
|
+
const nodeIds = getAllReachable(start);
|
|
445
|
+
return {
|
|
446
|
+
start,
|
|
447
|
+
nodeIds,
|
|
448
|
+
bias: handleToRowBias(splitHandles2?.get(start) ?? null) ?? branchPullBias(nodeIds, nodeBias)
|
|
449
|
+
};
|
|
450
|
+
});
|
|
279
451
|
const assigned2 = assignBranchRowsAroundMain(branchData, splitRow);
|
|
280
452
|
for (const b of branchData) {
|
|
281
453
|
const row = assigned2.get(b.start) ?? splitRow;
|
|
@@ -328,6 +500,17 @@ var LAYOUT_TASK_TYPES = /* @__PURE__ */ new Set([
|
|
|
328
500
|
]);
|
|
329
501
|
var TASK_LAYOUT_MIN_W = 130;
|
|
330
502
|
var TASK_LAYOUT_MIN_H = 80;
|
|
503
|
+
var SUBPROCESS_LAYOUT_MIN_W = 160;
|
|
504
|
+
var SUBPROCESS_LAYOUT_MIN_H = 80;
|
|
505
|
+
function layoutMinSize(node) {
|
|
506
|
+
if (LAYOUT_TASK_TYPES.has(node.data.elementType)) {
|
|
507
|
+
return { w: TASK_LAYOUT_MIN_W, h: TASK_LAYOUT_MIN_H };
|
|
508
|
+
}
|
|
509
|
+
if (COLLAPSED_SUBPROCESS_TYPES.has(node.data.elementType) && !node.data.isExpanded) {
|
|
510
|
+
return { w: SUBPROCESS_LAYOUT_MIN_W, h: SUBPROCESS_LAYOUT_MIN_H };
|
|
511
|
+
}
|
|
512
|
+
return null;
|
|
513
|
+
}
|
|
331
514
|
function nW(node) {
|
|
332
515
|
return node.width ?? node.measured?.width ?? 120;
|
|
333
516
|
}
|
|
@@ -335,18 +518,68 @@ function nH(node) {
|
|
|
335
518
|
return node.height ?? node.measured?.height ?? 60;
|
|
336
519
|
}
|
|
337
520
|
function layoutW(node) {
|
|
338
|
-
|
|
521
|
+
const min = layoutMinSize(node);
|
|
522
|
+
return min ? Math.max(nW(node), min.w) : nW(node);
|
|
339
523
|
}
|
|
340
524
|
function layoutH(node) {
|
|
341
|
-
|
|
525
|
+
const min = layoutMinSize(node);
|
|
526
|
+
return min ? Math.max(nH(node), min.h) : nH(node);
|
|
527
|
+
}
|
|
528
|
+
var LABEL_RESERVE_TYPES = /* @__PURE__ */ new Set([
|
|
529
|
+
...LAYOUT_GATEWAY_TYPES,
|
|
530
|
+
"StartEvent",
|
|
531
|
+
"EndEvent",
|
|
532
|
+
"IntermediateCatchEvent",
|
|
533
|
+
"IntermediateThrowEvent"
|
|
534
|
+
]);
|
|
535
|
+
var LABEL_CHAR_W = 6.5;
|
|
536
|
+
var LABEL_RESERVE_MAX = 150;
|
|
537
|
+
function columnW(node) {
|
|
538
|
+
const base = layoutW(node);
|
|
539
|
+
if (!LABEL_RESERVE_TYPES.has(node.data.elementType)) return base;
|
|
540
|
+
const label = typeof node.data.label === "string" ? node.data.label : "";
|
|
541
|
+
if (!label) return base;
|
|
542
|
+
const reserve = Math.min(Math.ceil(label.length * LABEL_CHAR_W), LABEL_RESERVE_MAX);
|
|
543
|
+
return Math.max(base, reserve);
|
|
342
544
|
}
|
|
343
545
|
function applyLayoutMinSize(node) {
|
|
344
|
-
if (!
|
|
546
|
+
if (!layoutMinSize(node)) return node;
|
|
345
547
|
const w = layoutW(node);
|
|
346
548
|
const h = layoutH(node);
|
|
347
549
|
if (w === nW(node) && h === nH(node)) return node;
|
|
348
550
|
return { ...node, width: w, height: h, measured: { width: w, height: h } };
|
|
349
551
|
}
|
|
552
|
+
function computeRowMetrics(contextNodes, rows, includeRowZero) {
|
|
553
|
+
const vals = contextNodes.map((n) => rows.get(n.id) ?? 0);
|
|
554
|
+
const base = includeRowZero ? [0, ...vals] : vals;
|
|
555
|
+
const minRow = Math.min(...base);
|
|
556
|
+
const maxRow = Math.max(...base);
|
|
557
|
+
const rowH = /* @__PURE__ */ new Map();
|
|
558
|
+
for (let r = minRow; r <= maxRow; r++) rowH.set(r, ROW_HEIGHT);
|
|
559
|
+
for (const node of contextNodes) {
|
|
560
|
+
const r = rows.get(node.id) ?? 0;
|
|
561
|
+
rowH.set(r, Math.max(rowH.get(r) ?? ROW_HEIGHT, layoutH(node)));
|
|
562
|
+
}
|
|
563
|
+
const rowY = /* @__PURE__ */ new Map();
|
|
564
|
+
let y = 0;
|
|
565
|
+
for (let r = minRow; r <= maxRow; r++) {
|
|
566
|
+
rowY.set(r, y);
|
|
567
|
+
y += (rowH.get(r) ?? ROW_HEIGHT) + ROW_GAP;
|
|
568
|
+
}
|
|
569
|
+
return { minRow, maxRow, rowH, rowY, contentH: y - ROW_GAP };
|
|
570
|
+
}
|
|
571
|
+
function reanchorBoundaryEdges(edges, boundaryEvents, contentIds) {
|
|
572
|
+
if (boundaryEvents.length === 0) return edges;
|
|
573
|
+
const hostByBoundaryId = /* @__PURE__ */ new Map();
|
|
574
|
+
for (const be of boundaryEvents) {
|
|
575
|
+
if (be.data.attachedToRef) hostByBoundaryId.set(be.id, be.data.attachedToRef);
|
|
576
|
+
}
|
|
577
|
+
if (hostByBoundaryId.size === 0) return edges;
|
|
578
|
+
return edges.map((edge) => {
|
|
579
|
+
const host = hostByBoundaryId.get(edge.source);
|
|
580
|
+
return host && contentIds.has(host) ? { ...edge, source: host, sourceHandle: "source-bottom" } : edge;
|
|
581
|
+
});
|
|
582
|
+
}
|
|
350
583
|
var BOUNDARY_SPACING = 10;
|
|
351
584
|
function repositionBoundaryEvents(boundaryEvents, positionedContent) {
|
|
352
585
|
if (boundaryEvents.length === 0) return [];
|
|
@@ -403,7 +636,8 @@ function layoutSubProcess(children, edges) {
|
|
|
403
636
|
};
|
|
404
637
|
}
|
|
405
638
|
const contentIds = new Set(mainChildren.map((n) => n.id));
|
|
406
|
-
const
|
|
639
|
+
const graphEdges = reanchorBoundaryEdges(edges, boundaryEvents, contentIds);
|
|
640
|
+
const seqEdges = extractSeqEdges(graphEdges, contentIds);
|
|
407
641
|
const backIds = detectBackEdges([...contentIds], seqEdges);
|
|
408
642
|
const fwdEdges = seqEdges.filter((e) => !backIds.has(e.id));
|
|
409
643
|
const columns = assignColumns([...contentIds], fwdEdges);
|
|
@@ -414,7 +648,7 @@ function layoutSubProcess(children, edges) {
|
|
|
414
648
|
for (let c = 0; c <= maxCol; c++) colW.set(c, 0);
|
|
415
649
|
for (const node of mainChildren) {
|
|
416
650
|
const c = columns.get(node.id) ?? 0;
|
|
417
|
-
colW.set(c, Math.max(colW.get(c) ?? 0,
|
|
651
|
+
colW.set(c, Math.max(colW.get(c) ?? 0, columnW(node)));
|
|
418
652
|
}
|
|
419
653
|
const colX = /* @__PURE__ */ new Map();
|
|
420
654
|
let cumX = 0;
|
|
@@ -423,20 +657,16 @@ function layoutSubProcess(children, edges) {
|
|
|
423
657
|
cumX += (colW.get(c) ?? 120) + COL_GAP;
|
|
424
658
|
}
|
|
425
659
|
const contentW = cumX - COL_GAP;
|
|
426
|
-
const
|
|
427
|
-
const minRow = Math.min(0, ...rowVals);
|
|
428
|
-
const maxRow = Math.max(0, ...rowVals);
|
|
429
|
-
const rowCount = maxRow - minRow + 1;
|
|
430
|
-
const contentH = rowCount * ROW_HEIGHT + Math.max(0, rowCount - 1) * ROW_GAP;
|
|
660
|
+
const rowMetrics = computeRowMetrics(mainChildren, rows, true);
|
|
431
661
|
const spW = Math.max(280, SP_PAD * 2 + contentW);
|
|
432
|
-
const spH = Math.max(160, SP_PAD * 2 + contentH);
|
|
662
|
+
const spH = Math.max(160, SP_PAD * 2 + rowMetrics.contentH);
|
|
433
663
|
const positionedChildren = mainChildren.map((node) => {
|
|
434
664
|
const c = columns.get(node.id) ?? 0;
|
|
435
665
|
const r = rows.get(node.id) ?? 0;
|
|
436
666
|
const lw = layoutW(node);
|
|
437
667
|
const lh = layoutH(node);
|
|
438
668
|
const colOffset = (colX.get(c) ?? 0) + (colW.get(c) ?? 120) / 2 - lw / 2;
|
|
439
|
-
const rowOffset = (r
|
|
669
|
+
const rowOffset = (rowMetrics.rowY.get(r) ?? 0) + (rowMetrics.rowH.get(r) ?? ROW_HEIGHT) / 2 - lh / 2;
|
|
440
670
|
return applyLayoutMinSize({ ...node, position: { x: SP_PAD + colOffset, y: SP_PAD + rowOffset } });
|
|
441
671
|
});
|
|
442
672
|
const positionedBoundaries = repositionBoundaryEvents(boundaryEvents, positionedChildren);
|
|
@@ -479,7 +709,8 @@ function layoutPool(pool, lanes, content, allEdges) {
|
|
|
479
709
|
nodeLaneId.set(node.id, lId);
|
|
480
710
|
}
|
|
481
711
|
const contentIds = new Set(mainContent.map((n) => n.id));
|
|
482
|
-
const
|
|
712
|
+
const graphEdges = reanchorBoundaryEdges(allEdges, boundaryEvents, contentIds);
|
|
713
|
+
const seqEdges = extractSeqEdges(graphEdges, contentIds);
|
|
483
714
|
const backIds = detectBackEdges([...contentIds], seqEdges);
|
|
484
715
|
const fwdEdges = seqEdges.filter((e) => !backIds.has(e.id));
|
|
485
716
|
const columns = assignColumns([...contentIds], fwdEdges);
|
|
@@ -490,47 +721,107 @@ function layoutPool(pool, lanes, content, allEdges) {
|
|
|
490
721
|
if (!contentByLane.has(lId)) contentByLane.set(lId, []);
|
|
491
722
|
contentByLane.get(lId).push(node);
|
|
492
723
|
}
|
|
724
|
+
const laneStackIndex = /* @__PURE__ */ new Map();
|
|
725
|
+
sortedLanes.forEach((laneNode, index) => laneStackIndex.set(laneNode.id, index));
|
|
726
|
+
laneStackIndex.set("_pool_", sortedLanes.length);
|
|
727
|
+
const crossLanePull = /* @__PURE__ */ new Map();
|
|
728
|
+
for (const e of fwdEdges) {
|
|
729
|
+
const sLane = nodeLaneId.get(e.source) ?? "_pool_";
|
|
730
|
+
const tLane = nodeLaneId.get(e.target) ?? "_pool_";
|
|
731
|
+
if (sLane === tLane) continue;
|
|
732
|
+
const dir = Math.sign((laneStackIndex.get(tLane) ?? 0) - (laneStackIndex.get(sLane) ?? 0));
|
|
733
|
+
crossLanePull.set(e.source, (crossLanePull.get(e.source) ?? 0) + dir);
|
|
734
|
+
crossLanePull.set(e.target, (crossLanePull.get(e.target) ?? 0) - dir);
|
|
735
|
+
}
|
|
493
736
|
for (const [, laneNodes] of contentByLane) {
|
|
494
737
|
const laneNodeIds = new Set(laneNodes.map((n) => n.id));
|
|
495
738
|
const intraEdges = fwdEdges.filter(
|
|
496
739
|
(e) => laneNodeIds.has(e.source) && laneNodeIds.has(e.target)
|
|
497
740
|
);
|
|
498
741
|
const lanePairs = detectGatewayPairs(laneNodes, intraEdges);
|
|
499
|
-
const laneRows = assignRows(laneNodes, intraEdges, columns, lanePairs);
|
|
742
|
+
const laneRows = assignRows(laneNodes, intraEdges, columns, lanePairs, crossLanePull);
|
|
500
743
|
for (const [id, row] of laneRows) rows.set(id, row);
|
|
501
744
|
}
|
|
502
|
-
const
|
|
745
|
+
const seqTouched = /* @__PURE__ */ new Set();
|
|
746
|
+
for (const e of seqEdges) {
|
|
747
|
+
seqTouched.add(e.source);
|
|
748
|
+
seqTouched.add(e.target);
|
|
749
|
+
}
|
|
750
|
+
for (const [, laneNodes] of contentByLane) {
|
|
751
|
+
const eventSPs = laneNodes.filter(
|
|
752
|
+
(n) => n.data.elementType === "EventSubProcess" && !seqTouched.has(n.id)
|
|
753
|
+
);
|
|
754
|
+
if (eventSPs.length === 0) continue;
|
|
755
|
+
const eventSpIds = new Set(eventSPs.map((n) => n.id));
|
|
756
|
+
const otherRows = laneNodes.filter((n) => !eventSpIds.has(n.id)).map((n) => rows.get(n.id) ?? 0);
|
|
757
|
+
const laneMaxRow = otherRows.length > 0 ? Math.max(...otherRows) : -1;
|
|
758
|
+
for (const sp of eventSPs) rows.set(sp.id, laneMaxRow + 1);
|
|
759
|
+
}
|
|
760
|
+
const hasPoolDirectContent = [...nodeLaneId.values()].includes("_pool_");
|
|
761
|
+
const laneIds = hasLanes ? [...sortedLanes.map((l) => l.id), ...hasPoolDirectContent ? ["_pool_"] : []] : ["_pool_"];
|
|
503
762
|
const laneStats = /* @__PURE__ */ new Map();
|
|
504
763
|
for (const laneId of laneIds) {
|
|
505
|
-
const
|
|
506
|
-
if (
|
|
507
|
-
laneStats.set(laneId, {
|
|
764
|
+
const laneNodes = mainContent.filter((n) => nodeLaneId.get(n.id) === laneId);
|
|
765
|
+
if (laneNodes.length === 0) {
|
|
766
|
+
laneStats.set(laneId, {
|
|
767
|
+
minRow: 0,
|
|
768
|
+
maxRow: 0,
|
|
769
|
+
height: LANE_MIN_H,
|
|
770
|
+
contentH: ROW_HEIGHT,
|
|
771
|
+
rowH: /* @__PURE__ */ new Map([[0, ROW_HEIGHT]]),
|
|
772
|
+
rowY: /* @__PURE__ */ new Map([[0, 0]])
|
|
773
|
+
});
|
|
508
774
|
} else {
|
|
509
|
-
const
|
|
510
|
-
const
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
775
|
+
const m = computeRowMetrics(laneNodes, rows, false);
|
|
776
|
+
const height = Math.max(LANE_MIN_H, LANE_V_PAD * 2 + m.contentH);
|
|
777
|
+
laneStats.set(laneId, {
|
|
778
|
+
minRow: m.minRow,
|
|
779
|
+
maxRow: m.maxRow,
|
|
780
|
+
height,
|
|
781
|
+
contentH: m.contentH,
|
|
782
|
+
rowH: m.rowH,
|
|
783
|
+
rowY: m.rowY
|
|
784
|
+
});
|
|
515
785
|
}
|
|
516
786
|
}
|
|
517
|
-
const
|
|
518
|
-
const
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
787
|
+
const laneColumnLayouts = /* @__PURE__ */ new Map();
|
|
788
|
+
for (const laneId of laneIds) {
|
|
789
|
+
const laneNodes = mainContent.filter(
|
|
790
|
+
(node) => (nodeLaneId.get(node.id) ?? "_pool_") === laneId
|
|
791
|
+
);
|
|
792
|
+
const usedCols = [...new Set(laneNodes.map((node) => columns.get(node.id) ?? 0))].sort((a, b) => a - b);
|
|
793
|
+
const colW = /* @__PURE__ */ new Map();
|
|
794
|
+
for (const col of usedCols) colW.set(col, 0);
|
|
795
|
+
for (const node of laneNodes) {
|
|
796
|
+
const col = columns.get(node.id) ?? 0;
|
|
797
|
+
colW.set(col, Math.max(colW.get(col) ?? 0, columnW(node)));
|
|
798
|
+
}
|
|
799
|
+
const colX = /* @__PURE__ */ new Map();
|
|
800
|
+
let laneCumX = 0;
|
|
801
|
+
for (const col of usedCols) {
|
|
802
|
+
colX.set(col, laneCumX);
|
|
803
|
+
laneCumX += (colW.get(col) ?? 120) + COL_GAP;
|
|
804
|
+
}
|
|
805
|
+
laneColumnLayouts.set(laneId, {
|
|
806
|
+
colW,
|
|
807
|
+
colX,
|
|
808
|
+
contentW: usedCols.length > 0 ? laneCumX - COL_GAP : 0
|
|
809
|
+
});
|
|
529
810
|
}
|
|
530
|
-
const
|
|
531
|
-
|
|
811
|
+
const baseLaneInnerW = Math.max(
|
|
812
|
+
0,
|
|
813
|
+
...laneIds.filter((laneId) => laneId !== "_pool_").map((laneId) => {
|
|
814
|
+
const contentW = laneColumnLayouts.get(laneId)?.contentW ?? 0;
|
|
815
|
+
return LANE_LABEL_W + LANE_H_PAD + contentW + LANE_H_PAD;
|
|
816
|
+
})
|
|
817
|
+
);
|
|
818
|
+
const basePoolInnerW = Math.max(
|
|
819
|
+
0,
|
|
820
|
+
...laneIds.filter((laneId) => laneId === "_pool_").map((laneId) => (laneColumnLayouts.get(laneId)?.contentW ?? 0) + POOL_H_PAD * 2)
|
|
821
|
+
);
|
|
822
|
+
const innerW = Math.max(baseLaneInnerW, basePoolInnerW);
|
|
532
823
|
const poolW = Math.max(POOL_MIN_W, innerW + POOL_INNER_PAD * 2);
|
|
533
|
-
|
|
824
|
+
let laneW = poolW - POOL_INNER_PAD * 2;
|
|
534
825
|
const laneY = /* @__PURE__ */ new Map();
|
|
535
826
|
let cumY = POOL_INNER_PAD;
|
|
536
827
|
for (let i = 0; i < laneIds.length; i++) {
|
|
@@ -545,20 +836,106 @@ function layoutPool(pool, lanes, content, allEdges) {
|
|
|
545
836
|
const r = rows.get(node.id) ?? 0;
|
|
546
837
|
const laneId = nodeLaneId.get(node.id) ?? "_pool_";
|
|
547
838
|
const stat = laneStats.get(laneId);
|
|
839
|
+
const laneLayout = laneColumnLayouts.get(laneId);
|
|
548
840
|
const lYOff = laneY.get(laneId) ?? 0;
|
|
549
841
|
const lw = layoutW(node);
|
|
550
842
|
const lh = layoutH(node);
|
|
551
|
-
const colOffset = (colX.get(c) ?? 0) + (colW.get(c) ?? 120) / 2 - lw / 2;
|
|
552
|
-
const rowOffset = (
|
|
553
|
-
const
|
|
554
|
-
const vertTopOffset = Math.max(LANE_V_PAD, (stat.height - contentH_stat) / 2);
|
|
843
|
+
const colOffset = (laneLayout?.colX.get(c) ?? 0) + (laneLayout?.colW.get(c) ?? 120) / 2 - lw / 2;
|
|
844
|
+
const rowOffset = (stat.rowY.get(r) ?? 0) + (stat.rowH.get(r) ?? ROW_HEIGHT) / 2 - lh / 2;
|
|
845
|
+
const vertTopOffset = Math.max(LANE_V_PAD, (stat.height - stat.contentH) / 2);
|
|
555
846
|
const isLaneChild = hasLanes && !!node.parentId && node.parentId !== pool.id;
|
|
556
847
|
const x = isLaneChild ? LANE_LABEL_W + LANE_H_PAD + colOffset : POOL_H_PAD + colOffset;
|
|
557
848
|
const y = isLaneChild ? vertTopOffset + rowOffset : lYOff + vertTopOffset + rowOffset;
|
|
558
849
|
return applyLayoutMinSize({ ...node, position: { x, y } });
|
|
559
850
|
});
|
|
851
|
+
const handoffAdjustedContent = [...positionedContent];
|
|
852
|
+
const nodeIndexById = new Map(handoffAdjustedContent.map((node, index) => [node.id, index]));
|
|
853
|
+
const outgoingBySource = /* @__PURE__ */ new Map();
|
|
854
|
+
for (const edge of fwdEdges) {
|
|
855
|
+
if (!outgoingBySource.has(edge.source)) outgoingBySource.set(edge.source, []);
|
|
856
|
+
outgoingBySource.get(edge.source).push(edge);
|
|
857
|
+
}
|
|
858
|
+
const crossLaneEdges = fwdEdges.filter((edge) => {
|
|
859
|
+
const srcLane = nodeLaneId.get(edge.source) ?? "_pool_";
|
|
860
|
+
const tgtLane = nodeLaneId.get(edge.target) ?? "_pool_";
|
|
861
|
+
return srcLane !== tgtLane;
|
|
862
|
+
}).sort(
|
|
863
|
+
(a, b) => (columns.get(a.target) ?? 0) - (columns.get(b.target) ?? 0) || (columns.get(a.source) ?? 0) - (columns.get(b.source) ?? 0)
|
|
864
|
+
);
|
|
865
|
+
for (const edge of crossLaneEdges) {
|
|
866
|
+
const srcIndex = nodeIndexById.get(edge.source);
|
|
867
|
+
const tgtIndex = nodeIndexById.get(edge.target);
|
|
868
|
+
if (srcIndex == null || tgtIndex == null) continue;
|
|
869
|
+
const srcNode = handoffAdjustedContent[srcIndex];
|
|
870
|
+
const tgtNode = handoffAdjustedContent[tgtIndex];
|
|
871
|
+
const tgtLaneId = nodeLaneId.get(tgtNode.id) ?? "_pool_";
|
|
872
|
+
const tgtCol = columns.get(tgtNode.id) ?? 0;
|
|
873
|
+
const siblingTargets = (outgoingBySource.get(edge.source) ?? []).filter((candidate) => (columns.get(candidate.target) ?? 0) === tgtCol).map((candidate) => handoffAdjustedContent[nodeIndexById.get(candidate.target) ?? -1]).filter((node) => !!node);
|
|
874
|
+
const siblingAlignedX = siblingTargets.reduce(
|
|
875
|
+
(max, node) => Math.max(max, node.position.x),
|
|
876
|
+
Number.NEGATIVE_INFINITY
|
|
877
|
+
);
|
|
878
|
+
const minTargetX = Math.max(
|
|
879
|
+
siblingAlignedX,
|
|
880
|
+
srcNode.position.x + layoutW(srcNode) / 2 + layoutW(tgtNode) / 2 + COL_GAP
|
|
881
|
+
);
|
|
882
|
+
if (tgtNode.position.x >= minTargetX) continue;
|
|
883
|
+
const delta = minTargetX - tgtNode.position.x;
|
|
884
|
+
for (let i = 0; i < handoffAdjustedContent.length; i++) {
|
|
885
|
+
const candidate = handoffAdjustedContent[i];
|
|
886
|
+
if ((nodeLaneId.get(candidate.id) ?? "_pool_") !== tgtLaneId) continue;
|
|
887
|
+
if ((columns.get(candidate.id) ?? 0) < tgtCol) continue;
|
|
888
|
+
handoffAdjustedContent[i] = {
|
|
889
|
+
...candidate,
|
|
890
|
+
position: {
|
|
891
|
+
x: candidate.position.x + delta,
|
|
892
|
+
y: candidate.position.y
|
|
893
|
+
}
|
|
894
|
+
};
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
for (const [sourceId, outgoing] of outgoingBySource) {
|
|
898
|
+
if (outgoing.length < 2) continue;
|
|
899
|
+
const hasCrossLaneSibling = outgoing.some((edge) => {
|
|
900
|
+
const srcLane = nodeLaneId.get(edge.source) ?? "_pool_";
|
|
901
|
+
const tgtLane = nodeLaneId.get(edge.target) ?? "_pool_";
|
|
902
|
+
return srcLane !== tgtLane;
|
|
903
|
+
});
|
|
904
|
+
if (!hasCrossLaneSibling) continue;
|
|
905
|
+
const siblingsByCol = /* @__PURE__ */ new Map();
|
|
906
|
+
for (const edge of outgoing) {
|
|
907
|
+
const col = columns.get(edge.target) ?? 0;
|
|
908
|
+
const node = handoffAdjustedContent[nodeIndexById.get(edge.target) ?? -1];
|
|
909
|
+
if (!node) continue;
|
|
910
|
+
if (!siblingsByCol.has(col)) siblingsByCol.set(col, []);
|
|
911
|
+
siblingsByCol.get(col).push(node);
|
|
912
|
+
}
|
|
913
|
+
for (const [col, siblings] of siblingsByCol) {
|
|
914
|
+
if (siblings.length < 2) continue;
|
|
915
|
+
const alignedX = Math.max(...siblings.map((node) => node.position.x));
|
|
916
|
+
for (let i = 0; i < handoffAdjustedContent.length; i++) {
|
|
917
|
+
const candidate = handoffAdjustedContent[i];
|
|
918
|
+
if (!siblings.some((node) => node.id === candidate.id)) continue;
|
|
919
|
+
const laneId = nodeLaneId.get(candidate.id) ?? "_pool_";
|
|
920
|
+
for (let j = 0; j < handoffAdjustedContent.length; j++) {
|
|
921
|
+
const maybeShift = handoffAdjustedContent[j];
|
|
922
|
+
if ((nodeLaneId.get(maybeShift.id) ?? "_pool_") !== laneId) continue;
|
|
923
|
+
if ((columns.get(maybeShift.id) ?? 0) < col) continue;
|
|
924
|
+
const delta = alignedX - candidate.position.x;
|
|
925
|
+
if (delta <= 0) continue;
|
|
926
|
+
handoffAdjustedContent[j] = {
|
|
927
|
+
...maybeShift,
|
|
928
|
+
position: {
|
|
929
|
+
x: maybeShift.position.x + delta,
|
|
930
|
+
y: maybeShift.position.y
|
|
931
|
+
}
|
|
932
|
+
};
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
}
|
|
560
937
|
const NODE_MIN_GAP = 24;
|
|
561
|
-
const resolvedContent = [...
|
|
938
|
+
const resolvedContent = [...handoffAdjustedContent];
|
|
562
939
|
for (const laneId of laneIds) {
|
|
563
940
|
const laneNodeIndices = resolvedContent.map((n, i) => ({ n, i })).filter(({ n }) => (nodeLaneId.get(n.id) ?? "_pool_") === laneId).sort((a, b) => a.n.position.x - b.n.position.x);
|
|
564
941
|
for (let k = 1; k < laneNodeIndices.length; k++) {
|
|
@@ -580,6 +957,15 @@ function layoutPool(pool, lanes, content, allEdges) {
|
|
|
580
957
|
}
|
|
581
958
|
}
|
|
582
959
|
const positionedBoundaries = repositionBoundaryEvents(boundaryEvents, resolvedContent);
|
|
960
|
+
const laneChildRight = resolvedContent.filter((node) => hasLanes && !!node.parentId && node.parentId !== pool.id).reduce((max, node) => Math.max(max, node.position.x + nW(node) + LANE_H_PAD), 0);
|
|
961
|
+
const poolChildRight = resolvedContent.filter((node) => !hasLanes || !node.parentId || node.parentId === pool.id).reduce((max, node) => Math.max(max, node.position.x + nW(node) + POOL_H_PAD), 0);
|
|
962
|
+
const boundaryRight = positionedBoundaries.reduce(
|
|
963
|
+
(max, node) => Math.max(max, node.position.x + nW(node) + (hasLanes ? LANE_H_PAD : POOL_H_PAD)),
|
|
964
|
+
0
|
|
965
|
+
);
|
|
966
|
+
const finalInnerW = Math.max(innerW, laneChildRight, poolChildRight, boundaryRight);
|
|
967
|
+
const finalPoolW = Math.max(POOL_MIN_W, finalInnerW + POOL_INNER_PAD * 2);
|
|
968
|
+
laneW = finalPoolW - POOL_INNER_PAD * 2;
|
|
583
969
|
const positionedLanes = hasLanes ? sortedLanes.map((lane) => ({
|
|
584
970
|
...lane,
|
|
585
971
|
position: { x: POOL_INNER_PAD, y: laneY.get(lane.id) ?? POOL_INNER_PAD },
|
|
@@ -588,10 +974,21 @@ function layoutPool(pool, lanes, content, allEdges) {
|
|
|
588
974
|
})) : [];
|
|
589
975
|
return {
|
|
590
976
|
nodes: [...resolvedContent, ...positionedBoundaries, ...positionedLanes],
|
|
591
|
-
width:
|
|
977
|
+
width: finalPoolW,
|
|
592
978
|
height: poolH
|
|
593
979
|
};
|
|
594
980
|
}
|
|
981
|
+
function layoutVirtualContext(contextNodes, allEdges, offsetY) {
|
|
982
|
+
if (contextNodes.length === 0) return [];
|
|
983
|
+
const virtualPool = {
|
|
984
|
+
id: "__bpmn_virtual_pool__"};
|
|
985
|
+
const result = layoutPool(virtualPool, [], contextNodes, allEdges);
|
|
986
|
+
if (offsetY === 0) return result.nodes;
|
|
987
|
+
return result.nodes.map((n) => ({
|
|
988
|
+
...n,
|
|
989
|
+
position: { x: n.position.x, y: n.position.y + offsetY }
|
|
990
|
+
}));
|
|
991
|
+
}
|
|
595
992
|
function absolutePos(nodeId, byId, cache) {
|
|
596
993
|
const cached = cache.get(nodeId);
|
|
597
994
|
if (cached) return cached;
|
|
@@ -672,9 +1069,75 @@ function routeEdges(edges, layoutNodes, backEdgeIds, laneIds, poolIds) {
|
|
|
672
1069
|
const cache = /* @__PURE__ */ new Map();
|
|
673
1070
|
const abs = (id) => absolutePos(id, byId, cache);
|
|
674
1071
|
const sortedLanes = [...laneIds].map((id) => byId.get(id)).filter((n) => !!n).sort((a, b) => abs(a.id).y - abs(b.id).y);
|
|
675
|
-
|
|
1072
|
+
const contentInfos = layoutNodes.filter((n) => !poolIds.has(n.id) && !laneIds.has(n.id)).map((n) => {
|
|
1073
|
+
const p = abs(n.id);
|
|
1074
|
+
return { id: n.id, x: p.x, y: p.y, w: nW(n), h: nH(n), poolId: poolOf(n, poolIds, byId) ?? null };
|
|
1075
|
+
});
|
|
1076
|
+
const findClearX = (desiredX, y0, y1, minX, maxX, excludeA, excludeB, poolId) => {
|
|
1077
|
+
if (minX > maxX) return desiredX;
|
|
1078
|
+
const clampX = (x) => Math.min(maxX, Math.max(minX, x));
|
|
1079
|
+
const blockers = contentInfos.filter(
|
|
1080
|
+
(c) => c.poolId === poolId && c.id !== excludeA && c.id !== excludeB && c.y < y1 && c.y + c.h > y0
|
|
1081
|
+
);
|
|
1082
|
+
const isFree = (x) => blockers.every((c) => x < c.x - 4 || x > c.x + c.w + 4);
|
|
1083
|
+
const clamped = clampX(desiredX);
|
|
1084
|
+
if (isFree(clamped)) return clamped;
|
|
1085
|
+
const candidates = [];
|
|
1086
|
+
for (const c of blockers) candidates.push(c.x - 8, c.x + c.w + 8);
|
|
1087
|
+
const free = candidates.map(clampX).filter(isFree).sort((a, b) => Math.abs(a - desiredX) - Math.abs(b - desiredX));
|
|
1088
|
+
return free.length > 0 ? free[0] : clamped;
|
|
1089
|
+
};
|
|
1090
|
+
const backEdgeOrder = /* @__PURE__ */ new Map();
|
|
1091
|
+
for (const edge of [...edges].sort((a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0)) {
|
|
1092
|
+
if (backEdgeIds.has(edge.id)) backEdgeOrder.set(edge.id, backEdgeOrder.size);
|
|
1093
|
+
}
|
|
1094
|
+
const routeMessageFlow = (edge) => {
|
|
1095
|
+
const src = byId.get(edge.source);
|
|
1096
|
+
const tgt = byId.get(edge.target);
|
|
1097
|
+
if (!src || !tgt) return null;
|
|
1098
|
+
const srcPoolId = poolOf(src, poolIds, byId);
|
|
1099
|
+
const tgtPoolId = poolOf(tgt, poolIds, byId);
|
|
1100
|
+
if (!srcPoolId || !tgtPoolId || srcPoolId === tgtPoolId) return null;
|
|
1101
|
+
const srcPoolNode = byId.get(srcPoolId);
|
|
1102
|
+
const tgtPoolNode = byId.get(tgtPoolId);
|
|
1103
|
+
if (!srcPoolNode || !tgtPoolNode) return null;
|
|
1104
|
+
const sAbs = abs(src.id);
|
|
1105
|
+
const tAbs = abs(tgt.id);
|
|
1106
|
+
const sCX = sAbs.x + nW(src) / 2;
|
|
1107
|
+
const tCX = tAbs.x + nW(tgt) / 2;
|
|
1108
|
+
const srcPoolAbs = abs(srcPoolId);
|
|
1109
|
+
const tgtPoolAbs = abs(tgtPoolId);
|
|
1110
|
+
const srcPoolBottom = srcPoolAbs.y + nH(srcPoolNode);
|
|
1111
|
+
const tgtPoolBottom = tgtPoolAbs.y + nH(tgtPoolNode);
|
|
1112
|
+
if (tgtPoolAbs.y >= srcPoolBottom) {
|
|
1113
|
+
const corridorY = (srcPoolBottom + tgtPoolAbs.y) / 2;
|
|
1114
|
+
return [
|
|
1115
|
+
{ x: sCX, y: sAbs.y + nH(src) },
|
|
1116
|
+
{ x: sCX, y: corridorY },
|
|
1117
|
+
{ x: tCX, y: corridorY },
|
|
1118
|
+
{ x: tCX, y: tAbs.y }
|
|
1119
|
+
];
|
|
1120
|
+
}
|
|
1121
|
+
if (srcPoolAbs.y >= tgtPoolBottom) {
|
|
1122
|
+
const corridorY = (tgtPoolBottom + srcPoolAbs.y) / 2;
|
|
1123
|
+
return [
|
|
1124
|
+
{ x: sCX, y: sAbs.y },
|
|
1125
|
+
{ x: sCX, y: corridorY },
|
|
1126
|
+
{ x: tCX, y: corridorY },
|
|
1127
|
+
{ x: tCX, y: tAbs.y + nH(tgt) }
|
|
1128
|
+
];
|
|
1129
|
+
}
|
|
1130
|
+
return null;
|
|
1131
|
+
};
|
|
1132
|
+
const routed = edges.map((edge) => {
|
|
676
1133
|
const edgeType = edge.data?.edgeType ?? edge.type;
|
|
677
1134
|
if (edgeType !== "sequenceFlow") {
|
|
1135
|
+
if (edgeType === "messageFlow") {
|
|
1136
|
+
const pts = routeMessageFlow(edge);
|
|
1137
|
+
if (pts) {
|
|
1138
|
+
return { ...edge, data: { ...edge.data, routingPoints: pts } };
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
678
1141
|
const d = { ...edge.data };
|
|
679
1142
|
delete d.routingPoints;
|
|
680
1143
|
return { ...edge, data: d };
|
|
@@ -699,7 +1162,16 @@ function routeEdges(edges, layoutNodes, backEdgeIds, laneIds, poolIds) {
|
|
|
699
1162
|
}
|
|
700
1163
|
let routingPoints;
|
|
701
1164
|
if (backEdgeIds.has(edge.id)) {
|
|
702
|
-
const
|
|
1165
|
+
const spanMinX = Math.min(tAbs.x, sAbs.x) - EDGE_ROUTE_PAD;
|
|
1166
|
+
const spanMaxX = Math.max(tAbs.x + tW, sAbs.x + sW) + EDGE_ROUTE_PAD;
|
|
1167
|
+
let topMost = Math.min(sAbs.y, tAbs.y);
|
|
1168
|
+
for (const cand of contentInfos) {
|
|
1169
|
+
if (cand.poolId !== srcPool) continue;
|
|
1170
|
+
if (cand.x + cand.w < spanMinX || cand.x > spanMaxX) continue;
|
|
1171
|
+
topMost = Math.min(topMost, cand.y);
|
|
1172
|
+
}
|
|
1173
|
+
const stagger = (backEdgeOrder.get(edge.id) ?? 0) * 14;
|
|
1174
|
+
const topY = topMost - BACK_EDGE_CLEARANCE - stagger;
|
|
703
1175
|
routingPoints = [
|
|
704
1176
|
{ x: sAbs.x + sW, y: sCY },
|
|
705
1177
|
{ x: sAbs.x + sW + EDGE_ROUTE_PAD, y: sCY },
|
|
@@ -713,7 +1185,16 @@ function routeEdges(edges, layoutNodes, backEdgeIds, laneIds, poolIds) {
|
|
|
713
1185
|
const tgtLane = byId.get(laneOf(tgt, laneIds, byId) ?? "");
|
|
714
1186
|
if (srcLane && tgtLane && laneIds.has(srcLane.id) && laneIds.has(tgtLane.id)) {
|
|
715
1187
|
const goingDown = tAbs.y > sAbs.y;
|
|
716
|
-
const sharedX =
|
|
1188
|
+
const sharedX = findClearX(
|
|
1189
|
+
gapMidX(sAbs, sW, tAbs, tW),
|
|
1190
|
+
Math.min(sCY, tCY),
|
|
1191
|
+
Math.max(sCY, tCY),
|
|
1192
|
+
sAbs.x + sW + 6,
|
|
1193
|
+
tAbs.x - EDGE_ROUTE_PAD - 4,
|
|
1194
|
+
src.id,
|
|
1195
|
+
tgt.id,
|
|
1196
|
+
srcPool
|
|
1197
|
+
);
|
|
717
1198
|
const srcLaneIdx = sortedLanes.findIndex((l) => l.id === srcLane.id);
|
|
718
1199
|
const tgtLaneIdx = sortedLanes.findIndex((l) => l.id === tgtLane.id);
|
|
719
1200
|
const pts = [];
|
|
@@ -748,7 +1229,16 @@ function routeEdges(edges, layoutNodes, backEdgeIds, laneIds, poolIds) {
|
|
|
748
1229
|
}
|
|
749
1230
|
routingPoints = pts;
|
|
750
1231
|
} else {
|
|
751
|
-
const sharedX =
|
|
1232
|
+
const sharedX = findClearX(
|
|
1233
|
+
gapMidX(sAbs, sW, tAbs, tW),
|
|
1234
|
+
Math.min(sCY, tCY),
|
|
1235
|
+
Math.max(sCY, tCY),
|
|
1236
|
+
sAbs.x + sW + 6,
|
|
1237
|
+
tAbs.x - 6,
|
|
1238
|
+
src.id,
|
|
1239
|
+
tgt.id,
|
|
1240
|
+
srcPool
|
|
1241
|
+
);
|
|
752
1242
|
routingPoints = [
|
|
753
1243
|
{ x: sAbs.x + sW, y: sCY },
|
|
754
1244
|
{ x: sharedX, y: sCY },
|
|
@@ -778,7 +1268,16 @@ function routeEdges(edges, layoutNodes, backEdgeIds, laneIds, poolIds) {
|
|
|
778
1268
|
const midX = routeMidX(sAbs, sW, tAbs, tW);
|
|
779
1269
|
const exitX = sAbs.x + sW;
|
|
780
1270
|
const entryX = tAbs.x;
|
|
781
|
-
const corridorX =
|
|
1271
|
+
const corridorX = findClearX(
|
|
1272
|
+
Math.max(midX, exitX + EDGE_ROUTE_PAD),
|
|
1273
|
+
Math.min(sCY, tCY),
|
|
1274
|
+
Math.max(sCY, tCY),
|
|
1275
|
+
exitX + 6,
|
|
1276
|
+
entryX - 6,
|
|
1277
|
+
src.id,
|
|
1278
|
+
tgt.id,
|
|
1279
|
+
srcPool
|
|
1280
|
+
);
|
|
782
1281
|
routingPoints = [
|
|
783
1282
|
{ x: exitX, y: sCY },
|
|
784
1283
|
{ x: corridorX, y: sCY },
|
|
@@ -789,9 +1288,81 @@ function routeEdges(edges, layoutNodes, backEdgeIds, laneIds, poolIds) {
|
|
|
789
1288
|
}
|
|
790
1289
|
return { ...edge, data: { ...edge.data, routingPoints } };
|
|
791
1290
|
});
|
|
1291
|
+
return spreadVerticalChannels(routed);
|
|
1292
|
+
}
|
|
1293
|
+
var CHANNEL_GAP = 10;
|
|
1294
|
+
var CHANNEL_CLUSTER_TOL = 8;
|
|
1295
|
+
function spreadVerticalChannels(edges) {
|
|
1296
|
+
const runs = [];
|
|
1297
|
+
edges.forEach((edge, edgeIdx) => {
|
|
1298
|
+
const pts = edge.data?.routingPoints;
|
|
1299
|
+
if (!pts || pts.length < 4) return;
|
|
1300
|
+
let i = 1;
|
|
1301
|
+
while (i < pts.length) {
|
|
1302
|
+
let j = i;
|
|
1303
|
+
while (j < pts.length && Math.abs(pts[j].x - pts[j - 1].x) <= 0.5) j++;
|
|
1304
|
+
if (j > i) {
|
|
1305
|
+
const fromIdx = i - 1;
|
|
1306
|
+
const toIdx = j - 1;
|
|
1307
|
+
if (fromIdx > 0 && toIdx < pts.length - 1) {
|
|
1308
|
+
const ys = pts.slice(fromIdx, toIdx + 1).map((p) => p.y);
|
|
1309
|
+
const y0 = Math.min(...ys);
|
|
1310
|
+
const y1 = Math.max(...ys);
|
|
1311
|
+
if (y1 - y0 >= 4) {
|
|
1312
|
+
runs.push({ edgeIdx, fromIdx, toIdx, x: pts[fromIdx].x, y0, y1 });
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
i = j + 1;
|
|
1316
|
+
} else {
|
|
1317
|
+
i++;
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
});
|
|
1321
|
+
if (runs.length < 2) return edges;
|
|
1322
|
+
runs.sort((a, b) => a.x - b.x);
|
|
1323
|
+
const clusters = [];
|
|
1324
|
+
for (const run of runs) {
|
|
1325
|
+
const last = clusters[clusters.length - 1];
|
|
1326
|
+
if (last && run.x - last[0].x <= CHANNEL_CLUSTER_TOL) last.push(run);
|
|
1327
|
+
else clusters.push([run]);
|
|
1328
|
+
}
|
|
1329
|
+
const offsets = /* @__PURE__ */ new Map();
|
|
1330
|
+
for (const cluster of clusters) {
|
|
1331
|
+
if (cluster.length < 2) continue;
|
|
1332
|
+
const colliding = cluster.filter(
|
|
1333
|
+
(run) => cluster.some((other) => other !== run && run.y0 < other.y1 && other.y0 < run.y1)
|
|
1334
|
+
);
|
|
1335
|
+
if (colliding.length < 2) continue;
|
|
1336
|
+
const ordered = [...colliding].sort((a, b) => {
|
|
1337
|
+
const idA = edges[a.edgeIdx].id;
|
|
1338
|
+
const idB = edges[b.edgeIdx].id;
|
|
1339
|
+
return idA < idB ? -1 : idA > idB ? 1 : a.fromIdx - b.fromIdx;
|
|
1340
|
+
});
|
|
1341
|
+
ordered.forEach((run, k) => {
|
|
1342
|
+
const off = Math.round((k - (ordered.length - 1) / 2) * CHANNEL_GAP);
|
|
1343
|
+
if (off !== 0) offsets.set(run, off);
|
|
1344
|
+
});
|
|
1345
|
+
}
|
|
1346
|
+
if (offsets.size === 0) return edges;
|
|
1347
|
+
const runsByEdge = /* @__PURE__ */ new Map();
|
|
1348
|
+
for (const [run, off] of offsets) {
|
|
1349
|
+
if (!runsByEdge.has(run.edgeIdx)) runsByEdge.set(run.edgeIdx, []);
|
|
1350
|
+
runsByEdge.get(run.edgeIdx).push(run);
|
|
1351
|
+
}
|
|
1352
|
+
return edges.map((edge, edgeIdx) => {
|
|
1353
|
+
const edgeRuns = runsByEdge.get(edgeIdx);
|
|
1354
|
+
if (!edgeRuns) return edge;
|
|
1355
|
+
const pts = (edge.data?.routingPoints).map((p) => ({ ...p }));
|
|
1356
|
+
for (const run of edgeRuns) {
|
|
1357
|
+
const off = offsets.get(run);
|
|
1358
|
+
for (let p = run.fromIdx; p <= run.toIdx; p++) pts[p].x += off;
|
|
1359
|
+
}
|
|
1360
|
+
return { ...edge, data: { ...edge.data, routingPoints: pts } };
|
|
1361
|
+
});
|
|
792
1362
|
}
|
|
793
1363
|
var ARTIFACT_ABOVE_GAP = 16;
|
|
794
1364
|
var ARTIFACT_H_SPACING = 12;
|
|
1365
|
+
var ARTIFACT_EDGE_PAD = 4;
|
|
795
1366
|
function positionArtifacts(artifacts, resultNodes, edges, originalNodes) {
|
|
796
1367
|
if (artifacts.length === 0) return [];
|
|
797
1368
|
const byId = new Map(resultNodes.map((n) => [n.id, n]));
|
|
@@ -832,11 +1403,21 @@ function positionArtifacts(artifacts, resultNodes, edges, originalNodes) {
|
|
|
832
1403
|
let desiredAbsX = connAbsP.x + nW(connNode) / 2 - totalW / 2;
|
|
833
1404
|
for (const artifact of arts) {
|
|
834
1405
|
const parentAbsP = artifact.parentId ? absPos(artifact.parentId) : { x: 0, y: 0 };
|
|
1406
|
+
let relY = desiredAbsY - parentAbsP.y;
|
|
1407
|
+
const parentNode = artifact.parentId ? byId.get(artifact.parentId) : void 0;
|
|
1408
|
+
if (parentNode) {
|
|
1409
|
+
if (relY < ARTIFACT_EDGE_PAD) {
|
|
1410
|
+
const belowAbsY = connAbsP.y + nH(connNode) + ARTIFACT_ABOVE_GAP;
|
|
1411
|
+
relY = belowAbsY - parentAbsP.y;
|
|
1412
|
+
}
|
|
1413
|
+
relY = Math.min(relY, nH(parentNode) - nH(artifact) - ARTIFACT_EDGE_PAD);
|
|
1414
|
+
relY = Math.max(relY, ARTIFACT_EDGE_PAD);
|
|
1415
|
+
}
|
|
835
1416
|
positioned.push({
|
|
836
1417
|
...artifact,
|
|
837
1418
|
position: {
|
|
838
1419
|
x: desiredAbsX - parentAbsP.x,
|
|
839
|
-
y:
|
|
1420
|
+
y: relY
|
|
840
1421
|
}
|
|
841
1422
|
});
|
|
842
1423
|
desiredAbsX += nW(artifact) + ARTIFACT_H_SPACING;
|
|
@@ -901,9 +1482,17 @@ async function bpmnCustomLayout(nodes, edges) {
|
|
|
901
1482
|
const mainNodes = nodes.filter((n) => !LAYOUT_ARTIFACT_TYPES.has(n.data.elementType));
|
|
902
1483
|
const pools = mainNodes.filter((n) => n.data.elementType === "Pool");
|
|
903
1484
|
const lanes = mainNodes.filter((n) => n.data.elementType === "Lane");
|
|
904
|
-
const
|
|
905
|
-
|
|
906
|
-
)
|
|
1485
|
+
const nodeDepthById = /* @__PURE__ */ new Map();
|
|
1486
|
+
const mainById = new Map(mainNodes.map((n) => [n.id, n]));
|
|
1487
|
+
const depthOf = (node) => {
|
|
1488
|
+
const cached = nodeDepthById.get(node.id);
|
|
1489
|
+
if (cached != null) return cached;
|
|
1490
|
+
const parent = node.parentId ? mainById.get(node.parentId) : void 0;
|
|
1491
|
+
const depth = parent ? depthOf(parent) + 1 : 0;
|
|
1492
|
+
nodeDepthById.set(node.id, depth);
|
|
1493
|
+
return depth;
|
|
1494
|
+
};
|
|
1495
|
+
const expandedSubProcesses = mainNodes.filter((n) => COLLAPSED_SUBPROCESS_TYPES.has(n.data.elementType) && n.data.isExpanded).sort((a, b) => depthOf(b) - depthOf(a));
|
|
907
1496
|
const subProcessLayouts = /* @__PURE__ */ new Map();
|
|
908
1497
|
const workingMainNodes = [...mainNodes];
|
|
909
1498
|
for (const sp of expandedSubProcesses) {
|
|
@@ -921,15 +1510,30 @@ async function bpmnCustomLayout(nodes, edges) {
|
|
|
921
1510
|
}
|
|
922
1511
|
}
|
|
923
1512
|
const content = workingMainNodes.filter((n) => {
|
|
1513
|
+
if (n.data.elementType === "BoundaryEvent") return false;
|
|
924
1514
|
if (!LAYOUT_CONTAINER_TYPES.has(n.data.elementType)) return true;
|
|
925
1515
|
if (COLLAPSED_SUBPROCESS_TYPES.has(n.data.elementType)) return true;
|
|
926
1516
|
return false;
|
|
927
1517
|
});
|
|
928
1518
|
if (pools.length === 0) {
|
|
929
|
-
const
|
|
930
|
-
const
|
|
931
|
-
const
|
|
932
|
-
|
|
1519
|
+
const isSpChild = (n) => !!n.parentId && subProcessLayouts.has(n.parentId);
|
|
1520
|
+
const freeContent = content.filter((n) => !isSpChild(n));
|
|
1521
|
+
const freeBoundaries = workingMainNodes.filter(
|
|
1522
|
+
(n) => n.data.elementType === "BoundaryEvent" && !isSpChild(n)
|
|
1523
|
+
);
|
|
1524
|
+
const resultNodes2 = layoutVirtualContext([...freeContent, ...freeBoundaries], edges, 0);
|
|
1525
|
+
for (const [, spLayout] of subProcessLayouts) {
|
|
1526
|
+
for (const child of spLayout.children) resultNodes2.push(child);
|
|
1527
|
+
}
|
|
1528
|
+
const contentIds = new Set(freeContent.map((n) => n.id));
|
|
1529
|
+
const seqEdges = extractSeqEdges(edges, contentIds);
|
|
1530
|
+
const backIds = detectBackEdges([...contentIds], seqEdges);
|
|
1531
|
+
const routedEdges2 = routeEdges(edges, resultNodes2, backIds, /* @__PURE__ */ new Set(), /* @__PURE__ */ new Set());
|
|
1532
|
+
const posArtifacts = positionArtifacts(artifacts, resultNodes2, edges, nodes);
|
|
1533
|
+
return {
|
|
1534
|
+
nodes: sortNodesParentFirst([...resultNodes2, ...posArtifacts]),
|
|
1535
|
+
edges: routedEdges2
|
|
1536
|
+
};
|
|
933
1537
|
}
|
|
934
1538
|
const poolIds = new Set(pools.map((p) => p.id));
|
|
935
1539
|
const allLaneIds = new Set(lanes.map((l) => l.id));
|
|
@@ -972,30 +1576,14 @@ async function bpmnCustomLayout(nodes, edges) {
|
|
|
972
1576
|
const layoutted = new Set(resultNodes.map((n) => n.id));
|
|
973
1577
|
const freeNodes = workingMainNodes.filter((n) => !layoutted.has(n.id));
|
|
974
1578
|
if (freeNodes.length > 0) {
|
|
975
|
-
const
|
|
976
|
-
|
|
977
|
-
(e) => freeNodeIds.has(e.source) && freeNodeIds.has(e.target)
|
|
1579
|
+
const freeFlow = freeNodes.filter(
|
|
1580
|
+
(n) => n.data.elementType === "BoundaryEvent" || !LAYOUT_CONTAINER_TYPES.has(n.data.elementType) || COLLAPSED_SUBPROCESS_TYPES.has(n.data.elementType)
|
|
978
1581
|
);
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
const offsetY = stackY;
|
|
983
|
-
for (const node of elkFree.nodes) {
|
|
984
|
-
resultNodes.push({
|
|
985
|
-
...node,
|
|
986
|
-
position: { x: node.position.x, y: node.position.y + offsetY }
|
|
987
|
-
});
|
|
988
|
-
}
|
|
989
|
-
const freeEdgeIds = new Set(freeEdges.map((e) => e.id));
|
|
990
|
-
const elkEdgeMap = new Map(elkFree.edges.map((e) => [e.id, e]));
|
|
991
|
-
for (let i = 0; i < edges.length; i++) {
|
|
992
|
-
if (freeEdgeIds.has(edges[i].id) && elkEdgeMap.has(edges[i].id)) {
|
|
993
|
-
edges[i] = elkEdgeMap.get(edges[i].id);
|
|
994
|
-
}
|
|
995
|
-
}
|
|
996
|
-
} catch {
|
|
997
|
-
for (const node of freeNodes) resultNodes.push(node);
|
|
1582
|
+
const freeRest = freeNodes.filter((n) => !freeFlow.includes(n));
|
|
1583
|
+
for (const node of layoutVirtualContext(freeFlow, edges, stackY)) {
|
|
1584
|
+
resultNodes.push(node);
|
|
998
1585
|
}
|
|
1586
|
+
for (const node of freeRest) resultNodes.push(node);
|
|
999
1587
|
}
|
|
1000
1588
|
const routedEdges = routeEdges(edges, resultNodes, allBackEdgeIds, allLaneIds, poolIds);
|
|
1001
1589
|
const positionedArtifacts = positionArtifacts(artifacts, resultNodes, edges, nodes);
|
|
@@ -1016,6 +1604,6 @@ function applyBpmnLayoutResult(state, result) {
|
|
|
1016
1604
|
return applyLayoutResultToDiagram(state, result);
|
|
1017
1605
|
}
|
|
1018
1606
|
|
|
1019
|
-
export { applyBpmnLayoutResult, bpmnCustomLayout, bpmnDagreLayout };
|
|
1607
|
+
export { applyBpmnLayoutResult, bpmnCustomLayout, bpmnDagreLayout, bpmnElkLayout };
|
|
1020
1608
|
//# sourceMappingURL=index.js.map
|
|
1021
1609
|
//# sourceMappingURL=index.js.map
|