@aranzatech/diagrams-bpmn 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +121 -0
  3. package/dist/{chunk-MLUJKUTG.js → chunk-5GRCJ5X6.js} +3 -3
  4. package/dist/{chunk-MLUJKUTG.js.map → chunk-5GRCJ5X6.js.map} +1 -1
  5. package/dist/{chunk-6TUC5QX5.js → chunk-DNR5WBQH.js} +83 -2
  6. package/dist/chunk-DNR5WBQH.js.map +1 -0
  7. package/dist/chunk-G5S4ASP3.js +277 -0
  8. package/dist/chunk-G5S4ASP3.js.map +1 -0
  9. package/dist/{chunk-4OAEWYYU.js → chunk-MF2WE3OM.js} +146 -37
  10. package/dist/chunk-MF2WE3OM.js.map +1 -0
  11. package/dist/chunk-OZKTOILD.js +3 -0
  12. package/dist/chunk-OZKTOILD.js.map +1 -0
  13. package/dist/{chunk-NXMUX67A.js → chunk-S3GGEEA5.js} +31 -8
  14. package/dist/chunk-S3GGEEA5.js.map +1 -0
  15. package/dist/elements/index.cjs +81 -0
  16. package/dist/elements/index.cjs.map +1 -1
  17. package/dist/elements/index.d.cts +2 -2
  18. package/dist/elements/index.d.ts +2 -2
  19. package/dist/elements/index.js +3 -2
  20. package/dist/index.cjs +535 -66
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.cts +7 -62
  23. package/dist/index.d.ts +7 -62
  24. package/dist/index.js +6 -40
  25. package/dist/index.js.map +1 -1
  26. package/dist/modeling/index.cjs +894 -0
  27. package/dist/modeling/index.cjs.map +1 -0
  28. package/dist/modeling/index.d.cts +88 -0
  29. package/dist/modeling/index.d.ts +88 -0
  30. package/dist/modeling/index.js +5 -0
  31. package/dist/modeling/index.js.map +1 -0
  32. package/dist/nodes/index.cjs +29 -6
  33. package/dist/nodes/index.cjs.map +1 -1
  34. package/dist/nodes/index.js +1 -1
  35. package/dist/{types-CxzazgBX.d.cts → types-BKA0GZz5.d.cts} +9 -19
  36. package/dist/{types-CxzazgBX.d.ts → types-BKA0GZz5.d.ts} +9 -19
  37. package/dist/types-CCkHqtC_.d.cts +20 -0
  38. package/dist/types-hj621ZRJ.d.ts +20 -0
  39. package/dist/xml/index.cjs +224 -34
  40. package/dist/xml/index.cjs.map +1 -1
  41. package/dist/xml/index.d.cts +4 -19
  42. package/dist/xml/index.d.ts +4 -19
  43. package/dist/xml/index.js +2 -2
  44. package/package.json +12 -4
  45. package/dist/chunk-4OAEWYYU.js.map +0 -1
  46. package/dist/chunk-6TUC5QX5.js.map +0 -1
  47. package/dist/chunk-NXMUX67A.js.map +0 -1
@@ -0,0 +1,277 @@
1
+ import { acceptsBoundaryEvents, isEventType, getHandlePolicy, isDataType } from './chunk-5GRCJ5X6.js';
2
+ import { BPMN_ELEMENT_CATALOG } from './chunk-DNR5WBQH.js';
3
+ import { createModelingRules, getNode, getOutgoingEdges, getIncomingEdges, addNode, connectNodes, reparentNode, patchNode, replaceNode, resizeNode, removeElements, copyElements, pasteElements, setSelection, createSelectionState, normalizeDiagramState, executeCommand, executeCommands } from '@aranzatech/diagrams-core';
4
+ import { createDiagramDocument, serializeDiagram, parseDiagramDocument, deserializeDiagram } from '@aranzatech/diagrams-core/serialization';
5
+
6
+ function createBpmnNode(options) {
7
+ const meta = BPMN_ELEMENT_CATALOG[options.elementType];
8
+ return {
9
+ id: options.id,
10
+ type: options.elementType,
11
+ position: options.position,
12
+ data: {
13
+ elementType: options.elementType,
14
+ ...options.label ? { label: options.label } : {},
15
+ ...options.data ?? {}
16
+ },
17
+ width: options.width ?? meta.defaultWidth,
18
+ height: options.height ?? meta.defaultHeight,
19
+ ...options.parentId ? { parentId: options.parentId } : {}
20
+ };
21
+ }
22
+ function inferBpmnEdgeType(state, sourceId, targetId) {
23
+ const source = getNode(state, sourceId);
24
+ const target = getNode(state, targetId);
25
+ if (!source || !target) return "sequenceFlow";
26
+ if (isDataType(source.data.elementType) || isDataType(target.data.elementType)) {
27
+ return "dataAssociation";
28
+ }
29
+ if (source.data.elementType === "Annotation" || target.data.elementType === "Annotation" || source.data.elementType === "Group" || target.data.elementType === "Group") {
30
+ return "association";
31
+ }
32
+ 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") {
33
+ return "conversationLink";
34
+ }
35
+ if (source.parentId && target.parentId && source.parentId !== target.parentId) {
36
+ return "messageFlow";
37
+ }
38
+ return "sequenceFlow";
39
+ }
40
+ function canUseSequenceFlow(type) {
41
+ const meta = BPMN_ELEMENT_CATALOG[type];
42
+ return meta.handlePolicy !== "none" && !isDataType(type) && type !== "Annotation" && type !== "Group" && meta.category !== "conversation";
43
+ }
44
+ function validateEdgeCardinality(state, edgeType, source, target) {
45
+ if (edgeType !== "sequenceFlow") return true;
46
+ const sourceMax = BPMN_ELEMENT_CATALOG[source.data.elementType].maxOutgoing;
47
+ const targetMax = BPMN_ELEMENT_CATALOG[target.data.elementType].maxIncoming;
48
+ const outgoing = getOutgoingEdges(state, source.id).filter(
49
+ (edge) => edge.data?.edgeType === "sequenceFlow"
50
+ );
51
+ const incoming = getIncomingEdges(state, target.id).filter(
52
+ (edge) => edge.data?.edgeType === "sequenceFlow"
53
+ );
54
+ if (sourceMax !== void 0 && outgoing.length >= sourceMax) {
55
+ return `${source.data.elementType} cannot have more than ${sourceMax} outgoing sequence flow(s).`;
56
+ }
57
+ if (targetMax !== void 0 && incoming.length >= targetMax) {
58
+ return `${target.data.elementType} cannot have more than ${targetMax} incoming sequence flow(s).`;
59
+ }
60
+ return true;
61
+ }
62
+ var bpmnConnectionValidators = [
63
+ ({ state, source, target }) => {
64
+ if (source.id === target.id) return "BPMN self-connections are not allowed.";
65
+ const edgeType = inferBpmnEdgeType(state, source.id, target.id);
66
+ if (getHandlePolicy(source.data.elementType) === "none" || getHandlePolicy(target.data.elementType) === "none") {
67
+ return "Elements without BPMN connection handles cannot be directly connected.";
68
+ }
69
+ if (edgeType === "sequenceFlow") {
70
+ if (!canUseSequenceFlow(source.data.elementType) || !canUseSequenceFlow(target.data.elementType)) {
71
+ return "Sequence flows can only connect BPMN flow nodes.";
72
+ }
73
+ if (source.data.elementType === "EndEvent") return "End events cannot have outgoing sequence flows.";
74
+ if (target.data.elementType === "StartEvent") return "Start events cannot have incoming sequence flows.";
75
+ return validateEdgeCardinality(state, edgeType, source, target);
76
+ }
77
+ return true;
78
+ }
79
+ ];
80
+ var BPMN_MODELING_RULES = createModelingRules({
81
+ connect: [
82
+ ({ state, source, target }) => {
83
+ if (!source || !target) return false;
84
+ for (const validator of bpmnConnectionValidators) {
85
+ const result = validator({
86
+ state,
87
+ source,
88
+ target,
89
+ existingEdges: state.edges
90
+ });
91
+ if (result !== true) return result;
92
+ }
93
+ return true;
94
+ }
95
+ ],
96
+ drop: [
97
+ ({ node, parent }) => {
98
+ if (!node || !parent) return true;
99
+ if (node.data.elementType === "BoundaryEvent") {
100
+ return acceptsBoundaryEvents(parent.data.elementType) ? true : "Boundary events can only be attached to tasks or subprocesses.";
101
+ }
102
+ if (parent.data.elementType === "Pool" || parent.data.elementType === "Lane") {
103
+ return isEventType(node.data.elementType) || node.data.elementType.includes("Task") || node.data.elementType.includes("Gateway") || node.data.elementType.includes("SubProcess") ? true : "Only flow nodes can be dropped into pools or lanes.";
104
+ }
105
+ return true;
106
+ }
107
+ ],
108
+ reparent: [
109
+ ({ node, parent }) => {
110
+ if (!node || !parent) return true;
111
+ if (node.data.elementType === "BoundaryEvent") {
112
+ return acceptsBoundaryEvents(parent.data.elementType) ? true : "Boundary events can only be reparented to tasks or subprocesses.";
113
+ }
114
+ return true;
115
+ }
116
+ ],
117
+ delete: [() => true],
118
+ resize: [() => true]
119
+ });
120
+ function createBpmnNodeCommand(options) {
121
+ return {
122
+ id: `bpmn.createNode.${options.id}`,
123
+ label: `Create ${options.elementType}`,
124
+ execute: (state) => addNode(state, createBpmnNode(options))
125
+ };
126
+ }
127
+ function connectBpmnCommand(options) {
128
+ return {
129
+ id: `bpmn.connect.${options.id ?? `${options.source}-${options.target}`}`,
130
+ label: "Connect BPMN elements",
131
+ execute: (state) => {
132
+ const edgeType = options.edgeType ?? inferBpmnEdgeType(state, options.source, options.target);
133
+ return connectNodes(
134
+ state,
135
+ {
136
+ source: options.source,
137
+ target: options.target,
138
+ type: edgeType,
139
+ ...options.sourceHandle !== void 0 ? { sourceHandle: options.sourceHandle } : {},
140
+ ...options.targetHandle !== void 0 ? { targetHandle: options.targetHandle } : {},
141
+ ...options.id ? { id: options.id } : {},
142
+ data: {
143
+ edgeType,
144
+ ...options.label ? { label: options.label } : {},
145
+ ...options.data ?? {}
146
+ }
147
+ },
148
+ bpmnConnectionValidators
149
+ );
150
+ }
151
+ };
152
+ }
153
+ function attachBoundaryEventCommand(boundaryId, hostId) {
154
+ return {
155
+ id: `bpmn.attachBoundary.${boundaryId}.${hostId}`,
156
+ label: "Attach boundary event",
157
+ execute: (state) => {
158
+ const host = getNode(state, hostId);
159
+ if (!host || !acceptsBoundaryEvents(host.data.elementType)) {
160
+ throw new Error(`Element "${hostId}" cannot host boundary events.`);
161
+ }
162
+ const boundary = getNode(state, boundaryId);
163
+ if (!boundary || boundary.data.elementType !== "BoundaryEvent") {
164
+ throw new Error(`Element "${boundaryId}" is not a boundary event.`);
165
+ }
166
+ const reparented = reparentNode(state, boundaryId, { parentId: hostId });
167
+ return patchNode(reparented, boundaryId, {
168
+ data: { attachedToRef: hostId }
169
+ });
170
+ }
171
+ };
172
+ }
173
+ function replaceBpmnNodeCommand(options) {
174
+ return {
175
+ id: `bpmn.replaceNode.${options.id}.${options.elementType}`,
176
+ label: `Replace with ${options.elementType}`,
177
+ execute: (state) => {
178
+ const current = getNode(state, options.id);
179
+ if (!current) throw new Error(`Element "${options.id}" does not exist.`);
180
+ const meta = BPMN_ELEMENT_CATALOG[options.elementType];
181
+ return replaceNode(state, options.id, {
182
+ ...current,
183
+ type: options.elementType,
184
+ width: options.width ?? current.width ?? meta.defaultWidth,
185
+ height: options.height ?? current.height ?? meta.defaultHeight,
186
+ data: {
187
+ ...current.data,
188
+ elementType: options.elementType,
189
+ ...options.label ? { label: options.label } : {},
190
+ ...options.data ?? {}
191
+ }
192
+ });
193
+ }
194
+ };
195
+ }
196
+ function reparentBpmnNodeCommand(options) {
197
+ return {
198
+ id: `bpmn.reparent.${options.id}.${options.parentId ?? "root"}`,
199
+ label: "Reparent BPMN element",
200
+ execute: (state) => {
201
+ const node = getNode(state, options.id);
202
+ const parent = options.parentId ? getNode(state, options.parentId) : void 0;
203
+ if (!node) throw new Error(`Element "${options.id}" does not exist.`);
204
+ if (parent && node.data.elementType === "BoundaryEvent" && !acceptsBoundaryEvents(parent.data.elementType)) {
205
+ throw new Error("Boundary events can only be reparented to tasks or subprocesses.");
206
+ }
207
+ return reparentNode(state, options.id, {
208
+ ...options.parentId !== void 0 ? { parentId: options.parentId } : {},
209
+ ...options.position ? { position: options.position } : {}
210
+ });
211
+ }
212
+ };
213
+ }
214
+ function resizeBpmnNodeCommand(options) {
215
+ return {
216
+ id: `bpmn.resize.${options.id}`,
217
+ label: "Resize BPMN element",
218
+ execute: (state) => resizeNode(state, options.id, options)
219
+ };
220
+ }
221
+ function deleteBpmnElementsCommand(ids) {
222
+ return {
223
+ id: `bpmn.delete.${ids.join(".")}`,
224
+ label: "Delete BPMN elements",
225
+ execute: (state) => removeElements(state, ids)
226
+ };
227
+ }
228
+ function copyBpmnElements(state, selection) {
229
+ return copyElements(state, selection);
230
+ }
231
+ function pasteBpmnElementsCommand(clipboard, options = {}) {
232
+ return {
233
+ id: "bpmn.paste",
234
+ label: "Paste BPMN elements",
235
+ execute: (state) => pasteElements(state, clipboard, options)
236
+ };
237
+ }
238
+ function selectBpmnElementsCommand(selection) {
239
+ return {
240
+ id: "bpmn.select",
241
+ label: "Select BPMN elements",
242
+ execute: (state) => setSelection(state, createSelectionState(selection.nodeIds, selection.edgeIds))
243
+ };
244
+ }
245
+ function createBpmnDiagramDocument(state, options = {}) {
246
+ return createDiagramDocument(normalizeDiagramState(state), {
247
+ ...options,
248
+ diagramType: "bpmn"
249
+ });
250
+ }
251
+ function serializeBpmnDiagram(state, options = {}) {
252
+ return serializeDiagram(normalizeDiagramState(state), {
253
+ ...options,
254
+ diagramType: "bpmn"
255
+ });
256
+ }
257
+ function parseBpmnDiagramDocument(json) {
258
+ const document = parseDiagramDocument(json);
259
+ if (document.diagramType && document.diagramType !== "bpmn") {
260
+ throw new Error(`Expected a BPMN diagram document, received "${document.diagramType}".`);
261
+ }
262
+ return document;
263
+ }
264
+ function deserializeBpmnDiagram(json) {
265
+ const document = parseBpmnDiagramDocument(json);
266
+ return deserializeDiagram(JSON.stringify(document));
267
+ }
268
+ function runBpmnCommand(stack, command) {
269
+ return executeCommand(stack, command);
270
+ }
271
+ function runBpmnCommands(stack, commands, options = {}) {
272
+ return executeCommands(stack, commands, options);
273
+ }
274
+
275
+ export { BPMN_MODELING_RULES, attachBoundaryEventCommand, bpmnConnectionValidators, connectBpmnCommand, copyBpmnElements, createBpmnDiagramDocument, createBpmnNode, createBpmnNodeCommand, deleteBpmnElementsCommand, deserializeBpmnDiagram, inferBpmnEdgeType, parseBpmnDiagramDocument, pasteBpmnElementsCommand, reparentBpmnNodeCommand, replaceBpmnNodeCommand, resizeBpmnNodeCommand, runBpmnCommand, runBpmnCommands, selectBpmnElementsCommand, serializeBpmnDiagram };
276
+ //# sourceMappingURL=chunk-G5S4ASP3.js.map
277
+ //# sourceMappingURL=chunk-G5S4ASP3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/modeling/index.ts"],"names":[],"mappings":"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","file":"chunk-G5S4ASP3.js","sourcesContent":["import {\n addNode,\n connectNodes,\n copyElements,\n createModelingRules,\n createSelectionState,\n executeCommand,\n executeCommands,\n getNode,\n getOutgoingEdges,\n getIncomingEdges,\n normalizeDiagramState,\n pasteElements,\n patchNode,\n removeElements,\n replaceNode,\n reparentNode,\n resizeNode,\n setSelection,\n type CommandStackState,\n type ClipboardState,\n type ConnectionValidator,\n type DiagramCommand,\n type DiagramState,\n type ModelingRules,\n type SelectionState,\n} from \"@aranzatech/diagrams-core\";\nimport {\n createDiagramDocument,\n deserializeDiagram,\n parseDiagramDocument,\n serializeDiagram,\n type CreateDiagramDocumentOptions,\n type DiagramDocument,\n} from \"@aranzatech/diagrams-core/serialization\";\nimport { BPMN_ELEMENT_CATALOG } from \"../elements/catalog\";\nimport {\n acceptsBoundaryEvents,\n getHandlePolicy,\n isDataType,\n isEventType,\n} from \"../elements/guards\";\nimport type { BpmnElementType, BpmnEdgeData, BpmnEdgeType, BpmnNodeData } from \"../elements/types\";\nimport type { BpmnRFEdge, BpmnRFNode } from \"../xml/types\";\n\nexport type BpmnDiagramState = DiagramState<BpmnRFNode, BpmnRFEdge>;\nexport type BpmnClipboardState = ClipboardState<BpmnRFNode, BpmnRFEdge>;\nexport type BpmnDiagramDocument = DiagramDocument<BpmnRFNode, BpmnRFEdge>;\n\nexport interface CreateBpmnNodeOptions {\n id: string;\n elementType: BpmnElementType;\n position: { x: number; y: number };\n label?: string;\n parentId?: string;\n width?: number;\n height?: number;\n data?: Partial<BpmnNodeData>;\n}\n\nexport interface ConnectBpmnOptions {\n id?: string;\n source: string;\n target: string;\n edgeType?: BpmnEdgeType;\n label?: string;\n sourceHandle?: string | null;\n targetHandle?: string | null;\n data?: Partial<BpmnEdgeData>;\n}\n\nexport interface ReplaceBpmnNodeOptions {\n id: string;\n elementType: BpmnElementType;\n label?: string;\n data?: Partial<BpmnNodeData>;\n width?: number;\n height?: number;\n}\n\nexport interface ReparentBpmnNodeOptions {\n id: string;\n parentId?: string;\n position?: { x: number; y: number };\n}\n\nexport interface ResizeBpmnNodeOptions {\n id: string;\n width?: number;\n height?: number;\n}\n\nexport interface PasteBpmnOptions {\n offset?: { x: number; y: number };\n position?: { x: number; y: number };\n}\n\nexport function createBpmnNode(options: CreateBpmnNodeOptions): BpmnRFNode {\n const meta = BPMN_ELEMENT_CATALOG[options.elementType];\n return {\n id: options.id,\n type: options.elementType,\n position: options.position,\n data: {\n elementType: options.elementType,\n ...(options.label ? { label: options.label } : {}),\n ...(options.data ?? {}),\n },\n width: options.width ?? meta.defaultWidth,\n height: options.height ?? meta.defaultHeight,\n ...(options.parentId ? { parentId: options.parentId } : {}),\n };\n}\n\nexport function inferBpmnEdgeType(\n state: BpmnDiagramState,\n sourceId: string,\n targetId: string,\n): BpmnEdgeType {\n const source = getNode(state, sourceId);\n const target = getNode(state, targetId);\n if (!source || !target) return \"sequenceFlow\";\n\n if (isDataType(source.data.elementType) || isDataType(target.data.elementType)) {\n return \"dataAssociation\";\n }\n if (\n source.data.elementType === \"Annotation\" ||\n target.data.elementType === \"Annotation\" ||\n source.data.elementType === \"Group\" ||\n target.data.elementType === \"Group\"\n ) {\n return \"association\";\n }\n if (\n source.data.elementType === \"Conversation\" ||\n source.data.elementType === \"SubConversation\" ||\n source.data.elementType === \"CallConversation\" ||\n target.data.elementType === \"Conversation\" ||\n target.data.elementType === \"SubConversation\" ||\n target.data.elementType === \"CallConversation\"\n ) {\n return \"conversationLink\";\n }\n if (source.parentId && target.parentId && source.parentId !== target.parentId) {\n return \"messageFlow\";\n }\n return \"sequenceFlow\";\n}\n\nfunction canUseSequenceFlow(type: BpmnElementType): boolean {\n const meta = BPMN_ELEMENT_CATALOG[type];\n return (\n meta.handlePolicy !== \"none\" &&\n !isDataType(type) &&\n type !== \"Annotation\" &&\n type !== \"Group\" &&\n meta.category !== \"conversation\"\n );\n}\n\nfunction validateEdgeCardinality(\n state: BpmnDiagramState,\n edgeType: BpmnEdgeType,\n source: BpmnRFNode,\n target: BpmnRFNode,\n): true | string {\n if (edgeType !== \"sequenceFlow\") return true;\n\n const sourceMax = BPMN_ELEMENT_CATALOG[source.data.elementType].maxOutgoing;\n const targetMax = BPMN_ELEMENT_CATALOG[target.data.elementType].maxIncoming;\n const outgoing = getOutgoingEdges(state, source.id).filter(\n (edge) => edge.data?.edgeType === \"sequenceFlow\",\n );\n const incoming = getIncomingEdges(state, target.id).filter(\n (edge) => edge.data?.edgeType === \"sequenceFlow\",\n );\n\n if (sourceMax !== undefined && outgoing.length >= sourceMax) {\n return `${source.data.elementType} cannot have more than ${sourceMax} outgoing sequence flow(s).`;\n }\n if (targetMax !== undefined && incoming.length >= targetMax) {\n return `${target.data.elementType} cannot have more than ${targetMax} incoming sequence flow(s).`;\n }\n return true;\n}\n\nexport const bpmnConnectionValidators: Array<\n ConnectionValidator<BpmnRFNode, BpmnRFEdge>\n> = [\n ({ state, source, target }) => {\n if (source.id === target.id) return \"BPMN self-connections are not allowed.\";\n const edgeType = inferBpmnEdgeType(state, source.id, target.id);\n\n if (getHandlePolicy(source.data.elementType) === \"none\" || getHandlePolicy(target.data.elementType) === \"none\") {\n return \"Elements without BPMN connection handles cannot be directly connected.\";\n }\n\n if (edgeType === \"sequenceFlow\") {\n if (!canUseSequenceFlow(source.data.elementType) || !canUseSequenceFlow(target.data.elementType)) {\n return \"Sequence flows can only connect BPMN flow nodes.\";\n }\n if (source.data.elementType === \"EndEvent\") return \"End events cannot have outgoing sequence flows.\";\n if (target.data.elementType === \"StartEvent\") return \"Start events cannot have incoming sequence flows.\";\n return validateEdgeCardinality(state, edgeType, source, target);\n }\n\n return true;\n },\n];\n\nexport const BPMN_MODELING_RULES: ModelingRules<BpmnRFNode, BpmnRFEdge> =\n createModelingRules({\n connect: [\n ({ state, source, target }) => {\n if (!source || !target) return false;\n for (const validator of bpmnConnectionValidators) {\n const result = validator({\n state,\n source,\n target,\n existingEdges: state.edges,\n });\n if (result !== true) return result;\n }\n return true;\n },\n ],\n drop: [\n ({ node, parent }) => {\n if (!node || !parent) return true;\n if (node.data.elementType === \"BoundaryEvent\") {\n return acceptsBoundaryEvents(parent.data.elementType)\n ? true\n : \"Boundary events can only be attached to tasks or subprocesses.\";\n }\n if (parent.data.elementType === \"Pool\" || parent.data.elementType === \"Lane\") {\n return isEventType(node.data.elementType) ||\n node.data.elementType.includes(\"Task\") ||\n node.data.elementType.includes(\"Gateway\") ||\n node.data.elementType.includes(\"SubProcess\")\n ? true\n : \"Only flow nodes can be dropped into pools or lanes.\";\n }\n return true;\n },\n ],\n reparent: [\n ({ node, parent }) => {\n if (!node || !parent) return true;\n if (node.data.elementType === \"BoundaryEvent\") {\n return acceptsBoundaryEvents(parent.data.elementType)\n ? true\n : \"Boundary events can only be reparented to tasks or subprocesses.\";\n }\n return true;\n },\n ],\n delete: [() => true],\n resize: [() => true],\n });\n\nexport function createBpmnNodeCommand(\n options: CreateBpmnNodeOptions,\n): DiagramCommand<BpmnRFNode, BpmnRFEdge> {\n return {\n id: `bpmn.createNode.${options.id}`,\n label: `Create ${options.elementType}`,\n execute: (state) => addNode(state, createBpmnNode(options)),\n };\n}\n\nexport function connectBpmnCommand(\n options: ConnectBpmnOptions,\n): DiagramCommand<BpmnRFNode, BpmnRFEdge> {\n return {\n id: `bpmn.connect.${options.id ?? `${options.source}-${options.target}`}`,\n label: \"Connect BPMN elements\",\n execute: (state) => {\n const edgeType = options.edgeType ?? inferBpmnEdgeType(state, options.source, options.target);\n return connectNodes(\n state,\n {\n source: options.source,\n target: options.target,\n type: edgeType,\n ...(options.sourceHandle !== undefined\n ? { sourceHandle: options.sourceHandle }\n : {}),\n ...(options.targetHandle !== undefined\n ? { targetHandle: options.targetHandle }\n : {}),\n ...(options.id ? { id: options.id } : {}),\n data: {\n edgeType,\n ...(options.label ? { label: options.label } : {}),\n ...(options.data ?? {}),\n },\n },\n bpmnConnectionValidators,\n );\n },\n };\n}\n\nexport function attachBoundaryEventCommand(\n boundaryId: string,\n hostId: string,\n): DiagramCommand<BpmnRFNode, BpmnRFEdge> {\n return {\n id: `bpmn.attachBoundary.${boundaryId}.${hostId}`,\n label: \"Attach boundary event\",\n execute: (state) => {\n const host = getNode(state, hostId);\n if (!host || !acceptsBoundaryEvents(host.data.elementType)) {\n throw new Error(`Element \"${hostId}\" cannot host boundary events.`);\n }\n const boundary = getNode(state, boundaryId);\n if (!boundary || boundary.data.elementType !== \"BoundaryEvent\") {\n throw new Error(`Element \"${boundaryId}\" is not a boundary event.`);\n }\n const reparented = reparentNode(state, boundaryId, { parentId: hostId });\n return patchNode(reparented, boundaryId, {\n data: { attachedToRef: hostId },\n });\n },\n };\n}\n\nexport function replaceBpmnNodeCommand(\n options: ReplaceBpmnNodeOptions,\n): DiagramCommand<BpmnRFNode, BpmnRFEdge> {\n return {\n id: `bpmn.replaceNode.${options.id}.${options.elementType}`,\n label: `Replace with ${options.elementType}`,\n execute: (state) => {\n const current = getNode(state, options.id);\n if (!current) throw new Error(`Element \"${options.id}\" does not exist.`);\n const meta = BPMN_ELEMENT_CATALOG[options.elementType];\n return replaceNode(state, options.id, {\n ...current,\n type: options.elementType,\n width: options.width ?? current.width ?? meta.defaultWidth,\n height: options.height ?? current.height ?? meta.defaultHeight,\n data: {\n ...current.data,\n elementType: options.elementType,\n ...(options.label ? { label: options.label } : {}),\n ...(options.data ?? {}),\n },\n });\n },\n };\n}\n\nexport function reparentBpmnNodeCommand(\n options: ReparentBpmnNodeOptions,\n): DiagramCommand<BpmnRFNode, BpmnRFEdge> {\n return {\n id: `bpmn.reparent.${options.id}.${options.parentId ?? \"root\"}`,\n label: \"Reparent BPMN element\",\n execute: (state) => {\n const node = getNode(state, options.id);\n const parent = options.parentId ? getNode(state, options.parentId) : undefined;\n if (!node) throw new Error(`Element \"${options.id}\" does not exist.`);\n if (parent && node.data.elementType === \"BoundaryEvent\" && !acceptsBoundaryEvents(parent.data.elementType)) {\n throw new Error(\"Boundary events can only be reparented to tasks or subprocesses.\");\n }\n return reparentNode(state, options.id, {\n ...(options.parentId !== undefined ? { parentId: options.parentId } : {}),\n ...(options.position ? { position: options.position } : {}),\n });\n },\n };\n}\n\nexport function resizeBpmnNodeCommand(\n options: ResizeBpmnNodeOptions,\n): DiagramCommand<BpmnRFNode, BpmnRFEdge> {\n return {\n id: `bpmn.resize.${options.id}`,\n label: \"Resize BPMN element\",\n execute: (state) => resizeNode(state, options.id, options),\n };\n}\n\nexport function deleteBpmnElementsCommand(\n ids: string[],\n): DiagramCommand<BpmnRFNode, BpmnRFEdge> {\n return {\n id: `bpmn.delete.${ids.join(\".\")}`,\n label: \"Delete BPMN elements\",\n execute: (state) => removeElements(state, ids),\n };\n}\n\nexport function copyBpmnElements(\n state: BpmnDiagramState,\n selection?: SelectionState,\n): BpmnClipboardState {\n return copyElements(state, selection);\n}\n\nexport function pasteBpmnElementsCommand(\n clipboard: BpmnClipboardState,\n options: PasteBpmnOptions = {},\n): DiagramCommand<BpmnRFNode, BpmnRFEdge> {\n return {\n id: \"bpmn.paste\",\n label: \"Paste BPMN elements\",\n execute: (state) => pasteElements(state, clipboard, options),\n };\n}\n\nexport function selectBpmnElementsCommand(\n selection: SelectionState,\n): DiagramCommand<BpmnRFNode, BpmnRFEdge> {\n return {\n id: \"bpmn.select\",\n label: \"Select BPMN elements\",\n execute: (state) => setSelection(state, createSelectionState(selection.nodeIds, selection.edgeIds)),\n };\n}\n\nexport function createBpmnDiagramDocument(\n state: BpmnDiagramState,\n options: Omit<CreateDiagramDocumentOptions, \"diagramType\"> = {},\n): BpmnDiagramDocument {\n return createDiagramDocument(normalizeDiagramState(state), {\n ...options,\n diagramType: \"bpmn\",\n });\n}\n\nexport function serializeBpmnDiagram(\n state: BpmnDiagramState,\n options: Omit<CreateDiagramDocumentOptions, \"diagramType\"> = {},\n): string {\n return serializeDiagram(normalizeDiagramState(state), {\n ...options,\n diagramType: \"bpmn\",\n });\n}\n\nexport function parseBpmnDiagramDocument(json: string): BpmnDiagramDocument {\n const document = parseDiagramDocument<BpmnRFNode, BpmnRFEdge>(json);\n if (document.diagramType && document.diagramType !== \"bpmn\") {\n throw new Error(`Expected a BPMN diagram document, received \"${document.diagramType}\".`);\n }\n return document;\n}\n\nexport function deserializeBpmnDiagram(json: string): BpmnDiagramState {\n const document = parseBpmnDiagramDocument(json);\n return deserializeDiagram<BpmnRFNode, BpmnRFEdge>(JSON.stringify(document));\n}\n\nexport function runBpmnCommand(\n stack: CommandStackState<BpmnRFNode, BpmnRFEdge>,\n command: DiagramCommand<BpmnRFNode, BpmnRFEdge>,\n): CommandStackState<BpmnRFNode, BpmnRFEdge> {\n return executeCommand(stack, command);\n}\n\nexport function runBpmnCommands(\n stack: CommandStackState<BpmnRFNode, BpmnRFEdge>,\n commands: Array<DiagramCommand<BpmnRFNode, BpmnRFEdge>>,\n options: { id?: string; label?: string } = {},\n): CommandStackState<BpmnRFNode, BpmnRFEdge> {\n return executeCommands(stack, commands, options);\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { BPMN_ELEMENT_CATALOG } from './chunk-6TUC5QX5.js';
1
+ import { BPMN_ELEMENT_CATALOG } from './chunk-DNR5WBQH.js';
2
2
  import { BpmnModdle } from 'bpmn-moddle';
3
3
 
4
4
  // src/xml/mapper.ts
@@ -23,8 +23,8 @@ var MODDLE_TO_ELEMENT_TYPE = {
23
23
  "bpmn:EventBasedGateway": "EventBasedGateway",
24
24
  "bpmn:ComplexGateway": "ComplexGateway",
25
25
  "bpmn:SubProcess": "SubProcess",
26
- "bpmn:AdHocSubProcess": "SubProcess",
27
- "bpmn:Transaction": "SubProcess",
26
+ "bpmn:AdHocSubProcess": "AdHocSubProcess",
27
+ "bpmn:Transaction": "Transaction",
28
28
  "bpmn:TextAnnotation": "Annotation",
29
29
  "bpmn:Group": "Group",
30
30
  "bpmn:DataObject": "DataObject",
@@ -62,6 +62,9 @@ var ELEMENT_TYPE_TO_MODDLE = {
62
62
  EventBasedGateway: "bpmn:EventBasedGateway",
63
63
  ComplexGateway: "bpmn:ComplexGateway",
64
64
  SubProcess: "bpmn:SubProcess",
65
+ Transaction: "bpmn:Transaction",
66
+ EventSubProcess: "bpmn:SubProcess",
67
+ AdHocSubProcess: "bpmn:AdHocSubProcess",
65
68
  Pool: "bpmn:Participant",
66
69
  Lane: "bpmn:Lane",
67
70
  Annotation: "bpmn:TextAnnotation",
@@ -126,6 +129,10 @@ function asElements(v) {
126
129
  function asString(v) {
127
130
  return typeof v === "string" && v.trim() ? v.trim() : void 0;
128
131
  }
132
+ function extractDocumentation(el) {
133
+ const [doc] = asElements(el.documentation);
134
+ return asString(doc?.text);
135
+ }
129
136
  function extractDiagramInfo(definitions) {
130
137
  const shapes = /* @__PURE__ */ new Map();
131
138
  const waypoints = /* @__PURE__ */ new Map();
@@ -181,6 +188,7 @@ function extractTrigger(el) {
181
188
  function extractSubProcessVariant(el) {
182
189
  if (el.$type === "bpmn:Transaction") return "transaction";
183
190
  if (el.$type === "bpmn:AdHocSubProcess") return "adhoc";
191
+ if (el.$type === "bpmn:SubProcess" && el.triggeredByEvent === true) return "event";
184
192
  if (el.triggeredByEvent === true) return "event";
185
193
  return "embedded";
186
194
  }
@@ -194,7 +202,7 @@ function walkFlowElements(elements, parentId, ctx, nodes, edges) {
194
202
  continue;
195
203
  }
196
204
  if ($type === "bpmn:LaneSet") continue;
197
- const elementType = MODDLE_TO_ELEMENT_TYPE[$type];
205
+ const elementType = $type === "bpmn:SubProcess" && el.triggeredByEvent === true ? "EventSubProcess" : MODDLE_TO_ELEMENT_TYPE[$type];
198
206
  if (!elementType) {
199
207
  ctx.warnings.push(`Unknown element type "${$type}" (id=${id}) \u2014 skipped.`);
200
208
  continue;
@@ -215,22 +223,26 @@ function buildNode(el, elementType, parentId, ctx, nodes) {
215
223
  const y = shape?.y ?? 100;
216
224
  if (!shape) ctx.autoX.value += (meta?.defaultWidth ?? 120) + 20;
217
225
  const label = asString(el.name);
226
+ const documentation = extractDocumentation(el);
218
227
  const trigger = extractTrigger(el);
219
228
  const isNonInterrupting = el.cancelActivity === false;
229
+ const attachedToRef = el.attachedToRef?.id;
220
230
  const data = {
221
231
  elementType,
222
232
  ...label ? { label } : {},
233
+ ...documentation ? { documentation } : {},
223
234
  ...trigger ? { trigger } : {},
224
- ...isNonInterrupting ? { isNonInterrupting: true } : {}
235
+ ...isNonInterrupting ? { isNonInterrupting: true } : {},
236
+ ...attachedToRef ? { attachedToRef } : {}
225
237
  };
226
- if (elementType === "SubProcess") {
238
+ if (elementType === "SubProcess" || elementType === "Transaction" || elementType === "EventSubProcess" || elementType === "AdHocSubProcess") {
227
239
  const variant = extractSubProcessVariant(el);
228
240
  if (variant) data.subProcessVariant = variant;
229
241
  const isExpanded = shape?.isExpanded ?? true;
230
242
  data.isExpanded = isExpanded;
231
243
  }
232
244
  const laneId = ctx.laneMembership.get(id);
233
- const effectiveParentId = laneId ?? parentId;
245
+ const effectiveParentId = attachedToRef ?? laneId ?? parentId;
234
246
  const node = {
235
247
  id,
236
248
  type: elementType,
@@ -251,10 +263,12 @@ function buildEdge(el, edgeType, ctx, edges) {
251
263
  return;
252
264
  }
253
265
  const label = asString(el.name);
266
+ const documentation = extractDocumentation(el);
254
267
  const condExpr = el.conditionExpression;
255
268
  const data = {
256
269
  edgeType,
257
270
  ...label ? { label } : {},
271
+ ...documentation ? { documentation } : {},
258
272
  ...condExpr?.body ? { conditionExpression: condExpr.body } : {}
259
273
  };
260
274
  const waypoints = ctx.waypoints.get(id);
@@ -355,7 +369,46 @@ async function parseBpmnXml(xml) {
355
369
  );
356
370
  }
357
371
  }
358
- return { nodes, edges, warnings };
372
+ const defaultFlowById = /* @__PURE__ */ new Set();
373
+ const nodeIds = new Set(nodes.map((node) => node.id));
374
+ for (const rootEl of asElements(rootElement.rootElements)) {
375
+ collectDefaultFlows(rootEl, defaultFlowById);
376
+ }
377
+ const normalizedEdges = edges.map((edge) => {
378
+ if (!defaultFlowById.has(edge.id)) return edge;
379
+ const data = {
380
+ edgeType: edge.data?.edgeType ?? edge.type,
381
+ ...edge.data ?? {},
382
+ isDefault: true
383
+ };
384
+ return { ...edge, data };
385
+ });
386
+ return {
387
+ nodes: normalizeChildPositions(nodes, nodeIds),
388
+ edges: normalizedEdges,
389
+ warnings
390
+ };
391
+ }
392
+ function collectDefaultFlows(el, defaultFlowById) {
393
+ const defaultRef = el.default;
394
+ if (defaultRef?.id) defaultFlowById.add(defaultRef.id);
395
+ for (const child of asElements(el.rootElements)) collectDefaultFlows(child, defaultFlowById);
396
+ for (const child of asElements(el.flowElements)) collectDefaultFlows(child, defaultFlowById);
397
+ }
398
+ function normalizeChildPositions(nodes, nodeIds) {
399
+ const absoluteById = new Map(nodes.map((node) => [node.id, node.position]));
400
+ return nodes.map((node) => {
401
+ if (!node.parentId || !nodeIds.has(node.parentId)) return node;
402
+ const parentPosition = absoluteById.get(node.parentId);
403
+ if (!parentPosition) return node;
404
+ return {
405
+ ...node,
406
+ position: {
407
+ x: node.position.x - parentPosition.x,
408
+ y: node.position.y - parentPosition.y
409
+ }
410
+ };
411
+ });
359
412
  }
360
413
  function uid(prefix, id) {
361
414
  return `${prefix}_${id}`;
@@ -363,19 +416,6 @@ function uid(prefix, id) {
363
416
  function asNodes(nodes, types) {
364
417
  return nodes.filter((n) => types.includes(n.data.elementType));
365
418
  }
366
- function buildFlowableAttrs(data) {
367
- const attrs = {};
368
- if (data.flowableAssignee) attrs["flowable:assignee"] = data.flowableAssignee;
369
- if (data.flowableCandidateGroups) attrs["flowable:candidateGroups"] = data.flowableCandidateGroups;
370
- if (data.flowableCandidateUsers) attrs["flowable:candidateUsers"] = data.flowableCandidateUsers;
371
- if (data.flowableFormKey) attrs["flowable:formKey"] = data.flowableFormKey;
372
- if (data.flowableDueDate) attrs["flowable:dueDate"] = data.flowableDueDate;
373
- if (data.flowableType) attrs["flowable:type"] = data.flowableType;
374
- if (data.flowableExpression) attrs["flowable:expression"] = data.flowableExpression;
375
- if (data.flowableClass) attrs["flowable:class"] = data.flowableClass;
376
- if (data.flowableDelegateExpression) attrs["flowable:delegateExpression"] = data.flowableDelegateExpression;
377
- return attrs;
378
- }
379
419
  function buildSemanticModel(moddle, nodes, edges, opts) {
380
420
  const defId = opts.id ?? "Definitions_1";
381
421
  const defName = opts.name;
@@ -434,13 +474,26 @@ function buildSemanticModel(moddle, nodes, edges, opts) {
434
474
  return definitions;
435
475
  }
436
476
  function buildProcess(moddle, allNodes, allEdges, poolId, laneNodes, processId) {
437
- const myNodes = poolId ? allNodes.filter(
477
+ const subProcessIds = new Set(
478
+ allNodes.filter(
479
+ (n) => n.data.elementType === "SubProcess" || n.data.elementType === "Transaction" || n.data.elementType === "EventSubProcess" || n.data.elementType === "AdHocSubProcess"
480
+ ).map((n) => n.id)
481
+ );
482
+ const isInsideSubProcess = (node) => {
483
+ let parentId = node.parentId;
484
+ while (parentId) {
485
+ if (subProcessIds.has(parentId)) return true;
486
+ parentId = allNodes.find((candidate) => candidate.id === parentId)?.parentId;
487
+ }
488
+ return false;
489
+ };
490
+ const myNodes = (poolId ? allNodes.filter(
438
491
  (n) => n.parentId === poolId || laneNodes.some((l) => l.id === n.parentId && l.parentId === poolId)
439
- ) : allNodes.filter((n) => n.data.elementType !== "Pool" && n.data.elementType !== "Lane");
492
+ ) : allNodes.filter((n) => n.data.elementType !== "Pool" && n.data.elementType !== "Lane")).filter((n) => !isInsideSubProcess(n));
440
493
  const myLanes = laneNodes.filter((l) => poolId ? l.parentId === poolId : true);
441
494
  const flowElements = [];
442
495
  for (const node of myNodes) {
443
- const el = buildFlowElement(moddle, node);
496
+ const el = buildFlowElement(moddle, node, allNodes, allEdges);
444
497
  if (el) flowElements.push(el);
445
498
  }
446
499
  const myNodeIds = new Set(myNodes.map((n) => n.id));
@@ -451,6 +504,17 @@ function buildProcess(moddle, allNodes, allEdges, poolId, laneNodes, processId)
451
504
  const edgeMeta = buildEdgeElement(moddle, edge);
452
505
  if (edgeMeta) flowElements.push(edgeMeta);
453
506
  }
507
+ const elementById = new Map(
508
+ flowElements.filter((element) => typeof element.id === "string").map((element) => [element.id, element])
509
+ );
510
+ for (const edge of myEdges) {
511
+ if (!edge.data?.isDefault) continue;
512
+ const sourceElement = elementById.get(edge.source);
513
+ const edgeElement = elementById.get(edge.id);
514
+ if (sourceElement && edgeElement) {
515
+ sourceElement.default = edgeElement;
516
+ }
517
+ }
454
518
  const process = moddle.create("bpmn:Process", {
455
519
  id: processId,
456
520
  isExecutable: true,
@@ -471,7 +535,7 @@ function buildProcess(moddle, allNodes, allEdges, poolId, laneNodes, processId)
471
535
  }
472
536
  return process;
473
537
  }
474
- function buildFlowElement(moddle, node, _allNodes, _allEdges) {
538
+ function buildFlowElement(moddle, node, allNodes, allEdges) {
475
539
  const { elementType, label, trigger } = node.data;
476
540
  if (elementType === "Pool" || elementType === "Lane") return null;
477
541
  const moddleType = ELEMENT_TYPE_TO_MODDLE[elementType];
@@ -480,25 +544,46 @@ function buildFlowElement(moddle, node, _allNodes, _allEdges) {
480
544
  id: node.id,
481
545
  name: label ?? ""
482
546
  };
547
+ if (node.data.documentation) {
548
+ attrs.documentation = [
549
+ moddle.create("bpmn:Documentation", { text: node.data.documentation })
550
+ ];
551
+ }
483
552
  if (trigger && trigger !== "none") {
484
553
  const defType = TRIGGER_TO_EVENT_DEF[trigger];
485
554
  if (defType) {
486
555
  attrs.eventDefinitions = [moddle.create(defType, { id: uid("EventDef", node.id) })];
487
556
  }
488
557
  }
489
- if (elementType === "SubProcess" && node.data.subProcessVariant === "transaction") {
490
- return moddle.create("bpmn:Transaction", attrs);
558
+ if (elementType === "BoundaryEvent") {
559
+ attrs.attachedToRef = { id: node.data.attachedToRef ?? node.parentId };
560
+ attrs.cancelActivity = node.data.isNonInterrupting ? false : true;
491
561
  }
492
- if (elementType === "SubProcess" && node.data.subProcessVariant === "adhoc") {
493
- return moddle.create("bpmn:AdHocSubProcess", attrs);
562
+ const isSubProcess = elementType === "SubProcess" || elementType === "Transaction" || elementType === "EventSubProcess" || elementType === "AdHocSubProcess";
563
+ if (isSubProcess) {
564
+ attrs.flowElements = buildNestedFlowElements(moddle, node, allNodes, allEdges);
565
+ if (elementType === "EventSubProcess" || node.data.subProcessVariant === "event") {
566
+ attrs.triggeredByEvent = true;
567
+ }
494
568
  }
495
569
  const element = moddle.create(moddleType, attrs);
496
- const flowableAttrs = buildFlowableAttrs(node.data);
497
- if (Object.keys(flowableAttrs).length > 0) {
498
- element.$attrs = flowableAttrs;
499
- }
500
570
  return element;
501
571
  }
572
+ function buildNestedFlowElements(moddle, parent, allNodes, allEdges) {
573
+ const childNodes = allNodes.filter((node) => node.parentId === parent.id);
574
+ const childNodeIds = new Set(childNodes.map((node) => node.id));
575
+ const flowElements = [];
576
+ for (const child of childNodes) {
577
+ const element = buildFlowElement(moddle, child, allNodes, allEdges);
578
+ if (element) flowElements.push(element);
579
+ }
580
+ for (const edge of allEdges) {
581
+ if (!childNodeIds.has(edge.source) || !childNodeIds.has(edge.target)) continue;
582
+ const element = buildEdgeElement(moddle, edge);
583
+ if (element) flowElements.push(element);
584
+ }
585
+ return flowElements;
586
+ }
502
587
  function buildEdgeElement(moddle, edge) {
503
588
  if (!edge.data) return null;
504
589
  const moddleType = EDGE_TYPE_TO_MODDLE[edge.data.edgeType];
@@ -509,6 +594,11 @@ function buildEdgeElement(moddle, edge) {
509
594
  sourceRef: { id: edge.source },
510
595
  targetRef: { id: edge.target }
511
596
  };
597
+ if (edge.data.documentation) {
598
+ attrs.documentation = [
599
+ moddle.create("bpmn:Documentation", { text: edge.data.documentation })
600
+ ];
601
+ }
512
602
  if (edge.data.conditionExpression) {
513
603
  attrs.conditionExpression = moddle.create("bpmn:FormalExpression", {
514
604
  body: edge.data.conditionExpression
@@ -519,13 +609,14 @@ function buildEdgeElement(moddle, edge) {
519
609
  function buildBpmnDI(moddle, definitions, nodes, edges) {
520
610
  const shapes = [];
521
611
  const edgeShapes = [];
612
+ const absolutePositionById = buildAbsolutePositionMap(nodes);
522
613
  for (const node of nodes) {
523
614
  const meta = BPMN_ELEMENT_CATALOG[node.data.elementType];
524
615
  const w = node.width ?? meta?.defaultWidth ?? 120;
525
616
  const h = node.height ?? meta?.defaultHeight ?? 60;
526
617
  const bounds = moddle.create("dc:Bounds", {
527
- x: node.position.x,
528
- y: node.position.y,
618
+ x: absolutePositionById.get(node.id)?.x ?? node.position.x,
619
+ y: absolutePositionById.get(node.id)?.y ?? node.position.y,
529
620
  width: w,
530
621
  height: h
531
622
  });
@@ -564,6 +655,24 @@ function buildBpmnDI(moddle, definitions, nodes, edges) {
564
655
  });
565
656
  definitions.diagrams = [diagram];
566
657
  }
658
+ function buildAbsolutePositionMap(nodes) {
659
+ const nodeById = new Map(nodes.map((node) => [node.id, node]));
660
+ const absoluteById = /* @__PURE__ */ new Map();
661
+ function resolve(node) {
662
+ const cached = absoluteById.get(node.id);
663
+ if (cached) return cached;
664
+ const parent = node.parentId ? nodeById.get(node.parentId) : void 0;
665
+ const parentPosition = parent ? resolve(parent) : { x: 0, y: 0 };
666
+ const absolute = {
667
+ x: parentPosition.x + node.position.x,
668
+ y: parentPosition.y + node.position.y
669
+ };
670
+ absoluteById.set(node.id, absolute);
671
+ return absolute;
672
+ }
673
+ for (const node of nodes) resolve(node);
674
+ return absoluteById;
675
+ }
567
676
  async function serializeBpmnXml(nodes, edges, opts = {}) {
568
677
  const moddle = new BpmnModdle();
569
678
  const definitions = buildSemanticModel(moddle, nodes, edges, opts);
@@ -575,5 +684,5 @@ async function serializeBpmnXml(nodes, edges, opts = {}) {
575
684
  }
576
685
 
577
686
  export { parseBpmnXml, serializeBpmnXml };
578
- //# sourceMappingURL=chunk-4OAEWYYU.js.map
579
- //# sourceMappingURL=chunk-4OAEWYYU.js.map
687
+ //# sourceMappingURL=chunk-MF2WE3OM.js.map
688
+ //# sourceMappingURL=chunk-MF2WE3OM.js.map