@metadev/daga 4.2.16 → 4.2.18

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,7 +6,13 @@ List of releases and changes.
6
6
 
7
7
  ## Next release Joyeuse
8
8
 
9
- ## v. 4.2.16
9
+ ## v. 4.2.18
10
+
11
+ - Remove usage of `<foreignObject>` elements for diagram fields [#375](https://github.com/metadevpro/daga/pull/375)
12
+ - 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)
13
+ - 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)
14
+
15
+ ## v. 4.2.17
10
16
 
11
17
  - Fix bug where the `DagaImporter` fails to create a node's label if it's blank [#373](https://github.com/metadevpro/daga/pull/373)
12
18
  - Add `openTextInput` method to `Canvas` to enable opening a text box editor for a text via API [#374](https://github.com/metadevpro/daga/pull/374)
package/index.cjs.js CHANGED
@@ -2701,6 +2701,7 @@ const DIAGRAM_FIELD_DEFAULTS = {
2701
2701
  horizontalAlign: exports.HorizontalAlign.Center,
2702
2702
  verticalAlign: exports.VerticalAlign.Center,
2703
2703
  orientation: exports.Side.Top,
2704
+ multiline: false,
2704
2705
  fit: false,
2705
2706
  shrink: true
2706
2707
  };
@@ -2730,7 +2731,7 @@ class DiagramField extends DiagramElement {
2730
2731
  (_a = this.model.canvas) === null || _a === void 0 ? void 0 : _a.fitFieldRootInView(this.id, this.shrink);
2731
2732
  }
2732
2733
  }
2733
- constructor(model, rootElement, coords, width, height, fontSize, fontFamily, color, selectedColor, horizontalAlign, verticalAlign, orientation, text, editable, fit, shrink) {
2734
+ constructor(model, rootElement, coords, width, height, fontSize, fontFamily, color, selectedColor, horizontalAlign, verticalAlign, orientation, multiline, text, editable, fit, shrink) {
2734
2735
  const id = `${rootElement === null || rootElement === void 0 ? void 0 : rootElement.id}_field`;
2735
2736
  if (model.fields.get(id) !== undefined) {
2736
2737
  throw new Error('DiagramField for rootElement already exists');
@@ -2771,6 +2772,7 @@ class DiagramField extends DiagramElement {
2771
2772
  this.orientation = 0;
2772
2773
  }
2773
2774
  }
2775
+ this.multiline = multiline;
2774
2776
  this.defaultText = text;
2775
2777
  this._text = text;
2776
2778
  this.editable = editable;
@@ -2815,8 +2817,8 @@ class DiagramFieldSet extends DiagramElementSet {
2815
2817
  * 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
2818
  * @private
2817
2819
  */
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);
2820
+ new(rootElement, coords, fontSize, fontFamily, color, selectedColor, width, height, horizontalAlign, verticalAlign, orientation, multiline, text, editable, fit, shrink) {
2821
+ const field = new DiagramField(this.model, rootElement, coords, width, height, fontSize, fontFamily, color, selectedColor, horizontalAlign, verticalAlign, orientation, multiline, text, editable, fit, shrink);
2820
2822
  super.add(field);
2821
2823
  field.updateInView();
2822
2824
  // add this field to its root element
@@ -3455,7 +3457,7 @@ class DiagramSectionSet extends DiagramElementSet {
3455
3457
  default:
3456
3458
  labelCoords = port.coords;
3457
3459
  }
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);
3460
+ 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
3461
  }
3460
3462
  }
3461
3463
  }
@@ -3463,7 +3465,7 @@ class DiagramSectionSet extends DiagramElementSet {
3463
3465
  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
3466
  if (sectionLabel) {
3465
3467
  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);
3468
+ 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
3469
  }
3468
3470
  return section;
3469
3471
  }
@@ -4383,14 +4385,14 @@ class DiagramNodeSet extends DiagramElementSet {
4383
4385
  default:
4384
4386
  labelCoords = port.coords;
4385
4387
  }
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);
4388
+ 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
4389
  }
4388
4390
  }
4389
4391
  }
4390
4392
  // add node label
4391
4393
  if (nodeType.label) {
4392
4394
  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);
4395
+ 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
4396
  }
4395
4397
  // add node decorators
4396
4398
  if (nodeType.decorators.length > 0) {
@@ -4960,7 +4962,7 @@ class DagaImporter {
4960
4962
  // add node label
4961
4963
  if (newNodeType.label) {
4962
4964
  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);
4965
+ 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
4966
  newField.text = node.label;
4965
4967
  newNode.label = newField;
4966
4968
  model.fields.add(newField);
@@ -4980,7 +4982,7 @@ class DagaImporter {
4980
4982
  // add section label
4981
4983
  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
4984
  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);
4985
+ 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
4986
  newField.text = section.label;
4985
4987
  newSection.label = newField;
4986
4988
  model.fields.add(newField);
@@ -5011,7 +5013,7 @@ class DagaImporter {
5011
5013
  default:
5012
5014
  labelCoords = newPort.coords;
5013
5015
  }
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);
5016
+ 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
5017
  newField.text = port.label;
5016
5018
  newPort.label = newField;
5017
5019
  model.fields.add(newField);
@@ -5058,7 +5060,7 @@ class DagaImporter {
5058
5060
  default:
5059
5061
  labelCoords = newPort.coords;
5060
5062
  }
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);
5063
+ 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
5064
  newField.text = port.label;
5063
5065
  newPort.label = newField;
5064
5066
  model.fields.add(newField);
@@ -6355,6 +6357,7 @@ exports.DiagramEvents = void 0;
6355
6357
  DiagramEvents[DiagramEvents["SecondaryClick"] = 2] = "SecondaryClick";
6356
6358
  DiagramEvents[DiagramEvents["Selection"] = 3] = "Selection";
6357
6359
  DiagramEvents[DiagramEvents["Highlight"] = 4] = "Highlight";
6360
+ DiagramEvents[DiagramEvents["DraggingNode"] = 5] = "DraggingNode";
6358
6361
  })(exports.DiagramEvents || (exports.DiagramEvents = {}));
6359
6362
  /**
6360
6363
  * Diagram event which consists of the user zooming or panning.
@@ -6438,6 +6441,20 @@ class DiagramHighlightedEvent extends DiagramEvent {
6438
6441
  this.target = target;
6439
6442
  }
6440
6443
  }
6444
+ /**
6445
+ * Diagram event which consists of the user dragging a diagram node.
6446
+ */
6447
+ class DiagramDraggingNodeEvent extends DiagramEvent {
6448
+ /**
6449
+ * Create a diagram dragging node event.
6450
+ *
6451
+ * @param target Diagram node which is targeted by the event.
6452
+ */
6453
+ constructor(target) {
6454
+ super(exports.DiagramEvents.DraggingNode);
6455
+ this.target = target;
6456
+ }
6457
+ }
6441
6458
 
6442
6459
  /**
6443
6460
  * A foreign object which is inserted with arbitrary html into a diagram.
@@ -7471,29 +7488,6 @@ class DiagramUserSelection extends DiagramElementSet {
7471
7488
  }
7472
7489
  }
7473
7490
 
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
7491
  /**
7498
7492
  * Thickness of the invisible path around a connection used to make it easier to click on, in diagram units.
7499
7493
  * @private
@@ -7792,10 +7786,6 @@ class DiagramCanvas {
7792
7786
  const transformAttribute = event.transform.toString();
7793
7787
  this.selectCanvasElements().attr('transform', transformAttribute);
7794
7788
  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
7789
  this.contextMenu.close();
7800
7790
  this.diagramEvent$.next(new DiagramZoomEvent([this.zoomTransform.x, this.zoomTransform.y], this.zoomTransform.k));
7801
7791
  }).on(exports.ZoomEvents.End, () => {
@@ -8042,7 +8032,7 @@ class DiagramCanvas {
8042
8032
  this.secondaryButton = false;
8043
8033
  }));
8044
8034
  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) => {
8035
+ 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
8036
  if (this.canUserPerformAction(exports.DiagramActions.StretchNode) && d.getResizableX() && !d.removed) {
8047
8037
  setCursorStyle(exports.CursorStyle.EWResize);
8048
8038
  }
@@ -8078,7 +8068,7 @@ class DiagramCanvas {
8078
8068
  }
8079
8069
  setCursorStyle();
8080
8070
  }));
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) => {
8071
+ 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
8072
  if (this.canUserPerformAction(exports.DiagramActions.StretchNode) && d.getResizableY() && !d.removed) {
8083
8073
  setCursorStyle(exports.CursorStyle.NSResize);
8084
8074
  }
@@ -8114,7 +8104,7 @@ class DiagramCanvas {
8114
8104
  }
8115
8105
  setCursorStyle();
8116
8106
  }));
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) => {
8107
+ 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
8108
  if (this.canUserPerformAction(exports.DiagramActions.StretchNode) && d.getResizableX() && !d.removed) {
8119
8109
  setCursorStyle(exports.CursorStyle.EWResize);
8120
8110
  }
@@ -8150,7 +8140,7 @@ class DiagramCanvas {
8150
8140
  }
8151
8141
  setCursorStyle();
8152
8142
  }));
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) => {
8143
+ 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
8144
  if (this.canUserPerformAction(exports.DiagramActions.StretchNode) && d.getResizableY() && !d.removed) {
8155
8145
  setCursorStyle(exports.CursorStyle.NSResize);
8156
8146
  }
@@ -8281,7 +8271,7 @@ class DiagramCanvas {
8281
8271
  this.secondaryButton = false;
8282
8272
  }));
8283
8273
  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) => {
8274
+ 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
8275
  if (this.canUserPerformAction(exports.DiagramActions.StretchSection) && d.getResizableX() && !d.removed) {
8286
8276
  setCursorStyle(exports.CursorStyle.EWResize);
8287
8277
  }
@@ -8315,7 +8305,7 @@ class DiagramCanvas {
8315
8305
  }
8316
8306
  setCursorStyle();
8317
8307
  }));
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) => {
8308
+ 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
8309
  if (this.canUserPerformAction(exports.DiagramActions.StretchSection) && d.getResizableY() && !d.removed) {
8320
8310
  setCursorStyle(exports.CursorStyle.NSResize);
8321
8311
  }
@@ -8349,7 +8339,7 @@ class DiagramCanvas {
8349
8339
  }
8350
8340
  setCursorStyle();
8351
8341
  }));
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) => {
8342
+ 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
8343
  if (this.canUserPerformAction(exports.DiagramActions.StretchSection) && d.getResizableX() && !d.removed) {
8354
8344
  setCursorStyle(exports.CursorStyle.EWResize);
8355
8345
  }
@@ -8383,7 +8373,7 @@ class DiagramCanvas {
8383
8373
  }
8384
8374
  setCursorStyle();
8385
8375
  }));
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) => {
8376
+ 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
8377
  if (this.canUserPerformAction(exports.DiagramActions.StretchSection) && d.getResizableY() && !d.removed) {
8388
8378
  setCursorStyle(exports.CursorStyle.NSResize);
8389
8379
  }
@@ -8664,28 +8654,28 @@ class DiagramCanvas {
8664
8654
  mergeSelection.attr('opacity', d => d.removed ? 0.5 : 1).select('path.diagram-connection-path').attr('d', d => {
8665
8655
  var _a, _b;
8666
8656
  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');
8657
+ }).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
8658
  mergeSelection.select('path.diagram-connection-path-box').attr('d', d => {
8669
8659
  var _a, _b;
8670
8660
  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
8661
  }).attr('stroke', 'transparent')
8672
8662
  // 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');
8663
+ .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
8664
  mergeSelection.data().forEach(connection => {
8675
8665
  this.updateConnectionLabelsInView(connection);
8676
8666
  this.updateConnectionMarkersInView(connection);
8677
8667
  });
8678
8668
  }
8679
8669
  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);
8670
+ 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
8671
  const exitSelection = updateSelection.exit();
8682
- const enterSelection = updateSelection.enter().append('foreignObject').attr('id', d => d.id).attr('class', 'diagram-field');
8672
+ const enterSelection = updateSelection.enter().append('g').attr('id', d => d.id).attr('class', 'diagram-field');
8683
8673
  if (ids && ids.length > 0) {
8684
8674
  updateSelection = updateSelection.filter(d => ids.includes(d.id));
8685
8675
  }
8686
8676
  const mergeSelection = enterSelection.merge(updateSelection);
8687
8677
  exitSelection.remove();
8688
- enterSelection.style('box-sizing', 'border-box').on(exports.Events.MouseOver, (_event, d) => {
8678
+ enterSelection.on(exports.Events.MouseOver, (_event, d) => {
8689
8679
  if (!this.dragging) {
8690
8680
  this.userHighlight.focusOn(d);
8691
8681
  this.diagramEvent$.next(new DiagramHighlightedEvent(d));
@@ -8776,12 +8766,15 @@ class DiagramCanvas {
8776
8766
  }
8777
8767
  }
8778
8768
  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
- }
8769
+ }));
8770
+ enterSelection.append('text');
8771
+ enterSelection.append('rect');
8772
+ 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 => {
8773
+ this.setFieldTextAndWrap(d);
8774
+ });
8775
+ mergeSelection
8776
+ // add a transparent rectangle to capture pointer events on the text
8777
+ .select('rect').attr('x', 0).attr('y', 0).attr('width', d => d.width).attr('height', d => d.height).attr('fill', 'transparent');
8785
8778
  }
8786
8779
  updateObjectsInView(...ids) {
8787
8780
  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 +8784,7 @@ class DiagramCanvas {
8791
8784
  updateSelection = updateSelection.filter(d => ids.includes(d.id));
8792
8785
  }
8793
8786
  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);
8787
+ 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
8788
  exitSelection.remove();
8796
8789
  enterSelection.on(exports.Events.ContextMenu, (event, d) => {
8797
8790
  if (this.dragging) {
@@ -8834,7 +8827,7 @@ class DiagramCanvas {
8834
8827
  updateSelection = updateSelection.filter(d => ids.includes(d.id));
8835
8828
  }
8836
8829
  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);
8830
+ 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
8831
  exitSelection.remove();
8839
8832
  enterSelection.on(exports.Events.MouseOver, (_event, d) => {
8840
8833
  if (!this.dragging) {
@@ -9313,7 +9306,7 @@ class DiagramCanvas {
9313
9306
  openTextInput(id) {
9314
9307
  const field = this.model.fields.get(id);
9315
9308
  if (field) {
9316
- this.createInputField(field.text, field.coords, field.width, field.height, field.fontSize, field.fontFamily || DIAGRAM_FIELD_DEFAULTS.fontFamily, field.orientation, () => {
9309
+ this.createInputField(field.text, field.coords, field.width, field.height, field.fontSize, field.fontFamily || DIAGRAM_FIELD_DEFAULTS.fontFamily, field.orientation, field.multiline, () => {
9317
9310
  // (_text)
9318
9311
  /*
9319
9312
  Empty for now
@@ -9331,7 +9324,7 @@ class DiagramCanvas {
9331
9324
  });
9332
9325
  }
9333
9326
  }
9334
- createInputField(text, coords, width, height, fontSize, fontFamily, orientation, changeCallback, finishCallback) {
9327
+ createInputField(text, coords, width, height, fontSize, fontFamily, orientation, multiline, changeCallback, finishCallback) {
9335
9328
  // if we have a text input open, close it before creating a new one
9336
9329
  this.removeInputField();
9337
9330
  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 +9334,16 @@ class DiagramCanvas {
9341
9334
  let inputFieldHeight;
9342
9335
  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
9336
  event.stopPropagation();
9344
- }).on(exports.Events.KeyUp, event => {
9345
- event.stopPropagation();
9346
- if (event.key === exports.Keys.Escape) {
9347
- const value = inputField.property('value');
9337
+ if (event.key === exports.Keys.Escape || event.key === exports.Keys.Enter && !multiline) {
9338
+ const value = inputField.property('value') || '';
9348
9339
  this.removeInputField();
9349
9340
  if (finishCallback) {
9350
9341
  finishCallback(value);
9351
9342
  }
9352
9343
  }
9353
- }).on(exports.Events.Input, () => {
9344
+ }).on(exports.Events.KeyUp, event => {
9345
+ event.stopPropagation();
9346
+ }).on(exports.Events.Input, event => {
9354
9347
  const value = inputField.property('value');
9355
9348
  inputField.attr('cols', numberOfColumns(value) + 1);
9356
9349
  inputField.attr('rows', numberOfRows(value) + 1);
@@ -9393,13 +9386,54 @@ class DiagramCanvas {
9393
9386
  }
9394
9387
  minimumSizeOfField(field) {
9395
9388
  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) {
9389
+ const textNode = (_b = (_a = field.select()) === null || _a === void 0 ? void 0 : _a.select('text')) === null || _b === void 0 ? void 0 : _b.node();
9390
+ if (!textNode) {
9398
9391
  // happens when a field has been created but not updated in view yet
9399
9392
  return [0, 0];
9400
9393
  }
9401
- const pBoundingBox = pNode.getBoundingClientRect();
9402
- return [pBoundingBox.width / this.zoomTransform.k, pBoundingBox.height / this.zoomTransform.k];
9394
+ const textBoundingBox = textNode.getBoundingClientRect();
9395
+ return [textBoundingBox.width / this.zoomTransform.k, textBoundingBox.height / this.zoomTransform.k];
9396
+ }
9397
+ setFieldTextAndWrap(field) {
9398
+ var _a, _b, _c, _d;
9399
+ const textSelection = (_a = field.select()) === null || _a === void 0 ? void 0 : _a.select('text');
9400
+ const textNode = textSelection === null || textSelection === void 0 ? void 0 : textSelection.node();
9401
+ if (textSelection && textNode) {
9402
+ this.setFieldText(field, textSelection, field.text);
9403
+ } else {
9404
+ // can happen if a field has been created but not updated in view yet
9405
+ // not sure if this still happens but should check just in case
9406
+ return;
9407
+ }
9408
+ if (field.fit) {
9409
+ // no need to wrap
9410
+ return;
9411
+ }
9412
+ let minimumSize = this.minimumSizeOfField(field);
9413
+ while (minimumSize[0] > field.width || minimumSize[1] > field.height) {
9414
+ 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)) || '';
9415
+ let newTextString = '...';
9416
+ if (textString.endsWith('...')) {
9417
+ newTextString = textString.slice(0, -4) + '...';
9418
+ } else {
9419
+ newTextString = textString.slice(0, -1) + '...';
9420
+ }
9421
+ if (textSelection) {
9422
+ this.setFieldText(field, textSelection, newTextString);
9423
+ }
9424
+ if (newTextString === '...') {
9425
+ // if no more characters can be removed and the new text is a bare ellipsis, stop the execution
9426
+ return;
9427
+ }
9428
+ minimumSize = this.minimumSizeOfField(field);
9429
+ }
9430
+ }
9431
+ setFieldText(field, textSelection, text) {
9432
+ const lines = text.split('\n');
9433
+ textSelection.html('');
9434
+ for (let i = 0; i < lines.length; ++i) {
9435
+ 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]);
9436
+ }
9403
9437
  }
9404
9438
  /**
9405
9439
  * Method to call to start the moving of a node triggered by a user drag event.
@@ -9431,6 +9465,7 @@ class DiagramCanvas {
9431
9465
  }
9432
9466
  this.userHighlight.clear();
9433
9467
  this.dragging = true;
9468
+ this.diagramEvent$.next(new DiagramDraggingNodeEvent(d));
9434
9469
  }
9435
9470
  }
9436
9471
  /**
@@ -10456,6 +10491,7 @@ exports.DiagramContextMenu = DiagramContextMenu;
10456
10491
  exports.DiagramDecorator = DiagramDecorator;
10457
10492
  exports.DiagramDecoratorSet = DiagramDecoratorSet;
10458
10493
  exports.DiagramDoubleClickEvent = DiagramDoubleClickEvent;
10494
+ exports.DiagramDraggingNodeEvent = DiagramDraggingNodeEvent;
10459
10495
  exports.DiagramElement = DiagramElement;
10460
10496
  exports.DiagramElementSet = DiagramElementSet;
10461
10497
  exports.DiagramEntitySet = DiagramEntitySet;
package/index.esm.js CHANGED
@@ -2680,6 +2680,7 @@ const DIAGRAM_FIELD_DEFAULTS = {
2680
2680
  horizontalAlign: HorizontalAlign.Center,
2681
2681
  verticalAlign: VerticalAlign.Center,
2682
2682
  orientation: Side.Top,
2683
+ multiline: false,
2683
2684
  fit: false,
2684
2685
  shrink: true
2685
2686
  };
@@ -2709,7 +2710,7 @@ class DiagramField extends DiagramElement {
2709
2710
  (_a = this.model.canvas) === null || _a === void 0 ? void 0 : _a.fitFieldRootInView(this.id, this.shrink);
2710
2711
  }
2711
2712
  }
2712
- constructor(model, rootElement, coords, width, height, fontSize, fontFamily, color, selectedColor, horizontalAlign, verticalAlign, orientation, text, editable, fit, shrink) {
2713
+ constructor(model, rootElement, coords, width, height, fontSize, fontFamily, color, selectedColor, horizontalAlign, verticalAlign, orientation, multiline, text, editable, fit, shrink) {
2713
2714
  const id = `${rootElement === null || rootElement === void 0 ? void 0 : rootElement.id}_field`;
2714
2715
  if (model.fields.get(id) !== undefined) {
2715
2716
  throw new Error('DiagramField for rootElement already exists');
@@ -2750,6 +2751,7 @@ class DiagramField extends DiagramElement {
2750
2751
  this.orientation = 0;
2751
2752
  }
2752
2753
  }
2754
+ this.multiline = multiline;
2753
2755
  this.defaultText = text;
2754
2756
  this._text = text;
2755
2757
  this.editable = editable;
@@ -2794,8 +2796,8 @@ class DiagramFieldSet extends DiagramElementSet {
2794
2796
  * 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
2797
  * @private
2796
2798
  */
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);
2799
+ new(rootElement, coords, fontSize, fontFamily, color, selectedColor, width, height, horizontalAlign, verticalAlign, orientation, multiline, text, editable, fit, shrink) {
2800
+ const field = new DiagramField(this.model, rootElement, coords, width, height, fontSize, fontFamily, color, selectedColor, horizontalAlign, verticalAlign, orientation, multiline, text, editable, fit, shrink);
2799
2801
  super.add(field);
2800
2802
  field.updateInView();
2801
2803
  // add this field to its root element
@@ -3434,7 +3436,7 @@ class DiagramSectionSet extends DiagramElementSet {
3434
3436
  default:
3435
3437
  labelCoords = port.coords;
3436
3438
  }
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);
3439
+ 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
3440
  }
3439
3441
  }
3440
3442
  }
@@ -3442,7 +3444,7 @@ class DiagramSectionSet extends DiagramElementSet {
3442
3444
  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
3445
  if (sectionLabel) {
3444
3446
  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);
3447
+ 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
3448
  }
3447
3449
  return section;
3448
3450
  }
@@ -4362,14 +4364,14 @@ class DiagramNodeSet extends DiagramElementSet {
4362
4364
  default:
4363
4365
  labelCoords = port.coords;
4364
4366
  }
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);
4367
+ 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
4368
  }
4367
4369
  }
4368
4370
  }
4369
4371
  // add node label
4370
4372
  if (nodeType.label) {
4371
4373
  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);
4374
+ 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
4375
  }
4374
4376
  // add node decorators
4375
4377
  if (nodeType.decorators.length > 0) {
@@ -4939,7 +4941,7 @@ class DagaImporter {
4939
4941
  // add node label
4940
4942
  if (newNodeType.label) {
4941
4943
  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);
4944
+ 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
4945
  newField.text = node.label;
4944
4946
  newNode.label = newField;
4945
4947
  model.fields.add(newField);
@@ -4959,7 +4961,7 @@ class DagaImporter {
4959
4961
  // add section label
4960
4962
  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
4963
  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);
4964
+ 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
4965
  newField.text = section.label;
4964
4966
  newSection.label = newField;
4965
4967
  model.fields.add(newField);
@@ -4990,7 +4992,7 @@ class DagaImporter {
4990
4992
  default:
4991
4993
  labelCoords = newPort.coords;
4992
4994
  }
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);
4995
+ 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
4996
  newField.text = port.label;
4995
4997
  newPort.label = newField;
4996
4998
  model.fields.add(newField);
@@ -5037,7 +5039,7 @@ class DagaImporter {
5037
5039
  default:
5038
5040
  labelCoords = newPort.coords;
5039
5041
  }
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);
5042
+ 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
5043
  newField.text = port.label;
5042
5044
  newPort.label = newField;
5043
5045
  model.fields.add(newField);
@@ -6334,6 +6336,7 @@ var DiagramEvents;
6334
6336
  DiagramEvents[DiagramEvents["SecondaryClick"] = 2] = "SecondaryClick";
6335
6337
  DiagramEvents[DiagramEvents["Selection"] = 3] = "Selection";
6336
6338
  DiagramEvents[DiagramEvents["Highlight"] = 4] = "Highlight";
6339
+ DiagramEvents[DiagramEvents["DraggingNode"] = 5] = "DraggingNode";
6337
6340
  })(DiagramEvents || (DiagramEvents = {}));
6338
6341
  /**
6339
6342
  * Diagram event which consists of the user zooming or panning.
@@ -6417,6 +6420,20 @@ class DiagramHighlightedEvent extends DiagramEvent {
6417
6420
  this.target = target;
6418
6421
  }
6419
6422
  }
6423
+ /**
6424
+ * Diagram event which consists of the user dragging a diagram node.
6425
+ */
6426
+ class DiagramDraggingNodeEvent extends DiagramEvent {
6427
+ /**
6428
+ * Create a diagram dragging node event.
6429
+ *
6430
+ * @param target Diagram node which is targeted by the event.
6431
+ */
6432
+ constructor(target) {
6433
+ super(DiagramEvents.DraggingNode);
6434
+ this.target = target;
6435
+ }
6436
+ }
6420
6437
 
6421
6438
  /**
6422
6439
  * A foreign object which is inserted with arbitrary html into a diagram.
@@ -7450,29 +7467,6 @@ class DiagramUserSelection extends DiagramElementSet {
7450
7467
  }
7451
7468
  }
7452
7469
 
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
7470
  /**
7477
7471
  * Thickness of the invisible path around a connection used to make it easier to click on, in diagram units.
7478
7472
  * @private
@@ -7771,10 +7765,6 @@ class DiagramCanvas {
7771
7765
  const transformAttribute = event.transform.toString();
7772
7766
  this.selectCanvasElements().attr('transform', transformAttribute);
7773
7767
  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
7768
  this.contextMenu.close();
7779
7769
  this.diagramEvent$.next(new DiagramZoomEvent([this.zoomTransform.x, this.zoomTransform.y], this.zoomTransform.k));
7780
7770
  }).on(ZoomEvents.End, () => {
@@ -8021,7 +8011,7 @@ class DiagramCanvas {
8021
8011
  this.secondaryButton = false;
8022
8012
  }));
8023
8013
  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) => {
8014
+ enterSelection.filter('.resizable-x').append('line').attr('class', 'left-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(Events.MouseOver, (_event, d) => {
8025
8015
  if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableX() && !d.removed) {
8026
8016
  setCursorStyle(CursorStyle.EWResize);
8027
8017
  }
@@ -8057,7 +8047,7 @@ class DiagramCanvas {
8057
8047
  }
8058
8048
  setCursorStyle();
8059
8049
  }));
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) => {
8050
+ enterSelection.filter('.resizable-y').append('line').attr('class', 'top-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(Events.MouseOver, (_event, d) => {
8061
8051
  if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableY() && !d.removed) {
8062
8052
  setCursorStyle(CursorStyle.NSResize);
8063
8053
  }
@@ -8093,7 +8083,7 @@ class DiagramCanvas {
8093
8083
  }
8094
8084
  setCursorStyle();
8095
8085
  }));
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) => {
8086
+ enterSelection.filter('.resizable-x').append('line').attr('class', 'right-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(Events.MouseOver, (_event, d) => {
8097
8087
  if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableX() && !d.removed) {
8098
8088
  setCursorStyle(CursorStyle.EWResize);
8099
8089
  }
@@ -8129,7 +8119,7 @@ class DiagramCanvas {
8129
8119
  }
8130
8120
  setCursorStyle();
8131
8121
  }));
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) => {
8122
+ enterSelection.filter('.resizable-y').append('line').attr('class', 'bottom-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(Events.MouseOver, (_event, d) => {
8133
8123
  if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableY() && !d.removed) {
8134
8124
  setCursorStyle(CursorStyle.NSResize);
8135
8125
  }
@@ -8260,7 +8250,7 @@ class DiagramCanvas {
8260
8250
  this.secondaryButton = false;
8261
8251
  }));
8262
8252
  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) => {
8253
+ enterSelection.filter('.resizable-x').append('line').attr('class', 'left-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(Events.MouseOver, (_event, d) => {
8264
8254
  if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableX() && !d.removed) {
8265
8255
  setCursorStyle(CursorStyle.EWResize);
8266
8256
  }
@@ -8294,7 +8284,7 @@ class DiagramCanvas {
8294
8284
  }
8295
8285
  setCursorStyle();
8296
8286
  }));
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) => {
8287
+ enterSelection.filter('.resizable-y').append('line').attr('class', 'top-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(Events.MouseOver, (_event, d) => {
8298
8288
  if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableY() && !d.removed) {
8299
8289
  setCursorStyle(CursorStyle.NSResize);
8300
8290
  }
@@ -8328,7 +8318,7 @@ class DiagramCanvas {
8328
8318
  }
8329
8319
  setCursorStyle();
8330
8320
  }));
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) => {
8321
+ enterSelection.filter('.resizable-x').append('line').attr('class', 'right-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(Events.MouseOver, (_event, d) => {
8332
8322
  if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableX() && !d.removed) {
8333
8323
  setCursorStyle(CursorStyle.EWResize);
8334
8324
  }
@@ -8362,7 +8352,7 @@ class DiagramCanvas {
8362
8352
  }
8363
8353
  setCursorStyle();
8364
8354
  }));
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) => {
8355
+ enterSelection.filter('.resizable-y').append('line').attr('class', 'bottom-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(Events.MouseOver, (_event, d) => {
8366
8356
  if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableY() && !d.removed) {
8367
8357
  setCursorStyle(CursorStyle.NSResize);
8368
8358
  }
@@ -8643,28 +8633,28 @@ class DiagramCanvas {
8643
8633
  mergeSelection.attr('opacity', d => d.removed ? 0.5 : 1).select('path.diagram-connection-path').attr('d', d => {
8644
8634
  var _a, _b;
8645
8635
  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');
8636
+ }).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
8637
  mergeSelection.select('path.diagram-connection-path-box').attr('d', d => {
8648
8638
  var _a, _b;
8649
8639
  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
8640
  }).attr('stroke', 'transparent')
8651
8641
  // 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');
8642
+ .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
8643
  mergeSelection.data().forEach(connection => {
8654
8644
  this.updateConnectionLabelsInView(connection);
8655
8645
  this.updateConnectionMarkersInView(connection);
8656
8646
  });
8657
8647
  }
8658
8648
  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);
8649
+ 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
8650
  const exitSelection = updateSelection.exit();
8661
- const enterSelection = updateSelection.enter().append('foreignObject').attr('id', d => d.id).attr('class', 'diagram-field');
8651
+ const enterSelection = updateSelection.enter().append('g').attr('id', d => d.id).attr('class', 'diagram-field');
8662
8652
  if (ids && ids.length > 0) {
8663
8653
  updateSelection = updateSelection.filter(d => ids.includes(d.id));
8664
8654
  }
8665
8655
  const mergeSelection = enterSelection.merge(updateSelection);
8666
8656
  exitSelection.remove();
8667
- enterSelection.style('box-sizing', 'border-box').on(Events.MouseOver, (_event, d) => {
8657
+ enterSelection.on(Events.MouseOver, (_event, d) => {
8668
8658
  if (!this.dragging) {
8669
8659
  this.userHighlight.focusOn(d);
8670
8660
  this.diagramEvent$.next(new DiagramHighlightedEvent(d));
@@ -8755,12 +8745,15 @@ class DiagramCanvas {
8755
8745
  }
8756
8746
  }
8757
8747
  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
- }
8748
+ }));
8749
+ enterSelection.append('text');
8750
+ enterSelection.append('rect');
8751
+ 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 => {
8752
+ this.setFieldTextAndWrap(d);
8753
+ });
8754
+ mergeSelection
8755
+ // add a transparent rectangle to capture pointer events on the text
8756
+ .select('rect').attr('x', 0).attr('y', 0).attr('width', d => d.width).attr('height', d => d.height).attr('fill', 'transparent');
8764
8757
  }
8765
8758
  updateObjectsInView(...ids) {
8766
8759
  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 +8763,7 @@ class DiagramCanvas {
8770
8763
  updateSelection = updateSelection.filter(d => ids.includes(d.id));
8771
8764
  }
8772
8765
  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);
8766
+ 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
8767
  exitSelection.remove();
8775
8768
  enterSelection.on(Events.ContextMenu, (event, d) => {
8776
8769
  if (this.dragging) {
@@ -8813,7 +8806,7 @@ class DiagramCanvas {
8813
8806
  updateSelection = updateSelection.filter(d => ids.includes(d.id));
8814
8807
  }
8815
8808
  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);
8809
+ 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
8810
  exitSelection.remove();
8818
8811
  enterSelection.on(Events.MouseOver, (_event, d) => {
8819
8812
  if (!this.dragging) {
@@ -9292,7 +9285,7 @@ class DiagramCanvas {
9292
9285
  openTextInput(id) {
9293
9286
  const field = this.model.fields.get(id);
9294
9287
  if (field) {
9295
- this.createInputField(field.text, field.coords, field.width, field.height, field.fontSize, field.fontFamily || DIAGRAM_FIELD_DEFAULTS.fontFamily, field.orientation, () => {
9288
+ this.createInputField(field.text, field.coords, field.width, field.height, field.fontSize, field.fontFamily || DIAGRAM_FIELD_DEFAULTS.fontFamily, field.orientation, field.multiline, () => {
9296
9289
  // (_text)
9297
9290
  /*
9298
9291
  Empty for now
@@ -9310,7 +9303,7 @@ class DiagramCanvas {
9310
9303
  });
9311
9304
  }
9312
9305
  }
9313
- createInputField(text, coords, width, height, fontSize, fontFamily, orientation, changeCallback, finishCallback) {
9306
+ createInputField(text, coords, width, height, fontSize, fontFamily, orientation, multiline, changeCallback, finishCallback) {
9314
9307
  // if we have a text input open, close it before creating a new one
9315
9308
  this.removeInputField();
9316
9309
  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 +9313,16 @@ class DiagramCanvas {
9320
9313
  let inputFieldHeight;
9321
9314
  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
9315
  event.stopPropagation();
9323
- }).on(Events.KeyUp, event => {
9324
- event.stopPropagation();
9325
- if (event.key === Keys.Escape) {
9326
- const value = inputField.property('value');
9316
+ if (event.key === Keys.Escape || event.key === Keys.Enter && !multiline) {
9317
+ const value = inputField.property('value') || '';
9327
9318
  this.removeInputField();
9328
9319
  if (finishCallback) {
9329
9320
  finishCallback(value);
9330
9321
  }
9331
9322
  }
9332
- }).on(Events.Input, () => {
9323
+ }).on(Events.KeyUp, event => {
9324
+ event.stopPropagation();
9325
+ }).on(Events.Input, event => {
9333
9326
  const value = inputField.property('value');
9334
9327
  inputField.attr('cols', numberOfColumns(value) + 1);
9335
9328
  inputField.attr('rows', numberOfRows(value) + 1);
@@ -9372,13 +9365,54 @@ class DiagramCanvas {
9372
9365
  }
9373
9366
  minimumSizeOfField(field) {
9374
9367
  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) {
9368
+ const textNode = (_b = (_a = field.select()) === null || _a === void 0 ? void 0 : _a.select('text')) === null || _b === void 0 ? void 0 : _b.node();
9369
+ if (!textNode) {
9377
9370
  // happens when a field has been created but not updated in view yet
9378
9371
  return [0, 0];
9379
9372
  }
9380
- const pBoundingBox = pNode.getBoundingClientRect();
9381
- return [pBoundingBox.width / this.zoomTransform.k, pBoundingBox.height / this.zoomTransform.k];
9373
+ const textBoundingBox = textNode.getBoundingClientRect();
9374
+ return [textBoundingBox.width / this.zoomTransform.k, textBoundingBox.height / this.zoomTransform.k];
9375
+ }
9376
+ setFieldTextAndWrap(field) {
9377
+ var _a, _b, _c, _d;
9378
+ const textSelection = (_a = field.select()) === null || _a === void 0 ? void 0 : _a.select('text');
9379
+ const textNode = textSelection === null || textSelection === void 0 ? void 0 : textSelection.node();
9380
+ if (textSelection && textNode) {
9381
+ this.setFieldText(field, textSelection, field.text);
9382
+ } else {
9383
+ // can happen if a field has been created but not updated in view yet
9384
+ // not sure if this still happens but should check just in case
9385
+ return;
9386
+ }
9387
+ if (field.fit) {
9388
+ // no need to wrap
9389
+ return;
9390
+ }
9391
+ let minimumSize = this.minimumSizeOfField(field);
9392
+ while (minimumSize[0] > field.width || minimumSize[1] > field.height) {
9393
+ 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)) || '';
9394
+ let newTextString = '...';
9395
+ if (textString.endsWith('...')) {
9396
+ newTextString = textString.slice(0, -4) + '...';
9397
+ } else {
9398
+ newTextString = textString.slice(0, -1) + '...';
9399
+ }
9400
+ if (textSelection) {
9401
+ this.setFieldText(field, textSelection, newTextString);
9402
+ }
9403
+ if (newTextString === '...') {
9404
+ // if no more characters can be removed and the new text is a bare ellipsis, stop the execution
9405
+ return;
9406
+ }
9407
+ minimumSize = this.minimumSizeOfField(field);
9408
+ }
9409
+ }
9410
+ setFieldText(field, textSelection, text) {
9411
+ const lines = text.split('\n');
9412
+ textSelection.html('');
9413
+ for (let i = 0; i < lines.length; ++i) {
9414
+ 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]);
9415
+ }
9382
9416
  }
9383
9417
  /**
9384
9418
  * Method to call to start the moving of a node triggered by a user drag event.
@@ -9410,6 +9444,7 @@ class DiagramCanvas {
9410
9444
  }
9411
9445
  this.userHighlight.clear();
9412
9446
  this.dragging = true;
9447
+ this.diagramEvent$.next(new DiagramDraggingNodeEvent(d));
9413
9448
  }
9414
9449
  }
9415
9450
  /**
@@ -10415,4 +10450,4 @@ const getLocationsOfNodes = model => {
10415
10450
  return locations;
10416
10451
  };
10417
10452
 
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 };
10453
+ 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.16",
3
+ "version": "4.2.18",
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];