@xyflow/react 12.0.0-next.24 → 12.0.0-next.26

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 (90) hide show
  1. package/dist/esm/additional-components/MiniMap/MiniMap.d.ts.map +1 -1
  2. package/dist/esm/additional-components/MiniMap/MiniMapNodes.d.ts.map +1 -1
  3. package/dist/esm/additional-components/NodeResizer/NodeResizeControl.d.ts.map +1 -1
  4. package/dist/esm/additional-components/NodeToolbar/NodeToolbar.d.ts.map +1 -1
  5. package/dist/esm/components/ConnectionLine/index.d.ts.map +1 -1
  6. package/dist/esm/components/Handle/index.d.ts.map +1 -1
  7. package/dist/esm/components/NodeWrapper/index.d.ts +1 -1
  8. package/dist/esm/components/NodeWrapper/index.d.ts.map +1 -1
  9. package/dist/esm/components/NodesSelection/index.d.ts.map +1 -1
  10. package/dist/esm/components/ReactFlowProvider/index.d.ts +3 -1
  11. package/dist/esm/components/ReactFlowProvider/index.d.ts.map +1 -1
  12. package/dist/esm/components/StoreUpdater/index.d.ts +1 -1
  13. package/dist/esm/components/StoreUpdater/index.d.ts.map +1 -1
  14. package/dist/esm/container/FlowRenderer/index.d.ts +1 -1
  15. package/dist/esm/container/FlowRenderer/index.d.ts.map +1 -1
  16. package/dist/esm/container/GraphView/index.d.ts +2 -2
  17. package/dist/esm/container/GraphView/index.d.ts.map +1 -1
  18. package/dist/esm/container/NodeRenderer/index.d.ts +1 -1
  19. package/dist/esm/container/NodeRenderer/index.d.ts.map +1 -1
  20. package/dist/esm/container/Pane/index.d.ts.map +1 -1
  21. package/dist/esm/container/ReactFlow/Wrapper.d.ts +3 -1
  22. package/dist/esm/container/ReactFlow/Wrapper.d.ts.map +1 -1
  23. package/dist/esm/container/ReactFlow/index.d.ts.map +1 -1
  24. package/dist/esm/contexts/RFStoreContext.d.ts +5 -0
  25. package/dist/esm/contexts/RFStoreContext.d.ts.map +1 -0
  26. package/dist/esm/hooks/useConnection.d.ts +4 -15
  27. package/dist/esm/hooks/useConnection.d.ts.map +1 -1
  28. package/dist/esm/hooks/useViewportHelper.d.ts.map +1 -1
  29. package/dist/esm/index.d.ts +1 -1
  30. package/dist/esm/index.d.ts.map +1 -1
  31. package/dist/esm/index.js +201 -238
  32. package/dist/esm/index.mjs +201 -238
  33. package/dist/esm/store/index.d.ts +3 -1
  34. package/dist/esm/store/index.d.ts.map +1 -1
  35. package/dist/esm/store/initialState.d.ts +3 -1
  36. package/dist/esm/store/initialState.d.ts.map +1 -1
  37. package/dist/esm/store/utils.d.ts +12 -0
  38. package/dist/esm/store/utils.d.ts.map +1 -0
  39. package/dist/esm/types/changes.d.ts +51 -0
  40. package/dist/esm/types/changes.d.ts.map +1 -0
  41. package/dist/esm/types/component-props.d.ts +4 -0
  42. package/dist/esm/types/component-props.d.ts.map +1 -1
  43. package/dist/esm/types/edges.d.ts +6 -4
  44. package/dist/esm/types/edges.d.ts.map +1 -1
  45. package/dist/esm/types/nodes.d.ts +1 -2
  46. package/dist/esm/types/nodes.d.ts.map +1 -1
  47. package/dist/esm/types/store.d.ts +5 -7
  48. package/dist/esm/types/store.d.ts.map +1 -1
  49. package/dist/umd/additional-components/MiniMap/MiniMap.d.ts.map +1 -1
  50. package/dist/umd/additional-components/MiniMap/MiniMapNodes.d.ts.map +1 -1
  51. package/dist/umd/additional-components/NodeResizer/NodeResizeControl.d.ts.map +1 -1
  52. package/dist/umd/additional-components/NodeToolbar/NodeToolbar.d.ts.map +1 -1
  53. package/dist/umd/components/ConnectionLine/index.d.ts.map +1 -1
  54. package/dist/umd/components/Handle/index.d.ts.map +1 -1
  55. package/dist/umd/components/NodeWrapper/index.d.ts +1 -1
  56. package/dist/umd/components/NodeWrapper/index.d.ts.map +1 -1
  57. package/dist/umd/components/NodesSelection/index.d.ts.map +1 -1
  58. package/dist/umd/components/ReactFlowProvider/index.d.ts +3 -1
  59. package/dist/umd/components/ReactFlowProvider/index.d.ts.map +1 -1
  60. package/dist/umd/components/StoreUpdater/index.d.ts +1 -1
  61. package/dist/umd/components/StoreUpdater/index.d.ts.map +1 -1
  62. package/dist/umd/container/FlowRenderer/index.d.ts +1 -1
  63. package/dist/umd/container/FlowRenderer/index.d.ts.map +1 -1
  64. package/dist/umd/container/GraphView/index.d.ts +2 -2
  65. package/dist/umd/container/GraphView/index.d.ts.map +1 -1
  66. package/dist/umd/container/NodeRenderer/index.d.ts +1 -1
  67. package/dist/umd/container/NodeRenderer/index.d.ts.map +1 -1
  68. package/dist/umd/container/Pane/index.d.ts.map +1 -1
  69. package/dist/umd/container/ReactFlow/Wrapper.d.ts +3 -1
  70. package/dist/umd/container/ReactFlow/Wrapper.d.ts.map +1 -1
  71. package/dist/umd/container/ReactFlow/index.d.ts.map +1 -1
  72. package/dist/umd/hooks/useConnection.d.ts +4 -15
  73. package/dist/umd/hooks/useConnection.d.ts.map +1 -1
  74. package/dist/umd/hooks/useViewportHelper.d.ts.map +1 -1
  75. package/dist/umd/index.d.ts +1 -1
  76. package/dist/umd/index.d.ts.map +1 -1
  77. package/dist/umd/index.js +2 -2
  78. package/dist/umd/store/index.d.ts +3 -1
  79. package/dist/umd/store/index.d.ts.map +1 -1
  80. package/dist/umd/store/initialState.d.ts +3 -1
  81. package/dist/umd/store/initialState.d.ts.map +1 -1
  82. package/dist/umd/types/component-props.d.ts +4 -0
  83. package/dist/umd/types/component-props.d.ts.map +1 -1
  84. package/dist/umd/types/edges.d.ts +6 -4
  85. package/dist/umd/types/edges.d.ts.map +1 -1
  86. package/dist/umd/types/nodes.d.ts +1 -2
  87. package/dist/umd/types/nodes.d.ts.map +1 -1
  88. package/dist/umd/types/store.d.ts +5 -7
  89. package/dist/umd/types/store.d.ts.map +1 -1
  90. package/package.json +2 -2
@@ -1,7 +1,7 @@
1
1
  "use client"
2
2
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
3
3
  import cc from 'classcat';
4
- import { errorMessages, infiniteExtent, isInputDOMNode, fitView, getViewportForBounds, pointToRendererPoint, rendererPointToPoint, isNodeBase, isEdgeBase, getElementsToRemove, isRectObject, nodeToRect, getOverlappingArea, evaluateAbsolutePosition, getDimensions, XYPanZoom, PanOnScrollMode, SelectionMode, getEventPosition, getNodesInside, XYDrag, snapPosition, calculateNodePosition, Position, ConnectionMode, isMouseEvent, XYHandle, getHostForElement, addEdge, getInternalNodesBounds, isNumeric, nodeHasDimensions, getNodeDimensions, clampPosition, getPositionWithOrigin, elementSelectionKeys, isEdgeVisible, MarkerType, createMarkerIds, getBezierEdgeCenter, getSmoothStepPath, getStraightPath, getBezierPath, getEdgePosition, getElevatedEdgeZIndex, getMarkerId, ConnectionLineType, updateConnectionLookup, adoptUserNodes, devWarn, updateNodeInternals, updateAbsolutePositions, handleExpandParent, panBy, isMacOs, areConnectionMapsEqual, handleConnectionChange, shallowNodeData, getNodePositionWithOrigin, XYMinimap, getBoundsOfRects, ResizeControlVariant, XYResizer, XY_RESIZER_LINE_POSITIONS, XY_RESIZER_HANDLE_POSITIONS, getNodesBounds, getNodeToolbarTransform } from '@xyflow/system';
4
+ import { errorMessages, infiniteExtent, isInputDOMNode, fitView, getViewportForBounds, pointToRendererPoint, rendererPointToPoint, isNodeBase, isEdgeBase, getElementsToRemove, isRectObject, nodeToRect, getOverlappingArea, evaluateAbsolutePosition, getDimensions, XYPanZoom, PanOnScrollMode, SelectionMode, getEventPosition, getNodesInside, XYDrag, snapPosition, calculateNodePosition, Position, ConnectionMode, isMouseEvent, XYHandle, getHostForElement, addEdge, getInternalNodesBounds, isNumeric, nodeHasDimensions, getNodeDimensions, clampPosition, elementSelectionKeys, isEdgeVisible, MarkerType, createMarkerIds, getBezierEdgeCenter, getSmoothStepPath, getStraightPath, getBezierPath, getEdgePosition, getElevatedEdgeZIndex, getMarkerId, getConnectionStatus, ConnectionLineType, updateConnectionLookup, adoptUserNodes, initialConnection, devWarn, updateNodeInternals, updateAbsolutePositions, handleExpandParent, panBy, isMacOs, areConnectionMapsEqual, handleConnectionChange, shallowNodeData, XYMinimap, getBoundsOfRects, ResizeControlVariant, XYResizer, XY_RESIZER_LINE_POSITIONS, XY_RESIZER_HANDLE_POSITIONS, getNodeToolbarTransform } from '@xyflow/system';
5
5
  export { ConnectionLineType, ConnectionMode, MarkerType, PanOnScrollMode, Position, SelectionMode, addEdge, getBezierEdgeCenter, getBezierPath, getConnectedEdges, getEdgeCenter, getIncomers, getNodesBounds, getOutgoers, getSmoothStepPath, getStraightPath, getViewportForBounds, reconnectEdge } from '@xyflow/system';
6
6
  import { createContext, useContext, useMemo, useEffect, useRef, useState, forwardRef, useLayoutEffect, useCallback, memo } from 'react';
7
7
  import { useStoreWithEqualityFn, createWithEqualityFn } from 'zustand/traditional';
@@ -58,18 +58,18 @@ const ariaLiveStyle = {
58
58
  const ARIA_NODE_DESC_KEY = 'react-flow__node-desc';
59
59
  const ARIA_EDGE_DESC_KEY = 'react-flow__edge-desc';
60
60
  const ARIA_LIVE_MESSAGE = 'react-flow__aria-live';
61
- const selector$q = (s) => s.ariaLiveMessage;
61
+ const selector$p = (s) => s.ariaLiveMessage;
62
62
  function AriaLiveMessage({ rfId }) {
63
- const ariaLiveMessage = useStore(selector$q);
63
+ const ariaLiveMessage = useStore(selector$p);
64
64
  return (jsx("div", { id: `${ARIA_LIVE_MESSAGE}-${rfId}`, "aria-live": "assertive", "aria-atomic": "true", style: ariaLiveStyle, children: ariaLiveMessage }));
65
65
  }
66
66
  function A11yDescriptions({ rfId, disableKeyboardA11y }) {
67
67
  return (jsxs(Fragment, { children: [jsxs("div", { id: `${ARIA_NODE_DESC_KEY}-${rfId}`, style: style, children: ["Press enter or space to select a node.", !disableKeyboardA11y && 'You can then use the arrow keys to move the node around.', " Press delete to remove it and escape to cancel.", ' '] }), jsx("div", { id: `${ARIA_EDGE_DESC_KEY}-${rfId}`, style: style, children: "Press enter or space to select an edge. You can then press delete to remove it or escape to cancel." }), !disableKeyboardA11y && jsx(AriaLiveMessage, { rfId: rfId })] }));
68
68
  }
69
69
 
70
- const selector$p = (s) => (s.userSelectionActive ? 'none' : 'all');
70
+ const selector$o = (s) => (s.userSelectionActive ? 'none' : 'all');
71
71
  function Panel({ position = 'top-left', children, className, style, ...rest }) {
72
- const pointerEvents = useStore(selector$p);
72
+ const pointerEvents = useStore(selector$o);
73
73
  const positionClasses = `${position}`.split('-');
74
74
  return (jsx("div", { className: cc(['react-flow__panel', className, ...positionClasses]), style: { ...style, pointerEvents }, ...rest, children: children }));
75
75
  }
@@ -81,7 +81,7 @@ function Attribution({ proOptions, position = 'bottom-right' }) {
81
81
  return (jsx(Panel, { position: position, className: "react-flow__attribution", "data-message": "Please only hide this attribution when you are subscribed to React Flow Pro: https://pro.reactflow.dev", children: jsx("a", { href: "https://reactflow.dev", target: "_blank", rel: "noopener noreferrer", "aria-label": "React Flow attribution", children: "React Flow" }) }));
82
82
  }
83
83
 
84
- const selector$o = (s) => {
84
+ const selector$n = (s) => {
85
85
  const selectedNodes = [];
86
86
  const selectedEdges = [];
87
87
  for (const [, node] of s.nodeLookup) {
@@ -103,7 +103,7 @@ function areEqual(a, b) {
103
103
  }
104
104
  function SelectionListenerInner({ onSelectionChange }) {
105
105
  const store = useStoreApi();
106
- const { selectedNodes, selectedEdges } = useStore(selector$o, areEqual);
106
+ const { selectedNodes, selectedEdges } = useStore(selector$n, areEqual);
107
107
  useEffect(() => {
108
108
  const params = { nodes: selectedNodes, edges: selectedEdges };
109
109
  onSelectionChange?.(params);
@@ -183,10 +183,11 @@ const reactFlowFieldsToTrack = [
183
183
  'nodeDragThreshold',
184
184
  'onBeforeDelete',
185
185
  'debug',
186
+ 'autoPanSpeed',
186
187
  ];
187
188
  // rfId doesn't exist in ReactFlowProps, but it's one of the fields we want to update
188
189
  const fieldsToTrack = [...reactFlowFieldsToTrack, 'rfId'];
189
- const selector$n = (s) => ({
190
+ const selector$m = (s) => ({
190
191
  setNodes: s.setNodes,
191
192
  setEdges: s.setEdges,
192
193
  setMinZoom: s.setMinZoom,
@@ -209,7 +210,7 @@ const initPrevValues = {
209
210
  rfId: '1',
210
211
  };
211
212
  function StoreUpdater(props) {
212
- const { setNodes, setEdges, setMinZoom, setMaxZoom, setTranslateExtent, setNodeExtent, reset, setDefaultNodesAndEdges, } = useStore(selector$n, shallow);
213
+ const { setNodes, setEdges, setMinZoom, setMaxZoom, setTranslateExtent, setNodeExtent, reset, setDefaultNodesAndEdges, } = useStore(selector$m, shallow);
213
214
  const store = useStoreApi();
214
215
  useEffect(() => {
215
216
  setDefaultNodesAndEdges(props.defaultNodes, props.defaultEdges);
@@ -419,18 +420,18 @@ const useViewportHelper = () => {
419
420
  return { x, y, zoom };
420
421
  },
421
422
  fitView: (options) => {
422
- const { nodeLookup, width, height, nodeOrigin, minZoom, maxZoom, panZoom } = store.getState();
423
- return panZoom
424
- ? fitView({
425
- nodeLookup,
426
- width,
427
- height,
428
- nodeOrigin,
429
- minZoom,
430
- maxZoom,
431
- panZoom,
432
- }, options)
433
- : false;
423
+ const { nodeLookup, width, height, minZoom, maxZoom, panZoom } = store.getState();
424
+ if (!panZoom) {
425
+ return false;
426
+ }
427
+ return fitView({
428
+ nodeLookup,
429
+ width,
430
+ height,
431
+ minZoom,
432
+ maxZoom,
433
+ panZoom,
434
+ }, options);
434
435
  },
435
436
  setCenter: (x, y, options) => {
436
437
  const { width, height, maxZoom, panZoom } = store.getState();
@@ -800,7 +801,7 @@ function useBatchContext() {
800
801
  return batchContext;
801
802
  }
802
803
 
803
- const selector$m = (s) => !!s.panZoom;
804
+ const selector$l = (s) => !!s.panZoom;
804
805
  /**
805
806
  * Hook for accessing the ReactFlow instance.
806
807
  *
@@ -811,7 +812,7 @@ function useReactFlow() {
811
812
  const viewportHelper = useViewportHelper();
812
813
  const store = useStoreApi();
813
814
  const batchContext = useBatchContext();
814
- const viewportInitialized = useStore(selector$m);
815
+ const viewportInitialized = useStore(selector$l);
815
816
  const generalHelper = useMemo(() => {
816
817
  const getInternalNode = (id) => store.getState().nodeLookup.get(id);
817
818
  const setNodes = (payload) => {
@@ -824,7 +825,7 @@ function useReactFlow() {
824
825
  const { nodeLookup, nodeOrigin } = store.getState();
825
826
  const nodeToUse = isNode(node) ? node : nodeLookup.get(node.id);
826
827
  const position = nodeToUse.parentId
827
- ? evaluateAbsolutePosition(nodeToUse.position, nodeToUse.parentId, nodeLookup, nodeOrigin)
828
+ ? evaluateAbsolutePosition(nodeToUse.position, nodeToUse.measured, nodeToUse.parentId, nodeLookup, nodeOrigin)
828
829
  : nodeToUse.position;
829
830
  const nodeWithPosition = {
830
831
  id: nodeToUse.id,
@@ -1030,14 +1031,14 @@ const containerStyle = {
1030
1031
  left: 0,
1031
1032
  };
1032
1033
 
1033
- const selector$l = (s) => ({
1034
+ const selector$k = (s) => ({
1034
1035
  userSelectionActive: s.userSelectionActive,
1035
1036
  lib: s.lib,
1036
1037
  });
1037
1038
  function ZoomPane({ onPaneContextMenu, zoomOnScroll = true, zoomOnPinch = true, panOnScroll = false, panOnScrollSpeed = 0.5, panOnScrollMode = PanOnScrollMode.Free, zoomOnDoubleClick = true, panOnDrag = true, defaultViewport, translateExtent, minZoom, maxZoom, zoomActivationKeyCode, preventScrolling = true, children, noWheelClassName, noPanClassName, onViewportChange, isControlledViewport, }) {
1038
1039
  const store = useStoreApi();
1039
1040
  const zoomPane = useRef(null);
1040
- const { userSelectionActive, lib } = useStore(selector$l, shallow);
1041
+ const { userSelectionActive, lib } = useStore(selector$k, shallow);
1041
1042
  const zoomActivationKeyPressed = useKeyPress(zoomActivationKeyCode);
1042
1043
  const panZoom = useRef();
1043
1044
  useResizeHandler(zoomPane);
@@ -1119,12 +1120,12 @@ function ZoomPane({ onPaneContextMenu, zoomOnScroll = true, zoomOnPinch = true,
1119
1120
  return (jsx("div", { className: "react-flow__renderer", ref: zoomPane, style: containerStyle, children: children }));
1120
1121
  }
1121
1122
 
1122
- const selector$k = (s) => ({
1123
+ const selector$j = (s) => ({
1123
1124
  userSelectionActive: s.userSelectionActive,
1124
1125
  userSelectionRect: s.userSelectionRect,
1125
1126
  });
1126
1127
  function UserSelection() {
1127
- const { userSelectionActive, userSelectionRect } = useStore(selector$k, shallow);
1128
+ const { userSelectionActive, userSelectionRect } = useStore(selector$j, shallow);
1128
1129
  const isActive = userSelectionActive && userSelectionRect;
1129
1130
  if (!isActive) {
1130
1131
  return null;
@@ -1144,7 +1145,7 @@ const wrapHandler = (handler, containerRef) => {
1144
1145
  handler?.(event);
1145
1146
  };
1146
1147
  };
1147
- const selector$j = (s) => ({
1148
+ const selector$i = (s) => ({
1148
1149
  userSelectionActive: s.userSelectionActive,
1149
1150
  elementsSelectable: s.elementsSelectable,
1150
1151
  dragging: s.paneDragging,
@@ -1156,7 +1157,7 @@ function Pane({ isSelecting, selectionKeyPressed, selectionMode = SelectionMode.
1156
1157
  const prevSelectedEdgesCount = useRef(0);
1157
1158
  const containerBounds = useRef();
1158
1159
  const edgeIdLookup = useRef(new Map());
1159
- const { userSelectionActive, elementsSelectable, dragging } = useStore(selector$j, shallow);
1160
+ const { userSelectionActive, elementsSelectable, dragging } = useStore(selector$i, shallow);
1160
1161
  const hasActiveSelection = elementsSelectable && (isSelecting || userSelectionActive);
1161
1162
  // Used to prevent click events when the user lets go of the selectionKey during a selection
1162
1163
  const selectionInProgress = useRef(false);
@@ -1214,7 +1215,7 @@ function Pane({ isSelecting, selectionKeyPressed, selectionMode = SelectionMode.
1214
1215
  onSelectionStart?.(event);
1215
1216
  };
1216
1217
  const onPointerMove = (event) => {
1217
- const { userSelectionRect, edgeLookup, transform, nodeOrigin, nodeLookup, triggerNodeChanges, triggerEdgeChanges } = store.getState();
1218
+ const { userSelectionRect, edgeLookup, transform, nodeLookup, triggerNodeChanges, triggerEdgeChanges } = store.getState();
1218
1219
  if (!containerBounds.current || !userSelectionRect) {
1219
1220
  return;
1220
1221
  }
@@ -1229,7 +1230,7 @@ function Pane({ isSelecting, selectionKeyPressed, selectionMode = SelectionMode.
1229
1230
  width: Math.abs(mouseX - startX),
1230
1231
  height: Math.abs(mouseY - startY),
1231
1232
  };
1232
- const selectedNodes = getNodesInside(nodeLookup, nextUserSelectRect, transform, selectionMode === SelectionMode.Partial, true, nodeOrigin);
1233
+ const selectedNodes = getNodesInside(nodeLookup, nextUserSelectRect, transform, selectionMode === SelectionMode.Partial, true);
1233
1234
  const selectedEdgeIds = new Set();
1234
1235
  const selectedNodeIds = new Set();
1235
1236
  for (const selectedNode of selectedNodes) {
@@ -1403,23 +1404,24 @@ const useNodeId = () => {
1403
1404
  return nodeId;
1404
1405
  };
1405
1406
 
1406
- const selector$i = (s) => ({
1407
+ const selector$h = (s) => ({
1407
1408
  connectOnClick: s.connectOnClick,
1408
1409
  noPanClassName: s.noPanClassName,
1409
1410
  rfId: s.rfId,
1410
1411
  });
1411
1412
  const connectingSelector = (nodeId, handleId, type) => (state) => {
1412
- const { connectionStartHandle: startHandle, connectionEndHandle: endHandle, connectionClickStartHandle: clickHandle, connectionMode, connectionStatus, } = state;
1413
- const connectingTo = endHandle?.nodeId === nodeId && endHandle?.handleId === handleId && endHandle?.type === type;
1413
+ const { connectionClickStartHandle: clickHandle, connectionMode, connection } = state;
1414
+ const { fromHandle, toHandle, isValid } = connection;
1415
+ const connectingTo = toHandle?.nodeId === nodeId && toHandle?.id === handleId && toHandle?.type === type;
1414
1416
  return {
1415
- connectingFrom: startHandle?.nodeId === nodeId && startHandle?.handleId === handleId && startHandle?.type === type,
1417
+ connectingFrom: fromHandle?.nodeId === nodeId && fromHandle?.id === handleId && fromHandle?.type === type,
1416
1418
  connectingTo,
1417
- clickConnecting: clickHandle?.nodeId === nodeId && clickHandle?.handleId === handleId && clickHandle?.type === type,
1419
+ clickConnecting: clickHandle?.nodeId === nodeId && clickHandle?.id === handleId && clickHandle?.type === type,
1418
1420
  isPossibleEndHandle: connectionMode === ConnectionMode.Strict
1419
- ? startHandle?.type !== type
1420
- : nodeId !== startHandle?.nodeId || handleId !== startHandle?.handleId,
1421
- connectionInProcess: !!startHandle,
1422
- valid: connectingTo && connectionStatus === 'valid',
1421
+ ? fromHandle?.type !== type
1422
+ : nodeId !== fromHandle?.nodeId || handleId !== fromHandle?.id,
1423
+ connectionInProcess: !!fromHandle,
1424
+ valid: connectingTo && isValid,
1423
1425
  };
1424
1426
  };
1425
1427
  function HandleComponent({ type = 'source', position = Position.Top, isValidConnection, isConnectable = true, isConnectableStart = true, isConnectableEnd = true, id, onConnect, children, className, onMouseDown, onTouchStart, ...rest }, ref) {
@@ -1427,7 +1429,7 @@ function HandleComponent({ type = 'source', position = Position.Top, isValidConn
1427
1429
  const isTarget = type === 'target';
1428
1430
  const store = useStoreApi();
1429
1431
  const nodeId = useNodeId();
1430
- const { connectOnClick, noPanClassName, rfId } = useStore(selector$i, shallow);
1432
+ const { connectOnClick, noPanClassName, rfId } = useStore(selector$h, shallow);
1431
1433
  const { connectingFrom, connectingTo, clickConnecting, isPossibleEndHandle, connectionInProcess, valid } = useStore(connectingSelector(nodeId, handleId, type), shallow);
1432
1434
  if (!nodeId) {
1433
1435
  store.getState().onError?.('010', errorMessages['error010']());
@@ -1472,7 +1474,8 @@ function HandleComponent({ type = 'source', position = Position.Top, isValidConn
1472
1474
  onConnect: onConnectExtended,
1473
1475
  isValidConnection: isValidConnection || currentStore.isValidConnection,
1474
1476
  getTransform: () => store.getState().transform,
1475
- getConnectionStartHandle: () => store.getState().connectionStartHandle,
1477
+ getFromHandle: () => store.getState().connection.fromHandle,
1478
+ autoPanSpeed: currentStore.autoPanSpeed,
1476
1479
  });
1477
1480
  }
1478
1481
  if (isMouseTriggered) {
@@ -1489,7 +1492,7 @@ function HandleComponent({ type = 'source', position = Position.Top, isValidConn
1489
1492
  }
1490
1493
  if (!connectionClickStartHandle) {
1491
1494
  onClickConnectStart?.(event.nativeEvent, { nodeId, handleId, handleType: type });
1492
- store.setState({ connectionClickStartHandle: { nodeId, type, handleId } });
1495
+ store.setState({ connectionClickStartHandle: { nodeId, type, id: handleId } });
1493
1496
  return;
1494
1497
  }
1495
1498
  const doc = getHostForElement(event.target);
@@ -1502,7 +1505,7 @@ function HandleComponent({ type = 'source', position = Position.Top, isValidConn
1502
1505
  },
1503
1506
  connectionMode,
1504
1507
  fromNodeId: connectionClickStartHandle.nodeId,
1505
- fromHandleId: connectionClickStartHandle.handleId || null,
1508
+ fromHandleId: connectionClickStartHandle.id || null,
1506
1509
  fromType: connectionClickStartHandle.type,
1507
1510
  isValidConnection: isValidConnectionHandler,
1508
1511
  flowId,
@@ -1585,9 +1588,8 @@ function getNodeInlineStyleDimensions(node) {
1585
1588
  };
1586
1589
  }
1587
1590
 
1588
- const selector$h = (s) => {
1591
+ const selector$g = (s) => {
1589
1592
  const { width, height, x, y } = getInternalNodesBounds(s.nodeLookup, {
1590
- nodeOrigin: s.nodeOrigin,
1591
1593
  filter: (node) => !!node.selected,
1592
1594
  });
1593
1595
  return {
@@ -1599,7 +1601,7 @@ const selector$h = (s) => {
1599
1601
  };
1600
1602
  function NodesSelection({ onSelectionContextMenu, noPanClassName, disableKeyboardA11y, }) {
1601
1603
  const store = useStoreApi();
1602
- const { width, height, transformString, userSelectionActive } = useStore(selector$h, shallow);
1604
+ const { width, height, transformString, userSelectionActive } = useStore(selector$g, shallow);
1603
1605
  const moveSelectedNodes = useMoveSelectedNodes();
1604
1606
  const nodeRef = useRef(null);
1605
1607
  useEffect(() => {
@@ -1638,11 +1640,11 @@ function NodesSelection({ onSelectionContextMenu, noPanClassName, disableKeyboar
1638
1640
  }
1639
1641
 
1640
1642
  const win = typeof window !== 'undefined' ? window : undefined;
1641
- const selector$g = (s) => {
1643
+ const selector$f = (s) => {
1642
1644
  return { nodesSelectionActive: s.nodesSelectionActive, userSelectionActive: s.userSelectionActive };
1643
1645
  };
1644
1646
  function FlowRendererComponent({ children, onPaneClick, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, onPaneContextMenu, onPaneScroll, deleteKeyCode, selectionKeyCode, selectionOnDrag, selectionMode, onSelectionStart, onSelectionEnd, multiSelectionKeyCode, panActivationKeyCode, zoomActivationKeyCode, elementsSelectable, zoomOnScroll, zoomOnPinch, panOnScroll: _panOnScroll, panOnScrollSpeed, panOnScrollMode, zoomOnDoubleClick, panOnDrag: _panOnDrag, defaultViewport, translateExtent, minZoom, maxZoom, preventScrolling, onSelectionContextMenu, noWheelClassName, noPanClassName, disableKeyboardA11y, onViewportChange, isControlledViewport, }) {
1645
- const { nodesSelectionActive, userSelectionActive } = useStore(selector$g);
1647
+ const { nodesSelectionActive, userSelectionActive } = useStore(selector$f);
1646
1648
  const selectionKeyPressed = useKeyPress(selectionKeyCode, { target: win });
1647
1649
  const panActivationKeyPressed = useKeyPress(panActivationKeyCode, { target: win });
1648
1650
  const panOnDrag = panActivationKeyPressed || _panOnDrag;
@@ -1654,7 +1656,7 @@ function FlowRendererComponent({ children, onPaneClick, onPaneMouseEnter, onPane
1654
1656
  FlowRendererComponent.displayName = 'FlowRenderer';
1655
1657
  const FlowRenderer = memo(FlowRendererComponent);
1656
1658
 
1657
- const selector$f = (onlyRenderVisible) => (s) => {
1659
+ const selector$e = (onlyRenderVisible) => (s) => {
1658
1660
  return onlyRenderVisible
1659
1661
  ? getNodesInside(s.nodeLookup, { x: 0, y: 0, width: s.width, height: s.height }, s.transform, true).map((node) => node.id)
1660
1662
  : Array.from(s.nodeLookup.keys());
@@ -1667,13 +1669,13 @@ const selector$f = (onlyRenderVisible) => (s) => {
1667
1669
  * @returns array with visible node ids
1668
1670
  */
1669
1671
  function useVisibleNodeIds(onlyRenderVisible) {
1670
- const nodeIds = useStore(useCallback(selector$f(onlyRenderVisible), [onlyRenderVisible]), shallow);
1672
+ const nodeIds = useStore(useCallback(selector$e(onlyRenderVisible), [onlyRenderVisible]), shallow);
1671
1673
  return nodeIds;
1672
1674
  }
1673
1675
 
1674
- const selector$e = (s) => s.updateNodeInternals;
1676
+ const selector$d = (s) => s.updateNodeInternals;
1675
1677
  function useResizeObserver() {
1676
- const updateNodeInternals = useStore(selector$e);
1678
+ const updateNodeInternals = useStore(selector$d);
1677
1679
  const [resizeObserver] = useState(() => {
1678
1680
  if (typeof ResizeObserver === 'undefined') {
1679
1681
  return null;
@@ -1750,7 +1752,7 @@ function useNodeObserver({ node, nodeType, hasDimensions, resizeObserver, }) {
1750
1752
  return nodeRef;
1751
1753
  }
1752
1754
 
1753
- function NodeWrapper({ id, onClick, onMouseEnter, onMouseMove, onMouseLeave, onContextMenu, onDoubleClick, nodesDraggable, elementsSelectable, nodesConnectable, nodesFocusable, resizeObserver, noDragClassName, noPanClassName, disableKeyboardA11y, rfId, nodeTypes, nodeExtent, nodeOrigin, onError, }) {
1755
+ function NodeWrapper({ id, onClick, onMouseEnter, onMouseMove, onMouseLeave, onContextMenu, onDoubleClick, nodesDraggable, elementsSelectable, nodesConnectable, nodesFocusable, resizeObserver, noDragClassName, noPanClassName, disableKeyboardA11y, rfId, nodeTypes, nodeExtent, onError, }) {
1754
1756
  const { node, internals, isParent } = useStore((s) => {
1755
1757
  const node = s.nodeLookup.get(id);
1756
1758
  const isParent = s.parentLookup.has(id);
@@ -1788,14 +1790,10 @@ function NodeWrapper({ id, onClick, onMouseEnter, onMouseMove, onMouseLeave, onC
1788
1790
  }
1789
1791
  const nodeDimensions = getNodeDimensions(node);
1790
1792
  const inlineDimensions = getNodeInlineStyleDimensions(node);
1793
+ // TODO: clamping should happen earlier
1791
1794
  const clampedPosition = nodeExtent
1792
1795
  ? clampPosition(internals.positionAbsolute, nodeExtent)
1793
1796
  : internals.positionAbsolute;
1794
- const positionWithOrigin = getPositionWithOrigin({
1795
- ...clampedPosition,
1796
- ...nodeDimensions,
1797
- origin: node.origin || nodeOrigin,
1798
- });
1799
1797
  const hasPointerEvents = isSelectable || isDraggable || onClick || onMouseEnter || onMouseMove || onMouseLeave;
1800
1798
  const onMouseEnterHandler = onMouseEnter
1801
1799
  ? (event) => onMouseEnter(event, { ...internals.userNode })
@@ -1869,7 +1867,7 @@ function NodeWrapper({ id, onClick, onMouseEnter, onMouseMove, onMouseLeave, onC
1869
1867
  },
1870
1868
  ]), ref: nodeRef, style: {
1871
1869
  zIndex: internals.z,
1872
- transform: `translate(${positionWithOrigin.x}px,${positionWithOrigin.y}px)`,
1870
+ transform: `translate(${clampedPosition.x}px,${clampedPosition.y}px)`,
1873
1871
  pointerEvents: hasPointerEvents ? 'all' : 'none',
1874
1872
  visibility: hasDimensions ? 'visible' : 'hidden',
1875
1873
  ...node.style,
@@ -1877,7 +1875,7 @@ function NodeWrapper({ id, onClick, onMouseEnter, onMouseMove, onMouseLeave, onC
1877
1875
  }, "data-id": id, "data-testid": `rf__node-${id}`, onMouseEnter: onMouseEnterHandler, onMouseMove: onMouseMoveHandler, onMouseLeave: onMouseLeaveHandler, onContextMenu: onContextMenuHandler, onClick: onSelectNodeHandler, onDoubleClick: onDoubleClickHandler, onKeyDown: isFocusable ? onKeyDown : undefined, tabIndex: isFocusable ? 0 : undefined, role: isFocusable ? 'button' : undefined, "aria-describedby": disableKeyboardA11y ? undefined : `${ARIA_NODE_DESC_KEY}-${rfId}`, "aria-label": node.ariaLabel, children: jsx(Provider, { value: id, children: jsx(NodeComponent, { id: id, data: node.data, type: nodeType, positionAbsoluteX: clampedPosition.x, positionAbsoluteY: clampedPosition.y, selected: node.selected, selectable: isSelectable, draggable: isDraggable, deletable: node.deletable ?? true, isConnectable: isConnectable, sourcePosition: node.sourcePosition, targetPosition: node.targetPosition, dragging: dragging, dragHandle: node.dragHandle, zIndex: internals.z, parentId: node.parentId, ...nodeDimensions }) }) }));
1878
1876
  }
1879
1877
 
1880
- const selector$d = (s) => ({
1878
+ const selector$c = (s) => ({
1881
1879
  nodesDraggable: s.nodesDraggable,
1882
1880
  nodesConnectable: s.nodesConnectable,
1883
1881
  nodesFocusable: s.nodesFocusable,
@@ -1885,7 +1883,7 @@ const selector$d = (s) => ({
1885
1883
  onError: s.onError,
1886
1884
  });
1887
1885
  function NodeRendererComponent(props) {
1888
- const { nodesDraggable, nodesConnectable, nodesFocusable, elementsSelectable, onError } = useStore(selector$d, shallow);
1886
+ const { nodesDraggable, nodesConnectable, nodesFocusable, elementsSelectable, onError } = useStore(selector$c, shallow);
1889
1887
  const nodeIds = useVisibleNodeIds(props.onlyRenderVisibleElements);
1890
1888
  const resizeObserver = useResizeObserver();
1891
1889
  return (jsx("div", { className: "react-flow__nodes", style: containerStyle, children: nodeIds.map((nodeId) => {
@@ -1913,7 +1911,7 @@ function NodeRendererComponent(props) {
1913
1911
  // moved into `NodeComponentWrapper`. This ensures they are
1914
1912
  // memorized – so if `NodeRenderer` *has* to rerender, it only
1915
1913
  // needs to regenerate the list of nodes, nothing else.
1916
- jsx(NodeWrapper, { id: nodeId, nodeTypes: props.nodeTypes, nodeExtent: props.nodeExtent, nodeOrigin: props.nodeOrigin, onClick: props.onNodeClick, onMouseEnter: props.onNodeMouseEnter, onMouseMove: props.onNodeMouseMove, onMouseLeave: props.onNodeMouseLeave, onContextMenu: props.onNodeContextMenu, onDoubleClick: props.onNodeDoubleClick, noDragClassName: props.noDragClassName, noPanClassName: props.noPanClassName, rfId: props.rfId, disableKeyboardA11y: props.disableKeyboardA11y, resizeObserver: resizeObserver, nodesDraggable: nodesDraggable, nodesConnectable: nodesConnectable, nodesFocusable: nodesFocusable, elementsSelectable: elementsSelectable, onError: onError }, nodeId));
1914
+ jsx(NodeWrapper, { id: nodeId, nodeTypes: props.nodeTypes, nodeExtent: props.nodeExtent, onClick: props.onNodeClick, onMouseEnter: props.onNodeMouseEnter, onMouseMove: props.onNodeMouseMove, onMouseLeave: props.onNodeMouseLeave, onContextMenu: props.onNodeContextMenu, onDoubleClick: props.onNodeDoubleClick, noDragClassName: props.noDragClassName, noPanClassName: props.noPanClassName, rfId: props.rfId, disableKeyboardA11y: props.disableKeyboardA11y, resizeObserver: resizeObserver, nodesDraggable: nodesDraggable, nodesConnectable: nodesConnectable, nodesFocusable: nodesFocusable, elementsSelectable: elementsSelectable, onError: onError }, nodeId));
1917
1915
  }) }));
1918
1916
  }
1919
1917
  NodeRendererComponent.displayName = 'NodeRenderer';
@@ -2243,7 +2241,7 @@ function EdgeUpdateAnchors({ isReconnectable, reconnectRadius, edge, targetHandl
2243
2241
  onReconnectEnd: _onReconnectEnd,
2244
2242
  updateConnection,
2245
2243
  getTransform: () => store.getState().transform,
2246
- getConnectionStartHandle: () => store.getState().connectionStartHandle,
2244
+ getFromHandle: () => store.getState().connection.fromHandle,
2247
2245
  });
2248
2246
  };
2249
2247
  const onReconnectSourceMouseDown = (event) => handleEdgeUpdater(event, true);
@@ -2376,7 +2374,7 @@ function EdgeWrapper({ id, edgesFocusable, edgesReconnectable, elementsSelectabl
2376
2374
  ]), onClick: onEdgeClick, onDoubleClick: onEdgeDoubleClick, onContextMenu: onEdgeContextMenu, onMouseEnter: onEdgeMouseEnter, onMouseMove: onEdgeMouseMove, onMouseLeave: onEdgeMouseLeave, onKeyDown: isFocusable ? onKeyDown : undefined, tabIndex: isFocusable ? 0 : undefined, role: isFocusable ? 'button' : 'img', "data-id": id, "data-testid": `rf__edge-${id}`, "aria-label": edge.ariaLabel === null ? undefined : edge.ariaLabel || `Edge from ${edge.source} to ${edge.target}`, "aria-describedby": isFocusable ? `${ARIA_EDGE_DESC_KEY}-${rfId}` : undefined, ref: edgeRef, children: [!reconnecting && (jsx(EdgeComponent, { id: id, source: edge.source, target: edge.target, type: edge.type, selected: edge.selected, animated: edge.animated, selectable: isSelectable, deletable: edge.deletable ?? true, label: edge.label, labelStyle: edge.labelStyle, labelShowBg: edge.labelShowBg, labelBgStyle: edge.labelBgStyle, labelBgPadding: edge.labelBgPadding, labelBgBorderRadius: edge.labelBgBorderRadius, sourceX: sourceX, sourceY: sourceY, targetX: targetX, targetY: targetY, sourcePosition: sourcePosition, targetPosition: targetPosition, data: edge.data, style: edge.style, sourceHandleId: edge.sourceHandle, targetHandleId: edge.targetHandle, markerStart: markerStartUrl, markerEnd: markerEndUrl, pathOptions: 'pathOptions' in edge ? edge.pathOptions : undefined, interactionWidth: edge.interactionWidth })), isReconnectable && (jsx(EdgeUpdateAnchors, { edge: edge, isReconnectable: isReconnectable, reconnectRadius: reconnectRadius, onReconnect: onReconnect, onReconnectStart: onReconnectStart, onReconnectEnd: onReconnectEnd, sourceX: sourceX, sourceY: sourceY, targetX: targetX, targetY: targetY, sourcePosition: sourcePosition, targetPosition: targetPosition, setUpdateHover: setUpdateHover, setReconnecting: setReconnecting, sourceHandleId: edge.sourceHandle, targetHandleId: edge.targetHandle }))] }) }));
2377
2375
  }
2378
2376
 
2379
- const selector$c = (s) => ({
2377
+ const selector$b = (s) => ({
2380
2378
  width: s.width,
2381
2379
  height: s.height,
2382
2380
  edgesFocusable: s.edgesFocusable,
@@ -2386,7 +2384,7 @@ const selector$c = (s) => ({
2386
2384
  onError: s.onError,
2387
2385
  });
2388
2386
  function EdgeRendererComponent({ defaultMarkerColor, onlyRenderVisibleElements, rfId, edgeTypes, noPanClassName, onReconnect, onEdgeContextMenu, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, onEdgeClick, reconnectRadius, onEdgeDoubleClick, onReconnectStart, onReconnectEnd, disableKeyboardA11y, }) {
2389
- const { edgesFocusable, edgesReconnectable, elementsSelectable, onError } = useStore(selector$c, shallow);
2387
+ const { edgesFocusable, edgesReconnectable, elementsSelectable, onError } = useStore(selector$b, shallow);
2390
2388
  const edgeIds = useVisibleEdgeIds(onlyRenderVisibleElements);
2391
2389
  return (jsxs("div", { className: "react-flow__edges", children: [jsx(MarkerDefinitions$1, { defaultColor: defaultMarkerColor, rfId: rfId }), edgeIds.map((id) => {
2392
2390
  return (jsx(EdgeWrapper, { id: id, edgesFocusable: edgesFocusable, edgesReconnectable: edgesReconnectable, elementsSelectable: elementsSelectable, noPanClassName: noPanClassName, onReconnect: onReconnect, onContextMenu: onEdgeContextMenu, onMouseEnter: onEdgeMouseEnter, onMouseMove: onEdgeMouseMove, onMouseLeave: onEdgeMouseLeave, onClick: onEdgeClick, reconnectRadius: reconnectRadius, onDoubleClick: onEdgeDoubleClick, onReconnectStart: onReconnectStart, onReconnectEnd: onReconnectEnd, rfId: rfId, onError: onError, edgeTypes: edgeTypes, disableKeyboardA11y: disableKeyboardA11y }, id));
@@ -2395,9 +2393,9 @@ function EdgeRendererComponent({ defaultMarkerColor, onlyRenderVisibleElements,
2395
2393
  EdgeRendererComponent.displayName = 'EdgeRenderer';
2396
2394
  const EdgeRenderer = memo(EdgeRendererComponent);
2397
2395
 
2398
- const selector$b = (s) => `translate(${s.transform[0]}px,${s.transform[1]}px) scale(${s.transform[2]})`;
2396
+ const selector$a = (s) => `translate(${s.transform[0]}px,${s.transform[1]}px) scale(${s.transform[2]})`;
2399
2397
  function Viewport({ children }) {
2400
- const transform = useStore(selector$b);
2398
+ const transform = useStore(selector$a);
2401
2399
  return (jsx("div", { className: "react-flow__viewport xyflow__viewport react-flow__container", style: { transform }, children: children }));
2402
2400
  }
2403
2401
 
@@ -2417,7 +2415,7 @@ function useOnInitHandler(onInit) {
2417
2415
  }, [onInit, rfInstance.viewportInitialized]);
2418
2416
  }
2419
2417
 
2420
- const selector$a = (state) => state.panZoom?.syncViewport;
2418
+ const selector$9 = (state) => state.panZoom?.syncViewport;
2421
2419
  /**
2422
2420
  * Hook for syncing the viewport with the panzoom instance.
2423
2421
  *
@@ -2425,7 +2423,7 @@ const selector$a = (state) => state.panZoom?.syncViewport;
2425
2423
  * @param viewport
2426
2424
  */
2427
2425
  function useViewportSync(viewport) {
2428
- const syncViewport = useStore(selector$a);
2426
+ const syncViewport = useStore(selector$9);
2429
2427
  const store = useStoreApi();
2430
2428
  useEffect(() => {
2431
2429
  if (viewport) {
@@ -2436,90 +2434,75 @@ function useViewportSync(viewport) {
2436
2434
  return null;
2437
2435
  }
2438
2436
 
2439
- const oppositePosition = {
2440
- [Position.Left]: Position.Right,
2441
- [Position.Right]: Position.Left,
2442
- [Position.Top]: Position.Bottom,
2443
- [Position.Bottom]: Position.Top,
2437
+ const selector$8 = (s) => {
2438
+ return s.connection.inProgress
2439
+ ? { ...s.connection, to: pointToRendererPoint(s.connection.to, s.transform) }
2440
+ : { ...s.connection };
2444
2441
  };
2445
- const ConnectionLine = ({ nodeId, handleType, style, type = ConnectionLineType.Bezier, CustomComponent, connectionStatus, }) => {
2446
- const { fromNode, handleId, toX, toY, connectionMode, endPosition, isValid } = useStore(useCallback((s) => ({
2447
- fromNode: s.nodeLookup.get(nodeId),
2448
- handleId: s.connectionStartHandle?.handleId,
2449
- toX: (s.connectionPosition.x - s.transform[0]) / s.transform[2],
2450
- toY: (s.connectionPosition.y - s.transform[1]) / s.transform[2],
2451
- connectionMode: s.connectionMode,
2452
- endPosition: s.connectionEndHandle?.position,
2453
- isValid: s.connectionStatus === 'valid',
2454
- }), [nodeId]), shallow);
2455
- const fromHandleBounds = fromNode?.internals.handleBounds;
2456
- let handleBounds = fromHandleBounds?.[handleType];
2457
- if (connectionMode === ConnectionMode.Loose) {
2458
- handleBounds = handleBounds ? handleBounds : fromHandleBounds?.[handleType === 'source' ? 'target' : 'source'];
2459
- }
2460
- if (!fromNode || !handleBounds) {
2442
+ /**
2443
+ * Hook for accessing the connection state.
2444
+ *
2445
+ * @public
2446
+ * @returns ConnectionState
2447
+ */
2448
+ function useConnection() {
2449
+ return useStore(selector$8, shallow);
2450
+ }
2451
+
2452
+ const selector$7 = (s) => ({
2453
+ nodesConnectable: s.nodesConnectable,
2454
+ isValid: s.connection.isValid,
2455
+ inProgress: s.connection.inProgress,
2456
+ width: s.width,
2457
+ height: s.height,
2458
+ });
2459
+ function ConnectionLineWrapper({ containerStyle, style, type, component }) {
2460
+ const { nodesConnectable, width, height, isValid, inProgress } = useStore(selector$7, shallow);
2461
+ const renderConnection = !!(width && nodesConnectable && inProgress);
2462
+ if (!renderConnection) {
2461
2463
  return null;
2462
2464
  }
2463
- const fromHandle = handleId ? handleBounds.find((d) => d.id === handleId) : handleBounds[0];
2464
- const fromHandleX = fromHandle ? fromHandle.x + fromHandle.width / 2 : (fromNode.measured.width ?? 0) / 2;
2465
- const fromHandleY = fromHandle ? fromHandle.y + fromHandle.height / 2 : fromNode.measured.height ?? 0;
2466
- const fromX = fromNode.internals.positionAbsolute.x + fromHandleX;
2467
- const fromY = fromNode.internals.positionAbsolute.y + fromHandleY;
2468
- const fromPosition = fromHandle?.position;
2469
- const toPosition = isValid && endPosition ? endPosition : fromPosition ? oppositePosition[fromPosition] : null;
2470
- if (!fromPosition || !toPosition) {
2471
- return null;
2465
+ return (jsx("svg", { style: containerStyle, width: width, height: height, className: "react-flow__connectionline react-flow__container", children: jsx("g", { className: cc(['react-flow__connection', getConnectionStatus(isValid)]), children: jsx(ConnectionLine, { style: style, type: type, CustomComponent: component, isValid: isValid }) }) }));
2466
+ }
2467
+ const ConnectionLine = ({ style, type = ConnectionLineType.Bezier, CustomComponent, isValid }) => {
2468
+ const { inProgress, from, fromNode, fromHandle, fromPosition, to, toNode, toHandle, toPosition } = useConnection();
2469
+ if (!inProgress) {
2470
+ return;
2472
2471
  }
2473
2472
  if (CustomComponent) {
2474
- return (jsx(CustomComponent, { connectionLineType: type, connectionLineStyle: style, fromNode: fromNode, fromHandle: fromHandle, fromX: fromX, fromY: fromY, toX: toX, toY: toY, fromPosition: fromPosition, toPosition: toPosition, connectionStatus: connectionStatus }));
2473
+ return (jsx(CustomComponent, { connectionLineType: type, connectionLineStyle: style, fromNode: fromNode, fromHandle: fromHandle, fromX: from.x, fromY: from.y, toX: to.x, toY: to.y, fromPosition: fromPosition, toPosition: toPosition, connectionStatus: getConnectionStatus(isValid), toNode: toNode, toHandle: toHandle }));
2475
2474
  }
2476
- let dAttr = '';
2475
+ let path = '';
2477
2476
  const pathParams = {
2478
- sourceX: fromX,
2479
- sourceY: fromY,
2477
+ sourceX: from.x,
2478
+ sourceY: from.y,
2480
2479
  sourcePosition: fromPosition,
2481
- targetX: toX,
2482
- targetY: toY,
2480
+ targetX: to.x,
2481
+ targetY: to.y,
2483
2482
  targetPosition: toPosition,
2484
2483
  };
2485
- if (type === ConnectionLineType.Bezier) {
2486
- // we assume the destination position is opposite to the source position
2487
- [dAttr] = getBezierPath(pathParams);
2488
- }
2489
- else if (type === ConnectionLineType.Step) {
2490
- [dAttr] = getSmoothStepPath({
2491
- ...pathParams,
2492
- borderRadius: 0,
2493
- });
2494
- }
2495
- else if (type === ConnectionLineType.SmoothStep) {
2496
- [dAttr] = getSmoothStepPath(pathParams);
2497
- }
2498
- else if (type === ConnectionLineType.SimpleBezier) {
2499
- [dAttr] = getSimpleBezierPath(pathParams);
2500
- }
2501
- else {
2502
- dAttr = `M${fromX},${fromY} ${toX},${toY}`;
2484
+ switch (type) {
2485
+ case ConnectionLineType.Bezier:
2486
+ [path] = getBezierPath(pathParams);
2487
+ break;
2488
+ case ConnectionLineType.SimpleBezier:
2489
+ [path] = getSimpleBezierPath(pathParams);
2490
+ break;
2491
+ case ConnectionLineType.Step:
2492
+ [path] = getSmoothStepPath({
2493
+ ...pathParams,
2494
+ borderRadius: 0,
2495
+ });
2496
+ break;
2497
+ case ConnectionLineType.SmoothStep:
2498
+ [path] = getSmoothStepPath(pathParams);
2499
+ break;
2500
+ default:
2501
+ [path] = getStraightPath(pathParams);
2503
2502
  }
2504
- return jsx("path", { d: dAttr, fill: "none", className: "react-flow__connection-path", style: style });
2503
+ return jsx("path", { d: path, fill: "none", className: "react-flow__connection-path", style: style });
2505
2504
  };
2506
2505
  ConnectionLine.displayName = 'ConnectionLine';
2507
- const selector$9 = (s) => ({
2508
- nodeId: s.connectionStartHandle?.nodeId,
2509
- handleType: s.connectionStartHandle?.type,
2510
- nodesConnectable: s.nodesConnectable,
2511
- connectionStatus: s.connectionStatus,
2512
- width: s.width,
2513
- height: s.height,
2514
- });
2515
- function ConnectionLineWrapper({ containerStyle, style, type, component }) {
2516
- const { nodeId, handleType, nodesConnectable, width, height, connectionStatus } = useStore(selector$9, shallow);
2517
- const isValid = !!(nodeId && handleType && width && nodesConnectable);
2518
- if (!isValid) {
2519
- return null;
2520
- }
2521
- return (jsx("svg", { style: containerStyle, width: width, height: height, className: "react-flow__connectionline react-flow__container", children: jsx("g", { className: cc(['react-flow__connection', connectionStatus]), children: jsx(ConnectionLine, { nodeId: nodeId, handleType: handleType, style: style, type: type, CustomComponent: component, connectionStatus: connectionStatus }) }) }));
2522
- }
2523
2506
 
2524
2507
  const emptyTypes = {};
2525
2508
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -2556,34 +2539,33 @@ function useStylesLoadedWarning() {
2556
2539
  }, []);
2557
2540
  }
2558
2541
 
2559
- function GraphViewComponent({ nodeTypes, edgeTypes, onInit, onNodeClick, onEdgeClick, onNodeDoubleClick, onEdgeDoubleClick, onNodeMouseEnter, onNodeMouseMove, onNodeMouseLeave, onNodeContextMenu, onSelectionContextMenu, onSelectionStart, onSelectionEnd, connectionLineType, connectionLineStyle, connectionLineComponent, connectionLineContainerStyle, selectionKeyCode, selectionOnDrag, selectionMode, multiSelectionKeyCode, panActivationKeyCode, zoomActivationKeyCode, deleteKeyCode, onlyRenderVisibleElements, elementsSelectable, defaultViewport, translateExtent, minZoom, maxZoom, preventScrolling, defaultMarkerColor, zoomOnScroll, zoomOnPinch, panOnScroll, panOnScrollSpeed, panOnScrollMode, zoomOnDoubleClick, panOnDrag, onPaneClick, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, onPaneScroll, onPaneContextMenu, onEdgeContextMenu, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, reconnectRadius, onReconnect, onReconnectStart, onReconnectEnd, noDragClassName, noWheelClassName, noPanClassName, disableKeyboardA11y, nodeOrigin, nodeExtent, rfId, viewport, onViewportChange, }) {
2542
+ function GraphViewComponent({ nodeTypes, edgeTypes, onInit, onNodeClick, onEdgeClick, onNodeDoubleClick, onEdgeDoubleClick, onNodeMouseEnter, onNodeMouseMove, onNodeMouseLeave, onNodeContextMenu, onSelectionContextMenu, onSelectionStart, onSelectionEnd, connectionLineType, connectionLineStyle, connectionLineComponent, connectionLineContainerStyle, selectionKeyCode, selectionOnDrag, selectionMode, multiSelectionKeyCode, panActivationKeyCode, zoomActivationKeyCode, deleteKeyCode, onlyRenderVisibleElements, elementsSelectable, defaultViewport, translateExtent, minZoom, maxZoom, preventScrolling, defaultMarkerColor, zoomOnScroll, zoomOnPinch, panOnScroll, panOnScrollSpeed, panOnScrollMode, zoomOnDoubleClick, panOnDrag, onPaneClick, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, onPaneScroll, onPaneContextMenu, onEdgeContextMenu, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, reconnectRadius, onReconnect, onReconnectStart, onReconnectEnd, noDragClassName, noWheelClassName, noPanClassName, disableKeyboardA11y, nodeExtent, rfId, viewport, onViewportChange, }) {
2560
2543
  useNodeOrEdgeTypesWarning(nodeTypes);
2561
2544
  useNodeOrEdgeTypesWarning(edgeTypes);
2562
2545
  useStylesLoadedWarning();
2563
2546
  useOnInitHandler(onInit);
2564
2547
  useViewportSync(viewport);
2565
- return (jsx(FlowRenderer, { onPaneClick: onPaneClick, onPaneMouseEnter: onPaneMouseEnter, onPaneMouseMove: onPaneMouseMove, onPaneMouseLeave: onPaneMouseLeave, onPaneContextMenu: onPaneContextMenu, onPaneScroll: onPaneScroll, deleteKeyCode: deleteKeyCode, selectionKeyCode: selectionKeyCode, selectionOnDrag: selectionOnDrag, selectionMode: selectionMode, onSelectionStart: onSelectionStart, onSelectionEnd: onSelectionEnd, multiSelectionKeyCode: multiSelectionKeyCode, panActivationKeyCode: panActivationKeyCode, zoomActivationKeyCode: zoomActivationKeyCode, elementsSelectable: elementsSelectable, zoomOnScroll: zoomOnScroll, zoomOnPinch: zoomOnPinch, zoomOnDoubleClick: zoomOnDoubleClick, panOnScroll: panOnScroll, panOnScrollSpeed: panOnScrollSpeed, panOnScrollMode: panOnScrollMode, panOnDrag: panOnDrag, defaultViewport: defaultViewport, translateExtent: translateExtent, minZoom: minZoom, maxZoom: maxZoom, onSelectionContextMenu: onSelectionContextMenu, preventScrolling: preventScrolling, noDragClassName: noDragClassName, noWheelClassName: noWheelClassName, noPanClassName: noPanClassName, disableKeyboardA11y: disableKeyboardA11y, onViewportChange: onViewportChange, isControlledViewport: !!viewport, children: jsxs(Viewport, { children: [jsx(EdgeRenderer, { edgeTypes: edgeTypes, onEdgeClick: onEdgeClick, onEdgeDoubleClick: onEdgeDoubleClick, onReconnect: onReconnect, onReconnectStart: onReconnectStart, onReconnectEnd: onReconnectEnd, onlyRenderVisibleElements: onlyRenderVisibleElements, onEdgeContextMenu: onEdgeContextMenu, onEdgeMouseEnter: onEdgeMouseEnter, onEdgeMouseMove: onEdgeMouseMove, onEdgeMouseLeave: onEdgeMouseLeave, reconnectRadius: reconnectRadius, defaultMarkerColor: defaultMarkerColor, noPanClassName: noPanClassName, disableKeyboardA11y: disableKeyboardA11y, rfId: rfId }), jsx(ConnectionLineWrapper, { style: connectionLineStyle, type: connectionLineType, component: connectionLineComponent, containerStyle: connectionLineContainerStyle }), jsx("div", { className: "react-flow__edgelabel-renderer" }), jsx(NodeRenderer, { nodeTypes: nodeTypes, onNodeClick: onNodeClick, onNodeDoubleClick: onNodeDoubleClick, onNodeMouseEnter: onNodeMouseEnter, onNodeMouseMove: onNodeMouseMove, onNodeMouseLeave: onNodeMouseLeave, onNodeContextMenu: onNodeContextMenu, onlyRenderVisibleElements: onlyRenderVisibleElements, noPanClassName: noPanClassName, noDragClassName: noDragClassName, disableKeyboardA11y: disableKeyboardA11y, nodeOrigin: nodeOrigin, nodeExtent: nodeExtent, rfId: rfId }), jsx("div", { className: "react-flow__viewport-portal" })] }) }));
2548
+ return (jsx(FlowRenderer, { onPaneClick: onPaneClick, onPaneMouseEnter: onPaneMouseEnter, onPaneMouseMove: onPaneMouseMove, onPaneMouseLeave: onPaneMouseLeave, onPaneContextMenu: onPaneContextMenu, onPaneScroll: onPaneScroll, deleteKeyCode: deleteKeyCode, selectionKeyCode: selectionKeyCode, selectionOnDrag: selectionOnDrag, selectionMode: selectionMode, onSelectionStart: onSelectionStart, onSelectionEnd: onSelectionEnd, multiSelectionKeyCode: multiSelectionKeyCode, panActivationKeyCode: panActivationKeyCode, zoomActivationKeyCode: zoomActivationKeyCode, elementsSelectable: elementsSelectable, zoomOnScroll: zoomOnScroll, zoomOnPinch: zoomOnPinch, zoomOnDoubleClick: zoomOnDoubleClick, panOnScroll: panOnScroll, panOnScrollSpeed: panOnScrollSpeed, panOnScrollMode: panOnScrollMode, panOnDrag: panOnDrag, defaultViewport: defaultViewport, translateExtent: translateExtent, minZoom: minZoom, maxZoom: maxZoom, onSelectionContextMenu: onSelectionContextMenu, preventScrolling: preventScrolling, noDragClassName: noDragClassName, noWheelClassName: noWheelClassName, noPanClassName: noPanClassName, disableKeyboardA11y: disableKeyboardA11y, onViewportChange: onViewportChange, isControlledViewport: !!viewport, children: jsxs(Viewport, { children: [jsx(EdgeRenderer, { edgeTypes: edgeTypes, onEdgeClick: onEdgeClick, onEdgeDoubleClick: onEdgeDoubleClick, onReconnect: onReconnect, onReconnectStart: onReconnectStart, onReconnectEnd: onReconnectEnd, onlyRenderVisibleElements: onlyRenderVisibleElements, onEdgeContextMenu: onEdgeContextMenu, onEdgeMouseEnter: onEdgeMouseEnter, onEdgeMouseMove: onEdgeMouseMove, onEdgeMouseLeave: onEdgeMouseLeave, reconnectRadius: reconnectRadius, defaultMarkerColor: defaultMarkerColor, noPanClassName: noPanClassName, disableKeyboardA11y: disableKeyboardA11y, rfId: rfId }), jsx(ConnectionLineWrapper, { style: connectionLineStyle, type: connectionLineType, component: connectionLineComponent, containerStyle: connectionLineContainerStyle }), jsx("div", { className: "react-flow__edgelabel-renderer" }), jsx(NodeRenderer, { nodeTypes: nodeTypes, onNodeClick: onNodeClick, onNodeDoubleClick: onNodeDoubleClick, onNodeMouseEnter: onNodeMouseEnter, onNodeMouseMove: onNodeMouseMove, onNodeMouseLeave: onNodeMouseLeave, onNodeContextMenu: onNodeContextMenu, onlyRenderVisibleElements: onlyRenderVisibleElements, noPanClassName: noPanClassName, noDragClassName: noDragClassName, disableKeyboardA11y: disableKeyboardA11y, nodeExtent: nodeExtent, rfId: rfId }), jsx("div", { className: "react-flow__viewport-portal" })] }) }));
2566
2549
  }
2567
2550
  GraphViewComponent.displayName = 'GraphView';
2568
2551
  const GraphView = memo(GraphViewComponent);
2569
2552
 
2570
- const getInitialState = ({ nodes, edges, defaultNodes, defaultEdges, width, height, fitView, } = {}) => {
2553
+ const getInitialState = ({ nodes, edges, defaultNodes, defaultEdges, width, height, fitView, nodeOrigin, } = {}) => {
2571
2554
  const nodeLookup = new Map();
2572
2555
  const parentLookup = new Map();
2573
2556
  const connectionLookup = new Map();
2574
2557
  const edgeLookup = new Map();
2575
2558
  const storeEdges = defaultEdges ?? edges ?? [];
2576
2559
  const storeNodes = defaultNodes ?? nodes ?? [];
2560
+ const storeNodeOrigin = nodeOrigin ?? [0, 0];
2577
2561
  updateConnectionLookup(connectionLookup, edgeLookup, storeEdges);
2578
2562
  adoptUserNodes(storeNodes, nodeLookup, parentLookup, {
2579
- nodeOrigin: [0, 0],
2563
+ nodeOrigin: storeNodeOrigin,
2580
2564
  elevateNodesOnSelect: false,
2581
2565
  });
2582
2566
  let transform = [0, 0, 1];
2583
2567
  if (fitView && width && height) {
2584
- // @todo users nodeOrigin should be used here
2585
2568
  const bounds = getInternalNodesBounds(nodeLookup, {
2586
- nodeOrigin: [0, 0],
2587
2569
  filter: (node) => !!((node.width || node.initialWidth) && (node.height || node.initialHeight)),
2588
2570
  });
2589
2571
  const { x, y, zoom } = getViewportForBounds(bounds, width, height, 0.5, 2, 0.1);
@@ -2612,13 +2594,11 @@ const getInitialState = ({ nodes, edges, defaultNodes, defaultEdges, width, heig
2612
2594
  nodesSelectionActive: false,
2613
2595
  userSelectionActive: false,
2614
2596
  userSelectionRect: null,
2615
- connectionPosition: { x: 0, y: 0 },
2616
- connectionStatus: null,
2617
2597
  connectionMode: ConnectionMode.Strict,
2618
2598
  domNode: null,
2619
2599
  paneDragging: false,
2620
2600
  noPanClassName: 'nopan',
2621
- nodeOrigin: [0, 0],
2601
+ nodeOrigin: storeNodeOrigin,
2622
2602
  nodeDragThreshold: 1,
2623
2603
  snapGrid: [15, 15],
2624
2604
  snapToGrid: false,
@@ -2635,13 +2615,13 @@ const getInitialState = ({ nodes, edges, defaultNodes, defaultEdges, width, heig
2635
2615
  fitViewOnInitOptions: undefined,
2636
2616
  selectNodesOnDrag: true,
2637
2617
  multiSelectionActive: false,
2638
- connectionStartHandle: null,
2639
- connectionEndHandle: null,
2618
+ connection: { ...initialConnection },
2640
2619
  connectionClickStartHandle: null,
2641
2620
  connectOnClick: true,
2642
2621
  ariaLiveMessage: '',
2643
2622
  autoPanOnConnect: true,
2644
2623
  autoPanOnNodeDrag: true,
2624
+ autoPanSpeed: 15,
2645
2625
  connectionRadius: 20,
2646
2626
  onError: devWarn,
2647
2627
  isValidConnection: undefined,
@@ -2651,8 +2631,8 @@ const getInitialState = ({ nodes, edges, defaultNodes, defaultEdges, width, heig
2651
2631
  };
2652
2632
  };
2653
2633
 
2654
- const createStore = ({ nodes, edges, defaultNodes, defaultEdges, width, height, fitView: fitView$1, }) => createWithEqualityFn((set, get) => ({
2655
- ...getInitialState({ nodes, edges, width, height, fitView: fitView$1, defaultNodes, defaultEdges }),
2634
+ const createStore = ({ nodes, edges, defaultNodes, defaultEdges, width, height, fitView: fitView$1, nodeOrigin, }) => createWithEqualityFn((set, get) => ({
2635
+ ...getInitialState({ nodes, edges, width, height, fitView: fitView$1, nodeOrigin, defaultNodes, defaultEdges }),
2656
2636
  setNodes: (nodes) => {
2657
2637
  const { nodeLookup, parentLookup, nodeOrigin, elevateNodesOnSelect } = get();
2658
2638
  // setNodes() is called exclusively in response to user actions:
@@ -2690,7 +2670,7 @@ const createStore = ({ nodes, edges, defaultNodes, defaultEdges, width, height,
2690
2670
  if (!updatedInternals) {
2691
2671
  return;
2692
2672
  }
2693
- updateAbsolutePositions(nodeLookup, { nodeOrigin });
2673
+ updateAbsolutePositions(nodeLookup, parentLookup, { nodeOrigin });
2694
2674
  // we call fitView once initially after all dimensions are set
2695
2675
  let nextFitViewDone = fitViewDone;
2696
2676
  if (!fitViewDone && fitViewOnInit) {
@@ -2739,8 +2719,8 @@ const createStore = ({ nodes, edges, defaultNodes, defaultEdges, width, height,
2739
2719
  changes.push(change);
2740
2720
  }
2741
2721
  if (parentExpandChildren.length > 0) {
2742
- const { nodeLookup, parentLookup } = get();
2743
- const parentExpandChanges = handleExpandParent(parentExpandChildren, nodeLookup, parentLookup);
2722
+ const { nodeLookup, parentLookup, nodeOrigin } = get();
2723
+ const parentExpandChanges = handleExpandParent(parentExpandChildren, nodeLookup, parentLookup, nodeOrigin);
2744
2724
  changes.push(...parentExpandChanges);
2745
2725
  }
2746
2726
  get().triggerNodeChanges(changes);
@@ -2845,7 +2825,7 @@ const createStore = ({ nodes, edges, defaultNodes, defaultEdges, width, height,
2845
2825
  return panBy({ delta, panZoom, transform, translateExtent, width, height });
2846
2826
  },
2847
2827
  fitView: (options) => {
2848
- const { panZoom, width, height, minZoom, maxZoom, nodeOrigin, nodeLookup } = get();
2828
+ const { panZoom, width, height, minZoom, maxZoom, nodeLookup } = get();
2849
2829
  if (!panZoom) {
2850
2830
  return false;
2851
2831
  }
@@ -2856,26 +2836,20 @@ const createStore = ({ nodes, edges, defaultNodes, defaultEdges, width, height,
2856
2836
  panZoom,
2857
2837
  minZoom,
2858
2838
  maxZoom,
2859
- nodeOrigin,
2860
2839
  }, options);
2861
2840
  },
2862
- cancelConnection: () => set({
2863
- connectionStatus: null,
2864
- connectionStartHandle: null,
2865
- connectionEndHandle: null,
2866
- }),
2867
- updateConnection: (params) => {
2868
- const { connectionPosition } = get();
2869
- const currentConnection = {
2870
- ...params,
2871
- connectionPosition: params.connectionPosition ?? connectionPosition,
2872
- };
2873
- set(currentConnection);
2841
+ cancelConnection: () => {
2842
+ set({
2843
+ connection: { ...initialConnection },
2844
+ });
2845
+ },
2846
+ updateConnection: (connection) => {
2847
+ set({ connection });
2874
2848
  },
2875
2849
  reset: () => set({ ...getInitialState() }),
2876
2850
  }), Object.is);
2877
2851
 
2878
- function ReactFlowProvider({ initialNodes: nodes, initialEdges: edges, defaultNodes, defaultEdges, initialWidth: width, initialHeight: height, fitView, children, }) {
2852
+ function ReactFlowProvider({ initialNodes: nodes, initialEdges: edges, defaultNodes, defaultEdges, initialWidth: width, initialHeight: height, fitView, nodeOrigin, children, }) {
2879
2853
  const [store] = useState(() => createStore({
2880
2854
  nodes,
2881
2855
  edges,
@@ -2884,18 +2858,19 @@ function ReactFlowProvider({ initialNodes: nodes, initialEdges: edges, defaultNo
2884
2858
  width,
2885
2859
  height,
2886
2860
  fitView,
2861
+ nodeOrigin,
2887
2862
  }));
2888
2863
  return (jsx(Provider$1, { value: store, children: jsx(BatchProvider, { children: children }) }));
2889
2864
  }
2890
2865
 
2891
- function Wrapper({ children, nodes, edges, defaultNodes, defaultEdges, width, height, fitView, }) {
2866
+ function Wrapper({ children, nodes, edges, defaultNodes, defaultEdges, width, height, fitView, nodeOrigin, }) {
2892
2867
  const isWrapped = useContext(StoreContext);
2893
2868
  if (isWrapped) {
2894
2869
  // we need to wrap it with a fragment because it's not allowed for children to be a ReactNode
2895
2870
  // https://github.com/DefinitelyTyped/DefinitelyTyped/issues/18051
2896
2871
  return jsx(Fragment, { children: children });
2897
2872
  }
2898
- return (jsx(ReactFlowProvider, { initialNodes: nodes, initialEdges: edges, defaultNodes: defaultNodes, defaultEdges: defaultEdges, initialWidth: width, initialHeight: height, fitView: fitView, children: children }));
2873
+ return (jsx(ReactFlowProvider, { initialNodes: nodes, initialEdges: edges, defaultNodes: defaultNodes, defaultEdges: defaultEdges, initialWidth: width, initialHeight: height, fitView: fitView, nodeOrigin: nodeOrigin, children: children }));
2899
2874
  }
2900
2875
 
2901
2876
  const wrapperStyle = {
@@ -2905,25 +2880,25 @@ const wrapperStyle = {
2905
2880
  position: 'relative',
2906
2881
  zIndex: 0,
2907
2882
  };
2908
- function ReactFlow({ nodes, edges, defaultNodes, defaultEdges, className, nodeTypes, edgeTypes, onNodeClick, onEdgeClick, onInit, onMove, onMoveStart, onMoveEnd, onConnect, onConnectStart, onConnectEnd, onClickConnectStart, onClickConnectEnd, onNodeMouseEnter, onNodeMouseMove, onNodeMouseLeave, onNodeContextMenu, onNodeDoubleClick, onNodeDragStart, onNodeDrag, onNodeDragStop, onNodesDelete, onEdgesDelete, onDelete, onSelectionChange, onSelectionDragStart, onSelectionDrag, onSelectionDragStop, onSelectionContextMenu, onSelectionStart, onSelectionEnd, onBeforeDelete, connectionMode, connectionLineType = ConnectionLineType.Bezier, connectionLineStyle, connectionLineComponent, connectionLineContainerStyle, deleteKeyCode = 'Backspace', selectionKeyCode = 'Shift', selectionOnDrag = false, selectionMode = SelectionMode.Full, panActivationKeyCode = 'Space', multiSelectionKeyCode = isMacOs() ? 'Meta' : 'Control', zoomActivationKeyCode = isMacOs() ? 'Meta' : 'Control', snapToGrid, snapGrid, onlyRenderVisibleElements = false, selectNodesOnDrag, nodesDraggable, nodesConnectable, nodesFocusable, nodeOrigin = defaultNodeOrigin, edgesFocusable, edgesReconnectable, elementsSelectable = true, defaultViewport: defaultViewport$1 = defaultViewport, minZoom = 0.5, maxZoom = 2, translateExtent = infiniteExtent, preventScrolling = true, nodeExtent, defaultMarkerColor = '#b1b1b7', zoomOnScroll = true, zoomOnPinch = true, panOnScroll = false, panOnScrollSpeed = 0.5, panOnScrollMode = PanOnScrollMode.Free, zoomOnDoubleClick = true, panOnDrag = true, onPaneClick, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, onPaneScroll, onPaneContextMenu, children, onReconnect, onReconnectStart, onReconnectEnd, onEdgeContextMenu, onEdgeDoubleClick, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, reconnectRadius = 10, onNodesChange, onEdgesChange, noDragClassName = 'nodrag', noWheelClassName = 'nowheel', noPanClassName = 'nopan', fitView, fitViewOptions, connectOnClick, attributionPosition, proOptions, defaultEdgeOptions, elevateNodesOnSelect, elevateEdgesOnSelect, disableKeyboardA11y = false, autoPanOnConnect, autoPanOnNodeDrag, connectionRadius, isValidConnection, onError, style, id, nodeDragThreshold, viewport, onViewportChange, width, height, colorMode = 'light', debug, ...rest }, ref) {
2883
+ function ReactFlow({ nodes, edges, defaultNodes, defaultEdges, className, nodeTypes, edgeTypes, onNodeClick, onEdgeClick, onInit, onMove, onMoveStart, onMoveEnd, onConnect, onConnectStart, onConnectEnd, onClickConnectStart, onClickConnectEnd, onNodeMouseEnter, onNodeMouseMove, onNodeMouseLeave, onNodeContextMenu, onNodeDoubleClick, onNodeDragStart, onNodeDrag, onNodeDragStop, onNodesDelete, onEdgesDelete, onDelete, onSelectionChange, onSelectionDragStart, onSelectionDrag, onSelectionDragStop, onSelectionContextMenu, onSelectionStart, onSelectionEnd, onBeforeDelete, connectionMode, connectionLineType = ConnectionLineType.Bezier, connectionLineStyle, connectionLineComponent, connectionLineContainerStyle, deleteKeyCode = 'Backspace', selectionKeyCode = 'Shift', selectionOnDrag = false, selectionMode = SelectionMode.Full, panActivationKeyCode = 'Space', multiSelectionKeyCode = isMacOs() ? 'Meta' : 'Control', zoomActivationKeyCode = isMacOs() ? 'Meta' : 'Control', snapToGrid, snapGrid, onlyRenderVisibleElements = false, selectNodesOnDrag, nodesDraggable, nodesConnectable, nodesFocusable, nodeOrigin = defaultNodeOrigin, edgesFocusable, edgesReconnectable, elementsSelectable = true, defaultViewport: defaultViewport$1 = defaultViewport, minZoom = 0.5, maxZoom = 2, translateExtent = infiniteExtent, preventScrolling = true, nodeExtent, defaultMarkerColor = '#b1b1b7', zoomOnScroll = true, zoomOnPinch = true, panOnScroll = false, panOnScrollSpeed = 0.5, panOnScrollMode = PanOnScrollMode.Free, zoomOnDoubleClick = true, panOnDrag = true, onPaneClick, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, onPaneScroll, onPaneContextMenu, children, onReconnect, onReconnectStart, onReconnectEnd, onEdgeContextMenu, onEdgeDoubleClick, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, reconnectRadius = 10, onNodesChange, onEdgesChange, noDragClassName = 'nodrag', noWheelClassName = 'nowheel', noPanClassName = 'nopan', fitView, fitViewOptions, connectOnClick, attributionPosition, proOptions, defaultEdgeOptions, elevateNodesOnSelect, elevateEdgesOnSelect, disableKeyboardA11y = false, autoPanOnConnect, autoPanOnNodeDrag, autoPanSpeed, connectionRadius, isValidConnection, onError, style, id, nodeDragThreshold, viewport, onViewportChange, width, height, colorMode = 'light', debug, ...rest }, ref) {
2909
2884
  const rfId = id || '1';
2910
2885
  const colorModeClassName = useColorModeClass(colorMode);
2911
- return (jsx("div", { ...rest, style: { ...style, ...wrapperStyle }, ref: ref, className: cc(['react-flow', className, colorModeClassName]), "data-testid": "rf__wrapper", id: id, children: jsxs(Wrapper, { nodes: nodes, edges: edges, width: width, height: height, fitView: fitView, children: [jsx(GraphView, { onInit: onInit, onNodeClick: onNodeClick, onEdgeClick: onEdgeClick, onNodeMouseEnter: onNodeMouseEnter, onNodeMouseMove: onNodeMouseMove, onNodeMouseLeave: onNodeMouseLeave, onNodeContextMenu: onNodeContextMenu, onNodeDoubleClick: onNodeDoubleClick, nodeTypes: nodeTypes, edgeTypes: edgeTypes, connectionLineType: connectionLineType, connectionLineStyle: connectionLineStyle, connectionLineComponent: connectionLineComponent, connectionLineContainerStyle: connectionLineContainerStyle, selectionKeyCode: selectionKeyCode, selectionOnDrag: selectionOnDrag, selectionMode: selectionMode, deleteKeyCode: deleteKeyCode, multiSelectionKeyCode: multiSelectionKeyCode, panActivationKeyCode: panActivationKeyCode, zoomActivationKeyCode: zoomActivationKeyCode, onlyRenderVisibleElements: onlyRenderVisibleElements, defaultViewport: defaultViewport$1, translateExtent: translateExtent, minZoom: minZoom, maxZoom: maxZoom, preventScrolling: preventScrolling, zoomOnScroll: zoomOnScroll, zoomOnPinch: zoomOnPinch, zoomOnDoubleClick: zoomOnDoubleClick, panOnScroll: panOnScroll, panOnScrollSpeed: panOnScrollSpeed, panOnScrollMode: panOnScrollMode, panOnDrag: panOnDrag, onPaneClick: onPaneClick, onPaneMouseEnter: onPaneMouseEnter, onPaneMouseMove: onPaneMouseMove, onPaneMouseLeave: onPaneMouseLeave, onPaneScroll: onPaneScroll, onPaneContextMenu: onPaneContextMenu, onSelectionContextMenu: onSelectionContextMenu, onSelectionStart: onSelectionStart, onSelectionEnd: onSelectionEnd, onReconnect: onReconnect, onReconnectStart: onReconnectStart, onReconnectEnd: onReconnectEnd, onEdgeContextMenu: onEdgeContextMenu, onEdgeDoubleClick: onEdgeDoubleClick, onEdgeMouseEnter: onEdgeMouseEnter, onEdgeMouseMove: onEdgeMouseMove, onEdgeMouseLeave: onEdgeMouseLeave, reconnectRadius: reconnectRadius, defaultMarkerColor: defaultMarkerColor, noDragClassName: noDragClassName, noWheelClassName: noWheelClassName, noPanClassName: noPanClassName, rfId: rfId, disableKeyboardA11y: disableKeyboardA11y, nodeOrigin: nodeOrigin, nodeExtent: nodeExtent, viewport: viewport, onViewportChange: onViewportChange }), jsx(StoreUpdater, { nodes: nodes, edges: edges, defaultNodes: defaultNodes, defaultEdges: defaultEdges, onConnect: onConnect, onConnectStart: onConnectStart, onConnectEnd: onConnectEnd, onClickConnectStart: onClickConnectStart, onClickConnectEnd: onClickConnectEnd, nodesDraggable: nodesDraggable, nodesConnectable: nodesConnectable, nodesFocusable: nodesFocusable, edgesFocusable: edgesFocusable, edgesReconnectable: edgesReconnectable, elementsSelectable: elementsSelectable, elevateNodesOnSelect: elevateNodesOnSelect, elevateEdgesOnSelect: elevateEdgesOnSelect, minZoom: minZoom, maxZoom: maxZoom, nodeExtent: nodeExtent, onNodesChange: onNodesChange, onEdgesChange: onEdgesChange, snapToGrid: snapToGrid, snapGrid: snapGrid, connectionMode: connectionMode, translateExtent: translateExtent, connectOnClick: connectOnClick, defaultEdgeOptions: defaultEdgeOptions, fitView: fitView, fitViewOptions: fitViewOptions, onNodesDelete: onNodesDelete, onEdgesDelete: onEdgesDelete, onDelete: onDelete, onNodeDragStart: onNodeDragStart, onNodeDrag: onNodeDrag, onNodeDragStop: onNodeDragStop, onSelectionDrag: onSelectionDrag, onSelectionDragStart: onSelectionDragStart, onSelectionDragStop: onSelectionDragStop, onMove: onMove, onMoveStart: onMoveStart, onMoveEnd: onMoveEnd, noPanClassName: noPanClassName, nodeOrigin: nodeOrigin, rfId: rfId, autoPanOnConnect: autoPanOnConnect, autoPanOnNodeDrag: autoPanOnNodeDrag, onError: onError, connectionRadius: connectionRadius, isValidConnection: isValidConnection, selectNodesOnDrag: selectNodesOnDrag, nodeDragThreshold: nodeDragThreshold, onBeforeDelete: onBeforeDelete, debug: debug }), jsx(SelectionListener, { onSelectionChange: onSelectionChange }), children, jsx(Attribution, { proOptions: proOptions, position: attributionPosition }), jsx(A11yDescriptions, { rfId: rfId, disableKeyboardA11y: disableKeyboardA11y })] }) }));
2886
+ return (jsx("div", { ...rest, style: { ...style, ...wrapperStyle }, ref: ref, className: cc(['react-flow', className, colorModeClassName]), "data-testid": "rf__wrapper", id: id, children: jsxs(Wrapper, { nodes: nodes, edges: edges, width: width, height: height, fitView: fitView, nodeOrigin: nodeOrigin, children: [jsx(GraphView, { onInit: onInit, onNodeClick: onNodeClick, onEdgeClick: onEdgeClick, onNodeMouseEnter: onNodeMouseEnter, onNodeMouseMove: onNodeMouseMove, onNodeMouseLeave: onNodeMouseLeave, onNodeContextMenu: onNodeContextMenu, onNodeDoubleClick: onNodeDoubleClick, nodeTypes: nodeTypes, edgeTypes: edgeTypes, connectionLineType: connectionLineType, connectionLineStyle: connectionLineStyle, connectionLineComponent: connectionLineComponent, connectionLineContainerStyle: connectionLineContainerStyle, selectionKeyCode: selectionKeyCode, selectionOnDrag: selectionOnDrag, selectionMode: selectionMode, deleteKeyCode: deleteKeyCode, multiSelectionKeyCode: multiSelectionKeyCode, panActivationKeyCode: panActivationKeyCode, zoomActivationKeyCode: zoomActivationKeyCode, onlyRenderVisibleElements: onlyRenderVisibleElements, defaultViewport: defaultViewport$1, translateExtent: translateExtent, minZoom: minZoom, maxZoom: maxZoom, preventScrolling: preventScrolling, zoomOnScroll: zoomOnScroll, zoomOnPinch: zoomOnPinch, zoomOnDoubleClick: zoomOnDoubleClick, panOnScroll: panOnScroll, panOnScrollSpeed: panOnScrollSpeed, panOnScrollMode: panOnScrollMode, panOnDrag: panOnDrag, onPaneClick: onPaneClick, onPaneMouseEnter: onPaneMouseEnter, onPaneMouseMove: onPaneMouseMove, onPaneMouseLeave: onPaneMouseLeave, onPaneScroll: onPaneScroll, onPaneContextMenu: onPaneContextMenu, onSelectionContextMenu: onSelectionContextMenu, onSelectionStart: onSelectionStart, onSelectionEnd: onSelectionEnd, onReconnect: onReconnect, onReconnectStart: onReconnectStart, onReconnectEnd: onReconnectEnd, onEdgeContextMenu: onEdgeContextMenu, onEdgeDoubleClick: onEdgeDoubleClick, onEdgeMouseEnter: onEdgeMouseEnter, onEdgeMouseMove: onEdgeMouseMove, onEdgeMouseLeave: onEdgeMouseLeave, reconnectRadius: reconnectRadius, defaultMarkerColor: defaultMarkerColor, noDragClassName: noDragClassName, noWheelClassName: noWheelClassName, noPanClassName: noPanClassName, rfId: rfId, disableKeyboardA11y: disableKeyboardA11y, nodeExtent: nodeExtent, viewport: viewport, onViewportChange: onViewportChange }), jsx(StoreUpdater, { nodes: nodes, edges: edges, defaultNodes: defaultNodes, defaultEdges: defaultEdges, onConnect: onConnect, onConnectStart: onConnectStart, onConnectEnd: onConnectEnd, onClickConnectStart: onClickConnectStart, onClickConnectEnd: onClickConnectEnd, nodesDraggable: nodesDraggable, nodesConnectable: nodesConnectable, nodesFocusable: nodesFocusable, edgesFocusable: edgesFocusable, edgesReconnectable: edgesReconnectable, elementsSelectable: elementsSelectable, elevateNodesOnSelect: elevateNodesOnSelect, elevateEdgesOnSelect: elevateEdgesOnSelect, minZoom: minZoom, maxZoom: maxZoom, nodeExtent: nodeExtent, onNodesChange: onNodesChange, onEdgesChange: onEdgesChange, snapToGrid: snapToGrid, snapGrid: snapGrid, connectionMode: connectionMode, translateExtent: translateExtent, connectOnClick: connectOnClick, defaultEdgeOptions: defaultEdgeOptions, fitView: fitView, fitViewOptions: fitViewOptions, onNodesDelete: onNodesDelete, onEdgesDelete: onEdgesDelete, onDelete: onDelete, onNodeDragStart: onNodeDragStart, onNodeDrag: onNodeDrag, onNodeDragStop: onNodeDragStop, onSelectionDrag: onSelectionDrag, onSelectionDragStart: onSelectionDragStart, onSelectionDragStop: onSelectionDragStop, onMove: onMove, onMoveStart: onMoveStart, onMoveEnd: onMoveEnd, noPanClassName: noPanClassName, nodeOrigin: nodeOrigin, rfId: rfId, autoPanOnConnect: autoPanOnConnect, autoPanOnNodeDrag: autoPanOnNodeDrag, autoPanSpeed: autoPanSpeed, onError: onError, connectionRadius: connectionRadius, isValidConnection: isValidConnection, selectNodesOnDrag: selectNodesOnDrag, nodeDragThreshold: nodeDragThreshold, onBeforeDelete: onBeforeDelete, debug: debug }), jsx(SelectionListener, { onSelectionChange: onSelectionChange }), children, jsx(Attribution, { proOptions: proOptions, position: attributionPosition }), jsx(A11yDescriptions, { rfId: rfId, disableKeyboardA11y: disableKeyboardA11y })] }) }));
2912
2887
  }
2913
2888
  var index = fixedForwardRef(ReactFlow);
2914
2889
 
2915
- const selector$8 = (s) => s.domNode?.querySelector('.react-flow__edgelabel-renderer');
2890
+ const selector$6 = (s) => s.domNode?.querySelector('.react-flow__edgelabel-renderer');
2916
2891
  function EdgeLabelRenderer({ children }) {
2917
- const edgeLabelRenderer = useStore(selector$8);
2892
+ const edgeLabelRenderer = useStore(selector$6);
2918
2893
  if (!edgeLabelRenderer) {
2919
2894
  return null;
2920
2895
  }
2921
2896
  return createPortal(children, edgeLabelRenderer);
2922
2897
  }
2923
2898
 
2924
- const selector$7 = (s) => s.domNode?.querySelector('.react-flow__viewport-portal');
2899
+ const selector$5 = (s) => s.domNode?.querySelector('.react-flow__viewport-portal');
2925
2900
  function ViewportPortal({ children }) {
2926
- const viewPortalDiv = useStore(selector$7);
2901
+ const viewPortalDiv = useStore(selector$5);
2927
2902
  if (!viewPortalDiv) {
2928
2903
  return null;
2929
2904
  }
@@ -3056,7 +3031,7 @@ function useOnSelectionChange({ onChange }) {
3056
3031
  }, [onChange]);
3057
3032
  }
3058
3033
 
3059
- const selector$6 = (options) => (s) => {
3034
+ const selector$4 = (options) => (s) => {
3060
3035
  if (s.nodeLookup.size === 0) {
3061
3036
  return false;
3062
3037
  }
@@ -3080,7 +3055,7 @@ const defaultOptions = {
3080
3055
  * @returns boolean indicating whether all nodes are initialized
3081
3056
  */
3082
3057
  function useNodesInitialized(options = defaultOptions) {
3083
- const initialized = useStore(selector$6(options));
3058
+ const initialized = useStore(selector$4(options));
3084
3059
  return initialized;
3085
3060
  }
3086
3061
 
@@ -3133,23 +3108,6 @@ function useNodesData(nodeIds) {
3133
3108
  return nodesData;
3134
3109
  }
3135
3110
 
3136
- const selector$5 = (s) => ({
3137
- startHandle: s.connectionStartHandle,
3138
- endHandle: s.connectionEndHandle,
3139
- status: s.connectionStatus,
3140
- position: s.connectionStartHandle ? s.connectionPosition : null,
3141
- });
3142
- /**
3143
- * Hook for accessing the ongoing connection.
3144
- *
3145
- * @public
3146
- * @returns ongoing connection
3147
- */
3148
- function useConnection() {
3149
- const ongoingConnection = useStore(selector$5, shallow);
3150
- return ongoingConnection;
3151
- }
3152
-
3153
3111
  /**
3154
3112
  * Hook for getting an internal node by id
3155
3113
  *
@@ -3181,14 +3139,14 @@ const defaultSize = {
3181
3139
  [BackgroundVariant.Lines]: 1,
3182
3140
  [BackgroundVariant.Cross]: 6,
3183
3141
  };
3184
- const selector$4 = (s) => ({ transform: s.transform, patternId: `pattern-${s.rfId}` });
3142
+ const selector$3 = (s) => ({ transform: s.transform, patternId: `pattern-${s.rfId}` });
3185
3143
  function BackgroundComponent({ id, variant = BackgroundVariant.Dots,
3186
3144
  // only used for dots and cross
3187
3145
  gap = 20,
3188
3146
  // only used for lines and cross
3189
3147
  size, lineWidth = 1, offset = 2, color, bgColor, style, className, patternClassName, }) {
3190
3148
  const ref = useRef(null);
3191
- const { transform, patternId } = useStore(selector$4, shallow);
3149
+ const { transform, patternId } = useStore(selector$3, shallow);
3192
3150
  const patternSize = size || defaultSize[variant];
3193
3151
  const isDots = variant === BackgroundVariant.Dots;
3194
3152
  const isCross = variant === BackgroundVariant.Cross;
@@ -3234,14 +3192,14 @@ function ControlButton({ children, className, ...rest }) {
3234
3192
  return (jsx("button", { type: "button", className: cc(['react-flow__controls-button', className]), ...rest, children: children }));
3235
3193
  }
3236
3194
 
3237
- const selector$3 = (s) => ({
3195
+ const selector$2 = (s) => ({
3238
3196
  isInteractive: s.nodesDraggable || s.nodesConnectable || s.elementsSelectable,
3239
3197
  minZoomReached: s.transform[2] <= s.minZoom,
3240
3198
  maxZoomReached: s.transform[2] >= s.maxZoom,
3241
3199
  });
3242
3200
  function ControlsComponent({ style, showZoom = true, showFitView = true, showInteractive = true, fitViewOptions, onZoomIn, onZoomOut, onFitView, onInteractiveChange, className, children, position = 'bottom-left', orientation = 'vertical', 'aria-label': ariaLabel = 'React Flow controls', }) {
3243
3201
  const store = useStoreApi();
3244
- const { isInteractive, minZoomReached, maxZoomReached } = useStore(selector$3, shallow);
3202
+ const { isInteractive, minZoomReached, maxZoomReached } = useStore(selector$2, shallow);
3245
3203
  const { zoomIn, zoomOut, fitView } = useReactFlow();
3246
3204
  const onZoomInHandler = () => {
3247
3205
  zoomIn();
@@ -3280,7 +3238,6 @@ function MiniMapNodeComponent({ id, x, y, width, height, style, color, strokeCol
3280
3238
  }
3281
3239
  const MiniMapNode = memo(MiniMapNodeComponent);
3282
3240
 
3283
- const selector$2 = (s) => s.nodeOrigin;
3284
3241
  const selectorNodeIds = (s) => s.nodes.map((node) => node.id);
3285
3242
  const getAttrFunction = (func) => func instanceof Function ? func : () => func;
3286
3243
  function MiniMapNodes({ nodeStrokeColor, nodeColor, nodeClassName = '', nodeBorderRadius = 5, nodeStrokeWidth,
@@ -3288,7 +3245,6 @@ function MiniMapNodes({ nodeStrokeColor, nodeColor, nodeClassName = '', nodeBord
3288
3245
  // a component properly.
3289
3246
  nodeComponent: NodeComponent = MiniMapNode, onClick, }) {
3290
3247
  const nodeIds = useStore(selectorNodeIds, shallow);
3291
- const nodeOrigin = useStore(selector$2);
3292
3248
  const nodeColorFunc = getAttrFunction(nodeColor);
3293
3249
  const nodeStrokeColorFunc = getAttrFunction(nodeStrokeColor);
3294
3250
  const nodeClassNameFunc = getAttrFunction(nodeClassName);
@@ -3299,12 +3255,12 @@ nodeComponent: NodeComponent = MiniMapNode, onClick, }) {
3299
3255
  // minimize the cost of updates when individual nodes change.
3300
3256
  //
3301
3257
  // For more details, see a similar commit in `NodeRenderer/index.tsx`.
3302
- jsx(NodeComponentWrapper, { id: nodeId, nodeOrigin: nodeOrigin, nodeColorFunc: nodeColorFunc, nodeStrokeColorFunc: nodeStrokeColorFunc, nodeClassNameFunc: nodeClassNameFunc, nodeBorderRadius: nodeBorderRadius, nodeStrokeWidth: nodeStrokeWidth, NodeComponent: NodeComponent, onClick: onClick, shapeRendering: shapeRendering }, nodeId))) }));
3258
+ jsx(NodeComponentWrapper, { id: nodeId, nodeColorFunc: nodeColorFunc, nodeStrokeColorFunc: nodeStrokeColorFunc, nodeClassNameFunc: nodeClassNameFunc, nodeBorderRadius: nodeBorderRadius, nodeStrokeWidth: nodeStrokeWidth, NodeComponent: NodeComponent, onClick: onClick, shapeRendering: shapeRendering }, nodeId))) }));
3303
3259
  }
3304
- function NodeComponentWrapperInner({ id, nodeOrigin, nodeColorFunc, nodeStrokeColorFunc, nodeClassNameFunc, nodeBorderRadius, nodeStrokeWidth, shapeRendering, NodeComponent, onClick, }) {
3260
+ function NodeComponentWrapperInner({ id, nodeColorFunc, nodeStrokeColorFunc, nodeClassNameFunc, nodeBorderRadius, nodeStrokeWidth, shapeRendering, NodeComponent, onClick, }) {
3305
3261
  const { node, x, y } = useStore((s) => {
3306
3262
  const node = s.nodeLookup.get(id);
3307
- const { x, y } = getNodePositionWithOrigin(node, nodeOrigin).positionAbsolute;
3263
+ const { x, y } = node.internals.positionAbsolute;
3308
3264
  return {
3309
3265
  node,
3310
3266
  x,
@@ -3331,11 +3287,8 @@ const selector$1 = (s) => {
3331
3287
  };
3332
3288
  return {
3333
3289
  viewBB,
3334
- boundingRect: s.nodeLookup.size > 0
3335
- ? getBoundsOfRects(getInternalNodesBounds(s.nodeLookup, { nodeOrigin: s.nodeOrigin }), viewBB)
3336
- : viewBB,
3290
+ boundingRect: s.nodeLookup.size > 0 ? getBoundsOfRects(getInternalNodesBounds(s.nodeLookup), viewBB) : viewBB,
3337
3291
  rfId: s.rfId,
3338
- nodeOrigin: s.nodeOrigin,
3339
3292
  panZoom: s.panZoom,
3340
3293
  translateExtent: s.translateExtent,
3341
3294
  flowWidth: s.width,
@@ -3449,23 +3402,27 @@ function ResizeControl({ nodeId, position, variant = ResizeControlVariant.Handle
3449
3402
  const nextPosition = { x: change.x, y: change.y };
3450
3403
  const node = nodeLookup.get(id);
3451
3404
  if (node && node.expandParent && node.parentId) {
3405
+ const origin = node.origin ?? nodeOrigin;
3406
+ const width = change.width ?? node.measured.width;
3407
+ const height = change.height ?? node.measured.height;
3452
3408
  const child = {
3453
3409
  id: node.id,
3454
3410
  parentId: node.parentId,
3455
3411
  rect: {
3456
- width: change.width ?? node.measured.width,
3457
- height: change.height ?? node.measured.height,
3412
+ width,
3413
+ height,
3458
3414
  ...evaluateAbsolutePosition({
3459
3415
  x: change.x ?? node.position.x,
3460
3416
  y: change.y ?? node.position.y,
3461
- }, node.parentId, nodeLookup, node.origin ?? nodeOrigin),
3417
+ }, { width, height }, node.parentId, nodeLookup, origin),
3462
3418
  },
3463
3419
  };
3464
3420
  const parentExpandChanges = handleExpandParent([child], nodeLookup, parentLookup, nodeOrigin);
3465
3421
  changes.push(...parentExpandChanges);
3466
- // when the parent was expanded by the child node, its position will be clamped at 0,0
3467
- nextPosition.x = change.x ? Math.max(0, change.x) : undefined;
3468
- nextPosition.y = change.y ? Math.max(0, change.y) : undefined;
3422
+ // when the parent was expanded by the child node, its position will be clamped at
3423
+ // 0,0 when node origin is 0,0 and to width, height if it's 1,1
3424
+ nextPosition.x = change.x ? Math.max(origin[0] * width, change.x) : undefined;
3425
+ nextPosition.y = change.y ? Math.max(origin[1] * height, change.y) : undefined;
3469
3426
  }
3470
3427
  if (nextPosition.x !== undefined && nextPosition.y !== undefined) {
3471
3428
  const positionChange = {
@@ -3566,48 +3523,54 @@ const nodeEqualityFn = (a, b) => a?.internals.positionAbsolute.x !== b?.internal
3566
3523
  a?.selected !== b?.selected ||
3567
3524
  a?.internals.z !== b?.internals.z;
3568
3525
  const nodesEqualityFn = (a, b) => {
3569
- if (a.length !== b.length) {
3526
+ if (a.size !== b.size) {
3570
3527
  return false;
3571
3528
  }
3572
- return !a.some((node, i) => nodeEqualityFn(node, b[i]));
3529
+ for (const [key, node] of a) {
3530
+ if (nodeEqualityFn(node, b.get(key))) {
3531
+ return false;
3532
+ }
3533
+ }
3534
+ return true;
3573
3535
  };
3574
3536
  const storeSelector = (state) => ({
3575
- viewport: {
3576
- x: state.transform[0],
3577
- y: state.transform[1],
3578
- zoom: state.transform[2],
3579
- },
3580
- nodeOrigin: state.nodeOrigin,
3537
+ x: state.transform[0],
3538
+ y: state.transform[1],
3539
+ zoom: state.transform[2],
3581
3540
  selectedNodesCount: state.nodes.filter((node) => node.selected).length,
3582
3541
  });
3583
3542
  function NodeToolbar({ nodeId, children, className, style, isVisible, position = Position.Top, offset = 10, align = 'center', ...rest }) {
3584
3543
  const contextNodeId = useNodeId();
3585
3544
  const nodesSelector = useCallback((state) => {
3586
3545
  const nodeIds = Array.isArray(nodeId) ? nodeId : [nodeId || contextNodeId || ''];
3587
- return nodeIds.reduce((acc, id) => {
3546
+ const internalNodes = nodeIds.reduce((res, id) => {
3588
3547
  const node = state.nodeLookup.get(id);
3589
3548
  if (node) {
3590
- acc.push(node);
3549
+ res.set(node.id, node);
3591
3550
  }
3592
- return acc;
3593
- }, []);
3551
+ return res;
3552
+ }, new Map());
3553
+ return internalNodes;
3594
3554
  }, [nodeId, contextNodeId]);
3595
3555
  const nodes = useStore(nodesSelector, nodesEqualityFn);
3596
- const { viewport, nodeOrigin, selectedNodesCount } = useStore(storeSelector, shallow);
3556
+ const { x, y, zoom, selectedNodesCount } = useStore(storeSelector, shallow);
3597
3557
  // if isVisible is not set, we show the toolbar only if its node is selected and no other node is selected
3598
- const isActive = typeof isVisible === 'boolean' ? isVisible : nodes.length === 1 && nodes[0].selected && selectedNodesCount === 1;
3599
- if (!isActive || !nodes.length) {
3558
+ const isActive = typeof isVisible === 'boolean'
3559
+ ? isVisible
3560
+ : nodes.size === 1 && nodes.values().next().value.selected && selectedNodesCount === 1;
3561
+ if (!isActive || !nodes.size) {
3600
3562
  return null;
3601
3563
  }
3602
- const nodeRect = getNodesBounds(nodes, { nodeOrigin });
3603
- const zIndex = Math.max(...nodes.map((node) => node.internals.z + 1));
3564
+ const nodeRect = getInternalNodesBounds(nodes);
3565
+ const nodesArray = Array.from(nodes.values());
3566
+ const zIndex = Math.max(...nodesArray.map((node) => node.internals.z + 1));
3604
3567
  const wrapperStyle = {
3605
3568
  position: 'absolute',
3606
- transform: getNodeToolbarTransform(nodeRect, viewport, position, offset, align),
3569
+ transform: getNodeToolbarTransform(nodeRect, { x, y, zoom }, position, offset, align),
3607
3570
  zIndex,
3608
3571
  ...style,
3609
3572
  };
3610
- return (jsx(NodeToolbarPortal, { children: jsx("div", { style: wrapperStyle, className: cc(['react-flow__node-toolbar', className]), ...rest, "data-id": nodes.reduce((acc, node) => `${acc}${node.id} `, '').trim(), children: children }) }));
3573
+ return (jsx(NodeToolbarPortal, { children: jsx("div", { style: wrapperStyle, className: cc(['react-flow__node-toolbar', className]), ...rest, "data-id": nodesArray.reduce((acc, node) => `${acc}${node.id} `, '').trim(), children: children }) }));
3611
3574
  }
3612
3575
 
3613
3576
  export { Background, BackgroundVariant, BaseEdge, BezierEdge, ControlButton, Controls, EdgeLabelRenderer, EdgeText, Handle, MiniMap, NodeResizeControl, NodeResizer, NodeToolbar, Panel, index as ReactFlow, ReactFlowProvider, SimpleBezierEdge, SmoothStepEdge, StepEdge, StraightEdge, ViewportPortal, applyEdgeChanges, applyNodeChanges, getSimpleBezierPath, isEdge, isNode, useConnection, useEdges, useEdgesState, useHandleConnections, useInternalNode, useKeyPress, useNodeId, useNodes, useNodesData, useNodesInitialized, useNodesState, useOnSelectionChange, useOnViewportChange, useReactFlow, useStore, useStoreApi, useUpdateNodeInternals, useViewport };