@xyflow/system 0.0.13 → 0.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/LICENSE +1 -1
  2. package/dist/esm/index.d.ts +1 -0
  3. package/dist/esm/index.d.ts.map +1 -1
  4. package/dist/esm/index.js +229 -11
  5. package/dist/esm/index.mjs +229 -11
  6. package/dist/esm/types/edges.d.ts +18 -0
  7. package/dist/esm/types/edges.d.ts.map +1 -1
  8. package/dist/esm/types/handles.d.ts +17 -0
  9. package/dist/esm/types/handles.d.ts.map +1 -1
  10. package/dist/esm/types/nodes.d.ts +36 -0
  11. package/dist/esm/types/nodes.d.ts.map +1 -1
  12. package/dist/esm/types/utils.d.ts.map +1 -1
  13. package/dist/esm/utils/edges/general.d.ts +2 -2
  14. package/dist/esm/utils/edges/general.d.ts.map +1 -1
  15. package/dist/esm/utils/graph.d.ts +3 -3
  16. package/dist/esm/utils/graph.d.ts.map +1 -1
  17. package/dist/esm/xyhandle/XYHandle.d.ts +2 -0
  18. package/dist/esm/xyhandle/XYHandle.d.ts.map +1 -1
  19. package/dist/esm/xyresizer/XYResizer.d.ts +46 -0
  20. package/dist/esm/xyresizer/XYResizer.d.ts.map +1 -0
  21. package/dist/esm/xyresizer/index.d.ts +3 -0
  22. package/dist/esm/xyresizer/index.d.ts.map +1 -0
  23. package/dist/esm/xyresizer/types.d.ts +26 -0
  24. package/dist/esm/xyresizer/types.d.ts.map +1 -0
  25. package/dist/esm/xyresizer/utils.d.ts +75 -0
  26. package/dist/esm/xyresizer/utils.d.ts.map +1 -0
  27. package/dist/umd/index.d.ts +1 -0
  28. package/dist/umd/index.d.ts.map +1 -1
  29. package/dist/umd/index.js +1 -1
  30. package/dist/umd/types/edges.d.ts +18 -0
  31. package/dist/umd/types/edges.d.ts.map +1 -1
  32. package/dist/umd/types/handles.d.ts +17 -0
  33. package/dist/umd/types/handles.d.ts.map +1 -1
  34. package/dist/umd/types/nodes.d.ts +36 -0
  35. package/dist/umd/types/nodes.d.ts.map +1 -1
  36. package/dist/umd/types/utils.d.ts.map +1 -1
  37. package/dist/umd/utils/edges/general.d.ts +2 -2
  38. package/dist/umd/utils/edges/general.d.ts.map +1 -1
  39. package/dist/umd/utils/graph.d.ts +3 -3
  40. package/dist/umd/utils/graph.d.ts.map +1 -1
  41. package/dist/umd/xyhandle/XYHandle.d.ts +2 -0
  42. package/dist/umd/xyhandle/XYHandle.d.ts.map +1 -1
  43. package/dist/umd/xyresizer/XYResizer.d.ts +46 -0
  44. package/dist/umd/xyresizer/XYResizer.d.ts.map +1 -0
  45. package/dist/umd/xyresizer/index.d.ts +3 -0
  46. package/dist/umd/xyresizer/index.d.ts.map +1 -0
  47. package/dist/umd/xyresizer/types.d.ts +26 -0
  48. package/dist/umd/xyresizer/types.d.ts.map +1 -0
  49. package/dist/umd/xyresizer/utils.d.ts +75 -0
  50. package/dist/umd/xyresizer/utils.d.ts.map +1 -0
  51. package/package.json +3 -3
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2019-2023 webkid GmbH
3
+ Copyright (c) 2019-2024 webkid GmbH
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -5,4 +5,5 @@ export * from './xydrag';
5
5
  export * from './xyhandle';
6
6
  export * from './xyminimap';
7
7
  export * from './xypanzoom';
8
+ export * from './xyresizer';
8
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC"}
package/dist/esm/index.js CHANGED
@@ -128,7 +128,7 @@ const isNodeBase = (element) => 'id' in element && !('source' in element) && !('
128
128
  * @param edges - The array of all edges
129
129
  * @returns An array of nodes that are connected over eges where the source is the given node
130
130
  */
131
- const getOutgoersBase = (node, nodes, edges) => {
131
+ const getOutgoers = (node, nodes, edges) => {
132
132
  if (!node.id) {
133
133
  return [];
134
134
  }
@@ -148,7 +148,7 @@ const getOutgoersBase = (node, nodes, edges) => {
148
148
  * @param edges - The array of all edges
149
149
  * @returns An array of nodes that are connected over eges where the target is the given node
150
150
  */
151
- const getIncomersBase = (node, nodes, edges) => {
151
+ const getIncomers = (node, nodes, edges) => {
152
152
  if (!node.id) {
153
153
  return [];
154
154
  }
@@ -200,7 +200,7 @@ const getNodesBounds = (nodes, nodeOrigin = [0, 0]) => {
200
200
  return { x: 0, y: 0, width: 0, height: 0 };
201
201
  }
202
202
  const box = nodes.reduce((currBox, node) => {
203
- const { x, y } = getNodePositionWithOrigin(node, node.origin || nodeOrigin).positionAbsolute;
203
+ const { x, y } = getNodePositionWithOrigin(node, node.origin || nodeOrigin);
204
204
  return getBoundsOfBoxes(currBox, rectToBox({
205
205
  x,
206
206
  y,
@@ -243,7 +243,7 @@ excludeNonSelectableNodes = false, nodeOrigin = [0, 0]) => {
243
243
  * @param edges - All edges
244
244
  * @returns Array of edges that connect any of the given nodes with each other
245
245
  */
246
- const getConnectedEdgesBase = (nodes, edges) => {
246
+ const getConnectedEdges = (nodes, edges) => {
247
247
  const nodeIds = new Set();
248
248
  nodes.forEach((node) => {
249
249
  nodeIds.add(node.id);
@@ -346,7 +346,7 @@ async function getElementsToRemove({ nodesToRemove = [], edgesToRemove = [], nod
346
346
  }
347
347
  const edgeIds = edgesToRemove.map((edge) => edge.id);
348
348
  const deletableEdges = edges.filter((edge) => edge.deletable !== false);
349
- const connectedEdges = getConnectedEdgesBase(matchingNodes, deletableEdges);
349
+ const connectedEdges = getConnectedEdges(matchingNodes, deletableEdges);
350
350
  const matchingEdges = connectedEdges;
351
351
  for (const edge of deletableEdges) {
352
352
  const isIncluded = edgeIds.includes(edge.id);
@@ -700,7 +700,7 @@ const connectionExists = (edge, edges) => {
700
700
  * @param edges - The array of all current edges
701
701
  * @returns A new array of edges with the new edge added
702
702
  */
703
- const addEdgeBase = (edgeParams, edges) => {
703
+ const addEdge = (edgeParams, edges) => {
704
704
  if (!edgeParams.source || !edgeParams.target) {
705
705
  devWarn('006', errorMessages['error006']());
706
706
  return edges;
@@ -734,7 +734,7 @@ const addEdgeBase = (edgeParams, edges) => {
734
734
  * @param options.shouldReplaceId - should the id of the old edge be replaced with the new connection id
735
735
  * @returns the updated edges array
736
736
  */
737
- const updateEdgeBase = (oldEdge, newConnection, edges, options = { shouldReplaceId: true }) => {
737
+ const updateEdge = (oldEdge, newConnection, edges, options = { shouldReplaceId: true }) => {
738
738
  const { id: oldEdgeId, ...rest } = oldEdge;
739
739
  if (!newConnection.source || !newConnection.target) {
740
740
  devWarn('006', errorMessages['error006']());
@@ -1610,7 +1610,7 @@ function getConnectionStatus(isInsideConnectionRadius, isHandleValid) {
1610
1610
 
1611
1611
  const alwaysValid = () => true;
1612
1612
  let connectionStartHandle = null;
1613
- function onPointerDown(event, { connectionMode, connectionRadius, handleId, nodeId, edgeUpdaterType, isTarget, domNode, nodes, lib, autoPanOnConnect, panBy, cancelConnection, onConnectStart, onConnect, onConnectEnd, isValidConnection = alwaysValid, onEdgeUpdateEnd, updateConnection, getTransform, }) {
1613
+ function onPointerDown(event, { connectionMode, connectionRadius, handleId, nodeId, edgeUpdaterType, isTarget, domNode, nodes, lib, autoPanOnConnect, flowId, panBy, cancelConnection, onConnectStart, onConnect, onConnectEnd, isValidConnection = alwaysValid, onEdgeUpdateEnd, updateConnection, getTransform, }) {
1614
1614
  // when xyflow is used inside a shadow root we can't use document
1615
1615
  const doc = getHostForElement(event.target);
1616
1616
  let autoPanId = 0;
@@ -1674,6 +1674,7 @@ function onPointerDown(event, { connectionMode, connectionRadius, handleId, node
1674
1674
  isValidConnection,
1675
1675
  doc,
1676
1676
  lib,
1677
+ flowId,
1677
1678
  });
1678
1679
  handleDomNode = result.handleDomNode;
1679
1680
  connection = result.connection;
@@ -1729,9 +1730,9 @@ function onPointerDown(event, { connectionMode, connectionRadius, handleId, node
1729
1730
  doc.addEventListener('touchend', onPointerUp);
1730
1731
  }
1731
1732
  // checks if and returns connection in fom of an object { source: 123, target: 312 }
1732
- function isValidHandle(event, { handle, connectionMode, fromNodeId, fromHandleId, fromType, doc, lib, isValidConnection = alwaysValid, }) {
1733
+ function isValidHandle(event, { handle, connectionMode, fromNodeId, fromHandleId, fromType, doc, lib, flowId, isValidConnection = alwaysValid, }) {
1733
1734
  const isTarget = fromType === 'target';
1734
- const handleDomNode = doc.querySelector(`.${lib}-flow__handle[data-id="${handle?.nodeId}-${handle?.id}-${handle?.type}"]`);
1735
+ const handleDomNode = doc.querySelector(`.${lib}-flow__handle[data-id="${flowId}-${handle?.nodeId}-${handle?.id}-${handle?.type}"]`);
1735
1736
  const { x, y } = getEventPosition(event);
1736
1737
  const handleBelow = doc.elementFromPoint(x, y);
1737
1738
  // we always want to prioritize the handle below the mouse cursor over the closest distance handle,
@@ -2173,4 +2174,221 @@ function XYPanZoom({ domNode, minZoom, maxZoom, translateExtent, viewport, onPan
2173
2174
  };
2174
2175
  }
2175
2176
 
2176
- export { ConnectionLineType, ConnectionMode, MarkerType, PanOnScrollMode, Position, SelectionMode, XYDrag, XYHandle, XYMinimap, XYPanZoom, addEdgeBase, adoptUserProvidedNodes, areConnectionMapsEqual, boxToRect, calcAutoPan, calcNextPosition, clamp, clampPosition, createMarkerIds, devWarn, elementSelectionKeys, errorMessages, fitView, getBezierEdgeCenter, getBezierPath, getBoundsOfBoxes, getBoundsOfRects, getConnectedEdgesBase, getDimensions, getEdgeCenter, getEdgePosition, getElementsToRemove, getElevatedEdgeZIndex, getEventPosition, getHandleBounds, getHostForElement, getIncomersBase, getMarkerId, getNodePositionWithOrigin, getNodeToolbarTransform, getNodesBounds, getNodesInside, getOutgoersBase, getOverlappingArea, getPointerPosition, getPositionWithOrigin, getSmoothStepPath, getStraightPath, getViewportForBounds, handleConnectionChange, infiniteExtent, internalsSymbol, isEdgeBase, isEdgeVisible, isInputDOMNode, isMacOs, isMouseEvent, isNodeBase, isNumeric, isRectObject, nodeToBox, nodeToRect, panBy, pointToRendererPoint, rectToBox, rendererPointToPoint, snapPosition, updateAbsolutePositions, updateConnectionLookup, updateEdgeBase, updateNodeDimensions };
2177
+ var ResizeControlVariant;
2178
+ (function (ResizeControlVariant) {
2179
+ ResizeControlVariant["Line"] = "line";
2180
+ ResizeControlVariant["Handle"] = "handle";
2181
+ })(ResizeControlVariant || (ResizeControlVariant = {}));
2182
+ const XY_RESIZER_HANDLE_POSITIONS = ['top-left', 'top-right', 'bottom-left', 'bottom-right'];
2183
+ const XY_RESIZER_LINE_POSITIONS = ['top', 'right', 'bottom', 'left'];
2184
+
2185
+ /**
2186
+ * Get all connecting edges for a given set of nodes
2187
+ * @param width - new width of the node
2188
+ * @param prevWidth - previous width of the node
2189
+ * @param height - new height of the node
2190
+ * @param prevHeight - previous height of the node
2191
+ * @param affectsX - whether to invert the resize direction for the x axis
2192
+ * @param affectsY - whether to invert the resize direction for the y axis
2193
+ * @returns array of two numbers representing the direction of the resize for each axis, 0 = no change, 1 = increase, -1 = decrease
2194
+ */
2195
+ function getResizeDirection({ width, prevWidth, height, prevHeight, affectsX, affectsY, }) {
2196
+ const deltaWidth = width - prevWidth;
2197
+ const deltaHeight = height - prevHeight;
2198
+ const direction = [deltaWidth > 0 ? 1 : deltaWidth < 0 ? -1 : 0, deltaHeight > 0 ? 1 : deltaHeight < 0 ? -1 : 0];
2199
+ if (deltaWidth && affectsX) {
2200
+ direction[0] = direction[0] * -1;
2201
+ }
2202
+ if (deltaHeight && affectsY) {
2203
+ direction[1] = direction[1] * -1;
2204
+ }
2205
+ return direction;
2206
+ }
2207
+ /**
2208
+ * Parses the control position that is being dragged to dimensions that are being resized
2209
+ * @param controlPosition - position of the control that is being dragged
2210
+ * @returns isHorizontal, isVertical, affectsX, affectsY,
2211
+ */
2212
+ function getControlDirection(controlPosition) {
2213
+ const isHorizontal = controlPosition.includes('right') || controlPosition.includes('left');
2214
+ const isVertical = controlPosition.includes('bottom') || controlPosition.includes('top');
2215
+ const affectsX = controlPosition.includes('left');
2216
+ const affectsY = controlPosition.includes('top');
2217
+ return {
2218
+ isHorizontal,
2219
+ isVertical,
2220
+ affectsX,
2221
+ affectsY,
2222
+ };
2223
+ }
2224
+ /**
2225
+ * Calculates new width & height of node after resize based on pointer position
2226
+ * @param startValues - starting values of resize
2227
+ * @param controlDirection - dimensions affected by the resize
2228
+ * @param pointerPosition - the current pointer position corrected for snapping
2229
+ * @param boundaries - minimum and maximum dimensions of the node
2230
+ * @param keepAspectRatio - prevent changes of asprect ratio
2231
+ * @returns width: new width of node, height: new height of node
2232
+ */
2233
+ function getDimensionsAfterResize(startValues, controlDirection, pointerPosition, boundaries, keepAspectRatio) {
2234
+ const { isHorizontal, isVertical, affectsX, affectsY } = controlDirection;
2235
+ const { xSnapped, ySnapped } = pointerPosition;
2236
+ const { minWidth, maxWidth, minHeight, maxHeight } = boundaries;
2237
+ const { pointerX: startX, pointerY: startY, width: startWidth, height: startHeight, aspectRatio } = startValues;
2238
+ const distX = Math.floor(isHorizontal ? xSnapped - startX : 0);
2239
+ const distY = Math.floor(isVertical ? ySnapped - startY : 0);
2240
+ let width = clamp(startWidth + (affectsX ? -distX : distX), minWidth, maxWidth);
2241
+ let height = clamp(startHeight + (affectsY ? -distY : distY), minHeight, maxHeight);
2242
+ if (keepAspectRatio) {
2243
+ const nextAspectRatio = width / height;
2244
+ const isDiagonal = isHorizontal && isVertical;
2245
+ const isOnlyHorizontal = isHorizontal && !isVertical;
2246
+ const isOnlyVertical = isVertical && !isHorizontal;
2247
+ width = (nextAspectRatio <= aspectRatio && isDiagonal) || isOnlyVertical ? height * aspectRatio : width;
2248
+ height = (nextAspectRatio > aspectRatio && isDiagonal) || isOnlyHorizontal ? width / aspectRatio : height;
2249
+ if (width >= maxWidth) {
2250
+ width = maxWidth;
2251
+ height = maxWidth / aspectRatio;
2252
+ }
2253
+ else if (width <= minWidth) {
2254
+ width = minWidth;
2255
+ height = minWidth / aspectRatio;
2256
+ }
2257
+ if (height >= maxHeight) {
2258
+ height = maxHeight;
2259
+ width = maxHeight * aspectRatio;
2260
+ }
2261
+ else if (height <= minHeight) {
2262
+ height = minHeight;
2263
+ width = minHeight * aspectRatio;
2264
+ }
2265
+ }
2266
+ return {
2267
+ width,
2268
+ height,
2269
+ };
2270
+ }
2271
+ /**
2272
+ * Determines new x & y position of node after resize based on new width & height
2273
+ * @param startValues - starting values of resize
2274
+ * @param controlDirection - dimensions affected by the resize
2275
+ * @param width - new width of node
2276
+ * @param height - new height of node
2277
+ * @returns x: new x position of node, y: new y position of node
2278
+ */
2279
+ function getPositionAfterResize(startValues, controlDirection, width, height) {
2280
+ return {
2281
+ x: controlDirection.affectsX ? startValues.x - (width - startValues.width) : startValues.x,
2282
+ y: controlDirection.affectsY ? startValues.y - (height - startValues.height) : startValues.y,
2283
+ };
2284
+ }
2285
+
2286
+ const initPrevValues = { width: 0, height: 0, x: 0, y: 0 };
2287
+ const initStartValues = {
2288
+ ...initPrevValues,
2289
+ pointerX: 0,
2290
+ pointerY: 0,
2291
+ aspectRatio: 1,
2292
+ };
2293
+ const initChange = {
2294
+ x: 0,
2295
+ y: 0,
2296
+ width: 0,
2297
+ height: 0,
2298
+ isXPosChange: false,
2299
+ isYPosChange: false,
2300
+ isWidthChange: false,
2301
+ isHeightChange: false,
2302
+ };
2303
+ function XYResizer({ domNode, nodeId, getStoreItems, onChange }) {
2304
+ const selection = select(domNode);
2305
+ function update({ controlPosition, boundaries, keepAspectRatio, onResizeStart, onResize, onResizeEnd, shouldResize, }) {
2306
+ let prevValues = { ...initPrevValues };
2307
+ let startValues = { ...initStartValues };
2308
+ const controlDirection = getControlDirection(controlPosition);
2309
+ const dragHandler = drag()
2310
+ .on('start', (event) => {
2311
+ const { nodeLookup, transform, snapGrid, snapToGrid } = getStoreItems();
2312
+ const node = nodeLookup.get(nodeId);
2313
+ const { xSnapped, ySnapped } = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid });
2314
+ prevValues = {
2315
+ width: node?.computed?.width ?? 0,
2316
+ height: node?.computed?.height ?? 0,
2317
+ x: node?.position.x ?? 0,
2318
+ y: node?.position.y ?? 0,
2319
+ };
2320
+ startValues = {
2321
+ ...prevValues,
2322
+ pointerX: xSnapped,
2323
+ pointerY: ySnapped,
2324
+ aspectRatio: prevValues.width / prevValues.height,
2325
+ };
2326
+ onResizeStart?.(event, { ...prevValues });
2327
+ })
2328
+ .on('drag', (event) => {
2329
+ const { nodeLookup, transform, snapGrid, snapToGrid } = getStoreItems();
2330
+ const pointerPosition = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid });
2331
+ const node = nodeLookup.get(nodeId);
2332
+ if (node) {
2333
+ const change = { ...initChange };
2334
+ const { x: prevX, y: prevY, width: prevWidth, height: prevHeight } = prevValues;
2335
+ const { width, height } = getDimensionsAfterResize(startValues, controlDirection, pointerPosition, boundaries, keepAspectRatio);
2336
+ const isWidthChange = width !== prevWidth;
2337
+ const isHeightChange = height !== prevHeight;
2338
+ if (controlDirection.affectsX || controlDirection.affectsY) {
2339
+ const { x, y } = getPositionAfterResize(startValues, controlDirection, width, height);
2340
+ // only transform the node if the width or height changes
2341
+ const isXPosChange = x !== prevX && isWidthChange;
2342
+ const isYPosChange = y !== prevY && isHeightChange;
2343
+ if (isXPosChange || isYPosChange) {
2344
+ change.isXPosChange = isXPosChange;
2345
+ change.isYPosChange = isYPosChange;
2346
+ change.x = isXPosChange ? x : prevX;
2347
+ change.y = isYPosChange ? y : prevY;
2348
+ prevValues.x = change.x;
2349
+ prevValues.y = change.y;
2350
+ }
2351
+ }
2352
+ if (isWidthChange || isHeightChange) {
2353
+ change.isWidthChange = isWidthChange;
2354
+ change.isHeightChange = isHeightChange;
2355
+ change.width = width;
2356
+ change.height = height;
2357
+ prevValues.width = width;
2358
+ prevValues.height = height;
2359
+ }
2360
+ if (!change.isXPosChange && !change.isYPosChange && !isWidthChange && !isHeightChange) {
2361
+ return;
2362
+ }
2363
+ const direction = getResizeDirection({
2364
+ width: prevValues.width,
2365
+ prevWidth,
2366
+ height: prevValues.height,
2367
+ prevHeight,
2368
+ affectsX: controlDirection.affectsX,
2369
+ affectsY: controlDirection.affectsY,
2370
+ });
2371
+ const nextValues = { ...prevValues, direction };
2372
+ const callResize = shouldResize?.(event, nextValues);
2373
+ if (callResize === false) {
2374
+ return;
2375
+ }
2376
+ onResize?.(event, nextValues);
2377
+ onChange(change);
2378
+ }
2379
+ })
2380
+ .on('end', (event) => {
2381
+ onResizeEnd?.(event, { ...prevValues });
2382
+ });
2383
+ selection.call(dragHandler);
2384
+ }
2385
+ function destroy() {
2386
+ selection.on('.drag', null);
2387
+ }
2388
+ return {
2389
+ update,
2390
+ destroy,
2391
+ };
2392
+ }
2393
+
2394
+ export { ConnectionLineType, ConnectionMode, MarkerType, PanOnScrollMode, Position, ResizeControlVariant, SelectionMode, XYDrag, XYHandle, XYMinimap, XYPanZoom, XYResizer, XY_RESIZER_HANDLE_POSITIONS, XY_RESIZER_LINE_POSITIONS, addEdge, adoptUserProvidedNodes, areConnectionMapsEqual, boxToRect, calcAutoPan, calcNextPosition, clamp, clampPosition, createMarkerIds, devWarn, elementSelectionKeys, errorMessages, fitView, getBezierEdgeCenter, getBezierPath, getBoundsOfBoxes, getBoundsOfRects, getConnectedEdges, getDimensions, getEdgeCenter, getEdgePosition, getElementsToRemove, getElevatedEdgeZIndex, getEventPosition, getHandleBounds, getHostForElement, getIncomers, getMarkerId, getNodePositionWithOrigin, getNodeToolbarTransform, getNodesBounds, getNodesInside, getOutgoers, getOverlappingArea, getPointerPosition, getPositionWithOrigin, getSmoothStepPath, getStraightPath, getViewportForBounds, handleConnectionChange, infiniteExtent, internalsSymbol, isEdgeBase, isEdgeVisible, isInputDOMNode, isMacOs, isMouseEvent, isNodeBase, isNumeric, isRectObject, nodeToBox, nodeToRect, panBy, pointToRendererPoint, rectToBox, rendererPointToPoint, snapPosition, updateAbsolutePositions, updateConnectionLookup, updateEdge, updateNodeDimensions };
@@ -128,7 +128,7 @@ const isNodeBase = (element) => 'id' in element && !('source' in element) && !('
128
128
  * @param edges - The array of all edges
129
129
  * @returns An array of nodes that are connected over eges where the source is the given node
130
130
  */
131
- const getOutgoersBase = (node, nodes, edges) => {
131
+ const getOutgoers = (node, nodes, edges) => {
132
132
  if (!node.id) {
133
133
  return [];
134
134
  }
@@ -148,7 +148,7 @@ const getOutgoersBase = (node, nodes, edges) => {
148
148
  * @param edges - The array of all edges
149
149
  * @returns An array of nodes that are connected over eges where the target is the given node
150
150
  */
151
- const getIncomersBase = (node, nodes, edges) => {
151
+ const getIncomers = (node, nodes, edges) => {
152
152
  if (!node.id) {
153
153
  return [];
154
154
  }
@@ -200,7 +200,7 @@ const getNodesBounds = (nodes, nodeOrigin = [0, 0]) => {
200
200
  return { x: 0, y: 0, width: 0, height: 0 };
201
201
  }
202
202
  const box = nodes.reduce((currBox, node) => {
203
- const { x, y } = getNodePositionWithOrigin(node, node.origin || nodeOrigin).positionAbsolute;
203
+ const { x, y } = getNodePositionWithOrigin(node, node.origin || nodeOrigin);
204
204
  return getBoundsOfBoxes(currBox, rectToBox({
205
205
  x,
206
206
  y,
@@ -243,7 +243,7 @@ excludeNonSelectableNodes = false, nodeOrigin = [0, 0]) => {
243
243
  * @param edges - All edges
244
244
  * @returns Array of edges that connect any of the given nodes with each other
245
245
  */
246
- const getConnectedEdgesBase = (nodes, edges) => {
246
+ const getConnectedEdges = (nodes, edges) => {
247
247
  const nodeIds = new Set();
248
248
  nodes.forEach((node) => {
249
249
  nodeIds.add(node.id);
@@ -346,7 +346,7 @@ async function getElementsToRemove({ nodesToRemove = [], edgesToRemove = [], nod
346
346
  }
347
347
  const edgeIds = edgesToRemove.map((edge) => edge.id);
348
348
  const deletableEdges = edges.filter((edge) => edge.deletable !== false);
349
- const connectedEdges = getConnectedEdgesBase(matchingNodes, deletableEdges);
349
+ const connectedEdges = getConnectedEdges(matchingNodes, deletableEdges);
350
350
  const matchingEdges = connectedEdges;
351
351
  for (const edge of deletableEdges) {
352
352
  const isIncluded = edgeIds.includes(edge.id);
@@ -700,7 +700,7 @@ const connectionExists = (edge, edges) => {
700
700
  * @param edges - The array of all current edges
701
701
  * @returns A new array of edges with the new edge added
702
702
  */
703
- const addEdgeBase = (edgeParams, edges) => {
703
+ const addEdge = (edgeParams, edges) => {
704
704
  if (!edgeParams.source || !edgeParams.target) {
705
705
  devWarn('006', errorMessages['error006']());
706
706
  return edges;
@@ -734,7 +734,7 @@ const addEdgeBase = (edgeParams, edges) => {
734
734
  * @param options.shouldReplaceId - should the id of the old edge be replaced with the new connection id
735
735
  * @returns the updated edges array
736
736
  */
737
- const updateEdgeBase = (oldEdge, newConnection, edges, options = { shouldReplaceId: true }) => {
737
+ const updateEdge = (oldEdge, newConnection, edges, options = { shouldReplaceId: true }) => {
738
738
  const { id: oldEdgeId, ...rest } = oldEdge;
739
739
  if (!newConnection.source || !newConnection.target) {
740
740
  devWarn('006', errorMessages['error006']());
@@ -1610,7 +1610,7 @@ function getConnectionStatus(isInsideConnectionRadius, isHandleValid) {
1610
1610
 
1611
1611
  const alwaysValid = () => true;
1612
1612
  let connectionStartHandle = null;
1613
- function onPointerDown(event, { connectionMode, connectionRadius, handleId, nodeId, edgeUpdaterType, isTarget, domNode, nodes, lib, autoPanOnConnect, panBy, cancelConnection, onConnectStart, onConnect, onConnectEnd, isValidConnection = alwaysValid, onEdgeUpdateEnd, updateConnection, getTransform, }) {
1613
+ function onPointerDown(event, { connectionMode, connectionRadius, handleId, nodeId, edgeUpdaterType, isTarget, domNode, nodes, lib, autoPanOnConnect, flowId, panBy, cancelConnection, onConnectStart, onConnect, onConnectEnd, isValidConnection = alwaysValid, onEdgeUpdateEnd, updateConnection, getTransform, }) {
1614
1614
  // when xyflow is used inside a shadow root we can't use document
1615
1615
  const doc = getHostForElement(event.target);
1616
1616
  let autoPanId = 0;
@@ -1674,6 +1674,7 @@ function onPointerDown(event, { connectionMode, connectionRadius, handleId, node
1674
1674
  isValidConnection,
1675
1675
  doc,
1676
1676
  lib,
1677
+ flowId,
1677
1678
  });
1678
1679
  handleDomNode = result.handleDomNode;
1679
1680
  connection = result.connection;
@@ -1729,9 +1730,9 @@ function onPointerDown(event, { connectionMode, connectionRadius, handleId, node
1729
1730
  doc.addEventListener('touchend', onPointerUp);
1730
1731
  }
1731
1732
  // checks if and returns connection in fom of an object { source: 123, target: 312 }
1732
- function isValidHandle(event, { handle, connectionMode, fromNodeId, fromHandleId, fromType, doc, lib, isValidConnection = alwaysValid, }) {
1733
+ function isValidHandle(event, { handle, connectionMode, fromNodeId, fromHandleId, fromType, doc, lib, flowId, isValidConnection = alwaysValid, }) {
1733
1734
  const isTarget = fromType === 'target';
1734
- const handleDomNode = doc.querySelector(`.${lib}-flow__handle[data-id="${handle?.nodeId}-${handle?.id}-${handle?.type}"]`);
1735
+ const handleDomNode = doc.querySelector(`.${lib}-flow__handle[data-id="${flowId}-${handle?.nodeId}-${handle?.id}-${handle?.type}"]`);
1735
1736
  const { x, y } = getEventPosition(event);
1736
1737
  const handleBelow = doc.elementFromPoint(x, y);
1737
1738
  // we always want to prioritize the handle below the mouse cursor over the closest distance handle,
@@ -2173,4 +2174,221 @@ function XYPanZoom({ domNode, minZoom, maxZoom, translateExtent, viewport, onPan
2173
2174
  };
2174
2175
  }
2175
2176
 
2176
- export { ConnectionLineType, ConnectionMode, MarkerType, PanOnScrollMode, Position, SelectionMode, XYDrag, XYHandle, XYMinimap, XYPanZoom, addEdgeBase, adoptUserProvidedNodes, areConnectionMapsEqual, boxToRect, calcAutoPan, calcNextPosition, clamp, clampPosition, createMarkerIds, devWarn, elementSelectionKeys, errorMessages, fitView, getBezierEdgeCenter, getBezierPath, getBoundsOfBoxes, getBoundsOfRects, getConnectedEdgesBase, getDimensions, getEdgeCenter, getEdgePosition, getElementsToRemove, getElevatedEdgeZIndex, getEventPosition, getHandleBounds, getHostForElement, getIncomersBase, getMarkerId, getNodePositionWithOrigin, getNodeToolbarTransform, getNodesBounds, getNodesInside, getOutgoersBase, getOverlappingArea, getPointerPosition, getPositionWithOrigin, getSmoothStepPath, getStraightPath, getViewportForBounds, handleConnectionChange, infiniteExtent, internalsSymbol, isEdgeBase, isEdgeVisible, isInputDOMNode, isMacOs, isMouseEvent, isNodeBase, isNumeric, isRectObject, nodeToBox, nodeToRect, panBy, pointToRendererPoint, rectToBox, rendererPointToPoint, snapPosition, updateAbsolutePositions, updateConnectionLookup, updateEdgeBase, updateNodeDimensions };
2177
+ var ResizeControlVariant;
2178
+ (function (ResizeControlVariant) {
2179
+ ResizeControlVariant["Line"] = "line";
2180
+ ResizeControlVariant["Handle"] = "handle";
2181
+ })(ResizeControlVariant || (ResizeControlVariant = {}));
2182
+ const XY_RESIZER_HANDLE_POSITIONS = ['top-left', 'top-right', 'bottom-left', 'bottom-right'];
2183
+ const XY_RESIZER_LINE_POSITIONS = ['top', 'right', 'bottom', 'left'];
2184
+
2185
+ /**
2186
+ * Get all connecting edges for a given set of nodes
2187
+ * @param width - new width of the node
2188
+ * @param prevWidth - previous width of the node
2189
+ * @param height - new height of the node
2190
+ * @param prevHeight - previous height of the node
2191
+ * @param affectsX - whether to invert the resize direction for the x axis
2192
+ * @param affectsY - whether to invert the resize direction for the y axis
2193
+ * @returns array of two numbers representing the direction of the resize for each axis, 0 = no change, 1 = increase, -1 = decrease
2194
+ */
2195
+ function getResizeDirection({ width, prevWidth, height, prevHeight, affectsX, affectsY, }) {
2196
+ const deltaWidth = width - prevWidth;
2197
+ const deltaHeight = height - prevHeight;
2198
+ const direction = [deltaWidth > 0 ? 1 : deltaWidth < 0 ? -1 : 0, deltaHeight > 0 ? 1 : deltaHeight < 0 ? -1 : 0];
2199
+ if (deltaWidth && affectsX) {
2200
+ direction[0] = direction[0] * -1;
2201
+ }
2202
+ if (deltaHeight && affectsY) {
2203
+ direction[1] = direction[1] * -1;
2204
+ }
2205
+ return direction;
2206
+ }
2207
+ /**
2208
+ * Parses the control position that is being dragged to dimensions that are being resized
2209
+ * @param controlPosition - position of the control that is being dragged
2210
+ * @returns isHorizontal, isVertical, affectsX, affectsY,
2211
+ */
2212
+ function getControlDirection(controlPosition) {
2213
+ const isHorizontal = controlPosition.includes('right') || controlPosition.includes('left');
2214
+ const isVertical = controlPosition.includes('bottom') || controlPosition.includes('top');
2215
+ const affectsX = controlPosition.includes('left');
2216
+ const affectsY = controlPosition.includes('top');
2217
+ return {
2218
+ isHorizontal,
2219
+ isVertical,
2220
+ affectsX,
2221
+ affectsY,
2222
+ };
2223
+ }
2224
+ /**
2225
+ * Calculates new width & height of node after resize based on pointer position
2226
+ * @param startValues - starting values of resize
2227
+ * @param controlDirection - dimensions affected by the resize
2228
+ * @param pointerPosition - the current pointer position corrected for snapping
2229
+ * @param boundaries - minimum and maximum dimensions of the node
2230
+ * @param keepAspectRatio - prevent changes of asprect ratio
2231
+ * @returns width: new width of node, height: new height of node
2232
+ */
2233
+ function getDimensionsAfterResize(startValues, controlDirection, pointerPosition, boundaries, keepAspectRatio) {
2234
+ const { isHorizontal, isVertical, affectsX, affectsY } = controlDirection;
2235
+ const { xSnapped, ySnapped } = pointerPosition;
2236
+ const { minWidth, maxWidth, minHeight, maxHeight } = boundaries;
2237
+ const { pointerX: startX, pointerY: startY, width: startWidth, height: startHeight, aspectRatio } = startValues;
2238
+ const distX = Math.floor(isHorizontal ? xSnapped - startX : 0);
2239
+ const distY = Math.floor(isVertical ? ySnapped - startY : 0);
2240
+ let width = clamp(startWidth + (affectsX ? -distX : distX), minWidth, maxWidth);
2241
+ let height = clamp(startHeight + (affectsY ? -distY : distY), minHeight, maxHeight);
2242
+ if (keepAspectRatio) {
2243
+ const nextAspectRatio = width / height;
2244
+ const isDiagonal = isHorizontal && isVertical;
2245
+ const isOnlyHorizontal = isHorizontal && !isVertical;
2246
+ const isOnlyVertical = isVertical && !isHorizontal;
2247
+ width = (nextAspectRatio <= aspectRatio && isDiagonal) || isOnlyVertical ? height * aspectRatio : width;
2248
+ height = (nextAspectRatio > aspectRatio && isDiagonal) || isOnlyHorizontal ? width / aspectRatio : height;
2249
+ if (width >= maxWidth) {
2250
+ width = maxWidth;
2251
+ height = maxWidth / aspectRatio;
2252
+ }
2253
+ else if (width <= minWidth) {
2254
+ width = minWidth;
2255
+ height = minWidth / aspectRatio;
2256
+ }
2257
+ if (height >= maxHeight) {
2258
+ height = maxHeight;
2259
+ width = maxHeight * aspectRatio;
2260
+ }
2261
+ else if (height <= minHeight) {
2262
+ height = minHeight;
2263
+ width = minHeight * aspectRatio;
2264
+ }
2265
+ }
2266
+ return {
2267
+ width,
2268
+ height,
2269
+ };
2270
+ }
2271
+ /**
2272
+ * Determines new x & y position of node after resize based on new width & height
2273
+ * @param startValues - starting values of resize
2274
+ * @param controlDirection - dimensions affected by the resize
2275
+ * @param width - new width of node
2276
+ * @param height - new height of node
2277
+ * @returns x: new x position of node, y: new y position of node
2278
+ */
2279
+ function getPositionAfterResize(startValues, controlDirection, width, height) {
2280
+ return {
2281
+ x: controlDirection.affectsX ? startValues.x - (width - startValues.width) : startValues.x,
2282
+ y: controlDirection.affectsY ? startValues.y - (height - startValues.height) : startValues.y,
2283
+ };
2284
+ }
2285
+
2286
+ const initPrevValues = { width: 0, height: 0, x: 0, y: 0 };
2287
+ const initStartValues = {
2288
+ ...initPrevValues,
2289
+ pointerX: 0,
2290
+ pointerY: 0,
2291
+ aspectRatio: 1,
2292
+ };
2293
+ const initChange = {
2294
+ x: 0,
2295
+ y: 0,
2296
+ width: 0,
2297
+ height: 0,
2298
+ isXPosChange: false,
2299
+ isYPosChange: false,
2300
+ isWidthChange: false,
2301
+ isHeightChange: false,
2302
+ };
2303
+ function XYResizer({ domNode, nodeId, getStoreItems, onChange }) {
2304
+ const selection = select(domNode);
2305
+ function update({ controlPosition, boundaries, keepAspectRatio, onResizeStart, onResize, onResizeEnd, shouldResize, }) {
2306
+ let prevValues = { ...initPrevValues };
2307
+ let startValues = { ...initStartValues };
2308
+ const controlDirection = getControlDirection(controlPosition);
2309
+ const dragHandler = drag()
2310
+ .on('start', (event) => {
2311
+ const { nodeLookup, transform, snapGrid, snapToGrid } = getStoreItems();
2312
+ const node = nodeLookup.get(nodeId);
2313
+ const { xSnapped, ySnapped } = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid });
2314
+ prevValues = {
2315
+ width: node?.computed?.width ?? 0,
2316
+ height: node?.computed?.height ?? 0,
2317
+ x: node?.position.x ?? 0,
2318
+ y: node?.position.y ?? 0,
2319
+ };
2320
+ startValues = {
2321
+ ...prevValues,
2322
+ pointerX: xSnapped,
2323
+ pointerY: ySnapped,
2324
+ aspectRatio: prevValues.width / prevValues.height,
2325
+ };
2326
+ onResizeStart?.(event, { ...prevValues });
2327
+ })
2328
+ .on('drag', (event) => {
2329
+ const { nodeLookup, transform, snapGrid, snapToGrid } = getStoreItems();
2330
+ const pointerPosition = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid });
2331
+ const node = nodeLookup.get(nodeId);
2332
+ if (node) {
2333
+ const change = { ...initChange };
2334
+ const { x: prevX, y: prevY, width: prevWidth, height: prevHeight } = prevValues;
2335
+ const { width, height } = getDimensionsAfterResize(startValues, controlDirection, pointerPosition, boundaries, keepAspectRatio);
2336
+ const isWidthChange = width !== prevWidth;
2337
+ const isHeightChange = height !== prevHeight;
2338
+ if (controlDirection.affectsX || controlDirection.affectsY) {
2339
+ const { x, y } = getPositionAfterResize(startValues, controlDirection, width, height);
2340
+ // only transform the node if the width or height changes
2341
+ const isXPosChange = x !== prevX && isWidthChange;
2342
+ const isYPosChange = y !== prevY && isHeightChange;
2343
+ if (isXPosChange || isYPosChange) {
2344
+ change.isXPosChange = isXPosChange;
2345
+ change.isYPosChange = isYPosChange;
2346
+ change.x = isXPosChange ? x : prevX;
2347
+ change.y = isYPosChange ? y : prevY;
2348
+ prevValues.x = change.x;
2349
+ prevValues.y = change.y;
2350
+ }
2351
+ }
2352
+ if (isWidthChange || isHeightChange) {
2353
+ change.isWidthChange = isWidthChange;
2354
+ change.isHeightChange = isHeightChange;
2355
+ change.width = width;
2356
+ change.height = height;
2357
+ prevValues.width = width;
2358
+ prevValues.height = height;
2359
+ }
2360
+ if (!change.isXPosChange && !change.isYPosChange && !isWidthChange && !isHeightChange) {
2361
+ return;
2362
+ }
2363
+ const direction = getResizeDirection({
2364
+ width: prevValues.width,
2365
+ prevWidth,
2366
+ height: prevValues.height,
2367
+ prevHeight,
2368
+ affectsX: controlDirection.affectsX,
2369
+ affectsY: controlDirection.affectsY,
2370
+ });
2371
+ const nextValues = { ...prevValues, direction };
2372
+ const callResize = shouldResize?.(event, nextValues);
2373
+ if (callResize === false) {
2374
+ return;
2375
+ }
2376
+ onResize?.(event, nextValues);
2377
+ onChange(change);
2378
+ }
2379
+ })
2380
+ .on('end', (event) => {
2381
+ onResizeEnd?.(event, { ...prevValues });
2382
+ });
2383
+ selection.call(dragHandler);
2384
+ }
2385
+ function destroy() {
2386
+ selection.on('.drag', null);
2387
+ }
2388
+ return {
2389
+ update,
2390
+ destroy,
2391
+ };
2392
+ }
2393
+
2394
+ export { ConnectionLineType, ConnectionMode, MarkerType, PanOnScrollMode, Position, ResizeControlVariant, SelectionMode, XYDrag, XYHandle, XYMinimap, XYPanZoom, XYResizer, XY_RESIZER_HANDLE_POSITIONS, XY_RESIZER_LINE_POSITIONS, addEdge, adoptUserProvidedNodes, areConnectionMapsEqual, boxToRect, calcAutoPan, calcNextPosition, clamp, clampPosition, createMarkerIds, devWarn, elementSelectionKeys, errorMessages, fitView, getBezierEdgeCenter, getBezierPath, getBoundsOfBoxes, getBoundsOfRects, getConnectedEdges, getDimensions, getEdgeCenter, getEdgePosition, getElementsToRemove, getElevatedEdgeZIndex, getEventPosition, getHandleBounds, getHostForElement, getIncomers, getMarkerId, getNodePositionWithOrigin, getNodeToolbarTransform, getNodesBounds, getNodesInside, getOutgoers, getOverlappingArea, getPointerPosition, getPositionWithOrigin, getSmoothStepPath, getStraightPath, getViewportForBounds, handleConnectionChange, infiniteExtent, internalsSymbol, isEdgeBase, isEdgeVisible, isInputDOMNode, isMacOs, isMouseEvent, isNodeBase, isNumeric, isRectObject, nodeToBox, nodeToRect, panBy, pointToRendererPoint, rectToBox, rendererPointToPoint, snapPosition, updateAbsolutePositions, updateConnectionLookup, updateEdge, updateNodeDimensions };