@aranzatech/diagrams-bpmn 0.3.0 → 0.3.2
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-DAGDhO-D.d.cts → catalog-DG-sz0VM.d.cts} +1 -1
- package/dist/{catalog-Q1QmKLDD.d.ts → catalog-DNIyjHbl.d.ts} +1 -1
- package/dist/{chunk-334WN4JZ.js → chunk-NYIYQUGX.js} +104 -23
- package/dist/chunk-NYIYQUGX.js.map +1 -0
- 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 +102 -21
- 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 +1 -1
- package/dist/layout/index.cjs +392 -95
- 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 +392 -95
- package/dist/layout/index.js.map +1 -1
- package/dist/modeling/index.d.cts +4 -4
- package/dist/modeling/index.d.ts +4 -4
- package/dist/{types-CggktCqr.d.cts → types-CDp9kWQ4.d.cts} +2 -2
- package/dist/{types-DmDODKlh.d.ts → types-CuDL2YGL.d.ts} +2 -2
- package/dist/{types-D7zel9dq.d.ts → types-X5FyP8oS.d.ts} +1 -1
- package/dist/{types-BX_o95GC.d.cts → types-dQUuSnV5.d.cts} +1 -1
- package/dist/{types-BYN4Zuee.d.cts → types-nvF59RGF.d.cts} +12 -0
- package/dist/{types-BYN4Zuee.d.ts → types-nvF59RGF.d.ts} +12 -0
- package/dist/validation/index.d.cts +3 -3
- package/dist/validation/index.d.ts +3 -3
- package/dist/xml/index.cjs +102 -21
- 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 +1 -1
- package/package.json +1 -1
- package/dist/chunk-334WN4JZ.js.map +0 -1
package/dist/layout/index.js
CHANGED
|
@@ -249,63 +249,221 @@ function assignRows(nodes, forwardEdges, columns, gatewayPairs) {
|
|
|
249
249
|
|
|
250
250
|
// src/layout/bpmn-custom-layout.ts
|
|
251
251
|
var LANE_LABEL_W = 28;
|
|
252
|
-
var LANE_H_PAD =
|
|
253
|
-
var COL_GAP =
|
|
254
|
-
var ROW_HEIGHT =
|
|
255
|
-
var ROW_GAP =
|
|
256
|
-
var LANE_V_PAD =
|
|
257
|
-
var POOL_H_PAD =
|
|
258
|
-
var POOL_V_GAP =
|
|
259
|
-
var LANE_MIN_H =
|
|
252
|
+
var LANE_H_PAD = 32;
|
|
253
|
+
var COL_GAP = 60;
|
|
254
|
+
var ROW_HEIGHT = 90;
|
|
255
|
+
var ROW_GAP = 50;
|
|
256
|
+
var LANE_V_PAD = 48;
|
|
257
|
+
var POOL_H_PAD = 64;
|
|
258
|
+
var POOL_V_GAP = 48;
|
|
259
|
+
var LANE_MIN_H = 180;
|
|
260
260
|
var POOL_MIN_W = 720;
|
|
261
|
-
var POOL_INNER_PAD =
|
|
261
|
+
var POOL_INNER_PAD = 10;
|
|
262
|
+
var BACK_EDGE_CLEARANCE = 56;
|
|
263
|
+
var LAYOUT_ARTIFACT_TYPES = /* @__PURE__ */ new Set([
|
|
264
|
+
"DataObject",
|
|
265
|
+
"DataObjectReference",
|
|
266
|
+
"DataInput",
|
|
267
|
+
"DataOutput",
|
|
268
|
+
"DataStore",
|
|
269
|
+
"DataStoreReference",
|
|
270
|
+
"Annotation",
|
|
271
|
+
"Group"
|
|
272
|
+
]);
|
|
273
|
+
var COLLAPSED_SUBPROCESS_TYPES = /* @__PURE__ */ new Set([
|
|
274
|
+
"SubProcess",
|
|
275
|
+
"Transaction",
|
|
276
|
+
"EventSubProcess",
|
|
277
|
+
"AdHocSubProcess"
|
|
278
|
+
]);
|
|
279
|
+
var LAYOUT_TASK_TYPES = /* @__PURE__ */ new Set([
|
|
280
|
+
"Task",
|
|
281
|
+
"UserTask",
|
|
282
|
+
"ServiceTask",
|
|
283
|
+
"ScriptTask",
|
|
284
|
+
"ManualTask",
|
|
285
|
+
"BusinessRuleTask",
|
|
286
|
+
"ReceiveTask",
|
|
287
|
+
"SendTask",
|
|
288
|
+
"CallActivity"
|
|
289
|
+
]);
|
|
290
|
+
var TASK_LAYOUT_MIN_W = 130;
|
|
291
|
+
var TASK_LAYOUT_MIN_H = 80;
|
|
262
292
|
function nW(node) {
|
|
263
293
|
return node.width ?? node.measured?.width ?? 120;
|
|
264
294
|
}
|
|
265
295
|
function nH(node) {
|
|
266
296
|
return node.height ?? node.measured?.height ?? 60;
|
|
267
297
|
}
|
|
298
|
+
function layoutW(node) {
|
|
299
|
+
return LAYOUT_TASK_TYPES.has(node.data.elementType) ? Math.max(nW(node), TASK_LAYOUT_MIN_W) : nW(node);
|
|
300
|
+
}
|
|
301
|
+
function layoutH(node) {
|
|
302
|
+
return LAYOUT_TASK_TYPES.has(node.data.elementType) ? Math.max(nH(node), TASK_LAYOUT_MIN_H) : nH(node);
|
|
303
|
+
}
|
|
304
|
+
function applyLayoutMinSize(node) {
|
|
305
|
+
if (!LAYOUT_TASK_TYPES.has(node.data.elementType)) return node;
|
|
306
|
+
const w = layoutW(node);
|
|
307
|
+
const h = layoutH(node);
|
|
308
|
+
if (w === nW(node) && h === nH(node)) return node;
|
|
309
|
+
return { ...node, width: w, height: h, measured: { width: w, height: h } };
|
|
310
|
+
}
|
|
311
|
+
var BOUNDARY_SPACING = 10;
|
|
312
|
+
function repositionBoundaryEvents(boundaryEvents, positionedContent) {
|
|
313
|
+
if (boundaryEvents.length === 0) return [];
|
|
314
|
+
const hostById = new Map(positionedContent.map((n) => [n.id, n]));
|
|
315
|
+
const byHost = /* @__PURE__ */ new Map();
|
|
316
|
+
for (const be of boundaryEvents) {
|
|
317
|
+
const hostId = be.data.attachedToRef;
|
|
318
|
+
if (!hostId) continue;
|
|
319
|
+
if (!byHost.has(hostId)) byHost.set(hostId, []);
|
|
320
|
+
byHost.get(hostId).push(be);
|
|
321
|
+
}
|
|
322
|
+
const result = [];
|
|
323
|
+
for (const be of boundaryEvents) {
|
|
324
|
+
const hostId = be.data.attachedToRef;
|
|
325
|
+
if (!hostId) {
|
|
326
|
+
result.push(be);
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
const host = hostById.get(hostId);
|
|
330
|
+
if (!host) {
|
|
331
|
+
result.push(be);
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
const hostGroup = byHost.get(hostId);
|
|
335
|
+
const siblingIdx = hostGroup.findIndex((n) => n.id === be.id);
|
|
336
|
+
const hostW = layoutW(host);
|
|
337
|
+
const hostH = layoutH(host);
|
|
338
|
+
const beH = nH(be);
|
|
339
|
+
const totalGroupW = hostGroup.reduce((s, b) => s + nW(b), 0) + (hostGroup.length - 1) * BOUNDARY_SPACING;
|
|
340
|
+
const groupStartX = host.position.x + hostW / 2 - totalGroupW / 2;
|
|
341
|
+
const offsetX = hostGroup.slice(0, siblingIdx).reduce((s, b) => s + nW(b) + BOUNDARY_SPACING, 0);
|
|
342
|
+
result.push({
|
|
343
|
+
...be,
|
|
344
|
+
position: {
|
|
345
|
+
x: groupStartX + offsetX,
|
|
346
|
+
y: host.position.y + hostH - beH / 2
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
return result;
|
|
351
|
+
}
|
|
352
|
+
var SP_PAD = 48;
|
|
353
|
+
function layoutSubProcess(children, edges) {
|
|
354
|
+
if (children.length === 0) {
|
|
355
|
+
return { children: [], width: 280, height: 160 };
|
|
356
|
+
}
|
|
357
|
+
const boundaryEvents = children.filter((n) => n.data.elementType === "BoundaryEvent");
|
|
358
|
+
const mainChildren = children.filter((n) => n.data.elementType !== "BoundaryEvent");
|
|
359
|
+
if (mainChildren.length === 0) {
|
|
360
|
+
return {
|
|
361
|
+
children: repositionBoundaryEvents(boundaryEvents, []),
|
|
362
|
+
width: 280,
|
|
363
|
+
height: 160
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
const contentIds = new Set(mainChildren.map((n) => n.id));
|
|
367
|
+
const seqEdges = extractSeqEdges(edges, contentIds);
|
|
368
|
+
const backIds = detectBackEdges([...contentIds], seqEdges);
|
|
369
|
+
const fwdEdges = seqEdges.filter((e) => !backIds.has(e.id));
|
|
370
|
+
const columns = assignColumns([...contentIds], fwdEdges);
|
|
371
|
+
const pairs = detectGatewayPairs(mainChildren, fwdEdges);
|
|
372
|
+
const rows = assignRows(mainChildren, fwdEdges, columns, pairs);
|
|
373
|
+
const maxCol = Math.max(0, ...[...columns.values()]);
|
|
374
|
+
const colW = /* @__PURE__ */ new Map();
|
|
375
|
+
for (let c = 0; c <= maxCol; c++) colW.set(c, 0);
|
|
376
|
+
for (const node of mainChildren) {
|
|
377
|
+
const c = columns.get(node.id) ?? 0;
|
|
378
|
+
colW.set(c, Math.max(colW.get(c) ?? 0, layoutW(node)));
|
|
379
|
+
}
|
|
380
|
+
const colX = /* @__PURE__ */ new Map();
|
|
381
|
+
let cumX = 0;
|
|
382
|
+
for (let c = 0; c <= maxCol; c++) {
|
|
383
|
+
colX.set(c, cumX);
|
|
384
|
+
cumX += (colW.get(c) ?? 120) + COL_GAP;
|
|
385
|
+
}
|
|
386
|
+
const contentW = cumX - COL_GAP;
|
|
387
|
+
const rowVals = [...rows.values()];
|
|
388
|
+
const minRow = Math.min(0, ...rowVals);
|
|
389
|
+
const maxRow = Math.max(0, ...rowVals);
|
|
390
|
+
const rowCount = maxRow - minRow + 1;
|
|
391
|
+
const contentH = rowCount * ROW_HEIGHT + Math.max(0, rowCount - 1) * ROW_GAP;
|
|
392
|
+
const spW = Math.max(280, SP_PAD * 2 + contentW);
|
|
393
|
+
const spH = Math.max(160, SP_PAD * 2 + contentH);
|
|
394
|
+
const positionedChildren = mainChildren.map((node) => {
|
|
395
|
+
const c = columns.get(node.id) ?? 0;
|
|
396
|
+
const r = rows.get(node.id) ?? 0;
|
|
397
|
+
const lw = layoutW(node);
|
|
398
|
+
const lh = layoutH(node);
|
|
399
|
+
const colOffset = (colX.get(c) ?? 0) + (colW.get(c) ?? 120) / 2 - lw / 2;
|
|
400
|
+
const rowOffset = (r - minRow) * (ROW_HEIGHT + ROW_GAP) + ROW_HEIGHT / 2 - lh / 2;
|
|
401
|
+
return applyLayoutMinSize({ ...node, position: { x: SP_PAD + colOffset, y: SP_PAD + rowOffset } });
|
|
402
|
+
});
|
|
403
|
+
const positionedBoundaries = repositionBoundaryEvents(boundaryEvents, positionedChildren);
|
|
404
|
+
return {
|
|
405
|
+
children: [...positionedChildren, ...positionedBoundaries],
|
|
406
|
+
width: spW,
|
|
407
|
+
height: spH
|
|
408
|
+
};
|
|
409
|
+
}
|
|
268
410
|
function layoutPool(pool, lanes, content, allEdges) {
|
|
269
|
-
|
|
411
|
+
const boundaryEvents = content.filter((n) => n.data.elementType === "BoundaryEvent");
|
|
412
|
+
const mainContent = content.filter((n) => n.data.elementType !== "BoundaryEvent");
|
|
413
|
+
if (mainContent.length === 0) {
|
|
414
|
+
const positionedBoundaries2 = repositionBoundaryEvents(boundaryEvents, []);
|
|
270
415
|
if (lanes.length === 0) {
|
|
271
|
-
return { nodes:
|
|
416
|
+
return { nodes: positionedBoundaries2, width: 300, height: 140 };
|
|
272
417
|
}
|
|
273
418
|
const laneH = LANE_MIN_H;
|
|
274
419
|
const h = POOL_INNER_PAD * 2 + lanes.length * laneH + Math.max(0, lanes.length - 1) * POOL_INNER_PAD;
|
|
275
|
-
const w = POOL_MIN_W;
|
|
276
420
|
return {
|
|
277
|
-
nodes:
|
|
278
|
-
...
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
421
|
+
nodes: [
|
|
422
|
+
...positionedBoundaries2,
|
|
423
|
+
...lanes.map((lane, i) => ({
|
|
424
|
+
...lane,
|
|
425
|
+
position: { x: POOL_INNER_PAD, y: POOL_INNER_PAD + i * (laneH + POOL_INNER_PAD) },
|
|
426
|
+
width: POOL_MIN_W - POOL_INNER_PAD * 2,
|
|
427
|
+
height: laneH
|
|
428
|
+
}))
|
|
429
|
+
],
|
|
430
|
+
width: POOL_MIN_W,
|
|
284
431
|
height: h
|
|
285
432
|
};
|
|
286
433
|
}
|
|
287
|
-
const
|
|
434
|
+
const sortedLanes = [...lanes].sort((a, b) => a.position.y - b.position.y);
|
|
435
|
+
const hasLanes = sortedLanes.length > 0;
|
|
436
|
+
const laneIdSet = new Set(sortedLanes.map((l) => l.id));
|
|
437
|
+
const nodeLaneId = /* @__PURE__ */ new Map();
|
|
438
|
+
for (const node of mainContent) {
|
|
439
|
+
const lId = hasLanes && node.parentId && laneIdSet.has(node.parentId) ? node.parentId : "_pool_";
|
|
440
|
+
nodeLaneId.set(node.id, lId);
|
|
441
|
+
}
|
|
442
|
+
const contentIds = new Set(mainContent.map((n) => n.id));
|
|
288
443
|
const seqEdges = extractSeqEdges(allEdges, contentIds);
|
|
289
444
|
const backIds = detectBackEdges([...contentIds], seqEdges);
|
|
290
445
|
const fwdEdges = seqEdges.filter((e) => !backIds.has(e.id));
|
|
291
446
|
const columns = assignColumns([...contentIds], fwdEdges);
|
|
292
|
-
const
|
|
293
|
-
const
|
|
294
|
-
const
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
447
|
+
const rows = /* @__PURE__ */ new Map();
|
|
448
|
+
const contentByLane = /* @__PURE__ */ new Map();
|
|
449
|
+
for (const node of mainContent) {
|
|
450
|
+
const lId = nodeLaneId.get(node.id) ?? "_pool_";
|
|
451
|
+
if (!contentByLane.has(lId)) contentByLane.set(lId, []);
|
|
452
|
+
contentByLane.get(lId).push(node);
|
|
453
|
+
}
|
|
454
|
+
for (const [, laneNodes] of contentByLane) {
|
|
455
|
+
const laneNodeIds = new Set(laneNodes.map((n) => n.id));
|
|
456
|
+
const intraEdges = fwdEdges.filter(
|
|
457
|
+
(e) => laneNodeIds.has(e.source) && laneNodeIds.has(e.target)
|
|
458
|
+
);
|
|
459
|
+
const lanePairs = detectGatewayPairs(laneNodes, intraEdges);
|
|
460
|
+
const laneRows = assignRows(laneNodes, intraEdges, columns, lanePairs);
|
|
461
|
+
for (const [id, row] of laneRows) rows.set(id, row);
|
|
304
462
|
}
|
|
305
463
|
const laneIds = hasLanes ? sortedLanes.map((l) => l.id) : ["_pool_"];
|
|
306
464
|
const laneStats = /* @__PURE__ */ new Map();
|
|
307
465
|
for (const laneId of laneIds) {
|
|
308
|
-
const laneRows =
|
|
466
|
+
const laneRows = mainContent.filter((n) => nodeLaneId.get(n.id) === laneId).map((n) => rows.get(n.id) ?? 0);
|
|
309
467
|
if (laneRows.length === 0) {
|
|
310
468
|
laneStats.set(laneId, { minRow: 0, maxRow: 0, rowCount: 1, height: LANE_MIN_H });
|
|
311
469
|
} else {
|
|
@@ -320,9 +478,9 @@ function layoutPool(pool, lanes, content, allEdges) {
|
|
|
320
478
|
const maxCol = Math.max(0, ...[...columns.values()]);
|
|
321
479
|
const colW = /* @__PURE__ */ new Map();
|
|
322
480
|
for (let c = 0; c <= maxCol; c++) colW.set(c, 0);
|
|
323
|
-
for (const node of
|
|
481
|
+
for (const node of mainContent) {
|
|
324
482
|
const c = columns.get(node.id) ?? 0;
|
|
325
|
-
colW.set(c, Math.max(colW.get(c) ?? 0,
|
|
483
|
+
colW.set(c, Math.max(colW.get(c) ?? 0, layoutW(node)));
|
|
326
484
|
}
|
|
327
485
|
const colX = /* @__PURE__ */ new Map();
|
|
328
486
|
let cumX = 0;
|
|
@@ -343,62 +501,58 @@ function layoutPool(pool, lanes, content, allEdges) {
|
|
|
343
501
|
if (i < laneIds.length - 1) cumY += POOL_INNER_PAD;
|
|
344
502
|
}
|
|
345
503
|
const poolH = cumY + POOL_INNER_PAD;
|
|
346
|
-
const positionedContent =
|
|
504
|
+
const positionedContent = mainContent.map((node) => {
|
|
347
505
|
const c = columns.get(node.id) ?? 0;
|
|
348
506
|
const r = rows.get(node.id) ?? 0;
|
|
349
507
|
const laneId = nodeLaneId.get(node.id) ?? "_pool_";
|
|
350
508
|
const stat = laneStats.get(laneId);
|
|
351
509
|
const lYOff = laneY.get(laneId) ?? 0;
|
|
352
|
-
const
|
|
353
|
-
const
|
|
354
|
-
const
|
|
510
|
+
const lw = layoutW(node);
|
|
511
|
+
const lh = layoutH(node);
|
|
512
|
+
const colOffset = (colX.get(c) ?? 0) + (colW.get(c) ?? 120) / 2 - lw / 2;
|
|
513
|
+
const rowOffset = (r - stat.minRow) * (ROW_HEIGHT + ROW_GAP) + ROW_HEIGHT / 2 - lh / 2;
|
|
355
514
|
const contentH_stat = stat.rowCount * ROW_HEIGHT + Math.max(0, stat.rowCount - 1) * ROW_GAP;
|
|
356
515
|
const vertTopOffset = Math.max(LANE_V_PAD, (stat.height - contentH_stat) / 2);
|
|
516
|
+
const isLaneChild = hasLanes && !!node.parentId && node.parentId !== pool.id;
|
|
357
517
|
const x = isLaneChild ? LANE_LABEL_W + LANE_H_PAD + colOffset : POOL_H_PAD + colOffset;
|
|
358
518
|
const y = isLaneChild ? vertTopOffset + rowOffset : lYOff + vertTopOffset + rowOffset;
|
|
359
|
-
return { ...node, position: { x, y } };
|
|
519
|
+
return applyLayoutMinSize({ ...node, position: { x, y } });
|
|
360
520
|
});
|
|
361
|
-
const NODE_MIN_GAP =
|
|
521
|
+
const NODE_MIN_GAP = 24;
|
|
362
522
|
const resolvedContent = [...positionedContent];
|
|
363
523
|
for (const laneId of laneIds) {
|
|
364
524
|
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);
|
|
365
525
|
for (let k = 1; k < laneNodeIndices.length; k++) {
|
|
366
526
|
const prev = resolvedContent[laneNodeIndices[k - 1].i];
|
|
367
527
|
const curr = resolvedContent[laneNodeIndices[k].i];
|
|
368
|
-
const prevBottom = prev.position.y +
|
|
528
|
+
const prevBottom = prev.position.y + layoutH(prev);
|
|
369
529
|
const currTop = curr.position.y;
|
|
370
530
|
const prevTop = prev.position.y;
|
|
371
|
-
const currBottom = curr.position.y +
|
|
531
|
+
const currBottom = curr.position.y + layoutH(curr);
|
|
372
532
|
const yOverlap = prevBottom + NODE_MIN_GAP > currTop && currBottom + NODE_MIN_GAP > prevTop;
|
|
373
533
|
if (!yOverlap) continue;
|
|
374
|
-
const prevRight = prev.position.x +
|
|
534
|
+
const prevRight = prev.position.x + layoutW(prev);
|
|
375
535
|
if (prevRight + NODE_MIN_GAP > curr.position.x) {
|
|
376
536
|
resolvedContent[laneNodeIndices[k].i] = {
|
|
377
537
|
...curr,
|
|
378
|
-
position: {
|
|
379
|
-
x: prevRight + NODE_MIN_GAP,
|
|
380
|
-
y: curr.position.y
|
|
381
|
-
}
|
|
538
|
+
position: { x: prevRight + NODE_MIN_GAP, y: curr.position.y }
|
|
382
539
|
};
|
|
383
540
|
}
|
|
384
541
|
}
|
|
385
542
|
}
|
|
543
|
+
const positionedBoundaries = repositionBoundaryEvents(boundaryEvents, resolvedContent);
|
|
386
544
|
const positionedLanes = hasLanes ? sortedLanes.map((lane) => ({
|
|
387
545
|
...lane,
|
|
388
|
-
// x: after pool label strip + left inner padding
|
|
389
|
-
// y: laneY already includes top POOL_INNER_PAD offset
|
|
390
546
|
position: { x: POOL_INNER_PAD, y: laneY.get(lane.id) ?? POOL_INNER_PAD },
|
|
391
547
|
width: laneW,
|
|
392
548
|
height: laneStats.get(lane.id)?.height ?? LANE_MIN_H
|
|
393
549
|
})) : [];
|
|
394
550
|
return {
|
|
395
|
-
nodes: [...resolvedContent, ...positionedLanes],
|
|
551
|
+
nodes: [...resolvedContent, ...positionedBoundaries, ...positionedLanes],
|
|
396
552
|
width: poolW,
|
|
397
553
|
height: poolH
|
|
398
554
|
};
|
|
399
555
|
}
|
|
400
|
-
var BACK_EDGE_CLEARANCE = 50;
|
|
401
|
-
var SAME_ROW_THRESHOLD = 15;
|
|
402
556
|
function absolutePos(nodeId, byId, cache) {
|
|
403
557
|
const cached = cache.get(nodeId);
|
|
404
558
|
if (cached) return cached;
|
|
@@ -417,10 +571,22 @@ function absolutePos(nodeId, byId, cache) {
|
|
|
417
571
|
function laneOf(node, laneIds) {
|
|
418
572
|
return node.parentId && laneIds.has(node.parentId) ? node.parentId : void 0;
|
|
419
573
|
}
|
|
574
|
+
function gapMidX(sAbs, sW, tAbs, tW) {
|
|
575
|
+
const leftRightEdge = Math.min(sAbs.x + sW, tAbs.x + tW);
|
|
576
|
+
const rightLeftEdge = Math.max(sAbs.x, tAbs.x);
|
|
577
|
+
return leftRightEdge < rightLeftEdge ? (leftRightEdge + rightLeftEdge) / 2 : sAbs.x + sW / 2;
|
|
578
|
+
}
|
|
579
|
+
function routeMidX(sAbs, sW, tAbs, tW) {
|
|
580
|
+
const leftEdge = Math.min(sAbs.x + sW, tAbs.x + tW);
|
|
581
|
+
const rightEdge = Math.max(sAbs.x, tAbs.x);
|
|
582
|
+
return leftEdge < rightEdge ? leftEdge + (rightEdge - leftEdge) * 0.35 : sAbs.x + sW / 2;
|
|
583
|
+
}
|
|
584
|
+
var SAME_ROW_THRESHOLD = 15;
|
|
420
585
|
function routeEdges(edges, layoutNodes, backEdgeIds, laneIds, poolIds) {
|
|
421
586
|
const byId = new Map(layoutNodes.map((n) => [n.id, n]));
|
|
422
587
|
const cache = /* @__PURE__ */ new Map();
|
|
423
588
|
const abs = (id) => absolutePos(id, byId, cache);
|
|
589
|
+
const sortedLanes = [...laneIds].map((id) => byId.get(id)).filter((n) => !!n).sort((a, b) => abs(a.id).y - abs(b.id).y);
|
|
424
590
|
return edges.map((edge) => {
|
|
425
591
|
const edgeType = edge.data?.edgeType ?? edge.type;
|
|
426
592
|
if (edgeType !== "sequenceFlow") {
|
|
@@ -435,11 +601,22 @@ function routeEdges(edges, layoutNodes, backEdgeIds, laneIds, poolIds) {
|
|
|
435
601
|
const tAbs = abs(tgt.id);
|
|
436
602
|
const sW = nW(src), sH = nH(src);
|
|
437
603
|
const tW = nW(tgt), tH = nH(tgt);
|
|
438
|
-
const sCX = sAbs.x + sW / 2
|
|
439
|
-
const tCX = tAbs.x + tW / 2
|
|
440
|
-
const
|
|
441
|
-
const
|
|
442
|
-
|
|
604
|
+
const sCX = sAbs.x + sW / 2;
|
|
605
|
+
const tCX = tAbs.x + tW / 2;
|
|
606
|
+
const sCY = sAbs.y + sH / 2;
|
|
607
|
+
const tCY = tAbs.y + tH / 2;
|
|
608
|
+
const getPool = (nodeId) => {
|
|
609
|
+
const node = byId.get(nodeId);
|
|
610
|
+
if (!node) return null;
|
|
611
|
+
if (poolIds.has(nodeId)) return nodeId;
|
|
612
|
+
if (node.parentId && poolIds.has(node.parentId)) return node.parentId;
|
|
613
|
+
if (node.parentId) {
|
|
614
|
+
const gp = byId.get(node.parentId)?.parentId ?? null;
|
|
615
|
+
if (gp && poolIds.has(gp)) return gp;
|
|
616
|
+
}
|
|
617
|
+
return node.parentId ?? null;
|
|
618
|
+
};
|
|
619
|
+
if (getPool(edge.source) !== getPool(edge.target)) {
|
|
443
620
|
const d = { ...edge.data };
|
|
444
621
|
delete d.routingPoints;
|
|
445
622
|
return { ...edge, data: d };
|
|
@@ -449,33 +626,49 @@ function routeEdges(edges, layoutNodes, backEdgeIds, laneIds, poolIds) {
|
|
|
449
626
|
const topY = Math.min(sAbs.y, tAbs.y) - BACK_EDGE_CLEARANCE;
|
|
450
627
|
routingPoints = [
|
|
451
628
|
{ x: sCX, y: sAbs.y },
|
|
452
|
-
// [0] discarded
|
|
453
629
|
{ x: sCX, y: topY },
|
|
454
|
-
// [1] go up
|
|
455
630
|
{ x: tCX, y: topY },
|
|
456
|
-
|
|
457
|
-
{ x: tCX, y: tAbs.y }
|
|
458
|
-
// [3] discarded
|
|
631
|
+
{ x: tCX, y: tAbs.y + tH }
|
|
459
632
|
];
|
|
460
633
|
} else if (laneOf(src, laneIds) !== laneOf(tgt, laneIds)) {
|
|
461
|
-
const goingDown = tAbs.y > sAbs.y;
|
|
462
|
-
const sharedX = Math.abs(sCX - tCX) < 10 ? sCX : (sCX + tCX) / 2;
|
|
463
634
|
const srcLane = byId.get(src.parentId ?? "");
|
|
464
635
|
const tgtLane = byId.get(tgt.parentId ?? "");
|
|
465
636
|
if (srcLane && tgtLane && laneIds.has(srcLane.id) && laneIds.has(tgtLane.id)) {
|
|
466
|
-
const
|
|
467
|
-
const
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
{ x: sharedX, y:
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
637
|
+
const goingDown = tAbs.y > sAbs.y;
|
|
638
|
+
const sharedX = gapMidX(sAbs, sW, tAbs, tW);
|
|
639
|
+
const srcLaneIdx = sortedLanes.findIndex((l) => l.id === srcLane.id);
|
|
640
|
+
const tgtLaneIdx = sortedLanes.findIndex((l) => l.id === tgtLane.id);
|
|
641
|
+
const pts = [];
|
|
642
|
+
if (goingDown) {
|
|
643
|
+
pts.push({ x: sCX, y: sAbs.y + sH });
|
|
644
|
+
pts.push({ x: sharedX, y: sAbs.y + sH });
|
|
645
|
+
const fromIdx = Math.min(srcLaneIdx, tgtLaneIdx);
|
|
646
|
+
const toIdx = Math.max(srcLaneIdx, tgtLaneIdx);
|
|
647
|
+
for (let i = fromIdx; i < toIdx; i++) {
|
|
648
|
+
const lane = sortedLanes[i];
|
|
649
|
+
const laneBot = abs(lane.id).y + (lane.height ?? LANE_MIN_H);
|
|
650
|
+
pts.push({ x: sharedX, y: laneBot });
|
|
651
|
+
}
|
|
652
|
+
const lastY = pts[pts.length - 1].y;
|
|
653
|
+
pts.push({ x: tCX, y: lastY });
|
|
654
|
+
pts.push({ x: tCX, y: tAbs.y + tH });
|
|
655
|
+
} else {
|
|
656
|
+
pts.push({ x: sCX, y: sAbs.y });
|
|
657
|
+
pts.push({ x: sharedX, y: sAbs.y });
|
|
658
|
+
const fromIdx = Math.min(srcLaneIdx, tgtLaneIdx);
|
|
659
|
+
const toIdx = Math.max(srcLaneIdx, tgtLaneIdx);
|
|
660
|
+
for (let i = toIdx; i > fromIdx; i--) {
|
|
661
|
+
const lane = sortedLanes[i];
|
|
662
|
+
const laneTop = abs(lane.id).y;
|
|
663
|
+
pts.push({ x: sharedX, y: laneTop });
|
|
664
|
+
}
|
|
665
|
+
const lastY = pts[pts.length - 1].y;
|
|
666
|
+
pts.push({ x: tCX, y: lastY });
|
|
667
|
+
pts.push({ x: tCX, y: tAbs.y });
|
|
668
|
+
}
|
|
669
|
+
routingPoints = pts;
|
|
478
670
|
} else {
|
|
671
|
+
const sharedX = gapMidX(sAbs, sW, tAbs, tW);
|
|
479
672
|
routingPoints = [
|
|
480
673
|
{ x: sCX, y: sCY },
|
|
481
674
|
{ x: sharedX, y: sCY },
|
|
@@ -494,39 +687,108 @@ function routeEdges(edges, layoutNodes, backEdgeIds, laneIds, poolIds) {
|
|
|
494
687
|
if (exitsTop || exitsBottom) {
|
|
495
688
|
routingPoints = [
|
|
496
689
|
{ x: sCX, y: exitsTop ? sAbs.y : sAbs.y + sH },
|
|
497
|
-
// [0] discarded
|
|
498
690
|
{ x: sCX, y: tCY },
|
|
499
|
-
// [1] vertical to target row
|
|
500
691
|
{ x: tCX, y: tCY },
|
|
501
|
-
// [2] horizontal to target
|
|
502
692
|
{ x: tCX, y: exitsTop ? tAbs.y + tH : tAbs.y }
|
|
503
|
-
// [3] discarded
|
|
504
693
|
];
|
|
505
694
|
} else {
|
|
506
|
-
const
|
|
507
|
-
const midX = goingRight ? sAbs.x + sW + COL_GAP / 2 : sAbs.x - COL_GAP / 2;
|
|
695
|
+
const midX = routeMidX(sAbs, sW, tAbs, tW);
|
|
508
696
|
routingPoints = [
|
|
509
697
|
{ x: sAbs.x + sW, y: sCY },
|
|
510
|
-
// [0] discarded
|
|
511
698
|
{ x: midX, y: sCY },
|
|
512
|
-
// [1] horizontal exit
|
|
513
699
|
{ x: midX, y: tCY },
|
|
514
|
-
// [2] vertical to target row
|
|
515
700
|
{ x: tAbs.x, y: tCY }
|
|
516
|
-
// [3] discarded
|
|
517
701
|
];
|
|
518
702
|
}
|
|
519
703
|
}
|
|
520
704
|
return { ...edge, data: { ...edge.data, routingPoints } };
|
|
521
705
|
});
|
|
522
706
|
}
|
|
707
|
+
var ARTIFACT_ABOVE_GAP = 16;
|
|
708
|
+
var ARTIFACT_H_SPACING = 12;
|
|
709
|
+
function positionArtifacts(artifacts, resultNodes, edges) {
|
|
710
|
+
if (artifacts.length === 0) return [];
|
|
711
|
+
const byId = new Map(resultNodes.map((n) => [n.id, n]));
|
|
712
|
+
const cache = /* @__PURE__ */ new Map();
|
|
713
|
+
const absPos = (id) => absolutePos(id, byId, cache);
|
|
714
|
+
const artifactsByNode = /* @__PURE__ */ new Map();
|
|
715
|
+
const ungrouped = [];
|
|
716
|
+
for (const artifact of artifacts) {
|
|
717
|
+
if (artifact.data.elementType === "Group") {
|
|
718
|
+
ungrouped.push(artifact);
|
|
719
|
+
continue;
|
|
720
|
+
}
|
|
721
|
+
const connEdge = edges.find((e) => {
|
|
722
|
+
const t = e.data?.edgeType ?? e.type;
|
|
723
|
+
return (t === "association" || t === "dataAssociation") && (e.source === artifact.id || e.target === artifact.id);
|
|
724
|
+
});
|
|
725
|
+
if (!connEdge) {
|
|
726
|
+
ungrouped.push(artifact);
|
|
727
|
+
continue;
|
|
728
|
+
}
|
|
729
|
+
const connId = connEdge.source === artifact.id ? connEdge.target : connEdge.source;
|
|
730
|
+
if (!byId.has(connId)) {
|
|
731
|
+
ungrouped.push(artifact);
|
|
732
|
+
continue;
|
|
733
|
+
}
|
|
734
|
+
if (!artifactsByNode.has(connId)) artifactsByNode.set(connId, []);
|
|
735
|
+
artifactsByNode.get(connId).push(artifact);
|
|
736
|
+
}
|
|
737
|
+
const positioned = [...ungrouped];
|
|
738
|
+
for (const [connId, arts] of artifactsByNode) {
|
|
739
|
+
const connNode = byId.get(connId);
|
|
740
|
+
const connAbsP = absPos(connId);
|
|
741
|
+
const totalW = arts.reduce((s, a) => s + nW(a), 0) + (arts.length - 1) * ARTIFACT_H_SPACING;
|
|
742
|
+
const desiredAbsY = connAbsP.y - ARTIFACT_ABOVE_GAP - Math.max(...arts.map(nH));
|
|
743
|
+
let desiredAbsX = connAbsP.x + nW(connNode) / 2 - totalW / 2;
|
|
744
|
+
for (const artifact of arts) {
|
|
745
|
+
const parentAbsP = artifact.parentId ? absPos(artifact.parentId) : { x: 0, y: 0 };
|
|
746
|
+
positioned.push({
|
|
747
|
+
...artifact,
|
|
748
|
+
position: {
|
|
749
|
+
x: desiredAbsX - parentAbsP.x,
|
|
750
|
+
y: desiredAbsY - parentAbsP.y
|
|
751
|
+
}
|
|
752
|
+
});
|
|
753
|
+
desiredAbsX += nW(artifact) + ARTIFACT_H_SPACING;
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
return positioned;
|
|
757
|
+
}
|
|
523
758
|
async function bpmnCustomLayout(nodes, edges) {
|
|
524
|
-
const
|
|
525
|
-
const
|
|
526
|
-
const
|
|
759
|
+
const artifacts = nodes.filter((n) => LAYOUT_ARTIFACT_TYPES.has(n.data.elementType));
|
|
760
|
+
const mainNodes = nodes.filter((n) => !LAYOUT_ARTIFACT_TYPES.has(n.data.elementType));
|
|
761
|
+
const pools = mainNodes.filter((n) => n.data.elementType === "Pool");
|
|
762
|
+
const lanes = mainNodes.filter((n) => n.data.elementType === "Lane");
|
|
763
|
+
const expandedSubProcesses = mainNodes.filter(
|
|
764
|
+
(n) => COLLAPSED_SUBPROCESS_TYPES.has(n.data.elementType) && n.data.isExpanded
|
|
765
|
+
);
|
|
766
|
+
const subProcessLayouts = /* @__PURE__ */ new Map();
|
|
767
|
+
const workingMainNodes = [...mainNodes];
|
|
768
|
+
for (const sp of expandedSubProcesses) {
|
|
769
|
+
const spChildren = workingMainNodes.filter((n) => n.parentId === sp.id);
|
|
770
|
+
const result = layoutSubProcess(spChildren, edges);
|
|
771
|
+
subProcessLayouts.set(sp.id, result);
|
|
772
|
+
const spIdx = workingMainNodes.findIndex((n) => n.id === sp.id);
|
|
773
|
+
if (spIdx >= 0) {
|
|
774
|
+
workingMainNodes[spIdx] = {
|
|
775
|
+
...workingMainNodes[spIdx],
|
|
776
|
+
width: result.width,
|
|
777
|
+
height: result.height,
|
|
778
|
+
measured: { width: result.width, height: result.height }
|
|
779
|
+
};
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
const content = workingMainNodes.filter((n) => {
|
|
783
|
+
if (!LAYOUT_CONTAINER_TYPES.has(n.data.elementType)) return true;
|
|
784
|
+
if (COLLAPSED_SUBPROCESS_TYPES.has(n.data.elementType)) return true;
|
|
785
|
+
return false;
|
|
786
|
+
});
|
|
527
787
|
if (pools.length === 0) {
|
|
528
788
|
const { bpmnElkLayout: bpmnElkLayout2 } = await import('../elk-QT7H4252.js');
|
|
529
|
-
|
|
789
|
+
const elkResult = await bpmnElkLayout2(nodes.filter((n) => !LAYOUT_ARTIFACT_TYPES.has(n.data.elementType)), edges);
|
|
790
|
+
const posArtifacts = positionArtifacts(artifacts, elkResult.nodes, edges);
|
|
791
|
+
return { nodes: [...elkResult.nodes, ...posArtifacts], edges: elkResult.edges };
|
|
530
792
|
}
|
|
531
793
|
const poolIds = new Set(pools.map((p) => p.id));
|
|
532
794
|
const allLaneIds = new Set(lanes.map((l) => l.id));
|
|
@@ -546,7 +808,10 @@ async function bpmnCustomLayout(nodes, edges) {
|
|
|
546
808
|
const poolContent = content.filter(
|
|
547
809
|
(n) => n.parentId === pool.id || n.parentId != null && laneIds.has(n.parentId)
|
|
548
810
|
);
|
|
549
|
-
const
|
|
811
|
+
const poolBoundaries = workingMainNodes.filter(
|
|
812
|
+
(n) => n.data.elementType === "BoundaryEvent" && (n.parentId === pool.id || n.parentId != null && laneIds.has(n.parentId))
|
|
813
|
+
);
|
|
814
|
+
const result = layoutPool(pool, poolLanes, [...poolContent, ...poolBoundaries], edges);
|
|
550
815
|
resultNodes.push({
|
|
551
816
|
...pool,
|
|
552
817
|
position: { x: 0, y: stackY },
|
|
@@ -558,12 +823,44 @@ async function bpmnCustomLayout(nodes, edges) {
|
|
|
558
823
|
}
|
|
559
824
|
stackY += result.height + POOL_V_GAP;
|
|
560
825
|
}
|
|
826
|
+
for (const [, spLayout] of subProcessLayouts) {
|
|
827
|
+
for (const child of spLayout.children) {
|
|
828
|
+
resultNodes.push(child);
|
|
829
|
+
}
|
|
830
|
+
}
|
|
561
831
|
const layoutted = new Set(resultNodes.map((n) => n.id));
|
|
562
|
-
|
|
563
|
-
|
|
832
|
+
const freeNodes = workingMainNodes.filter((n) => !layoutted.has(n.id));
|
|
833
|
+
if (freeNodes.length > 0) {
|
|
834
|
+
const freeEdges = edges.filter(
|
|
835
|
+
(e) => freeNodes.some((n) => n.id === e.source || n.id === e.target)
|
|
836
|
+
);
|
|
837
|
+
try {
|
|
838
|
+
const { bpmnElkLayout: bpmnElkLayout2 } = await import('../elk-QT7H4252.js');
|
|
839
|
+
const elkFree = await bpmnElkLayout2(freeNodes, freeEdges);
|
|
840
|
+
const offsetY = stackY;
|
|
841
|
+
for (const node of elkFree.nodes) {
|
|
842
|
+
resultNodes.push({
|
|
843
|
+
...node,
|
|
844
|
+
position: { x: node.position.x, y: node.position.y + offsetY }
|
|
845
|
+
});
|
|
846
|
+
}
|
|
847
|
+
const freeEdgeIds = new Set(freeEdges.map((e) => e.id));
|
|
848
|
+
const elkEdgeMap = new Map(elkFree.edges.map((e) => [e.id, e]));
|
|
849
|
+
for (let i = 0; i < edges.length; i++) {
|
|
850
|
+
if (freeEdgeIds.has(edges[i].id) && elkEdgeMap.has(edges[i].id)) {
|
|
851
|
+
edges[i] = elkEdgeMap.get(edges[i].id);
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
} catch {
|
|
855
|
+
for (const node of freeNodes) resultNodes.push(node);
|
|
856
|
+
}
|
|
564
857
|
}
|
|
565
858
|
const routedEdges = routeEdges(edges, resultNodes, allBackEdgeIds, allLaneIds, poolIds);
|
|
566
|
-
|
|
859
|
+
const positionedArtifacts = positionArtifacts(artifacts, resultNodes, edges);
|
|
860
|
+
return {
|
|
861
|
+
nodes: [...resultNodes, ...positionedArtifacts],
|
|
862
|
+
edges: routedEdges
|
|
863
|
+
};
|
|
567
864
|
}
|
|
568
865
|
|
|
569
866
|
// src/layout/index.ts
|