@metadev/daga 5.0.5 → 5.1.1

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
@@ -1151,7 +1151,9 @@ var CursorStyle;
1151
1151
  CursorStyle["Grabbing"] = "grabbing";
1152
1152
  CursorStyle["Move"] = "move";
1153
1153
  CursorStyle["NoDrop"] = "no-drop";
1154
+ CursorStyle["NESWResize"] = "nesw-resize";
1154
1155
  CursorStyle["NSResize"] = "ns-resize";
1156
+ CursorStyle["NWSEResize"] = "nwse-resize";
1155
1157
  CursorStyle["NotAllowed"] = "not-allowed";
1156
1158
  CursorStyle["ZoomIn"] = "zoom-in";
1157
1159
  CursorStyle["ZoomOut"] = "zoom-out";
@@ -1250,283 +1252,6 @@ const extractLooksFromConfig = lookConfig => {
1250
1252
  };
1251
1253
  };
1252
1254
 
1253
- /**
1254
- * Represents a collection of diagram entities of a type that exists as part of a diagram model.
1255
- * @public
1256
- * @see DiagramEntity
1257
- * @see DiagramModel
1258
- */
1259
- class DiagramEntitySet {
1260
- constructor() {
1261
- /**
1262
- * The list of entities contained in this set.
1263
- * @private
1264
- */
1265
- this.entities = [];
1266
- /**
1267
- * A mapping of entity ids to their corresponding entity in this set for quickly fetching entities based on their id.
1268
- * @private
1269
- */
1270
- this.entityMap = {};
1271
- }
1272
- /**
1273
- * The number of entities in this set.
1274
- * @public
1275
- */
1276
- get length() {
1277
- return this.size();
1278
- }
1279
- /**
1280
- * Gets all of the entities of this set.
1281
- * @public
1282
- * @returns An array containing all of the entities of this set.
1283
- */
1284
- all() {
1285
- return [...this.entities];
1286
- }
1287
- /**
1288
- * Adds an entity to this set if there are no entities with the same id. Has no effect if there already exists an entity with the same id as the given entity.
1289
- * For creating entities with relationships with other entities, the new() method should be used instead. The add() method adds an entity but doesn't take care of setting that entity's relationships with other entities.
1290
- * @private
1291
- * @param entity An entity to be added to this set.
1292
- */
1293
- add(entity) {
1294
- if (this.entityMap[entity.id] === undefined) {
1295
- this.entityMap[entity.id] = entity;
1296
- this.entities.push(entity);
1297
- }
1298
- }
1299
- /**
1300
- * Removes all the entities in this set.
1301
- * @public
1302
- */
1303
- clear() {
1304
- // remove each entity individually in case classes that extend this implement their own specific cleanup
1305
- while (this.entities.length > 0) {
1306
- this.remove(this.entities[0].id);
1307
- }
1308
- }
1309
- /**
1310
- * Checks if this set contains an entity with the given id.
1311
- * @public
1312
- * @param id An id.
1313
- * @returns `true` if this set contains an entity with the given id, `false` otherwise.
1314
- */
1315
- contains(id) {
1316
- return this.entityMap[id] !== undefined;
1317
- }
1318
- /**
1319
- * Counts the number of entities of this set following the given criteria.
1320
- * @public
1321
- * @returns The number of entities of this set following the given criteria.
1322
- */
1323
- count(predicate) {
1324
- return this.entities.filter(predicate).length;
1325
- }
1326
- /**
1327
- * Gets all of the entities of this set filtered following given criteria.
1328
- * @public
1329
- * @returns An array containing the entities of this set that meet the given criteria.
1330
- */
1331
- filter(predicate) {
1332
- return this.entities.filter(predicate);
1333
- }
1334
- /**
1335
- * Gets an entity of this set matching specific criteria.
1336
- * @public
1337
- * @returns An entity of this set.
1338
- */
1339
- find(predicate) {
1340
- return this.entities.find(predicate);
1341
- }
1342
- /**
1343
- * Gets an entity from this set.
1344
- * @public
1345
- * @param id An id.
1346
- * @returns An entity with the given id, or `undefined` if there are no entities with the given id.
1347
- */
1348
- get(id) {
1349
- return this.entityMap[id];
1350
- }
1351
- /**
1352
- * Gets all of the entities of this set mapped to the result of the given function applied to them.
1353
- * @public
1354
- * @returns An array containing the entities of this set that meet the given criteria.
1355
- */
1356
- map(callback) {
1357
- return this.entities.map(callback);
1358
- }
1359
- /**
1360
- * Attempts to find and remove an entity with the given id. Has no effect if there are no entities with the given id.
1361
- * @public
1362
- * @param id An id.
1363
- */
1364
- remove(id) {
1365
- const entity = this.get(id);
1366
- if (entity !== undefined) {
1367
- delete this.entityMap[id];
1368
- removeIfExists(this.entities, entity);
1369
- }
1370
- }
1371
- /**
1372
- * Gets the number of entities in this set.
1373
- * @public
1374
- */
1375
- size() {
1376
- return this.entities.length;
1377
- }
1378
- /**
1379
- * Iterator to iterate over the entities of this set.
1380
- * @public
1381
- */
1382
- *[Symbol.iterator]() {
1383
- for (const entity of this.entities) {
1384
- yield entity;
1385
- }
1386
- }
1387
- }
1388
-
1389
- /**
1390
- * Default priority value for diagram elements.
1391
- * @private
1392
- */
1393
- const DEFAULT_PRIORITY = 0;
1394
- /**
1395
- * Represents an object which exists as part of a specific diagram model and has a visual representation in a diagram canvas.
1396
- * @public
1397
- * @see DiagramModel
1398
- * @see DiagramCanvas
1399
- */
1400
- class DiagramElement {
1401
- /**
1402
- * Identifier that uniquely identifies this element within its diagram model. Cannot be an empty string.
1403
- * @public
1404
- */
1405
- get id() {
1406
- return this._id;
1407
- }
1408
- /**
1409
- * Whether this diagram element is currently in the user highlight.
1410
- * @private
1411
- */
1412
- get highlighted() {
1413
- var _a, _b;
1414
- return ((_b = (_a = this.model.canvas) === null || _a === void 0 ? void 0 : _a.userHighlight) === null || _b === void 0 ? void 0 : _b.contains(this.id)) || false;
1415
- }
1416
- /**
1417
- * Whether this diagram element is currently in the user selection.
1418
- */
1419
- get selected() {
1420
- var _a, _b;
1421
- return ((_b = (_a = this.model.canvas) === null || _a === void 0 ? void 0 : _a.userSelection) === null || _b === void 0 ? void 0 : _b.contains(this.id)) || false;
1422
- }
1423
- constructor(model, id) {
1424
- /**
1425
- * Whether this diagram element has itself been explicitly removed.
1426
- *
1427
- * Override the `removed` getter so that it returns true if and only if:
1428
- * - `selfRemoved` is true, or
1429
- * - `removed` is true for any of this element's dependencies.
1430
- *
1431
- * For example, a DiagramConnection is removed if either of its ports are removed,
1432
- * even if the connection's own `selfRemoved` field is false.
1433
- * @private
1434
- */
1435
- this.selfRemoved = false;
1436
- /**
1437
- * Collaborative timestamp for selfRemoved.
1438
- * @private
1439
- */
1440
- this.selfRemovedTimestamp = null;
1441
- this.model = model;
1442
- this._id = id;
1443
- }
1444
- /**
1445
- * Obtain the selection of this element.
1446
- * @private
1447
- */
1448
- select() {
1449
- var _a, _b;
1450
- return (_b = (_a = this.model.canvas) === null || _a === void 0 ? void 0 : _a.selectCanvasView()) === null || _b === void 0 ? void 0 : _b.select(`[id='${escapeSelector(this.id)}']`);
1451
- }
1452
- }
1453
- class DiagramElementSet extends DiagramEntitySet {
1454
- all(includeRemoved = false) {
1455
- if (includeRemoved) {
1456
- return super.all();
1457
- } else {
1458
- return super.filter(e => !e.removed);
1459
- }
1460
- }
1461
- contains(id, includeRemoved = false) {
1462
- if (includeRemoved) {
1463
- return super.contains(id);
1464
- } else {
1465
- return super.contains(id) && !this.entityMap[id].removed;
1466
- }
1467
- }
1468
- count(predicate, includeRemoved = false) {
1469
- if (includeRemoved) {
1470
- return super.count(predicate);
1471
- } else {
1472
- return super.count((e, i, a) => predicate(e, i, a) && !e.removed);
1473
- }
1474
- }
1475
- filter(predicate, includeRemoved = false) {
1476
- if (includeRemoved) {
1477
- return super.filter(predicate);
1478
- } else {
1479
- return super.filter((e, i, a) => predicate(e, i, a) && !e.removed);
1480
- }
1481
- }
1482
- find(predicate, includeRemoved = false) {
1483
- if (includeRemoved) {
1484
- return super.find(predicate);
1485
- } else {
1486
- return super.find((e, i, a) => predicate(e, i, a) && !e.removed);
1487
- }
1488
- }
1489
- get(id, includeRemoved = false) {
1490
- if (includeRemoved) {
1491
- return super.get(id);
1492
- } else {
1493
- return this.contains(id) ? super.get(id) : undefined;
1494
- }
1495
- }
1496
- map(callback, includeRemoved = false) {
1497
- if (includeRemoved) {
1498
- return super.map(callback);
1499
- } else {
1500
- return super.filter(e => !e.removed).map(callback);
1501
- }
1502
- }
1503
- remove(id) {
1504
- const entity = this.get(id, true);
1505
- if (entity !== undefined) {
1506
- delete this.entityMap[id];
1507
- removeIfExists(this.entities, entity);
1508
- }
1509
- }
1510
- size(includeRemoved = false) {
1511
- if (includeRemoved) {
1512
- return super.size();
1513
- } else {
1514
- return super.filter(e => !e.removed).length;
1515
- }
1516
- }
1517
- *[Symbol.iterator](includeRemoved = false) {
1518
- if (includeRemoved) {
1519
- for (const entity of this.entities) {
1520
- yield entity;
1521
- }
1522
- } else {
1523
- for (const entity of this.entities.filter(e => !e.removed)) {
1524
- yield entity;
1525
- }
1526
- }
1527
- }
1528
- }
1529
-
1530
1255
  /**
1531
1256
  * A property which is part of a property set and defines what values a value in a value set can take.
1532
1257
  * @public
@@ -2041,76 +1766,353 @@ class ValueSet {
2041
1766
  }
2042
1767
  }
2043
1768
  /**
2044
- * Sets all the values of this set to the defaults.
2045
- * If this set has a root element and any of its properties have root attributes, the root element's attributes are also set to the property's default value if one is provided.
2046
- * @private
1769
+ * Sets all the values of this set to the defaults.
1770
+ * If this set has a root element and any of its properties have root attributes, the root element's attributes are also set to the property's default value if one is provided.
1771
+ * @private
1772
+ */
1773
+ resetValues() {
1774
+ this.displayedProperties = [];
1775
+ this.hiddenProperties = [];
1776
+ this.ownTimestamps = {};
1777
+ for (const key in this.propertySet.propertyMap) {
1778
+ const property = this.propertySet.getProperty(key);
1779
+ const rootAttribute = property.rootAttribute;
1780
+ if (property.type === Type.Object) {
1781
+ this.valueSets[key] = this.constructSubValueSet(key);
1782
+ } else {
1783
+ this.values[key] = clone(property.defaultValue);
1784
+ }
1785
+ if (rootAttribute !== undefined && rootAttribute !== null) {
1786
+ if (property.defaultValue !== undefined && !equals(this.getRootElementValue(rootAttribute), property.defaultValue)) {
1787
+ this.setRootElementValue(rootAttribute, this.values[key]);
1788
+ }
1789
+ }
1790
+ if (property.basic !== false) {
1791
+ this.displayedProperties.push(property);
1792
+ } else {
1793
+ this.hiddenProperties.push(property);
1794
+ }
1795
+ }
1796
+ }
1797
+ /**
1798
+ * Constructs a ValueSet with its corresponding PropertySet representing the values of the object.
1799
+ * @private
1800
+ * @param key Key that the ValueSet is under.
1801
+ * @returns The constructed ValueSet.
1802
+ */
1803
+ constructSubValueSet(key) {
1804
+ const property = this.propertySet.getProperty(key);
1805
+ const propertySet = new PropertySet(property.properties);
1806
+ const valueSet = new ValueSet(propertySet, this.rootElement);
1807
+ valueSet.overwriteValues(clone(property.defaultValue));
1808
+ return valueSet;
1809
+ }
1810
+ /**
1811
+ * Gets the ValueSet under the given key when there are nested ValueSets.
1812
+ * @private
1813
+ * @param key A key.
1814
+ * @returns A ValueSet.
1815
+ */
1816
+ getSubValueSet(key) {
1817
+ return this.valueSets[key];
1818
+ }
1819
+ /**
1820
+ * Moves the given property to the list of displayed properties.
1821
+ * @private
1822
+ * @param property A property.
1823
+ */
1824
+ displayProperty(property) {
1825
+ if (!this.displayedProperties.includes(property)) {
1826
+ this.displayedProperties.push(property);
1827
+ removeIfExists(this.hiddenProperties, property);
1828
+ }
1829
+ }
1830
+ /**
1831
+ * Moves the given property to the list of hidden properties.
1832
+ * @private
1833
+ * @param property A property.
1834
+ */
1835
+ hideProperty(property) {
1836
+ if (!this.hiddenProperties.includes(property)) {
1837
+ this.hiddenProperties.push(property);
1838
+ removeIfExists(this.displayedProperties, property);
1839
+ }
1840
+ }
1841
+ }
1842
+
1843
+ /**
1844
+ * Represents a collection of diagram entities of a type that exists as part of a diagram model.
1845
+ * @public
1846
+ * @see DiagramEntity
1847
+ * @see DiagramModel
1848
+ */
1849
+ class DiagramEntitySet {
1850
+ constructor() {
1851
+ /**
1852
+ * The list of entities contained in this set.
1853
+ * @private
1854
+ */
1855
+ this.entities = [];
1856
+ /**
1857
+ * A mapping of entity ids to their corresponding entity in this set for quickly fetching entities based on their id.
1858
+ * @private
1859
+ */
1860
+ this.entityMap = {};
1861
+ }
1862
+ /**
1863
+ * The number of entities in this set.
1864
+ * @public
1865
+ */
1866
+ get length() {
1867
+ return this.size();
1868
+ }
1869
+ /**
1870
+ * Gets all of the entities of this set.
1871
+ * @public
1872
+ * @returns An array containing all of the entities of this set.
1873
+ */
1874
+ all() {
1875
+ return [...this.entities];
1876
+ }
1877
+ /**
1878
+ * Adds an entity to this set if there are no entities with the same id. Has no effect if there already exists an entity with the same id as the given entity.
1879
+ * For creating entities with relationships with other entities, the new() method should be used instead. The add() method adds an entity but doesn't take care of setting that entity's relationships with other entities.
1880
+ * @private
1881
+ * @param entity An entity to be added to this set.
1882
+ */
1883
+ add(entity) {
1884
+ if (this.entityMap[entity.id] === undefined) {
1885
+ this.entityMap[entity.id] = entity;
1886
+ this.entities.push(entity);
1887
+ }
1888
+ }
1889
+ /**
1890
+ * Removes all the entities in this set.
1891
+ * @public
1892
+ */
1893
+ clear() {
1894
+ // remove each entity individually in case classes that extend this implement their own specific cleanup
1895
+ while (this.entities.length > 0) {
1896
+ this.remove(this.entities[0].id);
1897
+ }
1898
+ }
1899
+ /**
1900
+ * Checks if this set contains an entity with the given id.
1901
+ * @public
1902
+ * @param id An id.
1903
+ * @returns `true` if this set contains an entity with the given id, `false` otherwise.
1904
+ */
1905
+ contains(id) {
1906
+ return this.entityMap[id] !== undefined;
1907
+ }
1908
+ /**
1909
+ * Counts the number of entities of this set following the given criteria.
1910
+ * @public
1911
+ * @returns The number of entities of this set following the given criteria.
1912
+ */
1913
+ count(predicate) {
1914
+ return this.entities.filter(predicate).length;
1915
+ }
1916
+ /**
1917
+ * Gets all of the entities of this set filtered following given criteria.
1918
+ * @public
1919
+ * @returns An array containing the entities of this set that meet the given criteria.
1920
+ */
1921
+ filter(predicate) {
1922
+ return this.entities.filter(predicate);
1923
+ }
1924
+ /**
1925
+ * Gets an entity of this set matching specific criteria.
1926
+ * @public
1927
+ * @returns An entity of this set.
1928
+ */
1929
+ find(predicate) {
1930
+ return this.entities.find(predicate);
1931
+ }
1932
+ /**
1933
+ * Gets an entity from this set.
1934
+ * @public
1935
+ * @param id An id.
1936
+ * @returns An entity with the given id, or `undefined` if there are no entities with the given id.
1937
+ */
1938
+ get(id) {
1939
+ return this.entityMap[id];
1940
+ }
1941
+ /**
1942
+ * Gets all of the entities of this set mapped to the result of the given function applied to them.
1943
+ * @public
1944
+ * @returns An array containing the entities of this set that meet the given criteria.
1945
+ */
1946
+ map(callback) {
1947
+ return this.entities.map(callback);
1948
+ }
1949
+ /**
1950
+ * Attempts to find and remove an entity with the given id. Has no effect if there are no entities with the given id.
1951
+ * @public
1952
+ * @param id An id.
1953
+ */
1954
+ remove(id) {
1955
+ const entity = this.get(id);
1956
+ if (entity !== undefined) {
1957
+ delete this.entityMap[id];
1958
+ removeIfExists(this.entities, entity);
1959
+ }
1960
+ }
1961
+ /**
1962
+ * Gets the number of entities in this set.
1963
+ * @public
2047
1964
  */
2048
- resetValues() {
2049
- this.displayedProperties = [];
2050
- this.hiddenProperties = [];
2051
- this.ownTimestamps = {};
2052
- for (const key in this.propertySet.propertyMap) {
2053
- const property = this.propertySet.getProperty(key);
2054
- const rootAttribute = property.rootAttribute;
2055
- if (property.type === Type.Object) {
2056
- this.valueSets[key] = this.constructSubValueSet(key);
2057
- } else {
2058
- this.values[key] = clone(property.defaultValue);
2059
- }
2060
- if (rootAttribute !== undefined && rootAttribute !== null) {
2061
- if (property.defaultValue !== undefined && !equals(this.getRootElementValue(rootAttribute), property.defaultValue)) {
2062
- this.setRootElementValue(rootAttribute, this.values[key]);
2063
- }
2064
- }
2065
- if (property.basic !== false) {
2066
- this.displayedProperties.push(property);
2067
- } else {
2068
- this.hiddenProperties.push(property);
2069
- }
1965
+ size() {
1966
+ return this.entities.length;
1967
+ }
1968
+ /**
1969
+ * Iterator to iterate over the entities of this set.
1970
+ * @public
1971
+ */
1972
+ *[Symbol.iterator]() {
1973
+ for (const entity of this.entities) {
1974
+ yield entity;
2070
1975
  }
2071
1976
  }
1977
+ }
1978
+
1979
+ /**
1980
+ * Default priority value for diagram elements.
1981
+ * @private
1982
+ */
1983
+ const DEFAULT_PRIORITY = 0;
1984
+ /**
1985
+ * Represents an object which exists as part of a specific diagram model and has a visual representation in a diagram canvas.
1986
+ * @public
1987
+ * @see DiagramModel
1988
+ * @see DiagramCanvas
1989
+ */
1990
+ class DiagramElement {
2072
1991
  /**
2073
- * Constructs a ValueSet with its corresponding PropertySet representing the values of the object.
2074
- * @private
2075
- * @param key Key that the ValueSet is under.
2076
- * @returns The constructed ValueSet.
1992
+ * Identifier that uniquely identifies this element within its diagram model. Cannot be an empty string.
1993
+ * @public
2077
1994
  */
2078
- constructSubValueSet(key) {
2079
- const property = this.propertySet.getProperty(key);
2080
- const propertySet = new PropertySet(property.properties);
2081
- const valueSet = new ValueSet(propertySet, this.rootElement);
2082
- valueSet.overwriteValues(clone(property.defaultValue));
2083
- return valueSet;
1995
+ get id() {
1996
+ return this._id;
2084
1997
  }
2085
1998
  /**
2086
- * Gets the ValueSet under the given key when there are nested ValueSets.
1999
+ * Whether this diagram element is currently in the user highlight.
2087
2000
  * @private
2088
- * @param key A key.
2089
- * @returns A ValueSet.
2090
2001
  */
2091
- getSubValueSet(key) {
2092
- return this.valueSets[key];
2002
+ get highlighted() {
2003
+ var _a, _b;
2004
+ return ((_b = (_a = this.model.canvas) === null || _a === void 0 ? void 0 : _a.userHighlight) === null || _b === void 0 ? void 0 : _b.contains(this.id)) || false;
2093
2005
  }
2094
2006
  /**
2095
- * Moves the given property to the list of displayed properties.
2096
- * @private
2097
- * @param property A property.
2007
+ * Whether this diagram element is currently in the user selection.
2098
2008
  */
2099
- displayProperty(property) {
2100
- if (!this.displayedProperties.includes(property)) {
2101
- this.displayedProperties.push(property);
2102
- removeIfExists(this.hiddenProperties, property);
2103
- }
2009
+ get selected() {
2010
+ var _a, _b;
2011
+ return ((_b = (_a = this.model.canvas) === null || _a === void 0 ? void 0 : _a.userSelection) === null || _b === void 0 ? void 0 : _b.contains(this.id)) || false;
2012
+ }
2013
+ constructor(model, id) {
2014
+ /**
2015
+ * Whether this diagram element has itself been explicitly removed.
2016
+ *
2017
+ * Override the `removed` getter so that it returns true if and only if:
2018
+ * - `selfRemoved` is true, or
2019
+ * - `removed` is true for any of this element's dependencies.
2020
+ *
2021
+ * For example, a DiagramConnection is removed if either of its ports are removed,
2022
+ * even if the connection's own `selfRemoved` field is false.
2023
+ * @private
2024
+ */
2025
+ this.selfRemoved = false;
2026
+ /**
2027
+ * Collaborative timestamp for selfRemoved.
2028
+ * @private
2029
+ */
2030
+ this.selfRemovedTimestamp = null;
2031
+ this.model = model;
2032
+ this._id = id;
2104
2033
  }
2105
2034
  /**
2106
- * Moves the given property to the list of hidden properties.
2035
+ * Obtain the selection of this element.
2107
2036
  * @private
2108
- * @param property A property.
2109
2037
  */
2110
- hideProperty(property) {
2111
- if (!this.hiddenProperties.includes(property)) {
2112
- this.hiddenProperties.push(property);
2113
- removeIfExists(this.displayedProperties, property);
2038
+ select() {
2039
+ var _a, _b;
2040
+ return (_b = (_a = this.model.canvas) === null || _a === void 0 ? void 0 : _a.selectCanvasView()) === null || _b === void 0 ? void 0 : _b.select(`[id='${escapeSelector(this.id)}']`);
2041
+ }
2042
+ }
2043
+ class DiagramElementSet extends DiagramEntitySet {
2044
+ all(includeRemoved = false) {
2045
+ if (includeRemoved) {
2046
+ return super.all();
2047
+ } else {
2048
+ return super.filter(e => !e.removed);
2049
+ }
2050
+ }
2051
+ contains(id, includeRemoved = false) {
2052
+ if (includeRemoved) {
2053
+ return super.contains(id);
2054
+ } else {
2055
+ return super.contains(id) && !this.entityMap[id].removed;
2056
+ }
2057
+ }
2058
+ count(predicate, includeRemoved = false) {
2059
+ if (includeRemoved) {
2060
+ return super.count(predicate);
2061
+ } else {
2062
+ return super.count((e, i, a) => predicate(e, i, a) && !e.removed);
2063
+ }
2064
+ }
2065
+ filter(predicate, includeRemoved = false) {
2066
+ if (includeRemoved) {
2067
+ return super.filter(predicate);
2068
+ } else {
2069
+ return super.filter((e, i, a) => predicate(e, i, a) && !e.removed);
2070
+ }
2071
+ }
2072
+ find(predicate, includeRemoved = false) {
2073
+ if (includeRemoved) {
2074
+ return super.find(predicate);
2075
+ } else {
2076
+ return super.find((e, i, a) => predicate(e, i, a) && !e.removed);
2077
+ }
2078
+ }
2079
+ get(id, includeRemoved = false) {
2080
+ if (includeRemoved) {
2081
+ return super.get(id);
2082
+ } else {
2083
+ return this.contains(id) ? super.get(id) : undefined;
2084
+ }
2085
+ }
2086
+ map(callback, includeRemoved = false) {
2087
+ if (includeRemoved) {
2088
+ return super.map(callback);
2089
+ } else {
2090
+ return super.filter(e => !e.removed).map(callback);
2091
+ }
2092
+ }
2093
+ remove(id) {
2094
+ const entity = this.get(id, true);
2095
+ if (entity !== undefined) {
2096
+ delete this.entityMap[id];
2097
+ removeIfExists(this.entities, entity);
2098
+ }
2099
+ }
2100
+ size(includeRemoved = false) {
2101
+ if (includeRemoved) {
2102
+ return super.size();
2103
+ } else {
2104
+ return super.filter(e => !e.removed).length;
2105
+ }
2106
+ }
2107
+ *[Symbol.iterator](includeRemoved = false) {
2108
+ if (includeRemoved) {
2109
+ for (const entity of this.entities) {
2110
+ yield entity;
2111
+ }
2112
+ } else {
2113
+ for (const entity of this.entities.filter(e => !e.removed)) {
2114
+ yield entity;
2115
+ }
2114
2116
  }
2115
2117
  }
2116
2118
  }
@@ -2124,7 +2126,6 @@ const DIAGRAM_CONNECTION_TYPE_DEFAULTS = {
2124
2126
  name: '',
2125
2127
  label: null,
2126
2128
  look: {
2127
- lookType: 'connection-look',
2128
2129
  color: '#000000',
2129
2130
  thickness: 1,
2130
2131
  shape: LineShape.Straight,
@@ -2666,6 +2667,28 @@ class DiagramConnectionSet extends DiagramElementSet {
2666
2667
  }
2667
2668
  }
2668
2669
 
2670
+ /**
2671
+ * The different modes for when a node or section can be resized.
2672
+ * @public
2673
+ * @see DiagramNode
2674
+ * @see DiagramSection
2675
+ */
2676
+ var ResizableMode;
2677
+ (function (ResizableMode) {
2678
+ /**
2679
+ * Resizable mode for always being resizable.
2680
+ */
2681
+ ResizableMode[ResizableMode["Always"] = 0] = "Always";
2682
+ /**
2683
+ * Resizable mode for only being resizable while selected.
2684
+ */
2685
+ ResizableMode[ResizableMode["OnlyWhenSelected"] = 1] = "OnlyWhenSelected";
2686
+ /**
2687
+ * Resizable mode for never being resizable.
2688
+ */
2689
+ ResizableMode[ResizableMode["Never"] = 2] = "Never";
2690
+ })(ResizableMode || (ResizableMode = {}));
2691
+
2669
2692
  /**
2670
2693
  * Default values of the parameters of a diagram field.
2671
2694
  * @private
@@ -2673,19 +2696,21 @@ class DiagramConnectionSet extends DiagramElementSet {
2673
2696
  */
2674
2697
  const DIAGRAM_FIELD_DEFAULTS = {
2675
2698
  editable: true,
2676
- fontSize: 0,
2677
2699
  margin: 0,
2678
2700
  padding: 0,
2679
- fontFamily: "'Wonder Unit Sans', sans-serif",
2680
- color: '#000000',
2681
- selectedColor: '#000000',
2682
- backgroundColor: 'transparent',
2683
2701
  horizontalAlign: HorizontalAlign.Center,
2684
2702
  verticalAlign: VerticalAlign.Center,
2685
2703
  orientation: Side.Top,
2686
2704
  multiline: false,
2687
2705
  fit: false,
2688
- shrink: true
2706
+ shrink: true,
2707
+ look: {
2708
+ fillColor: 'transparent',
2709
+ fontColor: '#000000',
2710
+ fontFamily: "'Wonder Unit Sans', sans-serif",
2711
+ fontSize: 10,
2712
+ fontWeight: 400
2713
+ }
2689
2714
  };
2690
2715
  /**
2691
2716
  * A field which displays text and is part of a diagram element.
@@ -2713,7 +2738,26 @@ class DiagramField extends DiagramElement {
2713
2738
  (_a = this.model.canvas) === null || _a === void 0 ? void 0 : _a.fitFieldRootInView(this.id, this.shrink);
2714
2739
  }
2715
2740
  }
2716
- constructor(model, rootElement, coords, width, height, fontSize, fontFamily, color, selectedColor, horizontalAlign, verticalAlign, orientation, multiline, text, editable, fit, shrink) {
2741
+ /**
2742
+ * Current look of this field.
2743
+ * @private
2744
+ */
2745
+ get look() {
2746
+ if (this.selected) {
2747
+ if (this.highlighted) {
2748
+ return this.selectedAndHighlightedLook;
2749
+ } else {
2750
+ return this.selectedLook;
2751
+ }
2752
+ } else {
2753
+ if (this.highlighted) {
2754
+ return this.highlightedLook;
2755
+ } else {
2756
+ return this.defaultLook;
2757
+ }
2758
+ }
2759
+ }
2760
+ constructor(model, rootElement, coords, width, height, horizontalAlign, verticalAlign, orientation, multiline, look, text, editable, fit, shrink) {
2717
2761
  const id = `${rootElement === null || rootElement === void 0 ? void 0 : rootElement.id}_field`;
2718
2762
  if (model.fields.get(id) !== undefined) {
2719
2763
  throw new Error('DiagramField for rootElement already exists');
@@ -2728,12 +2772,9 @@ class DiagramField extends DiagramElement {
2728
2772
  this.coords = coords;
2729
2773
  this.width = width;
2730
2774
  this.height = height;
2731
- this.fontSize = fontSize;
2732
- this.fontFamily = fontFamily;
2733
- this.color = color;
2734
- this.selectedColor = selectedColor;
2735
2775
  this.horizontalAlign = horizontalAlign;
2736
2776
  this.verticalAlign = verticalAlign;
2777
+ this.multiline = multiline;
2737
2778
  if (!isNaN(Number(orientation))) {
2738
2779
  this.orientation = Number(orientation);
2739
2780
  } else {
@@ -2754,7 +2795,11 @@ class DiagramField extends DiagramElement {
2754
2795
  this.orientation = 0;
2755
2796
  }
2756
2797
  }
2757
- this.multiline = multiline;
2798
+ const looks = extractLooksFromConfig(look);
2799
+ this.defaultLook = looks.defaultLook;
2800
+ this.selectedLook = looks.selectedLook;
2801
+ this.highlightedLook = looks.highlightedLook;
2802
+ this.selectedAndHighlightedLook = looks.selectedAndHighlightedLook;
2758
2803
  this.defaultText = text;
2759
2804
  this._text = text;
2760
2805
  this.editable = editable;
@@ -2799,8 +2844,8 @@ class DiagramFieldSet extends DiagramElementSet {
2799
2844
  * Instance a new field and add it to this set. This method is normally called when instancing an element with a field and it is rarely called by itself.
2800
2845
  * @private
2801
2846
  */
2802
- new(rootElement, coords, fontSize, fontFamily, color, selectedColor, width, height, horizontalAlign, verticalAlign, orientation, multiline, text, editable, fit, shrink) {
2803
- const field = new DiagramField(this.model, rootElement, coords, width, height, fontSize, fontFamily, color, selectedColor, horizontalAlign, verticalAlign, orientation, multiline, text, editable, fit, shrink);
2847
+ new(rootElement, coords, width, height, horizontalAlign, verticalAlign, orientation, multiline, look, text, editable, fit, shrink) {
2848
+ const field = new DiagramField(this.model, rootElement, coords, width, height, horizontalAlign, verticalAlign, orientation, multiline, look, text, editable, fit, shrink);
2804
2849
  super.add(field);
2805
2850
  field.updateInView();
2806
2851
  // add this field to its root element
@@ -2832,9 +2877,7 @@ const getBottomMargin = config => {
2832
2877
  } else if (typeof config.margin === 'number') {
2833
2878
  return config.margin;
2834
2879
  } else {
2835
- if (config.margin.length === 0) {
2836
- return DIAGRAM_FIELD_DEFAULTS.margin;
2837
- } else if (config.margin.length === 1) {
2880
+ if (config.margin.length === 1) {
2838
2881
  return config.margin[0];
2839
2882
  } else if (config.margin.length === 2) {
2840
2883
  return config.margin[0];
@@ -2851,9 +2894,7 @@ const getLeftMargin = config => {
2851
2894
  } else if (typeof config.margin === 'number') {
2852
2895
  return config.margin;
2853
2896
  } else {
2854
- if (config.margin.length === 0) {
2855
- return DIAGRAM_FIELD_DEFAULTS.margin;
2856
- } else if (config.margin.length === 1) {
2897
+ if (config.margin.length === 1) {
2857
2898
  return config.margin[0];
2858
2899
  } else if (config.margin.length === 2) {
2859
2900
  return config.margin[1];
@@ -2870,9 +2911,7 @@ const getRightMargin = config => {
2870
2911
  } else if (typeof config.margin === 'number') {
2871
2912
  return config.margin;
2872
2913
  } else {
2873
- if (config.margin.length === 0) {
2874
- return DIAGRAM_FIELD_DEFAULTS.margin;
2875
- } else if (config.margin.length === 1) {
2914
+ if (config.margin.length === 1) {
2876
2915
  return config.margin[0];
2877
2916
  } else if (config.margin.length === 2) {
2878
2917
  return config.margin[1];
@@ -2889,9 +2928,7 @@ const getTopMargin = config => {
2889
2928
  } else if (typeof config.margin === 'number') {
2890
2929
  return config.margin;
2891
2930
  } else {
2892
- if (config.margin.length === 0) {
2893
- return DIAGRAM_FIELD_DEFAULTS.margin;
2894
- } else if (config.margin.length === 1) {
2931
+ if (config.margin.length === 1) {
2895
2932
  return config.margin[0];
2896
2933
  } else if (config.margin.length === 2) {
2897
2934
  return config.margin[0];
@@ -2908,9 +2945,7 @@ const getBottomPadding$1 = config => {
2908
2945
  } else if (typeof config.padding === 'number') {
2909
2946
  return config.padding;
2910
2947
  } else {
2911
- if (config.padding.length === 0) {
2912
- return DIAGRAM_FIELD_DEFAULTS.padding;
2913
- } else if (config.padding.length === 1) {
2948
+ if (config.padding.length === 1) {
2914
2949
  return config.padding[0];
2915
2950
  } else if (config.padding.length === 2) {
2916
2951
  return config.padding[0];
@@ -2927,9 +2962,7 @@ const getLeftPadding$1 = config => {
2927
2962
  } else if (typeof config.padding === 'number') {
2928
2963
  return config.padding;
2929
2964
  } else {
2930
- if (config.padding.length === 0) {
2931
- return DIAGRAM_FIELD_DEFAULTS.padding;
2932
- } else if (config.padding.length === 1) {
2965
+ if (config.padding.length === 1) {
2933
2966
  return config.padding[0];
2934
2967
  } else if (config.padding.length === 2) {
2935
2968
  return config.padding[1];
@@ -2946,9 +2979,7 @@ const getRightPadding$1 = config => {
2946
2979
  } else if (typeof config.padding === 'number') {
2947
2980
  return config.padding;
2948
2981
  } else {
2949
- if (config.padding.length === 0) {
2950
- return DIAGRAM_FIELD_DEFAULTS.padding;
2951
- } else if (config.padding.length === 1) {
2982
+ if (config.padding.length === 1) {
2952
2983
  return config.padding[0];
2953
2984
  } else if (config.padding.length === 2) {
2954
2985
  return config.padding[1];
@@ -2965,24 +2996,88 @@ const getTopPadding$1 = config => {
2965
2996
  } else if (typeof config.padding === 'number') {
2966
2997
  return config.padding;
2967
2998
  } else {
2968
- if (config.padding.length === 0) {
2969
- return DIAGRAM_FIELD_DEFAULTS.padding;
2970
- } else if (config.padding.length === 1) {
2999
+ if (config.padding.length === 1) {
2971
3000
  return config.padding[0];
2972
3001
  } else if (config.padding.length === 2) {
2973
3002
  return config.padding[0];
2974
3003
  } else if (config.padding.length === 3) {
2975
3004
  return config.padding[0];
2976
3005
  } else {
2977
- return config.padding[0];
3006
+ return config.padding[0];
3007
+ }
3008
+ }
3009
+ };
3010
+
3011
+ /**
3012
+ * Default values of the parameters of a diagram field.
3013
+ * @private
3014
+ * @see ResizerConfig
3015
+ */
3016
+ const DIAGRAM_RESIZER_DEFAULTS = {
3017
+ mode: ResizableMode.Never,
3018
+ thickness: 10,
3019
+ outerMargin: 0,
3020
+ look: {
3021
+ fillColor: 'transparent',
3022
+ borderColor: 'transparent',
3023
+ borderThickness: 0
3024
+ }
3025
+ };
3026
+ /**
3027
+ * Holds the data for the resizers of a type of node or section.
3028
+ * @public
3029
+ * @see DiagramNode
3030
+ * @see DiagramSection
3031
+ */
3032
+ class DiagramResizer {
3033
+ constructor(options) {
3034
+ var _a;
3035
+ let config;
3036
+ if (typeof options === 'boolean') {
3037
+ config = {
3038
+ mode: options ? ResizableMode.Always : ResizableMode.Never
3039
+ };
3040
+ } else if (typeof options === 'string' || typeof options === 'number') {
3041
+ config = {
3042
+ mode: options
3043
+ };
3044
+ } else {
3045
+ config = options;
3046
+ }
3047
+ config = Object.assign(Object.assign({}, DIAGRAM_RESIZER_DEFAULTS), config);
3048
+ this.mode = config.mode;
3049
+ this.thickness = config.thickness;
3050
+ this.outerMargin = config.outerMargin;
3051
+ const looks = extractLooksFromConfig((_a = config.look) !== null && _a !== void 0 ? _a : DIAGRAM_RESIZER_DEFAULTS.look);
3052
+ this.defaultLook = looks.defaultLook;
3053
+ this.selectedLook = looks.selectedLook;
3054
+ this.highlightedLook = looks.highlightedLook;
3055
+ this.selectedAndHighlightedLook = looks.selectedAndHighlightedLook;
3056
+ }
3057
+ /**
3058
+ * Current look of this resizer.
3059
+ * @private
3060
+ */
3061
+ getLook(rootElement) {
3062
+ if (!rootElement) {
3063
+ return this.defaultLook;
3064
+ }
3065
+ if (rootElement.selected) {
3066
+ if (rootElement.highlighted) {
3067
+ return this.selectedAndHighlightedLook;
3068
+ } else {
3069
+ return this.selectedLook;
3070
+ }
3071
+ } else {
3072
+ if (rootElement.highlighted) {
3073
+ return this.highlightedLook;
3074
+ } else {
3075
+ return this.defaultLook;
3076
+ }
2978
3077
  }
2979
3078
  }
2980
- };
2981
-
2982
- var ResizableMode;
2983
- (function (ResizableMode) {
2984
- ResizableMode[ResizableMode["OnlyWhenSelected"] = 0] = "OnlyWhenSelected";
2985
- })(ResizableMode || (ResizableMode = {}));
3079
+ }
3080
+ const DIAGRAM_DEFAULT_RESIZER = new DiagramResizer(DIAGRAM_RESIZER_DEFAULTS);
2986
3081
 
2987
3082
  /**
2988
3083
  * Default value of the default width of a diagram section.
@@ -3036,8 +3131,21 @@ class DiagramSectionType {
3036
3131
  this.label = options.label || null;
3037
3132
  this.ports = options.ports || [];
3038
3133
  this.priority = options.priority || DEFAULT_PRIORITY;
3039
- this.resizableX = options.resizableX;
3040
- this.resizableY = options.resizableY;
3134
+ if (typeof options.resizableX === 'undefined') {
3135
+ this.resizerX = undefined;
3136
+ } else {
3137
+ this.resizerX = new DiagramResizer(options.resizableX);
3138
+ }
3139
+ if (typeof options.resizableY === 'undefined') {
3140
+ this.resizerY = undefined;
3141
+ } else {
3142
+ this.resizerY = new DiagramResizer(options.resizableY);
3143
+ }
3144
+ if (typeof options.resizableXY === 'undefined') {
3145
+ this.resizerXY = undefined;
3146
+ } else {
3147
+ this.resizerXY = new DiagramResizer(options.resizableXY);
3148
+ }
3041
3149
  const looks = extractLooksFromConfig(options.look || DIAGRAM_NODE_LOOK_DEFAULTS);
3042
3150
  this.defaultLook = looks.defaultLook;
3043
3151
  this.selectedLook = looks.selectedLook;
@@ -3181,6 +3289,30 @@ class DiagramSection extends DiagramElement {
3181
3289
  var _a, _b, _c, _d, _e, _f;
3182
3290
  return ((_f = (_e = (_d = (_c = (_b = (_a = this.node) === null || _a === void 0 ? void 0 : _a.type) === null || _b === void 0 ? void 0 : _b.sectionGrid) === null || _c === void 0 ? void 0 : _c.sections) === null || _d === void 0 ? void 0 : _d[this.indexYInNode]) === null || _e === void 0 ? void 0 : _e[this.indexXInNode]) === null || _f === void 0 ? void 0 : _f.priority) || DEFAULT_PRIORITY;
3183
3291
  }
3292
+ /**
3293
+ * Returns the horizontal resizer of this section.
3294
+ * @public
3295
+ */
3296
+ getResizerX() {
3297
+ var _a, _b, _c, _d;
3298
+ return (_d = (_b = (_a = this.type) === null || _a === void 0 ? void 0 : _a.resizerX) !== null && _b !== void 0 ? _b : (_c = this.node) === null || _c === void 0 ? void 0 : _c.getResizerX()) !== null && _d !== void 0 ? _d : DIAGRAM_DEFAULT_RESIZER;
3299
+ }
3300
+ /**
3301
+ * Returns the vertical resizer of this section.
3302
+ * @public
3303
+ */
3304
+ getResizerY() {
3305
+ var _a, _b, _c, _d;
3306
+ return (_d = (_b = (_a = this.type) === null || _a === void 0 ? void 0 : _a.resizerY) !== null && _b !== void 0 ? _b : (_c = this.node) === null || _c === void 0 ? void 0 : _c.getResizerY()) !== null && _d !== void 0 ? _d : DIAGRAM_DEFAULT_RESIZER;
3307
+ }
3308
+ /**
3309
+ * Returns the diagonal resizer of this section.
3310
+ * @public
3311
+ */
3312
+ getResizerXY() {
3313
+ var _a, _b, _c, _d;
3314
+ return (_d = (_b = (_a = this.type) === null || _a === void 0 ? void 0 : _a.resizerXY) !== null && _b !== void 0 ? _b : (_c = this.node) === null || _c === void 0 ? void 0 : _c.getResizerXY()) !== null && _d !== void 0 ? _d : DIAGRAM_DEFAULT_RESIZER;
3315
+ }
3184
3316
  /**
3185
3317
  * Returns whether this section can be resized horizontally.
3186
3318
  * If the section has a specific resizableX setting, it uses that.
@@ -3190,11 +3322,16 @@ class DiagramSection extends DiagramElement {
3190
3322
  getResizableX() {
3191
3323
  var _a;
3192
3324
  const sectionType = this.type;
3193
- if ((sectionType === null || sectionType === void 0 ? void 0 : sectionType.resizableX) !== undefined) {
3194
- if (sectionType.resizableX === ResizableMode.OnlyWhenSelected) {
3195
- return this.selected;
3325
+ if ((sectionType === null || sectionType === void 0 ? void 0 : sectionType.resizerX) !== undefined) {
3326
+ switch (sectionType.resizerX.mode) {
3327
+ case ResizableMode.OnlyWhenSelected:
3328
+ return this.selected;
3329
+ case ResizableMode.Always:
3330
+ return true;
3331
+ case ResizableMode.Never:
3332
+ default:
3333
+ return false;
3196
3334
  }
3197
- return sectionType.resizableX;
3198
3335
  }
3199
3336
  return ((_a = this.node) === null || _a === void 0 ? void 0 : _a.getResizableX()) || false;
3200
3337
  }
@@ -3207,14 +3344,41 @@ class DiagramSection extends DiagramElement {
3207
3344
  getResizableY() {
3208
3345
  var _a;
3209
3346
  const sectionType = this.type;
3210
- if ((sectionType === null || sectionType === void 0 ? void 0 : sectionType.resizableY) !== undefined) {
3211
- if (sectionType.resizableY === ResizableMode.OnlyWhenSelected) {
3212
- return this.selected;
3347
+ if ((sectionType === null || sectionType === void 0 ? void 0 : sectionType.resizerY) !== undefined) {
3348
+ switch (sectionType.resizerY.mode) {
3349
+ case ResizableMode.OnlyWhenSelected:
3350
+ return this.selected;
3351
+ case ResizableMode.Always:
3352
+ return true;
3353
+ case ResizableMode.Never:
3354
+ default:
3355
+ return false;
3213
3356
  }
3214
- return sectionType.resizableY;
3215
3357
  }
3216
3358
  return ((_a = this.node) === null || _a === void 0 ? void 0 : _a.getResizableY()) || false;
3217
3359
  }
3360
+ /**
3361
+ * Returns whether this section can be resized diagonally.
3362
+ * If the section has a specific resizableXY setting, it uses that.
3363
+ * Otherwise, it inherits from the parent node's resizableXY setting.
3364
+ * @public
3365
+ */
3366
+ getResizableXY() {
3367
+ var _a;
3368
+ const sectionType = this.type;
3369
+ if ((sectionType === null || sectionType === void 0 ? void 0 : sectionType.resizerXY) !== undefined) {
3370
+ switch (sectionType.resizerXY.mode) {
3371
+ case ResizableMode.OnlyWhenSelected:
3372
+ return this.selected;
3373
+ case ResizableMode.Always:
3374
+ return true;
3375
+ case ResizableMode.Never:
3376
+ default:
3377
+ return false;
3378
+ }
3379
+ }
3380
+ return ((_a = this.node) === null || _a === void 0 ? void 0 : _a.getResizableXY()) || false;
3381
+ }
3218
3382
  /**
3219
3383
  * Get the port of this section which is closest to the given coordinates.
3220
3384
  * @param coords A point in the diagram.
@@ -3424,8 +3588,9 @@ class DiagramSectionSet extends DiagramElementSet {
3424
3588
  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 === void 0 ? void 0 : portConfig.direction, `${section.id}_${i}`, portConfig.anchorPointX || 'floating', portConfig.anchorPointY || 'floating');
3425
3589
  if ((_e = port.type) === null || _e === void 0 ? void 0 : _e.label) {
3426
3590
  const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), (_f = port.type) === null || _f === void 0 ? void 0 : _f.label);
3427
- const labelWidth = 6 * labelConfiguration.fontSize + getLeftPadding$1(labelConfiguration) + getRightPadding$1(labelConfiguration);
3428
- const labelHeight = labelConfiguration.fontSize + getTopPadding$1(labelConfiguration) + getBottomPadding$1(labelConfiguration);
3591
+ labelConfiguration.look = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS.look), labelConfiguration.look);
3592
+ const labelWidth = 6 * (labelConfiguration.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize) + getLeftPadding$1(labelConfiguration) + getRightPadding$1(labelConfiguration);
3593
+ const labelHeight = (labelConfiguration.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize) + getTopPadding$1(labelConfiguration) + getBottomPadding$1(labelConfiguration);
3429
3594
  let labelCoords;
3430
3595
  switch (port.direction) {
3431
3596
  case Side.Bottom:
@@ -3439,7 +3604,7 @@ class DiagramSectionSet extends DiagramElementSet {
3439
3604
  default:
3440
3605
  labelCoords = port.coords;
3441
3606
  }
3442
- this.model.fields.new(port, labelCoords, labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelWidth, labelHeight, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
3607
+ this.model.fields.new(port, labelCoords, labelWidth, labelHeight, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, labelConfiguration.look, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
3443
3608
  }
3444
3609
  }
3445
3610
  }
@@ -3447,7 +3612,8 @@ class DiagramSectionSet extends DiagramElementSet {
3447
3612
  const sectionLabel = (_k = (_j = (_h = (_g = node.type.sectionGrid) === null || _g === void 0 ? void 0 : _g.sections) === null || _h === void 0 ? void 0 : _h[indexYInNode]) === null || _j === void 0 ? void 0 : _j[indexXInNode]) === null || _k === void 0 ? void 0 : _k.label;
3448
3613
  if (sectionLabel) {
3449
3614
  const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), sectionLabel);
3450
- this.model.fields.new(section, [section.coords[0] + getLeftMargin(labelConfiguration), section.coords[1] + getTopMargin(labelConfiguration)], labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, section.width - getLeftMargin(labelConfiguration) - getRightMargin(labelConfiguration), section.height - getTopMargin(labelConfiguration) - getBottomMargin(labelConfiguration), labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
3615
+ labelConfiguration.look = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS.look), labelConfiguration.look);
3616
+ this.model.fields.new(section, [section.coords[0] + getLeftMargin(labelConfiguration), section.coords[1] + getTopMargin(labelConfiguration)], section.width - getLeftMargin(labelConfiguration) - getRightMargin(labelConfiguration), section.height - getTopMargin(labelConfiguration) - getBottomMargin(labelConfiguration), labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, labelConfiguration.look, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
3451
3617
  }
3452
3618
  return section;
3453
3619
  }
@@ -3533,8 +3699,27 @@ class DiagramNodeType {
3533
3699
  this.defaultHeight = values.defaultHeight;
3534
3700
  this.minWidth = values.minWidth;
3535
3701
  this.minHeight = values.minHeight;
3536
- this.resizableX = values.resizableX;
3537
- this.resizableY = values.resizableY;
3702
+ if (typeof options.resizableX === 'undefined') {
3703
+ this.resizerX = new DiagramResizer({
3704
+ mode: ResizableMode.Never
3705
+ });
3706
+ } else {
3707
+ this.resizerX = new DiagramResizer(options.resizableX);
3708
+ }
3709
+ if (typeof options.resizableY === 'undefined') {
3710
+ this.resizerY = new DiagramResizer({
3711
+ mode: ResizableMode.Never
3712
+ });
3713
+ } else {
3714
+ this.resizerY = new DiagramResizer(options.resizableY);
3715
+ }
3716
+ if (typeof options.resizableXY === 'undefined') {
3717
+ this.resizerXY = new DiagramResizer({
3718
+ mode: ResizableMode.Never
3719
+ });
3720
+ } else {
3721
+ this.resizerXY = new DiagramResizer(options.resizableXY);
3722
+ }
3538
3723
  this.snapToGridOffset = values.snapToGridOffset;
3539
3724
  this.bottomPadding = getBottomPadding(values);
3540
3725
  this.leftPadding = getLeftPadding(values);
@@ -3603,7 +3788,7 @@ class DiagramNode extends DiagramElement {
3603
3788
  }
3604
3789
  }
3605
3790
  /**
3606
- * Current look of this port.
3791
+ * Current look of this node.
3607
3792
  * @private
3608
3793
  */
3609
3794
  get look() {
@@ -3724,27 +3909,71 @@ class DiagramNode extends DiagramElement {
3724
3909
  getPriority() {
3725
3910
  return this.type.priority;
3726
3911
  }
3912
+ /**
3913
+ * Returns the horizontal resizer of this node.
3914
+ * @public
3915
+ */
3916
+ getResizerX() {
3917
+ return this.type.resizerX;
3918
+ }
3919
+ /**
3920
+ * Returns the vertical resizer of this node.
3921
+ * @public
3922
+ */
3923
+ getResizerY() {
3924
+ return this.type.resizerY;
3925
+ }
3926
+ /**
3927
+ * Returns the diagonal resizer of this node.
3928
+ * @public
3929
+ */
3930
+ getResizerXY() {
3931
+ return this.type.resizerXY;
3932
+ }
3727
3933
  /**
3728
3934
  * Returns whether this node can be resized horizontally.
3729
3935
  * @public
3730
3936
  */
3731
3937
  getResizableX() {
3732
- const resizableX = this.type.resizableX;
3733
- if (resizableX === ResizableMode.OnlyWhenSelected) {
3734
- return this.selected;
3938
+ switch (this.type.resizerX.mode) {
3939
+ case ResizableMode.OnlyWhenSelected:
3940
+ return this.selected;
3941
+ case ResizableMode.Always:
3942
+ return true;
3943
+ case ResizableMode.Never:
3944
+ default:
3945
+ return false;
3735
3946
  }
3736
- return resizableX;
3737
3947
  }
3738
3948
  /**
3739
3949
  * Returns whether this node can be resized vertically.
3740
3950
  * @public
3741
3951
  */
3742
3952
  getResizableY() {
3743
- const resizableY = this.type.resizableY;
3744
- if (resizableY === ResizableMode.OnlyWhenSelected) {
3745
- return this.selected;
3953
+ switch (this.type.resizerY.mode) {
3954
+ case ResizableMode.OnlyWhenSelected:
3955
+ return this.selected;
3956
+ case ResizableMode.Always:
3957
+ return true;
3958
+ case ResizableMode.Never:
3959
+ default:
3960
+ return false;
3961
+ }
3962
+ }
3963
+ /**
3964
+ * Returns whether this node can be resized diagonally.
3965
+ * @public
3966
+ */
3967
+ getResizableXY() {
3968
+ switch (this.type.resizerXY.mode) {
3969
+ case ResizableMode.OnlyWhenSelected:
3970
+ return this.selected;
3971
+ case ResizableMode.Always:
3972
+ return true;
3973
+ case ResizableMode.Never:
3974
+ default:
3975
+ return false;
3746
3976
  }
3747
- return resizableY;
3748
3977
  }
3749
3978
  /**
3750
3979
  * Get the port of this node which is closest to the given coordinates.
@@ -4352,8 +4581,9 @@ class DiagramNodeSet extends DiagramElementSet {
4352
4581
  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}`, portConfig.anchorPointX || 'floating', portConfig.anchorPointY || 'floating');
4353
4582
  if ((_e = port.type) === null || _e === void 0 ? void 0 : _e.label) {
4354
4583
  const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), (_f = port.type) === null || _f === void 0 ? void 0 : _f.label);
4355
- const labelWidth = 6 * labelConfiguration.fontSize + getLeftPadding$1(labelConfiguration) + getRightPadding$1(labelConfiguration);
4356
- const labelHeight = labelConfiguration.fontSize + getTopPadding$1(labelConfiguration) + getBottomPadding$1(labelConfiguration);
4584
+ labelConfiguration.look = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS.look), labelConfiguration.look);
4585
+ const labelWidth = 6 * (labelConfiguration.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize) + getLeftPadding$1(labelConfiguration) + getRightPadding$1(labelConfiguration);
4586
+ const labelHeight = (labelConfiguration.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize) + getTopPadding$1(labelConfiguration) + getBottomPadding$1(labelConfiguration);
4357
4587
  let labelCoords;
4358
4588
  switch (port.direction) {
4359
4589
  case Side.Bottom:
@@ -4367,20 +4597,21 @@ class DiagramNodeSet extends DiagramElementSet {
4367
4597
  default:
4368
4598
  labelCoords = port.coords;
4369
4599
  }
4370
- this.model.fields.new(port, labelCoords, labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelWidth, labelHeight, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
4600
+ this.model.fields.new(port, labelCoords, labelWidth, labelHeight, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, labelConfiguration.look, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
4371
4601
  }
4372
4602
  }
4373
4603
  }
4374
4604
  // add node label
4375
4605
  if (nodeType.label) {
4376
4606
  const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), nodeType.label);
4377
- this.model.fields.new(node, [node.coords[0] + getLeftMargin(labelConfiguration), node.coords[1] + getTopMargin(labelConfiguration)], labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, node.width - getLeftMargin(labelConfiguration) - getRightMargin(labelConfiguration), node.height - getTopMargin(labelConfiguration) - getBottomMargin(labelConfiguration), labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
4607
+ labelConfiguration.look = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS.look), labelConfiguration.look);
4608
+ this.model.fields.new(node, [node.coords[0] + getLeftMargin(labelConfiguration), node.coords[1] + getTopMargin(labelConfiguration)], node.width - getLeftMargin(labelConfiguration) - getRightMargin(labelConfiguration), node.height - getTopMargin(labelConfiguration) - getBottomMargin(labelConfiguration), labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, labelConfiguration.look, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
4378
4609
  }
4379
4610
  // add node decorators
4380
4611
  if (nodeType.decorators.length > 0) {
4381
4612
  for (let i = 0; i < nodeType.decorators.length; ++i) {
4382
4613
  const decoratorConfig = nodeType.decorators[i];
4383
- 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}`, decoratorConfig.anchorPointX || 'floating', decoratorConfig.anchorPointY || 'floating');
4614
+ this.model.decorators.new(node, [node.coords[0] + decoratorConfig.coords[0], node.coords[1] + decoratorConfig.coords[1]], decoratorConfig.width, decoratorConfig.height, node.getPriority(), decoratorConfig.svg, `${node.id}_decorator_${i}`, decoratorConfig.anchorPointX || 'floating', decoratorConfig.anchorPointY || 'floating');
4384
4615
  }
4385
4616
  }
4386
4617
  node.valueSet.resetValues();
@@ -4481,9 +4712,7 @@ const getBottomPadding = config => {
4481
4712
  } else if (typeof config.padding === 'number') {
4482
4713
  return config.padding;
4483
4714
  } else {
4484
- if (config.padding.length === 0) {
4485
- return DIAGRAM_NODE_TYPE_DEFAULTS.padding;
4486
- } else if (config.padding.length === 1) {
4715
+ if (config.padding.length === 1) {
4487
4716
  return config.padding[0];
4488
4717
  } else if (config.padding.length === 2) {
4489
4718
  return config.padding[0];
@@ -4493,64 +4722,235 @@ const getBottomPadding = config => {
4493
4722
  return config.padding[2];
4494
4723
  }
4495
4724
  }
4496
- };
4497
- const getLeftPadding = config => {
4498
- if ((config === null || config === void 0 ? void 0 : config.padding) === null || (config === null || config === void 0 ? void 0 : config.padding) === undefined) {
4499
- return DIAGRAM_NODE_TYPE_DEFAULTS.padding;
4500
- } else if (typeof config.padding === 'number') {
4501
- return config.padding;
4502
- } else {
4503
- if (config.padding.length === 0) {
4504
- return DIAGRAM_NODE_TYPE_DEFAULTS.padding;
4505
- } else if (config.padding.length === 1) {
4506
- return config.padding[0];
4507
- } else if (config.padding.length === 2) {
4508
- return config.padding[1];
4509
- } else if (config.padding.length === 3) {
4510
- return config.padding[1];
4511
- } else {
4512
- return config.padding[3];
4513
- }
4725
+ };
4726
+ const getLeftPadding = config => {
4727
+ if ((config === null || config === void 0 ? void 0 : config.padding) === null || (config === null || config === void 0 ? void 0 : config.padding) === undefined) {
4728
+ return DIAGRAM_NODE_TYPE_DEFAULTS.padding;
4729
+ } else if (typeof config.padding === 'number') {
4730
+ return config.padding;
4731
+ } else {
4732
+ if (config.padding.length === 1) {
4733
+ return config.padding[0];
4734
+ } else if (config.padding.length === 2) {
4735
+ return config.padding[1];
4736
+ } else if (config.padding.length === 3) {
4737
+ return config.padding[1];
4738
+ } else {
4739
+ return config.padding[3];
4740
+ }
4741
+ }
4742
+ };
4743
+ const getRightPadding = config => {
4744
+ if ((config === null || config === void 0 ? void 0 : config.padding) === null || (config === null || config === void 0 ? void 0 : config.padding) === undefined) {
4745
+ return DIAGRAM_NODE_TYPE_DEFAULTS.padding;
4746
+ } else if (typeof config.padding === 'number') {
4747
+ return config.padding;
4748
+ } else {
4749
+ if (config.padding.length === 1) {
4750
+ return config.padding[0];
4751
+ } else if (config.padding.length === 2) {
4752
+ return config.padding[1];
4753
+ } else if (config.padding.length === 3) {
4754
+ return config.padding[1];
4755
+ } else {
4756
+ return config.padding[1];
4757
+ }
4758
+ }
4759
+ };
4760
+ const getTopPadding = config => {
4761
+ if ((config === null || config === void 0 ? void 0 : config.padding) === null || (config === null || config === void 0 ? void 0 : config.padding) === undefined) {
4762
+ return DIAGRAM_NODE_TYPE_DEFAULTS.padding;
4763
+ } else if (typeof config.padding === 'number') {
4764
+ return config.padding;
4765
+ } else {
4766
+ if (config.padding.length === 1) {
4767
+ return config.padding[0];
4768
+ } else if (config.padding.length === 2) {
4769
+ return config.padding[0];
4770
+ } else if (config.padding.length === 3) {
4771
+ return config.padding[0];
4772
+ } else {
4773
+ return config.padding[0];
4774
+ }
4775
+ }
4776
+ };
4777
+
4778
+ /**
4779
+ * A foreign object which is inserted with arbitrary SVG code into a diagram.
4780
+ * Similar to a diagram object, but it's part of a node or section and it moves and stretches as its geometry changes.
4781
+ * Diagram decorators are not serialized with other diagram elements.
4782
+ * @public
4783
+ * @see DiagramNode
4784
+ * @see DiagramObject
4785
+ * @see DiagramSection
4786
+ */
4787
+ class DiagramDecorator extends DiagramElement {
4788
+ constructor(model, rootElement, coords, width, height, priority, svg, id, anchorPointX = 'floating', anchorPointY = 'floating') {
4789
+ if (model.objects.get(id) !== undefined) {
4790
+ throw new Error(`DiagramDecorator with id "${id}" already exists`);
4791
+ }
4792
+ if (!id) {
4793
+ throw new Error(`DiagramDecorator cannot have an empty or null id`);
4794
+ }
4795
+ super(model, id);
4796
+ this.rootElement = rootElement;
4797
+ this.coords = coords;
4798
+ this.width = width;
4799
+ this.height = height;
4800
+ this.priority = priority;
4801
+ this.svg = svg;
4802
+ this.anchorPointX = anchorPointX;
4803
+ this.anchorPointY = anchorPointY;
4804
+ }
4805
+ get removed() {
4806
+ return this.selfRemoved || this.rootElement !== undefined && this.rootElement.removed;
4807
+ }
4808
+ updateInView() {
4809
+ var _a;
4810
+ (_a = this.model.canvas) === null || _a === void 0 ? void 0 : _a.updateDecoratorsInView(this.id);
4811
+ }
4812
+ raise() {
4813
+ var _a;
4814
+ (_a = this.select()) === null || _a === void 0 ? void 0 : _a.raise();
4815
+ }
4816
+ /**
4817
+ * Change the coordinates of this decorator to the given coordinates.
4818
+ * @public
4819
+ * @param coords A point in the diagram.
4820
+ */
4821
+ move(coords) {
4822
+ this.coords = coords;
4823
+ this.updateInView();
4824
+ }
4825
+ getPriority() {
4826
+ return this.priority;
4827
+ }
4828
+ }
4829
+ class DiagramDecoratorSet extends DiagramElementSet {
4830
+ /**
4831
+ * Instance a set of decorators for the given model. This method is used internally.
4832
+ * @private
4833
+ */
4834
+ constructor(model) {
4835
+ super();
4836
+ this.model = model;
4837
+ }
4838
+ /**
4839
+ * Instance a new decorator and add it to this set.
4840
+ * @public
4841
+ * @param coords The coordinates of the top left corner of the decorator in the diagram.
4842
+ * @param width The dimension of the decorator along the x axis.
4843
+ * @param height The dimension of the decorator along the y axis.
4844
+ * @param priority The priority of the decorator. Used when filtering by priority.
4845
+ * @param svg The SVG contents of the decorator.
4846
+ * @param id The id of the decorator. Cannot be an empty string.
4847
+ * @returns The instanced decorator.
4848
+ */
4849
+ new(rootElement, coords, width, height, priority, svg, id, anchorPointX = 'floating', anchorPointY = 'floating') {
4850
+ const decorator = new DiagramDecorator(this.model, rootElement, coords, width, height, priority, svg, id, anchorPointX, anchorPointY);
4851
+ super.add(decorator);
4852
+ decorator.updateInView();
4853
+ // add this port to its root element
4854
+ if (rootElement !== undefined) {
4855
+ rootElement.decorators.push(decorator);
4856
+ }
4857
+ return decorator;
4858
+ }
4859
+ remove(id) {
4860
+ const decorator = this.get(id, true);
4861
+ if (decorator) {
4862
+ // remove from root element
4863
+ if (decorator.rootElement instanceof DiagramNode || decorator.rootElement instanceof DiagramSection) {
4864
+ removeIfExists(decorator.rootElement.decorators, decorator);
4865
+ }
4866
+ // remove from set of objects
4867
+ super.remove(id);
4868
+ // remove from canvas
4869
+ decorator.updateInView();
4870
+ }
4871
+ }
4872
+ }
4873
+
4874
+ /**
4875
+ * A foreign object which is inserted with arbitrary SVG code into a diagram.
4876
+ * Diagram objects are not serialized with other diagram elements.
4877
+ * @public
4878
+ */
4879
+ class DiagramObject extends DiagramElement {
4880
+ constructor(model, coords, width, height, priority, svg, id) {
4881
+ if (model.objects.get(id) !== undefined) {
4882
+ throw new Error(`DiagramObject with id "${id}" already exists`);
4883
+ }
4884
+ if (!id) {
4885
+ throw new Error(`DiagramObject cannot have an empty or null id`);
4886
+ }
4887
+ super(model, id);
4888
+ this.coords = coords;
4889
+ this.width = width;
4890
+ this.height = height;
4891
+ this.priority = priority;
4892
+ this.svg = svg;
4893
+ }
4894
+ get removed() {
4895
+ return this.selfRemoved;
4896
+ }
4897
+ updateInView() {
4898
+ var _a;
4899
+ (_a = this.model.canvas) === null || _a === void 0 ? void 0 : _a.updateObjectsInView(this.id);
4900
+ }
4901
+ raise() {
4902
+ var _a;
4903
+ (_a = this.select()) === null || _a === void 0 ? void 0 : _a.raise();
4904
+ }
4905
+ /**
4906
+ * Change the coordinates of this object to the given coordinates.
4907
+ * @public
4908
+ * @param coords A point in the diagram.
4909
+ */
4910
+ move(coords) {
4911
+ this.coords = coords;
4912
+ this.updateInView();
4514
4913
  }
4515
- };
4516
- const getRightPadding = config => {
4517
- if ((config === null || config === void 0 ? void 0 : config.padding) === null || (config === null || config === void 0 ? void 0 : config.padding) === undefined) {
4518
- return DIAGRAM_NODE_TYPE_DEFAULTS.padding;
4519
- } else if (typeof config.padding === 'number') {
4520
- return config.padding;
4521
- } else {
4522
- if (config.padding.length === 0) {
4523
- return DIAGRAM_NODE_TYPE_DEFAULTS.padding;
4524
- } else if (config.padding.length === 1) {
4525
- return config.padding[0];
4526
- } else if (config.padding.length === 2) {
4527
- return config.padding[1];
4528
- } else if (config.padding.length === 3) {
4529
- return config.padding[1];
4530
- } else {
4531
- return config.padding[1];
4532
- }
4914
+ getPriority() {
4915
+ return this.priority;
4533
4916
  }
4534
- };
4535
- const getTopPadding = config => {
4536
- if ((config === null || config === void 0 ? void 0 : config.padding) === null || (config === null || config === void 0 ? void 0 : config.padding) === undefined) {
4537
- return DIAGRAM_NODE_TYPE_DEFAULTS.padding;
4538
- } else if (typeof config.padding === 'number') {
4539
- return config.padding;
4540
- } else {
4541
- if (config.padding.length === 0) {
4542
- return DIAGRAM_NODE_TYPE_DEFAULTS.padding;
4543
- } else if (config.padding.length === 1) {
4544
- return config.padding[0];
4545
- } else if (config.padding.length === 2) {
4546
- return config.padding[0];
4547
- } else if (config.padding.length === 3) {
4548
- return config.padding[0];
4549
- } else {
4550
- return config.padding[0];
4917
+ }
4918
+ class DiagramObjectSet extends DiagramElementSet {
4919
+ /**
4920
+ * Instance a set of objects for the given model. This method is used internally.
4921
+ * @private
4922
+ */
4923
+ constructor(model) {
4924
+ super();
4925
+ this.model = model;
4926
+ }
4927
+ /**
4928
+ * Instance a new object and add it to this set.
4929
+ * @public
4930
+ * @param coords The coordinates of the top left corner of the object in the diagram.
4931
+ * @param width The dimension of the object along the x axis.
4932
+ * @param height The dimension of the object along the y axis.
4933
+ * @param priority The priority of the object. Used when filtering by priority.
4934
+ * @param svg The SVG contents of the object.
4935
+ * @param id The id of the object. Cannot be an empty string.
4936
+ * @returns The instanced object.
4937
+ */
4938
+ new(coords, width, height, priority, svg, id) {
4939
+ const object = new DiagramObject(this.model, coords, width, height, priority, svg, id);
4940
+ super.add(object);
4941
+ object.updateInView();
4942
+ return object;
4943
+ }
4944
+ remove(id) {
4945
+ const object = this.get(id, true);
4946
+ if (object) {
4947
+ // remove from set of objects
4948
+ super.remove(id);
4949
+ // remove from canvas
4950
+ object.updateInView();
4551
4951
  }
4552
4952
  }
4553
- };
4953
+ }
4554
4954
 
4555
4955
  /**
4556
4956
  * Default values of the look of a diagram port.
@@ -4917,6 +5317,14 @@ class DagaImporter {
4917
5317
  for (const connection of data.connections || []) {
4918
5318
  this.importConnection(model, connection);
4919
5319
  }
5320
+ for (const object of data.objects || []) {
5321
+ const newObject = new DiagramObject(model, object.coords, object.width, object.height, object.priority, object.svg, object.id);
5322
+ if (object.collabMeta) {
5323
+ newObject.selfRemoved = object.collabMeta.selfRemoved;
5324
+ }
5325
+ model.objects.add(newObject);
5326
+ newObject.updateInView();
5327
+ }
4920
5328
  if (data.data) {
4921
5329
  model.valueSet.setValues(data.data);
4922
5330
  }
@@ -4934,17 +5342,11 @@ class DagaImporter {
4934
5342
  model.nodes.add(newNode);
4935
5343
  newNode.width = node.width;
4936
5344
  newNode.height = node.height;
4937
- // add node decorators
4938
- if (newNodeType.decorators) {
4939
- for (let i = 0; i < newNodeType.decorators.length; ++i) {
4940
- const decoratorConfig = newNodeType.decorators[i];
4941
- 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}`);
4942
- }
4943
- }
4944
5345
  // add node label
4945
5346
  if (newNodeType.label) {
4946
5347
  const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), newNodeType.label);
4947
- const newField = new DiagramField(model, newNode, [newNode.coords[0] + getLeftMargin(labelConfiguration), newNode.coords[1] + getTopMargin(labelConfiguration)], newNode.width - getLeftMargin(labelConfiguration) - getRightMargin(labelConfiguration), newNode.height - getTopMargin(labelConfiguration) - getBottomMargin(labelConfiguration), labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
5348
+ labelConfiguration.look = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS.look), labelConfiguration.look);
5349
+ const newField = new DiagramField(model, newNode, [newNode.coords[0] + getLeftMargin(labelConfiguration), newNode.coords[1] + getTopMargin(labelConfiguration)], newNode.width - getLeftMargin(labelConfiguration) - getRightMargin(labelConfiguration), newNode.height - getTopMargin(labelConfiguration) - getBottomMargin(labelConfiguration), labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, labelConfiguration.look, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
4948
5350
  newField.text = node.label;
4949
5351
  newNode.label = newField;
4950
5352
  model.fields.add(newField);
@@ -4964,7 +5366,8 @@ class DagaImporter {
4964
5366
  // add section label
4965
5367
  if ((_f = (_e = (_d = (_c = newNodeType.sectionGrid) === null || _c === void 0 ? void 0 : _c.sections) === null || _d === void 0 ? void 0 : _d[section.indexYInNode]) === null || _e === void 0 ? void 0 : _e[section.indexXInNode]) === null || _f === void 0 ? void 0 : _f.label) {
4966
5368
  const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), (_k = (_j = (_h = (_g = newNodeType.sectionGrid) === null || _g === void 0 ? void 0 : _g.sections) === null || _h === void 0 ? void 0 : _h[section.indexYInNode]) === null || _j === void 0 ? void 0 : _j[section.indexXInNode]) === null || _k === void 0 ? void 0 : _k.label);
4967
- const newField = new DiagramField(model, newSection, [newSection.coords[0] + getLeftMargin(labelConfiguration), newSection.coords[1] + getTopMargin(labelConfiguration)], newSection.width - getLeftMargin(labelConfiguration) - getRightMargin(labelConfiguration), newSection.height - getTopMargin(labelConfiguration) - getBottomMargin(labelConfiguration), labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
5369
+ labelConfiguration.look = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS.look), labelConfiguration.look);
5370
+ const newField = new DiagramField(model, newSection, [newSection.coords[0] + getLeftMargin(labelConfiguration), newSection.coords[1] + getTopMargin(labelConfiguration)], newSection.width - getLeftMargin(labelConfiguration) - getRightMargin(labelConfiguration), newSection.height - getTopMargin(labelConfiguration) - getBottomMargin(labelConfiguration), labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, labelConfiguration.look, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
4968
5371
  newField.text = section.label;
4969
5372
  newSection.label = newField;
4970
5373
  model.fields.add(newField);
@@ -4980,22 +5383,23 @@ class DagaImporter {
4980
5383
  // add port label
4981
5384
  if (newNodeType.ports.length > portCounter && (newPortType === null || newPortType === void 0 ? void 0 : newPortType.label)) {
4982
5385
  const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), newPortType === null || newPortType === void 0 ? void 0 : newPortType.label);
5386
+ labelConfiguration.look = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS.look), labelConfiguration.look);
4983
5387
  let labelCoords;
4984
5388
  switch (newPort.direction) {
4985
5389
  case Side.Top:
4986
5390
  case Side.Left:
4987
- labelCoords = [newPort.coords[0] - labelConfiguration.fontSize, newPort.coords[1] - labelConfiguration.fontSize];
5391
+ labelCoords = [newPort.coords[0] - (labelConfiguration.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize), newPort.coords[1] - (labelConfiguration.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize)];
4988
5392
  break;
4989
5393
  case Side.Bottom:
4990
- labelCoords = [newPort.coords[0] - labelConfiguration.fontSize, newPort.coords[1] + labelConfiguration.fontSize];
5394
+ labelCoords = [newPort.coords[0] - (labelConfiguration.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize), newPort.coords[1] + (labelConfiguration.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize)];
4991
5395
  break;
4992
5396
  case Side.Right:
4993
- labelCoords = [newPort.coords[0] + labelConfiguration.fontSize, newPort.coords[1] - labelConfiguration.fontSize];
5397
+ labelCoords = [newPort.coords[0] + (labelConfiguration.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize), newPort.coords[1] - (labelConfiguration.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize)];
4994
5398
  break;
4995
5399
  default:
4996
5400
  labelCoords = newPort.coords;
4997
5401
  }
4998
- const newField = new DiagramField(model, newPort, labelCoords, labelConfiguration.fontSize, labelConfiguration.fontSize, labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
5402
+ const newField = new DiagramField(model, newPort, labelCoords, labelConfiguration.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize, labelConfiguration.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, labelConfiguration.look, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
4999
5403
  newField.text = port.label;
5000
5404
  newPort.label = newField;
5001
5405
  model.fields.add(newField);
@@ -5010,6 +5414,15 @@ class DagaImporter {
5010
5414
  }
5011
5415
  newPort.updateInView();
5012
5416
  }
5417
+ for (const decorator of section.decorators || []) {
5418
+ const newDecorator = new DiagramDecorator(model, newSection, decorator.coords, decorator.width, decorator.height, decorator.priority, decorator.svg, decorator.id, decorator.anchorPoints[0], decorator.anchorPoints[1]);
5419
+ if (decorator.collabMeta) {
5420
+ newDecorator.selfRemoved = decorator.collabMeta.selfRemoved;
5421
+ }
5422
+ newNode.decorators.push(newDecorator);
5423
+ model.decorators.add(newDecorator);
5424
+ newDecorator.updateInView();
5425
+ }
5013
5426
  if (section.collabMeta) {
5014
5427
  newSection.selfRemoved = section.collabMeta.selfRemoved;
5015
5428
  newSection.selfRemovedTimestamp = section.collabMeta.selfRemovedTimestamp;
@@ -5027,22 +5440,23 @@ class DagaImporter {
5027
5440
  // add port label
5028
5441
  if (newNodeType.ports.length > portCounter && (newPortType === null || newPortType === void 0 ? void 0 : newPortType.label)) {
5029
5442
  const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), newPortType === null || newPortType === void 0 ? void 0 : newPortType.label);
5443
+ labelConfiguration.look = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS.look), labelConfiguration.look);
5030
5444
  let labelCoords;
5031
5445
  switch (newPort.direction) {
5032
5446
  case Side.Top:
5033
5447
  case Side.Left:
5034
- labelCoords = [newPort.coords[0] - labelConfiguration.fontSize, newPort.coords[1] - labelConfiguration.fontSize];
5448
+ labelCoords = [newPort.coords[0] - (labelConfiguration.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize), newPort.coords[1] - (labelConfiguration.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize)];
5035
5449
  break;
5036
5450
  case Side.Bottom:
5037
- labelCoords = [newPort.coords[0] - labelConfiguration.fontSize, newPort.coords[1] + labelConfiguration.fontSize];
5451
+ labelCoords = [newPort.coords[0] - (labelConfiguration.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize), newPort.coords[1] + (labelConfiguration.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize)];
5038
5452
  break;
5039
5453
  case Side.Right:
5040
- labelCoords = [newPort.coords[0] + labelConfiguration.fontSize, newPort.coords[1] - labelConfiguration.fontSize];
5454
+ labelCoords = [newPort.coords[0] + (labelConfiguration.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize), newPort.coords[1] - (labelConfiguration.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize)];
5041
5455
  break;
5042
5456
  default:
5043
5457
  labelCoords = newPort.coords;
5044
5458
  }
5045
- const newField = new DiagramField(model, newPort, labelCoords, labelConfiguration.fontSize, labelConfiguration.fontSize, labelConfiguration.fontSize, labelConfiguration.fontFamily, labelConfiguration.color, labelConfiguration.selectedColor, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
5459
+ const newField = new DiagramField(model, newPort, labelCoords, labelConfiguration.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize, labelConfiguration.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize, labelConfiguration.horizontalAlign, labelConfiguration.verticalAlign, labelConfiguration.orientation, labelConfiguration.multiline, labelConfiguration.look, '', labelConfiguration.editable, labelConfiguration.fit, labelConfiguration.shrink);
5046
5460
  newField.text = port.label;
5047
5461
  newPort.label = newField;
5048
5462
  model.fields.add(newField);
@@ -5057,6 +5471,15 @@ class DagaImporter {
5057
5471
  }
5058
5472
  newPort.updateInView();
5059
5473
  }
5474
+ for (const decorator of node.decorators || []) {
5475
+ const newDecorator = new DiagramDecorator(model, newNode, decorator.coords, decorator.width, decorator.height, decorator.priority, decorator.svg, decorator.id, decorator.anchorPoints[0], decorator.anchorPoints[1]);
5476
+ if (decorator.collabMeta) {
5477
+ newDecorator.selfRemoved = decorator.collabMeta.selfRemoved;
5478
+ }
5479
+ newNode.decorators.push(newDecorator);
5480
+ model.decorators.add(newDecorator);
5481
+ newDecorator.updateInView();
5482
+ }
5060
5483
  if (node.data) {
5061
5484
  newNode.valueSet.setValues(node.data);
5062
5485
  }
@@ -6348,7 +6771,8 @@ class DiagramZoomEvent extends DiagramEvent {
6348
6771
  /**
6349
6772
  * Create a diagram zoom event.
6350
6773
  *
6351
- * @param coords .
6774
+ * @param coords Coordinates to which the user panned. Calling the method `canvas.translateTo()` with these coordinates after this event should cause no changes.
6775
+ * @param zoom Zoom level to which the user zoomed. Calling the method `canvas.zoomTo()` with this zoom level after this event should cause no changes.
6352
6776
  */
6353
6777
  constructor(coords, zoom) {
6354
6778
  super(DiagramEvents.Zoom);
@@ -6408,210 +6832,33 @@ class DiagramSelectionEvent extends DiagramEvent {
6408
6832
  this.selected = selected;
6409
6833
  }
6410
6834
  }
6411
- /**
6412
- * Diagram event which consists of the user highlighting a diagram element.
6413
- * If the target is `null`, that means that the previously highlighted element was unhighlighted.
6414
- */
6415
- class DiagramHighlightedEvent extends DiagramEvent {
6416
- /**
6417
- * Create a diagram highlight event.
6418
- *
6419
- * @param target Diagram element which is targeted by the event.
6420
- */
6421
- constructor(target) {
6422
- super(DiagramEvents.Highlight);
6423
- this.target = target;
6424
- }
6425
- }
6426
- /**
6427
- * Diagram event which consists of the user dragging a diagram node.
6428
- */
6429
- class DiagramDraggingNodeEvent extends DiagramEvent {
6430
- /**
6431
- * Create a diagram dragging node event.
6432
- *
6433
- * @param target Diagram node which is targeted by the event.
6434
- */
6435
- constructor(target) {
6436
- super(DiagramEvents.DraggingNode);
6437
- this.target = target;
6438
- }
6439
- }
6440
-
6441
- /**
6442
- * A foreign object which is inserted with arbitrary html into a diagram.
6443
- * Similar to a diagram object, but it's part of a node or section and it moves and stretches as its geometry changes.
6444
- * Diagram decorators are not serialized with other diagram elements.
6445
- * @public
6446
- * @see DiagramNode
6447
- * @see DiagramObject
6448
- * @see DiagramSection
6449
- */
6450
- class DiagramDecorator extends DiagramElement {
6451
- constructor(model, rootElement, coords, width, height, priority, html, id, anchorPointX = 'floating', anchorPointY = 'floating') {
6452
- if (model.objects.get(id) !== undefined) {
6453
- throw new Error(`DiagramDecorator with id "${id}" already exists`);
6454
- }
6455
- if (!id) {
6456
- throw new Error(`DiagramDecorator cannot have an empty or null id`);
6457
- }
6458
- super(model, id);
6459
- this.rootElement = rootElement;
6460
- this.coords = coords;
6461
- this.width = width;
6462
- this.height = height;
6463
- this.priority = priority;
6464
- this.html = html;
6465
- this.anchorPointX = anchorPointX;
6466
- this.anchorPointY = anchorPointY;
6467
- }
6468
- get removed() {
6469
- return this.selfRemoved || this.rootElement !== undefined && this.rootElement.removed;
6470
- }
6471
- updateInView() {
6472
- var _a;
6473
- (_a = this.model.canvas) === null || _a === void 0 ? void 0 : _a.updateDecoratorsInView(this.id);
6474
- }
6475
- raise() {
6476
- var _a;
6477
- (_a = this.select()) === null || _a === void 0 ? void 0 : _a.raise();
6478
- }
6479
- /**
6480
- * Change the coordinates of this decorator to the given coordinates.
6481
- * @public
6482
- * @param coords A point in the diagram.
6483
- */
6484
- move(coords) {
6485
- this.coords = coords;
6486
- this.updateInView();
6487
- }
6488
- getPriority() {
6489
- return this.priority;
6490
- }
6491
- }
6492
- class DiagramDecoratorSet extends DiagramElementSet {
6493
- /**
6494
- * Instance a set of decorators for the given model. This method is used internally.
6495
- * @private
6496
- */
6497
- constructor(model) {
6498
- super();
6499
- this.model = model;
6500
- }
6501
- /**
6502
- * Instance a new decorator and add it to this set.
6503
- * @public
6504
- * @param coords The coordinates of the top left corner of the decorator in the diagram.
6505
- * @param width The dimension of the decorator along the x axis.
6506
- * @param height The dimension of the decorator along the y axis.
6507
- * @param priority The priority of the decorator. Used when filtering by priority.
6508
- * @param html The html contents of the decorator.
6509
- * @param id The id of the decorator. Cannot be an empty string.
6510
- * @returns The instanced decorator.
6511
- */
6512
- new(rootElement, coords, width, height, priority, html, id, anchorPointX = 'floating', anchorPointY = 'floating') {
6513
- const decorator = new DiagramDecorator(this.model, rootElement, coords, width, height, priority, html, id, anchorPointX, anchorPointY);
6514
- super.add(decorator);
6515
- decorator.updateInView();
6516
- // add this port to its root element
6517
- if (rootElement !== undefined) {
6518
- rootElement.decorators.push(decorator);
6519
- }
6520
- return decorator;
6521
- }
6522
- remove(id) {
6523
- const decorator = this.get(id, true);
6524
- if (decorator) {
6525
- // remove from root element
6526
- if (decorator.rootElement instanceof DiagramNode || decorator.rootElement instanceof DiagramSection) {
6527
- removeIfExists(decorator.rootElement.decorators, decorator);
6528
- }
6529
- // remove from set of objects
6530
- super.remove(id);
6531
- // remove from canvas
6532
- decorator.updateInView();
6533
- }
6534
- }
6535
- }
6536
-
6537
- /**
6538
- * A foreign object which is inserted with arbitrary html into a diagram.
6539
- * Diagram objects are not serialized with other diagram elements.
6540
- * @public
6541
- */
6542
- class DiagramObject extends DiagramElement {
6543
- constructor(model, coords, width, height, priority, html, id) {
6544
- if (model.objects.get(id) !== undefined) {
6545
- throw new Error(`DiagramObject with id "${id}" already exists`);
6546
- }
6547
- if (!id) {
6548
- throw new Error(`DiagramObject cannot have an empty or null id`);
6549
- }
6550
- super(model, id);
6551
- this.coords = coords;
6552
- this.width = width;
6553
- this.height = height;
6554
- this.priority = priority;
6555
- this.html = html;
6556
- }
6557
- get removed() {
6558
- return this.selfRemoved;
6559
- }
6560
- updateInView() {
6561
- var _a;
6562
- (_a = this.model.canvas) === null || _a === void 0 ? void 0 : _a.updateObjectsInView(this.id);
6563
- }
6564
- raise() {
6565
- var _a;
6566
- (_a = this.select()) === null || _a === void 0 ? void 0 : _a.raise();
6567
- }
6568
- /**
6569
- * Change the coordinates of this object to the given coordinates.
6570
- * @public
6571
- * @param coords A point in the diagram.
6572
- */
6573
- move(coords) {
6574
- this.coords = coords;
6575
- this.updateInView();
6576
- }
6577
- getPriority() {
6578
- return this.priority;
6579
- }
6580
- }
6581
- class DiagramObjectSet extends DiagramElementSet {
6835
+ /**
6836
+ * Diagram event which consists of the user highlighting a diagram element.
6837
+ * If the target is `null`, that means that the previously highlighted element was unhighlighted.
6838
+ */
6839
+ class DiagramHighlightedEvent extends DiagramEvent {
6582
6840
  /**
6583
- * Instance a set of objects for the given model. This method is used internally.
6584
- * @private
6841
+ * Create a diagram highlight event.
6842
+ *
6843
+ * @param target Diagram element which is targeted by the event.
6585
6844
  */
6586
- constructor(model) {
6587
- super();
6588
- this.model = model;
6845
+ constructor(target) {
6846
+ super(DiagramEvents.Highlight);
6847
+ this.target = target;
6589
6848
  }
6849
+ }
6850
+ /**
6851
+ * Diagram event which consists of the user dragging a diagram node.
6852
+ */
6853
+ class DiagramDraggingNodeEvent extends DiagramEvent {
6590
6854
  /**
6591
- * Instance a new object and add it to this set.
6592
- * @public
6593
- * @param coords The coordinates of the top left corner of the object in the diagram.
6594
- * @param width The dimension of the object along the x axis.
6595
- * @param height The dimension of the object along the y axis.
6596
- * @param priority The priority of the object. Used when filtering by priority.
6597
- * @param html The html contents of the object.
6598
- * @param id The id of the object. Cannot be an empty string.
6599
- * @returns The instanced object.
6855
+ * Create a diagram dragging node event.
6856
+ *
6857
+ * @param target Diagram node which is targeted by the event.
6600
6858
  */
6601
- new(coords, width, height, priority, html, id) {
6602
- const object = new DiagramObject(this.model, coords, width, height, priority, html, id);
6603
- super.add(object);
6604
- object.updateInView();
6605
- return object;
6606
- }
6607
- remove(id) {
6608
- const object = this.get(id, true);
6609
- if (object) {
6610
- // remove from set of objects
6611
- super.remove(id);
6612
- // remove from canvas
6613
- object.updateInView();
6614
- }
6859
+ constructor(target) {
6860
+ super(DiagramEvents.DraggingNode);
6861
+ this.target = target;
6615
6862
  }
6616
6863
  }
6617
6864
 
@@ -6716,7 +6963,7 @@ const isSecondaryButton = event => {
6716
6963
  const getConnectionPath = (shape, startCoords, endCoords, startDirection, endDirection, points, width, startMarkerWidth, endMarkerWidth) => {
6717
6964
  return linePath(shape, [startCoords, ...points, endCoords], startDirection, endDirection, Math.max(
6718
6965
  // reasonable value for the minimumDistanceBeforeTurn relative to the line width
6719
- 10, startMarkerWidth || 0, endMarkerWidth || 0) * width);
6966
+ 10, startMarkerWidth !== null && startMarkerWidth !== void 0 ? startMarkerWidth : 0, endMarkerWidth !== null && endMarkerWidth !== void 0 ? endMarkerWidth : 0) * width);
6720
6967
  };
6721
6968
  const setCursorStyle = style => {
6722
6969
  if (!style) {
@@ -6726,21 +6973,23 @@ const setCursorStyle = style => {
6726
6973
  }
6727
6974
  };
6728
6975
  const getRelatedNodeOrItself = element => {
6976
+ var _a;
6729
6977
  if (element instanceof DiagramNode) {
6730
6978
  return element;
6731
6979
  }
6732
6980
  if (element instanceof DiagramSection) {
6733
- return element.node || element;
6981
+ return (_a = element.node) !== null && _a !== void 0 ? _a : element;
6734
6982
  }
6735
6983
  return element.rootElement instanceof DiagramNode || element.rootElement instanceof DiagramSection || element.rootElement instanceof DiagramPort ? getRelatedNodeOrItself(element.rootElement) : element;
6736
6984
  };
6737
6985
  const needsResizerX = element => {
6986
+ var _a;
6738
6987
  if (element instanceof DiagramNode) {
6739
- return element.type.resizableX !== false;
6988
+ return element.type.resizerX.mode !== ResizableMode.Never;
6740
6989
  }
6741
6990
  if (element instanceof DiagramSection) {
6742
- if (element.type !== undefined) {
6743
- return element.type.resizableX !== false;
6991
+ if (((_a = element.type) === null || _a === void 0 ? void 0 : _a.resizerX) !== undefined) {
6992
+ return element.type.resizerX.mode !== ResizableMode.Never;
6744
6993
  }
6745
6994
  if (element.node !== undefined) {
6746
6995
  return needsResizerX(element.node);
@@ -6749,12 +6998,13 @@ const needsResizerX = element => {
6749
6998
  return false;
6750
6999
  };
6751
7000
  const needsResizerY = element => {
7001
+ var _a;
6752
7002
  if (element instanceof DiagramNode) {
6753
- return element.type.resizableY !== false;
7003
+ return element.type.resizerY.mode !== ResizableMode.Never;
6754
7004
  }
6755
7005
  if (element instanceof DiagramSection) {
6756
- if (element.type !== undefined) {
6757
- return element.type.resizableY !== false;
7006
+ if (((_a = element.type) === null || _a === void 0 ? void 0 : _a.resizerY) !== undefined) {
7007
+ return element.type.resizerY.mode !== ResizableMode.Never;
6758
7008
  }
6759
7009
  if (element.node !== undefined) {
6760
7010
  return needsResizerY(element.node);
@@ -6762,6 +7012,21 @@ const needsResizerY = element => {
6762
7012
  }
6763
7013
  return false;
6764
7014
  };
7015
+ const needsResizerXY = element => {
7016
+ var _a;
7017
+ if (element instanceof DiagramNode) {
7018
+ return element.type.resizerXY.mode !== ResizableMode.Never;
7019
+ }
7020
+ if (element instanceof DiagramSection) {
7021
+ if (((_a = element.type) === null || _a === void 0 ? void 0 : _a.resizerXY) !== undefined) {
7022
+ return element.type.resizerXY.mode !== ResizableMode.Never;
7023
+ }
7024
+ if (element.node !== undefined) {
7025
+ return needsResizerXY(element.node);
7026
+ }
7027
+ }
7028
+ return false;
7029
+ };
6765
7030
  const initializeLook = selection => {
6766
7031
  selection.filter('.shaped-look').append('path');
6767
7032
  selection.filter('.image-look').append('image').attr('preserveAspectRatio', 'none');
@@ -6782,9 +7047,21 @@ const SHAPED_LOOK_DEFAULTS = {
6782
7047
  borderStyle: LineStyle.Solid
6783
7048
  };
6784
7049
  const updateLook = selection => {
6785
- selection.filter('.shaped-look').select('path').attr('d', d => generalClosedPath(d.look.shape || ClosedShape.Rectangle, 0, 0, d.width, d.height)).attr('fill', d => d.look.fillColor || SHAPED_LOOK_DEFAULTS.fillColor).attr('stroke', d => d.look.borderColor || SHAPED_LOOK_DEFAULTS.borderColor).attr('stroke-width', d => `${d.look.borderThickness || SHAPED_LOOK_DEFAULTS.borderThickness}px`).attr('stroke-dasharray', d => {
6786
- var _a, _b, _c;
6787
- return lineStyleDasharray(d.look.borderStyle || SHAPED_LOOK_DEFAULTS.borderStyle, ((_b = (_a = d.type) === null || _a === void 0 ? void 0 : _a.defaultLook) === null || _b === void 0 ? void 0 : _b.borderThickness) || ((_c = d.look) === null || _c === void 0 ? void 0 : _c.borderThickness) || SHAPED_LOOK_DEFAULTS.borderThickness);
7050
+ selection.filter('.shaped-look').select('path').attr('d', d => {
7051
+ var _a;
7052
+ return generalClosedPath((_a = d.look.shape) !== null && _a !== void 0 ? _a : ClosedShape.Rectangle, 0, 0, d.width, d.height);
7053
+ }).attr('fill', d => {
7054
+ var _a;
7055
+ return (_a = d.look.fillColor) !== null && _a !== void 0 ? _a : SHAPED_LOOK_DEFAULTS.fillColor;
7056
+ }).attr('stroke', d => {
7057
+ var _a;
7058
+ return (_a = d.look.borderColor) !== null && _a !== void 0 ? _a : SHAPED_LOOK_DEFAULTS.borderColor;
7059
+ }).attr('stroke-width', d => {
7060
+ var _a;
7061
+ return `${(_a = d.look.borderThickness) !== null && _a !== void 0 ? _a : SHAPED_LOOK_DEFAULTS.borderThickness}px`;
7062
+ }).attr('stroke-dasharray', d => {
7063
+ var _a, _b, _c, _d, _e, _f;
7064
+ return lineStyleDasharray((_a = d.look.borderStyle) !== null && _a !== void 0 ? _a : SHAPED_LOOK_DEFAULTS.borderStyle, (_f = (_d = (_c = (_b = d.type) === null || _b === void 0 ? void 0 : _b.defaultLook) === null || _c === void 0 ? void 0 : _c.borderThickness) !== null && _d !== void 0 ? _d : (_e = d.look) === null || _e === void 0 ? void 0 : _e.borderThickness) !== null && _f !== void 0 ? _f : SHAPED_LOOK_DEFAULTS.borderThickness);
6788
7065
  });
6789
7066
  selection.filter('.image-look').select('image').attr('x', 0).attr('y', 0).attr('width', d => d.width).attr('height', d => d.height).attr('href', d => d.look.backgroundImage);
6790
7067
  selection.filter('.stretchable-image-look').select('image.top-left-image').attr('x', 0).attr('y', 0).attr('width', d => d.look.leftMargin).attr('height', d => d.look.topMargin).attr('href', d => d.look.backgroundImageTopLeft);
@@ -6797,30 +7074,91 @@ const updateLook = selection => {
6797
7074
  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);
6798
7075
  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);
6799
7076
  };
7077
+ const BACKGROUND_DEFAULTS = {
7078
+ style: 'solid',
7079
+ color: '#FFFFFF'
7080
+ };
6800
7081
  const GRID_DEFAULTS = {
7082
+ enabled: true,
7083
+ style: 'none',
7084
+ snap: false,
7085
+ spacing: 1
7086
+ };
7087
+ const DOTS_GRID_DEFAULTS = Object.assign(Object.assign({}, GRID_DEFAULTS), {
6801
7088
  style: 'dots',
6802
- color: 'rgba(0, 0, 0, 0.1)',
6803
7089
  snap: false,
6804
7090
  spacing: 10,
6805
- thickness: 0.05
7091
+ thickness: 0.05,
7092
+ color: 'rgba(0, 0, 0, 0.1)'
7093
+ });
7094
+ const initializeBackground = (canvasView, backgroundConfig) => {
7095
+ var _a, _b;
7096
+ switch ((_a = backgroundConfig === null || backgroundConfig === void 0 ? void 0 : backgroundConfig.style) !== null && _a !== void 0 ? _a : '') {
7097
+ case 'image':
7098
+ return canvasView.append('image').attr('x', 0).attr('y', 0).attr('width', `100%`).attr('height', `100%`).attr('href', backgroundConfig.image).attr('preserveAspectRatio', 'none');
7099
+ case 'solid':
7100
+ default:
7101
+ return canvasView.append('rect').attr('x', 0).attr('y', 0).attr('width', `100%`).attr('height', `100%`).attr('fill', (_b = backgroundConfig.color) !== null && _b !== void 0 ? _b : '#FFFFFF').attr('stroke-width', '0');
7102
+ }
6806
7103
  };
6807
- const initializeGrid = (canvas, canvasView, backgroundPatternId) => {
6808
- const canvasDefs = canvasView.append('defs');
6809
- if (canvas.gridSize > 0 && isFinite(canvas.gridSize)) {
6810
- 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');
6811
- canvasBackgroundPattern.append('rect').attr('x', 0).attr('y', 0).attr('width', canvas.gridSize).attr('height', canvas.gridSize).attr('fill', canvas.backgroundColor);
6812
- switch (canvas.gridStyle) {
7104
+ const applyGridDefaults = gridConfig => {
7105
+ if (!gridConfig) {
7106
+ return DOTS_GRID_DEFAULTS;
7107
+ }
7108
+ switch (gridConfig.style) {
7109
+ case 'dots':
7110
+ case 'lines':
7111
+ // lines has the same parameters as dots
7112
+ return Object.assign(Object.assign({}, DOTS_GRID_DEFAULTS), gridConfig);
7113
+ default:
7114
+ return Object.assign(Object.assign({}, GRID_DEFAULTS), gridConfig);
7115
+ }
7116
+ };
7117
+ const initializeGrid = (canvas, canvasView, canvasDefs, gridPatternId, gridConfig) => {
7118
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
7119
+ if (getGridSpacingX(gridConfig) !== 0 && getGridSpacingY(gridConfig) !== 0) {
7120
+ const canvasBackgroundPattern = canvasDefs.append('pattern').attr('id', gridPatternId).attr('x', -getGridSpacingX(gridConfig) / 2).attr('y', -getGridSpacingY(gridConfig) / 2).attr('width', getGridSpacingX(gridConfig)).attr('height', getGridSpacingY(gridConfig)).attr('patternUnits', 'userSpaceOnUse');
7121
+ canvasBackgroundPattern.append('rect').attr('x', 0).attr('y', 0).attr('width', getGridSpacingX(gridConfig)).attr('height', getGridSpacingY(gridConfig)).attr('fill', 'transparent');
7122
+ switch (gridConfig.style) {
6813
7123
  case 'dots':
6814
- canvasBackgroundPattern.append('circle').attr('cx', canvas.gridSize / 2).attr('cy', canvas.gridSize / 2).attr('r', canvas.gridSize * canvas.gridThickness).attr('fill', canvas.gridColor);
7124
+ canvasBackgroundPattern.append('circle').attr('cx', getGridSpacingX(gridConfig) / 2).attr('cy', getGridSpacingY(gridConfig) / 2).attr('r', Math.min(getGridSpacingX(gridConfig), getGridSpacingY(gridConfig)) * ((_a = gridConfig.thickness) !== null && _a !== void 0 ? _a : 0)).attr('fill', (_b = gridConfig.color) !== null && _b !== void 0 ? _b : '');
6815
7125
  break;
6816
7126
  case 'lines':
6817
- 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);
6818
- 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);
6819
- 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);
7127
+ canvasBackgroundPattern.append('line').attr('x1', getGridSpacingX(gridConfig) / 2).attr('x2', getGridSpacingX(gridConfig) / 2).attr('y1', 0).attr('y2', getGridSpacingY(gridConfig)).attr('stroke-width', Math.min(getGridSpacingX(gridConfig), getGridSpacingY(gridConfig)) * ((_c = gridConfig.thickness) !== null && _c !== void 0 ? _c : 0)).attr('stroke', (_d = gridConfig.color) !== null && _d !== void 0 ? _d : '');
7128
+ canvasBackgroundPattern.append('line').attr('x1', 0).attr('x2', (getGridSpacingX(gridConfig) - getGridSpacingX(gridConfig) * ((_e = gridConfig.thickness) !== null && _e !== void 0 ? _e : 0)) / 2).attr('y1', getGridSpacingY(gridConfig) / 2).attr('y2', getGridSpacingY(gridConfig) / 2).attr('stroke-width', Math.min(getGridSpacingX(gridConfig), getGridSpacingY(gridConfig)) * ((_f = gridConfig.thickness) !== null && _f !== void 0 ? _f : 0)).attr('stroke', (_g = gridConfig.color) !== null && _g !== void 0 ? _g : '');
7129
+ canvasBackgroundPattern.append('line').attr('x1', (getGridSpacingX(gridConfig) + getGridSpacingX(gridConfig) * ((_h = gridConfig.thickness) !== null && _h !== void 0 ? _h : 0)) / 2).attr('x2', getGridSpacingX(gridConfig)).attr('y1', getGridSpacingY(gridConfig) / 2).attr('y2', getGridSpacingY(gridConfig) / 2).attr('stroke-width', Math.min(getGridSpacingX(gridConfig), getGridSpacingY(gridConfig)) * ((_j = gridConfig.thickness) !== null && _j !== void 0 ? _j : 0)).attr('stroke', (_k = gridConfig.color) !== null && _k !== void 0 ? _k : '');
7130
+ break;
7131
+ case 'image':
7132
+ canvasBackgroundPattern.append('image').attr('x', 0).attr('y', 0).attr('width', getGridSpacingX(gridConfig)).attr('height', getGridSpacingY(gridConfig)).attr('href', gridConfig.image).attr('preserveAspectRatio', 'none');
6820
7133
  break;
6821
7134
  }
6822
- canvasView.select('rect').attr('fill', `url(#${backgroundPatternId})`);
7135
+ return canvasView.append('rect').attr('x', 0).attr('y', 0).attr('width', `100%`).attr('height', `100%`).attr('fill', `url(#${gridPatternId})`).attr('stroke-width', '0');
7136
+ }
7137
+ return undefined;
7138
+ };
7139
+ const getGridSpacingX = gridConfig => {
7140
+ let value = 0;
7141
+ if (typeof gridConfig.spacing === 'number') {
7142
+ value = gridConfig.spacing;
7143
+ } else if (Array.isArray(gridConfig.spacing) && typeof gridConfig.spacing[0] === 'number') {
7144
+ value = gridConfig.spacing[0];
7145
+ }
7146
+ if (!isFinite(value)) {
7147
+ return 0;
7148
+ }
7149
+ return value;
7150
+ };
7151
+ const getGridSpacingY = gridConfig => {
7152
+ let value = 0;
7153
+ if (typeof gridConfig.spacing === 'number') {
7154
+ value = gridConfig.spacing;
7155
+ } else if (Array.isArray(gridConfig.spacing) && typeof gridConfig.spacing[1] === 'number') {
7156
+ value = gridConfig.spacing[1];
7157
+ }
7158
+ if (!isFinite(value)) {
7159
+ return 0;
6823
7160
  }
7161
+ return value;
6824
7162
  };
6825
7163
 
6826
7164
  const CONTEXT_MENU_MENU_RADIUS = 96;
@@ -7066,6 +7404,7 @@ const DAGA_FILE_VERSION = 1;
7066
7404
  */
7067
7405
  class DagaExporter {
7068
7406
  export(model, includeCollabMeta = false) {
7407
+ var _a;
7069
7408
  const result = Object.assign({
7070
7409
  name: model.name,
7071
7410
  type: model.type,
@@ -7074,6 +7413,7 @@ class DagaExporter {
7074
7413
  updatedAt: model.updatedAt,
7075
7414
  nodes: [],
7076
7415
  connections: [],
7416
+ objects: [],
7077
7417
  data: model.valueSet.getValues()
7078
7418
  }, includeCollabMeta ? {
7079
7419
  collabMeta: {
@@ -7096,6 +7436,21 @@ class DagaExporter {
7096
7436
  if (!includeCollabMeta && connection.removed) continue;
7097
7437
  result.connections.push(this.exportConnection(connection, includeCollabMeta));
7098
7438
  }
7439
+ for (const object of model.objects.all(true)) {
7440
+ (_a = result.objects) === null || _a === void 0 ? void 0 : _a.push(Object.assign({
7441
+ id: object.id,
7442
+ coords: roundPoint(object.coords),
7443
+ width: object.width,
7444
+ height: object.height,
7445
+ priority: object.priority,
7446
+ svg: object.svg
7447
+ }, includeCollabMeta ? {
7448
+ collabMeta: {
7449
+ removed: object.removed,
7450
+ selfRemoved: object.selfRemoved
7451
+ }
7452
+ } : {}));
7453
+ }
7099
7454
  return result;
7100
7455
  }
7101
7456
  exportNode(node, includeCollabMeta = false) {
@@ -7123,9 +7478,27 @@ class DagaExporter {
7123
7478
  }, this.exportLabelCollabMeta(port))
7124
7479
  } : {}));
7125
7480
  }
7481
+ const decorators = [];
7482
+ for (const decorator of section.decorators) {
7483
+ decorators.push(Object.assign({
7484
+ id: decorator.id,
7485
+ coords: roundPoint(decorator.coords),
7486
+ width: decorator.width,
7487
+ height: decorator.height,
7488
+ priority: decorator.priority,
7489
+ svg: decorator.svg,
7490
+ anchorPoints: [decorator.anchorPointX, decorator.anchorPointY]
7491
+ }, includeCollabMeta ? {
7492
+ collabMeta: {
7493
+ removed: decorator.removed,
7494
+ selfRemoved: decorator.selfRemoved
7495
+ }
7496
+ } : {}));
7497
+ }
7126
7498
  sections.push(Object.assign({
7127
7499
  id: section.id,
7128
7500
  ports,
7501
+ decorators,
7129
7502
  label: ((_c = section.label) === null || _c === void 0 ? void 0 : _c.text) || '',
7130
7503
  indexXInNode: section.indexXInNode,
7131
7504
  indexYInNode: section.indexYInNode,
@@ -7157,12 +7530,30 @@ class DagaExporter {
7157
7530
  }, this.exportLabelCollabMeta(port))
7158
7531
  } : {}));
7159
7532
  }
7533
+ const decorators = [];
7534
+ for (const decorator of node.decorators) {
7535
+ decorators.push(Object.assign({
7536
+ id: decorator.id,
7537
+ coords: roundPoint(decorator.coords),
7538
+ width: decorator.width,
7539
+ height: decorator.height,
7540
+ priority: decorator.priority,
7541
+ svg: decorator.svg,
7542
+ anchorPoints: [decorator.anchorPointX, decorator.anchorPointY]
7543
+ }, includeCollabMeta ? {
7544
+ collabMeta: {
7545
+ removed: decorator.removed,
7546
+ selfRemoved: decorator.selfRemoved
7547
+ }
7548
+ } : {}));
7549
+ }
7160
7550
  return Object.assign({
7161
7551
  id: node.id,
7162
7552
  type: node.type.id,
7163
7553
  children,
7164
7554
  sections,
7165
7555
  ports,
7556
+ decorators,
7166
7557
  label: ((_f = node.label) === null || _f === void 0 ? void 0 : _f.text) || '',
7167
7558
  coords: roundPoint(node.coords),
7168
7559
  width: node.width,
@@ -7476,11 +7867,6 @@ class DiagramUserSelection extends DiagramElementSet {
7476
7867
  * @private
7477
7868
  */
7478
7869
  const CONNECTION_PATH_BOX_THICKNESS = 12;
7479
- /**
7480
- * Thickness of the resizer line used to resize nodes and sections on drag, in diagram units.
7481
- * @private
7482
- */
7483
- const RESIZER_THICKNESS = 6;
7484
7870
  /**
7485
7871
  * Maximum number of user actions that can be recorded in the user action stack.
7486
7872
  * @private
@@ -7505,8 +7891,9 @@ class DiagramCanvas {
7505
7891
  * @param config The configuration object used to set the parameters of this canvas.
7506
7892
  */
7507
7893
  constructor(parentComponent, config) {
7508
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8;
7509
- this.backgroundPatternId = `daga-background-pattern-id-${DiagramCanvas.canvasCount++}`;
7894
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
7895
+ this.gridPatternId = `daga-grid-pattern-id-${++DiagramCanvas.canvasCount}`;
7896
+ this.ancillaryGridPatternIds = [];
7510
7897
  this.zoomTransform = d3.zoomIdentity;
7511
7898
  // used to distinguish drags from clicks when dragging elements and during multiple selection
7512
7899
  this.draggingFrom = [0, 0];
@@ -7523,23 +7910,25 @@ class DiagramCanvas {
7523
7910
  this.userSelection = new DiagramUserSelection(this, (_b = (_a = config.components) === null || _a === void 0 ? void 0 : _a.propertyEditor) === null || _b === void 0 ? void 0 : _b.title);
7524
7911
  this.userHighlight = new DiagramUserHighlight(this, ((_c = config.canvas) === null || _c === void 0 ? void 0 : _c.highlightSections) !== false);
7525
7912
  this.contextMenu = new DiagramContextMenu(this, (_d = config.canvas) === null || _d === void 0 ? void 0 : _d.contextMenu);
7526
- this.backgroundColor = ((_e = config.canvas) === null || _e === void 0 ? void 0 : _e.backgroundColor) || '#FFFFFF';
7527
- this.gridStyle = (_h = (_g = (_f = config.canvas) === null || _f === void 0 ? void 0 : _f.grid) === null || _g === void 0 ? void 0 : _g.style) !== null && _h !== void 0 ? _h : GRID_DEFAULTS.style;
7528
- this.gridSize = ((_k = (_j = config.canvas) === null || _j === void 0 ? void 0 : _j.grid) === null || _k === void 0 ? void 0 : _k.enabled) === false || ((_l = config.canvas) === null || _l === void 0 ? void 0 : _l.grid) === undefined ? 0 : Math.abs(((_o = (_m = config.canvas) === null || _m === void 0 ? void 0 : _m.grid) === null || _o === void 0 ? void 0 : _o.spacing) || GRID_DEFAULTS.spacing);
7529
- this.gridThickness = Math.abs(((_q = (_p = config.canvas) === null || _p === void 0 ? void 0 : _p.grid) === null || _q === void 0 ? void 0 : _q.thickness) || GRID_DEFAULTS.thickness);
7530
- this.gridColor = ((_s = (_r = config.canvas) === null || _r === void 0 ? void 0 : _r.grid) === null || _s === void 0 ? void 0 : _s.color) || GRID_DEFAULTS.color;
7531
- this.snapToGrid = ((_u = (_t = config.canvas) === null || _t === void 0 ? void 0 : _t.grid) === null || _u === void 0 ? void 0 : _u.enabled) === false || ((_v = config.canvas) === null || _v === void 0 ? void 0 : _v.grid) === undefined ? false : ((_x = (_w = config.canvas) === null || _w === void 0 ? void 0 : _w.grid) === null || _x === void 0 ? void 0 : _x.snap) || GRID_DEFAULTS.snap;
7532
- this.zoomFactor = ((_y = config.canvas) === null || _y === void 0 ? void 0 : _y.zoomFactor) || 2;
7533
- this.panRate = ((_z = config.canvas) === null || _z === void 0 ? void 0 : _z.panRate) || 100;
7534
- this.inferConnectionType = ((_0 = config.connectionSettings) === null || _0 === void 0 ? void 0 : _0.inferConnectionType) || false;
7535
- this.autoTightenConnections = ((_1 = config.connectionSettings) === null || _1 === void 0 ? void 0 : _1.autoTighten) !== false;
7536
- this.tightenConnectionsAcrossPortTypes = ((_2 = config.connectionSettings) === null || _2 === void 0 ? void 0 : _2.tightenAcrossPortTypes) || false;
7537
- this.allowConnectionLoops = ((_3 = config.connectionSettings) === null || _3 === void 0 ? void 0 : _3.allowLoops) || false;
7538
- this.allowSharingPorts = ((_4 = config.connectionSettings) === null || _4 === void 0 ? void 0 : _4.sharePorts) !== false;
7539
- this.allowSharingBothPorts = ((_5 = config.connectionSettings) === null || _5 === void 0 ? void 0 : _5.shareBothPorts) || false;
7540
- this.portHighlightRadius = ((_6 = config.connectionSettings) === null || _6 === void 0 ? void 0 : _6.portHighlightRadius) || 100;
7913
+ // TODO
7914
+ this.backgroundConfig = (_f = (_e = config.canvas) === null || _e === void 0 ? void 0 : _e.background) !== null && _f !== void 0 ? _f : BACKGROUND_DEFAULTS;
7915
+ this.gridConfig = applyGridDefaults((_g = config.canvas) === null || _g === void 0 ? void 0 : _g.grid);
7916
+ this.ancillaryGridsConfig = [];
7917
+ for (let i = 0; i < (((_j = (_h = config.canvas) === null || _h === void 0 ? void 0 : _h.ancillaryGrids) === null || _j === void 0 ? void 0 : _j.length) || 0); ++i) {
7918
+ this.ancillaryGridsConfig.push(applyGridDefaults((_l = (_k = config.canvas) === null || _k === void 0 ? void 0 : _k.ancillaryGrids) === null || _l === void 0 ? void 0 : _l[i]));
7919
+ this.ancillaryGridPatternIds.push(`${this.gridPatternId}-ancillary-${i}`);
7920
+ }
7921
+ this.zoomFactor = ((_m = config.canvas) === null || _m === void 0 ? void 0 : _m.zoomFactor) || 2;
7922
+ this.panRate = ((_o = config.canvas) === null || _o === void 0 ? void 0 : _o.panRate) || 100;
7923
+ this.inferConnectionType = ((_p = config.connectionSettings) === null || _p === void 0 ? void 0 : _p.inferConnectionType) || false;
7924
+ this.autoTightenConnections = ((_q = config.connectionSettings) === null || _q === void 0 ? void 0 : _q.autoTighten) !== false;
7925
+ this.tightenConnectionsAcrossPortTypes = ((_r = config.connectionSettings) === null || _r === void 0 ? void 0 : _r.tightenAcrossPortTypes) || false;
7926
+ this.allowConnectionLoops = ((_s = config.connectionSettings) === null || _s === void 0 ? void 0 : _s.allowLoops) || false;
7927
+ this.allowSharingPorts = ((_t = config.connectionSettings) === null || _t === void 0 ? void 0 : _t.sharePorts) !== false;
7928
+ this.allowSharingBothPorts = ((_u = config.connectionSettings) === null || _u === void 0 ? void 0 : _u.shareBothPorts) || false;
7929
+ this.portHighlightRadius = ((_v = config.connectionSettings) === null || _v === void 0 ? void 0 : _v.portHighlightRadius) || 100;
7541
7930
  this.multipleSelectionOn = false;
7542
- this.priorityThresholds = ((_7 = config.canvas) === null || _7 === void 0 ? void 0 : _7.priorityThresholds) || [];
7931
+ this.priorityThresholds = ((_w = config.canvas) === null || _w === void 0 ? void 0 : _w.priorityThresholds) || [];
7543
7932
  this.priorityThreshold = this.priorityThresholds ? this.priorityThresholds[0] : undefined;
7544
7933
  this.layoutFormat = config.layoutFormat;
7545
7934
  this.userActions = config.userActions || {};
@@ -7566,7 +7955,7 @@ class DiagramCanvas {
7566
7955
  const connectionType = new DiagramConnectionType(Object.assign(Object.assign({}, config.connectionTypeDefaults), connectionTypeConfig));
7567
7956
  this.model.connections.types.add(connectionType);
7568
7957
  }
7569
- this._connectionType = ((_8 = config === null || config === void 0 ? void 0 : config.connectionSettings) === null || _8 === void 0 ? void 0 : _8.defaultConnection) !== undefined ? this.model.connections.types.get(config.connectionSettings.defaultConnection) : undefined;
7958
+ this._connectionType = ((_x = config === null || config === void 0 ? void 0 : config.connectionSettings) === null || _x === void 0 ? void 0 : _x.defaultConnection) !== undefined ? this.model.connections.types.get(config.connectionSettings.defaultConnection) : undefined;
7570
7959
  }
7571
7960
  }
7572
7961
  addValidator(validator) {
@@ -7598,13 +7987,13 @@ class DiagramCanvas {
7598
7987
  // remove all children
7599
7988
  appendToSelection.html('');
7600
7989
  this.diagramRoot = appendToSelection.append('div').node();
7601
- d3.select(this.diagramRoot).attr('tabindex', 0) // make element focusable
7990
+ this.selectRoot().attr('tabindex', 0) // make element focusable
7602
7991
  .style('width', '100%').style('height', '100%').append('svg').style('width', '100%').style('height', '100%');
7603
- d3.select(this.diagramRoot).on(Events.Click, () => {
7992
+ this.selectRoot().on(Events.Click, () => {
7604
7993
  var _a;
7605
7994
  // focus on the diagram when clicking so that we can focus on the diagram
7606
7995
  // keyboard events only work if we're focusing on the diagram
7607
- (_a = d3.select(this.diagramRoot).node()) === null || _a === void 0 ? void 0 : _a.focus();
7996
+ (_a = this.selectRoot().node()) === null || _a === void 0 ? void 0 : _a.focus();
7608
7997
  }).on(Events.ContextMenu, event => {
7609
7998
  if (this.dragging) {
7610
7999
  event.preventDefault();
@@ -7768,44 +8157,57 @@ class DiagramCanvas {
7768
8157
  this.zoomTransform = event.transform;
7769
8158
  const transformAttribute = event.transform.toString();
7770
8159
  this.selectCanvasElements().attr('transform', transformAttribute);
7771
- d3.select(`#${this.backgroundPatternId}`).attr('patternTransform', transformAttribute);
8160
+ for (const gridPatternId of [this.gridPatternId, ...this.ancillaryGridPatternIds]) {
8161
+ this.selectCanvasView().select(`#${gridPatternId}`).attr('patternTransform', transformAttribute);
8162
+ }
7772
8163
  this.contextMenu.close();
7773
8164
  this.diagramEvent$.next(new DiagramZoomEvent([this.zoomTransform.x, this.zoomTransform.y], this.zoomTransform.k));
7774
8165
  }).on(ZoomEvents.End, () => {
7775
8166
  setCursorStyle();
7776
8167
  }));
7777
- 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 => {
7778
- if (this.unfinishedConnection !== undefined) {
7779
- const pointerCoords = this.getPointerLocationRelativeToCanvas(event);
7780
- this.unfinishedConnection.endCoords = pointerCoords;
7781
- }
7782
- }).on(Events.MouseOver, () => {
7783
- if (this.userHighlight.size() > 0) {
7784
- this.userHighlight.clear();
7785
- this.diagramEvent$.next(new DiagramHighlightedEvent(null));
7786
- }
7787
- }).on(Events.Click, () => {
7788
- if (this.userHighlight.size() > 0) {
7789
- this.userHighlight.clear();
7790
- this.diagramEvent$.next(new DiagramHighlightedEvent(null));
7791
- }
7792
- this.contextMenu.close();
7793
- if (this.userSelection.size() > 0) {
7794
- const deselectedElements = this.userSelection.all();
7795
- this.userSelection.clear();
7796
- this.diagramEvent$.next(new DiagramSelectionEvent(deselectedElements, false));
7797
- }
7798
- this.userSelection.openInPropertyEditor(this.model);
7799
- }).call(d3.drag().filter(event => {
7800
- return this.multipleSelectionOn || isSecondaryButton(event);
7801
- }).on(DragEvents.Start, event => {
7802
- this.startMultipleSelection(event);
7803
- }).on(DragEvents.Drag, event => {
7804
- this.continueMultipleSelection(event);
7805
- }).on(DragEvents.End, event => {
7806
- this.finishMultipleSelection(event);
7807
- }));
7808
- initializeGrid(this, canvasView, this.backgroundPatternId);
8168
+ const canvasDefs = canvasView.append('defs');
8169
+ const canvasBackground = [];
8170
+ canvasBackground.push(initializeBackground(canvasView, this.backgroundConfig).attr('class', 'daga-background'));
8171
+ for (let i = 0; i < this.ancillaryGridsConfig.length; ++i) {
8172
+ canvasBackground.push(initializeGrid(this, canvasView, canvasDefs, this.ancillaryGridPatternIds[i], this.ancillaryGridsConfig[i]));
8173
+ }
8174
+ canvasBackground.push(initializeGrid(this, canvasView, canvasDefs, this.gridPatternId, this.gridConfig));
8175
+ for (const canvasBackgroundElement of canvasBackground) {
8176
+ canvasBackgroundElement.on(Events.MouseMove, event => {
8177
+ if (this.unfinishedConnection !== undefined) {
8178
+ const pointerCoords = this.getPointerLocationRelativeToCanvas(event);
8179
+ this.unfinishedConnection.endCoords = pointerCoords;
8180
+ }
8181
+ });
8182
+ canvasBackgroundElement.on(Events.MouseOver, () => {
8183
+ if (this.userHighlight.size() > 0) {
8184
+ this.userHighlight.clear();
8185
+ this.diagramEvent$.next(new DiagramHighlightedEvent(null));
8186
+ }
8187
+ });
8188
+ canvasBackgroundElement.on(Events.Click, () => {
8189
+ if (this.userHighlight.size() > 0) {
8190
+ this.userHighlight.clear();
8191
+ this.diagramEvent$.next(new DiagramHighlightedEvent(null));
8192
+ }
8193
+ this.contextMenu.close();
8194
+ if (this.userSelection.size() > 0) {
8195
+ const deselectedElements = this.userSelection.all();
8196
+ this.userSelection.clear();
8197
+ this.diagramEvent$.next(new DiagramSelectionEvent(deselectedElements, false));
8198
+ }
8199
+ this.userSelection.openInPropertyEditor(this.model);
8200
+ });
8201
+ canvasBackgroundElement.call(d3.drag().filter(event => {
8202
+ return this.multipleSelectionOn || isSecondaryButton(event);
8203
+ }).on(DragEvents.Start, event => {
8204
+ this.startMultipleSelection(event);
8205
+ }).on(DragEvents.Drag, event => {
8206
+ this.continueMultipleSelection(event);
8207
+ }).on(DragEvents.End, event => {
8208
+ this.finishMultipleSelection(event);
8209
+ }));
8210
+ }
7809
8211
  canvasView.append('g').attr('class', 'daga-canvas-elements');
7810
8212
  }
7811
8213
  getZoomLevel() {
@@ -7823,7 +8225,7 @@ class DiagramCanvas {
7823
8225
  }
7824
8226
  getViewCoordinates() {
7825
8227
  var _a, _b, _c;
7826
- const canvasViewBoundingBox = (_c = (_b = (_a = this.selectCanvasView()) === null || _a === void 0 ? void 0 : _a.select('rect')) === null || _b === void 0 ? void 0 : _b.node()) === null || _c === void 0 ? void 0 : _c.getBBox();
8228
+ const canvasViewBoundingBox = (_c = (_b = (_a = this.selectCanvasView()) === null || _a === void 0 ? void 0 : _a.select('.daga-background')) === null || _b === void 0 ? void 0 : _b.node()) === null || _c === void 0 ? void 0 : _c.getBBox();
7827
8229
  /*
7828
8230
  transform the coordinates of the zoomTransform to the coordinates
7829
8231
  needed to point the zoomTransfrom to the center of the screen to
@@ -7875,7 +8277,11 @@ class DiagramCanvas {
7875
8277
  var _a;
7876
8278
  // if there are no nodes, we have nothing to do here
7877
8279
  if (this.model.nodes.length > 0) {
7878
- const canvasViewBoundingBox = (_a = this.selectCanvasView().select('rect').node()) === null || _a === void 0 ? void 0 : _a.getBBox();
8280
+ const canvasViewBoundingBox = (_a = this.selectCanvasView().select('.daga-background').node()) === null || _a === void 0 ? void 0 : _a.getBBox();
8281
+ if (!canvasViewBoundingBox.width || !canvasViewBoundingBox.height) {
8282
+ // prevent errors if the width or height is invalid
8283
+ return;
8284
+ }
7879
8285
  const nonRemovedNodes = (nodeIds === null || nodeIds === void 0 ? void 0 : nodeIds.map(i => this.model.nodes.get(i)).filter(n => !!n)) || this.model.nodes.all();
7880
8286
  const minimumX = Math.min(...nonRemovedNodes.map(n => n.coords[0]));
7881
8287
  const maximumX = Math.max(...nonRemovedNodes.map(n => n.coords[0] + n.width));
@@ -7900,10 +8306,17 @@ class DiagramCanvas {
7900
8306
  }
7901
8307
  }
7902
8308
  getClosestGridPoint(point) {
7903
- if (this.gridSize === 0 || !isFinite(this.gridSize)) {
7904
- return point;
8309
+ let pointX = point[0];
8310
+ const spacingX = getGridSpacingX(this.gridConfig);
8311
+ if (spacingX !== 0) {
8312
+ pointX = Math.round(pointX / spacingX) * spacingX;
8313
+ }
8314
+ let pointY = point[1];
8315
+ const spacingY = getGridSpacingY(this.gridConfig);
8316
+ if (spacingY !== 0) {
8317
+ pointY = Math.round(pointY / spacingY) * spacingY;
7905
8318
  }
7906
- return [Math.round(point[0] / this.gridSize) * this.gridSize, Math.round(point[1] / this.gridSize) * this.gridSize];
8319
+ return [pointX, pointY];
7907
8320
  }
7908
8321
  getCoordinatesOnScreen() {
7909
8322
  var _a;
@@ -7952,7 +8365,7 @@ class DiagramCanvas {
7952
8365
  updateNodesInView(...ids) {
7953
8366
  let updateSelection = this.selectCanvasElements().selectAll('g.diagram-node').data(this.model.nodes.filter(e => this.priorityThreshold !== undefined ? e.getPriority() >= this.priorityThreshold : true), d => d.id);
7954
8367
  const exitSelection = updateSelection.exit();
7955
- const enterSelection = updateSelection.enter().append('g').attr('id', d => d.id).attr('class', d => `diagram-node${needsResizerX(d) ? ' resizable-x' : ''}${needsResizerY(d) ? ' resizable-y' : ''} ${d.type.defaultLook.lookType}`);
8368
+ const enterSelection = updateSelection.enter().append('g').attr('id', d => d.id).attr('class', d => `diagram-node${needsResizerX(d) ? ' resizable-x' : ''}${needsResizerY(d) ? ' resizable-y' : ''}${needsResizerXY(d) ? ' resizable-xy' : ''} ${d.type.defaultLook.lookType}`);
7956
8369
  if (ids && ids.length > 0) {
7957
8370
  updateSelection = updateSelection.filter(d => ids.includes(d.id));
7958
8371
  }
@@ -7988,62 +8401,208 @@ class DiagramCanvas {
7988
8401
  this.diagramEvent$.next(new DiagramSelectionEvent([d], true));
7989
8402
  this.contextMenu.open(event);
7990
8403
  }
7991
- }).on(Events.DoubleClick, (event, d) => {
7992
- const diagramEvent = new DiagramDoubleClickEvent(event, d);
7993
- this.diagramEvent$.next(diagramEvent);
7994
- }).call(d3.drag().filter(event => {
7995
- this.secondaryButton = isSecondaryButton(event);
7996
- return true;
7997
- }).on(DragEvents.Start, (event, d) => {
7998
- if (this.multipleSelectionOn || this.secondaryButton) {
7999
- this.startMultipleSelection(event);
8404
+ }).on(Events.DoubleClick, (event, d) => {
8405
+ const diagramEvent = new DiagramDoubleClickEvent(event, d);
8406
+ this.diagramEvent$.next(diagramEvent);
8407
+ }).call(d3.drag().filter(event => {
8408
+ this.secondaryButton = isSecondaryButton(event);
8409
+ return true;
8410
+ }).on(DragEvents.Start, (event, d) => {
8411
+ if (this.multipleSelectionOn || this.secondaryButton) {
8412
+ this.startMultipleSelection(event);
8413
+ } else {
8414
+ this.startMovingNode(event, d);
8415
+ }
8416
+ }).on(DragEvents.Drag, (event, d) => {
8417
+ if (this.multipleSelectionOn || this.secondaryButton) {
8418
+ this.continueMultipleSelection(event);
8419
+ } else {
8420
+ this.continueMovingNode(event, d);
8421
+ }
8422
+ }).on(DragEvents.End, (event, d) => {
8423
+ if (this.multipleSelectionOn || this.secondaryButton) {
8424
+ this.finishMultipleSelection(event);
8425
+ } else {
8426
+ this.finishMovingNode(event, d);
8427
+ }
8428
+ this.secondaryButton = false;
8429
+ }));
8430
+ initializeLook(enterSelection);
8431
+ enterSelection.filter('.resizable-x').append('rect').attr('class', 'left-resizer').on(Events.MouseOver, (_event, d) => {
8432
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableX() && !d.removed) {
8433
+ setCursorStyle(CursorStyle.EWResize);
8434
+ }
8435
+ }).on(Events.MouseOut, (_event, d) => {
8436
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableX() && !d.removed) {
8437
+ setCursorStyle();
8438
+ }
8439
+ }).call(d3.drag().on(DragEvents.Start, (_event, d) => {
8440
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableX() && !d.removed) {
8441
+ setCursorStyle(CursorStyle.EWResize);
8442
+ this.currentAction = new SetGeometryAction(this, DiagramActions.StretchNode, d.id, d.getGeometry(), d.getGeometry());
8443
+ } else {
8444
+ setCursorStyle(CursorStyle.NotAllowed);
8445
+ }
8446
+ }).on(DragEvents.Drag, (event, d) => {
8447
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableX() && !d.removed) {
8448
+ const pointerCoords = this.getPointerLocationRelativeToCanvas(event);
8449
+ d.stretch(Side.Left, d.coords[0] - pointerCoords[0]);
8450
+ }
8451
+ }).on(DragEvents.End, (event, d) => {
8452
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableX() && !d.removed && this.currentAction instanceof SetGeometryAction && this.currentAction.intent === DiagramActions.StretchNode) {
8453
+ let pointerCoords = this.getPointerLocationRelativeToCanvas(event);
8454
+ if (this.gridConfig.snap) {
8455
+ pointerCoords = this.getClosestGridPoint([pointerCoords[0] - d.type.snapToGridOffset[0], pointerCoords[1] - d.type.snapToGridOffset[1]]);
8456
+ pointerCoords[0] += d.type.snapToGridOffset[0];
8457
+ pointerCoords[1] += d.type.snapToGridOffset[1];
8458
+ }
8459
+ d.stretch(Side.Left, d.coords[0] - pointerCoords[0]);
8460
+ this.currentAction.to = d.getGeometry();
8461
+ this.currentAction.do();
8462
+ this.actionStack.add(this.currentAction);
8463
+ this.currentAction = undefined;
8464
+ }
8465
+ setCursorStyle();
8466
+ }));
8467
+ enterSelection.filter('.resizable-x').append('rect').attr('class', 'right-resizer').on(Events.MouseOver, (_event, d) => {
8468
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableX() && !d.removed) {
8469
+ setCursorStyle(CursorStyle.EWResize);
8470
+ }
8471
+ }).on(Events.MouseOut, (_event, d) => {
8472
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableX() && !d.removed) {
8473
+ setCursorStyle();
8474
+ }
8475
+ }).call(d3.drag().on(DragEvents.Start, (_event, d) => {
8476
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableX() && !d.removed) {
8477
+ setCursorStyle(CursorStyle.EWResize);
8478
+ this.currentAction = new SetGeometryAction(this, DiagramActions.StretchNode, d.id, d.getGeometry(), d.getGeometry());
8479
+ } else {
8480
+ setCursorStyle(CursorStyle.NotAllowed);
8481
+ }
8482
+ }).on(DragEvents.Drag, (event, d) => {
8483
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableX() && !d.removed) {
8484
+ const pointerCoords = this.getPointerLocationRelativeToCanvas(event);
8485
+ d.stretch(Side.Right, pointerCoords[0] - (d.coords[0] + d.width));
8486
+ }
8487
+ }).on(DragEvents.End, (event, d) => {
8488
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableX() && !d.removed && this.currentAction instanceof SetGeometryAction && this.currentAction.intent === DiagramActions.StretchNode) {
8489
+ let pointerCoords = this.getPointerLocationRelativeToCanvas(event);
8490
+ if (this.gridConfig.snap) {
8491
+ pointerCoords = this.getClosestGridPoint([pointerCoords[0] - d.type.snapToGridOffset[2], pointerCoords[1] - d.type.snapToGridOffset[3]]);
8492
+ pointerCoords[0] += d.type.snapToGridOffset[2];
8493
+ pointerCoords[1] += d.type.snapToGridOffset[3];
8494
+ }
8495
+ d.stretch(Side.Right, pointerCoords[0] - (d.coords[0] + d.width));
8496
+ this.currentAction.to = d.getGeometry();
8497
+ this.currentAction.do();
8498
+ this.actionStack.add(this.currentAction);
8499
+ this.currentAction = undefined;
8500
+ }
8501
+ setCursorStyle();
8502
+ }));
8503
+ enterSelection.filter('.resizable-y').append('rect').attr('class', 'top-resizer').on(Events.MouseOver, (_event, d) => {
8504
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableY() && !d.removed) {
8505
+ setCursorStyle(CursorStyle.NSResize);
8506
+ }
8507
+ }).on(Events.MouseOut, (_event, d) => {
8508
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableY() && !d.removed) {
8509
+ setCursorStyle();
8510
+ }
8511
+ }).call(d3.drag().on(DragEvents.Start, (_event, d) => {
8512
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableY() && !d.removed) {
8513
+ setCursorStyle(CursorStyle.NSResize);
8514
+ this.currentAction = new SetGeometryAction(this, DiagramActions.StretchNode, d.id, d.getGeometry(), d.getGeometry());
8515
+ } else {
8516
+ setCursorStyle(CursorStyle.NotAllowed);
8517
+ }
8518
+ }).on(DragEvents.Drag, (event, d) => {
8519
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableY() && !d.removed) {
8520
+ const pointerCoords = this.getPointerLocationRelativeToCanvas(event);
8521
+ d.stretch(Side.Top, d.coords[1] - pointerCoords[1]);
8522
+ }
8523
+ }).on(DragEvents.End, (event, d) => {
8524
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableY() && !d.removed && this.currentAction instanceof SetGeometryAction && this.currentAction.intent === DiagramActions.StretchNode) {
8525
+ let pointerCoords = this.getPointerLocationRelativeToCanvas(event);
8526
+ if (this.gridConfig.snap) {
8527
+ pointerCoords = this.getClosestGridPoint([pointerCoords[0] - d.type.snapToGridOffset[0], pointerCoords[1] - d.type.snapToGridOffset[1]]);
8528
+ pointerCoords[0] += d.type.snapToGridOffset[0];
8529
+ pointerCoords[1] += d.type.snapToGridOffset[1];
8530
+ }
8531
+ d.stretch(Side.Top, d.coords[1] - pointerCoords[1]);
8532
+ this.currentAction.to = d.getGeometry();
8533
+ this.currentAction.do();
8534
+ this.actionStack.add(this.currentAction);
8535
+ this.currentAction = undefined;
8536
+ }
8537
+ setCursorStyle();
8538
+ }));
8539
+ enterSelection.filter('.resizable-y').append('rect').attr('class', 'bottom-resizer').on(Events.MouseOver, (_event, d) => {
8540
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableY() && !d.removed) {
8541
+ setCursorStyle(CursorStyle.NSResize);
8542
+ }
8543
+ }).on(Events.MouseOut, (_event, d) => {
8544
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableY() && !d.removed) {
8545
+ setCursorStyle();
8546
+ }
8547
+ }).call(d3.drag().on(DragEvents.Start, (_event, d) => {
8548
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableY() && !d.removed) {
8549
+ setCursorStyle(CursorStyle.NSResize);
8550
+ this.currentAction = new SetGeometryAction(this, DiagramActions.StretchNode, d.id, d.getGeometry(), d.getGeometry());
8000
8551
  } else {
8001
- this.startMovingNode(event, d);
8552
+ setCursorStyle(CursorStyle.NotAllowed);
8002
8553
  }
8003
8554
  }).on(DragEvents.Drag, (event, d) => {
8004
- if (this.multipleSelectionOn || this.secondaryButton) {
8005
- this.continueMultipleSelection(event);
8006
- } else {
8007
- this.continueMovingNode(event, d);
8555
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableY() && !d.removed) {
8556
+ const pointerCoords = this.getPointerLocationRelativeToCanvas(event);
8557
+ d.stretch(Side.Bottom, pointerCoords[1] - (d.coords[1] + d.height));
8008
8558
  }
8009
8559
  }).on(DragEvents.End, (event, d) => {
8010
- if (this.multipleSelectionOn || this.secondaryButton) {
8011
- this.finishMultipleSelection(event);
8012
- } else {
8013
- this.finishMovingNode(event, d);
8560
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableY() && !d.removed && this.currentAction instanceof SetGeometryAction && this.currentAction.intent === DiagramActions.StretchNode) {
8561
+ let pointerCoords = this.getPointerLocationRelativeToCanvas(event);
8562
+ if (this.gridConfig.snap) {
8563
+ pointerCoords = this.getClosestGridPoint([pointerCoords[0] - d.type.snapToGridOffset[2], pointerCoords[1] - d.type.snapToGridOffset[3]]);
8564
+ pointerCoords[0] += d.type.snapToGridOffset[2];
8565
+ pointerCoords[1] += d.type.snapToGridOffset[3];
8566
+ }
8567
+ d.stretch(Side.Bottom, pointerCoords[1] - (d.coords[1] + d.height));
8568
+ this.currentAction.to = d.getGeometry();
8569
+ this.currentAction.do();
8570
+ this.actionStack.add(this.currentAction);
8571
+ this.currentAction = undefined;
8014
8572
  }
8015
- this.secondaryButton = false;
8573
+ setCursorStyle();
8016
8574
  }));
8017
- initializeLook(enterSelection);
8018
- enterSelection.filter('.resizable-x').append('line').attr('class', 'left-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(Events.MouseOver, (_event, d) => {
8019
- if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableX() && !d.removed) {
8020
- setCursorStyle(CursorStyle.EWResize);
8575
+ enterSelection.filter('.resizable-xy').append('rect').attr('class', 'top-left-resizer').on(Events.MouseOver, (_event, d) => {
8576
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableXY() && !d.removed) {
8577
+ setCursorStyle(CursorStyle.NWSEResize);
8021
8578
  }
8022
8579
  }).on(Events.MouseOut, (_event, d) => {
8023
- if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableX() && !d.removed) {
8580
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableXY() && !d.removed) {
8024
8581
  setCursorStyle();
8025
8582
  }
8026
8583
  }).call(d3.drag().on(DragEvents.Start, (_event, d) => {
8027
- if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableX() && !d.removed) {
8028
- setCursorStyle(CursorStyle.EWResize);
8584
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableXY() && !d.removed) {
8585
+ setCursorStyle(CursorStyle.NWSEResize);
8029
8586
  this.currentAction = new SetGeometryAction(this, DiagramActions.StretchNode, d.id, d.getGeometry(), d.getGeometry());
8030
8587
  } else {
8031
8588
  setCursorStyle(CursorStyle.NotAllowed);
8032
8589
  }
8033
8590
  }).on(DragEvents.Drag, (event, d) => {
8034
- if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableX() && !d.removed) {
8591
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableXY() && !d.removed) {
8035
8592
  const pointerCoords = this.getPointerLocationRelativeToCanvas(event);
8036
8593
  d.stretch(Side.Left, d.coords[0] - pointerCoords[0]);
8594
+ d.stretch(Side.Top, d.coords[1] - pointerCoords[1]);
8037
8595
  }
8038
8596
  }).on(DragEvents.End, (event, d) => {
8039
- if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableX() && !d.removed && this.currentAction instanceof SetGeometryAction && this.currentAction.intent === DiagramActions.StretchNode) {
8597
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableXY() && !d.removed && this.currentAction instanceof SetGeometryAction && this.currentAction.intent === DiagramActions.StretchNode) {
8040
8598
  let pointerCoords = this.getPointerLocationRelativeToCanvas(event);
8041
- if (this.snapToGrid) {
8599
+ if (this.gridConfig.snap) {
8042
8600
  pointerCoords = this.getClosestGridPoint([pointerCoords[0] - d.type.snapToGridOffset[0], pointerCoords[1] - d.type.snapToGridOffset[1]]);
8043
8601
  pointerCoords[0] += d.type.snapToGridOffset[0];
8044
8602
  pointerCoords[1] += d.type.snapToGridOffset[1];
8045
8603
  }
8046
8604
  d.stretch(Side.Left, d.coords[0] - pointerCoords[0]);
8605
+ d.stretch(Side.Top, d.coords[1] - pointerCoords[1]);
8047
8606
  this.currentAction.to = d.getGeometry();
8048
8607
  this.currentAction.do();
8049
8608
  this.actionStack.add(this.currentAction);
@@ -8051,34 +8610,36 @@ class DiagramCanvas {
8051
8610
  }
8052
8611
  setCursorStyle();
8053
8612
  }));
8054
- enterSelection.filter('.resizable-y').append('line').attr('class', 'top-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(Events.MouseOver, (_event, d) => {
8055
- if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableY() && !d.removed) {
8056
- setCursorStyle(CursorStyle.NSResize);
8613
+ enterSelection.filter('.resizable-xy').append('rect').attr('class', 'top-right-resizer').on(Events.MouseOver, (_event, d) => {
8614
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableXY() && !d.removed) {
8615
+ setCursorStyle(CursorStyle.NESWResize);
8057
8616
  }
8058
8617
  }).on(Events.MouseOut, (_event, d) => {
8059
- if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableY() && !d.removed) {
8618
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableXY() && !d.removed) {
8060
8619
  setCursorStyle();
8061
8620
  }
8062
8621
  }).call(d3.drag().on(DragEvents.Start, (_event, d) => {
8063
- if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableY() && !d.removed) {
8064
- setCursorStyle(CursorStyle.NSResize);
8622
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableXY() && !d.removed) {
8623
+ setCursorStyle(CursorStyle.NESWResize);
8065
8624
  this.currentAction = new SetGeometryAction(this, DiagramActions.StretchNode, d.id, d.getGeometry(), d.getGeometry());
8066
8625
  } else {
8067
8626
  setCursorStyle(CursorStyle.NotAllowed);
8068
8627
  }
8069
8628
  }).on(DragEvents.Drag, (event, d) => {
8070
- if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableY() && !d.removed) {
8629
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableXY() && !d.removed) {
8071
8630
  const pointerCoords = this.getPointerLocationRelativeToCanvas(event);
8631
+ d.stretch(Side.Right, pointerCoords[0] - (d.coords[0] + d.width));
8072
8632
  d.stretch(Side.Top, d.coords[1] - pointerCoords[1]);
8073
8633
  }
8074
8634
  }).on(DragEvents.End, (event, d) => {
8075
- if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableY() && !d.removed && this.currentAction instanceof SetGeometryAction && this.currentAction.intent === DiagramActions.StretchNode) {
8635
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableXY() && !d.removed && this.currentAction instanceof SetGeometryAction && this.currentAction.intent === DiagramActions.StretchNode) {
8076
8636
  let pointerCoords = this.getPointerLocationRelativeToCanvas(event);
8077
- if (this.snapToGrid) {
8637
+ if (this.gridConfig.snap) {
8078
8638
  pointerCoords = this.getClosestGridPoint([pointerCoords[0] - d.type.snapToGridOffset[0], pointerCoords[1] - d.type.snapToGridOffset[1]]);
8079
8639
  pointerCoords[0] += d.type.snapToGridOffset[0];
8080
8640
  pointerCoords[1] += d.type.snapToGridOffset[1];
8081
8641
  }
8642
+ d.stretch(Side.Right, pointerCoords[0] - (d.coords[0] + d.width));
8082
8643
  d.stretch(Side.Top, d.coords[1] - pointerCoords[1]);
8083
8644
  this.currentAction.to = d.getGeometry();
8084
8645
  this.currentAction.do();
@@ -8087,35 +8648,37 @@ class DiagramCanvas {
8087
8648
  }
8088
8649
  setCursorStyle();
8089
8650
  }));
8090
- enterSelection.filter('.resizable-x').append('line').attr('class', 'right-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(Events.MouseOver, (_event, d) => {
8091
- if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableX() && !d.removed) {
8092
- setCursorStyle(CursorStyle.EWResize);
8651
+ enterSelection.filter('.resizable-xy').append('rect').attr('class', 'bottom-left-resizer').on(Events.MouseOver, (_event, d) => {
8652
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableXY() && !d.removed) {
8653
+ setCursorStyle(CursorStyle.NESWResize);
8093
8654
  }
8094
8655
  }).on(Events.MouseOut, (_event, d) => {
8095
- if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableX() && !d.removed) {
8656
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableXY() && !d.removed) {
8096
8657
  setCursorStyle();
8097
8658
  }
8098
8659
  }).call(d3.drag().on(DragEvents.Start, (_event, d) => {
8099
- if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableX() && !d.removed) {
8100
- setCursorStyle(CursorStyle.EWResize);
8660
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableXY() && !d.removed) {
8661
+ setCursorStyle(CursorStyle.NESWResize);
8101
8662
  this.currentAction = new SetGeometryAction(this, DiagramActions.StretchNode, d.id, d.getGeometry(), d.getGeometry());
8102
8663
  } else {
8103
8664
  setCursorStyle(CursorStyle.NotAllowed);
8104
8665
  }
8105
8666
  }).on(DragEvents.Drag, (event, d) => {
8106
- if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableX() && !d.removed) {
8667
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableXY() && !d.removed) {
8107
8668
  const pointerCoords = this.getPointerLocationRelativeToCanvas(event);
8108
- d.stretch(Side.Right, pointerCoords[0] - (d.coords[0] + d.width));
8669
+ d.stretch(Side.Left, d.coords[0] - pointerCoords[0]);
8670
+ d.stretch(Side.Bottom, pointerCoords[1] - (d.coords[1] + d.height));
8109
8671
  }
8110
8672
  }).on(DragEvents.End, (event, d) => {
8111
- if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableX() && !d.removed && this.currentAction instanceof SetGeometryAction && this.currentAction.intent === DiagramActions.StretchNode) {
8673
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableXY() && !d.removed && this.currentAction instanceof SetGeometryAction && this.currentAction.intent === DiagramActions.StretchNode) {
8112
8674
  let pointerCoords = this.getPointerLocationRelativeToCanvas(event);
8113
- if (this.snapToGrid) {
8114
- pointerCoords = this.getClosestGridPoint([pointerCoords[0] - d.type.snapToGridOffset[2], pointerCoords[1] - d.type.snapToGridOffset[3]]);
8115
- pointerCoords[0] += d.type.snapToGridOffset[2];
8116
- pointerCoords[1] += d.type.snapToGridOffset[3];
8675
+ if (this.gridConfig.snap) {
8676
+ pointerCoords = this.getClosestGridPoint([pointerCoords[0] - d.type.snapToGridOffset[0], pointerCoords[1] - d.type.snapToGridOffset[1]]);
8677
+ pointerCoords[0] += d.type.snapToGridOffset[0];
8678
+ pointerCoords[1] += d.type.snapToGridOffset[1];
8117
8679
  }
8118
- d.stretch(Side.Right, pointerCoords[0] - (d.coords[0] + d.width));
8680
+ d.stretch(Side.Left, d.coords[0] - pointerCoords[0]);
8681
+ d.stretch(Side.Bottom, pointerCoords[1] - (d.coords[1] + d.height));
8119
8682
  this.currentAction.to = d.getGeometry();
8120
8683
  this.currentAction.do();
8121
8684
  this.actionStack.add(this.currentAction);
@@ -8123,36 +8686,36 @@ class DiagramCanvas {
8123
8686
  }
8124
8687
  setCursorStyle();
8125
8688
  }));
8126
- enterSelection.filter('.resizable-y').append('line').attr('class', 'bottom-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(Events.MouseOver, (_event, d) => {
8127
- if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableY() && !d.removed) {
8128
- setCursorStyle(CursorStyle.NSResize);
8689
+ enterSelection.filter('.resizable-xy').append('rect').attr('class', 'bottom-right-resizer').on(Events.MouseOver, (_event, d) => {
8690
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableXY() && !d.removed) {
8691
+ setCursorStyle(CursorStyle.NWSEResize);
8129
8692
  }
8130
8693
  }).on(Events.MouseOut, (_event, d) => {
8131
- if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableY() && !d.removed) {
8694
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableXY() && !d.removed) {
8132
8695
  setCursorStyle();
8133
8696
  }
8134
8697
  }).call(d3.drag().on(DragEvents.Start, (_event, d) => {
8135
- if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableY() && !d.removed) {
8136
- setCursorStyle(CursorStyle.NSResize);
8698
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableXY() && !d.removed) {
8699
+ setCursorStyle(CursorStyle.NWSEResize);
8137
8700
  this.currentAction = new SetGeometryAction(this, DiagramActions.StretchNode, d.id, d.getGeometry(), d.getGeometry());
8138
8701
  } else {
8139
8702
  setCursorStyle(CursorStyle.NotAllowed);
8140
8703
  }
8141
8704
  }).on(DragEvents.Drag, (event, d) => {
8142
- if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableY() && !d.removed) {
8705
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableXY() && !d.removed) {
8143
8706
  const pointerCoords = this.getPointerLocationRelativeToCanvas(event);
8707
+ d.stretch(Side.Right, pointerCoords[0] - (d.coords[0] + d.width));
8144
8708
  d.stretch(Side.Bottom, pointerCoords[1] - (d.coords[1] + d.height));
8145
8709
  }
8146
8710
  }).on(DragEvents.End, (event, d) => {
8147
- if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableY() && !d.removed && this.currentAction instanceof SetGeometryAction && this.currentAction.intent === DiagramActions.StretchNode) {
8711
+ if (this.canUserPerformAction(DiagramActions.StretchNode) && d.getResizableXY() && !d.removed && this.currentAction instanceof SetGeometryAction && this.currentAction.intent === DiagramActions.StretchNode) {
8148
8712
  let pointerCoords = this.getPointerLocationRelativeToCanvas(event);
8149
- if (this.snapToGrid) {
8150
- if (this.snapToGrid) {
8151
- pointerCoords = this.getClosestGridPoint([pointerCoords[0] - d.type.snapToGridOffset[2], pointerCoords[1] - d.type.snapToGridOffset[3]]);
8152
- pointerCoords[0] += d.type.snapToGridOffset[2];
8153
- pointerCoords[1] += d.type.snapToGridOffset[3];
8154
- }
8713
+ if (this.gridConfig.snap) {
8714
+ pointerCoords = this.getClosestGridPoint([pointerCoords[0] - d.type.snapToGridOffset[0], pointerCoords[1] - d.type.snapToGridOffset[1]]);
8715
+ pointerCoords[0] += d.type.snapToGridOffset[0];
8716
+ pointerCoords[1] += d.type.snapToGridOffset[1];
8155
8717
  }
8718
+ d.stretch(Side.Right, pointerCoords[0] - (d.coords[0] + d.width));
8156
8719
  d.stretch(Side.Bottom, pointerCoords[1] - (d.coords[1] + d.height));
8157
8720
  this.currentAction.to = d.getGeometry();
8158
8721
  this.currentAction.do();
@@ -8163,17 +8726,21 @@ class DiagramCanvas {
8163
8726
  }));
8164
8727
  mergeSelection.attr('transform', d => `translate(${d.coords[0]},${d.coords[1]})`).attr('opacity', d => d.removed ? 0.5 : 1);
8165
8728
  updateLook(mergeSelection);
8166
- mergeSelection.filter('.resizable-x').select('line.left-resizer').style('pointer-events', d => d.getResizableX() ? 'initial' : 'none').attr('x1', RESIZER_THICKNESS / 2).attr('x2', RESIZER_THICKNESS / 2).attr('y1', 0).attr('y2', d => d.height);
8167
- mergeSelection.filter('.resizable-y').select('line.top-resizer').style('pointer-events', d => d.getResizableY() ? 'initial' : 'none').attr('x1', 0).attr('x2', d => d.width).attr('y1', RESIZER_THICKNESS / 2).attr('y2', RESIZER_THICKNESS / 2);
8168
- mergeSelection.filter('.resizable-x').select('line.right-resizer').style('pointer-events', d => d.getResizableX() ? 'initial' : 'none').attr('x1', d => d.width - RESIZER_THICKNESS / 2).attr('x2', d => d.width - RESIZER_THICKNESS / 2).attr('y1', 0).attr('y2', d => d.height);
8169
- mergeSelection.filter('.resizable-y').select('line.bottom-resizer').style('pointer-events', d => d.getResizableY() ? 'initial' : 'none').attr('x1', 0).attr('x2', d => d.width).attr('y1', d => d.height - RESIZER_THICKNESS / 2).attr('y2', d => d.height - RESIZER_THICKNESS / 2);
8729
+ mergeSelection.filter('.resizable-x').select('rect.left-resizer').style('pointer-events', d => d.getResizableX() ? 'initial' : 'none').attr('x', d => -d.getResizerX().outerMargin).attr('y', d => d.getResizerXY().thickness - d.getResizerXY().outerMargin).attr('width', d => d.getResizerX().thickness).attr('height', d => d.height - d.getResizerXY().thickness * 2 + d.getResizerXY().outerMargin * 2).attr('fill', d => d.getResizerX().getLook(d).fillColor || 'transparent').attr('stroke', d => d.getResizerX().getLook(d).borderColor || 'transparent').attr('stroke-width', d => d.getResizerX().getLook(d).borderThickness || 0);
8730
+ mergeSelection.filter('.resizable-x').select('rect.right-resizer').style('pointer-events', d => d.getResizableX() ? 'initial' : 'none').attr('x', d => d.width - d.getResizerX().thickness + d.getResizerX().outerMargin).attr('y', d => d.getResizerXY().thickness - d.getResizerXY().outerMargin).attr('width', d => d.getResizerX().thickness).attr('height', d => d.height - d.getResizerXY().thickness * 2 + d.getResizerXY().outerMargin * 2).attr('fill', d => d.getResizerX().getLook(d).fillColor || 'transparent').attr('stroke', d => d.getResizerX().getLook(d).borderColor || 'transparent').attr('stroke-width', d => d.getResizerX().getLook(d).borderThickness || 0);
8731
+ mergeSelection.filter('.resizable-y').select('rect.top-resizer').style('pointer-events', d => d.getResizableY() ? 'initial' : 'none').attr('x', d => d.getResizerXY().thickness - d.getResizerXY().outerMargin).attr('y', d => -d.getResizerY().outerMargin).attr('width', d => d.width - d.getResizerXY().thickness * 2 + d.getResizerXY().outerMargin * 2).attr('height', d => d.getResizerY().thickness).attr('fill', d => d.getResizerY().getLook(d).fillColor || 'transparent').attr('stroke', d => d.getResizerY().getLook(d).borderColor || 'transparent').attr('stroke-width', d => d.getResizerY().getLook(d).borderThickness || 0);
8732
+ mergeSelection.filter('.resizable-y').select('rect.bottom-resizer').style('pointer-events', d => d.getResizableY() ? 'initial' : 'none').attr('x', d => d.getResizerXY().thickness - d.getResizerXY().outerMargin).attr('y', d => d.height - d.getResizerY().thickness + d.getResizerY().outerMargin).attr('width', d => d.width - d.getResizerXY().thickness * 2 + d.getResizerXY().outerMargin * 2).attr('height', d => d.getResizerY().thickness).attr('fill', d => d.getResizerY().getLook(d).fillColor || 'transparent').attr('stroke', d => d.getResizerY().getLook(d).borderColor || 'transparent').attr('stroke-width', d => d.getResizerY().getLook(d).borderThickness || 0);
8733
+ mergeSelection.filter('.resizable-xy').select('rect.top-left-resizer').style('pointer-events', d => d.getResizableXY() ? 'initial' : 'none').attr('x', d => -d.getResizerXY().outerMargin).attr('y', d => -d.getResizerXY().outerMargin).attr('width', d => d.getResizerXY().thickness).attr('height', d => d.getResizerXY().thickness).attr('fill', d => d.getResizerXY().getLook(d).fillColor || 'transparent').attr('stroke', d => d.getResizerXY().getLook(d).borderColor || 'transparent').attr('stroke-width', d => d.getResizerXY().getLook(d).borderThickness || 0);
8734
+ mergeSelection.filter('.resizable-xy').select('rect.top-right-resizer').style('pointer-events', d => d.getResizableXY() ? 'initial' : 'none').attr('x', d => d.width - d.getResizerXY().thickness + d.getResizerXY().outerMargin).attr('y', d => -d.getResizerXY().outerMargin).attr('width', d => d.getResizerXY().thickness).attr('height', d => d.getResizerXY().thickness).attr('fill', d => d.getResizerXY().getLook(d).fillColor || 'transparent').attr('stroke', d => d.getResizerXY().getLook(d).borderColor || 'transparent').attr('stroke-width', d => d.getResizerXY().getLook(d).borderThickness || 0);
8735
+ mergeSelection.filter('.resizable-xy').select('rect.bottom-left-resizer').style('pointer-events', d => d.getResizableXY() ? 'initial' : 'none').attr('x', d => -d.getResizerXY().outerMargin).attr('y', d => d.height - d.getResizerXY().thickness + d.getResizerXY().outerMargin).attr('width', d => d.getResizerXY().thickness).attr('height', d => d.getResizerXY().thickness).attr('fill', d => d.getResizerXY().getLook(d).fillColor || 'transparent').attr('stroke', d => d.getResizerXY().getLook(d).borderColor || 'transparent').attr('stroke-width', d => d.getResizerXY().getLook(d).borderThickness || 0);
8736
+ mergeSelection.filter('.resizable-xy').select('rect.bottom-right-resizer').style('pointer-events', d => d.getResizableXY() ? 'initial' : 'none').attr('x', d => d.width - d.getResizerXY().thickness + d.getResizerXY().outerMargin).attr('y', d => d.height - d.getResizerXY().thickness + d.getResizerXY().outerMargin).attr('width', d => d.getResizerXY().thickness).attr('height', d => d.getResizerXY().thickness).attr('fill', d => d.getResizerXY().getLook(d).fillColor || 'transparent').attr('stroke', d => d.getResizerXY().getLook(d).borderColor || 'transparent').attr('stroke-width', d => d.getResizerXY().getLook(d).borderThickness || 0);
8170
8737
  }
8171
8738
  updateSectionsInView(...ids) {
8172
8739
  let updateSelection = this.selectCanvasElements().selectAll('g.diagram-section').data(this.model.sections.filter(e => this.priorityThreshold !== undefined ? e.getPriority() >= this.priorityThreshold : true), d => d.id);
8173
8740
  const exitSelection = updateSelection.exit();
8174
8741
  const enterSelection = updateSelection.enter().append('g').attr('id', d => d.id).attr('class', d => {
8175
8742
  var _a;
8176
- return `diagram-section${needsResizerX(d) ? ' resizable-x' : ''}${needsResizerY(d) ? ' resizable-y' : ''} ${(_a = d.look) === null || _a === void 0 ? void 0 : _a.lookType}`;
8743
+ return `diagram-section${needsResizerX(d) ? ' resizable-x' : ''}${needsResizerY(d) ? ' resizable-y' : ''}${needsResizerXY(d) ? ' resizable-xy' : ''} ${(_a = d.look) === null || _a === void 0 ? void 0 : _a.lookType}`;
8177
8744
  });
8178
8745
  if (ids && ids.length > 0) {
8179
8746
  updateSelection = updateSelection.filter(d => ids.includes(d.id));
@@ -8254,7 +8821,7 @@ class DiagramCanvas {
8254
8821
  this.secondaryButton = false;
8255
8822
  }));
8256
8823
  initializeLook(enterSelection);
8257
- enterSelection.filter('.resizable-x').append('line').attr('class', 'left-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(Events.MouseOver, (_event, d) => {
8824
+ enterSelection.filter('.resizable-x').append('rect').attr('class', 'left-resizer').on(Events.MouseOver, (_event, d) => {
8258
8825
  if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableX() && !d.removed) {
8259
8826
  setCursorStyle(CursorStyle.EWResize);
8260
8827
  }
@@ -8277,7 +8844,7 @@ class DiagramCanvas {
8277
8844
  }).on(DragEvents.End, (event, d) => {
8278
8845
  if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableX() && !d.removed && this.currentAction instanceof SetGeometryAction && this.currentAction.intent === DiagramActions.StretchSection && d.node) {
8279
8846
  let pointerCoords = this.getPointerLocationRelativeToCanvas(event);
8280
- if (this.snapToGrid) {
8847
+ if (this.gridConfig.snap) {
8281
8848
  pointerCoords = this.getClosestGridPoint(pointerCoords);
8282
8849
  }
8283
8850
  d.node.stretchSections(Side.Left, d.coords[0] - pointerCoords[0], d.indexXInNode, d.indexYInNode);
@@ -8288,7 +8855,41 @@ class DiagramCanvas {
8288
8855
  }
8289
8856
  setCursorStyle();
8290
8857
  }));
8291
- enterSelection.filter('.resizable-y').append('line').attr('class', 'top-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(Events.MouseOver, (_event, d) => {
8858
+ enterSelection.filter('.resizable-x').append('rect').attr('class', 'right-resizer').on(Events.MouseOver, (_event, d) => {
8859
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableX() && !d.removed) {
8860
+ setCursorStyle(CursorStyle.EWResize);
8861
+ }
8862
+ }).on(Events.MouseOut, (_event, d) => {
8863
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableX() && !d.removed) {
8864
+ setCursorStyle();
8865
+ }
8866
+ }).call(d3.drag().on(DragEvents.Start, (_event, d) => {
8867
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableX() && !d.removed && d.node) {
8868
+ setCursorStyle(CursorStyle.EWResize);
8869
+ this.currentAction = new SetGeometryAction(this, DiagramActions.StretchSection, d.node.id, d.node.getGeometry(), d.node.getGeometry());
8870
+ } else {
8871
+ setCursorStyle(CursorStyle.NotAllowed);
8872
+ }
8873
+ }).on(DragEvents.Drag, (event, d) => {
8874
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableX() && !d.removed && d.node) {
8875
+ const pointerCoords = this.getPointerLocationRelativeToCanvas(event);
8876
+ d.node.stretchSections(Side.Right, pointerCoords[0] - (d.coords[0] + d.width), d.indexXInNode, d.indexYInNode);
8877
+ }
8878
+ }).on(DragEvents.End, (event, d) => {
8879
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableX() && !d.removed && this.currentAction instanceof SetGeometryAction && this.currentAction.intent === DiagramActions.StretchSection && d.node) {
8880
+ let pointerCoords = this.getPointerLocationRelativeToCanvas(event);
8881
+ if (this.gridConfig.snap) {
8882
+ pointerCoords = this.getClosestGridPoint(pointerCoords);
8883
+ }
8884
+ d.node.stretchSections(Side.Right, pointerCoords[0] - (d.coords[0] + d.width), d.indexXInNode, d.indexYInNode);
8885
+ this.currentAction.to = d.node.getGeometry();
8886
+ this.currentAction.do();
8887
+ this.actionStack.add(this.currentAction);
8888
+ this.currentAction = undefined;
8889
+ }
8890
+ setCursorStyle();
8891
+ }));
8892
+ enterSelection.filter('.resizable-y').append('rect').attr('class', 'top-resizer').on(Events.MouseOver, (_event, d) => {
8292
8893
  if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableY() && !d.removed) {
8293
8894
  setCursorStyle(CursorStyle.NSResize);
8294
8895
  }
@@ -8311,7 +8912,7 @@ class DiagramCanvas {
8311
8912
  }).on(DragEvents.End, (event, d) => {
8312
8913
  if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableY() && !d.removed && this.currentAction instanceof SetGeometryAction && this.currentAction.intent === DiagramActions.StretchSection && d.node) {
8313
8914
  let pointerCoords = this.getPointerLocationRelativeToCanvas(event);
8314
- if (this.snapToGrid) {
8915
+ if (this.gridConfig.snap) {
8315
8916
  pointerCoords = this.getClosestGridPoint(pointerCoords);
8316
8917
  }
8317
8918
  d.node.stretchSections(Side.Top, d.coords[1] - pointerCoords[1], d.indexXInNode, d.indexYInNode);
@@ -8322,33 +8923,105 @@ class DiagramCanvas {
8322
8923
  }
8323
8924
  setCursorStyle();
8324
8925
  }));
8325
- enterSelection.filter('.resizable-x').append('line').attr('class', 'right-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(Events.MouseOver, (_event, d) => {
8326
- if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableX() && !d.removed) {
8327
- setCursorStyle(CursorStyle.EWResize);
8926
+ enterSelection.filter('.resizable-y').append('rect').attr('class', 'bottom-resizer').on(Events.MouseOver, (_event, d) => {
8927
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableY() && !d.removed) {
8928
+ setCursorStyle(CursorStyle.NSResize);
8328
8929
  }
8329
8930
  }).on(Events.MouseOut, (_event, d) => {
8330
- if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableX() && !d.removed) {
8931
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableY() && !d.removed) {
8331
8932
  setCursorStyle();
8332
8933
  }
8333
8934
  }).call(d3.drag().on(DragEvents.Start, (_event, d) => {
8334
- if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableX() && !d.removed && d.node) {
8335
- setCursorStyle(CursorStyle.EWResize);
8935
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableY() && !d.removed && d.node) {
8936
+ setCursorStyle(CursorStyle.NSResize);
8336
8937
  this.currentAction = new SetGeometryAction(this, DiagramActions.StretchSection, d.node.id, d.node.getGeometry(), d.node.getGeometry());
8337
8938
  } else {
8338
8939
  setCursorStyle(CursorStyle.NotAllowed);
8339
8940
  }
8340
8941
  }).on(DragEvents.Drag, (event, d) => {
8341
- if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableX() && !d.removed && d.node) {
8942
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableY() && !d.removed && d.node) {
8943
+ const pointerCoords = this.getPointerLocationRelativeToCanvas(event);
8944
+ d.node.stretchSections(Side.Bottom, pointerCoords[1] - (d.coords[1] + d.height), d.indexXInNode, d.indexYInNode);
8945
+ }
8946
+ }).on(DragEvents.End, (event, d) => {
8947
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableY() && !d.removed && this.currentAction instanceof SetGeometryAction && this.currentAction.intent === DiagramActions.StretchSection && d.node) {
8948
+ let pointerCoords = this.getPointerLocationRelativeToCanvas(event);
8949
+ if (this.gridConfig.snap) {
8950
+ pointerCoords = this.getClosestGridPoint(pointerCoords);
8951
+ }
8952
+ d.node.stretchSections(Side.Bottom, pointerCoords[1] - (d.coords[1] + d.height), d.indexXInNode, d.indexYInNode);
8953
+ this.currentAction.to = d.node.getGeometry();
8954
+ this.currentAction.do();
8955
+ this.actionStack.add(this.currentAction);
8956
+ this.currentAction = undefined;
8957
+ }
8958
+ setCursorStyle();
8959
+ }));
8960
+ enterSelection.filter('.resizable-xy').append('rect').attr('class', 'top-left-resizer').on(Events.MouseOver, (_event, d) => {
8961
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableXY() && !d.removed) {
8962
+ setCursorStyle(CursorStyle.NWSEResize);
8963
+ }
8964
+ }).on(Events.MouseOut, (_event, d) => {
8965
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableXY() && !d.removed) {
8966
+ setCursorStyle();
8967
+ }
8968
+ }).call(d3.drag().on(DragEvents.Start, (_event, d) => {
8969
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableXY() && !d.removed && d.node) {
8970
+ setCursorStyle(CursorStyle.NWSEResize);
8971
+ this.currentAction = new SetGeometryAction(this, DiagramActions.StretchSection, d.node.id, d.node.getGeometry(), d.node.getGeometry());
8972
+ } else {
8973
+ setCursorStyle(CursorStyle.NotAllowed);
8974
+ }
8975
+ }).on(DragEvents.Drag, (event, d) => {
8976
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableXY() && !d.removed && d.node) {
8977
+ const pointerCoords = this.getPointerLocationRelativeToCanvas(event);
8978
+ d.node.stretchSections(Side.Left, d.coords[0] - pointerCoords[0], d.indexXInNode, d.indexYInNode);
8979
+ d.node.stretchSections(Side.Top, d.coords[1] - pointerCoords[1], d.indexXInNode, d.indexYInNode);
8980
+ }
8981
+ }).on(DragEvents.End, (event, d) => {
8982
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableXY() && !d.removed && this.currentAction instanceof SetGeometryAction && this.currentAction.intent === DiagramActions.StretchSection && d.node) {
8983
+ let pointerCoords = this.getPointerLocationRelativeToCanvas(event);
8984
+ if (this.gridConfig.snap) {
8985
+ pointerCoords = this.getClosestGridPoint(pointerCoords);
8986
+ }
8987
+ d.node.stretchSections(Side.Left, d.coords[0] - pointerCoords[0], d.indexXInNode, d.indexYInNode);
8988
+ d.node.stretchSections(Side.Top, d.coords[1] - pointerCoords[1], d.indexXInNode, d.indexYInNode);
8989
+ this.currentAction.to = d.node.getGeometry();
8990
+ this.currentAction.do();
8991
+ this.actionStack.add(this.currentAction);
8992
+ this.currentAction = undefined;
8993
+ }
8994
+ setCursorStyle();
8995
+ }));
8996
+ enterSelection.filter('.resizable-xy').append('rect').attr('class', 'top-right-resizer').on(Events.MouseOver, (_event, d) => {
8997
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableXY() && !d.removed) {
8998
+ setCursorStyle(CursorStyle.NESWResize);
8999
+ }
9000
+ }).on(Events.MouseOut, (_event, d) => {
9001
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableXY() && !d.removed) {
9002
+ setCursorStyle();
9003
+ }
9004
+ }).call(d3.drag().on(DragEvents.Start, (_event, d) => {
9005
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableXY() && !d.removed && d.node) {
9006
+ setCursorStyle(CursorStyle.NESWResize);
9007
+ this.currentAction = new SetGeometryAction(this, DiagramActions.StretchSection, d.node.id, d.node.getGeometry(), d.node.getGeometry());
9008
+ } else {
9009
+ setCursorStyle(CursorStyle.NotAllowed);
9010
+ }
9011
+ }).on(DragEvents.Drag, (event, d) => {
9012
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableXY() && !d.removed && d.node) {
8342
9013
  const pointerCoords = this.getPointerLocationRelativeToCanvas(event);
8343
9014
  d.node.stretchSections(Side.Right, pointerCoords[0] - (d.coords[0] + d.width), d.indexXInNode, d.indexYInNode);
9015
+ d.node.stretchSections(Side.Top, d.coords[1] - pointerCoords[1], d.indexXInNode, d.indexYInNode);
8344
9016
  }
8345
9017
  }).on(DragEvents.End, (event, d) => {
8346
- if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableX() && !d.removed && this.currentAction instanceof SetGeometryAction && this.currentAction.intent === DiagramActions.StretchSection && d.node) {
9018
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableXY() && !d.removed && this.currentAction instanceof SetGeometryAction && this.currentAction.intent === DiagramActions.StretchSection && d.node) {
8347
9019
  let pointerCoords = this.getPointerLocationRelativeToCanvas(event);
8348
- if (this.snapToGrid) {
9020
+ if (this.gridConfig.snap) {
8349
9021
  pointerCoords = this.getClosestGridPoint(pointerCoords);
8350
9022
  }
8351
9023
  d.node.stretchSections(Side.Right, pointerCoords[0] - (d.coords[0] + d.width), d.indexXInNode, d.indexYInNode);
9024
+ d.node.stretchSections(Side.Top, d.coords[1] - pointerCoords[1], d.indexXInNode, d.indexYInNode);
8352
9025
  this.currentAction.to = d.node.getGeometry();
8353
9026
  this.currentAction.do();
8354
9027
  this.actionStack.add(this.currentAction);
@@ -8356,32 +9029,70 @@ class DiagramCanvas {
8356
9029
  }
8357
9030
  setCursorStyle();
8358
9031
  }));
8359
- enterSelection.filter('.resizable-y').append('line').attr('class', 'bottom-resizer').attr('stroke', 'transparent').attr('stroke-width', RESIZER_THICKNESS).on(Events.MouseOver, (_event, d) => {
8360
- if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableY() && !d.removed) {
8361
- setCursorStyle(CursorStyle.NSResize);
9032
+ enterSelection.filter('.resizable-xy').append('rect').attr('class', 'bottom-left-resizer').on(Events.MouseOver, (_event, d) => {
9033
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableXY() && !d.removed) {
9034
+ setCursorStyle(CursorStyle.NESWResize);
8362
9035
  }
8363
9036
  }).on(Events.MouseOut, (_event, d) => {
8364
- if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableY() && !d.removed) {
9037
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableXY() && !d.removed) {
8365
9038
  setCursorStyle();
8366
9039
  }
8367
9040
  }).call(d3.drag().on(DragEvents.Start, (_event, d) => {
8368
- if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableY() && !d.removed && d.node) {
8369
- setCursorStyle(CursorStyle.NSResize);
9041
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableXY() && !d.removed && d.node) {
9042
+ setCursorStyle(CursorStyle.NESWResize);
8370
9043
  this.currentAction = new SetGeometryAction(this, DiagramActions.StretchSection, d.node.id, d.node.getGeometry(), d.node.getGeometry());
8371
9044
  } else {
8372
9045
  setCursorStyle(CursorStyle.NotAllowed);
8373
9046
  }
8374
9047
  }).on(DragEvents.Drag, (event, d) => {
8375
- if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableY() && !d.removed && d.node) {
9048
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableXY() && !d.removed && d.node) {
8376
9049
  const pointerCoords = this.getPointerLocationRelativeToCanvas(event);
9050
+ d.node.stretchSections(Side.Left, d.coords[0] - pointerCoords[0], d.indexXInNode, d.indexYInNode);
8377
9051
  d.node.stretchSections(Side.Bottom, pointerCoords[1] - (d.coords[1] + d.height), d.indexXInNode, d.indexYInNode);
8378
9052
  }
8379
9053
  }).on(DragEvents.End, (event, d) => {
8380
- if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableY() && !d.removed && this.currentAction instanceof SetGeometryAction && this.currentAction.intent === DiagramActions.StretchSection && d.node) {
9054
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableXY() && !d.removed && this.currentAction instanceof SetGeometryAction && this.currentAction.intent === DiagramActions.StretchSection && d.node) {
9055
+ let pointerCoords = this.getPointerLocationRelativeToCanvas(event);
9056
+ if (this.gridConfig.snap) {
9057
+ pointerCoords = this.getClosestGridPoint(pointerCoords);
9058
+ }
9059
+ d.node.stretchSections(Side.Left, d.coords[0] - pointerCoords[0], d.indexXInNode, d.indexYInNode);
9060
+ d.node.stretchSections(Side.Bottom, pointerCoords[1] - (d.coords[1] + d.height), d.indexXInNode, d.indexYInNode);
9061
+ this.currentAction.to = d.node.getGeometry();
9062
+ this.currentAction.do();
9063
+ this.actionStack.add(this.currentAction);
9064
+ this.currentAction = undefined;
9065
+ }
9066
+ setCursorStyle();
9067
+ }));
9068
+ enterSelection.filter('.resizable-xy').append('rect').attr('class', 'bottom-right-resizer').on(Events.MouseOver, (_event, d) => {
9069
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableXY() && !d.removed) {
9070
+ setCursorStyle(CursorStyle.NWSEResize);
9071
+ }
9072
+ }).on(Events.MouseOut, (_event, d) => {
9073
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableXY() && !d.removed) {
9074
+ setCursorStyle();
9075
+ }
9076
+ }).call(d3.drag().on(DragEvents.Start, (_event, d) => {
9077
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableXY() && !d.removed && d.node) {
9078
+ setCursorStyle(CursorStyle.NWSEResize);
9079
+ this.currentAction = new SetGeometryAction(this, DiagramActions.StretchSection, d.node.id, d.node.getGeometry(), d.node.getGeometry());
9080
+ } else {
9081
+ setCursorStyle(CursorStyle.NotAllowed);
9082
+ }
9083
+ }).on(DragEvents.Drag, (event, d) => {
9084
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableXY() && !d.removed && d.node) {
9085
+ const pointerCoords = this.getPointerLocationRelativeToCanvas(event);
9086
+ d.node.stretchSections(Side.Right, pointerCoords[0] - (d.coords[0] + d.width), d.indexXInNode, d.indexYInNode);
9087
+ d.node.stretchSections(Side.Bottom, pointerCoords[1] - (d.coords[1] + d.height), d.indexXInNode, d.indexYInNode);
9088
+ }
9089
+ }).on(DragEvents.End, (event, d) => {
9090
+ if (this.canUserPerformAction(DiagramActions.StretchSection) && d.getResizableXY() && !d.removed && this.currentAction instanceof SetGeometryAction && this.currentAction.intent === DiagramActions.StretchSection && d.node) {
8381
9091
  let pointerCoords = this.getPointerLocationRelativeToCanvas(event);
8382
- if (this.snapToGrid) {
9092
+ if (this.gridConfig.snap) {
8383
9093
  pointerCoords = this.getClosestGridPoint(pointerCoords);
8384
9094
  }
9095
+ d.node.stretchSections(Side.Right, pointerCoords[0] - (d.coords[0] + d.width), d.indexXInNode, d.indexYInNode);
8385
9096
  d.node.stretchSections(Side.Bottom, pointerCoords[1] - (d.coords[1] + d.height), d.indexXInNode, d.indexYInNode);
8386
9097
  this.currentAction.to = d.node.getGeometry();
8387
9098
  this.currentAction.do();
@@ -8392,10 +9103,14 @@ class DiagramCanvas {
8392
9103
  }));
8393
9104
  mergeSelection.attr('transform', d => `translate(${d.coords[0]},${d.coords[1]})`).attr('opacity', d => d.removed ? 0.5 : 1);
8394
9105
  updateLook(mergeSelection);
8395
- mergeSelection.filter('.resizable-x').select('line.left-resizer').style('pointer-events', d => d.getResizableX() ? 'initial' : 'none').attr('x1', RESIZER_THICKNESS / 2).attr('x2', RESIZER_THICKNESS / 2).attr('y1', 0).attr('y2', d => d.height);
8396
- mergeSelection.filter('.resizable-y').select('line.top-resizer').style('pointer-events', d => d.getResizableY() ? 'initial' : 'none').attr('x1', 0).attr('x2', d => d.width).attr('y1', RESIZER_THICKNESS / 2).attr('y2', RESIZER_THICKNESS / 2);
8397
- mergeSelection.filter('.resizable-x').select('line.right-resizer').style('pointer-events', d => d.getResizableX() ? 'initial' : 'none').attr('x1', d => d.width - RESIZER_THICKNESS / 2).attr('x2', d => d.width - RESIZER_THICKNESS / 2).attr('y1', 0).attr('y2', d => d.height);
8398
- mergeSelection.filter('.resizable-y').select('line.bottom-resizer').style('pointer-events', d => d.getResizableY() ? 'initial' : 'none').attr('x1', 0).attr('x2', d => d.width).attr('y1', d => d.height - RESIZER_THICKNESS / 2).attr('y2', d => d.height - RESIZER_THICKNESS / 2);
9106
+ mergeSelection.filter('.resizable-x').select('rect.left-resizer').style('pointer-events', d => d.getResizableX() ? 'initial' : 'none').attr('x', d => -d.getResizerX().outerMargin).attr('y', d => d.getResizerXY().thickness - d.getResizerXY().outerMargin).attr('width', d => d.getResizerX().thickness).attr('height', d => d.height - d.getResizerXY().thickness * 2 + d.getResizerXY().outerMargin * 2).attr('fill', d => d.getResizerX().getLook(d).fillColor || 'transparent').attr('stroke', d => d.getResizerX().getLook(d).borderColor || 'transparent').attr('stroke-width', d => d.getResizerX().getLook(d).borderThickness || 0);
9107
+ mergeSelection.filter('.resizable-x').select('rect.right-resizer').style('pointer-events', d => d.getResizableX() ? 'initial' : 'none').attr('x', d => d.width - d.getResizerX().thickness + d.getResizerX().outerMargin).attr('y', d => d.getResizerXY().thickness - d.getResizerXY().outerMargin).attr('width', d => d.getResizerX().thickness).attr('height', d => d.height - d.getResizerXY().thickness * 2 + d.getResizerXY().outerMargin * 2).attr('fill', d => d.getResizerX().getLook(d).fillColor || 'transparent').attr('stroke', d => d.getResizerX().getLook(d).borderColor || 'transparent').attr('stroke-width', d => d.getResizerX().getLook(d).borderThickness || 0);
9108
+ mergeSelection.filter('.resizable-y').select('rect.top-resizer').style('pointer-events', d => d.getResizableY() ? 'initial' : 'none').attr('x', d => d.getResizerXY().thickness - d.getResizerXY().outerMargin).attr('y', d => -d.getResizerY().outerMargin).attr('width', d => d.width - d.getResizerXY().thickness * 2 + d.getResizerXY().outerMargin * 2).attr('height', d => d.getResizerY().thickness).attr('fill', d => d.getResizerY().getLook(d).fillColor || 'transparent').attr('stroke', d => d.getResizerY().getLook(d).borderColor || 'transparent').attr('stroke-width', d => d.getResizerY().getLook(d).borderThickness || 0);
9109
+ mergeSelection.filter('.resizable-y').select('rect.bottom-resizer').style('pointer-events', d => d.getResizableY() ? 'initial' : 'none').attr('x', d => d.getResizerXY().thickness - d.getResizerXY().outerMargin).attr('y', d => d.height - d.getResizerY().thickness + d.getResizerY().outerMargin).attr('width', d => d.width - d.getResizerXY().thickness * 2 + d.getResizerXY().outerMargin * 2).attr('height', d => d.getResizerY().thickness).attr('fill', d => d.getResizerY().getLook(d).fillColor || 'transparent').attr('stroke', d => d.getResizerY().getLook(d).borderColor || 'transparent').attr('stroke-width', d => d.getResizerY().getLook(d).borderThickness || 0);
9110
+ mergeSelection.filter('.resizable-xy').select('rect.top-left-resizer').style('pointer-events', d => d.getResizableXY() ? 'initial' : 'none').attr('x', d => -d.getResizerXY().outerMargin).attr('y', d => -d.getResizerXY().outerMargin).attr('width', d => d.getResizerXY().thickness).attr('height', d => d.getResizerXY().thickness).attr('fill', d => d.getResizerXY().getLook(d).fillColor || 'transparent').attr('stroke', d => d.getResizerXY().getLook(d).borderColor || 'transparent').attr('stroke-width', d => d.getResizerXY().getLook(d).borderThickness || 0);
9111
+ mergeSelection.filter('.resizable-xy').select('rect.top-right-resizer').style('pointer-events', d => d.getResizableXY() ? 'initial' : 'none').attr('x', d => d.width - d.getResizerXY().thickness + d.getResizerXY().outerMargin).attr('y', d => -d.getResizerXY().outerMargin).attr('width', d => d.getResizerXY().thickness).attr('height', d => d.getResizerXY().thickness).attr('fill', d => d.getResizerXY().getLook(d).fillColor || 'transparent').attr('stroke', d => d.getResizerXY().getLook(d).borderColor || 'transparent').attr('stroke-width', d => d.getResizerXY().getLook(d).borderThickness || 0);
9112
+ mergeSelection.filter('.resizable-xy').select('rect.bottom-left-resizer').style('pointer-events', d => d.getResizableXY() ? 'initial' : 'none').attr('x', d => -d.getResizerXY().outerMargin).attr('y', d => d.height - d.getResizerXY().thickness + d.getResizerXY().outerMargin).attr('width', d => d.getResizerXY().thickness).attr('height', d => d.getResizerXY().thickness).attr('fill', d => d.getResizerXY().getLook(d).fillColor || 'transparent').attr('stroke', d => d.getResizerXY().getLook(d).borderColor || 'transparent').attr('stroke-width', d => d.getResizerXY().getLook(d).borderThickness || 0);
9113
+ mergeSelection.filter('.resizable-xy').select('rect.bottom-right-resizer').style('pointer-events', d => d.getResizableXY() ? 'initial' : 'none').attr('x', d => d.width - d.getResizerXY().thickness + d.getResizerXY().outerMargin).attr('y', d => d.height - d.getResizerXY().thickness + d.getResizerXY().outerMargin).attr('width', d => d.getResizerXY().thickness).attr('height', d => d.getResizerXY().thickness).attr('fill', d => d.getResizerXY().getLook(d).fillColor || 'transparent').attr('stroke', d => d.getResizerXY().getLook(d).borderColor || 'transparent').attr('stroke-width', d => d.getResizerXY().getLook(d).borderThickness || 0);
8399
9114
  }
8400
9115
  updatePortsInView(...ids) {
8401
9116
  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);
@@ -8750,9 +9465,9 @@ class DiagramCanvas {
8750
9465
  }
8751
9466
  this.secondaryButton = false;
8752
9467
  }));
8753
- enterSelection.append('text');
9468
+ enterSelection.append('text').style('user-select', 'none').style('font-kerning', 'none').style('white-space', 'nowrap');
8754
9469
  enterSelection.append('rect');
8755
- mergeSelection.attr('x', 0).attr('y', 0).attr('width', d => d.width).attr('height', d => d.height).attr('transform', d => `translate(${d.coords[0]},${d.coords[1]}) rotate(${d.orientation} ${d.width / 2} ${d.height / 2})`).attr('opacity', d => d.removed ? 0.5 : 1).select('text').attr('x', d => d.horizontalAlign === HorizontalAlign.Center ? d.width / 2 : d.horizontalAlign === HorizontalAlign.Right ? d.width : 0).attr('text-anchor', d => d.horizontalAlign === HorizontalAlign.Center ? 'middle' : d.horizontalAlign === HorizontalAlign.Right ? 'end' : 'start').attr('y', d => d.verticalAlign === VerticalAlign.Center ? d.height / 2 : d.verticalAlign === VerticalAlign.Bottom ? d.height : 0).attr('dominant-baseline', d => d.verticalAlign === VerticalAlign.Center ? 'middle' : d.verticalAlign === VerticalAlign.Bottom ? 'auto' : 'hanging').attr('font-size', d => d.fontSize).attr('font-family', d => d.fontFamily || "'Wonder Unit Sans', sans-serif").attr('font-weight', d => d.highlighted ? 600 : 400).attr('fill', d => d.selected ? d.selectedColor || '#000000' : d.color || '#000000').each(d => {
9470
+ mergeSelection.attr('x', 0).attr('y', 0).attr('width', d => d.width).attr('height', d => d.height).attr('transform', d => `translate(${d.coords[0]},${d.coords[1]}) rotate(${d.orientation} ${d.width / 2} ${d.height / 2})`).attr('opacity', d => d.removed ? 0.5 : 1).select('text').attr('x', d => d.horizontalAlign === HorizontalAlign.Center ? d.width / 2 : d.horizontalAlign === HorizontalAlign.Right ? d.width : 0).attr('text-anchor', d => d.horizontalAlign === HorizontalAlign.Center ? 'middle' : d.horizontalAlign === HorizontalAlign.Right ? 'end' : 'start').attr('y', d => d.verticalAlign === VerticalAlign.Center ? d.height / 2 : d.verticalAlign === VerticalAlign.Bottom ? d.height : 0).attr('dominant-baseline', d => d.verticalAlign === VerticalAlign.Center ? 'middle' : d.verticalAlign === VerticalAlign.Bottom ? 'auto' : 'hanging').attr('font-size', d => d.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize).attr('font-family', d => d.look.fontFamily || "'Wonder Unit Sans', sans-serif").attr('font-weight', d => d.look.fontWeight || DIAGRAM_FIELD_DEFAULTS.look.fontWeight).attr('fill', d => d.look.fontColor || DIAGRAM_FIELD_DEFAULTS.look.fontColor).style('font-kerning', 'none').each(d => {
8756
9471
  this.setFieldTextAndWrap(d);
8757
9472
  });
8758
9473
  mergeSelection
@@ -8767,7 +9482,7 @@ class DiagramCanvas {
8767
9482
  updateSelection = updateSelection.filter(d => ids.includes(d.id));
8768
9483
  }
8769
9484
  const mergeSelection = enterSelection.merge(updateSelection);
8770
- mergeSelection.attr('width', d => d.width).attr('height', d => d.height).attr('transform', d => `translate(${d.coords[0]},${d.coords[1]})`).html(d => d.html);
9485
+ mergeSelection.attr('width', d => d.width).attr('height', d => d.height).attr('transform', d => `translate(${d.coords[0]},${d.coords[1]})`).html(d => d.svg);
8771
9486
  exitSelection.remove();
8772
9487
  enterSelection.on(Events.ContextMenu, (event, d) => {
8773
9488
  if (this.dragging) {
@@ -8810,7 +9525,7 @@ class DiagramCanvas {
8810
9525
  updateSelection = updateSelection.filter(d => ids.includes(d.id));
8811
9526
  }
8812
9527
  const mergeSelection = enterSelection.merge(updateSelection);
8813
- mergeSelection.attr('width', d => d.width).attr('height', d => d.height).attr('transform', d => `translate(${d.coords[0]},${d.coords[1]})`).html(d => d.html);
9528
+ mergeSelection.attr('width', d => d.width).attr('height', d => d.height).attr('transform', d => `translate(${d.coords[0]},${d.coords[1]})`).html(d => d.svg);
8814
9529
  exitSelection.remove();
8815
9530
  enterSelection.on(Events.MouseOver, (_event, d) => {
8816
9531
  if (!this.dragging) {
@@ -8911,6 +9626,7 @@ class DiagramCanvas {
8911
9626
  const pathSelection = connectionSelection.select('path');
8912
9627
  const pathNode = pathSelection.node();
8913
9628
  const labelConfiguration = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS), connection.type.label);
9629
+ labelConfiguration.look = Object.assign(Object.assign({}, DIAGRAM_FIELD_DEFAULTS.look), labelConfiguration.look);
8914
9630
  if (pathNode) {
8915
9631
  const pathLength = pathNode.getTotalLength();
8916
9632
  let startLabelShiftX = 0;
@@ -8919,7 +9635,7 @@ class DiagramCanvas {
8919
9635
  let middleLabelShiftY = 0;
8920
9636
  let endLabelShiftX = 0;
8921
9637
  let endLabelShiftY = 0;
8922
- if (labelConfiguration.backgroundColor === 'transparent') {
9638
+ if (labelConfiguration.look.fillColor === 'transparent') {
8923
9639
  // background color is transparent / not set, so we find an alternative position for the label
8924
9640
  const deltaX = connection.endCoords[0] - connection.startCoords[0];
8925
9641
  const deltaY = connection.endCoords[1] - connection.startCoords[1];
@@ -8974,7 +9690,7 @@ class DiagramCanvas {
8974
9690
  }
8975
9691
  }
8976
9692
  // bind start labels
8977
- connectionSelection.select('g.diagram-connection-start-label text').attr('x', 0).attr('y', labelConfiguration.fontSize / 3).attr('text-anchor', 'middle').attr('font-family', labelConfiguration.fontFamily).attr('font-size', labelConfiguration.fontSize).attr('fill', connection.selected ? labelConfiguration.selectedColor : labelConfiguration.color).style('font-kerning', 'none').text(connection.startLabel);
9693
+ connectionSelection.select('g.diagram-connection-start-label text').attr('x', 0).attr('y', (labelConfiguration.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize) / 3).attr('text-anchor', 'middle').attr('font-family', labelConfiguration.look.fontFamily || DIAGRAM_FIELD_DEFAULTS.look.fontFamily).attr('font-size', labelConfiguration.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize).attr('fill', labelConfiguration.look.fontColor || DIAGRAM_FIELD_DEFAULTS.look.fontColor).text(connection.startLabel);
8978
9694
  const startLabelBoundingRect = (_a = connectionSelection.select('g.diagram-connection-start-label text').node()) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
8979
9695
  if (startLabelBoundingRect) {
8980
9696
  // don't create space for the label if the label is empty
@@ -8997,22 +9713,22 @@ class DiagramCanvas {
8997
9713
  default:
8998
9714
  pathStartLabelPoint = pathNode.getPointAtLength(Math.max(getLeftMargin(labelConfiguration) + boundingWidth / 2, getRightMargin(labelConfiguration) + boundingWidth / 2, getTopMargin(labelConfiguration) + boundingHeight / 2, getBottomMargin(labelConfiguration) + boundingHeight / 2));
8999
9715
  }
9000
- connectionSelection.select('g.diagram-connection-start-label path').attr('d', pillPath(-boundingWidth / 2, -boundingHeight / 2, boundingWidth, boundingHeight)).attr('fill', labelConfiguration.backgroundColor).attr('stroke', 'none');
9716
+ connectionSelection.select('g.diagram-connection-start-label path').attr('d', pillPath(-boundingWidth / 2, -boundingHeight / 2, boundingWidth, boundingHeight)).attr('fill', labelConfiguration.look.fillColor || DIAGRAM_FIELD_DEFAULTS.look.fillColor).attr('stroke', 'none');
9001
9717
  connectionSelection.select('g.diagram-connection-start-label').attr('transform', `translate(${pathStartLabelPoint.x + startLabelShiftX * boundingWidth},${pathStartLabelPoint.y + startLabelShiftY * boundingHeight})`);
9002
9718
  }
9003
9719
  // bind middle labels
9004
- connectionSelection.select('g.diagram-connection-middle-label text').attr('x', 0).attr('y', labelConfiguration.fontSize / 3).attr('text-anchor', 'middle').attr('font-family', labelConfiguration.fontFamily).attr('font-size', labelConfiguration.fontSize).attr('fill', connection.selected ? labelConfiguration.selectedColor : labelConfiguration.color).style('font-kerning', 'none').text(connection.middleLabel);
9720
+ connectionSelection.select('g.diagram-connection-middle-label text').attr('x', 0).attr('y', (labelConfiguration.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize) / 3).attr('text-anchor', 'middle').attr('font-family', labelConfiguration.look.fontFamily || DIAGRAM_FIELD_DEFAULTS.look.fontFamily).attr('font-size', labelConfiguration.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize).attr('fill', labelConfiguration.look.fontColor || DIAGRAM_FIELD_DEFAULTS.look.fillColor).style('font-kerning', 'none').text(connection.middleLabel);
9005
9721
  const middleLabelBoundingRect = (_b = connectionSelection.select('g.diagram-connection-middle-label text').node()) === null || _b === void 0 ? void 0 : _b.getBoundingClientRect();
9006
9722
  if (middleLabelBoundingRect) {
9007
9723
  // don't create space for the label if the label is empty
9008
9724
  const boundingWidth = !connection.middleLabel ? 0 : middleLabelBoundingRect.width / this.zoomTransform.k + getLeftPadding$1(labelConfiguration) + getRightPadding$1(labelConfiguration);
9009
9725
  const boundingHeight = !connection.middleLabel ? 0 : middleLabelBoundingRect.height / this.zoomTransform.k + getTopPadding$1(labelConfiguration) + getBottomPadding$1(labelConfiguration);
9010
9726
  const pathMiddleLabelPoint = pathNode.getPointAtLength(pathLength / 2);
9011
- connectionSelection.select('g.diagram-connection-middle-label path').attr('d', pillPath(-boundingWidth / 2, -boundingHeight / 2, boundingWidth, boundingHeight)).attr('fill', labelConfiguration.backgroundColor).attr('stroke', 'none');
9727
+ connectionSelection.select('g.diagram-connection-middle-label path').attr('d', pillPath(-boundingWidth / 2, -boundingHeight / 2, boundingWidth, boundingHeight)).attr('fill', labelConfiguration.look.fillColor || DIAGRAM_FIELD_DEFAULTS.look.fillColor).attr('stroke', 'none');
9012
9728
  connectionSelection.select('g.diagram-connection-middle-label').attr('transform', `translate(${pathMiddleLabelPoint.x + middleLabelShiftX * boundingWidth},${pathMiddleLabelPoint.y + middleLabelShiftY * boundingHeight})`);
9013
9729
  }
9014
9730
  // bind end labels
9015
- connectionSelection.select('g.diagram-connection-end-label text').attr('x', 0).attr('y', labelConfiguration.fontSize / 3).attr('text-anchor', 'middle').attr('font-family', labelConfiguration.fontFamily).attr('font-size', labelConfiguration.fontSize).attr('fill', connection.selected ? labelConfiguration.selectedColor : labelConfiguration.color).style('font-kerning', 'none').text(connection.endLabel);
9731
+ connectionSelection.select('g.diagram-connection-end-label text').attr('x', 0).attr('y', (labelConfiguration.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize) / 3).attr('text-anchor', 'middle').attr('font-family', labelConfiguration.look.fontFamily || DIAGRAM_FIELD_DEFAULTS.look.fontFamily).attr('font-size', labelConfiguration.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize).attr('fill', labelConfiguration.look.fontColor || DIAGRAM_FIELD_DEFAULTS.look.fontColor).style('font-kerning', 'none').text(connection.endLabel);
9016
9732
  const endLabelBoundingRect = (_c = connectionSelection.select('g.diagram-connection-end-label text').node()) === null || _c === void 0 ? void 0 : _c.getBoundingClientRect();
9017
9733
  if (endLabelBoundingRect) {
9018
9734
  // don't create space for the label if the label is empty
@@ -9035,7 +9751,7 @@ class DiagramCanvas {
9035
9751
  default:
9036
9752
  pathEndLabelPoint = pathNode.getPointAtLength(pathLength - Math.max(getLeftMargin(labelConfiguration) + boundingWidth / 2, getRightMargin(labelConfiguration) + boundingWidth / 2, getTopMargin(labelConfiguration) + boundingHeight / 2, getBottomMargin(labelConfiguration) + boundingHeight / 2));
9037
9753
  }
9038
- connectionSelection.select('g.diagram-connection-end-label path').attr('d', pillPath(-boundingWidth / 2, -boundingHeight / 2, boundingWidth, boundingHeight)).attr('fill', labelConfiguration.backgroundColor).attr('stroke', 'none');
9754
+ connectionSelection.select('g.diagram-connection-end-label path').attr('d', pillPath(-boundingWidth / 2, -boundingHeight / 2, boundingWidth, boundingHeight)).attr('fill', labelConfiguration.look.fillColor || DIAGRAM_FIELD_DEFAULTS.look.fillColor).attr('stroke', 'none');
9039
9755
  connectionSelection.select('g.diagram-connection-end-label').attr('transform', `translate(${pathEndLabelPoint.x + endLabelShiftX * boundingWidth},${pathEndLabelPoint.y + endLabelShiftY * boundingHeight})`);
9040
9756
  }
9041
9757
  }
@@ -9079,9 +9795,13 @@ class DiagramCanvas {
9079
9795
  const fieldDimensions = this.minimumSizeOfField(field);
9080
9796
  let stretchX = fieldDimensions[0] + getLeftMargin(field.rootElement.type.label) + getRightMargin(field.rootElement.type.label) - field.rootElement.width;
9081
9797
  let stretchY = fieldDimensions[1] + getTopMargin(field.rootElement.type.label) + getBottomMargin(field.rootElement.type.label) - field.rootElement.height;
9082
- if (this.snapToGrid) {
9083
- stretchX = Math.ceil(stretchX / this.gridSize) * this.gridSize;
9084
- stretchY = Math.ceil(stretchY / this.gridSize) * this.gridSize;
9798
+ const spacingX = getGridSpacingX(this.gridConfig);
9799
+ const spacingY = getGridSpacingY(this.gridConfig);
9800
+ if (this.gridConfig.snap && spacingX !== 0) {
9801
+ stretchX = Math.ceil(stretchX / spacingX) * spacingX;
9802
+ }
9803
+ if (this.gridConfig.snap && spacingY !== 0) {
9804
+ stretchY = Math.ceil(stretchY / spacingY) * spacingY;
9085
9805
  }
9086
9806
  // ensure node is not stretched under its minimum dimensions
9087
9807
  if (field.rootElement.width + stretchX < field.rootElement.type.minWidth) {
@@ -9119,9 +9839,13 @@ class DiagramCanvas {
9119
9839
  const type = field.rootElement.type;
9120
9840
  let stretchX = fieldDimensions[0] + getLeftMargin(type === null || type === void 0 ? void 0 : type.label) + getRightMargin(type === null || type === void 0 ? void 0 : type.label) - field.rootElement.width;
9121
9841
  let stretchY = fieldDimensions[1] + getTopMargin(type === null || type === void 0 ? void 0 : type.label) + getBottomMargin(type === null || type === void 0 ? void 0 : type.label) - field.rootElement.height;
9122
- if (this.snapToGrid) {
9123
- stretchX = Math.ceil(stretchX / this.gridSize) * this.gridSize;
9124
- stretchY = Math.ceil(stretchY / this.gridSize) * this.gridSize;
9842
+ const spacingX = getGridSpacingX(this.gridConfig);
9843
+ const spacingY = getGridSpacingY(this.gridConfig);
9844
+ if (this.gridConfig.snap && spacingX !== 0) {
9845
+ stretchX = Math.ceil(stretchX / spacingX) * spacingX;
9846
+ }
9847
+ if (this.gridConfig.snap && spacingY !== 0) {
9848
+ stretchY = Math.ceil(stretchY / spacingY) * spacingY;
9125
9849
  }
9126
9850
  // ensure section is not stretched under its minimum dimensions
9127
9851
  if (field.rootElement.width + stretchX < (field.rootElement.getMinWidth() || 0)) {
@@ -9171,13 +9895,13 @@ class DiagramCanvas {
9171
9895
  return d3.select(this.diagramRoot);
9172
9896
  }
9173
9897
  selectSVGElement() {
9174
- return d3.select(this.diagramRoot).select('svg');
9898
+ return this.selectRoot().select('svg');
9175
9899
  }
9176
9900
  selectCanvasView() {
9177
9901
  return this.selectSVGElement().select(`.daga-canvas-view`);
9178
9902
  }
9179
9903
  selectCanvasElements() {
9180
- return this.selectSVGElement().select(`.daga-canvas-elements`);
9904
+ return this.selectCanvasView().select(`.daga-canvas-elements`);
9181
9905
  }
9182
9906
  // User actions
9183
9907
  startConnection(port) {
@@ -9289,7 +10013,7 @@ class DiagramCanvas {
9289
10013
  openTextInput(id) {
9290
10014
  const field = this.model.fields.get(id);
9291
10015
  if (field) {
9292
- this.createInputField(field.text, field.coords, field.width, field.height, field.fontSize, field.fontFamily || DIAGRAM_FIELD_DEFAULTS.fontFamily, field.orientation, field.multiline, () => {
10016
+ this.createInputField(field.text, field.coords, field.width, field.height, field.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize, field.look.fontFamily || DIAGRAM_FIELD_DEFAULTS.look.fontFamily, field.orientation, field.multiline, () => {
9293
10017
  // (_text)
9294
10018
  /*
9295
10019
  Empty for now
@@ -9326,7 +10050,7 @@ class DiagramCanvas {
9326
10050
  }
9327
10051
  }).on(Events.KeyUp, event => {
9328
10052
  event.stopPropagation();
9329
- }).on(Events.Input, _event => {
10053
+ }).on(Events.Input, () => {
9330
10054
  const value = inputField.property('value');
9331
10055
  inputField.attr('cols', numberOfColumns(value) + 1);
9332
10056
  inputField.attr('rows', numberOfRows(value) + 1);
@@ -9415,7 +10139,7 @@ class DiagramCanvas {
9415
10139
  const lines = text.split('\n');
9416
10140
  textSelection.html('');
9417
10141
  for (let i = 0; i < lines.length; ++i) {
9418
- textSelection.append('tspan').attr('x', field.horizontalAlign === HorizontalAlign.Center ? field.width / 2 : field.horizontalAlign === HorizontalAlign.Right ? field.width : 0).attr('y', field.verticalAlign === VerticalAlign.Center ? (i + 0.5 - lines.length / 2) * field.fontSize + field.height / 2 : field.verticalAlign === VerticalAlign.Bottom ? field.height - (lines.length - i - 1) * field.fontSize : i * field.fontSize).text(lines[i]);
10142
+ textSelection.append('tspan').attr('x', field.horizontalAlign === HorizontalAlign.Center ? field.width / 2 : field.horizontalAlign === HorizontalAlign.Right ? field.width : 0).attr('y', field.verticalAlign === VerticalAlign.Center ? (i + 0.5 - lines.length / 2) * (field.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize) + field.height / 2 : field.verticalAlign === VerticalAlign.Bottom ? field.height - (lines.length - i - 1) * (field.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize) : i * (field.look.fontSize || DIAGRAM_FIELD_DEFAULTS.look.fontSize)).text(lines[i]);
9419
10143
  }
9420
10144
  }
9421
10145
  /**
@@ -9455,12 +10179,12 @@ class DiagramCanvas {
9455
10179
  * Method to call to finish the moving of a node triggered by a user drag event.
9456
10180
  */
9457
10181
  finishMovingNode(event, d) {
9458
- var _a, _b, _c;
10182
+ var _a, _b, _c, _d;
9459
10183
  if (this.canUserPerformAction(DiagramActions.MoveNode) && !d.removed) {
9460
10184
  // prevent drag behavior if mouse hasn't moved
9461
10185
  if (this.draggingFrom[0] !== event.x || this.draggingFrom[1] !== event.y) {
9462
10186
  let newNodeCoords = [event.x - d.width / 2, event.y - d.height / 2];
9463
- if (this.snapToGrid) {
10187
+ if ((_a = this.gridConfig) === null || _a === void 0 ? void 0 : _a.snap) {
9464
10188
  newNodeCoords = this.getClosestGridPoint([newNodeCoords[0] - d.type.snapToGridOffset[0], newNodeCoords[1] - d.type.snapToGridOffset[1]]);
9465
10189
  newNodeCoords[0] += d.type.snapToGridOffset[0];
9466
10190
  newNodeCoords[1] += d.type.snapToGridOffset[1];
@@ -9487,8 +10211,8 @@ class DiagramCanvas {
9487
10211
  if (droppedOn !== d.parent && (d.type.canBeParentless || droppedOn !== undefined)) {
9488
10212
  const ancestorOfDroppedOn = droppedOn === null || droppedOn === void 0 ? void 0 : droppedOn.getLastAncestor();
9489
10213
  const fromChildGeometry = this.currentAction.from;
9490
- const setParentAction = new SetParentAction(this, d.id, (_a = d.parent) === null || _a === void 0 ? void 0 : _a.id, droppedOn === null || droppedOn === void 0 ? void 0 : droppedOn.id, fromChildGeometry, d.getGeometry(), ancestorOfDroppedOn === null || ancestorOfDroppedOn === void 0 ? void 0 : ancestorOfDroppedOn.id, ancestorOfDroppedOn === null || ancestorOfDroppedOn === void 0 ? void 0 : ancestorOfDroppedOn.getGeometry(d.id), ancestorOfDroppedOn === null || ancestorOfDroppedOn === void 0 ? void 0 : ancestorOfDroppedOn.getGeometry(d.id));
9491
- (_b = d.parent) === null || _b === void 0 ? void 0 : _b.removeChild(d);
10214
+ const setParentAction = new SetParentAction(this, d.id, (_b = d.parent) === null || _b === void 0 ? void 0 : _b.id, droppedOn === null || droppedOn === void 0 ? void 0 : droppedOn.id, fromChildGeometry, d.getGeometry(), ancestorOfDroppedOn === null || ancestorOfDroppedOn === void 0 ? void 0 : ancestorOfDroppedOn.id, ancestorOfDroppedOn === null || ancestorOfDroppedOn === void 0 ? void 0 : ancestorOfDroppedOn.getGeometry(d.id), ancestorOfDroppedOn === null || ancestorOfDroppedOn === void 0 ? void 0 : ancestorOfDroppedOn.getGeometry(d.id));
10215
+ (_c = d.parent) === null || _c === void 0 ? void 0 : _c.removeChild(d);
9492
10216
  if (droppedOn !== undefined) {
9493
10217
  droppedOn.addChild(d);
9494
10218
  }
@@ -9499,7 +10223,7 @@ class DiagramCanvas {
9499
10223
  const ancestorOfNode = d === null || d === void 0 ? void 0 : d.getLastAncestor();
9500
10224
  this.currentAction.ancestorId = ancestorOfNode === null || ancestorOfNode === void 0 ? void 0 : ancestorOfNode.id;
9501
10225
  this.currentAction.fromAncestorGeometry = ancestorOfNode === null || ancestorOfNode === void 0 ? void 0 : ancestorOfNode.getGeometry(d.id);
9502
- (_c = d.parent) === null || _c === void 0 ? void 0 : _c.fitToChild(d);
10226
+ (_d = d.parent) === null || _d === void 0 ? void 0 : _d.fitToChild(d);
9503
10227
  this.currentAction.to = d.getGeometry(d.id);
9504
10228
  this.currentAction.toAncestorGeometry = ancestorOfNode === null || ancestorOfNode === void 0 ? void 0 : ancestorOfNode.getGeometry(d.id);
9505
10229
  }
@@ -9910,7 +10634,7 @@ class AdjacencyLayout {
9910
10634
  this.gapSize = gapSize;
9911
10635
  }
9912
10636
  apply(model) {
9913
- var _a;
10637
+ var _a, _b, _c, _d;
9914
10638
  if (model.nodes.length === 0) {
9915
10639
  // nothing to arrange...
9916
10640
  return model;
@@ -9924,12 +10648,13 @@ class AdjacencyLayout {
9924
10648
  // place nodes according to arrangement
9925
10649
  const maximumWidth = Math.max(...model.nodes.map(n => n.width));
9926
10650
  const maximumHeight = Math.max(...model.nodes.map(n => n.height));
9927
- const gapSize = this.gapSize !== undefined ? this.gapSize : (((_a = model.canvas) === null || _a === void 0 ? void 0 : _a.gridSize) || 0) * 2;
10651
+ const gapSizeX = this.gapSize !== undefined ? this.gapSize : ((_a = model.canvas) === null || _a === void 0 ? void 0 : _a.gridConfig) ? getGridSpacingX((_b = model.canvas) === null || _b === void 0 ? void 0 : _b.gridConfig) * 2 : 0;
10652
+ const gapSizeY = this.gapSize !== undefined ? this.gapSize : ((_c = model.canvas) === null || _c === void 0 ? void 0 : _c.gridConfig) ? getGridSpacingY((_d = model.canvas) === null || _d === void 0 ? void 0 : _d.gridConfig) * 2 : 0;
9928
10653
  for (let y = nodeArrangement.minY(); y <= nodeArrangement.maxY(); ++y) {
9929
10654
  for (let x = nodeArrangement.minX(); x <= nodeArrangement.maxX(); ++x) {
9930
10655
  const node = nodeArrangement.get([x, y]);
9931
10656
  if (node !== undefined) {
9932
- node.move([x * (maximumWidth + gapSize), y * (maximumHeight + gapSize)]);
10657
+ node.move([x * (maximumWidth + gapSizeX), y * (maximumHeight + gapSizeY)]);
9933
10658
  }
9934
10659
  }
9935
10660
  }
@@ -9956,7 +10681,7 @@ class BreadthAdjacencyLayout {
9956
10681
  this.gapSize = gapSize;
9957
10682
  }
9958
10683
  apply(model) {
9959
- var _a;
10684
+ var _a, _b, _c, _d;
9960
10685
  if (model.nodes.length === 0) {
9961
10686
  // nothing to arrange...
9962
10687
  return model;
@@ -9992,12 +10717,13 @@ class BreadthAdjacencyLayout {
9992
10717
  // place nodes according to arrangement
9993
10718
  const maximumWidth = Math.max(...model.nodes.map(n => n.width));
9994
10719
  const maximumHeight = Math.max(...model.nodes.map(n => n.height));
9995
- const gapSize = this.gapSize !== undefined ? this.gapSize : (((_a = model.canvas) === null || _a === void 0 ? void 0 : _a.gridSize) || 0) * 2;
10720
+ const gapSizeX = this.gapSize !== undefined ? this.gapSize : ((_a = model.canvas) === null || _a === void 0 ? void 0 : _a.gridConfig) ? getGridSpacingX((_b = model.canvas) === null || _b === void 0 ? void 0 : _b.gridConfig) * 2 : 0;
10721
+ const gapSizeY = this.gapSize !== undefined ? this.gapSize : ((_c = model.canvas) === null || _c === void 0 ? void 0 : _c.gridConfig) ? getGridSpacingY((_d = model.canvas) === null || _d === void 0 ? void 0 : _d.gridConfig) * 2 : 0;
9996
10722
  for (let y = nodeArrangement.minY(); y <= nodeArrangement.maxY(); ++y) {
9997
10723
  for (let x = nodeArrangement.minX(); x <= nodeArrangement.maxX(); ++x) {
9998
10724
  const node = nodeArrangement.get([x, y]);
9999
10725
  if (node !== undefined) {
10000
- node.move([x * (maximumWidth + gapSize), y * (maximumHeight + gapSize)]);
10726
+ node.move([x * (maximumWidth + gapSizeX), y * (maximumHeight + gapSizeY)]);
10001
10727
  }
10002
10728
  }
10003
10729
  }
@@ -10014,12 +10740,13 @@ class BreadthLayout {
10014
10740
  this.gapSize = gapSize;
10015
10741
  }
10016
10742
  apply(model) {
10017
- var _a;
10743
+ var _a, _b, _c, _d;
10018
10744
  if (model.nodes.length === 0) {
10019
10745
  // nothing to arrange...
10020
10746
  return model;
10021
10747
  }
10022
- const gapSize = this.gapSize !== undefined ? this.gapSize : (((_a = model.canvas) === null || _a === void 0 ? void 0 : _a.gridSize) || 0) * 2;
10748
+ const gapSizeX = this.gapSize !== undefined ? this.gapSize : ((_a = model.canvas) === null || _a === void 0 ? void 0 : _a.gridConfig) ? getGridSpacingX((_b = model.canvas) === null || _b === void 0 ? void 0 : _b.gridConfig) * 2 : 0;
10749
+ const gapSizeY = this.gapSize !== undefined ? this.gapSize : ((_c = model.canvas) === null || _c === void 0 ? void 0 : _c.gridConfig) ? getGridSpacingY((_d = model.canvas) === null || _d === void 0 ? void 0 : _d.gridConfig) * 2 : 0;
10023
10750
  let nodesToBeArranged = model.nodes.filter(n => !n.parent);
10024
10751
  // Arrange nodes by a breadth first search
10025
10752
  const firstNode = nodesToBeArranged[0];
@@ -10058,10 +10785,10 @@ class BreadthLayout {
10058
10785
  let heightAccumulator = 0;
10059
10786
  for (const node of nodeArrangementRow) {
10060
10787
  node.move([widthAccumulator, heightAccumulator]);
10061
- heightAccumulator += gapSize + node.height;
10788
+ heightAccumulator += gapSizeY + node.height;
10062
10789
  }
10063
10790
  const maximumWidth = Math.max(...nodeArrangementRow.map(n => n.width));
10064
- widthAccumulator += gapSize + maximumWidth;
10791
+ widthAccumulator += gapSizeX + maximumWidth;
10065
10792
  }
10066
10793
  for (const connection of model.connections) {
10067
10794
  connection.tighten();
@@ -10079,14 +10806,16 @@ class ForceLayout {
10079
10806
  this.gapSize = gapSize;
10080
10807
  }
10081
10808
  apply(model) {
10082
- var _a;
10809
+ var _a, _b, _c, _d;
10083
10810
  if (model.nodes.length === 0) {
10084
10811
  // nothing to arrange...
10085
10812
  return model;
10086
10813
  }
10087
10814
  // as a starting point, we apply a simple layout
10088
10815
  new BreadthLayout(this.gapSize).apply(model);
10089
- const gapSize = this.gapSize !== undefined ? this.gapSize : (((_a = model.canvas) === null || _a === void 0 ? void 0 : _a.gridSize) || 0) * 2;
10816
+ const gapSizeX = this.gapSize !== undefined ? this.gapSize : ((_a = model.canvas) === null || _a === void 0 ? void 0 : _a.gridConfig) ? getGridSpacingX((_b = model.canvas) === null || _b === void 0 ? void 0 : _b.gridConfig) * 2 : 0;
10817
+ const gapSizeY = this.gapSize !== undefined ? this.gapSize : ((_c = model.canvas) === null || _c === void 0 ? void 0 : _c.gridConfig) ? getGridSpacingY((_d = model.canvas) === null || _d === void 0 ? void 0 : _d.gridConfig) * 2 : 0;
10818
+ const gapSize = Math.max(gapSizeX, gapSizeY);
10090
10819
  const coolingFactor = 0.99;
10091
10820
  const minimumTemperature = 1;
10092
10821
  const attractionFactor = 0.1;
@@ -10155,7 +10884,7 @@ class ForceLayout {
10155
10884
  }
10156
10885
  }
10157
10886
  }
10158
- if (model.canvas && model.canvas.snapToGrid) {
10887
+ if (model.canvas && model.canvas.gridConfig.snap) {
10159
10888
  for (const node of model.nodes) {
10160
10889
  const snappedCoords = model.canvas.getClosestGridPoint([node.coords[0] - node.type.snapToGridOffset[0], node.coords[1] - node.type.snapToGridOffset[1]]);
10161
10890
  snappedCoords[0] += node.type.snapToGridOffset[0];
@@ -10179,18 +10908,18 @@ class HorizontalLayout {
10179
10908
  this.gapSize = gapSize;
10180
10909
  }
10181
10910
  apply(model) {
10182
- var _a;
10911
+ var _a, _b;
10183
10912
  if (model.nodes.length === 0) {
10184
10913
  // nothing to arrange...
10185
10914
  return model;
10186
10915
  }
10187
- const gapSize = this.gapSize !== undefined ? this.gapSize : (((_a = model.canvas) === null || _a === void 0 ? void 0 : _a.gridSize) || 0) * 2;
10916
+ const gapSizeX = this.gapSize !== undefined ? this.gapSize : ((_a = model.canvas) === null || _a === void 0 ? void 0 : _a.gridConfig) ? getGridSpacingX((_b = model.canvas) === null || _b === void 0 ? void 0 : _b.gridConfig) * 2 : 0;
10188
10917
  const nodesToBeArranged = model.nodes.filter(n => !n.parent);
10189
10918
  nodesToBeArranged.sort((a, b) => b.type.priority - a.type.priority);
10190
10919
  let widthAccumulator = 0;
10191
10920
  for (const node of nodesToBeArranged) {
10192
10921
  node.move([widthAccumulator, 0]);
10193
- widthAccumulator += node.width + gapSize;
10922
+ widthAccumulator += node.width + gapSizeX;
10194
10923
  }
10195
10924
  return model;
10196
10925
  }
@@ -10205,7 +10934,7 @@ class PriorityLayout {
10205
10934
  this.gapSize = gapSize;
10206
10935
  }
10207
10936
  apply(model) {
10208
- var _a;
10937
+ var _a, _b, _c, _d;
10209
10938
  if (model.nodes.length === 0) {
10210
10939
  // nothing to arrange...
10211
10940
  return model;
@@ -10217,7 +10946,8 @@ class PriorityLayout {
10217
10946
  new BreadthLayout(this.gapSize).apply(model);
10218
10947
  return model;
10219
10948
  }
10220
- const gapSize = this.gapSize !== undefined ? this.gapSize : (((_a = model.canvas) === null || _a === void 0 ? void 0 : _a.gridSize) || 0) * 2;
10949
+ const gapSizeX = this.gapSize !== undefined ? this.gapSize : ((_a = model.canvas) === null || _a === void 0 ? void 0 : _a.gridConfig) ? getGridSpacingX((_b = model.canvas) === null || _b === void 0 ? void 0 : _b.gridConfig) * 2 : 0;
10950
+ const gapSizeY = this.gapSize !== undefined ? this.gapSize : ((_c = model.canvas) === null || _c === void 0 ? void 0 : _c.gridConfig) ? getGridSpacingY((_d = model.canvas) === null || _d === void 0 ? void 0 : _d.gridConfig) * 2 : 0;
10221
10951
  const nodesToBeArranged = model.nodes.filter(n => !n.parent);
10222
10952
  const nodeArrangement = [];
10223
10953
  const nodesWithMaximumPriorityToBeArranged = model.nodes.filter(n => !n.parent).filter(n => n.getPriority() >= maximumPriority);
@@ -10294,10 +11024,10 @@ class PriorityLayout {
10294
11024
  for (let j = 0; j < nodeArrangement[i].length; ++j) {
10295
11025
  const node = nodeArrangement[i][j];
10296
11026
  node.move([widthAccumulator, heightAccumulator]);
10297
- heightAccumulator += gapSize + node.height;
11027
+ heightAccumulator += gapSizeY + node.height;
10298
11028
  }
10299
11029
  const maximumWidth = Math.max(...nodeArrangement[i].map(n => n.width));
10300
- widthAccumulator += gapSize + maximumWidth;
11030
+ widthAccumulator += gapSizeX + maximumWidth;
10301
11031
  }
10302
11032
  for (const connection of model.connections) {
10303
11033
  connection.tighten();
@@ -10315,7 +11045,7 @@ class TreeLayout {
10315
11045
  this.gapSize = gapSize;
10316
11046
  }
10317
11047
  apply(model) {
10318
- var _a;
11048
+ var _a, _b, _c, _d;
10319
11049
  if (model.nodes.length === 0) {
10320
11050
  // nothing to arrange...
10321
11051
  return model;
@@ -10327,7 +11057,8 @@ class TreeLayout {
10327
11057
  new BreadthLayout(this.gapSize).apply(model);
10328
11058
  return model;
10329
11059
  }
10330
- const gapSize = this.gapSize !== undefined ? this.gapSize : (((_a = model.canvas) === null || _a === void 0 ? void 0 : _a.gridSize) || 0) * 2;
11060
+ const gapSizeX = this.gapSize !== undefined ? this.gapSize : ((_a = model.canvas) === null || _a === void 0 ? void 0 : _a.gridConfig) ? getGridSpacingX((_b = model.canvas) === null || _b === void 0 ? void 0 : _b.gridConfig) * 2 : 0;
11061
+ const gapSizeY = this.gapSize !== undefined ? this.gapSize : ((_c = model.canvas) === null || _c === void 0 ? void 0 : _c.gridConfig) ? getGridSpacingY((_d = model.canvas) === null || _d === void 0 ? void 0 : _d.gridConfig) * 2 : 0;
10331
11062
  const nodesToBeArranged = model.nodes.filter(n => !n.parent).sort((n1, n2) => n2.getPriority() - n1.getPriority());
10332
11063
  const branches = [];
10333
11064
  while (nodesToBeArranged.length > 0) {
@@ -10349,10 +11080,10 @@ class TreeLayout {
10349
11080
  for (let j = 0; j < branchArrangement[i].length; ++j) {
10350
11081
  const branch = branchArrangement[i][j];
10351
11082
  branch.node.move([widthAccumulator, heightAccumulator]);
10352
- heightAccumulator += (gapSize + maximumHeight) * branch.countBranchHeight();
11083
+ heightAccumulator += (gapSizeY + maximumHeight) * branch.countBranchHeight();
10353
11084
  }
10354
11085
  const maximumWidth = Math.max(...branchArrangement[i].map(b => b.node.width));
10355
- widthAccumulator += gapSize + maximumWidth;
11086
+ widthAccumulator += gapSizeX + maximumWidth;
10356
11087
  }
10357
11088
  for (const connection of model.connections) {
10358
11089
  connection.tighten();
@@ -10416,18 +11147,18 @@ class VerticalLayout {
10416
11147
  this.gapSize = gapSize;
10417
11148
  }
10418
11149
  apply(model) {
10419
- var _a;
11150
+ var _a, _b;
10420
11151
  if (model.nodes.length === 0) {
10421
11152
  // nothing to arrange...
10422
11153
  return model;
10423
11154
  }
10424
- const gapSize = this.gapSize !== undefined ? this.gapSize : (((_a = model.canvas) === null || _a === void 0 ? void 0 : _a.gridSize) || 0) * 2;
11155
+ const gapSizeY = this.gapSize !== undefined ? this.gapSize : ((_a = model.canvas) === null || _a === void 0 ? void 0 : _a.gridConfig) ? getGridSpacingY((_b = model.canvas) === null || _b === void 0 ? void 0 : _b.gridConfig) * 2 : 0;
10425
11156
  const nodesToBeArranged = model.nodes.filter(n => !n.parent);
10426
11157
  nodesToBeArranged.sort((a, b) => b.type.priority - a.type.priority);
10427
11158
  let heightAccumulator = 0;
10428
11159
  for (const node of nodesToBeArranged) {
10429
11160
  node.move([0, heightAccumulator]);
10430
- heightAccumulator += node.height + gapSize;
11161
+ heightAccumulator += node.height + gapSizeY;
10431
11162
  }
10432
11163
  return model;
10433
11164
  }