@metadev/daga 4.0.1 → 4.0.2

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/index.esm.js CHANGED
@@ -1146,24 +1146,6 @@ class DiagramElementSet extends DiagramEntitySet {
1146
1146
  }
1147
1147
  }
1148
1148
 
1149
- /**
1150
- * Returns whether the incoming timestamp wins over the existing timestamp.
1151
- *
1152
- * In the DiagramModel, timestamps that have never been set are left null;
1153
- * `timestampWins` treats that as an "initial timestamp" that loses to all LogicalTimestamps.
1154
- */
1155
- function timestampWins(incoming, existing) {
1156
- if (!existing) return true;
1157
- if (incoming[0] > existing[0]) return true;
1158
- if (incoming[0] === existing[0]) {
1159
- // In case of equality, declare the incoming timestamp the "winner".
1160
- // This occurs if a client reuses a timestamp for multiple actions in a row,
1161
- // in which case the last created should win.
1162
- return incoming[1] >= existing[1];
1163
- }
1164
- return false;
1165
- }
1166
-
1167
1149
  /**
1168
1150
  * A property which is part of a property set and defines what values a value in a value set can take.
1169
1151
  * @public
@@ -1280,6 +1262,121 @@ class PropertySet {
1280
1262
  return this.propertyList.length > 0;
1281
1263
  }
1282
1264
  }
1265
+
1266
+ /**
1267
+ * Returns whether the incoming timestamp wins over the existing timestamp.
1268
+ *
1269
+ * In the DiagramModel, timestamps that have never been set are left null;
1270
+ * `timestampWins` treats that as an "initial timestamp" that loses to all LogicalTimestamps.
1271
+ */
1272
+ function timestampWins(incoming, existing) {
1273
+ if (!existing) return true;
1274
+ if (incoming[0] > existing[0]) return true;
1275
+ if (incoming[0] === existing[0]) {
1276
+ // In case of equality, declare the incoming timestamp the "winner".
1277
+ // This occurs if a client reuses a timestamp for multiple actions in a row,
1278
+ // in which case the last created should win.
1279
+ return incoming[1] >= existing[1];
1280
+ }
1281
+ return false;
1282
+ }
1283
+
1284
+ /**
1285
+ * Checks if the given value is not empty.
1286
+ * @private
1287
+ * @param a A value.
1288
+ * @returns `true` if the given value is not `undefined`, `null`, `''`, `[]` or `{}`; `false` otherwise.
1289
+ */
1290
+ const empty = a => {
1291
+ return a === undefined || a === null || a === '' || a instanceof Array && a.length === 0 || a instanceof Object && Object.keys(a).length === 0;
1292
+ };
1293
+ /**
1294
+ * Checks whether the given values are equal.
1295
+ * @public
1296
+ * @param a A value.
1297
+ * @param b A value.
1298
+ * @returns `true` if the given values are equal, `false` otherwise.
1299
+ */
1300
+ const equals = (a, b) => {
1301
+ return a === b || JSON.stringify(a) === JSON.stringify(b);
1302
+ };
1303
+ /**
1304
+ * Calculates the differences between the two given objects and returns two objects containing the differences in each relative to the other.
1305
+ *
1306
+ * For each key that holds a different value in the two objects, the resulting objects will contain the differences in the values under that key.
1307
+ *
1308
+ * This function is recursive, that is, if the value under the key is an object, the function will be applied to that value recursively.
1309
+ *
1310
+ * @public
1311
+ * @param a An object.
1312
+ * @param b An object.
1313
+ * @returns A tuple of two objects with each containing the keys that have a different value in the corresponding argument compared to the other argument.
1314
+ */
1315
+ const diff = (a, b) => {
1316
+ const aDiff = {};
1317
+ const bDiff = {};
1318
+ const allKeys = [];
1319
+ for (const key in a) {
1320
+ allKeys.push(key);
1321
+ }
1322
+ for (const key in b) {
1323
+ if (!(key in a)) {
1324
+ allKeys.push(key);
1325
+ }
1326
+ }
1327
+ for (const key of allKeys) {
1328
+ if (isObject(a[key]) && isObject(b[key])) {
1329
+ const diffAB = diff(a[key], b[key]);
1330
+ // only add the key if differences are detected
1331
+ if (Object.keys(diffAB[0]).length > 0 && Object.keys(diffAB[1]).length > 0) {
1332
+ aDiff[key] = diffAB[0];
1333
+ bDiff[key] = diffAB[1];
1334
+ }
1335
+ } else {
1336
+ if (!equals(a[key], b[key])) {
1337
+ aDiff[key] = a[key];
1338
+ bDiff[key] = b[key];
1339
+ }
1340
+ }
1341
+ }
1342
+ return [aDiff, bDiff];
1343
+ };
1344
+ /**
1345
+ * Calculates the differences between the two given values of a valueset and returns two objects containing the differences in each relative to the other.
1346
+ *
1347
+ * @param a An object.
1348
+ * @param b An object.
1349
+ * @param valueSet A ValueSet to use as reference for the keys and types of each property.
1350
+ * @returns A tuple of two objects with each containing the keys that have a different value in the corresponding argument compared to the other argument.
1351
+ */
1352
+ const diffProperties = (a, b, valueSet) => {
1353
+ const aDiff = {};
1354
+ const bDiff = {};
1355
+ for (const key in valueSet.propertySet.propertyMap) {
1356
+ if (valueSet.propertySet.propertyMap[key].type === Type.Object) {
1357
+ const diffAB = diffProperties(a[key], b[key], valueSet.getSubValueSet(key));
1358
+ // only add the key if differences are detected
1359
+ if (Object.keys(diffAB[0]).length > 0 && Object.keys(diffAB[1]).length > 0) {
1360
+ aDiff[key] = diffAB[0];
1361
+ bDiff[key] = diffAB[1];
1362
+ }
1363
+ } else {
1364
+ if (!equals(a[key], b[key])) {
1365
+ aDiff[key] = a[key];
1366
+ bDiff[key] = b[key];
1367
+ }
1368
+ }
1369
+ }
1370
+ return [aDiff, bDiff];
1371
+ };
1372
+ /**
1373
+ * Checks if the given value is an object.
1374
+ * @public
1375
+ * @param x A value.
1376
+ * @returns `true` if the given value is an object, `false` otherwise.
1377
+ */
1378
+ const isObject = x => x !== undefined && x !== null && x.constructor === Object;
1379
+
1283
1380
  /**
1284
1381
  * A set of values corresponding to a set of properties.
1285
1382
  * @public
@@ -1631,101 +1728,6 @@ class ValueSet {
1631
1728
  }
1632
1729
  }
1633
1730
  }
1634
- /**
1635
- * Checks if the given value is not empty.
1636
- * @private
1637
- * @param a A value.
1638
- * @returns `true` if the given value is not `undefined`, `null`, `''`, `[]` or `{}`; `false` otherwise.
1639
- */
1640
- const empty = a => {
1641
- return a === undefined || a === null || a === '' || a instanceof Array && a.length === 0 || a instanceof Object && Object.keys(a).length === 0;
1642
- };
1643
- /**
1644
- * Checks whether the given values are equal.
1645
- * @public
1646
- * @param a A value.
1647
- * @param b A value.
1648
- * @returns `true` if the given values are equal, `false` otherwise.
1649
- */
1650
- const equals = (a, b) => {
1651
- return a === b || JSON.stringify(a) === JSON.stringify(b);
1652
- };
1653
- /**
1654
- * Calculates the differences between the two given objects and returns two objects containing the differences in each relative to the other.
1655
- *
1656
- * For each key that holds a different value in the two objects, the resulting objects will contain the differences in the values under that key.
1657
- *
1658
- * This function is recursive, that is, if the value under the key is an object, the function will be applied to that value recursively.
1659
- *
1660
- * @public
1661
- * @param a An object.
1662
- * @param b An object.
1663
- * @returns A tuple of two objects with each containing the keys that have a different value in the corresponding argument compared to the other argument.
1664
- */
1665
- const diff = (a, b) => {
1666
- const aDiff = {};
1667
- const bDiff = {};
1668
- const allKeys = [];
1669
- for (const key in a) {
1670
- allKeys.push(key);
1671
- }
1672
- for (const key in b) {
1673
- if (!(key in a)) {
1674
- allKeys.push(key);
1675
- }
1676
- }
1677
- for (const key of allKeys) {
1678
- if (isObject(a[key]) && isObject(b[key])) {
1679
- const diffAB = diff(a[key], b[key]);
1680
- // only add the key if differences are detected
1681
- if (Object.keys(diffAB[0]).length > 0 && Object.keys(diffAB[1]).length > 0) {
1682
- aDiff[key] = diffAB[0];
1683
- bDiff[key] = diffAB[1];
1684
- }
1685
- } else {
1686
- if (!equals(a[key], b[key])) {
1687
- aDiff[key] = a[key];
1688
- bDiff[key] = b[key];
1689
- }
1690
- }
1691
- }
1692
- return [aDiff, bDiff];
1693
- };
1694
- /**
1695
- * Calculates the differences between the two given values of a valueset and returns two objects containing the differences in each relative to the other.
1696
- *
1697
- * @param a An object.
1698
- * @param b An object.
1699
- * @param valueSet A ValueSet to use as reference for the keys and types of each property.
1700
- * @returns A tuple of two objects with each containing the keys that have a different value in the corresponding argument compared to the other argument.
1701
- */
1702
- const diffProperties = (a, b, valueSet) => {
1703
- const aDiff = {};
1704
- const bDiff = {};
1705
- for (const key in valueSet.propertySet.propertyMap) {
1706
- if (valueSet.propertySet.propertyMap[key].type === Type.Object) {
1707
- const diffAB = diffProperties(a[key], b[key], valueSet.getSubValueSet(key));
1708
- // only add the key if differences are detected
1709
- if (Object.keys(diffAB[0]).length > 0 && Object.keys(diffAB[1]).length > 0) {
1710
- aDiff[key] = diffAB[0];
1711
- bDiff[key] = diffAB[1];
1712
- }
1713
- } else {
1714
- if (!equals(a[key], b[key])) {
1715
- aDiff[key] = a[key];
1716
- bDiff[key] = b[key];
1717
- }
1718
- }
1719
- }
1720
- return [aDiff, bDiff];
1721
- };
1722
- /**
1723
- * Checks if the given value is an object.
1724
- * @public
1725
- * @param x A value.
1726
- * @returns `true` if the given value is an object, `false` otherwise.
1727
- */
1728
- const isObject = x => x !== undefined && x !== null && x.constructor === Object;
1729
1731
 
1730
1732
  /**
1731
1733
  * Default values of the parameters of a diagram connection.
@@ -2962,6 +2964,7 @@ const DIAGRAM_NODE_TYPE_DEFAULTS = {
2962
2964
  padding: 0,
2963
2965
  label: null,
2964
2966
  ports: [],
2967
+ decorators: [],
2965
2968
  sectionGrid: null,
2966
2969
  look: DIAGRAM_NODE_LOOK_DEFAULTS,
2967
2970
  isUnique: false,
@@ -2992,6 +2995,7 @@ class DiagramNodeType {
2992
2995
  this.topPadding = getTopPadding(values);
2993
2996
  this.label = values.label;
2994
2997
  this.ports = values.ports;
2998
+ this.decorators = values.decorators;
2995
2999
  this.sectionGrid = values.sectionGrid ? new DiagramSectionGrid(values.sectionGrid) : null;
2996
3000
  const looks = extractLooksFromConfig(values.look);
2997
3001
  this.defaultLook = looks.defaultLook;
@@ -3633,7 +3637,7 @@ class DiagramNodeSet extends DiagramElementSet {
3633
3637
  for (let i = 0; i < nodeType.ports.length; ++i) {
3634
3638
  const portConfig = nodeType.ports[i];
3635
3639
  const portType = portConfig.type !== undefined ? this.model.ports.types.get(portConfig.type) : undefined;
3636
- const port = this.model.ports.new(portType, 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}`);
3640
+ const port = this.model.ports.new(portType, 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}_port_${i}`);
3637
3641
  if ((_e = port.type) === null || _e === undefined ? undefined : _e.label) {
3638
3642
  const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), (_f = port.type) === null || _f === undefined ? undefined : _f.label);
3639
3643
  const labelWidth = 6 * labelConfiguration.fontSize + getLeftPadding$1(labelConfiguration) + getRightPadding$1(labelConfiguration);
@@ -3660,6 +3664,13 @@ class DiagramNodeSet extends DiagramElementSet {
3660
3664
  const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), nodeType.label);
3661
3665
  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);
3662
3666
  }
3667
+ // add node decorators
3668
+ if (nodeType.decorators.length > 0) {
3669
+ for (let i = 0; i < nodeType.decorators.length; ++i) {
3670
+ const decoratorConfig = nodeType.decorators[i];
3671
+ this.model.decorators.new(node, [node.coords[0] + decoratorConfig.coords[0], node.coords[1] + decoratorConfig.coords[1]], decoratorConfig.width, decoratorConfig.height, node.getPriority(), decoratorConfig.html, `${node.id}_decorator_${i}`);
3672
+ }
3673
+ }
3663
3674
  node.valueSet.resetValues();
3664
3675
  (_g = node.model.canvas) === null || _g === undefined ? undefined : _g.fitNodeInView(node.id);
3665
3676
  return node;
@@ -4188,6 +4199,13 @@ class DagaImporter {
4188
4199
  newNode.width = node.width;
4189
4200
  newNode.height = node.height;
4190
4201
  if (node.label) {
4202
+ // add node decorators
4203
+ if (newNodeType.decorators) {
4204
+ for (let i = 0; i < newNodeType.decorators.length; ++i) {
4205
+ const decoratorConfig = newNodeType.decorators[i];
4206
+ model.decorators.new(newNode, [newNode.coords[0] + decoratorConfig.coords[0], newNode.coords[1] + decoratorConfig.coords[1]], decoratorConfig.width, decoratorConfig.height, newNode.getPriority(), decoratorConfig.html, `${newNode.id}_decorator_${i}`);
4207
+ }
4208
+ }
4191
4209
  // add node label
4192
4210
  if (newNodeType.label) {
4193
4211
  const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), newNodeType.label);
@@ -5909,6 +5927,32 @@ const updateLook = selection => {
5909
5927
  selection.filter('.stretchable-image-look').select('image.bottom-image').attr('x', d => d.look.leftMargin).attr('y', d => d.height - d.look.bottomMargin).attr('width', d => d.width - d.look.rightMargin - d.look.leftMargin).attr('height', d => d.look.bottomMargin).attr('href', d => d.look.backgroundImageBottom);
5910
5928
  selection.filter('.stretchable-image-look').select('image.bottom-right-image').attr('x', d => d.width - d.look.rightMargin).attr('y', d => d.height - d.look.bottomMargin).attr('width', d => d.look.rightMargin).attr('height', d => d.look.bottomMargin).attr('href', d => d.look.backgroundImageBottomRight);
5911
5929
  };
5930
+ const GRID_DEFAULTS = {
5931
+ enabled: true,
5932
+ style: 'dots',
5933
+ color: 'rgba(0, 0, 0, 0.1)',
5934
+ snap: false,
5935
+ spacing: 10,
5936
+ thickness: 0.05
5937
+ };
5938
+ const initializeGrid = (canvas, canvasView, backgroundPatternId) => {
5939
+ const canvasDefs = canvasView.append('defs');
5940
+ if (canvas.gridSize > 0 && isFinite(canvas.gridSize)) {
5941
+ const canvasBackgroundPattern = canvasDefs.append('pattern').attr('id', backgroundPatternId).attr('x', -canvas.gridSize / 2).attr('y', -canvas.gridSize / 2).attr('width', canvas.gridSize).attr('height', canvas.gridSize).attr('patternUnits', 'userSpaceOnUse');
5942
+ canvasBackgroundPattern.append('rect').attr('x', 0).attr('y', 0).attr('width', canvas.gridSize).attr('height', canvas.gridSize).attr('fill', canvas.backgroundColor);
5943
+ switch (canvas.gridStyle) {
5944
+ case 'dots':
5945
+ canvasBackgroundPattern.append('circle').attr('cx', canvas.gridSize / 2).attr('cy', canvas.gridSize / 2).attr('r', canvas.gridSize * canvas.gridThickness).attr('fill', canvas.gridColor);
5946
+ break;
5947
+ case 'lines':
5948
+ canvasBackgroundPattern.append('line').attr('x1', canvas.gridSize / 2).attr('x2', canvas.gridSize / 2).attr('y1', 0).attr('y2', canvas.gridSize).attr('stroke-width', canvas.gridSize * canvas.gridThickness).attr('stroke', canvas.gridColor);
5949
+ canvasBackgroundPattern.append('line').attr('x1', 0).attr('x2', (canvas.gridSize - canvas.gridSize * canvas.gridThickness) / 2).attr('y1', canvas.gridSize / 2).attr('y2', canvas.gridSize / 2).attr('stroke-width', canvas.gridSize * canvas.gridThickness).attr('stroke', canvas.gridColor);
5950
+ canvasBackgroundPattern.append('line').attr('x1', (canvas.gridSize + canvas.gridSize * canvas.gridThickness) / 2).attr('x2', canvas.gridSize).attr('y1', canvas.gridSize / 2).attr('y2', canvas.gridSize / 2).attr('stroke-width', canvas.gridSize * canvas.gridThickness).attr('stroke', canvas.gridColor);
5951
+ break;
5952
+ }
5953
+ canvasView.select('rect').attr('fill', `url(#${backgroundPatternId})`);
5954
+ }
5955
+ };
5912
5956
 
5913
5957
  const CONTEXT_MENU_MENU_RADIUS = 96;
5914
5958
  const CONTEXT_MENU_BUTTON_RADIUS = 32;
@@ -6078,7 +6122,7 @@ class DiagramUserHighlight extends DiagramElementSet {
6078
6122
  focusOn(element) {
6079
6123
  this.clear();
6080
6124
  this.focus = element;
6081
- if (element instanceof DiagramField && element.rootElement) {
6125
+ if ((element instanceof DiagramField || element instanceof DiagramDecorator) && element.rootElement) {
6082
6126
  this.focusOn(element.rootElement);
6083
6127
  } else {
6084
6128
  this.add(element);
@@ -6566,7 +6610,7 @@ class DiagramCanvas {
6566
6610
  * @param config The configuration object used to set the parameters of this canvas.
6567
6611
  */
6568
6612
  constructor(parentComponent, config) {
6569
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
6613
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
6570
6614
  this.backgroundPatternId = `daga-background-pattern-id-${DiagramCanvas.canvasCount++}`;
6571
6615
  this.zoomTransform = d3.zoomIdentity;
6572
6616
  // used to distinguish drags from clicks when dragging elements and during multiple selection
@@ -6585,15 +6629,16 @@ class DiagramCanvas {
6585
6629
  this.userHighlight = new DiagramUserHighlight(this);
6586
6630
  this.contextMenu = new DiagramContextMenu(this, (_a = config.canvas) === null || _a === undefined ? undefined : _a.contextMenu);
6587
6631
  this.backgroundColor = ((_b = config.canvas) === null || _b === undefined ? undefined : _b.backgroundColor) || '#FFFFFF';
6588
- this.gridSize = ((_d = (_c = config.canvas) === null || _c === undefined ? undefined : _c.grid) === null || _d === undefined ? undefined : _d.enabled) === false || ((_e = config.canvas) === null || _e === undefined ? undefined : _e.grid) === undefined ? 0 : Math.abs(((_g = (_f = config.canvas) === null || _f === undefined ? undefined : _f.grid) === null || _g === undefined ? undefined : _g.spacing) || 10);
6589
- this.gridThickness = Math.abs(((_j = (_h = config.canvas) === null || _h === undefined ? undefined : _h.grid) === null || _j === undefined ? undefined : _j.thickness) || 0.05);
6590
- this.gridColor = ((_l = (_k = config.canvas) === null || _k === undefined ? undefined : _k.grid) === null || _l === undefined ? undefined : _l.color) || 'rgba(0, 0, 0, 0.1)';
6591
- this.snapToGrid = ((_o = (_m = config.canvas) === null || _m === undefined ? undefined : _m.grid) === null || _o === undefined ? undefined : _o.enabled) === false || ((_p = config.canvas) === null || _p === undefined ? undefined : _p.grid) === undefined ? false : ((_r = (_q = config.canvas) === null || _q === undefined ? undefined : _q.grid) === null || _r === undefined ? undefined : _r.snap) || false;
6592
- this.zoomFactor = ((_s = config.canvas) === null || _s === undefined ? undefined : _s.zoomFactor) || 2;
6593
- this.panRate = ((_t = config.canvas) === null || _t === undefined ? undefined : _t.panRate) || 100;
6632
+ this.gridStyle = (_e = (_d = (_c = config.canvas) === null || _c === undefined ? undefined : _c.grid) === null || _d === undefined ? undefined : _d.style) !== null && _e !== undefined ? _e : GRID_DEFAULTS.style;
6633
+ this.gridSize = ((_g = (_f = config.canvas) === null || _f === undefined ? undefined : _f.grid) === null || _g === undefined ? undefined : _g.enabled) === false || ((_h = config.canvas) === null || _h === undefined ? undefined : _h.grid) === undefined ? 0 : Math.abs(((_k = (_j = config.canvas) === null || _j === undefined ? undefined : _j.grid) === null || _k === undefined ? undefined : _k.spacing) || GRID_DEFAULTS.spacing);
6634
+ this.gridThickness = Math.abs(((_m = (_l = config.canvas) === null || _l === undefined ? undefined : _l.grid) === null || _m === undefined ? undefined : _m.thickness) || GRID_DEFAULTS.thickness);
6635
+ this.gridColor = ((_p = (_o = config.canvas) === null || _o === undefined ? undefined : _o.grid) === null || _p === undefined ? undefined : _p.color) || GRID_DEFAULTS.color;
6636
+ this.snapToGrid = ((_r = (_q = config.canvas) === null || _q === undefined ? undefined : _q.grid) === null || _r === undefined ? undefined : _r.enabled) === false || ((_s = config.canvas) === null || _s === undefined ? undefined : _s.grid) === undefined ? false : ((_u = (_t = config.canvas) === null || _t === undefined ? undefined : _t.grid) === null || _u === undefined ? undefined : _u.snap) || GRID_DEFAULTS.snap;
6637
+ this.zoomFactor = ((_v = config.canvas) === null || _v === undefined ? undefined : _v.zoomFactor) || 2;
6638
+ this.panRate = ((_w = config.canvas) === null || _w === undefined ? undefined : _w.panRate) || 100;
6594
6639
  this.inferConnectionType = config.inferConnectionType || false;
6595
6640
  this.multipleSelectionOn = false;
6596
- this.priorityThresholds = ((_u = config.canvas) === null || _u === undefined ? undefined : _u.priorityThresholds) || [];
6641
+ this.priorityThresholds = ((_x = config.canvas) === null || _x === undefined ? undefined : _x.priorityThresholds) || [];
6597
6642
  this.priorityThreshold = this.priorityThresholds ? this.priorityThresholds[0] : undefined;
6598
6643
  this.layoutFormat = config.layoutFormat;
6599
6644
  this.userActions = config.userActions || {};
@@ -6720,23 +6765,29 @@ class DiagramCanvas {
6720
6765
  }
6721
6766
  }
6722
6767
  if (event.ctrlKey && event.key === 'c') {
6723
- event.preventDefault();
6724
- // copy
6725
- this.userSelection.copyToClipboard();
6726
- this.cancelAllUserActions();
6768
+ if (this.canUserPerformAction(DiagramActions.Clipboard)) {
6769
+ event.preventDefault();
6770
+ // copy
6771
+ this.userSelection.copyToClipboard();
6772
+ this.cancelAllUserActions();
6773
+ }
6727
6774
  }
6728
6775
  if (event.ctrlKey && event.key === 'x') {
6729
- event.preventDefault();
6730
- // cut
6731
- this.userSelection.cutToClipboard();
6732
- this.cancelAllUserActions();
6776
+ if (this.canUserPerformAction(DiagramActions.Clipboard) && this.canUserPerformAction(DiagramActions.Remove)) {
6777
+ event.preventDefault();
6778
+ // cut
6779
+ this.userSelection.cutToClipboard();
6780
+ this.cancelAllUserActions();
6781
+ }
6733
6782
  }
6734
6783
  if (event.ctrlKey && event.key === 'v') {
6735
- event.preventDefault();
6736
- // paste
6737
- const coordinateRange = this.getCoordinatesOnScreen();
6738
- this.userSelection.pasteFromClipboard(this.getClosestGridPoint([(coordinateRange[0][0] + coordinateRange[1][0]) / 2, (coordinateRange[0][1] + coordinateRange[1][1]) / 2]));
6739
- this.cancelAllUserActions();
6784
+ if (this.canUserPerformAction(DiagramActions.Paste)) {
6785
+ event.preventDefault();
6786
+ // paste
6787
+ const coordinateRange = this.getCoordinatesOnScreen();
6788
+ this.userSelection.pasteFromClipboard(this.getClosestGridPoint([(coordinateRange[0][0] + coordinateRange[1][0]) / 2, (coordinateRange[0][1] + coordinateRange[1][1]) / 2]));
6789
+ this.cancelAllUserActions();
6790
+ }
6740
6791
  }
6741
6792
  if (event.ctrlKey && event.key === 'y') {
6742
6793
  event.preventDefault();
@@ -6749,38 +6800,50 @@ class DiagramCanvas {
6749
6800
  this.actionStack.undo();
6750
6801
  }
6751
6802
  if (event.key === '+') {
6752
- event.preventDefault();
6753
- // zoom in
6754
- this.zoomBy(this.zoomFactor);
6803
+ if (this.canUserPerformAction(DiagramActions.Zoom)) {
6804
+ event.preventDefault();
6805
+ // zoom in
6806
+ this.zoomBy(this.zoomFactor);
6807
+ }
6755
6808
  }
6756
6809
  if (event.key === '-') {
6757
- event.preventDefault();
6758
- // zoom out
6759
- this.zoomBy(1 / this.zoomFactor);
6810
+ if (this.canUserPerformAction(DiagramActions.Zoom)) {
6811
+ event.preventDefault();
6812
+ // zoom out
6813
+ this.zoomBy(1 / this.zoomFactor);
6814
+ }
6760
6815
  }
6761
6816
  if (event.key === Keys.ArrowLeft) {
6762
- event.preventDefault();
6763
- // move left, faster if we're zoomed out and slower if we're zoomed in
6764
- this.translateBy(this.panRate / this.zoomTransform.k, 0);
6817
+ if (this.canUserPerformAction(DiagramActions.Zoom)) {
6818
+ event.preventDefault();
6819
+ // move left, faster if we're zoomed out and slower if we're zoomed in
6820
+ this.translateBy(this.panRate / this.zoomTransform.k, 0);
6821
+ }
6765
6822
  }
6766
6823
  if (event.key === Keys.ArrowRight) {
6767
- event.preventDefault();
6768
- // move right, faster if we're zoomed out and slower if we're zoomed in
6769
- this.translateBy(-this.panRate / this.zoomTransform.k, 0);
6824
+ if (this.canUserPerformAction(DiagramActions.Zoom)) {
6825
+ event.preventDefault();
6826
+ // move right, faster if we're zoomed out and slower if we're zoomed in
6827
+ this.translateBy(-this.panRate / this.zoomTransform.k, 0);
6828
+ }
6770
6829
  }
6771
6830
  if (event.key === Keys.ArrowDown) {
6772
- event.preventDefault();
6773
- // move down, faster if we're zoomed out and slower if we're zoomed in
6774
- this.translateBy(0, -this.panRate / this.zoomTransform.k);
6831
+ if (this.canUserPerformAction(DiagramActions.Zoom)) {
6832
+ event.preventDefault();
6833
+ // move down, faster if we're zoomed out and slower if we're zoomed in
6834
+ this.translateBy(0, -this.panRate / this.zoomTransform.k);
6835
+ }
6775
6836
  }
6776
6837
  if (event.key === Keys.ArrowUp) {
6777
- event.preventDefault();
6778
- // move up, faster if we're zoomed out and slower if we're zoomed in
6779
- this.translateBy(0, this.panRate / this.zoomTransform.k);
6838
+ if (this.canUserPerformAction(DiagramActions.Zoom)) {
6839
+ event.preventDefault();
6840
+ // move up, faster if we're zoomed out and slower if we're zoomed in
6841
+ this.translateBy(0, this.panRate / this.zoomTransform.k);
6842
+ }
6780
6843
  }
6781
6844
  });
6782
6845
  const canvasView = this.selectSVGElement().append('g').attr('class', 'daga-canvas-view').attr('width', `100%`).attr('height', `100%`);
6783
- const canvasBackground = canvasView.append('rect').attr('x', 0).attr('y', 0).attr('width', `100%`).attr('height', `100%`).attr('fill', this.backgroundColor).attr('stroke-width', '0').on(Events.MouseMove, event => {
6846
+ canvasView.append('rect').attr('x', 0).attr('y', 0).attr('width', `100%`).attr('height', `100%`).attr('fill', this.backgroundColor).attr('stroke-width', '0').on(Events.MouseMove, event => {
6784
6847
  if (this.unfinishedConnection !== undefined) {
6785
6848
  const pointerCoords = this.getPointerLocationRelativeToCanvas(event);
6786
6849
  this.unfinishedConnection.endCoords = pointerCoords;
@@ -6836,13 +6899,7 @@ class DiagramCanvas {
6836
6899
  }).on(ZoomEvents.End, () => {
6837
6900
  setCursorStyle();
6838
6901
  }));
6839
- const canvasDefs = canvasView.append('defs');
6840
- if (this.gridSize > 0 && isFinite(this.gridSize)) {
6841
- const canvasBackgroundPattern = canvasDefs.append('pattern').attr('id', this.backgroundPatternId).attr('x', -this.gridSize / 2).attr('y', -this.gridSize / 2).attr('width', this.gridSize).attr('height', this.gridSize).attr('patternUnits', 'userSpaceOnUse');
6842
- canvasBackgroundPattern.append('rect').attr('x', 0).attr('y', 0).attr('width', this.gridSize).attr('height', this.gridSize).attr('fill', this.backgroundColor);
6843
- canvasBackgroundPattern.append('circle').attr('cx', this.gridSize / 2).attr('cy', this.gridSize / 2).attr('r', this.gridSize * this.gridThickness).attr('fill', this.gridColor);
6844
- canvasBackground.attr('fill', `url(#${this.backgroundPatternId})`);
6845
- }
6902
+ initializeGrid(this, canvasView, this.backgroundPatternId);
6846
6903
  canvasView.append('g').attr('class', 'daga-canvas-elements');
6847
6904
  }
6848
6905
  zoomBy(factor) {
@@ -7818,7 +7875,23 @@ class DiagramCanvas {
7818
7875
  const mergeSelection = enterSelection.merge(updateSelection);
7819
7876
  mergeSelection.attr('width', d => `${d.width}px`).attr('height', d => `${d.height}px`).attr('transform', d => `translate(${d.coords[0]},${d.coords[1]})`).html(d => d.html);
7820
7877
  exitSelection.remove();
7821
- enterSelection.on(Events.ContextMenu, (event, d) => {
7878
+ enterSelection.on(Events.MouseOver, (_event, d) => {
7879
+ if (!this.dragging) {
7880
+ this.userHighlight.focusOn(d);
7881
+ this.diagramEvent$.next(new DiagramHighlightedEvent(d));
7882
+ }
7883
+ }).on(Events.Click, (event, d) => {
7884
+ if (!event.ctrlKey && !event.shiftKey) {
7885
+ const deselectedElements = this.userSelection.all();
7886
+ this.userSelection.clear();
7887
+ this.diagramEvent$.next(new DiagramSelectionEvent(deselectedElements, false));
7888
+ }
7889
+ if (d.rootElement) {
7890
+ const elementToBeToggled = getRelatedNodeOrItself(d.rootElement);
7891
+ this.userSelection.toggle(elementToBeToggled);
7892
+ this.diagramEvent$.next(new DiagramSelectionEvent([elementToBeToggled], elementToBeToggled.selected));
7893
+ }
7894
+ }).on(Events.ContextMenu, (event, d) => {
7822
7895
  if (this.dragging) {
7823
7896
  event.preventDefault();
7824
7897
  event.stopPropagation();
@@ -7828,8 +7901,15 @@ class DiagramCanvas {
7828
7901
  const diagramEvent = new DiagramSecondaryClickEvent(event, d);
7829
7902
  this.diagramEvent$.next(diagramEvent);
7830
7903
  if (!diagramEvent.defaultPrevented && this.canUserPerformAction(DiagramActions.ContextMenu)) {
7831
- event.preventDefault();
7832
- this.contextMenu.open(event);
7904
+ if (d.rootElement) {
7905
+ event.preventDefault();
7906
+ const elementToSelect = getRelatedNodeOrItself(d.rootElement);
7907
+ this.userHighlight.focusOn(elementToSelect);
7908
+ this.diagramEvent$.next(new DiagramHighlightedEvent(elementToSelect));
7909
+ this.userSelection.add(elementToSelect);
7910
+ this.diagramEvent$.next(new DiagramSelectionEvent([elementToSelect], true));
7911
+ this.contextMenu.open(event);
7912
+ }
7833
7913
  }
7834
7914
  }).on(Events.DoubleClick, (event, d) => {
7835
7915
  const diagramEvent = new DiagramDoubleClickEvent(event, d);
@@ -8303,18 +8383,18 @@ class DiagramCanvas {
8303
8383
  }
8304
8384
  startMultipleSelection(event) {
8305
8385
  this.draggingFrom = this.getPointerLocationRelativeToCanvas(event);
8306
- /* TODO: would be a good idea to build the multipleSelectionContainer
8307
- * from selectRoot() instead of selectCanvasElements()
8308
- * to avoid having the thickness of the rectangle be affected by zoom
8309
- */
8310
- this.multipleSelectionContainer = this.selectCanvasElements().append('rect').attr('stroke', '#0E74B6').attr('fill', 'rgba(14, 116, 182, 0.06)');
8386
+ // we put the multiple selection rectangle in the diagram svg element
8387
+ // so it's not affected by the zoom level in the diagram elements
8388
+ this.multipleSelectionContainer = this.selectSVGElement().append('rect').attr('stroke', '#0E74B6').attr('fill', 'rgba(14, 116, 182, 0.06)');
8311
8389
  }
8312
8390
  continueMultipleSelection(event) {
8313
8391
  var _a, _b, _c, _d;
8314
8392
  const pointerCoords = this.getPointerLocationRelativeToCanvas(event);
8315
8393
  if (this.draggingFrom[0] !== pointerCoords[0] || this.draggingFrom[1] !== pointerCoords[1]) {
8316
8394
  setCursorStyle(CursorStyle.Crosshair);
8317
- (_d = (_c = (_b = (_a = this.multipleSelectionContainer) === null || _a === undefined ? undefined : _a.attr('x', Math.min(this.draggingFrom[0], pointerCoords[0]))) === null || _b === undefined ? undefined : _b.attr('y', Math.min(this.draggingFrom[1], pointerCoords[1]))) === null || _c === undefined ? undefined : _c.attr('width', Math.abs(this.draggingFrom[0] - pointerCoords[0]))) === null || _d === undefined ? undefined : _d.attr('height', Math.abs(this.draggingFrom[1] - pointerCoords[1]));
8395
+ // since the multiple selection rectangle is not affected by zoom,
8396
+ // we compensate its coordinates based in the zoom transform to draw it
8397
+ (_d = (_c = (_b = (_a = this.multipleSelectionContainer) === null || _a === undefined ? undefined : _a.attr('x', Math.min(this.draggingFrom[0], pointerCoords[0]) * this.zoomTransform.k + this.zoomTransform.x)) === null || _b === undefined ? undefined : _b.attr('y', Math.min(this.draggingFrom[1], pointerCoords[1]) * this.zoomTransform.k + this.zoomTransform.y)) === null || _c === undefined ? undefined : _c.attr('width', Math.abs(this.draggingFrom[0] - pointerCoords[0]) * this.zoomTransform.k)) === null || _d === undefined ? undefined : _d.attr('height', Math.abs(this.draggingFrom[1] - pointerCoords[1]) * this.zoomTransform.k);
8318
8398
  this.dragging = true;
8319
8399
  }
8320
8400
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metadev/daga",
3
- "version": "4.0.1",
3
+ "version": "4.0.2",
4
4
  "dependencies": {},
5
5
  "peerDependencies": {
6
6
  "d3": "^7.9.0",
package/src/index.d.ts CHANGED
@@ -7,9 +7,10 @@ export { DiagramUserSelection } from './lib/diagram/canvas/diagram-user-selectio
7
7
  export type { CollabAction, CollabActionSerialized } from './lib/diagram/collab/collab-action';
8
8
  export { CollabClient } from './lib/diagram/collab/collab-client';
9
9
  export type { CollabTimestamp, CollabTimestampSet } from './lib/diagram/collab/primitives';
10
- export type { CanvasConfig, GridConfig } from './lib/diagram/config/diagram-canvas-config';
11
- export type { ButtonsComponentConfig, ComponentsConfig, ConnectionTemplateConfig, ConnectionTypeConfig, DiagramConfig, ErrorsComponentConfig, FieldConfig, NodeTemplateConfig, NodeTypeConfig, PaletteComponentConfig, PaletteSectionConfig, PortConfig, PortTypeConfig, PropertyEditorComponentConfig, SectionConfig, SectionGridConfig, UserActionConfig } from './lib/diagram/config/diagram-config';
12
- export type { ImageLook, ImageLookConfig, Look, LookConfig, MarkerImageLook, MarkerImageLookConfig, ShapedLook, ShapedLookConfig, StretchableImageLook, StretchableImageLookConfig } from './lib/diagram/config/diagram-look-config';
10
+ export type { CanvasConfig, GridConfig, GridStyle } from './lib/diagram/config/diagram-canvas-config';
11
+ export type { ButtonsComponentConfig, ComponentsConfig, ConnectionTemplateConfig, ErrorsComponentConfig, NodeTemplateConfig, PaletteComponentConfig, PaletteSectionConfig, PropertyEditorComponentConfig } from './lib/diagram/config/diagram-components-config';
12
+ export type { ConnectionTypeConfig, DiagramConfig, FieldConfig, NodeTypeConfig, PortConfig, PortTypeConfig, SectionConfig, SectionGridConfig, UserActionConfig } from './lib/diagram/config/diagram-config';
13
+ export type { ConnectionLook, ConnectionLookConfig, ImageLook, ImageLookConfig, Look, LookConfig, MarkerImageLook, MarkerImageLookConfig, ShapedLook, ShapedLookConfig, StretchableImageLook, StretchableImageLookConfig } from './lib/diagram/config/diagram-look-config';
13
14
  export { DagaExporter } from './lib/diagram/converters/daga-exporter';
14
15
  export { DagaImporter } from './lib/diagram/converters/daga-importer';
15
16
  export type { DagaConnection, DagaModel, DagaNode, DagaPort, DagaSection } from './lib/diagram/converters/daga-model';
@@ -39,10 +40,12 @@ export { DiagramNode, DiagramNodeSet, DiagramNodeType, filterByOnlyAncestors, fi
39
40
  export type { DiagramNodeGeometry } from './lib/diagram/model/diagram-node';
40
41
  export { DiagramObject, DiagramObjectSet } from './lib/diagram/model/diagram-object';
41
42
  export { DiagramPort, DiagramPortSet, DiagramPortType } from './lib/diagram/model/diagram-port';
42
- export { diff, equals, isObject, Property, PropertySet, Type, ValueSet } from './lib/diagram/model/diagram-property';
43
- export type { Option } from './lib/diagram/model/diagram-property';
44
43
  export { DiagramSection, DiagramSectionSet } from './lib/diagram/model/diagram-section';
45
44
  export type { DiagramSectionGeometry } from './lib/diagram/model/diagram-section';
45
+ export { Property, PropertySet, Type } from './lib/diagram/property/property';
46
+ export type { Option } from './lib/diagram/property/property';
47
+ export { diff, equals, isObject } from './lib/diagram/property/property-util';
48
+ export { ValueSet } from './lib/diagram/property/value';
46
49
  export type { DiagramError } from './lib/errors/diagram-error';
47
50
  export type { DiagramValidator } from './lib/errors/diagram-validator';
48
51
  export type { Canvas } from './lib/interfaces/canvas';
@@ -7,6 +7,7 @@ import { DiagramField } from '../model/diagram-field';
7
7
  import { DiagramNode } from '../model/diagram-node';
8
8
  import { DiagramPort } from '../model/diagram-port';
9
9
  import { DiagramSection } from '../model/diagram-section';
10
+ import { DiagramCanvas } from './diagram-canvas';
10
11
  /**
11
12
  * Checks if the given mouse event was produced with a secondary button press.
12
13
  * @private
@@ -24,3 +25,12 @@ export declare const setCursorStyle: (style?: CursorStyle) => void;
24
25
  export declare const getRelatedNodeOrItself: (element: DiagramNode | DiagramSection | DiagramPort | DiagramField) => DiagramNode | DiagramSection | DiagramPort | DiagramField;
25
26
  export declare const initializeLook: (selection: d3.Selection<SVGGElement, DiagramNode | DiagramSection | DiagramPort, d3.BaseType, unknown>) => void;
26
27
  export declare const updateLook: (selection: d3.Selection<SVGGElement, DiagramNode | DiagramSection | DiagramPort, d3.BaseType, unknown>) => void;
28
+ export declare const GRID_DEFAULTS: {
29
+ enabled: boolean;
30
+ style: string;
31
+ color: string;
32
+ snap: boolean;
33
+ spacing: number;
34
+ thickness: number;
35
+ };
36
+ export declare const initializeGrid: (canvas: DiagramCanvas, canvasView: d3.Selection<SVGGElement, unknown, null, unknown>, backgroundPatternId: string) => void;
@@ -5,6 +5,7 @@ import { Canvas } from '../../interfaces/canvas';
5
5
  import { DiagramEditor } from '../../interfaces/diagram-editor';
6
6
  import { Point } from '../../util/canvas-util';
7
7
  import { CollabEngine } from '../collab/collab-engine';
8
+ import { GridStyle } from '../config/diagram-canvas-config';
8
9
  import { DiagramConfig } from '../config/diagram-config';
9
10
  import { ActionStack, DiagramAction, DiagramActionMethod, DiagramActions } from '../diagram-action';
10
11
  import { DiagramEvent } from '../diagram-event';
@@ -40,6 +41,7 @@ export declare class DiagramCanvas implements Canvas {
40
41
  readonly actionStack: ActionStack;
41
42
  readonly collabEngine: CollabEngine;
42
43
  backgroundColor: string;
44
+ gridStyle: GridStyle;
43
45
  gridSize: number;
44
46
  gridThickness: number;
45
47
  gridColor: string;