bpmn-js 18.9.0 → 18.10.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.9.0
2
+ * bpmn-js - bpmn-modeler v18.10.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: 2025-11-18
11
+ * Date: 2026-01-08
12
12
  */
13
13
  (function (global, factory) {
14
14
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
@@ -1830,7 +1830,7 @@
1830
1830
  return element;
1831
1831
  }
1832
1832
 
1833
- function clone$1(element) {
1833
+ function clone(element) {
1834
1834
  return element.cloneNode(true);
1835
1835
  }
1836
1836
 
@@ -3675,6 +3675,12 @@
3675
3675
 
3676
3676
  /* eslint no-fallthrough: "off" */
3677
3677
 
3678
+ /**
3679
+ * @typedef { import('./intersect.js').Path } Path
3680
+ * @typedef { import('./intersect.js').PathComponent } PathComponent
3681
+ */
3682
+
3683
+
3678
3684
  var p2s = /,?([a-z]),?/gi,
3679
3685
  toFloat = parseFloat,
3680
3686
  math = Math,
@@ -3692,23 +3698,6 @@
3692
3698
  return Object.prototype.hasOwnProperty.call(obj, property);
3693
3699
  }
3694
3700
 
3695
- function clone(obj) {
3696
-
3697
- if (typeof obj == 'function' || Object(obj) !== obj) {
3698
- return obj;
3699
- }
3700
-
3701
- var res = new obj.constructor;
3702
-
3703
- for (var key in obj) {
3704
- if (hasProperty(obj, key)) {
3705
- res[key] = clone(obj[key]);
3706
- }
3707
- }
3708
-
3709
- return res;
3710
- }
3711
-
3712
3701
  function repush(array, item) {
3713
3702
  for (var i = 0, ii = array.length; i < ii; i++) if (array[i] === item) {
3714
3703
  return array.push(array.splice(i, 1)[0]);
@@ -3738,77 +3727,84 @@
3738
3727
  return newf;
3739
3728
  }
3740
3729
 
3730
+ /**
3731
+ * Parse SVG path string and return an array of path components.
3732
+ *
3733
+ * @param {string} pathString
3734
+ *
3735
+ * @return {PathComponent[]}
3736
+ */
3741
3737
  function parsePathString(pathString) {
3742
3738
 
3743
3739
  if (!pathString) {
3744
3740
  return null;
3745
3741
  }
3746
3742
 
3747
- var pth = paths(pathString);
3748
-
3749
- if (pth.arr) {
3750
- return clone(pth.arr);
3751
- }
3752
-
3753
3743
  var paramCounts = { a: 7, c: 6, h: 1, l: 2, m: 2, q: 4, s: 4, t: 2, v: 1, z: 0 },
3754
- data = [];
3755
-
3756
- if (isArray(pathString) && isArray(pathString[0])) { // rough assumption
3757
- data = clone(pathString);
3758
- }
3759
-
3760
- if (!data.length) {
3744
+ pathComponents = [];
3761
3745
 
3762
- String(pathString).replace(pathCommand, function(a, b, c) {
3763
- var params = [],
3764
- name = b.toLowerCase();
3746
+ String(pathString).replace(pathCommand, function(a, b, c) {
3747
+ var params = [],
3748
+ name = b.toLowerCase();
3765
3749
 
3766
- c.replace(pathValues, function(a, b) {
3767
- b && params.push(+b);
3768
- });
3750
+ c.replace(pathValues, function(a, b) {
3751
+ b && params.push(+b);
3752
+ });
3769
3753
 
3770
- if (name == 'm' && params.length > 2) {
3771
- data.push([ b, ...params.splice(0, 2) ]);
3772
- name = 'l';
3773
- b = b == 'm' ? 'l' : 'L';
3774
- }
3754
+ if (name == 'm' && params.length > 2) {
3755
+ pathComponents.push([ b, ...params.splice(0, 2) ]);
3756
+ name = 'l';
3757
+ b = b == 'm' ? 'l' : 'L';
3758
+ }
3775
3759
 
3776
- while (params.length >= paramCounts[name]) {
3777
- data.push([ b, ...params.splice(0, paramCounts[name]) ]);
3778
- if (!paramCounts[name]) {
3779
- break;
3780
- }
3760
+ while (params.length >= paramCounts[name]) {
3761
+ pathComponents.push([ b, ...params.splice(0, paramCounts[name]) ]);
3762
+ if (!paramCounts[name]) {
3763
+ break;
3781
3764
  }
3782
- });
3783
- }
3765
+ }
3766
+ });
3784
3767
 
3785
- data.toString = paths.toString;
3786
- pth.arr = clone(data);
3768
+ pathComponents.toString = pathToString;
3787
3769
 
3788
- return data;
3770
+ return pathComponents;
3789
3771
  }
3790
3772
 
3791
- function paths(ps) {
3792
- var p = paths.ps = paths.ps || {};
3793
-
3794
- if (p[ps]) {
3795
- p[ps].sleep = 100;
3796
- } else {
3797
- p[ps] = {
3798
- sleep: 100
3799
- };
3773
+ /**
3774
+ * Checks if a path is already in absolute format.
3775
+ * An absolute path has all uppercase commands.
3776
+ *
3777
+ * @param {PathComponent[]} pathComponents
3778
+ * @return {boolean}
3779
+ */
3780
+ function isPathAbsolute(pathComponents) {
3781
+ for (var i = 0, ii = pathComponents.length; i < ii; i++) {
3782
+ var command = pathComponents[i][0];
3783
+ if (typeof command === 'string' && command !== command.toUpperCase()) {
3784
+ return false;
3785
+ }
3800
3786
  }
3801
3787
 
3802
- setTimeout(function() {
3803
- for (var key in p) {
3804
- if (hasProperty(p, key) && key != ps) {
3805
- p[key].sleep--;
3806
- !p[key].sleep && delete p[key];
3807
- }
3788
+ return true;
3789
+ }
3790
+
3791
+ /**
3792
+ * Checks if a path is already in curve format.
3793
+ * A curve path only contains 'M' and 'C' commands.
3794
+ *
3795
+ * @param {PathComponent[]} pathComponents
3796
+ *
3797
+ * @return {boolean}
3798
+ */
3799
+ function isPathCurve(pathComponents) {
3800
+ for (var i = 0, ii = pathComponents.length; i < ii; i++) {
3801
+ var command = pathComponents[i][0];
3802
+ if (command !== 'M' && command !== 'C') {
3803
+ return false;
3808
3804
  }
3809
- });
3805
+ }
3810
3806
 
3811
- return p[ps];
3807
+ return true;
3812
3808
  }
3813
3809
 
3814
3810
  function rectBBox(x, y, width, height) {
@@ -3834,10 +3830,27 @@
3834
3830
  return this.join(',').replace(p2s, '$1');
3835
3831
  }
3836
3832
 
3837
- function pathClone(pathArray) {
3838
- var res = clone(pathArray);
3839
- res.toString = pathToString;
3840
- return res;
3833
+ /**
3834
+ * @param {PathComponent[]} pathComponents
3835
+ *
3836
+ * @return {PathComponent[]}
3837
+ */
3838
+ function pathClone(pathComponents) {
3839
+
3840
+ var pathComponentsClone = new Array(pathComponents.length);
3841
+
3842
+ for (var i = 0, ii = pathComponents.length; i < ii; i++) {
3843
+ var component = pathComponents[i];
3844
+ var componentClone = pathComponentsClone[i] = new Array(component.length);
3845
+
3846
+ for (var j = 0, jj = component.length; j < jj; j++) {
3847
+ componentClone[j] = component[j];
3848
+ }
3849
+ }
3850
+
3851
+ pathComponentsClone.toString = pathToString;
3852
+
3853
+ return pathComponentsClone;
3841
3854
  }
3842
3855
 
3843
3856
  function findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
@@ -3980,26 +3993,29 @@
3980
3993
 
3981
3994
  var l1 = bezlen(...bez1),
3982
3995
  l2 = bezlen(...bez2),
3996
+ // eslint-disable-next-line no-bitwise
3983
3997
  n1 = isLine(bez1) ? 1 : ~~(l1 / 5) || 1,
3998
+ // eslint-disable-next-line no-bitwise
3984
3999
  n2 = isLine(bez2) ? 1 : ~~(l2 / 5) || 1,
3985
- dots1 = [],
3986
- dots2 = [],
4000
+ dots1 = new Array(n1 + 1),
4001
+ dots2 = new Array(n2 + 1),
3987
4002
  xy = {},
3988
- res = [];
4003
+ res = [],
4004
+ i, j;
3989
4005
 
3990
- for (var i = 0; i < n1 + 1; i++) {
4006
+ for (i = 0; i < n1 + 1; i++) {
3991
4007
  var p = findDotsAtSegment(...bez1, i / n1);
3992
- dots1.push({ x: p.x, y: p.y, t: i / n1 });
4008
+ dots1[i] = { x: p.x, y: p.y, t: i / n1 };
3993
4009
  }
3994
4010
 
3995
4011
  for (i = 0; i < n2 + 1; i++) {
3996
4012
  p = findDotsAtSegment(...bez2, i / n2);
3997
- dots2.push({ x: p.x, y: p.y, t: i / n2 });
4013
+ dots2[i] = { x: p.x, y: p.y, t: i / n2 };
3998
4014
  }
3999
4015
 
4000
4016
  for (i = 0; i < n1; i++) {
4001
4017
 
4002
- for (var j = 0; j < n2; j++) {
4018
+ for (j = 0; j < n2; j++) {
4003
4019
  var di = dots1[i],
4004
4020
  di1 = dots1[i + 1],
4005
4021
  dj = dots2[j],
@@ -4050,11 +4066,16 @@
4050
4066
  * on each path (segment1, segment2) and the relative location of the
4051
4067
  * intersection on these segments (t1, t2).
4052
4068
  *
4053
- * The path may be an SVG path string or a list of path components
4069
+ * The path may be an SVG path string or an array of path components
4054
4070
  * such as `[ [ 'M', 0, 10 ], [ 'L', 20, 0 ] ]`.
4055
4071
  *
4072
+ * For performance optimization, pre-parsed paths can be passed directly,
4073
+ * {@link parsePath | the parsePath utility} can be used to pre-parse any path.
4074
+ *
4056
4075
  * @example
4057
4076
  *
4077
+ * import findPathIntersections from 'path-intersection';
4078
+ *
4058
4079
  * var intersections = findPathIntersections(
4059
4080
  * 'M0,0L100,100',
4060
4081
  * [ [ 'M', 0, 100 ], [ 'L', 100, 0 ] ]
@@ -4064,11 +4085,11 @@
4064
4085
  * // { x: 50, y: 50, segment1: 1, segment2: 1, t1: 0.5, t2: 0.5 }
4065
4086
  * // ]
4066
4087
  *
4067
- * @param {String|Array<PathDef>} path1
4068
- * @param {String|Array<PathDef>} path2
4069
- * @param {Boolean} [justCount=false]
4088
+ * @param {Path} path1
4089
+ * @param {Path} path2
4090
+ * @param {boolean} [justCount=false]
4070
4091
  *
4071
- * @return {Array<Intersection>|Number}
4092
+ * @return {Intersection[]|number}
4072
4093
  */
4073
4094
  function findPathIntersections(path1, path2, justCount) {
4074
4095
  path1 = pathToCurve(path1);
@@ -4134,23 +4155,30 @@
4134
4155
  return res;
4135
4156
  }
4136
4157
 
4158
+ /**
4159
+ * Test if path is a set of path components of the form
4160
+ * `[ ['M', 0, 0 ], ['L', 100, 100], ...]`.
4161
+ *
4162
+ * @param {Path} path
4163
+ *
4164
+ * @return {boolean}
4165
+ */
4166
+ function isPathComponents(path) {
4167
+ return isArray(path) && isArray(path[0]);
4168
+ }
4137
4169
 
4138
- function pathToAbsolute(pathArray) {
4139
- var pth = paths(pathArray);
4140
-
4141
- if (pth.abs) {
4142
- return pathClone(pth.abs);
4143
- }
4144
-
4145
- if (!isArray(pathArray) || !isArray(pathArray && pathArray[0])) { // rough assumption
4146
- pathArray = parsePathString(pathArray);
4147
- }
4170
+ /**
4171
+ * @param {PathComponent[]} pathComponents
4172
+ *
4173
+ * @return {PathComponent[]}
4174
+ */
4175
+ function pathToAbsolute(pathComponents) {
4148
4176
 
4149
- if (!pathArray || !pathArray.length) {
4150
- return [ [ 'M', 0, 0 ] ];
4177
+ if (isPathAbsolute(pathComponents)) {
4178
+ return pathComponents;
4151
4179
  }
4152
4180
 
4153
- var res = [],
4181
+ var res = new Array(pathComponents.length),
4154
4182
  x = 0,
4155
4183
  y = 0,
4156
4184
  mx = 0,
@@ -4158,19 +4186,19 @@
4158
4186
  start = 0,
4159
4187
  pa0;
4160
4188
 
4161
- if (pathArray[0][0] == 'M') {
4162
- x = +pathArray[0][1];
4163
- y = +pathArray[0][2];
4189
+ if (pathComponents[0][0] == 'M') {
4190
+ x = +pathComponents[0][1];
4191
+ y = +pathComponents[0][2];
4164
4192
  mx = x;
4165
4193
  my = y;
4166
4194
  start++;
4167
4195
  res[0] = [ 'M', x, y ];
4168
4196
  }
4169
4197
 
4170
- for (var r, pa, i = start, ii = pathArray.length; i < ii; i++) {
4171
- res.push(r = []);
4172
- pa = pathArray[i];
4198
+ for (var r, pa, i = start, ii = pathComponents.length; i < ii; i++) {
4199
+ pa = pathComponents[i];
4173
4200
  pa0 = pa[0];
4201
+ res[i] = (r = new Array(pa.length));
4174
4202
 
4175
4203
  if (pa0 != pa0.toUpperCase()) {
4176
4204
  r[0] = pa0.toUpperCase();
@@ -4227,7 +4255,6 @@
4227
4255
  }
4228
4256
 
4229
4257
  res.toString = pathToString;
4230
- pth.abs = pathClone(res);
4231
4258
 
4232
4259
  return res;
4233
4260
  }
@@ -4448,16 +4475,24 @@
4448
4475
  };
4449
4476
  }
4450
4477
 
4478
+ /**
4479
+ * Convert path to a curve.
4480
+ *
4481
+ * @param {Path} path
4482
+ *
4483
+ * @return {PathComponent[]}
4484
+ */
4451
4485
  function pathToCurve(path) {
4452
4486
 
4453
- var pth = paths(path);
4487
+ if (!isPathComponents(path)) {
4488
+ path = parsePathString(path);
4489
+ }
4454
4490
 
4455
- // return cached curve, if existing
4456
- if (pth.curve) {
4457
- return pathClone(pth.curve);
4491
+ if (isPathCurve(path)) {
4492
+ return path;
4458
4493
  }
4459
4494
 
4460
- var curvedPath = pathToAbsolute(path),
4495
+ var curvedPath = pathClone(pathToAbsolute(path)),
4461
4496
  attrs = { x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null },
4462
4497
  processPath = function(path, d, pathCommand) {
4463
4498
  var nx, ny;
@@ -4581,9 +4616,6 @@
4581
4616
  attrs.by = toFloat(seg[seglen - 3]) || attrs.y;
4582
4617
  }
4583
4618
 
4584
- // cache curve
4585
- pth.curve = pathClone(curvedPath);
4586
-
4587
4619
  return curvedPath;
4588
4620
  }
4589
4621
 
@@ -25356,6 +25388,7 @@
25356
25388
 
25357
25389
  var KEYS_COPY = [ 'c', 'C' ];
25358
25390
  var KEYS_PASTE = [ 'v', 'V' ];
25391
+ var KEYS_DUPLICATE = [ 'd', 'D' ];
25359
25392
  var KEYS_REDO = [ 'y', 'Y' ];
25360
25393
  var KEYS_UNDO = [ 'z', 'Z' ];
25361
25394
 
@@ -25416,6 +25449,13 @@
25416
25449
  return isCmd(event) && isKey(KEYS_PASTE, event);
25417
25450
  }
25418
25451
 
25452
+ /**
25453
+ * @param {KeyboardEvent} event
25454
+ */
25455
+ function isDuplicate(event) {
25456
+ return isCmd(event) && isKey(KEYS_DUPLICATE, event);
25457
+ }
25458
+
25419
25459
  /**
25420
25460
  * @param {KeyboardEvent} event
25421
25461
  */
@@ -25741,6 +25781,20 @@
25741
25781
  }
25742
25782
  });
25743
25783
 
25784
+ // duplicate
25785
+ // CTRL/CMD + D
25786
+ addListener('duplicate', function(context) {
25787
+
25788
+ var event = context.keyEvent;
25789
+
25790
+ if (isDuplicate(event)) {
25791
+ editorActions.trigger('duplicate');
25792
+
25793
+ return true;
25794
+ }
25795
+ });
25796
+
25797
+
25744
25798
  // zoom in one step
25745
25799
  // CTRL/CMD + +
25746
25800
  addListener('stepZoom', function(context) {
@@ -30690,7 +30744,7 @@
30690
30744
  * @typedef {import('../../core/EventBus').default} EventBus
30691
30745
  */
30692
30746
 
30693
- var HIGH_PRIORITY$j = 1500;
30747
+ var HIGH_PRIORITY$k = 1500;
30694
30748
 
30695
30749
 
30696
30750
  /**
@@ -30758,7 +30812,7 @@
30758
30812
  */
30759
30813
  eventBus.on('drag.start', function(event) {
30760
30814
 
30761
- eventBus.once('drag.move', HIGH_PRIORITY$j, function(event) {
30815
+ eventBus.once('drag.move', HIGH_PRIORITY$k, function(event) {
30762
30816
 
30763
30817
  ensureHover(event);
30764
30818
 
@@ -30789,7 +30843,7 @@
30789
30843
  hover = event.element;
30790
30844
  });
30791
30845
 
30792
- eventBus.on('element.hover', HIGH_PRIORITY$j, function(event) {
30846
+ eventBus.on('element.hover', HIGH_PRIORITY$k, function(event) {
30793
30847
 
30794
30848
  // (3) am I on an element still?
30795
30849
  if (hover) {
@@ -32740,7 +32794,7 @@
32740
32794
  MARKER_CONNECT_UPDATING$1 = 'djs-updating',
32741
32795
  MARKER_DRAGGER = 'djs-dragging';
32742
32796
 
32743
- var HIGH_PRIORITY$i = 1100;
32797
+ var HIGH_PRIORITY$j = 1100;
32744
32798
 
32745
32799
  /**
32746
32800
  * Preview connection while moving bendpoints.
@@ -32808,7 +32862,7 @@
32808
32862
  eventBus.on([
32809
32863
  'bendpoint.move.out',
32810
32864
  'bendpoint.move.cleanup'
32811
- ], HIGH_PRIORITY$i, function(event) {
32865
+ ], HIGH_PRIORITY$j, function(event) {
32812
32866
  var context = event.context,
32813
32867
  hover = context.hover,
32814
32868
  target = context.target;
@@ -32894,7 +32948,7 @@
32894
32948
  eventBus.on([
32895
32949
  'bendpoint.move.end',
32896
32950
  'bendpoint.move.cancel'
32897
- ], HIGH_PRIORITY$i, function(event) {
32951
+ ], HIGH_PRIORITY$j, function(event) {
32898
32952
  var context = event.context,
32899
32953
  connection = context.connection,
32900
32954
  draggerGfx = context.draggerGfx,
@@ -33910,7 +33964,7 @@
33910
33964
  * @typedef {import('../../core/EventBus').default} EventBus
33911
33965
  */
33912
33966
 
33913
- var HIGH_PRIORITY$h = 1100,
33967
+ var HIGH_PRIORITY$i = 1100,
33914
33968
  LOW_PRIORITY$k = 900;
33915
33969
 
33916
33970
  var MARKER_OK$3 = 'connect-ok',
@@ -33971,7 +34025,7 @@
33971
34025
  eventBus.on([
33972
34026
  'connect.out',
33973
34027
  'connect.cleanup'
33974
- ], HIGH_PRIORITY$h, function(event) {
34028
+ ], HIGH_PRIORITY$i, function(event) {
33975
34029
  var hover = event.hover;
33976
34030
 
33977
34031
  if (hover) {
@@ -34383,7 +34437,7 @@
34383
34437
  PreviewSupport.prototype.addDragger = function(element, group, gfx, className = 'djs-dragger') {
34384
34438
  gfx = gfx || this.getGfx(element);
34385
34439
 
34386
- var dragger = clone$1(gfx);
34440
+ var dragger = clone(gfx);
34387
34441
  var bbox = gfx.getBoundingClientRect();
34388
34442
 
34389
34443
  this._cloneMarkers(getVisual(dragger), className);
@@ -34474,7 +34528,7 @@
34474
34528
 
34475
34529
  parentGfx = parentGfx || this._canvas._svg;
34476
34530
 
34477
- var clonedMarker = copiedMarker || clone$1(marker);
34531
+ var clonedMarker = copiedMarker || clone(marker);
34478
34532
 
34479
34533
  clonedMarker.id = clonedMarkerId;
34480
34534
 
@@ -35505,7 +35559,7 @@
35505
35559
 
35506
35560
  var PARTICIPANT_BORDER_WIDTH = 30;
35507
35561
 
35508
- var HIGH_PRIORITY$g = 2000;
35562
+ var HIGH_PRIORITY$h = 2000;
35509
35563
 
35510
35564
 
35511
35565
  /**
@@ -35522,7 +35576,7 @@
35522
35576
  eventBus.on([
35523
35577
  'create.start',
35524
35578
  'shape.move.start'
35525
- ], HIGH_PRIORITY$g, function(event) {
35579
+ ], HIGH_PRIORITY$h, function(event) {
35526
35580
  var context = event.context,
35527
35581
  shape = context.shape,
35528
35582
  rootElement = canvas.getRootElement();
@@ -35557,7 +35611,7 @@
35557
35611
  });
35558
35612
 
35559
35613
  // force hovering process when creating first participant
35560
- eventBus.on('create.start', HIGH_PRIORITY$g, function(event) {
35614
+ eventBus.on('create.start', HIGH_PRIORITY$h, function(event) {
35561
35615
  var context = event.context,
35562
35616
  shape = context.shape,
35563
35617
  rootElement = canvas.getRootElement(),
@@ -35569,7 +35623,7 @@
35569
35623
  }
35570
35624
 
35571
35625
  if (is(shape, 'bpmn:Participant') && is(rootElement, 'bpmn:Process')) {
35572
- eventBus.on('element.hover', HIGH_PRIORITY$g, ensureHoveringProcess);
35626
+ eventBus.on('element.hover', HIGH_PRIORITY$h, ensureHoveringProcess);
35573
35627
 
35574
35628
  eventBus.once('create.cleanup', function() {
35575
35629
  eventBus.off('element.hover', ensureHoveringProcess);
@@ -35590,7 +35644,7 @@
35590
35644
 
35591
35645
  // when creating mutliple elements through `elements.create` parent must be set to collaboration
35592
35646
  // and passed to `shape.create` as hint
35593
- this.preExecute('elements.create', HIGH_PRIORITY$g, function(context) {
35647
+ this.preExecute('elements.create', HIGH_PRIORITY$h, function(context) {
35594
35648
  var elements = context.elements,
35595
35649
  parent = context.parent,
35596
35650
  participant = findParticipant(elements),
@@ -37075,7 +37129,7 @@
37075
37129
  * @typedef {import('diagram-js/lib/core/Canvas').default} Canvas
37076
37130
  */
37077
37131
 
37078
- var HIGH_PRIORITY$f = 1500;
37132
+ var HIGH_PRIORITY$g = 1500;
37079
37133
  var HIGHEST_PRIORITY = 2000;
37080
37134
 
37081
37135
 
@@ -37097,7 +37151,7 @@
37097
37151
  'shape.move.move',
37098
37152
  'shape.move.out',
37099
37153
  'shape.move.end'
37100
- ], HIGH_PRIORITY$f, function(event) {
37154
+ ], HIGH_PRIORITY$g, function(event) {
37101
37155
  var context = event.context,
37102
37156
  shape = context.shape || event.shape,
37103
37157
  hover = event.hover;
@@ -37128,7 +37182,7 @@
37128
37182
  'global-connect.out',
37129
37183
  'global-connect.end',
37130
37184
  'global-connect.cleanup'
37131
- ], HIGH_PRIORITY$f, function(event) {
37185
+ ], HIGH_PRIORITY$g, function(event) {
37132
37186
  var hover = event.hover;
37133
37187
 
37134
37188
  // ensure connections start/end on bpmn:Participant,
@@ -37142,7 +37196,7 @@
37142
37196
 
37143
37197
  eventBus.on([
37144
37198
  'bendpoint.move.hover'
37145
- ], HIGH_PRIORITY$f, function(event) {
37199
+ ], HIGH_PRIORITY$g, function(event) {
37146
37200
  var context = event.context,
37147
37201
  hover = event.hover,
37148
37202
  type = context.type;
@@ -37158,7 +37212,7 @@
37158
37212
 
37159
37213
  eventBus.on([
37160
37214
  'connect.start'
37161
- ], HIGH_PRIORITY$f, function(event) {
37215
+ ], HIGH_PRIORITY$g, function(event) {
37162
37216
  var context = event.context,
37163
37217
  start = context.start;
37164
37218
 
@@ -39616,7 +39670,7 @@
39616
39670
  'selection'
39617
39671
  ];
39618
39672
 
39619
- var HIGH_PRIORITY$e = 1500;
39673
+ var HIGH_PRIORITY$f = 1500;
39620
39674
 
39621
39675
  /**
39622
39676
  * @typedef {import('diagram-js/lib/core/EventBus').default} EventBus
@@ -39669,7 +39723,7 @@
39669
39723
  * @param {EventBus} eventBus
39670
39724
  */
39671
39725
  function ResizeBehavior$1(eventBus) {
39672
- eventBus.on('resize.start', HIGH_PRIORITY$e, function(event) {
39726
+ eventBus.on('resize.start', HIGH_PRIORITY$f, function(event) {
39673
39727
  var context = event.context,
39674
39728
  shape = context.shape,
39675
39729
  direction = context.direction,
@@ -40317,7 +40371,7 @@
40317
40371
  */
40318
40372
 
40319
40373
  var LOW_PRIORITY$f = 400;
40320
- var HIGH_PRIORITY$d = 600;
40374
+ var HIGH_PRIORITY$e = 600;
40321
40375
 
40322
40376
  var DEFAULT_POSITION = {
40323
40377
  x: 180,
@@ -40604,7 +40658,7 @@
40604
40658
  }, true);
40605
40659
 
40606
40660
  // move elements between planes
40607
- this.postExecuted('shape.toggleCollapse', HIGH_PRIORITY$d, function(context) {
40661
+ this.postExecuted('shape.toggleCollapse', HIGH_PRIORITY$e, function(context) {
40608
40662
  var shape = context.shape;
40609
40663
 
40610
40664
  if (!is(shape, 'bpmn:SubProcess')) {
@@ -41290,7 +41344,7 @@
41290
41344
  */
41291
41345
 
41292
41346
  var LOW_PRIORITY$d = 500,
41293
- HIGH_PRIORITY$c = 5000;
41347
+ HIGH_PRIORITY$d = 5000;
41294
41348
 
41295
41349
 
41296
41350
  /**
@@ -41363,7 +41417,7 @@
41363
41417
 
41364
41418
  // listen to a lot of stuff to group lane updates
41365
41419
 
41366
- this.preExecute(laneRefUpdateEvents, HIGH_PRIORITY$c, function(event) {
41420
+ this.preExecute(laneRefUpdateEvents, HIGH_PRIORITY$d, function(event) {
41367
41421
  initContext();
41368
41422
  });
41369
41423
 
@@ -42773,7 +42827,7 @@
42773
42827
  * @typedef {import('diagram-js/lib/core/Canvas').default} Canvas
42774
42828
  */
42775
42829
 
42776
- var HIGH_PRIORITY$b = 2000;
42830
+ var HIGH_PRIORITY$c = 2000;
42777
42831
 
42778
42832
  /**
42779
42833
  * @param {EventBus} eventBus
@@ -42781,7 +42835,7 @@
42781
42835
  */
42782
42836
  function BpmnDiOrdering(eventBus, canvas) {
42783
42837
 
42784
- eventBus.on('saveXML.start', HIGH_PRIORITY$b, orderDi);
42838
+ eventBus.on('saveXML.start', HIGH_PRIORITY$c, orderDi);
42785
42839
 
42786
42840
  function orderDi() {
42787
42841
  var rootElements = canvas.getRootElements();
@@ -43149,7 +43203,7 @@
43149
43203
 
43150
43204
  var PREFIX = 'create';
43151
43205
 
43152
- var HIGH_PRIORITY$a = 2000;
43206
+ var HIGH_PRIORITY$b = 2000;
43153
43207
 
43154
43208
 
43155
43209
  /**
@@ -43377,7 +43431,7 @@
43377
43431
  eventBus.on('create.init', function() {
43378
43432
  eventBus.on('elements.changed', cancel);
43379
43433
 
43380
- eventBus.once([ 'create.cancel', 'create.end' ], HIGH_PRIORITY$a, function() {
43434
+ eventBus.once([ 'create.cancel', 'create.end' ], HIGH_PRIORITY$b, function() {
43381
43435
  eventBus.off('elements.changed', cancel);
43382
43436
  });
43383
43437
  });
@@ -43733,6 +43787,33 @@
43733
43787
  * @typedef { (event: { hints: any }) => void } CopyPastePasteElementsListener
43734
43788
  */
43735
43789
 
43790
+ /**
43791
+ * @typedef { any } Tree
43792
+ */
43793
+
43794
+ /**
43795
+ * @typedef { {
43796
+ * element: Shape,
43797
+ * point: Point
43798
+ * } } DirectPasteContext
43799
+ *
43800
+ * @typedef { {
43801
+ * hints?: Object,
43802
+ * tree?: Tree
43803
+ * } } BasePasteContext
43804
+ *
43805
+ * @typedef { {
43806
+ * hints?: Object
43807
+ * } } BaseDuplicateContext
43808
+ *
43809
+ * @typedef { BasePasteContext & (DirectPasteContext | {}) } PasteContext
43810
+ *
43811
+ * @typedef { BaseDuplicateContext & (DirectPasteContext | {}) } DuplicateContext
43812
+ */
43813
+
43814
+
43815
+ var HIGH_PRIORITY$a = 2000;
43816
+
43736
43817
  /**
43737
43818
  * Copy and paste elements.
43738
43819
  *
@@ -43758,7 +43839,6 @@
43758
43839
 
43759
43840
  this._canvas = canvas;
43760
43841
  this._create = create;
43761
- this._clipboard = clipboard;
43762
43842
  this._elementFactory = elementFactory;
43763
43843
  this._eventBus = eventBus;
43764
43844
  this._modeling = modeling;
@@ -43819,6 +43899,22 @@
43819
43899
 
43820
43900
  });
43821
43901
 
43902
+ eventBus.on('copyPaste.elementsCopied', HIGH_PRIORITY$a, function(context) {
43903
+
43904
+ if (context.hints?.clip !== false) {
43905
+
43906
+ // we set an empty tree, selection of elements
43907
+ // to copy was empty.
43908
+ clipboard.set(context.tree);
43909
+ }
43910
+ });
43911
+
43912
+ eventBus.on('copyPaste.pasteElements', HIGH_PRIORITY$a, function(context) {
43913
+ if (!context.tree) {
43914
+ context.tree = clipboard.get();
43915
+ }
43916
+ });
43917
+
43822
43918
  eventBus.on('copyPaste.pasteElements', function(context) {
43823
43919
  var hints = context.hints;
43824
43920
 
@@ -43841,13 +43937,15 @@
43841
43937
 
43842
43938
 
43843
43939
  /**
43844
- * Copy elements.
43940
+ * Copy elements. Will put elements into a {@link Clipboard} unless
43941
+ * specified otherwise.
43845
43942
  *
43846
43943
  * @param {Element[]} elements
43944
+ * @param {{ clip: boolean }} [hints]
43847
43945
  *
43848
- * @return {Object}
43946
+ * @return { Tree }
43849
43947
  */
43850
- CopyPaste.prototype.copy = function(elements) {
43948
+ CopyPaste.prototype.copy = function(elements, hints = {}) {
43851
43949
  var allowed,
43852
43950
  tree;
43853
43951
 
@@ -43865,13 +43963,10 @@
43865
43963
  tree = this.createTree(isArray$3(allowed) ? allowed : elements);
43866
43964
  }
43867
43965
 
43868
- // we set an empty tree, selection of elements
43869
- // to copy was empty.
43870
- this._clipboard.set(tree);
43871
-
43872
43966
  this._eventBus.fire('copyPaste.elementsCopied', {
43873
43967
  elements: elements,
43874
- tree: tree
43968
+ tree: tree,
43969
+ hints: hints
43875
43970
  });
43876
43971
 
43877
43972
  return tree;
@@ -43880,36 +43975,61 @@
43880
43975
  /**
43881
43976
  * Paste elements.
43882
43977
  *
43883
- * @param {Object} [context]
43884
- * @param {Shape} [context.element] The optional parent.
43885
- * @param {Point} [context.point] The optional position.
43886
- * @param {Object} [context.hints] The optional hints.
43978
+ * @param {PasteContext} [context]
43887
43979
  */
43888
- CopyPaste.prototype.paste = function(context) {
43889
- var tree = this._clipboard.get();
43980
+ CopyPaste.prototype.paste = function(context = {}) {
43890
43981
 
43891
- if (this._clipboard.isEmpty()) {
43982
+ var pasteEvent = this._eventBus.createEvent({
43983
+ type: 'copyPaste.pasteElements',
43984
+ hints: { },
43985
+ ...context
43986
+ });
43987
+
43988
+ var canPaste = this._eventBus.fire(pasteEvent);
43989
+
43990
+ if (canPaste === false) {
43892
43991
  return;
43893
43992
  }
43894
43993
 
43895
- var hints = context && context.hints || {};
43994
+ var tree = pasteEvent.tree;
43896
43995
 
43897
- this._eventBus.fire('copyPaste.pasteElements', {
43898
- hints: hints
43899
- });
43996
+ if (!tree) {
43997
+ return;
43998
+ }
43999
+
44000
+ var hints = pasteEvent.hints;
43900
44001
 
43901
44002
  var elements = this._createElements(tree);
43902
44003
 
43903
44004
  // paste directly
43904
- if (context && context.element && context.point) {
43905
- return this._paste(elements, context.element, context.point, hints);
44005
+ if (pasteEvent.element && pasteEvent.point) {
44006
+ return this._paste(elements, pasteEvent.element, pasteEvent.point, hints);
43906
44007
  }
43907
44008
 
43908
44009
  this._create.start(this._mouse.getLastMoveEvent(), elements, {
43909
- hints: hints || {}
44010
+ hints: hints
44011
+ });
44012
+ };
44013
+
44014
+ /**
44015
+ * Duplicate the given elements into the specified paste context.
44016
+ *
44017
+ * @param {Element[]} elements
44018
+ * @param {DuplicateContext} pasteContext
44019
+ *
44020
+ * @return {Element[]|undefined} the pasted elements, if direct paste happened.
44021
+ */
44022
+ CopyPaste.prototype.duplicate = function(elements, pasteContext = {}) {
44023
+
44024
+ var tree = this.copy(elements, { clip: false });
44025
+
44026
+ return this.paste({
44027
+ ...pasteContext,
44028
+ tree
43910
44029
  });
43911
44030
  };
43912
44031
 
44032
+
43913
44033
  /**
43914
44034
  * Paste elements directly.
43915
44035
  *
@@ -43955,6 +44075,10 @@
43955
44075
 
43956
44076
  /**
43957
44077
  * Create elements from tree.
44078
+ *
44079
+ * @param {Tree} tree
44080
+ *
44081
+ * @return {Element[]} elements
43958
44082
  */
43959
44083
  CopyPaste.prototype._createElements = function(tree) {
43960
44084
  var self = this;
@@ -58455,6 +58579,16 @@
58455
58579
  });
58456
58580
  }
58457
58581
 
58582
+ if (copyPaste && selection) {
58583
+ this.register('duplicate', function() {
58584
+ var selectedElements = selection.get();
58585
+
58586
+ if (selectedElements.length) {
58587
+ return copyPaste.duplicate(selectedElements);
58588
+ }
58589
+ });
58590
+ }
58591
+
58458
58592
  if (copyPaste) {
58459
58593
  this.register('paste', function() {
58460
58594
  copyPaste.paste();
@@ -61776,7 +61910,7 @@
61776
61910
 
61777
61911
  eventBus.on('shape.changed', function({ element }) {
61778
61912
 
61779
- if (!isAny(element, ALLOWED_ELEMENTS)) {
61913
+ if (!isAny(element, ALLOWED_ELEMENTS) || !isElementSelected(element)) {
61780
61914
  return;
61781
61915
  }
61782
61916
 
@@ -61878,6 +62012,10 @@
61878
62012
  function getElementPath(element) {
61879
62013
  return graphicsFactory.getShapePath(element);
61880
62014
  }
62015
+
62016
+ function isElementSelected(element) {
62017
+ return selection.get().includes(element);
62018
+ }
61881
62019
  }
61882
62020
 
61883
62021
  LabelLink$1.$inject = [