@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
package/dist/index.cjs CHANGED
@@ -4,6 +4,8 @@ var react = require('@xyflow/react');
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
5
  var routing = require('@aranzatech/diagrams-core/routing');
6
6
  var bpmnModdle = require('bpmn-moddle');
7
+ var diagramsCore = require('@aranzatech/diagrams-core');
8
+ var serialization = require('@aranzatech/diagrams-core/serialization');
7
9
 
8
10
  // src/elements/catalog.ts
9
11
  var BPMN_ELEMENT_CATALOG = {
@@ -41,7 +43,7 @@ var BPMN_ELEMENT_CATALOG = {
41
43
  },
42
44
  IntermediateCatchEvent: {
43
45
  label: "Intermediate Catch Event",
44
- icon: "Clock",
46
+ icon: "Clock3",
45
47
  category: "event",
46
48
  defaultWidth: 36,
47
49
  defaultHeight: 36,
@@ -55,7 +57,7 @@ var BPMN_ELEMENT_CATALOG = {
55
57
  },
56
58
  IntermediateThrowEvent: {
57
59
  label: "Intermediate Throw Event",
58
- icon: "Zap",
60
+ icon: "Send",
59
61
  category: "event",
60
62
  defaultWidth: 36,
61
63
  defaultHeight: 36,
@@ -69,7 +71,7 @@ var BPMN_ELEMENT_CATALOG = {
69
71
  },
70
72
  BoundaryEvent: {
71
73
  label: "Boundary Event",
72
- icon: "AlertCircle",
74
+ icon: "AlarmClock",
73
75
  category: "event",
74
76
  defaultWidth: 36,
75
77
  defaultHeight: 36,
@@ -85,7 +87,7 @@ var BPMN_ELEMENT_CATALOG = {
85
87
  // ─── Tasks ───────────────────────────────────────────────────────────────────
86
88
  Task: {
87
89
  label: "Task",
88
- icon: "Square",
90
+ icon: "CheckSquare",
89
91
  category: "task",
90
92
  defaultWidth: 120,
91
93
  defaultHeight: 60,
@@ -99,7 +101,7 @@ var BPMN_ELEMENT_CATALOG = {
99
101
  },
100
102
  UserTask: {
101
103
  label: "User Task",
102
- icon: "User",
104
+ icon: "UserRound",
103
105
  category: "task",
104
106
  defaultWidth: 120,
105
107
  defaultHeight: 60,
@@ -113,7 +115,7 @@ var BPMN_ELEMENT_CATALOG = {
113
115
  },
114
116
  ServiceTask: {
115
117
  label: "Service Task",
116
- icon: "Settings",
118
+ icon: "Cog",
117
119
  category: "task",
118
120
  defaultWidth: 120,
119
121
  defaultHeight: 60,
@@ -155,7 +157,7 @@ var BPMN_ELEMENT_CATALOG = {
155
157
  },
156
158
  BusinessRuleTask: {
157
159
  label: "Business Rule Task",
158
- icon: "Scale",
160
+ icon: "Table2",
159
161
  category: "task",
160
162
  defaultWidth: 120,
161
163
  defaultHeight: 60,
@@ -169,7 +171,7 @@ var BPMN_ELEMENT_CATALOG = {
169
171
  },
170
172
  ReceiveTask: {
171
173
  label: "Receive Task",
172
- icon: "Mail",
174
+ icon: "Inbox",
173
175
  category: "task",
174
176
  defaultWidth: 120,
175
177
  defaultHeight: 60,
@@ -212,7 +214,7 @@ var BPMN_ELEMENT_CATALOG = {
212
214
  // ─── Gateways ────────────────────────────────────────────────────────────────
213
215
  ExclusiveGateway: {
214
216
  label: "Exclusive Gateway",
215
- icon: "GitBranch",
217
+ icon: "X",
216
218
  category: "gateway",
217
219
  defaultWidth: 50,
218
220
  defaultHeight: 50,
@@ -225,7 +227,7 @@ var BPMN_ELEMENT_CATALOG = {
225
227
  },
226
228
  InclusiveGateway: {
227
229
  label: "Inclusive Gateway",
228
- icon: "GitMerge",
230
+ icon: "Circle",
229
231
  category: "gateway",
230
232
  defaultWidth: 50,
231
233
  defaultHeight: 50,
@@ -238,7 +240,7 @@ var BPMN_ELEMENT_CATALOG = {
238
240
  },
239
241
  ParallelGateway: {
240
242
  label: "Parallel Gateway",
241
- icon: "GitFork",
243
+ icon: "Plus",
242
244
  category: "gateway",
243
245
  defaultWidth: 50,
244
246
  defaultHeight: 50,
@@ -279,7 +281,7 @@ var BPMN_ELEMENT_CATALOG = {
279
281
  // ─── Containers ───────────────────────────────────────────────────────────────
280
282
  SubProcess: {
281
283
  label: "Sub-Process",
282
- icon: "Layout",
284
+ icon: "PlusSquare",
283
285
  category: "container",
284
286
  defaultWidth: 350,
285
287
  defaultHeight: 200,
@@ -294,7 +296,7 @@ var BPMN_ELEMENT_CATALOG = {
294
296
  },
295
297
  Transaction: {
296
298
  label: "Transaction",
297
- icon: "CreditCard",
299
+ icon: "Receipt",
298
300
  category: "container",
299
301
  defaultWidth: 350,
300
302
  defaultHeight: 200,
@@ -309,7 +311,7 @@ var BPMN_ELEMENT_CATALOG = {
309
311
  },
310
312
  EventSubProcess: {
311
313
  label: "Event Sub-Process",
312
- icon: "Workflow",
314
+ icon: "CircleDotDashed",
313
315
  category: "container",
314
316
  defaultWidth: 350,
315
317
  defaultHeight: 200,
@@ -324,7 +326,7 @@ var BPMN_ELEMENT_CATALOG = {
324
326
  },
325
327
  AdHocSubProcess: {
326
328
  label: "Ad-Hoc Sub-Process",
327
- icon: "Shuffle",
329
+ icon: "Waves",
328
330
  category: "container",
329
331
  defaultWidth: 350,
330
332
  defaultHeight: 200,
@@ -339,7 +341,7 @@ var BPMN_ELEMENT_CATALOG = {
339
341
  },
340
342
  Pool: {
341
343
  label: "Pool",
342
- icon: "Columns",
344
+ icon: "Rows3",
343
345
  category: "container",
344
346
  defaultWidth: 600,
345
347
  defaultHeight: 200,
@@ -354,7 +356,7 @@ var BPMN_ELEMENT_CATALOG = {
354
356
  },
355
357
  Lane: {
356
358
  label: "Lane",
357
- icon: "AlignJustify",
359
+ icon: "PanelTop",
358
360
  category: "container",
359
361
  defaultWidth: 600,
360
362
  defaultHeight: 120,
@@ -573,6 +575,67 @@ var BPMN_ELEMENT_CATALOG = {
573
575
  function getElementMeta(type) {
574
576
  return BPMN_ELEMENT_CATALOG[type];
575
577
  }
578
+ var BPMN_RESIZABLE_ELEMENT_TYPES = [
579
+ "Task",
580
+ "UserTask",
581
+ "ServiceTask",
582
+ "ScriptTask",
583
+ "ManualTask",
584
+ "BusinessRuleTask",
585
+ "ReceiveTask",
586
+ "SendTask",
587
+ "CallActivity",
588
+ "SubProcess",
589
+ "Transaction",
590
+ "EventSubProcess",
591
+ "AdHocSubProcess",
592
+ "Pool",
593
+ "Lane",
594
+ "Annotation",
595
+ "Group",
596
+ "SubConversation",
597
+ "ChoreographyTask",
598
+ "SubChoreography",
599
+ "CallChoreography"
600
+ ];
601
+ var BPMN_MIN_SIZE_OVERRIDES = {
602
+ Task: { minWidth: 80, minHeight: 48 },
603
+ UserTask: { minWidth: 80, minHeight: 48 },
604
+ ServiceTask: { minWidth: 80, minHeight: 48 },
605
+ ScriptTask: { minWidth: 80, minHeight: 48 },
606
+ ManualTask: { minWidth: 80, minHeight: 48 },
607
+ BusinessRuleTask: { minWidth: 80, minHeight: 48 },
608
+ ReceiveTask: { minWidth: 80, minHeight: 48 },
609
+ SendTask: { minWidth: 80, minHeight: 48 },
610
+ CallActivity: { minWidth: 80, minHeight: 48 },
611
+ SubProcess: { minWidth: 160, minHeight: 100 },
612
+ Transaction: { minWidth: 160, minHeight: 100 },
613
+ EventSubProcess: { minWidth: 160, minHeight: 100 },
614
+ AdHocSubProcess: { minWidth: 160, minHeight: 100 },
615
+ Pool: { minWidth: 240, minHeight: 120 },
616
+ Lane: { minWidth: 240, minHeight: 80 },
617
+ Annotation: { minWidth: 80, minHeight: 40 },
618
+ Group: { minWidth: 120, minHeight: 80 },
619
+ SubConversation: { minWidth: 60, minHeight: 52 },
620
+ ChoreographyTask: { minWidth: 100, minHeight: 70 },
621
+ SubChoreography: { minWidth: 100, minHeight: 70 },
622
+ CallChoreography: { minWidth: 100, minHeight: 70 }
623
+ };
624
+ var resizableTypes = new Set(BPMN_RESIZABLE_ELEMENT_TYPES);
625
+ function isBpmnElementResizable(type) {
626
+ return resizableTypes.has(type);
627
+ }
628
+ function getBpmnElementSize(type) {
629
+ const meta = getElementMeta(type);
630
+ const min = BPMN_MIN_SIZE_OVERRIDES[type];
631
+ return {
632
+ width: meta.defaultWidth,
633
+ height: meta.defaultHeight,
634
+ minWidth: meta.minWidth ?? min?.minWidth ?? meta.defaultWidth,
635
+ minHeight: meta.minHeight ?? min?.minHeight ?? meta.defaultHeight,
636
+ resizable: meta.resizable ?? isBpmnElementResizable(type)
637
+ };
638
+ }
576
639
 
577
640
  // src/elements/guards.ts
578
641
  var TASK_TYPES = /* @__PURE__ */ new Set([
@@ -696,13 +759,19 @@ function BpmnHandles({ variant = "all" }) {
696
759
  // src/nodes/shared/theme.ts
697
760
  var BPMN_THEME = {
698
761
  fill: "#ffffff",
699
- stroke: "#404040",
700
- strokeSelected: "#1a56db",
762
+ fillSoft: "#f8fbff",
763
+ fillSubtle: "#eef6ff",
764
+ stroke: "#334155",
765
+ strokeSelected: "#2563eb",
701
766
  strokeWidth: 1.5,
702
767
  strokeWidthSelected: 2.5,
703
768
  fontFamily: "Inter, system-ui, sans-serif",
704
769
  fontSize: 11,
705
- labelColor: "#1a1a1a"};
770
+ labelColor: "#0f172a",
771
+ shadow: "0 4px 12px rgba(15, 23, 42, 0.08)",
772
+ shadowSelected: "0 0 0 4px rgba(37, 99, 235, 0.14), 0 8px 18px rgba(15, 23, 42, 0.12)",
773
+ transition: "box-shadow 140ms ease, filter 140ms ease, transform 140ms ease"
774
+ };
706
775
  function resolveStroke(selected, override) {
707
776
  if (selected) return BPMN_THEME.strokeSelected;
708
777
  return override ?? BPMN_THEME.stroke;
@@ -710,6 +779,12 @@ function resolveStroke(selected, override) {
710
779
  function resolveStrokeWidth(selected) {
711
780
  return selected ? BPMN_THEME.strokeWidthSelected : BPMN_THEME.strokeWidth;
712
781
  }
782
+ function resolveShapeFilter(selected) {
783
+ return selected ? "drop-shadow(0 0 0 rgba(37,99,235,0.2)) drop-shadow(0 8px 14px rgba(15,23,42,0.12))" : "drop-shadow(0 4px 10px rgba(15,23,42,0.08))";
784
+ }
785
+ function resolveNodeShadow(selected) {
786
+ return selected ? BPMN_THEME.shadowSelected : BPMN_THEME.shadow;
787
+ }
713
788
  var EXTERNAL_STYLE = {
714
789
  position: "absolute",
715
790
  top: "100%",
@@ -862,7 +937,7 @@ function StartEventNode({ data, selected }) {
862
937
  const trigger = d.trigger ?? "none";
863
938
  const dashArray = d.isNonInterrupting ? "4 2" : void 0;
864
939
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { width: SIZE, height: SIZE, position: "relative" }, children: [
865
- /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: SIZE, height: SIZE, style: { overflow: "visible", display: "block" }, children: [
940
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: SIZE, height: SIZE, style: { overflow: "visible", display: "block", filter: resolveShapeFilter(selected) }, children: [
866
941
  /* @__PURE__ */ jsxRuntime.jsx(
867
942
  "circle",
868
943
  {
@@ -891,7 +966,7 @@ function EndEventNode({ data, selected }) {
891
966
  const fill = d.color?.fill ?? BPMN_THEME.fill;
892
967
  const trigger = d.trigger ?? "none";
893
968
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { width: SIZE2, height: SIZE2, position: "relative" }, children: [
894
- /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: SIZE2, height: SIZE2, style: { overflow: "visible", display: "block" }, children: [
969
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: SIZE2, height: SIZE2, style: { overflow: "visible", display: "block", filter: resolveShapeFilter(selected) }, children: [
895
970
  /* @__PURE__ */ jsxRuntime.jsx(
896
971
  "circle",
897
972
  {
@@ -919,9 +994,9 @@ function IntermediateCatchEventNode({ data, selected }) {
919
994
  const stroke = resolveStroke(selected, d.color?.stroke);
920
995
  const sw = resolveStrokeWidth(selected);
921
996
  const fill = d.color?.fill ?? BPMN_THEME.fill;
922
- const trigger = d.trigger ?? "none";
997
+ const trigger = d.trigger && d.trigger !== "none" ? d.trigger : "timer";
923
998
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { width: SIZE3, height: SIZE3, position: "relative" }, children: [
924
- /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: SIZE3, height: SIZE3, style: { overflow: "visible", display: "block" }, children: [
999
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: SIZE3, height: SIZE3, style: { overflow: "visible", display: "block", filter: resolveShapeFilter(selected) }, children: [
925
1000
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: CX3, cy: CX3, r: R_OUTER, fill, stroke, strokeWidth: sw }),
926
1001
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: CX3, cy: CX3, r: R_INNER, fill: "none", stroke, strokeWidth: sw }),
927
1002
  /* @__PURE__ */ jsxRuntime.jsx(EventMarker, { cx: CX3, cy: CX3, trigger, filled: false, stroke, bg: fill, r: ICON_R })
@@ -935,9 +1010,9 @@ function IntermediateThrowEventNode({ data, selected }) {
935
1010
  const stroke = resolveStroke(selected, d.color?.stroke);
936
1011
  const sw = resolveStrokeWidth(selected);
937
1012
  const fill = d.color?.fill ?? BPMN_THEME.fill;
938
- const trigger = d.trigger ?? "none";
1013
+ const trigger = d.trigger && d.trigger !== "none" ? d.trigger : "message";
939
1014
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { width: SIZE3, height: SIZE3, position: "relative" }, children: [
940
- /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: SIZE3, height: SIZE3, style: { overflow: "visible", display: "block" }, children: [
1015
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: SIZE3, height: SIZE3, style: { overflow: "visible", display: "block", filter: resolveShapeFilter(selected) }, children: [
941
1016
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: CX3, cy: CX3, r: R_OUTER, fill, stroke, strokeWidth: sw }),
942
1017
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: CX3, cy: CX3, r: R_INNER, fill: stroke, stroke, strokeWidth: sw }),
943
1018
  /* @__PURE__ */ jsxRuntime.jsx(EventMarker, { cx: CX3, cy: CX3, trigger, filled: true, stroke: fill, bg: stroke, r: ICON_R })
@@ -951,10 +1026,10 @@ function BoundaryEventNode({ data, selected }) {
951
1026
  const stroke = resolveStroke(selected, d.color?.stroke);
952
1027
  const sw = resolveStrokeWidth(selected);
953
1028
  const fill = d.color?.fill ?? BPMN_THEME.fill;
954
- const trigger = d.trigger ?? "none";
1029
+ const trigger = d.trigger && d.trigger !== "none" ? d.trigger : "timer";
955
1030
  const dashArray = d.isNonInterrupting ? "4 2" : void 0;
956
1031
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { width: SIZE3, height: SIZE3, position: "relative" }, children: [
957
- /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: SIZE3, height: SIZE3, style: { overflow: "visible", display: "block" }, children: [
1032
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: SIZE3, height: SIZE3, style: { overflow: "visible", display: "block", filter: resolveShapeFilter(selected) }, children: [
958
1033
  /* @__PURE__ */ jsxRuntime.jsx(
959
1034
  "circle",
960
1035
  {
@@ -989,6 +1064,11 @@ function TaskIcon({ type, size = 14, color = "#404040" }) {
989
1064
  const s = size;
990
1065
  const c = color;
991
1066
  switch (type) {
1067
+ case "Task":
1068
+ return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: s, height: s, viewBox: "0 0 16 16", fill: "none", children: [
1069
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "3", width: "10", height: "10", rx: "1.5", stroke: c, strokeWidth: "1.5" }),
1070
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5.5 8.2 7.2 10 10.8 6", stroke: c, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
1071
+ ] });
992
1072
  case "UserTask":
993
1073
  return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: s, height: s, viewBox: "0 0 16 16", fill: "none", children: [
994
1074
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "8", cy: "5", r: "3", stroke: c, strokeWidth: "1.5" }),
@@ -1131,20 +1211,22 @@ function TaskNode({ data, selected }) {
1131
1211
  style: {
1132
1212
  width: "100%",
1133
1213
  height: "100%",
1134
- background: d.color?.fill ?? BPMN_THEME.fill,
1214
+ background: d.color?.fill ?? `linear-gradient(180deg, ${BPMN_THEME.fill} 0%, ${BPMN_THEME.fillSoft} 100%)`,
1135
1215
  border: `${borderWidth}px solid ${stroke}`,
1136
- borderRadius: 6,
1216
+ borderRadius: 7,
1137
1217
  boxSizing: "border-box",
1218
+ boxShadow: resolveNodeShadow(selected),
1138
1219
  display: "flex",
1139
1220
  flexDirection: "column",
1140
1221
  alignItems: "center",
1141
1222
  justifyContent: "center",
1142
1223
  padding: hasMarkers ? "4px 8px 22px" : "4px 8px",
1143
1224
  position: "relative",
1144
- fontFamily: BPMN_THEME.fontFamily
1225
+ fontFamily: BPMN_THEME.fontFamily,
1226
+ transition: BPMN_THEME.transition
1145
1227
  },
1146
1228
  children: [
1147
- d.elementType && d.elementType !== "Task" && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { position: "absolute", top: 5, left: 5 }, children: /* @__PURE__ */ jsxRuntime.jsx(TaskIcon, { type: d.elementType, size: 14, color: stroke }) }),
1229
+ d.elementType && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { position: "absolute", top: 5, left: 5 }, children: /* @__PURE__ */ jsxRuntime.jsx(TaskIcon, { type: d.elementType, size: 14, color: stroke }) }),
1148
1230
  /* @__PURE__ */ jsxRuntime.jsx(BpmnLabel, { style: { width: "100%" }, children: d.label ?? d.elementType }),
1149
1231
  d.priority && /* @__PURE__ */ jsxRuntime.jsx(
1150
1232
  "div",
@@ -1222,7 +1304,7 @@ function GatewayNode({ data, selected }) {
1222
1304
  const stroke = resolveStroke(selected, d.color?.stroke);
1223
1305
  const sw = resolveStrokeWidth(selected);
1224
1306
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { width: SIZE4, height: SIZE4, position: "relative" }, children: [
1225
- /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: SIZE4, height: SIZE4, style: { overflow: "visible", display: "block" }, children: [
1307
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: SIZE4, height: SIZE4, style: { overflow: "visible", display: "block", filter: resolveShapeFilter(selected) }, children: [
1226
1308
  /* @__PURE__ */ jsxRuntime.jsx(
1227
1309
  "polygon",
1228
1310
  {
@@ -1238,11 +1320,24 @@ function GatewayNode({ data, selected }) {
1238
1320
  /* @__PURE__ */ jsxRuntime.jsx(BpmnLabel, { external: true, children: d.label })
1239
1321
  ] });
1240
1322
  }
1323
+ function resolveVariant(d) {
1324
+ if (d.subProcessVariant) return d.subProcessVariant;
1325
+ switch (d.elementType) {
1326
+ case "Transaction":
1327
+ return "transaction";
1328
+ case "EventSubProcess":
1329
+ return "event";
1330
+ case "AdHocSubProcess":
1331
+ return "adhoc";
1332
+ default:
1333
+ return "embedded";
1334
+ }
1335
+ }
1241
1336
  function SubProcessNode({ data, selected }) {
1242
1337
  const d = data;
1243
1338
  const stroke = resolveStroke(selected, d.color?.stroke);
1244
1339
  const sw = resolveStrokeWidth(selected);
1245
- const variant = d.subProcessVariant ?? "embedded";
1340
+ const variant = resolveVariant(d);
1246
1341
  const isExpanded = d.isExpanded ?? true;
1247
1342
  const hasMarkers = d.markers && d.markers.length > 0;
1248
1343
  const borderStyle = variant === "event" ? "dashed" : "solid";
@@ -1252,12 +1347,14 @@ function SubProcessNode({ data, selected }) {
1252
1347
  style: {
1253
1348
  width: "100%",
1254
1349
  height: "100%",
1255
- background: d.color?.fill ?? "#f8faff",
1350
+ background: d.color?.fill ?? `linear-gradient(180deg, ${BPMN_THEME.fill} 0%, ${BPMN_THEME.fillSubtle} 100%)`,
1256
1351
  border: `${sw}px ${borderStyle} ${stroke}`,
1257
1352
  borderRadius: 6,
1258
1353
  boxSizing: "border-box",
1354
+ boxShadow: resolveNodeShadow(selected),
1259
1355
  position: "relative",
1260
- fontFamily: BPMN_THEME.fontFamily
1356
+ fontFamily: BPMN_THEME.fontFamily,
1357
+ transition: BPMN_THEME.transition
1261
1358
  },
1262
1359
  children: [
1263
1360
  variant === "transaction" && /* @__PURE__ */ jsxRuntime.jsx(
@@ -1311,8 +1408,8 @@ function PoolNode({ data, selected }) {
1311
1408
  const stroke = resolveStroke(selected, d.color?.stroke);
1312
1409
  const sw = resolveStrokeWidth(selected);
1313
1410
  const orientation = d.orientation ?? "horizontal";
1314
- const fill = d.color?.fill ?? "#f5f7ff";
1315
- const headerFill = d.color?.fill ?? "#edf0ff";
1411
+ const fill = d.color?.fill ?? "#f8fbff";
1412
+ const headerFill = d.color?.fill ?? "#eaf2ff";
1316
1413
  if (orientation === "vertical") {
1317
1414
  return /* @__PURE__ */ jsxRuntime.jsxs(
1318
1415
  "div",
@@ -1326,14 +1423,17 @@ function PoolNode({ data, selected }) {
1326
1423
  borderRadius: 4,
1327
1424
  boxSizing: "border-box",
1328
1425
  background: fill,
1426
+ boxShadow: resolveNodeShadow(selected),
1329
1427
  overflow: "hidden",
1330
- fontFamily: BPMN_THEME.fontFamily
1428
+ fontFamily: BPMN_THEME.fontFamily,
1429
+ transition: BPMN_THEME.transition
1331
1430
  },
1332
1431
  children: [
1333
1432
  /* @__PURE__ */ jsxRuntime.jsx(
1334
1433
  "div",
1335
1434
  {
1336
1435
  "aria-label": "pool-header",
1436
+ className: "pool-drag-handle",
1337
1437
  style: {
1338
1438
  height: HEADER_HEIGHT,
1339
1439
  minHeight: HEADER_HEIGHT,
@@ -1342,7 +1442,8 @@ function PoolNode({ data, selected }) {
1342
1442
  alignItems: "center",
1343
1443
  justifyContent: "center",
1344
1444
  background: headerFill,
1345
- padding: "0 8px"
1445
+ padding: "0 8px",
1446
+ cursor: "grab"
1346
1447
  },
1347
1448
  children: /* @__PURE__ */ jsxRuntime.jsx(
1348
1449
  "span",
@@ -1376,14 +1477,17 @@ function PoolNode({ data, selected }) {
1376
1477
  borderRadius: 4,
1377
1478
  boxSizing: "border-box",
1378
1479
  background: fill,
1480
+ boxShadow: resolveNodeShadow(selected),
1379
1481
  overflow: "hidden",
1380
- fontFamily: BPMN_THEME.fontFamily
1482
+ fontFamily: BPMN_THEME.fontFamily,
1483
+ transition: BPMN_THEME.transition
1381
1484
  },
1382
1485
  children: [
1383
1486
  /* @__PURE__ */ jsxRuntime.jsx(
1384
1487
  "div",
1385
1488
  {
1386
1489
  "aria-label": "pool-header",
1490
+ className: "pool-drag-handle",
1387
1491
  style: {
1388
1492
  width: HEADER_WIDTH,
1389
1493
  minWidth: HEADER_WIDTH,
@@ -1391,7 +1495,8 @@ function PoolNode({ data, selected }) {
1391
1495
  display: "flex",
1392
1496
  alignItems: "center",
1393
1497
  justifyContent: "center",
1394
- background: headerFill
1498
+ background: headerFill,
1499
+ cursor: "grab"
1395
1500
  },
1396
1501
  children: /* @__PURE__ */ jsxRuntime.jsx(
1397
1502
  "span",
@@ -1424,8 +1529,8 @@ function LaneNode({ data, selected }) {
1424
1529
  const stroke = resolveStroke(selected, d.color?.stroke);
1425
1530
  const sw = resolveStrokeWidth(selected);
1426
1531
  const orientation = d.orientation ?? "horizontal";
1427
- const fill = d.color?.fill ?? "#fafbff";
1428
- const headerFill = d.color?.fill ?? "#f0f3ff";
1532
+ const fill = d.color?.fill ?? "#fbfdff";
1533
+ const headerFill = d.color?.fill ?? "#eef6ff";
1429
1534
  if (orientation === "vertical") {
1430
1535
  return /* @__PURE__ */ jsxRuntime.jsxs(
1431
1536
  "div",
@@ -1438,14 +1543,17 @@ function LaneNode({ data, selected }) {
1438
1543
  borderRadius: 2,
1439
1544
  boxSizing: "border-box",
1440
1545
  background: fill,
1546
+ boxShadow: resolveNodeShadow(selected),
1441
1547
  overflow: "hidden",
1442
- fontFamily: BPMN_THEME.fontFamily
1548
+ fontFamily: BPMN_THEME.fontFamily,
1549
+ transition: BPMN_THEME.transition
1443
1550
  },
1444
1551
  children: [
1445
1552
  /* @__PURE__ */ jsxRuntime.jsx(
1446
1553
  "div",
1447
1554
  {
1448
1555
  "aria-label": "lane-header",
1556
+ className: "lane-drag-handle",
1449
1557
  style: {
1450
1558
  width: HEADER_WIDTH2,
1451
1559
  minWidth: HEADER_WIDTH2,
@@ -1454,7 +1562,8 @@ function LaneNode({ data, selected }) {
1454
1562
  alignItems: "center",
1455
1563
  justifyContent: "center",
1456
1564
  background: headerFill,
1457
- padding: "6px 0"
1565
+ padding: "6px 0",
1566
+ cursor: "grab"
1458
1567
  },
1459
1568
  children: /* @__PURE__ */ jsxRuntime.jsx(
1460
1569
  "span",
@@ -1492,14 +1601,17 @@ function LaneNode({ data, selected }) {
1492
1601
  borderRadius: 2,
1493
1602
  boxSizing: "border-box",
1494
1603
  background: fill,
1604
+ boxShadow: resolveNodeShadow(selected),
1495
1605
  overflow: "hidden",
1496
- fontFamily: BPMN_THEME.fontFamily
1606
+ fontFamily: BPMN_THEME.fontFamily,
1607
+ transition: BPMN_THEME.transition
1497
1608
  },
1498
1609
  children: [
1499
1610
  /* @__PURE__ */ jsxRuntime.jsx(
1500
1611
  "div",
1501
1612
  {
1502
1613
  "aria-label": "lane-header",
1614
+ className: "lane-drag-handle",
1503
1615
  style: {
1504
1616
  height: HEADER_HEIGHT2,
1505
1617
  minHeight: HEADER_HEIGHT2,
@@ -1510,7 +1622,8 @@ function LaneNode({ data, selected }) {
1510
1622
  background: headerFill,
1511
1623
  fontSize: BPMN_THEME.fontSize,
1512
1624
  fontWeight: 500,
1513
- color: BPMN_THEME.labelColor
1625
+ color: BPMN_THEME.labelColor,
1626
+ cursor: "grab"
1514
1627
  },
1515
1628
  children: d.label
1516
1629
  }
@@ -1627,7 +1740,7 @@ function DataObjectNode({ data, selected }) {
1627
1740
  `L ${W} ${FOLD}`
1628
1741
  ].join(" ");
1629
1742
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { width: W, height: H2, position: "relative" }, children: [
1630
- /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: W, height: H2, style: { overflow: "visible", display: "block" }, children: [
1743
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: W, height: H2, style: { overflow: "visible", display: "block", filter: resolveShapeFilter(selected) }, children: [
1631
1744
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: path, fill, stroke, strokeWidth: sw }),
1632
1745
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: foldPath2, fill: "none", stroke, strokeWidth: sw })
1633
1746
  ] }),
@@ -1645,7 +1758,7 @@ function DataStoreNode({ data, selected }) {
1645
1758
  const sw = resolveStrokeWidth(selected);
1646
1759
  const fill = d.color?.fill ?? BPMN_THEME.fill;
1647
1760
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { width: DS_W, height: DS_H, position: "relative" }, children: [
1648
- /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: DS_W, height: DS_H, style: { overflow: "visible", display: "block" }, children: [
1761
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: DS_W, height: DS_H, style: { overflow: "visible", display: "block", filter: resolveShapeFilter(selected) }, children: [
1649
1762
  /* @__PURE__ */ jsxRuntime.jsx(
1650
1763
  "path",
1651
1764
  {
@@ -1691,7 +1804,7 @@ function DataObjectReferenceNode({ data, selected }) {
1691
1804
  const sw = resolveStrokeWidth(selected);
1692
1805
  const fill = d.color?.fill ?? BPMN_THEME.fill;
1693
1806
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { width: W2, height: H3, position: "relative" }, children: [
1694
- /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: W2, height: H3, style: { overflow: "visible", display: "block" }, children: [
1807
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: W2, height: H3, style: { overflow: "visible", display: "block", filter: resolveShapeFilter(selected) }, children: [
1695
1808
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: documentPath(), fill, stroke, strokeWidth: sw }),
1696
1809
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: foldPath(), fill: "none", stroke, strokeWidth: sw }),
1697
1810
  d.isCollection && collectionLines(stroke, sw)
@@ -1706,7 +1819,7 @@ function DataInputNode({ data, selected }) {
1706
1819
  const sw = resolveStrokeWidth(selected);
1707
1820
  const fill = d.color?.fill ?? BPMN_THEME.fill;
1708
1821
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { width: W2, height: H3, position: "relative" }, children: [
1709
- /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: W2, height: H3, style: { overflow: "visible", display: "block" }, children: [
1822
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: W2, height: H3, style: { overflow: "visible", display: "block", filter: resolveShapeFilter(selected) }, children: [
1710
1823
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: documentPath(), fill, stroke, strokeWidth: sw }),
1711
1824
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: foldPath(), fill: "none", stroke, strokeWidth: sw }),
1712
1825
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -1730,7 +1843,7 @@ function DataOutputNode({ data, selected }) {
1730
1843
  const sw = resolveStrokeWidth(selected);
1731
1844
  const fill = d.color?.fill ?? BPMN_THEME.fill;
1732
1845
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { width: W2, height: H3, position: "relative" }, children: [
1733
- /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: W2, height: H3, style: { overflow: "visible", display: "block" }, children: [
1846
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: W2, height: H3, style: { overflow: "visible", display: "block", filter: resolveShapeFilter(selected) }, children: [
1734
1847
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: documentPath(), fill, stroke, strokeWidth: sw }),
1735
1848
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: foldPath(), fill: "none", stroke, strokeWidth: sw }),
1736
1849
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -1758,7 +1871,7 @@ function DataStoreReferenceNode({ data, selected }) {
1758
1871
  const sw = resolveStrokeWidth(selected);
1759
1872
  const fill = d.color?.fill ?? BPMN_THEME.fill;
1760
1873
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { width: DS_W2, height: DS_H2, position: "relative" }, children: [
1761
- /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: DS_W2, height: DS_H2, style: { overflow: "visible", display: "block" }, children: [
1874
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: DS_W2, height: DS_H2, style: { overflow: "visible", display: "block", filter: resolveShapeFilter(selected) }, children: [
1762
1875
  /* @__PURE__ */ jsxRuntime.jsx(
1763
1876
  "path",
1764
1877
  {
@@ -2084,8 +2197,11 @@ var BPMN_NODE_TYPES = {
2084
2197
  ParallelGateway: GatewayNode,
2085
2198
  EventBasedGateway: GatewayNode,
2086
2199
  ComplexGateway: GatewayNode,
2087
- // Containers
2200
+ // Containers — Transaction, EventSubProcess, AdHocSubProcess derive their visual variant from elementType
2088
2201
  SubProcess: SubProcessNode,
2202
+ Transaction: SubProcessNode,
2203
+ EventSubProcess: SubProcessNode,
2204
+ AdHocSubProcess: SubProcessNode,
2089
2205
  Pool: PoolNode,
2090
2206
  Lane: LaneNode,
2091
2207
  // Artifacts
@@ -2408,8 +2524,8 @@ var MODDLE_TO_ELEMENT_TYPE = {
2408
2524
  "bpmn:EventBasedGateway": "EventBasedGateway",
2409
2525
  "bpmn:ComplexGateway": "ComplexGateway",
2410
2526
  "bpmn:SubProcess": "SubProcess",
2411
- "bpmn:AdHocSubProcess": "SubProcess",
2412
- "bpmn:Transaction": "SubProcess",
2527
+ "bpmn:AdHocSubProcess": "AdHocSubProcess",
2528
+ "bpmn:Transaction": "Transaction",
2413
2529
  "bpmn:TextAnnotation": "Annotation",
2414
2530
  "bpmn:Group": "Group",
2415
2531
  "bpmn:DataObject": "DataObject",
@@ -2447,6 +2563,9 @@ var ELEMENT_TYPE_TO_MODDLE = {
2447
2563
  EventBasedGateway: "bpmn:EventBasedGateway",
2448
2564
  ComplexGateway: "bpmn:ComplexGateway",
2449
2565
  SubProcess: "bpmn:SubProcess",
2566
+ Transaction: "bpmn:Transaction",
2567
+ EventSubProcess: "bpmn:SubProcess",
2568
+ AdHocSubProcess: "bpmn:AdHocSubProcess",
2450
2569
  Pool: "bpmn:Participant",
2451
2570
  Lane: "bpmn:Lane",
2452
2571
  Annotation: "bpmn:TextAnnotation",
@@ -2511,6 +2630,10 @@ function asElements(v) {
2511
2630
  function asString(v) {
2512
2631
  return typeof v === "string" && v.trim() ? v.trim() : void 0;
2513
2632
  }
2633
+ function extractDocumentation(el) {
2634
+ const [doc] = asElements(el.documentation);
2635
+ return asString(doc?.text);
2636
+ }
2514
2637
  function extractDiagramInfo(definitions) {
2515
2638
  const shapes = /* @__PURE__ */ new Map();
2516
2639
  const waypoints = /* @__PURE__ */ new Map();
@@ -2566,6 +2689,7 @@ function extractTrigger(el) {
2566
2689
  function extractSubProcessVariant(el) {
2567
2690
  if (el.$type === "bpmn:Transaction") return "transaction";
2568
2691
  if (el.$type === "bpmn:AdHocSubProcess") return "adhoc";
2692
+ if (el.$type === "bpmn:SubProcess" && el.triggeredByEvent === true) return "event";
2569
2693
  if (el.triggeredByEvent === true) return "event";
2570
2694
  return "embedded";
2571
2695
  }
@@ -2579,7 +2703,7 @@ function walkFlowElements(elements, parentId, ctx, nodes, edges) {
2579
2703
  continue;
2580
2704
  }
2581
2705
  if ($type === "bpmn:LaneSet") continue;
2582
- const elementType = MODDLE_TO_ELEMENT_TYPE[$type];
2706
+ const elementType = $type === "bpmn:SubProcess" && el.triggeredByEvent === true ? "EventSubProcess" : MODDLE_TO_ELEMENT_TYPE[$type];
2583
2707
  if (!elementType) {
2584
2708
  ctx.warnings.push(`Unknown element type "${$type}" (id=${id}) \u2014 skipped.`);
2585
2709
  continue;
@@ -2600,22 +2724,26 @@ function buildNode(el, elementType, parentId, ctx, nodes) {
2600
2724
  const y = shape?.y ?? 100;
2601
2725
  if (!shape) ctx.autoX.value += (meta?.defaultWidth ?? 120) + 20;
2602
2726
  const label = asString(el.name);
2727
+ const documentation = extractDocumentation(el);
2603
2728
  const trigger = extractTrigger(el);
2604
2729
  const isNonInterrupting = el.cancelActivity === false;
2730
+ const attachedToRef = el.attachedToRef?.id;
2605
2731
  const data = {
2606
2732
  elementType,
2607
2733
  ...label ? { label } : {},
2734
+ ...documentation ? { documentation } : {},
2608
2735
  ...trigger ? { trigger } : {},
2609
- ...isNonInterrupting ? { isNonInterrupting: true } : {}
2736
+ ...isNonInterrupting ? { isNonInterrupting: true } : {},
2737
+ ...attachedToRef ? { attachedToRef } : {}
2610
2738
  };
2611
- if (elementType === "SubProcess") {
2739
+ if (elementType === "SubProcess" || elementType === "Transaction" || elementType === "EventSubProcess" || elementType === "AdHocSubProcess") {
2612
2740
  const variant = extractSubProcessVariant(el);
2613
2741
  if (variant) data.subProcessVariant = variant;
2614
2742
  const isExpanded = shape?.isExpanded ?? true;
2615
2743
  data.isExpanded = isExpanded;
2616
2744
  }
2617
2745
  const laneId = ctx.laneMembership.get(id);
2618
- const effectiveParentId = laneId ?? parentId;
2746
+ const effectiveParentId = attachedToRef ?? laneId ?? parentId;
2619
2747
  const node = {
2620
2748
  id,
2621
2749
  type: elementType,
@@ -2636,10 +2764,12 @@ function buildEdge(el, edgeType, ctx, edges) {
2636
2764
  return;
2637
2765
  }
2638
2766
  const label = asString(el.name);
2767
+ const documentation = extractDocumentation(el);
2639
2768
  const condExpr = el.conditionExpression;
2640
2769
  const data = {
2641
2770
  edgeType,
2642
2771
  ...label ? { label } : {},
2772
+ ...documentation ? { documentation } : {},
2643
2773
  ...condExpr?.body ? { conditionExpression: condExpr.body } : {}
2644
2774
  };
2645
2775
  const waypoints = ctx.waypoints.get(id);
@@ -2740,7 +2870,46 @@ async function parseBpmnXml(xml) {
2740
2870
  );
2741
2871
  }
2742
2872
  }
2743
- return { nodes, edges, warnings };
2873
+ const defaultFlowById = /* @__PURE__ */ new Set();
2874
+ const nodeIds = new Set(nodes.map((node) => node.id));
2875
+ for (const rootEl of asElements(rootElement.rootElements)) {
2876
+ collectDefaultFlows(rootEl, defaultFlowById);
2877
+ }
2878
+ const normalizedEdges = edges.map((edge) => {
2879
+ if (!defaultFlowById.has(edge.id)) return edge;
2880
+ const data = {
2881
+ edgeType: edge.data?.edgeType ?? edge.type,
2882
+ ...edge.data ?? {},
2883
+ isDefault: true
2884
+ };
2885
+ return { ...edge, data };
2886
+ });
2887
+ return {
2888
+ nodes: normalizeChildPositions(nodes, nodeIds),
2889
+ edges: normalizedEdges,
2890
+ warnings
2891
+ };
2892
+ }
2893
+ function collectDefaultFlows(el, defaultFlowById) {
2894
+ const defaultRef = el.default;
2895
+ if (defaultRef?.id) defaultFlowById.add(defaultRef.id);
2896
+ for (const child of asElements(el.rootElements)) collectDefaultFlows(child, defaultFlowById);
2897
+ for (const child of asElements(el.flowElements)) collectDefaultFlows(child, defaultFlowById);
2898
+ }
2899
+ function normalizeChildPositions(nodes, nodeIds) {
2900
+ const absoluteById = new Map(nodes.map((node) => [node.id, node.position]));
2901
+ return nodes.map((node) => {
2902
+ if (!node.parentId || !nodeIds.has(node.parentId)) return node;
2903
+ const parentPosition = absoluteById.get(node.parentId);
2904
+ if (!parentPosition) return node;
2905
+ return {
2906
+ ...node,
2907
+ position: {
2908
+ x: node.position.x - parentPosition.x,
2909
+ y: node.position.y - parentPosition.y
2910
+ }
2911
+ };
2912
+ });
2744
2913
  }
2745
2914
  function uid(prefix, id) {
2746
2915
  return `${prefix}_${id}`;
@@ -2748,19 +2917,6 @@ function uid(prefix, id) {
2748
2917
  function asNodes(nodes, types) {
2749
2918
  return nodes.filter((n) => types.includes(n.data.elementType));
2750
2919
  }
2751
- function buildFlowableAttrs(data) {
2752
- const attrs = {};
2753
- if (data.flowableAssignee) attrs["flowable:assignee"] = data.flowableAssignee;
2754
- if (data.flowableCandidateGroups) attrs["flowable:candidateGroups"] = data.flowableCandidateGroups;
2755
- if (data.flowableCandidateUsers) attrs["flowable:candidateUsers"] = data.flowableCandidateUsers;
2756
- if (data.flowableFormKey) attrs["flowable:formKey"] = data.flowableFormKey;
2757
- if (data.flowableDueDate) attrs["flowable:dueDate"] = data.flowableDueDate;
2758
- if (data.flowableType) attrs["flowable:type"] = data.flowableType;
2759
- if (data.flowableExpression) attrs["flowable:expression"] = data.flowableExpression;
2760
- if (data.flowableClass) attrs["flowable:class"] = data.flowableClass;
2761
- if (data.flowableDelegateExpression) attrs["flowable:delegateExpression"] = data.flowableDelegateExpression;
2762
- return attrs;
2763
- }
2764
2920
  function buildSemanticModel(moddle, nodes, edges, opts) {
2765
2921
  const defId = opts.id ?? "Definitions_1";
2766
2922
  const defName = opts.name;
@@ -2819,13 +2975,32 @@ function buildSemanticModel(moddle, nodes, edges, opts) {
2819
2975
  return definitions;
2820
2976
  }
2821
2977
  function buildProcess(moddle, allNodes, allEdges, poolId, laneNodes, processId) {
2822
- const myNodes = poolId ? allNodes.filter(
2823
- (n) => n.parentId === poolId || laneNodes.some((l) => l.id === n.parentId && l.parentId === poolId)
2824
- ) : allNodes.filter((n) => n.data.elementType !== "Pool" && n.data.elementType !== "Lane");
2978
+ const subProcessIds = new Set(
2979
+ allNodes.filter(
2980
+ (n) => n.data.elementType === "SubProcess" || n.data.elementType === "Transaction" || n.data.elementType === "EventSubProcess" || n.data.elementType === "AdHocSubProcess"
2981
+ ).map((n) => n.id)
2982
+ );
2983
+ const isInsideSubProcess = (node) => {
2984
+ let parentId = node.parentId;
2985
+ while (parentId) {
2986
+ if (subProcessIds.has(parentId)) return true;
2987
+ parentId = allNodes.find((candidate) => candidate.id === parentId)?.parentId;
2988
+ }
2989
+ return false;
2990
+ };
2991
+ const belongsToPool = (node) => {
2992
+ let parentId = node.parentId;
2993
+ while (parentId) {
2994
+ if (parentId === poolId) return true;
2995
+ parentId = allNodes.find((candidate) => candidate.id === parentId)?.parentId;
2996
+ }
2997
+ return false;
2998
+ };
2999
+ const myNodes = (poolId ? allNodes.filter((n) => belongsToPool(n)) : allNodes.filter((n) => n.data.elementType !== "Pool" && n.data.elementType !== "Lane")).filter((n) => !isInsideSubProcess(n));
2825
3000
  const myLanes = laneNodes.filter((l) => poolId ? l.parentId === poolId : true);
2826
3001
  const flowElements = [];
2827
3002
  for (const node of myNodes) {
2828
- const el = buildFlowElement(moddle, node);
3003
+ const el = buildFlowElement(moddle, node, allNodes, allEdges);
2829
3004
  if (el) flowElements.push(el);
2830
3005
  }
2831
3006
  const myNodeIds = new Set(myNodes.map((n) => n.id));
@@ -2836,6 +3011,17 @@ function buildProcess(moddle, allNodes, allEdges, poolId, laneNodes, processId)
2836
3011
  const edgeMeta = buildEdgeElement(moddle, edge);
2837
3012
  if (edgeMeta) flowElements.push(edgeMeta);
2838
3013
  }
3014
+ const elementById = new Map(
3015
+ flowElements.filter((element) => typeof element.id === "string").map((element) => [element.id, element])
3016
+ );
3017
+ for (const edge of myEdges) {
3018
+ if (!edge.data?.isDefault) continue;
3019
+ const sourceElement = elementById.get(edge.source);
3020
+ const edgeElement = elementById.get(edge.id);
3021
+ if (sourceElement && edgeElement) {
3022
+ sourceElement.default = edgeElement;
3023
+ }
3024
+ }
2839
3025
  const process = moddle.create("bpmn:Process", {
2840
3026
  id: processId,
2841
3027
  isExecutable: true,
@@ -2856,7 +3042,7 @@ function buildProcess(moddle, allNodes, allEdges, poolId, laneNodes, processId)
2856
3042
  }
2857
3043
  return process;
2858
3044
  }
2859
- function buildFlowElement(moddle, node, _allNodes, _allEdges) {
3045
+ function buildFlowElement(moddle, node, allNodes, allEdges) {
2860
3046
  const { elementType, label, trigger } = node.data;
2861
3047
  if (elementType === "Pool" || elementType === "Lane") return null;
2862
3048
  const moddleType = ELEMENT_TYPE_TO_MODDLE[elementType];
@@ -2865,25 +3051,46 @@ function buildFlowElement(moddle, node, _allNodes, _allEdges) {
2865
3051
  id: node.id,
2866
3052
  name: label ?? ""
2867
3053
  };
3054
+ if (node.data.documentation) {
3055
+ attrs.documentation = [
3056
+ moddle.create("bpmn:Documentation", { text: node.data.documentation })
3057
+ ];
3058
+ }
2868
3059
  if (trigger && trigger !== "none") {
2869
3060
  const defType = TRIGGER_TO_EVENT_DEF[trigger];
2870
3061
  if (defType) {
2871
3062
  attrs.eventDefinitions = [moddle.create(defType, { id: uid("EventDef", node.id) })];
2872
3063
  }
2873
3064
  }
2874
- if (elementType === "SubProcess" && node.data.subProcessVariant === "transaction") {
2875
- return moddle.create("bpmn:Transaction", attrs);
3065
+ if (elementType === "BoundaryEvent") {
3066
+ attrs.attachedToRef = { id: node.data.attachedToRef ?? node.parentId };
3067
+ attrs.cancelActivity = node.data.isNonInterrupting ? false : true;
2876
3068
  }
2877
- if (elementType === "SubProcess" && node.data.subProcessVariant === "adhoc") {
2878
- return moddle.create("bpmn:AdHocSubProcess", attrs);
3069
+ const isSubProcess3 = elementType === "SubProcess" || elementType === "Transaction" || elementType === "EventSubProcess" || elementType === "AdHocSubProcess";
3070
+ if (isSubProcess3) {
3071
+ attrs.flowElements = buildNestedFlowElements(moddle, node, allNodes, allEdges);
3072
+ if (elementType === "EventSubProcess" || node.data.subProcessVariant === "event") {
3073
+ attrs.triggeredByEvent = true;
3074
+ }
2879
3075
  }
2880
3076
  const element = moddle.create(moddleType, attrs);
2881
- const flowableAttrs = buildFlowableAttrs(node.data);
2882
- if (Object.keys(flowableAttrs).length > 0) {
2883
- element.$attrs = flowableAttrs;
2884
- }
2885
3077
  return element;
2886
3078
  }
3079
+ function buildNestedFlowElements(moddle, parent, allNodes, allEdges) {
3080
+ const childNodes = allNodes.filter((node) => node.parentId === parent.id);
3081
+ const childNodeIds = new Set(childNodes.map((node) => node.id));
3082
+ const flowElements = [];
3083
+ for (const child of childNodes) {
3084
+ const element = buildFlowElement(moddle, child, allNodes, allEdges);
3085
+ if (element) flowElements.push(element);
3086
+ }
3087
+ for (const edge of allEdges) {
3088
+ if (!childNodeIds.has(edge.source) || !childNodeIds.has(edge.target)) continue;
3089
+ const element = buildEdgeElement(moddle, edge);
3090
+ if (element) flowElements.push(element);
3091
+ }
3092
+ return flowElements;
3093
+ }
2887
3094
  function buildEdgeElement(moddle, edge) {
2888
3095
  if (!edge.data) return null;
2889
3096
  const moddleType = EDGE_TYPE_TO_MODDLE[edge.data.edgeType];
@@ -2894,6 +3101,11 @@ function buildEdgeElement(moddle, edge) {
2894
3101
  sourceRef: { id: edge.source },
2895
3102
  targetRef: { id: edge.target }
2896
3103
  };
3104
+ if (edge.data.documentation) {
3105
+ attrs.documentation = [
3106
+ moddle.create("bpmn:Documentation", { text: edge.data.documentation })
3107
+ ];
3108
+ }
2897
3109
  if (edge.data.conditionExpression) {
2898
3110
  attrs.conditionExpression = moddle.create("bpmn:FormalExpression", {
2899
3111
  body: edge.data.conditionExpression
@@ -2904,13 +3116,14 @@ function buildEdgeElement(moddle, edge) {
2904
3116
  function buildBpmnDI(moddle, definitions, nodes, edges) {
2905
3117
  const shapes = [];
2906
3118
  const edgeShapes = [];
3119
+ const absolutePositionById = buildAbsolutePositionMap(nodes);
2907
3120
  for (const node of nodes) {
2908
3121
  const meta = BPMN_ELEMENT_CATALOG[node.data.elementType];
2909
3122
  const w = node.width ?? meta?.defaultWidth ?? 120;
2910
3123
  const h = node.height ?? meta?.defaultHeight ?? 60;
2911
3124
  const bounds = moddle.create("dc:Bounds", {
2912
- x: node.position.x,
2913
- y: node.position.y,
3125
+ x: absolutePositionById.get(node.id)?.x ?? node.position.x,
3126
+ y: absolutePositionById.get(node.id)?.y ?? node.position.y,
2914
3127
  width: w,
2915
3128
  height: h
2916
3129
  });
@@ -2925,9 +3138,9 @@ function buildBpmnDI(moddle, definitions, nodes, edges) {
2925
3138
  shapes.push(shape);
2926
3139
  }
2927
3140
  for (const edge of edges) {
2928
- const waypoints = edge.data?.routingPoints?.map(
3141
+ const waypoints = resolveEdgeWaypoints(edge, nodes, absolutePositionById).map(
2929
3142
  (p) => moddle.create("dc:Point", { x: p.x, y: p.y })
2930
- ) ?? [];
3143
+ );
2931
3144
  edgeShapes.push(
2932
3145
  moddle.create("bpmndi:BPMNEdge", {
2933
3146
  id: uid("BPMNEdge", edge.id),
@@ -2949,6 +3162,46 @@ function buildBpmnDI(moddle, definitions, nodes, edges) {
2949
3162
  });
2950
3163
  definitions.diagrams = [diagram];
2951
3164
  }
3165
+ function resolveEdgeWaypoints(edge, nodes, absolutePositionById) {
3166
+ if (edge.data?.routingPoints && edge.data.routingPoints.length >= 2) {
3167
+ return edge.data.routingPoints;
3168
+ }
3169
+ const source = nodes.find((node) => node.id === edge.source);
3170
+ const target = nodes.find((node) => node.id === edge.target);
3171
+ if (!source || !target) return [];
3172
+ const sourceMeta = BPMN_ELEMENT_CATALOG[source.data.elementType];
3173
+ const targetMeta = BPMN_ELEMENT_CATALOG[target.data.elementType];
3174
+ const sourcePosition = absolutePositionById.get(source.id) ?? source.position;
3175
+ const targetPosition = absolutePositionById.get(target.id) ?? target.position;
3176
+ return [
3177
+ {
3178
+ x: sourcePosition.x + (source.width ?? sourceMeta.defaultWidth) / 2,
3179
+ y: sourcePosition.y + (source.height ?? sourceMeta.defaultHeight) / 2
3180
+ },
3181
+ {
3182
+ x: targetPosition.x + (target.width ?? targetMeta.defaultWidth) / 2,
3183
+ y: targetPosition.y + (target.height ?? targetMeta.defaultHeight) / 2
3184
+ }
3185
+ ];
3186
+ }
3187
+ function buildAbsolutePositionMap(nodes) {
3188
+ const nodeById2 = new Map(nodes.map((node) => [node.id, node]));
3189
+ const absoluteById = /* @__PURE__ */ new Map();
3190
+ function resolve(node) {
3191
+ const cached = absoluteById.get(node.id);
3192
+ if (cached) return cached;
3193
+ const parent = node.parentId ? nodeById2.get(node.parentId) : void 0;
3194
+ const parentPosition = parent ? resolve(parent) : { x: 0, y: 0 };
3195
+ const absolute = {
3196
+ x: parentPosition.x + node.position.x,
3197
+ y: parentPosition.y + node.position.y
3198
+ };
3199
+ absoluteById.set(node.id, absolute);
3200
+ return absolute;
3201
+ }
3202
+ for (const node of nodes) resolve(node);
3203
+ return absoluteById;
3204
+ }
2952
3205
  async function serializeBpmnXml(nodes, edges, opts = {}) {
2953
3206
  const moddle = new bpmnModdle.BpmnModdle();
2954
3207
  const definitions = buildSemanticModel(moddle, nodes, edges, opts);
@@ -3431,45 +3684,761 @@ function isCompleted(state) {
3431
3684
  function setVariable(state, key, value) {
3432
3685
  return { ...state, variables: { ...state.variables, [key]: value } };
3433
3686
  }
3434
-
3435
- // src/flowable/adapter.ts
3436
- var PreviewAdapter = class {
3437
- constructor(diagram, initialVariables = {}) {
3438
- this.diagram = diagram;
3439
- this.mode = "preview";
3440
- this.state = createSimulation(diagram, initialVariables);
3687
+ function createBpmnNode(options) {
3688
+ const size = getBpmnElementSize(options.elementType);
3689
+ const meta = BPMN_ELEMENT_CATALOG[options.elementType];
3690
+ const orientation = options.data?.orientation ?? meta.orientation;
3691
+ const dragHandle = getBpmnDragHandleSelector(options.elementType);
3692
+ return {
3693
+ id: options.id,
3694
+ type: options.elementType,
3695
+ position: options.position,
3696
+ data: {
3697
+ elementType: options.elementType,
3698
+ orientation,
3699
+ ...options.label ? { label: options.label } : {},
3700
+ ...options.data ?? {}
3701
+ },
3702
+ width: options.width ?? size.width,
3703
+ height: options.height ?? size.height,
3704
+ ...options.parentId ? { parentId: options.parentId } : {},
3705
+ ...dragHandle ? { dragHandle } : {}
3706
+ };
3707
+ }
3708
+ var BPMN_POOL_LANE_LAYOUT = {
3709
+ poolHeaderSize: 30,
3710
+ laneHeaderSize: 24,
3711
+ laneGap: 0
3712
+ };
3713
+ function getBpmnDragHandleSelector(elementType) {
3714
+ if (elementType === "Pool") return ".pool-drag-handle";
3715
+ if (elementType === "Lane") return ".lane-drag-handle";
3716
+ return void 0;
3717
+ }
3718
+ var BPMN_SELECTION_STYLE = {
3719
+ nodeOutline: "#2563eb",
3720
+ edgeStroke: "#2563eb",
3721
+ handleFill: "#ffffff",
3722
+ handleStroke: "#2563eb",
3723
+ resizeHandleSize: 8,
3724
+ routingPointRadius: 5
3725
+ };
3726
+ var BPMN_ROUTABLE_EDGE_TYPES = [
3727
+ "sequenceFlow",
3728
+ "messageFlow",
3729
+ "association",
3730
+ "dataAssociation",
3731
+ "conversationLink"
3732
+ ];
3733
+ var BPMN_EDGE_CONNECTION_RULES = {
3734
+ sequenceFlow: {
3735
+ edgeType: "sequenceFlow",
3736
+ sourceCategories: ["flowNode"],
3737
+ targetCategories: ["flowNode"],
3738
+ allowSameParent: true,
3739
+ allowDifferentParent: false
3740
+ },
3741
+ messageFlow: {
3742
+ edgeType: "messageFlow",
3743
+ sourceCategories: ["flowNode"],
3744
+ targetCategories: ["flowNode"],
3745
+ allowSameParent: false,
3746
+ allowDifferentParent: true
3747
+ },
3748
+ association: {
3749
+ edgeType: "association",
3750
+ sourceCategories: ["flowNode", "artifact", "data"],
3751
+ targetCategories: ["flowNode", "artifact", "data"],
3752
+ allowSameParent: true,
3753
+ allowDifferentParent: true
3754
+ },
3755
+ dataAssociation: {
3756
+ edgeType: "dataAssociation",
3757
+ sourceCategories: ["flowNode", "data"],
3758
+ targetCategories: ["flowNode", "data"],
3759
+ allowSameParent: true,
3760
+ allowDifferentParent: true
3761
+ },
3762
+ conversationLink: {
3763
+ edgeType: "conversationLink",
3764
+ sourceCategories: ["conversation", "flowNode"],
3765
+ targetCategories: ["conversation", "flowNode"],
3766
+ allowSameParent: true,
3767
+ allowDifferentParent: true
3441
3768
  }
3442
- async start(variables) {
3443
- this.state = tick(this.diagram, createSimulation(this.diagram, variables ?? {}));
3444
- return this.state;
3769
+ };
3770
+ function inferBpmnEdgeType(state, sourceId, targetId) {
3771
+ const source = diagramsCore.getNode(state, sourceId);
3772
+ const target = diagramsCore.getNode(state, targetId);
3773
+ if (!source || !target) return "sequenceFlow";
3774
+ if (isDataType(source.data.elementType) || isDataType(target.data.elementType)) {
3775
+ return "dataAssociation";
3445
3776
  }
3446
- async tick() {
3447
- this.state = tick(this.diagram, this.state);
3448
- return this.state;
3777
+ if (source.data.elementType === "Annotation" || target.data.elementType === "Annotation" || source.data.elementType === "Group" || target.data.elementType === "Group") {
3778
+ return "association";
3449
3779
  }
3450
- async fire(elementId, variables) {
3451
- this.state = fire(this.diagram, this.state, elementId, variables);
3452
- return this.state;
3780
+ 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") {
3781
+ return "conversationLink";
3453
3782
  }
3454
- async getFireable() {
3455
- return getFireable(this.diagram, this.state);
3783
+ if (source.parentId && target.parentId && source.parentId !== target.parentId) {
3784
+ return "messageFlow";
3456
3785
  }
3457
- getState() {
3458
- return this.state;
3786
+ return "sequenceFlow";
3787
+ }
3788
+ function canUseSequenceFlow(type) {
3789
+ const meta = BPMN_ELEMENT_CATALOG[type];
3790
+ return meta.handlePolicy !== "none" && !isDataType(type) && type !== "Annotation" && type !== "Group" && meta.category !== "conversation";
3791
+ }
3792
+ function matchesConnectionCategory(type, categories) {
3793
+ return categories.some((category) => {
3794
+ if (category === type) return true;
3795
+ if (category === "flowNode") return canUseSequenceFlow(type);
3796
+ if (category === "data") return isDataType(type);
3797
+ if (category === "artifact") return type === "Annotation" || type === "Group";
3798
+ if (category === "conversation") return BPMN_ELEMENT_CATALOG[type].category === "conversation";
3799
+ return false;
3800
+ });
3801
+ }
3802
+ function isBpmnEdgeRoutingEditable(edgeType) {
3803
+ return BPMN_ROUTABLE_EDGE_TYPES.includes(edgeType);
3804
+ }
3805
+ function isBpmnProcessNode(type) {
3806
+ return isEventType(type) || isGatewayType(type) || type.includes("Task") || type === "CallActivity" || type === "SubProcess" || type === "Transaction" || type === "EventSubProcess" || type === "AdHocSubProcess";
3807
+ }
3808
+ function canContainBpmnElement(parentType, childType) {
3809
+ if (!parentType) return true;
3810
+ if (parentType === "Pool") {
3811
+ return childType === "Lane" || isBpmnProcessNode(childType) ? true : "Pools can contain lanes or BPMN process nodes.";
3459
3812
  }
3460
- isCompleted() {
3461
- return isCompleted(this.state);
3813
+ if (parentType === "Lane") {
3814
+ return isBpmnProcessNode(childType) ? true : "Lanes can only contain BPMN process nodes.";
3462
3815
  }
3463
- };
3464
- function createPreviewAdapter(diagram, initialVariables) {
3465
- return new PreviewAdapter(diagram, initialVariables);
3816
+ if (parentType === "SubProcess" || parentType === "Transaction" || parentType === "EventSubProcess" || parentType === "AdHocSubProcess") {
3817
+ return isBpmnProcessNode(childType) ? true : "Subprocesses can only contain BPMN process nodes.";
3818
+ }
3819
+ return `${parentType} cannot contain BPMN child elements.`;
3820
+ }
3821
+ function getDirectBpmnChildren(state, parentId) {
3822
+ return state.nodes.filter((node) => node.parentId === parentId);
3823
+ }
3824
+ function getBpmnPoolLanes(state, poolId) {
3825
+ return getDirectBpmnChildren(state, poolId).filter(
3826
+ (node) => node.data.elementType === "Lane"
3827
+ );
3828
+ }
3829
+ function getNodeDimension(node, axis) {
3830
+ return node[axis] ?? node.measured?.[axis] ?? getBpmnElementSize(node.data.elementType)[axis];
3831
+ }
3832
+ function resolvePoolLaneDirection(pool) {
3833
+ return pool.data.orientation === "vertical" ? "horizontal" : "vertical";
3834
+ }
3835
+ function getBpmnLaneIndexAtPosition(state, poolId, position) {
3836
+ const pool = diagramsCore.getNode(state, poolId);
3837
+ if (!pool) return 0;
3838
+ const lanes = getBpmnPoolLanes(state, poolId);
3839
+ const direction = resolvePoolLaneDirection(pool);
3840
+ const axis = direction === "vertical" ? "y" : "x";
3841
+ const sizeKey = direction === "vertical" ? "height" : "width";
3842
+ for (let index = 0; index < lanes.length; index += 1) {
3843
+ const lane = lanes[index];
3844
+ const midpoint = lane.position[axis] + getNodeDimension(lane, sizeKey) / 2;
3845
+ if (position[axis] < midpoint) return index;
3846
+ }
3847
+ return lanes.length;
3848
+ }
3849
+ function sortBpmnLanes(state, poolId, laneId, index) {
3850
+ const lanes = getBpmnPoolLanes(state, poolId);
3851
+ const currentIndex = lanes.findIndex((lane) => lane.id === laneId);
3852
+ if (currentIndex < 0) return state;
3853
+ const orderedIds = lanes.map((lane) => lane.id);
3854
+ const [moved] = orderedIds.splice(currentIndex, 1);
3855
+ orderedIds.splice(Math.max(0, Math.min(index, orderedIds.length)), 0, moved);
3856
+ const order = new Map(orderedIds.map((id, laneIndex) => [id, laneIndex]));
3857
+ return {
3858
+ ...state,
3859
+ nodes: [...state.nodes].sort((a, b) => {
3860
+ const aOrder = order.get(a.id);
3861
+ const bOrder = order.get(b.id);
3862
+ if (aOrder === void 0 && bOrder === void 0) return 0;
3863
+ if (aOrder === void 0) return -1;
3864
+ if (bOrder === void 0) return 1;
3865
+ return aOrder - bOrder;
3866
+ })
3867
+ };
3868
+ }
3869
+ function layoutBpmnPoolLanes(state, poolId) {
3870
+ const pool = diagramsCore.getNode(state, poolId);
3871
+ if (!pool) return state;
3872
+ const poolSize = getBpmnElementSize("Pool");
3873
+ const direction = resolvePoolLaneDirection(pool);
3874
+ const lanes = getBpmnPoolLanes(state, poolId);
3875
+ let cursor = direction === "vertical" ? BPMN_POOL_LANE_LAYOUT.poolHeaderSize : 0;
3876
+ let next = state;
3877
+ for (const lane of lanes) {
3878
+ const laneSize = getBpmnElementSize("Lane");
3879
+ const width = direction === "vertical" ? Math.max(poolSize.minWidth - BPMN_POOL_LANE_LAYOUT.poolHeaderSize, lane.width ?? laneSize.width) : lane.width ?? laneSize.width;
3880
+ const height = direction === "vertical" ? lane.height ?? laneSize.height : Math.max(poolSize.minHeight - BPMN_POOL_LANE_LAYOUT.poolHeaderSize, lane.height ?? laneSize.height);
3881
+ next = diagramsCore.patchNode(next, lane.id, {
3882
+ position: direction === "vertical" ? { x: BPMN_POOL_LANE_LAYOUT.poolHeaderSize, y: cursor } : { x: cursor, y: BPMN_POOL_LANE_LAYOUT.poolHeaderSize },
3883
+ width,
3884
+ height,
3885
+ data: { orientation: pool.data.orientation ?? "horizontal" }
3886
+ });
3887
+ cursor += (direction === "vertical" ? height : width) + BPMN_POOL_LANE_LAYOUT.laneGap;
3888
+ }
3889
+ const minWidth = direction === "vertical" ? poolSize.minWidth : Math.max(poolSize.minWidth, cursor);
3890
+ const minHeight = direction === "vertical" ? Math.max(poolSize.minHeight, cursor) : poolSize.minHeight;
3891
+ return diagramsCore.resizeNode(next, poolId, { width: minWidth, height: minHeight });
3892
+ }
3893
+ function reorderBpmnLane(state, options) {
3894
+ return layoutBpmnPoolLanes(
3895
+ sortBpmnLanes(state, options.poolId, options.laneId, options.index),
3896
+ options.poolId
3897
+ );
3898
+ }
3899
+ function validateBpmnConnectionForEdgeType(state, edgeType, source, target) {
3900
+ const rule = BPMN_EDGE_CONNECTION_RULES[edgeType];
3901
+ if (!matchesConnectionCategory(source.data.elementType, rule.sourceCategories)) {
3902
+ return `${edgeType} cannot start from ${source.data.elementType}.`;
3903
+ }
3904
+ if (!matchesConnectionCategory(target.data.elementType, rule.targetCategories)) {
3905
+ return `${edgeType} cannot target ${target.data.elementType}.`;
3906
+ }
3907
+ const sameParent = (source.parentId ?? null) === (target.parentId ?? null);
3908
+ if (sameParent && rule.allowSameParent === false) {
3909
+ return `${edgeType} must connect BPMN elements in different participants/scopes.`;
3910
+ }
3911
+ if (!sameParent && rule.allowDifferentParent === false) {
3912
+ return `${edgeType} must stay inside the same BPMN participant/scope.`;
3913
+ }
3914
+ if (edgeType === "sequenceFlow") {
3915
+ if (source.data.elementType === "EndEvent") return "End events cannot have outgoing sequence flows.";
3916
+ if (target.data.elementType === "StartEvent") return "Start events cannot have incoming sequence flows.";
3917
+ return validateEdgeCardinality(state, edgeType, source, target);
3918
+ }
3919
+ return true;
3920
+ }
3921
+ function validateEdgeCardinality(state, edgeType, source, target) {
3922
+ if (edgeType !== "sequenceFlow") return true;
3923
+ const sourceMax = BPMN_ELEMENT_CATALOG[source.data.elementType].maxOutgoing;
3924
+ const targetMax = BPMN_ELEMENT_CATALOG[target.data.elementType].maxIncoming;
3925
+ const outgoing = diagramsCore.getOutgoingEdges(state, source.id).filter(
3926
+ (edge) => edge.data?.edgeType === "sequenceFlow"
3927
+ );
3928
+ const incoming = diagramsCore.getIncomingEdges(state, target.id).filter(
3929
+ (edge) => edge.data?.edgeType === "sequenceFlow"
3930
+ );
3931
+ if (sourceMax !== void 0 && outgoing.length >= sourceMax) {
3932
+ return `${source.data.elementType} cannot have more than ${sourceMax} outgoing sequence flow(s).`;
3933
+ }
3934
+ if (targetMax !== void 0 && incoming.length >= targetMax) {
3935
+ return `${target.data.elementType} cannot have more than ${targetMax} incoming sequence flow(s).`;
3936
+ }
3937
+ return true;
3938
+ }
3939
+ var bpmnConnectionValidators = [
3940
+ ({ state, source, target }) => {
3941
+ if (source.id === target.id) return "BPMN self-connections are not allowed.";
3942
+ const edgeType = inferBpmnEdgeType(state, source.id, target.id);
3943
+ if (getHandlePolicy(source.data.elementType) === "none" || getHandlePolicy(target.data.elementType) === "none") {
3944
+ return "Elements without BPMN connection handles cannot be directly connected.";
3945
+ }
3946
+ if (edgeType === "sequenceFlow") {
3947
+ return validateBpmnConnectionForEdgeType(state, edgeType, source, target);
3948
+ }
3949
+ return validateBpmnConnectionForEdgeType(state, edgeType, source, target);
3950
+ }
3951
+ ];
3952
+ var BPMN_MODELING_RULES = diagramsCore.createModelingRules({
3953
+ connect: [
3954
+ ({ state, source, target }) => {
3955
+ if (!source || !target) return false;
3956
+ for (const validator of bpmnConnectionValidators) {
3957
+ const result = validator({
3958
+ state,
3959
+ source,
3960
+ target,
3961
+ existingEdges: state.edges
3962
+ });
3963
+ if (result !== true) return result;
3964
+ }
3965
+ return true;
3966
+ }
3967
+ ],
3968
+ drop: [
3969
+ ({ node, parent }) => {
3970
+ if (!node || !parent) return true;
3971
+ if (node.data.elementType === "BoundaryEvent") {
3972
+ return acceptsBoundaryEvents(parent.data.elementType) ? true : "Boundary events can only be attached to tasks or subprocesses.";
3973
+ }
3974
+ return canContainBpmnElement(parent.data.elementType, node.data.elementType);
3975
+ }
3976
+ ],
3977
+ reparent: [
3978
+ ({ node, parent }) => {
3979
+ if (!node || !parent) return true;
3980
+ if (node.data.elementType === "BoundaryEvent") {
3981
+ return acceptsBoundaryEvents(parent.data.elementType) ? true : "Boundary events can only be reparented to tasks or subprocesses.";
3982
+ }
3983
+ return canContainBpmnElement(parent?.data.elementType, node.data.elementType);
3984
+ }
3985
+ ],
3986
+ delete: [() => true],
3987
+ resize: [
3988
+ ({ node }) => !node || isBpmnElementResizable(node.data.elementType) ? true : `${node.data.elementType} is not resizable in BPMN.`
3989
+ ]
3990
+ });
3991
+ function createBpmnNodeCommand(options) {
3992
+ return {
3993
+ id: `bpmn.createNode.${options.id}`,
3994
+ label: `Create ${options.elementType}`,
3995
+ execute: (state) => diagramsCore.addNode(state, createBpmnNode(options))
3996
+ };
3997
+ }
3998
+ function connectBpmnCommand(options) {
3999
+ return {
4000
+ id: `bpmn.connect.${options.id ?? `${options.source}-${options.target}`}`,
4001
+ label: "Connect BPMN elements",
4002
+ execute: (state) => {
4003
+ const edgeType = options.edgeType ?? inferBpmnEdgeType(state, options.source, options.target);
4004
+ const source = diagramsCore.getNode(state, options.source);
4005
+ const target = diagramsCore.getNode(state, options.target);
4006
+ if (!source) throw new Error(`Source node "${options.source}" does not exist.`);
4007
+ if (!target) throw new Error(`Target node "${options.target}" does not exist.`);
4008
+ const validation = validateBpmnConnectionForEdgeType(state, edgeType, source, target);
4009
+ if (validation !== true) throw new Error(validation);
4010
+ return diagramsCore.connectNodes(
4011
+ state,
4012
+ {
4013
+ source: options.source,
4014
+ target: options.target,
4015
+ type: edgeType,
4016
+ ...options.sourceHandle !== void 0 ? { sourceHandle: options.sourceHandle } : {},
4017
+ ...options.targetHandle !== void 0 ? { targetHandle: options.targetHandle } : {},
4018
+ ...options.id ? { id: options.id } : {},
4019
+ data: {
4020
+ edgeType,
4021
+ ...options.label ? { label: options.label } : {},
4022
+ ...options.data ?? {}
4023
+ }
4024
+ },
4025
+ []
4026
+ );
4027
+ }
4028
+ };
4029
+ }
4030
+ function attachBoundaryEventCommand(boundaryId, hostId) {
4031
+ return {
4032
+ id: `bpmn.attachBoundary.${boundaryId}.${hostId}`,
4033
+ label: "Attach boundary event",
4034
+ execute: (state) => {
4035
+ const host = diagramsCore.getNode(state, hostId);
4036
+ if (!host || !acceptsBoundaryEvents(host.data.elementType)) {
4037
+ throw new Error(`Element "${hostId}" cannot host boundary events.`);
4038
+ }
4039
+ const boundary = diagramsCore.getNode(state, boundaryId);
4040
+ if (!boundary || boundary.data.elementType !== "BoundaryEvent") {
4041
+ throw new Error(`Element "${boundaryId}" is not a boundary event.`);
4042
+ }
4043
+ const reparented = diagramsCore.reparentNode(state, boundaryId, { parentId: hostId });
4044
+ return diagramsCore.patchNode(reparented, boundaryId, {
4045
+ data: { attachedToRef: hostId }
4046
+ });
4047
+ }
4048
+ };
4049
+ }
4050
+ function replaceBpmnNodeCommand(options) {
4051
+ return {
4052
+ id: `bpmn.replaceNode.${options.id}.${options.elementType}`,
4053
+ label: `Replace with ${options.elementType}`,
4054
+ execute: (state) => {
4055
+ const current = diagramsCore.getNode(state, options.id);
4056
+ if (!current) throw new Error(`Element "${options.id}" does not exist.`);
4057
+ const meta = BPMN_ELEMENT_CATALOG[options.elementType];
4058
+ return diagramsCore.replaceNode(state, options.id, {
4059
+ ...current,
4060
+ type: options.elementType,
4061
+ width: options.width ?? current.width ?? meta.defaultWidth,
4062
+ height: options.height ?? current.height ?? meta.defaultHeight,
4063
+ data: {
4064
+ ...current.data,
4065
+ elementType: options.elementType,
4066
+ ...options.label ? { label: options.label } : {},
4067
+ ...options.data ?? {}
4068
+ }
4069
+ });
4070
+ }
4071
+ };
4072
+ }
4073
+ function reparentBpmnNodeCommand(options) {
4074
+ return {
4075
+ id: `bpmn.reparent.${options.id}.${options.parentId ?? "root"}`,
4076
+ label: "Reparent BPMN element",
4077
+ execute: (state) => {
4078
+ const node = diagramsCore.getNode(state, options.id);
4079
+ const parent = options.parentId ? diagramsCore.getNode(state, options.parentId) : void 0;
4080
+ if (!node) throw new Error(`Element "${options.id}" does not exist.`);
4081
+ if (parent && node.data.elementType === "BoundaryEvent" && !acceptsBoundaryEvents(parent.data.elementType)) {
4082
+ throw new Error("Boundary events can only be reparented to tasks or subprocesses.");
4083
+ }
4084
+ const containment = canContainBpmnElement(parent?.data.elementType, node.data.elementType);
4085
+ if (containment !== true) throw new Error(containment);
4086
+ const reparented = diagramsCore.reparentNode(state, options.id, {
4087
+ ...options.parentId !== void 0 ? { parentId: options.parentId } : {},
4088
+ ...options.position ? { position: options.position } : {}
4089
+ });
4090
+ return parent?.data.elementType === "Pool" && node.data.elementType === "Lane" ? layoutBpmnPoolLanes(reparented, parent.id) : reparented;
4091
+ }
4092
+ };
4093
+ }
4094
+ function resizeBpmnNodeCommand(options) {
4095
+ return {
4096
+ id: `bpmn.resize.${options.id}`,
4097
+ label: "Resize BPMN element",
4098
+ execute: (state) => {
4099
+ const node = diagramsCore.getNode(state, options.id);
4100
+ if (!node) throw new Error(`Element "${options.id}" does not exist.`);
4101
+ const size = getBpmnElementSize(node.data.elementType);
4102
+ if (!size.resizable) {
4103
+ throw new Error(`${node.data.elementType} is not resizable in BPMN.`);
4104
+ }
4105
+ return diagramsCore.resizeNode(state, options.id, {
4106
+ width: options.width === void 0 ? void 0 : Math.max(size.minWidth, options.width),
4107
+ height: options.height === void 0 ? void 0 : Math.max(size.minHeight, options.height)
4108
+ });
4109
+ }
4110
+ };
4111
+ }
4112
+ function reorderBpmnLaneCommand(options) {
4113
+ return {
4114
+ id: `bpmn.reorderLane.${options.poolId}.${options.laneId}`,
4115
+ label: "Reorder BPMN lane",
4116
+ execute: (state) => {
4117
+ const pool = diagramsCore.getNode(state, options.poolId);
4118
+ const lane = diagramsCore.getNode(state, options.laneId);
4119
+ if (!pool || pool.data.elementType !== "Pool") {
4120
+ throw new Error(`Element "${options.poolId}" is not a pool.`);
4121
+ }
4122
+ if (!lane || lane.data.elementType !== "Lane" || lane.parentId !== options.poolId) {
4123
+ throw new Error(`Element "${options.laneId}" is not a lane in pool "${options.poolId}".`);
4124
+ }
4125
+ return reorderBpmnLane(state, options);
4126
+ }
4127
+ };
4128
+ }
4129
+ function moveBpmnLaneCommand(options) {
4130
+ return {
4131
+ id: `bpmn.moveLane.${options.poolId}.${options.laneId}`,
4132
+ label: "Move BPMN lane",
4133
+ execute: (state) => reorderBpmnLane(state, {
4134
+ poolId: options.poolId,
4135
+ laneId: options.laneId,
4136
+ index: getBpmnLaneIndexAtPosition(state, options.poolId, options.position)
4137
+ })
4138
+ };
4139
+ }
4140
+ function routeBpmnEdgeCommand(options) {
4141
+ return {
4142
+ id: `bpmn.routeEdge.${options.id}`,
4143
+ label: "Route BPMN edge",
4144
+ execute: (state) => {
4145
+ const edge = state.edges.find((item) => item.id === options.id);
4146
+ if (!edge) throw new Error(`Edge "${options.id}" does not exist.`);
4147
+ const edgeType = edge.data?.edgeType;
4148
+ if (!edgeType || !isBpmnEdgeRoutingEditable(edgeType)) {
4149
+ throw new Error(`${edgeType ?? "edge"} routing points cannot be edited.`);
4150
+ }
4151
+ return diagramsCore.patchEdge(state, options.id, {
4152
+ data: { routingPoints: options.routingPoints }
4153
+ });
4154
+ }
4155
+ };
4156
+ }
4157
+ function deleteBpmnElementsCommand(ids) {
4158
+ return {
4159
+ id: `bpmn.delete.${ids.join(".")}`,
4160
+ label: "Delete BPMN elements",
4161
+ execute: (state) => diagramsCore.removeElements(state, ids)
4162
+ };
4163
+ }
4164
+ function copyBpmnElements(state, selection) {
4165
+ return diagramsCore.copyElements(state, selection);
4166
+ }
4167
+ function pasteBpmnElementsCommand(clipboard, options = {}) {
4168
+ return {
4169
+ id: "bpmn.paste",
4170
+ label: "Paste BPMN elements",
4171
+ execute: (state) => diagramsCore.pasteElements(state, clipboard, options)
4172
+ };
4173
+ }
4174
+ function selectBpmnElementsCommand(selection) {
4175
+ return {
4176
+ id: "bpmn.select",
4177
+ label: "Select BPMN elements",
4178
+ execute: (state) => diagramsCore.setSelection(state, diagramsCore.createSelectionState(selection.nodeIds, selection.edgeIds))
4179
+ };
4180
+ }
4181
+ function createBpmnDiagramDocument(state, options = {}) {
4182
+ return serialization.createDiagramDocument(diagramsCore.normalizeDiagramState(state), {
4183
+ ...options,
4184
+ diagramType: "bpmn"
4185
+ });
4186
+ }
4187
+ function serializeBpmnDiagram(state, options = {}) {
4188
+ return serialization.serializeDiagram(diagramsCore.normalizeDiagramState(state), {
4189
+ ...options,
4190
+ diagramType: "bpmn"
4191
+ });
4192
+ }
4193
+ function parseBpmnDiagramDocument(json) {
4194
+ const document = serialization.parseDiagramDocument(json);
4195
+ if (document.diagramType && document.diagramType !== "bpmn") {
4196
+ throw new Error(`Expected a BPMN diagram document, received "${document.diagramType}".`);
4197
+ }
4198
+ return document;
4199
+ }
4200
+ function deserializeBpmnDiagram(json) {
4201
+ const document = parseBpmnDiagramDocument(json);
4202
+ return serialization.deserializeDiagram(JSON.stringify(document));
4203
+ }
4204
+ function runBpmnCommand(stack, command) {
4205
+ return diagramsCore.executeCommand(stack, command);
4206
+ }
4207
+ function runBpmnCommands(stack, commands, options = {}) {
4208
+ return diagramsCore.executeCommands(stack, commands, options);
4209
+ }
4210
+
4211
+ // src/validation/index.ts
4212
+ function isFlowNode(type) {
4213
+ return isEventType(type) || isGatewayType(type) || type.includes("Task") || type === "CallActivity" || type === "SubProcess" || type === "Transaction" || type === "EventSubProcess" || type === "AdHocSubProcess" || type === "ChoreographyTask" || type === "SubChoreography" || type === "CallChoreography";
4214
+ }
4215
+ function isProcessNode(type) {
4216
+ return isFlowNode(type) && type !== "BoundaryEvent";
4217
+ }
4218
+ function isSubProcess2(type) {
4219
+ return type === "SubProcess" || type === "Transaction" || type === "EventSubProcess" || type === "AdHocSubProcess";
4220
+ }
4221
+ function isCatchTarget(type) {
4222
+ return type === "IntermediateCatchEvent" || type === "ReceiveTask";
4223
+ }
4224
+ function poolAncestor(node, nodeById2) {
4225
+ let current = node;
4226
+ const visited = /* @__PURE__ */ new Set();
4227
+ while (current?.parentId && !visited.has(current.id)) {
4228
+ visited.add(current.id);
4229
+ const parent = nodeById2.get(current.parentId);
4230
+ if (parent?.data.elementType === "Pool") return parent.id;
4231
+ current = parent;
4232
+ }
4233
+ return void 0;
4234
+ }
4235
+ function countSequenceEdges(edges, nodeId, direction) {
4236
+ return edges.filter((edge) => {
4237
+ if (edge.data?.edgeType !== "sequenceFlow") return false;
4238
+ return direction === "in" ? edge.target === nodeId : edge.source === nodeId;
4239
+ }).length;
4240
+ }
4241
+ function sequenceEdges(edges) {
4242
+ return edges.filter((edge) => (edge.data?.edgeType ?? edge.type) === "sequenceFlow");
4243
+ }
4244
+ function sequenceOut(edges, nodeId) {
4245
+ return sequenceEdges(edges).filter((edge) => edge.source === nodeId);
4246
+ }
4247
+ function sequenceIn(edges, nodeId) {
4248
+ return sequenceEdges(edges).filter((edge) => edge.target === nodeId);
4249
+ }
4250
+ function issue(code, severity, message, elementId, relatedElementIds) {
4251
+ return {
4252
+ id: `${code}:${elementId ?? relatedElementIds?.join(",") ?? "diagram"}`,
4253
+ code,
4254
+ severity,
4255
+ message,
4256
+ ...elementId ? { elementId } : {},
4257
+ ...relatedElementIds ? { relatedElementIds } : {}
4258
+ };
4259
+ }
4260
+ function validateBpmnDiagram(nodes, edges, options = {}) {
4261
+ const opts = {
4262
+ requireStartEvent: true,
4263
+ requireEndEvent: true,
4264
+ strictNames: false,
4265
+ ...options
4266
+ };
4267
+ const issues = [];
4268
+ const nodeById2 = new Map(nodes.map((node) => [node.id, node]));
4269
+ const seqEdges = sequenceEdges(edges);
4270
+ const processNodes = nodes.filter((node) => isProcessNode(node.data.elementType));
4271
+ if (opts.requireStartEvent && !processNodes.some((node) => node.data.elementType === "StartEvent")) {
4272
+ issues.push(issue("bpmn/start-event-required", "error", "The diagram must contain at least one start event."));
4273
+ }
4274
+ if (opts.requireEndEvent && !processNodes.some((node) => node.data.elementType === "EndEvent")) {
4275
+ issues.push(issue("bpmn/end-event-required", "error", "The diagram must contain at least one end event."));
4276
+ }
4277
+ for (const edge of edges) {
4278
+ const edgeType = edge.data?.edgeType ?? edge.type;
4279
+ const source = nodeById2.get(edge.source);
4280
+ const target = nodeById2.get(edge.target);
4281
+ if (!source || !target) {
4282
+ issues.push(issue(
4283
+ "bpmn/no-orphan-edges",
4284
+ "error",
4285
+ `Edge "${edge.id}" references a missing ${!source ? "source" : "target"} node.`,
4286
+ edge.id,
4287
+ [edge.source, edge.target]
4288
+ ));
4289
+ continue;
4290
+ }
4291
+ if (edge.source === edge.target) {
4292
+ issues.push(issue("bpmn/no-self-loop", "error", "BPMN edges cannot connect an element to itself.", edge.id, [edge.source]));
4293
+ }
4294
+ if (edgeType === "sequenceFlow") {
4295
+ if (!isFlowNode(source.data.elementType) || !isFlowNode(target.data.elementType) || isDataType(source.data.elementType) || isDataType(target.data.elementType)) {
4296
+ issues.push(issue("bpmn/sequence-flow-valid-endpoints", "error", "Sequence flows must connect BPMN flow nodes.", edge.id, [source.id, target.id]));
4297
+ }
4298
+ const sourcePool = poolAncestor(source, nodeById2);
4299
+ const targetPool = poolAncestor(target, nodeById2);
4300
+ if (sourcePool && targetPool && sourcePool !== targetPool) {
4301
+ 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]));
4302
+ }
4303
+ }
4304
+ if (edgeType === "messageFlow") {
4305
+ const sourcePool = poolAncestor(source, nodeById2);
4306
+ const targetPool = poolAncestor(target, nodeById2);
4307
+ if (!sourcePool || !targetPool || sourcePool === targetPool) {
4308
+ issues.push(issue("bpmn/message-flow-valid-endpoints", "error", "Message flows must connect flow nodes in different pools.", edge.id, [source.id, target.id]));
4309
+ }
4310
+ if (!isFlowNode(source.data.elementType) || !isFlowNode(target.data.elementType)) {
4311
+ issues.push(issue("bpmn/message-flow-valid-endpoints", "error", "Message flows must connect BPMN flow nodes, not containers.", edge.id, [source.id, target.id]));
4312
+ }
4313
+ }
4314
+ if (edgeType === "dataAssociation") {
4315
+ const hasDataEndpoint = isDataType(source.data.elementType) || isDataType(target.data.elementType);
4316
+ const hasFlowEndpoint = isFlowNode(source.data.elementType) || isFlowNode(target.data.elementType);
4317
+ if (!hasDataEndpoint || !hasFlowEndpoint) {
4318
+ issues.push(issue("bpmn/data-association-valid-endpoints", "error", "Data associations must connect data elements with flow nodes.", edge.id, [source.id, target.id]));
4319
+ }
4320
+ }
4321
+ }
4322
+ const duplicateSequenceKeys = /* @__PURE__ */ new Set();
4323
+ const reportedDuplicateKeys = /* @__PURE__ */ new Set();
4324
+ for (const edge of seqEdges) {
4325
+ const key = `${edge.source}->${edge.target}`;
4326
+ if (duplicateSequenceKeys.has(key) && !reportedDuplicateKeys.has(key)) {
4327
+ reportedDuplicateKeys.add(key);
4328
+ 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]));
4329
+ }
4330
+ duplicateSequenceKeys.add(key);
4331
+ }
4332
+ for (const node of nodes) {
4333
+ const type = node.data.elementType;
4334
+ const incoming = countSequenceEdges(edges, node.id, "in");
4335
+ const outgoing = countSequenceEdges(edges, node.id, "out");
4336
+ const meta = BPMN_ELEMENT_CATALOG[type];
4337
+ if (type === "StartEvent" && incoming > 0) {
4338
+ issues.push(issue("bpmn/start-event-no-incoming", "error", "Start events cannot have incoming sequence flows.", node.id));
4339
+ }
4340
+ if (type === "EndEvent") {
4341
+ if (outgoing > 0) issues.push(issue("bpmn/no-outgoing-from-end-event", "error", "End events cannot have outgoing sequence flows.", node.id));
4342
+ if (incoming === 0) issues.push(issue("bpmn/end-event-has-incoming", "error", "End events should have at least one incoming sequence flow.", node.id));
4343
+ }
4344
+ if ((type === "IntermediateCatchEvent" || type === "IntermediateThrowEvent") && (incoming === 0 || outgoing === 0)) {
4345
+ issues.push(issue("bpmn/intermediate-event-both-flows", "error", "Intermediate events should have both incoming and outgoing sequence flows.", node.id));
4346
+ }
4347
+ if (type === "BoundaryEvent") {
4348
+ const hostId = node.data.attachedToRef ?? node.parentId;
4349
+ const host = hostId ? nodeById2.get(hostId) : void 0;
4350
+ if (!host || !BPMN_ELEMENT_CATALOG[host.data.elementType]?.acceptsBoundaryEvents) {
4351
+ issues.push(issue("bpmn/boundary-event-attached", "error", "Boundary events must be attached to an activity or subprocess.", node.id, hostId ? [hostId] : void 0));
4352
+ }
4353
+ if (sequenceIn(edges, node.id).length > 0) {
4354
+ issues.push(issue("bpmn/boundary-no-incoming", "error", "Boundary events cannot have incoming sequence flows.", node.id));
4355
+ }
4356
+ if (sequenceOut(edges, node.id).length === 0) {
4357
+ issues.push(issue("bpmn/boundary-has-outgoing", "warning", "Boundary events should define an outgoing exception path.", node.id));
4358
+ }
4359
+ }
4360
+ if (isGatewayType(type)) {
4361
+ if (incoming === 0) issues.push(issue("bpmn/gateway-has-incoming", "error", "Gateways should have at least one incoming sequence flow.", node.id));
4362
+ if (outgoing === 0) issues.push(issue("bpmn/gateway-has-outgoing", "error", "Gateways should have at least one outgoing sequence flow.", node.id));
4363
+ }
4364
+ if (type === "ExclusiveGateway" || type === "InclusiveGateway" || type === "ComplexGateway") {
4365
+ const outgoingEdges = sequenceOut(edges, node.id);
4366
+ const defaults = outgoingEdges.filter((edge) => edge.data?.isDefault);
4367
+ if (defaults.length > 1) {
4368
+ issues.push(issue("bpmn/gateway-single-default", "error", "Gateways can have at most one default sequence flow.", node.id, defaults.map((edge) => edge.id)));
4369
+ }
4370
+ if (outgoingEdges.length >= 2) {
4371
+ for (const edge of outgoingEdges) {
4372
+ if (!edge.data?.isDefault && !edge.data?.conditionExpression) {
4373
+ 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]));
4374
+ }
4375
+ }
4376
+ }
4377
+ }
4378
+ if (type === "EventBasedGateway") {
4379
+ const outgoingEdges = edges.filter((edge) => edge.data?.edgeType === "sequenceFlow" && edge.source === node.id);
4380
+ if (outgoingEdges.length < 2) {
4381
+ issues.push(issue("bpmn/event-based-gateway-min-outgoing", "error", "Event-based gateways should have at least two outgoing sequence flows.", node.id));
4382
+ }
4383
+ for (const edge of outgoingEdges) {
4384
+ const target = nodeById2.get(edge.target);
4385
+ if (target && !isCatchTarget(target.data.elementType)) {
4386
+ 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]));
4387
+ }
4388
+ }
4389
+ }
4390
+ if (meta.maxIncoming !== void 0 && incoming > meta.maxIncoming) {
4391
+ issues.push(issue("bpmn/max-incoming", "error", `${type} cannot have more than ${meta.maxIncoming} incoming sequence flow(s).`, node.id));
4392
+ }
4393
+ if (meta.maxOutgoing !== void 0 && outgoing > meta.maxOutgoing) {
4394
+ issues.push(issue("bpmn/max-outgoing", "error", `${type} cannot have more than ${meta.maxOutgoing} outgoing sequence flow(s).`, node.id));
4395
+ }
4396
+ if (opts.strictNames && (type.includes("Task") || isGatewayType(type)) && !node.data.label) {
4397
+ issues.push(issue("bpmn/name-required", "warning", `${type} should have a label.`, node.id));
4398
+ }
4399
+ if (isSubProcess2(type)) {
4400
+ const childNodes = nodes.filter((child) => child.parentId === node.id);
4401
+ if (childNodes.length > 0) {
4402
+ if (!childNodes.some((child) => child.data.elementType === "StartEvent")) {
4403
+ issues.push(issue("bpmn/subprocess-has-start-end", "error", "Expanded subprocesses should contain a start event.", node.id));
4404
+ }
4405
+ if (!childNodes.some((child) => child.data.elementType === "EndEvent")) {
4406
+ issues.push(issue("bpmn/subprocess-has-start-end", "error", "Expanded subprocesses should contain an end event.", node.id));
4407
+ }
4408
+ }
4409
+ if (type === "EventSubProcess") {
4410
+ const starts = childNodes.filter((child) => child.data.elementType === "StartEvent");
4411
+ for (const start of starts) {
4412
+ if (!start.data.trigger || start.data.trigger === "none") {
4413
+ issues.push(issue("bpmn/event-subprocess-triggered-start", "error", "Event subprocess start events must define an event trigger.", start.id, [node.id]));
4414
+ }
4415
+ }
4416
+ }
4417
+ }
4418
+ if (type === "Lane") {
4419
+ const parent = node.parentId ? nodeById2.get(node.parentId) : void 0;
4420
+ if (parent?.data.elementType !== "Pool") {
4421
+ issues.push(issue("bpmn/lane-parent-pool", "error", "Lanes must be contained by a pool.", node.id));
4422
+ }
4423
+ }
4424
+ }
4425
+ return {
4426
+ valid: issues.every((item) => item.severity !== "error"),
4427
+ issues
4428
+ };
3466
4429
  }
3467
4430
 
3468
4431
  exports.AnnotationNode = AnnotationNode;
3469
4432
  exports.AssociationEdge = AssociationEdge;
4433
+ exports.BPMN_EDGE_CONNECTION_RULES = BPMN_EDGE_CONNECTION_RULES;
3470
4434
  exports.BPMN_EDGE_TYPES = BPMN_EDGE_TYPES;
3471
4435
  exports.BPMN_ELEMENT_CATALOG = BPMN_ELEMENT_CATALOG;
4436
+ exports.BPMN_MODELING_RULES = BPMN_MODELING_RULES;
3472
4437
  exports.BPMN_NODE_TYPES = BPMN_NODE_TYPES;
4438
+ exports.BPMN_POOL_LANE_LAYOUT = BPMN_POOL_LANE_LAYOUT;
4439
+ exports.BPMN_RESIZABLE_ELEMENT_TYPES = BPMN_RESIZABLE_ELEMENT_TYPES;
4440
+ exports.BPMN_ROUTABLE_EDGE_TYPES = BPMN_ROUTABLE_EDGE_TYPES;
4441
+ exports.BPMN_SELECTION_STYLE = BPMN_SELECTION_STYLE;
3473
4442
  exports.BoundaryEventNode = BoundaryEventNode;
3474
4443
  exports.CallChoreographyNode = CallChoreographyNode;
3475
4444
  exports.CallConversationNode = CallConversationNode;
@@ -3498,13 +4467,30 @@ exports.SubConversationNode = SubConversationNode;
3498
4467
  exports.SubProcessNode = SubProcessNode;
3499
4468
  exports.TaskNode = TaskNode;
3500
4469
  exports.acceptsBoundaryEvents = acceptsBoundaryEvents;
3501
- exports.createPreviewAdapter = createPreviewAdapter;
4470
+ exports.attachBoundaryEventCommand = attachBoundaryEventCommand;
4471
+ exports.bpmnConnectionValidators = bpmnConnectionValidators;
4472
+ exports.canContainBpmnElement = canContainBpmnElement;
4473
+ exports.connectBpmnCommand = connectBpmnCommand;
4474
+ exports.copyBpmnElements = copyBpmnElements;
4475
+ exports.createBpmnDiagramDocument = createBpmnDiagramDocument;
4476
+ exports.createBpmnNode = createBpmnNode;
4477
+ exports.createBpmnNodeCommand = createBpmnNodeCommand;
3502
4478
  exports.createSimulation = createSimulation;
4479
+ exports.deleteBpmnElementsCommand = deleteBpmnElementsCommand;
4480
+ exports.deserializeBpmnDiagram = deserializeBpmnDiagram;
3503
4481
  exports.fire = fire;
4482
+ exports.getBpmnDragHandleSelector = getBpmnDragHandleSelector;
4483
+ exports.getBpmnElementSize = getBpmnElementSize;
4484
+ exports.getBpmnLaneIndexAtPosition = getBpmnLaneIndexAtPosition;
4485
+ exports.getBpmnPoolLanes = getBpmnPoolLanes;
3504
4486
  exports.getElementMeta = getElementMeta;
3505
4487
  exports.getFireable = getFireable;
3506
4488
  exports.getHandlePolicy = getHandlePolicy;
3507
4489
  exports.getOrientation = getOrientation;
4490
+ exports.inferBpmnEdgeType = inferBpmnEdgeType;
4491
+ exports.isBpmnEdgeRoutingEditable = isBpmnEdgeRoutingEditable;
4492
+ exports.isBpmnElementResizable = isBpmnElementResizable;
4493
+ exports.isBpmnProcessNode = isBpmnProcessNode;
3508
4494
  exports.isChoreographyType = isChoreographyType;
3509
4495
  exports.isCompleted = isCompleted;
3510
4496
  exports.isContainerType = isContainerType;
@@ -3513,11 +4499,27 @@ exports.isDataType = isDataType;
3513
4499
  exports.isEventType = isEventType;
3514
4500
  exports.isGatewayType = isGatewayType;
3515
4501
  exports.isTaskType = isTaskType;
4502
+ exports.layoutBpmnPoolLanes = layoutBpmnPoolLanes;
4503
+ exports.moveBpmnLaneCommand = moveBpmnLaneCommand;
4504
+ exports.parseBpmnDiagramDocument = parseBpmnDiagramDocument;
3516
4505
  exports.parseBpmnXml = parseBpmnXml;
4506
+ exports.pasteBpmnElementsCommand = pasteBpmnElementsCommand;
4507
+ exports.reorderBpmnLane = reorderBpmnLane;
4508
+ exports.reorderBpmnLaneCommand = reorderBpmnLaneCommand;
4509
+ exports.reparentBpmnNodeCommand = reparentBpmnNodeCommand;
4510
+ exports.replaceBpmnNodeCommand = replaceBpmnNodeCommand;
4511
+ exports.resizeBpmnNodeCommand = resizeBpmnNodeCommand;
4512
+ exports.routeBpmnEdgeCommand = routeBpmnEdgeCommand;
4513
+ exports.runBpmnCommand = runBpmnCommand;
4514
+ exports.runBpmnCommands = runBpmnCommands;
4515
+ exports.selectBpmnElementsCommand = selectBpmnElementsCommand;
4516
+ exports.serializeBpmnDiagram = serializeBpmnDiagram;
3517
4517
  exports.serializeBpmnXml = serializeBpmnXml;
3518
4518
  exports.setVariable = setVariable;
3519
4519
  exports.supportsCollapse = supportsCollapse;
3520
4520
  exports.supportsMarkers = supportsMarkers;
3521
4521
  exports.tick = tick;
4522
+ exports.validateBpmnConnectionForEdgeType = validateBpmnConnectionForEdgeType;
4523
+ exports.validateBpmnDiagram = validateBpmnDiagram;
3522
4524
  //# sourceMappingURL=index.cjs.map
3523
4525
  //# sourceMappingURL=index.cjs.map