@joint/core 4.2.0-alpha.0 → 4.2.0-alpha.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/README.md +3 -1
- package/dist/geometry.js +2 -2
- package/dist/geometry.min.js +3 -2
- package/dist/joint.d.ts +280 -149
- package/dist/joint.js +1427 -475
- package/dist/joint.min.js +4 -3
- package/dist/joint.nowrap.js +1427 -475
- package/dist/joint.nowrap.min.js +4 -3
- package/dist/vectorizer.js +21 -8
- package/dist/vectorizer.min.js +4 -3
- package/dist/version.mjs +1 -1
- package/package.json +7 -7
- package/src/V/index.mjs +20 -5
- package/src/alg/Deque.mjs +126 -0
- package/src/cellTools/Boundary.mjs +15 -13
- package/src/cellTools/Button.mjs +7 -5
- package/src/cellTools/Control.mjs +37 -14
- package/src/cellTools/HoverConnect.mjs +5 -1
- package/src/cellTools/helpers.mjs +44 -3
- package/src/config/index.mjs +8 -0
- package/src/dia/Cell.mjs +26 -10
- package/src/dia/CellView.mjs +7 -0
- package/src/dia/Element.mjs +4 -2
- package/src/dia/ElementView.mjs +2 -1
- package/src/dia/HighlighterView.mjs +22 -0
- package/src/dia/LinkView.mjs +118 -98
- package/src/dia/Paper.mjs +697 -209
- package/src/dia/ToolView.mjs +4 -0
- package/src/dia/ToolsView.mjs +12 -3
- package/src/dia/attributes/text.mjs +4 -2
- package/src/dia/ports.mjs +202 -82
- package/src/elementTools/HoverConnect.mjs +14 -8
- package/src/env/index.mjs +6 -3
- package/src/layout/ports/port.mjs +30 -15
- package/src/layout/ports/portLabel.mjs +1 -1
- package/src/mvc/View.mjs +4 -0
- package/src/mvc/ViewBase.mjs +1 -1
- package/types/geometry.d.ts +64 -60
- package/types/joint.d.ts +205 -88
- package/types/vectorizer.d.ts +11 -1
package/src/dia/LinkView.mjs
CHANGED
|
@@ -34,6 +34,8 @@ export const LinkView = CellView.extend({
|
|
|
34
34
|
_labelCache: null,
|
|
35
35
|
_labelSelectors: null,
|
|
36
36
|
_V: null,
|
|
37
|
+
_sourceMagnet: null,
|
|
38
|
+
_targetMagnet: null,
|
|
37
39
|
_dragData: null, // deprecated
|
|
38
40
|
|
|
39
41
|
metrics: null,
|
|
@@ -75,23 +77,31 @@ export const LinkView = CellView.extend({
|
|
|
75
77
|
UPDATE_PRIORITY: 1,
|
|
76
78
|
EPSILON: 1e-6,
|
|
77
79
|
|
|
78
|
-
confirmUpdate: function(flags, opt) {
|
|
80
|
+
confirmUpdate: function(flags, opt = {}) {
|
|
79
81
|
|
|
80
|
-
|
|
82
|
+
const { paper, model } = this;
|
|
83
|
+
const { attributes } = model;
|
|
84
|
+
const { source: { id: sourceId }, target: { id: targetId }} = attributes;
|
|
81
85
|
|
|
82
86
|
if (this.hasFlag(flags, Flags.SOURCE)) {
|
|
83
|
-
|
|
87
|
+
this._sourceMagnet = null; // reset cached source magnet
|
|
88
|
+
this.checkEndModel('source', sourceId);
|
|
84
89
|
flags = this.removeFlag(flags, Flags.SOURCE);
|
|
85
90
|
}
|
|
86
91
|
|
|
87
92
|
if (this.hasFlag(flags, Flags.TARGET)) {
|
|
88
|
-
|
|
93
|
+
this._targetMagnet = null; // reset cached target magnet
|
|
94
|
+
this.checkEndModel('target', targetId);
|
|
89
95
|
flags = this.removeFlag(flags, Flags.TARGET);
|
|
90
96
|
}
|
|
91
97
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
98
|
+
if (
|
|
99
|
+
paper && (
|
|
100
|
+
(sourceId && !paper.isCellVisible(sourceId)) ||
|
|
101
|
+
(targetId && !paper.isCellVisible(targetId))
|
|
102
|
+
)
|
|
103
|
+
) {
|
|
104
|
+
// Wait for the source and target views to be rendered
|
|
95
105
|
return flags;
|
|
96
106
|
}
|
|
97
107
|
|
|
@@ -101,8 +111,8 @@ export const LinkView = CellView.extend({
|
|
|
101
111
|
this.updateTools(opt);
|
|
102
112
|
flags = this.removeFlag(flags, [Flags.RENDER, Flags.UPDATE, Flags.LABELS, Flags.TOOLS, Flags.CONNECTOR]);
|
|
103
113
|
|
|
104
|
-
if (env.test('
|
|
105
|
-
this.
|
|
114
|
+
if (env.test('isAppleWebKit')) {
|
|
115
|
+
this.__fixWebKitBug268376();
|
|
106
116
|
}
|
|
107
117
|
|
|
108
118
|
return flags;
|
|
@@ -110,8 +120,6 @@ export const LinkView = CellView.extend({
|
|
|
110
120
|
|
|
111
121
|
let updateHighlighters = false;
|
|
112
122
|
|
|
113
|
-
const { model } = this;
|
|
114
|
-
const { attributes } = model;
|
|
115
123
|
let updateLabels = this.hasFlag(flags, Flags.LABELS);
|
|
116
124
|
|
|
117
125
|
if (updateLabels) {
|
|
@@ -157,8 +165,8 @@ export const LinkView = CellView.extend({
|
|
|
157
165
|
return flags;
|
|
158
166
|
},
|
|
159
167
|
|
|
160
|
-
|
|
161
|
-
//
|
|
168
|
+
__fixWebKitBug268376: function() {
|
|
169
|
+
// WebKit has a bug where any change after the first render is not reflected in the DOM.
|
|
162
170
|
// https://bugs.webkit.org/show_bug.cgi?id=268376
|
|
163
171
|
const { el } = this;
|
|
164
172
|
const childNodes = Array.from(el.childNodes);
|
|
@@ -931,44 +939,11 @@ export const LinkView = CellView.extend({
|
|
|
931
939
|
}
|
|
932
940
|
},
|
|
933
941
|
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
const
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
const endId = endDef && endDef.id;
|
|
940
|
-
|
|
941
|
-
if (!endId) {
|
|
942
|
-
// the link end is a point ~ rect 0x0
|
|
943
|
-
this[endViewProperty] = null;
|
|
944
|
-
this.updateEndMagnet(endType);
|
|
945
|
-
return true;
|
|
946
|
-
}
|
|
947
|
-
|
|
948
|
-
const endModel = paper.getModelById(endId);
|
|
949
|
-
if (!endModel) throw new Error('LinkView: invalid ' + endType + ' cell.');
|
|
950
|
-
|
|
951
|
-
const endView = endModel.findView(paper);
|
|
952
|
-
if (!endView) {
|
|
953
|
-
// A view for a model should always exist
|
|
954
|
-
return false;
|
|
955
|
-
}
|
|
956
|
-
|
|
957
|
-
this[endViewProperty] = endView;
|
|
958
|
-
this.updateEndMagnet(endType);
|
|
959
|
-
return true;
|
|
960
|
-
},
|
|
961
|
-
|
|
962
|
-
updateEndMagnet: function(endType) {
|
|
963
|
-
|
|
964
|
-
const endMagnetProperty = `${endType}Magnet`;
|
|
965
|
-
const endView = this.getEndView(endType);
|
|
966
|
-
if (endView) {
|
|
967
|
-
let connectedMagnet = endView.getMagnetFromLinkEnd(this.model.get(endType));
|
|
968
|
-
if (connectedMagnet === endView.el) connectedMagnet = null;
|
|
969
|
-
this[endMagnetProperty] = connectedMagnet;
|
|
970
|
-
} else {
|
|
971
|
-
this[endMagnetProperty] = null;
|
|
942
|
+
checkEndModel: function(endType, endId) {
|
|
943
|
+
if (!endId) return;
|
|
944
|
+
const endModel = this.paper.getModelById(endId);
|
|
945
|
+
if (!endModel) {
|
|
946
|
+
throw new Error(`LinkView: invalid ${endType} cell.`);
|
|
972
947
|
}
|
|
973
948
|
},
|
|
974
949
|
|
|
@@ -1858,56 +1833,30 @@ export const LinkView = CellView.extend({
|
|
|
1858
1833
|
let isSnapped = false;
|
|
1859
1834
|
// checking view in close area of the pointer
|
|
1860
1835
|
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
{ x: x - r, y: y - r, width: 2 * r, height: 2 * r },
|
|
1864
|
-
snapLinks.findInAreaOptions
|
|
1865
|
-
);
|
|
1836
|
+
const radius = snapLinks.radius || 50;
|
|
1837
|
+
const findInAreaOptions = snapLinks.findInAreaOptions;
|
|
1866
1838
|
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1839
|
+
const prevClosestView = data.closestView || null;
|
|
1840
|
+
const prevClosestMagnet = data.closestMagnet || null;
|
|
1841
|
+
const prevMagnetProxy = data.magnetProxy || null;
|
|
1870
1842
|
|
|
1871
1843
|
data.closestView = data.closestMagnet = data.magnetProxy = null;
|
|
1872
1844
|
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
const candidates = [];
|
|
1878
|
-
// skip connecting to the element in case '.': { magnet: false } attribute present
|
|
1879
|
-
if (view.el.getAttribute('magnet') !== 'false') {
|
|
1880
|
-
candidates.push({
|
|
1881
|
-
bbox: view.model.getBBox(),
|
|
1882
|
-
magnet: view.el
|
|
1883
|
-
});
|
|
1845
|
+
const isValidCandidate = (view, magnet) => {
|
|
1846
|
+
// Do not snap to the current view
|
|
1847
|
+
if (view === this) {
|
|
1848
|
+
return false;
|
|
1884
1849
|
}
|
|
1885
1850
|
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
});
|
|
1892
|
-
|
|
1893
|
-
candidates.forEach(candidate => {
|
|
1894
|
-
const { magnet, bbox } = candidate;
|
|
1895
|
-
// find distance from the center of the model to pointer coordinates
|
|
1896
|
-
const distance = bbox.center().squaredDistance(pointer);
|
|
1897
|
-
// the connection is looked up in a circle area by `distance < r`
|
|
1898
|
-
if (distance < minDistance) {
|
|
1899
|
-
const isAlreadyValidated = prevClosestMagnet === magnet;
|
|
1900
|
-
if (isAlreadyValidated || paper.options.validateConnection.apply(
|
|
1901
|
-
paper, data.validateConnectionArgs(view, (view.el === magnet) ? null : magnet)
|
|
1902
|
-
)) {
|
|
1903
|
-
minDistance = distance;
|
|
1904
|
-
data.closestView = view;
|
|
1905
|
-
data.closestMagnet = magnet;
|
|
1906
|
-
}
|
|
1907
|
-
}
|
|
1908
|
-
});
|
|
1851
|
+
const isAlreadyValidated = prevClosestMagnet === magnet;
|
|
1852
|
+
return isAlreadyValidated || paper.options.validateConnection.apply(
|
|
1853
|
+
paper, data.validateConnectionArgs(view, (view.el === magnet) ? null : magnet)
|
|
1854
|
+
);
|
|
1855
|
+
};
|
|
1909
1856
|
|
|
1910
|
-
},
|
|
1857
|
+
const closest = paper.findClosestMagnetToPoint({ x, y }, { radius, findInAreaOptions, filter: isValidCandidate });
|
|
1858
|
+
data.closestView = closest ? closest.view : null;
|
|
1859
|
+
data.closestMagnet = closest ? closest.magnet : null;
|
|
1911
1860
|
|
|
1912
1861
|
var end;
|
|
1913
1862
|
var magnetProxy = null;
|
|
@@ -2225,8 +2174,82 @@ export const LinkView = CellView.extend({
|
|
|
2225
2174
|
Flags: Flags,
|
|
2226
2175
|
});
|
|
2227
2176
|
|
|
2228
|
-
Object.defineProperty(LinkView.prototype, '
|
|
2177
|
+
Object.defineProperty(LinkView.prototype, 'sourceView', {
|
|
2178
|
+
enumerable: true,
|
|
2179
|
+
|
|
2180
|
+
get: function() {
|
|
2181
|
+
const source = this.model.attributes.source;
|
|
2182
|
+
if (source.id && this.paper) {
|
|
2183
|
+
return this.paper.findViewByModel(source.id);
|
|
2184
|
+
}
|
|
2185
|
+
return null;
|
|
2186
|
+
}
|
|
2187
|
+
|
|
2188
|
+
});
|
|
2189
|
+
|
|
2190
|
+
Object.defineProperty(LinkView.prototype, 'targetView', {
|
|
2191
|
+
enumerable: true,
|
|
2192
|
+
|
|
2193
|
+
get: function() {
|
|
2194
|
+
const target = this.model.attributes.target;
|
|
2195
|
+
if (target.id && this.paper) {
|
|
2196
|
+
return this.paper.findViewByModel(target.id);
|
|
2197
|
+
}
|
|
2198
|
+
return null;
|
|
2199
|
+
}
|
|
2200
|
+
});
|
|
2201
|
+
|
|
2202
|
+
Object.defineProperty(LinkView.prototype, 'sourceMagnet', {
|
|
2203
|
+
enumerable: true,
|
|
2204
|
+
|
|
2205
|
+
get: function() {
|
|
2206
|
+
const sourceView = this.sourceView;
|
|
2207
|
+
if (!sourceView) return null;
|
|
2208
|
+
let sourceMagnet = null;
|
|
2209
|
+
// Check if the magnet is already found and cached.
|
|
2210
|
+
// We need to check if the cached magnet is still part of the source view.
|
|
2211
|
+
// The source view might have been disposed and recreated, or the magnet might have been changed.
|
|
2212
|
+
const cachedSourceMagnet = this._sourceMagnet;
|
|
2213
|
+
if (cachedSourceMagnet && sourceView.el.contains(cachedSourceMagnet)) {
|
|
2214
|
+
sourceMagnet = cachedSourceMagnet;
|
|
2215
|
+
} else {
|
|
2216
|
+
// If the cached magnet is not valid, we need to find the magnet.
|
|
2217
|
+
sourceMagnet = sourceView.getMagnetFromLinkEnd(this.model.attributes.source);
|
|
2218
|
+
}
|
|
2219
|
+
this._sourceMagnet = sourceMagnet;
|
|
2220
|
+
if (sourceMagnet === sourceView.el) {
|
|
2221
|
+
// If the source magnet is the element itself, we treat it as no magnet.
|
|
2222
|
+
return null;
|
|
2223
|
+
}
|
|
2224
|
+
return sourceMagnet;
|
|
2225
|
+
}
|
|
2226
|
+
});
|
|
2229
2227
|
|
|
2228
|
+
Object.defineProperty(LinkView.prototype, 'targetMagnet', {
|
|
2229
|
+
enumerable: true,
|
|
2230
|
+
|
|
2231
|
+
get: function() {
|
|
2232
|
+
const targetView = this.targetView;
|
|
2233
|
+
if (!targetView) return null;
|
|
2234
|
+
let targetMagnet = null;
|
|
2235
|
+
// Check if the magnet is already found and cached (See `sourceMagnet` for explanation).
|
|
2236
|
+
const cachedTargetMagnet = this._targetMagnet;
|
|
2237
|
+
if (cachedTargetMagnet && targetView.el.contains(cachedTargetMagnet)) {
|
|
2238
|
+
targetMagnet = cachedTargetMagnet;
|
|
2239
|
+
} else {
|
|
2240
|
+
// If the cached magnet is not valid, we need to find the magnet.
|
|
2241
|
+
targetMagnet = targetView.getMagnetFromLinkEnd(this.model.attributes.target);
|
|
2242
|
+
}
|
|
2243
|
+
this._targetMagnet = targetMagnet;
|
|
2244
|
+
if (targetMagnet === targetView.el) {
|
|
2245
|
+
// If the target magnet is the element itself, we treat it as no magnet.
|
|
2246
|
+
return null;
|
|
2247
|
+
}
|
|
2248
|
+
return targetMagnet;
|
|
2249
|
+
}
|
|
2250
|
+
});
|
|
2251
|
+
|
|
2252
|
+
Object.defineProperty(LinkView.prototype, 'sourceBBox', {
|
|
2230
2253
|
enumerable: true,
|
|
2231
2254
|
|
|
2232
2255
|
get: function() {
|
|
@@ -2241,11 +2264,9 @@ Object.defineProperty(LinkView.prototype, 'sourceBBox', {
|
|
|
2241
2264
|
}
|
|
2242
2265
|
return sourceView.getNodeBBox(sourceMagnet || sourceView.el);
|
|
2243
2266
|
}
|
|
2244
|
-
|
|
2245
2267
|
});
|
|
2246
2268
|
|
|
2247
2269
|
Object.defineProperty(LinkView.prototype, 'targetBBox', {
|
|
2248
|
-
|
|
2249
2270
|
enumerable: true,
|
|
2250
2271
|
|
|
2251
2272
|
get: function() {
|
|
@@ -2261,4 +2282,3 @@ Object.defineProperty(LinkView.prototype, 'targetBBox', {
|
|
|
2261
2282
|
return targetView.getNodeBBox(targetMagnet || targetView.el);
|
|
2262
2283
|
}
|
|
2263
2284
|
});
|
|
2264
|
-
|