@aranzatech/diagrams-bpmn 0.3.3 → 0.3.5

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/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export { getAllowedEventTriggers } from './chunk-JEGYVEJO.js';
2
2
  export { AnnotationNode, BPMN_NODE_TYPES, BoundaryEventNode, CallChoreographyNode, CallConversationNode, ChoreographyTaskNode, ConversationNode, DataInputNode, DataObjectNode, DataObjectReferenceNode, DataOutputNode, DataStoreNode, DataStoreReferenceNode, EndEventNode, GatewayNode, GroupNode, IntermediateCatchEventNode, IntermediateThrowEventNode, LaneNode, PoolNode, StartEventNode, SubChoreographyNode, SubConversationNode, SubProcessNode, TaskNode } from './chunk-X54NHLBA.js';
3
- export { AssociationEdge, BPMN_EDGE_TYPES, ConversationLinkEdge, DataAssociationEdge, MessageFlowEdge, SequenceFlowEdge } from './chunk-CPFUQM6H.js';
3
+ export { AssociationEdge, BPMN_EDGE_TYPES, ConversationLinkEdge, DataAssociationEdge, MessageFlowEdge, SequenceFlowEdge } from './chunk-JFYWN6QH.js';
4
4
  import './chunk-PDTXM32P.js';
5
5
  export { parseBpmnXml, serializeBpmnXml } from './chunk-NYIYQUGX.js';
6
6
  import './chunk-77L6O76M.js';
@@ -1576,23 +1576,44 @@ function layoutPool(pool, lanes, content, allEdges) {
1576
1576
  laneStats.set(laneId, { minRow, maxRow, rowCount, height });
1577
1577
  }
1578
1578
  }
1579
- const maxCol = Math.max(0, ...[...columns.values()]);
1580
- const colW = /* @__PURE__ */ new Map();
1581
- for (let c = 0; c <= maxCol; c++) colW.set(c, 0);
1582
- for (const node of mainContent) {
1583
- const c = columns.get(node.id) ?? 0;
1584
- colW.set(c, Math.max(colW.get(c) ?? 0, layoutW(node)));
1585
- }
1586
- const colX = /* @__PURE__ */ new Map();
1587
- let cumX = 0;
1588
- for (let c = 0; c <= maxCol; c++) {
1589
- colX.set(c, cumX);
1590
- cumX += (colW.get(c) ?? 120) + COL_GAP;
1579
+ const laneColumnLayouts = /* @__PURE__ */ new Map();
1580
+ for (const laneId of laneIds) {
1581
+ const laneNodes = mainContent.filter(
1582
+ (node) => (nodeLaneId.get(node.id) ?? "_pool_") === laneId
1583
+ );
1584
+ const usedCols = [...new Set(laneNodes.map((node) => columns.get(node.id) ?? 0))].sort((a, b) => a - b);
1585
+ const colW = /* @__PURE__ */ new Map();
1586
+ for (const col of usedCols) colW.set(col, 0);
1587
+ for (const node of laneNodes) {
1588
+ const col = columns.get(node.id) ?? 0;
1589
+ colW.set(col, Math.max(colW.get(col) ?? 0, layoutW(node)));
1590
+ }
1591
+ const colX = /* @__PURE__ */ new Map();
1592
+ let laneCumX = 0;
1593
+ for (const col of usedCols) {
1594
+ colX.set(col, laneCumX);
1595
+ laneCumX += (colW.get(col) ?? 120) + COL_GAP;
1596
+ }
1597
+ laneColumnLayouts.set(laneId, {
1598
+ colW,
1599
+ colX,
1600
+ contentW: usedCols.length > 0 ? laneCumX - COL_GAP : 0
1601
+ });
1591
1602
  }
1592
- const contentW = cumX - COL_GAP;
1593
- const innerW = LANE_LABEL_W + LANE_H_PAD + contentW + LANE_H_PAD;
1603
+ const baseLaneInnerW = Math.max(
1604
+ 0,
1605
+ ...laneIds.filter((laneId) => laneId !== "_pool_").map((laneId) => {
1606
+ const contentW = laneColumnLayouts.get(laneId)?.contentW ?? 0;
1607
+ return LANE_LABEL_W + LANE_H_PAD + contentW + LANE_H_PAD;
1608
+ })
1609
+ );
1610
+ const basePoolInnerW = Math.max(
1611
+ 0,
1612
+ ...laneIds.filter((laneId) => laneId === "_pool_").map((laneId) => (laneColumnLayouts.get(laneId)?.contentW ?? 0) + POOL_H_PAD * 2)
1613
+ );
1614
+ const innerW = Math.max(baseLaneInnerW, basePoolInnerW);
1594
1615
  const poolW = Math.max(POOL_MIN_W, innerW + POOL_INNER_PAD * 2);
1595
- const laneW = poolW - POOL_INNER_PAD * 2;
1616
+ let laneW = poolW - POOL_INNER_PAD * 2;
1596
1617
  const laneY = /* @__PURE__ */ new Map();
1597
1618
  let cumY = POOL_INNER_PAD;
1598
1619
  for (let i = 0; i < laneIds.length; i++) {
@@ -1607,10 +1628,11 @@ function layoutPool(pool, lanes, content, allEdges) {
1607
1628
  const r = rows.get(node.id) ?? 0;
1608
1629
  const laneId = nodeLaneId.get(node.id) ?? "_pool_";
1609
1630
  const stat = laneStats.get(laneId);
1631
+ const laneLayout = laneColumnLayouts.get(laneId);
1610
1632
  const lYOff = laneY.get(laneId) ?? 0;
1611
1633
  const lw = layoutW(node);
1612
1634
  const lh = layoutH(node);
1613
- const colOffset = (colX.get(c) ?? 0) + (colW.get(c) ?? 120) / 2 - lw / 2;
1635
+ const colOffset = (laneLayout?.colX.get(c) ?? 0) + (laneLayout?.colW.get(c) ?? 120) / 2 - lw / 2;
1614
1636
  const rowOffset = (r - stat.minRow) * (ROW_HEIGHT + ROW_GAP) + ROW_HEIGHT / 2 - lh / 2;
1615
1637
  const contentH_stat = stat.rowCount * ROW_HEIGHT + Math.max(0, stat.rowCount - 1) * ROW_GAP;
1616
1638
  const vertTopOffset = Math.max(LANE_V_PAD, (stat.height - contentH_stat) / 2);
@@ -1619,8 +1641,94 @@ function layoutPool(pool, lanes, content, allEdges) {
1619
1641
  const y = isLaneChild ? vertTopOffset + rowOffset : lYOff + vertTopOffset + rowOffset;
1620
1642
  return applyLayoutMinSize({ ...node, position: { x, y } });
1621
1643
  });
1644
+ const handoffAdjustedContent = [...positionedContent];
1645
+ const nodeIndexById = new Map(handoffAdjustedContent.map((node, index) => [node.id, index]));
1646
+ const outgoingBySource = /* @__PURE__ */ new Map();
1647
+ for (const edge of fwdEdges) {
1648
+ if (!outgoingBySource.has(edge.source)) outgoingBySource.set(edge.source, []);
1649
+ outgoingBySource.get(edge.source).push(edge);
1650
+ }
1651
+ const crossLaneEdges = fwdEdges.filter((edge) => {
1652
+ const srcLane = nodeLaneId.get(edge.source) ?? "_pool_";
1653
+ const tgtLane = nodeLaneId.get(edge.target) ?? "_pool_";
1654
+ return srcLane !== tgtLane;
1655
+ }).sort(
1656
+ (a, b) => (columns.get(a.target) ?? 0) - (columns.get(b.target) ?? 0) || (columns.get(a.source) ?? 0) - (columns.get(b.source) ?? 0)
1657
+ );
1658
+ for (const edge of crossLaneEdges) {
1659
+ const srcIndex = nodeIndexById.get(edge.source);
1660
+ const tgtIndex = nodeIndexById.get(edge.target);
1661
+ if (srcIndex == null || tgtIndex == null) continue;
1662
+ const srcNode = handoffAdjustedContent[srcIndex];
1663
+ const tgtNode = handoffAdjustedContent[tgtIndex];
1664
+ const tgtLaneId = nodeLaneId.get(tgtNode.id) ?? "_pool_";
1665
+ const tgtCol = columns.get(tgtNode.id) ?? 0;
1666
+ 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);
1667
+ const siblingAlignedX = siblingTargets.reduce(
1668
+ (max, node) => Math.max(max, node.position.x),
1669
+ Number.NEGATIVE_INFINITY
1670
+ );
1671
+ const minTargetX = Math.max(
1672
+ siblingAlignedX,
1673
+ srcNode.position.x + layoutW(srcNode) / 2 + layoutW(tgtNode) / 2 + COL_GAP
1674
+ );
1675
+ if (tgtNode.position.x >= minTargetX) continue;
1676
+ const delta = minTargetX - tgtNode.position.x;
1677
+ for (let i = 0; i < handoffAdjustedContent.length; i++) {
1678
+ const candidate = handoffAdjustedContent[i];
1679
+ if ((nodeLaneId.get(candidate.id) ?? "_pool_") !== tgtLaneId) continue;
1680
+ if ((columns.get(candidate.id) ?? 0) < tgtCol) continue;
1681
+ handoffAdjustedContent[i] = {
1682
+ ...candidate,
1683
+ position: {
1684
+ x: candidate.position.x + delta,
1685
+ y: candidate.position.y
1686
+ }
1687
+ };
1688
+ }
1689
+ }
1690
+ for (const [sourceId, outgoing] of outgoingBySource) {
1691
+ if (outgoing.length < 2) continue;
1692
+ const hasCrossLaneSibling = outgoing.some((edge) => {
1693
+ const srcLane = nodeLaneId.get(edge.source) ?? "_pool_";
1694
+ const tgtLane = nodeLaneId.get(edge.target) ?? "_pool_";
1695
+ return srcLane !== tgtLane;
1696
+ });
1697
+ if (!hasCrossLaneSibling) continue;
1698
+ const siblingsByCol = /* @__PURE__ */ new Map();
1699
+ for (const edge of outgoing) {
1700
+ const col = columns.get(edge.target) ?? 0;
1701
+ const node = handoffAdjustedContent[nodeIndexById.get(edge.target) ?? -1];
1702
+ if (!node) continue;
1703
+ if (!siblingsByCol.has(col)) siblingsByCol.set(col, []);
1704
+ siblingsByCol.get(col).push(node);
1705
+ }
1706
+ for (const [col, siblings] of siblingsByCol) {
1707
+ if (siblings.length < 2) continue;
1708
+ const alignedX = Math.max(...siblings.map((node) => node.position.x));
1709
+ for (let i = 0; i < handoffAdjustedContent.length; i++) {
1710
+ const candidate = handoffAdjustedContent[i];
1711
+ if (!siblings.some((node) => node.id === candidate.id)) continue;
1712
+ const laneId = nodeLaneId.get(candidate.id) ?? "_pool_";
1713
+ for (let j = 0; j < handoffAdjustedContent.length; j++) {
1714
+ const maybeShift = handoffAdjustedContent[j];
1715
+ if ((nodeLaneId.get(maybeShift.id) ?? "_pool_") !== laneId) continue;
1716
+ if ((columns.get(maybeShift.id) ?? 0) < col) continue;
1717
+ const delta = alignedX - candidate.position.x;
1718
+ if (delta <= 0) continue;
1719
+ handoffAdjustedContent[j] = {
1720
+ ...maybeShift,
1721
+ position: {
1722
+ x: maybeShift.position.x + delta,
1723
+ y: maybeShift.position.y
1724
+ }
1725
+ };
1726
+ }
1727
+ }
1728
+ }
1729
+ }
1622
1730
  const NODE_MIN_GAP = 24;
1623
- const resolvedContent = [...positionedContent];
1731
+ const resolvedContent = [...handoffAdjustedContent];
1624
1732
  for (const laneId of laneIds) {
1625
1733
  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);
1626
1734
  for (let k = 1; k < laneNodeIndices.length; k++) {
@@ -1642,6 +1750,15 @@ function layoutPool(pool, lanes, content, allEdges) {
1642
1750
  }
1643
1751
  }
1644
1752
  const positionedBoundaries = repositionBoundaryEvents(boundaryEvents, resolvedContent);
1753
+ 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);
1754
+ 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);
1755
+ const boundaryRight = positionedBoundaries.reduce(
1756
+ (max, node) => Math.max(max, node.position.x + nW(node) + (hasLanes ? LANE_H_PAD : POOL_H_PAD)),
1757
+ 0
1758
+ );
1759
+ const finalInnerW = Math.max(innerW, laneChildRight, poolChildRight, boundaryRight);
1760
+ const finalPoolW = Math.max(POOL_MIN_W, finalInnerW + POOL_INNER_PAD * 2);
1761
+ laneW = finalPoolW - POOL_INNER_PAD * 2;
1645
1762
  const positionedLanes = hasLanes ? sortedLanes.map((lane) => ({
1646
1763
  ...lane,
1647
1764
  position: { x: POOL_INNER_PAD, y: laneY.get(lane.id) ?? POOL_INNER_PAD },
@@ -1650,7 +1767,7 @@ function layoutPool(pool, lanes, content, allEdges) {
1650
1767
  })) : [];
1651
1768
  return {
1652
1769
  nodes: [...resolvedContent, ...positionedBoundaries, ...positionedLanes],
1653
- width: poolW,
1770
+ width: finalPoolW,
1654
1771
  height: poolH
1655
1772
  };
1656
1773
  }
@@ -1691,6 +1808,33 @@ function nodeRect(node, byId, cache) {
1691
1808
  function rectContainsRect(outer, inner) {
1692
1809
  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
1810
  }
1811
+ function sortNodesParentFirst(nodes) {
1812
+ const byId = new Map(nodes.map((node) => [node.id, node]));
1813
+ const memo = /* @__PURE__ */ new Map();
1814
+ const depthOf = (node) => {
1815
+ const cached = memo.get(node.id);
1816
+ if (cached != null) return cached;
1817
+ if (!node.parentId) {
1818
+ memo.set(node.id, 0);
1819
+ return 0;
1820
+ }
1821
+ const parent = byId.get(node.parentId);
1822
+ const depth = parent ? depthOf(parent) + 1 : 0;
1823
+ memo.set(node.id, depth);
1824
+ return depth;
1825
+ };
1826
+ return [...nodes].sort((a, b) => {
1827
+ const depthDiff = depthOf(a) - depthOf(b);
1828
+ if (depthDiff !== 0) return depthDiff;
1829
+ const ay = a.position?.y ?? 0;
1830
+ const by = b.position?.y ?? 0;
1831
+ if (ay !== by) return ay - by;
1832
+ const ax = a.position?.x ?? 0;
1833
+ const bx = b.position?.x ?? 0;
1834
+ if (ax !== bx) return ax - bx;
1835
+ return a.id.localeCompare(b.id);
1836
+ });
1837
+ }
1694
1838
  function gapMidX(sAbs, sW, tAbs, tW) {
1695
1839
  const leftRightEdge = Math.min(sAbs.x + sW, tAbs.x + tW);
1696
1840
  const rightLeftEdge = Math.max(sAbs.x, tAbs.x);
@@ -1964,7 +2108,7 @@ async function bpmnCustomLayout(nodes, edges) {
1964
2108
  const { bpmnElkLayout: bpmnElkLayout2 } = await Promise.resolve().then(() => (init_elk(), elk_exports));
1965
2109
  const elkResult = await bpmnElkLayout2(nodes.filter((n) => !LAYOUT_ARTIFACT_TYPES.has(n.data.elementType)), edges);
1966
2110
  const posArtifacts = positionArtifacts(artifacts, elkResult.nodes, edges, nodes);
1967
- return { nodes: [...elkResult.nodes, ...posArtifacts], edges: elkResult.edges };
2111
+ return { nodes: sortNodesParentFirst([...elkResult.nodes, ...posArtifacts]), edges: elkResult.edges };
1968
2112
  }
1969
2113
  const poolIds = new Set(pools.map((p) => p.id));
1970
2114
  const allLaneIds = new Set(lanes.map((l) => l.id));
@@ -2035,7 +2179,7 @@ async function bpmnCustomLayout(nodes, edges) {
2035
2179
  const routedEdges = routeEdges(edges, resultNodes, allBackEdgeIds, allLaneIds, poolIds);
2036
2180
  const positionedArtifacts = positionArtifacts(artifacts, resultNodes, edges, nodes);
2037
2181
  return {
2038
- nodes: [...resultNodes, ...positionedArtifacts],
2182
+ nodes: sortNodesParentFirst([...resultNodes, ...positionedArtifacts]),
2039
2183
  edges: routedEdges
2040
2184
  };
2041
2185
  }