bpmn-js 18.19.0 → 18.20.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.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * bpmn-js - bpmn-modeler v18.19.0
2
+ * bpmn-js - bpmn-modeler v18.20.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-06-24
11
+ * Date: 2026-07-06
12
12
  */
13
13
  (function (global, factory) {
14
14
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
@@ -2825,48 +2825,22 @@
2825
2825
  */
2826
2826
  function getParents$1(elements) {
2827
2827
 
2828
+ var elementsSet = new Set(elements);
2829
+
2828
2830
  // find elements that are not children of any other elements
2829
2831
  return filter(elements, function(element) {
2830
- return !find(elements, function(e) {
2831
- return e !== element && getParent$1(element, e);
2832
- });
2833
- });
2834
- }
2835
-
2836
-
2837
- function getParent$1(element, parent) {
2838
- if (!parent) {
2839
- return;
2840
- }
2841
-
2842
- if (element === parent) {
2843
- return parent;
2844
- }
2845
-
2846
- if (!element.parent) {
2847
- return;
2848
- }
2849
-
2850
- return getParent$1(element.parent, parent);
2851
- }
2852
-
2832
+ var parent = element.parent;
2853
2833
 
2854
- /**
2855
- * Adds an element to a collection and returns true if the
2856
- * element was added.
2857
- *
2858
- * @param {Object[]} elements
2859
- * @param {Object} element
2860
- * @param {boolean} [unique]
2861
- */
2862
- function add$1(elements, element, unique) {
2863
- var canAdd = !unique || elements.indexOf(element) === -1;
2834
+ while (parent) {
2835
+ if (elementsSet.has(parent)) {
2836
+ return false;
2837
+ }
2864
2838
 
2865
- if (canAdd) {
2866
- elements.push(element);
2867
- }
2839
+ parent = parent.parent;
2840
+ }
2868
2841
 
2869
- return canAdd;
2842
+ return true;
2843
+ });
2870
2844
  }
2871
2845
 
2872
2846
 
@@ -2901,18 +2875,20 @@
2901
2875
  /**
2902
2876
  * Collects self + child elements up to a given depth from a list of elements.
2903
2877
  *
2878
+ * The result is always a unique set of elements (no duplicates).
2879
+ *
2904
2880
  * @param {Element|Element[]} elements the elements to select the children from
2905
- * @param {boolean} unique whether to return a unique result set (no duplicates)
2881
+ * @param {boolean} [unique] deprecated, ignored; the result is always unique
2906
2882
  * @param {number} maxDepth the depth to search through or -1 for infinite
2907
2883
  *
2908
2884
  * @return {Element[]} found elements
2909
2885
  */
2910
2886
  function selfAndChildren(elements, unique, maxDepth) {
2911
- var result = [],
2912
- processedChildren = [];
2887
+ var result = new Set(),
2888
+ processedChildren = new Set();
2913
2889
 
2914
2890
  eachElement(elements, function(element, i, depth) {
2915
- add$1(result, element, unique);
2891
+ result.add(element);
2916
2892
 
2917
2893
  var children = element.children;
2918
2894
 
@@ -2920,26 +2896,30 @@
2920
2896
  {
2921
2897
 
2922
2898
  // children exist && children not yet processed
2923
- if (children && add$1(processedChildren, children, unique)) {
2899
+ if (children && !processedChildren.has(children)) {
2900
+ processedChildren.add(children);
2901
+
2924
2902
  return children;
2925
2903
  }
2926
2904
  }
2927
2905
  });
2928
2906
 
2929
- return result;
2907
+ return Array.from(result);
2930
2908
  }
2931
2909
 
2932
2910
 
2933
2911
  /**
2934
- * Return self + ALL children for a number of elements
2912
+ * Return self + ALL children for a number of elements.
2935
2913
  *
2936
- * @param {Element[]} elements to query
2937
- * @param {boolean} [allowDuplicates] to allow duplicates in the result set
2914
+ * The result is always a unique set of elements (no duplicates).
2915
+ *
2916
+ * @param {Element|Element[]} elements to query
2917
+ * @param {boolean} [allowDuplicates] deprecated, ignored; the result is always unique
2938
2918
  *
2939
2919
  * @return {Element[]} the collected elements
2940
2920
  */
2941
2921
  function selfAndAllChildren(elements, allowDuplicates) {
2942
- return selfAndChildren(elements, !allowDuplicates);
2922
+ return selfAndChildren(elements);
2943
2923
  }
2944
2924
 
2945
2925
 
@@ -8225,10 +8205,21 @@
8225
8205
 
8226
8206
  var childrenGfx = self._getChildrenContainer(parent);
8227
8207
 
8228
- forEach(children.slice().reverse(), function(child) {
8229
- var childGfx = elementRegistry.getGraphics(child);
8208
+ // only (re-)insert children that are not already in their expected
8209
+ // position; needlessly detaching and re-attaching siblings that did
8210
+ // not move breaks in-progress pointer interactions (the browser drops
8211
+ // the native `click` when the moused-down node is momentarily removed)
8212
+ // and causes unnecessary DOM churn
8213
+ var expected = childrenGfx.firstChild;
8214
+
8215
+ forEach(children, function(child) {
8216
+ var childGfx = elementRegistry.getGraphics(child).parentNode;
8230
8217
 
8231
- prependTo(childGfx.parentNode, childrenGfx);
8218
+ if (childGfx === expected) {
8219
+ expected = expected.nextSibling;
8220
+ } else {
8221
+ childrenGfx.insertBefore(childGfx, expected);
8222
+ }
8232
8223
  });
8233
8224
  });
8234
8225
  };
@@ -18356,7 +18347,7 @@
18356
18347
  function collectElementsAnnotations(elements) {
18357
18348
  const result = new Map();
18358
18349
 
18359
- forEach(selfAndChildren(elements, true), (element) => {
18350
+ forEach(selfAndChildren(elements), (element) => {
18360
18351
  forEach(getElementAnnotations(element), (entry) => {
18361
18352
  if (!result.has(entry.annotation)) {
18362
18353
  result.set(entry.annotation, { annotation: entry.annotation, associations: [] });
@@ -25027,9 +25018,9 @@
25027
25018
  this._canvas = canvas;
25028
25019
 
25029
25020
  /**
25030
- * @type {Object[]}
25021
+ * @type {Set<Object>}
25031
25022
  */
25032
- this._selectedElements = [];
25023
+ this._selectedElements = new Set();
25033
25024
 
25034
25025
  var self = this;
25035
25026
 
@@ -25051,17 +25042,18 @@
25051
25042
  * @param {Object} element The element to deselect.
25052
25043
  */
25053
25044
  Selection.prototype.deselect = function(element) {
25054
- var selectedElements = this._selectedElements;
25055
-
25056
- var idx = selectedElements.indexOf(element);
25045
+ if (!this._selectedElements.has(element)) {
25046
+ return;
25047
+ }
25057
25048
 
25058
- if (idx !== -1) {
25059
- var oldSelection = selectedElements.slice();
25049
+ var oldSelection = this.get();
25060
25050
 
25061
- selectedElements.splice(idx, 1);
25051
+ this._selectedElements.delete(element);
25062
25052
 
25063
- this._eventBus.fire('selection.changed', { oldSelection: oldSelection, newSelection: selectedElements });
25064
- }
25053
+ this._eventBus.fire('selection.changed', {
25054
+ oldSelection: oldSelection,
25055
+ newSelection: this.get()
25056
+ });
25065
25057
  };
25066
25058
 
25067
25059
  /**
@@ -25070,7 +25062,7 @@
25070
25062
  * @return {Object[]} The selected elements.
25071
25063
  */
25072
25064
  Selection.prototype.get = function() {
25073
- return this._selectedElements;
25065
+ return Array.from(this._selectedElements);
25074
25066
  };
25075
25067
 
25076
25068
  /**
@@ -25081,7 +25073,7 @@
25081
25073
  * @return {boolean} Whether the element is selected.
25082
25074
  */
25083
25075
  Selection.prototype.isSelected = function(element) {
25084
- return this._selectedElements.indexOf(element) !== -1;
25076
+ return this._selectedElements.has(element);
25085
25077
  };
25086
25078
 
25087
25079
 
@@ -25093,8 +25085,7 @@
25093
25085
  * Defaults to `false`.
25094
25086
  */
25095
25087
  Selection.prototype.select = function(elements, add) {
25096
- var selectedElements = this._selectedElements,
25097
- oldSelection = selectedElements.slice();
25088
+ var oldSelection = this.get();
25098
25089
 
25099
25090
  if (!isArray$2(elements)) {
25100
25091
  elements = elements ? [ elements ] : [];
@@ -25113,20 +25104,17 @@
25113
25104
  // selection may be cleared by passing an empty array or null
25114
25105
  // to the method
25115
25106
  if (add) {
25116
- forEach(elements, function(element) {
25117
- if (selectedElements.indexOf(element) !== -1) {
25118
-
25119
- // already selected
25120
- return;
25121
- } else {
25122
- selectedElements.push(element);
25123
- }
25107
+ forEach(elements, element => {
25108
+ this._selectedElements.add(element);
25124
25109
  });
25125
25110
  } else {
25126
- this._selectedElements = selectedElements = elements.slice();
25111
+ this._selectedElements = new Set(elements);
25127
25112
  }
25128
25113
 
25129
- this._eventBus.fire('selection.changed', { oldSelection: oldSelection, newSelection: selectedElements });
25114
+ this._eventBus.fire('selection.changed', {
25115
+ oldSelection: oldSelection,
25116
+ newSelection: this.get()
25117
+ });
25130
25118
  };
25131
25119
 
25132
25120
  /**
@@ -25177,20 +25165,20 @@
25177
25165
  addMarker(s, MARKER_SELECTED$1);
25178
25166
  }
25179
25167
 
25180
- var oldSelection = event.oldSelection,
25181
- newSelection = event.newSelection;
25168
+ var oldSelection = new Set(event.oldSelection),
25169
+ newSelection = new Set(event.newSelection);
25182
25170
 
25183
- forEach(oldSelection, function(e) {
25184
- if (newSelection.indexOf(e) === -1) {
25171
+ for (let e of oldSelection) {
25172
+ if (!newSelection.has(e)) {
25185
25173
  deselect(e);
25186
25174
  }
25187
- });
25175
+ }
25188
25176
 
25189
- forEach(newSelection, function(e) {
25190
- if (oldSelection.indexOf(e) === -1) {
25177
+ for (let e of newSelection) {
25178
+ if (!oldSelection.has(e)) {
25191
25179
  select(e);
25192
25180
  }
25193
- });
25181
+ }
25194
25182
  });
25195
25183
  }
25196
25184
 
@@ -27838,6 +27826,7 @@
27838
27826
  class=${ clsx('entry', { selected, disabled: entry.disabled }) }
27839
27827
  data-id=${ entry.id }
27840
27828
  title=${ entry.title }
27829
+ aria-label=${ entry.title || entry.label }
27841
27830
  aria-disabled=${ entry.disabled || undefined }
27842
27831
  tabIndex="0"
27843
27832
  onClick=${ handleClick }
@@ -27907,19 +27896,27 @@
27907
27896
  * @param {PopupMenuGroup[]} props.groupedEntries
27908
27897
  * @param {PopupMenuEntry} props.selectedEntry
27909
27898
  * @param {(entry: PopupMenuEntry | null) => void} props.setSelectedEntry
27899
+ * @param {import('@bpmn-io/diagram-js-ui').Ref<boolean>} props.keyboardSelection
27910
27900
  */
27911
27901
  function PopupMenuList(props) {
27912
27902
  const {
27913
27903
  selectedEntry,
27914
27904
  setSelectedEntry,
27915
27905
  groupedEntries,
27906
+ keyboardSelection,
27916
27907
  ...restProps
27917
27908
  } = props;
27918
27909
 
27919
27910
  const resultsRef = A();
27920
27911
 
27921
- // scroll to selected result
27912
+ // scroll selected entry into view when navigating by keyboard
27922
27913
  _(() => {
27914
+ if (!keyboardSelection || !keyboardSelection.current) {
27915
+ return;
27916
+ }
27917
+
27918
+ keyboardSelection.current = false;
27919
+
27923
27920
  const containerEl = resultsRef.current;
27924
27921
 
27925
27922
  if (!containerEl)
@@ -28080,6 +28077,13 @@
28080
28077
  const [ selectedEntry, setSelectedEntry ] = d(entriesToShow[0]);
28081
28078
  const restoreSelection = A(null);
28082
28079
 
28080
+ /**
28081
+ * Whether the current selection was made through keyboard navigation.
28082
+ *
28083
+ * @type {import('@bpmn-io/diagram-js-ui').Ref<boolean>}
28084
+ */
28085
+ const keyboardSelection = A(false);
28086
+
28083
28087
  y(() => {
28084
28088
  const restore = restoreSelection.current;
28085
28089
 
@@ -28107,15 +28111,21 @@
28107
28111
  nextIdx = 0;
28108
28112
  }
28109
28113
 
28114
+ keyboardSelection.current = true;
28115
+
28110
28116
  setSelectedEntry(entries[nextIdx]);
28111
28117
  }, [ groupedEntries, selectedEntry ]);
28112
28118
 
28113
28119
  const keyboardDrilldown = q((direction) => {
28114
28120
  if (direction > 0 && selectedEntry && selectedEntry.entries) {
28121
+ keyboardSelection.current = true;
28122
+
28115
28123
  setNavigationStack(stack => [ ...stack, selectedEntry ]);
28116
28124
  }
28117
28125
 
28118
28126
  if (direction < 0 && navigationStack.length > 0) {
28127
+ keyboardSelection.current = true;
28128
+
28119
28129
  restoreSelection.current = navigationStack[navigationStack.length + direction];
28120
28130
  setNavigationStack(stack => stack.slice(0, direction));
28121
28131
  }
@@ -28245,6 +28255,7 @@
28245
28255
  groupedEntries=${ groupedEntries }
28246
28256
  selectedEntry=${ selectedEntry }
28247
28257
  setSelectedEntry=${ setSelectedEntry }
28258
+ keyboardSelection=${ keyboardSelection }
28248
28259
  onAction=${ handleEntryAction }
28249
28260
  />
28250
28261
  </div>
@@ -32692,6 +32703,9 @@
32692
32703
 
32693
32704
  translate$1(floating, point.x, point.y);
32694
32705
 
32706
+ // mark as positioned so it may be shown; keeping it hidden until then
32707
+ // avoids a ghost bendpoint appearing at (0, 0)
32708
+ classes(floating).add('positioned');
32695
32709
  }
32696
32710
 
32697
32711
  function updateSegmentDraggerPosition(parentGfx, intersection, waypoints) {
@@ -32815,6 +32829,28 @@
32815
32829
  }
32816
32830
  });
32817
32831
 
32832
+ eventBus.on('element.out', function(event) {
32833
+ var element = event.element;
32834
+
32835
+ if (!element.waypoints) {
32836
+ return;
32837
+ }
32838
+
32839
+ var bendpointsGfx = getBendpointsContainer(element);
32840
+
32841
+ if (!bendpointsGfx) {
32842
+ return;
32843
+ }
32844
+
32845
+ // reset floating bendpoint so it does not re-appear at a stale position
32846
+ // before being re-positioned on the next element.mousemove
32847
+ var floating = query('.floating', bendpointsGfx);
32848
+
32849
+ if (floating) {
32850
+ classes(floating).remove('positioned');
32851
+ }
32852
+ });
32853
+
32818
32854
  // update bendpoint container data attribute on element ID change
32819
32855
  eventBus.on('element.updateId', function(context) {
32820
32856
  var element = context.element,
@@ -34770,14 +34806,10 @@
34770
34806
  gfx = gfx || this.getGfx(element);
34771
34807
 
34772
34808
  var dragger = clone(gfx);
34773
- var bbox = gfx.getBoundingClientRect();
34774
34809
 
34775
34810
  this._cloneMarkers(getVisual(dragger), className);
34776
34811
 
34777
- attr(dragger, this._styles.cls(className, [], {
34778
- x: bbox.top,
34779
- y: bbox.left
34780
- }));
34812
+ attr(dragger, this._styles.cls(className, []));
34781
34813
 
34782
34814
  append(group, dragger);
34783
34815
 
@@ -37204,7 +37236,7 @@
37204
37236
  shapes.forEach(function(shape, index) {
37205
37237
  var host = shape.host;
37206
37238
 
37207
- if (shouldReplace(shape, includes$6(shapes, host) ? host : newHost)) {
37239
+ if (shouldReplace(shape, includes$3(shapes, host) ? host : newHost)) {
37208
37240
  shapes[ index ] = self._replaceShape(shape);
37209
37241
  }
37210
37242
  });
@@ -37250,7 +37282,7 @@
37250
37282
  return !isLabel(shape) && is(shape, 'bpmn:BoundaryEvent') && !host;
37251
37283
  }
37252
37284
 
37253
- function includes$6(array, item) {
37285
+ function includes$3(array, item) {
37254
37286
  return array.indexOf(item) !== -1;
37255
37287
  }
37256
37288
 
@@ -37607,8 +37639,9 @@
37607
37639
  var rootElement = canvas.getRootElement();
37608
37640
 
37609
37641
  // ensure bpmn:Group and label elements are dropped
37610
- // always onto the root
37611
- if (hover !== rootElement && (shape.labelTarget || isAny(shape, [ 'bpmn:Group', 'bpmn:TextAnnotation' ]))) {
37642
+ // always onto the root; keep a missing hover (e.g. dropped outside
37643
+ // the canvas) untouched so it can be rejected by the rules
37644
+ if (hover && hover !== rootElement && (shape.labelTarget || isAny(shape, [ 'bpmn:Group', 'bpmn:TextAnnotation' ]))) {
37612
37645
  event.hover = rootElement;
37613
37646
  event.hoverGfx = elementRegistry.getGraphics(event.hover);
37614
37647
  }
@@ -39546,7 +39579,7 @@
39546
39579
  }
39547
39580
 
39548
39581
  function getMessageFlows(parent) {
39549
- var elements = selfAndAllChildren([ parent ], false);
39582
+ var elements = selfAndAllChildren([ parent ]);
39550
39583
 
39551
39584
  var incoming = [],
39552
39585
  outgoing = [];
@@ -41488,7 +41521,7 @@
41488
41521
  * @return {Element[]}
41489
41522
  */
41490
41523
  function getExternalLabels(element) {
41491
- return selfAndChildren(element.children || [], true)
41524
+ return selfAndChildren(element.children || [])
41492
41525
  .reduce(function(labels, child) {
41493
41526
  if (child.label && child.label.parent !== element) {
41494
41527
  labels.push(child.label);
@@ -43170,11 +43203,16 @@
43170
43203
  return false;
43171
43204
  }
43172
43205
 
43173
- // allow default move check to start move operation
43174
- if (!target) {
43206
+ // allow move to start when there is no target yet (`undefined`)
43207
+ if (target === undefined) {
43175
43208
  return true;
43176
43209
  }
43177
43210
 
43211
+ // disallow dropping outside the canvas (`null` target)
43212
+ if (target === null) {
43213
+ return false;
43214
+ }
43215
+
43178
43216
  return elements.every(function(element) {
43179
43217
  return canDrop(element, target);
43180
43218
  });
@@ -43399,7 +43437,7 @@
43399
43437
  *
43400
43438
  * @return {boolean}
43401
43439
  */
43402
- function includes$5(elements, element) {
43440
+ function includes$2(elements, element) {
43403
43441
  return (elements && element) && elements.indexOf(element) !== -1;
43404
43442
  }
43405
43443
 
@@ -43414,7 +43452,7 @@
43414
43452
  return true;
43415
43453
  }
43416
43454
 
43417
- if (is(element, 'bpmn:Lane') && !includes$5(elements, element.parent)) {
43455
+ if (is(element, 'bpmn:Lane') && !includes$2(elements, element.parent)) {
43418
43456
  return false;
43419
43457
  }
43420
43458
 
@@ -43465,7 +43503,7 @@
43465
43503
  elements,
43466
43504
  diElements;
43467
43505
 
43468
- elements = selfAndAllChildren([ root ], false);
43506
+ elements = selfAndAllChildren([ root ]);
43469
43507
 
43470
43508
  // only bpmndi:Shape and bpmndi:Edge can be direct children of bpmndi:Plane
43471
43509
  elements = filter(elements, function(element) {
@@ -44468,19 +44506,15 @@
44468
44506
  eventBus.on('copyPaste.copyElement', function(context) {
44469
44507
  var descriptor = context.descriptor,
44470
44508
  element = context.element,
44471
- elements = context.elements;
44509
+ elementsSet = context.elementsSet;
44472
44510
 
44473
44511
  // default priority (priority = 1)
44474
44512
  descriptor.priority = 1;
44475
44513
 
44476
44514
  descriptor.id = element.id;
44477
44515
 
44478
- var parentCopied = find(elements, function(e) {
44479
- return e === element.parent;
44480
- });
44481
-
44482
44516
  // do NOT reference parent if parent wasn't copied
44483
- if (parentCopied) {
44517
+ if (elementsSet.has(element.parent)) {
44484
44518
  descriptor.parent = element.parent.id;
44485
44519
  }
44486
44520
 
@@ -44832,31 +44866,29 @@
44832
44866
  };
44833
44867
 
44834
44868
  /**
44835
- * Check wether element has relations to other elements e.g. attachers, labels and connections.
44869
+ * Check whether element has relations to other elements e.g. attachers, labels and connections.
44836
44870
  *
44837
44871
  * @param {Object} element
44838
44872
  * @param {Element[]} elements
44873
+ * @param {Set<Element>} [elementsSet] pre-computed set of `elements`; pass it
44874
+ * to avoid a linear scan per invocation
44839
44875
  *
44840
44876
  * @return {boolean}
44841
44877
  */
44842
- CopyPaste.prototype.hasRelations = function(element, elements) {
44843
- var labelTarget,
44844
- source,
44845
- target;
44878
+ CopyPaste.prototype.hasRelations = function(element, elements, elementsSet) {
44846
44879
 
44847
- if (isConnection(element)) {
44848
- source = find(elements, matchPattern({ id: element.source.id }));
44849
- target = find(elements, matchPattern({ id: element.target.id }));
44880
+ if (!elementsSet) {
44881
+ elementsSet = new Set(elements);
44882
+ }
44850
44883
 
44851
- if (!source || !target) {
44884
+ if (isConnection(element)) {
44885
+ if (!elementsSet.has(element.source) || !elementsSet.has(element.target)) {
44852
44886
  return false;
44853
44887
  }
44854
44888
  }
44855
44889
 
44856
44890
  if (isLabel(element)) {
44857
- labelTarget = find(elements, matchPattern({ id: element.labelTarget.id }));
44858
-
44859
- if (!labelTarget) {
44891
+ if (!elementsSet.has(element.labelTarget)) {
44860
44892
  return false;
44861
44893
  }
44862
44894
  }
@@ -44895,6 +44927,9 @@
44895
44927
  var tree = {},
44896
44928
  elementsData = [];
44897
44929
 
44930
+ // O(1) lookup of already added element data during the add phase
44931
+ var elementsDataMap = new Map();
44932
+
44898
44933
  var parents = getParents$1(elements);
44899
44934
 
44900
44935
  function canCopy(element, elements) {
@@ -44906,17 +44941,18 @@
44906
44941
 
44907
44942
  function addElementData(element, depth) {
44908
44943
 
44909
- // (1) check wether element has already been added
44910
- var foundElementData = find(elementsData, function(elementsData) {
44911
- return element === elementsData.element;
44912
- });
44944
+ // (1) check whether element has already been added
44945
+ var foundElementData = elementsDataMap.get(element);
44913
44946
 
44914
44947
  // (2) add element if not already added
44915
44948
  if (!foundElementData) {
44916
- elementsData.push({
44949
+ var elementData = {
44917
44950
  element: element,
44918
44951
  depth: depth
44919
- });
44952
+ };
44953
+
44954
+ elementsData.push(elementData);
44955
+ elementsDataMap.set(element, elementData);
44920
44956
 
44921
44957
  return;
44922
44958
  }
@@ -44925,10 +44961,13 @@
44925
44961
  if (foundElementData.depth < depth) {
44926
44962
  elementsData = removeElementData(foundElementData, elementsData);
44927
44963
 
44928
- elementsData.push({
44964
+ var updatedElementData = {
44929
44965
  element: foundElementData.element,
44930
44966
  depth: depth
44931
- });
44967
+ };
44968
+
44969
+ elementsData.push(updatedElementData);
44970
+ elementsDataMap.set(element, updatedElementData);
44932
44971
  }
44933
44972
  }
44934
44973
 
@@ -44991,13 +45030,20 @@
44991
45030
  });
44992
45031
 
44993
45032
  // (2) copy elements
45033
+ //
45034
+ // build a Set of copied elements, kept in sync as unrelated elements are
45035
+ // pruned below, so both the `copyPaste.copyElement` listener and relation
45036
+ // checks resolve membership in O(1)
45037
+ var elementsSet = new Set(elements);
45038
+
44994
45039
  elementsData = map(elementsData, function(elementData) {
44995
45040
  elementData.descriptor = {};
44996
45041
 
44997
45042
  self._eventBus.fire('copyPaste.copyElement', {
44998
45043
  descriptor: elementData.descriptor,
44999
45044
  element: elementData.element,
45000
- elements: elements
45045
+ elements: elements,
45046
+ elementsSet: elementsSet
45001
45047
  });
45002
45048
 
45003
45049
  return elementData;
@@ -45016,14 +45062,16 @@
45016
45062
  forEach(elementsData, function(elementData) {
45017
45063
  var depth = elementData.depth;
45018
45064
 
45019
- if (!self.hasRelations(elementData.element, elements)) {
45065
+ if (!self.hasRelations(elementData.element, elements, elementsSet)) {
45020
45066
  removeElement(elementData.element, elements);
45067
+ elementsSet.delete(elementData.element);
45021
45068
 
45022
45069
  return;
45023
45070
  }
45024
45071
 
45025
45072
  if (!canCopy(elementData.element, elements)) {
45026
45073
  removeElement(elementData.element, elements);
45074
+ elementsSet.delete(elementData.element);
45027
45075
 
45028
45076
  return;
45029
45077
  }
@@ -46235,7 +46283,15 @@
46235
46283
  function getWaypointsUpdatingConnections(movingShapes, resizingShapes) {
46236
46284
  var waypointsUpdatingConnections = [];
46237
46285
 
46238
- forEach(movingShapes.concat(resizingShapes), function(shape) {
46286
+ var adjustedShapes = new Set(movingShapes);
46287
+
46288
+ forEach(resizingShapes, function(shape) {
46289
+ adjustedShapes.add(shape);
46290
+ });
46291
+
46292
+ var seenConnections = new Set();
46293
+
46294
+ adjustedShapes.forEach(function(shape) {
46239
46295
  var incoming = shape.incoming,
46240
46296
  outgoing = shape.outgoing;
46241
46297
 
@@ -46243,12 +46299,11 @@
46243
46299
  var source = connection.source,
46244
46300
  target = connection.target;
46245
46301
 
46246
- if (includes$4(movingShapes, source) ||
46247
- includes$4(movingShapes, target) ||
46248
- includes$4(resizingShapes, source) ||
46249
- includes$4(resizingShapes, target)) {
46302
+ if (adjustedShapes.has(source) || adjustedShapes.has(target)) {
46303
+
46304
+ if (!seenConnections.has(connection)) {
46305
+ seenConnections.add(connection);
46250
46306
 
46251
- if (!includes$4(waypointsUpdatingConnections, connection)) {
46252
46307
  waypointsUpdatingConnections.push(connection);
46253
46308
  }
46254
46309
  }
@@ -46258,10 +46313,6 @@
46258
46313
  return waypointsUpdatingConnections;
46259
46314
  }
46260
46315
 
46261
- function includes$4(array, item) {
46262
- return array.indexOf(item) !== -1;
46263
- }
46264
-
46265
46316
  /**
46266
46317
  * Resize bounds.
46267
46318
  *
@@ -46535,7 +46586,7 @@
46535
46586
  }
46536
46587
 
46537
46588
  var children = [
46538
- ...selfAndAllChildren(root, true),
46589
+ ...selfAndAllChildren(root),
46539
46590
  ...(root.attachers || [])
46540
46591
  ];
46541
46592
 
@@ -46582,24 +46633,30 @@
46582
46633
  var movingShapes = [],
46583
46634
  resizingShapes = [];
46584
46635
 
46636
+ var movingShapesSet = new Set(),
46637
+ resizingShapesSet = new Set();
46638
+
46585
46639
  var attachers = [],
46586
46640
  connections = [];
46587
46641
 
46588
46642
  function moveShape(shape) {
46589
- if (!movingShapes.includes(shape)) {
46643
+ if (!movingShapesSet.has(shape)) {
46644
+ movingShapesSet.add(shape);
46590
46645
  movingShapes.push(shape);
46591
46646
  }
46592
46647
 
46593
46648
  var label = shape.label;
46594
46649
 
46595
46650
  // move external label if its label target is moving
46596
- if (label && !movingShapes.includes(label)) {
46651
+ if (label && !movingShapesSet.has(label)) {
46652
+ movingShapesSet.add(label);
46597
46653
  movingShapes.push(label);
46598
46654
  }
46599
46655
  }
46600
46656
 
46601
46657
  function resizeShape(shape) {
46602
- if (!resizingShapes.includes(shape)) {
46658
+ if (!resizingShapesSet.has(shape)) {
46659
+ resizingShapesSet.add(shape);
46603
46660
  resizingShapes.push(shape);
46604
46661
  }
46605
46662
  }
@@ -46658,27 +46715,23 @@
46658
46715
  }
46659
46716
  });
46660
46717
 
46661
- var allShapes = movingShapes.concat(resizingShapes);
46662
-
46663
46718
  // move attacher if its mid is after space tool and its host is moving or resizing
46664
46719
  forEach(attachers, function(attacher) {
46665
46720
  var host = attacher.host;
46666
46721
 
46667
- if (includes$3(allShapes, host)) {
46722
+ if (movingShapesSet.has(host) || resizingShapesSet.has(host)) {
46668
46723
  moveShape(attacher);
46669
46724
  }
46670
46725
  });
46671
46726
 
46672
- allShapes = movingShapes.concat(resizingShapes);
46673
-
46674
46727
  // move external label if its label target's (connection) source and target are moving
46675
46728
  forEach(connections, function(connection) {
46676
46729
  var source = connection.source,
46677
46730
  target = connection.target,
46678
46731
  label = connection.label;
46679
46732
 
46680
- if (includes$3(allShapes, source)
46681
- && includes$3(allShapes, target)
46733
+ if ((movingShapesSet.has(source) || resizingShapesSet.has(source))
46734
+ && (movingShapesSet.has(target) || resizingShapesSet.has(target))
46682
46735
  && label) {
46683
46736
  moveShape(label);
46684
46737
  }
@@ -46773,6 +46826,9 @@
46773
46826
  min,
46774
46827
  max;
46775
46828
 
46829
+ var movingShapesSet = new Set(movingShapes),
46830
+ resizingShapesSet = new Set(resizingShapes);
46831
+
46776
46832
  forEach(resizingShapes, function(resizingShape) {
46777
46833
  var attachers = resizingShape.attachers,
46778
46834
  children = resizingShape.children;
@@ -46783,13 +46839,13 @@
46783
46839
  var nonMovingResizingChildren = filter(children, function(child) {
46784
46840
  return !isConnection(child) &&
46785
46841
  !isLabel(child) &&
46786
- !includes$3(movingShapes, child) &&
46787
- !includes$3(resizingShapes, child);
46842
+ !movingShapesSet.has(child) &&
46843
+ !resizingShapesSet.has(child);
46788
46844
  });
46789
46845
 
46790
46846
  // find children that are moving
46791
46847
  var movingChildren = filter(children, function(child) {
46792
- return !isConnection(child) && !isLabel(child) && includes$3(movingShapes, child);
46848
+ return !isConnection(child) && !isLabel(child) && movingShapesSet.has(child);
46793
46849
  });
46794
46850
 
46795
46851
  var minOrMax,
@@ -46840,7 +46896,7 @@
46840
46896
 
46841
46897
  if (attachers && attachers.length) {
46842
46898
  attachers.forEach(function(attacher) {
46843
- if (includes$3(movingShapes, attacher)) {
46899
+ if (movingShapesSet.has(attacher)) {
46844
46900
  movingAttachers.push(attacher);
46845
46901
  } else {
46846
46902
  nonMovingAttachers.push(attacher);
@@ -46915,10 +46971,6 @@
46915
46971
  return spaceToolConstraints;
46916
46972
  }
46917
46973
 
46918
- function includes$3(array, item) {
46919
- return array.indexOf(item) !== -1;
46920
- }
46921
-
46922
46974
  function isAttacher$1(element) {
46923
46975
  return !!element.host;
46924
46976
  }
@@ -47039,54 +47091,31 @@
47039
47091
  // shapes
47040
47092
  addPreviewGfx(movingShapes, dragGroup);
47041
47093
 
47042
- // connections
47043
- var movingConnections = context.movingConnections = elementRegistry.filter(function(element) {
47044
- var sourceIsMoving = false;
47045
-
47046
- forEach(movingShapes, function(shape) {
47047
- forEach(shape.outgoing, function(connection) {
47048
- if (element === connection) {
47049
- sourceIsMoving = true;
47050
- }
47051
- });
47052
- });
47094
+ // connections whose source *and* target are moving or resizing
47095
+ var adjustedShapes = new Set(movingShapes);
47053
47096
 
47054
- var targetIsMoving = false;
47097
+ forEach(resizingShapes, function(shape) {
47098
+ adjustedShapes.add(shape);
47099
+ });
47055
47100
 
47056
- forEach(movingShapes, function(shape) {
47057
- forEach(shape.incoming, function(connection) {
47058
- if (element === connection) {
47059
- targetIsMoving = true;
47060
- }
47061
- });
47062
- });
47101
+ var seenConnections = new Set();
47063
47102
 
47064
- var sourceIsResizing = false;
47103
+ var movingConnections = context.movingConnections = [];
47065
47104
 
47066
- forEach(resizingShapes, function(shape) {
47067
- forEach(shape.outgoing, function(connection) {
47068
- if (element === connection) {
47069
- sourceIsResizing = true;
47070
- }
47071
- });
47072
- });
47105
+ adjustedShapes.forEach(function(shape) {
47106
+ forEach(shape.outgoing, function(connection) {
47107
+ if (seenConnections.has(connection)
47108
+ || !isConnection(connection)
47109
+ || !adjustedShapes.has(connection.target)) {
47110
+ return;
47111
+ }
47073
47112
 
47074
- var targetIsResizing = false;
47113
+ seenConnections.add(connection);
47075
47114
 
47076
- forEach(resizingShapes, function(shape) {
47077
- forEach(shape.incoming, function(connection) {
47078
- if (element === connection) {
47079
- targetIsResizing = true;
47080
- }
47081
- });
47115
+ movingConnections.push(connection);
47082
47116
  });
47083
-
47084
- return isConnection(element)
47085
- && (sourceIsMoving || sourceIsResizing)
47086
- && (targetIsMoving || targetIsResizing);
47087
47117
  });
47088
47118
 
47089
-
47090
47119
  addPreviewGfx(movingConnections, dragGroup);
47091
47120
 
47092
47121
  context.dragGroup = dragGroup;
@@ -47954,28 +47983,26 @@
47954
47983
  movePreview && eventBus.on('shape.move.start', LOW_PRIORITY$8, function(e) {
47955
47984
 
47956
47985
  var context = e.context,
47957
- shapes = context.shapes;
47986
+ shapeSet = new Set(context.shapes),
47987
+ labelSet = new Set();
47958
47988
 
47959
- var labels = [];
47989
+ for (const shape of shapeSet) {
47960
47990
 
47961
- forEach(shapes, function(element) {
47962
-
47963
- forEach(element.labels, function(label) {
47991
+ for (const label of shape.labels) {
47964
47992
 
47965
- if (!label.hidden && context.shapes.indexOf(label) === -1) {
47966
- labels.push(label);
47993
+ if (!label.hidden && !shapeSet.has(label)) {
47994
+ labelSet.add(label);
47967
47995
  }
47968
47996
 
47969
- if (element.labelTarget) {
47970
- labels.push(element);
47997
+ if (shape.labelTarget) {
47998
+ labelSet.add(shape);
47971
47999
  }
47972
- });
47973
- });
48000
+ }
48001
+ }
47974
48002
 
47975
- forEach(labels, function(label) {
48003
+ for (const label of labelSet) {
47976
48004
  movePreview.makeDraggable(context, label, true);
47977
- });
47978
-
48005
+ }
47979
48006
  });
47980
48007
 
47981
48008
  // add all labels to move closure
@@ -48066,12 +48093,13 @@
48066
48093
  * @return {Element[]} filtered
48067
48094
  */
48068
48095
  function removeLabels(elements) {
48096
+ var elementsSet = new Set(elements);
48069
48097
 
48070
48098
  return filter(elements, function(element) {
48071
48099
 
48072
48100
  // filter out labels that are move together
48073
48101
  // with their label targets
48074
- return elements.indexOf(element.labelTarget) === -1;
48102
+ return !elementsSet.has(element.labelTarget);
48075
48103
  });
48076
48104
  }
48077
48105
 
@@ -48210,7 +48238,7 @@
48210
48238
  attachers = filter(shapes, function(shape) {
48211
48239
  var host = shape.host;
48212
48240
 
48213
- return isAttacher(shape) && !includes$2(shapes, host);
48241
+ return isAttacher(shape) && !includes$1(shapes, host);
48214
48242
  });
48215
48243
  }
48216
48244
 
@@ -48406,7 +48434,7 @@
48406
48434
  return !!shape.host;
48407
48435
  }
48408
48436
 
48409
- function includes$2(array, item) {
48437
+ function includes$1(array, item) {
48410
48438
  return array.indexOf(item) !== -1;
48411
48439
  }
48412
48440
 
@@ -50027,7 +50055,7 @@
50027
50055
  });
50028
50056
  });
50029
50057
 
50030
- var parents = getParents$1(elements);
50058
+ var parentsSet = new Set(getParents$1(elements));
50031
50059
 
50032
50060
  var cache = {};
50033
50061
 
@@ -50055,7 +50083,7 @@
50055
50083
 
50056
50084
  var createShapeHints = assign$1({}, hints);
50057
50085
 
50058
- if (parents.indexOf(element) === -1) {
50086
+ if (!parentsSet.has(element)) {
50059
50087
  createShapeHints.autoResize = false;
50060
50088
  }
50061
50089
 
@@ -51475,7 +51503,8 @@
51475
51503
  oldBounds
51476
51504
  ) {
51477
51505
  var self = this,
51478
- affectedShapes = movingShapes.concat(resizingShapes);
51506
+ movingShapesSet = new Set(movingShapes),
51507
+ resizingShapesSet = new Set(resizingShapes);
51479
51508
 
51480
51509
  forEach(connections, function(connection) {
51481
51510
  var source = connection.source,
@@ -51484,7 +51513,10 @@
51484
51513
  axis = getAxisFromDirection(direction),
51485
51514
  layoutHints = {};
51486
51515
 
51487
- if (includes$1(affectedShapes, source) && includes$1(affectedShapes, target)) {
51516
+ var sourceAffected = movingShapesSet.has(source) || resizingShapesSet.has(source),
51517
+ targetAffected = movingShapesSet.has(target) || resizingShapesSet.has(target);
51518
+
51519
+ if (sourceAffected && targetAffected) {
51488
51520
 
51489
51521
  // move waypoints
51490
51522
  waypoints = map(waypoints, function(waypoint) {
@@ -51506,18 +51538,18 @@
51506
51538
  self._modeling.updateWaypoints(connection, waypoints, {
51507
51539
  labelBehavior: false
51508
51540
  });
51509
- } else if (includes$1(affectedShapes, source) || includes$1(affectedShapes, target)) {
51541
+ } else if (sourceAffected || targetAffected) {
51510
51542
 
51511
51543
  // re-layout connection with moved start/end
51512
- if (includes$1(movingShapes, source)) {
51544
+ if (movingShapesSet.has(source)) {
51513
51545
  layoutHints.connectionStart = getMovedSourceAnchor(connection, source, delta);
51514
- } else if (includes$1(movingShapes, target)) {
51546
+ } else if (movingShapesSet.has(target)) {
51515
51547
  layoutHints.connectionEnd = getMovedTargetAnchor(connection, target, delta);
51516
- } else if (includes$1(resizingShapes, source)) {
51548
+ } else if (resizingShapesSet.has(source)) {
51517
51549
  layoutHints.connectionStart = getResizedSourceAnchor(
51518
51550
  connection, source, oldBounds[source.id]
51519
51551
  );
51520
- } else if (includes$1(resizingShapes, target)) {
51552
+ } else if (resizingShapesSet.has(target)) {
51521
51553
  layoutHints.connectionEnd = getResizedTargetAnchor(
51522
51554
  connection, target, oldBounds[target.id]
51523
51555
  );
@@ -51571,10 +51603,6 @@
51571
51603
  }
51572
51604
  }
51573
51605
 
51574
- function includes$1(array, item) {
51575
- return array.indexOf(item) !== -1;
51576
- }
51577
-
51578
51606
  function getBounds(shape) {
51579
51607
  return {
51580
51608
  x: shape.x,
@@ -62325,6 +62353,7 @@
62325
62353
  *
62326
62354
  * @typedef {import('./OutlineProvider.js').default} OutlineProvider
62327
62355
  * @typedef {import('../../core/EventBus.js').default} EventBus
62356
+ * @typedef {import('../../core/ElementRegistry.js').default} ElementRegistry
62328
62357
  * @typedef {import('../../draw/Styles.js').default} Styles
62329
62358
  */
62330
62359
 
@@ -62334,68 +62363,124 @@
62334
62363
  * A plugin that adds an outline to shapes and connections that may be activated and styled
62335
62364
  * via CSS classes.
62336
62365
  *
62366
+ * The outline is created lazily, i.e. only once an element is hovered or selected
62367
+ * for the first time. This keeps importing large diagrams fast, as we avoid
62368
+ * creating (and laying out) an outline for every single element up front.
62369
+ *
62337
62370
  * @param {EventBus} eventBus
62338
62371
  * @param {Styles} styles
62372
+ * @param {ElementRegistry} elementRegistry
62339
62373
  */
62340
- function Outline$1(eventBus, styles) {
62374
+ function Outline$1(eventBus, styles, elementRegistry) {
62341
62375
 
62342
62376
  this._eventBus = eventBus;
62377
+ this._elementRegistry = elementRegistry;
62343
62378
 
62344
- this.offset = 5;
62379
+ this._outlineOffset = 5;
62345
62380
 
62346
- var OUTLINE_STYLE = styles.cls('djs-outline', [ 'no-fill' ]);
62381
+ this._outlineStyle = styles.cls('djs-outline', [ 'no-fill' ]);
62347
62382
 
62348
62383
  var self = this;
62349
62384
 
62350
62385
  /**
62351
- * @param {SVGElement} gfx
62386
+ * Lazily create the outline once an element is hovered or selected.
62352
62387
  *
62353
- * @return {SVGElement} outline
62388
+ * @param {Element} element
62354
62389
  */
62355
- function createOutline(gfx) {
62356
- var outline = create$1('rect');
62390
+ function createElementOutline(element) {
62391
+ self.createOutline(element);
62392
+ }
62357
62393
 
62358
- attr(outline, assign$1({
62359
- x: 0,
62360
- y: 0,
62361
- rx: 4,
62362
- width: 100,
62363
- height: 100
62364
- }, OUTLINE_STYLE));
62394
+ eventBus.on('element.hover', function(event) {
62395
+ createElementOutline(event.element);
62396
+ });
62365
62397
 
62366
- return outline;
62367
- }
62398
+ eventBus.on('selection.changed', function(event) {
62399
+ forEach(event.newSelection, createElementOutline);
62400
+ });
62368
62401
 
62369
- // A low priortity is necessary, because outlines of labels have to be updated
62402
+ // Keep an already created outline in sync with its element. Elements that
62403
+ // have not been hovered or selected yet do not have an outline; those are
62404
+ // created (and updated) lazily via the handlers above.
62405
+ //
62406
+ // A low priority is necessary, because outlines of labels have to be updated
62370
62407
  // after the label bounds have been updated in the renderer.
62371
- eventBus.on([ 'shape.added', 'shape.changed' ], LOW_PRIORITY$3, function(event) {
62408
+ eventBus.on([ 'shape.changed', 'connection.changed' ], LOW_PRIORITY$3, function(event) {
62372
62409
  var element = event.element,
62373
62410
  gfx = event.gfx;
62374
62411
 
62375
62412
  var outline = query('.djs-outline', gfx);
62376
62413
 
62377
- if (!outline) {
62378
- outline = self.getOutline(element) || createOutline();
62379
- append(gfx, outline);
62414
+ if (outline) {
62415
+ self.updateOutline(element, outline);
62380
62416
  }
62381
-
62382
- self.updateShapeOutline(outline, element);
62383
62417
  });
62418
+ }
62384
62419
 
62385
- eventBus.on([ 'connection.added', 'connection.changed' ], function(event) {
62386
- var element = event.element,
62387
- gfx = event.gfx;
62420
+ /**
62421
+ * Ensure the outline for the given element is present, creating, appending
62422
+ * and updating it on first access.
62423
+ *
62424
+ * Outlines are created lazily, i.e. only once an element is hovered or
62425
+ * selected. Use this to force outline creation, e.g. for features or tests
62426
+ * that rely on the outline being present.
62427
+ *
62428
+ * @param {Element} element
62429
+ *
62430
+ * @return {SVGElement} the element's outline
62431
+ */
62432
+ Outline$1.prototype.createOutline = function(element) {
62433
+ var gfx = this._elementRegistry.getGraphics(element);
62388
62434
 
62389
- var outline = query('.djs-outline', gfx);
62435
+ if (!gfx) {
62436
+ throw new Error('cannot create outline for non-rendered element');
62437
+ }
62390
62438
 
62391
- if (!outline) {
62392
- outline = createOutline();
62393
- append(gfx, outline);
62394
- }
62439
+ var outline = query('.djs-outline', gfx);
62395
62440
 
62396
- self.updateConnectionOutline(outline, element);
62397
- });
62398
- }
62441
+ if (!outline) {
62442
+ outline = this.getOutline(element) || this._createOutlineGfx();
62443
+ append(gfx, outline);
62444
+
62445
+ this.updateOutline(element, outline);
62446
+ }
62447
+
62448
+ return outline;
62449
+ };
62450
+
62451
+ /**
62452
+ * Create the default outline graphics.
62453
+ *
62454
+ * @return {SVGElement} outline
62455
+ */
62456
+ Outline$1.prototype._createOutlineGfx = function() {
62457
+ var outline = create$1('rect');
62458
+
62459
+ attr(outline, assign$1({
62460
+ x: 0,
62461
+ y: 0,
62462
+ rx: 4,
62463
+ width: 100,
62464
+ height: 100
62465
+ }, this._outlineStyle));
62466
+
62467
+ return outline;
62468
+ };
62469
+
62470
+ /**
62471
+ * Updates the outline of the given element, dispatching to the shape or
62472
+ * connection specific update depending on the element type.
62473
+ *
62474
+ * @param {Element} element
62475
+ * @param {SVGElement} outline
62476
+ */
62477
+ Outline$1.prototype.updateOutline = function(element, outline) {
62478
+ if (element.waypoints) {
62479
+ this.updateConnectionOutline(outline, element);
62480
+ } else {
62481
+ this.updateShapeOutline(outline, element);
62482
+ }
62483
+ };
62399
62484
 
62400
62485
 
62401
62486
  /**
@@ -62418,10 +62503,10 @@
62418
62503
 
62419
62504
  if (!updated) {
62420
62505
  attr(outline, {
62421
- x: -this.offset,
62422
- y: -this.offset,
62423
- width: element.width + this.offset * 2,
62424
- height: element.height + this.offset * 2
62506
+ x: -this._outlineOffset,
62507
+ y: -this._outlineOffset,
62508
+ width: element.width + this._outlineOffset * 2,
62509
+ height: element.height + this._outlineOffset * 2
62425
62510
  });
62426
62511
  }
62427
62512
  };
@@ -62438,10 +62523,10 @@
62438
62523
  var bbox = getBBox(connection);
62439
62524
 
62440
62525
  attr(outline, {
62441
- x: bbox.x - this.offset,
62442
- y: bbox.y - this.offset,
62443
- width: bbox.width + this.offset * 2,
62444
- height: bbox.height + this.offset * 2
62526
+ x: bbox.x - this._outlineOffset,
62527
+ y: bbox.y - this._outlineOffset,
62528
+ width: bbox.width + this._outlineOffset * 2,
62529
+ height: bbox.height + this._outlineOffset * 2
62445
62530
  });
62446
62531
  };
62447
62532
 
@@ -62640,9 +62725,9 @@
62640
62725
  if (allowedElements.length === 1) {
62641
62726
  const element = allowedElements[0];
62642
62727
  if (isLabel(element)) {
62643
- createLink(element, element.labelTarget, newSelection);
62728
+ createLink(element, element.labelTarget);
62644
62729
  } else if (element.labels?.length) {
62645
- createLink(element.labels[0], element, newSelection);
62730
+ createLink(element.labels[0], element);
62646
62731
  }
62647
62732
  }
62648
62733
 
@@ -62651,7 +62736,7 @@
62651
62736
  const label = allowedElements.find(isLabel);
62652
62737
  const target = allowedElements.find(el => el.labels?.includes(label));
62653
62738
  if (label && target) {
62654
- createLink(label, target, newSelection);
62739
+ createLink(label, target);
62655
62740
  }
62656
62741
  }
62657
62742
  });
@@ -62663,9 +62748,9 @@
62663
62748
  }
62664
62749
 
62665
62750
  if (isLabel(element)) {
62666
- createLink(element, element.labelTarget, selection.get());
62751
+ createLink(element, element.labelTarget);
62667
62752
  } else if (element.labels?.length) {
62668
- createLink(element.labels[0], element, selection.get());
62753
+ createLink(element.labels[0], element);
62669
62754
  }
62670
62755
  });
62671
62756
 
@@ -62674,9 +62759,8 @@
62674
62759
  *
62675
62760
  * @param {Element} label
62676
62761
  * @param {Element} target
62677
- * @param {Element[]} selection
62678
62762
  */
62679
- function createLink(label, target, selection = []) {
62763
+ function createLink(label, target) {
62680
62764
 
62681
62765
  // Create an auxiliary line between label and target mid points
62682
62766
  const line = createLine(
@@ -62686,7 +62770,7 @@
62686
62770
  const linePath = line.getAttribute('d');
62687
62771
 
62688
62772
  // Calculate the intersection point between line and label
62689
- const labelSelected = selection.includes(label);
62773
+ const labelSelected = selection.isSelected(label);
62690
62774
  const labelPath = labelSelected ? getElementOutlinePath(label) : getElementPath(label);
62691
62775
  const labelInter = getElementLineIntersection(labelPath, linePath);
62692
62776
 
@@ -62698,7 +62782,7 @@
62698
62782
  // Calculate the intersection point between line and label
62699
62783
  // If the target is a sequence flow, there is no intersection,
62700
62784
  // so we link to the middle of it.
62701
- const targetSelected = selection.includes(target);
62785
+ const targetSelected = selection.isSelected(target);
62702
62786
  const targetPath = targetSelected ? getElementOutlinePath(target) : getElementPath(target);
62703
62787
  const targetInter = getElementLineIntersection(targetPath, linePath) || getMid(target);
62704
62788
 
@@ -62728,7 +62812,6 @@
62728
62812
  */
62729
62813
  function getElementOutlinePath(element) {
62730
62814
  const outlineShape = outline.getOutline(element);
62731
- const outlineOffset = outline.offset;
62732
62815
 
62733
62816
  if (!outlineShape) {
62734
62817
  return getElementPath(element);
@@ -62746,11 +62829,13 @@
62746
62829
  }
62747
62830
 
62748
62831
  if (outlineShape.cx) {
62832
+ const radius = parseSvgNumAttr(outlineShape, 'r');
62833
+
62749
62834
  const shape = {
62750
- x: element.x - outlineOffset,
62751
- y: element.y - outlineOffset,
62752
- width: parseSvgNumAttr(outlineShape, 'r') * 2,
62753
- height: parseSvgNumAttr(outlineShape, 'r') * 2,
62835
+ x: element.x + parseSvgNumAttr(outlineShape, 'cx') - radius,
62836
+ y: element.y + parseSvgNumAttr(outlineShape, 'cy') - radius,
62837
+ width: radius * 2,
62838
+ height: radius * 2,
62754
62839
  };
62755
62840
 
62756
62841
  return getCirclePath(shape);
@@ -62762,7 +62847,7 @@
62762
62847
  }
62763
62848
 
62764
62849
  function isElementSelected(element) {
62765
- return selection.get().includes(element);
62850
+ return selection.isSelected(element);
62766
62851
  }
62767
62852
  }
62768
62853
 
@@ -63546,7 +63631,7 @@
63546
63631
  }
63547
63632
 
63548
63633
  function getAllDraggedElements(shapes) {
63549
- var allShapes = selfAndAllChildren(shapes, true);
63634
+ var allShapes = selfAndAllChildren(shapes);
63550
63635
 
63551
63636
  var allConnections = allShapes.flatMap(shape =>
63552
63637
  (shape.incoming || []).concat(shape.outgoing || [])
@@ -63722,6 +63807,12 @@
63722
63807
  */
63723
63808
  function removeEdges(elements) {
63724
63809
 
63810
+ var elementIds = new Set();
63811
+
63812
+ elements.forEach(function(element) {
63813
+ elementIds.add(element.id);
63814
+ });
63815
+
63725
63816
  var filteredElements = filter(elements, function(element) {
63726
63817
 
63727
63818
  if (!isConnection(element)) {
@@ -63729,8 +63820,8 @@
63729
63820
  } else {
63730
63821
 
63731
63822
  return (
63732
- find(elements, matchPattern({ id: element.source.id })) &&
63733
- find(elements, matchPattern({ id: element.target.id }))
63823
+ elementIds.has(element.source.id) &&
63824
+ elementIds.has(element.target.id)
63734
63825
  );
63735
63826
  }
63736
63827
  });