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-navigated-viewer v18.13.2
2
+ * bpmn-js - bpmn-navigated-viewer 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() :
@@ -2646,7 +2646,7 @@
2646
2646
  *
2647
2647
  * @param {Object} [element] element to bind the id to
2648
2648
  *
2649
- * @return {String} id
2649
+ * @return {string} id
2650
2650
  */
2651
2651
  Ids.prototype.next = function(element) {
2652
2652
  return this._seed(element || true);
@@ -2657,7 +2657,7 @@
2657
2657
  *
2658
2658
  * @param {Object} [element] element to bind the id to
2659
2659
  *
2660
- * @return {String} id
2660
+ * @return {string} id
2661
2661
  */
2662
2662
  Ids.prototype.nextPrefixed = function(prefix, element) {
2663
2663
  var id;
@@ -2676,8 +2676,8 @@
2676
2676
  /**
2677
2677
  * Manually claim an existing id.
2678
2678
  *
2679
- * @param {String} id
2680
- * @param {String} [element] element the id is claimed by
2679
+ * @param {string} id
2680
+ * @param {any} [element] element the id is claimed by
2681
2681
  */
2682
2682
  Ids.prototype.claim = function(id, element) {
2683
2683
  this._seed.set(id, element || true);
@@ -2686,8 +2686,8 @@
2686
2686
  /**
2687
2687
  * Returns true if the given id has already been assigned.
2688
2688
  *
2689
- * @param {String} id
2690
- * @return {Boolean}
2689
+ * @param {string} id
2690
+ * @return {boolean}
2691
2691
  */
2692
2692
  Ids.prototype.assigned = function(id) {
2693
2693
  return this._seed.get(id) || false;
@@ -2696,7 +2696,7 @@
2696
2696
  /**
2697
2697
  * Unclaim an id.
2698
2698
  *
2699
- * @param {String} id the id to unclaim
2699
+ * @param {string} id the id to unclaim
2700
2700
  */
2701
2701
  Ids.prototype.unclaim = function(id) {
2702
2702
  delete this._seed.hats[id];
@@ -5149,47 +5149,105 @@
5149
5149
  }
5150
5150
  }
5151
5151
 
5152
+ /** @type {CanvasRenderingContext2D | null} */
5153
+ var _canvasContext = null;
5154
+
5152
5155
  /**
5153
- * @param {string} text
5154
- * @param {SVGTextElement} fakeText
5156
+ * @return {CanvasRenderingContext2D | null}
5157
+ */
5158
+ function getCanvasContext() {
5159
+ if (!_canvasContext) {
5160
+ _canvasContext = document.createElement('canvas').getContext('2d');
5161
+ }
5162
+
5163
+ return _canvasContext;
5164
+ }
5165
+
5166
+ /**
5167
+ * Build a CSS font string from a style object for use with the canvas
5168
+ * measureText API.
5155
5169
  *
5156
- * @return {import('../util/Types').Dimensions}
5170
+ * @param {Record<string, number | string>} style
5171
+ *
5172
+ * @return {string}
5157
5173
  */
5158
- function getTextBBox(text, fakeText) {
5174
+ function buildFont(style) {
5175
+ var parts = [];
5159
5176
 
5160
- fakeText.textContent = text;
5177
+ if (style.fontStyle) {
5178
+ parts.push(style.fontStyle);
5179
+ }
5161
5180
 
5162
- var textBBox;
5181
+ if (style.fontVariant) {
5182
+ parts.push(style.fontVariant);
5183
+ }
5163
5184
 
5164
- try {
5165
- var bbox,
5166
- emptyLine = text === '';
5185
+ if (style.fontWeight) {
5186
+ parts.push(style.fontWeight);
5187
+ }
5167
5188
 
5168
- // add dummy text, when line is empty to
5169
- // determine correct height
5170
- fakeText.textContent = emptyLine ? 'dummy' : text;
5189
+ if (style.fontStretch) {
5190
+ parts.push(style.fontStretch);
5191
+ }
5171
5192
 
5172
- textBBox = fakeText.getBBox();
5193
+ parts.push(buildLength(style.fontSize) || '12px');
5194
+ parts.push(style.fontFamily || 'sans-serif');
5173
5195
 
5174
- // take text rendering related horizontal
5175
- // padding into account
5176
- bbox = {
5177
- width: textBBox.width + textBBox.x * 2,
5178
- height: textBBox.height
5179
- };
5196
+ return parts.join(' ');
5197
+ }
5180
5198
 
5181
- if (emptyLine) {
5199
+ /**
5200
+ * Coerce a CSS length to a string with units, since canvas APIs
5201
+ * silently reject unitless lengths and keep the previous value.
5202
+ *
5203
+ * @param {number | string | undefined} value
5204
+ *
5205
+ * @return {string | undefined}
5206
+ */
5207
+ function buildLength(value) {
5208
+ if (value == null) {
5209
+ return undefined;
5210
+ }
5182
5211
 
5183
- // correct width
5184
- bbox.width = 0;
5185
- }
5212
+ if (typeof value === 'number' || /^-?\d+(\.\d+)?$/.test(value)) {
5213
+ return value + 'px';
5214
+ }
5186
5215
 
5187
- return bbox;
5188
- } catch (e) {
5189
- console.log(e);
5216
+ return value;
5217
+ }
5218
+
5219
+ /**
5220
+ * @param {string} text
5221
+ * @param {Record<string, number | string>} style
5222
+ *
5223
+ * @return {import('../util/Types').Dimensions}
5224
+ */
5225
+ function getTextBBox(text, style) {
5226
+ var ctx = getCanvasContext();
5190
5227
 
5228
+ if (!ctx) {
5191
5229
  return { width: 0, height: 0 };
5192
5230
  }
5231
+
5232
+ ctx.font = buildFont(style);
5233
+
5234
+ if ('letterSpacing' in ctx) {
5235
+ ctx.letterSpacing = buildLength(style.letterSpacing) || '0px';
5236
+ }
5237
+
5238
+ var emptyLine = text === '';
5239
+
5240
+ // strip trailing whitespace so measurement matches the browser's
5241
+ // native rendering used by direct editing
5242
+ var measurable = emptyLine ? 'dummy' : text.replace(/\s+$/, '');
5243
+ var metrics = ctx.measureText(measurable);
5244
+
5245
+ return {
5246
+ width: emptyLine ? 0 : metrics.width,
5247
+ height: 'fontBoundingBoxAscent' in metrics
5248
+ ? metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent
5249
+ : metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent
5250
+ };
5193
5251
  }
5194
5252
 
5195
5253
 
@@ -5200,11 +5258,11 @@
5200
5258
  *
5201
5259
  * @param {string[]} lines
5202
5260
  * @param {number} maxWidth
5203
- * @param {SVGTextElement} fakeText
5261
+ * @param {Record<string, number | string>} style
5204
5262
  *
5205
5263
  * @return {LineDescriptor} the line descriptor
5206
5264
  */
5207
- function layoutNext(lines, maxWidth, fakeText) {
5265
+ function layoutNext(lines, maxWidth, style) {
5208
5266
 
5209
5267
  var originalLine = lines.shift(),
5210
5268
  fitLine = originalLine;
@@ -5212,7 +5270,7 @@
5212
5270
  var textBBox;
5213
5271
 
5214
5272
  for (;;) {
5215
- textBBox = getTextBBox(fitLine, fakeText);
5273
+ textBBox = getTextBBox(fitLine, style);
5216
5274
 
5217
5275
  textBBox.width = fitLine ? textBBox.width : 0;
5218
5276
 
@@ -5319,33 +5377,6 @@
5319
5377
  }
5320
5378
 
5321
5379
 
5322
- /**
5323
- * @return {SVGSVGElement}
5324
- */
5325
- function getHelperSvg() {
5326
- var helperSvg = document.getElementById('helper-svg');
5327
-
5328
- if (!helperSvg) {
5329
- helperSvg = create$1('svg');
5330
-
5331
- attr$1(helperSvg, {
5332
- id: 'helper-svg'
5333
- });
5334
-
5335
- assign(helperSvg, {
5336
- visibility: 'hidden',
5337
- position: 'fixed',
5338
- width: 0,
5339
- height: 0
5340
- });
5341
-
5342
- document.body.appendChild(helperSvg);
5343
- }
5344
-
5345
- return helperSvg;
5346
- }
5347
-
5348
-
5349
5380
  /**
5350
5381
  * Creates a new label utility
5351
5382
  *
@@ -5412,17 +5443,8 @@
5412
5443
 
5413
5444
  var maxWidth = box.width - padding.left - padding.right;
5414
5445
 
5415
- // ensure correct rendering by attaching helper text node to invisible SVG
5416
- var helperText = create$1('text');
5417
- attr$1(helperText, { x: 0, y: 0 });
5418
- attr$1(helperText, style);
5419
-
5420
- var helperSvg = getHelperSvg();
5421
-
5422
- append(helperSvg, helperText);
5423
-
5424
5446
  while (lines.length) {
5425
- layouted.push(layoutNext(lines, maxWidth, helperText));
5447
+ layouted.push(layoutNext(lines, maxWidth, style));
5426
5448
  }
5427
5449
 
5428
5450
  if (align.vertical === 'middle') {
@@ -5485,8 +5507,6 @@
5485
5507
  append(textElement, tspan);
5486
5508
  });
5487
5509
 
5488
- remove$2(helperText);
5489
-
5490
5510
  var dimensions = {
5491
5511
  width: maxLineWidth,
5492
5512
  height: totalHeight