bpmn-js 18.20.0 → 18.22.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-navigated-viewer v18.20.0
2
+ * bpmn-js - bpmn-navigated-viewer v18.22.0
3
3
  *
4
4
  * Copyright (c) 2014-present, camunda Services GmbH
5
5
  *
@@ -8,7 +8,7 @@
8
8
  *
9
9
  * Source Code: https://github.com/bpmn-io/bpmn-js
10
10
  *
11
- * Date: 2026-07-06
11
+ * Date: 2026-07-23
12
12
  */
13
13
  (function (global, factory) {
14
14
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
@@ -381,8 +381,9 @@
381
381
  }
382
382
 
383
383
  /**
384
+ * @template {(...args: any[]) => any} T
384
385
  * @typedef { {
385
- * (...args: any[]): any;
386
+ * (...args: Parameters<T>): void;
386
387
  * flush: () => void;
387
388
  * cancel: () => void;
388
389
  * } } DebouncedFunction
@@ -395,10 +396,12 @@
395
396
  * Lodash-style the function exposes methods to `#clear`
396
397
  * and `#flush` to control internal behavior.
397
398
  *
398
- * @param {Function} fn
399
- * @param {Number} timeout
399
+ * @template {(...args: any[]) => any} T
400
+ *
401
+ * @param {T} fn
402
+ * @param {number} timeout
400
403
  *
401
- * @return {DebouncedFunction} debounced function
404
+ * @return {DebouncedFunction<T>} debounced function
402
405
  */
403
406
  function debounce(fn, timeout) {
404
407
 
@@ -445,7 +448,7 @@
445
448
  }
446
449
 
447
450
  /**
448
- * @type { DebouncedFunction }
451
+ * @type {DebouncedFunction<T>}
449
452
  */
450
453
  function callback(...args) {
451
454
  lastNow = Date.now();
@@ -10385,6 +10388,8 @@
10385
10388
  * @typedef {import('./Types.js').ParentLike } ParentLike
10386
10389
  * @typedef {import('./Types.js').ShapeLike} ShapeLike
10387
10390
  *
10391
+ * @typedef {ShapeLike|ConnectionLike|RootLike|string} ElementOrIdentifier
10392
+ *
10388
10393
  * @typedef { {
10389
10394
  * container?: HTMLElement;
10390
10395
  * deferUpdate?: boolean;
@@ -10608,9 +10613,16 @@
10608
10613
  // debounce canvas.viewbox.changed events when deferUpdate is set
10609
10614
  // to help with potential performance issues
10610
10615
  if (config.deferUpdate) {
10611
- this._viewboxChanged = debounce(bind$1(this._viewboxChanged, this), 300);
10616
+ this._viewboxChanged = debounce(this._viewboxChanged, 300);
10612
10617
  }
10613
10618
 
10619
+ /**
10620
+ * Schedule focus restoration.
10621
+ *
10622
+ * @type {import('min-dash').DebouncedFunction<typeof this.restoreFocus>}
10623
+ */
10624
+ this._restoreFocus = debounce(this._restoreFocus, 0);
10625
+
10614
10626
  eventBus.on('diagram.init', () => {
10615
10627
 
10616
10628
  /**
@@ -10649,6 +10661,8 @@
10649
10661
  };
10650
10662
 
10651
10663
  Canvas.prototype._destroy = function() {
10664
+ this._restoreFocus.cancel();
10665
+
10652
10666
  this._eventBus.fire('canvas.destroy', {
10653
10667
  svg: this._svg,
10654
10668
  viewport: this._viewport
@@ -10712,9 +10726,17 @@
10712
10726
  };
10713
10727
 
10714
10728
  /**
10715
- * Sets focus on the canvas SVG element if `document.body` is currently focused.
10716
- */
10729
+ * Restores focus on the canvas SVG element if `document.body` is
10730
+ * currently focused.
10731
+ *
10732
+ * Safely executes on the next render cycle - never prevents pending
10733
+ * (in flight) user clicks.
10734
+ */
10717
10735
  Canvas.prototype.restoreFocus = function() {
10736
+ this._restoreFocus();
10737
+ };
10738
+
10739
+ Canvas.prototype._restoreFocus = function() {
10718
10740
  if (document.activeElement === document.body) {
10719
10741
  this.focus();
10720
10742
  }
@@ -10916,26 +10938,40 @@
10916
10938
 
10917
10939
 
10918
10940
  /**
10919
- * Returns the plane which contains the given element.
10941
+ * Returns the plane which contains the given element(s).
10920
10942
  *
10921
- * @param {ShapeLike|ConnectionLike|string} element The element or its ID.
10943
+ * If multiple elements are passed, the shared plane is returned
10944
+ * (or undefined if no shared plane exists).
10945
+ *
10946
+ * @param {ElementOrIdentifier|ElementOrIdentifier[]} element
10922
10947
  *
10923
10948
  * @return {RootLike|undefined} The root of the element.
10924
10949
  */
10925
10950
  Canvas.prototype.findRoot = function(element) {
10926
- if (typeof element === 'string') {
10927
- element = this._elementRegistry.get(element);
10928
- }
10929
10951
 
10930
- if (!element) {
10931
- return;
10932
- }
10952
+ const elements = this._resolveElements(element);
10933
10953
 
10934
- const plane = this._findPlaneForRoot(
10935
- findRoot(element)
10936
- ) || {};
10954
+ let root;
10955
+
10956
+ for (const element of elements) {
10957
+ const plane = this._findPlaneForRoot(
10958
+ findRoot(element)
10959
+ );
10960
+
10961
+ if (!plane) {
10962
+ return;
10963
+ }
10937
10964
 
10938
- return plane.rootElement;
10965
+ if (root && plane.rootElement !== root) {
10966
+
10967
+ // no shared root
10968
+ return undefined;
10969
+ }
10970
+
10971
+ root = plane.rootElement;
10972
+ }
10973
+
10974
+ return root;
10939
10975
  };
10940
10976
 
10941
10977
  /**
@@ -10955,6 +10991,33 @@
10955
10991
  });
10956
10992
  };
10957
10993
 
10994
+ /**
10995
+ * @param {ElementOrIdentifier} element
10996
+ *
10997
+ * @return {ShapeLike|ConnectionLike|RootLike|undefined}
10998
+ */
10999
+ Canvas.prototype._resolveElement = function(element) {
11000
+
11001
+ if (typeof element === 'string') {
11002
+ return this._elementRegistry.get(element);
11003
+ }
11004
+
11005
+ return element;
11006
+ };
11007
+
11008
+ /**
11009
+ * @param {ElementOrIdentifier|ElementOrIdentifier[]} elements
11010
+ *
11011
+ * @return {Array<ShapeLike|ConnectionLike|RootLike>}
11012
+ */
11013
+ Canvas.prototype._resolveElements = function(elements) {
11014
+
11015
+ if (!isArray$1(elements)) {
11016
+ elements = [ elements ];
11017
+ }
11018
+
11019
+ return elements.map(element => this._resolveElement(element)).filter(Boolean);
11020
+ };
10958
11021
 
10959
11022
  /**
10960
11023
  * Returns the html element that encloses the
@@ -10972,9 +11035,7 @@
10972
11035
  Canvas.prototype._updateMarker = function(element, marker, add) {
10973
11036
  let container;
10974
11037
 
10975
- if (!element.id) {
10976
- element = this._elementRegistry.get(element);
10977
- }
11038
+ element = this._resolveElement(element);
10978
11039
 
10979
11040
  element.markers = element.markers || new Set();
10980
11041
 
@@ -11057,9 +11118,7 @@
11057
11118
  * @param {string} marker The marker.
11058
11119
  */
11059
11120
  Canvas.prototype.hasMarker = function(element, marker) {
11060
- if (!element.id) {
11061
- element = this._elementRegistry.get(element);
11062
- }
11121
+ element = this._resolveElement(element);
11063
11122
 
11064
11123
  if (!element.markers) {
11065
11124
  return false;
@@ -11156,9 +11215,7 @@
11156
11215
  */
11157
11216
  Canvas.prototype.removeRootElement = function(rootElement) {
11158
11217
 
11159
- if (typeof rootElement === 'string') {
11160
- rootElement = this._elementRegistry.get(rootElement);
11161
- }
11218
+ rootElement = this._resolveElement(rootElement);
11162
11219
 
11163
11220
  const plane = this._findPlaneForRoot(rootElement);
11164
11221
 
@@ -11655,34 +11712,44 @@
11655
11712
  };
11656
11713
 
11657
11714
  /**
11658
- * Scrolls the viewbox to contain the given element.
11715
+ * Scrolls the viewbox to contain the given element or elements.
11659
11716
  * Optionally specify a padding to be applied to the edges.
11660
11717
  *
11661
- * @param {ShapeLike|ConnectionLike|string} element The element to scroll to or its ID.
11718
+ * The canvas navigates to the shared root of the element(s). If no shared
11719
+ * root can be found, no navigation is performed.
11720
+ *
11721
+ * @param {ElementOrIdentifier|ElementOrIdentifier[]} element The element(s) to scroll to or their ID(s).
11662
11722
  * @param {RectTRBL|number} [padding=100] The padding to be applied. Can also specify top, bottom, left and right.
11663
11723
  */
11664
11724
  Canvas.prototype.scrollToElement = function(element, padding) {
11665
11725
  let defaultPadding = 100;
11666
11726
 
11667
- if (typeof element === 'string') {
11668
- element = this._elementRegistry.get(element);
11727
+ const elements = this._resolveElements(element);
11728
+
11729
+ if (!elements.length) {
11730
+ return;
11669
11731
  }
11670
11732
 
11671
- // set to correct rootElement
11672
- const rootElement = this.findRoot(element);
11733
+ const rootElement = this.findRoot(elements);
11734
+
11735
+ if (!rootElement) {
11736
+ return;
11737
+ }
11673
11738
 
11674
11739
  if (rootElement !== this.getRootElement()) {
11675
11740
  this.setRootElement(rootElement);
11676
11741
  }
11677
11742
 
11678
- // element is rootElement, do not change viewport
11679
- if (rootElement === element) {
11743
+ const visibleElements = elements.filter(e => e != rootElement);
11744
+
11745
+ if (!visibleElements.length) {
11680
11746
  return;
11681
11747
  }
11682
11748
 
11683
11749
  if (!padding) {
11684
11750
  padding = {};
11685
11751
  }
11752
+
11686
11753
  if (typeof padding === 'number') {
11687
11754
  defaultPadding = padding;
11688
11755
  }
@@ -11694,7 +11761,7 @@
11694
11761
  left: padding.left || defaultPadding
11695
11762
  };
11696
11763
 
11697
- const elementBounds = getBBox(element),
11764
+ const elementBounds = getBBox(visibleElements),
11698
11765
  elementTrbl = asTRBL(elementBounds),
11699
11766
  viewboxBounds = this.viewbox(),
11700
11767
  zoom = this.zoom();