@metadev/daga 4.0.2 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Changelog.md CHANGED
@@ -6,6 +6,20 @@ List of releases and changes.
6
6
 
7
7
  ## Next release Joyeuse
8
8
 
9
+ ## v. 4.1.0
10
+
11
+ - Add methods for adding and removing rows and columns of sections in a node.
12
+ - Allow toggling gapSize in layout algorithms [#279](https://github.com/metadevpro/daga/pull/279)
13
+ - Raise ports after raising sections inside nodes so that sections don't hide ports [#280](https://github.com/metadevpro/daga/pull/280)
14
+ - Add `fieldRootFitsInView()` method to canvas [#281](https://github.com/metadevpro/daga/pull/281)
15
+ - Add `shrink` parameter to canvas method `fitFieldRootInView()` to toggle whether nodes and sections should be shrunk as part of the fitting process [#282](https://github.com/metadevpro/daga/pull/282)
16
+ - Set root vlaue of property to default value when resetting values [#284](https://github.com/metadevpro/daga/pull/284)
17
+
18
+ ## v. 4.0.3
19
+
20
+ - Allow angular 20.
21
+ - Fix bug with connections breaking when they have an id which is not a valid CSS selector [#277](https://github.com/metadevpro/daga/pull/277)
22
+
9
23
  ## v. 4.0.2
10
24
 
11
25
  - Add grid style [#261](https://github.com/metadevpro/daga/pull/261)
package/index.cjs.js CHANGED
@@ -1691,10 +1691,8 @@ class ValueSet {
1691
1691
  this.values[key] = structuredClone(property.defaultValue);
1692
1692
  }
1693
1693
  if (rootAttribute !== undefined && rootAttribute !== null) {
1694
- if (property.defaultValue !== undefined && !equals(this.values[key], property.defaultValue)) {
1694
+ if (property.defaultValue !== undefined && !equals(this.getRootElementValue(rootAttribute), property.defaultValue)) {
1695
1695
  this.setRootElementValue(rootAttribute, this.values[key]);
1696
- } else {
1697
- this.values[key] = this.getRootElementValue(rootAttribute);
1698
1696
  }
1699
1697
  }
1700
1698
  if (property.basic) {
@@ -3160,15 +3158,15 @@ class DiagramNode extends DiagramElement {
3160
3158
  raise() {
3161
3159
  var _a;
3162
3160
  (_a = this.select()) === null || _a === undefined ? undefined : _a.raise();
3161
+ for (const section of this.sections) {
3162
+ section.raise();
3163
+ }
3163
3164
  if (this.label) {
3164
3165
  this.label.raise();
3165
3166
  }
3166
3167
  for (const port of this.ports) {
3167
3168
  port.raise();
3168
3169
  }
3169
- for (const section of this.sections) {
3170
- section.raise();
3171
- }
3172
3170
  for (const decorator of this.decorators) {
3173
3171
  decorator.raise();
3174
3172
  }
@@ -3602,6 +3600,106 @@ class DiagramNode extends DiagramElement {
3602
3600
  this.getConnections().forEach(c => c.tighten());
3603
3601
  this.updateInView();
3604
3602
  }
3603
+ /**
3604
+ * Removes all sections with the given index along the x axis.
3605
+ * @public
3606
+ */
3607
+ removeSectionColumn(columnIndex) {
3608
+ var _a;
3609
+ const margin = ((_a = this.type.sectionGrid) === null || _a === undefined ? undefined : _a.margin) || 0;
3610
+ let columnWidth = 0;
3611
+ const sections = [...this.sections];
3612
+ for (const section of sections) {
3613
+ if (section.indexYInNode === columnIndex) {
3614
+ columnWidth = Math.max(columnWidth, section.width);
3615
+ this.model.sections.remove(section.id);
3616
+ }
3617
+ }
3618
+ for (const section of sections) {
3619
+ if (section.indexYInNode > columnIndex) {
3620
+ --section.indexYInNode;
3621
+ section.move([section.coords[0] - columnWidth - margin, section.coords[1]]);
3622
+ }
3623
+ }
3624
+ this.stretch(exports.Side.Right, -margin - columnWidth);
3625
+ }
3626
+ /**
3627
+ * Removes all sections with the given index along the y axis.
3628
+ * @public
3629
+ */
3630
+ removeSectionRow(rowIndex) {
3631
+ var _a;
3632
+ const margin = ((_a = this.type.sectionGrid) === null || _a === undefined ? undefined : _a.margin) || 0;
3633
+ let rowHeight = 0;
3634
+ const sections = [...this.sections];
3635
+ for (const section of sections) {
3636
+ if (section.indexXInNode === rowIndex) {
3637
+ rowHeight = Math.max(rowHeight, section.height);
3638
+ this.model.sections.remove(section.id);
3639
+ }
3640
+ }
3641
+ for (const section of sections) {
3642
+ if (section.indexYInNode > rowIndex) {
3643
+ --section.indexXInNode;
3644
+ section.move([section.coords[0], section.coords[1] - rowHeight - margin]);
3645
+ }
3646
+ }
3647
+ this.stretch(exports.Side.Bottom, -margin - rowHeight);
3648
+ }
3649
+ /**
3650
+ * Creates a copy of all sections with the given index along the x axis.
3651
+ * @public
3652
+ */
3653
+ copySectionColumn(columnIndex) {
3654
+ var _a;
3655
+ const margin = ((_a = this.type.sectionGrid) === null || _a === undefined ? undefined : _a.margin) || 0;
3656
+ let columnWidth = 0;
3657
+ const sections = [...this.sections];
3658
+ for (const section of sections) {
3659
+ if (section.indexXInNode === columnIndex) {
3660
+ columnWidth = Math.max(columnWidth, section.width);
3661
+ let newSectionIdIndexX = section.indexXInNode + 1;
3662
+ while (this.model.sections.get(`${section.id}_copy_${newSectionIdIndexX}_${section.indexYInNode}`, true) !== undefined) {
3663
+ ++newSectionIdIndexX;
3664
+ }
3665
+ this.model.sections.new(this, section.indexXInNode + 1, section.indexYInNode, [section.coords[0] + section.width + margin, section.coords[1]], section.width, section.height, `${section.id}_copy_${newSectionIdIndexX}_${section.indexYInNode}`);
3666
+ }
3667
+ }
3668
+ for (const section of sections) {
3669
+ if (section.indexXInNode > columnIndex) {
3670
+ ++section.indexXInNode;
3671
+ section.move([section.coords[0] + columnWidth + margin, section.coords[1]]);
3672
+ }
3673
+ }
3674
+ this.stretch(exports.Side.Right, margin + columnWidth);
3675
+ }
3676
+ /**
3677
+ * Creates a copy of all sections with the given index along the y axis.
3678
+ * @public
3679
+ */
3680
+ copySectionRow(rowIndex) {
3681
+ var _a;
3682
+ const margin = ((_a = this.type.sectionGrid) === null || _a === undefined ? undefined : _a.margin) || 0;
3683
+ let rowHeight = 0;
3684
+ const sections = [...this.sections];
3685
+ for (const section of sections) {
3686
+ if (section.indexYInNode === rowIndex) {
3687
+ rowHeight = Math.max(rowHeight, section.height);
3688
+ let newSectionIdIndexY = section.indexYInNode + 1;
3689
+ while (this.model.sections.get(`${section.id}_copy_${section.indexXInNode}_${newSectionIdIndexY}`, true) !== undefined) {
3690
+ ++newSectionIdIndexY;
3691
+ }
3692
+ this.model.sections.new(this, section.indexXInNode, section.indexYInNode + 1, [section.coords[0], section.coords[1] + section.height + margin], section.width, section.height, `${section.id}_copy_${section.indexXInNode}_${newSectionIdIndexY}`);
3693
+ }
3694
+ }
3695
+ for (const section of sections) {
3696
+ if (section.indexYInNode > rowIndex) {
3697
+ ++section.indexYInNode;
3698
+ section.move([section.coords[0], section.coords[1] + rowHeight + margin]);
3699
+ }
3700
+ }
3701
+ this.stretch(exports.Side.Bottom, margin + rowHeight);
3702
+ }
3605
3703
  }
3606
3704
  class DiagramNodeSet extends DiagramElementSet {
3607
3705
  /**
@@ -4439,6 +4537,54 @@ class AddNodeCollabAction {
4439
4537
  return new AddNodeCollabAction(canvas, serialized.id, serialized.typeId, serialized.coords, serialized.parentId, serialized.label, serialized.values);
4440
4538
  }
4441
4539
  }
4540
+ /**
4541
+ * Collaborative action which consists of adding or removing sections in a node.
4542
+ * @private
4543
+ * @see AddNodeAction
4544
+ */
4545
+ class AddSectionCollabAction {
4546
+ constructor(canvas, nodeId, copyColumnIndex, copyRowIndex, removeColumnIndex, removeRowIndex, timestamp) {
4547
+ this.canvas = canvas;
4548
+ this.nodeId = nodeId;
4549
+ this.copyColumnIndex = copyColumnIndex;
4550
+ this.copyRowIndex = copyRowIndex;
4551
+ this.removeColumnIndex = removeColumnIndex;
4552
+ this.removeRowIndex = removeRowIndex;
4553
+ this.timestamp = timestamp;
4554
+ }
4555
+ do() {
4556
+ const node = this.canvas.model.nodes.get(this.nodeId);
4557
+ if (node && timestampWins(this.timestamp, node.geometryTimestamp)) {
4558
+ if (this.copyColumnIndex !== undefined) {
4559
+ node.copySectionColumn(this.copyColumnIndex);
4560
+ }
4561
+ if (this.copyRowIndex !== undefined) {
4562
+ node.copySectionRow(this.copyRowIndex);
4563
+ }
4564
+ if (this.removeColumnIndex !== undefined) {
4565
+ node.removeSectionColumn(this.removeColumnIndex);
4566
+ }
4567
+ if (this.removeRowIndex !== undefined) {
4568
+ node.removeSectionRow(this.removeRowIndex);
4569
+ }
4570
+ node.geometryTimestamp = this.timestamp;
4571
+ }
4572
+ }
4573
+ serialize() {
4574
+ return {
4575
+ type: 'addSection',
4576
+ nodeId: this.nodeId,
4577
+ copyColumnIndex: this.copyColumnIndex,
4578
+ copyRowIndex: this.copyRowIndex,
4579
+ removeColumnIndex: this.removeColumnIndex,
4580
+ removeRowIndex: this.removeRowIndex,
4581
+ timestamp: this.timestamp
4582
+ };
4583
+ }
4584
+ static deserialize(canvas, serialized) {
4585
+ return new AddSectionCollabAction(canvas, serialized.nodeId, serialized.copyColumnIndex, serialized.copyRowIndex, serialized.removeColumnIndex, serialized.removeRowIndex, serialized.timestamp);
4586
+ }
4587
+ }
4442
4588
  /**
4443
4589
  * Collaborative which consists of applying a layout to the diagram which can change the location of several nodes.
4444
4590
  * @private
@@ -4855,6 +5001,12 @@ class CollabEngine {
4855
5001
  action.do();
4856
5002
  break;
4857
5003
  }
5004
+ case 'addSection':
5005
+ {
5006
+ const action = AddSectionCollabAction.deserialize(this.canvas, message);
5007
+ action.do();
5008
+ break;
5009
+ }
4858
5010
  case 'applyLayout':
4859
5011
  {
4860
5012
  const action = ApplyLayoutCollabAction.deserialize(this.canvas, message);
@@ -5017,6 +5169,12 @@ exports.DiagramActions = void 0;
5017
5169
  * @see AddNodeAction
5018
5170
  */
5019
5171
  DiagramActions["AddNode"] = "add-node";
5172
+ /**
5173
+ * Action that corresponds to the addition or removal of sections in a node.
5174
+ * @public
5175
+ * @see AddSectionAction
5176
+ */
5177
+ DiagramActions["AddSectionAction"] = "add-section";
5020
5178
  /**
5021
5179
  * Action that corresponds to applying a layout which changes the location of several nodes.
5022
5180
  * @public
@@ -7991,7 +8149,7 @@ class DiagramCanvas {
7991
8149
  }
7992
8150
  updateConnectionLabelsInView(connection) {
7993
8151
  var _a, _b, _c;
7994
- const connectionSelection = this.selectCanvasView().select(`g.diagram-connection#${connection.id}`);
8152
+ const connectionSelection = this.selectCanvasView().select(`[id='${escapeSelector(connection.id)}']`);
7995
8153
  const pathSelection = connectionSelection.select('path');
7996
8154
  const pathNode = pathSelection.node();
7997
8155
  const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), connection.type.label);
@@ -8033,7 +8191,7 @@ class DiagramCanvas {
8033
8191
  }
8034
8192
  }
8035
8193
  updateConnectionMarkersInView(connection) {
8036
- const connectionSelection = this.selectCanvasView().select(`g.diagram-connection#${connection.id}`);
8194
+ const connectionSelection = this.selectCanvasView().select(`[id='${escapeSelector(connection.id)}']`);
8037
8195
  const startMarkerSelection = connectionSelection.select('marker.diagram-connection-start-marker');
8038
8196
  const endMarkerSelection = connectionSelection.select('marker.diagram-connection-end-marker');
8039
8197
  if (connection.startMarkerLook !== null) {
@@ -8047,13 +8205,27 @@ class DiagramCanvas {
8047
8205
  endMarkerSelection.attr('orient', 'auto-start-reverse').attr('markerWidth', 0).attr('markerHeight', 0);
8048
8206
  }
8049
8207
  }
8050
- fitFieldRootInView(id) {
8208
+ fieldRootFitsInView(id) {
8209
+ var _a, _b, _c, _d;
8210
+ const field = this.model.fields.get(id);
8211
+ if (!field) {
8212
+ return false;
8213
+ }
8214
+ if (field.rootElement instanceof DiagramNode || field.rootElement instanceof DiagramSection) {
8215
+ const fieldDimensions = this.minimumSizeOfField(field);
8216
+ const stretchX = fieldDimensions[0] + getLeftMargin((_a = field.rootElement.type) === null || _a === undefined ? undefined : _a.label) + getRightMargin((_b = field.rootElement.type) === null || _b === undefined ? undefined : _b.label) - field.rootElement.width;
8217
+ const stretchY = fieldDimensions[1] + getTopMargin((_c = field.rootElement.type) === null || _c === undefined ? undefined : _c.label) + getBottomMargin((_d = field.rootElement.type) === null || _d === undefined ? undefined : _d.label) - field.rootElement.height;
8218
+ return stretchX <= 0 && stretchY <= 0;
8219
+ }
8220
+ return true;
8221
+ }
8222
+ fitFieldRootInView(id, shrink) {
8051
8223
  var _a, _b, _c;
8052
8224
  const field = this.model.fields.get(id);
8053
8225
  if (!field) {
8054
8226
  return;
8055
8227
  }
8056
- if (field.rootElement instanceof DiagramNode && field.fit) {
8228
+ if (field.rootElement instanceof DiagramNode) {
8057
8229
  const fieldDimensions = this.minimumSizeOfField(field);
8058
8230
  let stretchX = fieldDimensions[0] + getLeftMargin(field.rootElement.type.label) + getRightMargin(field.rootElement.type.label) - field.rootElement.width;
8059
8231
  let stretchY = fieldDimensions[1] + getTopMargin(field.rootElement.type.label) + getBottomMargin(field.rootElement.type.label) - field.rootElement.height;
@@ -8068,10 +8240,14 @@ class DiagramCanvas {
8068
8240
  if (field.rootElement.height + stretchY < field.rootElement.type.minHeight) {
8069
8241
  stretchY = field.rootElement.type.minHeight - field.rootElement.height;
8070
8242
  }
8071
- field.rootElement.stretch(exports.Side.Right, stretchX);
8072
- field.rootElement.stretch(exports.Side.Bottom, stretchY);
8243
+ if (shrink !== false || stretchX > 0) {
8244
+ field.rootElement.stretch(exports.Side.Right, stretchX);
8245
+ }
8246
+ if (shrink !== false || stretchY > 0) {
8247
+ field.rootElement.stretch(exports.Side.Bottom, stretchY);
8248
+ }
8073
8249
  }
8074
- if (field.rootElement instanceof DiagramSection && field.fit) {
8250
+ if (field.rootElement instanceof DiagramSection) {
8075
8251
  const fieldDimensions = this.minimumSizeOfField(field);
8076
8252
  let minimumFieldWidth = fieldDimensions[0];
8077
8253
  let minimumFieldHeight = fieldDimensions[1];
@@ -8104,8 +8280,12 @@ class DiagramCanvas {
8104
8280
  if (field.rootElement.height + stretchY < (field.rootElement.getMinHeight() || 0)) {
8105
8281
  stretchY = (field.rootElement.getMinHeight() || 0) - field.rootElement.height;
8106
8282
  }
8107
- (_b = field.rootElement.node) === null || _b === undefined ? undefined : _b.stretchSections(exports.Side.Right, stretchX, field.rootElement.indexXInNode, field.rootElement.indexYInNode);
8108
- (_c = field.rootElement.node) === null || _c === undefined ? undefined : _c.stretchSections(exports.Side.Bottom, stretchY, field.rootElement.indexXInNode, field.rootElement.indexYInNode);
8283
+ if (shrink !== false || stretchX > 0) {
8284
+ (_b = field.rootElement.node) === null || _b === undefined ? undefined : _b.stretchSections(exports.Side.Right, stretchX, field.rootElement.indexXInNode, field.rootElement.indexYInNode);
8285
+ }
8286
+ if (shrink !== false || stretchY > 0) {
8287
+ (_c = field.rootElement.node) === null || _c === undefined ? undefined : _c.stretchSections(exports.Side.Bottom, stretchY, field.rootElement.indexXInNode, field.rootElement.indexYInNode);
8288
+ }
8109
8289
  }
8110
8290
  }
8111
8291
  fitNodeInView(id) {
@@ -8794,6 +8974,9 @@ class Grid {
8794
8974
  * @public
8795
8975
  */
8796
8976
  class AdjacencyLayout {
8977
+ constructor(gapSize) {
8978
+ this.gapSize = gapSize;
8979
+ }
8797
8980
  apply(model) {
8798
8981
  var _a;
8799
8982
  if (model.nodes.length === 0) {
@@ -8809,7 +8992,7 @@ class AdjacencyLayout {
8809
8992
  // place nodes according to arrangement
8810
8993
  const maximumWidth = Math.max(...model.nodes.map(n => n.width));
8811
8994
  const maximumHeight = Math.max(...model.nodes.map(n => n.height));
8812
- const gapSize = (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
8995
+ const gapSize = this.gapSize !== undefined ? this.gapSize : (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
8813
8996
  for (let y = nodeArrangement.minY(); y <= nodeArrangement.maxY(); ++y) {
8814
8997
  for (let x = nodeArrangement.minX(); x <= nodeArrangement.maxX(); ++x) {
8815
8998
  const node = nodeArrangement.get([x, y]);
@@ -8837,6 +9020,9 @@ const arrangeNode = (node, nodeArrangement, coords, nodesToBeArranged) => {
8837
9020
  * @public
8838
9021
  */
8839
9022
  class BreadthAdjacencyLayout {
9023
+ constructor(gapSize) {
9024
+ this.gapSize = gapSize;
9025
+ }
8840
9026
  apply(model) {
8841
9027
  var _a;
8842
9028
  if (model.nodes.length === 0) {
@@ -8874,7 +9060,7 @@ class BreadthAdjacencyLayout {
8874
9060
  // place nodes according to arrangement
8875
9061
  const maximumWidth = Math.max(...model.nodes.map(n => n.width));
8876
9062
  const maximumHeight = Math.max(...model.nodes.map(n => n.height));
8877
- const gapSize = (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
9063
+ const gapSize = this.gapSize !== undefined ? this.gapSize : (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
8878
9064
  for (let y = nodeArrangement.minY(); y <= nodeArrangement.maxY(); ++y) {
8879
9065
  for (let x = nodeArrangement.minX(); x <= nodeArrangement.maxX(); ++x) {
8880
9066
  const node = nodeArrangement.get([x, y]);
@@ -8892,13 +9078,16 @@ class BreadthAdjacencyLayout {
8892
9078
  * @public
8893
9079
  */
8894
9080
  class BreadthLayout {
9081
+ constructor(gapSize) {
9082
+ this.gapSize = gapSize;
9083
+ }
8895
9084
  apply(model) {
8896
9085
  var _a;
8897
9086
  if (model.nodes.length === 0) {
8898
9087
  // nothing to arrange...
8899
9088
  return model;
8900
9089
  }
8901
- const gapSize = (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
9090
+ const gapSize = this.gapSize !== undefined ? this.gapSize : (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
8902
9091
  let nodesToBeArranged = model.nodes.filter(n => !n.parent);
8903
9092
  // Arrange nodes by a breadth first search
8904
9093
  const firstNode = nodesToBeArranged[0];
@@ -8954,6 +9143,9 @@ class BreadthLayout {
8954
9143
  * @public
8955
9144
  */
8956
9145
  class ForceLayout {
9146
+ constructor(gapSize) {
9147
+ this.gapSize = gapSize;
9148
+ }
8957
9149
  apply(model) {
8958
9150
  var _a;
8959
9151
  if (model.nodes.length === 0) {
@@ -8962,7 +9154,7 @@ class ForceLayout {
8962
9154
  }
8963
9155
  // as a starting point, we apply a simple layout
8964
9156
  new BreadthLayout().apply(model);
8965
- const gapSize = (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
9157
+ const gapSize = this.gapSize !== undefined ? this.gapSize : (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
8966
9158
  const coolingFactor = 0.99;
8967
9159
  const minimumTemperature = 1;
8968
9160
  const attractionFactor = 0.1;
@@ -9049,13 +9241,16 @@ class ForceLayout {
9049
9241
  * @public
9050
9242
  */
9051
9243
  class HorizontalLayout {
9244
+ constructor(gapSize) {
9245
+ this.gapSize = gapSize;
9246
+ }
9052
9247
  apply(model) {
9053
9248
  var _a;
9054
9249
  if (model.nodes.length === 0) {
9055
9250
  // nothing to arrange...
9056
9251
  return model;
9057
9252
  }
9058
- const gapSize = (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
9253
+ const gapSize = this.gapSize !== undefined ? this.gapSize : (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
9059
9254
  const nodesToBeArranged = model.nodes.filter(n => !n.parent);
9060
9255
  nodesToBeArranged.sort((a, b) => b.type.priority - a.type.priority);
9061
9256
  let widthAccumulator = 0;
@@ -9072,6 +9267,9 @@ class HorizontalLayout {
9072
9267
  * @public
9073
9268
  */
9074
9269
  class PriorityLayout {
9270
+ constructor(gapSize) {
9271
+ this.gapSize = gapSize;
9272
+ }
9075
9273
  apply(model) {
9076
9274
  var _a;
9077
9275
  if (model.nodes.length === 0) {
@@ -9085,7 +9283,7 @@ class PriorityLayout {
9085
9283
  new BreadthLayout().apply(model);
9086
9284
  return model;
9087
9285
  }
9088
- const gapSize = (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
9286
+ const gapSize = this.gapSize !== undefined ? this.gapSize : (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
9089
9287
  const nodesToBeArranged = model.nodes.filter(n => !n.parent);
9090
9288
  const nodeArrangement = [];
9091
9289
  const nodesWithMaximumPriorityToBeArranged = model.nodes.filter(n => !n.parent).filter(n => n.getPriority() >= maximumPriority);
@@ -9179,6 +9377,9 @@ class PriorityLayout {
9179
9377
  * @public
9180
9378
  */
9181
9379
  class TreeLayout {
9380
+ constructor(gapSize) {
9381
+ this.gapSize = gapSize;
9382
+ }
9182
9383
  apply(model) {
9183
9384
  var _a;
9184
9385
  if (model.nodes.length === 0) {
@@ -9192,7 +9393,7 @@ class TreeLayout {
9192
9393
  new BreadthLayout().apply(model);
9193
9394
  return model;
9194
9395
  }
9195
- const gapSize = (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
9396
+ const gapSize = this.gapSize !== undefined ? this.gapSize : (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
9196
9397
  const nodesToBeArranged = model.nodes.filter(n => !n.parent).sort((n1, n2) => n2.getPriority() - n1.getPriority());
9197
9398
  const branches = [];
9198
9399
  while (nodesToBeArranged.length > 0) {
@@ -9277,13 +9478,16 @@ class Branch {
9277
9478
  * @public
9278
9479
  */
9279
9480
  class VerticalLayout {
9481
+ constructor(gapSize) {
9482
+ this.gapSize = gapSize;
9483
+ }
9280
9484
  apply(model) {
9281
9485
  var _a;
9282
9486
  if (model.nodes.length === 0) {
9283
9487
  // nothing to arrange...
9284
9488
  return model;
9285
9489
  }
9286
- const gapSize = (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
9490
+ const gapSize = this.gapSize !== undefined ? this.gapSize : (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
9287
9491
  const nodesToBeArranged = model.nodes.filter(n => !n.parent);
9288
9492
  nodesToBeArranged.sort((a, b) => b.type.priority - a.type.priority);
9289
9493
  let heightAccumulator = 0;
package/index.esm.js CHANGED
@@ -1670,10 +1670,8 @@ class ValueSet {
1670
1670
  this.values[key] = structuredClone(property.defaultValue);
1671
1671
  }
1672
1672
  if (rootAttribute !== undefined && rootAttribute !== null) {
1673
- if (property.defaultValue !== undefined && !equals(this.values[key], property.defaultValue)) {
1673
+ if (property.defaultValue !== undefined && !equals(this.getRootElementValue(rootAttribute), property.defaultValue)) {
1674
1674
  this.setRootElementValue(rootAttribute, this.values[key]);
1675
- } else {
1676
- this.values[key] = this.getRootElementValue(rootAttribute);
1677
1675
  }
1678
1676
  }
1679
1677
  if (property.basic) {
@@ -3139,15 +3137,15 @@ class DiagramNode extends DiagramElement {
3139
3137
  raise() {
3140
3138
  var _a;
3141
3139
  (_a = this.select()) === null || _a === undefined ? undefined : _a.raise();
3140
+ for (const section of this.sections) {
3141
+ section.raise();
3142
+ }
3142
3143
  if (this.label) {
3143
3144
  this.label.raise();
3144
3145
  }
3145
3146
  for (const port of this.ports) {
3146
3147
  port.raise();
3147
3148
  }
3148
- for (const section of this.sections) {
3149
- section.raise();
3150
- }
3151
3149
  for (const decorator of this.decorators) {
3152
3150
  decorator.raise();
3153
3151
  }
@@ -3581,6 +3579,106 @@ class DiagramNode extends DiagramElement {
3581
3579
  this.getConnections().forEach(c => c.tighten());
3582
3580
  this.updateInView();
3583
3581
  }
3582
+ /**
3583
+ * Removes all sections with the given index along the x axis.
3584
+ * @public
3585
+ */
3586
+ removeSectionColumn(columnIndex) {
3587
+ var _a;
3588
+ const margin = ((_a = this.type.sectionGrid) === null || _a === undefined ? undefined : _a.margin) || 0;
3589
+ let columnWidth = 0;
3590
+ const sections = [...this.sections];
3591
+ for (const section of sections) {
3592
+ if (section.indexYInNode === columnIndex) {
3593
+ columnWidth = Math.max(columnWidth, section.width);
3594
+ this.model.sections.remove(section.id);
3595
+ }
3596
+ }
3597
+ for (const section of sections) {
3598
+ if (section.indexYInNode > columnIndex) {
3599
+ --section.indexYInNode;
3600
+ section.move([section.coords[0] - columnWidth - margin, section.coords[1]]);
3601
+ }
3602
+ }
3603
+ this.stretch(Side.Right, -margin - columnWidth);
3604
+ }
3605
+ /**
3606
+ * Removes all sections with the given index along the y axis.
3607
+ * @public
3608
+ */
3609
+ removeSectionRow(rowIndex) {
3610
+ var _a;
3611
+ const margin = ((_a = this.type.sectionGrid) === null || _a === undefined ? undefined : _a.margin) || 0;
3612
+ let rowHeight = 0;
3613
+ const sections = [...this.sections];
3614
+ for (const section of sections) {
3615
+ if (section.indexXInNode === rowIndex) {
3616
+ rowHeight = Math.max(rowHeight, section.height);
3617
+ this.model.sections.remove(section.id);
3618
+ }
3619
+ }
3620
+ for (const section of sections) {
3621
+ if (section.indexYInNode > rowIndex) {
3622
+ --section.indexXInNode;
3623
+ section.move([section.coords[0], section.coords[1] - rowHeight - margin]);
3624
+ }
3625
+ }
3626
+ this.stretch(Side.Bottom, -margin - rowHeight);
3627
+ }
3628
+ /**
3629
+ * Creates a copy of all sections with the given index along the x axis.
3630
+ * @public
3631
+ */
3632
+ copySectionColumn(columnIndex) {
3633
+ var _a;
3634
+ const margin = ((_a = this.type.sectionGrid) === null || _a === undefined ? undefined : _a.margin) || 0;
3635
+ let columnWidth = 0;
3636
+ const sections = [...this.sections];
3637
+ for (const section of sections) {
3638
+ if (section.indexXInNode === columnIndex) {
3639
+ columnWidth = Math.max(columnWidth, section.width);
3640
+ let newSectionIdIndexX = section.indexXInNode + 1;
3641
+ while (this.model.sections.get(`${section.id}_copy_${newSectionIdIndexX}_${section.indexYInNode}`, true) !== undefined) {
3642
+ ++newSectionIdIndexX;
3643
+ }
3644
+ this.model.sections.new(this, section.indexXInNode + 1, section.indexYInNode, [section.coords[0] + section.width + margin, section.coords[1]], section.width, section.height, `${section.id}_copy_${newSectionIdIndexX}_${section.indexYInNode}`);
3645
+ }
3646
+ }
3647
+ for (const section of sections) {
3648
+ if (section.indexXInNode > columnIndex) {
3649
+ ++section.indexXInNode;
3650
+ section.move([section.coords[0] + columnWidth + margin, section.coords[1]]);
3651
+ }
3652
+ }
3653
+ this.stretch(Side.Right, margin + columnWidth);
3654
+ }
3655
+ /**
3656
+ * Creates a copy of all sections with the given index along the y axis.
3657
+ * @public
3658
+ */
3659
+ copySectionRow(rowIndex) {
3660
+ var _a;
3661
+ const margin = ((_a = this.type.sectionGrid) === null || _a === undefined ? undefined : _a.margin) || 0;
3662
+ let rowHeight = 0;
3663
+ const sections = [...this.sections];
3664
+ for (const section of sections) {
3665
+ if (section.indexYInNode === rowIndex) {
3666
+ rowHeight = Math.max(rowHeight, section.height);
3667
+ let newSectionIdIndexY = section.indexYInNode + 1;
3668
+ while (this.model.sections.get(`${section.id}_copy_${section.indexXInNode}_${newSectionIdIndexY}`, true) !== undefined) {
3669
+ ++newSectionIdIndexY;
3670
+ }
3671
+ this.model.sections.new(this, section.indexXInNode, section.indexYInNode + 1, [section.coords[0], section.coords[1] + section.height + margin], section.width, section.height, `${section.id}_copy_${section.indexXInNode}_${newSectionIdIndexY}`);
3672
+ }
3673
+ }
3674
+ for (const section of sections) {
3675
+ if (section.indexYInNode > rowIndex) {
3676
+ ++section.indexYInNode;
3677
+ section.move([section.coords[0], section.coords[1] + rowHeight + margin]);
3678
+ }
3679
+ }
3680
+ this.stretch(Side.Bottom, margin + rowHeight);
3681
+ }
3584
3682
  }
3585
3683
  class DiagramNodeSet extends DiagramElementSet {
3586
3684
  /**
@@ -4418,6 +4516,54 @@ class AddNodeCollabAction {
4418
4516
  return new AddNodeCollabAction(canvas, serialized.id, serialized.typeId, serialized.coords, serialized.parentId, serialized.label, serialized.values);
4419
4517
  }
4420
4518
  }
4519
+ /**
4520
+ * Collaborative action which consists of adding or removing sections in a node.
4521
+ * @private
4522
+ * @see AddNodeAction
4523
+ */
4524
+ class AddSectionCollabAction {
4525
+ constructor(canvas, nodeId, copyColumnIndex, copyRowIndex, removeColumnIndex, removeRowIndex, timestamp) {
4526
+ this.canvas = canvas;
4527
+ this.nodeId = nodeId;
4528
+ this.copyColumnIndex = copyColumnIndex;
4529
+ this.copyRowIndex = copyRowIndex;
4530
+ this.removeColumnIndex = removeColumnIndex;
4531
+ this.removeRowIndex = removeRowIndex;
4532
+ this.timestamp = timestamp;
4533
+ }
4534
+ do() {
4535
+ const node = this.canvas.model.nodes.get(this.nodeId);
4536
+ if (node && timestampWins(this.timestamp, node.geometryTimestamp)) {
4537
+ if (this.copyColumnIndex !== undefined) {
4538
+ node.copySectionColumn(this.copyColumnIndex);
4539
+ }
4540
+ if (this.copyRowIndex !== undefined) {
4541
+ node.copySectionRow(this.copyRowIndex);
4542
+ }
4543
+ if (this.removeColumnIndex !== undefined) {
4544
+ node.removeSectionColumn(this.removeColumnIndex);
4545
+ }
4546
+ if (this.removeRowIndex !== undefined) {
4547
+ node.removeSectionRow(this.removeRowIndex);
4548
+ }
4549
+ node.geometryTimestamp = this.timestamp;
4550
+ }
4551
+ }
4552
+ serialize() {
4553
+ return {
4554
+ type: 'addSection',
4555
+ nodeId: this.nodeId,
4556
+ copyColumnIndex: this.copyColumnIndex,
4557
+ copyRowIndex: this.copyRowIndex,
4558
+ removeColumnIndex: this.removeColumnIndex,
4559
+ removeRowIndex: this.removeRowIndex,
4560
+ timestamp: this.timestamp
4561
+ };
4562
+ }
4563
+ static deserialize(canvas, serialized) {
4564
+ return new AddSectionCollabAction(canvas, serialized.nodeId, serialized.copyColumnIndex, serialized.copyRowIndex, serialized.removeColumnIndex, serialized.removeRowIndex, serialized.timestamp);
4565
+ }
4566
+ }
4421
4567
  /**
4422
4568
  * Collaborative which consists of applying a layout to the diagram which can change the location of several nodes.
4423
4569
  * @private
@@ -4834,6 +4980,12 @@ class CollabEngine {
4834
4980
  action.do();
4835
4981
  break;
4836
4982
  }
4983
+ case 'addSection':
4984
+ {
4985
+ const action = AddSectionCollabAction.deserialize(this.canvas, message);
4986
+ action.do();
4987
+ break;
4988
+ }
4837
4989
  case 'applyLayout':
4838
4990
  {
4839
4991
  const action = ApplyLayoutCollabAction.deserialize(this.canvas, message);
@@ -4996,6 +5148,12 @@ var DiagramActions;
4996
5148
  * @see AddNodeAction
4997
5149
  */
4998
5150
  DiagramActions["AddNode"] = "add-node";
5151
+ /**
5152
+ * Action that corresponds to the addition or removal of sections in a node.
5153
+ * @public
5154
+ * @see AddSectionAction
5155
+ */
5156
+ DiagramActions["AddSectionAction"] = "add-section";
4999
5157
  /**
5000
5158
  * Action that corresponds to applying a layout which changes the location of several nodes.
5001
5159
  * @public
@@ -7970,7 +8128,7 @@ class DiagramCanvas {
7970
8128
  }
7971
8129
  updateConnectionLabelsInView(connection) {
7972
8130
  var _a, _b, _c;
7973
- const connectionSelection = this.selectCanvasView().select(`g.diagram-connection#${connection.id}`);
8131
+ const connectionSelection = this.selectCanvasView().select(`[id='${escapeSelector(connection.id)}']`);
7974
8132
  const pathSelection = connectionSelection.select('path');
7975
8133
  const pathNode = pathSelection.node();
7976
8134
  const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), connection.type.label);
@@ -8012,7 +8170,7 @@ class DiagramCanvas {
8012
8170
  }
8013
8171
  }
8014
8172
  updateConnectionMarkersInView(connection) {
8015
- const connectionSelection = this.selectCanvasView().select(`g.diagram-connection#${connection.id}`);
8173
+ const connectionSelection = this.selectCanvasView().select(`[id='${escapeSelector(connection.id)}']`);
8016
8174
  const startMarkerSelection = connectionSelection.select('marker.diagram-connection-start-marker');
8017
8175
  const endMarkerSelection = connectionSelection.select('marker.diagram-connection-end-marker');
8018
8176
  if (connection.startMarkerLook !== null) {
@@ -8026,13 +8184,27 @@ class DiagramCanvas {
8026
8184
  endMarkerSelection.attr('orient', 'auto-start-reverse').attr('markerWidth', 0).attr('markerHeight', 0);
8027
8185
  }
8028
8186
  }
8029
- fitFieldRootInView(id) {
8187
+ fieldRootFitsInView(id) {
8188
+ var _a, _b, _c, _d;
8189
+ const field = this.model.fields.get(id);
8190
+ if (!field) {
8191
+ return false;
8192
+ }
8193
+ if (field.rootElement instanceof DiagramNode || field.rootElement instanceof DiagramSection) {
8194
+ const fieldDimensions = this.minimumSizeOfField(field);
8195
+ const stretchX = fieldDimensions[0] + getLeftMargin((_a = field.rootElement.type) === null || _a === undefined ? undefined : _a.label) + getRightMargin((_b = field.rootElement.type) === null || _b === undefined ? undefined : _b.label) - field.rootElement.width;
8196
+ const stretchY = fieldDimensions[1] + getTopMargin((_c = field.rootElement.type) === null || _c === undefined ? undefined : _c.label) + getBottomMargin((_d = field.rootElement.type) === null || _d === undefined ? undefined : _d.label) - field.rootElement.height;
8197
+ return stretchX <= 0 && stretchY <= 0;
8198
+ }
8199
+ return true;
8200
+ }
8201
+ fitFieldRootInView(id, shrink) {
8030
8202
  var _a, _b, _c;
8031
8203
  const field = this.model.fields.get(id);
8032
8204
  if (!field) {
8033
8205
  return;
8034
8206
  }
8035
- if (field.rootElement instanceof DiagramNode && field.fit) {
8207
+ if (field.rootElement instanceof DiagramNode) {
8036
8208
  const fieldDimensions = this.minimumSizeOfField(field);
8037
8209
  let stretchX = fieldDimensions[0] + getLeftMargin(field.rootElement.type.label) + getRightMargin(field.rootElement.type.label) - field.rootElement.width;
8038
8210
  let stretchY = fieldDimensions[1] + getTopMargin(field.rootElement.type.label) + getBottomMargin(field.rootElement.type.label) - field.rootElement.height;
@@ -8047,10 +8219,14 @@ class DiagramCanvas {
8047
8219
  if (field.rootElement.height + stretchY < field.rootElement.type.minHeight) {
8048
8220
  stretchY = field.rootElement.type.minHeight - field.rootElement.height;
8049
8221
  }
8050
- field.rootElement.stretch(Side.Right, stretchX);
8051
- field.rootElement.stretch(Side.Bottom, stretchY);
8222
+ if (shrink !== false || stretchX > 0) {
8223
+ field.rootElement.stretch(Side.Right, stretchX);
8224
+ }
8225
+ if (shrink !== false || stretchY > 0) {
8226
+ field.rootElement.stretch(Side.Bottom, stretchY);
8227
+ }
8052
8228
  }
8053
- if (field.rootElement instanceof DiagramSection && field.fit) {
8229
+ if (field.rootElement instanceof DiagramSection) {
8054
8230
  const fieldDimensions = this.minimumSizeOfField(field);
8055
8231
  let minimumFieldWidth = fieldDimensions[0];
8056
8232
  let minimumFieldHeight = fieldDimensions[1];
@@ -8083,8 +8259,12 @@ class DiagramCanvas {
8083
8259
  if (field.rootElement.height + stretchY < (field.rootElement.getMinHeight() || 0)) {
8084
8260
  stretchY = (field.rootElement.getMinHeight() || 0) - field.rootElement.height;
8085
8261
  }
8086
- (_b = field.rootElement.node) === null || _b === undefined ? undefined : _b.stretchSections(Side.Right, stretchX, field.rootElement.indexXInNode, field.rootElement.indexYInNode);
8087
- (_c = field.rootElement.node) === null || _c === undefined ? undefined : _c.stretchSections(Side.Bottom, stretchY, field.rootElement.indexXInNode, field.rootElement.indexYInNode);
8262
+ if (shrink !== false || stretchX > 0) {
8263
+ (_b = field.rootElement.node) === null || _b === undefined ? undefined : _b.stretchSections(Side.Right, stretchX, field.rootElement.indexXInNode, field.rootElement.indexYInNode);
8264
+ }
8265
+ if (shrink !== false || stretchY > 0) {
8266
+ (_c = field.rootElement.node) === null || _c === undefined ? undefined : _c.stretchSections(Side.Bottom, stretchY, field.rootElement.indexXInNode, field.rootElement.indexYInNode);
8267
+ }
8088
8268
  }
8089
8269
  }
8090
8270
  fitNodeInView(id) {
@@ -8773,6 +8953,9 @@ class Grid {
8773
8953
  * @public
8774
8954
  */
8775
8955
  class AdjacencyLayout {
8956
+ constructor(gapSize) {
8957
+ this.gapSize = gapSize;
8958
+ }
8776
8959
  apply(model) {
8777
8960
  var _a;
8778
8961
  if (model.nodes.length === 0) {
@@ -8788,7 +8971,7 @@ class AdjacencyLayout {
8788
8971
  // place nodes according to arrangement
8789
8972
  const maximumWidth = Math.max(...model.nodes.map(n => n.width));
8790
8973
  const maximumHeight = Math.max(...model.nodes.map(n => n.height));
8791
- const gapSize = (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
8974
+ const gapSize = this.gapSize !== undefined ? this.gapSize : (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
8792
8975
  for (let y = nodeArrangement.minY(); y <= nodeArrangement.maxY(); ++y) {
8793
8976
  for (let x = nodeArrangement.minX(); x <= nodeArrangement.maxX(); ++x) {
8794
8977
  const node = nodeArrangement.get([x, y]);
@@ -8816,6 +8999,9 @@ const arrangeNode = (node, nodeArrangement, coords, nodesToBeArranged) => {
8816
8999
  * @public
8817
9000
  */
8818
9001
  class BreadthAdjacencyLayout {
9002
+ constructor(gapSize) {
9003
+ this.gapSize = gapSize;
9004
+ }
8819
9005
  apply(model) {
8820
9006
  var _a;
8821
9007
  if (model.nodes.length === 0) {
@@ -8853,7 +9039,7 @@ class BreadthAdjacencyLayout {
8853
9039
  // place nodes according to arrangement
8854
9040
  const maximumWidth = Math.max(...model.nodes.map(n => n.width));
8855
9041
  const maximumHeight = Math.max(...model.nodes.map(n => n.height));
8856
- const gapSize = (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
9042
+ const gapSize = this.gapSize !== undefined ? this.gapSize : (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
8857
9043
  for (let y = nodeArrangement.minY(); y <= nodeArrangement.maxY(); ++y) {
8858
9044
  for (let x = nodeArrangement.minX(); x <= nodeArrangement.maxX(); ++x) {
8859
9045
  const node = nodeArrangement.get([x, y]);
@@ -8871,13 +9057,16 @@ class BreadthAdjacencyLayout {
8871
9057
  * @public
8872
9058
  */
8873
9059
  class BreadthLayout {
9060
+ constructor(gapSize) {
9061
+ this.gapSize = gapSize;
9062
+ }
8874
9063
  apply(model) {
8875
9064
  var _a;
8876
9065
  if (model.nodes.length === 0) {
8877
9066
  // nothing to arrange...
8878
9067
  return model;
8879
9068
  }
8880
- const gapSize = (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
9069
+ const gapSize = this.gapSize !== undefined ? this.gapSize : (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
8881
9070
  let nodesToBeArranged = model.nodes.filter(n => !n.parent);
8882
9071
  // Arrange nodes by a breadth first search
8883
9072
  const firstNode = nodesToBeArranged[0];
@@ -8933,6 +9122,9 @@ class BreadthLayout {
8933
9122
  * @public
8934
9123
  */
8935
9124
  class ForceLayout {
9125
+ constructor(gapSize) {
9126
+ this.gapSize = gapSize;
9127
+ }
8936
9128
  apply(model) {
8937
9129
  var _a;
8938
9130
  if (model.nodes.length === 0) {
@@ -8941,7 +9133,7 @@ class ForceLayout {
8941
9133
  }
8942
9134
  // as a starting point, we apply a simple layout
8943
9135
  new BreadthLayout().apply(model);
8944
- const gapSize = (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
9136
+ const gapSize = this.gapSize !== undefined ? this.gapSize : (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
8945
9137
  const coolingFactor = 0.99;
8946
9138
  const minimumTemperature = 1;
8947
9139
  const attractionFactor = 0.1;
@@ -9028,13 +9220,16 @@ class ForceLayout {
9028
9220
  * @public
9029
9221
  */
9030
9222
  class HorizontalLayout {
9223
+ constructor(gapSize) {
9224
+ this.gapSize = gapSize;
9225
+ }
9031
9226
  apply(model) {
9032
9227
  var _a;
9033
9228
  if (model.nodes.length === 0) {
9034
9229
  // nothing to arrange...
9035
9230
  return model;
9036
9231
  }
9037
- const gapSize = (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
9232
+ const gapSize = this.gapSize !== undefined ? this.gapSize : (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
9038
9233
  const nodesToBeArranged = model.nodes.filter(n => !n.parent);
9039
9234
  nodesToBeArranged.sort((a, b) => b.type.priority - a.type.priority);
9040
9235
  let widthAccumulator = 0;
@@ -9051,6 +9246,9 @@ class HorizontalLayout {
9051
9246
  * @public
9052
9247
  */
9053
9248
  class PriorityLayout {
9249
+ constructor(gapSize) {
9250
+ this.gapSize = gapSize;
9251
+ }
9054
9252
  apply(model) {
9055
9253
  var _a;
9056
9254
  if (model.nodes.length === 0) {
@@ -9064,7 +9262,7 @@ class PriorityLayout {
9064
9262
  new BreadthLayout().apply(model);
9065
9263
  return model;
9066
9264
  }
9067
- const gapSize = (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
9265
+ const gapSize = this.gapSize !== undefined ? this.gapSize : (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
9068
9266
  const nodesToBeArranged = model.nodes.filter(n => !n.parent);
9069
9267
  const nodeArrangement = [];
9070
9268
  const nodesWithMaximumPriorityToBeArranged = model.nodes.filter(n => !n.parent).filter(n => n.getPriority() >= maximumPriority);
@@ -9158,6 +9356,9 @@ class PriorityLayout {
9158
9356
  * @public
9159
9357
  */
9160
9358
  class TreeLayout {
9359
+ constructor(gapSize) {
9360
+ this.gapSize = gapSize;
9361
+ }
9161
9362
  apply(model) {
9162
9363
  var _a;
9163
9364
  if (model.nodes.length === 0) {
@@ -9171,7 +9372,7 @@ class TreeLayout {
9171
9372
  new BreadthLayout().apply(model);
9172
9373
  return model;
9173
9374
  }
9174
- const gapSize = (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
9375
+ const gapSize = this.gapSize !== undefined ? this.gapSize : (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
9175
9376
  const nodesToBeArranged = model.nodes.filter(n => !n.parent).sort((n1, n2) => n2.getPriority() - n1.getPriority());
9176
9377
  const branches = [];
9177
9378
  while (nodesToBeArranged.length > 0) {
@@ -9256,13 +9457,16 @@ class Branch {
9256
9457
  * @public
9257
9458
  */
9258
9459
  class VerticalLayout {
9460
+ constructor(gapSize) {
9461
+ this.gapSize = gapSize;
9462
+ }
9259
9463
  apply(model) {
9260
9464
  var _a;
9261
9465
  if (model.nodes.length === 0) {
9262
9466
  // nothing to arrange...
9263
9467
  return model;
9264
9468
  }
9265
- const gapSize = (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
9469
+ const gapSize = this.gapSize !== undefined ? this.gapSize : (((_a = model.canvas) === null || _a === undefined ? undefined : _a.gridSize) || 0) * 2;
9266
9470
  const nodesToBeArranged = model.nodes.filter(n => !n.parent);
9267
9471
  nodesToBeArranged.sort((a, b) => b.type.priority - a.type.priority);
9268
9472
  let heightAccumulator = 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metadev/daga",
3
- "version": "4.0.2",
3
+ "version": "4.1.0",
4
4
  "dependencies": {},
5
5
  "peerDependencies": {
6
6
  "d3": "^7.9.0",
@@ -116,7 +116,8 @@ export declare class DiagramCanvas implements Canvas {
116
116
  updateDecoratorsInView(...ids: string[]): void;
117
117
  private updateConnectionLabelsInView;
118
118
  private updateConnectionMarkersInView;
119
- fitFieldRootInView(id: string): void;
119
+ fieldRootFitsInView(id: string): boolean;
120
+ fitFieldRootInView(id: string, shrink?: boolean): void;
120
121
  fitNodeInView(id: string): void;
121
122
  selectRoot(): d3.Selection<HTMLDivElement, unknown, null, unknown>;
122
123
  selectSVGElement(): d3.Selection<SVGElement, unknown, null, unknown>;
@@ -32,7 +32,7 @@ export interface CollabAction {
32
32
  /**
33
33
  * @private
34
34
  */
35
- export type CollabActionSerialized = AddNodeSerialized | ApplyLayoutSerialized | MoveSerialized | SetGeometrySerialized | SetParentSerialized | AddConnectionSerialized | EditFieldSerialized | UpdateValuesSerialized | SetSelfRemovedSerialized | PasteSerialized;
35
+ export type CollabActionSerialized = AddNodeSerialized | AddSectionSerialized | ApplyLayoutSerialized | MoveSerialized | SetGeometrySerialized | SetParentSerialized | AddConnectionSerialized | EditFieldSerialized | UpdateValuesSerialized | SetSelfRemovedSerialized | PasteSerialized;
36
36
  /**
37
37
  * @private
38
38
  */
@@ -69,6 +69,36 @@ export declare class AddNodeCollabAction implements CollabAction {
69
69
  serialize(): AddNodeSerialized;
70
70
  static deserialize(canvas: Canvas, serialized: AddNodeSerialized): AddNodeCollabAction;
71
71
  }
72
+ /**
73
+ * @private
74
+ */
75
+ export type AddSectionSerialized = {
76
+ type: 'addSection';
77
+ nodeId: string;
78
+ copyColumnIndex: number | undefined;
79
+ copyRowIndex: number | undefined;
80
+ removeColumnIndex: number | undefined;
81
+ removeRowIndex: number | undefined;
82
+ timestamp: CollabTimestamp;
83
+ };
84
+ /**
85
+ * Collaborative action which consists of adding or removing sections in a node.
86
+ * @private
87
+ * @see AddNodeAction
88
+ */
89
+ export declare class AddSectionCollabAction implements CollabAction {
90
+ readonly canvas: Canvas;
91
+ readonly nodeId: string;
92
+ readonly copyColumnIndex: number | undefined;
93
+ readonly copyRowIndex: number | undefined;
94
+ readonly removeColumnIndex: number | undefined;
95
+ readonly removeRowIndex: number | undefined;
96
+ readonly timestamp: CollabTimestamp;
97
+ constructor(canvas: Canvas, nodeId: string, copyColumnIndex: number | undefined, copyRowIndex: number | undefined, removeColumnIndex: number | undefined, removeRowIndex: number | undefined, timestamp: CollabTimestamp);
98
+ do(): void;
99
+ serialize(): AddSectionSerialized;
100
+ static deserialize(canvas: Canvas, serialized: AddSectionSerialized): AddSectionCollabAction;
101
+ }
72
102
  /**
73
103
  * @private
74
104
  */
@@ -3,8 +3,8 @@ import { HorizontalAlign, Side, VerticalAlign } from '../../util/svg-util';
3
3
  import { DiagramActions } from '../diagram-action';
4
4
  import { Property } from '../property/property';
5
5
  import { CanvasConfig } from './diagram-canvas-config';
6
- import { ConnectionLookConfig, ImageLookConfig, MarkerImageLookConfig, ShapedLookConfig, StretchableImageLookConfig } from './diagram-look-config';
7
6
  import { ComponentsConfig } from './diagram-components-config';
7
+ import { ConnectionLookConfig, ImageLookConfig, MarkerImageLookConfig, ShapedLookConfig, StretchableImageLookConfig } from './diagram-look-config';
8
8
  /**
9
9
  * The configuration for a diagram.
10
10
  * @public
@@ -102,6 +102,12 @@ export declare enum DiagramActions {
102
102
  * @see AddNodeAction
103
103
  */
104
104
  AddNode = "add-node",
105
+ /**
106
+ * Action that corresponds to the addition or removal of sections in a node.
107
+ * @public
108
+ * @see AddSectionAction
109
+ */
110
+ AddSectionAction = "add-section",
105
111
  /**
106
112
  * Action that corresponds to applying a layout which changes the location of several nodes.
107
113
  * @public
@@ -192,6 +198,23 @@ export declare class AddNodeAction implements DiagramAction {
192
198
  undo(): boolean;
193
199
  redo(): boolean;
194
200
  }
201
+ /**
202
+ * Action which consists of adding or removing sections in a node.
203
+ * @private
204
+ * @see DiagramSection
205
+ */
206
+ export declare class AddSectionAction implements DiagramAction {
207
+ readonly canvas: Canvas;
208
+ nodeId: string;
209
+ copyColumnIndex: number | undefined;
210
+ copyRowIndex: number | undefined;
211
+ removeColumnIndex: number | undefined;
212
+ removeRowIndex: number | undefined;
213
+ constructor(canvas: Canvas, nodeId: string, copyColumnIndex: number | undefined, copyRowIndex: number | undefined, removeColumnIndex: number | undefined, removeRowIndex: number | undefined);
214
+ do(): boolean;
215
+ undo(): boolean;
216
+ redo(): boolean;
217
+ }
195
218
  /**
196
219
  * Action which consists of applying a layout to the diagram which can change the location of several nodes.
197
220
  * @private
@@ -5,5 +5,7 @@ import { DiagramLayout } from './diagram-layout';
5
5
  * @public
6
6
  */
7
7
  export declare class AdjacencyLayout implements DiagramLayout {
8
+ gapSize?: number;
9
+ constructor(gapSize?: number);
8
10
  apply(model: DiagramModel): DiagramModel;
9
11
  }
@@ -5,5 +5,7 @@ import { DiagramLayout } from './diagram-layout';
5
5
  * @public
6
6
  */
7
7
  export declare class BreadthAdjacencyLayout implements DiagramLayout {
8
+ gapSize?: number;
9
+ constructor(gapSize?: number);
8
10
  apply(model: DiagramModel): DiagramModel;
9
11
  }
@@ -5,5 +5,7 @@ import { DiagramLayout } from './diagram-layout';
5
5
  * @public
6
6
  */
7
7
  export declare class BreadthLayout implements DiagramLayout {
8
+ gapSize?: number;
9
+ constructor(gapSize?: number);
8
10
  apply(model: DiagramModel): DiagramModel;
9
11
  }
@@ -5,5 +5,7 @@ import { DiagramLayout } from './diagram-layout';
5
5
  * @public
6
6
  */
7
7
  export declare class ForceLayout implements DiagramLayout {
8
+ gapSize?: number;
9
+ constructor(gapSize?: number);
8
10
  apply(model: DiagramModel): DiagramModel;
9
11
  }
@@ -5,5 +5,7 @@ import { DiagramLayout } from './diagram-layout';
5
5
  * @public
6
6
  */
7
7
  export declare class HorizontalLayout implements DiagramLayout {
8
+ gapSize?: number;
9
+ constructor(gapSize?: number);
8
10
  apply(model: DiagramModel): DiagramModel;
9
11
  }
@@ -5,5 +5,7 @@ import { DiagramLayout } from './diagram-layout';
5
5
  * @public
6
6
  */
7
7
  export declare class PriorityLayout implements DiagramLayout {
8
+ gapSize?: number;
9
+ constructor(gapSize?: number);
8
10
  apply(model: DiagramModel): DiagramModel;
9
11
  }
@@ -5,5 +5,7 @@ import { DiagramLayout } from './diagram-layout';
5
5
  * @public
6
6
  */
7
7
  export declare class TreeLayout implements DiagramLayout {
8
+ gapSize?: number;
9
+ constructor(gapSize?: number);
8
10
  apply(model: DiagramModel): DiagramModel;
9
11
  }
@@ -5,5 +5,7 @@ import { DiagramLayout } from './diagram-layout';
5
5
  * @public
6
6
  */
7
7
  export declare class VerticalLayout implements DiagramLayout {
8
+ gapSize?: number;
9
+ constructor(gapSize?: number);
8
10
  apply(model: DiagramModel): DiagramModel;
9
11
  }
@@ -276,6 +276,26 @@ export declare class DiagramNode extends DiagramElement implements LabeledElemen
276
276
  * @public
277
277
  */
278
278
  setGeometry(geometry: DiagramNodeGeometry): void;
279
+ /**
280
+ * Removes all sections with the given index along the x axis.
281
+ * @public
282
+ */
283
+ removeSectionColumn(columnIndex: number): void;
284
+ /**
285
+ * Removes all sections with the given index along the y axis.
286
+ * @public
287
+ */
288
+ removeSectionRow(rowIndex: number): void;
289
+ /**
290
+ * Creates a copy of all sections with the given index along the x axis.
291
+ * @public
292
+ */
293
+ copySectionColumn(columnIndex: number): void;
294
+ /**
295
+ * Creates a copy of all sections with the given index along the y axis.
296
+ * @public
297
+ */
298
+ copySectionRow(rowIndex: number): void;
279
299
  }
280
300
  export declare class DiagramNodeSet extends DiagramElementSet<DiagramNode> {
281
301
  private model;
@@ -284,11 +284,18 @@ export interface Canvas {
284
284
  * @public
285
285
  */
286
286
  updateDecoratorsInView(...ids: string[]): void;
287
+ /**
288
+ * Checks whether the root of a diagram field encompasses the totality of the field.
289
+ * @param id The id of a diagram field
290
+ * @returns `true` if the root of a diagram field encompasses the totality of the field, `false` otherwise.
291
+ */
292
+ fieldRootFitsInView(id: string): boolean;
287
293
  /**
288
294
  * Fit the root of a diagram field to encompass the totality of the field.
289
295
  * @param id The id of a diagram field
296
+ * @param shrink Whether the root of the diagram field should shrink if there is excess space; `true` by default
290
297
  */
291
- fitFieldRootInView(id: string): void;
298
+ fitFieldRootInView(id: string, shrink?: boolean): void;
292
299
  /**
293
300
  * Fit a node to encompass the totality of its sections.
294
301
  * @param id The id of a node