@xyflow/system 0.0.16 → 0.0.17
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 +256 -76
- package/dist/esm/index.mjs +256 -76
- package/dist/esm/types/general.d.ts +5 -2
- package/dist/esm/types/general.d.ts.map +1 -1
- package/dist/esm/utils/connections.d.ts +3 -3
- package/dist/esm/utils/connections.d.ts.map +1 -1
- package/dist/esm/utils/dom.d.ts.map +1 -1
- package/dist/esm/xyresizer/XYResizer.d.ts +7 -2
- package/dist/esm/xyresizer/XYResizer.d.ts.map +1 -1
- package/dist/esm/xyresizer/utils.d.ts +12 -13
- package/dist/esm/xyresizer/utils.d.ts.map +1 -1
- package/dist/umd/index.js +1 -1
- package/dist/umd/types/general.d.ts +5 -2
- package/dist/umd/types/general.d.ts.map +1 -1
- package/dist/umd/utils/connections.d.ts +3 -3
- package/dist/umd/utils/connections.d.ts.map +1 -1
- package/dist/umd/utils/dom.d.ts.map +1 -1
- package/dist/umd/xyresizer/XYResizer.d.ts +7 -2
- package/dist/umd/xyresizer/XYResizer.d.ts.map +1 -1
- package/dist/umd/xyresizer/utils.d.ts +12 -13
- package/dist/umd/xyresizer/utils.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/esm/index.js
CHANGED
|
@@ -539,10 +539,8 @@ function isInputDOMNode(event) {
|
|
|
539
539
|
// using composed path for handling shadow dom
|
|
540
540
|
const target = (event.composedPath?.()?.[0] || event.target);
|
|
541
541
|
const isInput = inputTags.includes(target?.nodeName) || target?.hasAttribute('contenteditable');
|
|
542
|
-
// we want to be able to do a multi selection event if we are in an input field
|
|
543
|
-
const isModifierKey = event.ctrlKey || event.metaKey || event.shiftKey;
|
|
544
542
|
// when an input field is focused we don't want to trigger deletion or movement of nodes
|
|
545
|
-
return
|
|
543
|
+
return isInput || !!target?.closest('.nokey');
|
|
546
544
|
}
|
|
547
545
|
const isMouseEvent = (event) => 'clientX' in event;
|
|
548
546
|
const getEventPosition = (event, bounds) => {
|
|
@@ -1182,8 +1180,8 @@ function adoptUserProvidedNodes(nodes, nodeLookup, options = {
|
|
|
1182
1180
|
...n,
|
|
1183
1181
|
computed: {
|
|
1184
1182
|
positionAbsolute: n.position,
|
|
1185
|
-
width: n.computed?.width
|
|
1186
|
-
height: n.computed?.height
|
|
1183
|
+
width: n.computed?.width,
|
|
1184
|
+
height: n.computed?.height,
|
|
1187
1185
|
},
|
|
1188
1186
|
};
|
|
1189
1187
|
const z = (isNumeric(n.zIndex) ? n.zIndex : 0) + (n.selected ? selectedNodeZ : 0);
|
|
@@ -1280,7 +1278,7 @@ function updateConnectionLookup(connectionLookup, edgeLookup, edges) {
|
|
|
1280
1278
|
const targetKey = `${target}-target-${targetHandle}`;
|
|
1281
1279
|
const prevSource = connectionLookup.get(sourceKey) || new Map();
|
|
1282
1280
|
const prevTarget = connectionLookup.get(targetKey) || new Map();
|
|
1283
|
-
const connection = { source, target, sourceHandle, targetHandle };
|
|
1281
|
+
const connection = { edgeId: edge.id, source, target, sourceHandle, targetHandle };
|
|
1284
1282
|
edgeLookup.set(edge.id, edge);
|
|
1285
1283
|
connectionLookup.set(sourceKey, prevSource.set(`${target}-${targetHandle}`, connection));
|
|
1286
1284
|
connectionLookup.set(targetKey, prevTarget.set(`${source}-${sourceHandle}`, connection));
|
|
@@ -1418,7 +1416,7 @@ function XYDrag({ domNode, onNodeMouseDown, getStoreItems, onDragStart, onDrag,
|
|
|
1418
1416
|
if (!hasChange) {
|
|
1419
1417
|
return;
|
|
1420
1418
|
}
|
|
1421
|
-
updateNodePositions(dragItems, true
|
|
1419
|
+
updateNodePositions(dragItems, true);
|
|
1422
1420
|
const onNodeOrSelectionDrag = nodeId ? onNodeDrag : wrapSelectionDragFunc(onSelectionDrag);
|
|
1423
1421
|
if (dragEvent && (onDrag || onNodeOrSelectionDrag)) {
|
|
1424
1422
|
const [currentNode, currentNodes] = getEventHandlerParams({
|
|
@@ -1461,7 +1459,7 @@ function XYDrag({ domNode, onNodeMouseDown, getStoreItems, onDragStart, onDrag,
|
|
|
1461
1459
|
lastPos = pointerPos;
|
|
1462
1460
|
dragItems = getDragItems(nodes, nodesDraggable, pointerPos, nodeId);
|
|
1463
1461
|
const onNodeOrSelectionDragStart = nodeId ? onNodeDragStart : wrapSelectionDragFunc(onSelectionDragStart);
|
|
1464
|
-
if (dragItems && (onDragStart || onNodeOrSelectionDragStart)) {
|
|
1462
|
+
if (dragItems.length > 0 && (onDragStart || onNodeOrSelectionDragStart)) {
|
|
1465
1463
|
const [currentNode, currentNodes] = getEventHandlerParams({
|
|
1466
1464
|
nodeId,
|
|
1467
1465
|
dragItems,
|
|
@@ -1511,10 +1509,10 @@ function XYDrag({ domNode, onNodeMouseDown, getStoreItems, onDragStart, onDrag,
|
|
|
1511
1509
|
autoPanStarted = false;
|
|
1512
1510
|
dragStarted = false;
|
|
1513
1511
|
cancelAnimationFrame(autoPanId);
|
|
1514
|
-
if (dragItems) {
|
|
1512
|
+
if (dragItems.length > 0) {
|
|
1515
1513
|
const { nodeLookup, updateNodePositions, onNodeDragStop, onSelectionDragStop } = getStoreItems();
|
|
1516
1514
|
const onNodeOrSelectionDragStop = nodeId ? onNodeDragStop : wrapSelectionDragFunc(onSelectionDragStop);
|
|
1517
|
-
updateNodePositions(dragItems, false
|
|
1515
|
+
updateNodePositions(dragItems, false);
|
|
1518
1516
|
if (onDragStop || onNodeOrSelectionDragStop) {
|
|
1519
1517
|
const [currentNode, currentNodes] = getEventHandlerParams({
|
|
1520
1518
|
nodeId,
|
|
@@ -2240,65 +2238,173 @@ function getControlDirection(controlPosition) {
|
|
|
2240
2238
|
affectsY,
|
|
2241
2239
|
};
|
|
2242
2240
|
}
|
|
2241
|
+
function getLowerExtentClamp(lowerExtent, lowerBound) {
|
|
2242
|
+
return Math.max(0, lowerBound - lowerExtent);
|
|
2243
|
+
}
|
|
2244
|
+
function getUpperExtentClamp(upperExtent, upperBound) {
|
|
2245
|
+
return Math.max(0, upperExtent - upperBound);
|
|
2246
|
+
}
|
|
2247
|
+
function getSizeClamp(size, minSize, maxSize) {
|
|
2248
|
+
return Math.max(0, minSize - size, size - maxSize);
|
|
2249
|
+
}
|
|
2250
|
+
function xor(a, b) {
|
|
2251
|
+
return a ? !b : b;
|
|
2252
|
+
}
|
|
2243
2253
|
/**
|
|
2244
|
-
* Calculates new width & height of node after resize based on pointer position
|
|
2254
|
+
* Calculates new width & height and x & y of node after resize based on pointer position
|
|
2255
|
+
* @description - Buckle up, this is a chunky one! If you want to determine the new dimensions of a node after a resize,
|
|
2256
|
+
* you have to account for all possible restrictions: min/max width/height of the node, the maximum extent the node is allowed
|
|
2257
|
+
* to move in (in this case: resize into) determined by the parent node, the minimal extent determined by child nodes
|
|
2258
|
+
* with expandParent or extent: 'parent' set and oh yeah, these things also have to work with keepAspectRatio!
|
|
2259
|
+
* The way this is done is by determining how much each of these restricting actually restricts the resize and then applying the
|
|
2260
|
+
* strongest restriction. Because the resize affects x, y and width, height and width, height of a opposing side with keepAspectRatio,
|
|
2261
|
+
* the resize amount is always kept in distX & distY amount (the distance in mouse movement)
|
|
2262
|
+
* Instead of clamping each value, we first calculate the biggest 'clamp' (for the lack of a better name) and then apply it to all values.
|
|
2245
2263
|
* @param startValues - starting values of resize
|
|
2246
2264
|
* @param controlDirection - dimensions affected by the resize
|
|
2247
2265
|
* @param pointerPosition - the current pointer position corrected for snapping
|
|
2248
2266
|
* @param boundaries - minimum and maximum dimensions of the node
|
|
2249
2267
|
* @param keepAspectRatio - prevent changes of asprect ratio
|
|
2250
|
-
* @returns
|
|
2268
|
+
* @returns x, y, width and height of the node after resize
|
|
2251
2269
|
*/
|
|
2252
|
-
function getDimensionsAfterResize(startValues, controlDirection, pointerPosition, boundaries, keepAspectRatio) {
|
|
2253
|
-
|
|
2270
|
+
function getDimensionsAfterResize(startValues, controlDirection, pointerPosition, boundaries, keepAspectRatio, extent, childExtent) {
|
|
2271
|
+
let { affectsX, affectsY } = controlDirection;
|
|
2272
|
+
const { isHorizontal, isVertical } = controlDirection;
|
|
2273
|
+
const isDiagonal = isHorizontal && isVertical;
|
|
2254
2274
|
const { xSnapped, ySnapped } = pointerPosition;
|
|
2255
2275
|
const { minWidth, maxWidth, minHeight, maxHeight } = boundaries;
|
|
2256
|
-
const {
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2276
|
+
const { x: startX, y: startY, width: startWidth, height: startHeight, aspectRatio } = startValues;
|
|
2277
|
+
let distX = Math.floor(isHorizontal ? xSnapped - startValues.pointerX : 0);
|
|
2278
|
+
let distY = Math.floor(isVertical ? ySnapped - startValues.pointerY : 0);
|
|
2279
|
+
const newWidth = startWidth + (affectsX ? -distX : distX);
|
|
2280
|
+
const newHeight = startHeight + (affectsY ? -distY : distY);
|
|
2281
|
+
// Check if maxWidth, minWWidth, maxHeight, minHeight are restricting the resize
|
|
2282
|
+
let clampX = getSizeClamp(newWidth, minWidth, maxWidth);
|
|
2283
|
+
let clampY = getSizeClamp(newHeight, minHeight, maxHeight);
|
|
2284
|
+
// Check if extent is restricting the resize
|
|
2285
|
+
if (extent) {
|
|
2286
|
+
let xExtentClamp = 0;
|
|
2287
|
+
let yExtentClamp = 0;
|
|
2288
|
+
if (affectsX && distX < 0) {
|
|
2289
|
+
xExtentClamp = getLowerExtentClamp(startX + distX, extent[0][0]);
|
|
2290
|
+
}
|
|
2291
|
+
else if (!affectsX && distX > 0) {
|
|
2292
|
+
xExtentClamp = getUpperExtentClamp(startX + newWidth, extent[1][0]);
|
|
2293
|
+
}
|
|
2294
|
+
if (affectsY && distY < 0) {
|
|
2295
|
+
yExtentClamp = getLowerExtentClamp(startY + distY, extent[0][1]);
|
|
2296
|
+
}
|
|
2297
|
+
else if (!affectsY && distY > 0) {
|
|
2298
|
+
yExtentClamp = getUpperExtentClamp(startY + newHeight, extent[1][1]);
|
|
2299
|
+
}
|
|
2300
|
+
clampX = Math.max(clampX, xExtentClamp);
|
|
2301
|
+
clampY = Math.max(clampY, yExtentClamp);
|
|
2302
|
+
}
|
|
2303
|
+
// Check if the child extent is restricting the resize
|
|
2304
|
+
if (childExtent) {
|
|
2305
|
+
let xExtentClamp = 0;
|
|
2306
|
+
let yExtentClamp = 0;
|
|
2307
|
+
if (affectsX && distX > 0) {
|
|
2308
|
+
xExtentClamp = getUpperExtentClamp(startX + distX, childExtent[0][0]);
|
|
2309
|
+
}
|
|
2310
|
+
else if (!affectsX && distX < 0) {
|
|
2311
|
+
xExtentClamp = getLowerExtentClamp(startX + newWidth, childExtent[1][0]);
|
|
2312
|
+
}
|
|
2313
|
+
if (affectsY && distY > 0) {
|
|
2314
|
+
yExtentClamp = getUpperExtentClamp(startY + distY, childExtent[0][1]);
|
|
2315
|
+
}
|
|
2316
|
+
else if (!affectsY && distY < 0) {
|
|
2317
|
+
yExtentClamp = getLowerExtentClamp(startY + newHeight, childExtent[1][1]);
|
|
2318
|
+
}
|
|
2319
|
+
clampX = Math.max(clampX, xExtentClamp);
|
|
2320
|
+
clampY = Math.max(clampY, yExtentClamp);
|
|
2321
|
+
}
|
|
2322
|
+
// Check if the aspect ratio resizing of the other side is restricting the resize
|
|
2261
2323
|
if (keepAspectRatio) {
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2324
|
+
if (isHorizontal) {
|
|
2325
|
+
// Check if the max dimensions might be restricting the resize
|
|
2326
|
+
const aspectHeightClamp = getSizeClamp(newWidth / aspectRatio, minHeight, maxHeight) * aspectRatio;
|
|
2327
|
+
clampX = Math.max(clampX, aspectHeightClamp);
|
|
2328
|
+
// Check if the extent is restricting the resize
|
|
2329
|
+
if (extent) {
|
|
2330
|
+
let aspectExtentClamp = 0;
|
|
2331
|
+
if ((!affectsX && !affectsY) || (affectsX && !affectsY && isDiagonal)) {
|
|
2332
|
+
aspectExtentClamp = getUpperExtentClamp(startY + newWidth / aspectRatio, extent[1][1]) * aspectRatio;
|
|
2333
|
+
}
|
|
2334
|
+
else {
|
|
2335
|
+
aspectExtentClamp =
|
|
2336
|
+
getLowerExtentClamp(startY + (affectsX ? distX : -distX) / aspectRatio, extent[0][1]) * aspectRatio;
|
|
2337
|
+
}
|
|
2338
|
+
clampX = Math.max(clampX, aspectExtentClamp);
|
|
2339
|
+
}
|
|
2340
|
+
// Check if the child extent is restricting the resize
|
|
2341
|
+
if (childExtent) {
|
|
2342
|
+
let aspectExtentClamp = 0;
|
|
2343
|
+
if ((!affectsX && !affectsY) || (affectsX && !affectsY && isDiagonal)) {
|
|
2344
|
+
aspectExtentClamp = getLowerExtentClamp(startY + newWidth / aspectRatio, childExtent[1][1]) * aspectRatio;
|
|
2345
|
+
}
|
|
2346
|
+
else {
|
|
2347
|
+
aspectExtentClamp =
|
|
2348
|
+
getUpperExtentClamp(startY + (affectsX ? distX : -distX) / aspectRatio, childExtent[0][1]) * aspectRatio;
|
|
2349
|
+
}
|
|
2350
|
+
clampX = Math.max(clampX, aspectExtentClamp);
|
|
2351
|
+
}
|
|
2271
2352
|
}
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2353
|
+
// Do the same thing for vertical resizing
|
|
2354
|
+
if (isVertical) {
|
|
2355
|
+
const aspectWidthClamp = getSizeClamp(newHeight * aspectRatio, minWidth, maxWidth) / aspectRatio;
|
|
2356
|
+
clampY = Math.max(clampY, aspectWidthClamp);
|
|
2357
|
+
if (extent) {
|
|
2358
|
+
let aspectExtentClamp = 0;
|
|
2359
|
+
if ((!affectsX && !affectsY) || (affectsY && !affectsX && isDiagonal)) {
|
|
2360
|
+
aspectExtentClamp = getUpperExtentClamp(startX + newHeight * aspectRatio, extent[1][0]) / aspectRatio;
|
|
2361
|
+
}
|
|
2362
|
+
else {
|
|
2363
|
+
aspectExtentClamp =
|
|
2364
|
+
getLowerExtentClamp(startX + (affectsY ? distY : -distY) * aspectRatio, extent[0][0]) / aspectRatio;
|
|
2365
|
+
}
|
|
2366
|
+
clampY = Math.max(clampY, aspectExtentClamp);
|
|
2367
|
+
}
|
|
2368
|
+
if (childExtent) {
|
|
2369
|
+
let aspectExtentClamp = 0;
|
|
2370
|
+
if ((!affectsX && !affectsY) || (affectsY && !affectsX && isDiagonal)) {
|
|
2371
|
+
aspectExtentClamp = getLowerExtentClamp(startX + newHeight * aspectRatio, childExtent[1][0]) / aspectRatio;
|
|
2372
|
+
}
|
|
2373
|
+
else {
|
|
2374
|
+
aspectExtentClamp =
|
|
2375
|
+
getUpperExtentClamp(startX + (affectsY ? distY : -distY) * aspectRatio, childExtent[0][0]) / aspectRatio;
|
|
2376
|
+
}
|
|
2377
|
+
clampY = Math.max(clampY, aspectExtentClamp);
|
|
2378
|
+
}
|
|
2275
2379
|
}
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2380
|
+
}
|
|
2381
|
+
distY = distY + (distY < 0 ? clampY : -clampY);
|
|
2382
|
+
distX = distX + (distX < 0 ? clampX : -clampX);
|
|
2383
|
+
if (keepAspectRatio) {
|
|
2384
|
+
if (isDiagonal) {
|
|
2385
|
+
if (newWidth > newHeight * aspectRatio) {
|
|
2386
|
+
distY = (xor(affectsX, affectsY) ? -distX : distX) / aspectRatio;
|
|
2387
|
+
}
|
|
2388
|
+
else {
|
|
2389
|
+
distX = (xor(affectsX, affectsY) ? -distY : distY) * aspectRatio;
|
|
2390
|
+
}
|
|
2279
2391
|
}
|
|
2280
|
-
else
|
|
2281
|
-
|
|
2282
|
-
|
|
2392
|
+
else {
|
|
2393
|
+
if (isHorizontal) {
|
|
2394
|
+
distY = distX / aspectRatio;
|
|
2395
|
+
affectsY = affectsX;
|
|
2396
|
+
}
|
|
2397
|
+
else {
|
|
2398
|
+
distX = distY * aspectRatio;
|
|
2399
|
+
affectsX = affectsY;
|
|
2400
|
+
}
|
|
2283
2401
|
}
|
|
2284
2402
|
}
|
|
2285
2403
|
return {
|
|
2286
|
-
width,
|
|
2287
|
-
height,
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
/**
|
|
2291
|
-
* Determines new x & y position of node after resize based on new width & height
|
|
2292
|
-
* @param startValues - starting values of resize
|
|
2293
|
-
* @param controlDirection - dimensions affected by the resize
|
|
2294
|
-
* @param width - new width of node
|
|
2295
|
-
* @param height - new height of node
|
|
2296
|
-
* @returns x: new x position of node, y: new y position of node
|
|
2297
|
-
*/
|
|
2298
|
-
function getPositionAfterResize(startValues, controlDirection, width, height) {
|
|
2299
|
-
return {
|
|
2300
|
-
x: controlDirection.affectsX ? startValues.x - (width - startValues.width) : startValues.x,
|
|
2301
|
-
y: controlDirection.affectsY ? startValues.y - (height - startValues.height) : startValues.y,
|
|
2404
|
+
width: startWidth + (affectsX ? -distX : distX),
|
|
2405
|
+
height: startHeight + (affectsY ? -distY : distY),
|
|
2406
|
+
x: affectsX ? startX + distX : startX,
|
|
2407
|
+
y: affectsY ? startY + distY : startY,
|
|
2302
2408
|
};
|
|
2303
2409
|
}
|
|
2304
2410
|
|
|
@@ -2319,44 +2425,96 @@ const initChange = {
|
|
|
2319
2425
|
isWidthChange: false,
|
|
2320
2426
|
isHeightChange: false,
|
|
2321
2427
|
};
|
|
2428
|
+
function nodeToParentExtent(node) {
|
|
2429
|
+
return [
|
|
2430
|
+
[0, 0],
|
|
2431
|
+
[node.computed.width, node.computed.height],
|
|
2432
|
+
];
|
|
2433
|
+
}
|
|
2434
|
+
function nodeToChildExtent(child, parent) {
|
|
2435
|
+
return [
|
|
2436
|
+
[parent.position.x + child.position.x, parent.position.y + child.position.y],
|
|
2437
|
+
[
|
|
2438
|
+
parent.position.x + child.position.x + child.computed.width,
|
|
2439
|
+
parent.position.y + child.position.y + child.computed.height,
|
|
2440
|
+
],
|
|
2441
|
+
];
|
|
2442
|
+
}
|
|
2322
2443
|
function XYResizer({ domNode, nodeId, getStoreItems, onChange }) {
|
|
2323
2444
|
const selection = select(domNode);
|
|
2324
2445
|
function update({ controlPosition, boundaries, keepAspectRatio, onResizeStart, onResize, onResizeEnd, shouldResize, }) {
|
|
2325
2446
|
let prevValues = { ...initPrevValues };
|
|
2326
2447
|
let startValues = { ...initStartValues };
|
|
2327
2448
|
const controlDirection = getControlDirection(controlPosition);
|
|
2449
|
+
let node = undefined;
|
|
2450
|
+
let childNodes = [];
|
|
2451
|
+
let parentNode = undefined; // Needed to fix expandParent
|
|
2452
|
+
let parentExtent = undefined;
|
|
2453
|
+
let childExtent = undefined;
|
|
2328
2454
|
const dragHandler = drag()
|
|
2329
2455
|
.on('start', (event) => {
|
|
2330
2456
|
const { nodeLookup, transform, snapGrid, snapToGrid } = getStoreItems();
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2457
|
+
node = nodeLookup.get(nodeId);
|
|
2458
|
+
if (node) {
|
|
2459
|
+
const { xSnapped, ySnapped } = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid });
|
|
2460
|
+
prevValues = {
|
|
2461
|
+
width: node.computed?.width ?? 0,
|
|
2462
|
+
height: node.computed?.height ?? 0,
|
|
2463
|
+
x: node.position.x ?? 0,
|
|
2464
|
+
y: node.position.y ?? 0,
|
|
2465
|
+
};
|
|
2466
|
+
startValues = {
|
|
2467
|
+
...prevValues,
|
|
2468
|
+
pointerX: xSnapped,
|
|
2469
|
+
pointerY: ySnapped,
|
|
2470
|
+
aspectRatio: prevValues.width / prevValues.height,
|
|
2471
|
+
};
|
|
2472
|
+
parentNode = undefined;
|
|
2473
|
+
if (node.extent === 'parent' || node.expandParent) {
|
|
2474
|
+
parentNode = nodeLookup.get(node.parentNode);
|
|
2475
|
+
if (parentNode && node.extent === 'parent') {
|
|
2476
|
+
parentExtent = nodeToParentExtent(parentNode);
|
|
2477
|
+
}
|
|
2478
|
+
}
|
|
2479
|
+
// Collect all child nodes to correct their relative positions when top/left changes
|
|
2480
|
+
// Determine largest minimal extent the parent node is allowed to resize to
|
|
2481
|
+
childNodes = [];
|
|
2482
|
+
childExtent = undefined;
|
|
2483
|
+
for (const [childId, child] of nodeLookup) {
|
|
2484
|
+
if (child.parentNode === nodeId) {
|
|
2485
|
+
childNodes.push({
|
|
2486
|
+
id: childId,
|
|
2487
|
+
position: { ...child.position },
|
|
2488
|
+
extent: child.extent,
|
|
2489
|
+
});
|
|
2490
|
+
if (child.extent === 'parent' || child.expandParent) {
|
|
2491
|
+
const extent = nodeToChildExtent(child, node);
|
|
2492
|
+
if (childExtent) {
|
|
2493
|
+
childExtent = [
|
|
2494
|
+
[Math.min(extent[0][0], childExtent[0][0]), Math.min(extent[0][1], childExtent[0][1])],
|
|
2495
|
+
[Math.max(extent[1][0], childExtent[1][0]), Math.max(extent[1][1], childExtent[1][1])],
|
|
2496
|
+
];
|
|
2497
|
+
}
|
|
2498
|
+
else {
|
|
2499
|
+
childExtent = extent;
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2502
|
+
}
|
|
2503
|
+
}
|
|
2504
|
+
onResizeStart?.(event, { ...prevValues });
|
|
2505
|
+
}
|
|
2346
2506
|
})
|
|
2347
2507
|
.on('drag', (event) => {
|
|
2348
|
-
const {
|
|
2508
|
+
const { transform, snapGrid, snapToGrid } = getStoreItems();
|
|
2349
2509
|
const pointerPosition = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid });
|
|
2350
|
-
const
|
|
2510
|
+
const childChanges = [];
|
|
2351
2511
|
if (node) {
|
|
2352
2512
|
const change = { ...initChange };
|
|
2353
2513
|
const { x: prevX, y: prevY, width: prevWidth, height: prevHeight } = prevValues;
|
|
2354
|
-
const { width, height } = getDimensionsAfterResize(startValues, controlDirection, pointerPosition, boundaries, keepAspectRatio);
|
|
2514
|
+
const { width, height, x, y } = getDimensionsAfterResize(startValues, controlDirection, pointerPosition, boundaries, keepAspectRatio, parentExtent, childExtent);
|
|
2355
2515
|
const isWidthChange = width !== prevWidth;
|
|
2356
2516
|
const isHeightChange = height !== prevHeight;
|
|
2357
2517
|
if (controlDirection.affectsX || controlDirection.affectsY) {
|
|
2358
|
-
const { x, y } = getPositionAfterResize(startValues, controlDirection, width, height);
|
|
2359
|
-
// only transform the node if the width or height changes
|
|
2360
2518
|
const isXPosChange = x !== prevX && isWidthChange;
|
|
2361
2519
|
const isYPosChange = y !== prevY && isHeightChange;
|
|
2362
2520
|
if (isXPosChange || isYPosChange) {
|
|
@@ -2366,6 +2524,28 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange }) {
|
|
|
2366
2524
|
change.y = isYPosChange ? y : prevY;
|
|
2367
2525
|
prevValues.x = change.x;
|
|
2368
2526
|
prevValues.y = change.y;
|
|
2527
|
+
// Fix expandParent when resizing from top/left
|
|
2528
|
+
if (parentNode && node.expandParent) {
|
|
2529
|
+
if (change.x < 0) {
|
|
2530
|
+
prevValues.x = 0;
|
|
2531
|
+
startValues.x = startValues.x - change.x;
|
|
2532
|
+
}
|
|
2533
|
+
if (change.y < 0) {
|
|
2534
|
+
prevValues.y = 0;
|
|
2535
|
+
startValues.y = startValues.y - change.y;
|
|
2536
|
+
}
|
|
2537
|
+
}
|
|
2538
|
+
}
|
|
2539
|
+
if (childNodes.length > 0) {
|
|
2540
|
+
const xChange = x - prevX;
|
|
2541
|
+
const yChange = y - prevY;
|
|
2542
|
+
for (const childNode of childNodes) {
|
|
2543
|
+
childNode.position = {
|
|
2544
|
+
x: childNode.position.x - xChange,
|
|
2545
|
+
y: childNode.position.y - yChange,
|
|
2546
|
+
};
|
|
2547
|
+
childChanges.push(childNode);
|
|
2548
|
+
}
|
|
2369
2549
|
}
|
|
2370
2550
|
}
|
|
2371
2551
|
if (isWidthChange || isHeightChange) {
|
|
@@ -2373,8 +2553,8 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange }) {
|
|
|
2373
2553
|
change.isHeightChange = isHeightChange;
|
|
2374
2554
|
change.width = width;
|
|
2375
2555
|
change.height = height;
|
|
2376
|
-
prevValues.width = width;
|
|
2377
|
-
prevValues.height = height;
|
|
2556
|
+
prevValues.width = change.width;
|
|
2557
|
+
prevValues.height = change.height;
|
|
2378
2558
|
}
|
|
2379
2559
|
if (!change.isXPosChange && !change.isYPosChange && !isWidthChange && !isHeightChange) {
|
|
2380
2560
|
return;
|
|
@@ -2393,7 +2573,7 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange }) {
|
|
|
2393
2573
|
return;
|
|
2394
2574
|
}
|
|
2395
2575
|
onResize?.(event, nextValues);
|
|
2396
|
-
onChange(change);
|
|
2576
|
+
onChange(change, childChanges);
|
|
2397
2577
|
}
|
|
2398
2578
|
})
|
|
2399
2579
|
.on('end', (event) => {
|