@aranzatech/diagrams-bpmn 0.2.14 → 0.3.0

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.
Files changed (81) hide show
  1. package/README.md +34 -4
  2. package/dist/{catalog-xOMF2ifW.d.cts → catalog-DAGDhO-D.d.cts} +1 -1
  3. package/dist/{catalog-CK3_4cOb.d.ts → catalog-Q1QmKLDD.d.ts} +1 -1
  4. package/dist/{chunk-YUE5EM3W.js → chunk-334WN4JZ.js} +276 -107
  5. package/dist/chunk-334WN4JZ.js.map +1 -0
  6. package/dist/chunk-77L6O76M.js +3 -0
  7. package/dist/chunk-77L6O76M.js.map +1 -0
  8. package/dist/{chunk-QSMP34CT.js → chunk-CPFUQM6H.js} +80 -44
  9. package/dist/chunk-CPFUQM6H.js.map +1 -0
  10. package/dist/chunk-FFWJA5BV.js +163 -0
  11. package/dist/chunk-FFWJA5BV.js.map +1 -0
  12. package/dist/{chunk-FBTGIYZS.js → chunk-JEGYVEJO.js} +80 -3
  13. package/dist/{chunk-FBTGIYZS.js.map → chunk-JEGYVEJO.js.map} +1 -1
  14. package/dist/chunk-TB6V4S5N.js +104 -0
  15. package/dist/chunk-TB6V4S5N.js.map +1 -0
  16. package/dist/{chunk-IMW6RG6F.js → chunk-X54NHLBA.js} +43 -190
  17. package/dist/chunk-X54NHLBA.js.map +1 -0
  18. package/dist/{chunk-UAWLUDKC.js → chunk-YAYZW45I.js} +481 -26
  19. package/dist/chunk-YAYZW45I.js.map +1 -0
  20. package/dist/edges/index.cjs +78 -42
  21. package/dist/edges/index.cjs.map +1 -1
  22. package/dist/edges/index.js +1 -1
  23. package/dist/elements/index.cjs +78 -0
  24. package/dist/elements/index.cjs.map +1 -1
  25. package/dist/elements/index.d.cts +24 -5
  26. package/dist/elements/index.d.ts +24 -5
  27. package/dist/elements/index.js +1 -1
  28. package/dist/elk-QT7H4252.js +6 -0
  29. package/dist/elk-QT7H4252.js.map +1 -0
  30. package/dist/extensions/index.cjs +108 -0
  31. package/dist/extensions/index.cjs.map +1 -0
  32. package/dist/extensions/index.d.cts +145 -0
  33. package/dist/extensions/index.d.ts +145 -0
  34. package/dist/extensions/index.js +4 -0
  35. package/dist/extensions/index.js.map +1 -0
  36. package/dist/index.cjs +1067 -358
  37. package/dist/index.cjs.map +1 -1
  38. package/dist/index.d.cts +7 -5
  39. package/dist/index.d.ts +7 -5
  40. package/dist/index.js +7 -5
  41. package/dist/index.js.map +1 -1
  42. package/dist/layout/index.cjs +1396 -749
  43. package/dist/layout/index.cjs.map +1 -1
  44. package/dist/layout/index.d.cts +10 -4
  45. package/dist/layout/index.d.ts +10 -4
  46. package/dist/layout/index.js +543 -104
  47. package/dist/layout/index.js.map +1 -1
  48. package/dist/modeling/index.cjs +490 -23
  49. package/dist/modeling/index.cjs.map +1 -1
  50. package/dist/modeling/index.d.cts +81 -6
  51. package/dist/modeling/index.d.ts +81 -6
  52. package/dist/modeling/index.js +1 -1
  53. package/dist/nodes/index.cjs +42 -188
  54. package/dist/nodes/index.cjs.map +1 -1
  55. package/dist/nodes/index.d.cts +1 -1
  56. package/dist/nodes/index.d.ts +1 -1
  57. package/dist/nodes/index.js +1 -1
  58. package/dist/types-BX_o95GC.d.cts +40 -0
  59. package/dist/{types-y-ZbX-ff.d.cts → types-BYN4Zuee.d.cts} +15 -1
  60. package/dist/{types-y-ZbX-ff.d.ts → types-BYN4Zuee.d.ts} +15 -1
  61. package/dist/{types-jIDz306Y.d.cts → types-CggktCqr.d.cts} +4 -1
  62. package/dist/types-D7zel9dq.d.ts +40 -0
  63. package/dist/{types-DG5yPKld.d.ts → types-DmDODKlh.d.ts} +4 -1
  64. package/dist/validation/index.cjs +81 -125
  65. package/dist/validation/index.cjs.map +1 -1
  66. package/dist/validation/index.d.cts +22 -5
  67. package/dist/validation/index.d.ts +22 -5
  68. package/dist/validation/index.js +82 -126
  69. package/dist/validation/index.js.map +1 -1
  70. package/dist/xml/index.cjs +319 -49
  71. package/dist/xml/index.cjs.map +1 -1
  72. package/dist/xml/index.d.cts +5 -3
  73. package/dist/xml/index.d.ts +5 -3
  74. package/dist/xml/index.js +2 -1
  75. package/package.json +6 -1
  76. package/dist/chunk-IMW6RG6F.js.map +0 -1
  77. package/dist/chunk-QSMP34CT.js.map +0 -1
  78. package/dist/chunk-UAWLUDKC.js.map +0 -1
  79. package/dist/chunk-YUE5EM3W.js.map +0 -1
  80. package/dist/guards-C70uIY_O.d.cts +0 -16
  81. package/dist/guards-foB6XIfZ.d.ts +0 -16
@@ -694,7 +694,9 @@ function createBpmnNode(options) {
694
694
  height: options.height ?? size.height,
695
695
  zIndex: getBpmnNodeZIndex(options.elementType),
696
696
  ...options.parentId ? { parentId: options.parentId } : {},
697
- ...options.elementType === "Lane" && options.parentId ? { extent: "parent" } : {},
697
+ // extent:"parent" is intentionally omitted for Lane it blocks resize beyond
698
+ // the Pool boundary before the Pool/Lane coupling can expand the Pool.
699
+ // Lane containment during drag is handled programmatically in handleNodeDragStop.
698
700
  ...dragHandle ? { dragHandle } : {}
699
701
  };
700
702
  }
@@ -711,12 +713,24 @@ function withBpmnNodeZIndexes(nodes) {
711
713
  });
712
714
  }
713
715
  var BPMN_POOL_LANE_LAYOUT = {
714
- poolHeaderSize: 30,
715
- laneHeaderSize: 24,
716
+ // Pool inner padding on all sides (no left label strip).
717
+ // 8px = pool border (2px) + 6px visible gap.
718
+ poolPad: 8,
719
+ /** @deprecated use poolPad */
720
+ poolHeaderSize: 8,
721
+ // Lane left label strip (vertical text).
722
+ laneHeaderSize: 28,
716
723
  laneGap: 0,
717
724
  verticalPoolHeaderSize: 28,
718
725
  minLaneSize: 96
719
726
  };
727
+ var BPMN_POOL_LANE_STACK_LAYOUT = {
728
+ poolInnerPad: 8,
729
+ laneGap: 8,
730
+ minLaneWidth: 240,
731
+ minLaneHeight: 80,
732
+ defaultLaneHeight: 120
733
+ };
720
734
  function getBpmnDragHandleSelector(elementType) {
721
735
  if (elementType === "Pool") return ".pool-drag-handle";
722
736
  if (elementType === "Lane") return ".lane-drag-handle";
@@ -787,7 +801,9 @@ function inferBpmnEdgeType(state, sourceId, targetId) {
787
801
  if (source.data.elementType === "Conversation" || source.data.elementType === "SubConversation" || source.data.elementType === "CallConversation" || target.data.elementType === "Conversation" || target.data.elementType === "SubConversation" || target.data.elementType === "CallConversation") {
788
802
  return "conversationLink";
789
803
  }
790
- if (source.parentId && target.parentId && source.parentId !== target.parentId) {
804
+ const sourcePoolId = getAncestorContainerId(state, source, "Pool");
805
+ const targetPoolId = getAncestorContainerId(state, target, "Pool");
806
+ if (sourcePoolId && targetPoolId && sourcePoolId !== targetPoolId) {
791
807
  return "messageFlow";
792
808
  }
793
809
  return "sequenceFlow";
@@ -836,6 +852,67 @@ function getBpmnPoolLanes(state, poolId) {
836
852
  (node) => node.data.elementType === "Lane"
837
853
  );
838
854
  }
855
+ function getBpmnNodeBounds(state, node) {
856
+ const position = getBpmnNodeAbsolutePosition(state, node) ?? node.position;
857
+ const size = getBpmnNodeSize(node);
858
+ return {
859
+ ...position,
860
+ width: size.width,
861
+ height: size.height
862
+ };
863
+ }
864
+ var BPMN_BOUNDARY_ATTACH_MARGIN = 32;
865
+ function clampBoundaryCoordinate(value, min, max) {
866
+ return Math.min(max, Math.max(min, value));
867
+ }
868
+ function isPointInsideExpandedBounds(point, origin, size) {
869
+ return point.x >= origin.x - BPMN_BOUNDARY_ATTACH_MARGIN && point.x <= origin.x + size.width + BPMN_BOUNDARY_ATTACH_MARGIN && point.y >= origin.y - BPMN_BOUNDARY_ATTACH_MARGIN && point.y <= origin.y + size.height + BPMN_BOUNDARY_ATTACH_MARGIN;
870
+ }
871
+ function snapBoundaryCenterToHostBorder(center, hostOrigin, hostSize) {
872
+ const distances = [
873
+ { side: "left", value: Math.abs(center.x - hostOrigin.x) },
874
+ { side: "right", value: Math.abs(center.x - (hostOrigin.x + hostSize.width)) },
875
+ { side: "top", value: Math.abs(center.y - hostOrigin.y) },
876
+ { side: "bottom", value: Math.abs(center.y - (hostOrigin.y + hostSize.height)) }
877
+ ].sort((a, b) => a.value - b.value);
878
+ const side = distances[0]?.side;
879
+ if (side === "left") {
880
+ return { x: hostOrigin.x, y: clampBoundaryCoordinate(center.y, hostOrigin.y, hostOrigin.y + hostSize.height) };
881
+ }
882
+ if (side === "right") {
883
+ return { x: hostOrigin.x + hostSize.width, y: clampBoundaryCoordinate(center.y, hostOrigin.y, hostOrigin.y + hostSize.height) };
884
+ }
885
+ if (side === "top") {
886
+ return { x: clampBoundaryCoordinate(center.x, hostOrigin.x, hostOrigin.x + hostSize.width), y: hostOrigin.y };
887
+ }
888
+ return {
889
+ x: clampBoundaryCoordinate(center.x, hostOrigin.x, hostOrigin.x + hostSize.width),
890
+ y: hostOrigin.y + hostSize.height
891
+ };
892
+ }
893
+ function findBpmnLaneAt(state, position) {
894
+ return state.nodes.find((node) => {
895
+ if (node.data.elementType !== "Lane") return false;
896
+ const bounds = getBpmnNodeBounds(state, node);
897
+ return position.x >= bounds.x && position.x <= bounds.x + bounds.width && position.y >= bounds.y && position.y <= bounds.y + bounds.height;
898
+ });
899
+ }
900
+ function getAncestorLaneId(state, node) {
901
+ let current = node;
902
+ while (current) {
903
+ if (current.data.elementType === "Lane") return current.id;
904
+ current = current.parentId ? diagramsCore.getNode(state, current.parentId) : void 0;
905
+ }
906
+ return void 0;
907
+ }
908
+ function getAncestorContainerId(state, node, elementType) {
909
+ let current = node;
910
+ while (current) {
911
+ if (current.data.elementType === elementType) return current.id;
912
+ current = current.parentId ? diagramsCore.getNode(state, current.parentId) : void 0;
913
+ }
914
+ return void 0;
915
+ }
839
916
  function getNodeDimension(node, axis) {
840
917
  return node[axis] ?? node.measured?.[axis] ?? getBpmnElementSize(node.data.elementType)[axis];
841
918
  }
@@ -843,17 +920,250 @@ function getBpmnLaneOrderPosition(lane, orientation) {
843
920
  const size = getBpmnNodeSize(lane);
844
921
  return orientation === "vertical" ? lane.position.x + size.width / 2 : lane.position.y + size.height / 2;
845
922
  }
923
+ function getBpmnPoolOrientation(pool) {
924
+ return pool.data.orientation === "vertical" ? "vertical" : "horizontal";
925
+ }
926
+ function getBpmnPoolLanesOrderedByStack(nodes, poolId, orientation) {
927
+ return nodes.filter((node) => node.parentId === poolId && node.data.elementType === "Lane").sort((a, b) => {
928
+ const aIndex = typeof a.data.laneIndex === "number" ? a.data.laneIndex : void 0;
929
+ const bIndex = typeof b.data.laneIndex === "number" ? b.data.laneIndex : void 0;
930
+ if (aIndex !== void 0 || bIndex !== void 0) return (aIndex ?? 0) - (bIndex ?? 0);
931
+ return orientation === "vertical" ? (a.position?.x ?? 0) - (b.position?.x ?? 0) : (a.position?.y ?? 0) - (b.position?.y ?? 0);
932
+ });
933
+ }
934
+ function layoutBpmnPoolLaneNodesPreservingHeights(nodes, poolId) {
935
+ const pool = nodes.find((node) => node.id === poolId && node.data.elementType === "Pool");
936
+ if (!pool) return nodes;
937
+ const orientation = getBpmnPoolOrientation(pool);
938
+ const lanes = getBpmnPoolLanesOrderedByStack(nodes, pool.id, orientation);
939
+ if (lanes.length === 0) return withBpmnNodeZIndexes(nodes);
940
+ const poolW = pool.measured?.width ?? pool.width ?? 720;
941
+ const poolH = pool.measured?.height ?? pool.height ?? 200;
942
+ const pad = BPMN_POOL_LANE_STACK_LAYOUT.poolInnerPad;
943
+ const gap = BPMN_POOL_LANE_STACK_LAYOUT.laneGap;
944
+ const minLaneW = BPMN_POOL_LANE_STACK_LAYOUT.minLaneWidth;
945
+ const minLaneH = BPMN_POOL_LANE_STACK_LAYOUT.minLaneHeight;
946
+ const defaultLaneH = BPMN_POOL_LANE_STACK_LAYOUT.defaultLaneHeight;
947
+ if (orientation === "vertical") {
948
+ const laneWidth2 = Math.max(
949
+ minLaneW,
950
+ Math.floor((poolW - pad * 2 - gap * Math.max(0, lanes.length - 1)) / Math.max(1, lanes.length))
951
+ );
952
+ const laneHeight = Math.max(minLaneH, poolH - pad * 2);
953
+ let cumX = pad;
954
+ const laneMap2 = new Map(
955
+ lanes.map((lane, index) => {
956
+ const nextLane = {
957
+ ...lane,
958
+ position: { x: cumX, y: pad },
959
+ width: laneWidth2,
960
+ height: laneHeight,
961
+ parentId: pool.id,
962
+ data: { ...lane.data, orientation: "vertical", laneIndex: index }
963
+ };
964
+ cumX += laneWidth2 + gap;
965
+ return [lane.id, nextLane];
966
+ })
967
+ );
968
+ const requiredPoolW = cumX - gap + pad;
969
+ return withBpmnNodeZIndexes(
970
+ nodes.map(
971
+ (node) => laneMap2.get(node.id) ?? (node.id === pool.id ? { ...pool, width: Math.max(requiredPoolW, poolW) } : node)
972
+ )
973
+ );
974
+ }
975
+ const laneWidth = Math.max(minLaneW, poolW - pad * 2);
976
+ let cumY = pad;
977
+ const laneMap = new Map(
978
+ lanes.map((lane, index) => {
979
+ const laneHeight = Math.max(minLaneH, lane.measured?.height ?? lane.height ?? defaultLaneH);
980
+ const nextLane = {
981
+ ...lane,
982
+ position: { x: pad, y: cumY },
983
+ width: laneWidth,
984
+ height: laneHeight,
985
+ parentId: pool.id,
986
+ data: { ...lane.data, orientation: "horizontal", laneIndex: index }
987
+ };
988
+ cumY += laneHeight + gap;
989
+ return [lane.id, nextLane];
990
+ })
991
+ );
992
+ const requiredPoolH = cumY - gap + pad;
993
+ return withBpmnNodeZIndexes(
994
+ nodes.map(
995
+ (node) => laneMap.get(node.id) ?? (node.id === pool.id ? { ...pool, height: Math.max(requiredPoolH, poolH) } : node)
996
+ )
997
+ );
998
+ }
999
+ function reorderBpmnPoolLaneAfterDropPreservingHeights(nodes, laneId) {
1000
+ const lane = nodes.find((node) => node.id === laneId && node.data.elementType === "Lane");
1001
+ if (!lane?.parentId) return nodes;
1002
+ const pool = nodes.find((node) => node.id === lane.parentId && node.data.elementType === "Pool");
1003
+ if (!pool) return nodes;
1004
+ const orientation = getBpmnPoolOrientation(pool);
1005
+ const lanes = getBpmnPoolLanesOrderedByStack(nodes, pool.id, orientation);
1006
+ const moved = lanes.find((candidate) => candidate.id === lane.id);
1007
+ if (!moved) return layoutBpmnPoolLaneNodesPreservingHeights(nodes, pool.id);
1008
+ const withoutMoved = lanes.filter((candidate) => candidate.id !== lane.id);
1009
+ const movedCenter = orientation === "vertical" ? (lane.position?.x ?? 0) + (lane.width ?? 0) / 2 : (lane.position?.y ?? 0) + (lane.height ?? 0) / 2;
1010
+ const insertIndex = withoutMoved.findIndex((candidate) => {
1011
+ const candidateCenter = orientation === "vertical" ? (candidate.position?.x ?? 0) + (candidate.width ?? 0) / 2 : (candidate.position?.y ?? 0) + (candidate.height ?? 0) / 2;
1012
+ return movedCenter < candidateCenter;
1013
+ });
1014
+ const ordered = [...withoutMoved];
1015
+ ordered.splice(insertIndex === -1 ? ordered.length : insertIndex, 0, moved);
1016
+ const orderedMap = new Map(ordered.map((candidate, index) => [candidate.id, index]));
1017
+ return layoutBpmnPoolLaneNodesPreservingHeights(
1018
+ nodes.map(
1019
+ (node) => node.parentId === pool.id && node.data.elementType === "Lane" ? { ...node, data: { ...node.data, laneIndex: orderedMap.get(node.id) ?? 0 } } : node
1020
+ ),
1021
+ pool.id
1022
+ );
1023
+ }
1024
+ function getAppendedBpmnLaneFrame(nodes, poolOrId) {
1025
+ const pool = typeof poolOrId === "string" ? nodes.find((node) => node.id === poolOrId && node.data.elementType === "Pool") : poolOrId;
1026
+ if (!pool || pool.data.elementType !== "Pool") return null;
1027
+ const orientation = getBpmnPoolOrientation(pool);
1028
+ const existingLanes = getBpmnPoolLanesOrderedByStack(nodes, pool.id, orientation);
1029
+ const poolW = pool.measured?.width ?? pool.width ?? 600;
1030
+ const poolH = pool.measured?.height ?? pool.height ?? 400;
1031
+ const pad = BPMN_POOL_LANE_STACK_LAYOUT.poolInnerPad;
1032
+ const gap = BPMN_POOL_LANE_STACK_LAYOUT.laneGap;
1033
+ const minLaneW = BPMN_POOL_LANE_STACK_LAYOUT.minLaneWidth;
1034
+ const minLaneH = BPMN_POOL_LANE_STACK_LAYOUT.minLaneHeight;
1035
+ const defaultLaneH = BPMN_POOL_LANE_STACK_LAYOUT.defaultLaneHeight;
1036
+ if (orientation === "horizontal") {
1037
+ const lastLane2 = existingLanes[existingLanes.length - 1];
1038
+ return {
1039
+ position: {
1040
+ x: pad,
1041
+ y: lastLane2 ? (lastLane2.position?.y ?? pad) + (lastLane2.height ?? defaultLaneH) + gap : pad
1042
+ },
1043
+ width: Math.max(minLaneW, poolW - pad * 2),
1044
+ height: existingLanes.length === 0 ? Math.max(minLaneH, poolH - pad * 2) : defaultLaneH,
1045
+ laneIndex: existingLanes.length,
1046
+ orientation
1047
+ };
1048
+ }
1049
+ const lastLane = existingLanes[existingLanes.length - 1];
1050
+ return {
1051
+ position: {
1052
+ x: lastLane ? (lastLane.position?.x ?? pad) + (lastLane.width ?? defaultLaneH) + gap : pad,
1053
+ y: pad
1054
+ },
1055
+ width: existingLanes.length === 0 ? Math.max(minLaneW, poolW - pad * 2) : defaultLaneH,
1056
+ height: Math.max(minLaneH, poolH - pad * 2),
1057
+ laneIndex: existingLanes.length,
1058
+ orientation
1059
+ };
1060
+ }
1061
+ function getBpmnPoolLaneNodeMaxSize(state, nodeId) {
1062
+ const n = diagramsCore.getNode(state, nodeId);
1063
+ if (n?.data.elementType === "Lane" && n.parentId) {
1064
+ const pool = diagramsCore.getNode(state, n.parentId);
1065
+ if (pool) {
1066
+ const siblings = state.nodes.filter(
1067
+ (x) => x.parentId === n.parentId && x.data.elementType === "Lane" && x.id !== n.id
1068
+ );
1069
+ const poolH = pool.measured?.height ?? pool.height ?? 500;
1070
+ const siblingsMinH = siblings.length * BPMN_POOL_LANE_STACK_LAYOUT.minLaneHeight;
1071
+ const siblingGaps = siblings.length * BPMN_POOL_LANE_STACK_LAYOUT.laneGap;
1072
+ const maxH = Math.max(
1073
+ BPMN_POOL_LANE_STACK_LAYOUT.minLaneHeight,
1074
+ poolH - BPMN_POOL_LANE_STACK_LAYOUT.poolInnerPad * 2 - siblingsMinH - siblingGaps
1075
+ );
1076
+ return {
1077
+ width: (pool.width ?? 720) - BPMN_POOL_LANE_STACK_LAYOUT.poolInnerPad * 2,
1078
+ height: maxH
1079
+ };
1080
+ }
1081
+ }
1082
+ return void 0;
1083
+ }
1084
+ function getBpmnPoolLaneNodeMinSize(state, nodeId) {
1085
+ const n = diagramsCore.getNode(state, nodeId);
1086
+ if (n?.data.elementType === "Pool") {
1087
+ const lanes = state.nodes.filter((x) => x.parentId === nodeId && x.data.elementType === "Lane");
1088
+ if (lanes.length > 0) {
1089
+ const minW = Math.max(...lanes.map((l) => (l.width ?? 0) + BPMN_POOL_LANE_STACK_LAYOUT.poolInnerPad * 2));
1090
+ const minH = lanes.reduce((s, l) => s + (l.height ?? BPMN_POOL_LANE_STACK_LAYOUT.defaultLaneHeight), 0) + BPMN_POOL_LANE_STACK_LAYOUT.poolInnerPad * 2 + Math.max(0, lanes.length - 1) * BPMN_POOL_LANE_STACK_LAYOUT.laneGap;
1091
+ return { width: minW, height: minH };
1092
+ }
1093
+ }
1094
+ return void 0;
1095
+ }
1096
+ function applyBpmnPoolLaneDimensionChange(nodes, previousNodes, nodeId, width, height) {
1097
+ const node = nodes.find((candidate) => candidate.id === nodeId);
1098
+ const previousNode = previousNodes.find((candidate) => candidate.id === nodeId);
1099
+ if (!node) return nodes;
1100
+ const curW = previousNode?.measured?.width ?? previousNode?.width ?? 0;
1101
+ const curH = previousNode?.measured?.height ?? previousNode?.height ?? 0;
1102
+ if (Math.abs(width - curW) < 1 && Math.abs(height - curH) < 1) return nodes;
1103
+ const pad = BPMN_POOL_LANE_STACK_LAYOUT.poolInnerPad;
1104
+ const gap = BPMN_POOL_LANE_STACK_LAYOUT.laneGap;
1105
+ const minLaneW = BPMN_POOL_LANE_STACK_LAYOUT.minLaneWidth;
1106
+ const defaultLaneH = BPMN_POOL_LANE_STACK_LAYOUT.defaultLaneHeight;
1107
+ if (node.data.elementType === "Pool") {
1108
+ const targetLaneW = Math.max(minLaneW, width - pad * 2);
1109
+ return nodes.map(
1110
+ (candidate) => candidate.parentId === node.id && candidate.data.elementType === "Lane" ? {
1111
+ ...candidate,
1112
+ width: targetLaneW,
1113
+ measured: {
1114
+ width: targetLaneW,
1115
+ height: candidate.measured?.height ?? candidate.height ?? defaultLaneH
1116
+ },
1117
+ position: { x: pad, y: candidate.position?.y ?? pad }
1118
+ } : candidate
1119
+ );
1120
+ }
1121
+ if (node.data.elementType === "Lane" && node.parentId) {
1122
+ const pool = nodes.find((candidate) => candidate.id === node.parentId && candidate.data.elementType === "Pool");
1123
+ if (!pool) return nodes;
1124
+ const poolW = Math.max(width + pad * 2, pool.measured?.width ?? pool.width ?? 720);
1125
+ const sortedLanes = getBpmnPoolLanesOrderedByStack(nodes, node.parentId, "horizontal");
1126
+ let cumY = pad;
1127
+ const laneMap = /* @__PURE__ */ new Map();
1128
+ for (const lane of sortedLanes) {
1129
+ const laneH = lane.id === node.id ? height : lane.measured?.height ?? lane.height ?? defaultLaneH;
1130
+ laneMap.set(lane.id, {
1131
+ ...lane,
1132
+ width,
1133
+ height: laneH,
1134
+ measured: { width, height: laneH },
1135
+ position: { x: pad, y: cumY }
1136
+ });
1137
+ cumY += laneH + gap;
1138
+ }
1139
+ const newPoolH = cumY - gap + pad;
1140
+ return nodes.map((candidate) => {
1141
+ if (candidate.id === pool.id) {
1142
+ return {
1143
+ ...candidate,
1144
+ width: poolW,
1145
+ height: newPoolH,
1146
+ measured: { width: poolW, height: newPoolH }
1147
+ };
1148
+ }
1149
+ return laneMap.get(candidate.id) ?? candidate;
1150
+ });
1151
+ }
1152
+ return nodes;
1153
+ }
846
1154
  function resizeHorizontalBpmnLanes(lanes, pool) {
1155
+ const pad = BPMN_POOL_LANE_LAYOUT.poolPad;
847
1156
  const poolSize = getBpmnNodeSize(pool);
848
- const laneWidth = Math.max(BPMN_POOL_LANE_LAYOUT.minLaneSize, poolSize.width - BPMN_POOL_LANE_LAYOUT.poolHeaderSize);
849
- const laneHeight = Math.max(BPMN_POOL_LANE_LAYOUT.minLaneSize, poolSize.height / Math.max(1, lanes.length));
1157
+ const laneWidth = Math.max(BPMN_POOL_LANE_LAYOUT.minLaneSize, poolSize.width - pad * 2);
1158
+ const availH = Math.max(0, poolSize.height - pad * 2);
1159
+ const laneHeight = Math.max(BPMN_POOL_LANE_LAYOUT.minLaneSize, availH / Math.max(1, lanes.length));
850
1160
  return lanes.map((lane, index) => ({
851
1161
  ...lane,
852
- position: { x: BPMN_POOL_LANE_LAYOUT.poolHeaderSize, y: index * laneHeight },
1162
+ position: { x: pad, y: pad + index * laneHeight },
853
1163
  width: laneWidth,
854
1164
  height: laneHeight,
855
1165
  parentId: pool.id,
856
- extent: "parent",
1166
+ // extent:"parent" intentionally omitted — blocks resize→Pool coupling.
857
1167
  zIndex: getBpmnNodeZIndex("Lane"),
858
1168
  data: { ...lane.data, orientation: "horizontal", laneIndex: index }
859
1169
  }));
@@ -884,10 +1194,22 @@ function layoutBpmnPoolLaneNodes(nodes, poolId) {
884
1194
  return getBpmnLaneOrderPosition(a, orientation) - getBpmnLaneOrderPosition(b, orientation);
885
1195
  });
886
1196
  if (lanes.length === 0) return withBpmnNodeZIndexes(nodes);
887
- const laneMap = new Map(
888
- (orientation === "vertical" ? resizeVerticalBpmnLanes(lanes, pool) : resizeHorizontalBpmnLanes(lanes, pool)).map((lane) => [lane.id, lane])
1197
+ const resizedLanes = orientation === "vertical" ? resizeVerticalBpmnLanes(lanes, pool) : resizeHorizontalBpmnLanes(lanes, pool);
1198
+ const laneMap = new Map(resizedLanes.map((lane) => [lane.id, lane]));
1199
+ const pad = BPMN_POOL_LANE_LAYOUT.poolPad;
1200
+ const totalLaneH = resizedLanes.reduce((sum, l) => sum + (l.height ?? 0), 0);
1201
+ const requiredPoolH = totalLaneH + pad * 2;
1202
+ const poolMap = /* @__PURE__ */ new Map();
1203
+ if (orientation === "horizontal") {
1204
+ const currentH = getBpmnNodeSize(pool).height;
1205
+ poolMap.set(pool.id, {
1206
+ ...pool,
1207
+ height: Math.max(requiredPoolH, currentH)
1208
+ });
1209
+ }
1210
+ return withBpmnNodeZIndexes(
1211
+ nodes.map((node) => laneMap.get(node.id) ?? poolMap.get(node.id) ?? node)
889
1212
  );
890
- return withBpmnNodeZIndexes(nodes.map((node) => laneMap.get(node.id) ?? node));
891
1213
  }
892
1214
  function reorderBpmnLaneAfterDrop(nodes, laneId) {
893
1215
  const lane = nodes.find((node) => node.id === laneId && node.data.elementType === "Lane");
@@ -946,9 +1268,116 @@ function findBpmnContainerAt(state, options) {
946
1268
  }
947
1269
  });
948
1270
  }
1271
+ function resolveBpmnDropTarget(state, options) {
1272
+ if (options.elementType === "Pool") {
1273
+ return { highlightedContainerId: null, invalidContainerId: null, isValid: true };
1274
+ }
1275
+ if (options.elementType === "Lane") {
1276
+ const pool = state.nodes.find((node) => {
1277
+ if (node.data.elementType !== "Pool") return false;
1278
+ const bounds = getBpmnNodeBounds(state, node);
1279
+ return options.position.x >= bounds.x && options.position.x <= bounds.x + bounds.width && options.position.y >= bounds.y && options.position.y <= bounds.y + bounds.height;
1280
+ });
1281
+ return {
1282
+ ...pool ? { container: pool } : {},
1283
+ highlightedContainerId: pool?.id ?? null,
1284
+ invalidContainerId: null,
1285
+ isValid: Boolean(pool)
1286
+ };
1287
+ }
1288
+ const lane = findBpmnLaneAt(state, options.position);
1289
+ if (lane) {
1290
+ return {
1291
+ container: lane,
1292
+ highlightedContainerId: lane.id,
1293
+ invalidContainerId: null,
1294
+ isValid: true
1295
+ };
1296
+ }
1297
+ const container = findBpmnContainerAt(state, {
1298
+ position: options.position,
1299
+ ...options.excludeId ? { excludeId: options.excludeId } : {}
1300
+ });
1301
+ if (container?.data.elementType === "Pool") {
1302
+ const hasLanes = getBpmnPoolLanes(state, container.id).length > 0;
1303
+ if (hasLanes) {
1304
+ return {
1305
+ highlightedContainerId: null,
1306
+ invalidContainerId: container.id,
1307
+ isValid: false
1308
+ };
1309
+ }
1310
+ }
1311
+ return {
1312
+ ...container ? { container } : {},
1313
+ highlightedContainerId: getAncestorLaneId(state, container) ?? container?.id ?? null,
1314
+ invalidContainerId: null,
1315
+ isValid: true
1316
+ };
1317
+ }
949
1318
  function getBpmnNodeCenter(node, absolutePosition) {
950
1319
  return diagramsCore.getNodeCenterPosition(absolutePosition, getBpmnNodeSize(node));
951
1320
  }
1321
+ function getBoundaryEventAttachment(state, boundaryNode) {
1322
+ if (boundaryNode.data.elementType !== "BoundaryEvent") return null;
1323
+ const boundaryOrigin = getBpmnNodeAbsolutePosition(state, boundaryNode) ?? boundaryNode.position;
1324
+ const boundarySize = getBpmnNodeSize(boundaryNode);
1325
+ const boundaryCenter = {
1326
+ x: boundaryOrigin.x + boundarySize.width / 2,
1327
+ y: boundaryOrigin.y + boundarySize.height / 2
1328
+ };
1329
+ const candidates = state.nodes.filter((node) => node.id !== boundaryNode.id && acceptsBoundaryEvents(node.data.elementType)).map((node) => {
1330
+ const origin = getBpmnNodeAbsolutePosition(state, node) ?? node.position;
1331
+ const size = getBpmnNodeSize(node);
1332
+ const hostCenter = { x: origin.x + size.width / 2, y: origin.y + size.height / 2 };
1333
+ return {
1334
+ node,
1335
+ origin,
1336
+ size,
1337
+ distance: Math.hypot(boundaryCenter.x - hostCenter.x, boundaryCenter.y - hostCenter.y)
1338
+ };
1339
+ }).filter(({ origin, size }) => isPointInsideExpandedBounds(boundaryCenter, origin, size)).sort((a, b) => a.distance - b.distance);
1340
+ const host = candidates[0];
1341
+ if (!host) return null;
1342
+ const snappedCenter = snapBoundaryCenterToHostBorder(boundaryCenter, host.origin, host.size);
1343
+ return {
1344
+ hostId: host.node.id,
1345
+ position: {
1346
+ x: snappedCenter.x - host.origin.x - boundarySize.width / 2,
1347
+ y: snappedCenter.y - host.origin.y - boundarySize.height / 2
1348
+ }
1349
+ };
1350
+ }
1351
+ function getBpmnEdgeLaneContext(state, edgeOrId) {
1352
+ const edge = typeof edgeOrId === "string" ? state.edges.find((candidate) => candidate.id === edgeOrId) : edgeOrId;
1353
+ if (!edge) return void 0;
1354
+ const source = diagramsCore.getNode(state, edge.source);
1355
+ const target = diagramsCore.getNode(state, edge.target);
1356
+ if (!source || !target) return void 0;
1357
+ const sourceLaneId = getAncestorLaneId(state, source);
1358
+ const targetLaneId = getAncestorLaneId(state, target);
1359
+ const sourcePoolId = getAncestorContainerId(state, source, "Pool");
1360
+ const targetPoolId = getAncestorContainerId(state, target, "Pool");
1361
+ const sameLane = Boolean(sourceLaneId) && sourceLaneId === targetLaneId;
1362
+ const samePool = Boolean(sourcePoolId) && sourcePoolId === targetPoolId;
1363
+ const crossesLanesWithinPool = Boolean(
1364
+ sourceLaneId && targetLaneId && sourceLaneId !== targetLaneId && samePool
1365
+ );
1366
+ const crossesPools = Boolean(
1367
+ sourcePoolId && targetPoolId && sourcePoolId !== targetPoolId
1368
+ );
1369
+ return {
1370
+ edgeId: edge.id,
1371
+ ...sourceLaneId ? { sourceLaneId } : {},
1372
+ ...targetLaneId ? { targetLaneId } : {},
1373
+ ...sourcePoolId ? { sourcePoolId } : {},
1374
+ ...targetPoolId ? { targetPoolId } : {},
1375
+ sameLane,
1376
+ samePool,
1377
+ crossesLanesWithinPool,
1378
+ crossesPools
1379
+ };
1380
+ }
952
1381
  function resolvePoolLaneDirection(pool) {
953
1382
  return pool.data.orientation === "vertical" ? "horizontal" : "vertical";
954
1383
  }
@@ -1038,6 +1467,14 @@ function validateBpmnConnectionForEdgeType(state, edgeType, source, target) {
1038
1467
  }
1039
1468
  return true;
1040
1469
  }
1470
+ function resolveBpmnConnection(state, sourceId, targetId, requestedType) {
1471
+ const source = diagramsCore.getNode(state, sourceId);
1472
+ const target = diagramsCore.getNode(state, targetId);
1473
+ if (!source || !target) return { ok: false, reason: "No se encontr\xF3 el origen o destino." };
1474
+ const validation = validateBpmnConnectionForEdgeType(state, requestedType, source, target);
1475
+ if (validation !== true) return { ok: false, reason: validation };
1476
+ return { ok: true, edgeType: requestedType };
1477
+ }
1041
1478
  function validateEdgeCardinality(state, edgeType, source, target) {
1042
1479
  if (edgeType !== "sequenceFlow") return true;
1043
1480
  const sourceMax = BPMN_ELEMENT_CATALOG[source.data.elementType].maxOutgoing;
@@ -1225,6 +1662,28 @@ function reparentBpmnNodeAtPosition(state, options) {
1225
1662
  });
1226
1663
  }
1227
1664
  var BE_HALF = 18;
1665
+ function getBoundarySpanRatio(value, size) {
1666
+ const min = BE_HALF;
1667
+ const max = size - BE_HALF;
1668
+ if (max <= min) return 0.5;
1669
+ return (clampBoundaryCoordinate(value, min, max) - min) / (max - min);
1670
+ }
1671
+ function fromBoundarySpanRatio(ratio, size) {
1672
+ const min = BE_HALF;
1673
+ const max = size - BE_HALF;
1674
+ if (max <= min) return size / 2;
1675
+ return min + (max - min) * ratio;
1676
+ }
1677
+ function detectBoundarySide(center, hostSize) {
1678
+ const distances = [
1679
+ { side: "left", value: Math.abs(center.x) },
1680
+ { side: "right", value: Math.abs(center.x - hostSize.width) },
1681
+ { side: "top", value: Math.abs(center.y) },
1682
+ { side: "bottom", value: Math.abs(center.y - hostSize.height) }
1683
+ ];
1684
+ distances.sort((a, b) => a.value - b.value);
1685
+ return distances[0]?.side ?? "bottom";
1686
+ }
1228
1687
  function clampBoundaryEventsAfterResize(state, hostId, oldW, oldH, newW, newH) {
1229
1688
  const boundaryEvents = state.nodes.filter(
1230
1689
  (n) => n.data.elementType === "BoundaryEvent" && n.parentId === hostId
@@ -1235,25 +1694,21 @@ function clampBoundaryEventsAfterResize(state, hostId, oldW, oldH, newW, newH) {
1235
1694
  const py = be.position?.y ?? 0;
1236
1695
  const cx = px + BE_HALF;
1237
1696
  const cy = py + BE_HALF;
1238
- const distLeft = Math.abs(cx);
1239
- const distRight = Math.abs(cx - oldW);
1240
- const distTop = Math.abs(cy);
1241
- const distBottom = Math.abs(cy - oldH);
1242
- const minDist = Math.min(distLeft, distRight, distTop, distBottom);
1697
+ const side = detectBoundarySide({ x: cx, y: cy }, { width: oldW, height: oldH });
1243
1698
  let newCx;
1244
1699
  let newCy;
1245
- if (minDist === distBottom) {
1700
+ if (side === "bottom") {
1246
1701
  newCy = newH;
1247
- newCx = Math.min(Math.max(cx, BE_HALF), newW - BE_HALF);
1248
- } else if (minDist === distRight) {
1702
+ newCx = fromBoundarySpanRatio(getBoundarySpanRatio(cx, oldW), newW);
1703
+ } else if (side === "right") {
1249
1704
  newCx = newW;
1250
- newCy = Math.min(Math.max(cy, BE_HALF), newH - BE_HALF);
1251
- } else if (minDist === distTop) {
1705
+ newCy = fromBoundarySpanRatio(getBoundarySpanRatio(cy, oldH), newH);
1706
+ } else if (side === "top") {
1252
1707
  newCy = 0;
1253
- newCx = Math.min(Math.max(cx, BE_HALF), newW - BE_HALF);
1708
+ newCx = fromBoundarySpanRatio(getBoundarySpanRatio(cx, oldW), newW);
1254
1709
  } else {
1255
1710
  newCx = 0;
1256
- newCy = Math.min(Math.max(cy, BE_HALF), newH - BE_HALF);
1711
+ newCy = fromBoundarySpanRatio(getBoundarySpanRatio(cy, oldH), newH);
1257
1712
  }
1258
1713
  next = diagramsCore.moveNode(next, be.id, { x: newCx - BE_HALF, y: newCy - BE_HALF });
1259
1714
  }
@@ -1520,8 +1975,10 @@ function withBpmnLayoutCache(layoutFn, cache) {
1520
1975
  exports.BPMN_EDGE_CONNECTION_RULES = BPMN_EDGE_CONNECTION_RULES;
1521
1976
  exports.BPMN_MODELING_RULES = BPMN_MODELING_RULES;
1522
1977
  exports.BPMN_POOL_LANE_LAYOUT = BPMN_POOL_LANE_LAYOUT;
1978
+ exports.BPMN_POOL_LANE_STACK_LAYOUT = BPMN_POOL_LANE_STACK_LAYOUT;
1523
1979
  exports.BPMN_ROUTABLE_EDGE_TYPES = BPMN_ROUTABLE_EDGE_TYPES;
1524
1980
  exports.BPMN_SELECTION_STYLE = BPMN_SELECTION_STYLE;
1981
+ exports.applyBpmnPoolLaneDimensionChange = applyBpmnPoolLaneDimensionChange;
1525
1982
  exports.attachBoundaryEventCommand = attachBoundaryEventCommand;
1526
1983
  exports.bpmnConnectionValidators = bpmnConnectionValidators;
1527
1984
  exports.canContainBpmnElement = canContainBpmnElement;
@@ -1537,15 +1994,21 @@ exports.deleteBpmnElementsCommand = deleteBpmnElementsCommand;
1537
1994
  exports.deserializeBpmnDiagram = deserializeBpmnDiagram;
1538
1995
  exports.deserializeBpmnDiagramSnapshot = deserializeBpmnDiagramSnapshot;
1539
1996
  exports.findBpmnContainerAt = findBpmnContainerAt;
1997
+ exports.getAppendedBpmnLaneFrame = getAppendedBpmnLaneFrame;
1998
+ exports.getBoundaryEventAttachment = getBoundaryEventAttachment;
1540
1999
  exports.getBpmnDragHandleSelector = getBpmnDragHandleSelector;
1541
2000
  exports.getBpmnEdgeLabelLayout = getBpmnEdgeLabelLayout;
2001
+ exports.getBpmnEdgeLaneContext = getBpmnEdgeLaneContext;
1542
2002
  exports.getBpmnElementSize = getBpmnElementSize;
1543
2003
  exports.getBpmnLaneIndexAtPosition = getBpmnLaneIndexAtPosition;
1544
2004
  exports.getBpmnNodeAbsolutePosition = getBpmnNodeAbsolutePosition;
1545
2005
  exports.getBpmnNodeCenter = getBpmnNodeCenter;
1546
2006
  exports.getBpmnNodeSize = getBpmnNodeSize;
1547
2007
  exports.getBpmnNodeZIndex = getBpmnNodeZIndex;
2008
+ exports.getBpmnPoolLaneNodeMaxSize = getBpmnPoolLaneNodeMaxSize;
2009
+ exports.getBpmnPoolLaneNodeMinSize = getBpmnPoolLaneNodeMinSize;
1548
2010
  exports.getBpmnPoolLanes = getBpmnPoolLanes;
2011
+ exports.getBpmnPoolOrientation = getBpmnPoolOrientation;
1549
2012
  exports.getBpmnTabOrder = getBpmnTabOrder;
1550
2013
  exports.groupAsBpmnSubProcessCommand = groupAsBpmnSubProcessCommand;
1551
2014
  exports.inferBpmnEdgeType = inferBpmnEdgeType;
@@ -1554,6 +2017,7 @@ exports.isBpmnEdgeRoutingEditable = isBpmnEdgeRoutingEditable;
1554
2017
  exports.isBpmnElementResizable = isBpmnElementResizable;
1555
2018
  exports.isBpmnProcessNode = isBpmnProcessNode;
1556
2019
  exports.layoutBpmnPoolLaneNodes = layoutBpmnPoolLaneNodes;
2020
+ exports.layoutBpmnPoolLaneNodesPreservingHeights = layoutBpmnPoolLaneNodesPreservingHeights;
1557
2021
  exports.layoutBpmnPoolLanes = layoutBpmnPoolLanes;
1558
2022
  exports.moveBpmnLaneCommand = moveBpmnLaneCommand;
1559
2023
  exports.parseBpmnDiagramDocument = parseBpmnDiagramDocument;
@@ -1562,11 +2026,14 @@ exports.persistBpmnHistory = persistBpmnHistory;
1562
2026
  exports.reorderBpmnLane = reorderBpmnLane;
1563
2027
  exports.reorderBpmnLaneAfterDrop = reorderBpmnLaneAfterDrop;
1564
2028
  exports.reorderBpmnLaneCommand = reorderBpmnLaneCommand;
2029
+ exports.reorderBpmnPoolLaneAfterDropPreservingHeights = reorderBpmnPoolLaneAfterDropPreservingHeights;
1565
2030
  exports.reparentBpmnNodeAtPosition = reparentBpmnNodeAtPosition;
1566
2031
  exports.reparentBpmnNodeCommand = reparentBpmnNodeCommand;
1567
2032
  exports.replaceBpmnNodeCommand = replaceBpmnNodeCommand;
1568
2033
  exports.resizeBpmnNodeByHandleCommand = resizeBpmnNodeByHandleCommand;
1569
2034
  exports.resizeBpmnNodeCommand = resizeBpmnNodeCommand;
2035
+ exports.resolveBpmnConnection = resolveBpmnConnection;
2036
+ exports.resolveBpmnDropTarget = resolveBpmnDropTarget;
1570
2037
  exports.restoreBpmnHistory = restoreBpmnHistory;
1571
2038
  exports.routeBpmnEdgeCommand = routeBpmnEdgeCommand;
1572
2039
  exports.runBpmnCommand = runBpmnCommand;