@xyflow/system 0.0.21 → 0.0.22
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/dist/esm/constants.d.ts +0 -1
- package/dist/esm/constants.d.ts.map +1 -1
- package/dist/esm/index.js +297 -188
- package/dist/esm/index.mjs +297 -188
- package/dist/esm/types/general.d.ts +3 -3
- package/dist/esm/types/general.d.ts.map +1 -1
- package/dist/esm/types/index.d.ts +1 -0
- package/dist/esm/types/index.d.ts.map +1 -1
- package/dist/esm/types/nodes.d.ts +21 -15
- package/dist/esm/types/nodes.d.ts.map +1 -1
- package/dist/esm/utils/edges/general.d.ts +5 -6
- package/dist/esm/utils/edges/general.d.ts.map +1 -1
- package/dist/esm/utils/edges/positions.d.ts +3 -3
- package/dist/esm/utils/edges/positions.d.ts.map +1 -1
- package/dist/esm/utils/general.d.ts +3 -3
- package/dist/esm/utils/general.d.ts.map +1 -1
- package/dist/esm/utils/graph.d.ts +16 -5
- package/dist/esm/utils/graph.d.ts.map +1 -1
- package/dist/esm/utils/store.d.ts +5 -5
- package/dist/esm/utils/store.d.ts.map +1 -1
- package/dist/esm/xydrag/XYDrag.d.ts +2 -2
- package/dist/esm/xydrag/XYDrag.d.ts.map +1 -1
- package/dist/esm/xydrag/utils.d.ts +3 -3
- package/dist/esm/xydrag/utils.d.ts.map +1 -1
- package/dist/esm/xyhandle/XYHandle.d.ts +2 -2
- package/dist/esm/xyhandle/XYHandle.d.ts.map +1 -1
- package/dist/esm/xyhandle/utils.d.ts +4 -4
- package/dist/esm/xyhandle/utils.d.ts.map +1 -1
- package/dist/esm/xypanzoom/XYPanZoom.d.ts.map +1 -1
- package/dist/esm/xypanzoom/filter.d.ts.map +1 -1
- package/dist/umd/constants.d.ts +0 -1
- package/dist/umd/constants.d.ts.map +1 -1
- package/dist/umd/index.js +1 -1
- package/dist/umd/types/changes.d.ts +50 -0
- package/dist/umd/types/changes.d.ts.map +1 -0
- package/dist/umd/types/general.d.ts +3 -3
- package/dist/umd/types/general.d.ts.map +1 -1
- package/dist/umd/types/index.d.ts +1 -0
- package/dist/umd/types/index.d.ts.map +1 -1
- package/dist/umd/types/nodes.d.ts +21 -15
- package/dist/umd/types/nodes.d.ts.map +1 -1
- package/dist/umd/utils/edges/general.d.ts +5 -6
- package/dist/umd/utils/edges/general.d.ts.map +1 -1
- package/dist/umd/utils/edges/positions.d.ts +3 -3
- package/dist/umd/utils/edges/positions.d.ts.map +1 -1
- package/dist/umd/utils/general.d.ts +3 -3
- package/dist/umd/utils/general.d.ts.map +1 -1
- package/dist/umd/utils/graph.d.ts +16 -5
- package/dist/umd/utils/graph.d.ts.map +1 -1
- package/dist/umd/utils/store.d.ts +5 -5
- package/dist/umd/utils/store.d.ts.map +1 -1
- package/dist/umd/xydrag/XYDrag.d.ts +2 -2
- package/dist/umd/xydrag/XYDrag.d.ts.map +1 -1
- package/dist/umd/xydrag/utils.d.ts +3 -3
- package/dist/umd/xydrag/utils.d.ts.map +1 -1
- package/dist/umd/xyhandle/XYHandle.d.ts +2 -2
- package/dist/umd/xyhandle/XYHandle.d.ts.map +1 -1
- package/dist/umd/xyhandle/utils.d.ts +4 -4
- package/dist/umd/xyhandle/utils.d.ts.map +1 -1
- package/dist/umd/xypanzoom/XYPanZoom.d.ts.map +1 -1
- package/dist/umd/xypanzoom/filter.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/esm/index.js
CHANGED
|
@@ -17,7 +17,6 @@ const errorMessages = {
|
|
|
17
17
|
error011: (edgeType) => `Edge type "${edgeType}" not found. Using fallback type "default".`,
|
|
18
18
|
error012: (id) => `Node with id "${id}" does not exist, it may have been removed. This can happen when a node is deleted before the "onNodeClick" handler is called.`,
|
|
19
19
|
};
|
|
20
|
-
const internalsSymbol = Symbol.for('internals');
|
|
21
20
|
const infiniteExtent = [
|
|
22
21
|
[Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY],
|
|
23
22
|
[Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY],
|
|
@@ -120,6 +119,7 @@ const isEdgeBase = (element) => 'id' in element && 'source' in element && 'targe
|
|
|
120
119
|
* @returns A boolean indicating whether the element is an Node
|
|
121
120
|
*/
|
|
122
121
|
const isNodeBase = (element) => 'id' in element && 'position' in element && !('source' in element) && !('target' in element);
|
|
122
|
+
const isInternalNodeBase = (element) => 'id' in element && 'internals' in element && !('source' in element) && !('target' in element);
|
|
123
123
|
/**
|
|
124
124
|
* Pass in a node, and get connected nodes where edge.source === node.id
|
|
125
125
|
* @public
|
|
@@ -182,10 +182,10 @@ const getNodePositionWithOrigin = (node, nodeOrigin = [0, 0]) => {
|
|
|
182
182
|
};
|
|
183
183
|
return {
|
|
184
184
|
position,
|
|
185
|
-
positionAbsolute: node
|
|
185
|
+
positionAbsolute: 'internals' in node
|
|
186
186
|
? {
|
|
187
|
-
x: node.
|
|
188
|
-
y: node.
|
|
187
|
+
x: node.internals.positionAbsolute.x - offsetX,
|
|
188
|
+
y: node.internals.positionAbsolute.y - offsetY,
|
|
189
189
|
}
|
|
190
190
|
: position,
|
|
191
191
|
};
|
|
@@ -199,6 +199,7 @@ const getNodePositionWithOrigin = (node, nodeOrigin = [0, 0]) => {
|
|
|
199
199
|
* @param params.useRelativePosition - Whether to use the relative or absolute node positions
|
|
200
200
|
* @returns Bounding box enclosing all nodes
|
|
201
201
|
*/
|
|
202
|
+
// @todo how to handle this if users do not have absolute positions?
|
|
202
203
|
const getNodesBounds = (nodes, params = { nodeOrigin: [0, 0], useRelativePosition: false }) => {
|
|
203
204
|
if (nodes.length === 0) {
|
|
204
205
|
return { x: 0, y: 0, width: 0, height: 0 };
|
|
@@ -212,7 +213,30 @@ const getNodesBounds = (nodes, params = { nodeOrigin: [0, 0], useRelativePositio
|
|
|
212
213
|
}, { x: Infinity, y: Infinity, x2: -Infinity, y2: -Infinity });
|
|
213
214
|
return boxToRect(box);
|
|
214
215
|
};
|
|
215
|
-
|
|
216
|
+
/**
|
|
217
|
+
* Determines a bounding box that contains all given nodes in an array
|
|
218
|
+
* @internal
|
|
219
|
+
*/
|
|
220
|
+
const getInternalNodesBounds = (nodeLookup, params = {
|
|
221
|
+
nodeOrigin: [0, 0],
|
|
222
|
+
useRelativePosition: false,
|
|
223
|
+
}) => {
|
|
224
|
+
if (nodeLookup.size === 0) {
|
|
225
|
+
return { x: 0, y: 0, width: 0, height: 0 };
|
|
226
|
+
}
|
|
227
|
+
let box = { x: Infinity, y: Infinity, x2: -Infinity, y2: -Infinity };
|
|
228
|
+
nodeLookup.forEach((node) => {
|
|
229
|
+
if (params.filter == undefined || params.filter(node)) {
|
|
230
|
+
const nodePos = getNodePositionWithOrigin(node, node.origin || params.nodeOrigin);
|
|
231
|
+
box = getBoundsOfBoxes(box, rectToBox({
|
|
232
|
+
...nodePos[params.useRelativePosition ? 'position' : 'positionAbsolute'],
|
|
233
|
+
...getNodeDimensions(node),
|
|
234
|
+
}));
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
return boxToRect(box);
|
|
238
|
+
};
|
|
239
|
+
const getNodesInside = (nodeLookup, rect, [tx, ty, tScale] = [0, 0, 1], partially = false,
|
|
216
240
|
// set excludeNonSelectableNodes if you want to pay attention to the nodes "selectable" attribute
|
|
217
241
|
excludeNonSelectableNodes = false, nodeOrigin = [0, 0]) => {
|
|
218
242
|
const paneRect = {
|
|
@@ -220,12 +244,13 @@ excludeNonSelectableNodes = false, nodeOrigin = [0, 0]) => {
|
|
|
220
244
|
width: rect.width / tScale,
|
|
221
245
|
height: rect.height / tScale,
|
|
222
246
|
};
|
|
223
|
-
const visibleNodes =
|
|
224
|
-
|
|
225
|
-
const
|
|
226
|
-
const
|
|
247
|
+
const visibleNodes = [];
|
|
248
|
+
for (const [, node] of nodeLookup) {
|
|
249
|
+
const { measured, selectable = true, hidden = false } = node;
|
|
250
|
+
const width = measured.width ?? node.width ?? node.initialWidth ?? null;
|
|
251
|
+
const height = measured.height ?? node.height ?? node.initialHeight ?? null;
|
|
227
252
|
if ((excludeNonSelectableNodes && !selectable) || hidden) {
|
|
228
|
-
|
|
253
|
+
continue;
|
|
229
254
|
}
|
|
230
255
|
const overlappingArea = getOverlappingArea(paneRect, nodeToRect(node, nodeOrigin));
|
|
231
256
|
const notInitialized = width === null || height === null;
|
|
@@ -233,10 +258,9 @@ excludeNonSelectableNodes = false, nodeOrigin = [0, 0]) => {
|
|
|
233
258
|
const area = (width ?? 0) * (height ?? 0);
|
|
234
259
|
const isVisible = notInitialized || partiallyVisible || overlappingArea >= area;
|
|
235
260
|
if (isVisible || node.dragging) {
|
|
236
|
-
|
|
261
|
+
visibleNodes.push(node);
|
|
237
262
|
}
|
|
238
|
-
|
|
239
|
-
}, []);
|
|
263
|
+
}
|
|
240
264
|
return visibleNodes;
|
|
241
265
|
};
|
|
242
266
|
/**
|
|
@@ -252,13 +276,14 @@ const getConnectedEdges = (nodes, edges) => {
|
|
|
252
276
|
});
|
|
253
277
|
return edges.filter((edge) => nodeIds.has(edge.source) || nodeIds.has(edge.target));
|
|
254
278
|
};
|
|
255
|
-
function fitView({
|
|
256
|
-
const filteredNodes =
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
279
|
+
function fitView({ nodeLookup, width, height, panZoom, minZoom, maxZoom, nodeOrigin = [0, 0] }, options) {
|
|
280
|
+
const filteredNodes = [];
|
|
281
|
+
nodeLookup.forEach((n) => {
|
|
282
|
+
const isVisible = n.measured.width && n.measured.height && (options?.includeHiddenNodes || !n.hidden);
|
|
283
|
+
if (isVisible &&
|
|
284
|
+
(!options?.nodes || (options?.nodes.length && options?.nodes.some((optionNode) => optionNode.id === n.id)))) {
|
|
285
|
+
filteredNodes.push(n);
|
|
260
286
|
}
|
|
261
|
-
return isVisible;
|
|
262
287
|
});
|
|
263
288
|
if (filteredNodes.length > 0) {
|
|
264
289
|
const bounds = getNodesBounds(filteredNodes, { nodeOrigin });
|
|
@@ -280,7 +305,7 @@ function clampNodeExtent(node, extent) {
|
|
|
280
305
|
if (!extent || extent === 'parent') {
|
|
281
306
|
return extent;
|
|
282
307
|
}
|
|
283
|
-
return [extent[0], [extent[1][0] - (node.
|
|
308
|
+
return [extent[0], [extent[1][0] - (node.measured?.width ?? 0), extent[1][1] - (node.measured?.height ?? 0)]];
|
|
284
309
|
}
|
|
285
310
|
/**
|
|
286
311
|
* This function calculates the next position of a node, taking into account the node's extent, parent node, and origin.
|
|
@@ -290,7 +315,7 @@ function clampNodeExtent(node, extent) {
|
|
|
290
315
|
*/
|
|
291
316
|
function calculateNodePosition({ nodeId, nextPosition, nodeLookup, nodeOrigin = [0, 0], nodeExtent, onError, }) {
|
|
292
317
|
const node = nodeLookup.get(nodeId);
|
|
293
|
-
const parentNode = node.
|
|
318
|
+
const parentNode = node.parentId ? nodeLookup.get(node.parentId) : undefined;
|
|
294
319
|
const { x: parentX, y: parentY } = parentNode
|
|
295
320
|
? getNodePositionWithOrigin(parentNode, parentNode.origin || nodeOrigin).positionAbsolute
|
|
296
321
|
: { x: 0, y: 0 };
|
|
@@ -300,10 +325,10 @@ function calculateNodePosition({ nodeId, nextPosition, nodeLookup, nodeOrigin =
|
|
|
300
325
|
onError?.('005', errorMessages['error005']());
|
|
301
326
|
}
|
|
302
327
|
else {
|
|
303
|
-
const nodeWidth = node.
|
|
304
|
-
const nodeHeight = node.
|
|
305
|
-
const parentWidth = parentNode
|
|
306
|
-
const parentHeight = parentNode
|
|
328
|
+
const nodeWidth = node.measured.width;
|
|
329
|
+
const nodeHeight = node.measured.height;
|
|
330
|
+
const parentWidth = parentNode.measured.width;
|
|
331
|
+
const parentHeight = parentNode.measured.height;
|
|
307
332
|
if (nodeWidth && nodeHeight && parentWidth && parentHeight) {
|
|
308
333
|
const currNodeOrigin = node.origin || nodeOrigin;
|
|
309
334
|
const extentX = parentX + nodeWidth * currNodeOrigin[0];
|
|
@@ -350,7 +375,7 @@ async function getElementsToRemove({ nodesToRemove = [], edgesToRemove = [], nod
|
|
|
350
375
|
continue;
|
|
351
376
|
}
|
|
352
377
|
const isIncluded = nodeIds.includes(node.id);
|
|
353
|
-
const parentHit = !isIncluded && node.
|
|
378
|
+
const parentHit = !isIncluded && node.parentId && matchingNodes.find((n) => n.id === node.parentId);
|
|
354
379
|
if (isIncluded || parentHit) {
|
|
355
380
|
matchingNodes.push(node);
|
|
356
381
|
}
|
|
@@ -430,16 +455,16 @@ const nodeToRect = (node, nodeOrigin = [0, 0]) => {
|
|
|
430
455
|
const { positionAbsolute } = getNodePositionWithOrigin(node, node.origin || nodeOrigin);
|
|
431
456
|
return {
|
|
432
457
|
...positionAbsolute,
|
|
433
|
-
width: node.
|
|
434
|
-
height: node.
|
|
458
|
+
width: node.measured?.width ?? node.width ?? 0,
|
|
459
|
+
height: node.measured?.height ?? node.height ?? 0,
|
|
435
460
|
};
|
|
436
461
|
};
|
|
437
462
|
const nodeToBox = (node, nodeOrigin = [0, 0]) => {
|
|
438
463
|
const { positionAbsolute } = getNodePositionWithOrigin(node, node.origin || nodeOrigin);
|
|
439
464
|
return {
|
|
440
465
|
...positionAbsolute,
|
|
441
|
-
x2: positionAbsolute.x + (node.
|
|
442
|
-
y2: positionAbsolute.y + (node.
|
|
466
|
+
x2: positionAbsolute.x + (node.measured?.width ?? node.width ?? 0),
|
|
467
|
+
y2: positionAbsolute.y + (node.measured?.height ?? node.height ?? 0),
|
|
443
468
|
};
|
|
444
469
|
};
|
|
445
470
|
const getBoundsOfRects = (rect1, rect2) => boxToRect(getBoundsOfBoxes(rectToBox(rect1), rectToBox(rect2)));
|
|
@@ -519,13 +544,13 @@ function isCoordinateExtent(extent) {
|
|
|
519
544
|
}
|
|
520
545
|
function getNodeDimensions(node) {
|
|
521
546
|
return {
|
|
522
|
-
width: node.
|
|
523
|
-
height: node.
|
|
547
|
+
width: node.measured?.width ?? node.width ?? node.initialWidth ?? 0,
|
|
548
|
+
height: node.measured?.height ?? node.height ?? node.initialHeight ?? 0,
|
|
524
549
|
};
|
|
525
550
|
}
|
|
526
551
|
function nodeHasDimensions(node) {
|
|
527
|
-
return ((node.
|
|
528
|
-
(node.
|
|
552
|
+
return ((node.measured?.width ?? node.width ?? node.initialWidth) !== undefined &&
|
|
553
|
+
(node.measured?.height ?? node.height ?? node.initialHeight) !== undefined);
|
|
529
554
|
}
|
|
530
555
|
|
|
531
556
|
function getPointerPosition(event, { snapGrid = [0, 0], snapToGrid = false, transform }) {
|
|
@@ -688,7 +713,7 @@ function getElevatedEdgeZIndex({ sourceNode, targetNode, selected = false, zInde
|
|
|
688
713
|
return zIndex;
|
|
689
714
|
}
|
|
690
715
|
const edgeOrConnectedNodeSelected = selected || targetNode.selected || sourceNode.selected;
|
|
691
|
-
const selectedZIndex = Math.max(sourceNode
|
|
716
|
+
const selectedZIndex = Math.max(sourceNode.internals.z || 0, targetNode.internals.z || 0, 1000);
|
|
692
717
|
return zIndex + (edgeOrConnectedNodeSelected ? selectedZIndex : 0);
|
|
693
718
|
}
|
|
694
719
|
function isEdgeVisible({ sourceNode, targetNode, width, height, transform }) {
|
|
@@ -993,16 +1018,17 @@ function getSmoothStepPath({ sourceX, sourceY, sourcePosition = Position.Bottom,
|
|
|
993
1018
|
}
|
|
994
1019
|
|
|
995
1020
|
function isNodeInitialized(node) {
|
|
996
|
-
return (
|
|
997
|
-
!!(node
|
|
1021
|
+
return (node &&
|
|
1022
|
+
!!(node.internals.handleBounds || node.handles?.length) &&
|
|
1023
|
+
!!(node.measured.width || node.width || node.initialWidth));
|
|
998
1024
|
}
|
|
999
1025
|
function getEdgePosition(params) {
|
|
1000
1026
|
const { sourceNode, targetNode } = params;
|
|
1001
1027
|
if (!isNodeInitialized(sourceNode) || !isNodeInitialized(targetNode)) {
|
|
1002
1028
|
return null;
|
|
1003
1029
|
}
|
|
1004
|
-
const sourceHandleBounds = sourceNode
|
|
1005
|
-
const targetHandleBounds = targetNode
|
|
1030
|
+
const sourceHandleBounds = sourceNode.internals.handleBounds || toHandleBounds(sourceNode.handles);
|
|
1031
|
+
const targetHandleBounds = targetNode.internals.handleBounds || toHandleBounds(targetNode.handles);
|
|
1006
1032
|
const sourceHandle = getHandle(sourceHandleBounds?.source ?? [], params.sourceHandle);
|
|
1007
1033
|
const targetHandle = getHandle(
|
|
1008
1034
|
// when connection type is loose we can define all handles as sources and connect source -> source
|
|
@@ -1052,8 +1078,8 @@ function toHandleBounds(handles) {
|
|
|
1052
1078
|
};
|
|
1053
1079
|
}
|
|
1054
1080
|
function getHandlePosition(position, node, handle = null) {
|
|
1055
|
-
const x = (handle?.x ?? 0) + (node.
|
|
1056
|
-
const y = (handle?.y ?? 0) + (node.
|
|
1081
|
+
const x = (handle?.x ?? 0) + (node.internals.positionAbsolute?.x ?? 0);
|
|
1082
|
+
const y = (handle?.y ?? 0) + (node.internals.positionAbsolute?.y ?? 0);
|
|
1057
1083
|
const { width, height } = handle ?? getNodeDimensions(node);
|
|
1058
1084
|
switch (position) {
|
|
1059
1085
|
case Position.Top:
|
|
@@ -1144,111 +1170,176 @@ function getNodeToolbarTransform(nodeRect, viewport, position, offset, align) {
|
|
|
1144
1170
|
return `translate(${pos[0]}px, ${pos[1]}px) translate(${shift[0]}%, ${shift[1]}%)`;
|
|
1145
1171
|
}
|
|
1146
1172
|
|
|
1147
|
-
function updateAbsolutePositions(
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1173
|
+
function updateAbsolutePositions(nodeLookup, options = {
|
|
1174
|
+
nodeOrigin: [0, 0],
|
|
1175
|
+
elevateNodesOnSelect: true,
|
|
1176
|
+
defaults: {},
|
|
1177
|
+
}, parentNodeIds) {
|
|
1178
|
+
const selectedNodeZ = options?.elevateNodesOnSelect ? 1000 : 0;
|
|
1179
|
+
for (const [id, node] of nodeLookup) {
|
|
1180
|
+
const parentId = node.parentId;
|
|
1181
|
+
if (parentId && !nodeLookup.has(parentId)) {
|
|
1182
|
+
throw new Error(`Parent node ${parentId} not found`);
|
|
1183
|
+
}
|
|
1184
|
+
if (parentId || node.internals.isParent || parentNodeIds?.has(id)) {
|
|
1185
|
+
const parentNode = parentId ? nodeLookup.get(parentId) : null;
|
|
1186
|
+
const { x, y, z } = calculateXYZPosition(node, nodeLookup, {
|
|
1155
1187
|
...node.position,
|
|
1156
|
-
z: node
|
|
1157
|
-
}, parentNode?.origin || nodeOrigin);
|
|
1158
|
-
const
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
: node.computed?.positionAbsolute;
|
|
1165
|
-
node[internalsSymbol].z = z;
|
|
1166
|
-
if (parentNodes?.[node.id]) {
|
|
1167
|
-
node[internalsSymbol].isParent = true;
|
|
1188
|
+
z: (isNumeric(node.zIndex) ? node.zIndex : 0) + (node.selected ? selectedNodeZ : 0),
|
|
1189
|
+
}, parentNode?.origin || options.nodeOrigin);
|
|
1190
|
+
const currPosition = node.internals.positionAbsolute;
|
|
1191
|
+
const positionChanged = x !== currPosition.x || y !== currPosition.y;
|
|
1192
|
+
node.internals.positionAbsolute = positionChanged ? { x, y } : currPosition;
|
|
1193
|
+
node.internals.z = z;
|
|
1194
|
+
if (parentNodeIds !== undefined) {
|
|
1195
|
+
node.internals.isParent = !!parentNodeIds?.has(id);
|
|
1168
1196
|
}
|
|
1197
|
+
nodeLookup.set(id, node);
|
|
1169
1198
|
}
|
|
1170
|
-
|
|
1171
|
-
});
|
|
1199
|
+
}
|
|
1172
1200
|
}
|
|
1173
|
-
function
|
|
1201
|
+
function adoptUserNodes(nodes, nodeLookup, options = {
|
|
1174
1202
|
nodeOrigin: [0, 0],
|
|
1175
1203
|
elevateNodesOnSelect: true,
|
|
1176
1204
|
defaults: {},
|
|
1177
1205
|
}) {
|
|
1178
1206
|
const tmpLookup = new Map(nodeLookup);
|
|
1179
1207
|
nodeLookup.clear();
|
|
1180
|
-
const parentNodes = {};
|
|
1181
1208
|
const selectedNodeZ = options?.elevateNodesOnSelect ? 1000 : 0;
|
|
1182
|
-
const
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
}
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
},
|
|
1209
|
-
});
|
|
1210
|
-
nodeLookup.set(node.id, node);
|
|
1211
|
-
return node;
|
|
1209
|
+
const parentNodeIds = new Set();
|
|
1210
|
+
nodes.forEach((userNode) => {
|
|
1211
|
+
const currentStoreNode = tmpLookup.get(userNode.id);
|
|
1212
|
+
if (userNode.parentId) {
|
|
1213
|
+
parentNodeIds.add(userNode.parentId);
|
|
1214
|
+
}
|
|
1215
|
+
if (userNode === currentStoreNode?.internals.userNode) {
|
|
1216
|
+
nodeLookup.set(userNode.id, currentStoreNode);
|
|
1217
|
+
}
|
|
1218
|
+
else {
|
|
1219
|
+
nodeLookup.set(userNode.id, {
|
|
1220
|
+
...options.defaults,
|
|
1221
|
+
...userNode,
|
|
1222
|
+
measured: {
|
|
1223
|
+
width: userNode.measured?.width,
|
|
1224
|
+
height: userNode.measured?.height,
|
|
1225
|
+
},
|
|
1226
|
+
internals: {
|
|
1227
|
+
positionAbsolute: userNode.position,
|
|
1228
|
+
handleBounds: currentStoreNode?.internals?.handleBounds,
|
|
1229
|
+
z: (isNumeric(userNode.zIndex) ? userNode.zIndex : 0) + (userNode.selected ? selectedNodeZ : 0),
|
|
1230
|
+
userNode,
|
|
1231
|
+
isParent: false,
|
|
1232
|
+
},
|
|
1233
|
+
});
|
|
1234
|
+
}
|
|
1212
1235
|
});
|
|
1213
|
-
|
|
1214
|
-
|
|
1236
|
+
if (parentNodeIds.size > 0) {
|
|
1237
|
+
updateAbsolutePositions(nodeLookup, options, parentNodeIds);
|
|
1238
|
+
}
|
|
1215
1239
|
}
|
|
1216
|
-
function calculateXYZPosition(node,
|
|
1217
|
-
if (!node.
|
|
1240
|
+
function calculateXYZPosition(node, nodeLookup, result, nodeOrigin = [0, 0]) {
|
|
1241
|
+
if (!node.parentId) {
|
|
1218
1242
|
return result;
|
|
1219
1243
|
}
|
|
1220
|
-
const parentNode = nodeLookup.get(node.
|
|
1244
|
+
const parentNode = nodeLookup.get(node.parentId);
|
|
1221
1245
|
const { position: parentNodePosition } = getNodePositionWithOrigin(parentNode, parentNode?.origin || nodeOrigin);
|
|
1222
|
-
return calculateXYZPosition(parentNode,
|
|
1246
|
+
return calculateXYZPosition(parentNode, nodeLookup, {
|
|
1223
1247
|
x: (result.x ?? 0) + parentNodePosition.x,
|
|
1224
1248
|
y: (result.y ?? 0) + parentNodePosition.y,
|
|
1225
|
-
z: (parentNode
|
|
1249
|
+
z: (parentNode.internals.z ?? 0) > (result.z ?? 0) ? parentNode.internals.z ?? 0 : result.z ?? 0,
|
|
1226
1250
|
}, parentNode.origin || nodeOrigin);
|
|
1227
1251
|
}
|
|
1228
|
-
function
|
|
1252
|
+
function handleParentExpand(nodes, nodeLookup) {
|
|
1253
|
+
const changes = [];
|
|
1254
|
+
const chilNodeRects = new Map();
|
|
1255
|
+
nodes.forEach((node) => {
|
|
1256
|
+
const parentId = node.parentId;
|
|
1257
|
+
if (node.expandParent && parentId) {
|
|
1258
|
+
const parentNode = nodeLookup.get(parentId);
|
|
1259
|
+
if (parentNode) {
|
|
1260
|
+
const parentRect = chilNodeRects.get(parentId) || nodeToRect(parentNode, node.origin);
|
|
1261
|
+
const expandedRect = getBoundsOfRects(parentRect, nodeToRect(node, node.origin));
|
|
1262
|
+
chilNodeRects.set(parentId, expandedRect);
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
});
|
|
1266
|
+
if (chilNodeRects.size > 0) {
|
|
1267
|
+
chilNodeRects.forEach((rect, id) => {
|
|
1268
|
+
const origParent = nodeLookup.get(id);
|
|
1269
|
+
const { position } = getNodePositionWithOrigin(origParent, origParent.origin);
|
|
1270
|
+
const dimensions = getNodeDimensions(origParent);
|
|
1271
|
+
if (rect.x < position.x || rect.y < position.y) {
|
|
1272
|
+
const xChange = Math.round(Math.abs(position.x - rect.x));
|
|
1273
|
+
const yChange = Math.round(Math.abs(position.y - rect.y));
|
|
1274
|
+
changes.push({
|
|
1275
|
+
id,
|
|
1276
|
+
type: 'position',
|
|
1277
|
+
position: {
|
|
1278
|
+
x: position.x - xChange,
|
|
1279
|
+
y: position.y - yChange,
|
|
1280
|
+
},
|
|
1281
|
+
});
|
|
1282
|
+
changes.push({
|
|
1283
|
+
id,
|
|
1284
|
+
type: 'dimensions',
|
|
1285
|
+
resizing: true,
|
|
1286
|
+
dimensions: {
|
|
1287
|
+
width: dimensions.width + xChange,
|
|
1288
|
+
height: dimensions.height + yChange,
|
|
1289
|
+
},
|
|
1290
|
+
});
|
|
1291
|
+
// @todo we need to reset child node positions if < 0
|
|
1292
|
+
}
|
|
1293
|
+
else if (dimensions.width < rect.width || dimensions.height < rect.height) {
|
|
1294
|
+
changes.push({
|
|
1295
|
+
id,
|
|
1296
|
+
type: 'dimensions',
|
|
1297
|
+
resizing: true,
|
|
1298
|
+
dimensions: {
|
|
1299
|
+
width: Math.max(dimensions.width, rect.width),
|
|
1300
|
+
height: Math.max(dimensions.height, rect.height),
|
|
1301
|
+
},
|
|
1302
|
+
});
|
|
1303
|
+
}
|
|
1304
|
+
});
|
|
1305
|
+
}
|
|
1306
|
+
return changes;
|
|
1307
|
+
}
|
|
1308
|
+
function updateNodeDimensions(updates, nodeLookup, domNode, nodeOrigin) {
|
|
1229
1309
|
const viewportNode = domNode?.querySelector('.xyflow__viewport');
|
|
1230
1310
|
if (!viewportNode) {
|
|
1231
|
-
return
|
|
1311
|
+
return [];
|
|
1232
1312
|
}
|
|
1313
|
+
const changes = [];
|
|
1233
1314
|
const style = window.getComputedStyle(viewportNode);
|
|
1234
1315
|
const { m22: zoom } = new window.DOMMatrixReadOnly(style.transform);
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1316
|
+
// in this array we collect nodes, that might trigger changes (like expanding parent)
|
|
1317
|
+
const triggerChangeNodes = [];
|
|
1318
|
+
updates.forEach((update) => {
|
|
1319
|
+
const node = nodeLookup.get(update.id);
|
|
1320
|
+
if (node?.hidden) {
|
|
1321
|
+
nodeLookup.set(node.id, {
|
|
1322
|
+
...node,
|
|
1323
|
+
internals: {
|
|
1324
|
+
...node.internals,
|
|
1325
|
+
handleBounds: undefined,
|
|
1326
|
+
},
|
|
1327
|
+
});
|
|
1328
|
+
}
|
|
1329
|
+
else if (node) {
|
|
1238
1330
|
const dimensions = getDimensions(update.nodeElement);
|
|
1239
1331
|
const doUpdate = !!(dimensions.width &&
|
|
1240
1332
|
dimensions.height &&
|
|
1241
|
-
(node.
|
|
1333
|
+
(node.measured?.width !== dimensions.width || node.measured?.height !== dimensions.height || update.force));
|
|
1242
1334
|
if (doUpdate) {
|
|
1243
|
-
onUpdate?.(node.id, dimensions);
|
|
1244
1335
|
const newNode = {
|
|
1245
1336
|
...node,
|
|
1246
|
-
|
|
1247
|
-
...node.
|
|
1337
|
+
measured: {
|
|
1338
|
+
...node.measured,
|
|
1248
1339
|
...dimensions,
|
|
1249
1340
|
},
|
|
1250
|
-
|
|
1251
|
-
...node
|
|
1341
|
+
internals: {
|
|
1342
|
+
...node.internals,
|
|
1252
1343
|
handleBounds: {
|
|
1253
1344
|
source: getHandleBounds('.source', update.nodeElement, zoom, node.origin || nodeOrigin),
|
|
1254
1345
|
target: getHandleBounds('.target', update.nodeElement, zoom, node.origin || nodeOrigin),
|
|
@@ -1256,12 +1347,22 @@ function updateNodeDimensions(updates, nodes, nodeLookup, domNode, nodeOrigin, o
|
|
|
1256
1347
|
},
|
|
1257
1348
|
};
|
|
1258
1349
|
nodeLookup.set(node.id, newNode);
|
|
1259
|
-
|
|
1350
|
+
changes.push({
|
|
1351
|
+
id: newNode.id,
|
|
1352
|
+
type: 'dimensions',
|
|
1353
|
+
dimensions,
|
|
1354
|
+
});
|
|
1355
|
+
if (newNode.expandParent) {
|
|
1356
|
+
triggerChangeNodes.push(newNode);
|
|
1357
|
+
}
|
|
1260
1358
|
}
|
|
1261
1359
|
}
|
|
1262
|
-
return node;
|
|
1263
1360
|
});
|
|
1264
|
-
|
|
1361
|
+
if (triggerChangeNodes.length > 0) {
|
|
1362
|
+
const parentExpandChanges = handleParentExpand(triggerChangeNodes, nodeLookup);
|
|
1363
|
+
changes.push(...parentExpandChanges);
|
|
1364
|
+
}
|
|
1365
|
+
return changes;
|
|
1265
1366
|
}
|
|
1266
1367
|
function panBy({ delta, panZoom, transform, translateExtent, width, height, }) {
|
|
1267
1368
|
if (!panZoom || (!delta.x && !delta.y)) {
|
|
@@ -1315,18 +1416,18 @@ function shallowNodeData(a, b) {
|
|
|
1315
1416
|
function wrapSelectionDragFunc(selectionFunc) {
|
|
1316
1417
|
return (event, _, nodes) => selectionFunc?.(event, nodes);
|
|
1317
1418
|
}
|
|
1318
|
-
function isParentSelected(node,
|
|
1319
|
-
if (!node.
|
|
1419
|
+
function isParentSelected(node, nodeLookup) {
|
|
1420
|
+
if (!node.parentId) {
|
|
1320
1421
|
return false;
|
|
1321
1422
|
}
|
|
1322
|
-
const parentNode =
|
|
1423
|
+
const parentNode = nodeLookup.get(node.parentId);
|
|
1323
1424
|
if (!parentNode) {
|
|
1324
1425
|
return false;
|
|
1325
1426
|
}
|
|
1326
1427
|
if (parentNode.selected) {
|
|
1327
1428
|
return true;
|
|
1328
1429
|
}
|
|
1329
|
-
return isParentSelected(parentNode,
|
|
1430
|
+
return isParentSelected(parentNode, nodeLookup);
|
|
1330
1431
|
}
|
|
1331
1432
|
function hasSelector(target, selector, domNode) {
|
|
1332
1433
|
let current = target;
|
|
@@ -1340,32 +1441,35 @@ function hasSelector(target, selector, domNode) {
|
|
|
1340
1441
|
return false;
|
|
1341
1442
|
}
|
|
1342
1443
|
// looks for all selected nodes and created a NodeDragItem for each of them
|
|
1343
|
-
function getDragItems(
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
(
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1444
|
+
function getDragItems(nodeLookup, nodesDraggable, mousePos, nodeId) {
|
|
1445
|
+
const dragItems = [];
|
|
1446
|
+
for (const [id, node] of nodeLookup) {
|
|
1447
|
+
if ((node.selected || node.id === nodeId) &&
|
|
1448
|
+
(!node.parentId || !isParentSelected(node, nodeLookup)) &&
|
|
1449
|
+
(node.draggable || (nodesDraggable && typeof node.draggable === 'undefined'))) {
|
|
1450
|
+
const internalNode = nodeLookup.get(id);
|
|
1451
|
+
dragItems.push({
|
|
1452
|
+
id: internalNode.id,
|
|
1453
|
+
position: internalNode.position || { x: 0, y: 0 },
|
|
1454
|
+
distance: {
|
|
1455
|
+
x: mousePos.x - (internalNode.internals.positionAbsolute?.x ?? 0),
|
|
1456
|
+
y: mousePos.y - (internalNode.internals.positionAbsolute?.y ?? 0),
|
|
1457
|
+
},
|
|
1458
|
+
extent: internalNode.extent,
|
|
1459
|
+
parentId: internalNode.parentId,
|
|
1460
|
+
origin: internalNode.origin,
|
|
1461
|
+
expandParent: internalNode.expandParent,
|
|
1462
|
+
internals: {
|
|
1463
|
+
positionAbsolute: internalNode.internals.positionAbsolute || { x: 0, y: 0 },
|
|
1464
|
+
},
|
|
1465
|
+
measured: {
|
|
1466
|
+
width: internalNode.measured.width || 0,
|
|
1467
|
+
height: internalNode.measured.height || 0,
|
|
1468
|
+
},
|
|
1469
|
+
});
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
return dragItems;
|
|
1369
1473
|
}
|
|
1370
1474
|
// returns two params:
|
|
1371
1475
|
// 1. the dragged node (or the first of the list, if we are dragging a node selection)
|
|
@@ -1376,9 +1480,8 @@ function getEventHandlerParams({ nodeId, dragItems, nodeLookup, }) {
|
|
|
1376
1480
|
return {
|
|
1377
1481
|
...node,
|
|
1378
1482
|
position: n.position,
|
|
1379
|
-
|
|
1380
|
-
...n.
|
|
1381
|
-
positionAbsolute: n.computed.positionAbsolute,
|
|
1483
|
+
measured: {
|
|
1484
|
+
...n.measured,
|
|
1382
1485
|
},
|
|
1383
1486
|
};
|
|
1384
1487
|
});
|
|
@@ -1414,17 +1517,20 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
|
|
|
1414
1517
|
}
|
|
1415
1518
|
// if there is selection with multiple nodes and a node extent is set, we need to adjust the node extent for each node
|
|
1416
1519
|
// based on its position so that the node stays at it's position relative to the selection.
|
|
1417
|
-
|
|
1520
|
+
let adjustedNodeExtent = [
|
|
1418
1521
|
[nodeExtent[0][0], nodeExtent[0][1]],
|
|
1419
1522
|
[nodeExtent[1][0], nodeExtent[1][1]],
|
|
1420
1523
|
];
|
|
1421
1524
|
if (dragItems.length > 1 && nodeExtent && !n.extent) {
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1525
|
+
const { positionAbsolute } = n.internals;
|
|
1526
|
+
const x1 = positionAbsolute.x - nodesBox.x + nodeExtent[0][0];
|
|
1527
|
+
const x2 = positionAbsolute.x + (n.measured?.width ?? 0) - nodesBox.x2 + nodeExtent[1][0];
|
|
1528
|
+
const y1 = positionAbsolute.y - nodesBox.y + nodeExtent[0][1];
|
|
1529
|
+
const y2 = positionAbsolute.y + (n.measured?.height ?? 0) - nodesBox.y2 + nodeExtent[1][1];
|
|
1530
|
+
adjustedNodeExtent = [
|
|
1531
|
+
[x1, y1],
|
|
1532
|
+
[x2, y2],
|
|
1533
|
+
];
|
|
1428
1534
|
}
|
|
1429
1535
|
const { position, positionAbsolute } = calculateNodePosition({
|
|
1430
1536
|
nodeId: n.id,
|
|
@@ -1437,7 +1543,7 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
|
|
|
1437
1543
|
// we want to make sure that we only fire a change event when there is a change
|
|
1438
1544
|
hasChange = hasChange || n.position.x !== position.x || n.position.y !== position.y;
|
|
1439
1545
|
n.position = position;
|
|
1440
|
-
n.
|
|
1546
|
+
n.internals.positionAbsolute = positionAbsolute;
|
|
1441
1547
|
return n;
|
|
1442
1548
|
});
|
|
1443
1549
|
if (!hasChange) {
|
|
@@ -1474,7 +1580,7 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
|
|
|
1474
1580
|
autoPanId = requestAnimationFrame(autoPan);
|
|
1475
1581
|
}
|
|
1476
1582
|
function startDrag(event) {
|
|
1477
|
-
const {
|
|
1583
|
+
const { nodeLookup, multiSelectionActive, nodesDraggable, transform, snapGrid, snapToGrid, selectNodesOnDrag, onNodeDragStart, onSelectionDragStart, unselectNodesAndEdges, } = getStoreItems();
|
|
1478
1584
|
dragStarted = true;
|
|
1479
1585
|
if ((!selectNodesOnDrag || !isSelectable) && !multiSelectionActive && nodeId) {
|
|
1480
1586
|
if (!nodeLookup.get(nodeId)?.selected) {
|
|
@@ -1487,7 +1593,7 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
|
|
|
1487
1593
|
}
|
|
1488
1594
|
const pointerPos = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid });
|
|
1489
1595
|
lastPos = pointerPos;
|
|
1490
|
-
dragItems = getDragItems(
|
|
1596
|
+
dragItems = getDragItems(nodeLookup, nodesDraggable, pointerPos, nodeId);
|
|
1491
1597
|
if (dragItems.length > 0 && (onDragStart || onNodeDragStart || (!nodeId && onSelectionDragStart))) {
|
|
1492
1598
|
const [currentNode, currentNodes] = getEventHandlerParams({
|
|
1493
1599
|
nodeId,
|
|
@@ -1587,8 +1693,8 @@ function getHandles(node, handleBounds, type, currentHandle) {
|
|
|
1587
1693
|
id: h.id || null,
|
|
1588
1694
|
type,
|
|
1589
1695
|
nodeId: node.id,
|
|
1590
|
-
x: (node.
|
|
1591
|
-
y: (node.
|
|
1696
|
+
x: (node.internals.positionAbsolute.x ?? 0) + h.x + h.width / 2,
|
|
1697
|
+
y: (node.internals.positionAbsolute.y ?? 0) + h.y + h.height / 2,
|
|
1592
1698
|
});
|
|
1593
1699
|
}
|
|
1594
1700
|
return res;
|
|
@@ -1618,20 +1724,17 @@ function getClosestHandle(pos, connectionRadius, handles) {
|
|
|
1618
1724
|
: // if multiple handles are layouted on top of each other we take the one with type = target because it's more likely that the user wants to connect to this one
|
|
1619
1725
|
closestHandles.find((handle) => handle.type === 'target') || closestHandles[0];
|
|
1620
1726
|
}
|
|
1621
|
-
function getHandleLookup({
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
targetHandles = getHandles(node, handleBounds, 'target', `${nodeId}-${handleId}-${handleType}`);
|
|
1630
|
-
}
|
|
1631
|
-
res.push(...sourceHandles, ...targetHandles);
|
|
1727
|
+
function getHandleLookup({ nodeLookup, nodeId, handleId, handleType, }) {
|
|
1728
|
+
const connectionHandles = [];
|
|
1729
|
+
for (const [, node] of nodeLookup) {
|
|
1730
|
+
if (node.internals.handleBounds) {
|
|
1731
|
+
const id = `${nodeId}-${handleId}-${handleType}`;
|
|
1732
|
+
const sourceHandles = getHandles(node, node.internals.handleBounds, 'source', id);
|
|
1733
|
+
const targetHandles = getHandles(node, node.internals.handleBounds, 'target', id);
|
|
1734
|
+
connectionHandles.push(...sourceHandles, ...targetHandles);
|
|
1632
1735
|
}
|
|
1633
|
-
|
|
1634
|
-
|
|
1736
|
+
}
|
|
1737
|
+
return connectionHandles;
|
|
1635
1738
|
}
|
|
1636
1739
|
function getHandleType(edgeUpdaterType, handleDomNode) {
|
|
1637
1740
|
if (edgeUpdaterType) {
|
|
@@ -1658,7 +1761,7 @@ function getConnectionStatus(isInsideConnectionRadius, isHandleValid) {
|
|
|
1658
1761
|
|
|
1659
1762
|
const alwaysValid = () => true;
|
|
1660
1763
|
let connectionStartHandle = null;
|
|
1661
|
-
function onPointerDown(event, { connectionMode, connectionRadius, handleId, nodeId, edgeUpdaterType, isTarget, domNode,
|
|
1764
|
+
function onPointerDown(event, { connectionMode, connectionRadius, handleId, nodeId, edgeUpdaterType, isTarget, domNode, nodeLookup, lib, autoPanOnConnect, flowId, panBy, cancelConnection, onConnectStart, onConnect, onConnectEnd, isValidConnection = alwaysValid, onEdgeUpdateEnd, updateConnection, getTransform, getConnectionStartHandle, }) {
|
|
1662
1765
|
// when xyflow is used inside a shadow root we can't use document
|
|
1663
1766
|
const doc = getHostForElement(event.target);
|
|
1664
1767
|
let autoPanId = 0;
|
|
@@ -1676,7 +1779,7 @@ function onPointerDown(event, { connectionMode, connectionRadius, handleId, node
|
|
|
1676
1779
|
let isValid = false;
|
|
1677
1780
|
let handleDomNode = null;
|
|
1678
1781
|
const handleLookup = getHandleLookup({
|
|
1679
|
-
|
|
1782
|
+
nodeLookup,
|
|
1680
1783
|
nodeId,
|
|
1681
1784
|
handleId,
|
|
1682
1785
|
handleType,
|
|
@@ -2021,10 +2124,6 @@ function createFilter({ zoomActivationKeyPressed, zoomOnScroll, zoomOnPinch, pan
|
|
|
2021
2124
|
if (userSelectionActive) {
|
|
2022
2125
|
return false;
|
|
2023
2126
|
}
|
|
2024
|
-
// if zoom on double click is disabled, we prevent the double click event
|
|
2025
|
-
if (!zoomOnDoubleClick && event.type === 'dblclick') {
|
|
2026
|
-
return false;
|
|
2027
|
-
}
|
|
2028
2127
|
// if the target element is inside an element with the nowheel class, we prevent zooming
|
|
2029
2128
|
if (isWrappedWithClass(event, noWheelClassName) && event.type === 'wheel') {
|
|
2030
2129
|
return false;
|
|
@@ -2080,6 +2179,7 @@ function XYPanZoom({ domNode, minZoom, maxZoom, translateExtent, viewport, onPan
|
|
|
2080
2179
|
[bbox.width, bbox.height],
|
|
2081
2180
|
], translateExtent);
|
|
2082
2181
|
const d3ZoomHandler = d3Selection.on('wheel.zoom');
|
|
2182
|
+
const d3DblClickZoomHandler = d3Selection.on('dblclick.zoom');
|
|
2083
2183
|
d3ZoomInstance.wheelDelta(wheelDelta);
|
|
2084
2184
|
function setTransform(transform, options) {
|
|
2085
2185
|
if (d3Selection) {
|
|
@@ -2152,6 +2252,15 @@ function XYPanZoom({ domNode, minZoom, maxZoom, translateExtent, viewport, onPan
|
|
|
2152
2252
|
lib,
|
|
2153
2253
|
});
|
|
2154
2254
|
d3ZoomInstance.filter(filter);
|
|
2255
|
+
// We cannot add zoomOnDoubleClick to the filter above because
|
|
2256
|
+
// double tapping on touch screens circumvents the filter and
|
|
2257
|
+
// dblclick.zoom is fired on the selection directly
|
|
2258
|
+
if (zoomOnDoubleClick) {
|
|
2259
|
+
d3Selection.on('dblclick.zoom', d3DblClickZoomHandler);
|
|
2260
|
+
}
|
|
2261
|
+
else {
|
|
2262
|
+
d3Selection.on('dblclick.zoom', null);
|
|
2263
|
+
}
|
|
2155
2264
|
}
|
|
2156
2265
|
function destroy() {
|
|
2157
2266
|
d3ZoomInstance.on('zoom', null);
|
|
@@ -2462,14 +2571,14 @@ const initChange = {
|
|
|
2462
2571
|
function nodeToParentExtent(node) {
|
|
2463
2572
|
return [
|
|
2464
2573
|
[0, 0],
|
|
2465
|
-
[node.
|
|
2574
|
+
[node.measured.width, node.measured.height],
|
|
2466
2575
|
];
|
|
2467
2576
|
}
|
|
2468
2577
|
function nodeToChildExtent(child, parent, nodeOrigin) {
|
|
2469
2578
|
const x = parent.position.x + child.position.x;
|
|
2470
2579
|
const y = parent.position.y + child.position.y;
|
|
2471
|
-
const width = child.
|
|
2472
|
-
const height = child.
|
|
2580
|
+
const width = child.measured.width ?? 0;
|
|
2581
|
+
const height = child.measured.height ?? 0;
|
|
2473
2582
|
const originOffsetX = nodeOrigin[0] * width;
|
|
2474
2583
|
const originOffsetY = nodeOrigin[1] * height;
|
|
2475
2584
|
return [
|
|
@@ -2495,8 +2604,8 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange }) {
|
|
|
2495
2604
|
if (node) {
|
|
2496
2605
|
const { xSnapped, ySnapped } = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid });
|
|
2497
2606
|
prevValues = {
|
|
2498
|
-
width: node.
|
|
2499
|
-
height: node.
|
|
2607
|
+
width: node.measured?.width ?? 0,
|
|
2608
|
+
height: node.measured?.height ?? 0,
|
|
2500
2609
|
x: node.position.x ?? 0,
|
|
2501
2610
|
y: node.position.y ?? 0,
|
|
2502
2611
|
};
|
|
@@ -2508,7 +2617,7 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange }) {
|
|
|
2508
2617
|
};
|
|
2509
2618
|
parentNode = undefined;
|
|
2510
2619
|
if (node.extent === 'parent' || node.expandParent) {
|
|
2511
|
-
parentNode = nodeLookup.get(node.
|
|
2620
|
+
parentNode = nodeLookup.get(node.parentId);
|
|
2512
2621
|
if (parentNode && node.extent === 'parent') {
|
|
2513
2622
|
parentExtent = nodeToParentExtent(parentNode);
|
|
2514
2623
|
}
|
|
@@ -2518,7 +2627,7 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange }) {
|
|
|
2518
2627
|
childNodes = [];
|
|
2519
2628
|
childExtent = undefined;
|
|
2520
2629
|
for (const [childId, child] of nodeLookup) {
|
|
2521
|
-
if (child.
|
|
2630
|
+
if (child.parentId === nodeId) {
|
|
2522
2631
|
childNodes.push({
|
|
2523
2632
|
id: childId,
|
|
2524
2633
|
position: { ...child.position },
|
|
@@ -2626,4 +2735,4 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange }) {
|
|
|
2626
2735
|
};
|
|
2627
2736
|
}
|
|
2628
2737
|
|
|
2629
|
-
export { ConnectionLineType, ConnectionMode, MarkerType, PanOnScrollMode, Position, ResizeControlVariant, SelectionMode, XYDrag, XYHandle, XYMinimap, XYPanZoom, XYResizer, XY_RESIZER_HANDLE_POSITIONS, XY_RESIZER_LINE_POSITIONS, addEdge,
|
|
2738
|
+
export { ConnectionLineType, ConnectionMode, MarkerType, PanOnScrollMode, Position, ResizeControlVariant, SelectionMode, XYDrag, XYHandle, XYMinimap, XYPanZoom, XYResizer, XY_RESIZER_HANDLE_POSITIONS, XY_RESIZER_LINE_POSITIONS, addEdge, adoptUserNodes, areConnectionMapsEqual, boxToRect, calcAutoPan, calculateNodePosition, clamp, clampPosition, createMarkerIds, devWarn, elementSelectionKeys, errorMessages, fitView, getBezierEdgeCenter, getBezierPath, getBoundsOfBoxes, getBoundsOfRects, getConnectedEdges, getDimensions, getEdgeCenter, getEdgePosition, getElementsToRemove, getElevatedEdgeZIndex, getEventPosition, getHandleBounds, getHostForElement, getIncomers, getInternalNodesBounds, getMarkerId, getNodeDimensions, getNodePositionWithOrigin, getNodeToolbarTransform, getNodesBounds, getNodesInside, getOutgoers, getOverlappingArea, getPointerPosition, getPositionWithOrigin, getSmoothStepPath, getStraightPath, getViewportForBounds, handleConnectionChange, handleParentExpand, infiniteExtent, isCoordinateExtent, isEdgeBase, isEdgeVisible, isInputDOMNode, isInternalNodeBase, isMacOs, isMouseEvent, isNodeBase, isNumeric, isRectObject, nodeHasDimensions, nodeToBox, nodeToRect, panBy, pointToRendererPoint, rectToBox, rendererPointToPoint, shallowNodeData, snapPosition, updateAbsolutePositions, updateConnectionLookup, updateEdge, updateNodeDimensions };
|