@metadev/daga 4.2.17 → 4.2.19

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.
package/Changelog.md CHANGED
@@ -6,6 +6,17 @@ List of releases and changes.
6
6
 
7
7
  ## Next release Joyeuse
8
8
 
9
+ ## v. 4.2.19
10
+
11
+ - Fix bug where diagram properties with a `null` value fail because the `clone` function fails with `null` values [#379](https://github.com/metadevpro/daga/pull/379)
12
+ - Fix bugs in incorrect calculation of the margin of connection labels [#382](https://github.com/metadevpro/daga/pull/382)
13
+
14
+ ## v. 4.2.18
15
+
16
+ - Remove usage of `<foreignObject>` elements for diagram fields [#375](https://github.com/metadevpro/daga/pull/375)
17
+ - Add a `DiagramDraggingNodeEvent` for when the user drags a node to enable listening to the active dragging of a node if unfinished [#376](https://github.com/metadevpro/daga/pull/376)
18
+ - Add `multiline` property to label configuration to enable toggling whether a label should be multiline or not [#378](https://github.com/metadevpro/daga/pull/378)
19
+
9
20
  ## v. 4.2.17
10
21
 
11
22
  - Fix bug where the `DagaImporter` fails to create a node's label if it's blank [#373](https://github.com/metadevpro/daga/pull/373)
package/index.cjs.js CHANGED
@@ -1191,6 +1191,9 @@ const numberOfRows = s => {
1191
1191
  * @private
1192
1192
  */
1193
1193
  const clone = o => {
1194
+ if (o === null) {
1195
+ return o;
1196
+ }
1194
1197
  if (typeof o !== 'object') {
1195
1198
  return o;
1196
1199
  }
@@ -2701,6 +2704,7 @@ const DIAGRAM_FIELD_DEFAULTS = {
2701
2704
  horizontalAlign: exports.HorizontalAlign.Center,
2702
2705
  verticalAlign: exports.VerticalAlign.Center,
2703
2706
  orientation: exports.Side.Top,
2707
+ multiline: false,
2704
2708
  fit: false,
2705
2709
  shrink: true
2706
2710
  };
@@ -2730,7 +2734,7 @@ class DiagramField extends DiagramElement {
2730
2734
  (_a = this.model.canvas) === null || _a === void 0 ? void 0 : _a.fitFieldRootInView(this.id, this.shrink);
2731
2735
  }
2732
2736
  }
2733
- constructor(model, rootElement, coords, width, height, fontSize, fontFamily, color, selectedColor, horizontalAlign, verticalAlign, orientation, text, editable, fit, shrink) {
2737
+ constructor(model, rootElement, coords, width, height, fontSize, fontFamily, color, selectedColor, horizontalAlign, verticalAlign, orientation, multiline, text, editable, fit, shrink) {
2734
2738
  const id = `${rootElement === null || rootElement === void 0 ? void 0 : rootElement.id}_field`;
2735
2739
  if (model.fields.get(id) !== undefined) {
2736
2740
  throw new Error('DiagramField for rootElement already exists');
@@ -2771,6 +2775,7 @@ class DiagramField extends DiagramElement {
2771
2775
  this.orientation = 0;
2772
2776
  }
2773
2777
  }
2778
+ this.multiline = multiline;
2774
2779
  this.defaultText = text;
2775
2780
  this._text = text;
2776
2781
  this.editable = editable;
@@ -2815,8 +2820,8 @@ class DiagramFieldSet extends DiagramElementSet {
2815
2820
  * Instance a new field and add it to this set. This method is normally called when instancing an element with a field and it is rarely called by itself.
2816
2821
  * @private
2817
2822
  */
2818
- new(rootElement, coords, fontSize, fontFamily, color, selectedColor, width, height, horizontalAlign, verticalAlign, orientation, text, editable, fit, shrink) {
2819
- const field = new DiagramField(this.model, rootElement, coords, width, height, fontSize, fontFamily, color, selectedColor, horizontalAlign, verticalAlign, orientation, text, editable, fit, shrink);
2823
+ new(rootElement, coords, fontSize, fontFamily, color, selectedColor, width, height, horizontalAlign, verticalAlign, orientation, multiline, text, editable, fit, shrink) {
2824
+ const field = new DiagramField(this.model, rootElement, coords, width, height, fontSize, fontFamily, color, selectedColor, horizontalAlign, verticalAlign, orientation, multiline, text, editable, fit, shrink);
2820
2825
  super.add(field);
2821
2826
  field.updateInView();
2822
2827
  // add this field to its root element
@@ -3455,7 +3460,7 @@ class DiagramSectionSet extends DiagramElementSet {
3455
3460
  default:
3456
3461
  labelCoords = port.coords;
3457
3462
  }
3458
- this.model.fields.new(port, labelCoords, labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelWidth, labelHeight, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
3463
+ this.model.fields.new(port, labelCoords, labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelWidth, labelHeight, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
3459
3464
  }
3460
3465
  }
3461
3466
  }
@@ -3463,7 +3468,7 @@ class DiagramSectionSet extends DiagramElementSet {
3463
3468
  const sectionLabel = (_k = (_j = (_h = (_g = node.type.sectionGrid) === null || _g === void 0 ? void 0 : _g.sections) === null || _h === void 0 ? void 0 : _h[indexYInNode]) === null || _j === void 0 ? void 0 : _j[indexXInNode]) === null || _k === void 0 ? void 0 : _k.label;
3464
3469
  if (sectionLabel) {
3465
3470
  const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), sectionLabel);
3466
- this.model.fields.new(section, [section.coords[0] + getLeftMargin(labelConfiguration), section.coords[1] + getTopMargin(labelConfiguration)], labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, section.width - getLeftMargin(labelConfiguration) - getRightMargin(labelConfiguration), section.height - getTopMargin(labelConfiguration) - getBottomMargin(labelConfiguration), labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
3471
+ this.model.fields.new(section, [section.coords[0] + getLeftMargin(labelConfiguration), section.coords[1] + getTopMargin(labelConfiguration)], labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, section.width - getLeftMargin(labelConfiguration) - getRightMargin(labelConfiguration), section.height - getTopMargin(labelConfiguration) - getBottomMargin(labelConfiguration), labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
3467
3472
  }
3468
3473
  return section;
3469
3474
  }
@@ -4383,14 +4388,14 @@ class DiagramNodeSet extends DiagramElementSet {
4383
4388
  default:
4384
4389
  labelCoords = port.coords;
4385
4390
  }
4386
- this.model.fields.new(port, labelCoords, labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelWidth, labelHeight, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
4391
+ this.model.fields.new(port, labelCoords, labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelWidth, labelHeight, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
4387
4392
  }
4388
4393
  }
4389
4394
  }
4390
4395
  // add node label
4391
4396
  if (nodeType.label) {
4392
4397
  const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), nodeType.label);
4393
- this.model.fields.new(node, [node.coords[0] + getLeftMargin(labelConfiguration), node.coords[1] + getTopMargin(labelConfiguration)], labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, node.width - getLeftMargin(labelConfiguration) - getRightMargin(labelConfiguration), node.height - getTopMargin(labelConfiguration) - getBottomMargin(labelConfiguration), labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
4398
+ this.model.fields.new(node, [node.coords[0] + getLeftMargin(labelConfiguration), node.coords[1] + getTopMargin(labelConfiguration)], labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, node.width - getLeftMargin(labelConfiguration) - getRightMargin(labelConfiguration), node.height - getTopMargin(labelConfiguration) - getBottomMargin(labelConfiguration), labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
4394
4399
  }
4395
4400
  // add node decorators
4396
4401
  if (nodeType.decorators.length > 0) {
@@ -4960,7 +4965,7 @@ class DagaImporter {
4960
4965
  // add node label
4961
4966
  if (newNodeType.label) {
4962
4967
  const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), newNodeType.label);
4963
- const newField = new DiagramField(model, newNode, [newNode.coords[0] + getLeftMargin(labelConfiguration), newNode.coords[1] + getTopMargin(labelConfiguration)], newNode.width - getLeftMargin(labelConfiguration) - getRightMargin(labelConfiguration), newNode.height - getTopMargin(labelConfiguration) - getBottomMargin(labelConfiguration), labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
4968
+ const newField = new DiagramField(model, newNode, [newNode.coords[0] + getLeftMargin(labelConfiguration), newNode.coords[1] + getTopMargin(labelConfiguration)], newNode.width - getLeftMargin(labelConfiguration) - getRightMargin(labelConfiguration), newNode.height - getTopMargin(labelConfiguration) - getBottomMargin(labelConfiguration), labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
4964
4969
  newField.text = node.label;
4965
4970
  newNode.label = newField;
4966
4971
  model.fields.add(newField);
@@ -4980,7 +4985,7 @@ class DagaImporter {
4980
4985
  // add section label
4981
4986
  if ((_f = (_e = (_d = (_c = newNodeType.sectionGrid) === null || _c === void 0 ? void 0 : _c.sections) === null || _d === void 0 ? void 0 : _d[section.indexYInNode]) === null || _e === void 0 ? void 0 : _e[section.indexXInNode]) === null || _f === void 0 ? void 0 : _f.label) {
4982
4987
  const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), (_k = (_j = (_h = (_g = newNodeType.sectionGrid) === null || _g === void 0 ? void 0 : _g.sections) === null || _h === void 0 ? void 0 : _h[section.indexYInNode]) === null || _j === void 0 ? void 0 : _j[section.indexXInNode]) === null || _k === void 0 ? void 0 : _k.label);
4983
- const newField = new DiagramField(model, newSection, [newSection.coords[0] + getLeftMargin(labelConfiguration), newSection.coords[1] + getTopMargin(labelConfiguration)], newSection.width - getLeftMargin(labelConfiguration) - getRightMargin(labelConfiguration), newSection.height - getTopMargin(labelConfiguration) - getBottomMargin(labelConfiguration), labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
4988
+ const newField = new DiagramField(model, newSection, [newSection.coords[0] + getLeftMargin(labelConfiguration), newSection.coords[1] + getTopMargin(labelConfiguration)], newSection.width - getLeftMargin(labelConfiguration) - getRightMargin(labelConfiguration), newSection.height - getTopMargin(labelConfiguration) - getBottomMargin(labelConfiguration), labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
4984
4989
  newField.text = section.label;
4985
4990
  newSection.label = newField;
4986
4991
  model.fields.add(newField);
@@ -5011,7 +5016,7 @@ class DagaImporter {
5011
5016
  default:
5012
5017
  labelCoords = newPort.coords;
5013
5018
  }
5014
- const newField = new DiagramField(model, newPort, labelCoords, labelConfiguration.fontSize, labelConfiguration.fontSize, labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
5019
+ const newField = new DiagramField(model, newPort, labelCoords, labelConfiguration.fontSize, labelConfiguration.fontSize, labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
5015
5020
  newField.text = port.label;
5016
5021
  newPort.label = newField;
5017
5022
  model.fields.add(newField);
@@ -5058,7 +5063,7 @@ class DagaImporter {
5058
5063
  default:
5059
5064
  labelCoords = newPort.coords;
5060
5065
  }
5061
- const newField = new DiagramField(model, newPort, labelCoords, labelConfiguration.fontSize, labelConfiguration.fontSize, labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
5066
+ const newField = new DiagramField(model, newPort, labelCoords, labelConfiguration.fontSize, labelConfiguration.fontSize, labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
5062
5067
  newField.text = port.label;
5063
5068
  newPort.label = newField;
5064
5069
  model.fields.add(newField);
@@ -6355,6 +6360,7 @@ exports.DiagramEvents = void 0;
6355
6360
  DiagramEvents[DiagramEvents["SecondaryClick"] = 2] = "SecondaryClick";
6356
6361
  DiagramEvents[DiagramEvents["Selection"] = 3] = "Selection";
6357
6362
  DiagramEvents[DiagramEvents["Highlight"] = 4] = "Highlight";
6363
+ DiagramEvents[DiagramEvents["DraggingNode"] = 5] = "DraggingNode";
6358
6364
  })(exports.DiagramEvents || (exports.DiagramEvents = {}));
6359
6365
  /**
6360
6366
  * Diagram event which consists of the user zooming or panning.
@@ -6438,6 +6444,20 @@ class DiagramHighlightedEvent extends DiagramEvent {
6438
6444
  this.target = target;
6439
6445
  }
6440
6446
  }
6447
+ /**
6448
+ * Diagram event which consists of the user dragging a diagram node.
6449
+ */
6450
+ class DiagramDraggingNodeEvent extends DiagramEvent {
6451
+ /**
6452
+ * Create a diagram dragging node event.
6453
+ *
6454
+ * @param target Diagram node which is targeted by the event.
6455
+ */
6456
+ constructor(target) {
6457
+ super(exports.DiagramEvents.DraggingNode);
6458
+ this.target = target;
6459
+ }
6460
+ }
6441
6461
 
6442
6462
  /**
6443
6463
  * A foreign object which is inserted with arbitrary html into a diagram.
@@ -7471,29 +7491,6 @@ class DiagramUserSelection extends DiagramElementSet {
7471
7491
  }
7472
7492
  }
7473
7493
 
7474
- const degreesToRadians = theta => theta * Math.PI / 180;
7475
- /**
7476
- * Calculates the original size of the a rectangle that has been rotated by the given number of degrees resulting in a bounding box of the given size.
7477
- *
7478
- * @param width The width of a bounding box.
7479
- * @param height The height of a bounding box.
7480
- * @param orientation A rotation in degrees.
7481
- * @returns The size of the original rectangle.
7482
- */
7483
- const unrotate = (width, height, orientation) => {
7484
- // TODO: this method fails under certain edge cases
7485
- // like for example, when angle is 45 degrees so sin(theta) == cos(theta)
7486
- const theta = degreesToRadians(orientation);
7487
- const orientationSine = Math.sin(theta);
7488
- const orientationCosine = Math.cos(theta);
7489
- const oldWidth = (Math.abs(width * orientationCosine) - Math.abs(height * orientationSine)) / (orientationCosine * orientationCosine - orientationSine * orientationSine);
7490
- const oldHeight = (Math.abs(width * orientationSine) - Math.abs(height * orientationCosine)) / (orientationSine * orientationSine - orientationCosine * orientationCosine);
7491
- return [oldWidth, oldHeight];
7492
- };
7493
-
7494
- const isUserAgentSafari = userAgent => /^((?!chrome|android).)*safari/i.test(userAgent);
7495
- const isSafari = isUserAgentSafari(navigator.userAgent);
7496
-
7497
7494
  /**
7498
7495
  * Thickness of the invisible path around a connection used to make it easier to click on, in diagram units.
7499
7496
  * @private
@@ -7792,10 +7789,6 @@ class DiagramCanvas {
7792
7789
  const transformAttribute = event.transform.toString();
7793
7790
  this.selectCanvasElements().attr('transform', transformAttribute);
7794
7791
  d3__namespace.select(`#${this.backgroundPatternId}`).attr('patternTransform', transformAttribute);
7795
- if (isSafari) {
7796
- // force update fields to compensate for a rendering bug in webkit
7797
- this.updateFieldsInView();
7798
- }
7799
7792
  this.contextMenu.close();
7800
7793
  this.diagramEvent$.next(new DiagramZoomEvent([this.zoomTransform.x, this.zoomTransform.y], this.zoomTransform.k));
7801
7794
  }).on(exports.ZoomEvents.End, () => {
@@ -8042,7 +8035,7 @@ class DiagramCanvas {
8042
8035
  this.secondaryButton = false;
8043
8036
  }));
8044
8037
  initializeLook(enterSelection);
8045
- enterSelection.filter('.resizable-x').append('line').attr('class', 'left-resizer').attr('stroke', 'transparent').attr('stroke-width', `${RESIZER_THICKNESS}px`).on(exports.Events.MouseOver, (_event, d) => {
8038
+ enterSelection.filter('.resizable-x').append('line').attr('class', 'left-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(exports.Events.MouseOver, (_event, d) => {
8046
8039
  if (this.canUserPerformAction(exports.DiagramActions.StretchNode) && d.getResizableX() && !d.removed) {
8047
8040
  setCursorStyle(exports.CursorStyle.EWResize);
8048
8041
  }
@@ -8078,7 +8071,7 @@ class DiagramCanvas {
8078
8071
  }
8079
8072
  setCursorStyle();
8080
8073
  }));
8081
- enterSelection.filter('.resizable-y').append('line').attr('class', 'top-resizer').attr('stroke', 'transparent').attr('stroke-width', `${RESIZER_THICKNESS}px`).on(exports.Events.MouseOver, (_event, d) => {
8074
+ enterSelection.filter('.resizable-y').append('line').attr('class', 'top-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(exports.Events.MouseOver, (_event, d) => {
8082
8075
  if (this.canUserPerformAction(exports.DiagramActions.StretchNode) && d.getResizableY() && !d.removed) {
8083
8076
  setCursorStyle(exports.CursorStyle.NSResize);
8084
8077
  }
@@ -8114,7 +8107,7 @@ class DiagramCanvas {
8114
8107
  }
8115
8108
  setCursorStyle();
8116
8109
  }));
8117
- enterSelection.filter('.resizable-x').append('line').attr('class', 'right-resizer').attr('stroke', 'transparent').attr('stroke-width', `${RESIZER_THICKNESS}px`).on(exports.Events.MouseOver, (_event, d) => {
8110
+ enterSelection.filter('.resizable-x').append('line').attr('class', 'right-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(exports.Events.MouseOver, (_event, d) => {
8118
8111
  if (this.canUserPerformAction(exports.DiagramActions.StretchNode) && d.getResizableX() && !d.removed) {
8119
8112
  setCursorStyle(exports.CursorStyle.EWResize);
8120
8113
  }
@@ -8150,7 +8143,7 @@ class DiagramCanvas {
8150
8143
  }
8151
8144
  setCursorStyle();
8152
8145
  }));
8153
- enterSelection.filter('.resizable-y').append('line').attr('class', 'bottom-resizer').attr('stroke', 'transparent').attr('stroke-width', `${RESIZER_THICKNESS}px`).on(exports.Events.MouseOver, (_event, d) => {
8146
+ enterSelection.filter('.resizable-y').append('line').attr('class', 'bottom-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(exports.Events.MouseOver, (_event, d) => {
8154
8147
  if (this.canUserPerformAction(exports.DiagramActions.StretchNode) && d.getResizableY() && !d.removed) {
8155
8148
  setCursorStyle(exports.CursorStyle.NSResize);
8156
8149
  }
@@ -8281,7 +8274,7 @@ class DiagramCanvas {
8281
8274
  this.secondaryButton = false;
8282
8275
  }));
8283
8276
  initializeLook(enterSelection);
8284
- enterSelection.filter('.resizable-x').append('line').attr('class', 'left-resizer').attr('stroke', 'transparent').attr('stroke-width', `${RESIZER_THICKNESS}px`).on(exports.Events.MouseOver, (_event, d) => {
8277
+ enterSelection.filter('.resizable-x').append('line').attr('class', 'left-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(exports.Events.MouseOver, (_event, d) => {
8285
8278
  if (this.canUserPerformAction(exports.DiagramActions.StretchSection) && d.getResizableX() && !d.removed) {
8286
8279
  setCursorStyle(exports.CursorStyle.EWResize);
8287
8280
  }
@@ -8315,7 +8308,7 @@ class DiagramCanvas {
8315
8308
  }
8316
8309
  setCursorStyle();
8317
8310
  }));
8318
- enterSelection.filter('.resizable-y').append('line').attr('class', 'top-resizer').attr('stroke', 'transparent').attr('stroke-width', `${RESIZER_THICKNESS}px`).on(exports.Events.MouseOver, (_event, d) => {
8311
+ enterSelection.filter('.resizable-y').append('line').attr('class', 'top-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(exports.Events.MouseOver, (_event, d) => {
8319
8312
  if (this.canUserPerformAction(exports.DiagramActions.StretchSection) && d.getResizableY() && !d.removed) {
8320
8313
  setCursorStyle(exports.CursorStyle.NSResize);
8321
8314
  }
@@ -8349,7 +8342,7 @@ class DiagramCanvas {
8349
8342
  }
8350
8343
  setCursorStyle();
8351
8344
  }));
8352
- enterSelection.filter('.resizable-x').append('line').attr('class', 'right-resizer').attr('stroke', 'transparent').attr('stroke-width', `${RESIZER_THICKNESS}px`).on(exports.Events.MouseOver, (_event, d) => {
8345
+ enterSelection.filter('.resizable-x').append('line').attr('class', 'right-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(exports.Events.MouseOver, (_event, d) => {
8353
8346
  if (this.canUserPerformAction(exports.DiagramActions.StretchSection) && d.getResizableX() && !d.removed) {
8354
8347
  setCursorStyle(exports.CursorStyle.EWResize);
8355
8348
  }
@@ -8383,7 +8376,7 @@ class DiagramCanvas {
8383
8376
  }
8384
8377
  setCursorStyle();
8385
8378
  }));
8386
- enterSelection.filter('.resizable-y').append('line').attr('class', 'bottom-resizer').attr('stroke', 'transparent').attr('stroke-width', `${RESIZER_THICKNESS}px`).on(exports.Events.MouseOver, (_event, d) => {
8379
+ enterSelection.filter('.resizable-y').append('line').attr('class', 'bottom-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(exports.Events.MouseOver, (_event, d) => {
8387
8380
  if (this.canUserPerformAction(exports.DiagramActions.StretchSection) && d.getResizableY() && !d.removed) {
8388
8381
  setCursorStyle(exports.CursorStyle.NSResize);
8389
8382
  }
@@ -8664,28 +8657,28 @@ class DiagramCanvas {
8664
8657
  mergeSelection.attr('opacity', d => d.removed ? 0.5 : 1).select('path.diagram-connection-path').attr('d', d => {
8665
8658
  var _a, _b;
8666
8659
  return getConnectionPath(d.look.shape || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.shape, d.startCoords, d.endCoords, d.startDirection, d.endDirection, d.points, d.type.defaultLook.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness, (_a = d.type.defaultStartMarkerLook) === null || _a === void 0 ? void 0 : _a.width, (_b = d.type.defaultEndMarkerLook) === null || _b === void 0 ? void 0 : _b.width);
8667
- }).attr('marker-start', d => `url(#${d.id}-start-marker)`).attr('marker-end', d => `url(#${d.id}-end-marker)`).attr('stroke', d => d.look.color || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.color).attr('stroke-width', d => `${d.look.thickness}px`).attr('stroke-dasharray', d => lineStyleDasharray(d.look.style || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.style, d.type.defaultLook.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness)).attr('fill', 'none');
8660
+ }).attr('marker-start', d => `url(#${d.id}-start-marker)`).attr('marker-end', d => `url(#${d.id}-end-marker)`).attr('stroke', d => d.look.color || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.color).attr('stroke-width', d => d.look.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness).attr('stroke-dasharray', d => lineStyleDasharray(d.look.style || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.style, d.type.defaultLook.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness)).attr('fill', 'none');
8668
8661
  mergeSelection.select('path.diagram-connection-path-box').attr('d', d => {
8669
8662
  var _a, _b;
8670
8663
  return getConnectionPath(d.look.shape || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.shape, d.startCoords, d.endCoords, d.startDirection, d.endDirection, d.points, d.type.defaultLook.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness, (_a = d.type.defaultStartMarkerLook) === null || _a === void 0 ? void 0 : _a.width, (_b = d.type.defaultEndMarkerLook) === null || _b === void 0 ? void 0 : _b.width);
8671
8664
  }).attr('stroke', 'transparent')
8672
8665
  // allow generating pointer events even when it is transparent
8673
- .attr('pointer-events', 'stroke').attr('stroke-width', d => `${(d.look.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness) + CONNECTION_PATH_BOX_THICKNESS}px`).attr('stroke-dasharray', d => lineStyleDasharray(d.look.style || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.style, d.type.defaultLook.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness)).attr('fill', 'none');
8666
+ .attr('pointer-events', 'stroke').attr('stroke-width', d => (d.look.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness) + CONNECTION_PATH_BOX_THICKNESS).attr('stroke-dasharray', d => lineStyleDasharray(d.look.style || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.style, d.type.defaultLook.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness)).attr('fill', 'none');
8674
8667
  mergeSelection.data().forEach(connection => {
8675
8668
  this.updateConnectionLabelsInView(connection);
8676
8669
  this.updateConnectionMarkersInView(connection);
8677
8670
  });
8678
8671
  }
8679
8672
  updateFieldsInView(...ids) {
8680
- let updateSelection = this.selectCanvasElements().selectAll('foreignObject.diagram-field').data(this.model.fields.filter(e => this.priorityThreshold !== undefined ? e.getPriority() >= this.priorityThreshold : true), d => d.id);
8673
+ let updateSelection = this.selectCanvasElements().selectAll('g.diagram-field').data(this.model.fields.filter(e => this.priorityThreshold !== undefined ? e.getPriority() >= this.priorityThreshold : true), d => d.id);
8681
8674
  const exitSelection = updateSelection.exit();
8682
- const enterSelection = updateSelection.enter().append('foreignObject').attr('id', d => d.id).attr('class', 'diagram-field');
8675
+ const enterSelection = updateSelection.enter().append('g').attr('id', d => d.id).attr('class', 'diagram-field');
8683
8676
  if (ids && ids.length > 0) {
8684
8677
  updateSelection = updateSelection.filter(d => ids.includes(d.id));
8685
8678
  }
8686
8679
  const mergeSelection = enterSelection.merge(updateSelection);
8687
8680
  exitSelection.remove();
8688
- enterSelection.style('box-sizing', 'border-box').on(exports.Events.MouseOver, (_event, d) => {
8681
+ enterSelection.on(exports.Events.MouseOver, (_event, d) => {
8689
8682
  if (!this.dragging) {
8690
8683
  this.userHighlight.focusOn(d);
8691
8684
  this.diagramEvent$.next(new DiagramHighlightedEvent(d));
@@ -8776,12 +8769,15 @@ class DiagramCanvas {
8776
8769
  }
8777
8770
  }
8778
8771
  this.secondaryButton = false;
8779
- })).append('xhtml:div').style('width', '100%').style('height', '100%').style('display', 'flex').append('xhtml:p').style('box-sizing', 'border-box').style('outline', 0).style('margin', 0).style('border', 0).style('padding', 0).style('user-select', 'none').style('font-kerning', 'none').style('white-space', 'nowrap');
8780
- mergeSelection.attr('x', 0).attr('y', 0).attr('width', d => `${d.width}px`).attr('height', d => `${d.height}px`).attr('transform', d => `translate(${d.coords[0]},${d.coords[1]})`).attr('opacity', d => d.removed ? 0.5 : 1).select('div').style('justify-content', d => d.horizontalAlign === exports.HorizontalAlign.Center ? 'center' : d.horizontalAlign === exports.HorizontalAlign.Right ? 'flex-end' : 'flex-start').style('align-items', d => d.verticalAlign === exports.VerticalAlign.Center ? 'center' : d.verticalAlign === exports.VerticalAlign.Bottom ? 'end' : 'start').select('p').style('max-width', d => d.fit ? 'default' : `${unrotate(d.width, d.height, d.orientation)[0]}px`).style('max-height', d => d.fit ? 'default' : `${unrotate(d.width, d.height, d.orientation)[1]}px`).style('overflow', d => d.fit ? 'default' : 'clip').style('text-overflow', d => d.fit ? 'default' : 'ellipsis').style('text-align', d => d.horizontalAlign === exports.HorizontalAlign.Center ? 'center' : d.horizontalAlign === exports.HorizontalAlign.Right ? 'end' : 'start').style('transform', d => `rotate(${d.orientation}deg)`).style('font-size', d => `${d.fontSize}px`).style('font-family', d => d.fontFamily || "'Wonder Unit Sans', sans-serif").style('font-weight', d => d.highlighted ? 600 : 400).style('color', d => d.selected ? d.selectedColor || '#000000' : d.color || '#000000').html(d => d.text.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\n/g, '<br/>'));
8781
- if (isSafari) {
8782
- const zoomFactor = this.zoomTransform.k;
8783
- mergeSelection.attr('width', d => `${d.width * zoomFactor}px`).attr('height', d => `${d.height * zoomFactor}px`).select('div').style('position', 'absolute').style('left', d => `${d.coords[0] * zoomFactor + this.zoomTransform.x}px`).style('top', d => `${d.coords[1] * zoomFactor + this.zoomTransform.y}px`).select('p').style('font-size', d => `${d.fontSize * zoomFactor}px`);
8784
- }
8772
+ }));
8773
+ enterSelection.append('text');
8774
+ enterSelection.append('rect');
8775
+ mergeSelection.attr('x', 0).attr('y', 0).attr('width', d => d.width).attr('height', d => d.height).attr('transform', d => `translate(${d.coords[0]},${d.coords[1]}) rotate(${d.orientation} ${d.width / 2} ${d.height / 2})`).attr('opacity', d => d.removed ? 0.5 : 1).select('text').attr('x', d => d.horizontalAlign === exports.HorizontalAlign.Center ? d.width / 2 : d.horizontalAlign === exports.HorizontalAlign.Right ? d.width : 0).attr('text-anchor', d => d.horizontalAlign === exports.HorizontalAlign.Center ? 'middle' : d.horizontalAlign === exports.HorizontalAlign.Right ? 'end' : 'start').attr('y', d => d.verticalAlign === exports.VerticalAlign.Center ? d.height / 2 : d.verticalAlign === exports.VerticalAlign.Bottom ? d.height : 0).attr('dominant-baseline', d => d.verticalAlign === exports.VerticalAlign.Center ? 'middle' : d.verticalAlign === exports.VerticalAlign.Bottom ? 'auto' : 'hanging').attr('font-size', d => d.fontSize).attr('font-family', d => d.fontFamily || "'Wonder Unit Sans', sans-serif").attr('font-weight', d => d.highlighted ? 600 : 400).attr('fill', d => d.selected ? d.selectedColor || '#000000' : d.color || '#000000').each(d => {
8776
+ this.setFieldTextAndWrap(d);
8777
+ });
8778
+ mergeSelection
8779
+ // add a transparent rectangle to capture pointer events on the text
8780
+ .select('rect').attr('x', 0).attr('y', 0).attr('width', d => d.width).attr('height', d => d.height).attr('fill', 'transparent');
8785
8781
  }
8786
8782
  updateObjectsInView(...ids) {
8787
8783
  let updateSelection = this.selectCanvasElements().selectAll('g.diagram-object').data(this.model.objects.filter(e => this.priorityThreshold !== undefined ? e.getPriority() >= this.priorityThreshold : true), d => d.id);
@@ -8791,7 +8787,7 @@ class DiagramCanvas {
8791
8787
  updateSelection = updateSelection.filter(d => ids.includes(d.id));
8792
8788
  }
8793
8789
  const mergeSelection = enterSelection.merge(updateSelection);
8794
- mergeSelection.attr('width', d => `${d.width}px`).attr('height', d => `${d.height}px`).attr('transform', d => `translate(${d.coords[0]},${d.coords[1]})`).html(d => d.html);
8790
+ mergeSelection.attr('width', d => d.width).attr('height', d => d.height).attr('transform', d => `translate(${d.coords[0]},${d.coords[1]})`).html(d => d.html);
8795
8791
  exitSelection.remove();
8796
8792
  enterSelection.on(exports.Events.ContextMenu, (event, d) => {
8797
8793
  if (this.dragging) {
@@ -8834,7 +8830,7 @@ class DiagramCanvas {
8834
8830
  updateSelection = updateSelection.filter(d => ids.includes(d.id));
8835
8831
  }
8836
8832
  const mergeSelection = enterSelection.merge(updateSelection);
8837
- mergeSelection.attr('width', d => `${d.width}px`).attr('height', d => `${d.height}px`).attr('transform', d => `translate(${d.coords[0]},${d.coords[1]})`).html(d => d.html);
8833
+ mergeSelection.attr('width', d => d.width).attr('height', d => d.height).attr('transform', d => `translate(${d.coords[0]},${d.coords[1]})`).html(d => d.html);
8838
8834
  exitSelection.remove();
8839
8835
  enterSelection.on(exports.Events.MouseOver, (_event, d) => {
8840
8836
  if (!this.dragging) {
@@ -9013,10 +9009,10 @@ class DiagramCanvas {
9013
9009
  pathStartLabelPoint = pathNode.getPointAtLength(getLeftMargin(labelConfiguration) + boundingWidth / 2);
9014
9010
  break;
9015
9011
  case exports.Side.Top:
9016
- pathStartLabelPoint = pathNode.getPointAtLength(getBottomMargin(labelConfiguration) + boundingWidth / 2);
9012
+ pathStartLabelPoint = pathNode.getPointAtLength(getBottomMargin(labelConfiguration) + boundingHeight / 2);
9017
9013
  break;
9018
9014
  case exports.Side.Bottom:
9019
- pathStartLabelPoint = pathNode.getPointAtLength(getTopMargin(labelConfiguration) + boundingWidth / 2);
9015
+ pathStartLabelPoint = pathNode.getPointAtLength(getTopMargin(labelConfiguration) + boundingHeight / 2);
9020
9016
  break;
9021
9017
  default:
9022
9018
  pathStartLabelPoint = pathNode.getPointAtLength(Math.max(getLeftMargin(labelConfiguration) + boundingWidth / 2, getRightMargin(labelConfiguration) + boundingWidth / 2, getTopMargin(labelConfiguration) + boundingHeight / 2, getBottomMargin(labelConfiguration) + boundingHeight / 2));
@@ -9051,10 +9047,10 @@ class DiagramCanvas {
9051
9047
  pathEndLabelPoint = pathNode.getPointAtLength(pathLength - (getLeftMargin(labelConfiguration) + boundingWidth / 2));
9052
9048
  break;
9053
9049
  case exports.Side.Top:
9054
- pathEndLabelPoint = pathNode.getPointAtLength(pathLength - (getBottomMargin(labelConfiguration) + boundingWidth / 2));
9050
+ pathEndLabelPoint = pathNode.getPointAtLength(pathLength - (getBottomMargin(labelConfiguration) + boundingHeight / 2));
9055
9051
  break;
9056
9052
  case exports.Side.Bottom:
9057
- pathEndLabelPoint = pathNode.getPointAtLength(pathLength - (getTopMargin(labelConfiguration) + boundingWidth / 2));
9053
+ pathEndLabelPoint = pathNode.getPointAtLength(pathLength - (getTopMargin(labelConfiguration) + boundingHeight / 2));
9058
9054
  break;
9059
9055
  default:
9060
9056
  pathEndLabelPoint = pathNode.getPointAtLength(pathLength - Math.max(getLeftMargin(labelConfiguration) + boundingWidth / 2, getRightMargin(labelConfiguration) + boundingWidth / 2, getTopMargin(labelConfiguration) + boundingHeight / 2, getBottomMargin(labelConfiguration) + boundingHeight / 2));
@@ -9313,7 +9309,7 @@ class DiagramCanvas {
9313
9309
  openTextInput(id) {
9314
9310
  const field = this.model.fields.get(id);
9315
9311
  if (field) {
9316
- this.createInputField(field.text, field.coords, field.width, field.height, field.fontSize, field.fontFamily || DIAGRAM_FIELD_DEFAULTS.fontFamily, field.orientation, () => {
9312
+ this.createInputField(field.text, field.coords, field.width, field.height, field.fontSize, field.fontFamily || DIAGRAM_FIELD_DEFAULTS.fontFamily, field.orientation, field.multiline, () => {
9317
9313
  // (_text)
9318
9314
  /*
9319
9315
  Empty for now
@@ -9331,7 +9327,7 @@ class DiagramCanvas {
9331
9327
  });
9332
9328
  }
9333
9329
  }
9334
- createInputField(text, coords, width, height, fontSize, fontFamily, orientation, changeCallback, finishCallback) {
9330
+ createInputField(text, coords, width, height, fontSize, fontFamily, orientation, multiline, changeCallback, finishCallback) {
9335
9331
  // if we have a text input open, close it before creating a new one
9336
9332
  this.removeInputField();
9337
9333
  const inputFieldContainer = this.selectCanvasElements().append('foreignObject').attr('x', `${coords[0]}px`).attr('y', `${coords[1]}px`).attr('width', `${width}px`).attr('height', `${height}px`).style('box-sizing', 'border-box').style('border', '1px solid');
@@ -9341,16 +9337,16 @@ class DiagramCanvas {
9341
9337
  let inputFieldHeight;
9342
9338
  inputField.text(text).style('box-sizing', 'border-box').style('width', `${width}px`).style('height', `${height}px`).style('font-size', `${fontSize}px`).style('font-family', fontFamily).style('resize', 'none').style('outline', 0).style('border', 0).style('margin', 0).style('padding', 0).on(exports.Events.KeyDown, event => {
9343
9339
  event.stopPropagation();
9344
- }).on(exports.Events.KeyUp, event => {
9345
- event.stopPropagation();
9346
- if (event.key === exports.Keys.Escape) {
9347
- const value = inputField.property('value');
9340
+ if (event.key === exports.Keys.Escape || event.key === exports.Keys.Enter && !multiline) {
9341
+ const value = inputField.property('value') || '';
9348
9342
  this.removeInputField();
9349
9343
  if (finishCallback) {
9350
9344
  finishCallback(value);
9351
9345
  }
9352
9346
  }
9353
- }).on(exports.Events.Input, () => {
9347
+ }).on(exports.Events.KeyUp, event => {
9348
+ event.stopPropagation();
9349
+ }).on(exports.Events.Input, event => {
9354
9350
  const value = inputField.property('value');
9355
9351
  inputField.attr('cols', numberOfColumns(value) + 1);
9356
9352
  inputField.attr('rows', numberOfRows(value) + 1);
@@ -9393,13 +9389,54 @@ class DiagramCanvas {
9393
9389
  }
9394
9390
  minimumSizeOfField(field) {
9395
9391
  var _a, _b;
9396
- const pNode = (_b = (_a = field.select()) === null || _a === void 0 ? void 0 : _a.select('p')) === null || _b === void 0 ? void 0 : _b.node();
9397
- if (!pNode) {
9392
+ const textNode = (_b = (_a = field.select()) === null || _a === void 0 ? void 0 : _a.select('text')) === null || _b === void 0 ? void 0 : _b.node();
9393
+ if (!textNode) {
9398
9394
  // happens when a field has been created but not updated in view yet
9399
9395
  return [0, 0];
9400
9396
  }
9401
- const pBoundingBox = pNode.getBoundingClientRect();
9402
- return [pBoundingBox.width / this.zoomTransform.k, pBoundingBox.height / this.zoomTransform.k];
9397
+ const textBoundingBox = textNode.getBoundingClientRect();
9398
+ return [textBoundingBox.width / this.zoomTransform.k, textBoundingBox.height / this.zoomTransform.k];
9399
+ }
9400
+ setFieldTextAndWrap(field) {
9401
+ var _a, _b, _c, _d;
9402
+ const textSelection = (_a = field.select()) === null || _a === void 0 ? void 0 : _a.select('text');
9403
+ const textNode = textSelection === null || textSelection === void 0 ? void 0 : textSelection.node();
9404
+ if (textSelection && textNode) {
9405
+ this.setFieldText(field, textSelection, field.text);
9406
+ } else {
9407
+ // can happen if a field has been created but not updated in view yet
9408
+ // not sure if this still happens but should check just in case
9409
+ return;
9410
+ }
9411
+ if (field.fit) {
9412
+ // no need to wrap
9413
+ return;
9414
+ }
9415
+ let minimumSize = this.minimumSizeOfField(field);
9416
+ while (minimumSize[0] > field.width || minimumSize[1] > field.height) {
9417
+ const textString = ((_d = (_c = (_b = textSelection === null || textSelection === void 0 ? void 0 : textSelection.html()) === null || _b === void 0 ? void 0 : _b.replace(/<\/tspan>/g, '\n')) === null || _c === void 0 ? void 0 : _c.replace(/<tspan[^>]*>/g, '')) === null || _d === void 0 ? void 0 : _d.slice(0, -1)) || '';
9418
+ let newTextString = '...';
9419
+ if (textString.endsWith('...')) {
9420
+ newTextString = textString.slice(0, -4) + '...';
9421
+ } else {
9422
+ newTextString = textString.slice(0, -1) + '...';
9423
+ }
9424
+ if (textSelection) {
9425
+ this.setFieldText(field, textSelection, newTextString);
9426
+ }
9427
+ if (newTextString === '...') {
9428
+ // if no more characters can be removed and the new text is a bare ellipsis, stop the execution
9429
+ return;
9430
+ }
9431
+ minimumSize = this.minimumSizeOfField(field);
9432
+ }
9433
+ }
9434
+ setFieldText(field, textSelection, text) {
9435
+ const lines = text.split('\n');
9436
+ textSelection.html('');
9437
+ for (let i = 0; i < lines.length; ++i) {
9438
+ textSelection.append('tspan').attr('x', field.horizontalAlign === exports.HorizontalAlign.Center ? field.width / 2 : field.horizontalAlign === exports.HorizontalAlign.Right ? field.width : 0).attr('y', field.verticalAlign === exports.VerticalAlign.Center ? (i + 0.5 - lines.length / 2) * field.fontSize + field.height / 2 : field.verticalAlign === exports.VerticalAlign.Bottom ? field.height - (lines.length - i - 1) * field.fontSize : i * field.fontSize).text(lines[i]);
9439
+ }
9403
9440
  }
9404
9441
  /**
9405
9442
  * Method to call to start the moving of a node triggered by a user drag event.
@@ -9431,6 +9468,7 @@ class DiagramCanvas {
9431
9468
  }
9432
9469
  this.userHighlight.clear();
9433
9470
  this.dragging = true;
9471
+ this.diagramEvent$.next(new DiagramDraggingNodeEvent(d));
9434
9472
  }
9435
9473
  }
9436
9474
  /**
@@ -10456,6 +10494,7 @@ exports.DiagramContextMenu = DiagramContextMenu;
10456
10494
  exports.DiagramDecorator = DiagramDecorator;
10457
10495
  exports.DiagramDecoratorSet = DiagramDecoratorSet;
10458
10496
  exports.DiagramDoubleClickEvent = DiagramDoubleClickEvent;
10497
+ exports.DiagramDraggingNodeEvent = DiagramDraggingNodeEvent;
10459
10498
  exports.DiagramElement = DiagramElement;
10460
10499
  exports.DiagramElementSet = DiagramElementSet;
10461
10500
  exports.DiagramEntitySet = DiagramEntitySet;
package/index.esm.js CHANGED
@@ -1170,6 +1170,9 @@ const numberOfRows = s => {
1170
1170
  * @private
1171
1171
  */
1172
1172
  const clone = o => {
1173
+ if (o === null) {
1174
+ return o;
1175
+ }
1173
1176
  if (typeof o !== 'object') {
1174
1177
  return o;
1175
1178
  }
@@ -2680,6 +2683,7 @@ const DIAGRAM_FIELD_DEFAULTS = {
2680
2683
  horizontalAlign: HorizontalAlign.Center,
2681
2684
  verticalAlign: VerticalAlign.Center,
2682
2685
  orientation: Side.Top,
2686
+ multiline: false,
2683
2687
  fit: false,
2684
2688
  shrink: true
2685
2689
  };
@@ -2709,7 +2713,7 @@ class DiagramField extends DiagramElement {
2709
2713
  (_a = this.model.canvas) === null || _a === void 0 ? void 0 : _a.fitFieldRootInView(this.id, this.shrink);
2710
2714
  }
2711
2715
  }
2712
- constructor(model, rootElement, coords, width, height, fontSize, fontFamily, color, selectedColor, horizontalAlign, verticalAlign, orientation, text, editable, fit, shrink) {
2716
+ constructor(model, rootElement, coords, width, height, fontSize, fontFamily, color, selectedColor, horizontalAlign, verticalAlign, orientation, multiline, text, editable, fit, shrink) {
2713
2717
  const id = `${rootElement === null || rootElement === void 0 ? void 0 : rootElement.id}_field`;
2714
2718
  if (model.fields.get(id) !== undefined) {
2715
2719
  throw new Error('DiagramField for rootElement already exists');
@@ -2750,6 +2754,7 @@ class DiagramField extends DiagramElement {
2750
2754
  this.orientation = 0;
2751
2755
  }
2752
2756
  }
2757
+ this.multiline = multiline;
2753
2758
  this.defaultText = text;
2754
2759
  this._text = text;
2755
2760
  this.editable = editable;
@@ -2794,8 +2799,8 @@ class DiagramFieldSet extends DiagramElementSet {
2794
2799
  * Instance a new field and add it to this set. This method is normally called when instancing an element with a field and it is rarely called by itself.
2795
2800
  * @private
2796
2801
  */
2797
- new(rootElement, coords, fontSize, fontFamily, color, selectedColor, width, height, horizontalAlign, verticalAlign, orientation, text, editable, fit, shrink) {
2798
- const field = new DiagramField(this.model, rootElement, coords, width, height, fontSize, fontFamily, color, selectedColor, horizontalAlign, verticalAlign, orientation, text, editable, fit, shrink);
2802
+ new(rootElement, coords, fontSize, fontFamily, color, selectedColor, width, height, horizontalAlign, verticalAlign, orientation, multiline, text, editable, fit, shrink) {
2803
+ const field = new DiagramField(this.model, rootElement, coords, width, height, fontSize, fontFamily, color, selectedColor, horizontalAlign, verticalAlign, orientation, multiline, text, editable, fit, shrink);
2799
2804
  super.add(field);
2800
2805
  field.updateInView();
2801
2806
  // add this field to its root element
@@ -3434,7 +3439,7 @@ class DiagramSectionSet extends DiagramElementSet {
3434
3439
  default:
3435
3440
  labelCoords = port.coords;
3436
3441
  }
3437
- this.model.fields.new(port, labelCoords, labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelWidth, labelHeight, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
3442
+ this.model.fields.new(port, labelCoords, labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelWidth, labelHeight, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
3438
3443
  }
3439
3444
  }
3440
3445
  }
@@ -3442,7 +3447,7 @@ class DiagramSectionSet extends DiagramElementSet {
3442
3447
  const sectionLabel = (_k = (_j = (_h = (_g = node.type.sectionGrid) === null || _g === void 0 ? void 0 : _g.sections) === null || _h === void 0 ? void 0 : _h[indexYInNode]) === null || _j === void 0 ? void 0 : _j[indexXInNode]) === null || _k === void 0 ? void 0 : _k.label;
3443
3448
  if (sectionLabel) {
3444
3449
  const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), sectionLabel);
3445
- this.model.fields.new(section, [section.coords[0] + getLeftMargin(labelConfiguration), section.coords[1] + getTopMargin(labelConfiguration)], labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, section.width - getLeftMargin(labelConfiguration) - getRightMargin(labelConfiguration), section.height - getTopMargin(labelConfiguration) - getBottomMargin(labelConfiguration), labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
3450
+ this.model.fields.new(section, [section.coords[0] + getLeftMargin(labelConfiguration), section.coords[1] + getTopMargin(labelConfiguration)], labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, section.width - getLeftMargin(labelConfiguration) - getRightMargin(labelConfiguration), section.height - getTopMargin(labelConfiguration) - getBottomMargin(labelConfiguration), labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
3446
3451
  }
3447
3452
  return section;
3448
3453
  }
@@ -4362,14 +4367,14 @@ class DiagramNodeSet extends DiagramElementSet {
4362
4367
  default:
4363
4368
  labelCoords = port.coords;
4364
4369
  }
4365
- this.model.fields.new(port, labelCoords, labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelWidth, labelHeight, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
4370
+ this.model.fields.new(port, labelCoords, labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelWidth, labelHeight, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
4366
4371
  }
4367
4372
  }
4368
4373
  }
4369
4374
  // add node label
4370
4375
  if (nodeType.label) {
4371
4376
  const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), nodeType.label);
4372
- this.model.fields.new(node, [node.coords[0] + getLeftMargin(labelConfiguration), node.coords[1] + getTopMargin(labelConfiguration)], labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, node.width - getLeftMargin(labelConfiguration) - getRightMargin(labelConfiguration), node.height - getTopMargin(labelConfiguration) - getBottomMargin(labelConfiguration), labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
4377
+ this.model.fields.new(node, [node.coords[0] + getLeftMargin(labelConfiguration), node.coords[1] + getTopMargin(labelConfiguration)], labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, node.width - getLeftMargin(labelConfiguration) - getRightMargin(labelConfiguration), node.height - getTopMargin(labelConfiguration) - getBottomMargin(labelConfiguration), labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
4373
4378
  }
4374
4379
  // add node decorators
4375
4380
  if (nodeType.decorators.length > 0) {
@@ -4939,7 +4944,7 @@ class DagaImporter {
4939
4944
  // add node label
4940
4945
  if (newNodeType.label) {
4941
4946
  const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), newNodeType.label);
4942
- const newField = new DiagramField(model, newNode, [newNode.coords[0] + getLeftMargin(labelConfiguration), newNode.coords[1] + getTopMargin(labelConfiguration)], newNode.width - getLeftMargin(labelConfiguration) - getRightMargin(labelConfiguration), newNode.height - getTopMargin(labelConfiguration) - getBottomMargin(labelConfiguration), labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
4947
+ const newField = new DiagramField(model, newNode, [newNode.coords[0] + getLeftMargin(labelConfiguration), newNode.coords[1] + getTopMargin(labelConfiguration)], newNode.width - getLeftMargin(labelConfiguration) - getRightMargin(labelConfiguration), newNode.height - getTopMargin(labelConfiguration) - getBottomMargin(labelConfiguration), labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
4943
4948
  newField.text = node.label;
4944
4949
  newNode.label = newField;
4945
4950
  model.fields.add(newField);
@@ -4959,7 +4964,7 @@ class DagaImporter {
4959
4964
  // add section label
4960
4965
  if ((_f = (_e = (_d = (_c = newNodeType.sectionGrid) === null || _c === void 0 ? void 0 : _c.sections) === null || _d === void 0 ? void 0 : _d[section.indexYInNode]) === null || _e === void 0 ? void 0 : _e[section.indexXInNode]) === null || _f === void 0 ? void 0 : _f.label) {
4961
4966
  const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), (_k = (_j = (_h = (_g = newNodeType.sectionGrid) === null || _g === void 0 ? void 0 : _g.sections) === null || _h === void 0 ? void 0 : _h[section.indexYInNode]) === null || _j === void 0 ? void 0 : _j[section.indexXInNode]) === null || _k === void 0 ? void 0 : _k.label);
4962
- const newField = new DiagramField(model, newSection, [newSection.coords[0] + getLeftMargin(labelConfiguration), newSection.coords[1] + getTopMargin(labelConfiguration)], newSection.width - getLeftMargin(labelConfiguration) - getRightMargin(labelConfiguration), newSection.height - getTopMargin(labelConfiguration) - getBottomMargin(labelConfiguration), labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
4967
+ const newField = new DiagramField(model, newSection, [newSection.coords[0] + getLeftMargin(labelConfiguration), newSection.coords[1] + getTopMargin(labelConfiguration)], newSection.width - getLeftMargin(labelConfiguration) - getRightMargin(labelConfiguration), newSection.height - getTopMargin(labelConfiguration) - getBottomMargin(labelConfiguration), labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
4963
4968
  newField.text = section.label;
4964
4969
  newSection.label = newField;
4965
4970
  model.fields.add(newField);
@@ -4990,7 +4995,7 @@ class DagaImporter {
4990
4995
  default:
4991
4996
  labelCoords = newPort.coords;
4992
4997
  }
4993
- const newField = new DiagramField(model, newPort, labelCoords, labelConfiguration.fontSize, labelConfiguration.fontSize, labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
4998
+ const newField = new DiagramField(model, newPort, labelCoords, labelConfiguration.fontSize, labelConfiguration.fontSize, labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
4994
4999
  newField.text = port.label;
4995
5000
  newPort.label = newField;
4996
5001
  model.fields.add(newField);
@@ -5037,7 +5042,7 @@ class DagaImporter {
5037
5042
  default:
5038
5043
  labelCoords = newPort.coords;
5039
5044
  }
5040
- const newField = new DiagramField(model, newPort, labelCoords, labelConfiguration.fontSize, labelConfiguration.fontSize, labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
5045
+ const newField = new DiagramField(model, newPort, labelCoords, labelConfiguration.fontSize, labelConfiguration.fontSize, labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
5041
5046
  newField.text = port.label;
5042
5047
  newPort.label = newField;
5043
5048
  model.fields.add(newField);
@@ -6334,6 +6339,7 @@ var DiagramEvents;
6334
6339
  DiagramEvents[DiagramEvents["SecondaryClick"] = 2] = "SecondaryClick";
6335
6340
  DiagramEvents[DiagramEvents["Selection"] = 3] = "Selection";
6336
6341
  DiagramEvents[DiagramEvents["Highlight"] = 4] = "Highlight";
6342
+ DiagramEvents[DiagramEvents["DraggingNode"] = 5] = "DraggingNode";
6337
6343
  })(DiagramEvents || (DiagramEvents = {}));
6338
6344
  /**
6339
6345
  * Diagram event which consists of the user zooming or panning.
@@ -6417,6 +6423,20 @@ class DiagramHighlightedEvent extends DiagramEvent {
6417
6423
  this.target = target;
6418
6424
  }
6419
6425
  }
6426
+ /**
6427
+ * Diagram event which consists of the user dragging a diagram node.
6428
+ */
6429
+ class DiagramDraggingNodeEvent extends DiagramEvent {
6430
+ /**
6431
+ * Create a diagram dragging node event.
6432
+ *
6433
+ * @param target Diagram node which is targeted by the event.
6434
+ */
6435
+ constructor(target) {
6436
+ super(DiagramEvents.DraggingNode);
6437
+ this.target = target;
6438
+ }
6439
+ }
6420
6440
 
6421
6441
  /**
6422
6442
  * A foreign object which is inserted with arbitrary html into a diagram.
@@ -7450,29 +7470,6 @@ class DiagramUserSelection extends DiagramElementSet {
7450
7470
  }
7451
7471
  }
7452
7472
 
7453
- const degreesToRadians = theta => theta * Math.PI / 180;
7454
- /**
7455
- * Calculates the original size of the a rectangle that has been rotated by the given number of degrees resulting in a bounding box of the given size.
7456
- *
7457
- * @param width The width of a bounding box.
7458
- * @param height The height of a bounding box.
7459
- * @param orientation A rotation in degrees.
7460
- * @returns The size of the original rectangle.
7461
- */
7462
- const unrotate = (width, height, orientation) => {
7463
- // TODO: this method fails under certain edge cases
7464
- // like for example, when angle is 45 degrees so sin(theta) == cos(theta)
7465
- const theta = degreesToRadians(orientation);
7466
- const orientationSine = Math.sin(theta);
7467
- const orientationCosine = Math.cos(theta);
7468
- const oldWidth = (Math.abs(width * orientationCosine) - Math.abs(height * orientationSine)) / (orientationCosine * orientationCosine - orientationSine * orientationSine);
7469
- const oldHeight = (Math.abs(width * orientationSine) - Math.abs(height * orientationCosine)) / (orientationSine * orientationSine - orientationCosine * orientationCosine);
7470
- return [oldWidth, oldHeight];
7471
- };
7472
-
7473
- const isUserAgentSafari = userAgent => /^((?!chrome|android).)*safari/i.test(userAgent);
7474
- const isSafari = isUserAgentSafari(navigator.userAgent);
7475
-
7476
7473
  /**
7477
7474
  * Thickness of the invisible path around a connection used to make it easier to click on, in diagram units.
7478
7475
  * @private
@@ -7771,10 +7768,6 @@ class DiagramCanvas {
7771
7768
  const transformAttribute = event.transform.toString();
7772
7769
  this.selectCanvasElements().attr('transform', transformAttribute);
7773
7770
  d3.select(`#${this.backgroundPatternId}`).attr('patternTransform', transformAttribute);
7774
- if (isSafari) {
7775
- // force update fields to compensate for a rendering bug in webkit
7776
- this.updateFieldsInView();
7777
- }
7778
7771
  this.contextMenu.close();
7779
7772
  this.diagramEvent$.next(new DiagramZoomEvent([this.zoomTransform.x, this.zoomTransform.y], this.zoomTransform.k));
7780
7773
  }).on(ZoomEvents.End, () => {
@@ -8021,7 +8014,7 @@ class DiagramCanvas {
8021
8014
  this.secondaryButton = false;
8022
8015
  }));
8023
8016
  initializeLook(enterSelection);
8024
- enterSelection.filter('.resizable-x').append('line').attr('class', 'left-resizer').attr('stroke', 'transparent').attr('stroke-width', `${RESIZER_THICKNESS}px`).on(Events.MouseOver, (_event, d) => {
8017
+ enterSelection.filter('.resizable-x').append('line').attr('class', 'left-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(Events.MouseOver, (_event, d) => {
8025
8018
  if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableX() && !d.removed) {
8026
8019
  setCursorStyle(CursorStyle.EWResize);
8027
8020
  }
@@ -8057,7 +8050,7 @@ class DiagramCanvas {
8057
8050
  }
8058
8051
  setCursorStyle();
8059
8052
  }));
8060
- enterSelection.filter('.resizable-y').append('line').attr('class', 'top-resizer').attr('stroke', 'transparent').attr('stroke-width', `${RESIZER_THICKNESS}px`).on(Events.MouseOver, (_event, d) => {
8053
+ enterSelection.filter('.resizable-y').append('line').attr('class', 'top-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(Events.MouseOver, (_event, d) => {
8061
8054
  if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableY() && !d.removed) {
8062
8055
  setCursorStyle(CursorStyle.NSResize);
8063
8056
  }
@@ -8093,7 +8086,7 @@ class DiagramCanvas {
8093
8086
  }
8094
8087
  setCursorStyle();
8095
8088
  }));
8096
- enterSelection.filter('.resizable-x').append('line').attr('class', 'right-resizer').attr('stroke', 'transparent').attr('stroke-width', `${RESIZER_THICKNESS}px`).on(Events.MouseOver, (_event, d) => {
8089
+ enterSelection.filter('.resizable-x').append('line').attr('class', 'right-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(Events.MouseOver, (_event, d) => {
8097
8090
  if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableX() && !d.removed) {
8098
8091
  setCursorStyle(CursorStyle.EWResize);
8099
8092
  }
@@ -8129,7 +8122,7 @@ class DiagramCanvas {
8129
8122
  }
8130
8123
  setCursorStyle();
8131
8124
  }));
8132
- enterSelection.filter('.resizable-y').append('line').attr('class', 'bottom-resizer').attr('stroke', 'transparent').attr('stroke-width', `${RESIZER_THICKNESS}px`).on(Events.MouseOver, (_event, d) => {
8125
+ enterSelection.filter('.resizable-y').append('line').attr('class', 'bottom-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(Events.MouseOver, (_event, d) => {
8133
8126
  if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableY() && !d.removed) {
8134
8127
  setCursorStyle(CursorStyle.NSResize);
8135
8128
  }
@@ -8260,7 +8253,7 @@ class DiagramCanvas {
8260
8253
  this.secondaryButton = false;
8261
8254
  }));
8262
8255
  initializeLook(enterSelection);
8263
- enterSelection.filter('.resizable-x').append('line').attr('class', 'left-resizer').attr('stroke', 'transparent').attr('stroke-width', `${RESIZER_THICKNESS}px`).on(Events.MouseOver, (_event, d) => {
8256
+ enterSelection.filter('.resizable-x').append('line').attr('class', 'left-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(Events.MouseOver, (_event, d) => {
8264
8257
  if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableX() && !d.removed) {
8265
8258
  setCursorStyle(CursorStyle.EWResize);
8266
8259
  }
@@ -8294,7 +8287,7 @@ class DiagramCanvas {
8294
8287
  }
8295
8288
  setCursorStyle();
8296
8289
  }));
8297
- enterSelection.filter('.resizable-y').append('line').attr('class', 'top-resizer').attr('stroke', 'transparent').attr('stroke-width', `${RESIZER_THICKNESS}px`).on(Events.MouseOver, (_event, d) => {
8290
+ enterSelection.filter('.resizable-y').append('line').attr('class', 'top-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(Events.MouseOver, (_event, d) => {
8298
8291
  if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableY() && !d.removed) {
8299
8292
  setCursorStyle(CursorStyle.NSResize);
8300
8293
  }
@@ -8328,7 +8321,7 @@ class DiagramCanvas {
8328
8321
  }
8329
8322
  setCursorStyle();
8330
8323
  }));
8331
- enterSelection.filter('.resizable-x').append('line').attr('class', 'right-resizer').attr('stroke', 'transparent').attr('stroke-width', `${RESIZER_THICKNESS}px`).on(Events.MouseOver, (_event, d) => {
8324
+ enterSelection.filter('.resizable-x').append('line').attr('class', 'right-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(Events.MouseOver, (_event, d) => {
8332
8325
  if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableX() && !d.removed) {
8333
8326
  setCursorStyle(CursorStyle.EWResize);
8334
8327
  }
@@ -8362,7 +8355,7 @@ class DiagramCanvas {
8362
8355
  }
8363
8356
  setCursorStyle();
8364
8357
  }));
8365
- enterSelection.filter('.resizable-y').append('line').attr('class', 'bottom-resizer').attr('stroke', 'transparent').attr('stroke-width', `${RESIZER_THICKNESS}px`).on(Events.MouseOver, (_event, d) => {
8358
+ enterSelection.filter('.resizable-y').append('line').attr('class', 'bottom-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(Events.MouseOver, (_event, d) => {
8366
8359
  if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableY() && !d.removed) {
8367
8360
  setCursorStyle(CursorStyle.NSResize);
8368
8361
  }
@@ -8643,28 +8636,28 @@ class DiagramCanvas {
8643
8636
  mergeSelection.attr('opacity', d => d.removed ? 0.5 : 1).select('path.diagram-connection-path').attr('d', d => {
8644
8637
  var _a, _b;
8645
8638
  return getConnectionPath(d.look.shape || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.shape, d.startCoords, d.endCoords, d.startDirection, d.endDirection, d.points, d.type.defaultLook.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness, (_a = d.type.defaultStartMarkerLook) === null || _a === void 0 ? void 0 : _a.width, (_b = d.type.defaultEndMarkerLook) === null || _b === void 0 ? void 0 : _b.width);
8646
- }).attr('marker-start', d => `url(#${d.id}-start-marker)`).attr('marker-end', d => `url(#${d.id}-end-marker)`).attr('stroke', d => d.look.color || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.color).attr('stroke-width', d => `${d.look.thickness}px`).attr('stroke-dasharray', d => lineStyleDasharray(d.look.style || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.style, d.type.defaultLook.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness)).attr('fill', 'none');
8639
+ }).attr('marker-start', d => `url(#${d.id}-start-marker)`).attr('marker-end', d => `url(#${d.id}-end-marker)`).attr('stroke', d => d.look.color || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.color).attr('stroke-width', d => d.look.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness).attr('stroke-dasharray', d => lineStyleDasharray(d.look.style || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.style, d.type.defaultLook.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness)).attr('fill', 'none');
8647
8640
  mergeSelection.select('path.diagram-connection-path-box').attr('d', d => {
8648
8641
  var _a, _b;
8649
8642
  return getConnectionPath(d.look.shape || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.shape, d.startCoords, d.endCoords, d.startDirection, d.endDirection, d.points, d.type.defaultLook.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness, (_a = d.type.defaultStartMarkerLook) === null || _a === void 0 ? void 0 : _a.width, (_b = d.type.defaultEndMarkerLook) === null || _b === void 0 ? void 0 : _b.width);
8650
8643
  }).attr('stroke', 'transparent')
8651
8644
  // allow generating pointer events even when it is transparent
8652
- .attr('pointer-events', 'stroke').attr('stroke-width', d => `${(d.look.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness) + CONNECTION_PATH_BOX_THICKNESS}px`).attr('stroke-dasharray', d => lineStyleDasharray(d.look.style || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.style, d.type.defaultLook.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness)).attr('fill', 'none');
8645
+ .attr('pointer-events', 'stroke').attr('stroke-width', d => (d.look.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness) + CONNECTION_PATH_BOX_THICKNESS).attr('stroke-dasharray', d => lineStyleDasharray(d.look.style || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.style, d.type.defaultLook.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness)).attr('fill', 'none');
8653
8646
  mergeSelection.data().forEach(connection => {
8654
8647
  this.updateConnectionLabelsInView(connection);
8655
8648
  this.updateConnectionMarkersInView(connection);
8656
8649
  });
8657
8650
  }
8658
8651
  updateFieldsInView(...ids) {
8659
- let updateSelection = this.selectCanvasElements().selectAll('foreignObject.diagram-field').data(this.model.fields.filter(e => this.priorityThreshold !== undefined ? e.getPriority() >= this.priorityThreshold : true), d => d.id);
8652
+ let updateSelection = this.selectCanvasElements().selectAll('g.diagram-field').data(this.model.fields.filter(e => this.priorityThreshold !== undefined ? e.getPriority() >= this.priorityThreshold : true), d => d.id);
8660
8653
  const exitSelection = updateSelection.exit();
8661
- const enterSelection = updateSelection.enter().append('foreignObject').attr('id', d => d.id).attr('class', 'diagram-field');
8654
+ const enterSelection = updateSelection.enter().append('g').attr('id', d => d.id).attr('class', 'diagram-field');
8662
8655
  if (ids && ids.length > 0) {
8663
8656
  updateSelection = updateSelection.filter(d => ids.includes(d.id));
8664
8657
  }
8665
8658
  const mergeSelection = enterSelection.merge(updateSelection);
8666
8659
  exitSelection.remove();
8667
- enterSelection.style('box-sizing', 'border-box').on(Events.MouseOver, (_event, d) => {
8660
+ enterSelection.on(Events.MouseOver, (_event, d) => {
8668
8661
  if (!this.dragging) {
8669
8662
  this.userHighlight.focusOn(d);
8670
8663
  this.diagramEvent$.next(new DiagramHighlightedEvent(d));
@@ -8755,12 +8748,15 @@ class DiagramCanvas {
8755
8748
  }
8756
8749
  }
8757
8750
  this.secondaryButton = false;
8758
- })).append('xhtml:div').style('width', '100%').style('height', '100%').style('display', 'flex').append('xhtml:p').style('box-sizing', 'border-box').style('outline', 0).style('margin', 0).style('border', 0).style('padding', 0).style('user-select', 'none').style('font-kerning', 'none').style('white-space', 'nowrap');
8759
- mergeSelection.attr('x', 0).attr('y', 0).attr('width', d => `${d.width}px`).attr('height', d => `${d.height}px`).attr('transform', d => `translate(${d.coords[0]},${d.coords[1]})`).attr('opacity', d => d.removed ? 0.5 : 1).select('div').style('justify-content', d => d.horizontalAlign === HorizontalAlign.Center ? 'center' : d.horizontalAlign === HorizontalAlign.Right ? 'flex-end' : 'flex-start').style('align-items', d => d.verticalAlign === VerticalAlign.Center ? 'center' : d.verticalAlign === VerticalAlign.Bottom ? 'end' : 'start').select('p').style('max-width', d => d.fit ? 'default' : `${unrotate(d.width, d.height, d.orientation)[0]}px`).style('max-height', d => d.fit ? 'default' : `${unrotate(d.width, d.height, d.orientation)[1]}px`).style('overflow', d => d.fit ? 'default' : 'clip').style('text-overflow', d => d.fit ? 'default' : 'ellipsis').style('text-align', d => d.horizontalAlign === HorizontalAlign.Center ? 'center' : d.horizontalAlign === HorizontalAlign.Right ? 'end' : 'start').style('transform', d => `rotate(${d.orientation}deg)`).style('font-size', d => `${d.fontSize}px`).style('font-family', d => d.fontFamily || "'Wonder Unit Sans', sans-serif").style('font-weight', d => d.highlighted ? 600 : 400).style('color', d => d.selected ? d.selectedColor || '#000000' : d.color || '#000000').html(d => d.text.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\n/g, '<br/>'));
8760
- if (isSafari) {
8761
- const zoomFactor = this.zoomTransform.k;
8762
- mergeSelection.attr('width', d => `${d.width * zoomFactor}px`).attr('height', d => `${d.height * zoomFactor}px`).select('div').style('position', 'absolute').style('left', d => `${d.coords[0] * zoomFactor + this.zoomTransform.x}px`).style('top', d => `${d.coords[1] * zoomFactor + this.zoomTransform.y}px`).select('p').style('font-size', d => `${d.fontSize * zoomFactor}px`);
8763
- }
8751
+ }));
8752
+ enterSelection.append('text');
8753
+ enterSelection.append('rect');
8754
+ mergeSelection.attr('x', 0).attr('y', 0).attr('width', d => d.width).attr('height', d => d.height).attr('transform', d => `translate(${d.coords[0]},${d.coords[1]}) rotate(${d.orientation} ${d.width / 2} ${d.height / 2})`).attr('opacity', d => d.removed ? 0.5 : 1).select('text').attr('x', d => d.horizontalAlign === HorizontalAlign.Center ? d.width / 2 : d.horizontalAlign === HorizontalAlign.Right ? d.width : 0).attr('text-anchor', d => d.horizontalAlign === HorizontalAlign.Center ? 'middle' : d.horizontalAlign === HorizontalAlign.Right ? 'end' : 'start').attr('y', d => d.verticalAlign === VerticalAlign.Center ? d.height / 2 : d.verticalAlign === VerticalAlign.Bottom ? d.height : 0).attr('dominant-baseline', d => d.verticalAlign === VerticalAlign.Center ? 'middle' : d.verticalAlign === VerticalAlign.Bottom ? 'auto' : 'hanging').attr('font-size', d => d.fontSize).attr('font-family', d => d.fontFamily || "'Wonder Unit Sans', sans-serif").attr('font-weight', d => d.highlighted ? 600 : 400).attr('fill', d => d.selected ? d.selectedColor || '#000000' : d.color || '#000000').each(d => {
8755
+ this.setFieldTextAndWrap(d);
8756
+ });
8757
+ mergeSelection
8758
+ // add a transparent rectangle to capture pointer events on the text
8759
+ .select('rect').attr('x', 0).attr('y', 0).attr('width', d => d.width).attr('height', d => d.height).attr('fill', 'transparent');
8764
8760
  }
8765
8761
  updateObjectsInView(...ids) {
8766
8762
  let updateSelection = this.selectCanvasElements().selectAll('g.diagram-object').data(this.model.objects.filter(e => this.priorityThreshold !== undefined ? e.getPriority() >= this.priorityThreshold : true), d => d.id);
@@ -8770,7 +8766,7 @@ class DiagramCanvas {
8770
8766
  updateSelection = updateSelection.filter(d => ids.includes(d.id));
8771
8767
  }
8772
8768
  const mergeSelection = enterSelection.merge(updateSelection);
8773
- mergeSelection.attr('width', d => `${d.width}px`).attr('height', d => `${d.height}px`).attr('transform', d => `translate(${d.coords[0]},${d.coords[1]})`).html(d => d.html);
8769
+ mergeSelection.attr('width', d => d.width).attr('height', d => d.height).attr('transform', d => `translate(${d.coords[0]},${d.coords[1]})`).html(d => d.html);
8774
8770
  exitSelection.remove();
8775
8771
  enterSelection.on(Events.ContextMenu, (event, d) => {
8776
8772
  if (this.dragging) {
@@ -8813,7 +8809,7 @@ class DiagramCanvas {
8813
8809
  updateSelection = updateSelection.filter(d => ids.includes(d.id));
8814
8810
  }
8815
8811
  const mergeSelection = enterSelection.merge(updateSelection);
8816
- mergeSelection.attr('width', d => `${d.width}px`).attr('height', d => `${d.height}px`).attr('transform', d => `translate(${d.coords[0]},${d.coords[1]})`).html(d => d.html);
8812
+ mergeSelection.attr('width', d => d.width).attr('height', d => d.height).attr('transform', d => `translate(${d.coords[0]},${d.coords[1]})`).html(d => d.html);
8817
8813
  exitSelection.remove();
8818
8814
  enterSelection.on(Events.MouseOver, (_event, d) => {
8819
8815
  if (!this.dragging) {
@@ -8992,10 +8988,10 @@ class DiagramCanvas {
8992
8988
  pathStartLabelPoint = pathNode.getPointAtLength(getLeftMargin(labelConfiguration) + boundingWidth / 2);
8993
8989
  break;
8994
8990
  case Side.Top:
8995
- pathStartLabelPoint = pathNode.getPointAtLength(getBottomMargin(labelConfiguration) + boundingWidth / 2);
8991
+ pathStartLabelPoint = pathNode.getPointAtLength(getBottomMargin(labelConfiguration) + boundingHeight / 2);
8996
8992
  break;
8997
8993
  case Side.Bottom:
8998
- pathStartLabelPoint = pathNode.getPointAtLength(getTopMargin(labelConfiguration) + boundingWidth / 2);
8994
+ pathStartLabelPoint = pathNode.getPointAtLength(getTopMargin(labelConfiguration) + boundingHeight / 2);
8999
8995
  break;
9000
8996
  default:
9001
8997
  pathStartLabelPoint = pathNode.getPointAtLength(Math.max(getLeftMargin(labelConfiguration) + boundingWidth / 2, getRightMargin(labelConfiguration) + boundingWidth / 2, getTopMargin(labelConfiguration) + boundingHeight / 2, getBottomMargin(labelConfiguration) + boundingHeight / 2));
@@ -9030,10 +9026,10 @@ class DiagramCanvas {
9030
9026
  pathEndLabelPoint = pathNode.getPointAtLength(pathLength - (getLeftMargin(labelConfiguration) + boundingWidth / 2));
9031
9027
  break;
9032
9028
  case Side.Top:
9033
- pathEndLabelPoint = pathNode.getPointAtLength(pathLength - (getBottomMargin(labelConfiguration) + boundingWidth / 2));
9029
+ pathEndLabelPoint = pathNode.getPointAtLength(pathLength - (getBottomMargin(labelConfiguration) + boundingHeight / 2));
9034
9030
  break;
9035
9031
  case Side.Bottom:
9036
- pathEndLabelPoint = pathNode.getPointAtLength(pathLength - (getTopMargin(labelConfiguration) + boundingWidth / 2));
9032
+ pathEndLabelPoint = pathNode.getPointAtLength(pathLength - (getTopMargin(labelConfiguration) + boundingHeight / 2));
9037
9033
  break;
9038
9034
  default:
9039
9035
  pathEndLabelPoint = pathNode.getPointAtLength(pathLength - Math.max(getLeftMargin(labelConfiguration) + boundingWidth / 2, getRightMargin(labelConfiguration) + boundingWidth / 2, getTopMargin(labelConfiguration) + boundingHeight / 2, getBottomMargin(labelConfiguration) + boundingHeight / 2));
@@ -9292,7 +9288,7 @@ class DiagramCanvas {
9292
9288
  openTextInput(id) {
9293
9289
  const field = this.model.fields.get(id);
9294
9290
  if (field) {
9295
- this.createInputField(field.text, field.coords, field.width, field.height, field.fontSize, field.fontFamily || DIAGRAM_FIELD_DEFAULTS.fontFamily, field.orientation, () => {
9291
+ this.createInputField(field.text, field.coords, field.width, field.height, field.fontSize, field.fontFamily || DIAGRAM_FIELD_DEFAULTS.fontFamily, field.orientation, field.multiline, () => {
9296
9292
  // (_text)
9297
9293
  /*
9298
9294
  Empty for now
@@ -9310,7 +9306,7 @@ class DiagramCanvas {
9310
9306
  });
9311
9307
  }
9312
9308
  }
9313
- createInputField(text, coords, width, height, fontSize, fontFamily, orientation, changeCallback, finishCallback) {
9309
+ createInputField(text, coords, width, height, fontSize, fontFamily, orientation, multiline, changeCallback, finishCallback) {
9314
9310
  // if we have a text input open, close it before creating a new one
9315
9311
  this.removeInputField();
9316
9312
  const inputFieldContainer = this.selectCanvasElements().append('foreignObject').attr('x', `${coords[0]}px`).attr('y', `${coords[1]}px`).attr('width', `${width}px`).attr('height', `${height}px`).style('box-sizing', 'border-box').style('border', '1px solid');
@@ -9320,16 +9316,16 @@ class DiagramCanvas {
9320
9316
  let inputFieldHeight;
9321
9317
  inputField.text(text).style('box-sizing', 'border-box').style('width', `${width}px`).style('height', `${height}px`).style('font-size', `${fontSize}px`).style('font-family', fontFamily).style('resize', 'none').style('outline', 0).style('border', 0).style('margin', 0).style('padding', 0).on(Events.KeyDown, event => {
9322
9318
  event.stopPropagation();
9323
- }).on(Events.KeyUp, event => {
9324
- event.stopPropagation();
9325
- if (event.key === Keys.Escape) {
9326
- const value = inputField.property('value');
9319
+ if (event.key === Keys.Escape || event.key === Keys.Enter && !multiline) {
9320
+ const value = inputField.property('value') || '';
9327
9321
  this.removeInputField();
9328
9322
  if (finishCallback) {
9329
9323
  finishCallback(value);
9330
9324
  }
9331
9325
  }
9332
- }).on(Events.Input, () => {
9326
+ }).on(Events.KeyUp, event => {
9327
+ event.stopPropagation();
9328
+ }).on(Events.Input, event => {
9333
9329
  const value = inputField.property('value');
9334
9330
  inputField.attr('cols', numberOfColumns(value) + 1);
9335
9331
  inputField.attr('rows', numberOfRows(value) + 1);
@@ -9372,13 +9368,54 @@ class DiagramCanvas {
9372
9368
  }
9373
9369
  minimumSizeOfField(field) {
9374
9370
  var _a, _b;
9375
- const pNode = (_b = (_a = field.select()) === null || _a === void 0 ? void 0 : _a.select('p')) === null || _b === void 0 ? void 0 : _b.node();
9376
- if (!pNode) {
9371
+ const textNode = (_b = (_a = field.select()) === null || _a === void 0 ? void 0 : _a.select('text')) === null || _b === void 0 ? void 0 : _b.node();
9372
+ if (!textNode) {
9377
9373
  // happens when a field has been created but not updated in view yet
9378
9374
  return [0, 0];
9379
9375
  }
9380
- const pBoundingBox = pNode.getBoundingClientRect();
9381
- return [pBoundingBox.width / this.zoomTransform.k, pBoundingBox.height / this.zoomTransform.k];
9376
+ const textBoundingBox = textNode.getBoundingClientRect();
9377
+ return [textBoundingBox.width / this.zoomTransform.k, textBoundingBox.height / this.zoomTransform.k];
9378
+ }
9379
+ setFieldTextAndWrap(field) {
9380
+ var _a, _b, _c, _d;
9381
+ const textSelection = (_a = field.select()) === null || _a === void 0 ? void 0 : _a.select('text');
9382
+ const textNode = textSelection === null || textSelection === void 0 ? void 0 : textSelection.node();
9383
+ if (textSelection && textNode) {
9384
+ this.setFieldText(field, textSelection, field.text);
9385
+ } else {
9386
+ // can happen if a field has been created but not updated in view yet
9387
+ // not sure if this still happens but should check just in case
9388
+ return;
9389
+ }
9390
+ if (field.fit) {
9391
+ // no need to wrap
9392
+ return;
9393
+ }
9394
+ let minimumSize = this.minimumSizeOfField(field);
9395
+ while (minimumSize[0] > field.width || minimumSize[1] > field.height) {
9396
+ const textString = ((_d = (_c = (_b = textSelection === null || textSelection === void 0 ? void 0 : textSelection.html()) === null || _b === void 0 ? void 0 : _b.replace(/<\/tspan>/g, '\n')) === null || _c === void 0 ? void 0 : _c.replace(/<tspan[^>]*>/g, '')) === null || _d === void 0 ? void 0 : _d.slice(0, -1)) || '';
9397
+ let newTextString = '...';
9398
+ if (textString.endsWith('...')) {
9399
+ newTextString = textString.slice(0, -4) + '...';
9400
+ } else {
9401
+ newTextString = textString.slice(0, -1) + '...';
9402
+ }
9403
+ if (textSelection) {
9404
+ this.setFieldText(field, textSelection, newTextString);
9405
+ }
9406
+ if (newTextString === '...') {
9407
+ // if no more characters can be removed and the new text is a bare ellipsis, stop the execution
9408
+ return;
9409
+ }
9410
+ minimumSize = this.minimumSizeOfField(field);
9411
+ }
9412
+ }
9413
+ setFieldText(field, textSelection, text) {
9414
+ const lines = text.split('\n');
9415
+ textSelection.html('');
9416
+ for (let i = 0; i < lines.length; ++i) {
9417
+ textSelection.append('tspan').attr('x', field.horizontalAlign === HorizontalAlign.Center ? field.width / 2 : field.horizontalAlign === HorizontalAlign.Right ? field.width : 0).attr('y', field.verticalAlign === VerticalAlign.Center ? (i + 0.5 - lines.length / 2) * field.fontSize + field.height / 2 : field.verticalAlign === VerticalAlign.Bottom ? field.height - (lines.length - i - 1) * field.fontSize : i * field.fontSize).text(lines[i]);
9418
+ }
9382
9419
  }
9383
9420
  /**
9384
9421
  * Method to call to start the moving of a node triggered by a user drag event.
@@ -9410,6 +9447,7 @@ class DiagramCanvas {
9410
9447
  }
9411
9448
  this.userHighlight.clear();
9412
9449
  this.dragging = true;
9450
+ this.diagramEvent$.next(new DiagramDraggingNodeEvent(d));
9413
9451
  }
9414
9452
  }
9415
9453
  /**
@@ -10415,4 +10453,4 @@ const getLocationsOfNodes = model => {
10415
10453
  return locations;
10416
10454
  };
10417
10455
 
10418
- export { ACTION_STACK_SIZE, ActionStack, AddConnectionAction, AddNodeAction, AdjacencyLayout, ApplyLayoutAction, BreadthAdjacencyLayout, BreadthLayout, ClosedShape, CollabClient, Corner, CursorStyle, DIAGRAM_FIELD_DEFAULTS, DagaExporter, DagaImporter, DiagramActionMethod, DiagramActions, DiagramCanvas, DiagramConnection, DiagramConnectionSet, DiagramConnectionType, DiagramContextMenu, DiagramDecorator, DiagramDecoratorSet, DiagramDoubleClickEvent, DiagramElement, DiagramElementSet, DiagramEntitySet, DiagramEvent, DiagramEvents, DiagramField, DiagramFieldSet, DiagramHighlightedEvent, DiagramModel, DiagramNode, DiagramNodeSet, DiagramNodeType, DiagramObject, DiagramObjectSet, DiagramPort, DiagramPortSet, DiagramPortType, DiagramSecondaryClickEvent, DiagramSection, DiagramSectionSet, DiagramSelectionEvent, DiagramUserHighlight, DiagramUserSelection, DiagramZoomEvent, DragEvents, EditFieldAction, Events, ForceLayout, HorizontalAlign, HorizontalLayout, Keys, LineShape, LineStyle, MoveAction, PasteAction, PriorityLayout, Property, PropertySet, RemoveAction, ResizableMode, SetGeometryAction, SetParentAction, Side, TreeLayout, Type, UpdateValuesAction, ValueSet, VerticalAlign, VerticalLayout, ZoomEvents, addIfNotExists, diff, equals, filterByOnlyAncestors, filterByOnlyDescendants, generalClosedPath, getBottomMargin, getBottomPadding$1 as getBottomPadding, getLeftMargin, getLeftPadding$1 as getLeftPadding, getLocationsOfNodes, getRightMargin, getRightPadding$1 as getRightPadding, getTopMargin, getTopPadding$1 as getTopPadding, isObject, layouts, linePath, lineStyleDasharray, removeIfExists, setCursorStyle };
10456
+ export { ACTION_STACK_SIZE, ActionStack, AddConnectionAction, AddNodeAction, AdjacencyLayout, ApplyLayoutAction, BreadthAdjacencyLayout, BreadthLayout, ClosedShape, CollabClient, Corner, CursorStyle, DIAGRAM_FIELD_DEFAULTS, DagaExporter, DagaImporter, DiagramActionMethod, DiagramActions, DiagramCanvas, DiagramConnection, DiagramConnectionSet, DiagramConnectionType, DiagramContextMenu, DiagramDecorator, DiagramDecoratorSet, DiagramDoubleClickEvent, DiagramDraggingNodeEvent, DiagramElement, DiagramElementSet, DiagramEntitySet, DiagramEvent, DiagramEvents, DiagramField, DiagramFieldSet, DiagramHighlightedEvent, DiagramModel, DiagramNode, DiagramNodeSet, DiagramNodeType, DiagramObject, DiagramObjectSet, DiagramPort, DiagramPortSet, DiagramPortType, DiagramSecondaryClickEvent, DiagramSection, DiagramSectionSet, DiagramSelectionEvent, DiagramUserHighlight, DiagramUserSelection, DiagramZoomEvent, DragEvents, EditFieldAction, Events, ForceLayout, HorizontalAlign, HorizontalLayout, Keys, LineShape, LineStyle, MoveAction, PasteAction, PriorityLayout, Property, PropertySet, RemoveAction, ResizableMode, SetGeometryAction, SetParentAction, Side, TreeLayout, Type, UpdateValuesAction, ValueSet, VerticalAlign, VerticalLayout, ZoomEvents, addIfNotExists, diff, equals, filterByOnlyAncestors, filterByOnlyDescendants, generalClosedPath, getBottomMargin, getBottomPadding$1 as getBottomPadding, getLeftMargin, getLeftPadding$1 as getLeftPadding, getLocationsOfNodes, getRightMargin, getRightPadding$1 as getRightPadding, getTopMargin, getTopPadding$1 as getTopPadding, isObject, layouts, linePath, lineStyleDasharray, removeIfExists, setCursorStyle };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metadev/daga",
3
- "version": "4.2.17",
3
+ "version": "4.2.19",
4
4
  "dependencies": {},
5
5
  "peerDependencies": {
6
6
  "d3": "^7.9.0",
package/src/index.d.ts CHANGED
@@ -19,7 +19,7 @@ export type { DiagramModelExporter } from './lib/diagram/converters/diagram-mode
19
19
  export type { DiagramModelImporter } from './lib/diagram/converters/diagram-model-importer';
20
20
  export { ActionStack, AddConnectionAction, AddNodeAction, ApplyLayoutAction, DiagramActionMethod, DiagramActions, EditFieldAction, MoveAction, PasteAction, RemoveAction, SetGeometryAction, SetParentAction, UpdateValuesAction } from './lib/diagram/diagram-action';
21
21
  export type { DiagramAction } from './lib/diagram/diagram-action';
22
- export { DiagramDoubleClickEvent, DiagramEvent, DiagramEvents, DiagramHighlightedEvent, DiagramSecondaryClickEvent, DiagramSelectionEvent, DiagramZoomEvent } from './lib/diagram/diagram-event';
22
+ export { DiagramDoubleClickEvent, DiagramEvent, DiagramEvents, DiagramHighlightedEvent, DiagramDraggingNodeEvent, DiagramSecondaryClickEvent, DiagramSelectionEvent, DiagramZoomEvent } from './lib/diagram/diagram-event';
23
23
  export { AdjacencyLayout } from './lib/diagram/layout/adjacency-layout';
24
24
  export { BreadthAdjacencyLayout } from './lib/diagram/layout/breadth-adjacency-layout';
25
25
  export { BreadthLayout } from './lib/diagram/layout/breadth-layout';
@@ -142,6 +142,8 @@ export declare class DiagramCanvas implements Canvas {
142
142
  private createInputField;
143
143
  private removeInputField;
144
144
  private minimumSizeOfField;
145
+ private setFieldTextAndWrap;
146
+ private setFieldText;
145
147
  /**
146
148
  * Method to call to start the moving of a node triggered by a user drag event.
147
149
  */
@@ -386,6 +386,11 @@ export interface FieldConfig {
386
386
  * @default 'top'
387
387
  */
388
388
  orientation?: Side | number;
389
+ /**
390
+ * Whether this field can have multiple lines.
391
+ * @default false
392
+ */
393
+ multiline?: boolean;
389
394
  /**
390
395
  * Whether this field and its root element should be resized automatically if the size of the text increases.
391
396
  * Setting this to true should also entail setting reasonable `minWidth` and `minHeight` values for the configuration of any nodes or sections that contain this field.
@@ -1,5 +1,6 @@
1
1
  import { Point } from '../util/canvas-util';
2
2
  import { DiagramElement } from './model/diagram-element';
3
+ import { DiagramNode } from './model/diagram-node';
3
4
  /**
4
5
  * Represents an action taken by the user on the diagram which doesn't have an impact on the diagram's model.
5
6
  * Contrast with {@link DiagramAction} which does have an impact on the diagram's model.
@@ -20,7 +21,8 @@ export declare enum DiagramEvents {
20
21
  DoubleClick = 1,
21
22
  SecondaryClick = 2,
22
23
  Selection = 3,
23
- Highlight = 4
24
+ Highlight = 4,
25
+ DraggingNode = 5
24
26
  }
25
27
  /**
26
28
  * Diagram event which consists of the user zooming or panning.
@@ -94,3 +96,15 @@ export declare class DiagramHighlightedEvent extends DiagramEvent {
94
96
  */
95
97
  constructor(target: DiagramElement | null);
96
98
  }
99
+ /**
100
+ * Diagram event which consists of the user dragging a diagram node.
101
+ */
102
+ export declare class DiagramDraggingNodeEvent extends DiagramEvent {
103
+ target: DiagramNode;
104
+ /**
105
+ * Create a diagram dragging node event.
106
+ *
107
+ * @param target Diagram node which is targeted by the event.
108
+ */
109
+ constructor(target: DiagramNode);
110
+ }
@@ -21,6 +21,7 @@ export declare const DIAGRAM_FIELD_DEFAULTS: {
21
21
  horizontalAlign: HorizontalAlign;
22
22
  verticalAlign: VerticalAlign;
23
23
  orientation: Side;
24
+ multiline: boolean;
24
25
  fit: boolean;
25
26
  shrink: boolean;
26
27
  };
@@ -90,6 +91,11 @@ export declare class DiagramField extends DiagramElement {
90
91
  * @public
91
92
  */
92
93
  orientation: number;
94
+ /**
95
+ * Whether this field can have multiple lines.
96
+ * @public
97
+ */
98
+ multiline: boolean;
93
99
  private _text;
94
100
  /**
95
101
  * Default text that this field's text resets to when empty.
@@ -122,7 +128,7 @@ export declare class DiagramField extends DiagramElement {
122
128
  * @public
123
129
  */
124
130
  shrink: boolean;
125
- constructor(model: DiagramModel, rootElement: (LabeledElement & DiagramElement) | undefined, coords: Point, width: number, height: number, fontSize: number, fontFamily: string | null, color: string, selectedColor: string, horizontalAlign: HorizontalAlign, verticalAlign: VerticalAlign, orientation: Side | number, text: string, editable: boolean, fit: boolean, shrink: boolean);
131
+ constructor(model: DiagramModel, rootElement: (LabeledElement & DiagramElement) | undefined, coords: Point, width: number, height: number, fontSize: number, fontFamily: string | null, color: string, selectedColor: string, horizontalAlign: HorizontalAlign, verticalAlign: VerticalAlign, orientation: Side | number, multiline: boolean, text: string, editable: boolean, fit: boolean, shrink: boolean);
126
132
  get removed(): boolean;
127
133
  updateInView(): void;
128
134
  raise(): void;
@@ -145,7 +151,7 @@ export declare class DiagramFieldSet extends DiagramElementSet<DiagramField> {
145
151
  * Instance a new field and add it to this set. This method is normally called when instancing an element with a field and it is rarely called by itself.
146
152
  * @private
147
153
  */
148
- new(rootElement: (LabeledElement & DiagramElement) | undefined, coords: Point, fontSize: number, fontFamily: string | null, color: string, selectedColor: string, width: number, height: number, horizontalAlign: HorizontalAlign, verticalAlign: VerticalAlign, orientation: Side | number, text: string, editable: boolean, fit: boolean, shrink: boolean): DiagramField;
154
+ new(rootElement: (LabeledElement & DiagramElement) | undefined, coords: Point, fontSize: number, fontFamily: string | null, color: string, selectedColor: string, width: number, height: number, horizontalAlign: HorizontalAlign, verticalAlign: VerticalAlign, orientation: Side | number, multiline: boolean, text: string, editable: boolean, fit: boolean, shrink: boolean): DiagramField;
149
155
  remove(id: string): void;
150
156
  }
151
157
  export declare const getBottomMargin: (config?: FieldConfig | null) => number;
@@ -9,12 +9,3 @@ export declare const radiansToDegrees: (theta: number) => number;
9
9
  * @returns The size of the bounding box.
10
10
  */
11
11
  export declare const rotate: (width: number, height: number, orientation: number) => [number, number];
12
- /**
13
- * Calculates the original size of the a rectangle that has been rotated by the given number of degrees resulting in a bounding box of the given size.
14
- *
15
- * @param width The width of a bounding box.
16
- * @param height The height of a bounding box.
17
- * @param orientation A rotation in degrees.
18
- * @returns The size of the original rectangle.
19
- */
20
- export declare const unrotate: (width: number, height: number, orientation: number) => [number, number];