@metadev/daga 3.1.4 → 3.1.5

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,8 +6,22 @@ List of releases and changes.
6
6
 
7
7
  ## Next release Joyeuse
8
8
 
9
+ ## v. 3.1.5
10
+
11
+ Date: _2025-02-07_
12
+
13
+ - Fix bug with the initial loading of a diagram not working [#226](https://github.com/metadevpro/daga/pull/226)
14
+ - Ensure that the parent element of a diagram has fully loaded before initializing the view [#226](https://github.com/metadevpro/daga/pull/226)
15
+ - Ensure that the elements of a diagram are rendered in the correct order after importing a diagram [#228](https://github.com/metadevpro/daga/pull/228)
16
+ - Add port directionality such that ports can be configured as only allowing incoming connections or only allowing outgoing connections [#229](https://github.com/metadevpro/daga/pull/229)
17
+ - Add port types and enable configuring the look of ports and the start/end point of connections within the port [#230](https://github.com/metadevpro/daga/pull/230)
18
+ - Fix bug where the close icons for some property editor inputs wasn't showing [#231](https://github.com/metadevpro/daga/pull/231)
19
+ - Enable configuring the labels of ports [#233](https://github.com/metadevpro/daga/pull/233)
20
+
9
21
  ## v. 3.1.4
10
22
 
23
+ Date: _2025-01-30_
24
+
11
25
  - Make dragging the palette node templates create a clone of the node appended to the diagram root instead of a child of the palette to prevent the palette from being affected by CSS transforms on the diagram [#224](https://github.com/metadevpro/daga/pull/224)
12
26
 
13
27
  ## v. 3.1.3
package/index.cjs.js CHANGED
@@ -1788,11 +1788,11 @@ class DiagramConnection extends DiagramElement {
1788
1788
  if (start !== undefined) {
1789
1789
  start.outgoingConnections.push(this);
1790
1790
  this.startDirection = start === null || start === undefined ? undefined : start.direction;
1791
- this.startCoords = (start === null || start === undefined ? undefined : start.coords) || [0, 0];
1791
+ this.startCoords = (start === null || start === undefined ? undefined : start.connectionPoint) || [0, 0];
1792
1792
  }
1793
1793
  } else {
1794
1794
  this.startDirection = start === null || start === undefined ? undefined : start.direction;
1795
- this.startCoords = (start === null || start === undefined ? undefined : start.coords) || [0, 0];
1795
+ this.startCoords = (start === null || start === undefined ? undefined : start.connectionPoint) || [0, 0];
1796
1796
  }
1797
1797
  this.updateInView();
1798
1798
  }
@@ -1811,11 +1811,11 @@ class DiagramConnection extends DiagramElement {
1811
1811
  if (end !== undefined) {
1812
1812
  end.incomingConnections.push(this);
1813
1813
  this.endDirection = end === null || end === undefined ? undefined : end.direction;
1814
- this.endCoords = (end === null || end === undefined ? undefined : end.coords) || [0, 0];
1814
+ this.endCoords = (end === null || end === undefined ? undefined : end.connectionPoint) || [0, 0];
1815
1815
  }
1816
1816
  } else {
1817
1817
  this.endDirection = end === null || end === undefined ? undefined : end.direction;
1818
- this.endCoords = (end === null || end === undefined ? undefined : end.coords) || [0, 0];
1818
+ this.endCoords = (end === null || end === undefined ? undefined : end.connectionPoint) || [0, 0];
1819
1819
  }
1820
1820
  this.updateInView();
1821
1821
  }
@@ -1833,6 +1833,10 @@ class DiagramConnection extends DiagramElement {
1833
1833
  // alternative start port not valid, it is the same as the end port
1834
1834
  continue checkAlternativeStartPorts;
1835
1835
  }
1836
+ if (!alternativeStartPort.allowsOutgoing) {
1837
+ // alternative start port not valid, it doesn't allow outgoing connections
1838
+ continue checkAlternativeStartPorts;
1839
+ }
1836
1840
  {
1837
1841
  for (const connection of alternativeStartPort.outgoingConnections) {
1838
1842
  if (connection !== this && connection.end === this.end) {
@@ -1860,24 +1864,28 @@ class DiagramConnection extends DiagramElement {
1860
1864
  const alternativeEndPortsSortedByDistanceAscending = this.end.rootElement.ports.map(p => [p, p.distanceTo(this.start.coords)]).sort((a, b) => a[1] - b[1]).map(a => a[0]);
1861
1865
  checkAlternativeEndPorts: for (const alternativeEndPort of alternativeEndPortsSortedByDistanceAscending) {
1862
1866
  if (alternativeEndPort === this.start) {
1863
- // alternative start port not valid, it is the same as the end port
1867
+ // alternative end port not valid, it is the same as the end port
1868
+ continue checkAlternativeEndPorts;
1869
+ }
1870
+ if (!alternativeEndPort.allowsIncoming) {
1871
+ // alternative end port not valid, it doesn't allow incoming connections
1864
1872
  continue checkAlternativeEndPorts;
1865
1873
  }
1866
1874
  {
1867
1875
  for (const connection of alternativeEndPort.incomingConnections) {
1868
1876
  if (connection !== this && connection.start === this.start) {
1869
- // alternative start port not valid, there is a connection whose start and end matches the alternative end port and this connection's start
1877
+ // alternative end port not valid, there is a connection whose start and end matches the alternative end port and this connection's start
1870
1878
  continue checkAlternativeEndPorts;
1871
1879
  }
1872
1880
  }
1873
1881
  for (const connection of alternativeEndPort.outgoingConnections) {
1874
1882
  if (connection !== this && connection.end === this.start) {
1875
- // alternative start port not valid, there is a connection whose start and end matches the alternative end port and this connection's start
1883
+ // alternative end port not valid, there is a connection whose start and end matches the alternative end port and this connection's start
1876
1884
  continue checkAlternativeEndPorts;
1877
1885
  }
1878
1886
  }
1879
1887
  }
1880
- // found a valid start port
1888
+ // found a valid end port
1881
1889
  if (alternativeEndPort === this.end) {
1882
1890
  break checkAlternativeEndPorts;
1883
1891
  } else {
@@ -2579,25 +2587,25 @@ class DiagramSectionSet extends DiagramElementSet {
2579
2587
  if (sectionPorts && sectionPorts.length > 0) {
2580
2588
  for (let i = 0; i < sectionPorts.length; ++i) {
2581
2589
  const portConfig = sectionPorts[i];
2582
- const port = this.model.ports.new(section, [section.coords[0] + (((_e = portConfig === null || portConfig === undefined ? undefined : portConfig.coords) === null || _e === undefined ? undefined : _e[0]) || 0), section.coords[1] + (((_f = portConfig === null || portConfig === undefined ? undefined : portConfig.coords) === null || _f === undefined ? undefined : _f[1]) || 0)], portConfig === null || portConfig === undefined ? undefined : portConfig.direction, `${section.id}_${i}`);
2583
- if (portConfig.label) {
2584
- const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), portConfig.label);
2590
+ const port = this.model.ports.new(portConfig.type !== undefined ? this.model.ports.types.get(portConfig.type) : undefined, section, [section.coords[0] + (portConfig.coords[0] || 0), section.coords[1] + (portConfig.coords[1] || 0)], portConfig.connectionPoint !== undefined ? [section.coords[0] + (portConfig.connectionPoint[0] || 0), section.coords[1] + (portConfig.connectionPoint[1] || 0)] : undefined, portConfig === null || portConfig === undefined ? undefined : portConfig.direction, `${section.id}_${i}`);
2591
+ if ((_e = port.type) === null || _e === undefined ? undefined : _e.label) {
2592
+ const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), (_f = port.type) === null || _f === undefined ? undefined : _f.label);
2593
+ const labelWidth = 6 * labelConfiguration.fontSize + getLeftPadding$1(labelConfiguration) + getRightPadding$1(labelConfiguration);
2594
+ const labelHeight = labelConfiguration.fontSize + getTopPadding$1(labelConfiguration) + getBottomPadding$1(labelConfiguration);
2585
2595
  let labelCoords;
2586
2596
  switch (port.direction) {
2587
- case exports.Side.Top:
2588
- case exports.Side.Left:
2589
- labelCoords = [port.coords[0] - labelConfiguration.fontSize, port.coords[1] - labelConfiguration.fontSize];
2590
- break;
2591
2597
  case exports.Side.Bottom:
2592
- labelCoords = [port.coords[0] - labelConfiguration.fontSize, port.coords[1] + labelConfiguration.fontSize];
2593
- break;
2598
+ case exports.Side.Left:
2594
2599
  case exports.Side.Right:
2595
- labelCoords = [port.coords[0] + labelConfiguration.fontSize, port.coords[1] - labelConfiguration.fontSize];
2600
+ labelCoords = [port.coords[0] - labelWidth / 2, port.coords[1] - labelHeight - getBottomMargin(labelConfiguration)];
2601
+ break;
2602
+ case exports.Side.Top:
2603
+ labelCoords = [port.coords[0] - labelWidth / 2, port.coords[1] + getTopMargin(labelConfiguration)];
2596
2604
  break;
2597
2605
  default:
2598
2606
  labelCoords = port.coords;
2599
2607
  }
2600
- this.model.fields.new(port, labelCoords, labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelConfiguration.fontSize, labelConfiguration.fontSize, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, '', labelConfiguration.editable, labelConfiguration.fit);
2608
+ this.model.fields.new(port, labelCoords, labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelWidth, labelHeight, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, '', labelConfiguration.editable, labelConfiguration.fit);
2601
2609
  }
2602
2610
  }
2603
2611
  }
@@ -3234,7 +3242,7 @@ class DiagramNodeSet extends DiagramElementSet {
3234
3242
  * @returns The instanced node.
3235
3243
  */
3236
3244
  new(type, coords, id) {
3237
- var _a, _b, _c, _d, _e;
3245
+ var _a, _b, _c, _d, _e, _f, _g;
3238
3246
  let nodeType;
3239
3247
  if (type instanceof DiagramNodeType) {
3240
3248
  nodeType = type;
@@ -3265,25 +3273,25 @@ class DiagramNodeSet extends DiagramElementSet {
3265
3273
  if (nodeType.ports.length > 0) {
3266
3274
  for (let i = 0; i < nodeType.ports.length; ++i) {
3267
3275
  const portConfig = nodeType.ports[i];
3268
- const port = this.model.ports.new(node, [node.coords[0] + portConfig.coords[0], node.coords[1] + portConfig.coords[1]], portConfig.direction, `${node.id}_${i}`);
3269
- if (portConfig.label) {
3270
- const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), portConfig.label);
3276
+ const port = this.model.ports.new(portConfig.type !== undefined ? this.model.ports.types.get(portConfig.type) : undefined, node, [node.coords[0] + portConfig.coords[0], node.coords[1] + portConfig.coords[1]], portConfig.connectionPoint !== undefined ? [node.coords[0] + (portConfig.connectionPoint[0] || 0), node.coords[1] + (portConfig.connectionPoint[1] || 0)] : undefined, portConfig.direction, `${node.id}_${i}`);
3277
+ if ((_e = port.type) === null || _e === undefined ? undefined : _e.label) {
3278
+ const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), (_f = port.type) === null || _f === undefined ? undefined : _f.label);
3279
+ const labelWidth = 6 * labelConfiguration.fontSize + getLeftPadding$1(labelConfiguration) + getRightPadding$1(labelConfiguration);
3280
+ const labelHeight = labelConfiguration.fontSize + getTopPadding$1(labelConfiguration) + getBottomPadding$1(labelConfiguration);
3271
3281
  let labelCoords;
3272
3282
  switch (port.direction) {
3273
- case exports.Side.Top:
3274
- case exports.Side.Left:
3275
- labelCoords = [port.coords[0] - labelConfiguration.fontSize, port.coords[1] - labelConfiguration.fontSize];
3276
- break;
3277
3283
  case exports.Side.Bottom:
3278
- labelCoords = [port.coords[0] - labelConfiguration.fontSize, port.coords[1] + labelConfiguration.fontSize];
3279
- break;
3284
+ case exports.Side.Left:
3280
3285
  case exports.Side.Right:
3281
- labelCoords = [port.coords[0] + labelConfiguration.fontSize, port.coords[1] - labelConfiguration.fontSize];
3286
+ labelCoords = [port.coords[0] - labelWidth / 2, port.coords[1] - labelHeight - getBottomMargin(labelConfiguration)];
3287
+ break;
3288
+ case exports.Side.Top:
3289
+ labelCoords = [port.coords[0] - labelWidth / 2, port.coords[1] + getTopMargin(labelConfiguration)];
3282
3290
  break;
3283
3291
  default:
3284
3292
  labelCoords = port.coords;
3285
3293
  }
3286
- this.model.fields.new(port, labelCoords, labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelConfiguration.fontSize, labelConfiguration.fontSize, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, '', labelConfiguration.editable, labelConfiguration.fit);
3294
+ this.model.fields.new(port, labelCoords, labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelWidth, labelHeight, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, '', labelConfiguration.editable, labelConfiguration.fit);
3287
3295
  }
3288
3296
  }
3289
3297
  }
@@ -3293,7 +3301,7 @@ class DiagramNodeSet extends DiagramElementSet {
3293
3301
  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.editable, labelConfiguration.fit);
3294
3302
  }
3295
3303
  node.valueSet.resetValues();
3296
- (_e = node.model.canvas) === null || _e === undefined ? undefined : _e.fitNodeInView(node.id);
3304
+ (_g = node.model.canvas) === null || _g === undefined ? undefined : _g.fitNodeInView(node.id);
3297
3305
  return node;
3298
3306
  }
3299
3307
  remove(id) {
@@ -3467,10 +3475,38 @@ const getTopPadding = config => {
3467
3475
  * @see DiagramPort
3468
3476
  */
3469
3477
  const DIAGRAM_PORT_DEFAULTS = {
3470
- radius: 12,
3471
3478
  highlightedColor: 'cyan',
3472
3479
  selectedColor: 'violet'
3473
3480
  };
3481
+ /**
3482
+ * Default values of the parameters of a diagram port.
3483
+ * @private
3484
+ * @see DiagramPort
3485
+ */
3486
+ const DIAGRAM_PORT_TYPE_DEFAULTS = {
3487
+ name: '',
3488
+ label: null,
3489
+ allowsOutgoing: true,
3490
+ allowsIncoming: true,
3491
+ width: 24
3492
+ };
3493
+ /**
3494
+ * A port type, which holds properties that ports of this type share in common.
3495
+ * @public
3496
+ * @see PortTypeConfig
3497
+ */
3498
+ class DiagramPortType {
3499
+ constructor(options) {
3500
+ const values = Object.assign(Object.assign({}, DIAGRAM_PORT_TYPE_DEFAULTS), options);
3501
+ this.id = values.id;
3502
+ this.name = values.name;
3503
+ this.label = values.label;
3504
+ this.allowsOutgoing = values.allowsOutgoing;
3505
+ this.allowsIncoming = values.allowsIncoming;
3506
+ this.width = values.width;
3507
+ this.look = values.look;
3508
+ }
3509
+ }
3474
3510
  /**
3475
3511
  * A port which is part of a node or section and at which connections can start or end.
3476
3512
  * @public
@@ -3479,7 +3515,34 @@ const DIAGRAM_PORT_DEFAULTS = {
3479
3515
  * @see DiagramSection
3480
3516
  */
3481
3517
  class DiagramPort extends DiagramElement {
3482
- constructor(model, rootElement, coords, direction, id) {
3518
+ /**
3519
+ * Whether this port can be used as a connection start point.
3520
+ */
3521
+ get allowsOutgoing() {
3522
+ var _a, _b;
3523
+ return ((_a = this.type) === null || _a === undefined ? undefined : _a.allowsOutgoing) !== undefined ? (_b = this.type) === null || _b === undefined ? undefined : _b.allowsOutgoing : true;
3524
+ }
3525
+ /**
3526
+ * Whether this port can be used as a connection end point.
3527
+ */
3528
+ get allowsIncoming() {
3529
+ var _a, _b;
3530
+ return ((_a = this.type) === null || _a === undefined ? undefined : _a.allowsIncoming) !== undefined ? (_b = this.type) === null || _b === undefined ? undefined : _b.allowsIncoming : true;
3531
+ }
3532
+ /**
3533
+ * Name of this port. Alias for this port's label's text.
3534
+ * @public
3535
+ */
3536
+ get name() {
3537
+ var _a;
3538
+ return ((_a = this.label) === null || _a === undefined ? undefined : _a.text) || '';
3539
+ }
3540
+ set name(name) {
3541
+ if (this.label) {
3542
+ this.label.text = name;
3543
+ }
3544
+ }
3545
+ constructor(model, type, rootElement, coords, connectionPoint, direction, id) {
3483
3546
  if (model.ports.get(id) !== undefined) {
3484
3547
  throw new Error(`DiagramPort with id "${id}" already exists`);
3485
3548
  }
@@ -3494,8 +3557,10 @@ class DiagramPort extends DiagramElement {
3494
3557
  * @public
3495
3558
  */
3496
3559
  this.incomingConnections = [];
3560
+ this.type = type;
3497
3561
  this.rootElement = rootElement;
3498
3562
  this.coords = coords;
3563
+ this.connectionPoint = connectionPoint || coords;
3499
3564
  this.direction = direction;
3500
3565
  }
3501
3566
  get removed() {
@@ -3508,6 +3573,9 @@ class DiagramPort extends DiagramElement {
3508
3573
  raise() {
3509
3574
  var _a;
3510
3575
  (_a = this.select()) === null || _a === undefined ? undefined : _a.raise();
3576
+ if (this.label) {
3577
+ this.label.raise();
3578
+ }
3511
3579
  for (const connection of this.incomingConnections) {
3512
3580
  connection.raise();
3513
3581
  }
@@ -3556,6 +3624,8 @@ class DiagramPort extends DiagramElement {
3556
3624
  move(coords) {
3557
3625
  const coordDifferences = [coords[0] - this.coords[0], coords[1] - this.coords[1]];
3558
3626
  this.coords = coords;
3627
+ this.connectionPoint[0] = this.connectionPoint[0] + coordDifferences[0];
3628
+ this.connectionPoint[1] = this.connectionPoint[1] + coordDifferences[1];
3559
3629
  for (const connection of this.outgoingConnections) {
3560
3630
  connection.setStart(this);
3561
3631
  }
@@ -3578,14 +3648,19 @@ class DiagramPortSet extends DiagramElementSet {
3578
3648
  */
3579
3649
  constructor(model) {
3580
3650
  super();
3651
+ /**
3652
+ * Set of the possible types of port that the ports of this set can have.
3653
+ * @public
3654
+ */
3655
+ this.types = new DiagramEntitySet();
3581
3656
  this.model = model;
3582
3657
  }
3583
3658
  /**
3584
3659
  * Instance a new port and add it to this set. This method is normally called when instancing an element with a port and it is rarely called by itself.
3585
3660
  * @private
3586
3661
  */
3587
- new(rootElement, coords, direction, id) {
3588
- const port = new DiagramPort(this.model, rootElement, coords, direction, id);
3662
+ new(type, rootElement, coords, connectionPoint, direction, id) {
3663
+ const port = new DiagramPort(this.model, type, rootElement, coords, connectionPoint, direction, id);
3589
3664
  super.add(port);
3590
3665
  port.updateInView();
3591
3666
  // add this port to its root element
@@ -3694,13 +3769,14 @@ class DagaImporter {
3694
3769
  }
3695
3770
  let portCounter = 0;
3696
3771
  for (const port of section.ports || []) {
3697
- const newPort = new DiagramPort(model, newSection, port.coords, port.direction, port.id);
3772
+ const newPortType = port.type !== undefined ? model.ports.types.get(port.type) : undefined;
3773
+ const newPort = new DiagramPort(model, newPortType, newSection, port.coords, port.connectionPoint, port.direction, port.id);
3698
3774
  newSection.ports.push(newPort);
3699
3775
  model.ports.add(newPort);
3700
3776
  if (port.label) {
3701
3777
  // add port label
3702
- if (newNodeType.ports.length > portCounter && newNodeType.ports[portCounter].label) {
3703
- const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), newNodeType.ports[portCounter].label);
3778
+ if (newNodeType.ports.length > portCounter && (newPortType === null || newPortType === undefined ? undefined : newPortType.label)) {
3779
+ const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), newPortType === null || newPortType === undefined ? undefined : newPortType.label);
3704
3780
  let labelCoords;
3705
3781
  switch (newPort.direction) {
3706
3782
  case exports.Side.Top:
@@ -3740,13 +3816,14 @@ class DagaImporter {
3740
3816
  }
3741
3817
  let portCounter = 0;
3742
3818
  for (const port of node.ports || []) {
3743
- const newPort = new DiagramPort(model, newNode, port.coords, port.direction, port.id);
3819
+ const newPortType = port.type !== undefined ? model.ports.types.get(port.type) : undefined;
3820
+ const newPort = new DiagramPort(model, newPortType, newNode, port.coords, port.connectionPoint, port.direction, port.id);
3744
3821
  newNode.ports.push(newPort);
3745
3822
  model.ports.add(newPort);
3746
3823
  if (port.label) {
3747
3824
  // add port label
3748
- if (newNodeType.ports.length > portCounter && newNodeType.ports[portCounter].label) {
3749
- const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), newNodeType.ports[portCounter].label);
3825
+ if (newNodeType.ports.length > portCounter && (newPortType === null || newPortType === undefined ? undefined : newPortType.label)) {
3826
+ const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), newPortType === null || newPortType === undefined ? undefined : newPortType.label);
3750
3827
  let labelCoords;
3751
3828
  switch (newPort.direction) {
3752
3829
  case exports.Side.Top:
@@ -3788,6 +3865,8 @@ class DagaImporter {
3788
3865
  newNode.valueSet.setTimestamps(node.collabMeta.dataTimestamps);
3789
3866
  }
3790
3867
  newNode.updateInView();
3868
+ // raise node to sort the render order of the node and its components
3869
+ newNode.raise();
3791
3870
  return newNode;
3792
3871
  }
3793
3872
  return undefined;
@@ -3810,6 +3889,8 @@ class DagaImporter {
3810
3889
  newConnection.valueSet.setTimestamps(connection.collabMeta.dataTimestamps);
3811
3890
  }
3812
3891
  newConnection.updateInView();
3892
+ // raise connection just in case it is necessary to sort the render order
3893
+ newConnection.raise();
3813
3894
  return newConnection;
3814
3895
  }
3815
3896
  return undefined;
@@ -5552,7 +5633,7 @@ class DagaExporter {
5552
5633
  return result;
5553
5634
  }
5554
5635
  exportNode(node, includeCollabMeta = false) {
5555
- var _a, _b, _c, _d;
5636
+ var _a, _b, _c, _d, _e, _f;
5556
5637
  const children = [];
5557
5638
  for (const child of node.children) {
5558
5639
  children.push(this.exportNode(child, includeCollabMeta));
@@ -5563,9 +5644,11 @@ class DagaExporter {
5563
5644
  for (const port of section.ports) {
5564
5645
  ports.push(Object.assign({
5565
5646
  id: port.id,
5647
+ type: (_a = port.type) === null || _a === undefined ? undefined : _a.id,
5566
5648
  coords: roundPoint(port.coords),
5649
+ connectionPoint: roundPoint(port.connectionPoint),
5567
5650
  direction: port.direction,
5568
- label: ((_a = port.label) === null || _a === undefined ? undefined : _a.text) || ''
5651
+ label: ((_b = port.label) === null || _b === undefined ? undefined : _b.text) || ''
5569
5652
  }, includeCollabMeta ? {
5570
5653
  collabMeta: Object.assign({
5571
5654
  removed: port.removed,
@@ -5577,7 +5660,7 @@ class DagaExporter {
5577
5660
  sections.push(Object.assign({
5578
5661
  id: section.id,
5579
5662
  ports,
5580
- label: ((_b = section.label) === null || _b === undefined ? undefined : _b.text) || '',
5663
+ label: ((_c = section.label) === null || _c === undefined ? undefined : _c.text) || '',
5581
5664
  indexXInNode: section.indexXInNode,
5582
5665
  indexYInNode: section.indexYInNode,
5583
5666
  coords: roundPoint(section.coords),
@@ -5595,9 +5678,11 @@ class DagaExporter {
5595
5678
  for (const port of node.ports) {
5596
5679
  ports.push(Object.assign({
5597
5680
  id: port.id,
5681
+ type: (_d = port.type) === null || _d === undefined ? undefined : _d.id,
5598
5682
  coords: roundPoint(port.coords),
5683
+ connectionPoint: roundPoint(port.connectionPoint),
5599
5684
  direction: port.direction,
5600
- label: ((_c = port.label) === null || _c === undefined ? undefined : _c.text) || ''
5685
+ label: ((_e = port.label) === null || _e === undefined ? undefined : _e.text) || ''
5601
5686
  }, includeCollabMeta ? {
5602
5687
  collabMeta: Object.assign({
5603
5688
  removed: port.removed,
@@ -5612,7 +5697,7 @@ class DagaExporter {
5612
5697
  children,
5613
5698
  sections,
5614
5699
  ports,
5615
- label: ((_d = node.label) === null || _d === undefined ? undefined : _d.text) || '',
5700
+ label: ((_f = node.label) === null || _f === undefined ? undefined : _f.text) || '',
5616
5701
  coords: roundPoint(node.coords),
5617
5702
  width: node.width,
5618
5703
  height: node.height,
@@ -5988,6 +6073,13 @@ class DiagramCanvas {
5988
6073
  this.model.nodes.types.add(nodeType);
5989
6074
  }
5990
6075
  }
6076
+ // load port types
6077
+ if (config.portTypes) {
6078
+ for (const portTypeConfig of config.portTypes) {
6079
+ const portType = new DiagramPortType(Object.assign(Object.assign({}, config.portTypeDefaults), portTypeConfig));
6080
+ this.model.ports.types.add(portType);
6081
+ }
6082
+ }
5991
6083
  // load connection types
5992
6084
  if (config.connectionTypes) {
5993
6085
  for (const connectionTypeConfig of config.connectionTypes) {
@@ -6240,9 +6332,10 @@ class DiagramCanvas {
6240
6332
  }
6241
6333
  }
6242
6334
  center() {
6335
+ var _a;
6243
6336
  // if there are no nodes, we have nothing to do here
6244
6337
  if (this.model.nodes.length > 0) {
6245
- const canvasViewBoundingBox = this.selectCanvasView().select('rect').node().getBBox();
6338
+ const canvasViewBoundingBox = (_a = this.selectCanvasView().select('rect').node()) === null || _a === undefined ? undefined : _a.getBBox();
6246
6339
  const nonRemovedNodes = this.model.nodes.all();
6247
6340
  const minimumX = Math.min(...nonRemovedNodes.map(n => n.coords[0]));
6248
6341
  const maximumX = Math.max(...nonRemovedNodes.map(n => n.coords[0] + n.width));
@@ -6946,21 +7039,32 @@ class DiagramCanvas {
6946
7039
  updatePortsInView(...ids) {
6947
7040
  let updateSelection = this.selectCanvasElements().selectAll('g.diagram-port').data(this.model.ports.filter(e => this.priorityThreshold !== undefined ? e.getPriority() >= this.priorityThreshold : true), d => d.id);
6948
7041
  const exitSelection = updateSelection.exit();
6949
- const enterSelection = updateSelection.enter().append('g').attr('id', d => d.id).attr('class', 'diagram-port');
7042
+ const enterSelection = updateSelection.enter().append('g').attr('id', d => d.id).attr('class', d => {
7043
+ var _a, _b;
7044
+ return `diagram-port ${((_b = (_a = d.type) === null || _a === undefined ? undefined : _a.look) === null || _b === undefined ? undefined : _b.lookType) || 'default'}`;
7045
+ });
6950
7046
  if (ids && ids.length > 0) {
6951
7047
  updateSelection = updateSelection.filter(d => ids.includes(d.id));
6952
7048
  }
6953
7049
  const mergeSelection = enterSelection.merge(updateSelection);
6954
7050
  exitSelection.remove();
6955
7051
  enterSelection.on(exports.Events.MouseOver, (_event, d) => {
6956
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
7052
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
6957
7053
  if (!this.unfinishedConnection && !this.dragging) {
6958
7054
  // if there is an unfinished connection, the port will be highlighted automatically if the pointer is close
6959
7055
  this.userHighlight.focusOn(d);
6960
7056
  this.diagramEvent$.next(new DiagramHighlightedEvent(d));
6961
7057
  }
6962
7058
  if (this.unfinishedConnection) {
6963
- const canConnectionFinishAtThisPort = this.unfinishedConnection.type.canStartFromType(((_c = (_b = (_a = this.unfinishedConnection.start) === null || _a === undefined ? undefined : _a.getNode()) === null || _b === undefined ? undefined : _b.type) === null || _c === undefined ? undefined : _c.id) || '') && this.unfinishedConnection.type.canFinishOnType(((_e = (_d = d.getNode()) === null || _d === undefined ? undefined : _d.type) === null || _e === undefined ? undefined : _e.id) || '') || this.unfinishedConnection.type.canStartFromType(((_g = (_f = d.getNode()) === null || _f === undefined ? undefined : _f.type) === null || _g === undefined ? undefined : _g.id) || '') && this.unfinishedConnection.type.canFinishOnType(((_k = (_j = (_h = this.unfinishedConnection.start) === null || _h === undefined ? undefined : _h.getNode()) === null || _j === undefined ? undefined : _j.type) === null || _k === undefined ? undefined : _k.id) || '');
7059
+ const canConnectionFinishAtThisPort =
7060
+ // can start at the starting port
7061
+ this.unfinishedConnection.type.canStartFromType(((_c = (_b = (_a = this.unfinishedConnection.start) === null || _a === undefined ? undefined : _a.getNode()) === null || _b === undefined ? undefined : _b.type) === null || _c === undefined ? undefined : _c.id) || '') && ((_d = this.unfinishedConnection.start) === null || _d === undefined ? undefined : _d.allowsOutgoing) &&
7062
+ // can end at the ending port
7063
+ this.unfinishedConnection.type.canFinishOnType(((_f = (_e = d.getNode()) === null || _e === undefined ? undefined : _e.type) === null || _f === undefined ? undefined : _f.id) || '') && d.allowsIncoming ||
7064
+ // can start at the ending port
7065
+ this.unfinishedConnection.type.canStartFromType(((_h = (_g = d.getNode()) === null || _g === undefined ? undefined : _g.type) === null || _h === undefined ? undefined : _h.id) || '') && d.allowsOutgoing &&
7066
+ // can end at the starting port
7067
+ this.unfinishedConnection.type.canFinishOnType(((_l = (_k = (_j = this.unfinishedConnection.start) === null || _j === undefined ? undefined : _j.getNode()) === null || _k === undefined ? undefined : _k.type) === null || _l === undefined ? undefined : _l.id) || '') && ((_m = this.unfinishedConnection.start) === null || _m === undefined ? undefined : _m.allowsIncoming);
6964
7068
  if (!canConnectionFinishAtThisPort) {
6965
7069
  setCursorStyle(exports.CursorStyle.NoDrop);
6966
7070
  }
@@ -7097,8 +7201,14 @@ class DiagramCanvas {
7097
7201
  }
7098
7202
  this.secondaryButton = false;
7099
7203
  }));
7100
- enterSelection.append('circle');
7101
- mergeSelection.attr('transform', d => `translate(${d.coords[0]},${d.coords[1]})`).attr('opacity', d => d.removed ? 0.5 : 1).select('circle').attr('cx', 0).attr('cy', 0).attr('r', DIAGRAM_PORT_DEFAULTS.radius).attr('fill', d => d.selected ? DIAGRAM_PORT_DEFAULTS.selectedColor : DIAGRAM_PORT_DEFAULTS.highlightedColor).attr('opacity', d => d.highlighted || d.selected ? 0.5 : 0);
7204
+ enterSelection.filter('.default').append('circle');
7205
+ enterSelection.filter('.image-look').append('image');
7206
+ mergeSelection.attr('transform', d => `translate(${d.coords[0]},${d.coords[1]})`).attr('opacity', d => d.removed ? 0.5 : 1);
7207
+ mergeSelection.filter('.default').select('circle').attr('cx', 0).attr('cy', 0).attr('r', DIAGRAM_PORT_TYPE_DEFAULTS.width / 2).attr('fill', d => d.selected ? DIAGRAM_PORT_DEFAULTS.selectedColor : DIAGRAM_PORT_DEFAULTS.highlightedColor).attr('opacity', d => d.highlighted || d.selected ? 0.5 : 0);
7208
+ mergeSelection.filter('.image-look').select('image').attr('x', d => -d.type.width / 2).attr('y', d => -d.type.width / 2).attr('width', d => d.type.width).attr('height', d => d.type.width).attr('href', d => {
7209
+ var _a, _b;
7210
+ return d.selected ? ((_a = d.type) === null || _a === undefined ? undefined : _a.look).selectedBackgroundImage : ((_b = d.type) === null || _b === undefined ? undefined : _b.look).backgroundImage;
7211
+ });
7102
7212
  }
7103
7213
  updateConnectionsInView(...ids) {
7104
7214
  const connectionList = this.model.connections.filter(e => this.priorityThreshold !== undefined ? e.getPriority() >= this.priorityThreshold : true);
@@ -7529,39 +7639,41 @@ class DiagramCanvas {
7529
7639
  // User actions
7530
7640
  startConnection(port) {
7531
7641
  var _a, _b, _c, _d;
7532
- if (this.connectionType && (this.connectionType.canStartFromType(((_b = (_a = port.getNode()) === null || _a === undefined ? undefined : _a.type) === null || _b === undefined ? undefined : _b.id) || '') || this.connectionType.canFinishOnType(((_d = (_c = port.getNode()) === null || _c === undefined ? undefined : _c.type) === null || _d === undefined ? undefined : _d.id) || ''))) {
7533
- this.unfinishedConnection = new DiagramConnection(this.model, this.connectionType, port, undefined, UNFINISHED_CONNECTION_ID);
7534
- } else {
7535
- if (this.inferConnectionType) {
7536
- let differentConnectionType = this.model.connections.types.all().find(t => {
7537
- var _a, _b;
7538
- return t.canStartFromType(((_b = (_a = port.getNode()) === null || _a === undefined ? undefined : _a.type) === null || _b === undefined ? undefined : _b.id) || '');
7539
- });
7540
- if (differentConnectionType === undefined) {
7541
- differentConnectionType = this.model.connections.types.all().find(t => {
7642
+ if (port.allowsOutgoing || port.allowsIncoming) {
7643
+ if (this.connectionType && (this.connectionType.canStartFromType(((_b = (_a = port.getNode()) === null || _a === undefined ? undefined : _a.type) === null || _b === undefined ? undefined : _b.id) || '') && port.allowsOutgoing || this.connectionType.canFinishOnType(((_d = (_c = port.getNode()) === null || _c === undefined ? undefined : _c.type) === null || _d === undefined ? undefined : _d.id) || '') && port.allowsIncoming)) {
7644
+ this.unfinishedConnection = new DiagramConnection(this.model, this.connectionType, port, undefined, UNFINISHED_CONNECTION_ID);
7645
+ } else {
7646
+ if (this.inferConnectionType) {
7647
+ let differentConnectionType = this.model.connections.types.all().find(t => {
7542
7648
  var _a, _b;
7543
- return t.canFinishOnType(((_b = (_a = port.getNode()) === null || _a === undefined ? undefined : _a.type) === null || _b === undefined ? undefined : _b.id) || '');
7649
+ return port.allowsOutgoing && t.canStartFromType(((_b = (_a = port.getNode()) === null || _a === undefined ? undefined : _a.type) === null || _b === undefined ? undefined : _b.id) || '');
7544
7650
  });
7545
- }
7546
- if (differentConnectionType !== undefined) {
7547
- this.unfinishedConnection = new DiagramConnection(this.model, differentConnectionType, port, undefined, UNFINISHED_CONNECTION_ID);
7651
+ if (differentConnectionType === undefined) {
7652
+ differentConnectionType = this.model.connections.types.all().find(t => {
7653
+ var _a, _b;
7654
+ return port.allowsIncoming && t.canFinishOnType(((_b = (_a = port.getNode()) === null || _a === undefined ? undefined : _a.type) === null || _b === undefined ? undefined : _b.id) || '');
7655
+ });
7656
+ }
7657
+ if (differentConnectionType !== undefined) {
7658
+ this.unfinishedConnection = new DiagramConnection(this.model, differentConnectionType, port, undefined, UNFINISHED_CONNECTION_ID);
7659
+ }
7548
7660
  }
7549
7661
  }
7550
7662
  }
7551
7663
  }
7552
7664
  finishConnection(port) {
7553
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
7665
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
7554
7666
  this.userHighlight.clear();
7555
7667
  if (this.unfinishedConnection !== undefined) {
7556
7668
  if (this.unfinishedConnection.start !== port) {
7557
- if (this.unfinishedConnection.type.canStartFromType(((_d = (_c = (_b = (_a = this.unfinishedConnection) === null || _a === undefined ? undefined : _a.start) === null || _b === undefined ? undefined : _b.getNode()) === null || _c === undefined ? undefined : _c.type) === null || _d === undefined ? undefined : _d.id) || '') && this.unfinishedConnection.type.canFinishOnType(((_f = (_e = port.getNode()) === null || _e === undefined ? undefined : _e.type) === null || _f === undefined ? undefined : _f.id) || '')) {
7558
- const addConnectionAction = new AddConnectionAction(this, this.unfinishedConnection.type, (_g = this.unfinishedConnection.start) === null || _g === undefined ? undefined : _g.id, port.id);
7669
+ if (this.unfinishedConnection.type.canStartFromType(((_d = (_c = (_b = (_a = this.unfinishedConnection) === null || _a === undefined ? undefined : _a.start) === null || _b === undefined ? undefined : _b.getNode()) === null || _c === undefined ? undefined : _c.type) === null || _d === undefined ? undefined : _d.id) || '') && ((_f = (_e = this.unfinishedConnection) === null || _e === undefined ? undefined : _e.start) === null || _f === undefined ? undefined : _f.allowsOutgoing) && this.unfinishedConnection.type.canFinishOnType(((_h = (_g = port.getNode()) === null || _g === undefined ? undefined : _g.type) === null || _h === undefined ? undefined : _h.id) || '') && port.allowsIncoming) {
7670
+ const addConnectionAction = new AddConnectionAction(this, this.unfinishedConnection.type, (_j = this.unfinishedConnection.start) === null || _j === undefined ? undefined : _j.id, port.id);
7559
7671
  // clean up the previous unfinished connection
7560
7672
  this.dropConnection();
7561
7673
  addConnectionAction.do();
7562
7674
  this.actionStack.add(addConnectionAction);
7563
- } else if (this.unfinishedConnection.type.canFinishOnType(((_l = (_k = (_j = (_h = this.unfinishedConnection) === null || _h === undefined ? undefined : _h.start) === null || _j === undefined ? undefined : _j.getNode()) === null || _k === undefined ? undefined : _k.type) === null || _l === undefined ? undefined : _l.id) || '') && this.unfinishedConnection.type.canStartFromType(((_o = (_m = port.getNode()) === null || _m === undefined ? undefined : _m.type) === null || _o === undefined ? undefined : _o.id) || '')) {
7564
- const addConnectionAction = new AddConnectionAction(this, this.unfinishedConnection.type, port.id, (_p = this.unfinishedConnection.start) === null || _p === undefined ? undefined : _p.id);
7675
+ } else if (this.unfinishedConnection.type.canFinishOnType(((_o = (_m = (_l = (_k = this.unfinishedConnection) === null || _k === undefined ? undefined : _k.start) === null || _l === undefined ? undefined : _l.getNode()) === null || _m === undefined ? undefined : _m.type) === null || _o === undefined ? undefined : _o.id) || '') && ((_q = (_p = this.unfinishedConnection) === null || _p === undefined ? undefined : _p.start) === null || _q === undefined ? undefined : _q.allowsIncoming) && this.unfinishedConnection.type.canStartFromType(((_s = (_r = port.getNode()) === null || _r === undefined ? undefined : _r.type) === null || _s === undefined ? undefined : _s.id) || '') && port.allowsOutgoing) {
7676
+ const addConnectionAction = new AddConnectionAction(this, this.unfinishedConnection.type, port.id, (_t = this.unfinishedConnection.start) === null || _t === undefined ? undefined : _t.id);
7565
7677
  // clean up the previous unfinished connection
7566
7678
  this.dropConnection();
7567
7679
  addConnectionAction.do();
@@ -7569,19 +7681,19 @@ class DiagramCanvas {
7569
7681
  } else {
7570
7682
  if (this.inferConnectionType) {
7571
7683
  let differentConnectionType = this.model.connections.types.all().find(t => {
7572
- var _a, _b, _c, _d, _e, _f;
7573
- return t.canStartFromType(((_d = (_c = (_b = (_a = this.unfinishedConnection) === null || _a === undefined ? undefined : _a.start) === null || _b === undefined ? undefined : _b.getNode()) === null || _c === undefined ? undefined : _c.type) === null || _d === undefined ? undefined : _d.id) || '') && t.canFinishOnType(((_f = (_e = port.getNode()) === null || _e === undefined ? undefined : _e.type) === null || _f === undefined ? undefined : _f.id) || '');
7684
+ var _a, _b, _c, _d, _e, _f, _g, _h;
7685
+ return t.canStartFromType(((_d = (_c = (_b = (_a = this.unfinishedConnection) === null || _a === undefined ? undefined : _a.start) === null || _b === undefined ? undefined : _b.getNode()) === null || _c === undefined ? undefined : _c.type) === null || _d === undefined ? undefined : _d.id) || '') && ((_f = (_e = this.unfinishedConnection) === null || _e === undefined ? undefined : _e.start) === null || _f === undefined ? undefined : _f.allowsOutgoing) && t.canFinishOnType(((_h = (_g = port.getNode()) === null || _g === undefined ? undefined : _g.type) === null || _h === undefined ? undefined : _h.id) || '') && port.allowsIncoming;
7574
7686
  });
7575
7687
  let invertConnection = false;
7576
7688
  if (differentConnectionType === undefined) {
7577
7689
  differentConnectionType = this.model.connections.types.all().find(t => {
7578
- var _a, _b, _c, _d, _e, _f;
7579
- return t.canFinishOnType(((_d = (_c = (_b = (_a = this.unfinishedConnection) === null || _a === undefined ? undefined : _a.start) === null || _b === undefined ? undefined : _b.getNode()) === null || _c === undefined ? undefined : _c.type) === null || _d === undefined ? undefined : _d.id) || '') && t.canStartFromType(((_f = (_e = port.getNode()) === null || _e === undefined ? undefined : _e.type) === null || _f === undefined ? undefined : _f.id) || '');
7690
+ var _a, _b, _c, _d, _e, _f, _g, _h;
7691
+ return t.canFinishOnType(((_d = (_c = (_b = (_a = this.unfinishedConnection) === null || _a === undefined ? undefined : _a.start) === null || _b === undefined ? undefined : _b.getNode()) === null || _c === undefined ? undefined : _c.type) === null || _d === undefined ? undefined : _d.id) || '') && ((_f = (_e = this.unfinishedConnection) === null || _e === undefined ? undefined : _e.start) === null || _f === undefined ? undefined : _f.allowsIncoming) && t.canStartFromType(((_h = (_g = port.getNode()) === null || _g === undefined ? undefined : _g.type) === null || _h === undefined ? undefined : _h.id) || '') && port.allowsOutgoing;
7580
7692
  });
7581
7693
  invertConnection = true;
7582
7694
  }
7583
7695
  if (differentConnectionType !== undefined) {
7584
- const addConnectionAction = new AddConnectionAction(this, differentConnectionType, invertConnection ? port.id : (_q = this.unfinishedConnection.start) === null || _q === undefined ? undefined : _q.id, invertConnection ? (_r = this.unfinishedConnection.start) === null || _r === undefined ? undefined : _r.id : port.id);
7696
+ const addConnectionAction = new AddConnectionAction(this, differentConnectionType, invertConnection ? port.id : (_u = this.unfinishedConnection.start) === null || _u === undefined ? undefined : _u.id, invertConnection ? (_v = this.unfinishedConnection.start) === null || _v === undefined ? undefined : _v.id : port.id);
7585
7697
  // clean up the previous unfinished connection
7586
7698
  this.dropConnection();
7587
7699
  addConnectionAction.do();
@@ -8765,6 +8877,7 @@ exports.DiagramObject = DiagramObject;
8765
8877
  exports.DiagramObjectSet = DiagramObjectSet;
8766
8878
  exports.DiagramPort = DiagramPort;
8767
8879
  exports.DiagramPortSet = DiagramPortSet;
8880
+ exports.DiagramPortType = DiagramPortType;
8768
8881
  exports.DiagramSecondaryClickEvent = DiagramSecondaryClickEvent;
8769
8882
  exports.DiagramSection = DiagramSection;
8770
8883
  exports.DiagramSectionSet = DiagramSectionSet;