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

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 (82) 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/container/FlowRenderer/index.d.ts +1 -1
  13. package/dist/esm/container/FlowRenderer/index.d.ts.map +1 -1
  14. package/dist/esm/container/GraphView/index.d.ts +2 -2
  15. package/dist/esm/container/GraphView/index.d.ts.map +1 -1
  16. package/dist/esm/container/NodeRenderer/index.d.ts +1 -1
  17. package/dist/esm/container/NodeRenderer/index.d.ts.map +1 -1
  18. package/dist/esm/container/Pane/index.d.ts.map +1 -1
  19. package/dist/esm/container/ReactFlow/Wrapper.d.ts +3 -1
  20. package/dist/esm/container/ReactFlow/Wrapper.d.ts.map +1 -1
  21. package/dist/esm/container/ReactFlow/index.d.ts.map +1 -1
  22. package/dist/esm/contexts/RFStoreContext.d.ts +5 -0
  23. package/dist/esm/contexts/RFStoreContext.d.ts.map +1 -0
  24. package/dist/esm/hooks/useConnection.d.ts +4 -15
  25. package/dist/esm/hooks/useConnection.d.ts.map +1 -1
  26. package/dist/esm/hooks/useViewportHelper.d.ts.map +1 -1
  27. package/dist/esm/index.d.ts +1 -1
  28. package/dist/esm/index.d.ts.map +1 -1
  29. package/dist/esm/index.js +197 -237
  30. package/dist/esm/index.mjs +197 -237
  31. package/dist/esm/store/index.d.ts +3 -1
  32. package/dist/esm/store/index.d.ts.map +1 -1
  33. package/dist/esm/store/initialState.d.ts +3 -1
  34. package/dist/esm/store/initialState.d.ts.map +1 -1
  35. package/dist/esm/store/utils.d.ts +12 -0
  36. package/dist/esm/store/utils.d.ts.map +1 -0
  37. package/dist/esm/types/changes.d.ts +51 -0
  38. package/dist/esm/types/changes.d.ts.map +1 -0
  39. package/dist/esm/types/edges.d.ts +6 -4
  40. package/dist/esm/types/edges.d.ts.map +1 -1
  41. package/dist/esm/types/nodes.d.ts +1 -2
  42. package/dist/esm/types/nodes.d.ts.map +1 -1
  43. package/dist/esm/types/store.d.ts +4 -7
  44. package/dist/esm/types/store.d.ts.map +1 -1
  45. package/dist/umd/additional-components/MiniMap/MiniMap.d.ts.map +1 -1
  46. package/dist/umd/additional-components/MiniMap/MiniMapNodes.d.ts.map +1 -1
  47. package/dist/umd/additional-components/NodeResizer/NodeResizeControl.d.ts.map +1 -1
  48. package/dist/umd/additional-components/NodeToolbar/NodeToolbar.d.ts.map +1 -1
  49. package/dist/umd/components/ConnectionLine/index.d.ts.map +1 -1
  50. package/dist/umd/components/Handle/index.d.ts.map +1 -1
  51. package/dist/umd/components/NodeWrapper/index.d.ts +1 -1
  52. package/dist/umd/components/NodeWrapper/index.d.ts.map +1 -1
  53. package/dist/umd/components/NodesSelection/index.d.ts.map +1 -1
  54. package/dist/umd/components/ReactFlowProvider/index.d.ts +3 -1
  55. package/dist/umd/components/ReactFlowProvider/index.d.ts.map +1 -1
  56. package/dist/umd/container/FlowRenderer/index.d.ts +1 -1
  57. package/dist/umd/container/FlowRenderer/index.d.ts.map +1 -1
  58. package/dist/umd/container/GraphView/index.d.ts +2 -2
  59. package/dist/umd/container/GraphView/index.d.ts.map +1 -1
  60. package/dist/umd/container/NodeRenderer/index.d.ts +1 -1
  61. package/dist/umd/container/NodeRenderer/index.d.ts.map +1 -1
  62. package/dist/umd/container/Pane/index.d.ts.map +1 -1
  63. package/dist/umd/container/ReactFlow/Wrapper.d.ts +3 -1
  64. package/dist/umd/container/ReactFlow/Wrapper.d.ts.map +1 -1
  65. package/dist/umd/container/ReactFlow/index.d.ts.map +1 -1
  66. package/dist/umd/hooks/useConnection.d.ts +4 -15
  67. package/dist/umd/hooks/useConnection.d.ts.map +1 -1
  68. package/dist/umd/hooks/useViewportHelper.d.ts.map +1 -1
  69. package/dist/umd/index.d.ts +1 -1
  70. package/dist/umd/index.d.ts.map +1 -1
  71. package/dist/umd/index.js +2 -2
  72. package/dist/umd/store/index.d.ts +3 -1
  73. package/dist/umd/store/index.d.ts.map +1 -1
  74. package/dist/umd/store/initialState.d.ts +3 -1
  75. package/dist/umd/store/initialState.d.ts.map +1 -1
  76. package/dist/umd/types/edges.d.ts +6 -4
  77. package/dist/umd/types/edges.d.ts.map +1 -1
  78. package/dist/umd/types/nodes.d.ts +1 -2
  79. package/dist/umd/types/nodes.d.ts.map +1 -1
  80. package/dist/umd/types/store.d.ts +4 -7
  81. package/dist/umd/types/store.d.ts.map +1 -1
  82. package/package.json +3 -3
@@ -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);
@@ -186,7 +186,7 @@ const reactFlowFieldsToTrack = [
186
186
  ];
187
187
  // rfId doesn't exist in ReactFlowProps, but it's one of the fields we want to update
188
188
  const fieldsToTrack = [...reactFlowFieldsToTrack, 'rfId'];
189
- const selector$n = (s) => ({
189
+ const selector$m = (s) => ({
190
190
  setNodes: s.setNodes,
191
191
  setEdges: s.setEdges,
192
192
  setMinZoom: s.setMinZoom,
@@ -209,7 +209,7 @@ const initPrevValues = {
209
209
  rfId: '1',
210
210
  };
211
211
  function StoreUpdater(props) {
212
- const { setNodes, setEdges, setMinZoom, setMaxZoom, setTranslateExtent, setNodeExtent, reset, setDefaultNodesAndEdges, } = useStore(selector$n, shallow);
212
+ const { setNodes, setEdges, setMinZoom, setMaxZoom, setTranslateExtent, setNodeExtent, reset, setDefaultNodesAndEdges, } = useStore(selector$m, shallow);
213
213
  const store = useStoreApi();
214
214
  useEffect(() => {
215
215
  setDefaultNodesAndEdges(props.defaultNodes, props.defaultEdges);
@@ -419,18 +419,18 @@ const useViewportHelper = () => {
419
419
  return { x, y, zoom };
420
420
  },
421
421
  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;
422
+ const { nodeLookup, width, height, minZoom, maxZoom, panZoom } = store.getState();
423
+ if (!panZoom) {
424
+ return false;
425
+ }
426
+ return fitView({
427
+ nodeLookup,
428
+ width,
429
+ height,
430
+ minZoom,
431
+ maxZoom,
432
+ panZoom,
433
+ }, options);
434
434
  },
435
435
  setCenter: (x, y, options) => {
436
436
  const { width, height, maxZoom, panZoom } = store.getState();
@@ -800,7 +800,7 @@ function useBatchContext() {
800
800
  return batchContext;
801
801
  }
802
802
 
803
- const selector$m = (s) => !!s.panZoom;
803
+ const selector$l = (s) => !!s.panZoom;
804
804
  /**
805
805
  * Hook for accessing the ReactFlow instance.
806
806
  *
@@ -811,7 +811,7 @@ function useReactFlow() {
811
811
  const viewportHelper = useViewportHelper();
812
812
  const store = useStoreApi();
813
813
  const batchContext = useBatchContext();
814
- const viewportInitialized = useStore(selector$m);
814
+ const viewportInitialized = useStore(selector$l);
815
815
  const generalHelper = useMemo(() => {
816
816
  const getInternalNode = (id) => store.getState().nodeLookup.get(id);
817
817
  const setNodes = (payload) => {
@@ -824,7 +824,7 @@ function useReactFlow() {
824
824
  const { nodeLookup, nodeOrigin } = store.getState();
825
825
  const nodeToUse = isNode(node) ? node : nodeLookup.get(node.id);
826
826
  const position = nodeToUse.parentId
827
- ? evaluateAbsolutePosition(nodeToUse.position, nodeToUse.parentId, nodeLookup, nodeOrigin)
827
+ ? evaluateAbsolutePosition(nodeToUse.position, nodeToUse.measured, nodeToUse.parentId, nodeLookup, nodeOrigin)
828
828
  : nodeToUse.position;
829
829
  const nodeWithPosition = {
830
830
  id: nodeToUse.id,
@@ -1030,14 +1030,14 @@ const containerStyle = {
1030
1030
  left: 0,
1031
1031
  };
1032
1032
 
1033
- const selector$l = (s) => ({
1033
+ const selector$k = (s) => ({
1034
1034
  userSelectionActive: s.userSelectionActive,
1035
1035
  lib: s.lib,
1036
1036
  });
1037
1037
  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
1038
  const store = useStoreApi();
1039
1039
  const zoomPane = useRef(null);
1040
- const { userSelectionActive, lib } = useStore(selector$l, shallow);
1040
+ const { userSelectionActive, lib } = useStore(selector$k, shallow);
1041
1041
  const zoomActivationKeyPressed = useKeyPress(zoomActivationKeyCode);
1042
1042
  const panZoom = useRef();
1043
1043
  useResizeHandler(zoomPane);
@@ -1119,12 +1119,12 @@ function ZoomPane({ onPaneContextMenu, zoomOnScroll = true, zoomOnPinch = true,
1119
1119
  return (jsx("div", { className: "react-flow__renderer", ref: zoomPane, style: containerStyle, children: children }));
1120
1120
  }
1121
1121
 
1122
- const selector$k = (s) => ({
1122
+ const selector$j = (s) => ({
1123
1123
  userSelectionActive: s.userSelectionActive,
1124
1124
  userSelectionRect: s.userSelectionRect,
1125
1125
  });
1126
1126
  function UserSelection() {
1127
- const { userSelectionActive, userSelectionRect } = useStore(selector$k, shallow);
1127
+ const { userSelectionActive, userSelectionRect } = useStore(selector$j, shallow);
1128
1128
  const isActive = userSelectionActive && userSelectionRect;
1129
1129
  if (!isActive) {
1130
1130
  return null;
@@ -1144,7 +1144,7 @@ const wrapHandler = (handler, containerRef) => {
1144
1144
  handler?.(event);
1145
1145
  };
1146
1146
  };
1147
- const selector$j = (s) => ({
1147
+ const selector$i = (s) => ({
1148
1148
  userSelectionActive: s.userSelectionActive,
1149
1149
  elementsSelectable: s.elementsSelectable,
1150
1150
  dragging: s.paneDragging,
@@ -1156,7 +1156,7 @@ function Pane({ isSelecting, selectionKeyPressed, selectionMode = SelectionMode.
1156
1156
  const prevSelectedEdgesCount = useRef(0);
1157
1157
  const containerBounds = useRef();
1158
1158
  const edgeIdLookup = useRef(new Map());
1159
- const { userSelectionActive, elementsSelectable, dragging } = useStore(selector$j, shallow);
1159
+ const { userSelectionActive, elementsSelectable, dragging } = useStore(selector$i, shallow);
1160
1160
  const hasActiveSelection = elementsSelectable && (isSelecting || userSelectionActive);
1161
1161
  // Used to prevent click events when the user lets go of the selectionKey during a selection
1162
1162
  const selectionInProgress = useRef(false);
@@ -1214,7 +1214,7 @@ function Pane({ isSelecting, selectionKeyPressed, selectionMode = SelectionMode.
1214
1214
  onSelectionStart?.(event);
1215
1215
  };
1216
1216
  const onPointerMove = (event) => {
1217
- const { userSelectionRect, edgeLookup, transform, nodeOrigin, nodeLookup, triggerNodeChanges, triggerEdgeChanges } = store.getState();
1217
+ const { userSelectionRect, edgeLookup, transform, nodeLookup, triggerNodeChanges, triggerEdgeChanges } = store.getState();
1218
1218
  if (!containerBounds.current || !userSelectionRect) {
1219
1219
  return;
1220
1220
  }
@@ -1229,7 +1229,7 @@ function Pane({ isSelecting, selectionKeyPressed, selectionMode = SelectionMode.
1229
1229
  width: Math.abs(mouseX - startX),
1230
1230
  height: Math.abs(mouseY - startY),
1231
1231
  };
1232
- const selectedNodes = getNodesInside(nodeLookup, nextUserSelectRect, transform, selectionMode === SelectionMode.Partial, true, nodeOrigin);
1232
+ const selectedNodes = getNodesInside(nodeLookup, nextUserSelectRect, transform, selectionMode === SelectionMode.Partial, true);
1233
1233
  const selectedEdgeIds = new Set();
1234
1234
  const selectedNodeIds = new Set();
1235
1235
  for (const selectedNode of selectedNodes) {
@@ -1403,23 +1403,24 @@ const useNodeId = () => {
1403
1403
  return nodeId;
1404
1404
  };
1405
1405
 
1406
- const selector$i = (s) => ({
1406
+ const selector$h = (s) => ({
1407
1407
  connectOnClick: s.connectOnClick,
1408
1408
  noPanClassName: s.noPanClassName,
1409
1409
  rfId: s.rfId,
1410
1410
  });
1411
1411
  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;
1412
+ const { connectionClickStartHandle: clickHandle, connectionMode, connection } = state;
1413
+ const { fromHandle, toHandle, isValid } = connection;
1414
+ const connectingTo = toHandle?.nodeId === nodeId && toHandle?.id === handleId && toHandle?.type === type;
1414
1415
  return {
1415
- connectingFrom: startHandle?.nodeId === nodeId && startHandle?.handleId === handleId && startHandle?.type === type,
1416
+ connectingFrom: fromHandle?.nodeId === nodeId && fromHandle?.id === handleId && fromHandle?.type === type,
1416
1417
  connectingTo,
1417
- clickConnecting: clickHandle?.nodeId === nodeId && clickHandle?.handleId === handleId && clickHandle?.type === type,
1418
+ clickConnecting: clickHandle?.nodeId === nodeId && clickHandle?.id === handleId && clickHandle?.type === type,
1418
1419
  isPossibleEndHandle: connectionMode === ConnectionMode.Strict
1419
- ? startHandle?.type !== type
1420
- : nodeId !== startHandle?.nodeId || handleId !== startHandle?.handleId,
1421
- connectionInProcess: !!startHandle,
1422
- valid: connectingTo && connectionStatus === 'valid',
1420
+ ? fromHandle?.type !== type
1421
+ : nodeId !== fromHandle?.nodeId || handleId !== fromHandle?.id,
1422
+ connectionInProcess: !!fromHandle,
1423
+ valid: connectingTo && isValid,
1423
1424
  };
1424
1425
  };
1425
1426
  function HandleComponent({ type = 'source', position = Position.Top, isValidConnection, isConnectable = true, isConnectableStart = true, isConnectableEnd = true, id, onConnect, children, className, onMouseDown, onTouchStart, ...rest }, ref) {
@@ -1427,7 +1428,7 @@ function HandleComponent({ type = 'source', position = Position.Top, isValidConn
1427
1428
  const isTarget = type === 'target';
1428
1429
  const store = useStoreApi();
1429
1430
  const nodeId = useNodeId();
1430
- const { connectOnClick, noPanClassName, rfId } = useStore(selector$i, shallow);
1431
+ const { connectOnClick, noPanClassName, rfId } = useStore(selector$h, shallow);
1431
1432
  const { connectingFrom, connectingTo, clickConnecting, isPossibleEndHandle, connectionInProcess, valid } = useStore(connectingSelector(nodeId, handleId, type), shallow);
1432
1433
  if (!nodeId) {
1433
1434
  store.getState().onError?.('010', errorMessages['error010']());
@@ -1472,7 +1473,7 @@ function HandleComponent({ type = 'source', position = Position.Top, isValidConn
1472
1473
  onConnect: onConnectExtended,
1473
1474
  isValidConnection: isValidConnection || currentStore.isValidConnection,
1474
1475
  getTransform: () => store.getState().transform,
1475
- getConnectionStartHandle: () => store.getState().connectionStartHandle,
1476
+ getFromHandle: () => store.getState().connection.fromHandle,
1476
1477
  });
1477
1478
  }
1478
1479
  if (isMouseTriggered) {
@@ -1489,7 +1490,7 @@ function HandleComponent({ type = 'source', position = Position.Top, isValidConn
1489
1490
  }
1490
1491
  if (!connectionClickStartHandle) {
1491
1492
  onClickConnectStart?.(event.nativeEvent, { nodeId, handleId, handleType: type });
1492
- store.setState({ connectionClickStartHandle: { nodeId, type, handleId } });
1493
+ store.setState({ connectionClickStartHandle: { nodeId, type, id: handleId } });
1493
1494
  return;
1494
1495
  }
1495
1496
  const doc = getHostForElement(event.target);
@@ -1502,7 +1503,7 @@ function HandleComponent({ type = 'source', position = Position.Top, isValidConn
1502
1503
  },
1503
1504
  connectionMode,
1504
1505
  fromNodeId: connectionClickStartHandle.nodeId,
1505
- fromHandleId: connectionClickStartHandle.handleId || null,
1506
+ fromHandleId: connectionClickStartHandle.id || null,
1506
1507
  fromType: connectionClickStartHandle.type,
1507
1508
  isValidConnection: isValidConnectionHandler,
1508
1509
  flowId,
@@ -1585,9 +1586,8 @@ function getNodeInlineStyleDimensions(node) {
1585
1586
  };
1586
1587
  }
1587
1588
 
1588
- const selector$h = (s) => {
1589
+ const selector$g = (s) => {
1589
1590
  const { width, height, x, y } = getInternalNodesBounds(s.nodeLookup, {
1590
- nodeOrigin: s.nodeOrigin,
1591
1591
  filter: (node) => !!node.selected,
1592
1592
  });
1593
1593
  return {
@@ -1599,7 +1599,7 @@ const selector$h = (s) => {
1599
1599
  };
1600
1600
  function NodesSelection({ onSelectionContextMenu, noPanClassName, disableKeyboardA11y, }) {
1601
1601
  const store = useStoreApi();
1602
- const { width, height, transformString, userSelectionActive } = useStore(selector$h, shallow);
1602
+ const { width, height, transformString, userSelectionActive } = useStore(selector$g, shallow);
1603
1603
  const moveSelectedNodes = useMoveSelectedNodes();
1604
1604
  const nodeRef = useRef(null);
1605
1605
  useEffect(() => {
@@ -1638,11 +1638,11 @@ function NodesSelection({ onSelectionContextMenu, noPanClassName, disableKeyboar
1638
1638
  }
1639
1639
 
1640
1640
  const win = typeof window !== 'undefined' ? window : undefined;
1641
- const selector$g = (s) => {
1641
+ const selector$f = (s) => {
1642
1642
  return { nodesSelectionActive: s.nodesSelectionActive, userSelectionActive: s.userSelectionActive };
1643
1643
  };
1644
1644
  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);
1645
+ const { nodesSelectionActive, userSelectionActive } = useStore(selector$f);
1646
1646
  const selectionKeyPressed = useKeyPress(selectionKeyCode, { target: win });
1647
1647
  const panActivationKeyPressed = useKeyPress(panActivationKeyCode, { target: win });
1648
1648
  const panOnDrag = panActivationKeyPressed || _panOnDrag;
@@ -1654,7 +1654,7 @@ function FlowRendererComponent({ children, onPaneClick, onPaneMouseEnter, onPane
1654
1654
  FlowRendererComponent.displayName = 'FlowRenderer';
1655
1655
  const FlowRenderer = memo(FlowRendererComponent);
1656
1656
 
1657
- const selector$f = (onlyRenderVisible) => (s) => {
1657
+ const selector$e = (onlyRenderVisible) => (s) => {
1658
1658
  return onlyRenderVisible
1659
1659
  ? getNodesInside(s.nodeLookup, { x: 0, y: 0, width: s.width, height: s.height }, s.transform, true).map((node) => node.id)
1660
1660
  : Array.from(s.nodeLookup.keys());
@@ -1667,13 +1667,13 @@ const selector$f = (onlyRenderVisible) => (s) => {
1667
1667
  * @returns array with visible node ids
1668
1668
  */
1669
1669
  function useVisibleNodeIds(onlyRenderVisible) {
1670
- const nodeIds = useStore(useCallback(selector$f(onlyRenderVisible), [onlyRenderVisible]), shallow);
1670
+ const nodeIds = useStore(useCallback(selector$e(onlyRenderVisible), [onlyRenderVisible]), shallow);
1671
1671
  return nodeIds;
1672
1672
  }
1673
1673
 
1674
- const selector$e = (s) => s.updateNodeInternals;
1674
+ const selector$d = (s) => s.updateNodeInternals;
1675
1675
  function useResizeObserver() {
1676
- const updateNodeInternals = useStore(selector$e);
1676
+ const updateNodeInternals = useStore(selector$d);
1677
1677
  const [resizeObserver] = useState(() => {
1678
1678
  if (typeof ResizeObserver === 'undefined') {
1679
1679
  return null;
@@ -1750,7 +1750,7 @@ function useNodeObserver({ node, nodeType, hasDimensions, resizeObserver, }) {
1750
1750
  return nodeRef;
1751
1751
  }
1752
1752
 
1753
- function NodeWrapper({ id, onClick, onMouseEnter, onMouseMove, onMouseLeave, onContextMenu, onDoubleClick, nodesDraggable, elementsSelectable, nodesConnectable, nodesFocusable, resizeObserver, noDragClassName, noPanClassName, disableKeyboardA11y, rfId, nodeTypes, nodeExtent, nodeOrigin, onError, }) {
1753
+ function NodeWrapper({ id, onClick, onMouseEnter, onMouseMove, onMouseLeave, onContextMenu, onDoubleClick, nodesDraggable, elementsSelectable, nodesConnectable, nodesFocusable, resizeObserver, noDragClassName, noPanClassName, disableKeyboardA11y, rfId, nodeTypes, nodeExtent, onError, }) {
1754
1754
  const { node, internals, isParent } = useStore((s) => {
1755
1755
  const node = s.nodeLookup.get(id);
1756
1756
  const isParent = s.parentLookup.has(id);
@@ -1788,14 +1788,10 @@ function NodeWrapper({ id, onClick, onMouseEnter, onMouseMove, onMouseLeave, onC
1788
1788
  }
1789
1789
  const nodeDimensions = getNodeDimensions(node);
1790
1790
  const inlineDimensions = getNodeInlineStyleDimensions(node);
1791
+ // TODO: clamping should happen earlier
1791
1792
  const clampedPosition = nodeExtent
1792
1793
  ? clampPosition(internals.positionAbsolute, nodeExtent)
1793
1794
  : internals.positionAbsolute;
1794
- const positionWithOrigin = getPositionWithOrigin({
1795
- ...clampedPosition,
1796
- ...nodeDimensions,
1797
- origin: node.origin || nodeOrigin,
1798
- });
1799
1795
  const hasPointerEvents = isSelectable || isDraggable || onClick || onMouseEnter || onMouseMove || onMouseLeave;
1800
1796
  const onMouseEnterHandler = onMouseEnter
1801
1797
  ? (event) => onMouseEnter(event, { ...internals.userNode })
@@ -1869,7 +1865,7 @@ function NodeWrapper({ id, onClick, onMouseEnter, onMouseMove, onMouseLeave, onC
1869
1865
  },
1870
1866
  ]), ref: nodeRef, style: {
1871
1867
  zIndex: internals.z,
1872
- transform: `translate(${positionWithOrigin.x}px,${positionWithOrigin.y}px)`,
1868
+ transform: `translate(${clampedPosition.x}px,${clampedPosition.y}px)`,
1873
1869
  pointerEvents: hasPointerEvents ? 'all' : 'none',
1874
1870
  visibility: hasDimensions ? 'visible' : 'hidden',
1875
1871
  ...node.style,
@@ -1877,7 +1873,7 @@ function NodeWrapper({ id, onClick, onMouseEnter, onMouseMove, onMouseLeave, onC
1877
1873
  }, "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
1874
  }
1879
1875
 
1880
- const selector$d = (s) => ({
1876
+ const selector$c = (s) => ({
1881
1877
  nodesDraggable: s.nodesDraggable,
1882
1878
  nodesConnectable: s.nodesConnectable,
1883
1879
  nodesFocusable: s.nodesFocusable,
@@ -1885,7 +1881,7 @@ const selector$d = (s) => ({
1885
1881
  onError: s.onError,
1886
1882
  });
1887
1883
  function NodeRendererComponent(props) {
1888
- const { nodesDraggable, nodesConnectable, nodesFocusable, elementsSelectable, onError } = useStore(selector$d, shallow);
1884
+ const { nodesDraggable, nodesConnectable, nodesFocusable, elementsSelectable, onError } = useStore(selector$c, shallow);
1889
1885
  const nodeIds = useVisibleNodeIds(props.onlyRenderVisibleElements);
1890
1886
  const resizeObserver = useResizeObserver();
1891
1887
  return (jsx("div", { className: "react-flow__nodes", style: containerStyle, children: nodeIds.map((nodeId) => {
@@ -1913,7 +1909,7 @@ function NodeRendererComponent(props) {
1913
1909
  // moved into `NodeComponentWrapper`. This ensures they are
1914
1910
  // memorized – so if `NodeRenderer` *has* to rerender, it only
1915
1911
  // 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));
1912
+ 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
1913
  }) }));
1918
1914
  }
1919
1915
  NodeRendererComponent.displayName = 'NodeRenderer';
@@ -2243,7 +2239,7 @@ function EdgeUpdateAnchors({ isReconnectable, reconnectRadius, edge, targetHandl
2243
2239
  onReconnectEnd: _onReconnectEnd,
2244
2240
  updateConnection,
2245
2241
  getTransform: () => store.getState().transform,
2246
- getConnectionStartHandle: () => store.getState().connectionStartHandle,
2242
+ getFromHandle: () => store.getState().connection.fromHandle,
2247
2243
  });
2248
2244
  };
2249
2245
  const onReconnectSourceMouseDown = (event) => handleEdgeUpdater(event, true);
@@ -2376,7 +2372,7 @@ function EdgeWrapper({ id, edgesFocusable, edgesReconnectable, elementsSelectabl
2376
2372
  ]), 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
2373
  }
2378
2374
 
2379
- const selector$c = (s) => ({
2375
+ const selector$b = (s) => ({
2380
2376
  width: s.width,
2381
2377
  height: s.height,
2382
2378
  edgesFocusable: s.edgesFocusable,
@@ -2386,7 +2382,7 @@ const selector$c = (s) => ({
2386
2382
  onError: s.onError,
2387
2383
  });
2388
2384
  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);
2385
+ const { edgesFocusable, edgesReconnectable, elementsSelectable, onError } = useStore(selector$b, shallow);
2390
2386
  const edgeIds = useVisibleEdgeIds(onlyRenderVisibleElements);
2391
2387
  return (jsxs("div", { className: "react-flow__edges", children: [jsx(MarkerDefinitions$1, { defaultColor: defaultMarkerColor, rfId: rfId }), edgeIds.map((id) => {
2392
2388
  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 +2391,9 @@ function EdgeRendererComponent({ defaultMarkerColor, onlyRenderVisibleElements,
2395
2391
  EdgeRendererComponent.displayName = 'EdgeRenderer';
2396
2392
  const EdgeRenderer = memo(EdgeRendererComponent);
2397
2393
 
2398
- const selector$b = (s) => `translate(${s.transform[0]}px,${s.transform[1]}px) scale(${s.transform[2]})`;
2394
+ const selector$a = (s) => `translate(${s.transform[0]}px,${s.transform[1]}px) scale(${s.transform[2]})`;
2399
2395
  function Viewport({ children }) {
2400
- const transform = useStore(selector$b);
2396
+ const transform = useStore(selector$a);
2401
2397
  return (jsx("div", { className: "react-flow__viewport xyflow__viewport react-flow__container", style: { transform }, children: children }));
2402
2398
  }
2403
2399
 
@@ -2417,7 +2413,7 @@ function useOnInitHandler(onInit) {
2417
2413
  }, [onInit, rfInstance.viewportInitialized]);
2418
2414
  }
2419
2415
 
2420
- const selector$a = (state) => state.panZoom?.syncViewport;
2416
+ const selector$9 = (state) => state.panZoom?.syncViewport;
2421
2417
  /**
2422
2418
  * Hook for syncing the viewport with the panzoom instance.
2423
2419
  *
@@ -2425,7 +2421,7 @@ const selector$a = (state) => state.panZoom?.syncViewport;
2425
2421
  * @param viewport
2426
2422
  */
2427
2423
  function useViewportSync(viewport) {
2428
- const syncViewport = useStore(selector$a);
2424
+ const syncViewport = useStore(selector$9);
2429
2425
  const store = useStoreApi();
2430
2426
  useEffect(() => {
2431
2427
  if (viewport) {
@@ -2436,90 +2432,75 @@ function useViewportSync(viewport) {
2436
2432
  return null;
2437
2433
  }
2438
2434
 
2439
- const oppositePosition = {
2440
- [Position.Left]: Position.Right,
2441
- [Position.Right]: Position.Left,
2442
- [Position.Top]: Position.Bottom,
2443
- [Position.Bottom]: Position.Top,
2435
+ const selector$8 = (s) => {
2436
+ return s.connection.inProgress
2437
+ ? { ...s.connection, to: pointToRendererPoint(s.connection.to, s.transform) }
2438
+ : { ...s.connection };
2444
2439
  };
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) {
2440
+ /**
2441
+ * Hook for accessing the connection state.
2442
+ *
2443
+ * @public
2444
+ * @returns ConnectionState
2445
+ */
2446
+ function useConnection() {
2447
+ return useStore(selector$8, shallow);
2448
+ }
2449
+
2450
+ const selector$7 = (s) => ({
2451
+ nodesConnectable: s.nodesConnectable,
2452
+ isValid: s.connection.isValid,
2453
+ inProgress: s.connection.inProgress,
2454
+ width: s.width,
2455
+ height: s.height,
2456
+ });
2457
+ function ConnectionLineWrapper({ containerStyle, style, type, component }) {
2458
+ const { nodesConnectable, width, height, isValid, inProgress } = useStore(selector$7, shallow);
2459
+ const renderConnection = !!(width && nodesConnectable && inProgress);
2460
+ if (!renderConnection) {
2461
2461
  return null;
2462
2462
  }
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;
2463
+ 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 }) }) }));
2464
+ }
2465
+ const ConnectionLine = ({ style, type = ConnectionLineType.Bezier, CustomComponent, isValid }) => {
2466
+ const { inProgress, from, fromNode, fromHandle, fromPosition, to, toNode, toHandle, toPosition } = useConnection();
2467
+ if (!inProgress) {
2468
+ return;
2472
2469
  }
2473
2470
  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 }));
2471
+ 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
2472
  }
2476
- let dAttr = '';
2473
+ let path = '';
2477
2474
  const pathParams = {
2478
- sourceX: fromX,
2479
- sourceY: fromY,
2475
+ sourceX: from.x,
2476
+ sourceY: from.y,
2480
2477
  sourcePosition: fromPosition,
2481
- targetX: toX,
2482
- targetY: toY,
2478
+ targetX: to.x,
2479
+ targetY: to.y,
2483
2480
  targetPosition: toPosition,
2484
2481
  };
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}`;
2482
+ switch (type) {
2483
+ case ConnectionLineType.Bezier:
2484
+ [path] = getBezierPath(pathParams);
2485
+ break;
2486
+ case ConnectionLineType.SimpleBezier:
2487
+ [path] = getSimpleBezierPath(pathParams);
2488
+ break;
2489
+ case ConnectionLineType.Step:
2490
+ [path] = getSmoothStepPath({
2491
+ ...pathParams,
2492
+ borderRadius: 0,
2493
+ });
2494
+ break;
2495
+ case ConnectionLineType.SmoothStep:
2496
+ [path] = getSmoothStepPath(pathParams);
2497
+ break;
2498
+ default:
2499
+ [path] = getStraightPath(pathParams);
2503
2500
  }
2504
- return jsx("path", { d: dAttr, fill: "none", className: "react-flow__connection-path", style: style });
2501
+ return jsx("path", { d: path, fill: "none", className: "react-flow__connection-path", style: style });
2505
2502
  };
2506
2503
  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
2504
 
2524
2505
  const emptyTypes = {};
2525
2506
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -2556,34 +2537,33 @@ function useStylesLoadedWarning() {
2556
2537
  }, []);
2557
2538
  }
2558
2539
 
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, }) {
2540
+ 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
2541
  useNodeOrEdgeTypesWarning(nodeTypes);
2561
2542
  useNodeOrEdgeTypesWarning(edgeTypes);
2562
2543
  useStylesLoadedWarning();
2563
2544
  useOnInitHandler(onInit);
2564
2545
  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" })] }) }));
2546
+ 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
2547
  }
2567
2548
  GraphViewComponent.displayName = 'GraphView';
2568
2549
  const GraphView = memo(GraphViewComponent);
2569
2550
 
2570
- const getInitialState = ({ nodes, edges, defaultNodes, defaultEdges, width, height, fitView, } = {}) => {
2551
+ const getInitialState = ({ nodes, edges, defaultNodes, defaultEdges, width, height, fitView, nodeOrigin, } = {}) => {
2571
2552
  const nodeLookup = new Map();
2572
2553
  const parentLookup = new Map();
2573
2554
  const connectionLookup = new Map();
2574
2555
  const edgeLookup = new Map();
2575
2556
  const storeEdges = defaultEdges ?? edges ?? [];
2576
2557
  const storeNodes = defaultNodes ?? nodes ?? [];
2558
+ const storeNodeOrigin = nodeOrigin ?? [0, 0];
2577
2559
  updateConnectionLookup(connectionLookup, edgeLookup, storeEdges);
2578
2560
  adoptUserNodes(storeNodes, nodeLookup, parentLookup, {
2579
- nodeOrigin: [0, 0],
2561
+ nodeOrigin: storeNodeOrigin,
2580
2562
  elevateNodesOnSelect: false,
2581
2563
  });
2582
2564
  let transform = [0, 0, 1];
2583
2565
  if (fitView && width && height) {
2584
- // @todo users nodeOrigin should be used here
2585
2566
  const bounds = getInternalNodesBounds(nodeLookup, {
2586
- nodeOrigin: [0, 0],
2587
2567
  filter: (node) => !!((node.width || node.initialWidth) && (node.height || node.initialHeight)),
2588
2568
  });
2589
2569
  const { x, y, zoom } = getViewportForBounds(bounds, width, height, 0.5, 2, 0.1);
@@ -2612,13 +2592,11 @@ const getInitialState = ({ nodes, edges, defaultNodes, defaultEdges, width, heig
2612
2592
  nodesSelectionActive: false,
2613
2593
  userSelectionActive: false,
2614
2594
  userSelectionRect: null,
2615
- connectionPosition: { x: 0, y: 0 },
2616
- connectionStatus: null,
2617
2595
  connectionMode: ConnectionMode.Strict,
2618
2596
  domNode: null,
2619
2597
  paneDragging: false,
2620
2598
  noPanClassName: 'nopan',
2621
- nodeOrigin: [0, 0],
2599
+ nodeOrigin: storeNodeOrigin,
2622
2600
  nodeDragThreshold: 1,
2623
2601
  snapGrid: [15, 15],
2624
2602
  snapToGrid: false,
@@ -2635,8 +2613,7 @@ const getInitialState = ({ nodes, edges, defaultNodes, defaultEdges, width, heig
2635
2613
  fitViewOnInitOptions: undefined,
2636
2614
  selectNodesOnDrag: true,
2637
2615
  multiSelectionActive: false,
2638
- connectionStartHandle: null,
2639
- connectionEndHandle: null,
2616
+ connection: { ...initialConnection },
2640
2617
  connectionClickStartHandle: null,
2641
2618
  connectOnClick: true,
2642
2619
  ariaLiveMessage: '',
@@ -2651,8 +2628,8 @@ const getInitialState = ({ nodes, edges, defaultNodes, defaultEdges, width, heig
2651
2628
  };
2652
2629
  };
2653
2630
 
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 }),
2631
+ const createStore = ({ nodes, edges, defaultNodes, defaultEdges, width, height, fitView: fitView$1, nodeOrigin, }) => createWithEqualityFn((set, get) => ({
2632
+ ...getInitialState({ nodes, edges, width, height, fitView: fitView$1, nodeOrigin, defaultNodes, defaultEdges }),
2656
2633
  setNodes: (nodes) => {
2657
2634
  const { nodeLookup, parentLookup, nodeOrigin, elevateNodesOnSelect } = get();
2658
2635
  // setNodes() is called exclusively in response to user actions:
@@ -2690,7 +2667,7 @@ const createStore = ({ nodes, edges, defaultNodes, defaultEdges, width, height,
2690
2667
  if (!updatedInternals) {
2691
2668
  return;
2692
2669
  }
2693
- updateAbsolutePositions(nodeLookup, { nodeOrigin });
2670
+ updateAbsolutePositions(nodeLookup, parentLookup, { nodeOrigin });
2694
2671
  // we call fitView once initially after all dimensions are set
2695
2672
  let nextFitViewDone = fitViewDone;
2696
2673
  if (!fitViewDone && fitViewOnInit) {
@@ -2739,8 +2716,8 @@ const createStore = ({ nodes, edges, defaultNodes, defaultEdges, width, height,
2739
2716
  changes.push(change);
2740
2717
  }
2741
2718
  if (parentExpandChildren.length > 0) {
2742
- const { nodeLookup, parentLookup } = get();
2743
- const parentExpandChanges = handleExpandParent(parentExpandChildren, nodeLookup, parentLookup);
2719
+ const { nodeLookup, parentLookup, nodeOrigin } = get();
2720
+ const parentExpandChanges = handleExpandParent(parentExpandChildren, nodeLookup, parentLookup, nodeOrigin);
2744
2721
  changes.push(...parentExpandChanges);
2745
2722
  }
2746
2723
  get().triggerNodeChanges(changes);
@@ -2845,7 +2822,7 @@ const createStore = ({ nodes, edges, defaultNodes, defaultEdges, width, height,
2845
2822
  return panBy({ delta, panZoom, transform, translateExtent, width, height });
2846
2823
  },
2847
2824
  fitView: (options) => {
2848
- const { panZoom, width, height, minZoom, maxZoom, nodeOrigin, nodeLookup } = get();
2825
+ const { panZoom, width, height, minZoom, maxZoom, nodeLookup } = get();
2849
2826
  if (!panZoom) {
2850
2827
  return false;
2851
2828
  }
@@ -2856,26 +2833,20 @@ const createStore = ({ nodes, edges, defaultNodes, defaultEdges, width, height,
2856
2833
  panZoom,
2857
2834
  minZoom,
2858
2835
  maxZoom,
2859
- nodeOrigin,
2860
2836
  }, options);
2861
2837
  },
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);
2838
+ cancelConnection: () => {
2839
+ set({
2840
+ connection: { ...initialConnection },
2841
+ });
2842
+ },
2843
+ updateConnection: (connection) => {
2844
+ set({ connection });
2874
2845
  },
2875
2846
  reset: () => set({ ...getInitialState() }),
2876
2847
  }), Object.is);
2877
2848
 
2878
- function ReactFlowProvider({ initialNodes: nodes, initialEdges: edges, defaultNodes, defaultEdges, initialWidth: width, initialHeight: height, fitView, children, }) {
2849
+ function ReactFlowProvider({ initialNodes: nodes, initialEdges: edges, defaultNodes, defaultEdges, initialWidth: width, initialHeight: height, fitView, nodeOrigin, children, }) {
2879
2850
  const [store] = useState(() => createStore({
2880
2851
  nodes,
2881
2852
  edges,
@@ -2884,18 +2855,19 @@ function ReactFlowProvider({ initialNodes: nodes, initialEdges: edges, defaultNo
2884
2855
  width,
2885
2856
  height,
2886
2857
  fitView,
2858
+ nodeOrigin,
2887
2859
  }));
2888
2860
  return (jsx(Provider$1, { value: store, children: jsx(BatchProvider, { children: children }) }));
2889
2861
  }
2890
2862
 
2891
- function Wrapper({ children, nodes, edges, defaultNodes, defaultEdges, width, height, fitView, }) {
2863
+ function Wrapper({ children, nodes, edges, defaultNodes, defaultEdges, width, height, fitView, nodeOrigin, }) {
2892
2864
  const isWrapped = useContext(StoreContext);
2893
2865
  if (isWrapped) {
2894
2866
  // we need to wrap it with a fragment because it's not allowed for children to be a ReactNode
2895
2867
  // https://github.com/DefinitelyTyped/DefinitelyTyped/issues/18051
2896
2868
  return jsx(Fragment, { children: children });
2897
2869
  }
2898
- return (jsx(ReactFlowProvider, { initialNodes: nodes, initialEdges: edges, defaultNodes: defaultNodes, defaultEdges: defaultEdges, initialWidth: width, initialHeight: height, fitView: fitView, children: children }));
2870
+ return (jsx(ReactFlowProvider, { initialNodes: nodes, initialEdges: edges, defaultNodes: defaultNodes, defaultEdges: defaultEdges, initialWidth: width, initialHeight: height, fitView: fitView, nodeOrigin: nodeOrigin, children: children }));
2899
2871
  }
2900
2872
 
2901
2873
  const wrapperStyle = {
@@ -2908,22 +2880,22 @@ const wrapperStyle = {
2908
2880
  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) {
2909
2881
  const rfId = id || '1';
2910
2882
  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 })] }) }));
2883
+ 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, 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
2884
  }
2913
2885
  var index = fixedForwardRef(ReactFlow);
2914
2886
 
2915
- const selector$8 = (s) => s.domNode?.querySelector('.react-flow__edgelabel-renderer');
2887
+ const selector$6 = (s) => s.domNode?.querySelector('.react-flow__edgelabel-renderer');
2916
2888
  function EdgeLabelRenderer({ children }) {
2917
- const edgeLabelRenderer = useStore(selector$8);
2889
+ const edgeLabelRenderer = useStore(selector$6);
2918
2890
  if (!edgeLabelRenderer) {
2919
2891
  return null;
2920
2892
  }
2921
2893
  return createPortal(children, edgeLabelRenderer);
2922
2894
  }
2923
2895
 
2924
- const selector$7 = (s) => s.domNode?.querySelector('.react-flow__viewport-portal');
2896
+ const selector$5 = (s) => s.domNode?.querySelector('.react-flow__viewport-portal');
2925
2897
  function ViewportPortal({ children }) {
2926
- const viewPortalDiv = useStore(selector$7);
2898
+ const viewPortalDiv = useStore(selector$5);
2927
2899
  if (!viewPortalDiv) {
2928
2900
  return null;
2929
2901
  }
@@ -3056,7 +3028,7 @@ function useOnSelectionChange({ onChange }) {
3056
3028
  }, [onChange]);
3057
3029
  }
3058
3030
 
3059
- const selector$6 = (options) => (s) => {
3031
+ const selector$4 = (options) => (s) => {
3060
3032
  if (s.nodeLookup.size === 0) {
3061
3033
  return false;
3062
3034
  }
@@ -3080,7 +3052,7 @@ const defaultOptions = {
3080
3052
  * @returns boolean indicating whether all nodes are initialized
3081
3053
  */
3082
3054
  function useNodesInitialized(options = defaultOptions) {
3083
- const initialized = useStore(selector$6(options));
3055
+ const initialized = useStore(selector$4(options));
3084
3056
  return initialized;
3085
3057
  }
3086
3058
 
@@ -3133,23 +3105,6 @@ function useNodesData(nodeIds) {
3133
3105
  return nodesData;
3134
3106
  }
3135
3107
 
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
3108
  /**
3154
3109
  * Hook for getting an internal node by id
3155
3110
  *
@@ -3181,14 +3136,14 @@ const defaultSize = {
3181
3136
  [BackgroundVariant.Lines]: 1,
3182
3137
  [BackgroundVariant.Cross]: 6,
3183
3138
  };
3184
- const selector$4 = (s) => ({ transform: s.transform, patternId: `pattern-${s.rfId}` });
3139
+ const selector$3 = (s) => ({ transform: s.transform, patternId: `pattern-${s.rfId}` });
3185
3140
  function BackgroundComponent({ id, variant = BackgroundVariant.Dots,
3186
3141
  // only used for dots and cross
3187
3142
  gap = 20,
3188
3143
  // only used for lines and cross
3189
3144
  size, lineWidth = 1, offset = 2, color, bgColor, style, className, patternClassName, }) {
3190
3145
  const ref = useRef(null);
3191
- const { transform, patternId } = useStore(selector$4, shallow);
3146
+ const { transform, patternId } = useStore(selector$3, shallow);
3192
3147
  const patternSize = size || defaultSize[variant];
3193
3148
  const isDots = variant === BackgroundVariant.Dots;
3194
3149
  const isCross = variant === BackgroundVariant.Cross;
@@ -3234,14 +3189,14 @@ function ControlButton({ children, className, ...rest }) {
3234
3189
  return (jsx("button", { type: "button", className: cc(['react-flow__controls-button', className]), ...rest, children: children }));
3235
3190
  }
3236
3191
 
3237
- const selector$3 = (s) => ({
3192
+ const selector$2 = (s) => ({
3238
3193
  isInteractive: s.nodesDraggable || s.nodesConnectable || s.elementsSelectable,
3239
3194
  minZoomReached: s.transform[2] <= s.minZoom,
3240
3195
  maxZoomReached: s.transform[2] >= s.maxZoom,
3241
3196
  });
3242
3197
  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
3198
  const store = useStoreApi();
3244
- const { isInteractive, minZoomReached, maxZoomReached } = useStore(selector$3, shallow);
3199
+ const { isInteractive, minZoomReached, maxZoomReached } = useStore(selector$2, shallow);
3245
3200
  const { zoomIn, zoomOut, fitView } = useReactFlow();
3246
3201
  const onZoomInHandler = () => {
3247
3202
  zoomIn();
@@ -3280,7 +3235,6 @@ function MiniMapNodeComponent({ id, x, y, width, height, style, color, strokeCol
3280
3235
  }
3281
3236
  const MiniMapNode = memo(MiniMapNodeComponent);
3282
3237
 
3283
- const selector$2 = (s) => s.nodeOrigin;
3284
3238
  const selectorNodeIds = (s) => s.nodes.map((node) => node.id);
3285
3239
  const getAttrFunction = (func) => func instanceof Function ? func : () => func;
3286
3240
  function MiniMapNodes({ nodeStrokeColor, nodeColor, nodeClassName = '', nodeBorderRadius = 5, nodeStrokeWidth,
@@ -3288,7 +3242,6 @@ function MiniMapNodes({ nodeStrokeColor, nodeColor, nodeClassName = '', nodeBord
3288
3242
  // a component properly.
3289
3243
  nodeComponent: NodeComponent = MiniMapNode, onClick, }) {
3290
3244
  const nodeIds = useStore(selectorNodeIds, shallow);
3291
- const nodeOrigin = useStore(selector$2);
3292
3245
  const nodeColorFunc = getAttrFunction(nodeColor);
3293
3246
  const nodeStrokeColorFunc = getAttrFunction(nodeStrokeColor);
3294
3247
  const nodeClassNameFunc = getAttrFunction(nodeClassName);
@@ -3299,12 +3252,12 @@ nodeComponent: NodeComponent = MiniMapNode, onClick, }) {
3299
3252
  // minimize the cost of updates when individual nodes change.
3300
3253
  //
3301
3254
  // 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))) }));
3255
+ jsx(NodeComponentWrapper, { id: nodeId, nodeColorFunc: nodeColorFunc, nodeStrokeColorFunc: nodeStrokeColorFunc, nodeClassNameFunc: nodeClassNameFunc, nodeBorderRadius: nodeBorderRadius, nodeStrokeWidth: nodeStrokeWidth, NodeComponent: NodeComponent, onClick: onClick, shapeRendering: shapeRendering }, nodeId))) }));
3303
3256
  }
3304
- function NodeComponentWrapperInner({ id, nodeOrigin, nodeColorFunc, nodeStrokeColorFunc, nodeClassNameFunc, nodeBorderRadius, nodeStrokeWidth, shapeRendering, NodeComponent, onClick, }) {
3257
+ function NodeComponentWrapperInner({ id, nodeColorFunc, nodeStrokeColorFunc, nodeClassNameFunc, nodeBorderRadius, nodeStrokeWidth, shapeRendering, NodeComponent, onClick, }) {
3305
3258
  const { node, x, y } = useStore((s) => {
3306
3259
  const node = s.nodeLookup.get(id);
3307
- const { x, y } = getNodePositionWithOrigin(node, nodeOrigin).positionAbsolute;
3260
+ const { x, y } = node.internals.positionAbsolute;
3308
3261
  return {
3309
3262
  node,
3310
3263
  x,
@@ -3331,11 +3284,8 @@ const selector$1 = (s) => {
3331
3284
  };
3332
3285
  return {
3333
3286
  viewBB,
3334
- boundingRect: s.nodeLookup.size > 0
3335
- ? getBoundsOfRects(getInternalNodesBounds(s.nodeLookup, { nodeOrigin: s.nodeOrigin }), viewBB)
3336
- : viewBB,
3287
+ boundingRect: s.nodeLookup.size > 0 ? getBoundsOfRects(getInternalNodesBounds(s.nodeLookup), viewBB) : viewBB,
3337
3288
  rfId: s.rfId,
3338
- nodeOrigin: s.nodeOrigin,
3339
3289
  panZoom: s.panZoom,
3340
3290
  translateExtent: s.translateExtent,
3341
3291
  flowWidth: s.width,
@@ -3449,23 +3399,27 @@ function ResizeControl({ nodeId, position, variant = ResizeControlVariant.Handle
3449
3399
  const nextPosition = { x: change.x, y: change.y };
3450
3400
  const node = nodeLookup.get(id);
3451
3401
  if (node && node.expandParent && node.parentId) {
3402
+ const origin = node.origin ?? nodeOrigin;
3403
+ const width = change.width ?? node.measured.width;
3404
+ const height = change.height ?? node.measured.height;
3452
3405
  const child = {
3453
3406
  id: node.id,
3454
3407
  parentId: node.parentId,
3455
3408
  rect: {
3456
- width: change.width ?? node.measured.width,
3457
- height: change.height ?? node.measured.height,
3409
+ width,
3410
+ height,
3458
3411
  ...evaluateAbsolutePosition({
3459
3412
  x: change.x ?? node.position.x,
3460
3413
  y: change.y ?? node.position.y,
3461
- }, node.parentId, nodeLookup, node.origin ?? nodeOrigin),
3414
+ }, { width, height }, node.parentId, nodeLookup, origin),
3462
3415
  },
3463
3416
  };
3464
3417
  const parentExpandChanges = handleExpandParent([child], nodeLookup, parentLookup, nodeOrigin);
3465
3418
  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;
3419
+ // when the parent was expanded by the child node, its position will be clamped at
3420
+ // 0,0 when node origin is 0,0 and to width, height if it's 1,1
3421
+ nextPosition.x = change.x ? Math.max(origin[0] * width, change.x) : undefined;
3422
+ nextPosition.y = change.y ? Math.max(origin[1] * height, change.y) : undefined;
3469
3423
  }
3470
3424
  if (nextPosition.x !== undefined && nextPosition.y !== undefined) {
3471
3425
  const positionChange = {
@@ -3566,48 +3520,54 @@ const nodeEqualityFn = (a, b) => a?.internals.positionAbsolute.x !== b?.internal
3566
3520
  a?.selected !== b?.selected ||
3567
3521
  a?.internals.z !== b?.internals.z;
3568
3522
  const nodesEqualityFn = (a, b) => {
3569
- if (a.length !== b.length) {
3523
+ if (a.size !== b.size) {
3570
3524
  return false;
3571
3525
  }
3572
- return !a.some((node, i) => nodeEqualityFn(node, b[i]));
3526
+ for (const [key, node] of a) {
3527
+ if (nodeEqualityFn(node, b.get(key))) {
3528
+ return false;
3529
+ }
3530
+ }
3531
+ return true;
3573
3532
  };
3574
3533
  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,
3534
+ x: state.transform[0],
3535
+ y: state.transform[1],
3536
+ zoom: state.transform[2],
3581
3537
  selectedNodesCount: state.nodes.filter((node) => node.selected).length,
3582
3538
  });
3583
3539
  function NodeToolbar({ nodeId, children, className, style, isVisible, position = Position.Top, offset = 10, align = 'center', ...rest }) {
3584
3540
  const contextNodeId = useNodeId();
3585
3541
  const nodesSelector = useCallback((state) => {
3586
3542
  const nodeIds = Array.isArray(nodeId) ? nodeId : [nodeId || contextNodeId || ''];
3587
- return nodeIds.reduce((acc, id) => {
3543
+ const internalNodes = nodeIds.reduce((res, id) => {
3588
3544
  const node = state.nodeLookup.get(id);
3589
3545
  if (node) {
3590
- acc.push(node);
3546
+ res.set(node.id, node);
3591
3547
  }
3592
- return acc;
3593
- }, []);
3548
+ return res;
3549
+ }, new Map());
3550
+ return internalNodes;
3594
3551
  }, [nodeId, contextNodeId]);
3595
3552
  const nodes = useStore(nodesSelector, nodesEqualityFn);
3596
- const { viewport, nodeOrigin, selectedNodesCount } = useStore(storeSelector, shallow);
3553
+ const { x, y, zoom, selectedNodesCount } = useStore(storeSelector, shallow);
3597
3554
  // 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) {
3555
+ const isActive = typeof isVisible === 'boolean'
3556
+ ? isVisible
3557
+ : nodes.size === 1 && nodes.values().next().value.selected && selectedNodesCount === 1;
3558
+ if (!isActive || !nodes.size) {
3600
3559
  return null;
3601
3560
  }
3602
- const nodeRect = getNodesBounds(nodes, { nodeOrigin });
3603
- const zIndex = Math.max(...nodes.map((node) => node.internals.z + 1));
3561
+ const nodeRect = getInternalNodesBounds(nodes);
3562
+ const nodesArray = Array.from(nodes.values());
3563
+ const zIndex = Math.max(...nodesArray.map((node) => node.internals.z + 1));
3604
3564
  const wrapperStyle = {
3605
3565
  position: 'absolute',
3606
- transform: getNodeToolbarTransform(nodeRect, viewport, position, offset, align),
3566
+ transform: getNodeToolbarTransform(nodeRect, { x, y, zoom }, position, offset, align),
3607
3567
  zIndex,
3608
3568
  ...style,
3609
3569
  };
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 }) }));
3570
+ 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
3571
  }
3612
3572
 
3613
3573
  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 };