@aranzatech/diagrams-bpmn 0.2.8 → 0.2.9

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.
@@ -0,0 +1,881 @@
1
+ 'use strict';
2
+
3
+ var layout = require('@aranzatech/diagrams-core/layout');
4
+ var diagramsCore = require('@aranzatech/diagrams-core');
5
+ require('@aranzatech/diagrams-core/serialization');
6
+
7
+ // src/layout/index.ts
8
+
9
+ // src/elements/catalog.ts
10
+ var BPMN_ELEMENT_CATALOG = {
11
+ // ─── Events ──────────────────────────────────────────────────────────────────
12
+ StartEvent: {
13
+ label: "Start Event",
14
+ icon: "Circle",
15
+ category: "event",
16
+ defaultWidth: 36,
17
+ defaultHeight: 36,
18
+ handlePolicy: "source",
19
+ orientation: "free",
20
+ isContainer: false,
21
+ acceptsBoundaryEvents: false,
22
+ eventSemantics: "start",
23
+ canBeStart: true,
24
+ canBeEnd: false,
25
+ maxIncoming: 0,
26
+ maxOutgoing: 1
27
+ },
28
+ EndEvent: {
29
+ label: "End Event",
30
+ icon: "CircleDot",
31
+ category: "event",
32
+ defaultWidth: 36,
33
+ defaultHeight: 36,
34
+ handlePolicy: "target",
35
+ orientation: "free",
36
+ isContainer: false,
37
+ acceptsBoundaryEvents: false,
38
+ eventSemantics: "end",
39
+ canBeStart: false,
40
+ canBeEnd: true,
41
+ maxOutgoing: 0
42
+ },
43
+ IntermediateCatchEvent: {
44
+ label: "Intermediate Catch Event",
45
+ icon: "Clock3",
46
+ category: "event",
47
+ defaultWidth: 36,
48
+ defaultHeight: 36,
49
+ handlePolicy: "all",
50
+ orientation: "free",
51
+ isContainer: false,
52
+ acceptsBoundaryEvents: false,
53
+ eventSemantics: "intermediateCatch",
54
+ canBeStart: false,
55
+ canBeEnd: false
56
+ },
57
+ IntermediateThrowEvent: {
58
+ label: "Intermediate Throw Event",
59
+ icon: "Send",
60
+ category: "event",
61
+ defaultWidth: 36,
62
+ defaultHeight: 36,
63
+ handlePolicy: "all",
64
+ orientation: "free",
65
+ isContainer: false,
66
+ acceptsBoundaryEvents: false,
67
+ eventSemantics: "intermediateThrow",
68
+ canBeStart: false,
69
+ canBeEnd: false
70
+ },
71
+ BoundaryEvent: {
72
+ label: "Boundary Event",
73
+ icon: "AlarmClock",
74
+ category: "event",
75
+ defaultWidth: 36,
76
+ defaultHeight: 36,
77
+ handlePolicy: "source",
78
+ orientation: "free",
79
+ isContainer: false,
80
+ acceptsBoundaryEvents: false,
81
+ eventSemantics: "boundary",
82
+ canBeStart: false,
83
+ canBeEnd: false,
84
+ maxIncoming: 0
85
+ },
86
+ // ─── Tasks ───────────────────────────────────────────────────────────────────
87
+ Task: {
88
+ label: "Task",
89
+ icon: "CheckSquare",
90
+ category: "task",
91
+ defaultWidth: 120,
92
+ defaultHeight: 60,
93
+ handlePolicy: "all",
94
+ orientation: "free",
95
+ isContainer: false,
96
+ acceptsBoundaryEvents: true,
97
+ supportsMarkers: true,
98
+ canBeStart: false,
99
+ canBeEnd: false
100
+ },
101
+ UserTask: {
102
+ label: "User Task",
103
+ icon: "UserRound",
104
+ category: "task",
105
+ defaultWidth: 120,
106
+ defaultHeight: 60,
107
+ handlePolicy: "all",
108
+ orientation: "free",
109
+ isContainer: false,
110
+ acceptsBoundaryEvents: true,
111
+ supportsMarkers: true,
112
+ canBeStart: false,
113
+ canBeEnd: false
114
+ },
115
+ ServiceTask: {
116
+ label: "Service Task",
117
+ icon: "Cog",
118
+ category: "task",
119
+ defaultWidth: 120,
120
+ defaultHeight: 60,
121
+ handlePolicy: "all",
122
+ orientation: "free",
123
+ isContainer: false,
124
+ acceptsBoundaryEvents: true,
125
+ supportsMarkers: true,
126
+ canBeStart: false,
127
+ canBeEnd: false
128
+ },
129
+ ScriptTask: {
130
+ label: "Script Task",
131
+ icon: "FileCode",
132
+ category: "task",
133
+ defaultWidth: 120,
134
+ defaultHeight: 60,
135
+ handlePolicy: "all",
136
+ orientation: "free",
137
+ isContainer: false,
138
+ acceptsBoundaryEvents: true,
139
+ supportsMarkers: true,
140
+ canBeStart: false,
141
+ canBeEnd: false
142
+ },
143
+ ManualTask: {
144
+ label: "Manual Task",
145
+ icon: "Hand",
146
+ category: "task",
147
+ defaultWidth: 120,
148
+ defaultHeight: 60,
149
+ handlePolicy: "all",
150
+ orientation: "free",
151
+ isContainer: false,
152
+ acceptsBoundaryEvents: true,
153
+ supportsMarkers: true,
154
+ canBeStart: false,
155
+ canBeEnd: false
156
+ },
157
+ BusinessRuleTask: {
158
+ label: "Business Rule Task",
159
+ icon: "Table2",
160
+ category: "task",
161
+ defaultWidth: 120,
162
+ defaultHeight: 60,
163
+ handlePolicy: "all",
164
+ orientation: "free",
165
+ isContainer: false,
166
+ acceptsBoundaryEvents: true,
167
+ supportsMarkers: true,
168
+ canBeStart: false,
169
+ canBeEnd: false
170
+ },
171
+ ReceiveTask: {
172
+ label: "Receive Task",
173
+ icon: "Inbox",
174
+ category: "task",
175
+ defaultWidth: 120,
176
+ defaultHeight: 60,
177
+ handlePolicy: "all",
178
+ orientation: "free",
179
+ isContainer: false,
180
+ acceptsBoundaryEvents: true,
181
+ supportsMarkers: true,
182
+ canBeStart: false,
183
+ canBeEnd: false
184
+ },
185
+ SendTask: {
186
+ label: "Send Task",
187
+ icon: "Send",
188
+ category: "task",
189
+ defaultWidth: 120,
190
+ defaultHeight: 60,
191
+ handlePolicy: "all",
192
+ orientation: "free",
193
+ isContainer: false,
194
+ acceptsBoundaryEvents: true,
195
+ supportsMarkers: true,
196
+ canBeStart: false,
197
+ canBeEnd: false
198
+ },
199
+ CallActivity: {
200
+ label: "Call Activity",
201
+ icon: "ExternalLink",
202
+ category: "task",
203
+ defaultWidth: 120,
204
+ defaultHeight: 60,
205
+ handlePolicy: "all",
206
+ orientation: "free",
207
+ isContainer: false,
208
+ acceptsBoundaryEvents: true,
209
+ supportsMarkers: true,
210
+ canBeStart: false,
211
+ canBeEnd: false
212
+ },
213
+ // ─── Gateways ────────────────────────────────────────────────────────────────
214
+ ExclusiveGateway: {
215
+ label: "Exclusive Gateway",
216
+ icon: "X",
217
+ category: "gateway",
218
+ defaultWidth: 50,
219
+ defaultHeight: 50,
220
+ handlePolicy: "all",
221
+ orientation: "free",
222
+ isContainer: false,
223
+ acceptsBoundaryEvents: false,
224
+ canBeStart: false,
225
+ canBeEnd: false
226
+ },
227
+ InclusiveGateway: {
228
+ label: "Inclusive Gateway",
229
+ icon: "Circle",
230
+ category: "gateway",
231
+ defaultWidth: 50,
232
+ defaultHeight: 50,
233
+ handlePolicy: "all",
234
+ orientation: "free",
235
+ isContainer: false,
236
+ acceptsBoundaryEvents: false,
237
+ canBeStart: false,
238
+ canBeEnd: false
239
+ },
240
+ ParallelGateway: {
241
+ label: "Parallel Gateway",
242
+ icon: "Plus",
243
+ category: "gateway",
244
+ defaultWidth: 50,
245
+ defaultHeight: 50,
246
+ handlePolicy: "all",
247
+ orientation: "free",
248
+ isContainer: false,
249
+ acceptsBoundaryEvents: false,
250
+ canBeStart: false,
251
+ canBeEnd: false
252
+ },
253
+ EventBasedGateway: {
254
+ label: "Event-Based Gateway",
255
+ icon: "Radio",
256
+ category: "gateway",
257
+ defaultWidth: 50,
258
+ defaultHeight: 50,
259
+ handlePolicy: "all",
260
+ orientation: "free",
261
+ isContainer: false,
262
+ acceptsBoundaryEvents: false,
263
+ canBeStart: false,
264
+ canBeEnd: false,
265
+ maxIncoming: 1
266
+ },
267
+ ComplexGateway: {
268
+ label: "Complex Gateway",
269
+ icon: "Asterisk",
270
+ category: "gateway",
271
+ defaultWidth: 50,
272
+ defaultHeight: 50,
273
+ handlePolicy: "all",
274
+ orientation: "free",
275
+ isContainer: false,
276
+ acceptsBoundaryEvents: false,
277
+ canBeStart: false,
278
+ canBeEnd: false
279
+ },
280
+ // ─── Containers ───────────────────────────────────────────────────────────────
281
+ SubProcess: {
282
+ label: "Sub-Process",
283
+ icon: "PlusSquare",
284
+ category: "container",
285
+ defaultWidth: 350,
286
+ defaultHeight: 200,
287
+ handlePolicy: "all",
288
+ orientation: "horizontal",
289
+ isContainer: true,
290
+ acceptsBoundaryEvents: true,
291
+ supportsCollapse: true,
292
+ supportsMarkers: true,
293
+ canBeStart: false,
294
+ canBeEnd: false
295
+ },
296
+ Transaction: {
297
+ label: "Transaction",
298
+ icon: "Receipt",
299
+ category: "container",
300
+ defaultWidth: 350,
301
+ defaultHeight: 200,
302
+ handlePolicy: "all",
303
+ orientation: "horizontal",
304
+ isContainer: true,
305
+ acceptsBoundaryEvents: true,
306
+ supportsCollapse: true,
307
+ supportsMarkers: true,
308
+ canBeStart: false,
309
+ canBeEnd: false
310
+ },
311
+ EventSubProcess: {
312
+ label: "Event Sub-Process",
313
+ icon: "CircleDotDashed",
314
+ category: "container",
315
+ defaultWidth: 350,
316
+ defaultHeight: 200,
317
+ handlePolicy: "all",
318
+ orientation: "horizontal",
319
+ isContainer: true,
320
+ acceptsBoundaryEvents: false,
321
+ supportsCollapse: true,
322
+ supportsMarkers: true,
323
+ canBeStart: false,
324
+ canBeEnd: false
325
+ },
326
+ AdHocSubProcess: {
327
+ label: "Ad-Hoc Sub-Process",
328
+ icon: "Waves",
329
+ category: "container",
330
+ defaultWidth: 350,
331
+ defaultHeight: 200,
332
+ handlePolicy: "all",
333
+ orientation: "horizontal",
334
+ isContainer: true,
335
+ acceptsBoundaryEvents: true,
336
+ supportsCollapse: true,
337
+ supportsMarkers: true,
338
+ canBeStart: false,
339
+ canBeEnd: false
340
+ },
341
+ Pool: {
342
+ label: "Pool",
343
+ icon: "Rows3",
344
+ category: "container",
345
+ defaultWidth: 600,
346
+ defaultHeight: 200,
347
+ handlePolicy: "none",
348
+ orientation: "horizontal",
349
+ isContainer: true,
350
+ acceptsBoundaryEvents: false,
351
+ canBeStart: false,
352
+ canBeEnd: false,
353
+ maxIncoming: 0,
354
+ maxOutgoing: 0
355
+ },
356
+ Lane: {
357
+ label: "Lane",
358
+ icon: "PanelTop",
359
+ category: "container",
360
+ defaultWidth: 600,
361
+ defaultHeight: 120,
362
+ handlePolicy: "none",
363
+ orientation: "horizontal",
364
+ isContainer: true,
365
+ acceptsBoundaryEvents: false,
366
+ canBeStart: false,
367
+ canBeEnd: false,
368
+ maxIncoming: 0,
369
+ maxOutgoing: 0
370
+ },
371
+ // ─── Artifacts ────────────────────────────────────────────────────────────────
372
+ Annotation: {
373
+ label: "Text Annotation",
374
+ icon: "StickyNote",
375
+ category: "artifact",
376
+ defaultWidth: 100,
377
+ defaultHeight: 60,
378
+ handlePolicy: "none",
379
+ orientation: "free",
380
+ isContainer: false,
381
+ acceptsBoundaryEvents: false,
382
+ canBeStart: false,
383
+ canBeEnd: false,
384
+ maxIncoming: 0,
385
+ maxOutgoing: 0
386
+ },
387
+ Group: {
388
+ label: "Group",
389
+ icon: "Group",
390
+ category: "artifact",
391
+ defaultWidth: 300,
392
+ defaultHeight: 200,
393
+ handlePolicy: "none",
394
+ orientation: "free",
395
+ isContainer: false,
396
+ acceptsBoundaryEvents: false,
397
+ canBeStart: false,
398
+ canBeEnd: false,
399
+ maxIncoming: 0,
400
+ maxOutgoing: 0
401
+ },
402
+ // ─── Data (BPMN 2.0 §10.3) ───────────────────────────────────────────────────
403
+ DataObject: {
404
+ label: "Data Object",
405
+ icon: "File",
406
+ category: "data",
407
+ defaultWidth: 36,
408
+ defaultHeight: 50,
409
+ handlePolicy: "all",
410
+ orientation: "free",
411
+ isContainer: false,
412
+ acceptsBoundaryEvents: false,
413
+ canBeStart: false,
414
+ canBeEnd: false,
415
+ maxIncoming: 0,
416
+ maxOutgoing: 0
417
+ },
418
+ DataObjectReference: {
419
+ label: "Data Object Reference",
420
+ icon: "FileSymlink",
421
+ category: "data",
422
+ defaultWidth: 36,
423
+ defaultHeight: 50,
424
+ handlePolicy: "all",
425
+ orientation: "free",
426
+ isContainer: false,
427
+ acceptsBoundaryEvents: false,
428
+ canBeStart: false,
429
+ canBeEnd: false,
430
+ maxIncoming: 0,
431
+ maxOutgoing: 0
432
+ },
433
+ DataInput: {
434
+ label: "Data Input",
435
+ icon: "FileInput",
436
+ category: "data",
437
+ defaultWidth: 36,
438
+ defaultHeight: 50,
439
+ handlePolicy: "all",
440
+ orientation: "free",
441
+ isContainer: false,
442
+ acceptsBoundaryEvents: false,
443
+ canBeStart: false,
444
+ canBeEnd: false,
445
+ maxIncoming: 0
446
+ },
447
+ DataOutput: {
448
+ label: "Data Output",
449
+ icon: "FileOutput",
450
+ category: "data",
451
+ defaultWidth: 36,
452
+ defaultHeight: 50,
453
+ handlePolicy: "all",
454
+ orientation: "free",
455
+ isContainer: false,
456
+ acceptsBoundaryEvents: false,
457
+ canBeStart: false,
458
+ canBeEnd: false,
459
+ maxOutgoing: 0
460
+ },
461
+ DataStore: {
462
+ label: "Data Store",
463
+ icon: "Database",
464
+ category: "data",
465
+ defaultWidth: 50,
466
+ defaultHeight: 50,
467
+ handlePolicy: "all",
468
+ orientation: "free",
469
+ isContainer: false,
470
+ acceptsBoundaryEvents: false,
471
+ canBeStart: false,
472
+ canBeEnd: false,
473
+ maxIncoming: 0,
474
+ maxOutgoing: 0
475
+ },
476
+ DataStoreReference: {
477
+ label: "Data Store Reference",
478
+ icon: "DatabaseZap",
479
+ category: "data",
480
+ defaultWidth: 50,
481
+ defaultHeight: 50,
482
+ handlePolicy: "all",
483
+ orientation: "free",
484
+ isContainer: false,
485
+ acceptsBoundaryEvents: false,
486
+ canBeStart: false,
487
+ canBeEnd: false,
488
+ maxIncoming: 0,
489
+ maxOutgoing: 0
490
+ },
491
+ // ─── Conversation (BPMN 2.0 §12) ─────────────────────────────────────────────
492
+ Conversation: {
493
+ label: "Conversation",
494
+ icon: "MessageCircle",
495
+ category: "conversation",
496
+ defaultWidth: 60,
497
+ defaultHeight: 52,
498
+ handlePolicy: "all",
499
+ orientation: "free",
500
+ isContainer: false,
501
+ acceptsBoundaryEvents: false,
502
+ canBeStart: false,
503
+ canBeEnd: false
504
+ },
505
+ SubConversation: {
506
+ label: "Sub-Conversation",
507
+ icon: "MessagesSquare",
508
+ category: "conversation",
509
+ defaultWidth: 60,
510
+ defaultHeight: 52,
511
+ handlePolicy: "all",
512
+ orientation: "free",
513
+ isContainer: true,
514
+ acceptsBoundaryEvents: false,
515
+ supportsCollapse: true,
516
+ canBeStart: false,
517
+ canBeEnd: false
518
+ },
519
+ CallConversation: {
520
+ label: "Call Conversation",
521
+ icon: "PhoneCall",
522
+ category: "conversation",
523
+ defaultWidth: 60,
524
+ defaultHeight: 52,
525
+ handlePolicy: "all",
526
+ orientation: "free",
527
+ isContainer: false,
528
+ acceptsBoundaryEvents: false,
529
+ canBeStart: false,
530
+ canBeEnd: false
531
+ },
532
+ // ─── Choreography (BPMN 2.0 §11) ─────────────────────────────────────────────
533
+ ChoreographyTask: {
534
+ label: "Choreography Task",
535
+ icon: "ArrowLeftRight",
536
+ category: "choreography",
537
+ defaultWidth: 120,
538
+ defaultHeight: 80,
539
+ handlePolicy: "all",
540
+ orientation: "horizontal",
541
+ isContainer: false,
542
+ acceptsBoundaryEvents: false,
543
+ canBeStart: false,
544
+ canBeEnd: false
545
+ },
546
+ SubChoreography: {
547
+ label: "Sub-Choreography",
548
+ icon: "BoxSelect",
549
+ category: "choreography",
550
+ defaultWidth: 120,
551
+ defaultHeight: 80,
552
+ handlePolicy: "all",
553
+ orientation: "horizontal",
554
+ isContainer: true,
555
+ acceptsBoundaryEvents: false,
556
+ supportsCollapse: true,
557
+ canBeStart: false,
558
+ canBeEnd: false
559
+ },
560
+ CallChoreography: {
561
+ label: "Call Choreography",
562
+ icon: "Phone",
563
+ category: "choreography",
564
+ defaultWidth: 120,
565
+ defaultHeight: 80,
566
+ handlePolicy: "all",
567
+ orientation: "horizontal",
568
+ isContainer: false,
569
+ acceptsBoundaryEvents: false,
570
+ canBeStart: false,
571
+ canBeEnd: false
572
+ }
573
+ };
574
+ function getElementMeta(type) {
575
+ return BPMN_ELEMENT_CATALOG[type];
576
+ }
577
+ var BPMN_RESIZABLE_ELEMENT_TYPES = [
578
+ "Task",
579
+ "UserTask",
580
+ "ServiceTask",
581
+ "ScriptTask",
582
+ "ManualTask",
583
+ "BusinessRuleTask",
584
+ "ReceiveTask",
585
+ "SendTask",
586
+ "CallActivity",
587
+ "SubProcess",
588
+ "Transaction",
589
+ "EventSubProcess",
590
+ "AdHocSubProcess",
591
+ "Pool",
592
+ "Lane",
593
+ "Annotation",
594
+ "Group",
595
+ "SubConversation",
596
+ "ChoreographyTask",
597
+ "SubChoreography",
598
+ "CallChoreography"
599
+ ];
600
+ var BPMN_MIN_SIZE_OVERRIDES = {
601
+ Task: { minWidth: 80, minHeight: 48 },
602
+ UserTask: { minWidth: 80, minHeight: 48 },
603
+ ServiceTask: { minWidth: 80, minHeight: 48 },
604
+ ScriptTask: { minWidth: 80, minHeight: 48 },
605
+ ManualTask: { minWidth: 80, minHeight: 48 },
606
+ BusinessRuleTask: { minWidth: 80, minHeight: 48 },
607
+ ReceiveTask: { minWidth: 80, minHeight: 48 },
608
+ SendTask: { minWidth: 80, minHeight: 48 },
609
+ CallActivity: { minWidth: 80, minHeight: 48 },
610
+ SubProcess: { minWidth: 160, minHeight: 100 },
611
+ Transaction: { minWidth: 160, minHeight: 100 },
612
+ EventSubProcess: { minWidth: 160, minHeight: 100 },
613
+ AdHocSubProcess: { minWidth: 160, minHeight: 100 },
614
+ Pool: { minWidth: 240, minHeight: 120 },
615
+ Lane: { minWidth: 240, minHeight: 80 },
616
+ Annotation: { minWidth: 80, minHeight: 40 },
617
+ Group: { minWidth: 120, minHeight: 80 },
618
+ SubConversation: { minWidth: 60, minHeight: 52 },
619
+ ChoreographyTask: { minWidth: 100, minHeight: 70 },
620
+ SubChoreography: { minWidth: 100, minHeight: 70 },
621
+ CallChoreography: { minWidth: 100, minHeight: 70 }
622
+ };
623
+ var resizableTypes = new Set(BPMN_RESIZABLE_ELEMENT_TYPES);
624
+ function isBpmnElementResizable(type) {
625
+ return resizableTypes.has(type);
626
+ }
627
+ function getBpmnElementSize(type) {
628
+ const meta = getElementMeta(type);
629
+ const min = BPMN_MIN_SIZE_OVERRIDES[type];
630
+ return {
631
+ width: meta.defaultWidth,
632
+ height: meta.defaultHeight,
633
+ minWidth: meta.minWidth ?? min?.minWidth ?? meta.defaultWidth,
634
+ minHeight: meta.minHeight ?? min?.minHeight ?? meta.defaultHeight,
635
+ resizable: meta.resizable ?? isBpmnElementResizable(type)
636
+ };
637
+ }
638
+
639
+ // src/elements/guards.ts
640
+ var GATEWAY_TYPES = /* @__PURE__ */ new Set([
641
+ "ExclusiveGateway",
642
+ "InclusiveGateway",
643
+ "ParallelGateway",
644
+ "EventBasedGateway",
645
+ "ComplexGateway"
646
+ ]);
647
+ var EVENT_TYPES = /* @__PURE__ */ new Set([
648
+ "StartEvent",
649
+ "EndEvent",
650
+ "IntermediateCatchEvent",
651
+ "IntermediateThrowEvent",
652
+ "BoundaryEvent"
653
+ ]);
654
+ var DATA_TYPES = /* @__PURE__ */ new Set([
655
+ "DataObject",
656
+ "DataObjectReference",
657
+ "DataInput",
658
+ "DataOutput",
659
+ "DataStore",
660
+ "DataStoreReference"
661
+ ]);
662
+ function isGatewayType(type) {
663
+ return GATEWAY_TYPES.has(type);
664
+ }
665
+ function isEventType(type) {
666
+ return EVENT_TYPES.has(type);
667
+ }
668
+ function isDataType(type) {
669
+ return DATA_TYPES.has(type);
670
+ }
671
+ function acceptsBoundaryEvents(type) {
672
+ return BPMN_ELEMENT_CATALOG[type].acceptsBoundaryEvents;
673
+ }
674
+ function getHandlePolicy(type) {
675
+ return BPMN_ELEMENT_CATALOG[type].handlePolicy;
676
+ }
677
+
678
+ // src/modeling/index.ts
679
+ var BPMN_EDGE_CONNECTION_RULES = {
680
+ sequenceFlow: {
681
+ edgeType: "sequenceFlow",
682
+ sourceCategories: ["flowNode"],
683
+ targetCategories: ["flowNode"],
684
+ allowSameParent: true,
685
+ allowDifferentParent: false
686
+ },
687
+ messageFlow: {
688
+ edgeType: "messageFlow",
689
+ sourceCategories: ["flowNode"],
690
+ targetCategories: ["flowNode"],
691
+ allowSameParent: false,
692
+ allowDifferentParent: true
693
+ },
694
+ association: {
695
+ edgeType: "association",
696
+ sourceCategories: ["flowNode", "artifact", "data"],
697
+ targetCategories: ["flowNode", "artifact", "data"],
698
+ allowSameParent: true,
699
+ allowDifferentParent: true
700
+ },
701
+ dataAssociation: {
702
+ edgeType: "dataAssociation",
703
+ sourceCategories: ["flowNode", "data"],
704
+ targetCategories: ["flowNode", "data"],
705
+ allowSameParent: true,
706
+ allowDifferentParent: true
707
+ },
708
+ conversationLink: {
709
+ edgeType: "conversationLink",
710
+ sourceCategories: ["conversation", "flowNode"],
711
+ targetCategories: ["conversation", "flowNode"],
712
+ allowSameParent: true,
713
+ allowDifferentParent: true
714
+ }
715
+ };
716
+ function inferBpmnEdgeType(state, sourceId, targetId) {
717
+ const source = diagramsCore.getNode(state, sourceId);
718
+ const target = diagramsCore.getNode(state, targetId);
719
+ if (!source || !target) return "sequenceFlow";
720
+ if (isDataType(source.data.elementType) || isDataType(target.data.elementType)) {
721
+ return "dataAssociation";
722
+ }
723
+ if (source.data.elementType === "Annotation" || target.data.elementType === "Annotation" || source.data.elementType === "Group" || target.data.elementType === "Group") {
724
+ return "association";
725
+ }
726
+ 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") {
727
+ return "conversationLink";
728
+ }
729
+ if (source.parentId && target.parentId && source.parentId !== target.parentId) {
730
+ return "messageFlow";
731
+ }
732
+ return "sequenceFlow";
733
+ }
734
+ function canUseSequenceFlow(type) {
735
+ const meta = BPMN_ELEMENT_CATALOG[type];
736
+ return meta.handlePolicy !== "none" && !isDataType(type) && type !== "Annotation" && type !== "Group" && meta.category !== "conversation";
737
+ }
738
+ function matchesConnectionCategory(type, categories) {
739
+ return categories.some((category) => {
740
+ if (category === type) return true;
741
+ if (category === "flowNode") return canUseSequenceFlow(type);
742
+ if (category === "data") return isDataType(type);
743
+ if (category === "artifact") return type === "Annotation" || type === "Group";
744
+ if (category === "conversation") return BPMN_ELEMENT_CATALOG[type].category === "conversation";
745
+ return false;
746
+ });
747
+ }
748
+ function isBpmnProcessNode(type) {
749
+ return isEventType(type) || isGatewayType(type) || type.includes("Task") || type === "CallActivity" || type === "SubProcess" || type === "Transaction" || type === "EventSubProcess" || type === "AdHocSubProcess";
750
+ }
751
+ function isBpmnDroppableInContainer(type) {
752
+ return isBpmnProcessNode(type) || type === "Annotation" || type === "Group" || type === "DataObject" || type === "DataObjectReference" || type === "DataStore" || type === "DataStoreReference";
753
+ }
754
+ function canContainBpmnElement(parentType, childType) {
755
+ if (!parentType) return true;
756
+ if (parentType === "Pool") {
757
+ return childType === "Lane" || isBpmnDroppableInContainer(childType) ? true : "Pools can contain lanes, BPMN process nodes, annotations, groups, and data elements.";
758
+ }
759
+ if (parentType === "Lane") {
760
+ return isBpmnDroppableInContainer(childType) ? true : "Lanes can only contain BPMN process nodes, annotations, groups, and data elements.";
761
+ }
762
+ if (parentType === "SubProcess" || parentType === "Transaction" || parentType === "EventSubProcess" || parentType === "AdHocSubProcess") {
763
+ return isBpmnProcessNode(childType) ? true : "Subprocesses can only contain BPMN process nodes.";
764
+ }
765
+ return `${parentType} cannot contain BPMN child elements.`;
766
+ }
767
+ function getBpmnNodeSize(node) {
768
+ return diagramsCore.getNodeSize(node, getBpmnElementSize(node.data.elementType));
769
+ }
770
+ function validateBpmnConnectionForEdgeType(state, edgeType, source, target) {
771
+ const rule = BPMN_EDGE_CONNECTION_RULES[edgeType];
772
+ if (!matchesConnectionCategory(source.data.elementType, rule.sourceCategories)) {
773
+ return `${edgeType} cannot start from ${source.data.elementType}.`;
774
+ }
775
+ if (!matchesConnectionCategory(target.data.elementType, rule.targetCategories)) {
776
+ return `${edgeType} cannot target ${target.data.elementType}.`;
777
+ }
778
+ const sameParent = (source.parentId ?? null) === (target.parentId ?? null);
779
+ if (sameParent && rule.allowSameParent === false) {
780
+ return `${edgeType} must connect BPMN elements in different participants/scopes.`;
781
+ }
782
+ if (!sameParent && rule.allowDifferentParent === false) {
783
+ return `${edgeType} must stay inside the same BPMN participant/scope.`;
784
+ }
785
+ if (edgeType === "sequenceFlow") {
786
+ if (source.data.elementType === "EndEvent") return "End events cannot have outgoing sequence flows.";
787
+ if (target.data.elementType === "StartEvent") return "Start events cannot have incoming sequence flows.";
788
+ return validateEdgeCardinality(state, edgeType, source, target);
789
+ }
790
+ return true;
791
+ }
792
+ function validateEdgeCardinality(state, edgeType, source, target) {
793
+ if (edgeType !== "sequenceFlow") return true;
794
+ const sourceMax = BPMN_ELEMENT_CATALOG[source.data.elementType].maxOutgoing;
795
+ const targetMax = BPMN_ELEMENT_CATALOG[target.data.elementType].maxIncoming;
796
+ const outgoing = diagramsCore.getOutgoingEdges(state, source.id).filter(
797
+ (edge) => edge.data?.edgeType === "sequenceFlow"
798
+ );
799
+ const incoming = diagramsCore.getIncomingEdges(state, target.id).filter(
800
+ (edge) => edge.data?.edgeType === "sequenceFlow"
801
+ );
802
+ if (sourceMax !== void 0 && outgoing.length >= sourceMax) {
803
+ return `${source.data.elementType} cannot have more than ${sourceMax} outgoing sequence flow(s).`;
804
+ }
805
+ if (targetMax !== void 0 && incoming.length >= targetMax) {
806
+ return `${target.data.elementType} cannot have more than ${targetMax} incoming sequence flow(s).`;
807
+ }
808
+ return true;
809
+ }
810
+ var bpmnConnectionValidators = [
811
+ ({ state, source, target }) => {
812
+ if (source.id === target.id) return "BPMN self-connections are not allowed.";
813
+ const edgeType = inferBpmnEdgeType(state, source.id, target.id);
814
+ if (getHandlePolicy(source.data.elementType) === "none" || getHandlePolicy(target.data.elementType) === "none") {
815
+ return "Elements without BPMN connection handles cannot be directly connected.";
816
+ }
817
+ if (edgeType === "sequenceFlow") {
818
+ return validateBpmnConnectionForEdgeType(state, edgeType, source, target);
819
+ }
820
+ return validateBpmnConnectionForEdgeType(state, edgeType, source, target);
821
+ }
822
+ ];
823
+ diagramsCore.createModelingRules({
824
+ connect: [
825
+ ({ state, source, target }) => {
826
+ if (!source || !target) return false;
827
+ for (const validator of bpmnConnectionValidators) {
828
+ const result = validator({
829
+ state,
830
+ source,
831
+ target,
832
+ existingEdges: state.edges
833
+ });
834
+ if (result !== true) return result;
835
+ }
836
+ return true;
837
+ }
838
+ ],
839
+ drop: [
840
+ ({ node, parent }) => {
841
+ if (!node || !parent) return true;
842
+ if (node.data.elementType === "BoundaryEvent") {
843
+ return acceptsBoundaryEvents(parent.data.elementType) ? true : "Boundary events can only be attached to tasks or subprocesses.";
844
+ }
845
+ return canContainBpmnElement(parent.data.elementType, node.data.elementType);
846
+ }
847
+ ],
848
+ reparent: [
849
+ ({ node, parent }) => {
850
+ if (!node || !parent) return true;
851
+ if (node.data.elementType === "BoundaryEvent") {
852
+ return acceptsBoundaryEvents(parent.data.elementType) ? true : "Boundary events can only be reparented to tasks or subprocesses.";
853
+ }
854
+ return canContainBpmnElement(parent?.data.elementType, node.data.elementType);
855
+ }
856
+ ],
857
+ delete: [() => true],
858
+ resize: [
859
+ ({ node }) => !node || isBpmnElementResizable(node.data.elementType) ? true : `${node.data.elementType} is not resizable in BPMN.`
860
+ ]
861
+ });
862
+
863
+ // src/layout/index.ts
864
+ async function bpmnDagreLayout(nodes, edges, options = {}) {
865
+ return layout.dagreLayout(nodes, edges, {
866
+ ...options,
867
+ getNodeSize: (node) => getBpmnNodeSize(node)
868
+ });
869
+ }
870
+ function applyBpmnLayoutResult(state, result) {
871
+ return layout.applyLayoutResultToDiagram(state, result);
872
+ }
873
+
874
+ Object.defineProperty(exports, "applyLayoutResultToDiagram", {
875
+ enumerable: true,
876
+ get: function () { return layout.applyLayoutResultToDiagram; }
877
+ });
878
+ exports.applyBpmnLayoutResult = applyBpmnLayoutResult;
879
+ exports.bpmnDagreLayout = bpmnDagreLayout;
880
+ //# sourceMappingURL=index.cjs.map
881
+ //# sourceMappingURL=index.cjs.map