@aranzatech/diagrams-bpmn 0.2.5 → 0.2.6

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 (43) hide show
  1. package/dist/{catalog-D2AcvrDO.d.cts → catalog-CZsXqhL9.d.cts} +1 -1
  2. package/dist/{catalog-CQtKEV7q.d.ts → catalog-Clz8sN9x.d.ts} +1 -1
  3. package/dist/{chunk-ASZ3TFNQ.js → chunk-L64NM77A.js} +65 -6
  4. package/dist/chunk-L64NM77A.js.map +1 -0
  5. package/dist/{chunk-QOGZITWB.js → chunk-M46UDUN3.js} +2 -2
  6. package/dist/{chunk-QOGZITWB.js.map → chunk-M46UDUN3.js.map} +1 -1
  7. package/dist/{chunk-7MKU37XQ.js → chunk-XTUYPA3E.js} +191 -15
  8. package/dist/chunk-XTUYPA3E.js.map +1 -0
  9. package/dist/elements/index.d.cts +3 -3
  10. package/dist/elements/index.d.ts +3 -3
  11. package/dist/index.cjs +252 -227
  12. package/dist/index.cjs.map +1 -1
  13. package/dist/index.d.cts +5 -5
  14. package/dist/index.d.ts +5 -5
  15. package/dist/index.js +3 -4
  16. package/dist/modeling/index.cjs +197 -10
  17. package/dist/modeling/index.cjs.map +1 -1
  18. package/dist/modeling/index.d.cts +103 -7
  19. package/dist/modeling/index.d.ts +103 -7
  20. package/dist/modeling/index.js +1 -1
  21. package/dist/simulation/index.cjs.map +1 -1
  22. package/dist/simulation/index.d.cts +36 -0
  23. package/dist/simulation/index.d.ts +36 -0
  24. package/dist/simulation/index.js +1 -1
  25. package/dist/{types-rWbKYrHH.d.cts → types-BPqNeIU-.d.cts} +2 -0
  26. package/dist/{types-rWbKYrHH.d.ts → types-BPqNeIU-.d.ts} +2 -0
  27. package/dist/{types-CIBColRi.d.ts → types-D0Flgue2.d.ts} +1 -1
  28. package/dist/{types-fDlPLIHd.d.cts → types-exnfq24-.d.cts} +1 -1
  29. package/dist/validation/index.cjs.map +1 -1
  30. package/dist/validation/index.d.cts +7 -2
  31. package/dist/validation/index.d.ts +7 -2
  32. package/dist/validation/index.js +224 -3
  33. package/dist/validation/index.js.map +1 -1
  34. package/dist/xml/index.cjs +62 -6
  35. package/dist/xml/index.cjs.map +1 -1
  36. package/dist/xml/index.d.cts +18 -3
  37. package/dist/xml/index.d.ts +18 -3
  38. package/dist/xml/index.js +1 -1
  39. package/package.json +2 -2
  40. package/dist/chunk-7MKU37XQ.js.map +0 -1
  41. package/dist/chunk-ASZ3TFNQ.js.map +0 -1
  42. package/dist/chunk-ZFGQVLHB.js +0 -226
  43. package/dist/chunk-ZFGQVLHB.js.map +0 -1
package/dist/index.cjs CHANGED
@@ -3,7 +3,6 @@
3
3
  var react = require('@xyflow/react');
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
5
  var routing = require('@aranzatech/diagrams-core/routing');
6
- var bpmnModdle = require('bpmn-moddle');
7
6
  var diagramsCore = require('@aranzatech/diagrams-core');
8
7
  var serialization = require('@aranzatech/diagrams-core/serialization');
9
8
 
@@ -2493,6 +2492,27 @@ var BPMN_EDGE_TYPES = {
2493
2492
  conversationLink: ConversationLinkEdge
2494
2493
  };
2495
2494
 
2495
+ // src/xml/aranza-descriptor.ts
2496
+ var ARANZA_DESCRIPTOR = {
2497
+ name: "Aranza",
2498
+ uri: "http://aranzatech.io/schema/bpmn-extension/1.0",
2499
+ prefix: "aranza",
2500
+ xml: { tagAlias: "lowerCase" },
2501
+ types: [
2502
+ {
2503
+ name: "TaskConfig",
2504
+ superClass: ["Element"],
2505
+ properties: [
2506
+ { name: "priority", isAttr: true, type: "String" },
2507
+ { name: "owner", isAttr: true, type: "String" },
2508
+ { name: "sla", isAttr: true, type: "String" }
2509
+ ]
2510
+ }
2511
+ ],
2512
+ enumerations: [],
2513
+ associations: []
2514
+ };
2515
+
2496
2516
  // src/xml/mapper.ts
2497
2517
  var MODDLE_TO_ELEMENT_TYPE = {
2498
2518
  "bpmn:StartEvent": "StartEvent",
@@ -2759,6 +2779,22 @@ function extractSubProcessVariant(el) {
2759
2779
  if (el.triggeredByEvent === true) return "event";
2760
2780
  return "embedded";
2761
2781
  }
2782
+ function extractAranzaExtensions(el) {
2783
+ const ext = el.extensionElements;
2784
+ if (!ext) return {};
2785
+ const taskConfig = asElements(ext.values).find((v) => v.$type === "aranza:TaskConfig");
2786
+ if (!taskConfig) return {};
2787
+ const result = {};
2788
+ const priority = asString(taskConfig.priority);
2789
+ if (priority === "critical" || priority === "high" || priority === "medium" || priority === "low") {
2790
+ result.priority = priority;
2791
+ }
2792
+ const owner = asString(taskConfig.owner);
2793
+ if (owner) result.owner = owner;
2794
+ const sla = asString(taskConfig.sla);
2795
+ if (sla) result.sla = sla;
2796
+ return result;
2797
+ }
2762
2798
  function walkFlowElements(elements, parentId, ctx, nodes, edges) {
2763
2799
  for (const el of elements) {
2764
2800
  const { $type, id } = el;
@@ -2795,6 +2831,8 @@ function buildNode(el, elementType, parentId, ctx, nodes) {
2795
2831
  const eventDefinition = extractEventDefinition(el);
2796
2832
  const isNonInterrupting = el.cancelActivity === false;
2797
2833
  const attachedToRef = el.attachedToRef?.id;
2834
+ const calledElement = elementType === "CallActivity" ? asString(el.calledElement) : void 0;
2835
+ const aranzaExt = extractAranzaExtensions(el);
2798
2836
  const data = {
2799
2837
  elementType,
2800
2838
  ...label ? { label } : {},
@@ -2810,7 +2848,9 @@ function buildNode(el, elementType, parentId, ctx, nodes) {
2810
2848
  ...eventDefinition?.errorRef ? { errorRef: eventDefinition.errorRef } : {},
2811
2849
  ...eventDefinition?.escalationRef ? { escalationRef: eventDefinition.escalationRef } : {},
2812
2850
  ...eventDefinition?.conditionExpression ? { conditionExpression: eventDefinition.conditionExpression } : {},
2813
- ...eventDefinition?.linkName ? { linkName: eventDefinition.linkName } : {}
2851
+ ...eventDefinition?.linkName ? { linkName: eventDefinition.linkName } : {},
2852
+ ...calledElement ? { calledElement } : {},
2853
+ ...aranzaExt
2814
2854
  };
2815
2855
  if (elementType === "SubProcess" || elementType === "Transaction" || elementType === "EventSubProcess" || elementType === "AdHocSubProcess") {
2816
2856
  const variant = extractSubProcessVariant(el);
@@ -2910,7 +2950,8 @@ function addLaneNodes(laneSet, poolId, ctx, nodes) {
2910
2950
  }
2911
2951
  }
2912
2952
  async function parseBpmnXml(xml) {
2913
- const moddle = new bpmnModdle.BpmnModdle();
2953
+ const { BpmnModdle } = await import('bpmn-moddle');
2954
+ const moddle = new BpmnModdle({ aranza: ARANZA_DESCRIPTOR });
2914
2955
  const warnings = [];
2915
2956
  let rootElement;
2916
2957
  try {
@@ -3000,6 +3041,8 @@ function normalizeChildPositions(nodes, nodeIds) {
3000
3041
  };
3001
3042
  });
3002
3043
  }
3044
+
3045
+ // src/xml/exporter.ts
3003
3046
  function uid(prefix, id) {
3004
3047
  return `${prefix}_${id}`;
3005
3048
  }
@@ -3099,6 +3142,16 @@ function buildEventDefinitions(moddle, node, eventDefinition) {
3099
3142
  }
3100
3143
  return [moddle.create(defType, attrs)];
3101
3144
  }
3145
+ function buildAranzaExtensionElements(moddle, node) {
3146
+ const { priority, owner, sla } = node.data;
3147
+ if (!priority && !owner && !sla) return null;
3148
+ const configAttrs = {};
3149
+ if (priority) configAttrs.priority = priority;
3150
+ if (owner) configAttrs.owner = owner;
3151
+ if (sla) configAttrs.sla = sla;
3152
+ const taskConfig = moddle.create("aranza:TaskConfig", configAttrs);
3153
+ return moddle.create("bpmn:ExtensionElements", { values: [taskConfig] });
3154
+ }
3102
3155
  function buildSemanticModel(moddle, nodes, edges, opts) {
3103
3156
  const defId = opts.id ?? "Definitions_1";
3104
3157
  const defName = opts.name;
@@ -3268,8 +3321,13 @@ function buildFlowElement(moddle, node, allNodes, allEdges) {
3268
3321
  const interrupting = node.data.cancelActivity ?? !node.data.isNonInterrupting;
3269
3322
  attrs.cancelActivity = interrupting;
3270
3323
  }
3271
- const isSubProcess3 = elementType === "SubProcess" || elementType === "Transaction" || elementType === "EventSubProcess" || elementType === "AdHocSubProcess";
3272
- if (isSubProcess3) {
3324
+ if (elementType === "CallActivity" && node.data.calledElement) {
3325
+ attrs.calledElement = node.data.calledElement;
3326
+ }
3327
+ const aranzaConfig = buildAranzaExtensionElements(moddle, node);
3328
+ if (aranzaConfig) attrs.extensionElements = aranzaConfig;
3329
+ const isSubProcess2 = elementType === "SubProcess" || elementType === "Transaction" || elementType === "EventSubProcess" || elementType === "AdHocSubProcess";
3330
+ if (isSubProcess2) {
3273
3331
  attrs.flowElements = buildNestedFlowElements(moddle, node, allNodes, allEdges);
3274
3332
  if (elementType === "EventSubProcess" || node.data.subProcessVariant === "event") {
3275
3333
  attrs.triggeredByEvent = true;
@@ -3405,7 +3463,8 @@ function buildAbsolutePositionMap(nodes) {
3405
3463
  return absoluteById;
3406
3464
  }
3407
3465
  async function serializeBpmnXml(nodes, edges, opts = {}) {
3408
- const moddle = new bpmnModdle.BpmnModdle();
3466
+ const { BpmnModdle } = await import('bpmn-moddle');
3467
+ const moddle = new BpmnModdle({ aranza: ARANZA_DESCRIPTOR });
3409
3468
  const definitions = buildSemanticModel(moddle, nodes, edges, opts);
3410
3469
  buildBpmnDI(moddle, definitions, nodes, edges);
3411
3470
  const { xml } = await moddle.toXML(definitions, {
@@ -4436,6 +4495,41 @@ function reparentBpmnNodeAtPosition(state, options) {
4436
4495
  position: nextPosition
4437
4496
  });
4438
4497
  }
4498
+ var BE_HALF = 18;
4499
+ function clampBoundaryEventsAfterResize(state, hostId, oldW, oldH, newW, newH) {
4500
+ const boundaryEvents = state.nodes.filter(
4501
+ (n) => n.data.elementType === "BoundaryEvent" && n.parentId === hostId
4502
+ );
4503
+ let next = state;
4504
+ for (const be of boundaryEvents) {
4505
+ const px = be.position?.x ?? 0;
4506
+ const py = be.position?.y ?? 0;
4507
+ const cx = px + BE_HALF;
4508
+ const cy = py + BE_HALF;
4509
+ const distLeft = Math.abs(cx);
4510
+ const distRight = Math.abs(cx - oldW);
4511
+ const distTop = Math.abs(cy);
4512
+ const distBottom = Math.abs(cy - oldH);
4513
+ const minDist = Math.min(distLeft, distRight, distTop, distBottom);
4514
+ let newCx;
4515
+ let newCy;
4516
+ if (minDist === distBottom) {
4517
+ newCy = newH;
4518
+ newCx = Math.min(Math.max(cx, BE_HALF), newW - BE_HALF);
4519
+ } else if (minDist === distRight) {
4520
+ newCx = newW;
4521
+ newCy = Math.min(Math.max(cy, BE_HALF), newH - BE_HALF);
4522
+ } else if (minDist === distTop) {
4523
+ newCy = 0;
4524
+ newCx = Math.min(Math.max(cx, BE_HALF), newW - BE_HALF);
4525
+ } else {
4526
+ newCx = 0;
4527
+ newCy = Math.min(Math.max(cy, BE_HALF), newH - BE_HALF);
4528
+ }
4529
+ next = diagramsCore.moveNode(next, be.id, { x: newCx - BE_HALF, y: newCy - BE_HALF });
4530
+ }
4531
+ return next;
4532
+ }
4439
4533
  function resizeBpmnNodeCommand(options) {
4440
4534
  return {
4441
4535
  id: `bpmn.resize.${options.id}`,
@@ -4447,10 +4541,18 @@ function resizeBpmnNodeCommand(options) {
4447
4541
  if (!size.resizable) {
4448
4542
  throw new Error(`${node.data.elementType} is not resizable in BPMN.`);
4449
4543
  }
4450
- return diagramsCore.resizeNode(state, options.id, {
4451
- width: options.width === void 0 ? void 0 : Math.max(size.minWidth, options.width),
4452
- height: options.height === void 0 ? void 0 : Math.max(size.minHeight, options.height)
4544
+ const oldW = node.width ?? size.width;
4545
+ const oldH = node.height ?? size.height;
4546
+ const clampedW = options.width === void 0 ? void 0 : Math.max(size.minWidth, options.width);
4547
+ const clampedH = options.height === void 0 ? void 0 : Math.max(size.minHeight, options.height);
4548
+ const resized = diagramsCore.resizeNode(state, options.id, {
4549
+ width: clampedW,
4550
+ height: clampedH
4453
4551
  });
4552
+ const updatedNode = diagramsCore.getNode(resized, options.id);
4553
+ const newW = updatedNode?.width ?? clampedW ?? oldW;
4554
+ const newH = updatedNode?.height ?? clampedH ?? oldH;
4555
+ return clampBoundaryEventsAfterResize(resized, options.id, oldW, oldH, newW, newH);
4454
4556
  }
4455
4557
  };
4456
4558
  }
@@ -4530,10 +4632,15 @@ function createBpmnDiagramDocument(state, options = {}) {
4530
4632
  });
4531
4633
  }
4532
4634
  function serializeBpmnDiagram(state, options = {}) {
4533
- return serialization.serializeDiagram(diagramsCore.normalizeDiagramState(state), {
4534
- ...options,
4535
- diagramType: "bpmn"
4536
- });
4635
+ const { viewport, ...docOptions } = options;
4636
+ const normalized = diagramsCore.normalizeDiagramState(state);
4637
+ if (viewport) {
4638
+ return serialization.serializeDiagramSnapshot(
4639
+ { nodes: normalized.nodes, edges: normalized.edges, viewport },
4640
+ { ...docOptions, diagramType: "bpmn" }
4641
+ );
4642
+ }
4643
+ return serialization.serializeDiagram(normalized, { ...docOptions, diagramType: "bpmn" });
4537
4644
  }
4538
4645
  function parseBpmnDiagramDocument(json) {
4539
4646
  const document = serialization.parseDiagramDocument(json);
@@ -4546,232 +4653,140 @@ function deserializeBpmnDiagram(json) {
4546
4653
  const document = parseBpmnDiagramDocument(json);
4547
4654
  return serialization.deserializeDiagram(JSON.stringify(document));
4548
4655
  }
4549
- function runBpmnCommand(stack, command) {
4550
- return diagramsCore.executeCommand(stack, command);
4551
- }
4552
- function runBpmnCommands(stack, commands, options = {}) {
4553
- return diagramsCore.executeCommands(stack, commands, options);
4554
- }
4555
-
4556
- // src/validation/index.ts
4557
- function isFlowNode(type) {
4558
- return isEventType(type) || isGatewayType(type) || type.includes("Task") || type === "CallActivity" || type === "SubProcess" || type === "Transaction" || type === "EventSubProcess" || type === "AdHocSubProcess" || type === "ChoreographyTask" || type === "SubChoreography" || type === "CallChoreography";
4559
- }
4560
- function isProcessNode(type) {
4561
- return isFlowNode(type) && type !== "BoundaryEvent";
4562
- }
4563
- function isSubProcess2(type) {
4564
- return type === "SubProcess" || type === "Transaction" || type === "EventSubProcess" || type === "AdHocSubProcess";
4565
- }
4566
- function isCatchTarget(type) {
4567
- return type === "IntermediateCatchEvent" || type === "ReceiveTask";
4568
- }
4569
- function poolAncestor(node, nodeById2) {
4570
- let current = node;
4571
- const visited = /* @__PURE__ */ new Set();
4572
- while (current?.parentId && !visited.has(current.id)) {
4573
- visited.add(current.id);
4574
- const parent = nodeById2.get(current.parentId);
4575
- if (parent?.data.elementType === "Pool") return parent.id;
4576
- current = parent;
4577
- }
4578
- return void 0;
4656
+ function deserializeBpmnDiagramSnapshot(json) {
4657
+ const document = parseBpmnDiagramDocument(json);
4658
+ return serialization.deserializeDiagramSnapshot(JSON.stringify(document));
4579
4659
  }
4580
- function countSequenceEdges(edges, nodeId, direction) {
4581
- return edges.filter((edge) => {
4582
- if (edge.data?.edgeType !== "sequenceFlow") return false;
4583
- return direction === "in" ? edge.target === nodeId : edge.source === nodeId;
4584
- }).length;
4660
+ function createBpmnEventBus() {
4661
+ return diagramsCore.createDiagramEventBus();
4585
4662
  }
4586
- function sequenceEdges(edges) {
4587
- return edges.filter((edge) => (edge.data?.edgeType ?? edge.type) === "sequenceFlow");
4663
+ function runBpmnCommand(stack, command, bus) {
4664
+ const next = diagramsCore.executeCommand(stack, command);
4665
+ bus?.emit("command:executed", {
4666
+ commandId: command.id,
4667
+ ...command.label !== void 0 ? { label: command.label } : {},
4668
+ state: next.current
4669
+ });
4670
+ return next;
4588
4671
  }
4589
- function sequenceOut(edges, nodeId) {
4590
- return sequenceEdges(edges).filter((edge) => edge.source === nodeId);
4672
+ function runBpmnCommands(stack, commands, options = {}) {
4673
+ const { bus, ...execOptions } = options;
4674
+ const next = diagramsCore.executeCommands(stack, commands, execOptions);
4675
+ bus?.emit("command:executed", {
4676
+ commandId: execOptions.id ?? "bpmn.batch",
4677
+ ...execOptions.label !== void 0 ? { label: execOptions.label } : {},
4678
+ state: next.current
4679
+ });
4680
+ return next;
4591
4681
  }
4592
- function sequenceIn(edges, nodeId) {
4593
- return sequenceEdges(edges).filter((edge) => edge.target === nodeId);
4682
+ function persistBpmnHistory(stack, diagramId) {
4683
+ diagramsCore.persistCommandHistory(stack, `bpmn.history.${diagramId}`);
4684
+ }
4685
+ function restoreBpmnHistory(diagramId) {
4686
+ return diagramsCore.restoreCommandHistory(`bpmn.history.${diagramId}`);
4687
+ }
4688
+ function computeBpmnSmartGuides(movingNodes, state, poolId) {
4689
+ const movingIds = new Set(movingNodes.map((n) => n.id));
4690
+ const staticNodes = state.nodes.filter((n) => {
4691
+ if (movingIds.has(n.id)) return false;
4692
+ const et = n.data.elementType;
4693
+ if (et === "BoundaryEvent" || et === "Lane" || et === "Pool") return false;
4694
+ if (poolId) {
4695
+ const inPool = n.parentId === poolId || n.parentId !== void 0 && diagramsCore.getNode(state, n.parentId)?.parentId === poolId;
4696
+ if (!inPool) return false;
4697
+ }
4698
+ return true;
4699
+ });
4700
+ return diagramsCore.computeSmartGuides(movingNodes, staticNodes);
4594
4701
  }
4595
- function issue(code, severity, message, elementId, relatedElementIds) {
4702
+ function groupAsBpmnSubProcessCommand(options) {
4596
4703
  return {
4597
- id: `${code}:${elementId ?? relatedElementIds?.join(",") ?? "diagram"}`,
4598
- code,
4599
- severity,
4600
- message,
4601
- ...elementId ? { elementId } : {},
4602
- ...relatedElementIds ? { relatedElementIds } : {}
4603
- };
4604
- }
4605
- function validateBpmnDiagram(nodes, edges, options = {}) {
4606
- const opts = {
4607
- requireStartEvent: true,
4608
- requireEndEvent: true,
4609
- strictNames: false,
4610
- ...options
4611
- };
4612
- const issues = [];
4613
- const nodeById2 = new Map(nodes.map((node) => [node.id, node]));
4614
- const seqEdges = sequenceEdges(edges);
4615
- const processNodes = nodes.filter((node) => isProcessNode(node.data.elementType));
4616
- if (opts.requireStartEvent && !processNodes.some((node) => node.data.elementType === "StartEvent")) {
4617
- issues.push(issue("bpmn/start-event-required", "error", "The diagram must contain at least one start event."));
4618
- }
4619
- if (opts.requireEndEvent && !processNodes.some((node) => node.data.elementType === "EndEvent")) {
4620
- issues.push(issue("bpmn/end-event-required", "error", "The diagram must contain at least one end event."));
4621
- }
4622
- for (const edge of edges) {
4623
- const edgeType = edge.data?.edgeType ?? edge.type;
4624
- const source = nodeById2.get(edge.source);
4625
- const target = nodeById2.get(edge.target);
4626
- if (!source || !target) {
4627
- issues.push(issue(
4628
- "bpmn/no-orphan-edges",
4629
- "error",
4630
- `Edge "${edge.id}" references a missing ${!source ? "source" : "target"} node.`,
4631
- edge.id,
4632
- [edge.source, edge.target]
4633
- ));
4634
- continue;
4635
- }
4636
- if (edge.source === edge.target) {
4637
- issues.push(issue("bpmn/no-self-loop", "error", "BPMN edges cannot connect an element to itself.", edge.id, [edge.source]));
4638
- }
4639
- if (edgeType === "sequenceFlow") {
4640
- if (!isFlowNode(source.data.elementType) || !isFlowNode(target.data.elementType) || isDataType(source.data.elementType) || isDataType(target.data.elementType)) {
4641
- issues.push(issue("bpmn/sequence-flow-valid-endpoints", "error", "Sequence flows must connect BPMN flow nodes.", edge.id, [source.id, target.id]));
4642
- }
4643
- const sourcePool = poolAncestor(source, nodeById2);
4644
- const targetPool = poolAncestor(target, nodeById2);
4645
- if (sourcePool && targetPool && sourcePool !== targetPool) {
4646
- issues.push(issue("bpmn/sequence-flow-no-cross-pool", "error", "Sequence flows cannot cross pools. Use message flow between participants.", edge.id, [source.id, target.id]));
4647
- }
4648
- }
4649
- if (edgeType === "messageFlow") {
4650
- const sourcePool = poolAncestor(source, nodeById2);
4651
- const targetPool = poolAncestor(target, nodeById2);
4652
- if (!sourcePool || !targetPool || sourcePool === targetPool) {
4653
- issues.push(issue("bpmn/message-flow-valid-endpoints", "error", "Message flows must connect flow nodes in different pools.", edge.id, [source.id, target.id]));
4654
- }
4655
- if (!isFlowNode(source.data.elementType) || !isFlowNode(target.data.elementType)) {
4656
- issues.push(issue("bpmn/message-flow-valid-endpoints", "error", "Message flows must connect BPMN flow nodes, not containers.", edge.id, [source.id, target.id]));
4657
- }
4658
- }
4659
- if (edgeType === "dataAssociation") {
4660
- const hasDataEndpoint = isDataType(source.data.elementType) || isDataType(target.data.elementType);
4661
- const hasFlowEndpoint = isFlowNode(source.data.elementType) || isFlowNode(target.data.elementType);
4662
- if (!hasDataEndpoint || !hasFlowEndpoint) {
4663
- issues.push(issue("bpmn/data-association-valid-endpoints", "error", "Data associations must connect data elements with flow nodes.", edge.id, [source.id, target.id]));
4704
+ id: `bpmn.groupAsSubProcess.${options.groupId ?? options.nodeIds.join(".")}`,
4705
+ label: "Group as SubProcess",
4706
+ execute: (state) => {
4707
+ for (const nodeId of options.nodeIds) {
4708
+ const node = diagramsCore.getNode(state, nodeId);
4709
+ if (!node) continue;
4710
+ const result = canContainBpmnElement("SubProcess", node.data.elementType);
4711
+ if (result !== true) throw new Error(result);
4664
4712
  }
4713
+ const groupId = options.groupId ?? diagramsCore.createUniqueId("subprocess", state.nodes.map((n) => n.id));
4714
+ const groupNode = createBpmnNode({
4715
+ id: groupId,
4716
+ elementType: "SubProcess",
4717
+ position: { x: 0, y: 0 },
4718
+ ...options.label !== void 0 ? { label: options.label } : {},
4719
+ ...options.data !== void 0 ? { data: options.data } : {}
4720
+ });
4721
+ return diagramsCore.groupNodes(state, {
4722
+ groupNode,
4723
+ nodeIds: options.nodeIds,
4724
+ padding: options.padding ?? 20
4725
+ });
4665
4726
  }
4727
+ };
4728
+ }
4729
+ function getBpmnTabOrder(state, poolId) {
4730
+ if (!poolId) return diagramsCore.getNodeTabOrder(state);
4731
+ const pool = diagramsCore.getNode(state, poolId);
4732
+ if (!pool) return [];
4733
+ const scopeIds = state.nodes.filter((n) => {
4734
+ if (n.id === poolId) return false;
4735
+ if (n.parentId === poolId) return true;
4736
+ const parent = diagramsCore.getNode(state, n.parentId ?? "");
4737
+ return parent?.parentId === poolId;
4738
+ }).map((n) => n.id);
4739
+ return diagramsCore.getNodeTabOrder(state, scopeIds);
4740
+ }
4741
+ function getBpmnEdgeLabelLayout(edgeId, state, options) {
4742
+ const edge = state.edges.find((e) => e.id === edgeId);
4743
+ if (!edge) return null;
4744
+ const routingPoints = edge.data?.routingPoints ?? [];
4745
+ if (routingPoints.length >= 2) {
4746
+ return diagramsCore.getEdgeLabelLayout(routingPoints, options);
4666
4747
  }
4667
- const duplicateSequenceKeys = /* @__PURE__ */ new Set();
4668
- const reportedDuplicateKeys = /* @__PURE__ */ new Set();
4669
- for (const edge of seqEdges) {
4670
- const key = `${edge.source}->${edge.target}`;
4671
- if (duplicateSequenceKeys.has(key) && !reportedDuplicateKeys.has(key)) {
4672
- reportedDuplicateKeys.add(key);
4673
- issues.push(issue("bpmn/no-duplicate-sequence-flow", "error", "Only one sequence flow is allowed between the same source and target.", edge.id, [edge.source, edge.target]));
4674
- }
4675
- duplicateSequenceKeys.add(key);
4676
- }
4677
- for (const node of nodes) {
4678
- const type = node.data.elementType;
4679
- const incoming = countSequenceEdges(edges, node.id, "in");
4680
- const outgoing = countSequenceEdges(edges, node.id, "out");
4681
- const meta = BPMN_ELEMENT_CATALOG[type];
4682
- if (type === "StartEvent" && incoming > 0) {
4683
- issues.push(issue("bpmn/start-event-no-incoming", "error", "Start events cannot have incoming sequence flows.", node.id));
4684
- }
4685
- if (type === "EndEvent") {
4686
- if (outgoing > 0) issues.push(issue("bpmn/no-outgoing-from-end-event", "error", "End events cannot have outgoing sequence flows.", node.id));
4687
- if (incoming === 0) issues.push(issue("bpmn/end-event-has-incoming", "error", "End events should have at least one incoming sequence flow.", node.id));
4688
- }
4689
- if ((type === "IntermediateCatchEvent" || type === "IntermediateThrowEvent") && (incoming === 0 || outgoing === 0)) {
4690
- issues.push(issue("bpmn/intermediate-event-both-flows", "error", "Intermediate events should have both incoming and outgoing sequence flows.", node.id));
4691
- }
4692
- if (type === "BoundaryEvent") {
4693
- const hostId = node.data.attachedToRef ?? node.parentId;
4694
- const host = hostId ? nodeById2.get(hostId) : void 0;
4695
- if (!host || !BPMN_ELEMENT_CATALOG[host.data.elementType]?.acceptsBoundaryEvents) {
4696
- issues.push(issue("bpmn/boundary-event-attached", "error", "Boundary events must be attached to an activity or subprocess.", node.id, hostId ? [hostId] : void 0));
4697
- }
4698
- if (sequenceIn(edges, node.id).length > 0) {
4699
- issues.push(issue("bpmn/boundary-no-incoming", "error", "Boundary events cannot have incoming sequence flows.", node.id));
4700
- }
4701
- if (sequenceOut(edges, node.id).length === 0) {
4702
- issues.push(issue("bpmn/boundary-has-outgoing", "warning", "Boundary events should define an outgoing exception path.", node.id));
4703
- }
4704
- }
4705
- if (isGatewayType(type)) {
4706
- if (incoming === 0) issues.push(issue("bpmn/gateway-has-incoming", "error", "Gateways should have at least one incoming sequence flow.", node.id));
4707
- if (outgoing === 0) issues.push(issue("bpmn/gateway-has-outgoing", "error", "Gateways should have at least one outgoing sequence flow.", node.id));
4708
- }
4709
- if (type === "ExclusiveGateway" || type === "InclusiveGateway" || type === "ComplexGateway") {
4710
- const outgoingEdges = sequenceOut(edges, node.id);
4711
- const defaults = outgoingEdges.filter((edge) => edge.data?.isDefault);
4712
- if (defaults.length > 1) {
4713
- issues.push(issue("bpmn/gateway-single-default", "error", "Gateways can have at most one default sequence flow.", node.id, defaults.map((edge) => edge.id)));
4714
- }
4715
- if (outgoingEdges.length >= 2) {
4716
- for (const edge of outgoingEdges) {
4717
- if (!edge.data?.isDefault && !edge.data?.conditionExpression) {
4718
- issues.push(issue("bpmn/gateway-condition", "error", "Conditional gateway branches should have a condition or be marked as default.", edge.id, [node.id, edge.target]));
4719
- }
4720
- }
4721
- }
4722
- }
4723
- if (type === "EventBasedGateway") {
4724
- const outgoingEdges = edges.filter((edge) => edge.data?.edgeType === "sequenceFlow" && edge.source === node.id);
4725
- if (outgoingEdges.length < 2) {
4726
- issues.push(issue("bpmn/event-based-gateway-min-outgoing", "error", "Event-based gateways should have at least two outgoing sequence flows.", node.id));
4727
- }
4728
- for (const edge of outgoingEdges) {
4729
- const target = nodeById2.get(edge.target);
4730
- if (target && !isCatchTarget(target.data.elementType)) {
4731
- issues.push(issue("bpmn/event-based-gateway-valid-targets", "error", "Event-based gateways must target catch events or receive tasks.", edge.id, [node.id, target.id]));
4732
- }
4733
- }
4734
- }
4735
- if (meta.maxIncoming !== void 0 && incoming > meta.maxIncoming) {
4736
- issues.push(issue("bpmn/max-incoming", "error", `${type} cannot have more than ${meta.maxIncoming} incoming sequence flow(s).`, node.id));
4737
- }
4738
- if (meta.maxOutgoing !== void 0 && outgoing > meta.maxOutgoing) {
4739
- issues.push(issue("bpmn/max-outgoing", "error", `${type} cannot have more than ${meta.maxOutgoing} outgoing sequence flow(s).`, node.id));
4740
- }
4741
- if (opts.strictNames && (type.includes("Task") || isGatewayType(type)) && !node.data.label) {
4742
- issues.push(issue("bpmn/name-required", "warning", `${type} should have a label.`, node.id));
4743
- }
4744
- if (isSubProcess2(type)) {
4745
- const childNodes = nodes.filter((child) => child.parentId === node.id);
4746
- if (childNodes.length > 0) {
4747
- if (!childNodes.some((child) => child.data.elementType === "StartEvent")) {
4748
- issues.push(issue("bpmn/subprocess-has-start-end", "error", "Expanded subprocesses should contain a start event.", node.id));
4749
- }
4750
- if (!childNodes.some((child) => child.data.elementType === "EndEvent")) {
4751
- issues.push(issue("bpmn/subprocess-has-start-end", "error", "Expanded subprocesses should contain an end event.", node.id));
4752
- }
4753
- }
4754
- if (type === "EventSubProcess") {
4755
- const starts = childNodes.filter((child) => child.data.elementType === "StartEvent");
4756
- for (const start of starts) {
4757
- if (!start.data.trigger || start.data.trigger === "none") {
4758
- issues.push(issue("bpmn/event-subprocess-triggered-start", "error", "Event subprocess start events must define an event trigger.", start.id, [node.id]));
4759
- }
4760
- }
4761
- }
4762
- }
4763
- if (type === "Lane") {
4764
- const parent = node.parentId ? nodeById2.get(node.parentId) : void 0;
4765
- if (parent?.data.elementType !== "Pool") {
4766
- issues.push(issue("bpmn/lane-parent-pool", "error", "Lanes must be contained by a pool.", node.id));
4748
+ const sourceNode = diagramsCore.getNode(state, edge.source);
4749
+ const targetNode = diagramsCore.getNode(state, edge.target);
4750
+ if (!sourceNode || !targetNode) return null;
4751
+ const sourceAbsPos = getBpmnNodeAbsolutePosition(state, edge.source) ?? sourceNode.position;
4752
+ const targetAbsPos = getBpmnNodeAbsolutePosition(state, edge.target) ?? targetNode.position;
4753
+ const sourceCenter = diagramsCore.getNodeCenterPosition(sourceAbsPos, getBpmnNodeSize(sourceNode));
4754
+ const targetCenter = diagramsCore.getNodeCenterPosition(targetAbsPos, getBpmnNodeSize(targetNode));
4755
+ return diagramsCore.getEdgeLabelLayout([sourceCenter, targetCenter], options);
4756
+ }
4757
+ function resizeBpmnNodeByHandleCommand(options) {
4758
+ return {
4759
+ id: `bpmn.resizeByHandle.${options.id}`,
4760
+ label: "Resize BPMN element",
4761
+ execute: (state) => {
4762
+ const node = diagramsCore.getNode(state, options.id);
4763
+ if (!node) throw new Error(`Element "${options.id}" does not exist.`);
4764
+ const size = getBpmnElementSize(node.data.elementType);
4765
+ if (!size.resizable) {
4766
+ throw new Error(`${node.data.elementType} is not resizable in BPMN.`);
4767
4767
  }
4768
+ const oldW = node.width ?? size.width;
4769
+ const oldH = node.height ?? size.height;
4770
+ const resized = diagramsCore.resizeNodeByHandle(state, {
4771
+ id: options.id,
4772
+ handle: options.handle,
4773
+ dx: options.dx,
4774
+ dy: options.dy,
4775
+ constraints: { minWidth: size.minWidth, minHeight: size.minHeight }
4776
+ });
4777
+ const updatedNode = diagramsCore.getNode(resized, options.id);
4778
+ const newW = updatedNode?.width ?? oldW;
4779
+ const newH = updatedNode?.height ?? oldH;
4780
+ return clampBoundaryEventsAfterResize(resized, options.id, oldW, oldH, newW, newH);
4768
4781
  }
4769
- }
4770
- return {
4771
- valid: issues.every((item) => item.severity !== "error"),
4772
- issues
4773
4782
  };
4774
4783
  }
4784
+ function createBpmnLayoutCache(options) {
4785
+ return diagramsCore.createLayoutCache(options);
4786
+ }
4787
+ function withBpmnLayoutCache(layoutFn, cache) {
4788
+ return diagramsCore.withLayoutCache(layoutFn, cache ?? diagramsCore.createLayoutCache());
4789
+ }
4775
4790
 
4776
4791
  exports.AnnotationNode = AnnotationNode;
4777
4792
  exports.AssociationEdge = AssociationEdge;
@@ -4815,17 +4830,22 @@ exports.acceptsBoundaryEvents = acceptsBoundaryEvents;
4815
4830
  exports.attachBoundaryEventCommand = attachBoundaryEventCommand;
4816
4831
  exports.bpmnConnectionValidators = bpmnConnectionValidators;
4817
4832
  exports.canContainBpmnElement = canContainBpmnElement;
4833
+ exports.computeBpmnSmartGuides = computeBpmnSmartGuides;
4818
4834
  exports.connectBpmnCommand = connectBpmnCommand;
4819
4835
  exports.copyBpmnElements = copyBpmnElements;
4820
4836
  exports.createBpmnDiagramDocument = createBpmnDiagramDocument;
4837
+ exports.createBpmnEventBus = createBpmnEventBus;
4838
+ exports.createBpmnLayoutCache = createBpmnLayoutCache;
4821
4839
  exports.createBpmnNode = createBpmnNode;
4822
4840
  exports.createBpmnNodeCommand = createBpmnNodeCommand;
4823
4841
  exports.createSimulation = createSimulation;
4824
4842
  exports.deleteBpmnElementsCommand = deleteBpmnElementsCommand;
4825
4843
  exports.deserializeBpmnDiagram = deserializeBpmnDiagram;
4844
+ exports.deserializeBpmnDiagramSnapshot = deserializeBpmnDiagramSnapshot;
4826
4845
  exports.findBpmnContainerAt = findBpmnContainerAt;
4827
4846
  exports.fire = fire;
4828
4847
  exports.getBpmnDragHandleSelector = getBpmnDragHandleSelector;
4848
+ exports.getBpmnEdgeLabelLayout = getBpmnEdgeLabelLayout;
4829
4849
  exports.getBpmnElementSize = getBpmnElementSize;
4830
4850
  exports.getBpmnLaneIndexAtPosition = getBpmnLaneIndexAtPosition;
4831
4851
  exports.getBpmnNodeAbsolutePosition = getBpmnNodeAbsolutePosition;
@@ -4833,10 +4853,12 @@ exports.getBpmnNodeCenter = getBpmnNodeCenter;
4833
4853
  exports.getBpmnNodeSize = getBpmnNodeSize;
4834
4854
  exports.getBpmnNodeZIndex = getBpmnNodeZIndex;
4835
4855
  exports.getBpmnPoolLanes = getBpmnPoolLanes;
4856
+ exports.getBpmnTabOrder = getBpmnTabOrder;
4836
4857
  exports.getElementMeta = getElementMeta;
4837
4858
  exports.getFireable = getFireable;
4838
4859
  exports.getHandlePolicy = getHandlePolicy;
4839
4860
  exports.getOrientation = getOrientation;
4861
+ exports.groupAsBpmnSubProcessCommand = groupAsBpmnSubProcessCommand;
4840
4862
  exports.inferBpmnEdgeType = inferBpmnEdgeType;
4841
4863
  exports.isBpmnEdgeRoutingEditable = isBpmnEdgeRoutingEditable;
4842
4864
  exports.isBpmnElementResizable = isBpmnElementResizable;
@@ -4855,13 +4877,16 @@ exports.moveBpmnLaneCommand = moveBpmnLaneCommand;
4855
4877
  exports.parseBpmnDiagramDocument = parseBpmnDiagramDocument;
4856
4878
  exports.parseBpmnXml = parseBpmnXml;
4857
4879
  exports.pasteBpmnElementsCommand = pasteBpmnElementsCommand;
4880
+ exports.persistBpmnHistory = persistBpmnHistory;
4858
4881
  exports.reorderBpmnLane = reorderBpmnLane;
4859
4882
  exports.reorderBpmnLaneAfterDrop = reorderBpmnLaneAfterDrop;
4860
4883
  exports.reorderBpmnLaneCommand = reorderBpmnLaneCommand;
4861
4884
  exports.reparentBpmnNodeAtPosition = reparentBpmnNodeAtPosition;
4862
4885
  exports.reparentBpmnNodeCommand = reparentBpmnNodeCommand;
4863
4886
  exports.replaceBpmnNodeCommand = replaceBpmnNodeCommand;
4887
+ exports.resizeBpmnNodeByHandleCommand = resizeBpmnNodeByHandleCommand;
4864
4888
  exports.resizeBpmnNodeCommand = resizeBpmnNodeCommand;
4889
+ exports.restoreBpmnHistory = restoreBpmnHistory;
4865
4890
  exports.routeBpmnEdgeCommand = routeBpmnEdgeCommand;
4866
4891
  exports.runBpmnCommand = runBpmnCommand;
4867
4892
  exports.runBpmnCommands = runBpmnCommands;
@@ -4874,7 +4899,7 @@ exports.supportsMarkers = supportsMarkers;
4874
4899
  exports.tick = tick;
4875
4900
  exports.toBpmnRelativePosition = toBpmnRelativePosition;
4876
4901
  exports.validateBpmnConnectionForEdgeType = validateBpmnConnectionForEdgeType;
4877
- exports.validateBpmnDiagram = validateBpmnDiagram;
4902
+ exports.withBpmnLayoutCache = withBpmnLayoutCache;
4878
4903
  exports.withBpmnNodeZIndexes = withBpmnNodeZIndexes;
4879
4904
  //# sourceMappingURL=index.cjs.map
4880
4905
  //# sourceMappingURL=index.cjs.map