bpmn-js 18.22.0 → 18.23.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 (38) hide show
  1. package/dist/assets/diagram-js.css +4 -0
  2. package/dist/bpmn-modeler.development.js +1094 -326
  3. package/dist/bpmn-modeler.production.min.js +50 -50
  4. package/dist/bpmn-navigated-viewer.development.js +38 -5
  5. package/dist/bpmn-navigated-viewer.production.min.js +3 -3
  6. package/dist/bpmn-viewer.development.js +38 -5
  7. package/dist/bpmn-viewer.production.min.js +3 -3
  8. package/lib/BaseViewer.d.ts.map +1 -1
  9. package/lib/BaseViewer.js +37 -3
  10. package/lib/features/modeling/Modeling.d.ts +13 -0
  11. package/lib/features/modeling/Modeling.d.ts.map +1 -1
  12. package/lib/features/modeling/Modeling.js +21 -0
  13. package/lib/features/modeling/behavior/CategoryRootElementReferenceBehavior.d.ts +19 -0
  14. package/lib/features/modeling/behavior/CategoryRootElementReferenceBehavior.d.ts.map +1 -0
  15. package/lib/features/modeling/behavior/CategoryRootElementReferenceBehavior.js +157 -0
  16. package/lib/features/modeling/behavior/GroupBehavior.d.ts +2 -8
  17. package/lib/features/modeling/behavior/GroupBehavior.d.ts.map +1 -1
  18. package/lib/features/modeling/behavior/GroupBehavior.js +65 -134
  19. package/lib/features/modeling/behavior/UpdateCategoryValueRefsBehavior.d.ts +17 -0
  20. package/lib/features/modeling/behavior/UpdateCategoryValueRefsBehavior.d.ts.map +1 -0
  21. package/lib/features/modeling/behavior/UpdateCategoryValueRefsBehavior.js +169 -0
  22. package/lib/features/modeling/behavior/UpdateFlowNodeRefsBehavior.d.ts +1 -1
  23. package/lib/features/modeling/behavior/UpdateFlowNodeRefsBehavior.d.ts.map +1 -1
  24. package/lib/features/modeling/behavior/UpdateFlowNodeRefsBehavior.js +35 -37
  25. package/lib/features/modeling/behavior/index.d.ts +4 -0
  26. package/lib/features/modeling/behavior/index.d.ts.map +1 -1
  27. package/lib/features/modeling/behavior/index.js +6 -0
  28. package/lib/features/modeling/behavior/util/CategoryUtil.d.ts +12 -3
  29. package/lib/features/modeling/behavior/util/CategoryUtil.d.ts.map +1 -1
  30. package/lib/features/modeling/behavior/util/CategoryUtil.js +25 -2
  31. package/lib/features/modeling/cmd/UpdateCategoryValueRefsHandler.d.ts +40 -0
  32. package/lib/features/modeling/cmd/UpdateCategoryValueRefsHandler.d.ts.map +1 -0
  33. package/lib/features/modeling/cmd/UpdateCategoryValueRefsHandler.js +424 -0
  34. package/lib/features/modeling/cmd/UpdateFlowNodeRefsHandler.d.ts +0 -8
  35. package/lib/features/modeling/cmd/UpdateFlowNodeRefsHandler.d.ts.map +1 -1
  36. package/lib/features/modeling/cmd/UpdateFlowNodeRefsHandler.js +1 -9
  37. package/lib/features/rules/BpmnRules.js +38 -0
  38. package/package.json +3 -3
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * bpmn-js - bpmn-modeler v18.22.0
2
+ * bpmn-js - bpmn-modeler v18.23.0
3
3
  *
4
4
  * Copyright (c) 2014-present, camunda Services GmbH
5
5
  *
@@ -8,7 +8,7 @@
8
8
  *
9
9
  * Source Code: https://github.com/bpmn-io/bpmn-js
10
10
  *
11
- * Date: 2026-07-23
11
+ * Date: 2026-08-10
12
12
  */
13
13
  (function (global, factory) {
14
14
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
@@ -4544,6 +4544,17 @@
4544
4544
  return isObject(value) && has(value, 'labelTarget');
4545
4545
  }
4546
4546
 
4547
+ /**
4548
+ * Checks whether a value is an instance of Root.
4549
+ *
4550
+ * @param {any} value
4551
+ *
4552
+ * @return {boolean}
4553
+ */
4554
+ function isRoot(value) {
4555
+ return isObject(value) && isNil(value.parent);
4556
+ }
4557
+
4547
4558
  /**
4548
4559
  * @typedef {import('../core/Types.js').ElementLike} Element
4549
4560
  * @typedef {import('../core/Types.js').ConnectionLike} Connection
@@ -17087,6 +17098,23 @@
17087
17098
  * @see http://bpmn.io/license for more information.
17088
17099
  */
17089
17100
 
17101
+ /**
17102
+ * Padding added around the diagram bounds on SVG export.
17103
+ *
17104
+ * `getBBox` returns the geometry bounds only, excluding element strokes, so
17105
+ * without padding strokes at the diagram edges get clipped. Historically this
17106
+ * padding was provided implicitly by element outlines, which diagram-js now
17107
+ * creates lazily (diagram-js@15.19, bpmn-io/diagram-js#1064).
17108
+ */
17109
+ const EXPORT_PADDING = 5;
17110
+
17111
+ /**
17112
+ * Class set on the canvas container to hide element outlines, which diagram-js
17113
+ * excludes from rendering while present. Applied when measuring the export
17114
+ * bounds so lazily created outlines do not skew them.
17115
+ */
17116
+ const OUTLINE_HIDDEN_CLS = 'djs-outline-hidden';
17117
+
17090
17118
  /**
17091
17119
  * @template T
17092
17120
  *
@@ -17537,15 +17565,31 @@
17537
17565
  const contents = innerSVG(contentNode),
17538
17566
  defs = defsNode ? '<defs>' + innerSVG(defsNode) + '</defs>' : '';
17539
17567
 
17540
- const bbox = contentNode.getBBox();
17568
+ // hide outlines so they do not skew the measured bounds
17569
+ const container = canvas.getContainer();
17570
+
17571
+ classes$1(container).add(OUTLINE_HIDDEN_CLS);
17572
+
17573
+ let bbox;
17574
+
17575
+ try {
17576
+ bbox = contentNode.getBBox();
17577
+ } finally {
17578
+ classes$1(container).remove(OUTLINE_HIDDEN_CLS);
17579
+ }
17580
+
17581
+ const x = bbox.x - EXPORT_PADDING,
17582
+ y = bbox.y - EXPORT_PADDING,
17583
+ width = bbox.width + EXPORT_PADDING * 2,
17584
+ height = bbox.height + EXPORT_PADDING * 2;
17541
17585
 
17542
17586
  svg =
17543
17587
  '<?xml version="1.0" encoding="utf-8"?>\n' +
17544
17588
  '<!-- created with bpmn-js / http://bpmn.io -->\n' +
17545
17589
  '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n' +
17546
17590
  '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" ' +
17547
- 'width="' + bbox.width + '" height="' + bbox.height + '" ' +
17548
- 'viewBox="' + bbox.x + ' ' + bbox.y + ' ' + bbox.width + ' ' + bbox.height + '" version="1.1">' +
17591
+ 'width="' + width + '" height="' + height + '" ' +
17592
+ 'viewBox="' + x + ' ' + y + ' ' + width + ' ' + height + '" version="1.1">' +
17549
17593
  defs + contents +
17550
17594
  '</svg>';
17551
17595
  } catch (e) {
@@ -22527,7 +22571,7 @@
22527
22571
  // document wide unique overlay ids
22528
22572
  var ids$2 = new IdGenerator('ov');
22529
22573
 
22530
- var LOW_PRIORITY$q = 500;
22574
+ var LOW_PRIORITY$s = 500;
22531
22575
 
22532
22576
  /**
22533
22577
  * @typedef {import('../../core/Canvas.js').default} Canvas
@@ -23157,7 +23201,7 @@
23157
23201
 
23158
23202
  // move integration
23159
23203
 
23160
- eventBus.on('element.changed', LOW_PRIORITY$q, function(e) {
23204
+ eventBus.on('element.changed', LOW_PRIORITY$s, function(e) {
23161
23205
  var element = e.element;
23162
23206
 
23163
23207
  var container = self._getOverlayContainer(element, true);
@@ -24239,7 +24283,7 @@
24239
24283
  * @typedef {import('../../model/Types').Shape} Shape
24240
24284
  */
24241
24285
 
24242
- var LOW_PRIORITY$p = 250;
24286
+ var LOW_PRIORITY$r = 250;
24243
24287
  var ARROW_DOWN_SVG = '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M4.81801948,3.50735931 L10.4996894,9.1896894 L10.5,4 L12,4 L12,12 L4,12 L4,10.5 L9.6896894,10.4996894 L3.75735931,4.56801948 C3.46446609,4.27512627 3.46446609,3.80025253 3.75735931,3.50735931 C4.05025253,3.21446609 4.52512627,3.21446609 4.81801948,3.50735931 Z"/></svg>';
24244
24288
 
24245
24289
  var EMPTY_MARKER = 'bjs-drilldown-empty';
@@ -24264,7 +24308,7 @@
24264
24308
 
24265
24309
  var self = this;
24266
24310
 
24267
- this.executed('shape.toggleCollapse', LOW_PRIORITY$p, function(context) {
24311
+ this.executed('shape.toggleCollapse', LOW_PRIORITY$r, function(context) {
24268
24312
  var shape = context.shape;
24269
24313
 
24270
24314
  // Add overlay to the collapsed shape
@@ -24276,7 +24320,7 @@
24276
24320
  }, true);
24277
24321
 
24278
24322
 
24279
- this.reverted('shape.toggleCollapse', LOW_PRIORITY$p, function(context) {
24323
+ this.reverted('shape.toggleCollapse', LOW_PRIORITY$r, function(context) {
24280
24324
  var shape = context.shape;
24281
24325
 
24282
24326
  // Add overlay to the collapsed shape
@@ -24288,7 +24332,7 @@
24288
24332
  }, true);
24289
24333
 
24290
24334
 
24291
- this.executed([ 'shape.create', 'shape.move', 'shape.delete' ], LOW_PRIORITY$p,
24335
+ this.executed([ 'shape.create', 'shape.move', 'shape.delete' ], LOW_PRIORITY$r,
24292
24336
  function(context) {
24293
24337
  var oldParent = context.oldParent,
24294
24338
  newParent = context.newParent || context.parent,
@@ -24305,7 +24349,7 @@
24305
24349
  }, true);
24306
24350
 
24307
24351
 
24308
- this.reverted([ 'shape.create', 'shape.move', 'shape.delete' ], LOW_PRIORITY$p,
24352
+ this.reverted([ 'shape.create', 'shape.move', 'shape.delete' ], LOW_PRIORITY$r,
24309
24353
  function(context) {
24310
24354
  var oldParent = context.oldParent,
24311
24355
  newParent = context.newParent || context.parent,
@@ -24582,7 +24626,7 @@
24582
24626
  return isPrimaryButton(event) || isAuxiliaryButton(event);
24583
24627
  }
24584
24628
 
24585
- var LOW_PRIORITY$o = 500;
24629
+ var LOW_PRIORITY$q = 500;
24586
24630
 
24587
24631
 
24588
24632
  /**
@@ -24779,7 +24823,7 @@
24779
24823
  eventBus.on([
24780
24824
  'shape.changed',
24781
24825
  'connection.changed'
24782
- ], LOW_PRIORITY$o, function(event) {
24826
+ ], LOW_PRIORITY$q, function(event) {
24783
24827
 
24784
24828
  var element = event.element,
24785
24829
  gfx = event.gfx;
@@ -24787,7 +24831,7 @@
24787
24831
  eventBus.fire('interactionEvents.updateHit', { element: element, gfx: gfx });
24788
24832
  });
24789
24833
 
24790
- eventBus.on('interactionEvents.createHit', LOW_PRIORITY$o, function(event) {
24834
+ eventBus.on('interactionEvents.createHit', LOW_PRIORITY$q, function(event) {
24791
24835
  var element = event.element,
24792
24836
  gfx = event.gfx;
24793
24837
 
@@ -25750,7 +25794,7 @@
25750
25794
  Keyboard.prototype.isShift = isShift;
25751
25795
  Keyboard.prototype.isKey = isKey;
25752
25796
 
25753
- var LOW_PRIORITY$n = 500;
25797
+ var LOW_PRIORITY$p = 500;
25754
25798
 
25755
25799
 
25756
25800
  /**
@@ -25766,7 +25810,7 @@
25766
25810
 
25767
25811
  var self = this;
25768
25812
 
25769
- eventBus.on('editorActions.init', LOW_PRIORITY$n, function(event) {
25813
+ eventBus.on('editorActions.init', LOW_PRIORITY$p, function(event) {
25770
25814
 
25771
25815
  var editorActions = event.editorActions;
25772
25816
 
@@ -29760,7 +29804,7 @@
29760
29804
  * @typedef {import('diagram-js/lib/features/context-pad/ContextPadProvider').default<Element>} ContextPadProvider
29761
29805
  */
29762
29806
 
29763
- var LOW_PRIORITY$m = 900;
29807
+ var LOW_PRIORITY$o = 900;
29764
29808
 
29765
29809
  /**
29766
29810
  * A provider for the `Align elements` context pad entry.
@@ -29774,7 +29818,7 @@
29774
29818
  */
29775
29819
  function AlignElementsContextPadProvider(contextPad, popupMenu, translate, canvas) {
29776
29820
 
29777
- contextPad.registerProvider(LOW_PRIORITY$m, this);
29821
+ contextPad.registerProvider(LOW_PRIORITY$o, this);
29778
29822
 
29779
29823
  this._contextPad = contextPad;
29780
29824
  this._popupMenu = popupMenu;
@@ -30404,7 +30448,7 @@
30404
30448
  * @typedef {import('../modeling/Modeling.js').default} Modeling
30405
30449
  */
30406
30450
 
30407
- var LOW_PRIORITY$l = 100;
30451
+ var LOW_PRIORITY$n = 100;
30408
30452
 
30409
30453
 
30410
30454
  /**
@@ -30417,7 +30461,7 @@
30417
30461
  */
30418
30462
  function AutoPlace$1(eventBus, modeling, canvas) {
30419
30463
 
30420
- eventBus.on('autoPlace', LOW_PRIORITY$l, function(context) {
30464
+ eventBus.on('autoPlace', LOW_PRIORITY$n, function(context) {
30421
30465
  var shape = context.shape,
30422
30466
  source = context.source;
30423
30467
 
@@ -31280,7 +31324,7 @@
31280
31324
  * @typedef {import('../../core/EventBus.js').default} EventBus
31281
31325
  */
31282
31326
 
31283
- var HIGH_PRIORITY$l = 1500;
31327
+ var HIGH_PRIORITY$m = 1500;
31284
31328
 
31285
31329
 
31286
31330
  /**
@@ -31348,7 +31392,7 @@
31348
31392
  */
31349
31393
  eventBus.on('drag.start', function(event) {
31350
31394
 
31351
- eventBus.once('drag.move', HIGH_PRIORITY$l, function(event) {
31395
+ eventBus.once('drag.move', HIGH_PRIORITY$m, function(event) {
31352
31396
 
31353
31397
  ensureHover(event);
31354
31398
 
@@ -31379,7 +31423,7 @@
31379
31423
  hover = event.element;
31380
31424
  });
31381
31425
 
31382
- eventBus.on('element.hover', HIGH_PRIORITY$l, function(event) {
31426
+ eventBus.on('element.hover', HIGH_PRIORITY$m, function(event) {
31383
31427
 
31384
31428
  // (3) am I on an element still?
31385
31429
  if (hover) {
@@ -33358,7 +33402,7 @@
33358
33402
  MARKER_CONNECT_UPDATING$1 = 'djs-updating',
33359
33403
  MARKER_DRAGGER = 'djs-dragging';
33360
33404
 
33361
- var HIGH_PRIORITY$k = 1100;
33405
+ var HIGH_PRIORITY$l = 1100;
33362
33406
 
33363
33407
  /**
33364
33408
  * Preview connection while moving bendpoints.
@@ -33426,7 +33470,7 @@
33426
33470
  eventBus.on([
33427
33471
  'bendpoint.move.out',
33428
33472
  'bendpoint.move.cleanup'
33429
- ], HIGH_PRIORITY$k, function(event) {
33473
+ ], HIGH_PRIORITY$l, function(event) {
33430
33474
  var context = event.context,
33431
33475
  hover = context.hover,
33432
33476
  target = context.target;
@@ -33512,7 +33556,7 @@
33512
33556
  eventBus.on([
33513
33557
  'bendpoint.move.end',
33514
33558
  'bendpoint.move.cancel'
33515
- ], HIGH_PRIORITY$k, function(event) {
33559
+ ], HIGH_PRIORITY$l, function(event) {
33516
33560
  var context = event.context,
33517
33561
  connection = context.connection,
33518
33562
  draggerGfx = context.draggerGfx,
@@ -34528,8 +34572,8 @@
34528
34572
  * @typedef {import('../../core/EventBus.js').default} EventBus
34529
34573
  */
34530
34574
 
34531
- var HIGH_PRIORITY$j = 1100,
34532
- LOW_PRIORITY$k = 900;
34575
+ var HIGH_PRIORITY$k = 1100,
34576
+ LOW_PRIORITY$m = 900;
34533
34577
 
34534
34578
  var MARKER_OK$3 = 'connect-ok',
34535
34579
  MARKER_NOT_OK$3 = 'connect-not-ok';
@@ -34573,7 +34617,7 @@
34573
34617
  });
34574
34618
  });
34575
34619
 
34576
- eventBus.on('connect.hover', LOW_PRIORITY$k, function(event) {
34620
+ eventBus.on('connect.hover', LOW_PRIORITY$m, function(event) {
34577
34621
  var context = event.context,
34578
34622
  hover = event.hover,
34579
34623
  canExecute = context.canExecute;
@@ -34589,7 +34633,7 @@
34589
34633
  eventBus.on([
34590
34634
  'connect.out',
34591
34635
  'connect.cleanup'
34592
- ], HIGH_PRIORITY$j, function(event) {
34636
+ ], HIGH_PRIORITY$k, function(event) {
34593
34637
  var hover = event.hover;
34594
34638
 
34595
34639
  if (hover) {
@@ -35641,7 +35685,7 @@
35641
35685
  * @typedef {import('../../../model/Types').Element} Element
35642
35686
  */
35643
35687
 
35644
- var HIGH_PRIORITY$i = 1500;
35688
+ var HIGH_PRIORITY$j = 1500;
35645
35689
 
35646
35690
  /**
35647
35691
  * A behavior that ensures that visually enclosed artifacts are affected
@@ -35662,7 +35706,7 @@
35662
35706
  injector.invoke(CommandInterceptor, this);
35663
35707
 
35664
35708
  // enclosed artifacts are deleted with a container element
35665
- this.preExecute('elements.delete', HIGH_PRIORITY$i, function(event) {
35709
+ this.preExecute('elements.delete', HIGH_PRIORITY$j, function(event) {
35666
35710
  var context = event.context,
35667
35711
  elements = context.elements;
35668
35712
 
@@ -35775,7 +35819,7 @@
35775
35819
  * @typedef {import('didi').Injector} Injector
35776
35820
  */
35777
35821
 
35778
- var LOW_PRIORITY$j = 500;
35822
+ var LOW_PRIORITY$l = 500;
35779
35823
 
35780
35824
 
35781
35825
  /**
@@ -35791,7 +35835,7 @@
35791
35835
 
35792
35836
  var self = this;
35793
35837
 
35794
- this.postExecuted('elements.create', LOW_PRIORITY$j, function(context) {
35838
+ this.postExecuted('elements.create', LOW_PRIORITY$l, function(context) {
35795
35839
  var elements = context.elements;
35796
35840
 
35797
35841
  elements = elements.filter(function(shape) {
@@ -35814,7 +35858,7 @@
35814
35858
  }, true);
35815
35859
 
35816
35860
 
35817
- this.preExecute('elements.move', LOW_PRIORITY$j, function(context) {
35861
+ this.preExecute('elements.move', LOW_PRIORITY$l, function(context) {
35818
35862
  var shapes = context.shapes,
35819
35863
  host = context.newHost;
35820
35864
 
@@ -35932,6 +35976,255 @@
35932
35976
 
35933
35977
  e$3(BoundaryEventBehavior, CommandInterceptor);
35934
35978
 
35979
+ /**
35980
+ * @typedef {import('../../BpmnFactory').default} BpmnFactory
35981
+ *
35982
+ * @typedef {import('../../../../model/Types').ModdleElement} ModdleElement
35983
+ */
35984
+
35985
+ /**
35986
+ * Creates a new bpmn:CategoryValue inside a new bpmn:Category
35987
+ *
35988
+ * @param {BpmnFactory} bpmnFactory
35989
+ *
35990
+ * @return {ModdleElement}
35991
+ */
35992
+ function createCategory(bpmnFactory) {
35993
+ return bpmnFactory.create('bpmn:Category');
35994
+ }
35995
+
35996
+ /**
35997
+ * Creates a new bpmn:CategoryValue inside a new bpmn:Category
35998
+ *
35999
+ * @param {BpmnFactory} bpmnFactory
36000
+ *
36001
+ * @return {ModdleElement}
36002
+ */
36003
+ function createCategoryValue(bpmnFactory) {
36004
+ return bpmnFactory.create('bpmn:CategoryValue');
36005
+ }
36006
+
36007
+ /**
36008
+ * Returns a group's category value, creating one (including a
36009
+ * category) if needed.
36010
+ *
36011
+ * @param {BpmnFactory} bpmnFactory
36012
+ * @param {ModdleElement} groupBo
36013
+ *
36014
+ * @return {ModdleElement}
36015
+ */
36016
+ function getOrCreateCategoryValueForGroup(bpmnFactory, groupBo) {
36017
+ var categoryValue = groupBo.get('categoryValueRef');
36018
+
36019
+ if (!categoryValue) {
36020
+ categoryValue = groupBo.categoryValueRef = createCategoryValue(bpmnFactory);
36021
+ }
36022
+
36023
+ if (!categoryValue.$parent) {
36024
+ categoryValue.$parent = createCategory(bpmnFactory);
36025
+ }
36026
+
36027
+ return categoryValue;
36028
+ }
36029
+
36030
+ /**
36031
+ * Adds category value to definitions
36032
+ *
36033
+ * @param {ModdleElement} categoryValue
36034
+ * @param {ModdleElement} category
36035
+ * @param {ModdleElement} definitions
36036
+ *
36037
+ * @return {ModdleElement}
36038
+ */
36039
+ function linkCategoryValue(categoryValue, category, definitions) {
36040
+ add(category.get('categoryValue'), categoryValue);
36041
+ categoryValue.$parent = category;
36042
+
36043
+ add(definitions.get('rootElements'), category);
36044
+ category.$parent = definitions;
36045
+
36046
+ return categoryValue;
36047
+ }
36048
+
36049
+ /**
36050
+ * Unlink category value from parent
36051
+ *
36052
+ * @param {ModdleElement} categoryValue
36053
+ *
36054
+ * @return {ModdleElement}
36055
+ */
36056
+ function unlinkCategoryValue(categoryValue) {
36057
+ var category = categoryValue.$parent;
36058
+
36059
+ if (category) {
36060
+ remove(category.get('categoryValue'), categoryValue);
36061
+ categoryValue.$parent = null;
36062
+ }
36063
+
36064
+ return categoryValue;
36065
+ }
36066
+
36067
+ /**
36068
+ * Unlink category from parent
36069
+ *
36070
+ * @param {ModdleElement} category
36071
+ *
36072
+ * @return {ModdleElement}
36073
+ */
36074
+ function unlinkCategory(category) {
36075
+ var definitions = category.$parent;
36076
+
36077
+ if (definitions) {
36078
+ remove(definitions.get('rootElements'), category);
36079
+ category.$parent = null;
36080
+ }
36081
+
36082
+ return category;
36083
+ }
36084
+
36085
+ var LOW_PRIORITY$k = 500;
36086
+
36087
+ /**
36088
+ * @typedef {import('../../../Modeler').default} Modeler
36089
+ * @typedef {import('diagram-js/lib/core/ElementRegistry').default} ElementRegistry
36090
+ * @typedef {import('didi').Injector} Injector
36091
+ */
36092
+
36093
+ /**
36094
+ * Maintains a group's category (value) inside definitions#rootElements.
36095
+ *
36096
+ * @param {Modeler} bpmnjs
36097
+ * @param {ElementRegistry} elementRegistry
36098
+ * @param {Injector} injector
36099
+ */
36100
+ function CategoryRootElementReferenceBehavior(
36101
+ bpmnjs, elementRegistry, injector
36102
+ ) {
36103
+ injector.invoke(CommandInterceptor, this);
36104
+
36105
+ function getGroupBusinessObjects(ignoredBusinessObject) {
36106
+ return elementRegistry.filter(function(element) {
36107
+ return is(element, 'bpmn:Group') && !element.labelTarget;
36108
+ }).map(getBusinessObject).filter(function(businessObject) {
36109
+ return businessObject !== ignoredBusinessObject;
36110
+ });
36111
+ }
36112
+
36113
+ function isCategoryValueReferenced(categoryValue, ignoredBusinessObject) {
36114
+ return getGroupBusinessObjects(ignoredBusinessObject).some(function(businessObject) {
36115
+ return businessObject.get('categoryValueRef') === categoryValue;
36116
+ });
36117
+ }
36118
+
36119
+ function isCategoryReferenced(category, ignoredBusinessObject) {
36120
+ return getGroupBusinessObjects(ignoredBusinessObject).some(function(businessObject) {
36121
+ var categoryValue = businessObject.get('categoryValueRef');
36122
+
36123
+ return categoryValue && categoryValue.$parent === category;
36124
+ });
36125
+ }
36126
+
36127
+ function link(categoryValue, category) {
36128
+ if (categoryValue && category) {
36129
+ linkCategoryValue(categoryValue, category, bpmnjs.getDefinitions());
36130
+ }
36131
+ }
36132
+
36133
+ function unlink(categoryValue, category, ignoredBusinessObject) {
36134
+ if (category && !isCategoryReferenced(category, ignoredBusinessObject)) {
36135
+ unlinkCategory(category);
36136
+ }
36137
+
36138
+ if (categoryValue && !isCategoryValueReferenced(categoryValue, ignoredBusinessObject)) {
36139
+ unlinkCategoryValue(categoryValue);
36140
+ }
36141
+ }
36142
+
36143
+
36144
+ this.executed([ 'shape.create', 'label.create' ], function(context) {
36145
+ var shape = context.labelTarget || context.shape;
36146
+
36147
+ if (!is(shape, 'bpmn:Group') || shape.labelTarget) {
36148
+ return;
36149
+ }
36150
+
36151
+ link(context.categoryValue, context.category);
36152
+ }, true);
36153
+
36154
+ this.reverted([ 'shape.create', 'label.create' ], function(context) {
36155
+ var shape = context.labelTarget || context.shape;
36156
+
36157
+ if (!is(shape, 'bpmn:Group') || shape.labelTarget) {
36158
+ return;
36159
+ }
36160
+
36161
+ unlink(context.categoryValue, context.category, getBusinessObject(shape));
36162
+ }, true);
36163
+
36164
+ this.executed([ 'shape.move', 'shape.resize' ], LOW_PRIORITY$k, function(context) {
36165
+ link(context.categoryValue, context.category);
36166
+ }, true);
36167
+
36168
+ this.reverted([ 'shape.move', 'shape.resize' ], function(context) {
36169
+ var shape = context.shape;
36170
+
36171
+ if (context.categoryValue) {
36172
+ unlink(context.categoryValue, context.category, getBusinessObject(shape));
36173
+ }
36174
+ }, true);
36175
+
36176
+ this.executed('group.updateRefs', function(context) {
36177
+ getGroupUpdates(context).forEach(function(update) {
36178
+ link(update.categoryValue, update.category);
36179
+ });
36180
+ }, true);
36181
+
36182
+ this.reverted('group.updateRefs', function(context) {
36183
+ getGroupUpdates(context).forEach(function(update) {
36184
+ unlink(
36185
+ update.categoryValue,
36186
+ update.category,
36187
+ getBusinessObject(update.groupShape)
36188
+ );
36189
+ });
36190
+ }, true);
36191
+
36192
+ this.executed('shape.delete', function(context) {
36193
+ var shape = context.shape;
36194
+
36195
+ if (!is(shape, 'bpmn:Group') || shape.labelTarget) {
36196
+ return;
36197
+ }
36198
+
36199
+ unlink(context.categoryValue, context.category, getBusinessObject(shape));
36200
+ }, true);
36201
+
36202
+ this.reverted('shape.delete', function(context) {
36203
+ var shape = context.shape;
36204
+
36205
+ if (!is(shape, 'bpmn:Group') || shape.labelTarget) {
36206
+ return;
36207
+ }
36208
+
36209
+ link(context.categoryValue, context.category);
36210
+ }, true);
36211
+ }
36212
+
36213
+ CategoryRootElementReferenceBehavior.$inject = [
36214
+ 'bpmnjs',
36215
+ 'elementRegistry',
36216
+ 'injector'
36217
+ ];
36218
+
36219
+ e$3(CategoryRootElementReferenceBehavior, CommandInterceptor);
36220
+
36221
+
36222
+ // helpers //////////
36223
+
36224
+ function getGroupUpdates(context) {
36225
+ return context.updates?.groups || [];
36226
+ }
36227
+
35935
36228
  /**
35936
36229
  * @typedef {import('diagram-js/lib/core/EventBus').default} EventBus
35937
36230
  * @typedef {import('../lib/features/modeling/Modeling').default} Modeling
@@ -36228,7 +36521,7 @@
36228
36521
 
36229
36522
  var PARTICIPANT_BORDER_WIDTH = 30;
36230
36523
 
36231
- var HIGH_PRIORITY$h = 2000;
36524
+ var HIGH_PRIORITY$i = 2000;
36232
36525
 
36233
36526
 
36234
36527
  /**
@@ -36245,7 +36538,7 @@
36245
36538
  eventBus.on([
36246
36539
  'create.start',
36247
36540
  'shape.move.start'
36248
- ], HIGH_PRIORITY$h, function(event) {
36541
+ ], HIGH_PRIORITY$i, function(event) {
36249
36542
  var context = event.context,
36250
36543
  shape = context.shape,
36251
36544
  rootElement = canvas.getRootElement();
@@ -36280,7 +36573,7 @@
36280
36573
  });
36281
36574
 
36282
36575
  // force hovering process when creating first participant
36283
- eventBus.on('create.start', HIGH_PRIORITY$h, function(event) {
36576
+ eventBus.on('create.start', HIGH_PRIORITY$i, function(event) {
36284
36577
  var context = event.context,
36285
36578
  shape = context.shape,
36286
36579
  rootElement = canvas.getRootElement(),
@@ -36292,7 +36585,7 @@
36292
36585
  }
36293
36586
 
36294
36587
  if (is(shape, 'bpmn:Participant') && is(rootElement, 'bpmn:Process')) {
36295
- eventBus.on('element.hover', HIGH_PRIORITY$h, ensureHoveringProcess);
36588
+ eventBus.on('element.hover', HIGH_PRIORITY$i, ensureHoveringProcess);
36296
36589
 
36297
36590
  eventBus.once('create.cleanup', function() {
36298
36591
  eventBus.off('element.hover', ensureHoveringProcess);
@@ -36313,7 +36606,7 @@
36313
36606
 
36314
36607
  // when creating mutliple elements through `elements.create` parent must be set to collaboration
36315
36608
  // and passed to `shape.create` as hint
36316
- this.preExecute('elements.create', HIGH_PRIORITY$h, function(context) {
36609
+ this.preExecute('elements.create', HIGH_PRIORITY$i, function(context) {
36317
36610
  var elements = context.elements,
36318
36611
  parent = context.parent,
36319
36612
  participant = findParticipant(elements),
@@ -37249,7 +37542,7 @@
37249
37542
  * @typedef {import('../../space-tool/BpmnSpaceTool').default} SpaceTool
37250
37543
  */
37251
37544
 
37252
- var LOW_PRIORITY$i = 500;
37545
+ var LOW_PRIORITY$j = 500;
37253
37546
 
37254
37547
 
37255
37548
  /**
@@ -37362,7 +37655,7 @@
37362
37655
  /**
37363
37656
  * Adjust sizes of other lanes after lane deletion
37364
37657
  */
37365
- this.postExecuted('shape.delete', LOW_PRIORITY$i, function(event) {
37658
+ this.postExecuted('shape.delete', LOW_PRIORITY$j, function(event) {
37366
37659
 
37367
37660
  var context = event.context,
37368
37661
  hints = context.hints,
@@ -37395,7 +37688,7 @@
37395
37688
  * @typedef {import('didi').Injector} Injector
37396
37689
  */
37397
37690
 
37398
- var LOW_PRIORITY$h = 500;
37691
+ var LOW_PRIORITY$i = 500;
37399
37692
 
37400
37693
 
37401
37694
  /**
@@ -37411,7 +37704,7 @@
37411
37704
 
37412
37705
  var self = this;
37413
37706
 
37414
- this.postExecuted('elements.create', LOW_PRIORITY$h, function(context) {
37707
+ this.postExecuted('elements.create', LOW_PRIORITY$i, function(context) {
37415
37708
  var elements = context.elements;
37416
37709
 
37417
37710
  elements.filter(function(shape) {
@@ -37425,7 +37718,7 @@
37425
37718
  });
37426
37719
  }, true);
37427
37720
 
37428
- this.preExecute('elements.move', LOW_PRIORITY$h, function(context) {
37721
+ this.preExecute('elements.move', LOW_PRIORITY$i, function(context) {
37429
37722
  var shapes = context.shapes,
37430
37723
  newHost = context.newHost;
37431
37724
 
@@ -37798,7 +38091,7 @@
37798
38091
  * @typedef {import('diagram-js/lib/core/Canvas').default} Canvas
37799
38092
  */
37800
38093
 
37801
- var HIGH_PRIORITY$g = 1500;
38094
+ var HIGH_PRIORITY$h = 1500;
37802
38095
  var HIGHEST_PRIORITY = 2000;
37803
38096
 
37804
38097
 
@@ -37820,7 +38113,7 @@
37820
38113
  'shape.move.move',
37821
38114
  'shape.move.out',
37822
38115
  'shape.move.end'
37823
- ], HIGH_PRIORITY$g, function(event) {
38116
+ ], HIGH_PRIORITY$h, function(event) {
37824
38117
  var context = event.context,
37825
38118
  shape = context.shape || event.shape,
37826
38119
  hover = event.hover;
@@ -37852,7 +38145,7 @@
37852
38145
  'global-connect.out',
37853
38146
  'global-connect.end',
37854
38147
  'global-connect.cleanup'
37855
- ], HIGH_PRIORITY$g, function(event) {
38148
+ ], HIGH_PRIORITY$h, function(event) {
37856
38149
  var hover = event.hover;
37857
38150
 
37858
38151
  // ensure connections start/end on bpmn:Participant,
@@ -37866,7 +38159,7 @@
37866
38159
 
37867
38160
  eventBus.on([
37868
38161
  'bendpoint.move.hover'
37869
- ], HIGH_PRIORITY$g, function(event) {
38162
+ ], HIGH_PRIORITY$h, function(event) {
37870
38163
  var context = event.context,
37871
38164
  hover = event.hover,
37872
38165
  type = context.type;
@@ -37882,7 +38175,7 @@
37882
38175
 
37883
38176
  eventBus.on([
37884
38177
  'connect.start'
37885
- ], HIGH_PRIORITY$g, function(event) {
38178
+ ], HIGH_PRIORITY$h, function(event) {
37886
38179
  var context = event.context,
37887
38180
  start = context.start;
37888
38181
 
@@ -37921,101 +38214,12 @@
37921
38214
  'canvas'
37922
38215
  ];
37923
38216
 
37924
- /**
37925
- * @typedef {import('../../BpmnFactory').default} BpmnFactory
37926
- *
37927
- * @typedef {import('../../../model/Types').ModdleElement} ModdleElement
37928
- */
37929
-
37930
- /**
37931
- * Creates a new bpmn:CategoryValue inside a new bpmn:Category
37932
- *
37933
- * @param {BpmnFactory} bpmnFactory
37934
- *
37935
- * @return {ModdleElement}
37936
- */
37937
- function createCategory(bpmnFactory) {
37938
- return bpmnFactory.create('bpmn:Category');
37939
- }
37940
-
37941
- /**
37942
- * Creates a new bpmn:CategoryValue inside a new bpmn:Category
37943
- *
37944
- * @param {BpmnFactory} bpmnFactory
37945
- *
37946
- * @return {ModdleElement}
37947
- */
37948
- function createCategoryValue(bpmnFactory) {
37949
- return bpmnFactory.create('bpmn:CategoryValue');
37950
- }
37951
-
37952
- /**
37953
- * Adds category value to definitions
37954
- *
37955
- * @param {ModdleElement} categoryValue
37956
- * @param {ModdleElement} category
37957
- * @param {ModdleElement} definitions
37958
- *
37959
- * @return {ModdleElement}
37960
- */
37961
- function linkCategoryValue(categoryValue, category, definitions) {
37962
- add(category.get('categoryValue'), categoryValue);
37963
- categoryValue.$parent = category;
37964
-
37965
- add(definitions.get('rootElements'), category);
37966
- category.$parent = definitions;
37967
-
37968
- return categoryValue;
37969
- }
37970
-
37971
- /**
37972
- * Unlink category value from parent
37973
- *
37974
- * @param {ModdleElement} categoryValue
37975
- *
37976
- * @return {ModdleElement}
37977
- */
37978
- function unlinkCategoryValue(categoryValue) {
37979
- var category = categoryValue.$parent;
37980
-
37981
- if (category) {
37982
- remove(category.get('categoryValue'), categoryValue);
37983
- categoryValue.$parent = null;
37984
- }
37985
-
37986
- return categoryValue;
37987
- }
37988
-
37989
- /**
37990
- * Unlink category from parent
37991
- *
37992
- * @param {ModdleElement} category
37993
- *
37994
- * @return {ModdleElement}
37995
- */
37996
- function unlinkCategory(category) {
37997
- var definitions = category.$parent;
37998
-
37999
- if (definitions) {
38000
- remove(definitions.get('rootElements'), category);
38001
- category.$parent = null;
38002
- }
38003
-
38004
- return category;
38005
- }
38006
-
38007
38217
  /**
38008
38218
  * @typedef {import('../BpmnFactory').default} BpmnFactory
38009
- * @typedef {import('../../../Modeler').default} Modeler
38010
- * @typedef {import('diagram-js/lib/core/ElementRegistry').default} ElementRegistry
38011
38219
  * @typedef {import('diagram-js/lib/core/EventBus').default} EventBus
38220
+ * @typedef {import('diagram-js/lib/core/ElementRegistry').default} ElementRegistry
38012
38221
  * @typedef {import('didi').Injector} Injector
38013
38222
  * @typedef {import('../../copy-paste/ModdleCopy').default} ModdleCopy
38014
- *
38015
- * @typedef {import('../../../model/Types').Element} Element
38016
- * @typedef {import('../../../model/Types').Shape} Shape
38017
- *
38018
- * @typedef {import('diagram-js/lib/util/Types').DirectionTRBL} DirectionTRBL
38019
38223
  */
38020
38224
 
38021
38225
  var LOWER_PRIORITY$1 = 770;
@@ -38025,137 +38229,45 @@
38025
38229
  * BPMN specific group behavior.
38026
38230
  *
38027
38231
  * @param {BpmnFactory} bpmnFactory
38028
- * @param {Modeler} bpmnjs
38029
- * @param {ElementRegistry} elementRegistry
38030
38232
  * @param {EventBus} eventBus
38031
38233
  * @param {Injector} injector
38032
38234
  * @param {ModdleCopy} moddleCopy
38033
38235
  */
38034
38236
  function GroupBehavior(
38035
38237
  bpmnFactory,
38036
- bpmnjs,
38037
- elementRegistry,
38038
38238
  eventBus,
38039
38239
  injector,
38040
38240
  moddleCopy
38041
38241
  ) {
38042
38242
  injector.invoke(CommandInterceptor, this);
38043
38243
 
38044
- /**
38045
- * Returns all group element in the current registry.
38046
- *
38047
- * @return {Shape[]}
38048
- */
38049
- function getGroupElements() {
38050
- return elementRegistry.filter(function(e) {
38051
- return is(e, 'bpmn:Group');
38052
- });
38053
- }
38054
-
38055
- /**
38056
- * Returns true if given category is referenced in one of the given elements.
38057
- *
38058
- * @param {Element[]} elements
38059
- * @param {ModdleElement} category
38060
- *
38061
- * @return {boolean}
38062
- */
38063
- function isReferencedCategory(elements, category) {
38064
- return elements.some(function(element) {
38065
- var businessObject = getBusinessObject(element);
38066
-
38067
- var _category = businessObject.categoryValueRef && businessObject.categoryValueRef.$parent;
38068
-
38069
- return _category === category;
38070
- });
38071
- }
38072
-
38073
- /**
38074
- * Returns true if given categoryValue is referenced in one of the given elements.
38075
- *
38076
- * @param {Element[]} elements
38077
- * @param {ModdleElement} categoryValue
38078
- *
38079
- * @return {boolean}
38080
- */
38081
- function isReferencedCategoryValue(elements, categoryValue) {
38082
- return elements.some(function(element) {
38083
- var businessObject = getBusinessObject(element);
38084
-
38085
- return businessObject.categoryValueRef === categoryValue;
38086
- });
38087
- }
38088
-
38089
- /**
38090
- * Remove category value unless it is still referenced.
38091
- *
38092
- * @param {ModdleElement} categoryValue
38093
- * @param {ModdleElement} category
38094
- * @param {ModdleElement} businessObject
38095
- */
38096
- function removeCategoryValue(categoryValue, category, businessObject) {
38097
-
38098
- var groups = getGroupElements().filter(function(element) {
38099
- return element.businessObject !== businessObject;
38100
- });
38101
-
38102
- if (category && !isReferencedCategory(groups, category)) {
38103
- unlinkCategory(category);
38104
- }
38105
-
38106
- if (categoryValue && !isReferencedCategoryValue(groups, categoryValue)) {
38107
- unlinkCategoryValue(categoryValue);
38108
- }
38109
- }
38110
-
38111
- /**
38112
- * Add category value.
38113
- *
38114
- * @param {ModdleElement} categoryValue
38115
- * @param {ModdleElement} category
38116
- *
38117
- * @return {ModdleElement}
38118
- */
38119
- function addCategoryValue(categoryValue, category) {
38120
- return linkCategoryValue(categoryValue, category, bpmnjs.getDefinitions());
38121
- }
38122
-
38123
38244
  function setCategoryValue(element, context) {
38124
38245
  var businessObject = getBusinessObject(element),
38125
- categoryValue = businessObject.categoryValueRef;
38246
+ categoryValue = context.categoryValue || businessObject.categoryValueRef;
38126
38247
 
38127
38248
  if (!categoryValue) {
38128
- categoryValue =
38129
- businessObject.categoryValueRef =
38130
- context.categoryValue = (
38131
- context.categoryValue || createCategoryValue(bpmnFactory)
38132
- );
38249
+ categoryValue = getOrCreateCategoryValueForGroup(bpmnFactory, businessObject);
38133
38250
  }
38134
38251
 
38135
- var category = categoryValue.$parent;
38252
+ var category = context.category || categoryValue.$parent || createCategory(bpmnFactory);
38136
38253
 
38137
- if (!category) {
38138
- category =
38139
- categoryValue.$parent =
38140
- context.category = (
38141
- context.category || createCategory(bpmnFactory)
38142
- );
38143
- }
38254
+ businessObject.categoryValueRef = categoryValue;
38255
+ categoryValue.$parent = category;
38144
38256
 
38145
- addCategoryValue(categoryValue, category, bpmnjs.getDefinitions());
38257
+ context.categoryValue = categoryValue;
38258
+ context.category = category;
38146
38259
  }
38147
38260
 
38148
38261
  function unsetCategoryValue(element, context) {
38149
- var category = context.category,
38150
- categoryValue = context.categoryValue,
38151
- businessObject = getBusinessObject(element);
38262
+ var businessObject = getBusinessObject(element),
38263
+ categoryValue = context.categoryValue || businessObject.categoryValueRef,
38264
+ category = context.category || (categoryValue && categoryValue.$parent);
38152
38265
 
38153
38266
  if (categoryValue) {
38154
- businessObject.categoryValueRef = null;
38267
+ context.categoryValue = categoryValue;
38268
+ context.category = category;
38155
38269
 
38156
- removeCategoryValue(categoryValue, category, businessObject);
38157
- } else {
38158
- removeCategoryValue(null, businessObject.categoryValueRef.$parent, businessObject);
38270
+ businessObject.categoryValueRef = null;
38159
38271
  }
38160
38272
  }
38161
38273
 
@@ -38197,14 +38309,10 @@
38197
38309
  return;
38198
38310
  }
38199
38311
 
38200
- var categoryValue = context.categoryValue = businessObject.categoryValueRef,
38201
- category;
38312
+ var categoryValue = context.categoryValue = businessObject.categoryValueRef;
38202
38313
 
38203
38314
  if (categoryValue) {
38204
- category = context.category = categoryValue.$parent;
38205
-
38206
- removeCategoryValue(categoryValue, category, businessObject);
38207
-
38315
+ context.category = categoryValue.$parent;
38208
38316
  businessObject.categoryValueRef = null;
38209
38317
  }
38210
38318
  });
@@ -38224,39 +38332,77 @@
38224
38332
 
38225
38333
  if (categoryValue) {
38226
38334
  businessObject.categoryValueRef = categoryValue;
38227
-
38228
- addCategoryValue(categoryValue, category);
38335
+ categoryValue.$parent = category;
38229
38336
  }
38230
38337
  });
38231
38338
 
38232
38339
 
38233
- // create new category + value when group was created
38340
+ // create new category + value when group was created so that visually
38341
+ // enclosed elements can be categorized against it, even if it is unlabeled
38234
38342
 
38235
38343
  this.execute('shape.create', function(event) {
38236
38344
  var context = event.context,
38237
- shape = context.shape;
38345
+ shape = context.shape,
38346
+ hints = context.hints || {};
38238
38347
 
38239
38348
  if (!is(shape, 'bpmn:Group') || shape.labelTarget) {
38240
38349
  return;
38241
38350
  }
38242
38351
 
38243
- if (getBusinessObject(shape).categoryValueRef) {
38244
- setCategoryValue(shape, context);
38352
+ // during paste the category value (if any) is carried over from the
38353
+ // source; only fabricate one for genuinely new groups
38354
+ if (hints.createElementsBehavior === false &&
38355
+ !getBusinessObject(shape).categoryValueRef &&
38356
+ !context.categoryValue) {
38357
+ return;
38245
38358
  }
38359
+
38360
+ setCategoryValue(shape, context);
38246
38361
  });
38247
38362
 
38248
38363
  this.reverted('shape.create', function(event) {
38249
38364
 
38250
38365
  var context = event.context,
38251
- shape = context.shape;
38366
+ shape = context.shape,
38367
+ hints = context.hints || {};
38252
38368
 
38253
38369
  if (!is(shape, 'bpmn:Group') || shape.labelTarget) {
38254
38370
  return;
38255
38371
  }
38256
38372
 
38257
- if (getBusinessObject(shape).categoryValueRef) {
38258
- unsetCategoryValue(shape, context);
38373
+ if (hints.createElementsBehavior === false &&
38374
+ !getBusinessObject(shape).categoryValueRef &&
38375
+ !context.categoryValue) {
38376
+ return;
38259
38377
  }
38378
+
38379
+ unsetCategoryValue(shape, context);
38380
+ });
38381
+
38382
+
38383
+ // add category -> categoryValue for groups when they change
38384
+
38385
+ this.executed([ 'shape.move', 'shape.resize' ], function(event) {
38386
+ var context = event.context,
38387
+ shape = context.shape;
38388
+
38389
+ if (!is(shape, 'bpmn:Group') || shape.labelTarget ||
38390
+ getBusinessObject(shape).categoryValueRef) {
38391
+ return;
38392
+ }
38393
+
38394
+ setCategoryValue(shape, context);
38395
+ });
38396
+
38397
+ this.reverted([ 'shape.move', 'shape.resize' ], function(event) {
38398
+ var context = event.context,
38399
+ shape = context.shape;
38400
+
38401
+ if (!is(shape, 'bpmn:Group') || shape.labelTarget || !context.categoryValue) {
38402
+ return;
38403
+ }
38404
+
38405
+ unsetCategoryValue(shape, context);
38260
38406
  });
38261
38407
 
38262
38408
 
@@ -38312,8 +38458,6 @@
38312
38458
 
38313
38459
  GroupBehavior.$inject = [
38314
38460
  'bpmnFactory',
38315
- 'bpmnjs',
38316
- 'elementRegistry',
38317
38461
  'eventBus',
38318
38462
  'injector',
38319
38463
  'moddleCopy'
@@ -40368,7 +40512,7 @@
40368
40512
  'selection'
40369
40513
  ];
40370
40514
 
40371
- var HIGH_PRIORITY$f = 1500;
40515
+ var HIGH_PRIORITY$g = 1500;
40372
40516
 
40373
40517
  /**
40374
40518
  * @typedef {import('diagram-js/lib/core/EventBus').default} EventBus
@@ -40421,7 +40565,7 @@
40421
40565
  * @param {EventBus} eventBus
40422
40566
  */
40423
40567
  function ResizeBehavior$1(eventBus) {
40424
- eventBus.on('resize.start', HIGH_PRIORITY$f, function(event) {
40568
+ eventBus.on('resize.start', HIGH_PRIORITY$g, function(event) {
40425
40569
  var context = event.context,
40426
40570
  shape = context.shape,
40427
40571
  direction = context.direction,
@@ -40693,7 +40837,7 @@
40693
40837
  * @typedef {import('diagram-js/lib/util/Types').DirectionTRBL} DirectionTRBL
40694
40838
  */
40695
40839
 
40696
- var LOW_PRIORITY$g = 500;
40840
+ var LOW_PRIORITY$h = 500;
40697
40841
 
40698
40842
 
40699
40843
  /**
@@ -40823,7 +40967,7 @@
40823
40967
  }
40824
40968
  });
40825
40969
 
40826
- eventBus.on('copyPaste.pasteElement', LOW_PRIORITY$g, function(context) {
40970
+ eventBus.on('copyPaste.pasteElement', LOW_PRIORITY$h, function(context) {
40827
40971
  var descriptor = context.descriptor,
40828
40972
  businessObject = descriptor.businessObject,
40829
40973
  referencedRootElement = descriptor.referencedRootElement;
@@ -41068,8 +41212,8 @@
41068
41212
  * @typedef {import('../../../model/Types').ModdleElement} ModdleElement
41069
41213
  */
41070
41214
 
41071
- var LOW_PRIORITY$f = 400;
41072
- var HIGH_PRIORITY$e = 600;
41215
+ var LOW_PRIORITY$g = 400;
41216
+ var HIGH_PRIORITY$f = 600;
41073
41217
 
41074
41218
  var DEFAULT_POSITION = {
41075
41219
  x: 180,
@@ -41343,7 +41487,7 @@
41343
41487
 
41344
41488
 
41345
41489
  // create/remove plane for the subprocess
41346
- this.executed('shape.toggleCollapse', LOW_PRIORITY$f, function(context) {
41490
+ this.executed('shape.toggleCollapse', LOW_PRIORITY$g, function(context) {
41347
41491
  var shape = context.shape;
41348
41492
 
41349
41493
  if (!is(shape, 'bpmn:SubProcess')) {
@@ -41361,7 +41505,7 @@
41361
41505
 
41362
41506
 
41363
41507
  // create/remove plane for the subprocess
41364
- this.reverted('shape.toggleCollapse', LOW_PRIORITY$f, function(context) {
41508
+ this.reverted('shape.toggleCollapse', LOW_PRIORITY$g, function(context) {
41365
41509
  var shape = context.shape;
41366
41510
 
41367
41511
  if (!is(shape, 'bpmn:SubProcess')) {
@@ -41378,7 +41522,7 @@
41378
41522
  }, true);
41379
41523
 
41380
41524
  // move elements between planes
41381
- this.postExecuted('shape.toggleCollapse', HIGH_PRIORITY$e, function(context) {
41525
+ this.postExecuted('shape.toggleCollapse', HIGH_PRIORITY$f, function(context) {
41382
41526
  var shape = context.shape;
41383
41527
 
41384
41528
  if (!is(shape, 'bpmn:SubProcess')) {
@@ -41925,7 +42069,7 @@
41925
42069
  * @typedef {import('../Modeling').default} Modeling
41926
42070
  */
41927
42071
 
41928
- var LOW_PRIORITY$e = 500;
42072
+ var LOW_PRIORITY$f = 500;
41929
42073
 
41930
42074
  /**
41931
42075
  * @param {EventBus} eventBus
@@ -41986,7 +42130,7 @@
41986
42130
  };
41987
42131
  }
41988
42132
 
41989
- this.executed([ 'shape.toggleCollapse' ], LOW_PRIORITY$e, function(e) {
42133
+ this.executed([ 'shape.toggleCollapse' ], LOW_PRIORITY$f, function(e) {
41990
42134
 
41991
42135
  var context = e.context,
41992
42136
  shape = context.shape;
@@ -42009,7 +42153,7 @@
42009
42153
  }
42010
42154
  });
42011
42155
 
42012
- this.reverted([ 'shape.toggleCollapse' ], LOW_PRIORITY$e, function(e) {
42156
+ this.reverted([ 'shape.toggleCollapse' ], LOW_PRIORITY$f, function(e) {
42013
42157
 
42014
42158
  var context = e.context;
42015
42159
  var shape = context.shape;
@@ -42024,7 +42168,7 @@
42024
42168
  }
42025
42169
  });
42026
42170
 
42027
- this.postExecuted([ 'shape.toggleCollapse' ], LOW_PRIORITY$e, function(e) {
42171
+ this.postExecuted([ 'shape.toggleCollapse' ], LOW_PRIORITY$f, function(e) {
42028
42172
  var shape = e.context.shape,
42029
42173
  defaultSize = elementFactory.getDefaultSize(shape),
42030
42174
  newBounds;
@@ -42179,12 +42323,31 @@
42179
42323
  * @typedef {import('../Modeling').default} Modeling
42180
42324
  */
42181
42325
 
42182
- var LOW_PRIORITY$d = 500,
42183
- HIGH_PRIORITY$d = 5000;
42326
+ var LOW_PRIORITY$e = 500,
42327
+ HIGH_PRIORITY$e = 5000;
42328
+
42329
+ // Commands that provide a shape whose lane references must be updated.
42330
+ var laneRefShapeEvents = [
42331
+ 'shape.create',
42332
+ 'shape.delete',
42333
+ 'shape.move',
42334
+ 'shape.resize'
42335
+ ];
42184
42336
 
42337
+ // Commands that bracket a complete lane reference update, including nested commands.
42338
+ var laneRefUpdateEvents = [
42339
+ ...laneRefShapeEvents,
42340
+ 'spaceTool',
42341
+ 'lane.add',
42342
+ 'lane.resize',
42343
+ 'lane.split',
42344
+ 'elements.create',
42345
+ 'elements.delete',
42346
+ 'elements.move'
42347
+ ];
42185
42348
 
42186
42349
  /**
42187
- * BPMN specific delete lane behavior.
42350
+ * Synchronizes lane flow node references after geometry changes.
42188
42351
  *
42189
42352
  * @param {EventBus} eventBus
42190
42353
  * @param {Modeling} modeling
@@ -42193,18 +42356,11 @@
42193
42356
 
42194
42357
  CommandInterceptor.call(this, eventBus);
42195
42358
 
42196
- /**
42197
- * Update Lane#flowNodeRefs and FlowNode#lanes with every flow node
42198
- * move/resize and lane move/resize. Groups elements to recompute containments
42199
- * as efficient as possible.
42200
- */
42201
-
42202
- // the update context
42203
42359
  var context;
42204
42360
 
42205
42361
 
42206
42362
  function initContext() {
42207
- context = context || new UpdateContext();
42363
+ context = context || new UpdateContext$1();
42208
42364
  context.enter();
42209
42365
 
42210
42366
  return context;
@@ -42236,40 +42392,26 @@
42236
42392
  }
42237
42393
 
42238
42394
 
42239
- var laneRefUpdateEvents = [
42240
- 'spaceTool',
42241
- 'lane.add',
42242
- 'lane.resize',
42243
- 'lane.split',
42244
- 'elements.create',
42245
- 'elements.delete',
42246
- 'elements.move',
42247
- 'shape.create',
42248
- 'shape.delete',
42249
- 'shape.move',
42250
- 'shape.resize'
42251
- ];
42252
-
42253
-
42254
- // listen to a lot of stuff to group lane updates
42255
-
42256
- this.preExecute(laneRefUpdateEvents, HIGH_PRIORITY$d, function(event) {
42395
+ /**
42396
+ * Sets up the context for lane reference updates before executing commands
42397
+ * that may affect them.
42398
+ */
42399
+ this.preExecute(laneRefUpdateEvents, HIGH_PRIORITY$e, function() {
42257
42400
  initContext();
42258
42401
  });
42259
42402
 
42260
- this.postExecuted(laneRefUpdateEvents, LOW_PRIORITY$d, function(event) {
42403
+ /**
42404
+ * Releases the context for lane reference updates after executing commands
42405
+ * that may affect them.
42406
+ */
42407
+ this.postExecuted(laneRefUpdateEvents, LOW_PRIORITY$e, function() {
42261
42408
  releaseContext();
42262
42409
  });
42263
42410
 
42264
-
42265
- // Mark flow nodes + lanes that need an update
42266
-
42267
- this.preExecute([
42268
- 'shape.create',
42269
- 'shape.move',
42270
- 'shape.delete',
42271
- 'shape.resize'
42272
- ], function(event) {
42411
+ /**
42412
+ * Handles updates to lane references for shapes.
42413
+ */
42414
+ this.preExecute(laneRefShapeEvents, function(event) {
42273
42415
 
42274
42416
  var context = event.context,
42275
42417
  shape = context.shape;
@@ -42277,7 +42419,7 @@
42277
42419
  var updateContext = getContext();
42278
42420
 
42279
42421
  // no need to update labels
42280
- if (shape.labelTarget) {
42422
+ if (!shape || shape.labelTarget) {
42281
42423
  return;
42282
42424
  }
42283
42425
 
@@ -42299,7 +42441,7 @@
42299
42441
  e$3(UpdateFlowNodeRefsBehavior, CommandInterceptor);
42300
42442
 
42301
42443
 
42302
- function UpdateContext() {
42444
+ function UpdateContext$1() {
42303
42445
 
42304
42446
  this.flowNodes = [];
42305
42447
  this.lanes = [];
@@ -42325,6 +42467,168 @@
42325
42467
  };
42326
42468
  }
42327
42469
 
42470
+ /**
42471
+ * @typedef {import('diagram-js/lib/core/EventBus').default} EventBus
42472
+ * @typedef {import('../Modeling').default} Modeling
42473
+ */
42474
+
42475
+ var LOW_PRIORITY$d = 500,
42476
+ HIGH_PRIORITY$d = 5000;
42477
+
42478
+ // Commands that provide a shape or connection whose references must be updated.
42479
+ var categoryValueRefShapeAndConnectionEvents = [
42480
+ 'connection.create',
42481
+ 'connection.delete',
42482
+ 'connection.layout',
42483
+ 'connection.move',
42484
+ 'connection.reconnect',
42485
+ 'connection.updateWaypoints',
42486
+ 'shape.create',
42487
+ 'shape.delete',
42488
+ 'shape.move',
42489
+ 'shape.resize'
42490
+ ];
42491
+
42492
+ // Commands that bracket a complete reference update, including nested commands.
42493
+ var categoryValueRefUpdateEvents = [
42494
+ ...categoryValueRefShapeAndConnectionEvents,
42495
+ 'elements.create',
42496
+ 'elements.delete',
42497
+ 'elements.move',
42498
+ 'label.create',
42499
+ 'spaceTool'
42500
+ ];
42501
+
42502
+ /**
42503
+ * Synchronizes group category references after geometry changes.
42504
+ *
42505
+ * @param {EventBus} eventBus
42506
+ * @param {Modeling} modeling
42507
+ */
42508
+ function UpdateCategoryValueRefsBehavior(eventBus, modeling) {
42509
+
42510
+ CommandInterceptor.call(this, eventBus);
42511
+
42512
+ var context;
42513
+
42514
+ function initContext() {
42515
+ context = context || new UpdateContext();
42516
+ context.enter();
42517
+
42518
+ return context;
42519
+ }
42520
+
42521
+ function getContext() {
42522
+ if (!context) {
42523
+ throw new Error('out of bounds release');
42524
+ }
42525
+
42526
+ return context;
42527
+ }
42528
+
42529
+ function releaseContext() {
42530
+ if (!context) {
42531
+ throw new Error('out of bounds release');
42532
+ }
42533
+
42534
+ var triggerUpdate = context.leave();
42535
+
42536
+ if (triggerUpdate) {
42537
+ modeling.updateCategoryValueRefs(
42538
+ Array.from(context.affectedFlowElements),
42539
+ Array.from(context.affectedGroupEntries.values())
42540
+ );
42541
+
42542
+ context = null;
42543
+ }
42544
+
42545
+ return triggerUpdate;
42546
+ }
42547
+
42548
+ /**
42549
+ * Sets up the context for category value reference updates before executing
42550
+ * commands that may affect them.
42551
+ */
42552
+ this.preExecute(categoryValueRefUpdateEvents, HIGH_PRIORITY$d, function() {
42553
+ initContext();
42554
+ });
42555
+
42556
+ /**
42557
+ * Releases the context for category value reference updates after executing
42558
+ * commands that may affect them.
42559
+ */
42560
+ this.postExecuted(categoryValueRefUpdateEvents, LOW_PRIORITY$d, function() {
42561
+ releaseContext();
42562
+ });
42563
+
42564
+ /**
42565
+ * Handles updates to category value references for shapes and connections.
42566
+ */
42567
+ this.preExecute(categoryValueRefShapeAndConnectionEvents, function(event) {
42568
+ var shape = event.context.connection || event.context.shape,
42569
+ updateContext = getContext();
42570
+
42571
+ if (!shape || shape.labelTarget) {
42572
+ return;
42573
+ }
42574
+
42575
+ if (is(shape, 'bpmn:FlowElement')) {
42576
+ updateContext.addFlowElement(shape);
42577
+ }
42578
+
42579
+ if (is(shape, 'bpmn:Group')) {
42580
+ updateContext.addGroup(shape);
42581
+ }
42582
+ });
42583
+
42584
+ this.preExecute('label.create', function(event) {
42585
+ var labelTarget = event.context.labelTarget;
42586
+
42587
+ if (is(labelTarget, 'bpmn:Group')) {
42588
+ getContext().addGroup(labelTarget);
42589
+ }
42590
+ });
42591
+ }
42592
+
42593
+ UpdateCategoryValueRefsBehavior.$inject = [
42594
+ 'eventBus',
42595
+ 'modeling'
42596
+ ];
42597
+
42598
+ e$3(UpdateCategoryValueRefsBehavior, CommandInterceptor);
42599
+
42600
+
42601
+ function UpdateContext() {
42602
+
42603
+ this.affectedFlowElements = new Set();
42604
+ this.affectedGroupEntries = new Map();
42605
+
42606
+ this.counter = 0;
42607
+
42608
+ this.addFlowElement = function(flowElement) {
42609
+ this.affectedFlowElements.add(flowElement);
42610
+ };
42611
+
42612
+ this.addGroup = function(group) {
42613
+ if (!this.affectedGroupEntries.has(group)) {
42614
+ this.affectedGroupEntries.set(group, {
42615
+ categoryValue: group.businessObject.categoryValueRef,
42616
+ groupShape: group
42617
+ });
42618
+ }
42619
+ };
42620
+
42621
+ this.enter = function() {
42622
+ this.counter++;
42623
+ };
42624
+
42625
+ this.leave = function() {
42626
+ this.counter--;
42627
+
42628
+ return !this.counter;
42629
+ };
42630
+ }
42631
+
42328
42632
  /**
42329
42633
  * @typedef {import('diagram-js/lib/core/EventBus').default} EventBus
42330
42634
  * @typedef {import('../../rules/BpmnRules').default} BpmnRules
@@ -42396,6 +42700,7 @@
42396
42700
  'associationBehavior',
42397
42701
  'attachEventBehavior',
42398
42702
  'boundaryEventBehavior',
42703
+ 'categoryRootElementReferenceBehavior',
42399
42704
  'compensateBoundaryEventBehaviour',
42400
42705
  'createBehavior',
42401
42706
  'createDataObjectBehavior',
@@ -42430,6 +42735,7 @@
42430
42735
  'toggleElementCollapseBehaviour',
42431
42736
  'unclaimIdBehavior',
42432
42737
  'updateFlowNodeRefsBehavior',
42738
+ 'updateCategoryValueRefsBehavior',
42433
42739
  'unsetDefaultFlowBehavior',
42434
42740
  'setCompensationActivityAfterPasteBehavior'
42435
42741
  ],
@@ -42439,6 +42745,7 @@
42439
42745
  attachEventBehavior: [ 'type', AttachEventBehavior ],
42440
42746
  artifactBehavior: [ 'type', ArtifactBehavior ],
42441
42747
  boundaryEventBehavior: [ 'type', BoundaryEventBehavior ],
42748
+ categoryRootElementReferenceBehavior: [ 'type', CategoryRootElementReferenceBehavior ],
42442
42749
  compensateBoundaryEventBehaviour: [ 'type', CompensateBoundaryEventBehavior ],
42443
42750
  createBehavior: [ 'type', CreateBehavior ],
42444
42751
  createDataObjectBehavior: [ 'type', CreateDataObjectBehavior ],
@@ -42474,6 +42781,7 @@
42474
42781
  unclaimIdBehavior: [ 'type', UnclaimIdBehavior ],
42475
42782
  unsetDefaultFlowBehavior: [ 'type', DeleteSequenceFlowBehavior ],
42476
42783
  updateFlowNodeRefsBehavior: [ 'type', UpdateFlowNodeRefsBehavior ],
42784
+ updateCategoryValueRefsBehavior: [ 'type', UpdateCategoryValueRefsBehavior ],
42477
42785
  setCompensationActivityAfterPasteBehavior: [ 'type', SetCompensationActivityAfterPasteBehavior ]
42478
42786
  };
42479
42787
 
@@ -43652,9 +43960,47 @@
43652
43960
  return false;
43653
43961
  }
43654
43962
 
43963
+ // do not copy message flows unless both connected participants are copied,
43964
+ // too; otherwise they would end up in an invalid organizational context
43965
+ if (is(element, 'bpmn:MessageFlow') && !canCopyMessageFlow(elements, element)) {
43966
+ return false;
43967
+ }
43968
+
43655
43969
  return true;
43656
43970
  }
43657
43971
 
43972
+ /**
43973
+ * A message flow may only be copied if both of its participants are copied,
43974
+ * too. Otherwise it would be pasted into an invalid organizational context,
43975
+ * e.g. a plain process.
43976
+ *
43977
+ * @param {Element[]} elements
43978
+ * @param {Connection} connection
43979
+ *
43980
+ * @return {boolean}
43981
+ */
43982
+ function canCopyMessageFlow(elements, connection) {
43983
+ var sourceParticipant = getParticipant(connection.source),
43984
+ targetParticipant = getParticipant(connection.target);
43985
+
43986
+ return includes$2(elements, sourceParticipant) && includes$2(elements, targetParticipant);
43987
+ }
43988
+
43989
+ /**
43990
+ * @param {Element} element
43991
+ *
43992
+ * @return {Element|null}
43993
+ */
43994
+ function getParticipant(element) {
43995
+ for (; element; element = element.parent) {
43996
+ if (is(element, 'bpmn:Participant')) {
43997
+ return element;
43998
+ }
43999
+ }
44000
+
44001
+ return null;
44002
+ }
44003
+
43658
44004
  /**
43659
44005
  * @param {Element} element
43660
44006
  *
@@ -53559,8 +53905,6 @@
53559
53905
  /**
53560
53906
  * @typedef {import('diagram-js/lib/command/CommandHandler').default} CommandHandler
53561
53907
  *
53562
- * @typedef {import('diagram-js/lib/core/ElementRegistry').default} ElementRegistry
53563
- *
53564
53908
  * @typedef {import('../../../model/Types').Shape} Shape
53565
53909
  */
53566
53910
 
@@ -53573,15 +53917,9 @@
53573
53917
  *
53574
53918
  * @implements {CommandHandler}
53575
53919
  *
53576
- * @param {ElementRegistry} elementRegistry
53577
53920
  */
53578
- function UpdateFlowNodeRefsHandler(elementRegistry) {
53579
- this._elementRegistry = elementRegistry;
53580
- }
53921
+ function UpdateFlowNodeRefsHandler() {}
53581
53922
 
53582
- UpdateFlowNodeRefsHandler.$inject = [
53583
- 'elementRegistry'
53584
- ];
53585
53923
 
53586
53924
  /**
53587
53925
  * @param {Shape} flowNodeShapes
@@ -53757,6 +54095,409 @@
53757
54095
  return [];
53758
54096
  };
53759
54097
 
54098
+ /**
54099
+ * @typedef {import('diagram-js/lib/command/CommandHandler').default} CommandHandler
54100
+ * @typedef {import('diagram-js/lib/core/ElementRegistry').default} ElementRegistry
54101
+ * @typedef {import('../BpmnFactory').default} BpmnFactory
54102
+ *
54103
+ * @typedef {import('../../../model/Types').Element} Element
54104
+ * @typedef {import('../../../model/Types').ModdleElement} ModdleElement
54105
+ *
54106
+ * @typedef { {
54107
+ * categoryValue: ModdleElement;
54108
+ * root?: Element;
54109
+ * } } CategoryGroupEntry
54110
+ */
54111
+
54112
+ var CATEGORY_VALUE_REFS_ATTR = 'categoryValueRef';
54113
+
54114
+
54115
+ /**
54116
+ * Updates category value references for flow elements visually enclosed by groups.
54117
+ *
54118
+ * A flow element is grouped only when it shares the group's diagram root and
54119
+ * is geometrically enclosed by the group. Consequently, visible children of an
54120
+ * expanded subprocess are grouped, while children of a collapsed subprocess
54121
+ * are not.
54122
+ *
54123
+ * Groups without a category value are auto-healed: if such a group visually
54124
+ * encloses an affected flow element a category value is created for it on the
54125
+ * fly, so that legacy diagrams (groups modeled without a category value) start
54126
+ * to categorize their contents as soon as they are interacted with.
54127
+ *
54128
+ * @implements {CommandHandler}
54129
+ *
54130
+ * @param {BpmnFactory} bpmnFactory
54131
+ * @param {ElementRegistry} elementRegistry
54132
+ */
54133
+ function UpdateCategoryValueRefsHandler(bpmnFactory, elementRegistry) {
54134
+ this._bpmnFactory = bpmnFactory;
54135
+ this._elementRegistry = elementRegistry;
54136
+ }
54137
+
54138
+ UpdateCategoryValueRefsHandler.$inject = [
54139
+ 'bpmnFactory',
54140
+ 'elementRegistry'
54141
+ ];
54142
+
54143
+
54144
+ /**
54145
+ * @param { Element[] } affectedFlowElements
54146
+ * @param { {
54147
+ * categoryValue: ModdleElement;
54148
+ * groupShape: Element;
54149
+ * }[] } affectedGroupEntries
54150
+ *
54151
+ * @return { {
54152
+ * flowElements: {
54153
+ * businessObject: ModdleElement;
54154
+ * categoryValuesToAdd: ModdleElement[];
54155
+ * categoryValuesToRemove: ModdleElement[];
54156
+ * }[];
54157
+ * groups: {
54158
+ * groupShape: Element;
54159
+ * categoryValue: ModdleElement;
54160
+ * category: ModdleElement;
54161
+ * }[];
54162
+ * } }
54163
+ */
54164
+ UpdateCategoryValueRefsHandler.prototype._computeUpdates = function(affectedFlowElements, affectedGroupEntries) {
54165
+ var elementRegistry = this._elementRegistry,
54166
+ bpmnFactory = this._bpmnFactory;
54167
+
54168
+ /** @type {Map<Element, ModdleElement>} */
54169
+ var flowElementBusinessObjects = new Map();
54170
+
54171
+ var groupUpdates = [];
54172
+
54173
+ /**
54174
+ * @type {Map<Element, {
54175
+ * present?: CategoryGroupEntry;
54176
+ * past?: CategoryGroupEntry;
54177
+ * }>}
54178
+ */
54179
+ var categoryGroups = new Map();
54180
+
54181
+ /**
54182
+ * Adds a group to the list of groups to consider for category value updates.
54183
+ *
54184
+ * @param {Element} groupShape
54185
+ * @param {ModdleElement} categoryValue
54186
+ * @param {boolean} isPresent
54187
+ */
54188
+ function addGroup(groupShape, categoryValue, isPresent) {
54189
+ if (!categoryValue) {
54190
+ return;
54191
+ }
54192
+
54193
+ var categoryGroup = categoryGroups.get(groupShape);
54194
+
54195
+ if (!categoryGroup) {
54196
+ categoryGroup = {};
54197
+ categoryGroups.set(groupShape, categoryGroup);
54198
+ }
54199
+
54200
+ if (isPresent && categoryGroup.present) {
54201
+ return;
54202
+ }
54203
+
54204
+ if (!isPresent && categoryGroup.past) {
54205
+ return;
54206
+ }
54207
+
54208
+ if (isPresent) {
54209
+ categoryGroup.present = {
54210
+ categoryValue: categoryValue,
54211
+ root: getRoot(groupShape)
54212
+ };
54213
+ } else {
54214
+ categoryGroup.past = {
54215
+ categoryValue: categoryValue
54216
+ };
54217
+ }
54218
+ }
54219
+
54220
+ /**
54221
+ * Adds a flow element to the list of flow elements to consider for category
54222
+ * value updates.
54223
+ *
54224
+ * @param {Element} flowElement
54225
+ */
54226
+ function addFlowElement(flowElement) {
54227
+ flowElementBusinessObjects.set(
54228
+ flowElement,
54229
+ getBusinessObject(flowElement)
54230
+ );
54231
+ }
54232
+
54233
+ /**
54234
+ * Adds all flow elements on the diagram to the list of flow elements to
54235
+ * consider; skips root elements (e.g. sub process planes) which share a
54236
+ * business object with their collapsed shape but carry no diagram position.
54237
+ */
54238
+ function addAllFlowElements() {
54239
+ elementRegistry.filter(function(element) {
54240
+ return is(element, 'bpmn:FlowElement') && !isLabel(element) && element.parent;
54241
+ }).forEach(addFlowElement);
54242
+ }
54243
+
54244
+ /**
54245
+ * Returns a group's category value, creating one on the fly for
54246
+ * legacy groups modeled without one. Retrieving the value in order to
54247
+ * reference it materializes it; the fresh value is recorded as a heal so
54248
+ * CategoryRootElementReferenceBehavior can maintain its root element.
54249
+ *
54250
+ * @param {Element} groupShape
54251
+ *
54252
+ * @return {ModdleElement}
54253
+ */
54254
+ function getCategoryValue(groupShape) {
54255
+ var groupBo = getBusinessObject(groupShape),
54256
+ categoryValue = groupBo.get('categoryValueRef');
54257
+
54258
+ if (!categoryValue) {
54259
+ categoryValue = getOrCreateCategoryValueForGroup(bpmnFactory, groupBo);
54260
+
54261
+ groupUpdates.push(createGroupUpdate(groupShape, categoryValue));
54262
+ }
54263
+
54264
+ return categoryValue;
54265
+ }
54266
+
54267
+ function getElementsByRoot(elements) {
54268
+ return elements.reduce(function(elementsByRoot, element) {
54269
+ var root = getRoot(element),
54270
+ elementsInRoot = elementsByRoot.get(root);
54271
+
54272
+ if (!elementsInRoot) {
54273
+ elementsInRoot = [];
54274
+ elementsByRoot.set(root, elementsInRoot);
54275
+ }
54276
+
54277
+ elementsInRoot.push(element);
54278
+
54279
+ return elementsByRoot;
54280
+ }, new Map());
54281
+ }
54282
+
54283
+ affectedFlowElements = Array.from(affectedFlowElements || []);
54284
+
54285
+ var affectedFlowElementsByRoot = getElementsByRoot(affectedFlowElements);
54286
+
54287
+ // when a group is moved, resized, added or removed, the category value
54288
+ // references of all flow elements must be rechecked
54289
+ if (affectedGroupEntries.length) {
54290
+ addAllFlowElements();
54291
+ }
54292
+
54293
+ // flow elements that were genuinely moved or created; unrelated groups
54294
+ // will not be touched
54295
+ affectedFlowElements.forEach(addFlowElement);
54296
+
54297
+ // add all present groups to the list of groups to consider for category
54298
+ // value updates, auto-healing legacy groups only when an affected flow
54299
+ // element moves into them
54300
+ elementRegistry.filter(function(element) {
54301
+ return is(element, 'bpmn:Group') && !isLabel(element) && element.parent;
54302
+ }).forEach(function(groupShape) {
54303
+ var categoryValue = getBusinessObject(groupShape).get('categoryValueRef');
54304
+
54305
+ if (!categoryValue) {
54306
+ var groupRoot = getRoot(groupShape),
54307
+ affectedFlowElementsInRoot = affectedFlowElementsByRoot.get(groupRoot) || [],
54308
+ enclosedAffectedFlowElements = getEnclosedElements(
54309
+ affectedFlowElementsInRoot,
54310
+ groupShape
54311
+ ),
54312
+ enclosesAffectedFlowElement = Object.keys(enclosedAffectedFlowElements).length > 0;
54313
+
54314
+ if (enclosesAffectedFlowElement) {
54315
+ categoryValue = getCategoryValue(groupShape);
54316
+ }
54317
+ }
54318
+
54319
+ addGroup(groupShape, categoryValue, true);
54320
+ });
54321
+
54322
+ affectedGroupEntries.forEach(function(groupEntry) {
54323
+ addGroup(groupEntry.groupShape, groupEntry.categoryValue, false);
54324
+ });
54325
+
54326
+ // a healed group receives a fresh category value; recheck all flow elements
54327
+ // so that everything it visually encloses is tagged consistently, not just
54328
+ // the flow element that triggered the healing
54329
+ if (groupUpdates.length) {
54330
+ addAllFlowElements();
54331
+ }
54332
+
54333
+ var flowElements = Array.from(flowElementBusinessObjects.keys());
54334
+
54335
+ var managedCategoryValues = Array.from(categoryGroups.values()).reduce(function(set, group) {
54336
+ if (group.present) {
54337
+ set.add(group.present.categoryValue);
54338
+ }
54339
+
54340
+ if (group.past) {
54341
+ set.add(group.past.categoryValue);
54342
+ }
54343
+
54344
+ return set;
54345
+ }, new Set());
54346
+
54347
+ var categoryValuesByFlowElement = new Map(),
54348
+ flowElementsByRoot = getElementsByRoot(flowElements);
54349
+
54350
+ // Containment is calculated once per group and diagram root. This avoids
54351
+ // allocating an enclosure result for every flow element / group pair.
54352
+ categoryGroups.forEach(function(categoryGroup, groupShape) {
54353
+ var presentGroup = categoryGroup.present;
54354
+
54355
+ if (!presentGroup) {
54356
+ return;
54357
+ }
54358
+
54359
+ var flowElementsInRoot = flowElementsByRoot.get(presentGroup.root) || [],
54360
+ enclosedFlowElements = getEnclosedElements(flowElementsInRoot, groupShape);
54361
+
54362
+ flowElementsInRoot.forEach(function(flowElement) {
54363
+ if (!enclosedFlowElements[flowElement.id]) {
54364
+ return;
54365
+ }
54366
+
54367
+ var categoryValues = categoryValuesByFlowElement.get(flowElement);
54368
+
54369
+ if (!categoryValues) {
54370
+ categoryValues = new Set();
54371
+ categoryValuesByFlowElement.set(flowElement, categoryValues);
54372
+ }
54373
+
54374
+ categoryValues.add(presentGroup.categoryValue);
54375
+ });
54376
+ });
54377
+
54378
+ // compute updates for all flow elements based on the groups they are inside
54379
+ var flowElementUpdates = flowElements.reduce(function(flowElementUpdates, flowElement) {
54380
+ var flowElementBo = flowElementBusinessObjects.get(flowElement),
54381
+ categoryValueRefs = flowElementBo.get(CATEGORY_VALUE_REFS_ATTR),
54382
+ categoryValueRefSet = new Set(categoryValueRefs),
54383
+ enclosingCategoryValues = categoryValuesByFlowElement.get(flowElement) || new Set(),
54384
+ categoryValuesToAdd = Array.from(enclosingCategoryValues).filter(function(categoryValue) {
54385
+ return !categoryValueRefSet.has(categoryValue);
54386
+ }),
54387
+ categoryValuesToRemove = categoryValueRefs.filter(function(categoryValue) {
54388
+ return managedCategoryValues.has(categoryValue) &&
54389
+ !enclosingCategoryValues.has(categoryValue);
54390
+ });
54391
+
54392
+ if (categoryValuesToAdd.length || categoryValuesToRemove.length) {
54393
+ flowElementUpdates.push({
54394
+ businessObject: flowElementBo,
54395
+ categoryValuesToAdd,
54396
+ categoryValuesToRemove
54397
+ });
54398
+ }
54399
+
54400
+ return flowElementUpdates;
54401
+ }, []);
54402
+
54403
+ return {
54404
+ flowElements: flowElementUpdates,
54405
+ groups: groupUpdates
54406
+ };
54407
+ };
54408
+
54409
+
54410
+ UpdateCategoryValueRefsHandler.prototype.execute = function(context) {
54411
+ var updates = context.updates;
54412
+
54413
+ if (!updates) {
54414
+ updates = context.updates = this._computeUpdates(
54415
+ context.affectedFlowElements,
54416
+ context.affectedGroupEntries
54417
+ );
54418
+ }
54419
+
54420
+ // set auto-healed category values first so that flow element updates can
54421
+ // reference them; root element linking is handled by
54422
+ // CategoryRootElementReferenceBehavior
54423
+ applyGroupUpdates(updates.groups);
54424
+
54425
+ applyFlowElementUpdates(updates.flowElements);
54426
+
54427
+ return [];
54428
+ };
54429
+
54430
+
54431
+ UpdateCategoryValueRefsHandler.prototype.revert = function(context) {
54432
+ var updates = context.updates;
54433
+
54434
+ revertFlowElementUpdates(updates.flowElements);
54435
+
54436
+ revertGroupUpdates(updates.groups);
54437
+
54438
+ return [];
54439
+ };
54440
+
54441
+
54442
+ function createGroupUpdate(groupShape, categoryValue) {
54443
+ return {
54444
+ groupShape: groupShape,
54445
+ categoryValue: categoryValue,
54446
+ category: categoryValue.$parent
54447
+ };
54448
+ }
54449
+
54450
+ function applyGroupUpdates(groupUpdates) {
54451
+ groupUpdates.forEach(function(groupUpdate) {
54452
+ getBusinessObject(groupUpdate.groupShape).categoryValueRef = groupUpdate.categoryValue;
54453
+ groupUpdate.categoryValue.$parent = groupUpdate.category;
54454
+ });
54455
+ }
54456
+
54457
+ function revertGroupUpdates(groupUpdates) {
54458
+ groupUpdates.forEach(function(groupUpdate) {
54459
+ getBusinessObject(groupUpdate.groupShape).categoryValueRef = null;
54460
+ });
54461
+ }
54462
+
54463
+ function applyFlowElementUpdates(flowElementUpdates) {
54464
+ flowElementUpdates.forEach(function(flowElementUpdate) {
54465
+ var businessObject = flowElementUpdate.businessObject,
54466
+ categoryValueRefs = businessObject.get(CATEGORY_VALUE_REFS_ATTR);
54467
+
54468
+ flowElementUpdate.categoryValuesToRemove.forEach(function(categoryValue) {
54469
+ remove(categoryValueRefs, categoryValue);
54470
+ });
54471
+
54472
+ flowElementUpdate.categoryValuesToAdd.forEach(function(categoryValue) {
54473
+ add(categoryValueRefs, categoryValue, true);
54474
+ });
54475
+ });
54476
+ }
54477
+
54478
+ function revertFlowElementUpdates(flowElementUpdates) {
54479
+ flowElementUpdates.forEach(function(flowElementUpdate) {
54480
+ var businessObject = flowElementUpdate.businessObject,
54481
+ categoryValueRefs = businessObject.get(CATEGORY_VALUE_REFS_ATTR);
54482
+
54483
+ flowElementUpdate.categoryValuesToAdd.forEach(function(categoryValue) {
54484
+ remove(categoryValueRefs, categoryValue);
54485
+ });
54486
+
54487
+ flowElementUpdate.categoryValuesToRemove.forEach(function(categoryValue) {
54488
+ add(categoryValueRefs, categoryValue, true);
54489
+ });
54490
+ });
54491
+ }
54492
+
54493
+ function getRoot(element) {
54494
+ while (element.parent) {
54495
+ element = element.parent;
54496
+ }
54497
+
54498
+ return element;
54499
+ }
54500
+
53760
54501
  /**
53761
54502
  * @typedef {import('diagram-js/lib/command/CommandHandler').default} CommandHandler
53762
54503
  *
@@ -54117,6 +54858,11 @@
54117
54858
  * @typedef { {
54118
54859
  * removeShape?: boolean;
54119
54860
  * } } UpdateLabelHints
54861
+ *
54862
+ * @typedef { {
54863
+ * categoryValue?: ModdleElement;
54864
+ * groupShape: Shape;
54865
+ * } } GroupEntry
54120
54866
  */
54121
54867
 
54122
54868
  /**
@@ -54167,6 +54913,7 @@
54167
54913
  handlers['lane.resize'] = ResizeLaneHandler;
54168
54914
  handlers['lane.split'] = SplitLaneHandler;
54169
54915
  handlers['lane.updateRefs'] = UpdateFlowNodeRefsHandler;
54916
+ handlers['group.updateRefs'] = UpdateCategoryValueRefsHandler;
54170
54917
  handlers['id.updateClaim'] = IdClaimHandler;
54171
54918
  handlers['element.setColor'] = SetColorHandler;
54172
54919
  handlers['element.updateLabel'] = UpdateLabelHandler;
@@ -54344,6 +55091,20 @@
54344
55091
  });
54345
55092
  };
54346
55093
 
55094
+ /**
55095
+ * Update the referenced category values of each flow element.
55096
+ *
55097
+ * @param {Element[]} affectedFlowElements The flow elements to update.
55098
+ * @param {GroupEntry[]} affectedGroupEntries The groups to update.
55099
+ */
55100
+ Modeling.prototype.updateCategoryValueRefs = function(affectedFlowElements, affectedGroupEntries) {
55101
+
55102
+ this._commandStack.execute('group.updateRefs', {
55103
+ affectedFlowElements: affectedFlowElements,
55104
+ affectedGroupEntries: affectedGroupEntries
55105
+ });
55106
+ };
55107
+
54347
55108
  /**
54348
55109
  * Claim an ID.
54349
55110
  *
@@ -62350,6 +63111,13 @@
62350
63111
  * @param {Element} element
62351
63112
  */
62352
63113
  function createElementOutline(element) {
63114
+
63115
+ // root elements have no outline; creating one would append a never-updated
63116
+ // rect to the untransformed root layer, polluting getActiveLayer().getBBox()
63117
+ if (isRoot(element)) {
63118
+ return;
63119
+ }
63120
+
62353
63121
  self.createOutline(element);
62354
63122
  }
62355
63123