bpmn-js 18.13.2 → 18.15.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.13.2
2
+ * bpmn-js - bpmn-modeler v18.15.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-03-23
11
+ * Date: 2026-04-22
12
12
  */
13
13
  (function (global, factory) {
14
14
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
@@ -123,7 +123,7 @@
123
123
  *
124
124
  * @param {Object} [element] element to bind the id to
125
125
  *
126
- * @return {String} id
126
+ * @return {string} id
127
127
  */
128
128
  Ids$1.prototype.next = function(element) {
129
129
  return this._seed(element || true);
@@ -134,7 +134,7 @@
134
134
  *
135
135
  * @param {Object} [element] element to bind the id to
136
136
  *
137
- * @return {String} id
137
+ * @return {string} id
138
138
  */
139
139
  Ids$1.prototype.nextPrefixed = function(prefix, element) {
140
140
  var id;
@@ -153,8 +153,8 @@
153
153
  /**
154
154
  * Manually claim an existing id.
155
155
  *
156
- * @param {String} id
157
- * @param {String} [element] element the id is claimed by
156
+ * @param {string} id
157
+ * @param {any} [element] element the id is claimed by
158
158
  */
159
159
  Ids$1.prototype.claim = function(id, element) {
160
160
  this._seed.set(id, element || true);
@@ -163,8 +163,8 @@
163
163
  /**
164
164
  * Returns true if the given id has already been assigned.
165
165
  *
166
- * @param {String} id
167
- * @return {Boolean}
166
+ * @param {string} id
167
+ * @return {boolean}
168
168
  */
169
169
  Ids$1.prototype.assigned = function(id) {
170
170
  return this._seed.get(id) || false;
@@ -173,7 +173,7 @@
173
173
  /**
174
174
  * Unclaim an id.
175
175
  *
176
- * @param {String} id the id to unclaim
176
+ * @param {string} id the id to unclaim
177
177
  */
178
178
  Ids$1.prototype.unclaim = function(id) {
179
179
  delete this._seed.hats[id];
@@ -3095,7 +3095,7 @@
3095
3095
  * @param {Element[]} elements List of Elements to search through
3096
3096
  * @param {Rect} bbox the enclosing bbox.
3097
3097
  *
3098
- * @return {Element[]} enclosed elements
3098
+ * @return {Record<string, Element>} enclosed elements
3099
3099
  */
3100
3100
  function getEnclosedElements(elements, bbox) {
3101
3101
 
@@ -20984,47 +20984,105 @@
20984
20984
  }
20985
20985
  }
20986
20986
 
20987
+ /** @type {CanvasRenderingContext2D | null} */
20988
+ var _canvasContext = null;
20989
+
20987
20990
  /**
20988
- * @param {string} text
20989
- * @param {SVGTextElement} fakeText
20991
+ * @return {CanvasRenderingContext2D | null}
20992
+ */
20993
+ function getCanvasContext() {
20994
+ if (!_canvasContext) {
20995
+ _canvasContext = document.createElement('canvas').getContext('2d');
20996
+ }
20997
+
20998
+ return _canvasContext;
20999
+ }
21000
+
21001
+ /**
21002
+ * Build a CSS font string from a style object for use with the canvas
21003
+ * measureText API.
20990
21004
  *
20991
- * @return {import('../util/Types').Dimensions}
21005
+ * @param {Record<string, number | string>} style
21006
+ *
21007
+ * @return {string}
20992
21008
  */
20993
- function getTextBBox(text, fakeText) {
21009
+ function buildFont(style) {
21010
+ var parts = [];
20994
21011
 
20995
- fakeText.textContent = text;
21012
+ if (style.fontStyle) {
21013
+ parts.push(style.fontStyle);
21014
+ }
20996
21015
 
20997
- var textBBox;
21016
+ if (style.fontVariant) {
21017
+ parts.push(style.fontVariant);
21018
+ }
20998
21019
 
20999
- try {
21000
- var bbox,
21001
- emptyLine = text === '';
21020
+ if (style.fontWeight) {
21021
+ parts.push(style.fontWeight);
21022
+ }
21002
21023
 
21003
- // add dummy text, when line is empty to
21004
- // determine correct height
21005
- fakeText.textContent = emptyLine ? 'dummy' : text;
21024
+ if (style.fontStretch) {
21025
+ parts.push(style.fontStretch);
21026
+ }
21006
21027
 
21007
- textBBox = fakeText.getBBox();
21028
+ parts.push(buildLength(style.fontSize) || '12px');
21029
+ parts.push(style.fontFamily || 'sans-serif');
21008
21030
 
21009
- // take text rendering related horizontal
21010
- // padding into account
21011
- bbox = {
21012
- width: textBBox.width + textBBox.x * 2,
21013
- height: textBBox.height
21014
- };
21031
+ return parts.join(' ');
21032
+ }
21033
+
21034
+ /**
21035
+ * Coerce a CSS length to a string with units, since canvas APIs
21036
+ * silently reject unitless lengths and keep the previous value.
21037
+ *
21038
+ * @param {number | string | undefined} value
21039
+ *
21040
+ * @return {string | undefined}
21041
+ */
21042
+ function buildLength(value) {
21043
+ if (value == null) {
21044
+ return undefined;
21045
+ }
21015
21046
 
21016
- if (emptyLine) {
21047
+ if (typeof value === 'number' || /^-?\d+(\.\d+)?$/.test(value)) {
21048
+ return value + 'px';
21049
+ }
21017
21050
 
21018
- // correct width
21019
- bbox.width = 0;
21020
- }
21051
+ return value;
21052
+ }
21021
21053
 
21022
- return bbox;
21023
- } catch (e) {
21024
- console.log(e);
21054
+ /**
21055
+ * @param {string} text
21056
+ * @param {Record<string, number | string>} style
21057
+ *
21058
+ * @return {import('../util/Types').Dimensions}
21059
+ */
21060
+ function getTextBBox(text, style) {
21061
+ var ctx = getCanvasContext();
21025
21062
 
21063
+ if (!ctx) {
21026
21064
  return { width: 0, height: 0 };
21027
21065
  }
21066
+
21067
+ ctx.font = buildFont(style);
21068
+
21069
+ if ('letterSpacing' in ctx) {
21070
+ ctx.letterSpacing = buildLength(style.letterSpacing) || '0px';
21071
+ }
21072
+
21073
+ var emptyLine = text === '';
21074
+
21075
+ // strip trailing whitespace so measurement matches the browser's
21076
+ // native rendering used by direct editing
21077
+ var measurable = emptyLine ? 'dummy' : text.replace(/\s+$/, '');
21078
+ var metrics = ctx.measureText(measurable);
21079
+
21080
+ return {
21081
+ width: emptyLine ? 0 : metrics.width,
21082
+ height: 'fontBoundingBoxAscent' in metrics
21083
+ ? metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent
21084
+ : metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent
21085
+ };
21028
21086
  }
21029
21087
 
21030
21088
 
@@ -21035,11 +21093,11 @@
21035
21093
  *
21036
21094
  * @param {string[]} lines
21037
21095
  * @param {number} maxWidth
21038
- * @param {SVGTextElement} fakeText
21096
+ * @param {Record<string, number | string>} style
21039
21097
  *
21040
21098
  * @return {LineDescriptor} the line descriptor
21041
21099
  */
21042
- function layoutNext(lines, maxWidth, fakeText) {
21100
+ function layoutNext(lines, maxWidth, style) {
21043
21101
 
21044
21102
  var originalLine = lines.shift(),
21045
21103
  fitLine = originalLine;
@@ -21047,7 +21105,7 @@
21047
21105
  var textBBox;
21048
21106
 
21049
21107
  for (;;) {
21050
- textBBox = getTextBBox(fitLine, fakeText);
21108
+ textBBox = getTextBBox(fitLine, style);
21051
21109
 
21052
21110
  textBBox.width = fitLine ? textBBox.width : 0;
21053
21111
 
@@ -21154,33 +21212,6 @@
21154
21212
  }
21155
21213
 
21156
21214
 
21157
- /**
21158
- * @return {SVGSVGElement}
21159
- */
21160
- function getHelperSvg() {
21161
- var helperSvg = document.getElementById('helper-svg');
21162
-
21163
- if (!helperSvg) {
21164
- helperSvg = create$1('svg');
21165
-
21166
- attr(helperSvg, {
21167
- id: 'helper-svg'
21168
- });
21169
-
21170
- assign(helperSvg, {
21171
- visibility: 'hidden',
21172
- position: 'fixed',
21173
- width: 0,
21174
- height: 0
21175
- });
21176
-
21177
- document.body.appendChild(helperSvg);
21178
- }
21179
-
21180
- return helperSvg;
21181
- }
21182
-
21183
-
21184
21215
  /**
21185
21216
  * Creates a new label utility
21186
21217
  *
@@ -21247,17 +21278,8 @@
21247
21278
 
21248
21279
  var maxWidth = box.width - padding.left - padding.right;
21249
21280
 
21250
- // ensure correct rendering by attaching helper text node to invisible SVG
21251
- var helperText = create$1('text');
21252
- attr(helperText, { x: 0, y: 0 });
21253
- attr(helperText, style);
21254
-
21255
- var helperSvg = getHelperSvg();
21256
-
21257
- append(helperSvg, helperText);
21258
-
21259
21281
  while (lines.length) {
21260
- layouted.push(layoutNext(lines, maxWidth, helperText));
21282
+ layouted.push(layoutNext(lines, maxWidth, style));
21261
21283
  }
21262
21284
 
21263
21285
  if (align.vertical === 'middle') {
@@ -21320,8 +21342,6 @@
21320
21342
  append(textElement, tspan);
21321
21343
  });
21322
21344
 
21323
- remove$1(helperText);
21324
-
21325
21345
  var dimensions = {
21326
21346
  width: maxLineWidth,
21327
21347
  height: totalHeight
@@ -25050,7 +25070,7 @@
25050
25070
  */
25051
25071
 
25052
25072
  var MARKER_HOVER = 'hover',
25053
- MARKER_SELECTED = 'selected';
25073
+ MARKER_SELECTED$1 = 'selected';
25054
25074
 
25055
25075
  /**
25056
25076
  * A plugin that adds a visible selection UI to shapes and connections
@@ -25085,11 +25105,11 @@
25085
25105
  eventBus.on('selection.changed', function(event) {
25086
25106
 
25087
25107
  function deselect(s) {
25088
- removeMarker(s, MARKER_SELECTED);
25108
+ removeMarker(s, MARKER_SELECTED$1);
25089
25109
  }
25090
25110
 
25091
25111
  function select(s) {
25092
- addMarker(s, MARKER_SELECTED);
25112
+ addMarker(s, MARKER_SELECTED$1);
25093
25113
  }
25094
25114
 
25095
25115
  var oldSelection = event.oldSelection,
@@ -28757,11 +28777,16 @@
28757
28777
  /**
28758
28778
  * @typedef { {
28759
28779
  * index: number;
28760
- * match: boolean;
28761
- * value: string;
28762
- * } } Token
28780
+ * value: string,
28781
+ * match?: boolean;
28782
+ * start?: boolean;
28783
+ * end?: boolean;
28784
+ * wordStart?: boolean;
28785
+ * wordEnd?: boolean;
28786
+ * all?: boolean;
28787
+ * } } BaseToken
28763
28788
  *
28764
- * @typedef {Token[]} Tokens
28789
+ * @typedef { BaseToken | BaseToken[] } Token
28765
28790
  */
28766
28791
 
28767
28792
  /**
@@ -28769,7 +28794,7 @@
28769
28794
  *
28770
28795
  * @typedef { {
28771
28796
  * item: R,
28772
- * tokens: Record<string, Tokens>
28797
+ * tokens: Record<string, Token[]>
28773
28798
  * } } SearchResult
28774
28799
  */
28775
28800
 
@@ -28780,15 +28805,15 @@
28780
28805
  /**
28781
28806
  * Search items by query.
28782
28807
  *
28783
- * @template {SearchItem} T
28808
+ * @template { SearchItem } T
28784
28809
  *
28785
- * @param {T[]} items elements to search in
28786
- * @param {string} pattern pattern to search for
28810
+ * @param { T[] } items elements to search in
28811
+ * @param { string } pattern pattern to search for
28787
28812
  * @param { {
28788
28813
  * keys: string[];
28789
28814
  * } } options
28790
28815
  *
28791
- * @returns {SearchResult<T>[]}
28816
+ * @returns { SearchResult<T>[] }
28792
28817
  */
28793
28818
  function search(items, pattern, options) {
28794
28819
 
@@ -28804,7 +28829,7 @@
28804
28829
 
28805
28830
  const words = pattern.trim().toLowerCase().split(/\s+/);
28806
28831
 
28807
- return items.flatMap((item) => {
28832
+ return items.flatMap((/** @type {T} */ item) => {
28808
28833
  const tokens = matchItem(item, words, keys);
28809
28834
 
28810
28835
  if (!tokens) {
@@ -28821,11 +28846,11 @@
28821
28846
  /**
28822
28847
  * Match an item and return tokens in case of a match.
28823
28848
  *
28824
- * @param {SearchItem} item element to be matched
28825
- * @param {string[]} words words from search pattern to find
28826
- * @param {string[]} keys keys to search in the item
28849
+ * @param { SearchItem } item element to be matched
28850
+ * @param { string[] } words words from search pattern to find
28851
+ * @param { string[] } keys keys to search in the item
28827
28852
  *
28828
- * @returns {Record<string, Tokens>}
28853
+ * @returns { Record<string, Token[]> | null }
28829
28854
  */
28830
28855
  function matchItem(item, words, keys) {
28831
28856
 
@@ -28852,8 +28877,8 @@
28852
28877
  };
28853
28878
  },
28854
28879
  {
28855
- matchedWords: {},
28856
- tokens: []
28880
+ matchedWords: /** @type { Record<string, boolean> } */ ({}),
28881
+ tokens: /** @type { Token[] } */ ([])
28857
28882
  }
28858
28883
  )
28859
28884
  ) : (
@@ -28886,15 +28911,17 @@
28886
28911
  /**
28887
28912
  * Creates a compare function that can be used in Array.sort() based on a custom scoring function
28888
28913
  *
28889
- * @param {string[]} keys
28914
+ * @template {SearchItem} T
28915
+ *
28916
+ * @param { string[] } keys
28890
28917
  *
28891
- * @returns { (resultA: SearchResult, resultB: SearchResult) => number}
28918
+ * @returns { (resultA: SearchResult<T>, resultB: SearchResult<T>) => number }
28892
28919
  */
28893
28920
  function createResultSorter(keys) {
28894
28921
 
28895
28922
  /**
28896
- * @param {SearchResult} resultA
28897
- * @param {SearchResult} resultB
28923
+ * @param { SearchResult<T> } resultA
28924
+ * @param { SearchResult<T> } resultB
28898
28925
  */
28899
28926
  return (resultA, resultB) => {
28900
28927
  let comparison = 0;
@@ -28911,7 +28938,7 @@
28911
28938
 
28912
28939
  if (tokenComparison !== 0) {
28913
28940
  comparison += tokenComparison * modifier;
28914
- modifier *= 0.9;
28941
+ modifier *= DECAY_MODIFIER;
28915
28942
  continue;
28916
28943
  }
28917
28944
 
@@ -28922,7 +28949,7 @@
28922
28949
 
28923
28950
  if (stringComparison !== 0) {
28924
28951
  comparison += stringComparison * modifier;
28925
- modifier *= 0.9;
28952
+ modifier *= DECAY_MODIFIER;
28926
28953
  continue;
28927
28954
  }
28928
28955
  }
@@ -28935,21 +28962,43 @@
28935
28962
  /**
28936
28963
  * Compares two token arrays.
28937
28964
  *
28938
- * @param {Token[]} [tokensA]
28939
- * @param {Token[]} [tokensB]
28965
+ * @param { Token[] } tokensA
28966
+ * @param { Token[] } tokensB
28940
28967
  *
28941
- * @returns {number}
28968
+ * @returns { number }
28942
28969
  */
28943
28970
  function compareTokens(tokensA, tokensB) {
28944
28971
  return scoreTokens(tokensB) - scoreTokens(tokensA);
28945
28972
  }
28946
28973
 
28974
+ const DECAY_MODIFIER = 0.5;
28975
+
28976
+ const TOKEN_MATCH_SCORES = {
28977
+ FULL: 131.9,
28978
+ START_FULL_WORD: 8.0,
28979
+ START_WORD_PART: 7.87,
28980
+ WORD_START: 2.19,
28981
+ WORD_PART: 1,
28982
+ NO_MATCH: -0.07
28983
+ };
28984
+
28947
28985
  /**
28948
28986
  * @param { Token[] } tokens
28949
28987
  * @returns { number }
28950
28988
  */
28951
28989
  function scoreTokens(tokens) {
28952
- return tokens.reduce((sum, token) => sum + scoreToken(token), 0);
28990
+ const baseScore = tokens.reduce((sum, token) => sum + scoreToken(token), 0);
28991
+
28992
+ const flatTokens = tokens.flat();
28993
+
28994
+ const totalLength = flatTokens.reduce((sum, token) => sum + token.value.length, 0);
28995
+ const matchedLength = flatTokens.reduce((sum, token) => sum + (token.match ? token.value.length : 0), 0);
28996
+
28997
+ const density = totalLength ? matchedLength / totalLength : 0;
28998
+
28999
+ const score = baseScore * (1 + density);
29000
+
29001
+ return score;
28953
29002
  }
28954
29003
 
28955
29004
  /**
@@ -28968,28 +29017,30 @@
28968
29017
  const modifier = Math.log(token.value.length);
28969
29018
 
28970
29019
  if (!token.match) {
28971
- return -0.07 * modifier;
29020
+ return TOKEN_MATCH_SCORES.NO_MATCH * modifier;
28972
29021
  }
28973
29022
 
28974
29023
  return (
28975
29024
  token.start
28976
29025
  ? (
28977
29026
  token.end
28978
- ? 131.9
28979
- : 7.87
29027
+ ? TOKEN_MATCH_SCORES.FULL
29028
+ : token.wordEnd
29029
+ ? TOKEN_MATCH_SCORES.START_FULL_WORD
29030
+ : TOKEN_MATCH_SCORES.START_WORD_PART
28980
29031
  )
28981
29032
  : (
28982
29033
  token.wordStart
28983
- ? 2.19
28984
- : 1
29034
+ ? TOKEN_MATCH_SCORES.WORD_START
29035
+ : TOKEN_MATCH_SCORES.WORD_PART
28985
29036
  )
28986
29037
  ) * modifier;
28987
29038
  }
28988
29039
 
28989
29040
  /**
28990
- * @param {string|string[]} [str='']
29041
+ * @param { string|string[] } [str='']
28991
29042
  *
28992
- * @return {string}
29043
+ * @return { string }
28993
29044
  */
28994
29045
  function stringJoin(str = '') {
28995
29046
  return isArray$2(str) ? str.join(', ') : str;
@@ -28998,10 +29049,10 @@
28998
29049
  /**
28999
29050
  * Compares two strings. also supports string arrays, which will be joined
29000
29051
  *
29001
- * @param {string|string[]} [a]
29002
- * @param {string|string[]} [b]
29052
+ * @param { string|string[] } [a]
29053
+ * @param { string|string[] } [b]
29003
29054
  *
29004
- * @returns {number}
29055
+ * @returns { number }
29005
29056
  */
29006
29057
  function compareStrings(a, b) {
29007
29058
  return stringJoin(a).localeCompare(stringJoin(b));
@@ -29011,11 +29062,11 @@
29011
29062
  * Match a given string against a set of words,
29012
29063
  * and return the result.
29013
29064
  *
29014
- * @param {string} string
29015
- * @param {string[]} words
29065
+ * @param { string } string
29066
+ * @param { string[] } words
29016
29067
  *
29017
29068
  * @return { {
29018
- * tokens: Token[],
29069
+ * tokens: BaseToken[],
29019
29070
  * matchedWords: Record<string, boolean>
29020
29071
  * } }
29021
29072
  */
@@ -29028,7 +29079,14 @@
29028
29079
  };
29029
29080
  }
29030
29081
 
29082
+ /**
29083
+ * @type { BaseToken[] }
29084
+ */
29031
29085
  const tokens = [];
29086
+
29087
+ /**
29088
+ * @type { Record<string, boolean> }
29089
+ */
29032
29090
  const matchedWords = {};
29033
29091
 
29034
29092
  const wordsEscaped = words.map(escapeRegexp);
@@ -29053,7 +29111,7 @@
29053
29111
  const start = startIndex === 0;
29054
29112
  const end = endIndex === string.length;
29055
29113
 
29056
- const all = !!match.groups.all;
29114
+ const all = !!match.groups?.all;
29057
29115
 
29058
29116
  const wordStart = start || /\s/.test(string.charAt(startIndex - 1));
29059
29117
  const wordEnd = end || /\s/.test(string.charAt(endIndex));
@@ -29102,6 +29160,13 @@
29102
29160
  };
29103
29161
  }
29104
29162
 
29163
+ /**
29164
+ * Escape string to not contain illegal regexp chars.
29165
+ *
29166
+ * @param { string } string
29167
+ *
29168
+ * @return { string }
29169
+ */
29105
29170
  function escapeRegexp(string) {
29106
29171
  return string.replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&');
29107
29172
  }
@@ -30695,7 +30760,7 @@
30695
30760
  * @typedef {import('../../core/EventBus').default} EventBus
30696
30761
  */
30697
30762
 
30698
- var HIGH_PRIORITY$k = 1500;
30763
+ var HIGH_PRIORITY$l = 1500;
30699
30764
 
30700
30765
 
30701
30766
  /**
@@ -30763,7 +30828,7 @@
30763
30828
  */
30764
30829
  eventBus.on('drag.start', function(event) {
30765
30830
 
30766
- eventBus.once('drag.move', HIGH_PRIORITY$k, function(event) {
30831
+ eventBus.once('drag.move', HIGH_PRIORITY$l, function(event) {
30767
30832
 
30768
30833
  ensureHover(event);
30769
30834
 
@@ -30794,7 +30859,7 @@
30794
30859
  hover = event.element;
30795
30860
  });
30796
30861
 
30797
- eventBus.on('element.hover', HIGH_PRIORITY$k, function(event) {
30862
+ eventBus.on('element.hover', HIGH_PRIORITY$l, function(event) {
30798
30863
 
30799
30864
  // (3) am I on an element still?
30800
30865
  if (hover) {
@@ -32745,7 +32810,7 @@
32745
32810
  MARKER_CONNECT_UPDATING$1 = 'djs-updating',
32746
32811
  MARKER_DRAGGER = 'djs-dragging';
32747
32812
 
32748
- var HIGH_PRIORITY$j = 1100;
32813
+ var HIGH_PRIORITY$k = 1100;
32749
32814
 
32750
32815
  /**
32751
32816
  * Preview connection while moving bendpoints.
@@ -32813,7 +32878,7 @@
32813
32878
  eventBus.on([
32814
32879
  'bendpoint.move.out',
32815
32880
  'bendpoint.move.cleanup'
32816
- ], HIGH_PRIORITY$j, function(event) {
32881
+ ], HIGH_PRIORITY$k, function(event) {
32817
32882
  var context = event.context,
32818
32883
  hover = context.hover,
32819
32884
  target = context.target;
@@ -32899,7 +32964,7 @@
32899
32964
  eventBus.on([
32900
32965
  'bendpoint.move.end',
32901
32966
  'bendpoint.move.cancel'
32902
- ], HIGH_PRIORITY$j, function(event) {
32967
+ ], HIGH_PRIORITY$k, function(event) {
32903
32968
  var context = event.context,
32904
32969
  connection = context.connection,
32905
32970
  draggerGfx = context.draggerGfx,
@@ -33915,7 +33980,7 @@
33915
33980
  * @typedef {import('../../core/EventBus').default} EventBus
33916
33981
  */
33917
33982
 
33918
- var HIGH_PRIORITY$i = 1100,
33983
+ var HIGH_PRIORITY$j = 1100,
33919
33984
  LOW_PRIORITY$k = 900;
33920
33985
 
33921
33986
  var MARKER_OK$3 = 'connect-ok',
@@ -33976,7 +34041,7 @@
33976
34041
  eventBus.on([
33977
34042
  'connect.out',
33978
34043
  'connect.cleanup'
33979
- ], HIGH_PRIORITY$i, function(event) {
34044
+ ], HIGH_PRIORITY$j, function(event) {
33980
34045
  var hover = event.hover;
33981
34046
 
33982
34047
  if (hover) {
@@ -35019,6 +35084,114 @@
35019
35084
  'eventBus'
35020
35085
  ];
35021
35086
 
35087
+ /**
35088
+ * @typedef {import('diagram-js/lib/core/EventBus').default} EventBus
35089
+ * @typedef {import('diagram-js/lib/core/Canvas').default} Canvas
35090
+ * @typedef {import('../Modeling').default} Modeling
35091
+ * @typedef {import('didi').Injector} Injector
35092
+ *
35093
+ * @typedef {import('../../../model/Types').Element} Element
35094
+ */
35095
+
35096
+ var HIGH_PRIORITY$i = 1500;
35097
+
35098
+ /**
35099
+ * A behavior that ensures that visually enclosed artifacts are affected
35100
+ * by container element behavior:
35101
+ *
35102
+ * * removed when the container is removed
35103
+ * * moved when the container is moved
35104
+ *
35105
+ * @param {Injector} injector
35106
+ * @param {EventBus} eventBus
35107
+ * @param {Canvas} canvas
35108
+ * @param {Modeling} modeling
35109
+ */
35110
+ function ArtifactBehavior(
35111
+ injector,
35112
+ eventBus,
35113
+ canvas,
35114
+ modeling
35115
+ ) {
35116
+ injector.invoke(CommandInterceptor, this);
35117
+
35118
+ // enclosed artifacts are deleted with a container element
35119
+ this.preExecute('elements.delete', HIGH_PRIORITY$i, function(event) {
35120
+ var context = event.context,
35121
+ elements = context.elements;
35122
+
35123
+ var enclosedArtifacts = getEnclosedArtifacts(elements);
35124
+
35125
+ if (enclosedArtifacts.length) {
35126
+ modeling.removeElements(enclosedArtifacts);
35127
+ }
35128
+ });
35129
+
35130
+ // enclosed artifacts are moved with container element
35131
+ eventBus.on('shape.move.start', function(event) {
35132
+
35133
+ var shapes = event.context.shapes;
35134
+
35135
+ var enclosedArtifacts = getEnclosedArtifacts(shapes);
35136
+
35137
+ if (enclosedArtifacts.length) {
35138
+ event.context.shapes = shapes.concat(enclosedArtifacts);
35139
+ }
35140
+ });
35141
+
35142
+
35143
+ /**
35144
+ * @param { Element[] } elements
35145
+ *
35146
+ * @return { Element[] }
35147
+ */
35148
+ function getEnclosedArtifacts(elements) {
35149
+
35150
+ var containerElements = filter(
35151
+ elements, e => is(e, 'bpmn:Participant') || is(e, 'bpmn:SubProcess')
35152
+ );
35153
+
35154
+ if (!containerElements.length) {
35155
+ return [];
35156
+ }
35157
+
35158
+ var canvasRoot = canvas.getRootElement();
35159
+
35160
+ // artifacts that still need to be checked for being enclosed
35161
+ var remainingArtifacts = new Set(canvasRoot.children.filter(
35162
+ (child) => is(child, 'bpmn:Artifact')
35163
+ ));
35164
+
35165
+ // artifacts that are definitely enclosed
35166
+ var enclosedArtifacts = new Set();
35167
+
35168
+ // we need to verify for all container elements, all artifacts <m:n>
35169
+ forEach(containerElements, containerElement => {
35170
+ const newEnclosedArtifacts = new Set(values(
35171
+ getEnclosedElements(
35172
+ Array.from(remainingArtifacts),
35173
+ getBBox(containerElement)
35174
+ )
35175
+ ));
35176
+
35177
+ enclosedArtifacts = enclosedArtifacts.union(newEnclosedArtifacts);
35178
+ remainingArtifacts = remainingArtifacts.difference(newEnclosedArtifacts);
35179
+ });
35180
+
35181
+ return Array.from(enclosedArtifacts);
35182
+ }
35183
+
35184
+ }
35185
+
35186
+ e$2(ArtifactBehavior, CommandInterceptor);
35187
+
35188
+ ArtifactBehavior.$inject = [
35189
+ 'injector',
35190
+ 'eventBus',
35191
+ 'canvas',
35192
+ 'modeling'
35193
+ ];
35194
+
35022
35195
  /**
35023
35196
  * @typedef {import('didi').Injector} Injector
35024
35197
  * @typedef {import('../Modeling').default} Modeling
@@ -41668,6 +41841,7 @@
41668
41841
  __init__: [
41669
41842
  'adaptiveLabelPositioningBehavior',
41670
41843
  'appendBehavior',
41844
+ 'artifactBehavior',
41671
41845
  'associationBehavior',
41672
41846
  'attachEventBehavior',
41673
41847
  'boundaryEventBehavior',
@@ -41712,6 +41886,7 @@
41712
41886
  appendBehavior: [ 'type', AppendBehavior ],
41713
41887
  associationBehavior: [ 'type', AssociationBehavior ],
41714
41888
  attachEventBehavior: [ 'type', AttachEventBehavior ],
41889
+ artifactBehavior: [ 'type', ArtifactBehavior ],
41715
41890
  boundaryEventBehavior: [ 'type', BoundaryEventBehavior ],
41716
41891
  compensateBoundaryEventBehaviour: [ 'type', CompensateBoundaryEventBehavior ],
41717
41892
  createBehavior: [ 'type', CreateBehavior ],
@@ -53075,149 +53250,155 @@
53075
53250
  return [];
53076
53251
  };
53077
53252
 
53078
- /**
53079
- * @typedef {import('diagram-js/lib/command/CommandHandler').default} CommandHandler
53080
- *
53081
- * @typedef {import('diagram-js/lib/command/CommandStack').default} CommandStack
53082
- *
53083
- * @typedef {import('../../../model/Types').ModdleElement} ModdleElement
53084
- */
53085
-
53086
- var DEFAULT_COLORS = {
53087
- fill: undefined,
53088
- stroke: undefined
53089
- };
53090
-
53091
- /**
53092
- * @implements {CommandHandler}
53093
- *
53094
- * @param {CommandStack} commandStack
53095
- */
53096
- function SetColorHandler(commandStack) {
53097
- this._commandStack = commandStack;
53098
-
53099
- this._normalizeColor = function(color) {
53100
-
53101
- // Remove color for falsy values.
53102
- if (!color) {
53103
- return undefined;
53104
- }
53105
-
53106
- if (isString(color)) {
53107
- var hexColor = colorToHex(color);
53108
-
53109
- if (hexColor) {
53110
- return hexColor;
53111
- }
53112
- }
53113
-
53114
- throw new Error(`invalid color value: ${ color }`);
53115
- };
53116
- }
53117
-
53118
- SetColorHandler.$inject = [
53119
- 'commandStack'
53120
- ];
53121
-
53122
-
53123
- SetColorHandler.prototype.postExecute = function(context) {
53124
- var elements = context.elements,
53125
- colors = context.colors || DEFAULT_COLORS;
53126
-
53127
- var self = this;
53128
-
53129
- var di = {};
53130
-
53131
- if ('fill' in colors) {
53132
- assign$1(di, {
53133
- 'background-color': this._normalizeColor(colors.fill) });
53134
- }
53135
-
53136
- if ('stroke' in colors) {
53137
- assign$1(di, {
53138
- 'border-color': this._normalizeColor(colors.stroke) });
53139
- }
53140
-
53141
- forEach(elements, function(element) {
53142
- var assignedDi = isConnection(element) ? pick(di, [ 'border-color' ]) : di,
53143
- elementDi = getDi(element);
53144
-
53145
- // TODO @barmac: remove once we drop bpmn.io properties
53146
- ensureLegacySupport(assignedDi);
53147
-
53148
- if (isLabel(element)) {
53149
-
53150
- // set label colors as bpmndi:BPMNLabel#color
53151
- self._commandStack.execute('element.updateModdleProperties', {
53152
- element: element,
53153
- moddleElement: elementDi.label,
53154
- properties: {
53155
- color: di['border-color']
53156
- }
53157
- });
53158
- } else {
53159
-
53160
- // ignore non-compliant di
53161
- if (!isAny(elementDi, [ 'bpmndi:BPMNEdge', 'bpmndi:BPMNShape' ])) {
53162
- return;
53163
- }
53164
-
53165
- // set colors bpmndi:BPMNEdge or bpmndi:BPMNShape
53166
- self._commandStack.execute('element.updateProperties', {
53167
- element: element,
53168
- properties: {
53169
- di: assignedDi
53170
- }
53171
- });
53172
- }
53173
- });
53174
-
53175
- };
53176
-
53177
- /**
53178
- * Convert color from rgb(a)/hsl to hex. Returns `null` for unknown color names
53179
- * and for colors with alpha less than 1.0. This depends on `<canvas>`
53180
- * serialization of the `context.fillStyle`.
53181
- * Cf. https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-fillstyle
53182
- *
53183
- * @example
53184
- *
53185
- * ```javascript
53186
- * colorToHex('fuchsia'); // "#ff00ff"
53187
- *
53188
- * colorToHex('rgba(1, 2, 3, 0.4)'); // null
53189
- * ```
53190
- *
53191
- * @param {string} color
53192
- *
53193
- * @return {string|null}
53194
- */
53195
- function colorToHex(color) {
53196
- var context = document.createElement('canvas').getContext('2d');
53197
-
53198
- // (0) Start with transparent to account for browser default values.
53199
- context.fillStyle = 'transparent';
53200
-
53201
- // (1) Assign color so that it's serialized.
53202
- context.fillStyle = color;
53203
-
53204
- // (2) Return null for non-hex serialization result.
53205
- return /^#[0-9a-fA-F]{6}$/.test(context.fillStyle) ? context.fillStyle : null;
53206
- }
53207
-
53208
- /**
53209
- * Add legacy properties if required.
53210
- *
53211
- * @param {ModdleElement} di
53212
- */
53213
- function ensureLegacySupport(di) {
53214
- if ('border-color' in di) {
53215
- di.stroke = di['border-color'];
53216
- }
53217
-
53218
- if ('background-color' in di) {
53219
- di.fill = di['background-color'];
53220
- }
53253
+ /**
53254
+ * @typedef {import('diagram-js/lib/command/CommandHandler').default} CommandHandler
53255
+ *
53256
+ * @typedef {import('diagram-js/lib/command/CommandStack').default} CommandStack
53257
+ *
53258
+ * @typedef {import('../../../model/Types').ModdleElement} ModdleElement
53259
+ */
53260
+
53261
+ var DEFAULT_COLORS = {
53262
+ fill: undefined,
53263
+ stroke: undefined
53264
+ };
53265
+
53266
+ /**
53267
+ * @implements {CommandHandler}
53268
+ *
53269
+ * @param {CommandStack} commandStack
53270
+ */
53271
+ function SetColorHandler(commandStack) {
53272
+ this._commandStack = commandStack;
53273
+
53274
+ this._normalizeColor = function(color) {
53275
+
53276
+ // Remove color for falsy values.
53277
+ if (!color) {
53278
+ return undefined;
53279
+ }
53280
+
53281
+ if (isString(color)) {
53282
+ var hexColor = colorToHex(color);
53283
+
53284
+ if (hexColor) {
53285
+ return hexColor;
53286
+ }
53287
+ }
53288
+
53289
+ throw new Error(`invalid color value: ${ color }`);
53290
+ };
53291
+ }
53292
+
53293
+ SetColorHandler.$inject = [
53294
+ 'commandStack'
53295
+ ];
53296
+
53297
+
53298
+ SetColorHandler.prototype.postExecute = function(context) {
53299
+ var elements = context.elements,
53300
+ colors = context.colors || DEFAULT_COLORS;
53301
+
53302
+ var self = this;
53303
+
53304
+ var di = {};
53305
+
53306
+ if ('fill' in colors) {
53307
+ assign$1(di, {
53308
+ 'background-color': this._normalizeColor(colors.fill)
53309
+ });
53310
+ }
53311
+
53312
+ if ('stroke' in colors) {
53313
+ assign$1(di, {
53314
+ 'border-color': this._normalizeColor(colors.stroke)
53315
+ });
53316
+ }
53317
+
53318
+ forEach(elements, function(element) {
53319
+ var assignedDi = isConnection(element) ? pick(di, [ 'border-color' ]) : di,
53320
+ elementDi = getDi(element);
53321
+
53322
+ // TODO @barmac: remove once we drop bpmn.io properties
53323
+ ensureLegacySupport(assignedDi);
53324
+
53325
+ if (isLabel(element)) {
53326
+
53327
+ if (!elementDi || !is(elementDi.label, 'bpmndi:BPMNLabel')) {
53328
+ return;
53329
+ }
53330
+
53331
+ // set label colors as bpmndi:BPMNLabel#color
53332
+ self._commandStack.execute('element.updateModdleProperties', {
53333
+ element: element,
53334
+ moddleElement: elementDi.label,
53335
+ properties: {
53336
+ color: di['border-color']
53337
+ }
53338
+ });
53339
+ } else {
53340
+
53341
+ // ignore non-compliant di
53342
+ if (!isAny(elementDi, [ 'bpmndi:BPMNEdge', 'bpmndi:BPMNShape' ])) {
53343
+ return;
53344
+ }
53345
+
53346
+ // set colors bpmndi:BPMNEdge or bpmndi:BPMNShape
53347
+ self._commandStack.execute('element.updateProperties', {
53348
+ element: element,
53349
+ properties: {
53350
+ di: assignedDi
53351
+ }
53352
+ });
53353
+ }
53354
+ });
53355
+
53356
+ };
53357
+
53358
+ /**
53359
+ * Convert color from rgb(a)/hsl to hex. Returns `null` for unknown color names
53360
+ * and for colors with alpha less than 1.0. This depends on `<canvas>`
53361
+ * serialization of the `context.fillStyle`.
53362
+ * Cf. https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-fillstyle
53363
+ *
53364
+ * @example
53365
+ *
53366
+ * ```javascript
53367
+ * colorToHex('fuchsia'); // "#ff00ff"
53368
+ *
53369
+ * colorToHex('rgba(1, 2, 3, 0.4)'); // null
53370
+ * ```
53371
+ *
53372
+ * @param {string} color
53373
+ *
53374
+ * @return {string|null}
53375
+ */
53376
+ function colorToHex(color) {
53377
+ var context = document.createElement('canvas').getContext('2d');
53378
+
53379
+ // (0) Start with transparent to account for browser default values.
53380
+ context.fillStyle = 'transparent';
53381
+
53382
+ // (1) Assign color so that it's serialized.
53383
+ context.fillStyle = color;
53384
+
53385
+ // (2) Return null for non-hex serialization result.
53386
+ return /^#[0-9a-fA-F]{6}$/.test(context.fillStyle) ? context.fillStyle : null;
53387
+ }
53388
+
53389
+ /**
53390
+ * Add legacy properties if required.
53391
+ *
53392
+ * @param {ModdleElement} di
53393
+ */
53394
+ function ensureLegacySupport(di) {
53395
+ if ('border-color' in di) {
53396
+ di.stroke = di['border-color'];
53397
+ }
53398
+
53399
+ if ('background-color' in di) {
53400
+ di.fill = di['background-color'];
53401
+ }
53221
53402
  }
53222
53403
 
53223
53404
  var NULL_DIMENSIONS = {
@@ -61270,8 +61451,7 @@
61270
61451
 
61271
61452
  function activateDirectEdit(element, force) {
61272
61453
  if (force ||
61273
- isAny(element, [ 'bpmn:Task', 'bpmn:TextAnnotation', 'bpmn:Participant' ]) ||
61274
- isCollapsedSubProcess(element)) {
61454
+ isAny(element, [ 'bpmn:Activity', 'bpmn:Event', 'bpmn:TextAnnotation', 'bpmn:Participant' ])) {
61275
61455
 
61276
61456
  directEditing.activate(element);
61277
61457
  }
@@ -63733,10 +63913,23 @@
63733
63913
  * @typedef {import('../tool-manager/ToolManager').default} ToolManager
63734
63914
  *
63735
63915
  * @typedef {import('../../util/Types').Rect} Rect
63916
+ * @typedef {import('../../model/Types').Element} Element
63917
+ *
63918
+ * @typedef { {
63919
+ * add?: boolean,
63920
+ * bbox?: Rect,
63921
+ * marked?: Set<Element>,
63922
+ * lastMarked?: Set<Element>,
63923
+ * initialMarked?: Set<Element>,
63924
+ * frame?: SVGElement
63925
+ * } } LassoContext
63736
63926
  */
63737
63927
 
63738
63928
  var LASSO_TOOL_CURSOR = 'crosshair';
63739
63929
 
63930
+ var MARKER_SELECTED = 'selected';
63931
+ var LASSO_ACTIVE_CLS = 'djs-dragging-active-lasso';
63932
+
63740
63933
  /**
63741
63934
  * @param {EventBus} eventBus
63742
63935
  * @param {Canvas} canvas
@@ -63764,11 +63957,13 @@
63764
63957
  */
63765
63958
  var visuals = {
63766
63959
 
63960
+ /**
63961
+ * @param {LassoContext} context
63962
+ */
63767
63963
  create: function(context) {
63768
- var container = canvas.getActiveLayer(),
63769
- frame;
63964
+ var container = canvas.getActiveLayer();
63965
+ var frame = context.frame = create$1('rect');
63770
63966
 
63771
- frame = context.frame = create$1('rect');
63772
63967
  attr(frame, {
63773
63968
  class: 'djs-lasso-overlay',
63774
63969
  width: 1,
@@ -63778,28 +63973,79 @@
63778
63973
  });
63779
63974
 
63780
63975
  append(container, frame);
63976
+
63977
+ toggleLassoMarkerClass(true);
63978
+
63979
+ this.update(context);
63781
63980
  },
63782
63981
 
63982
+ /**
63983
+ * @param {LassoContext} context
63984
+ */
63783
63985
  update: function(context) {
63784
63986
  var frame = context.frame,
63785
63987
  bbox = context.bbox;
63786
63988
 
63787
- attr(frame, {
63788
- x: bbox.x,
63789
- y: bbox.y,
63790
- width: bbox.width,
63791
- height: bbox.height
63792
- });
63989
+ if (frame && bbox) {
63990
+ attr(frame, {
63991
+ x: bbox.x,
63992
+ y: bbox.y,
63993
+ width: bbox.width,
63994
+ height: bbox.height
63995
+ });
63996
+ }
63997
+
63998
+ var currentlyMarked = context.marked,
63999
+ lastMarked = context.lastMarked;
64000
+
64001
+ if (currentlyMarked && lastMarked) {
64002
+ for (const e of lastMarked) {
64003
+ if (!currentlyMarked.has(e)) {
64004
+ canvas.removeMarker(e, MARKER_SELECTED);
64005
+ }
64006
+ }
64007
+
64008
+ for (const e of currentlyMarked) {
64009
+ if (!lastMarked.has(e)) {
64010
+ canvas.addMarker(e, MARKER_SELECTED);
64011
+ }
64012
+ }
64013
+ }
63793
64014
  },
63794
64015
 
64016
+ /**
64017
+ * @param {LassoContext} context
64018
+ */
63795
64019
  remove: function(context) {
63796
64020
 
64021
+ this.update(context);
64022
+
63797
64023
  if (context.frame) {
63798
64024
  remove$1(context.frame);
63799
64025
  }
64026
+
64027
+ toggleLassoMarkerClass(false);
63800
64028
  }
63801
64029
  };
63802
64030
 
64031
+ function toggleLassoMarkerClass(enabled) {
64032
+ classes(canvas.getContainer()).toggle(LASSO_ACTIVE_CLS, enabled);
64033
+ }
64034
+
64035
+ /**
64036
+ * @param {Rect} bbox
64037
+ *
64038
+ * @return {Set<Element>}
64039
+ */
64040
+ function getAllEnclosedElements(bbox) {
64041
+
64042
+ var allElements = elementRegistry.getAll();
64043
+
64044
+ return new Set(
64045
+ values(getEnclosedElements(allElements, bbox))
64046
+ );
64047
+ }
64048
+
63803
64049
  toolManager.registerTool('lasso', {
63804
64050
  tool: 'lasso.selection',
63805
64051
  dragging: 'lasso'
@@ -63823,42 +64069,66 @@
63823
64069
 
63824
64070
  eventBus.on('lasso.end', 0, function(event) {
63825
64071
 
64072
+ /**
64073
+ * @type {LassoContext}
64074
+ */
63826
64075
  var context = event.context;
63827
64076
 
63828
- var bbox = toBBox(event);
63829
-
63830
- var elements = elementRegistry.filter(function(element) {
63831
- return element;
63832
- });
63833
-
63834
- var add = hasSecondaryModifier(event);
63835
-
63836
- self.select(elements, bbox, add ? context.selection : []);
64077
+ self._select(Array.from(context.marked));
63837
64078
  });
63838
64079
 
63839
64080
  eventBus.on('lasso.start', function(event) {
63840
64081
 
64082
+ /**
64083
+ * @type {LassoContext}
64084
+ */
63841
64085
  var context = event.context;
63842
64086
 
63843
64087
  context.bbox = toBBox(event);
63844
- visuals.create(context);
64088
+ context.add = hasSecondaryModifier(event);
64089
+ context.lastMarked = new Set(selection.get());
64090
+
64091
+ if (context.add) {
64092
+ context.marked = context.lastMarked;
64093
+ } else {
64094
+ context.marked = new Set();
64095
+ }
64096
+
64097
+ context.initialMarked = context.marked;
63845
64098
 
63846
- context.selection = selection.get();
64099
+ visuals.create(context);
63847
64100
  });
63848
64101
 
63849
64102
  eventBus.on('lasso.move', function(event) {
63850
64103
 
64104
+ /**
64105
+ * @type {LassoContext}
64106
+ */
63851
64107
  var context = event.context;
63852
64108
 
63853
- context.bbox = toBBox(event);
64109
+ var bbox = context.bbox = toBBox(event);
64110
+
64111
+ var enclosedElements = getAllEnclosedElements(bbox);
64112
+
64113
+ var marked = context.initialMarked.union(enclosedElements);
64114
+
64115
+ context.lastMarked = context.marked;
64116
+ context.marked = marked;
64117
+
63854
64118
  visuals.update(context);
63855
64119
  });
63856
64120
 
63857
64121
  eventBus.on('lasso.cleanup', function(event) {
63858
64122
 
64123
+ /**
64124
+ * @type {LassoContext}
64125
+ */
63859
64126
  var context = event.context;
63860
64127
 
63861
- visuals.remove(context);
64128
+ context.lastMarked = context.marked;
64129
+ context.marked = new Set(selection.get());
64130
+
64131
+ visuals.remove(event.context);
63862
64132
  });
63863
64133
 
63864
64134
 
@@ -63900,7 +64170,8 @@
63900
64170
  cursor: LASSO_TOOL_CURSOR,
63901
64171
  data: {
63902
64172
  context: {}
63903
- }
64173
+ },
64174
+ keepSelection: true
63904
64175
  });
63905
64176
  };
63906
64177
 
@@ -63923,6 +64194,15 @@
63923
64194
  });
63924
64195
  };
63925
64196
 
64197
+ /**
64198
+ * Select elements.
64199
+ *
64200
+ * @param {Element[]} elements
64201
+ */
64202
+ LassoTool.prototype._select = function(elements) {
64203
+ this._selection.select(elements);
64204
+ };
64205
+
63926
64206
  /**
63927
64207
  * Select elements within the given bounds.
63928
64208
  *
@@ -63931,11 +64211,11 @@
63931
64211
  * @param {Element[]} [previousSelection]
63932
64212
  */
63933
64213
  LassoTool.prototype.select = function(elements, bbox, previousSelection = []) {
63934
- var selectedElements = getEnclosedElements(elements, bbox);
64214
+ var selectedElements = values(getEnclosedElements(elements, bbox));
63935
64215
 
63936
- this._selection.select([
64216
+ this._select([
63937
64217
  ...previousSelection,
63938
- ...values(selectedElements)
64218
+ ...selectedElements
63939
64219
  ]);
63940
64220
  };
63941
64221
 
@@ -63964,6 +64244,11 @@
63964
64244
  };
63965
64245
 
63966
64246
 
64247
+ /**
64248
+ * @param {Event} event
64249
+ *
64250
+ * @return {Rect}
64251
+ */
63967
64252
  function toBBox(event) {
63968
64253
 
63969
64254
  var start = {