bpmn-js 18.18.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.18.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-08
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.
2913
+ *
2914
+ * The result is always a unique set of elements (no duplicates).
2935
2915
  *
2936
- * @param {Element[]} elements to query
2937
- * @param {boolean} [allowDuplicates] to allow duplicates in the result set
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;
8230
8214
 
8231
- prependTo(childGfx.parentNode, childrenGfx);
8215
+ forEach(children, function(child) {
8216
+ var childGfx = elementRegistry.getGraphics(child).parentNode;
8217
+
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>
@@ -29050,22 +29061,43 @@
29050
29061
  * spliced in. Recurses into step entries so the whole tree uses the array
29051
29062
  * shape downstream.
29052
29063
  *
29064
+ * Leaf entries inherit the `search` terms of their ancestors, so a leaf can be
29065
+ * found by keywords declared on any of its parents.
29066
+ *
29053
29067
  * @param {import('./PopupMenuProvider').PopupMenuEntries} entriesMap
29068
+ * @param {string[]} [search]
29054
29069
  *
29055
29070
  * @return {import('./PopupMenuProvider').PopupMenuEntry[]}
29056
29071
  */
29057
- function flattenEntries(entriesMap) {
29072
+ function flattenEntries(entriesMap, search = []) {
29058
29073
  return Object.entries(entriesMap).map(([ id, value ]) => {
29059
29074
  const entry = { id, ...value };
29060
29075
 
29061
29076
  if (entry.entries) {
29062
- entry.entries = flattenEntries(entry.entries);
29077
+ entry.entries = flattenEntries(
29078
+ entry.entries,
29079
+ [ ...search, ...asArray(entry.search) ]
29080
+ );
29081
+ } else if (search.length) {
29082
+ entry.search = [ ...search, ...asArray(entry.search) ];
29063
29083
  }
29064
29084
 
29065
29085
  return entry;
29066
29086
  });
29067
29087
  }
29068
29088
 
29089
+ /**
29090
+ * @param {string | string[]} [value]
29091
+ * @return {string[]}
29092
+ */
29093
+ function asArray(value) {
29094
+ if (!value) {
29095
+ return [];
29096
+ }
29097
+
29098
+ return isArray$2(value) ? value : [ value ];
29099
+ }
29100
+
29069
29101
  /**
29070
29102
  * @typedef { {
29071
29103
  * index: number;
@@ -32671,6 +32703,9 @@
32671
32703
 
32672
32704
  translate$1(floating, point.x, point.y);
32673
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');
32674
32709
  }
32675
32710
 
32676
32711
  function updateSegmentDraggerPosition(parentGfx, intersection, waypoints) {
@@ -32794,6 +32829,28 @@
32794
32829
  }
32795
32830
  });
32796
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
+
32797
32854
  // update bendpoint container data attribute on element ID change
32798
32855
  eventBus.on('element.updateId', function(context) {
32799
32856
  var element = context.element,
@@ -34749,14 +34806,10 @@
34749
34806
  gfx = gfx || this.getGfx(element);
34750
34807
 
34751
34808
  var dragger = clone(gfx);
34752
- var bbox = gfx.getBoundingClientRect();
34753
34809
 
34754
34810
  this._cloneMarkers(getVisual(dragger), className);
34755
34811
 
34756
- attr(dragger, this._styles.cls(className, [], {
34757
- x: bbox.top,
34758
- y: bbox.left
34759
- }));
34812
+ attr(dragger, this._styles.cls(className, []));
34760
34813
 
34761
34814
  append(group, dragger);
34762
34815
 
@@ -37183,7 +37236,7 @@
37183
37236
  shapes.forEach(function(shape, index) {
37184
37237
  var host = shape.host;
37185
37238
 
37186
- if (shouldReplace(shape, includes$6(shapes, host) ? host : newHost)) {
37239
+ if (shouldReplace(shape, includes$3(shapes, host) ? host : newHost)) {
37187
37240
  shapes[ index ] = self._replaceShape(shape);
37188
37241
  }
37189
37242
  });
@@ -37229,7 +37282,7 @@
37229
37282
  return !isLabel(shape) && is(shape, 'bpmn:BoundaryEvent') && !host;
37230
37283
  }
37231
37284
 
37232
- function includes$6(array, item) {
37285
+ function includes$3(array, item) {
37233
37286
  return array.indexOf(item) !== -1;
37234
37287
  }
37235
37288
 
@@ -37586,8 +37639,9 @@
37586
37639
  var rootElement = canvas.getRootElement();
37587
37640
 
37588
37641
  // ensure bpmn:Group and label elements are dropped
37589
- // always onto the root
37590
- 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' ]))) {
37591
37645
  event.hover = rootElement;
37592
37646
  event.hoverGfx = elementRegistry.getGraphics(event.hover);
37593
37647
  }
@@ -39525,7 +39579,7 @@
39525
39579
  }
39526
39580
 
39527
39581
  function getMessageFlows(parent) {
39528
- var elements = selfAndAllChildren([ parent ], false);
39582
+ var elements = selfAndAllChildren([ parent ]);
39529
39583
 
39530
39584
  var incoming = [],
39531
39585
  outgoing = [];
@@ -41467,7 +41521,7 @@
41467
41521
  * @return {Element[]}
41468
41522
  */
41469
41523
  function getExternalLabels(element) {
41470
- return selfAndChildren(element.children || [], true)
41524
+ return selfAndChildren(element.children || [])
41471
41525
  .reduce(function(labels, child) {
41472
41526
  if (child.label && child.label.parent !== element) {
41473
41527
  labels.push(child.label);
@@ -43149,11 +43203,16 @@
43149
43203
  return false;
43150
43204
  }
43151
43205
 
43152
- // allow default move check to start move operation
43153
- if (!target) {
43206
+ // allow move to start when there is no target yet (`undefined`)
43207
+ if (target === undefined) {
43154
43208
  return true;
43155
43209
  }
43156
43210
 
43211
+ // disallow dropping outside the canvas (`null` target)
43212
+ if (target === null) {
43213
+ return false;
43214
+ }
43215
+
43157
43216
  return elements.every(function(element) {
43158
43217
  return canDrop(element, target);
43159
43218
  });
@@ -43378,7 +43437,7 @@
43378
43437
  *
43379
43438
  * @return {boolean}
43380
43439
  */
43381
- function includes$5(elements, element) {
43440
+ function includes$2(elements, element) {
43382
43441
  return (elements && element) && elements.indexOf(element) !== -1;
43383
43442
  }
43384
43443
 
@@ -43393,7 +43452,7 @@
43393
43452
  return true;
43394
43453
  }
43395
43454
 
43396
- if (is(element, 'bpmn:Lane') && !includes$5(elements, element.parent)) {
43455
+ if (is(element, 'bpmn:Lane') && !includes$2(elements, element.parent)) {
43397
43456
  return false;
43398
43457
  }
43399
43458
 
@@ -43444,7 +43503,7 @@
43444
43503
  elements,
43445
43504
  diElements;
43446
43505
 
43447
- elements = selfAndAllChildren([ root ], false);
43506
+ elements = selfAndAllChildren([ root ]);
43448
43507
 
43449
43508
  // only bpmndi:Shape and bpmndi:Edge can be direct children of bpmndi:Plane
43450
43509
  elements = filter(elements, function(element) {
@@ -44447,19 +44506,15 @@
44447
44506
  eventBus.on('copyPaste.copyElement', function(context) {
44448
44507
  var descriptor = context.descriptor,
44449
44508
  element = context.element,
44450
- elements = context.elements;
44509
+ elementsSet = context.elementsSet;
44451
44510
 
44452
44511
  // default priority (priority = 1)
44453
44512
  descriptor.priority = 1;
44454
44513
 
44455
44514
  descriptor.id = element.id;
44456
44515
 
44457
- var parentCopied = find(elements, function(e) {
44458
- return e === element.parent;
44459
- });
44460
-
44461
44516
  // do NOT reference parent if parent wasn't copied
44462
- if (parentCopied) {
44517
+ if (elementsSet.has(element.parent)) {
44463
44518
  descriptor.parent = element.parent.id;
44464
44519
  }
44465
44520
 
@@ -44811,31 +44866,29 @@
44811
44866
  };
44812
44867
 
44813
44868
  /**
44814
- * 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.
44815
44870
  *
44816
44871
  * @param {Object} element
44817
44872
  * @param {Element[]} elements
44873
+ * @param {Set<Element>} [elementsSet] pre-computed set of `elements`; pass it
44874
+ * to avoid a linear scan per invocation
44818
44875
  *
44819
44876
  * @return {boolean}
44820
44877
  */
44821
- CopyPaste.prototype.hasRelations = function(element, elements) {
44822
- var labelTarget,
44823
- source,
44824
- target;
44878
+ CopyPaste.prototype.hasRelations = function(element, elements, elementsSet) {
44825
44879
 
44826
- if (isConnection(element)) {
44827
- source = find(elements, matchPattern({ id: element.source.id }));
44828
- target = find(elements, matchPattern({ id: element.target.id }));
44880
+ if (!elementsSet) {
44881
+ elementsSet = new Set(elements);
44882
+ }
44829
44883
 
44830
- if (!source || !target) {
44884
+ if (isConnection(element)) {
44885
+ if (!elementsSet.has(element.source) || !elementsSet.has(element.target)) {
44831
44886
  return false;
44832
44887
  }
44833
44888
  }
44834
44889
 
44835
44890
  if (isLabel(element)) {
44836
- labelTarget = find(elements, matchPattern({ id: element.labelTarget.id }));
44837
-
44838
- if (!labelTarget) {
44891
+ if (!elementsSet.has(element.labelTarget)) {
44839
44892
  return false;
44840
44893
  }
44841
44894
  }
@@ -44874,6 +44927,9 @@
44874
44927
  var tree = {},
44875
44928
  elementsData = [];
44876
44929
 
44930
+ // O(1) lookup of already added element data during the add phase
44931
+ var elementsDataMap = new Map();
44932
+
44877
44933
  var parents = getParents$1(elements);
44878
44934
 
44879
44935
  function canCopy(element, elements) {
@@ -44885,17 +44941,18 @@
44885
44941
 
44886
44942
  function addElementData(element, depth) {
44887
44943
 
44888
- // (1) check wether element has already been added
44889
- var foundElementData = find(elementsData, function(elementsData) {
44890
- return element === elementsData.element;
44891
- });
44944
+ // (1) check whether element has already been added
44945
+ var foundElementData = elementsDataMap.get(element);
44892
44946
 
44893
44947
  // (2) add element if not already added
44894
44948
  if (!foundElementData) {
44895
- elementsData.push({
44949
+ var elementData = {
44896
44950
  element: element,
44897
44951
  depth: depth
44898
- });
44952
+ };
44953
+
44954
+ elementsData.push(elementData);
44955
+ elementsDataMap.set(element, elementData);
44899
44956
 
44900
44957
  return;
44901
44958
  }
@@ -44904,10 +44961,13 @@
44904
44961
  if (foundElementData.depth < depth) {
44905
44962
  elementsData = removeElementData(foundElementData, elementsData);
44906
44963
 
44907
- elementsData.push({
44964
+ var updatedElementData = {
44908
44965
  element: foundElementData.element,
44909
44966
  depth: depth
44910
- });
44967
+ };
44968
+
44969
+ elementsData.push(updatedElementData);
44970
+ elementsDataMap.set(element, updatedElementData);
44911
44971
  }
44912
44972
  }
44913
44973
 
@@ -44970,13 +45030,20 @@
44970
45030
  });
44971
45031
 
44972
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
+
44973
45039
  elementsData = map(elementsData, function(elementData) {
44974
45040
  elementData.descriptor = {};
44975
45041
 
44976
45042
  self._eventBus.fire('copyPaste.copyElement', {
44977
45043
  descriptor: elementData.descriptor,
44978
45044
  element: elementData.element,
44979
- elements: elements
45045
+ elements: elements,
45046
+ elementsSet: elementsSet
44980
45047
  });
44981
45048
 
44982
45049
  return elementData;
@@ -44995,14 +45062,16 @@
44995
45062
  forEach(elementsData, function(elementData) {
44996
45063
  var depth = elementData.depth;
44997
45064
 
44998
- if (!self.hasRelations(elementData.element, elements)) {
45065
+ if (!self.hasRelations(elementData.element, elements, elementsSet)) {
44999
45066
  removeElement(elementData.element, elements);
45067
+ elementsSet.delete(elementData.element);
45000
45068
 
45001
45069
  return;
45002
45070
  }
45003
45071
 
45004
45072
  if (!canCopy(elementData.element, elements)) {
45005
45073
  removeElement(elementData.element, elements);
45074
+ elementsSet.delete(elementData.element);
45006
45075
 
45007
45076
  return;
45008
45077
  }
@@ -46214,7 +46283,15 @@
46214
46283
  function getWaypointsUpdatingConnections(movingShapes, resizingShapes) {
46215
46284
  var waypointsUpdatingConnections = [];
46216
46285
 
46217
- 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) {
46218
46295
  var incoming = shape.incoming,
46219
46296
  outgoing = shape.outgoing;
46220
46297
 
@@ -46222,12 +46299,11 @@
46222
46299
  var source = connection.source,
46223
46300
  target = connection.target;
46224
46301
 
46225
- if (includes$4(movingShapes, source) ||
46226
- includes$4(movingShapes, target) ||
46227
- includes$4(resizingShapes, source) ||
46228
- includes$4(resizingShapes, target)) {
46302
+ if (adjustedShapes.has(source) || adjustedShapes.has(target)) {
46303
+
46304
+ if (!seenConnections.has(connection)) {
46305
+ seenConnections.add(connection);
46229
46306
 
46230
- if (!includes$4(waypointsUpdatingConnections, connection)) {
46231
46307
  waypointsUpdatingConnections.push(connection);
46232
46308
  }
46233
46309
  }
@@ -46237,10 +46313,6 @@
46237
46313
  return waypointsUpdatingConnections;
46238
46314
  }
46239
46315
 
46240
- function includes$4(array, item) {
46241
- return array.indexOf(item) !== -1;
46242
- }
46243
-
46244
46316
  /**
46245
46317
  * Resize bounds.
46246
46318
  *
@@ -46514,7 +46586,7 @@
46514
46586
  }
46515
46587
 
46516
46588
  var children = [
46517
- ...selfAndAllChildren(root, true),
46589
+ ...selfAndAllChildren(root),
46518
46590
  ...(root.attachers || [])
46519
46591
  ];
46520
46592
 
@@ -46561,24 +46633,30 @@
46561
46633
  var movingShapes = [],
46562
46634
  resizingShapes = [];
46563
46635
 
46636
+ var movingShapesSet = new Set(),
46637
+ resizingShapesSet = new Set();
46638
+
46564
46639
  var attachers = [],
46565
46640
  connections = [];
46566
46641
 
46567
46642
  function moveShape(shape) {
46568
- if (!movingShapes.includes(shape)) {
46643
+ if (!movingShapesSet.has(shape)) {
46644
+ movingShapesSet.add(shape);
46569
46645
  movingShapes.push(shape);
46570
46646
  }
46571
46647
 
46572
46648
  var label = shape.label;
46573
46649
 
46574
46650
  // move external label if its label target is moving
46575
- if (label && !movingShapes.includes(label)) {
46651
+ if (label && !movingShapesSet.has(label)) {
46652
+ movingShapesSet.add(label);
46576
46653
  movingShapes.push(label);
46577
46654
  }
46578
46655
  }
46579
46656
 
46580
46657
  function resizeShape(shape) {
46581
- if (!resizingShapes.includes(shape)) {
46658
+ if (!resizingShapesSet.has(shape)) {
46659
+ resizingShapesSet.add(shape);
46582
46660
  resizingShapes.push(shape);
46583
46661
  }
46584
46662
  }
@@ -46637,27 +46715,23 @@
46637
46715
  }
46638
46716
  });
46639
46717
 
46640
- var allShapes = movingShapes.concat(resizingShapes);
46641
-
46642
46718
  // move attacher if its mid is after space tool and its host is moving or resizing
46643
46719
  forEach(attachers, function(attacher) {
46644
46720
  var host = attacher.host;
46645
46721
 
46646
- if (includes$3(allShapes, host)) {
46722
+ if (movingShapesSet.has(host) || resizingShapesSet.has(host)) {
46647
46723
  moveShape(attacher);
46648
46724
  }
46649
46725
  });
46650
46726
 
46651
- allShapes = movingShapes.concat(resizingShapes);
46652
-
46653
46727
  // move external label if its label target's (connection) source and target are moving
46654
46728
  forEach(connections, function(connection) {
46655
46729
  var source = connection.source,
46656
46730
  target = connection.target,
46657
46731
  label = connection.label;
46658
46732
 
46659
- if (includes$3(allShapes, source)
46660
- && includes$3(allShapes, target)
46733
+ if ((movingShapesSet.has(source) || resizingShapesSet.has(source))
46734
+ && (movingShapesSet.has(target) || resizingShapesSet.has(target))
46661
46735
  && label) {
46662
46736
  moveShape(label);
46663
46737
  }
@@ -46752,6 +46826,9 @@
46752
46826
  min,
46753
46827
  max;
46754
46828
 
46829
+ var movingShapesSet = new Set(movingShapes),
46830
+ resizingShapesSet = new Set(resizingShapes);
46831
+
46755
46832
  forEach(resizingShapes, function(resizingShape) {
46756
46833
  var attachers = resizingShape.attachers,
46757
46834
  children = resizingShape.children;
@@ -46762,13 +46839,13 @@
46762
46839
  var nonMovingResizingChildren = filter(children, function(child) {
46763
46840
  return !isConnection(child) &&
46764
46841
  !isLabel(child) &&
46765
- !includes$3(movingShapes, child) &&
46766
- !includes$3(resizingShapes, child);
46842
+ !movingShapesSet.has(child) &&
46843
+ !resizingShapesSet.has(child);
46767
46844
  });
46768
46845
 
46769
46846
  // find children that are moving
46770
46847
  var movingChildren = filter(children, function(child) {
46771
- return !isConnection(child) && !isLabel(child) && includes$3(movingShapes, child);
46848
+ return !isConnection(child) && !isLabel(child) && movingShapesSet.has(child);
46772
46849
  });
46773
46850
 
46774
46851
  var minOrMax,
@@ -46819,7 +46896,7 @@
46819
46896
 
46820
46897
  if (attachers && attachers.length) {
46821
46898
  attachers.forEach(function(attacher) {
46822
- if (includes$3(movingShapes, attacher)) {
46899
+ if (movingShapesSet.has(attacher)) {
46823
46900
  movingAttachers.push(attacher);
46824
46901
  } else {
46825
46902
  nonMovingAttachers.push(attacher);
@@ -46894,10 +46971,6 @@
46894
46971
  return spaceToolConstraints;
46895
46972
  }
46896
46973
 
46897
- function includes$3(array, item) {
46898
- return array.indexOf(item) !== -1;
46899
- }
46900
-
46901
46974
  function isAttacher$1(element) {
46902
46975
  return !!element.host;
46903
46976
  }
@@ -47018,54 +47091,31 @@
47018
47091
  // shapes
47019
47092
  addPreviewGfx(movingShapes, dragGroup);
47020
47093
 
47021
- // connections
47022
- var movingConnections = context.movingConnections = elementRegistry.filter(function(element) {
47023
- var sourceIsMoving = false;
47094
+ // connections whose source *and* target are moving or resizing
47095
+ var adjustedShapes = new Set(movingShapes);
47024
47096
 
47025
- forEach(movingShapes, function(shape) {
47026
- forEach(shape.outgoing, function(connection) {
47027
- if (element === connection) {
47028
- sourceIsMoving = true;
47029
- }
47030
- });
47031
- });
47032
-
47033
- var targetIsMoving = false;
47097
+ forEach(resizingShapes, function(shape) {
47098
+ adjustedShapes.add(shape);
47099
+ });
47034
47100
 
47035
- forEach(movingShapes, function(shape) {
47036
- forEach(shape.incoming, function(connection) {
47037
- if (element === connection) {
47038
- targetIsMoving = true;
47039
- }
47040
- });
47041
- });
47101
+ var seenConnections = new Set();
47042
47102
 
47043
- var sourceIsResizing = false;
47103
+ var movingConnections = context.movingConnections = [];
47044
47104
 
47045
- forEach(resizingShapes, function(shape) {
47046
- forEach(shape.outgoing, function(connection) {
47047
- if (element === connection) {
47048
- sourceIsResizing = true;
47049
- }
47050
- });
47051
- });
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
+ }
47052
47112
 
47053
- var targetIsResizing = false;
47113
+ seenConnections.add(connection);
47054
47114
 
47055
- forEach(resizingShapes, function(shape) {
47056
- forEach(shape.incoming, function(connection) {
47057
- if (element === connection) {
47058
- targetIsResizing = true;
47059
- }
47060
- });
47115
+ movingConnections.push(connection);
47061
47116
  });
47062
-
47063
- return isConnection(element)
47064
- && (sourceIsMoving || sourceIsResizing)
47065
- && (targetIsMoving || targetIsResizing);
47066
47117
  });
47067
47118
 
47068
-
47069
47119
  addPreviewGfx(movingConnections, dragGroup);
47070
47120
 
47071
47121
  context.dragGroup = dragGroup;
@@ -47933,28 +47983,26 @@
47933
47983
  movePreview && eventBus.on('shape.move.start', LOW_PRIORITY$8, function(e) {
47934
47984
 
47935
47985
  var context = e.context,
47936
- shapes = context.shapes;
47986
+ shapeSet = new Set(context.shapes),
47987
+ labelSet = new Set();
47937
47988
 
47938
- var labels = [];
47989
+ for (const shape of shapeSet) {
47939
47990
 
47940
- forEach(shapes, function(element) {
47941
-
47942
- forEach(element.labels, function(label) {
47991
+ for (const label of shape.labels) {
47943
47992
 
47944
- if (!label.hidden && context.shapes.indexOf(label) === -1) {
47945
- labels.push(label);
47993
+ if (!label.hidden && !shapeSet.has(label)) {
47994
+ labelSet.add(label);
47946
47995
  }
47947
47996
 
47948
- if (element.labelTarget) {
47949
- labels.push(element);
47997
+ if (shape.labelTarget) {
47998
+ labelSet.add(shape);
47950
47999
  }
47951
- });
47952
- });
48000
+ }
48001
+ }
47953
48002
 
47954
- forEach(labels, function(label) {
48003
+ for (const label of labelSet) {
47955
48004
  movePreview.makeDraggable(context, label, true);
47956
- });
47957
-
48005
+ }
47958
48006
  });
47959
48007
 
47960
48008
  // add all labels to move closure
@@ -48045,12 +48093,13 @@
48045
48093
  * @return {Element[]} filtered
48046
48094
  */
48047
48095
  function removeLabels(elements) {
48096
+ var elementsSet = new Set(elements);
48048
48097
 
48049
48098
  return filter(elements, function(element) {
48050
48099
 
48051
48100
  // filter out labels that are move together
48052
48101
  // with their label targets
48053
- return elements.indexOf(element.labelTarget) === -1;
48102
+ return !elementsSet.has(element.labelTarget);
48054
48103
  });
48055
48104
  }
48056
48105
 
@@ -48189,7 +48238,7 @@
48189
48238
  attachers = filter(shapes, function(shape) {
48190
48239
  var host = shape.host;
48191
48240
 
48192
- return isAttacher(shape) && !includes$2(shapes, host);
48241
+ return isAttacher(shape) && !includes$1(shapes, host);
48193
48242
  });
48194
48243
  }
48195
48244
 
@@ -48385,7 +48434,7 @@
48385
48434
  return !!shape.host;
48386
48435
  }
48387
48436
 
48388
- function includes$2(array, item) {
48437
+ function includes$1(array, item) {
48389
48438
  return array.indexOf(item) !== -1;
48390
48439
  }
48391
48440
 
@@ -50006,7 +50055,7 @@
50006
50055
  });
50007
50056
  });
50008
50057
 
50009
- var parents = getParents$1(elements);
50058
+ var parentsSet = new Set(getParents$1(elements));
50010
50059
 
50011
50060
  var cache = {};
50012
50061
 
@@ -50034,7 +50083,7 @@
50034
50083
 
50035
50084
  var createShapeHints = assign$1({}, hints);
50036
50085
 
50037
- if (parents.indexOf(element) === -1) {
50086
+ if (!parentsSet.has(element)) {
50038
50087
  createShapeHints.autoResize = false;
50039
50088
  }
50040
50089
 
@@ -51454,7 +51503,8 @@
51454
51503
  oldBounds
51455
51504
  ) {
51456
51505
  var self = this,
51457
- affectedShapes = movingShapes.concat(resizingShapes);
51506
+ movingShapesSet = new Set(movingShapes),
51507
+ resizingShapesSet = new Set(resizingShapes);
51458
51508
 
51459
51509
  forEach(connections, function(connection) {
51460
51510
  var source = connection.source,
@@ -51463,7 +51513,10 @@
51463
51513
  axis = getAxisFromDirection(direction),
51464
51514
  layoutHints = {};
51465
51515
 
51466
- 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) {
51467
51520
 
51468
51521
  // move waypoints
51469
51522
  waypoints = map(waypoints, function(waypoint) {
@@ -51485,18 +51538,18 @@
51485
51538
  self._modeling.updateWaypoints(connection, waypoints, {
51486
51539
  labelBehavior: false
51487
51540
  });
51488
- } else if (includes$1(affectedShapes, source) || includes$1(affectedShapes, target)) {
51541
+ } else if (sourceAffected || targetAffected) {
51489
51542
 
51490
51543
  // re-layout connection with moved start/end
51491
- if (includes$1(movingShapes, source)) {
51544
+ if (movingShapesSet.has(source)) {
51492
51545
  layoutHints.connectionStart = getMovedSourceAnchor(connection, source, delta);
51493
- } else if (includes$1(movingShapes, target)) {
51546
+ } else if (movingShapesSet.has(target)) {
51494
51547
  layoutHints.connectionEnd = getMovedTargetAnchor(connection, target, delta);
51495
- } else if (includes$1(resizingShapes, source)) {
51548
+ } else if (resizingShapesSet.has(source)) {
51496
51549
  layoutHints.connectionStart = getResizedSourceAnchor(
51497
51550
  connection, source, oldBounds[source.id]
51498
51551
  );
51499
- } else if (includes$1(resizingShapes, target)) {
51552
+ } else if (resizingShapesSet.has(target)) {
51500
51553
  layoutHints.connectionEnd = getResizedTargetAnchor(
51501
51554
  connection, target, oldBounds[target.id]
51502
51555
  );
@@ -51550,10 +51603,6 @@
51550
51603
  }
51551
51604
  }
51552
51605
 
51553
- function includes$1(array, item) {
51554
- return array.indexOf(item) !== -1;
51555
- }
51556
-
51557
51606
  function getBounds(shape) {
51558
51607
  return {
51559
51608
  x: shape.x,
@@ -62304,6 +62353,7 @@
62304
62353
  *
62305
62354
  * @typedef {import('./OutlineProvider.js').default} OutlineProvider
62306
62355
  * @typedef {import('../../core/EventBus.js').default} EventBus
62356
+ * @typedef {import('../../core/ElementRegistry.js').default} ElementRegistry
62307
62357
  * @typedef {import('../../draw/Styles.js').default} Styles
62308
62358
  */
62309
62359
 
@@ -62313,68 +62363,124 @@
62313
62363
  * A plugin that adds an outline to shapes and connections that may be activated and styled
62314
62364
  * via CSS classes.
62315
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
+ *
62316
62370
  * @param {EventBus} eventBus
62317
62371
  * @param {Styles} styles
62372
+ * @param {ElementRegistry} elementRegistry
62318
62373
  */
62319
- function Outline$1(eventBus, styles) {
62374
+ function Outline$1(eventBus, styles, elementRegistry) {
62320
62375
 
62321
62376
  this._eventBus = eventBus;
62377
+ this._elementRegistry = elementRegistry;
62322
62378
 
62323
- this.offset = 5;
62379
+ this._outlineOffset = 5;
62324
62380
 
62325
- var OUTLINE_STYLE = styles.cls('djs-outline', [ 'no-fill' ]);
62381
+ this._outlineStyle = styles.cls('djs-outline', [ 'no-fill' ]);
62326
62382
 
62327
62383
  var self = this;
62328
62384
 
62329
62385
  /**
62330
- * @param {SVGElement} gfx
62386
+ * Lazily create the outline once an element is hovered or selected.
62331
62387
  *
62332
- * @return {SVGElement} outline
62388
+ * @param {Element} element
62333
62389
  */
62334
- function createOutline(gfx) {
62335
- var outline = create$1('rect');
62390
+ function createElementOutline(element) {
62391
+ self.createOutline(element);
62392
+ }
62336
62393
 
62337
- attr(outline, assign$1({
62338
- x: 0,
62339
- y: 0,
62340
- rx: 4,
62341
- width: 100,
62342
- height: 100
62343
- }, OUTLINE_STYLE));
62394
+ eventBus.on('element.hover', function(event) {
62395
+ createElementOutline(event.element);
62396
+ });
62344
62397
 
62345
- return outline;
62346
- }
62398
+ eventBus.on('selection.changed', function(event) {
62399
+ forEach(event.newSelection, createElementOutline);
62400
+ });
62347
62401
 
62348
- // 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
62349
62407
  // after the label bounds have been updated in the renderer.
62350
- eventBus.on([ 'shape.added', 'shape.changed' ], LOW_PRIORITY$3, function(event) {
62408
+ eventBus.on([ 'shape.changed', 'connection.changed' ], LOW_PRIORITY$3, function(event) {
62351
62409
  var element = event.element,
62352
62410
  gfx = event.gfx;
62353
62411
 
62354
62412
  var outline = query('.djs-outline', gfx);
62355
62413
 
62356
- if (!outline) {
62357
- outline = self.getOutline(element) || createOutline();
62358
- append(gfx, outline);
62414
+ if (outline) {
62415
+ self.updateOutline(element, outline);
62359
62416
  }
62360
-
62361
- self.updateShapeOutline(outline, element);
62362
62417
  });
62418
+ }
62363
62419
 
62364
- eventBus.on([ 'connection.added', 'connection.changed' ], function(event) {
62365
- var element = event.element,
62366
- 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);
62367
62434
 
62368
- var outline = query('.djs-outline', gfx);
62435
+ if (!gfx) {
62436
+ throw new Error('cannot create outline for non-rendered element');
62437
+ }
62369
62438
 
62370
- if (!outline) {
62371
- outline = createOutline();
62372
- append(gfx, outline);
62373
- }
62439
+ var outline = query('.djs-outline', gfx);
62374
62440
 
62375
- self.updateConnectionOutline(outline, element);
62376
- });
62377
- }
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
+ };
62378
62484
 
62379
62485
 
62380
62486
  /**
@@ -62397,10 +62503,10 @@
62397
62503
 
62398
62504
  if (!updated) {
62399
62505
  attr(outline, {
62400
- x: -this.offset,
62401
- y: -this.offset,
62402
- width: element.width + this.offset * 2,
62403
- 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
62404
62510
  });
62405
62511
  }
62406
62512
  };
@@ -62417,10 +62523,10 @@
62417
62523
  var bbox = getBBox(connection);
62418
62524
 
62419
62525
  attr(outline, {
62420
- x: bbox.x - this.offset,
62421
- y: bbox.y - this.offset,
62422
- width: bbox.width + this.offset * 2,
62423
- 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
62424
62530
  });
62425
62531
  };
62426
62532
 
@@ -62619,9 +62725,9 @@
62619
62725
  if (allowedElements.length === 1) {
62620
62726
  const element = allowedElements[0];
62621
62727
  if (isLabel(element)) {
62622
- createLink(element, element.labelTarget, newSelection);
62728
+ createLink(element, element.labelTarget);
62623
62729
  } else if (element.labels?.length) {
62624
- createLink(element.labels[0], element, newSelection);
62730
+ createLink(element.labels[0], element);
62625
62731
  }
62626
62732
  }
62627
62733
 
@@ -62630,7 +62736,7 @@
62630
62736
  const label = allowedElements.find(isLabel);
62631
62737
  const target = allowedElements.find(el => el.labels?.includes(label));
62632
62738
  if (label && target) {
62633
- createLink(label, target, newSelection);
62739
+ createLink(label, target);
62634
62740
  }
62635
62741
  }
62636
62742
  });
@@ -62642,9 +62748,9 @@
62642
62748
  }
62643
62749
 
62644
62750
  if (isLabel(element)) {
62645
- createLink(element, element.labelTarget, selection.get());
62751
+ createLink(element, element.labelTarget);
62646
62752
  } else if (element.labels?.length) {
62647
- createLink(element.labels[0], element, selection.get());
62753
+ createLink(element.labels[0], element);
62648
62754
  }
62649
62755
  });
62650
62756
 
@@ -62653,9 +62759,8 @@
62653
62759
  *
62654
62760
  * @param {Element} label
62655
62761
  * @param {Element} target
62656
- * @param {Element[]} selection
62657
62762
  */
62658
- function createLink(label, target, selection = []) {
62763
+ function createLink(label, target) {
62659
62764
 
62660
62765
  // Create an auxiliary line between label and target mid points
62661
62766
  const line = createLine(
@@ -62665,7 +62770,7 @@
62665
62770
  const linePath = line.getAttribute('d');
62666
62771
 
62667
62772
  // Calculate the intersection point between line and label
62668
- const labelSelected = selection.includes(label);
62773
+ const labelSelected = selection.isSelected(label);
62669
62774
  const labelPath = labelSelected ? getElementOutlinePath(label) : getElementPath(label);
62670
62775
  const labelInter = getElementLineIntersection(labelPath, linePath);
62671
62776
 
@@ -62677,7 +62782,7 @@
62677
62782
  // Calculate the intersection point between line and label
62678
62783
  // If the target is a sequence flow, there is no intersection,
62679
62784
  // so we link to the middle of it.
62680
- const targetSelected = selection.includes(target);
62785
+ const targetSelected = selection.isSelected(target);
62681
62786
  const targetPath = targetSelected ? getElementOutlinePath(target) : getElementPath(target);
62682
62787
  const targetInter = getElementLineIntersection(targetPath, linePath) || getMid(target);
62683
62788
 
@@ -62707,7 +62812,6 @@
62707
62812
  */
62708
62813
  function getElementOutlinePath(element) {
62709
62814
  const outlineShape = outline.getOutline(element);
62710
- const outlineOffset = outline.offset;
62711
62815
 
62712
62816
  if (!outlineShape) {
62713
62817
  return getElementPath(element);
@@ -62725,11 +62829,13 @@
62725
62829
  }
62726
62830
 
62727
62831
  if (outlineShape.cx) {
62832
+ const radius = parseSvgNumAttr(outlineShape, 'r');
62833
+
62728
62834
  const shape = {
62729
- x: element.x - outlineOffset,
62730
- y: element.y - outlineOffset,
62731
- width: parseSvgNumAttr(outlineShape, 'r') * 2,
62732
- 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,
62733
62839
  };
62734
62840
 
62735
62841
  return getCirclePath(shape);
@@ -62741,7 +62847,7 @@
62741
62847
  }
62742
62848
 
62743
62849
  function isElementSelected(element) {
62744
- return selection.get().includes(element);
62850
+ return selection.isSelected(element);
62745
62851
  }
62746
62852
  }
62747
62853
 
@@ -63525,7 +63631,7 @@
63525
63631
  }
63526
63632
 
63527
63633
  function getAllDraggedElements(shapes) {
63528
- var allShapes = selfAndAllChildren(shapes, true);
63634
+ var allShapes = selfAndAllChildren(shapes);
63529
63635
 
63530
63636
  var allConnections = allShapes.flatMap(shape =>
63531
63637
  (shape.incoming || []).concat(shape.outgoing || [])
@@ -63701,6 +63807,12 @@
63701
63807
  */
63702
63808
  function removeEdges(elements) {
63703
63809
 
63810
+ var elementIds = new Set();
63811
+
63812
+ elements.forEach(function(element) {
63813
+ elementIds.add(element.id);
63814
+ });
63815
+
63704
63816
  var filteredElements = filter(elements, function(element) {
63705
63817
 
63706
63818
  if (!isConnection(element)) {
@@ -63708,8 +63820,8 @@
63708
63820
  } else {
63709
63821
 
63710
63822
  return (
63711
- find(elements, matchPattern({ id: element.source.id })) &&
63712
- find(elements, matchPattern({ id: element.target.id }))
63823
+ elementIds.has(element.source.id) &&
63824
+ elementIds.has(element.target.id)
63713
63825
  );
63714
63826
  }
63715
63827
  });