@aranzatech/diagrams-bpmn 0.3.2 → 0.3.4

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.
@@ -1197,6 +1197,17 @@ function detectGatewayPairs(nodes, forwardEdges) {
1197
1197
  }
1198
1198
  return pairs;
1199
1199
  }
1200
+ function createSecondaryOffsets(count) {
1201
+ if (count <= 0) return [];
1202
+ const offsets = [];
1203
+ let step = 1;
1204
+ while (offsets.length < count) {
1205
+ offsets.push(-step);
1206
+ if (offsets.length < count) offsets.push(step);
1207
+ step++;
1208
+ }
1209
+ return offsets;
1210
+ }
1200
1211
  function handleToRowBias(handle) {
1201
1212
  if (!handle) return null;
1202
1213
  if (handle.includes("top")) return -1;
@@ -1212,6 +1223,52 @@ function buildHandleMap(edges) {
1212
1223
  }
1213
1224
  return map;
1214
1225
  }
1226
+ function pickMainBranch(branchData) {
1227
+ if (branchData.length === 0) return void 0;
1228
+ return [...branchData].sort((a, b) => {
1229
+ const aRight = a.bias === 0 ? 1 : 0;
1230
+ const bRight = b.bias === 0 ? 1 : 0;
1231
+ if (aRight !== bRight) return bRight - aRight;
1232
+ if (a.nodeIds.length !== b.nodeIds.length) return b.nodeIds.length - a.nodeIds.length;
1233
+ return a.start.localeCompare(b.start);
1234
+ })[0]?.start;
1235
+ }
1236
+ function resolveDirectionalRow(splitRow, preferredOffset, usedRows) {
1237
+ if (preferredOffset === 0 && !usedRows.has(splitRow)) return splitRow;
1238
+ const direction = preferredOffset < 0 ? -1 : 1;
1239
+ let distance = Math.max(1, Math.abs(preferredOffset));
1240
+ while (usedRows.has(splitRow + direction * distance)) distance++;
1241
+ return splitRow + direction * distance;
1242
+ }
1243
+ function assignBranchRowsAroundMain(branchData, splitRow) {
1244
+ const assigned = /* @__PURE__ */ new Map();
1245
+ const mainBranchStart = pickMainBranch(branchData);
1246
+ if (mainBranchStart) assigned.set(mainBranchStart, splitRow);
1247
+ const usedRows = new Set(assigned.values());
1248
+ const remaining = branchData.filter((branch) => branch.start !== mainBranchStart);
1249
+ const withBias = remaining.filter((branch) => branch.bias !== null && branch.bias !== 0).sort((a, b) => {
1250
+ const aMag = Math.abs(a.bias ?? 0);
1251
+ const bMag = Math.abs(b.bias ?? 0);
1252
+ if (aMag !== bMag) return aMag - bMag;
1253
+ return a.start.localeCompare(b.start);
1254
+ });
1255
+ const withoutBias = remaining.filter((branch) => branch.bias === null || branch.bias === 0).sort((a, b) => b.nodeIds.length - a.nodeIds.length || a.start.localeCompare(b.start));
1256
+ for (const branch of withBias) {
1257
+ const row = resolveDirectionalRow(splitRow, branch.bias ?? 0, usedRows);
1258
+ assigned.set(branch.start, row);
1259
+ usedRows.add(row);
1260
+ }
1261
+ const preferredOffsets = createSecondaryOffsets(withoutBias.length);
1262
+ for (let i = 0; i < withoutBias.length; i++) {
1263
+ let row = splitRow + preferredOffsets[i];
1264
+ if (usedRows.has(row)) {
1265
+ row = resolveDirectionalRow(splitRow, preferredOffsets[i], usedRows);
1266
+ }
1267
+ assigned.set(withoutBias[i].start, row);
1268
+ usedRows.add(row);
1269
+ }
1270
+ return assigned;
1271
+ }
1215
1272
  function assignRows(nodes, forwardEdges, columns, gatewayPairs) {
1216
1273
  const rows = new Map(nodes.map((n) => [n.id, 0]));
1217
1274
  const succs = new Map(nodes.map((n) => [n.id, []]));
@@ -1245,24 +1302,14 @@ function assignRows(nodes, forwardEdges, columns, gatewayPairs) {
1245
1302
  nodeIds: getBranchNodes(start),
1246
1303
  bias: handleToRowBias(splitHandles?.get(start) ?? null)
1247
1304
  }));
1248
- const withBias = branchData.filter((b) => b.bias !== null && b.bias !== 0);
1249
- const withoutBias = branchData.filter((b) => b.bias === null || b.bias === 0).sort((a, b) => b.nodeIds.length - a.nodeIds.length);
1250
- const assigned = /* @__PURE__ */ new Map();
1251
- for (const b of withBias) {
1252
- assigned.set(b.start, splitRow + b.bias);
1253
- }
1254
- let nextOffset = 0;
1255
- for (const b of withoutBias) {
1256
- while ([...assigned.values()].includes(splitRow + nextOffset)) nextOffset++;
1257
- assigned.set(b.start, splitRow + nextOffset);
1258
- nextOffset++;
1259
- }
1305
+ const assigned = assignBranchRowsAroundMain(branchData, splitRow);
1260
1306
  for (const b of branchData) {
1261
1307
  const row = assigned.get(b.start) ?? splitRow;
1262
1308
  for (const id of b.nodeIds) {
1263
1309
  rows.set(id, row);
1264
1310
  }
1265
1311
  }
1312
+ rows.set(mergeId, splitRow);
1266
1313
  }
1267
1314
  const pairedSplits = new Set(gatewayPairs.keys());
1268
1315
  const unpairedSplits = nodes.filter(
@@ -1291,16 +1338,7 @@ function assignRows(nodes, forwardEdges, columns, gatewayPairs) {
1291
1338
  nodeIds: getAllReachable(start),
1292
1339
  bias: handleToRowBias(splitHandles2?.get(start) ?? null)
1293
1340
  }));
1294
- const withBias2 = branchData.filter((b) => b.bias !== null && b.bias !== 0);
1295
- const withoutBias2 = branchData.filter((b) => b.bias === null || b.bias === 0).sort((a, b) => b.nodeIds.length - a.nodeIds.length);
1296
- const assigned2 = /* @__PURE__ */ new Map();
1297
- for (const b of withBias2) assigned2.set(b.start, splitRow + b.bias);
1298
- let nextOff = 0;
1299
- for (const b of withoutBias2) {
1300
- while ([...assigned2.values()].includes(splitRow + nextOff)) nextOff++;
1301
- assigned2.set(b.start, splitRow + nextOff);
1302
- nextOff++;
1303
- }
1341
+ const assigned2 = assignBranchRowsAroundMain(branchData, splitRow);
1304
1342
  for (const b of branchData) {
1305
1343
  const row = assigned2.get(b.start) ?? splitRow;
1306
1344
  for (const id of b.nodeIds) rows.set(id, row);
@@ -1322,6 +1360,7 @@ var LANE_MIN_H = 180;
1322
1360
  var POOL_MIN_W = 720;
1323
1361
  var POOL_INNER_PAD = 10;
1324
1362
  var BACK_EDGE_CLEARANCE = 56;
1363
+ var EDGE_ROUTE_PAD = 28;
1325
1364
  var LAYOUT_ARTIFACT_TYPES = /* @__PURE__ */ new Set([
1326
1365
  "DataObject",
1327
1366
  "DataObjectReference",
@@ -1630,8 +1669,54 @@ function absolutePos(nodeId, byId, cache) {
1630
1669
  cache.set(nodeId, abs);
1631
1670
  return abs;
1632
1671
  }
1633
- function laneOf(node, laneIds) {
1634
- return node.parentId && laneIds.has(node.parentId) ? node.parentId : void 0;
1672
+ function findAncestorNodeId(node, candidateIds, byId) {
1673
+ let current = node;
1674
+ while (current?.parentId) {
1675
+ if (candidateIds.has(current.parentId)) return current.parentId;
1676
+ current = byId.get(current.parentId);
1677
+ }
1678
+ return void 0;
1679
+ }
1680
+ function laneOf(node, laneIds, byId) {
1681
+ return findAncestorNodeId(node, laneIds, byId);
1682
+ }
1683
+ function poolOf(node, poolIds, byId) {
1684
+ if (poolIds.has(node.id)) return node.id;
1685
+ return findAncestorNodeId(node, poolIds, byId);
1686
+ }
1687
+ function nodeRect(node, byId, cache) {
1688
+ const pos = absolutePos(node.id, byId, cache);
1689
+ return { x: pos.x, y: pos.y, width: nW(node), height: nH(node) };
1690
+ }
1691
+ function rectContainsRect(outer, inner) {
1692
+ return inner.x >= outer.x && inner.y >= outer.y && inner.x + inner.width <= outer.x + outer.width && inner.y + inner.height <= outer.y + outer.height;
1693
+ }
1694
+ function sortNodesParentFirst(nodes) {
1695
+ const byId = new Map(nodes.map((node) => [node.id, node]));
1696
+ const memo = /* @__PURE__ */ new Map();
1697
+ const depthOf = (node) => {
1698
+ const cached = memo.get(node.id);
1699
+ if (cached != null) return cached;
1700
+ if (!node.parentId) {
1701
+ memo.set(node.id, 0);
1702
+ return 0;
1703
+ }
1704
+ const parent = byId.get(node.parentId);
1705
+ const depth = parent ? depthOf(parent) + 1 : 0;
1706
+ memo.set(node.id, depth);
1707
+ return depth;
1708
+ };
1709
+ return [...nodes].sort((a, b) => {
1710
+ const depthDiff = depthOf(a) - depthOf(b);
1711
+ if (depthDiff !== 0) return depthDiff;
1712
+ const ay = a.position?.y ?? 0;
1713
+ const by = b.position?.y ?? 0;
1714
+ if (ay !== by) return ay - by;
1715
+ const ax = a.position?.x ?? 0;
1716
+ const bx = b.position?.x ?? 0;
1717
+ if (ax !== bx) return ax - bx;
1718
+ return a.id.localeCompare(b.id);
1719
+ });
1635
1720
  }
1636
1721
  function gapMidX(sAbs, sW, tAbs, tW) {
1637
1722
  const leftRightEdge = Math.min(sAbs.x + sW, tAbs.x + tW);
@@ -1667,18 +1752,9 @@ function routeEdges(edges, layoutNodes, backEdgeIds, laneIds, poolIds) {
1667
1752
  const tCX = tAbs.x + tW / 2;
1668
1753
  const sCY = sAbs.y + sH / 2;
1669
1754
  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)) {
1755
+ const srcPool = poolOf(src, poolIds, byId) ?? null;
1756
+ const tgtPool = poolOf(tgt, poolIds, byId) ?? null;
1757
+ if (srcPool !== tgtPool) {
1682
1758
  const d = { ...edge.data };
1683
1759
  delete d.routingPoints;
1684
1760
  return { ...edge, data: d };
@@ -1687,14 +1763,16 @@ function routeEdges(edges, layoutNodes, backEdgeIds, laneIds, poolIds) {
1687
1763
  if (backEdgeIds.has(edge.id)) {
1688
1764
  const topY = Math.min(sAbs.y, tAbs.y) - BACK_EDGE_CLEARANCE;
1689
1765
  routingPoints = [
1690
- { x: sCX, y: sAbs.y },
1691
- { x: sCX, y: topY },
1692
- { x: tCX, y: topY },
1693
- { x: tCX, y: tAbs.y + tH }
1766
+ { x: sAbs.x + sW, y: sCY },
1767
+ { x: sAbs.x + sW + EDGE_ROUTE_PAD, y: sCY },
1768
+ { x: sAbs.x + sW + EDGE_ROUTE_PAD, y: topY },
1769
+ { x: tAbs.x - EDGE_ROUTE_PAD, y: topY },
1770
+ { x: tAbs.x - EDGE_ROUTE_PAD, y: tCY },
1771
+ { x: tAbs.x, y: tCY }
1694
1772
  ];
1695
- } else if (laneOf(src, laneIds) !== laneOf(tgt, laneIds)) {
1696
- const srcLane = byId.get(src.parentId ?? "");
1697
- const tgtLane = byId.get(tgt.parentId ?? "");
1773
+ } else if (laneOf(src, laneIds, byId) !== laneOf(tgt, laneIds, byId)) {
1774
+ const srcLane = byId.get(laneOf(src, laneIds, byId) ?? "");
1775
+ const tgtLane = byId.get(laneOf(tgt, laneIds, byId) ?? "");
1698
1776
  if (srcLane && tgtLane && laneIds.has(srcLane.id) && laneIds.has(tgtLane.id)) {
1699
1777
  const goingDown = tAbs.y > sAbs.y;
1700
1778
  const sharedX = gapMidX(sAbs, sW, tAbs, tW);
@@ -1702,8 +1780,8 @@ function routeEdges(edges, layoutNodes, backEdgeIds, laneIds, poolIds) {
1702
1780
  const tgtLaneIdx = sortedLanes.findIndex((l) => l.id === tgtLane.id);
1703
1781
  const pts = [];
1704
1782
  if (goingDown) {
1705
- pts.push({ x: sCX, y: sAbs.y + sH });
1706
- pts.push({ x: sharedX, y: sAbs.y + sH });
1783
+ pts.push({ x: sAbs.x + sW, y: sCY });
1784
+ pts.push({ x: sharedX, y: sCY });
1707
1785
  const fromIdx = Math.min(srcLaneIdx, tgtLaneIdx);
1708
1786
  const toIdx = Math.max(srcLaneIdx, tgtLaneIdx);
1709
1787
  for (let i = fromIdx; i < toIdx; i++) {
@@ -1712,11 +1790,12 @@ function routeEdges(edges, layoutNodes, backEdgeIds, laneIds, poolIds) {
1712
1790
  pts.push({ x: sharedX, y: laneBot });
1713
1791
  }
1714
1792
  const lastY = pts[pts.length - 1].y;
1715
- pts.push({ x: tCX, y: lastY });
1716
- pts.push({ x: tCX, y: tAbs.y + tH });
1793
+ pts.push({ x: tAbs.x - EDGE_ROUTE_PAD, y: lastY });
1794
+ pts.push({ x: tAbs.x - EDGE_ROUTE_PAD, y: tCY });
1795
+ pts.push({ x: tAbs.x, y: tCY });
1717
1796
  } else {
1718
- pts.push({ x: sCX, y: sAbs.y });
1719
- pts.push({ x: sharedX, y: sAbs.y });
1797
+ pts.push({ x: sAbs.x + sW, y: sCY });
1798
+ pts.push({ x: sharedX, y: sCY });
1720
1799
  const fromIdx = Math.min(srcLaneIdx, tgtLaneIdx);
1721
1800
  const toIdx = Math.max(srcLaneIdx, tgtLaneIdx);
1722
1801
  for (let i = toIdx; i > fromIdx; i--) {
@@ -1725,17 +1804,18 @@ function routeEdges(edges, layoutNodes, backEdgeIds, laneIds, poolIds) {
1725
1804
  pts.push({ x: sharedX, y: laneTop });
1726
1805
  }
1727
1806
  const lastY = pts[pts.length - 1].y;
1728
- pts.push({ x: tCX, y: lastY });
1729
- pts.push({ x: tCX, y: tAbs.y });
1807
+ pts.push({ x: tAbs.x - EDGE_ROUTE_PAD, y: lastY });
1808
+ pts.push({ x: tAbs.x - EDGE_ROUTE_PAD, y: tCY });
1809
+ pts.push({ x: tAbs.x, y: tCY });
1730
1810
  }
1731
1811
  routingPoints = pts;
1732
1812
  } else {
1733
1813
  const sharedX = gapMidX(sAbs, sW, tAbs, tW);
1734
1814
  routingPoints = [
1735
- { x: sCX, y: sCY },
1815
+ { x: sAbs.x + sW, y: sCY },
1736
1816
  { x: sharedX, y: sCY },
1737
1817
  { x: sharedX, y: tCY },
1738
- { x: tCX, y: tCY }
1818
+ { x: tAbs.x, y: tCY }
1739
1819
  ];
1740
1820
  }
1741
1821
  } else if (Math.abs(sCY - tCY) <= SAME_ROW_THRESHOLD) {
@@ -1747,19 +1827,25 @@ function routeEdges(edges, layoutNodes, backEdgeIds, laneIds, poolIds) {
1747
1827
  const exitsTop = handle.includes("top");
1748
1828
  const exitsBottom = handle.includes("bottom");
1749
1829
  if (exitsTop || exitsBottom) {
1830
+ const exitY = exitsTop ? sAbs.y : sAbs.y + sH;
1831
+ const entryY = exitsTop ? tAbs.y + tH : tAbs.y;
1832
+ const corridorY = exitsTop ? Math.min(exitY, entryY) - EDGE_ROUTE_PAD : Math.max(exitY, entryY) + EDGE_ROUTE_PAD;
1750
1833
  routingPoints = [
1751
- { x: sCX, y: exitsTop ? sAbs.y : sAbs.y + sH },
1752
- { x: sCX, y: tCY },
1753
- { x: tCX, y: tCY },
1754
- { x: tCX, y: exitsTop ? tAbs.y + tH : tAbs.y }
1834
+ { x: sCX, y: exitY },
1835
+ { x: sCX, y: corridorY },
1836
+ { x: tCX, y: corridorY },
1837
+ { x: tCX, y: entryY }
1755
1838
  ];
1756
1839
  } else {
1757
1840
  const midX = routeMidX(sAbs, sW, tAbs, tW);
1841
+ const exitX = sAbs.x + sW;
1842
+ const entryX = tAbs.x;
1843
+ const corridorX = Math.max(midX, exitX + EDGE_ROUTE_PAD);
1758
1844
  routingPoints = [
1759
- { x: sAbs.x + sW, y: sCY },
1760
- { x: midX, y: sCY },
1761
- { x: midX, y: tCY },
1762
- { x: tAbs.x, y: tCY }
1845
+ { x: exitX, y: sCY },
1846
+ { x: corridorX, y: sCY },
1847
+ { x: corridorX, y: tCY },
1848
+ { x: entryX, y: tCY }
1763
1849
  ];
1764
1850
  }
1765
1851
  }
@@ -1768,16 +1854,19 @@ function routeEdges(edges, layoutNodes, backEdgeIds, laneIds, poolIds) {
1768
1854
  }
1769
1855
  var ARTIFACT_ABOVE_GAP = 16;
1770
1856
  var ARTIFACT_H_SPACING = 12;
1771
- function positionArtifacts(artifacts, resultNodes, edges) {
1857
+ function positionArtifacts(artifacts, resultNodes, edges, originalNodes) {
1772
1858
  if (artifacts.length === 0) return [];
1773
1859
  const byId = new Map(resultNodes.map((n) => [n.id, n]));
1774
1860
  const cache = /* @__PURE__ */ new Map();
1775
1861
  const absPos = (id) => absolutePos(id, byId, cache);
1862
+ const originalById = new Map(originalNodes.map((n) => [n.id, n]));
1863
+ const originalCache = /* @__PURE__ */ new Map();
1776
1864
  const artifactsByNode = /* @__PURE__ */ new Map();
1777
1865
  const ungrouped = [];
1866
+ const groups = [];
1778
1867
  for (const artifact of artifacts) {
1779
1868
  if (artifact.data.elementType === "Group") {
1780
- ungrouped.push(artifact);
1869
+ groups.push(artifact);
1781
1870
  continue;
1782
1871
  }
1783
1872
  const connEdge = edges.find((e) => {
@@ -1815,6 +1904,58 @@ function positionArtifacts(artifacts, resultNodes, edges) {
1815
1904
  desiredAbsX += nW(artifact) + ARTIFACT_H_SPACING;
1816
1905
  }
1817
1906
  }
1907
+ const nonArtifactOriginalNodes = originalNodes.filter(
1908
+ (node) => !LAYOUT_ARTIFACT_TYPES.has(node.data.elementType)
1909
+ );
1910
+ for (const group of groups) {
1911
+ const originalGroup = originalById.get(group.id);
1912
+ if (!originalGroup) {
1913
+ positioned.push(group);
1914
+ continue;
1915
+ }
1916
+ const groupRect = nodeRect(originalGroup, originalById, originalCache);
1917
+ const containedOriginalIds = nonArtifactOriginalNodes.filter((node) => node.id !== group.id).filter((node) => {
1918
+ if (node.parentId !== group.parentId) return false;
1919
+ return rectContainsRect(groupRect, nodeRect(node, originalById, originalCache));
1920
+ }).map((node) => node.id);
1921
+ if (containedOriginalIds.length === 0) {
1922
+ positioned.push(group);
1923
+ continue;
1924
+ }
1925
+ const containedLaidOut = containedOriginalIds.map((id) => byId.get(id)).filter((node) => !!node);
1926
+ if (containedLaidOut.length === 0) {
1927
+ positioned.push(group);
1928
+ continue;
1929
+ }
1930
+ const GROUP_PAD_X = 24;
1931
+ const GROUP_PAD_Y = 20;
1932
+ const bounds = containedLaidOut.reduce(
1933
+ (acc, node) => {
1934
+ const rect = nodeRect(node, byId, cache);
1935
+ return {
1936
+ left: Math.min(acc.left, rect.x),
1937
+ top: Math.min(acc.top, rect.y),
1938
+ right: Math.max(acc.right, rect.x + rect.width),
1939
+ bottom: Math.max(acc.bottom, rect.y + rect.height)
1940
+ };
1941
+ },
1942
+ { left: Number.POSITIVE_INFINITY, top: Number.POSITIVE_INFINITY, right: Number.NEGATIVE_INFINITY, bottom: Number.NEGATIVE_INFINITY }
1943
+ );
1944
+ const parentAbsP = group.parentId ? absPos(group.parentId) : { x: 0, y: 0 };
1945
+ positioned.push({
1946
+ ...group,
1947
+ position: {
1948
+ x: bounds.left - GROUP_PAD_X - parentAbsP.x,
1949
+ y: bounds.top - GROUP_PAD_Y - parentAbsP.y
1950
+ },
1951
+ width: bounds.right - bounds.left + GROUP_PAD_X * 2,
1952
+ height: bounds.bottom - bounds.top + GROUP_PAD_Y * 2,
1953
+ measured: {
1954
+ width: bounds.right - bounds.left + GROUP_PAD_X * 2,
1955
+ height: bounds.bottom - bounds.top + GROUP_PAD_Y * 2
1956
+ }
1957
+ });
1958
+ }
1818
1959
  return positioned;
1819
1960
  }
1820
1961
  async function bpmnCustomLayout(nodes, edges) {
@@ -1849,8 +1990,8 @@ async function bpmnCustomLayout(nodes, edges) {
1849
1990
  if (pools.length === 0) {
1850
1991
  const { bpmnElkLayout: bpmnElkLayout2 } = await Promise.resolve().then(() => (init_elk(), elk_exports));
1851
1992
  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 };
1993
+ const posArtifacts = positionArtifacts(artifacts, elkResult.nodes, edges, nodes);
1994
+ return { nodes: sortNodesParentFirst([...elkResult.nodes, ...posArtifacts]), edges: elkResult.edges };
1854
1995
  }
1855
1996
  const poolIds = new Set(pools.map((p) => p.id));
1856
1997
  const allLaneIds = new Set(lanes.map((l) => l.id));
@@ -1893,8 +2034,9 @@ async function bpmnCustomLayout(nodes, edges) {
1893
2034
  const layoutted = new Set(resultNodes.map((n) => n.id));
1894
2035
  const freeNodes = workingMainNodes.filter((n) => !layoutted.has(n.id));
1895
2036
  if (freeNodes.length > 0) {
2037
+ const freeNodeIds = new Set(freeNodes.map((n) => n.id));
1896
2038
  const freeEdges = edges.filter(
1897
- (e) => freeNodes.some((n) => n.id === e.source || n.id === e.target)
2039
+ (e) => freeNodeIds.has(e.source) && freeNodeIds.has(e.target)
1898
2040
  );
1899
2041
  try {
1900
2042
  const { bpmnElkLayout: bpmnElkLayout2 } = await Promise.resolve().then(() => (init_elk(), elk_exports));
@@ -1918,9 +2060,9 @@ async function bpmnCustomLayout(nodes, edges) {
1918
2060
  }
1919
2061
  }
1920
2062
  const routedEdges = routeEdges(edges, resultNodes, allBackEdgeIds, allLaneIds, poolIds);
1921
- const positionedArtifacts = positionArtifacts(artifacts, resultNodes, edges);
2063
+ const positionedArtifacts = positionArtifacts(artifacts, resultNodes, edges, nodes);
1922
2064
  return {
1923
- nodes: [...resultNodes, ...positionedArtifacts],
2065
+ nodes: sortNodesParentFirst([...resultNodes, ...positionedArtifacts]),
1924
2066
  edges: routedEdges
1925
2067
  };
1926
2068
  }