@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.cjs
CHANGED
|
@@ -1311,63 +1311,221 @@ function assignRows(nodes, forwardEdges, columns, gatewayPairs) {
|
|
|
1311
1311
|
|
|
1312
1312
|
// src/layout/bpmn-custom-layout.ts
|
|
1313
1313
|
var LANE_LABEL_W = 28;
|
|
1314
|
-
var LANE_H_PAD =
|
|
1315
|
-
var COL_GAP =
|
|
1316
|
-
var ROW_HEIGHT =
|
|
1317
|
-
var ROW_GAP =
|
|
1318
|
-
var LANE_V_PAD =
|
|
1319
|
-
var POOL_H_PAD =
|
|
1320
|
-
var POOL_V_GAP =
|
|
1321
|
-
var LANE_MIN_H =
|
|
1314
|
+
var LANE_H_PAD = 32;
|
|
1315
|
+
var COL_GAP = 60;
|
|
1316
|
+
var ROW_HEIGHT = 90;
|
|
1317
|
+
var ROW_GAP = 50;
|
|
1318
|
+
var LANE_V_PAD = 48;
|
|
1319
|
+
var POOL_H_PAD = 64;
|
|
1320
|
+
var POOL_V_GAP = 48;
|
|
1321
|
+
var LANE_MIN_H = 180;
|
|
1322
1322
|
var POOL_MIN_W = 720;
|
|
1323
|
-
var POOL_INNER_PAD =
|
|
1323
|
+
var POOL_INNER_PAD = 10;
|
|
1324
|
+
var BACK_EDGE_CLEARANCE = 56;
|
|
1325
|
+
var LAYOUT_ARTIFACT_TYPES = /* @__PURE__ */ new Set([
|
|
1326
|
+
"DataObject",
|
|
1327
|
+
"DataObjectReference",
|
|
1328
|
+
"DataInput",
|
|
1329
|
+
"DataOutput",
|
|
1330
|
+
"DataStore",
|
|
1331
|
+
"DataStoreReference",
|
|
1332
|
+
"Annotation",
|
|
1333
|
+
"Group"
|
|
1334
|
+
]);
|
|
1335
|
+
var COLLAPSED_SUBPROCESS_TYPES = /* @__PURE__ */ new Set([
|
|
1336
|
+
"SubProcess",
|
|
1337
|
+
"Transaction",
|
|
1338
|
+
"EventSubProcess",
|
|
1339
|
+
"AdHocSubProcess"
|
|
1340
|
+
]);
|
|
1341
|
+
var LAYOUT_TASK_TYPES = /* @__PURE__ */ new Set([
|
|
1342
|
+
"Task",
|
|
1343
|
+
"UserTask",
|
|
1344
|
+
"ServiceTask",
|
|
1345
|
+
"ScriptTask",
|
|
1346
|
+
"ManualTask",
|
|
1347
|
+
"BusinessRuleTask",
|
|
1348
|
+
"ReceiveTask",
|
|
1349
|
+
"SendTask",
|
|
1350
|
+
"CallActivity"
|
|
1351
|
+
]);
|
|
1352
|
+
var TASK_LAYOUT_MIN_W = 130;
|
|
1353
|
+
var TASK_LAYOUT_MIN_H = 80;
|
|
1324
1354
|
function nW(node) {
|
|
1325
1355
|
return node.width ?? node.measured?.width ?? 120;
|
|
1326
1356
|
}
|
|
1327
1357
|
function nH(node) {
|
|
1328
1358
|
return node.height ?? node.measured?.height ?? 60;
|
|
1329
1359
|
}
|
|
1360
|
+
function layoutW(node) {
|
|
1361
|
+
return LAYOUT_TASK_TYPES.has(node.data.elementType) ? Math.max(nW(node), TASK_LAYOUT_MIN_W) : nW(node);
|
|
1362
|
+
}
|
|
1363
|
+
function layoutH(node) {
|
|
1364
|
+
return LAYOUT_TASK_TYPES.has(node.data.elementType) ? Math.max(nH(node), TASK_LAYOUT_MIN_H) : nH(node);
|
|
1365
|
+
}
|
|
1366
|
+
function applyLayoutMinSize(node) {
|
|
1367
|
+
if (!LAYOUT_TASK_TYPES.has(node.data.elementType)) return node;
|
|
1368
|
+
const w = layoutW(node);
|
|
1369
|
+
const h = layoutH(node);
|
|
1370
|
+
if (w === nW(node) && h === nH(node)) return node;
|
|
1371
|
+
return { ...node, width: w, height: h, measured: { width: w, height: h } };
|
|
1372
|
+
}
|
|
1373
|
+
var BOUNDARY_SPACING = 10;
|
|
1374
|
+
function repositionBoundaryEvents(boundaryEvents, positionedContent) {
|
|
1375
|
+
if (boundaryEvents.length === 0) return [];
|
|
1376
|
+
const hostById = new Map(positionedContent.map((n) => [n.id, n]));
|
|
1377
|
+
const byHost = /* @__PURE__ */ new Map();
|
|
1378
|
+
for (const be of boundaryEvents) {
|
|
1379
|
+
const hostId = be.data.attachedToRef;
|
|
1380
|
+
if (!hostId) continue;
|
|
1381
|
+
if (!byHost.has(hostId)) byHost.set(hostId, []);
|
|
1382
|
+
byHost.get(hostId).push(be);
|
|
1383
|
+
}
|
|
1384
|
+
const result = [];
|
|
1385
|
+
for (const be of boundaryEvents) {
|
|
1386
|
+
const hostId = be.data.attachedToRef;
|
|
1387
|
+
if (!hostId) {
|
|
1388
|
+
result.push(be);
|
|
1389
|
+
continue;
|
|
1390
|
+
}
|
|
1391
|
+
const host = hostById.get(hostId);
|
|
1392
|
+
if (!host) {
|
|
1393
|
+
result.push(be);
|
|
1394
|
+
continue;
|
|
1395
|
+
}
|
|
1396
|
+
const hostGroup = byHost.get(hostId);
|
|
1397
|
+
const siblingIdx = hostGroup.findIndex((n) => n.id === be.id);
|
|
1398
|
+
const hostW = layoutW(host);
|
|
1399
|
+
const hostH = layoutH(host);
|
|
1400
|
+
const beH = nH(be);
|
|
1401
|
+
const totalGroupW = hostGroup.reduce((s, b) => s + nW(b), 0) + (hostGroup.length - 1) * BOUNDARY_SPACING;
|
|
1402
|
+
const groupStartX = host.position.x + hostW / 2 - totalGroupW / 2;
|
|
1403
|
+
const offsetX = hostGroup.slice(0, siblingIdx).reduce((s, b) => s + nW(b) + BOUNDARY_SPACING, 0);
|
|
1404
|
+
result.push({
|
|
1405
|
+
...be,
|
|
1406
|
+
position: {
|
|
1407
|
+
x: groupStartX + offsetX,
|
|
1408
|
+
y: host.position.y + hostH - beH / 2
|
|
1409
|
+
}
|
|
1410
|
+
});
|
|
1411
|
+
}
|
|
1412
|
+
return result;
|
|
1413
|
+
}
|
|
1414
|
+
var SP_PAD = 48;
|
|
1415
|
+
function layoutSubProcess(children, edges) {
|
|
1416
|
+
if (children.length === 0) {
|
|
1417
|
+
return { children: [], width: 280, height: 160 };
|
|
1418
|
+
}
|
|
1419
|
+
const boundaryEvents = children.filter((n) => n.data.elementType === "BoundaryEvent");
|
|
1420
|
+
const mainChildren = children.filter((n) => n.data.elementType !== "BoundaryEvent");
|
|
1421
|
+
if (mainChildren.length === 0) {
|
|
1422
|
+
return {
|
|
1423
|
+
children: repositionBoundaryEvents(boundaryEvents, []),
|
|
1424
|
+
width: 280,
|
|
1425
|
+
height: 160
|
|
1426
|
+
};
|
|
1427
|
+
}
|
|
1428
|
+
const contentIds = new Set(mainChildren.map((n) => n.id));
|
|
1429
|
+
const seqEdges = extractSeqEdges(edges, contentIds);
|
|
1430
|
+
const backIds = detectBackEdges([...contentIds], seqEdges);
|
|
1431
|
+
const fwdEdges = seqEdges.filter((e) => !backIds.has(e.id));
|
|
1432
|
+
const columns = assignColumns([...contentIds], fwdEdges);
|
|
1433
|
+
const pairs = detectGatewayPairs(mainChildren, fwdEdges);
|
|
1434
|
+
const rows = assignRows(mainChildren, fwdEdges, columns, pairs);
|
|
1435
|
+
const maxCol = Math.max(0, ...[...columns.values()]);
|
|
1436
|
+
const colW = /* @__PURE__ */ new Map();
|
|
1437
|
+
for (let c = 0; c <= maxCol; c++) colW.set(c, 0);
|
|
1438
|
+
for (const node of mainChildren) {
|
|
1439
|
+
const c = columns.get(node.id) ?? 0;
|
|
1440
|
+
colW.set(c, Math.max(colW.get(c) ?? 0, layoutW(node)));
|
|
1441
|
+
}
|
|
1442
|
+
const colX = /* @__PURE__ */ new Map();
|
|
1443
|
+
let cumX = 0;
|
|
1444
|
+
for (let c = 0; c <= maxCol; c++) {
|
|
1445
|
+
colX.set(c, cumX);
|
|
1446
|
+
cumX += (colW.get(c) ?? 120) + COL_GAP;
|
|
1447
|
+
}
|
|
1448
|
+
const contentW = cumX - COL_GAP;
|
|
1449
|
+
const rowVals = [...rows.values()];
|
|
1450
|
+
const minRow = Math.min(0, ...rowVals);
|
|
1451
|
+
const maxRow = Math.max(0, ...rowVals);
|
|
1452
|
+
const rowCount = maxRow - minRow + 1;
|
|
1453
|
+
const contentH = rowCount * ROW_HEIGHT + Math.max(0, rowCount - 1) * ROW_GAP;
|
|
1454
|
+
const spW = Math.max(280, SP_PAD * 2 + contentW);
|
|
1455
|
+
const spH = Math.max(160, SP_PAD * 2 + contentH);
|
|
1456
|
+
const positionedChildren = mainChildren.map((node) => {
|
|
1457
|
+
const c = columns.get(node.id) ?? 0;
|
|
1458
|
+
const r = rows.get(node.id) ?? 0;
|
|
1459
|
+
const lw = layoutW(node);
|
|
1460
|
+
const lh = layoutH(node);
|
|
1461
|
+
const colOffset = (colX.get(c) ?? 0) + (colW.get(c) ?? 120) / 2 - lw / 2;
|
|
1462
|
+
const rowOffset = (r - minRow) * (ROW_HEIGHT + ROW_GAP) + ROW_HEIGHT / 2 - lh / 2;
|
|
1463
|
+
return applyLayoutMinSize({ ...node, position: { x: SP_PAD + colOffset, y: SP_PAD + rowOffset } });
|
|
1464
|
+
});
|
|
1465
|
+
const positionedBoundaries = repositionBoundaryEvents(boundaryEvents, positionedChildren);
|
|
1466
|
+
return {
|
|
1467
|
+
children: [...positionedChildren, ...positionedBoundaries],
|
|
1468
|
+
width: spW,
|
|
1469
|
+
height: spH
|
|
1470
|
+
};
|
|
1471
|
+
}
|
|
1330
1472
|
function layoutPool(pool, lanes, content, allEdges) {
|
|
1331
|
-
|
|
1473
|
+
const boundaryEvents = content.filter((n) => n.data.elementType === "BoundaryEvent");
|
|
1474
|
+
const mainContent = content.filter((n) => n.data.elementType !== "BoundaryEvent");
|
|
1475
|
+
if (mainContent.length === 0) {
|
|
1476
|
+
const positionedBoundaries2 = repositionBoundaryEvents(boundaryEvents, []);
|
|
1332
1477
|
if (lanes.length === 0) {
|
|
1333
|
-
return { nodes:
|
|
1478
|
+
return { nodes: positionedBoundaries2, width: 300, height: 140 };
|
|
1334
1479
|
}
|
|
1335
1480
|
const laneH = LANE_MIN_H;
|
|
1336
1481
|
const h = POOL_INNER_PAD * 2 + lanes.length * laneH + Math.max(0, lanes.length - 1) * POOL_INNER_PAD;
|
|
1337
|
-
const w = POOL_MIN_W;
|
|
1338
1482
|
return {
|
|
1339
|
-
nodes:
|
|
1340
|
-
...
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1483
|
+
nodes: [
|
|
1484
|
+
...positionedBoundaries2,
|
|
1485
|
+
...lanes.map((lane, i) => ({
|
|
1486
|
+
...lane,
|
|
1487
|
+
position: { x: POOL_INNER_PAD, y: POOL_INNER_PAD + i * (laneH + POOL_INNER_PAD) },
|
|
1488
|
+
width: POOL_MIN_W - POOL_INNER_PAD * 2,
|
|
1489
|
+
height: laneH
|
|
1490
|
+
}))
|
|
1491
|
+
],
|
|
1492
|
+
width: POOL_MIN_W,
|
|
1346
1493
|
height: h
|
|
1347
1494
|
};
|
|
1348
1495
|
}
|
|
1349
|
-
const
|
|
1496
|
+
const sortedLanes = [...lanes].sort((a, b) => a.position.y - b.position.y);
|
|
1497
|
+
const hasLanes = sortedLanes.length > 0;
|
|
1498
|
+
const laneIdSet = new Set(sortedLanes.map((l) => l.id));
|
|
1499
|
+
const nodeLaneId = /* @__PURE__ */ new Map();
|
|
1500
|
+
for (const node of mainContent) {
|
|
1501
|
+
const lId = hasLanes && node.parentId && laneIdSet.has(node.parentId) ? node.parentId : "_pool_";
|
|
1502
|
+
nodeLaneId.set(node.id, lId);
|
|
1503
|
+
}
|
|
1504
|
+
const contentIds = new Set(mainContent.map((n) => n.id));
|
|
1350
1505
|
const seqEdges = extractSeqEdges(allEdges, contentIds);
|
|
1351
1506
|
const backIds = detectBackEdges([...contentIds], seqEdges);
|
|
1352
1507
|
const fwdEdges = seqEdges.filter((e) => !backIds.has(e.id));
|
|
1353
1508
|
const columns = assignColumns([...contentIds], fwdEdges);
|
|
1354
|
-
const
|
|
1355
|
-
const
|
|
1356
|
-
const
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1509
|
+
const rows = /* @__PURE__ */ new Map();
|
|
1510
|
+
const contentByLane = /* @__PURE__ */ new Map();
|
|
1511
|
+
for (const node of mainContent) {
|
|
1512
|
+
const lId = nodeLaneId.get(node.id) ?? "_pool_";
|
|
1513
|
+
if (!contentByLane.has(lId)) contentByLane.set(lId, []);
|
|
1514
|
+
contentByLane.get(lId).push(node);
|
|
1515
|
+
}
|
|
1516
|
+
for (const [, laneNodes] of contentByLane) {
|
|
1517
|
+
const laneNodeIds = new Set(laneNodes.map((n) => n.id));
|
|
1518
|
+
const intraEdges = fwdEdges.filter(
|
|
1519
|
+
(e) => laneNodeIds.has(e.source) && laneNodeIds.has(e.target)
|
|
1520
|
+
);
|
|
1521
|
+
const lanePairs = detectGatewayPairs(laneNodes, intraEdges);
|
|
1522
|
+
const laneRows = assignRows(laneNodes, intraEdges, columns, lanePairs);
|
|
1523
|
+
for (const [id, row] of laneRows) rows.set(id, row);
|
|
1366
1524
|
}
|
|
1367
1525
|
const laneIds = hasLanes ? sortedLanes.map((l) => l.id) : ["_pool_"];
|
|
1368
1526
|
const laneStats = /* @__PURE__ */ new Map();
|
|
1369
1527
|
for (const laneId of laneIds) {
|
|
1370
|
-
const laneRows =
|
|
1528
|
+
const laneRows = mainContent.filter((n) => nodeLaneId.get(n.id) === laneId).map((n) => rows.get(n.id) ?? 0);
|
|
1371
1529
|
if (laneRows.length === 0) {
|
|
1372
1530
|
laneStats.set(laneId, { minRow: 0, maxRow: 0, rowCount: 1, height: LANE_MIN_H });
|
|
1373
1531
|
} else {
|
|
@@ -1382,9 +1540,9 @@ function layoutPool(pool, lanes, content, allEdges) {
|
|
|
1382
1540
|
const maxCol = Math.max(0, ...[...columns.values()]);
|
|
1383
1541
|
const colW = /* @__PURE__ */ new Map();
|
|
1384
1542
|
for (let c = 0; c <= maxCol; c++) colW.set(c, 0);
|
|
1385
|
-
for (const node of
|
|
1543
|
+
for (const node of mainContent) {
|
|
1386
1544
|
const c = columns.get(node.id) ?? 0;
|
|
1387
|
-
colW.set(c, Math.max(colW.get(c) ?? 0,
|
|
1545
|
+
colW.set(c, Math.max(colW.get(c) ?? 0, layoutW(node)));
|
|
1388
1546
|
}
|
|
1389
1547
|
const colX = /* @__PURE__ */ new Map();
|
|
1390
1548
|
let cumX = 0;
|
|
@@ -1405,62 +1563,58 @@ function layoutPool(pool, lanes, content, allEdges) {
|
|
|
1405
1563
|
if (i < laneIds.length - 1) cumY += POOL_INNER_PAD;
|
|
1406
1564
|
}
|
|
1407
1565
|
const poolH = cumY + POOL_INNER_PAD;
|
|
1408
|
-
const positionedContent =
|
|
1566
|
+
const positionedContent = mainContent.map((node) => {
|
|
1409
1567
|
const c = columns.get(node.id) ?? 0;
|
|
1410
1568
|
const r = rows.get(node.id) ?? 0;
|
|
1411
1569
|
const laneId = nodeLaneId.get(node.id) ?? "_pool_";
|
|
1412
1570
|
const stat = laneStats.get(laneId);
|
|
1413
1571
|
const lYOff = laneY.get(laneId) ?? 0;
|
|
1414
|
-
const
|
|
1415
|
-
const
|
|
1416
|
-
const
|
|
1572
|
+
const lw = layoutW(node);
|
|
1573
|
+
const lh = layoutH(node);
|
|
1574
|
+
const colOffset = (colX.get(c) ?? 0) + (colW.get(c) ?? 120) / 2 - lw / 2;
|
|
1575
|
+
const rowOffset = (r - stat.minRow) * (ROW_HEIGHT + ROW_GAP) + ROW_HEIGHT / 2 - lh / 2;
|
|
1417
1576
|
const contentH_stat = stat.rowCount * ROW_HEIGHT + Math.max(0, stat.rowCount - 1) * ROW_GAP;
|
|
1418
1577
|
const vertTopOffset = Math.max(LANE_V_PAD, (stat.height - contentH_stat) / 2);
|
|
1578
|
+
const isLaneChild = hasLanes && !!node.parentId && node.parentId !== pool.id;
|
|
1419
1579
|
const x = isLaneChild ? LANE_LABEL_W + LANE_H_PAD + colOffset : POOL_H_PAD + colOffset;
|
|
1420
1580
|
const y = isLaneChild ? vertTopOffset + rowOffset : lYOff + vertTopOffset + rowOffset;
|
|
1421
|
-
return { ...node, position: { x, y } };
|
|
1581
|
+
return applyLayoutMinSize({ ...node, position: { x, y } });
|
|
1422
1582
|
});
|
|
1423
|
-
const NODE_MIN_GAP =
|
|
1583
|
+
const NODE_MIN_GAP = 24;
|
|
1424
1584
|
const resolvedContent = [...positionedContent];
|
|
1425
1585
|
for (const laneId of laneIds) {
|
|
1426
1586
|
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);
|
|
1427
1587
|
for (let k = 1; k < laneNodeIndices.length; k++) {
|
|
1428
1588
|
const prev = resolvedContent[laneNodeIndices[k - 1].i];
|
|
1429
1589
|
const curr = resolvedContent[laneNodeIndices[k].i];
|
|
1430
|
-
const prevBottom = prev.position.y +
|
|
1590
|
+
const prevBottom = prev.position.y + layoutH(prev);
|
|
1431
1591
|
const currTop = curr.position.y;
|
|
1432
1592
|
const prevTop = prev.position.y;
|
|
1433
|
-
const currBottom = curr.position.y +
|
|
1593
|
+
const currBottom = curr.position.y + layoutH(curr);
|
|
1434
1594
|
const yOverlap = prevBottom + NODE_MIN_GAP > currTop && currBottom + NODE_MIN_GAP > prevTop;
|
|
1435
1595
|
if (!yOverlap) continue;
|
|
1436
|
-
const prevRight = prev.position.x +
|
|
1596
|
+
const prevRight = prev.position.x + layoutW(prev);
|
|
1437
1597
|
if (prevRight + NODE_MIN_GAP > curr.position.x) {
|
|
1438
1598
|
resolvedContent[laneNodeIndices[k].i] = {
|
|
1439
1599
|
...curr,
|
|
1440
|
-
position: {
|
|
1441
|
-
x: prevRight + NODE_MIN_GAP,
|
|
1442
|
-
y: curr.position.y
|
|
1443
|
-
}
|
|
1600
|
+
position: { x: prevRight + NODE_MIN_GAP, y: curr.position.y }
|
|
1444
1601
|
};
|
|
1445
1602
|
}
|
|
1446
1603
|
}
|
|
1447
1604
|
}
|
|
1605
|
+
const positionedBoundaries = repositionBoundaryEvents(boundaryEvents, resolvedContent);
|
|
1448
1606
|
const positionedLanes = hasLanes ? sortedLanes.map((lane) => ({
|
|
1449
1607
|
...lane,
|
|
1450
|
-
// x: after pool label strip + left inner padding
|
|
1451
|
-
// y: laneY already includes top POOL_INNER_PAD offset
|
|
1452
1608
|
position: { x: POOL_INNER_PAD, y: laneY.get(lane.id) ?? POOL_INNER_PAD },
|
|
1453
1609
|
width: laneW,
|
|
1454
1610
|
height: laneStats.get(lane.id)?.height ?? LANE_MIN_H
|
|
1455
1611
|
})) : [];
|
|
1456
1612
|
return {
|
|
1457
|
-
nodes: [...resolvedContent, ...positionedLanes],
|
|
1613
|
+
nodes: [...resolvedContent, ...positionedBoundaries, ...positionedLanes],
|
|
1458
1614
|
width: poolW,
|
|
1459
1615
|
height: poolH
|
|
1460
1616
|
};
|
|
1461
1617
|
}
|
|
1462
|
-
var BACK_EDGE_CLEARANCE = 50;
|
|
1463
|
-
var SAME_ROW_THRESHOLD = 15;
|
|
1464
1618
|
function absolutePos(nodeId, byId, cache) {
|
|
1465
1619
|
const cached = cache.get(nodeId);
|
|
1466
1620
|
if (cached) return cached;
|
|
@@ -1479,10 +1633,22 @@ function absolutePos(nodeId, byId, cache) {
|
|
|
1479
1633
|
function laneOf(node, laneIds) {
|
|
1480
1634
|
return node.parentId && laneIds.has(node.parentId) ? node.parentId : void 0;
|
|
1481
1635
|
}
|
|
1636
|
+
function gapMidX(sAbs, sW, tAbs, tW) {
|
|
1637
|
+
const leftRightEdge = Math.min(sAbs.x + sW, tAbs.x + tW);
|
|
1638
|
+
const rightLeftEdge = Math.max(sAbs.x, tAbs.x);
|
|
1639
|
+
return leftRightEdge < rightLeftEdge ? (leftRightEdge + rightLeftEdge) / 2 : sAbs.x + sW / 2;
|
|
1640
|
+
}
|
|
1641
|
+
function routeMidX(sAbs, sW, tAbs, tW) {
|
|
1642
|
+
const leftEdge = Math.min(sAbs.x + sW, tAbs.x + tW);
|
|
1643
|
+
const rightEdge = Math.max(sAbs.x, tAbs.x);
|
|
1644
|
+
return leftEdge < rightEdge ? leftEdge + (rightEdge - leftEdge) * 0.35 : sAbs.x + sW / 2;
|
|
1645
|
+
}
|
|
1646
|
+
var SAME_ROW_THRESHOLD = 15;
|
|
1482
1647
|
function routeEdges(edges, layoutNodes, backEdgeIds, laneIds, poolIds) {
|
|
1483
1648
|
const byId = new Map(layoutNodes.map((n) => [n.id, n]));
|
|
1484
1649
|
const cache = /* @__PURE__ */ new Map();
|
|
1485
1650
|
const abs = (id) => absolutePos(id, byId, cache);
|
|
1651
|
+
const sortedLanes = [...laneIds].map((id) => byId.get(id)).filter((n) => !!n).sort((a, b) => abs(a.id).y - abs(b.id).y);
|
|
1486
1652
|
return edges.map((edge) => {
|
|
1487
1653
|
const edgeType = edge.data?.edgeType ?? edge.type;
|
|
1488
1654
|
if (edgeType !== "sequenceFlow") {
|
|
@@ -1497,11 +1663,22 @@ function routeEdges(edges, layoutNodes, backEdgeIds, laneIds, poolIds) {
|
|
|
1497
1663
|
const tAbs = abs(tgt.id);
|
|
1498
1664
|
const sW = nW(src), sH = nH(src);
|
|
1499
1665
|
const tW = nW(tgt), tH = nH(tgt);
|
|
1500
|
-
const sCX = sAbs.x + sW / 2
|
|
1501
|
-
const tCX = tAbs.x + tW / 2
|
|
1502
|
-
const
|
|
1503
|
-
const
|
|
1504
|
-
|
|
1666
|
+
const sCX = sAbs.x + sW / 2;
|
|
1667
|
+
const tCX = tAbs.x + tW / 2;
|
|
1668
|
+
const sCY = sAbs.y + sH / 2;
|
|
1669
|
+
const tCY = tAbs.y + tH / 2;
|
|
1670
|
+
const getPool = (nodeId) => {
|
|
1671
|
+
const node = byId.get(nodeId);
|
|
1672
|
+
if (!node) return null;
|
|
1673
|
+
if (poolIds.has(nodeId)) return nodeId;
|
|
1674
|
+
if (node.parentId && poolIds.has(node.parentId)) return node.parentId;
|
|
1675
|
+
if (node.parentId) {
|
|
1676
|
+
const gp = byId.get(node.parentId)?.parentId ?? null;
|
|
1677
|
+
if (gp && poolIds.has(gp)) return gp;
|
|
1678
|
+
}
|
|
1679
|
+
return node.parentId ?? null;
|
|
1680
|
+
};
|
|
1681
|
+
if (getPool(edge.source) !== getPool(edge.target)) {
|
|
1505
1682
|
const d = { ...edge.data };
|
|
1506
1683
|
delete d.routingPoints;
|
|
1507
1684
|
return { ...edge, data: d };
|
|
@@ -1511,33 +1688,49 @@ function routeEdges(edges, layoutNodes, backEdgeIds, laneIds, poolIds) {
|
|
|
1511
1688
|
const topY = Math.min(sAbs.y, tAbs.y) - BACK_EDGE_CLEARANCE;
|
|
1512
1689
|
routingPoints = [
|
|
1513
1690
|
{ x: sCX, y: sAbs.y },
|
|
1514
|
-
// [0] discarded
|
|
1515
1691
|
{ x: sCX, y: topY },
|
|
1516
|
-
// [1] go up
|
|
1517
1692
|
{ x: tCX, y: topY },
|
|
1518
|
-
|
|
1519
|
-
{ x: tCX, y: tAbs.y }
|
|
1520
|
-
// [3] discarded
|
|
1693
|
+
{ x: tCX, y: tAbs.y + tH }
|
|
1521
1694
|
];
|
|
1522
1695
|
} else if (laneOf(src, laneIds) !== laneOf(tgt, laneIds)) {
|
|
1523
|
-
const goingDown = tAbs.y > sAbs.y;
|
|
1524
|
-
const sharedX = Math.abs(sCX - tCX) < 10 ? sCX : (sCX + tCX) / 2;
|
|
1525
1696
|
const srcLane = byId.get(src.parentId ?? "");
|
|
1526
1697
|
const tgtLane = byId.get(tgt.parentId ?? "");
|
|
1527
1698
|
if (srcLane && tgtLane && laneIds.has(srcLane.id) && laneIds.has(tgtLane.id)) {
|
|
1528
|
-
const
|
|
1529
|
-
const
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
{ x: sharedX, y:
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1699
|
+
const goingDown = tAbs.y > sAbs.y;
|
|
1700
|
+
const sharedX = gapMidX(sAbs, sW, tAbs, tW);
|
|
1701
|
+
const srcLaneIdx = sortedLanes.findIndex((l) => l.id === srcLane.id);
|
|
1702
|
+
const tgtLaneIdx = sortedLanes.findIndex((l) => l.id === tgtLane.id);
|
|
1703
|
+
const pts = [];
|
|
1704
|
+
if (goingDown) {
|
|
1705
|
+
pts.push({ x: sCX, y: sAbs.y + sH });
|
|
1706
|
+
pts.push({ x: sharedX, y: sAbs.y + sH });
|
|
1707
|
+
const fromIdx = Math.min(srcLaneIdx, tgtLaneIdx);
|
|
1708
|
+
const toIdx = Math.max(srcLaneIdx, tgtLaneIdx);
|
|
1709
|
+
for (let i = fromIdx; i < toIdx; i++) {
|
|
1710
|
+
const lane = sortedLanes[i];
|
|
1711
|
+
const laneBot = abs(lane.id).y + (lane.height ?? LANE_MIN_H);
|
|
1712
|
+
pts.push({ x: sharedX, y: laneBot });
|
|
1713
|
+
}
|
|
1714
|
+
const lastY = pts[pts.length - 1].y;
|
|
1715
|
+
pts.push({ x: tCX, y: lastY });
|
|
1716
|
+
pts.push({ x: tCX, y: tAbs.y + tH });
|
|
1717
|
+
} else {
|
|
1718
|
+
pts.push({ x: sCX, y: sAbs.y });
|
|
1719
|
+
pts.push({ x: sharedX, y: sAbs.y });
|
|
1720
|
+
const fromIdx = Math.min(srcLaneIdx, tgtLaneIdx);
|
|
1721
|
+
const toIdx = Math.max(srcLaneIdx, tgtLaneIdx);
|
|
1722
|
+
for (let i = toIdx; i > fromIdx; i--) {
|
|
1723
|
+
const lane = sortedLanes[i];
|
|
1724
|
+
const laneTop = abs(lane.id).y;
|
|
1725
|
+
pts.push({ x: sharedX, y: laneTop });
|
|
1726
|
+
}
|
|
1727
|
+
const lastY = pts[pts.length - 1].y;
|
|
1728
|
+
pts.push({ x: tCX, y: lastY });
|
|
1729
|
+
pts.push({ x: tCX, y: tAbs.y });
|
|
1730
|
+
}
|
|
1731
|
+
routingPoints = pts;
|
|
1540
1732
|
} else {
|
|
1733
|
+
const sharedX = gapMidX(sAbs, sW, tAbs, tW);
|
|
1541
1734
|
routingPoints = [
|
|
1542
1735
|
{ x: sCX, y: sCY },
|
|
1543
1736
|
{ x: sharedX, y: sCY },
|
|
@@ -1556,39 +1749,108 @@ function routeEdges(edges, layoutNodes, backEdgeIds, laneIds, poolIds) {
|
|
|
1556
1749
|
if (exitsTop || exitsBottom) {
|
|
1557
1750
|
routingPoints = [
|
|
1558
1751
|
{ x: sCX, y: exitsTop ? sAbs.y : sAbs.y + sH },
|
|
1559
|
-
// [0] discarded
|
|
1560
1752
|
{ x: sCX, y: tCY },
|
|
1561
|
-
// [1] vertical to target row
|
|
1562
1753
|
{ x: tCX, y: tCY },
|
|
1563
|
-
// [2] horizontal to target
|
|
1564
1754
|
{ x: tCX, y: exitsTop ? tAbs.y + tH : tAbs.y }
|
|
1565
|
-
// [3] discarded
|
|
1566
1755
|
];
|
|
1567
1756
|
} else {
|
|
1568
|
-
const
|
|
1569
|
-
const midX = goingRight ? sAbs.x + sW + COL_GAP / 2 : sAbs.x - COL_GAP / 2;
|
|
1757
|
+
const midX = routeMidX(sAbs, sW, tAbs, tW);
|
|
1570
1758
|
routingPoints = [
|
|
1571
1759
|
{ x: sAbs.x + sW, y: sCY },
|
|
1572
|
-
// [0] discarded
|
|
1573
1760
|
{ x: midX, y: sCY },
|
|
1574
|
-
// [1] horizontal exit
|
|
1575
1761
|
{ x: midX, y: tCY },
|
|
1576
|
-
// [2] vertical to target row
|
|
1577
1762
|
{ x: tAbs.x, y: tCY }
|
|
1578
|
-
// [3] discarded
|
|
1579
1763
|
];
|
|
1580
1764
|
}
|
|
1581
1765
|
}
|
|
1582
1766
|
return { ...edge, data: { ...edge.data, routingPoints } };
|
|
1583
1767
|
});
|
|
1584
1768
|
}
|
|
1769
|
+
var ARTIFACT_ABOVE_GAP = 16;
|
|
1770
|
+
var ARTIFACT_H_SPACING = 12;
|
|
1771
|
+
function positionArtifacts(artifacts, resultNodes, edges) {
|
|
1772
|
+
if (artifacts.length === 0) return [];
|
|
1773
|
+
const byId = new Map(resultNodes.map((n) => [n.id, n]));
|
|
1774
|
+
const cache = /* @__PURE__ */ new Map();
|
|
1775
|
+
const absPos = (id) => absolutePos(id, byId, cache);
|
|
1776
|
+
const artifactsByNode = /* @__PURE__ */ new Map();
|
|
1777
|
+
const ungrouped = [];
|
|
1778
|
+
for (const artifact of artifacts) {
|
|
1779
|
+
if (artifact.data.elementType === "Group") {
|
|
1780
|
+
ungrouped.push(artifact);
|
|
1781
|
+
continue;
|
|
1782
|
+
}
|
|
1783
|
+
const connEdge = edges.find((e) => {
|
|
1784
|
+
const t = e.data?.edgeType ?? e.type;
|
|
1785
|
+
return (t === "association" || t === "dataAssociation") && (e.source === artifact.id || e.target === artifact.id);
|
|
1786
|
+
});
|
|
1787
|
+
if (!connEdge) {
|
|
1788
|
+
ungrouped.push(artifact);
|
|
1789
|
+
continue;
|
|
1790
|
+
}
|
|
1791
|
+
const connId = connEdge.source === artifact.id ? connEdge.target : connEdge.source;
|
|
1792
|
+
if (!byId.has(connId)) {
|
|
1793
|
+
ungrouped.push(artifact);
|
|
1794
|
+
continue;
|
|
1795
|
+
}
|
|
1796
|
+
if (!artifactsByNode.has(connId)) artifactsByNode.set(connId, []);
|
|
1797
|
+
artifactsByNode.get(connId).push(artifact);
|
|
1798
|
+
}
|
|
1799
|
+
const positioned = [...ungrouped];
|
|
1800
|
+
for (const [connId, arts] of artifactsByNode) {
|
|
1801
|
+
const connNode = byId.get(connId);
|
|
1802
|
+
const connAbsP = absPos(connId);
|
|
1803
|
+
const totalW = arts.reduce((s, a) => s + nW(a), 0) + (arts.length - 1) * ARTIFACT_H_SPACING;
|
|
1804
|
+
const desiredAbsY = connAbsP.y - ARTIFACT_ABOVE_GAP - Math.max(...arts.map(nH));
|
|
1805
|
+
let desiredAbsX = connAbsP.x + nW(connNode) / 2 - totalW / 2;
|
|
1806
|
+
for (const artifact of arts) {
|
|
1807
|
+
const parentAbsP = artifact.parentId ? absPos(artifact.parentId) : { x: 0, y: 0 };
|
|
1808
|
+
positioned.push({
|
|
1809
|
+
...artifact,
|
|
1810
|
+
position: {
|
|
1811
|
+
x: desiredAbsX - parentAbsP.x,
|
|
1812
|
+
y: desiredAbsY - parentAbsP.y
|
|
1813
|
+
}
|
|
1814
|
+
});
|
|
1815
|
+
desiredAbsX += nW(artifact) + ARTIFACT_H_SPACING;
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
return positioned;
|
|
1819
|
+
}
|
|
1585
1820
|
async function bpmnCustomLayout(nodes, edges) {
|
|
1586
|
-
const
|
|
1587
|
-
const
|
|
1588
|
-
const
|
|
1821
|
+
const artifacts = nodes.filter((n) => LAYOUT_ARTIFACT_TYPES.has(n.data.elementType));
|
|
1822
|
+
const mainNodes = nodes.filter((n) => !LAYOUT_ARTIFACT_TYPES.has(n.data.elementType));
|
|
1823
|
+
const pools = mainNodes.filter((n) => n.data.elementType === "Pool");
|
|
1824
|
+
const lanes = mainNodes.filter((n) => n.data.elementType === "Lane");
|
|
1825
|
+
const expandedSubProcesses = mainNodes.filter(
|
|
1826
|
+
(n) => COLLAPSED_SUBPROCESS_TYPES.has(n.data.elementType) && n.data.isExpanded
|
|
1827
|
+
);
|
|
1828
|
+
const subProcessLayouts = /* @__PURE__ */ new Map();
|
|
1829
|
+
const workingMainNodes = [...mainNodes];
|
|
1830
|
+
for (const sp of expandedSubProcesses) {
|
|
1831
|
+
const spChildren = workingMainNodes.filter((n) => n.parentId === sp.id);
|
|
1832
|
+
const result = layoutSubProcess(spChildren, edges);
|
|
1833
|
+
subProcessLayouts.set(sp.id, result);
|
|
1834
|
+
const spIdx = workingMainNodes.findIndex((n) => n.id === sp.id);
|
|
1835
|
+
if (spIdx >= 0) {
|
|
1836
|
+
workingMainNodes[spIdx] = {
|
|
1837
|
+
...workingMainNodes[spIdx],
|
|
1838
|
+
width: result.width,
|
|
1839
|
+
height: result.height,
|
|
1840
|
+
measured: { width: result.width, height: result.height }
|
|
1841
|
+
};
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
1844
|
+
const content = workingMainNodes.filter((n) => {
|
|
1845
|
+
if (!LAYOUT_CONTAINER_TYPES.has(n.data.elementType)) return true;
|
|
1846
|
+
if (COLLAPSED_SUBPROCESS_TYPES.has(n.data.elementType)) return true;
|
|
1847
|
+
return false;
|
|
1848
|
+
});
|
|
1589
1849
|
if (pools.length === 0) {
|
|
1590
1850
|
const { bpmnElkLayout: bpmnElkLayout2 } = await Promise.resolve().then(() => (init_elk(), elk_exports));
|
|
1591
|
-
|
|
1851
|
+
const elkResult = await bpmnElkLayout2(nodes.filter((n) => !LAYOUT_ARTIFACT_TYPES.has(n.data.elementType)), edges);
|
|
1852
|
+
const posArtifacts = positionArtifacts(artifacts, elkResult.nodes, edges);
|
|
1853
|
+
return { nodes: [...elkResult.nodes, ...posArtifacts], edges: elkResult.edges };
|
|
1592
1854
|
}
|
|
1593
1855
|
const poolIds = new Set(pools.map((p) => p.id));
|
|
1594
1856
|
const allLaneIds = new Set(lanes.map((l) => l.id));
|
|
@@ -1608,7 +1870,10 @@ async function bpmnCustomLayout(nodes, edges) {
|
|
|
1608
1870
|
const poolContent = content.filter(
|
|
1609
1871
|
(n) => n.parentId === pool.id || n.parentId != null && laneIds.has(n.parentId)
|
|
1610
1872
|
);
|
|
1611
|
-
const
|
|
1873
|
+
const poolBoundaries = workingMainNodes.filter(
|
|
1874
|
+
(n) => n.data.elementType === "BoundaryEvent" && (n.parentId === pool.id || n.parentId != null && laneIds.has(n.parentId))
|
|
1875
|
+
);
|
|
1876
|
+
const result = layoutPool(pool, poolLanes, [...poolContent, ...poolBoundaries], edges);
|
|
1612
1877
|
resultNodes.push({
|
|
1613
1878
|
...pool,
|
|
1614
1879
|
position: { x: 0, y: stackY },
|
|
@@ -1620,12 +1885,44 @@ async function bpmnCustomLayout(nodes, edges) {
|
|
|
1620
1885
|
}
|
|
1621
1886
|
stackY += result.height + POOL_V_GAP;
|
|
1622
1887
|
}
|
|
1888
|
+
for (const [, spLayout] of subProcessLayouts) {
|
|
1889
|
+
for (const child of spLayout.children) {
|
|
1890
|
+
resultNodes.push(child);
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1623
1893
|
const layoutted = new Set(resultNodes.map((n) => n.id));
|
|
1624
|
-
|
|
1625
|
-
|
|
1894
|
+
const freeNodes = workingMainNodes.filter((n) => !layoutted.has(n.id));
|
|
1895
|
+
if (freeNodes.length > 0) {
|
|
1896
|
+
const freeEdges = edges.filter(
|
|
1897
|
+
(e) => freeNodes.some((n) => n.id === e.source || n.id === e.target)
|
|
1898
|
+
);
|
|
1899
|
+
try {
|
|
1900
|
+
const { bpmnElkLayout: bpmnElkLayout2 } = await Promise.resolve().then(() => (init_elk(), elk_exports));
|
|
1901
|
+
const elkFree = await bpmnElkLayout2(freeNodes, freeEdges);
|
|
1902
|
+
const offsetY = stackY;
|
|
1903
|
+
for (const node of elkFree.nodes) {
|
|
1904
|
+
resultNodes.push({
|
|
1905
|
+
...node,
|
|
1906
|
+
position: { x: node.position.x, y: node.position.y + offsetY }
|
|
1907
|
+
});
|
|
1908
|
+
}
|
|
1909
|
+
const freeEdgeIds = new Set(freeEdges.map((e) => e.id));
|
|
1910
|
+
const elkEdgeMap = new Map(elkFree.edges.map((e) => [e.id, e]));
|
|
1911
|
+
for (let i = 0; i < edges.length; i++) {
|
|
1912
|
+
if (freeEdgeIds.has(edges[i].id) && elkEdgeMap.has(edges[i].id)) {
|
|
1913
|
+
edges[i] = elkEdgeMap.get(edges[i].id);
|
|
1914
|
+
}
|
|
1915
|
+
}
|
|
1916
|
+
} catch {
|
|
1917
|
+
for (const node of freeNodes) resultNodes.push(node);
|
|
1918
|
+
}
|
|
1626
1919
|
}
|
|
1627
1920
|
const routedEdges = routeEdges(edges, resultNodes, allBackEdgeIds, allLaneIds, poolIds);
|
|
1628
|
-
|
|
1921
|
+
const positionedArtifacts = positionArtifacts(artifacts, resultNodes, edges);
|
|
1922
|
+
return {
|
|
1923
|
+
nodes: [...resultNodes, ...positionedArtifacts],
|
|
1924
|
+
edges: routedEdges
|
|
1925
|
+
};
|
|
1629
1926
|
}
|
|
1630
1927
|
|
|
1631
1928
|
// src/layout/index.ts
|