@aranzatech/diagrams-bpmn 0.1.3 → 0.2.1

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 (66) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +121 -0
  3. package/dist/catalog-OVnBDD8R.d.ts +9 -0
  4. package/dist/catalog-OWfI_yHU.d.cts +9 -0
  5. package/dist/{chunk-W3ROOC6E.js → chunk-33AR3PXF.js} +177 -40
  6. package/dist/chunk-33AR3PXF.js.map +1 -0
  7. package/dist/{chunk-3AFZDIMQ.js → chunk-ECTJRD7Z.js} +3 -3
  8. package/dist/{chunk-3AFZDIMQ.js.map → chunk-ECTJRD7Z.js.map} +1 -1
  9. package/dist/{chunk-NXMUX67A.js → chunk-H3YMTGFG.js} +79 -38
  10. package/dist/chunk-H3YMTGFG.js.map +1 -0
  11. package/dist/chunk-KALSGH4D.js +36 -0
  12. package/dist/chunk-KALSGH4D.js.map +1 -0
  13. package/dist/{chunk-DNR5WBQH.js → chunk-L5Z22RLX.js} +81 -20
  14. package/dist/chunk-L5Z22RLX.js.map +1 -0
  15. package/dist/chunk-OZKTOILD.js +3 -0
  16. package/dist/chunk-OZKTOILD.js.map +1 -0
  17. package/dist/{chunk-4AX573IV.js → chunk-RLAJNRF2.js} +3 -3
  18. package/dist/{chunk-4AX573IV.js.map → chunk-RLAJNRF2.js.map} +1 -1
  19. package/dist/chunk-YQTIODXH.js +532 -0
  20. package/dist/chunk-YQTIODXH.js.map +1 -0
  21. package/dist/chunk-ZFGQVLHB.js +226 -0
  22. package/dist/chunk-ZFGQVLHB.js.map +1 -0
  23. package/dist/edges/index.cjs +1 -1
  24. package/dist/edges/index.cjs.map +1 -1
  25. package/dist/edges/index.js +2 -2
  26. package/dist/elements/index.cjs +81 -17
  27. package/dist/elements/index.cjs.map +1 -1
  28. package/dist/elements/index.d.cts +4 -6
  29. package/dist/elements/index.d.ts +4 -6
  30. package/dist/elements/index.js +3 -2
  31. package/dist/index.cjs +1120 -118
  32. package/dist/index.cjs.map +1 -1
  33. package/dist/index.d.cts +10 -63
  34. package/dist/index.d.ts +10 -63
  35. package/dist/index.js +9 -42
  36. package/dist/index.js.map +1 -1
  37. package/dist/modeling/index.cjs +1241 -0
  38. package/dist/modeling/index.cjs.map +1 -0
  39. package/dist/modeling/index.d.cts +146 -0
  40. package/dist/modeling/index.d.ts +146 -0
  41. package/dist/modeling/index.js +5 -0
  42. package/dist/modeling/index.js.map +1 -0
  43. package/dist/nodes/index.cjs +91 -38
  44. package/dist/nodes/index.cjs.map +1 -1
  45. package/dist/nodes/index.js +2 -2
  46. package/dist/types-BxjCV2oX.d.ts +20 -0
  47. package/dist/{types-C78d_Kdh.d.cts → types-DznxZxpV.d.cts} +17 -19
  48. package/dist/{types-C78d_Kdh.d.ts → types-DznxZxpV.d.ts} +17 -19
  49. package/dist/types-vVi5T7qj.d.cts +20 -0
  50. package/dist/validation/index.cjs +848 -0
  51. package/dist/validation/index.cjs.map +1 -0
  52. package/dist/validation/index.d.cts +25 -0
  53. package/dist/validation/index.d.ts +25 -0
  54. package/dist/validation/index.js +5 -0
  55. package/dist/validation/index.js.map +1 -0
  56. package/dist/xml/index.cjs +215 -54
  57. package/dist/xml/index.cjs.map +1 -1
  58. package/dist/xml/index.d.cts +4 -19
  59. package/dist/xml/index.d.ts +4 -19
  60. package/dist/xml/index.js +2 -2
  61. package/package.json +16 -4
  62. package/dist/chunk-23B2IGK5.js +0 -24
  63. package/dist/chunk-23B2IGK5.js.map +0 -1
  64. package/dist/chunk-DNR5WBQH.js.map +0 -1
  65. package/dist/chunk-NXMUX67A.js.map +0 -1
  66. package/dist/chunk-W3ROOC6E.js.map +0 -1
@@ -40,7 +40,7 @@ var BPMN_ELEMENT_CATALOG = {
40
40
  },
41
41
  IntermediateCatchEvent: {
42
42
  label: "Intermediate Catch Event",
43
- icon: "Clock",
43
+ icon: "Clock3",
44
44
  category: "event",
45
45
  defaultWidth: 36,
46
46
  defaultHeight: 36,
@@ -54,7 +54,7 @@ var BPMN_ELEMENT_CATALOG = {
54
54
  },
55
55
  IntermediateThrowEvent: {
56
56
  label: "Intermediate Throw Event",
57
- icon: "Zap",
57
+ icon: "Send",
58
58
  category: "event",
59
59
  defaultWidth: 36,
60
60
  defaultHeight: 36,
@@ -68,7 +68,7 @@ var BPMN_ELEMENT_CATALOG = {
68
68
  },
69
69
  BoundaryEvent: {
70
70
  label: "Boundary Event",
71
- icon: "AlertCircle",
71
+ icon: "AlarmClock",
72
72
  category: "event",
73
73
  defaultWidth: 36,
74
74
  defaultHeight: 36,
@@ -84,7 +84,7 @@ var BPMN_ELEMENT_CATALOG = {
84
84
  // ─── Tasks ───────────────────────────────────────────────────────────────────
85
85
  Task: {
86
86
  label: "Task",
87
- icon: "Square",
87
+ icon: "CheckSquare",
88
88
  category: "task",
89
89
  defaultWidth: 120,
90
90
  defaultHeight: 60,
@@ -98,7 +98,7 @@ var BPMN_ELEMENT_CATALOG = {
98
98
  },
99
99
  UserTask: {
100
100
  label: "User Task",
101
- icon: "User",
101
+ icon: "UserRound",
102
102
  category: "task",
103
103
  defaultWidth: 120,
104
104
  defaultHeight: 60,
@@ -112,7 +112,7 @@ var BPMN_ELEMENT_CATALOG = {
112
112
  },
113
113
  ServiceTask: {
114
114
  label: "Service Task",
115
- icon: "Settings",
115
+ icon: "Cog",
116
116
  category: "task",
117
117
  defaultWidth: 120,
118
118
  defaultHeight: 60,
@@ -154,7 +154,7 @@ var BPMN_ELEMENT_CATALOG = {
154
154
  },
155
155
  BusinessRuleTask: {
156
156
  label: "Business Rule Task",
157
- icon: "Scale",
157
+ icon: "Table2",
158
158
  category: "task",
159
159
  defaultWidth: 120,
160
160
  defaultHeight: 60,
@@ -168,7 +168,7 @@ var BPMN_ELEMENT_CATALOG = {
168
168
  },
169
169
  ReceiveTask: {
170
170
  label: "Receive Task",
171
- icon: "Mail",
171
+ icon: "Inbox",
172
172
  category: "task",
173
173
  defaultWidth: 120,
174
174
  defaultHeight: 60,
@@ -211,7 +211,7 @@ var BPMN_ELEMENT_CATALOG = {
211
211
  // ─── Gateways ────────────────────────────────────────────────────────────────
212
212
  ExclusiveGateway: {
213
213
  label: "Exclusive Gateway",
214
- icon: "GitBranch",
214
+ icon: "X",
215
215
  category: "gateway",
216
216
  defaultWidth: 50,
217
217
  defaultHeight: 50,
@@ -224,7 +224,7 @@ var BPMN_ELEMENT_CATALOG = {
224
224
  },
225
225
  InclusiveGateway: {
226
226
  label: "Inclusive Gateway",
227
- icon: "GitMerge",
227
+ icon: "Circle",
228
228
  category: "gateway",
229
229
  defaultWidth: 50,
230
230
  defaultHeight: 50,
@@ -237,7 +237,7 @@ var BPMN_ELEMENT_CATALOG = {
237
237
  },
238
238
  ParallelGateway: {
239
239
  label: "Parallel Gateway",
240
- icon: "GitFork",
240
+ icon: "Plus",
241
241
  category: "gateway",
242
242
  defaultWidth: 50,
243
243
  defaultHeight: 50,
@@ -278,7 +278,7 @@ var BPMN_ELEMENT_CATALOG = {
278
278
  // ─── Containers ───────────────────────────────────────────────────────────────
279
279
  SubProcess: {
280
280
  label: "Sub-Process",
281
- icon: "Layout",
281
+ icon: "PlusSquare",
282
282
  category: "container",
283
283
  defaultWidth: 350,
284
284
  defaultHeight: 200,
@@ -293,7 +293,7 @@ var BPMN_ELEMENT_CATALOG = {
293
293
  },
294
294
  Transaction: {
295
295
  label: "Transaction",
296
- icon: "CreditCard",
296
+ icon: "Receipt",
297
297
  category: "container",
298
298
  defaultWidth: 350,
299
299
  defaultHeight: 200,
@@ -308,7 +308,7 @@ var BPMN_ELEMENT_CATALOG = {
308
308
  },
309
309
  EventSubProcess: {
310
310
  label: "Event Sub-Process",
311
- icon: "Workflow",
311
+ icon: "CircleDotDashed",
312
312
  category: "container",
313
313
  defaultWidth: 350,
314
314
  defaultHeight: 200,
@@ -323,7 +323,7 @@ var BPMN_ELEMENT_CATALOG = {
323
323
  },
324
324
  AdHocSubProcess: {
325
325
  label: "Ad-Hoc Sub-Process",
326
- icon: "Shuffle",
326
+ icon: "Waves",
327
327
  category: "container",
328
328
  defaultWidth: 350,
329
329
  defaultHeight: 200,
@@ -338,7 +338,7 @@ var BPMN_ELEMENT_CATALOG = {
338
338
  },
339
339
  Pool: {
340
340
  label: "Pool",
341
- icon: "Columns",
341
+ icon: "Rows3",
342
342
  category: "container",
343
343
  defaultWidth: 600,
344
344
  defaultHeight: 200,
@@ -353,7 +353,7 @@ var BPMN_ELEMENT_CATALOG = {
353
353
  },
354
354
  Lane: {
355
355
  label: "Lane",
356
- icon: "AlignJustify",
356
+ icon: "PanelTop",
357
357
  category: "container",
358
358
  defaultWidth: 600,
359
359
  defaultHeight: 120,
@@ -569,6 +569,30 @@ var BPMN_ELEMENT_CATALOG = {
569
569
  canBeEnd: false
570
570
  }
571
571
  };
572
+ var BPMN_RESIZABLE_ELEMENT_TYPES = [
573
+ "Task",
574
+ "UserTask",
575
+ "ServiceTask",
576
+ "ScriptTask",
577
+ "ManualTask",
578
+ "BusinessRuleTask",
579
+ "ReceiveTask",
580
+ "SendTask",
581
+ "CallActivity",
582
+ "SubProcess",
583
+ "Transaction",
584
+ "EventSubProcess",
585
+ "AdHocSubProcess",
586
+ "Pool",
587
+ "Lane",
588
+ "Annotation",
589
+ "Group",
590
+ "SubConversation",
591
+ "ChoreographyTask",
592
+ "SubChoreography",
593
+ "CallChoreography"
594
+ ];
595
+ new Set(BPMN_RESIZABLE_ELEMENT_TYPES);
572
596
 
573
597
  // src/xml/mapper.ts
574
598
  var MODDLE_TO_ELEMENT_TYPE = {
@@ -592,8 +616,8 @@ var MODDLE_TO_ELEMENT_TYPE = {
592
616
  "bpmn:EventBasedGateway": "EventBasedGateway",
593
617
  "bpmn:ComplexGateway": "ComplexGateway",
594
618
  "bpmn:SubProcess": "SubProcess",
595
- "bpmn:AdHocSubProcess": "SubProcess",
596
- "bpmn:Transaction": "SubProcess",
619
+ "bpmn:AdHocSubProcess": "AdHocSubProcess",
620
+ "bpmn:Transaction": "Transaction",
597
621
  "bpmn:TextAnnotation": "Annotation",
598
622
  "bpmn:Group": "Group",
599
623
  "bpmn:DataObject": "DataObject",
@@ -631,6 +655,9 @@ var ELEMENT_TYPE_TO_MODDLE = {
631
655
  EventBasedGateway: "bpmn:EventBasedGateway",
632
656
  ComplexGateway: "bpmn:ComplexGateway",
633
657
  SubProcess: "bpmn:SubProcess",
658
+ Transaction: "bpmn:Transaction",
659
+ EventSubProcess: "bpmn:SubProcess",
660
+ AdHocSubProcess: "bpmn:AdHocSubProcess",
634
661
  Pool: "bpmn:Participant",
635
662
  Lane: "bpmn:Lane",
636
663
  Annotation: "bpmn:TextAnnotation",
@@ -695,6 +722,10 @@ function asElements(v) {
695
722
  function asString(v) {
696
723
  return typeof v === "string" && v.trim() ? v.trim() : void 0;
697
724
  }
725
+ function extractDocumentation(el) {
726
+ const [doc] = asElements(el.documentation);
727
+ return asString(doc?.text);
728
+ }
698
729
  function extractDiagramInfo(definitions) {
699
730
  const shapes = /* @__PURE__ */ new Map();
700
731
  const waypoints = /* @__PURE__ */ new Map();
@@ -750,6 +781,7 @@ function extractTrigger(el) {
750
781
  function extractSubProcessVariant(el) {
751
782
  if (el.$type === "bpmn:Transaction") return "transaction";
752
783
  if (el.$type === "bpmn:AdHocSubProcess") return "adhoc";
784
+ if (el.$type === "bpmn:SubProcess" && el.triggeredByEvent === true) return "event";
753
785
  if (el.triggeredByEvent === true) return "event";
754
786
  return "embedded";
755
787
  }
@@ -763,7 +795,7 @@ function walkFlowElements(elements, parentId, ctx, nodes, edges) {
763
795
  continue;
764
796
  }
765
797
  if ($type === "bpmn:LaneSet") continue;
766
- const elementType = MODDLE_TO_ELEMENT_TYPE[$type];
798
+ const elementType = $type === "bpmn:SubProcess" && el.triggeredByEvent === true ? "EventSubProcess" : MODDLE_TO_ELEMENT_TYPE[$type];
767
799
  if (!elementType) {
768
800
  ctx.warnings.push(`Unknown element type "${$type}" (id=${id}) \u2014 skipped.`);
769
801
  continue;
@@ -784,22 +816,26 @@ function buildNode(el, elementType, parentId, ctx, nodes) {
784
816
  const y = shape?.y ?? 100;
785
817
  if (!shape) ctx.autoX.value += (meta?.defaultWidth ?? 120) + 20;
786
818
  const label = asString(el.name);
819
+ const documentation = extractDocumentation(el);
787
820
  const trigger = extractTrigger(el);
788
821
  const isNonInterrupting = el.cancelActivity === false;
822
+ const attachedToRef = el.attachedToRef?.id;
789
823
  const data = {
790
824
  elementType,
791
825
  ...label ? { label } : {},
826
+ ...documentation ? { documentation } : {},
792
827
  ...trigger ? { trigger } : {},
793
- ...isNonInterrupting ? { isNonInterrupting: true } : {}
828
+ ...isNonInterrupting ? { isNonInterrupting: true } : {},
829
+ ...attachedToRef ? { attachedToRef } : {}
794
830
  };
795
- if (elementType === "SubProcess") {
831
+ if (elementType === "SubProcess" || elementType === "Transaction" || elementType === "EventSubProcess" || elementType === "AdHocSubProcess") {
796
832
  const variant = extractSubProcessVariant(el);
797
833
  if (variant) data.subProcessVariant = variant;
798
834
  const isExpanded = shape?.isExpanded ?? true;
799
835
  data.isExpanded = isExpanded;
800
836
  }
801
837
  const laneId = ctx.laneMembership.get(id);
802
- const effectiveParentId = laneId ?? parentId;
838
+ const effectiveParentId = attachedToRef ?? laneId ?? parentId;
803
839
  const node = {
804
840
  id,
805
841
  type: elementType,
@@ -820,10 +856,12 @@ function buildEdge(el, edgeType, ctx, edges) {
820
856
  return;
821
857
  }
822
858
  const label = asString(el.name);
859
+ const documentation = extractDocumentation(el);
823
860
  const condExpr = el.conditionExpression;
824
861
  const data = {
825
862
  edgeType,
826
863
  ...label ? { label } : {},
864
+ ...documentation ? { documentation } : {},
827
865
  ...condExpr?.body ? { conditionExpression: condExpr.body } : {}
828
866
  };
829
867
  const waypoints = ctx.waypoints.get(id);
@@ -924,7 +962,46 @@ async function parseBpmnXml(xml) {
924
962
  );
925
963
  }
926
964
  }
927
- return { nodes, edges, warnings };
965
+ const defaultFlowById = /* @__PURE__ */ new Set();
966
+ const nodeIds = new Set(nodes.map((node) => node.id));
967
+ for (const rootEl of asElements(rootElement.rootElements)) {
968
+ collectDefaultFlows(rootEl, defaultFlowById);
969
+ }
970
+ const normalizedEdges = edges.map((edge) => {
971
+ if (!defaultFlowById.has(edge.id)) return edge;
972
+ const data = {
973
+ edgeType: edge.data?.edgeType ?? edge.type,
974
+ ...edge.data ?? {},
975
+ isDefault: true
976
+ };
977
+ return { ...edge, data };
978
+ });
979
+ return {
980
+ nodes: normalizeChildPositions(nodes, nodeIds),
981
+ edges: normalizedEdges,
982
+ warnings
983
+ };
984
+ }
985
+ function collectDefaultFlows(el, defaultFlowById) {
986
+ const defaultRef = el.default;
987
+ if (defaultRef?.id) defaultFlowById.add(defaultRef.id);
988
+ for (const child of asElements(el.rootElements)) collectDefaultFlows(child, defaultFlowById);
989
+ for (const child of asElements(el.flowElements)) collectDefaultFlows(child, defaultFlowById);
990
+ }
991
+ function normalizeChildPositions(nodes, nodeIds) {
992
+ const absoluteById = new Map(nodes.map((node) => [node.id, node.position]));
993
+ return nodes.map((node) => {
994
+ if (!node.parentId || !nodeIds.has(node.parentId)) return node;
995
+ const parentPosition = absoluteById.get(node.parentId);
996
+ if (!parentPosition) return node;
997
+ return {
998
+ ...node,
999
+ position: {
1000
+ x: node.position.x - parentPosition.x,
1001
+ y: node.position.y - parentPosition.y
1002
+ }
1003
+ };
1004
+ });
928
1005
  }
929
1006
  function uid(prefix, id) {
930
1007
  return `${prefix}_${id}`;
@@ -932,19 +1009,6 @@ function uid(prefix, id) {
932
1009
  function asNodes(nodes, types) {
933
1010
  return nodes.filter((n) => types.includes(n.data.elementType));
934
1011
  }
935
- function buildFlowableAttrs(data) {
936
- const attrs = {};
937
- if (data.flowableAssignee) attrs["flowable:assignee"] = data.flowableAssignee;
938
- if (data.flowableCandidateGroups) attrs["flowable:candidateGroups"] = data.flowableCandidateGroups;
939
- if (data.flowableCandidateUsers) attrs["flowable:candidateUsers"] = data.flowableCandidateUsers;
940
- if (data.flowableFormKey) attrs["flowable:formKey"] = data.flowableFormKey;
941
- if (data.flowableDueDate) attrs["flowable:dueDate"] = data.flowableDueDate;
942
- if (data.flowableType) attrs["flowable:type"] = data.flowableType;
943
- if (data.flowableExpression) attrs["flowable:expression"] = data.flowableExpression;
944
- if (data.flowableClass) attrs["flowable:class"] = data.flowableClass;
945
- if (data.flowableDelegateExpression) attrs["flowable:delegateExpression"] = data.flowableDelegateExpression;
946
- return attrs;
947
- }
948
1012
  function buildSemanticModel(moddle, nodes, edges, opts) {
949
1013
  const defId = opts.id ?? "Definitions_1";
950
1014
  const defName = opts.name;
@@ -1003,13 +1067,32 @@ function buildSemanticModel(moddle, nodes, edges, opts) {
1003
1067
  return definitions;
1004
1068
  }
1005
1069
  function buildProcess(moddle, allNodes, allEdges, poolId, laneNodes, processId) {
1006
- const myNodes = poolId ? allNodes.filter(
1007
- (n) => n.parentId === poolId || laneNodes.some((l) => l.id === n.parentId && l.parentId === poolId)
1008
- ) : allNodes.filter((n) => n.data.elementType !== "Pool" && n.data.elementType !== "Lane");
1070
+ const subProcessIds = new Set(
1071
+ allNodes.filter(
1072
+ (n) => n.data.elementType === "SubProcess" || n.data.elementType === "Transaction" || n.data.elementType === "EventSubProcess" || n.data.elementType === "AdHocSubProcess"
1073
+ ).map((n) => n.id)
1074
+ );
1075
+ const isInsideSubProcess = (node) => {
1076
+ let parentId = node.parentId;
1077
+ while (parentId) {
1078
+ if (subProcessIds.has(parentId)) return true;
1079
+ parentId = allNodes.find((candidate) => candidate.id === parentId)?.parentId;
1080
+ }
1081
+ return false;
1082
+ };
1083
+ const belongsToPool = (node) => {
1084
+ let parentId = node.parentId;
1085
+ while (parentId) {
1086
+ if (parentId === poolId) return true;
1087
+ parentId = allNodes.find((candidate) => candidate.id === parentId)?.parentId;
1088
+ }
1089
+ return false;
1090
+ };
1091
+ const myNodes = (poolId ? allNodes.filter((n) => belongsToPool(n)) : allNodes.filter((n) => n.data.elementType !== "Pool" && n.data.elementType !== "Lane")).filter((n) => !isInsideSubProcess(n));
1009
1092
  const myLanes = laneNodes.filter((l) => poolId ? l.parentId === poolId : true);
1010
1093
  const flowElements = [];
1011
1094
  for (const node of myNodes) {
1012
- const el = buildFlowElement(moddle, node);
1095
+ const el = buildFlowElement(moddle, node, allNodes, allEdges);
1013
1096
  if (el) flowElements.push(el);
1014
1097
  }
1015
1098
  const myNodeIds = new Set(myNodes.map((n) => n.id));
@@ -1020,6 +1103,17 @@ function buildProcess(moddle, allNodes, allEdges, poolId, laneNodes, processId)
1020
1103
  const edgeMeta = buildEdgeElement(moddle, edge);
1021
1104
  if (edgeMeta) flowElements.push(edgeMeta);
1022
1105
  }
1106
+ const elementById = new Map(
1107
+ flowElements.filter((element) => typeof element.id === "string").map((element) => [element.id, element])
1108
+ );
1109
+ for (const edge of myEdges) {
1110
+ if (!edge.data?.isDefault) continue;
1111
+ const sourceElement = elementById.get(edge.source);
1112
+ const edgeElement = elementById.get(edge.id);
1113
+ if (sourceElement && edgeElement) {
1114
+ sourceElement.default = edgeElement;
1115
+ }
1116
+ }
1023
1117
  const process = moddle.create("bpmn:Process", {
1024
1118
  id: processId,
1025
1119
  isExecutable: true,
@@ -1040,7 +1134,7 @@ function buildProcess(moddle, allNodes, allEdges, poolId, laneNodes, processId)
1040
1134
  }
1041
1135
  return process;
1042
1136
  }
1043
- function buildFlowElement(moddle, node, _allNodes, _allEdges) {
1137
+ function buildFlowElement(moddle, node, allNodes, allEdges) {
1044
1138
  const { elementType, label, trigger } = node.data;
1045
1139
  if (elementType === "Pool" || elementType === "Lane") return null;
1046
1140
  const moddleType = ELEMENT_TYPE_TO_MODDLE[elementType];
@@ -1049,25 +1143,46 @@ function buildFlowElement(moddle, node, _allNodes, _allEdges) {
1049
1143
  id: node.id,
1050
1144
  name: label ?? ""
1051
1145
  };
1146
+ if (node.data.documentation) {
1147
+ attrs.documentation = [
1148
+ moddle.create("bpmn:Documentation", { text: node.data.documentation })
1149
+ ];
1150
+ }
1052
1151
  if (trigger && trigger !== "none") {
1053
1152
  const defType = TRIGGER_TO_EVENT_DEF[trigger];
1054
1153
  if (defType) {
1055
1154
  attrs.eventDefinitions = [moddle.create(defType, { id: uid("EventDef", node.id) })];
1056
1155
  }
1057
1156
  }
1058
- if (elementType === "SubProcess" && node.data.subProcessVariant === "transaction") {
1059
- return moddle.create("bpmn:Transaction", attrs);
1157
+ if (elementType === "BoundaryEvent") {
1158
+ attrs.attachedToRef = { id: node.data.attachedToRef ?? node.parentId };
1159
+ attrs.cancelActivity = node.data.isNonInterrupting ? false : true;
1060
1160
  }
1061
- if (elementType === "SubProcess" && node.data.subProcessVariant === "adhoc") {
1062
- return moddle.create("bpmn:AdHocSubProcess", attrs);
1161
+ const isSubProcess = elementType === "SubProcess" || elementType === "Transaction" || elementType === "EventSubProcess" || elementType === "AdHocSubProcess";
1162
+ if (isSubProcess) {
1163
+ attrs.flowElements = buildNestedFlowElements(moddle, node, allNodes, allEdges);
1164
+ if (elementType === "EventSubProcess" || node.data.subProcessVariant === "event") {
1165
+ attrs.triggeredByEvent = true;
1166
+ }
1063
1167
  }
1064
1168
  const element = moddle.create(moddleType, attrs);
1065
- const flowableAttrs = buildFlowableAttrs(node.data);
1066
- if (Object.keys(flowableAttrs).length > 0) {
1067
- element.$attrs = flowableAttrs;
1068
- }
1069
1169
  return element;
1070
1170
  }
1171
+ function buildNestedFlowElements(moddle, parent, allNodes, allEdges) {
1172
+ const childNodes = allNodes.filter((node) => node.parentId === parent.id);
1173
+ const childNodeIds = new Set(childNodes.map((node) => node.id));
1174
+ const flowElements = [];
1175
+ for (const child of childNodes) {
1176
+ const element = buildFlowElement(moddle, child, allNodes, allEdges);
1177
+ if (element) flowElements.push(element);
1178
+ }
1179
+ for (const edge of allEdges) {
1180
+ if (!childNodeIds.has(edge.source) || !childNodeIds.has(edge.target)) continue;
1181
+ const element = buildEdgeElement(moddle, edge);
1182
+ if (element) flowElements.push(element);
1183
+ }
1184
+ return flowElements;
1185
+ }
1071
1186
  function buildEdgeElement(moddle, edge) {
1072
1187
  if (!edge.data) return null;
1073
1188
  const moddleType = EDGE_TYPE_TO_MODDLE[edge.data.edgeType];
@@ -1078,6 +1193,11 @@ function buildEdgeElement(moddle, edge) {
1078
1193
  sourceRef: { id: edge.source },
1079
1194
  targetRef: { id: edge.target }
1080
1195
  };
1196
+ if (edge.data.documentation) {
1197
+ attrs.documentation = [
1198
+ moddle.create("bpmn:Documentation", { text: edge.data.documentation })
1199
+ ];
1200
+ }
1081
1201
  if (edge.data.conditionExpression) {
1082
1202
  attrs.conditionExpression = moddle.create("bpmn:FormalExpression", {
1083
1203
  body: edge.data.conditionExpression
@@ -1088,13 +1208,14 @@ function buildEdgeElement(moddle, edge) {
1088
1208
  function buildBpmnDI(moddle, definitions, nodes, edges) {
1089
1209
  const shapes = [];
1090
1210
  const edgeShapes = [];
1211
+ const absolutePositionById = buildAbsolutePositionMap(nodes);
1091
1212
  for (const node of nodes) {
1092
1213
  const meta = BPMN_ELEMENT_CATALOG[node.data.elementType];
1093
1214
  const w = node.width ?? meta?.defaultWidth ?? 120;
1094
1215
  const h = node.height ?? meta?.defaultHeight ?? 60;
1095
1216
  const bounds = moddle.create("dc:Bounds", {
1096
- x: node.position.x,
1097
- y: node.position.y,
1217
+ x: absolutePositionById.get(node.id)?.x ?? node.position.x,
1218
+ y: absolutePositionById.get(node.id)?.y ?? node.position.y,
1098
1219
  width: w,
1099
1220
  height: h
1100
1221
  });
@@ -1109,9 +1230,9 @@ function buildBpmnDI(moddle, definitions, nodes, edges) {
1109
1230
  shapes.push(shape);
1110
1231
  }
1111
1232
  for (const edge of edges) {
1112
- const waypoints = edge.data?.routingPoints?.map(
1233
+ const waypoints = resolveEdgeWaypoints(edge, nodes, absolutePositionById).map(
1113
1234
  (p) => moddle.create("dc:Point", { x: p.x, y: p.y })
1114
- ) ?? [];
1235
+ );
1115
1236
  edgeShapes.push(
1116
1237
  moddle.create("bpmndi:BPMNEdge", {
1117
1238
  id: uid("BPMNEdge", edge.id),
@@ -1133,6 +1254,46 @@ function buildBpmnDI(moddle, definitions, nodes, edges) {
1133
1254
  });
1134
1255
  definitions.diagrams = [diagram];
1135
1256
  }
1257
+ function resolveEdgeWaypoints(edge, nodes, absolutePositionById) {
1258
+ if (edge.data?.routingPoints && edge.data.routingPoints.length >= 2) {
1259
+ return edge.data.routingPoints;
1260
+ }
1261
+ const source = nodes.find((node) => node.id === edge.source);
1262
+ const target = nodes.find((node) => node.id === edge.target);
1263
+ if (!source || !target) return [];
1264
+ const sourceMeta = BPMN_ELEMENT_CATALOG[source.data.elementType];
1265
+ const targetMeta = BPMN_ELEMENT_CATALOG[target.data.elementType];
1266
+ const sourcePosition = absolutePositionById.get(source.id) ?? source.position;
1267
+ const targetPosition = absolutePositionById.get(target.id) ?? target.position;
1268
+ return [
1269
+ {
1270
+ x: sourcePosition.x + (source.width ?? sourceMeta.defaultWidth) / 2,
1271
+ y: sourcePosition.y + (source.height ?? sourceMeta.defaultHeight) / 2
1272
+ },
1273
+ {
1274
+ x: targetPosition.x + (target.width ?? targetMeta.defaultWidth) / 2,
1275
+ y: targetPosition.y + (target.height ?? targetMeta.defaultHeight) / 2
1276
+ }
1277
+ ];
1278
+ }
1279
+ function buildAbsolutePositionMap(nodes) {
1280
+ const nodeById = new Map(nodes.map((node) => [node.id, node]));
1281
+ const absoluteById = /* @__PURE__ */ new Map();
1282
+ function resolve(node) {
1283
+ const cached = absoluteById.get(node.id);
1284
+ if (cached) return cached;
1285
+ const parent = node.parentId ? nodeById.get(node.parentId) : void 0;
1286
+ const parentPosition = parent ? resolve(parent) : { x: 0, y: 0 };
1287
+ const absolute = {
1288
+ x: parentPosition.x + node.position.x,
1289
+ y: parentPosition.y + node.position.y
1290
+ };
1291
+ absoluteById.set(node.id, absolute);
1292
+ return absolute;
1293
+ }
1294
+ for (const node of nodes) resolve(node);
1295
+ return absoluteById;
1296
+ }
1136
1297
  async function serializeBpmnXml(nodes, edges, opts = {}) {
1137
1298
  const moddle = new bpmnModdle.BpmnModdle();
1138
1299
  const definitions = buildSemanticModel(moddle, nodes, edges, opts);