@joint/core 4.0.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 (139) hide show
  1. package/LICENSE +376 -0
  2. package/README.md +49 -0
  3. package/dist/geometry.js +6486 -0
  4. package/dist/geometry.min.js +8 -0
  5. package/dist/joint.d.ts +5536 -0
  6. package/dist/joint.js +39629 -0
  7. package/dist/joint.min.js +8 -0
  8. package/dist/joint.nowrap.js +39626 -0
  9. package/dist/joint.nowrap.min.js +8 -0
  10. package/dist/vectorizer.js +9135 -0
  11. package/dist/vectorizer.min.js +8 -0
  12. package/dist/version.mjs +3 -0
  13. package/index.js +3 -0
  14. package/joint.mjs +27 -0
  15. package/package.json +192 -0
  16. package/src/V/annotation.mjs +0 -0
  17. package/src/V/index.mjs +2642 -0
  18. package/src/anchors/index.mjs +123 -0
  19. package/src/config/index.mjs +12 -0
  20. package/src/connectionPoints/index.mjs +202 -0
  21. package/src/connectionStrategies/index.mjs +73 -0
  22. package/src/connectors/curve.mjs +553 -0
  23. package/src/connectors/index.mjs +6 -0
  24. package/src/connectors/jumpover.mjs +452 -0
  25. package/src/connectors/normal.mjs +12 -0
  26. package/src/connectors/rounded.mjs +17 -0
  27. package/src/connectors/smooth.mjs +44 -0
  28. package/src/connectors/straight.mjs +110 -0
  29. package/src/dia/Cell.mjs +945 -0
  30. package/src/dia/CellView.mjs +1316 -0
  31. package/src/dia/Element.mjs +519 -0
  32. package/src/dia/ElementView.mjs +859 -0
  33. package/src/dia/Graph.mjs +1112 -0
  34. package/src/dia/HighlighterView.mjs +319 -0
  35. package/src/dia/Link.mjs +565 -0
  36. package/src/dia/LinkView.mjs +2207 -0
  37. package/src/dia/Paper.mjs +3171 -0
  38. package/src/dia/PaperLayer.mjs +75 -0
  39. package/src/dia/ToolView.mjs +69 -0
  40. package/src/dia/ToolsView.mjs +128 -0
  41. package/src/dia/attributes/calc.mjs +128 -0
  42. package/src/dia/attributes/connection.mjs +75 -0
  43. package/src/dia/attributes/defs.mjs +76 -0
  44. package/src/dia/attributes/eval.mjs +64 -0
  45. package/src/dia/attributes/index.mjs +69 -0
  46. package/src/dia/attributes/legacy.mjs +148 -0
  47. package/src/dia/attributes/offset.mjs +53 -0
  48. package/src/dia/attributes/props.mjs +30 -0
  49. package/src/dia/attributes/shape.mjs +92 -0
  50. package/src/dia/attributes/text.mjs +180 -0
  51. package/src/dia/index.mjs +13 -0
  52. package/src/dia/layers/GridLayer.mjs +176 -0
  53. package/src/dia/ports.mjs +874 -0
  54. package/src/elementTools/Control.mjs +153 -0
  55. package/src/elementTools/HoverConnect.mjs +37 -0
  56. package/src/elementTools/index.mjs +5 -0
  57. package/src/env/index.mjs +43 -0
  58. package/src/g/bezier.mjs +175 -0
  59. package/src/g/curve.mjs +956 -0
  60. package/src/g/ellipse.mjs +245 -0
  61. package/src/g/extend.mjs +64 -0
  62. package/src/g/geometry.helpers.mjs +58 -0
  63. package/src/g/index.mjs +17 -0
  64. package/src/g/intersection.mjs +511 -0
  65. package/src/g/line.bearing.mjs +30 -0
  66. package/src/g/line.length.mjs +5 -0
  67. package/src/g/line.mjs +356 -0
  68. package/src/g/line.squaredLength.mjs +10 -0
  69. package/src/g/path.mjs +2260 -0
  70. package/src/g/point.mjs +375 -0
  71. package/src/g/points.mjs +247 -0
  72. package/src/g/polygon.mjs +51 -0
  73. package/src/g/polyline.mjs +523 -0
  74. package/src/g/rect.mjs +556 -0
  75. package/src/g/types.mjs +10 -0
  76. package/src/highlighters/addClass.mjs +27 -0
  77. package/src/highlighters/index.mjs +5 -0
  78. package/src/highlighters/list.mjs +111 -0
  79. package/src/highlighters/mask.mjs +220 -0
  80. package/src/highlighters/opacity.mjs +17 -0
  81. package/src/highlighters/stroke.mjs +100 -0
  82. package/src/layout/index.mjs +4 -0
  83. package/src/layout/ports/port.mjs +188 -0
  84. package/src/layout/ports/portLabel.mjs +224 -0
  85. package/src/linkAnchors/index.mjs +76 -0
  86. package/src/linkTools/Anchor.mjs +235 -0
  87. package/src/linkTools/Arrowhead.mjs +103 -0
  88. package/src/linkTools/Boundary.mjs +48 -0
  89. package/src/linkTools/Button.mjs +121 -0
  90. package/src/linkTools/Connect.mjs +85 -0
  91. package/src/linkTools/HoverConnect.mjs +161 -0
  92. package/src/linkTools/Segments.mjs +393 -0
  93. package/src/linkTools/Vertices.mjs +253 -0
  94. package/src/linkTools/helpers.mjs +33 -0
  95. package/src/linkTools/index.mjs +8 -0
  96. package/src/mvc/Collection.mjs +560 -0
  97. package/src/mvc/Data.mjs +46 -0
  98. package/src/mvc/Dom/Dom.mjs +587 -0
  99. package/src/mvc/Dom/Event.mjs +130 -0
  100. package/src/mvc/Dom/animations.mjs +122 -0
  101. package/src/mvc/Dom/events.mjs +69 -0
  102. package/src/mvc/Dom/index.mjs +13 -0
  103. package/src/mvc/Dom/methods.mjs +392 -0
  104. package/src/mvc/Dom/props.mjs +77 -0
  105. package/src/mvc/Dom/vars.mjs +5 -0
  106. package/src/mvc/Events.mjs +337 -0
  107. package/src/mvc/Listener.mjs +33 -0
  108. package/src/mvc/Model.mjs +239 -0
  109. package/src/mvc/View.mjs +323 -0
  110. package/src/mvc/ViewBase.mjs +182 -0
  111. package/src/mvc/index.mjs +9 -0
  112. package/src/mvc/mvcUtils.mjs +90 -0
  113. package/src/polyfills/array.js +4 -0
  114. package/src/polyfills/base64.js +68 -0
  115. package/src/polyfills/index.mjs +5 -0
  116. package/src/polyfills/number.js +3 -0
  117. package/src/polyfills/string.js +3 -0
  118. package/src/polyfills/typedArray.js +47 -0
  119. package/src/routers/index.mjs +6 -0
  120. package/src/routers/manhattan.mjs +856 -0
  121. package/src/routers/metro.mjs +91 -0
  122. package/src/routers/normal.mjs +6 -0
  123. package/src/routers/oneSide.mjs +60 -0
  124. package/src/routers/orthogonal.mjs +323 -0
  125. package/src/routers/rightAngle.mjs +1056 -0
  126. package/src/shapes/index.mjs +3 -0
  127. package/src/shapes/standard.mjs +755 -0
  128. package/src/util/cloneCells.mjs +67 -0
  129. package/src/util/getRectPoint.mjs +65 -0
  130. package/src/util/index.mjs +5 -0
  131. package/src/util/svgTagTemplate.mjs +110 -0
  132. package/src/util/util.mjs +1754 -0
  133. package/src/util/utilHelpers.mjs +2402 -0
  134. package/src/util/wrappers.mjs +56 -0
  135. package/types/geometry.d.ts +815 -0
  136. package/types/index.d.ts +53 -0
  137. package/types/joint.d.ts +4391 -0
  138. package/types/joint.head.d.ts +12 -0
  139. package/types/vectorizer.d.ts +327 -0
@@ -0,0 +1,148 @@
1
+ import { Point } from '../../g/index.mjs';
2
+ import { isPercentage } from '../../util/util.mjs';
3
+
4
+ function positionWrapper(axis, dimension, origin) {
5
+ return function(value, refBBox) {
6
+ var valuePercentage = isPercentage(value);
7
+ value = parseFloat(value);
8
+ if (valuePercentage) {
9
+ value /= 100;
10
+ }
11
+
12
+ var delta;
13
+ if (isFinite(value)) {
14
+ var refOrigin = refBBox[origin]();
15
+ if (valuePercentage || value > 0 && value < 1) {
16
+ delta = refOrigin[axis] + refBBox[dimension] * value;
17
+ } else {
18
+ delta = refOrigin[axis] + value;
19
+ }
20
+ }
21
+
22
+ var point = Point();
23
+ point[axis] = delta || 0;
24
+ return point;
25
+ };
26
+ }
27
+
28
+ function setWrapper(attrName, dimension) {
29
+ return function(value, refBBox) {
30
+ var isValuePercentage = isPercentage(value);
31
+ value = parseFloat(value);
32
+ if (isValuePercentage) {
33
+ value /= 100;
34
+ }
35
+
36
+ var attrs = {};
37
+ if (isFinite(value)) {
38
+ var attrValue = (isValuePercentage || value >= 0 && value <= 1)
39
+ ? value * refBBox[dimension]
40
+ : Math.max(value + refBBox[dimension], 0);
41
+ attrs[attrName] = attrValue;
42
+ }
43
+
44
+ return attrs;
45
+ };
46
+ }
47
+
48
+ const legacyAttributesNS = {
49
+
50
+ // if `refX` is in [0, 1] then `refX` is a fraction of bounding box width
51
+ // if `refX` is < 0 then `refX`'s absolute values is the right coordinate of the bounding box
52
+ // otherwise, `refX` is the left coordinate of the bounding box
53
+ 'ref-x': {
54
+ position: positionWrapper('x', 'width', 'origin')
55
+ },
56
+
57
+ 'ref-y': {
58
+ position: positionWrapper('y', 'height', 'origin')
59
+ },
60
+
61
+ // `ref-dx` and `ref-dy` define the offset of the sub-element relative to the right and/or bottom
62
+ // coordinate of the reference element.
63
+
64
+ 'ref-dx': {
65
+ position: positionWrapper('x', 'width', 'corner')
66
+ },
67
+
68
+ 'ref-dy': {
69
+ position: positionWrapper('y', 'height', 'corner')
70
+ },
71
+
72
+ // 'ref-width'/'ref-height' defines the width/height of the sub-element relatively to
73
+ // the reference element size
74
+ // val in 0..1 ref-width = 0.75 sets the width to 75% of the ref. el. width
75
+ // val < 0 || val > 1 ref-height = -20 sets the height to the ref. el. height shorter by 20
76
+
77
+ 'ref-width': {
78
+ set: setWrapper('width', 'width')
79
+ },
80
+
81
+ 'ref-height': {
82
+ set: setWrapper('height', 'height')
83
+ },
84
+
85
+ 'ref-rx': {
86
+ set: setWrapper('rx', 'width')
87
+ },
88
+
89
+ 'ref-ry': {
90
+ set: setWrapper('ry', 'height')
91
+ },
92
+
93
+ 'ref-cx': {
94
+ set: setWrapper('cx', 'width')
95
+ },
96
+
97
+ 'ref-cy': {
98
+ set: setWrapper('cy', 'height')
99
+ },
100
+
101
+ 'ref-r-inscribed': {
102
+ set: (function(attrName) {
103
+ var widthFn = setWrapper(attrName, 'width');
104
+ var heightFn = setWrapper(attrName, 'height');
105
+ return function(value, refBBox) {
106
+ var fn = (refBBox.height > refBBox.width) ? widthFn : heightFn;
107
+ return fn(value, refBBox);
108
+ };
109
+ })('r')
110
+ },
111
+
112
+ 'ref-r-circumscribed': {
113
+ set: function(value, refBBox) {
114
+ var isValuePercentage = isPercentage(value);
115
+ value = parseFloat(value);
116
+ if (isValuePercentage) {
117
+ value /= 100;
118
+ }
119
+
120
+ var diagonalLength = Math.sqrt((refBBox.height * refBBox.height) + (refBBox.width * refBBox.width));
121
+
122
+ var rValue;
123
+ if (isFinite(value)) {
124
+ if (isValuePercentage || value >= 0 && value <= 1) rValue = value * diagonalLength;
125
+ else rValue = Math.max(value + diagonalLength, 0);
126
+ }
127
+
128
+ return { r: rValue };
129
+ }
130
+ },
131
+ };
132
+
133
+ // NOTE: refX & refY are SVG attributes that define the reference point of the marker.
134
+ // That's why we need to define both variants: `refX` and `ref-x` (and `refY` and `ref-y`).
135
+ legacyAttributesNS['refX'] = legacyAttributesNS['ref-x'];
136
+ legacyAttributesNS['refY'] = legacyAttributesNS['ref-y'];
137
+
138
+ // This allows to combine both absolute and relative positioning
139
+ // refX: 50%, refX2: 20
140
+ legacyAttributesNS['ref-x2'] = legacyAttributesNS['ref-x'];
141
+ legacyAttributesNS['ref-y2'] = legacyAttributesNS['ref-y'];
142
+ legacyAttributesNS['ref-width2'] = legacyAttributesNS['ref-width'];
143
+ legacyAttributesNS['ref-height2'] = legacyAttributesNS['ref-height'];
144
+
145
+ // Aliases
146
+ legacyAttributesNS['ref-r'] = legacyAttributesNS['ref-r-inscribed'];
147
+
148
+ export default legacyAttributesNS;
@@ -0,0 +1,53 @@
1
+
2
+ // Offset attributes require the cell view to be rendered before they can be applied
3
+ // (they must be appended to the DOM).
4
+
5
+ import { Point } from '../../g/index.mjs';
6
+ import { isPercentage } from '../../util/util.mjs';
7
+
8
+ function offsetWrapper(axis, dimension, corner) {
9
+ return function(value, nodeBBox) {
10
+ var delta;
11
+ if (value === 'middle') {
12
+ delta = nodeBBox[dimension] / 2;
13
+ } else if (value === corner) {
14
+ delta = nodeBBox[dimension];
15
+ } else if (isFinite(value)) {
16
+ // TODO: or not to do a breaking change?
17
+ delta = (value > -1 && value < 1) ? (-nodeBBox[dimension] * value) : -value;
18
+ } else if (isPercentage(value)) {
19
+ delta = nodeBBox[dimension] * parseFloat(value) / 100;
20
+ } else {
21
+ delta = 0;
22
+ }
23
+
24
+ var point = new Point();
25
+ point[axis] = -(nodeBBox[axis] + delta);
26
+ return point;
27
+ };
28
+ }
29
+
30
+ const offsetAttributesNS = {
31
+
32
+ // `x-alignment` when set to `middle` causes centering of the sub-element around its new x coordinate.
33
+ // `x-alignment` when set to `right` uses the x coordinate as referenced to the right of the bbox.
34
+ 'x-alignment': {
35
+ offset: offsetWrapper('x', 'width', 'right')
36
+ },
37
+
38
+ // `y-alignment` when set to `middle` causes centering of the sub-element around its new y coordinate.
39
+ // `y-alignment` when set to `bottom` uses the y coordinate as referenced to the bottom of the bbox.
40
+ 'y-alignment': {
41
+ offset: offsetWrapper('y', 'height', 'bottom')
42
+ },
43
+
44
+ 'reset-offset': {
45
+ offset: function(val, nodeBBox) {
46
+ return (val)
47
+ ? { x: -nodeBBox.x, y: -nodeBBox.y }
48
+ : { x: 0, y: 0 };
49
+ }
50
+ },
51
+ };
52
+
53
+ export default offsetAttributesNS;
@@ -0,0 +1,30 @@
1
+ import { isPlainObject } from '../../util/util.mjs';
2
+
3
+ const validPropertiesList = ['checked', 'selected', 'disabled', 'readOnly', 'contentEditable', 'value', 'indeterminate'];
4
+
5
+ const validProperties = validPropertiesList.reduce((acc, key) => {
6
+ acc[key] = true;
7
+ return acc;
8
+ }, {});
9
+
10
+ const props = {
11
+ qualify: function(properties) {
12
+ return isPlainObject(properties);
13
+ },
14
+ set: function(properties, _, node) {
15
+ Object.keys(properties).forEach(function(key) {
16
+ if (validProperties[key] && key in node) {
17
+ const value = properties[key];
18
+ if (node.tagName === 'SELECT' && Array.isArray(value)) {
19
+ Array.from(node.options).forEach(function(option, index) {
20
+ option.selected = value.includes(option.value);
21
+ });
22
+ } else {
23
+ node[key] = value;
24
+ }
25
+ }
26
+ });
27
+ }
28
+ };
29
+
30
+ export default props;
@@ -0,0 +1,92 @@
1
+ import { Path, Polyline } from '../../g/index.mjs';
2
+ import $ from '../../mvc/Dom/index.mjs';
3
+ import V from '../../V/index.mjs';
4
+
5
+ function shapeWrapper(shapeConstructor, opt) {
6
+ var cacheName = 'joint-shape';
7
+ var resetOffset = opt && opt.resetOffset;
8
+ return function(value, refBBox, node) {
9
+ var cache = $.data.get(node, cacheName);
10
+ if (!cache || cache.value !== value) {
11
+ // only recalculate if value has changed
12
+ var cachedShape = shapeConstructor(value);
13
+ cache = {
14
+ value: value,
15
+ shape: cachedShape,
16
+ shapeBBox: cachedShape.bbox()
17
+ };
18
+ $.data.set(node, cacheName, cache);
19
+ }
20
+
21
+ var shape = cache.shape.clone();
22
+ var shapeBBox = cache.shapeBBox.clone();
23
+ var shapeOrigin = shapeBBox.origin();
24
+ var refOrigin = refBBox.origin();
25
+
26
+ shapeBBox.x = refOrigin.x;
27
+ shapeBBox.y = refOrigin.y;
28
+
29
+ var fitScale = refBBox.maxRectScaleToFit(shapeBBox, refOrigin);
30
+ // `maxRectScaleToFit` can give Infinity if width or height is 0
31
+ var sx = (shapeBBox.width === 0 || refBBox.width === 0) ? 1 : fitScale.sx;
32
+ var sy = (shapeBBox.height === 0 || refBBox.height === 0) ? 1 : fitScale.sy;
33
+
34
+ shape.scale(sx, sy, shapeOrigin);
35
+ if (resetOffset) {
36
+ shape.translate(-shapeOrigin.x, -shapeOrigin.y);
37
+ }
38
+
39
+ return shape;
40
+ };
41
+ }
42
+
43
+ // `d` attribute for SVGPaths
44
+ function dWrapper(opt) {
45
+ function pathConstructor(value) {
46
+ return new Path(V.normalizePathData(value));
47
+ }
48
+
49
+ var shape = shapeWrapper(pathConstructor, opt);
50
+ return function(value, refBBox, node) {
51
+ var path = shape(value, refBBox, node);
52
+ return {
53
+ d: path.serialize()
54
+ };
55
+ };
56
+ }
57
+
58
+ // `points` attribute for SVGPolylines and SVGPolygons
59
+ function pointsWrapper(opt) {
60
+ var shape = shapeWrapper(Polyline, opt);
61
+ return function(value, refBBox, node) {
62
+ var polyline = shape(value, refBBox, node);
63
+ return {
64
+ points: polyline.serialize()
65
+ };
66
+ };
67
+ }
68
+
69
+ const shapeAttributesNS = {
70
+
71
+ 'ref-d-reset-offset': {
72
+ set: dWrapper({ resetOffset: true })
73
+ },
74
+
75
+ 'ref-d-keep-offset': {
76
+ set: dWrapper({ resetOffset: false })
77
+ },
78
+
79
+ 'ref-points-reset-offset': {
80
+ set: pointsWrapper({ resetOffset: true })
81
+ },
82
+
83
+ 'ref-points-keep-offset': {
84
+ set: pointsWrapper({ resetOffset: false })
85
+ },
86
+ };
87
+
88
+ // Aliases
89
+ shapeAttributesNS['ref-d'] = shapeAttributesNS['ref-d-reset-offset'];
90
+ shapeAttributesNS['ref-points'] = shapeAttributesNS['ref-points-reset-offset'];
91
+
92
+ export default shapeAttributesNS;
@@ -0,0 +1,180 @@
1
+ import { assign, isPlainObject, isObject, isPercentage, breakText } from '../../util/util.mjs';
2
+ import { isCalcAttribute, evalCalcAttribute } from './calc.mjs';
3
+ import $ from '../../mvc/Dom/index.mjs';
4
+ import V from '../../V/index.mjs';
5
+
6
+ function isTextInUse(_value, _node, attrs) {
7
+ return (attrs.text !== undefined);
8
+ }
9
+
10
+ const textAttributesNS = {
11
+
12
+ 'line-height': {
13
+ qualify: isTextInUse
14
+ },
15
+
16
+ 'text-vertical-anchor': {
17
+ qualify: isTextInUse
18
+ },
19
+
20
+ 'text-path': {
21
+ qualify: isTextInUse
22
+ },
23
+
24
+ 'annotations': {
25
+ qualify: isTextInUse
26
+ },
27
+
28
+ 'eol': {
29
+ qualify: isTextInUse
30
+ },
31
+
32
+ 'display-empty': {
33
+ qualify: isTextInUse
34
+ },
35
+
36
+ 'text': {
37
+ qualify: function(_text, _node, attrs) {
38
+ const textWrap = attrs['text-wrap'];
39
+ return !textWrap || !isPlainObject(textWrap);
40
+ },
41
+ set: function(text, refBBox, node, attrs) {
42
+ const cacheName = 'joint-text';
43
+ const cache = $.data.get(node, cacheName);
44
+ const lineHeight = attrs['line-height'];
45
+ const textVerticalAnchor = attrs['text-vertical-anchor'];
46
+ const displayEmpty = attrs['display-empty'];
47
+ const fontSize = attrs['font-size'];
48
+ const annotations = attrs.annotations;
49
+ const eol = attrs.eol;
50
+ const x = attrs.x;
51
+ let textPath = attrs['text-path'];
52
+ // Update the text only if there was a change in the string
53
+ // or any of its attributes.
54
+ const textHash = JSON.stringify([text, lineHeight, annotations, textVerticalAnchor, eol, displayEmpty, textPath, x, fontSize]);
55
+ if (cache === undefined || cache !== textHash) {
56
+ // Chrome bug:
57
+ // <tspan> positions defined as `em` are not updated
58
+ // when container `font-size` change.
59
+ if (fontSize) node.setAttribute('font-size', fontSize);
60
+ // Text Along Path Selector
61
+ if (isObject(textPath)) {
62
+ const pathSelector = textPath.selector;
63
+ if (typeof pathSelector === 'string') {
64
+ const pathNode = this.findNode(pathSelector);
65
+ if (pathNode instanceof SVGPathElement) {
66
+ textPath = assign({ 'xlink:href': '#' + pathNode.id }, textPath);
67
+ }
68
+ }
69
+ }
70
+ V(node).text('' + text, {
71
+ lineHeight,
72
+ annotations,
73
+ textPath,
74
+ x,
75
+ textVerticalAnchor,
76
+ eol,
77
+ displayEmpty
78
+ });
79
+ $.data.set(node, cacheName, textHash);
80
+ }
81
+ }
82
+ },
83
+
84
+ 'text-wrap': {
85
+ qualify: isPlainObject,
86
+ set: function(value, refBBox, node, attrs) {
87
+ var size = {};
88
+ // option `width`
89
+ var width = value.width || 0;
90
+ if (isPercentage(width)) {
91
+ size.width = refBBox.width * parseFloat(width) / 100;
92
+ } else if (isCalcAttribute(width)) {
93
+ size.width = Number(evalCalcAttribute(width, refBBox));
94
+ } else {
95
+ if (value.width === null) {
96
+ // breakText() requires width to be specified.
97
+ size.width = Infinity;
98
+ } else if (width <= 0) {
99
+ size.width = refBBox.width + width;
100
+ } else {
101
+ size.width = width;
102
+ }
103
+ }
104
+ // option `height`
105
+ var height = value.height || 0;
106
+ if (isPercentage(height)) {
107
+ size.height = refBBox.height * parseFloat(height) / 100;
108
+ } else if (isCalcAttribute(height)) {
109
+ size.height = Number(evalCalcAttribute(height, refBBox));
110
+ } else {
111
+ if (value.height === null) {
112
+ // if height is not specified breakText() does not
113
+ // restrict the height of the text.
114
+ } else if (height <= 0) {
115
+ size.height = refBBox.height + height;
116
+ } else {
117
+ size.height = height;
118
+ }
119
+ }
120
+ // option `text`
121
+ var wrappedText;
122
+ var text = value.text;
123
+ if (text === undefined) text = attrs.text;
124
+ if (text !== undefined) {
125
+ const breakTextFn = value.breakText || breakText;
126
+ wrappedText = breakTextFn('' + text, size, {
127
+ 'font-weight': attrs['font-weight'],
128
+ 'font-size': attrs['font-size'],
129
+ 'font-family': attrs['font-family'],
130
+ 'lineHeight': attrs['line-height'],
131
+ 'letter-spacing': attrs['letter-spacing']
132
+ }, {
133
+ // Provide an existing SVG Document here
134
+ // instead of creating a temporary one over again.
135
+ svgDocument: this.paper.svg,
136
+ ellipsis: value.ellipsis,
137
+ hyphen: value.hyphen,
138
+ separator: value.separator,
139
+ maxLineCount: value.maxLineCount,
140
+ preserveSpaces: value.preserveSpaces
141
+ });
142
+ } else {
143
+ wrappedText = '';
144
+ }
145
+ textAttributesNS.text.set.call(this, wrappedText, refBBox, node, attrs);
146
+ }
147
+ },
148
+
149
+ 'title': {
150
+ qualify: function(title, node) {
151
+ // HTMLElement title is specified via an attribute (i.e. not an element)
152
+ return node instanceof SVGElement;
153
+ },
154
+ set: function(title, refBBox, node) {
155
+ var cacheName = 'joint-title';
156
+ var cache = $.data.get(node, cacheName);
157
+ if (cache === undefined || cache !== title) {
158
+ $.data.set(node, cacheName, title);
159
+ if (node.tagName === 'title') {
160
+ // The target node is a <title> element.
161
+ node.textContent = title;
162
+ return;
163
+ }
164
+ // Generally <title> element should be the first child element of its parent.
165
+ var firstChild = node.firstElementChild;
166
+ if (firstChild && firstChild.tagName === 'title') {
167
+ // Update an existing title
168
+ firstChild.textContent = title;
169
+ } else {
170
+ // Create a new title
171
+ var titleNode = document.createElementNS(node.namespaceURI, 'title');
172
+ titleNode.textContent = title;
173
+ node.insertBefore(titleNode, firstChild);
174
+ }
175
+ }
176
+ }
177
+ },
178
+ };
179
+
180
+ export default textAttributesNS;
@@ -0,0 +1,13 @@
1
+ export * from './Graph.mjs';
2
+ export * from './attributes/index.mjs';
3
+ export * from './PaperLayer.mjs';
4
+ export * from './Cell.mjs';
5
+ export * from './CellView.mjs';
6
+ export * from './Element.mjs';
7
+ export * from './ElementView.mjs';
8
+ export * from './Link.mjs';
9
+ export * from './LinkView.mjs';
10
+ export * from './Paper.mjs';
11
+ export * from './ToolView.mjs';
12
+ export * from './ToolsView.mjs';
13
+ export * from './HighlighterView.mjs';
@@ -0,0 +1,176 @@
1
+ import { PaperLayer } from '../PaperLayer.mjs';
2
+ import {
3
+ isFunction,
4
+ isString,
5
+ defaults,
6
+ omit,
7
+ assign,
8
+ merge,
9
+ } from '../../util/index.mjs';
10
+ import V from '../../V/index.mjs';
11
+
12
+ export const GridLayer = PaperLayer.extend({
13
+
14
+ style: {
15
+ 'pointer-events': 'none'
16
+ },
17
+
18
+ _gridCache: null,
19
+ _gridSettings: null,
20
+
21
+ init() {
22
+ PaperLayer.prototype.init.apply(this, arguments);
23
+ const { options: { paper }} = this;
24
+ this._gridCache = null;
25
+ this._gridSettings = [];
26
+ this.listenTo(paper, 'transform resize', this.updateGrid);
27
+ },
28
+
29
+ setGrid(drawGrid) {
30
+ this._gridSettings = this.getGridSettings(drawGrid);
31
+ this.renderGrid();
32
+ },
33
+
34
+ getGridSettings(drawGrid) {
35
+ const gridSettings = [];
36
+ if (drawGrid) {
37
+ const optionsList = Array.isArray(drawGrid) ? drawGrid : [drawGrid || {}];
38
+ optionsList.forEach((item) => {
39
+ gridSettings.push(...this._resolveDrawGridOption(item));
40
+ });
41
+ }
42
+ return gridSettings;
43
+ },
44
+
45
+ removeGrid() {
46
+ const { _gridCache: grid } = this;
47
+ if (!grid) return;
48
+ grid.root.remove();
49
+ this._gridCache = null;
50
+ },
51
+
52
+ renderGrid() {
53
+
54
+ const { options: { paper }} = this;
55
+ const { _gridSettings: gridSettings } = this;
56
+
57
+ this.removeGrid();
58
+
59
+ if (gridSettings.length === 0) return;
60
+
61
+ const gridSize = paper.options.drawGridSize || paper.options.gridSize;
62
+ if (gridSize <= 1) {
63
+ return;
64
+ }
65
+
66
+ const refs = this._getGridRefs();
67
+
68
+ gridSettings.forEach((gridLayerSetting, index) => {
69
+
70
+ const id = 'pattern_' + index;
71
+ const options = merge({}, gridLayerSetting);
72
+ const { scaleFactor = 1 } = options;
73
+ options.width = gridSize * scaleFactor || 1;
74
+ options.height = gridSize * scaleFactor || 1;
75
+
76
+ let vPattern;
77
+ if (!refs.exist(id)) {
78
+ vPattern = V('pattern', { id: id, patternUnits: 'userSpaceOnUse' }, V(options.markup));
79
+ refs.add(id, vPattern);
80
+ } else {
81
+ vPattern = refs.get(id);
82
+ }
83
+
84
+ if (isFunction(options.render)) {
85
+ options.render(vPattern.node.firstChild, options, paper);
86
+ }
87
+ vPattern.attr({
88
+ width: options.width,
89
+ height: options.height
90
+ });
91
+ });
92
+
93
+ refs.root.appendTo(this.el);
94
+ this.updateGrid();
95
+ },
96
+
97
+ updateGrid() {
98
+
99
+ const { _gridCache: grid, _gridSettings: gridSettings, options: { paper }} = this;
100
+ if (!grid) return;
101
+ const { root: vSvg, patterns } = grid;
102
+ const { x, y, width, height } = paper.getArea();
103
+ vSvg.attr({ x, y, width, height });
104
+ for (const patternId in patterns) {
105
+ const vPattern = patterns[patternId];
106
+ vPattern.attr({ x: -x, y: -y });
107
+ }
108
+ gridSettings.forEach((options, index) => {
109
+ if (isFunction(options.update)) {
110
+ const vPattern = patterns['pattern_' + index];
111
+ options.update(vPattern.node.firstChild, options, paper);
112
+ }
113
+ });
114
+ },
115
+
116
+ _getGridRefs() {
117
+ let { _gridCache: grid } = this;
118
+ if (grid) return grid;
119
+ const defsVEl = V('defs');
120
+ const svgVEl = V('svg', { width: '100%', height: '100%' }, [defsVEl]);
121
+ grid = this._gridCache = {
122
+ root: svgVEl,
123
+ patterns: {},
124
+ add: function(id, patternVEl) {
125
+ const rectVEl = V('rect', { width: '100%', height: '100%', fill: `url(#${id})` });
126
+ defsVEl.append(patternVEl);
127
+ svgVEl.append(rectVEl);
128
+ this.patterns[id] = patternVEl;
129
+ },
130
+ get: function(id) {
131
+ return this.patterns[id];
132
+ },
133
+ exist: function(id) {
134
+ return this.patterns[id] !== undefined;
135
+ }
136
+ };
137
+ return grid;
138
+ },
139
+
140
+ _resolveDrawGridOption(opt) {
141
+
142
+ var namespace = this.options.patterns;
143
+ if (isString(opt) && Array.isArray(namespace[opt])) {
144
+ return namespace[opt].map(function(item) {
145
+ return assign({}, item);
146
+ });
147
+ }
148
+
149
+ var options = opt || { args: [{}] };
150
+ var isArray = Array.isArray(options);
151
+ var name = options.name;
152
+
153
+ if (!isArray && !name && !options.markup) {
154
+ name = 'dot';
155
+ }
156
+
157
+ if (name && Array.isArray(namespace[name])) {
158
+ var pattern = namespace[name].map(function(item) {
159
+ return assign({}, item);
160
+ });
161
+
162
+ var args = Array.isArray(options.args) ? options.args : [options.args || {}];
163
+
164
+ defaults(args[0], omit(opt, 'args'));
165
+ for (var i = 0; i < args.length; i++) {
166
+ if (pattern[i]) {
167
+ assign(pattern[i], args[i]);
168
+ }
169
+ }
170
+ return pattern;
171
+ }
172
+
173
+ return isArray ? options : [options];
174
+ },
175
+
176
+ });