@xyflow/system 0.0.22 → 0.0.24
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/index.js +360 -321
- package/dist/esm/index.mjs +360 -321
- package/dist/esm/types/changes.d.ts +1 -0
- package/dist/esm/types/changes.d.ts.map +1 -1
- package/dist/esm/types/general.d.ts +1 -1
- package/dist/esm/types/general.d.ts.map +1 -1
- package/dist/esm/types/nodes.d.ts +4 -4
- package/dist/esm/types/nodes.d.ts.map +1 -1
- package/dist/esm/utils/general.d.ts +22 -2
- package/dist/esm/utils/general.d.ts.map +1 -1
- package/dist/esm/utils/graph.d.ts +6 -8
- package/dist/esm/utils/graph.d.ts.map +1 -1
- package/dist/esm/utils/store.d.ts +10 -5
- package/dist/esm/utils/store.d.ts.map +1 -1
- package/dist/esm/utils/types.d.ts +6 -0
- package/dist/esm/utils/types.d.ts.map +1 -1
- package/dist/esm/xydrag/XYDrag.d.ts +1 -1
- package/dist/esm/xydrag/XYDrag.d.ts.map +1 -1
- package/dist/esm/xydrag/utils.d.ts +2 -3
- package/dist/esm/xydrag/utils.d.ts.map +1 -1
- package/dist/esm/xyminimap/index.d.ts.map +1 -1
- package/dist/esm/xypanzoom/eventhandler.d.ts.map +1 -1
- package/dist/esm/xyresizer/XYResizer.d.ts +6 -11
- package/dist/esm/xyresizer/XYResizer.d.ts.map +1 -1
- package/dist/umd/index.js +1 -1
- package/dist/umd/types/changes.d.ts +1 -0
- package/dist/umd/types/changes.d.ts.map +1 -1
- package/dist/umd/types/general.d.ts +1 -1
- package/dist/umd/types/general.d.ts.map +1 -1
- package/dist/umd/types/nodes.d.ts +4 -4
- package/dist/umd/types/nodes.d.ts.map +1 -1
- package/dist/umd/utils/general.d.ts +22 -2
- package/dist/umd/utils/general.d.ts.map +1 -1
- package/dist/umd/utils/graph.d.ts +6 -8
- package/dist/umd/utils/graph.d.ts.map +1 -1
- package/dist/umd/utils/store.d.ts +10 -5
- package/dist/umd/utils/store.d.ts.map +1 -1
- package/dist/umd/utils/types.d.ts +6 -0
- package/dist/umd/utils/types.d.ts.map +1 -1
- package/dist/umd/xydrag/XYDrag.d.ts +1 -1
- package/dist/umd/xydrag/XYDrag.d.ts.map +1 -1
- package/dist/umd/xydrag/utils.d.ts +2 -3
- package/dist/umd/xydrag/utils.d.ts.map +1 -1
- package/dist/umd/xyminimap/index.d.ts.map +1 -1
- package/dist/umd/xypanzoom/eventhandler.d.ts.map +1 -1
- package/dist/umd/xyresizer/XYResizer.d.ts +6 -11
- package/dist/umd/xyresizer/XYResizer.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/esm/index.mjs
CHANGED
|
@@ -161,33 +161,20 @@ const getIncomers = (node, nodes, edges) => {
|
|
|
161
161
|
return nodes.filter((n) => incomersIds.has(n.id));
|
|
162
162
|
};
|
|
163
163
|
const getNodePositionWithOrigin = (node, nodeOrigin = [0, 0]) => {
|
|
164
|
-
if (!node) {
|
|
165
|
-
return {
|
|
166
|
-
position: {
|
|
167
|
-
x: 0,
|
|
168
|
-
y: 0,
|
|
169
|
-
},
|
|
170
|
-
positionAbsolute: {
|
|
171
|
-
x: 0,
|
|
172
|
-
y: 0,
|
|
173
|
-
},
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
164
|
const { width, height } = getNodeDimensions(node);
|
|
177
|
-
const
|
|
178
|
-
const
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
y: node.position.y - offsetY,
|
|
182
|
-
};
|
|
165
|
+
const positionAbsolute = 'internals' in node ? node.internals.positionAbsolute : node.position;
|
|
166
|
+
const origin = node.origin || nodeOrigin;
|
|
167
|
+
const offsetX = width * origin[0];
|
|
168
|
+
const offsetY = height * origin[1];
|
|
183
169
|
return {
|
|
184
|
-
position
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
:
|
|
170
|
+
position: {
|
|
171
|
+
x: node.position.x - offsetX,
|
|
172
|
+
y: node.position.y - offsetY,
|
|
173
|
+
},
|
|
174
|
+
positionAbsolute: {
|
|
175
|
+
x: positionAbsolute.x - offsetX,
|
|
176
|
+
y: positionAbsolute.y - offsetY,
|
|
177
|
+
},
|
|
191
178
|
};
|
|
192
179
|
};
|
|
193
180
|
/**
|
|
@@ -196,20 +183,15 @@ const getNodePositionWithOrigin = (node, nodeOrigin = [0, 0]) => {
|
|
|
196
183
|
* @remarks Useful when combined with {@link getViewportForBounds} to calculate the correct transform to fit the given nodes in a viewport.
|
|
197
184
|
* @param nodes - Nodes to calculate the bounds for
|
|
198
185
|
* @param params.nodeOrigin - Origin of the nodes: [0, 0] - top left, [0.5, 0.5] - center
|
|
199
|
-
* @param params.useRelativePosition - Whether to use the relative or absolute node positions
|
|
200
186
|
* @returns Bounding box enclosing all nodes
|
|
201
187
|
*/
|
|
202
|
-
|
|
203
|
-
const getNodesBounds = (nodes, params = { nodeOrigin: [0, 0], useRelativePosition: false }) => {
|
|
188
|
+
const getNodesBounds = (nodes, params = { nodeOrigin: [0, 0] }) => {
|
|
204
189
|
if (nodes.length === 0) {
|
|
205
190
|
return { x: 0, y: 0, width: 0, height: 0 };
|
|
206
191
|
}
|
|
207
192
|
const box = nodes.reduce((currBox, node) => {
|
|
208
|
-
const
|
|
209
|
-
return getBoundsOfBoxes(currBox,
|
|
210
|
-
...nodePos[params.useRelativePosition ? 'position' : 'positionAbsolute'],
|
|
211
|
-
...getNodeDimensions(node),
|
|
212
|
-
}));
|
|
193
|
+
const nodeBox = nodeToBox(node, params.nodeOrigin);
|
|
194
|
+
return getBoundsOfBoxes(currBox, nodeBox);
|
|
213
195
|
}, { x: Infinity, y: Infinity, x2: -Infinity, y2: -Infinity });
|
|
214
196
|
return boxToRect(box);
|
|
215
197
|
};
|
|
@@ -219,7 +201,6 @@ const getNodesBounds = (nodes, params = { nodeOrigin: [0, 0], useRelativePositio
|
|
|
219
201
|
*/
|
|
220
202
|
const getInternalNodesBounds = (nodeLookup, params = {
|
|
221
203
|
nodeOrigin: [0, 0],
|
|
222
|
-
useRelativePosition: false,
|
|
223
204
|
}) => {
|
|
224
205
|
if (nodeLookup.size === 0) {
|
|
225
206
|
return { x: 0, y: 0, width: 0, height: 0 };
|
|
@@ -227,16 +208,13 @@ const getInternalNodesBounds = (nodeLookup, params = {
|
|
|
227
208
|
let box = { x: Infinity, y: Infinity, x2: -Infinity, y2: -Infinity };
|
|
228
209
|
nodeLookup.forEach((node) => {
|
|
229
210
|
if (params.filter == undefined || params.filter(node)) {
|
|
230
|
-
const
|
|
231
|
-
box = getBoundsOfBoxes(box,
|
|
232
|
-
...nodePos[params.useRelativePosition ? 'position' : 'positionAbsolute'],
|
|
233
|
-
...getNodeDimensions(node),
|
|
234
|
-
}));
|
|
211
|
+
const nodeBox = nodeToBox(node, params.nodeOrigin);
|
|
212
|
+
box = getBoundsOfBoxes(box, nodeBox);
|
|
235
213
|
}
|
|
236
214
|
});
|
|
237
215
|
return boxToRect(box);
|
|
238
216
|
};
|
|
239
|
-
const getNodesInside = (
|
|
217
|
+
const getNodesInside = (nodes, rect, [tx, ty, tScale] = [0, 0, 1], partially = false,
|
|
240
218
|
// set excludeNonSelectableNodes if you want to pay attention to the nodes "selectable" attribute
|
|
241
219
|
excludeNonSelectableNodes = false, nodeOrigin = [0, 0]) => {
|
|
242
220
|
const paneRect = {
|
|
@@ -245,7 +223,7 @@ excludeNonSelectableNodes = false, nodeOrigin = [0, 0]) => {
|
|
|
245
223
|
height: rect.height / tScale,
|
|
246
224
|
};
|
|
247
225
|
const visibleNodes = [];
|
|
248
|
-
for (const [, node] of
|
|
226
|
+
for (const [, node] of nodes) {
|
|
249
227
|
const { measured, selectable = true, hidden = false } = node;
|
|
250
228
|
const width = measured.width ?? node.width ?? node.initialWidth ?? null;
|
|
251
229
|
const height = measured.height ?? node.height ?? node.initialHeight ?? null;
|
|
@@ -278,10 +256,10 @@ const getConnectedEdges = (nodes, edges) => {
|
|
|
278
256
|
};
|
|
279
257
|
function fitView({ nodeLookup, width, height, panZoom, minZoom, maxZoom, nodeOrigin = [0, 0] }, options) {
|
|
280
258
|
const filteredNodes = [];
|
|
259
|
+
const optionNodeIds = options?.nodes ? new Set(options.nodes.map((node) => node.id)) : null;
|
|
281
260
|
nodeLookup.forEach((n) => {
|
|
282
261
|
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)))) {
|
|
262
|
+
if (isVisible && (!optionNodeIds || optionNodeIds.has(n.id))) {
|
|
285
263
|
filteredNodes.push(n);
|
|
286
264
|
}
|
|
287
265
|
});
|
|
@@ -452,19 +430,21 @@ const boxToRect = ({ x, y, x2, y2 }) => ({
|
|
|
452
430
|
height: y2 - y,
|
|
453
431
|
});
|
|
454
432
|
const nodeToRect = (node, nodeOrigin = [0, 0]) => {
|
|
455
|
-
const {
|
|
433
|
+
const { x, y } = getNodePositionWithOrigin(node, nodeOrigin).positionAbsolute;
|
|
456
434
|
return {
|
|
457
|
-
|
|
435
|
+
x,
|
|
436
|
+
y,
|
|
458
437
|
width: node.measured?.width ?? node.width ?? 0,
|
|
459
438
|
height: node.measured?.height ?? node.height ?? 0,
|
|
460
439
|
};
|
|
461
440
|
};
|
|
462
441
|
const nodeToBox = (node, nodeOrigin = [0, 0]) => {
|
|
463
|
-
const {
|
|
442
|
+
const { x, y } = getNodePositionWithOrigin(node, nodeOrigin).positionAbsolute;
|
|
464
443
|
return {
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
444
|
+
x,
|
|
445
|
+
y,
|
|
446
|
+
x2: x + (node.measured?.width ?? node.width ?? 0),
|
|
447
|
+
y2: y + (node.measured?.height ?? node.height ?? 0),
|
|
468
448
|
};
|
|
469
449
|
};
|
|
470
450
|
const getBoundsOfRects = (rect1, rect2) => boxToRect(getBoundsOfBoxes(rectToBox(rect1), rectToBox(rect2)));
|
|
@@ -552,6 +532,32 @@ function nodeHasDimensions(node) {
|
|
|
552
532
|
return ((node.measured?.width ?? node.width ?? node.initialWidth) !== undefined &&
|
|
553
533
|
(node.measured?.height ?? node.height ?? node.initialHeight) !== undefined);
|
|
554
534
|
}
|
|
535
|
+
/**
|
|
536
|
+
* Convert child position to aboslute position
|
|
537
|
+
*
|
|
538
|
+
* @internal
|
|
539
|
+
* @param position
|
|
540
|
+
* @param parentId
|
|
541
|
+
* @param nodeLookup
|
|
542
|
+
* @param nodeOrigin
|
|
543
|
+
* @returns an internal node with an absolute position
|
|
544
|
+
*/
|
|
545
|
+
function evaluateAbsolutePosition(position, parentId, nodeLookup, nodeOrigin = [0, 0]) {
|
|
546
|
+
let nextParentId = parentId;
|
|
547
|
+
const positionAbsolute = { ...position };
|
|
548
|
+
while (nextParentId) {
|
|
549
|
+
const parent = nodeLookup.get(parentId);
|
|
550
|
+
nextParentId = parent?.parentId;
|
|
551
|
+
if (parent) {
|
|
552
|
+
const origin = parent.origin || nodeOrigin;
|
|
553
|
+
const xOffset = (parent.measured.width ?? 0) * origin[0];
|
|
554
|
+
const yOffset = (parent.measured.height ?? 0) * origin[1];
|
|
555
|
+
positionAbsolute.x += parent.position.x - xOffset;
|
|
556
|
+
positionAbsolute.y += parent.position.y - yOffset;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
return positionAbsolute;
|
|
560
|
+
}
|
|
555
561
|
|
|
556
562
|
function getPointerPosition(event, { snapGrid = [0, 0], snapToGrid = false, transform }) {
|
|
557
563
|
const { x, y } = getEventPosition(event);
|
|
@@ -1078,8 +1084,8 @@ function toHandleBounds(handles) {
|
|
|
1078
1084
|
};
|
|
1079
1085
|
}
|
|
1080
1086
|
function getHandlePosition(position, node, handle = null) {
|
|
1081
|
-
const x = (handle?.x ?? 0) +
|
|
1082
|
-
const y = (handle?.y ?? 0) +
|
|
1087
|
+
const x = (handle?.x ?? 0) + node.internals.positionAbsolute.x;
|
|
1088
|
+
const y = (handle?.y ?? 0) + node.internals.positionAbsolute.y;
|
|
1083
1089
|
const { width, height } = handle ?? getNodeDimensions(node);
|
|
1084
1090
|
switch (position) {
|
|
1085
1091
|
case Position.Top:
|
|
@@ -1174,49 +1180,49 @@ function updateAbsolutePositions(nodeLookup, options = {
|
|
|
1174
1180
|
nodeOrigin: [0, 0],
|
|
1175
1181
|
elevateNodesOnSelect: true,
|
|
1176
1182
|
defaults: {},
|
|
1177
|
-
}
|
|
1183
|
+
}) {
|
|
1178
1184
|
const selectedNodeZ = options?.elevateNodesOnSelect ? 1000 : 0;
|
|
1179
|
-
for (const [
|
|
1185
|
+
for (const [, node] of nodeLookup) {
|
|
1180
1186
|
const parentId = node.parentId;
|
|
1181
|
-
if (
|
|
1187
|
+
if (!parentId) {
|
|
1188
|
+
continue;
|
|
1189
|
+
}
|
|
1190
|
+
if (!nodeLookup.has(parentId)) {
|
|
1182
1191
|
throw new Error(`Parent node ${parentId} not found`);
|
|
1183
1192
|
}
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
node.internals
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
}
|
|
1197
|
-
nodeLookup.set(id, node);
|
|
1193
|
+
const parentNode = nodeLookup.get(parentId);
|
|
1194
|
+
const { x, y, z } = calculateXYZPosition(node, nodeLookup, {
|
|
1195
|
+
...node.position,
|
|
1196
|
+
z: (isNumeric(node.zIndex) ? node.zIndex : 0) + (node.selected ? selectedNodeZ : 0),
|
|
1197
|
+
}, parentNode?.origin ?? options.nodeOrigin);
|
|
1198
|
+
const currPosition = node.internals.positionAbsolute;
|
|
1199
|
+
const positionChanged = x !== currPosition.x || y !== currPosition.y;
|
|
1200
|
+
if (positionChanged || z !== node.internals.z) {
|
|
1201
|
+
node.internals = {
|
|
1202
|
+
...node.internals,
|
|
1203
|
+
positionAbsolute: positionChanged ? { x, y } : currPosition,
|
|
1204
|
+
z,
|
|
1205
|
+
};
|
|
1198
1206
|
}
|
|
1199
1207
|
}
|
|
1200
1208
|
}
|
|
1201
|
-
function adoptUserNodes(nodes, nodeLookup, options = {
|
|
1209
|
+
function adoptUserNodes(nodes, nodeLookup, parentLookup, options = {
|
|
1202
1210
|
nodeOrigin: [0, 0],
|
|
1203
1211
|
elevateNodesOnSelect: true,
|
|
1204
1212
|
defaults: {},
|
|
1213
|
+
checkEquality: true,
|
|
1205
1214
|
}) {
|
|
1206
1215
|
const tmpLookup = new Map(nodeLookup);
|
|
1207
1216
|
nodeLookup.clear();
|
|
1217
|
+
parentLookup.clear();
|
|
1208
1218
|
const selectedNodeZ = options?.elevateNodesOnSelect ? 1000 : 0;
|
|
1209
|
-
const parentNodeIds = new Set();
|
|
1210
1219
|
nodes.forEach((userNode) => {
|
|
1211
|
-
|
|
1212
|
-
if (userNode.
|
|
1213
|
-
|
|
1214
|
-
}
|
|
1215
|
-
if (userNode === currentStoreNode?.internals.userNode) {
|
|
1216
|
-
nodeLookup.set(userNode.id, currentStoreNode);
|
|
1220
|
+
let internalNode = tmpLookup.get(userNode.id);
|
|
1221
|
+
if (options.checkEquality && userNode === internalNode?.internals.userNode) {
|
|
1222
|
+
nodeLookup.set(userNode.id, internalNode);
|
|
1217
1223
|
}
|
|
1218
1224
|
else {
|
|
1219
|
-
|
|
1225
|
+
internalNode = {
|
|
1220
1226
|
...options.defaults,
|
|
1221
1227
|
...userNode,
|
|
1222
1228
|
measured: {
|
|
@@ -1225,79 +1231,93 @@ function adoptUserNodes(nodes, nodeLookup, options = {
|
|
|
1225
1231
|
},
|
|
1226
1232
|
internals: {
|
|
1227
1233
|
positionAbsolute: userNode.position,
|
|
1228
|
-
handleBounds:
|
|
1234
|
+
handleBounds: internalNode?.internals.handleBounds,
|
|
1229
1235
|
z: (isNumeric(userNode.zIndex) ? userNode.zIndex : 0) + (userNode.selected ? selectedNodeZ : 0),
|
|
1230
1236
|
userNode,
|
|
1231
|
-
isParent: false,
|
|
1232
1237
|
},
|
|
1233
|
-
}
|
|
1238
|
+
};
|
|
1239
|
+
nodeLookup.set(userNode.id, internalNode);
|
|
1240
|
+
}
|
|
1241
|
+
if (userNode.parentId) {
|
|
1242
|
+
const childNodes = parentLookup.get(userNode.parentId);
|
|
1243
|
+
if (childNodes) {
|
|
1244
|
+
childNodes.push(internalNode);
|
|
1245
|
+
}
|
|
1246
|
+
else {
|
|
1247
|
+
parentLookup.set(userNode.parentId, [internalNode]);
|
|
1248
|
+
}
|
|
1234
1249
|
}
|
|
1235
1250
|
});
|
|
1236
|
-
if (
|
|
1237
|
-
updateAbsolutePositions(nodeLookup, options
|
|
1251
|
+
if (parentLookup.size > 0) {
|
|
1252
|
+
updateAbsolutePositions(nodeLookup, options);
|
|
1238
1253
|
}
|
|
1239
1254
|
}
|
|
1240
1255
|
function calculateXYZPosition(node, nodeLookup, result, nodeOrigin = [0, 0]) {
|
|
1241
1256
|
if (!node.parentId) {
|
|
1242
1257
|
return result;
|
|
1243
1258
|
}
|
|
1244
|
-
const
|
|
1245
|
-
const
|
|
1246
|
-
return calculateXYZPosition(
|
|
1247
|
-
x: (result.x ?? 0) +
|
|
1248
|
-
y: (result.y ?? 0) +
|
|
1249
|
-
z: (
|
|
1250
|
-
},
|
|
1251
|
-
}
|
|
1252
|
-
function
|
|
1259
|
+
const parent = nodeLookup.get(node.parentId);
|
|
1260
|
+
const parentPosition = getNodePositionWithOrigin(parent, nodeOrigin).position;
|
|
1261
|
+
return calculateXYZPosition(parent, nodeLookup, {
|
|
1262
|
+
x: (result.x ?? 0) + parentPosition.x,
|
|
1263
|
+
y: (result.y ?? 0) + parentPosition.y,
|
|
1264
|
+
z: (parent.internals.z ?? 0) > (result.z ?? 0) ? parent.internals.z ?? 0 : result.z ?? 0,
|
|
1265
|
+
}, parent.origin || nodeOrigin);
|
|
1266
|
+
}
|
|
1267
|
+
function handleExpandParent(children, nodeLookup, parentLookup, nodeOrigin) {
|
|
1253
1268
|
const changes = [];
|
|
1254
|
-
const
|
|
1255
|
-
nodes
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
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
|
-
}
|
|
1269
|
+
const parentExpansions = new Map();
|
|
1270
|
+
// determine the expanded rectangle the child nodes would take for each parent
|
|
1271
|
+
for (const child of children) {
|
|
1272
|
+
const parent = nodeLookup.get(child.parentId);
|
|
1273
|
+
if (!parent) {
|
|
1274
|
+
continue;
|
|
1264
1275
|
}
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1276
|
+
const parentRect = parentExpansions.get(child.parentId)?.expandedRect ?? nodeToRect(parent, parent.origin ?? nodeOrigin);
|
|
1277
|
+
const expandedRect = getBoundsOfRects(parentRect, child.rect);
|
|
1278
|
+
parentExpansions.set(child.parentId, { expandedRect, parent });
|
|
1279
|
+
}
|
|
1280
|
+
if (parentExpansions.size > 0) {
|
|
1281
|
+
parentExpansions.forEach(({ expandedRect, parent }, parentId) => {
|
|
1282
|
+
// determine the position & dimensions of the parent
|
|
1283
|
+
const { position } = getNodePositionWithOrigin(parent, parent.origin);
|
|
1284
|
+
const dimensions = getNodeDimensions(parent);
|
|
1285
|
+
// determine how much the parent expands by moving the position
|
|
1286
|
+
const xChange = expandedRect.x < position.x ? Math.round(Math.abs(position.x - expandedRect.x)) : 0;
|
|
1287
|
+
const yChange = expandedRect.y < position.y ? Math.round(Math.abs(position.y - expandedRect.y)) : 0;
|
|
1288
|
+
if (xChange > 0 || yChange > 0) {
|
|
1274
1289
|
changes.push({
|
|
1275
|
-
id,
|
|
1290
|
+
id: parentId,
|
|
1276
1291
|
type: 'position',
|
|
1277
1292
|
position: {
|
|
1278
1293
|
x: position.x - xChange,
|
|
1279
1294
|
y: position.y - yChange,
|
|
1280
1295
|
},
|
|
1281
1296
|
});
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1297
|
+
// We move all child nodes in the oppsite direction
|
|
1298
|
+
// so the x,y changes of the parent do not move the children
|
|
1299
|
+
const childNodes = parentLookup.get(parentId);
|
|
1300
|
+
childNodes?.forEach((childNode) => {
|
|
1301
|
+
if (!children.some((child) => child.id === childNode.id)) {
|
|
1302
|
+
changes.push({
|
|
1303
|
+
id: childNode.id,
|
|
1304
|
+
type: 'position',
|
|
1305
|
+
position: {
|
|
1306
|
+
x: childNode.position.x + xChange,
|
|
1307
|
+
y: childNode.position.y + yChange,
|
|
1308
|
+
},
|
|
1309
|
+
});
|
|
1310
|
+
}
|
|
1290
1311
|
});
|
|
1291
|
-
// @todo we need to reset child node positions if < 0
|
|
1292
1312
|
}
|
|
1293
|
-
|
|
1313
|
+
if (dimensions.width < expandedRect.width || dimensions.height < expandedRect.height) {
|
|
1294
1314
|
changes.push({
|
|
1295
|
-
id,
|
|
1315
|
+
id: parentId,
|
|
1296
1316
|
type: 'dimensions',
|
|
1297
|
-
|
|
1317
|
+
setAttributes: true,
|
|
1298
1318
|
dimensions: {
|
|
1299
|
-
width: Math.max(dimensions.width,
|
|
1300
|
-
height: Math.max(dimensions.height,
|
|
1319
|
+
width: Math.max(dimensions.width, Math.round(expandedRect.width)),
|
|
1320
|
+
height: Math.max(dimensions.height, Math.round(expandedRect.height)),
|
|
1301
1321
|
},
|
|
1302
1322
|
});
|
|
1303
1323
|
}
|
|
@@ -1305,16 +1325,17 @@ function handleParentExpand(nodes, nodeLookup) {
|
|
|
1305
1325
|
}
|
|
1306
1326
|
return changes;
|
|
1307
1327
|
}
|
|
1308
|
-
function
|
|
1328
|
+
function updateNodeInternals(updates, nodeLookup, parentLookup, domNode, nodeOrigin) {
|
|
1309
1329
|
const viewportNode = domNode?.querySelector('.xyflow__viewport');
|
|
1330
|
+
let updatedInternals = false;
|
|
1310
1331
|
if (!viewportNode) {
|
|
1311
|
-
return [];
|
|
1332
|
+
return { changes: [], updatedInternals };
|
|
1312
1333
|
}
|
|
1313
1334
|
const changes = [];
|
|
1314
1335
|
const style = window.getComputedStyle(viewportNode);
|
|
1315
1336
|
const { m22: zoom } = new window.DOMMatrixReadOnly(style.transform);
|
|
1316
1337
|
// in this array we collect nodes, that might trigger changes (like expanding parent)
|
|
1317
|
-
const
|
|
1338
|
+
const parentExpandChildren = [];
|
|
1318
1339
|
updates.forEach((update) => {
|
|
1319
1340
|
const node = nodeLookup.get(update.id);
|
|
1320
1341
|
if (node?.hidden) {
|
|
@@ -1325,19 +1346,18 @@ function updateNodeDimensions(updates, nodeLookup, domNode, nodeOrigin) {
|
|
|
1325
1346
|
handleBounds: undefined,
|
|
1326
1347
|
},
|
|
1327
1348
|
});
|
|
1349
|
+
updatedInternals = true;
|
|
1328
1350
|
}
|
|
1329
1351
|
else if (node) {
|
|
1330
1352
|
const dimensions = getDimensions(update.nodeElement);
|
|
1353
|
+
const dimensionChanged = node.measured.width !== dimensions.width || node.measured.height !== dimensions.height;
|
|
1331
1354
|
const doUpdate = !!(dimensions.width &&
|
|
1332
1355
|
dimensions.height &&
|
|
1333
|
-
(
|
|
1356
|
+
(dimensionChanged || !node.internals.handleBounds || update.force));
|
|
1334
1357
|
if (doUpdate) {
|
|
1335
1358
|
const newNode = {
|
|
1336
1359
|
...node,
|
|
1337
|
-
measured:
|
|
1338
|
-
...node.measured,
|
|
1339
|
-
...dimensions,
|
|
1340
|
-
},
|
|
1360
|
+
measured: dimensions,
|
|
1341
1361
|
internals: {
|
|
1342
1362
|
...node.internals,
|
|
1343
1363
|
handleBounds: {
|
|
@@ -1347,22 +1367,29 @@ function updateNodeDimensions(updates, nodeLookup, domNode, nodeOrigin) {
|
|
|
1347
1367
|
},
|
|
1348
1368
|
};
|
|
1349
1369
|
nodeLookup.set(node.id, newNode);
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1370
|
+
updatedInternals = true;
|
|
1371
|
+
if (dimensionChanged) {
|
|
1372
|
+
changes.push({
|
|
1373
|
+
id: newNode.id,
|
|
1374
|
+
type: 'dimensions',
|
|
1375
|
+
dimensions,
|
|
1376
|
+
});
|
|
1377
|
+
if (newNode.expandParent && newNode.parentId) {
|
|
1378
|
+
parentExpandChildren.push({
|
|
1379
|
+
id: newNode.id,
|
|
1380
|
+
parentId: newNode.parentId,
|
|
1381
|
+
rect: nodeToRect(newNode, newNode.origin || nodeOrigin),
|
|
1382
|
+
});
|
|
1383
|
+
}
|
|
1357
1384
|
}
|
|
1358
1385
|
}
|
|
1359
1386
|
}
|
|
1360
1387
|
});
|
|
1361
|
-
if (
|
|
1362
|
-
const parentExpandChanges =
|
|
1388
|
+
if (parentExpandChildren.length > 0) {
|
|
1389
|
+
const parentExpandChanges = handleExpandParent(parentExpandChildren, nodeLookup, parentLookup, nodeOrigin);
|
|
1363
1390
|
changes.push(...parentExpandChanges);
|
|
1364
1391
|
}
|
|
1365
|
-
return changes;
|
|
1392
|
+
return { changes, updatedInternals };
|
|
1366
1393
|
}
|
|
1367
1394
|
function panBy({ delta, panZoom, transform, translateExtent, width, height, }) {
|
|
1368
1395
|
if (!panZoom || (!delta.x && !delta.y)) {
|
|
@@ -1413,9 +1440,6 @@ function shallowNodeData(a, b) {
|
|
|
1413
1440
|
return true;
|
|
1414
1441
|
}
|
|
1415
1442
|
|
|
1416
|
-
function wrapSelectionDragFunc(selectionFunc) {
|
|
1417
|
-
return (event, _, nodes) => selectionFunc?.(event, nodes);
|
|
1418
|
-
}
|
|
1419
1443
|
function isParentSelected(node, nodeLookup) {
|
|
1420
1444
|
if (!node.parentId) {
|
|
1421
1445
|
return false;
|
|
@@ -1442,31 +1466,33 @@ function hasSelector(target, selector, domNode) {
|
|
|
1442
1466
|
}
|
|
1443
1467
|
// looks for all selected nodes and created a NodeDragItem for each of them
|
|
1444
1468
|
function getDragItems(nodeLookup, nodesDraggable, mousePos, nodeId) {
|
|
1445
|
-
const dragItems =
|
|
1469
|
+
const dragItems = new Map();
|
|
1446
1470
|
for (const [id, node] of nodeLookup) {
|
|
1447
1471
|
if ((node.selected || node.id === nodeId) &&
|
|
1448
1472
|
(!node.parentId || !isParentSelected(node, nodeLookup)) &&
|
|
1449
1473
|
(node.draggable || (nodesDraggable && typeof node.draggable === 'undefined'))) {
|
|
1450
1474
|
const internalNode = nodeLookup.get(id);
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1475
|
+
if (internalNode) {
|
|
1476
|
+
dragItems.set(id, {
|
|
1477
|
+
id,
|
|
1478
|
+
position: internalNode.position || { x: 0, y: 0 },
|
|
1479
|
+
distance: {
|
|
1480
|
+
x: mousePos.x - internalNode.internals.positionAbsolute.x,
|
|
1481
|
+
y: mousePos.y - internalNode.internals.positionAbsolute.y,
|
|
1482
|
+
},
|
|
1483
|
+
extent: internalNode.extent,
|
|
1484
|
+
parentId: internalNode.parentId,
|
|
1485
|
+
origin: internalNode.origin,
|
|
1486
|
+
expandParent: internalNode.expandParent,
|
|
1487
|
+
internals: {
|
|
1488
|
+
positionAbsolute: internalNode.internals.positionAbsolute || { x: 0, y: 0 },
|
|
1489
|
+
},
|
|
1490
|
+
measured: {
|
|
1491
|
+
width: internalNode.measured.width ?? 0,
|
|
1492
|
+
height: internalNode.measured.height ?? 0,
|
|
1493
|
+
},
|
|
1494
|
+
});
|
|
1495
|
+
}
|
|
1470
1496
|
}
|
|
1471
1497
|
}
|
|
1472
1498
|
return dragItems;
|
|
@@ -1475,24 +1501,34 @@ function getDragItems(nodeLookup, nodesDraggable, mousePos, nodeId) {
|
|
|
1475
1501
|
// 1. the dragged node (or the first of the list, if we are dragging a node selection)
|
|
1476
1502
|
// 2. array of selected nodes (for multi selections)
|
|
1477
1503
|
function getEventHandlerParams({ nodeId, dragItems, nodeLookup, }) {
|
|
1478
|
-
const nodesFromDragItems =
|
|
1479
|
-
|
|
1480
|
-
|
|
1504
|
+
const nodesFromDragItems = [];
|
|
1505
|
+
for (const [id, dragItem] of dragItems) {
|
|
1506
|
+
const node = nodeLookup.get(id);
|
|
1507
|
+
if (node) {
|
|
1508
|
+
nodesFromDragItems.push({
|
|
1509
|
+
...node,
|
|
1510
|
+
position: dragItem.position,
|
|
1511
|
+
});
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
if (!nodeId) {
|
|
1515
|
+
return [nodesFromDragItems[0], nodesFromDragItems];
|
|
1516
|
+
}
|
|
1517
|
+
const node = nodeLookup.get(nodeId);
|
|
1518
|
+
return [
|
|
1519
|
+
{
|
|
1481
1520
|
...node,
|
|
1482
|
-
position:
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
};
|
|
1487
|
-
});
|
|
1488
|
-
return [nodeId ? nodesFromDragItems.find((n) => n.id === nodeId) : nodesFromDragItems[0], nodesFromDragItems];
|
|
1521
|
+
position: dragItems.get(nodeId)?.position || node.position,
|
|
1522
|
+
},
|
|
1523
|
+
nodesFromDragItems,
|
|
1524
|
+
];
|
|
1489
1525
|
}
|
|
1490
1526
|
|
|
1491
1527
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1492
1528
|
function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragStop, }) {
|
|
1493
1529
|
let lastPos = { x: null, y: null };
|
|
1494
1530
|
let autoPanId = 0;
|
|
1495
|
-
let dragItems =
|
|
1531
|
+
let dragItems = new Map();
|
|
1496
1532
|
let autoPanStarted = false;
|
|
1497
1533
|
let mousePosition = { x: 0, y: 0 };
|
|
1498
1534
|
let containerBounds = null;
|
|
@@ -1506,12 +1542,12 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
|
|
|
1506
1542
|
lastPos = { x, y };
|
|
1507
1543
|
let hasChange = false;
|
|
1508
1544
|
let nodesBox = { x: 0, y: 0, x2: 0, y2: 0 };
|
|
1509
|
-
if (dragItems.
|
|
1510
|
-
const rect =
|
|
1545
|
+
if (dragItems.size > 1 && nodeExtent) {
|
|
1546
|
+
const rect = getInternalNodesBounds(dragItems, { nodeOrigin });
|
|
1511
1547
|
nodesBox = rectToBox(rect);
|
|
1512
1548
|
}
|
|
1513
|
-
|
|
1514
|
-
let nextPosition = { x: x -
|
|
1549
|
+
for (const [id, dragItem] of dragItems) {
|
|
1550
|
+
let nextPosition = { x: x - dragItem.distance.x, y: y - dragItem.distance.y };
|
|
1515
1551
|
if (snapToGrid) {
|
|
1516
1552
|
nextPosition = snapPosition(nextPosition, snapGrid);
|
|
1517
1553
|
}
|
|
@@ -1521,19 +1557,19 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
|
|
|
1521
1557
|
[nodeExtent[0][0], nodeExtent[0][1]],
|
|
1522
1558
|
[nodeExtent[1][0], nodeExtent[1][1]],
|
|
1523
1559
|
];
|
|
1524
|
-
if (dragItems.
|
|
1525
|
-
const { positionAbsolute } =
|
|
1560
|
+
if (dragItems.size > 1 && nodeExtent && !dragItem.extent) {
|
|
1561
|
+
const { positionAbsolute } = dragItem.internals;
|
|
1526
1562
|
const x1 = positionAbsolute.x - nodesBox.x + nodeExtent[0][0];
|
|
1527
|
-
const x2 = positionAbsolute.x +
|
|
1563
|
+
const x2 = positionAbsolute.x + dragItem.measured.width - nodesBox.x2 + nodeExtent[1][0];
|
|
1528
1564
|
const y1 = positionAbsolute.y - nodesBox.y + nodeExtent[0][1];
|
|
1529
|
-
const y2 = positionAbsolute.y +
|
|
1565
|
+
const y2 = positionAbsolute.y + dragItem.measured.height - nodesBox.y2 + nodeExtent[1][1];
|
|
1530
1566
|
adjustedNodeExtent = [
|
|
1531
1567
|
[x1, y1],
|
|
1532
1568
|
[x2, y2],
|
|
1533
1569
|
];
|
|
1534
1570
|
}
|
|
1535
1571
|
const { position, positionAbsolute } = calculateNodePosition({
|
|
1536
|
-
nodeId:
|
|
1572
|
+
nodeId: id,
|
|
1537
1573
|
nextPosition,
|
|
1538
1574
|
nodeLookup,
|
|
1539
1575
|
nodeExtent: adjustedNodeExtent,
|
|
@@ -1541,11 +1577,10 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
|
|
|
1541
1577
|
onError,
|
|
1542
1578
|
});
|
|
1543
1579
|
// we want to make sure that we only fire a change event when there is a change
|
|
1544
|
-
hasChange = hasChange ||
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
});
|
|
1580
|
+
hasChange = hasChange || dragItem.position.x !== position.x || dragItem.position.y !== position.y;
|
|
1581
|
+
dragItem.position = position;
|
|
1582
|
+
dragItem.internals.positionAbsolute = positionAbsolute;
|
|
1583
|
+
}
|
|
1549
1584
|
if (!hasChange) {
|
|
1550
1585
|
return;
|
|
1551
1586
|
}
|
|
@@ -1559,8 +1594,7 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
|
|
|
1559
1594
|
onDrag?.(dragEvent, dragItems, currentNode, currentNodes);
|
|
1560
1595
|
onNodeDrag?.(dragEvent, currentNode, currentNodes);
|
|
1561
1596
|
if (!nodeId) {
|
|
1562
|
-
|
|
1563
|
-
_onSelectionDrag(dragEvent, currentNode, currentNodes);
|
|
1597
|
+
onSelectionDrag?.(dragEvent, currentNodes);
|
|
1564
1598
|
}
|
|
1565
1599
|
}
|
|
1566
1600
|
}
|
|
@@ -1594,7 +1628,7 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
|
|
|
1594
1628
|
const pointerPos = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid });
|
|
1595
1629
|
lastPos = pointerPos;
|
|
1596
1630
|
dragItems = getDragItems(nodeLookup, nodesDraggable, pointerPos, nodeId);
|
|
1597
|
-
if (dragItems.
|
|
1631
|
+
if (dragItems.size > 0 && (onDragStart || onNodeDragStart || (!nodeId && onSelectionDragStart))) {
|
|
1598
1632
|
const [currentNode, currentNodes] = getEventHandlerParams({
|
|
1599
1633
|
nodeId,
|
|
1600
1634
|
dragItems,
|
|
@@ -1603,8 +1637,7 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
|
|
|
1603
1637
|
onDragStart?.(event.sourceEvent, dragItems, currentNode, currentNodes);
|
|
1604
1638
|
onNodeDragStart?.(event.sourceEvent, currentNode, currentNodes);
|
|
1605
1639
|
if (!nodeId) {
|
|
1606
|
-
|
|
1607
|
-
_onSelectionDragStart(event.sourceEvent, currentNode, currentNodes);
|
|
1640
|
+
onSelectionDragStart?.(event.sourceEvent, currentNodes);
|
|
1608
1641
|
}
|
|
1609
1642
|
}
|
|
1610
1643
|
}
|
|
@@ -1648,7 +1681,7 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
|
|
|
1648
1681
|
autoPanStarted = false;
|
|
1649
1682
|
dragStarted = false;
|
|
1650
1683
|
cancelAnimationFrame(autoPanId);
|
|
1651
|
-
if (dragItems.
|
|
1684
|
+
if (dragItems.size > 0) {
|
|
1652
1685
|
const { nodeLookup, updateNodePositions, onNodeDragStop, onSelectionDragStop } = getStoreItems();
|
|
1653
1686
|
updateNodePositions(dragItems, false);
|
|
1654
1687
|
if (onDragStop || onNodeDragStop || (!nodeId && onSelectionDragStop)) {
|
|
@@ -1660,8 +1693,7 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
|
|
|
1660
1693
|
onDragStop?.(event.sourceEvent, dragItems, currentNode, currentNodes);
|
|
1661
1694
|
onNodeDragStop?.(event.sourceEvent, currentNode, currentNodes);
|
|
1662
1695
|
if (!nodeId) {
|
|
1663
|
-
|
|
1664
|
-
_onSelectionDragStop(event.sourceEvent, currentNode, currentNodes);
|
|
1696
|
+
onSelectionDragStop?.(event.sourceEvent, currentNodes);
|
|
1665
1697
|
}
|
|
1666
1698
|
}
|
|
1667
1699
|
}
|
|
@@ -1693,8 +1725,8 @@ function getHandles(node, handleBounds, type, currentHandle) {
|
|
|
1693
1725
|
id: h.id || null,
|
|
1694
1726
|
type,
|
|
1695
1727
|
nodeId: node.id,
|
|
1696
|
-
x:
|
|
1697
|
-
y:
|
|
1728
|
+
x: node.internals.positionAbsolute.x + h.x + h.width / 2,
|
|
1729
|
+
y: node.internals.positionAbsolute.y + h.y + h.height / 2,
|
|
1698
1730
|
});
|
|
1699
1731
|
}
|
|
1700
1732
|
return res;
|
|
@@ -1940,15 +1972,30 @@ function XYMinimap({ domNode, panZoom, getTransform, getViewScale }) {
|
|
|
1940
1972
|
const nextZoom = transform[2] * Math.pow(2, pinchDelta);
|
|
1941
1973
|
panZoom.scaleTo(nextZoom);
|
|
1942
1974
|
};
|
|
1975
|
+
let panStart = [0, 0];
|
|
1976
|
+
const panStartHandler = (event) => {
|
|
1977
|
+
if (event.sourceEvent.type === 'mousedown' || event.sourceEvent.type === 'touchstart') {
|
|
1978
|
+
panStart = [
|
|
1979
|
+
event.sourceEvent.clientX ?? event.sourceEvent.touches[0].clientX,
|
|
1980
|
+
event.sourceEvent.clientY ?? event.sourceEvent.touches[0].clientY,
|
|
1981
|
+
];
|
|
1982
|
+
}
|
|
1983
|
+
};
|
|
1943
1984
|
const panHandler = (event) => {
|
|
1944
1985
|
const transform = getTransform();
|
|
1945
|
-
if (event.sourceEvent.type !== 'mousemove' || !panZoom) {
|
|
1986
|
+
if ((event.sourceEvent.type !== 'mousemove' && event.sourceEvent.type !== 'touchmove') || !panZoom) {
|
|
1946
1987
|
return;
|
|
1947
1988
|
}
|
|
1989
|
+
const panCurrent = [
|
|
1990
|
+
event.sourceEvent.clientX ?? event.sourceEvent.touches[0].clientX,
|
|
1991
|
+
event.sourceEvent.clientY ?? event.sourceEvent.touches[0].clientY,
|
|
1992
|
+
];
|
|
1993
|
+
const panDelta = [panCurrent[0] - panStart[0], panCurrent[1] - panStart[1]];
|
|
1994
|
+
panStart = panCurrent;
|
|
1948
1995
|
const moveScale = getViewScale() * Math.max(transform[2], Math.log(transform[2])) * (inversePan ? -1 : 1);
|
|
1949
1996
|
const position = {
|
|
1950
|
-
x: transform[0] -
|
|
1951
|
-
y: transform[1] -
|
|
1997
|
+
x: transform[0] - panDelta[0] * moveScale,
|
|
1998
|
+
y: transform[1] - panDelta[1] * moveScale,
|
|
1952
1999
|
};
|
|
1953
2000
|
const extent = [
|
|
1954
2001
|
[0, 0],
|
|
@@ -1961,6 +2008,7 @@ function XYMinimap({ domNode, panZoom, getTransform, getViewScale }) {
|
|
|
1961
2008
|
}, extent, translateExtent);
|
|
1962
2009
|
};
|
|
1963
2010
|
const zoomAndPanHandler = zoom()
|
|
2011
|
+
.on('start', panStartHandler)
|
|
1964
2012
|
// @ts-ignore
|
|
1965
2013
|
.on('zoom', pannable ? panHandler : null)
|
|
1966
2014
|
// @ts-ignore
|
|
@@ -2043,7 +2091,9 @@ function createPanOnScrollHandler({ zoomPanValues, noWheelClassName, d3Selection
|
|
|
2043
2091
|
}
|
|
2044
2092
|
function createZoomOnScrollHandler({ noWheelClassName, preventScrolling, d3ZoomHandler }) {
|
|
2045
2093
|
return function (event, d) {
|
|
2046
|
-
if
|
|
2094
|
+
// we still want to enable pinch zooming even if preventScrolling is set to false
|
|
2095
|
+
const preventZoom = !preventScrolling && event.type === 'wheel' && !event.ctrlKey;
|
|
2096
|
+
if (preventZoom || isWrappedWithClass(event, noWheelClassName)) {
|
|
2047
2097
|
return null;
|
|
2048
2098
|
}
|
|
2049
2099
|
event.preventDefault();
|
|
@@ -2558,16 +2608,6 @@ const initStartValues = {
|
|
|
2558
2608
|
pointerY: 0,
|
|
2559
2609
|
aspectRatio: 1,
|
|
2560
2610
|
};
|
|
2561
|
-
const initChange = {
|
|
2562
|
-
x: 0,
|
|
2563
|
-
y: 0,
|
|
2564
|
-
width: 0,
|
|
2565
|
-
height: 0,
|
|
2566
|
-
isXPosChange: false,
|
|
2567
|
-
isYPosChange: false,
|
|
2568
|
-
isWidthChange: false,
|
|
2569
|
-
isHeightChange: false,
|
|
2570
|
-
};
|
|
2571
2611
|
function nodeToParentExtent(node) {
|
|
2572
2612
|
return [
|
|
2573
2613
|
[0, 0],
|
|
@@ -2586,7 +2626,7 @@ function nodeToChildExtent(child, parent, nodeOrigin) {
|
|
|
2586
2626
|
[x + width - originOffsetX, y + height - originOffsetY],
|
|
2587
2627
|
];
|
|
2588
2628
|
}
|
|
2589
|
-
function XYResizer({ domNode, nodeId, getStoreItems, onChange }) {
|
|
2629
|
+
function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }) {
|
|
2590
2630
|
const selection = select(domNode);
|
|
2591
2631
|
function update({ controlPosition, boundaries, keepAspectRatio, onResizeStart, onResize, onResizeEnd, shouldResize, }) {
|
|
2592
2632
|
let prevValues = { ...initPrevValues };
|
|
@@ -2601,128 +2641,127 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange }) {
|
|
|
2601
2641
|
.on('start', (event) => {
|
|
2602
2642
|
const { nodeLookup, transform, snapGrid, snapToGrid, nodeOrigin } = getStoreItems();
|
|
2603
2643
|
node = nodeLookup.get(nodeId);
|
|
2604
|
-
if (node) {
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2644
|
+
if (!node) {
|
|
2645
|
+
return;
|
|
2646
|
+
}
|
|
2647
|
+
const { xSnapped, ySnapped } = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid });
|
|
2648
|
+
prevValues = {
|
|
2649
|
+
width: node.measured?.width ?? 0,
|
|
2650
|
+
height: node.measured?.height ?? 0,
|
|
2651
|
+
x: node.position.x ?? 0,
|
|
2652
|
+
y: node.position.y ?? 0,
|
|
2653
|
+
};
|
|
2654
|
+
startValues = {
|
|
2655
|
+
...prevValues,
|
|
2656
|
+
pointerX: xSnapped,
|
|
2657
|
+
pointerY: ySnapped,
|
|
2658
|
+
aspectRatio: prevValues.width / prevValues.height,
|
|
2659
|
+
};
|
|
2660
|
+
parentNode = undefined;
|
|
2661
|
+
if (node.extent === 'parent' || node.expandParent) {
|
|
2662
|
+
parentNode = nodeLookup.get(node.parentId);
|
|
2663
|
+
if (parentNode && node.extent === 'parent') {
|
|
2664
|
+
parentExtent = nodeToParentExtent(parentNode);
|
|
2624
2665
|
}
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
]
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2666
|
+
}
|
|
2667
|
+
// Collect all child nodes to correct their relative positions when top/left changes
|
|
2668
|
+
// Determine largest minimal extent the parent node is allowed to resize to
|
|
2669
|
+
childNodes = [];
|
|
2670
|
+
childExtent = undefined;
|
|
2671
|
+
for (const [childId, child] of nodeLookup) {
|
|
2672
|
+
if (child.parentId === nodeId) {
|
|
2673
|
+
childNodes.push({
|
|
2674
|
+
id: childId,
|
|
2675
|
+
position: { ...child.position },
|
|
2676
|
+
extent: child.extent,
|
|
2677
|
+
});
|
|
2678
|
+
if (child.extent === 'parent' || child.expandParent) {
|
|
2679
|
+
const extent = nodeToChildExtent(child, node, child.origin ?? nodeOrigin);
|
|
2680
|
+
if (childExtent) {
|
|
2681
|
+
childExtent = [
|
|
2682
|
+
[Math.min(extent[0][0], childExtent[0][0]), Math.min(extent[0][1], childExtent[0][1])],
|
|
2683
|
+
[Math.max(extent[1][0], childExtent[1][0]), Math.max(extent[1][1], childExtent[1][1])],
|
|
2684
|
+
];
|
|
2685
|
+
}
|
|
2686
|
+
else {
|
|
2687
|
+
childExtent = extent;
|
|
2647
2688
|
}
|
|
2648
2689
|
}
|
|
2649
2690
|
}
|
|
2650
|
-
onResizeStart?.(event, { ...prevValues });
|
|
2651
2691
|
}
|
|
2692
|
+
onResizeStart?.(event, { ...prevValues });
|
|
2652
2693
|
})
|
|
2653
2694
|
.on('drag', (event) => {
|
|
2654
2695
|
const { transform, snapGrid, snapToGrid, nodeOrigin: storeNodeOrigin } = getStoreItems();
|
|
2655
2696
|
const pointerPosition = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid });
|
|
2656
2697
|
const childChanges = [];
|
|
2657
|
-
if (node) {
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
startValues.y = startValues.y - change.y;
|
|
2682
|
-
}
|
|
2698
|
+
if (!node) {
|
|
2699
|
+
return;
|
|
2700
|
+
}
|
|
2701
|
+
const { x: prevX, y: prevY, width: prevWidth, height: prevHeight } = prevValues;
|
|
2702
|
+
const change = {};
|
|
2703
|
+
const nodeOrigin = node.origin ?? storeNodeOrigin;
|
|
2704
|
+
const { width, height, x, y } = getDimensionsAfterResize(startValues, controlDirection, pointerPosition, boundaries, keepAspectRatio, nodeOrigin, parentExtent, childExtent);
|
|
2705
|
+
const isWidthChange = width !== prevWidth;
|
|
2706
|
+
const isHeightChange = height !== prevHeight;
|
|
2707
|
+
const isXPosChange = x !== prevX && isWidthChange;
|
|
2708
|
+
const isYPosChange = y !== prevY && isHeightChange;
|
|
2709
|
+
if (!isXPosChange && !isYPosChange && !isWidthChange && !isHeightChange) {
|
|
2710
|
+
return;
|
|
2711
|
+
}
|
|
2712
|
+
if (isXPosChange || isYPosChange || nodeOrigin[0] === 1 || nodeOrigin[1] == 1) {
|
|
2713
|
+
change.x = isXPosChange ? x : prevValues.x;
|
|
2714
|
+
change.y = isYPosChange ? y : prevValues.y;
|
|
2715
|
+
prevValues.x = change.x;
|
|
2716
|
+
prevValues.y = change.y;
|
|
2717
|
+
// Fix expandParent when resizing from top/left
|
|
2718
|
+
if (parentNode && node.expandParent) {
|
|
2719
|
+
if (change.x && change.x < 0) {
|
|
2720
|
+
prevValues.x = 0;
|
|
2721
|
+
startValues.x = startValues.x - change.x;
|
|
2683
2722
|
}
|
|
2684
|
-
if (
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
for (const childNode of childNodes) {
|
|
2688
|
-
childNode.position = {
|
|
2689
|
-
x: childNode.position.x - xChange + nodeOrigin[0] * (width - prevWidth),
|
|
2690
|
-
y: childNode.position.y - yChange + nodeOrigin[1] * (height - prevHeight),
|
|
2691
|
-
};
|
|
2692
|
-
childChanges.push(childNode);
|
|
2693
|
-
}
|
|
2723
|
+
if (change.y && change.y < 0) {
|
|
2724
|
+
prevValues.y = 0;
|
|
2725
|
+
startValues.y = startValues.y - change.y;
|
|
2694
2726
|
}
|
|
2695
2727
|
}
|
|
2696
|
-
if (
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
}
|
|
2707
|
-
const direction = getResizeDirection({
|
|
2708
|
-
width: prevValues.width,
|
|
2709
|
-
prevWidth,
|
|
2710
|
-
height: prevValues.height,
|
|
2711
|
-
prevHeight,
|
|
2712
|
-
affectsX: controlDirection.affectsX,
|
|
2713
|
-
affectsY: controlDirection.affectsY,
|
|
2714
|
-
});
|
|
2715
|
-
const nextValues = { ...prevValues, direction };
|
|
2716
|
-
const callResize = shouldResize?.(event, nextValues);
|
|
2717
|
-
if (callResize === false) {
|
|
2718
|
-
return;
|
|
2728
|
+
if (childNodes.length > 0) {
|
|
2729
|
+
const xChange = x - prevX;
|
|
2730
|
+
const yChange = y - prevY;
|
|
2731
|
+
for (const childNode of childNodes) {
|
|
2732
|
+
childNode.position = {
|
|
2733
|
+
x: childNode.position.x - xChange + nodeOrigin[0] * (width - prevWidth),
|
|
2734
|
+
y: childNode.position.y - yChange + nodeOrigin[1] * (height - prevHeight),
|
|
2735
|
+
};
|
|
2736
|
+
childChanges.push(childNode);
|
|
2737
|
+
}
|
|
2719
2738
|
}
|
|
2720
|
-
onResize?.(event, nextValues);
|
|
2721
|
-
onChange(change, childChanges);
|
|
2722
2739
|
}
|
|
2740
|
+
if (isWidthChange || isHeightChange) {
|
|
2741
|
+
change.width = isWidthChange ? width : prevValues.width;
|
|
2742
|
+
change.height = isHeightChange ? height : prevValues.height;
|
|
2743
|
+
prevValues.width = change.width;
|
|
2744
|
+
prevValues.height = change.height;
|
|
2745
|
+
}
|
|
2746
|
+
const direction = getResizeDirection({
|
|
2747
|
+
width: prevValues.width,
|
|
2748
|
+
prevWidth,
|
|
2749
|
+
height: prevValues.height,
|
|
2750
|
+
prevHeight,
|
|
2751
|
+
affectsX: controlDirection.affectsX,
|
|
2752
|
+
affectsY: controlDirection.affectsY,
|
|
2753
|
+
});
|
|
2754
|
+
const nextValues = { ...prevValues, direction };
|
|
2755
|
+
const callResize = shouldResize?.(event, nextValues);
|
|
2756
|
+
if (callResize === false) {
|
|
2757
|
+
return;
|
|
2758
|
+
}
|
|
2759
|
+
onResize?.(event, nextValues);
|
|
2760
|
+
onChange(change, childChanges);
|
|
2723
2761
|
})
|
|
2724
2762
|
.on('end', (event) => {
|
|
2725
2763
|
onResizeEnd?.(event, { ...prevValues });
|
|
2764
|
+
onEnd?.();
|
|
2726
2765
|
});
|
|
2727
2766
|
selection.call(dragHandler);
|
|
2728
2767
|
}
|
|
@@ -2735,4 +2774,4 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange }) {
|
|
|
2735
2774
|
};
|
|
2736
2775
|
}
|
|
2737
2776
|
|
|
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,
|
|
2777
|
+
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, evaluateAbsolutePosition, 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, handleExpandParent, infiniteExtent, isCoordinateExtent, isEdgeBase, isEdgeVisible, isInputDOMNode, isInternalNodeBase, isMacOs, isMouseEvent, isNodeBase, isNumeric, isRectObject, nodeHasDimensions, nodeToBox, nodeToRect, panBy, pointToRendererPoint, rectToBox, rendererPointToPoint, shallowNodeData, snapPosition, updateAbsolutePositions, updateConnectionLookup, updateEdge, updateNodeInternals };
|