@joint/core 4.0.4 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +0 -8
  2. package/dist/geometry.js +4962 -6132
  3. package/dist/geometry.min.js +2 -2
  4. package/dist/joint.d.ts +328 -50
  5. package/dist/joint.js +34067 -37565
  6. package/dist/joint.min.js +2 -2
  7. package/dist/joint.nowrap.js +34067 -37565
  8. package/dist/joint.nowrap.min.js +2 -2
  9. package/dist/vectorizer.js +7288 -8907
  10. package/dist/vectorizer.min.js +2 -2
  11. package/dist/version.mjs +1 -1
  12. package/package.json +10 -15
  13. package/src/{linkTools → cellTools}/Button.mjs +8 -6
  14. package/src/{elementTools → cellTools}/Control.mjs +3 -3
  15. package/src/{linkTools → cellTools}/HoverConnect.mjs +1 -1
  16. package/src/dia/Cell.mjs +60 -33
  17. package/src/dia/CellView.mjs +75 -8
  18. package/src/dia/ElementView.mjs +13 -8
  19. package/src/dia/Graph.mjs +148 -40
  20. package/src/dia/HighlighterView.mjs +8 -4
  21. package/src/dia/LinkView.mjs +42 -3
  22. package/src/dia/Paper.mjs +84 -0
  23. package/src/dia/ToolView.mjs +29 -4
  24. package/src/dia/ToolsView.mjs +25 -10
  25. package/src/dia/attributes/connection.mjs +5 -0
  26. package/src/dia/attributes/defs.mjs +3 -0
  27. package/src/dia/attributes/eval.mjs +3 -3
  28. package/src/dia/attributes/index.mjs +3 -0
  29. package/src/dia/attributes/shape.mjs +4 -0
  30. package/src/dia/attributes/text.mjs +15 -5
  31. package/src/dia/ports.mjs +4 -0
  32. package/src/elementTools/HoverConnect.mjs +5 -5
  33. package/src/elementTools/index.mjs +5 -4
  34. package/src/g/rect.mjs +13 -5
  35. package/src/layout/ports/port.mjs +4 -5
  36. package/src/linkTools/Anchor.mjs +1 -1
  37. package/src/linkTools/Arrowhead.mjs +2 -1
  38. package/src/linkTools/RotateLabel.mjs +110 -0
  39. package/src/linkTools/Segments.mjs +1 -1
  40. package/src/linkTools/Vertices.mjs +41 -4
  41. package/src/linkTools/index.mjs +7 -4
  42. package/src/mvc/View.mjs +0 -1
  43. package/src/mvc/ViewBase.mjs +2 -1
  44. package/src/routers/rightAngle.mjs +538 -140
  45. package/src/shapes/standard.mjs +8 -1
  46. package/src/{dia/attributes → util}/calc.mjs +24 -12
  47. package/src/util/index.mjs +1 -0
  48. package/src/util/util.mjs +39 -0
  49. package/src/util/utilHelpers.mjs +2 -1
  50. package/types/geometry.d.ts +6 -1
  51. package/types/joint.d.ts +321 -48
  52. /package/src/{linkTools → cellTools}/Boundary.mjs +0 -0
  53. /package/src/{linkTools → cellTools}/Connect.mjs +0 -0
  54. /package/src/{linkTools → cellTools}/helpers.mjs +0 -0
@@ -2,7 +2,7 @@ import { CellView } from './CellView.mjs';
2
2
  import { Link } from './Link.mjs';
3
3
  import V from '../V/index.mjs';
4
4
  import { addClassNamePrefix, merge, assign, isObject, isFunction, clone, isPercentage, result, isEqual } from '../util/index.mjs';
5
- import { Point, Line, Path, normalizeAngle, Rect, Polyline } from '../g/index.mjs';
5
+ import { Point, Line, Path, normalizeAngle, Rect, Polyline, intersection } from '../g/index.mjs';
6
6
  import * as routers from '../routers/index.mjs';
7
7
  import * as connectors from '../connectors/index.mjs';
8
8
  import { env } from '../env/index.mjs';
@@ -63,7 +63,7 @@ export const LinkView = CellView.extend({
63
63
  attrs: [Flags.UPDATE],
64
64
  router: [Flags.UPDATE],
65
65
  connector: [Flags.CONNECTOR],
66
- labels: [Flags.LABELS],
66
+ labels: [Flags.LABELS, Flags.TOOLS],
67
67
  labelMarkup: [Flags.LABELS],
68
68
  vertices: [Flags.UPDATE],
69
69
  source: [Flags.SOURCE, Flags.UPDATE],
@@ -73,6 +73,7 @@ export const LinkView = CellView.extend({
73
73
  initFlag: [Flags.RENDER, Flags.SOURCE, Flags.TARGET, Flags.TOOLS],
74
74
 
75
75
  UPDATE_PRIORITY: 1,
76
+ EPSILON: 1e-6,
76
77
 
77
78
  confirmUpdate: function(flags, opt) {
78
79
 
@@ -461,6 +462,13 @@ export const LinkView = CellView.extend({
461
462
 
462
463
  if (!this._V.labels) return this;
463
464
 
465
+ if (!this.paper.options.labelLayer) {
466
+ // If there is no label layer, the cache needs to be cleared
467
+ // of the root node because the labels are attached
468
+ // to it and could affect the bounding box.
469
+ this.cleanNodeCache(this.el);
470
+ }
471
+
464
472
  var model = this.model;
465
473
  var labels = model.get('labels') || [];
466
474
  var canLabelMove = this.can('labelMove');
@@ -816,6 +824,34 @@ export const LinkView = CellView.extend({
816
824
  return connectionPoint.round(this.decimalsRounding);
817
825
  },
818
826
 
827
+ isIntersecting: function(geometryShape, geometryData) {
828
+ const connection = this.getConnection();
829
+ if (!connection) return false;
830
+ return intersection.exists(
831
+ geometryShape,
832
+ connection,
833
+ geometryData,
834
+ { segmentSubdivisions: this.getConnectionSubdivisions() },
835
+ );
836
+ },
837
+
838
+ isEnclosedIn: function(geometryRect) {
839
+ const connection = this.getConnection();
840
+ if (!connection) return false;
841
+ const bbox = connection.bbox();
842
+ if (!bbox) return false;
843
+ return geometryRect.containsRect(bbox);
844
+ },
845
+
846
+ isAtPoint: function(point /*, options */) {
847
+ // Note: `strict` option is not applicable for links.
848
+ // There is currently no method to determine if a path contains a point.
849
+ const area = new Rect(point);
850
+ // Intersection with a zero-size area is not possible.
851
+ area.inflate(this.EPSILON);
852
+ return this.isIntersecting(area);
853
+ },
854
+
819
855
  // combine default label position with built-in default label position
820
856
  _getDefaultLabelPositionProperty: function() {
821
857
 
@@ -1823,7 +1859,10 @@ export const LinkView = CellView.extend({
1823
1859
  // checking view in close area of the pointer
1824
1860
 
1825
1861
  var r = snapLinks.radius || 50;
1826
- var viewsInArea = paper.findViewsInArea({ x: x - r, y: y - r, width: 2 * r, height: 2 * r });
1862
+ var viewsInArea = paper.findElementViewsInArea(
1863
+ { x: x - r, y: y - r, width: 2 * r, height: 2 * r },
1864
+ snapLinks.findInAreaOptions
1865
+ );
1827
1866
 
1828
1867
  var prevClosestView = data.closestView || null;
1829
1868
  var prevClosestMagnet = data.closestMagnet || null;
package/src/dia/Paper.mjs CHANGED
@@ -382,6 +382,11 @@ export const Paper = View.extend({
382
382
  ],
383
383
  MIN_SCALE: 1e-6,
384
384
 
385
+ // Default find buffer for the findViewsInArea and findViewsAtPoint methods.
386
+ // The find buffer is used to extend the area of the search
387
+ // to mitigate the differences between the model and view geometry.
388
+ DEFAULT_FIND_BUFFER: 200,
389
+
385
390
  init: function() {
386
391
 
387
392
  const { options } = this;
@@ -1858,6 +1863,85 @@ export const Paper = View.extend({
1858
1863
  }, this);
1859
1864
  },
1860
1865
 
1866
+ findElementViewsInArea(plainArea, opt) {
1867
+ return this._filterViewsInArea(
1868
+ plainArea,
1869
+ (extArea, findOpt) => this.model.findElementsInArea(extArea, findOpt),
1870
+ opt
1871
+ );
1872
+ },
1873
+
1874
+ findLinkViewsInArea: function(plainArea, opt) {
1875
+ return this._filterViewsInArea(
1876
+ plainArea,
1877
+ (extArea, findOpt) => this.model.findLinksInArea(extArea, findOpt),
1878
+ opt
1879
+ );
1880
+ },
1881
+
1882
+ findCellViewsInArea: function(plainArea, opt) {
1883
+ return this._filterViewsInArea(
1884
+ plainArea,
1885
+ (extArea, findOpt) => this.model.findCellsInArea(extArea, findOpt),
1886
+ opt
1887
+ );
1888
+ },
1889
+
1890
+ findElementViewsAtPoint: function(plainPoint, opt) {
1891
+ return this._filterViewsAtPoint(
1892
+ plainPoint,
1893
+ (extArea) => this.model.findElementsInArea(extArea),
1894
+ opt
1895
+ );
1896
+ },
1897
+
1898
+ findLinkViewsAtPoint: function(plainPoint, opt) {
1899
+ return this._filterViewsAtPoint(
1900
+ plainPoint,
1901
+ (extArea) => this.model.findLinksInArea(extArea),
1902
+ opt,
1903
+ );
1904
+ },
1905
+
1906
+ findCellViewsAtPoint: function(plainPoint, opt) {
1907
+ return this._filterViewsAtPoint(
1908
+ plainPoint,
1909
+ // Note: we do not want to pass `opt` to `findCellsInArea`
1910
+ // because the `strict` option works differently for querying at a point
1911
+ (extArea) => this.model.findCellsInArea(extArea),
1912
+ opt
1913
+ );
1914
+ },
1915
+
1916
+ _findInExtendedArea: function(area, findCellsFn, opt = {}) {
1917
+ const {
1918
+ buffer = this.DEFAULT_FIND_BUFFER,
1919
+ } = opt;
1920
+ const extendedArea = (new Rect(area)).inflate(buffer);
1921
+ const cellsInExtendedArea = findCellsFn(extendedArea, opt);
1922
+ return cellsInExtendedArea.map(element => this.findViewByModel(element));
1923
+ },
1924
+
1925
+ _filterViewsInArea: function(plainArea, findCells, opt = {}) {
1926
+ const area = new Rect(plainArea);
1927
+ const viewsInExtendedArea = this._findInExtendedArea(area, findCells, opt);
1928
+ const viewsInArea = viewsInExtendedArea.filter(view => {
1929
+ if (!view) return false;
1930
+ return view.isInArea(area, opt);
1931
+ });
1932
+ return viewsInArea;
1933
+ },
1934
+
1935
+ _filterViewsAtPoint: function(plainPoint, findCells, opt = {}) {
1936
+ const area = new Rect(plainPoint); // zero-size area
1937
+ const viewsInExtendedArea = this._findInExtendedArea(area, findCells, opt);
1938
+ const viewsAtPoint = viewsInExtendedArea.filter(view => {
1939
+ if (!view) return false;
1940
+ return view.isAtPoint(plainPoint, opt);
1941
+ });
1942
+ return viewsAtPoint;
1943
+ },
1944
+
1861
1945
  removeTools: function() {
1862
1946
  this.dispatchToolsEvent('remove');
1863
1947
  return this;
@@ -6,6 +6,7 @@ export const ToolView = mvc.View.extend({
6
6
  className: 'tool',
7
7
  svgElement: true,
8
8
  _visible: true,
9
+ _visibleExplicit: true,
9
10
 
10
11
  init: function() {
11
12
  var name = this.name;
@@ -30,16 +31,40 @@ export const ToolView = mvc.View.extend({
30
31
  return this.name;
31
32
  },
32
33
 
34
+ // Evaluate the visibility of the tool and update the `display` CSS property
35
+ updateVisibility: function() {
36
+ const isVisible = this.computeVisibility();
37
+ this.el.style.display = isVisible ? '' : 'none';
38
+ this._visible = isVisible;
39
+ },
40
+
41
+ // Evaluate the visibility of the tool. The method returns `true` if the tool
42
+ // should be visible in the DOM.
43
+ computeVisibility() {
44
+ if (!this.isExplicitlyVisible()) return false;
45
+ const { visibility } = this.options;
46
+ if (typeof visibility !== 'function') return true;
47
+ return !!visibility.call(this, this.relatedView, this);
48
+ },
49
+
33
50
  show: function() {
34
- this.el.style.display = '';
35
- this._visible = true;
51
+ this._visibleExplicit = true;
52
+ this.updateVisibility();
36
53
  },
37
54
 
38
55
  hide: function() {
39
- this.el.style.display = 'none';
40
- this._visible = false;
56
+ this._visibleExplicit = false;
57
+ this.updateVisibility();
58
+ },
59
+
60
+ // The method returns `false` if the `hide()` method was called on the tool.
61
+ isExplicitlyVisible: function() {
62
+ return !!this._visibleExplicit;
41
63
  },
42
64
 
65
+ // The method returns `false` if the tool is not visible (it has `display: none`).
66
+ // This can happen if the `hide()` method was called or the tool is not visible
67
+ // because of the `visibility` option was evaluated to `false`.
43
68
  isVisible: function() {
44
69
  return !!this._visible;
45
70
  },
@@ -44,25 +44,37 @@ export const ToolsView = mvc.View.extend({
44
44
  update: function(opt) {
45
45
 
46
46
  opt || (opt = {});
47
- var tools = this.tools;
47
+ const tools = this.tools;
48
48
  if (!tools) return this;
49
- var isRendered = this.isRendered;
50
- for (var i = 0, n = tools.length; i < n; i++) {
51
- var tool = tools[i];
52
- if (!isRendered) {
49
+ const n = tools.length;
50
+ const wasRendered = this.isRendered;
51
+ for (let i = 0; i < n; i++) {
52
+ const tool = tools[i];
53
+ tool.updateVisibility();
54
+ if (!tool.isVisible()) continue;
55
+ if (!this.isRendered) {
56
+ // There is at least one visible tool
57
+ this.isRendered = Array(n).fill(false);
58
+ }
59
+ if (!this.isRendered[i]) {
53
60
  // First update executes render()
54
61
  tool.render();
55
- } else if (opt.tool !== tool.cid && tool.isVisible()) {
62
+ this.isRendered[i] = true;
63
+ } else if (opt.tool !== tool.cid) {
56
64
  tool.update();
57
65
  }
58
66
  }
67
+ if (!this.isRendered && n > 0) {
68
+ // None of the tools is visible
69
+ // Note: ToolsView with no tools are always mounted
70
+ return this;
71
+ }
59
72
  if (!this.isMounted()) {
60
73
  this.mount();
61
74
  }
62
- if (!isRendered) {
75
+ if (!wasRendered) {
63
76
  // Make sure tools are visible (if they were hidden and the tool removed)
64
77
  this.blurTool();
65
- this.isRendered = true;
66
78
  }
67
79
  return this;
68
80
  },
@@ -87,9 +99,12 @@ export const ToolsView = mvc.View.extend({
87
99
  if (!tools) return this;
88
100
  for (var i = 0, n = tools.length; i < n; i++) {
89
101
  var tool = tools[i];
90
- if (tool !== blurredTool && !tool.isVisible()) {
102
+ if (tool !== blurredTool && !tool.isExplicitlyVisible()) {
91
103
  tool.show();
92
- tool.update();
104
+ // Check if the tool is conditionally visible too
105
+ if (tool.isVisible()) {
106
+ tool.update();
107
+ }
93
108
  }
94
109
  }
95
110
  return this;
@@ -25,6 +25,7 @@ const connectionAttributesNS = {
25
25
 
26
26
  'connection': {
27
27
  qualify: isLinkView,
28
+ unset: 'd',
28
29
  set: function({ stubs = 0 }) {
29
30
  let d;
30
31
  if (isFinite(stubs) && stubs !== 0) {
@@ -49,21 +50,25 @@ const connectionAttributesNS = {
49
50
 
50
51
  'at-connection-length-keep-gradient': {
51
52
  qualify: isLinkView,
53
+ unset: 'transform',
52
54
  set: atConnectionWrapper('getTangentAtLength', { rotate: true })
53
55
  },
54
56
 
55
57
  'at-connection-length-ignore-gradient': {
56
58
  qualify: isLinkView,
59
+ unset: 'transform',
57
60
  set: atConnectionWrapper('getTangentAtLength', { rotate: false })
58
61
  },
59
62
 
60
63
  'at-connection-ratio-keep-gradient': {
61
64
  qualify: isLinkView,
65
+ unset: 'transform',
62
66
  set: atConnectionWrapper('getTangentAtRatio', { rotate: true })
63
67
  },
64
68
 
65
69
  'at-connection-ratio-ignore-gradient': {
66
70
  qualify: isLinkView,
71
+ unset: 'transform',
67
72
  set: atConnectionWrapper('getTangentAtRatio', { rotate: false })
68
73
  }
69
74
 
@@ -33,6 +33,7 @@ const defsAttributesNS = {
33
33
 
34
34
  'source-marker': {
35
35
  qualify: isPlainObject,
36
+ unset: 'marker-start',
36
37
  set: function(marker, refBBox, node, attrs) {
37
38
  marker = assign(contextMarker(attrs), marker);
38
39
  return { 'marker-start': 'url(#' + this.paper.defineMarker(marker) + ')' };
@@ -41,6 +42,7 @@ const defsAttributesNS = {
41
42
 
42
43
  'target-marker': {
43
44
  qualify: isPlainObject,
45
+ unset: 'marker-end',
44
46
  set: function(marker, refBBox, node, attrs) {
45
47
  marker = assign(contextMarker(attrs), { 'transform': 'rotate(180)' }, marker);
46
48
  return { 'marker-end': 'url(#' + this.paper.defineMarker(marker) + ')' };
@@ -49,6 +51,7 @@ const defsAttributesNS = {
49
51
 
50
52
  'vertex-marker': {
51
53
  qualify: isPlainObject,
54
+ unset: 'marker-mid',
52
55
  set: function(marker, refBBox, node, attrs) {
53
56
  marker = assign(contextMarker(attrs), marker);
54
57
  return { 'marker-mid': 'url(#' + this.paper.defineMarker(marker) + ')' };
@@ -1,4 +1,4 @@
1
- import { isCalcAttribute, evalCalcAttribute } from './calc.mjs';
1
+ import { isCalcExpression, evalCalcExpression } from '../../util/calc.mjs';
2
2
 
3
3
  const calcAttributesList = [
4
4
  'transform',
@@ -53,8 +53,8 @@ export function evalAttributes(attrs, refBBox) {
53
53
  }
54
54
 
55
55
  export function evalAttribute(attrName, attrValue, refBBox) {
56
- if (attrName in calcAttributes && isCalcAttribute(attrValue)) {
57
- let evalAttrValue = evalCalcAttribute(attrValue, refBBox);
56
+ if (attrName in calcAttributes && isCalcExpression(attrValue)) {
57
+ let evalAttrValue = evalCalcExpression(attrValue, refBBox);
58
58
  if (attrName in positiveValueAttributes) {
59
59
  evalAttrValue = Math.max(0, evalAttrValue);
60
60
  }
@@ -49,6 +49,9 @@ const attributesNS = {
49
49
  },
50
50
 
51
51
  'html': {
52
+ unset: function(node) {
53
+ $(node).empty();
54
+ },
52
55
  set: function(html, refBBox, node) {
53
56
  $(node).html(html + '');
54
57
  }
@@ -69,18 +69,22 @@ function pointsWrapper(opt) {
69
69
  const shapeAttributesNS = {
70
70
 
71
71
  'ref-d-reset-offset': {
72
+ unset: 'd',
72
73
  set: dWrapper({ resetOffset: true })
73
74
  },
74
75
 
75
76
  'ref-d-keep-offset': {
77
+ unset: 'd',
76
78
  set: dWrapper({ resetOffset: false })
77
79
  },
78
80
 
79
81
  'ref-points-reset-offset': {
82
+ unset: 'points',
80
83
  set: pointsWrapper({ resetOffset: true })
81
84
  },
82
85
 
83
86
  'ref-points-keep-offset': {
87
+ unset: 'points',
84
88
  set: pointsWrapper({ resetOffset: false })
85
89
  },
86
90
  };
@@ -1,5 +1,5 @@
1
1
  import { assign, isPlainObject, isObject, isPercentage, breakText } from '../../util/util.mjs';
2
- import { isCalcAttribute, evalCalcAttribute } from './calc.mjs';
2
+ import { isCalcExpression, evalCalcExpression } from '../../util/calc.mjs';
3
3
  import $ from '../../mvc/Dom/index.mjs';
4
4
  import V from '../../V/index.mjs';
5
5
 
@@ -40,6 +40,9 @@ const textAttributesNS = {
40
40
  const textWrap = attrs['text-wrap'];
41
41
  return !textWrap || !isPlainObject(textWrap);
42
42
  },
43
+ unset: function(node) {
44
+ node.textContent = '';
45
+ },
43
46
  set: function(text, refBBox, node, attrs) {
44
47
  const cacheName = 'joint-text';
45
48
  const cache = $.data.get(node, cacheName);
@@ -91,8 +94,8 @@ const textAttributesNS = {
91
94
  var width = value.width || 0;
92
95
  if (isPercentage(width)) {
93
96
  size.width = refBBox.width * parseFloat(width) / 100;
94
- } else if (isCalcAttribute(width)) {
95
- size.width = Number(evalCalcAttribute(width, refBBox));
97
+ } else if (isCalcExpression(width)) {
98
+ size.width = Number(evalCalcExpression(width, refBBox));
96
99
  } else {
97
100
  if (value.width === null) {
98
101
  // breakText() requires width to be specified.
@@ -107,8 +110,8 @@ const textAttributesNS = {
107
110
  var height = value.height || 0;
108
111
  if (isPercentage(height)) {
109
112
  size.height = refBBox.height * parseFloat(height) / 100;
110
- } else if (isCalcAttribute(height)) {
111
- size.height = Number(evalCalcAttribute(height, refBBox));
113
+ } else if (isCalcExpression(height)) {
114
+ size.height = Number(evalCalcExpression(height, refBBox));
112
115
  } else {
113
116
  if (value.height === null) {
114
117
  // if height is not specified breakText() does not
@@ -171,6 +174,13 @@ const textAttributesNS = {
171
174
  // HTMLElement title is specified via an attribute (i.e. not an element)
172
175
  return node instanceof SVGElement;
173
176
  },
177
+ unset: function(node) {
178
+ $.data.remove(node, 'joint-title');
179
+ const titleNode = node.firstElementChild;
180
+ if (titleNode) {
181
+ titleNode.remove();
182
+ }
183
+ },
174
184
  set: function(title, refBBox, node) {
175
185
  var cacheName = 'joint-title';
176
186
  var cache = $.data.get(node, cacheName);
package/src/dia/ports.mjs CHANGED
@@ -280,6 +280,10 @@ export const elementPortPrototype = {
280
280
  }));
281
281
  },
282
282
 
283
+ getPortGroupNames: function() {
284
+ return Object.keys(this._portSettingsData.groups);
285
+ },
286
+
283
287
  /**
284
288
  * @param {string} groupName
285
289
  * @returns {Object<portId, {x: number, y: number, angle: number}>}
@@ -1,8 +1,8 @@
1
- import { HoverConnect as LinkHoverConnect } from '../linkTools/HoverConnect.mjs';
1
+ import { HoverConnect as LinkHoverConnect } from '../cellTools/HoverConnect.mjs';
2
2
  import V from '../V/index.mjs';
3
3
  import * as g from '../g/index.mjs';
4
- import { getViewBBox } from '../linkTools/helpers.mjs';
5
- import { isCalcAttribute, evalCalcAttribute } from '../dia/attributes/calc.mjs';
4
+ import { isCalcExpression, evalCalcExpression } from '../util/calc.mjs';
5
+ import { getViewBBox } from '../cellTools/helpers.mjs';
6
6
 
7
7
  export const HoverConnect = LinkHoverConnect.extend({
8
8
 
@@ -15,9 +15,9 @@ export const HoverConnect = LinkHoverConnect.extend({
15
15
  if (typeof trackPath === 'function') {
16
16
  trackPath = trackPath.call(this, view);
17
17
  }
18
- if (isCalcAttribute(trackPath)) {
18
+ if (isCalcExpression(trackPath)) {
19
19
  const bbox = getViewBBox(view, useModelGeometry);
20
- trackPath = evalCalcAttribute(trackPath, bbox);
20
+ trackPath = evalCalcExpression(trackPath, bbox);
21
21
  }
22
22
  return new g.Path(V.normalizePathData(trackPath));
23
23
  },
@@ -1,5 +1,6 @@
1
- export * from './Control.mjs';
2
- export { Button, Remove } from '../linkTools/Button.mjs';
3
- export { Connect } from '../linkTools/Connect.mjs';
4
- export { Boundary } from '../linkTools/Boundary.mjs';
5
1
  export { HoverConnect } from './HoverConnect.mjs';
2
+
3
+ export { Button, Remove } from '../cellTools/Button.mjs';
4
+ export { Connect } from '../cellTools/Connect.mjs';
5
+ export { Boundary } from '../cellTools/Boundary.mjs';
6
+ export { Control } from '../cellTools/Control.mjs';
package/src/g/rect.mjs CHANGED
@@ -138,12 +138,20 @@ Rect.prototype = {
138
138
  },
139
139
 
140
140
  // @return {bool} true if point p is inside me.
141
- containsPoint: function(p) {
142
-
143
- if (!(p instanceof Point)) {
144
- p = new Point(p);
141
+ // @param {bool} strict If true, the point has to be strictly inside (not on the border).
142
+ containsPoint: function(p, opt) {
143
+ let x, y;
144
+ if (!p || (typeof p === 'string')) {
145
+ // Backwards compatibility: if the point is not provided,
146
+ // the point is considered to be the origin [0, 0].
147
+ ({ x, y } = new Point(p));
148
+ } else {
149
+ // Do not create a new Point object if the point is already a Point-like object.
150
+ ({ x = 0, y = 0 } = p);
145
151
  }
146
- return p.x >= this.x && p.x <= this.x + this.width && p.y >= this.y && p.y <= this.y + this.height;
152
+ return opt && opt.strict
153
+ ? (x > this.x && x < this.x + this.width && y > this.y && y < this.y + this.height)
154
+ : x >= this.x && x <= this.x + this.width && y >= this.y && y <= this.y + this.height;
147
155
  },
148
156
 
149
157
  // @return {bool} true if rectangle `r` is inside me.
@@ -1,4 +1,3 @@
1
- import { evalCalcAttribute, isCalcAttribute } from '../../dia/attributes/calc.mjs';
2
1
  import * as g from '../../g/index.mjs';
3
2
  import * as util from '../../util/index.mjs';
4
3
 
@@ -58,13 +57,13 @@ function argTransform(bbox, args) {
58
57
  let { x, y, angle } = args;
59
58
  if (util.isPercentage(x)) {
60
59
  x = parseFloat(x) / 100 * bbox.width;
61
- } else if (isCalcAttribute(x)) {
62
- x = Number(evalCalcAttribute(x, bbox));
60
+ } else if (util.isCalcExpression(x)) {
61
+ x = Number(util.evalCalcExpression(x, bbox));
63
62
  }
64
63
  if (util.isPercentage(y)) {
65
64
  y = parseFloat(y) / 100 * bbox.height;
66
- } else if (isCalcAttribute(y)) {
67
- y = Number(evalCalcAttribute(y, bbox));
65
+ } else if (util.isCalcExpression(y)) {
66
+ y = Number(util.evalCalcExpression(y, bbox));
68
67
  }
69
68
  return { x, y, angle };
70
69
  }
@@ -1,7 +1,7 @@
1
1
  import * as g from '../g/index.mjs';
2
2
  import * as util from '../util/index.mjs';
3
3
  import { ToolView } from '../dia/ToolView.mjs';
4
- import { getAnchor, snapAnchor } from './helpers.mjs';
4
+ import { getAnchor, snapAnchor } from '../cellTools/helpers.mjs';
5
5
 
6
6
  const Anchor = ToolView.extend({
7
7
  tagName: 'g',
@@ -51,7 +51,8 @@ const Arrowhead = ToolView.extend({
51
51
  var paper = relatedView.paper;
52
52
  relatedView.model.startBatch('arrowhead-move', { ui: true, tool: this.cid });
53
53
  relatedView.startArrowheadMove(this.arrowheadType);
54
- this.delegateDocumentEvents();
54
+ const data = evt.data || (evt.data = {});
55
+ this.delegateDocumentEvents(null, data);
55
56
  paper.undelegateEvents();
56
57
  this.focus();
57
58
  this.el.style.pointerEvents = 'none';