From db4c019fe42d1528f0fd6d816202281603c079fe Mon Sep 17 00:00:00 2001 From: peterkogo Date: Mon, 17 Mar 2025 16:01:22 +0100 Subject: [PATCH] either trigger fitView after adoptUserNodes or after updateNodeInternals --- examples/react/src/examples/Stress/index.tsx | 16 +++++++-- packages/react/src/store/index.ts | 36 ++++++++++++++++++-- packages/react/src/store/initialState.ts | 2 +- 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/examples/react/src/examples/Stress/index.tsx b/examples/react/src/examples/Stress/index.tsx index 9020ddd6..496fd500 100644 --- a/examples/react/src/examples/Stress/index.tsx +++ b/examples/react/src/examples/Stress/index.tsx @@ -12,6 +12,8 @@ import { Controls, Background, Panel, + ReactFlowProvider, + useReactFlow, } from '@xyflow/react'; import { getNodesAndEdges } from './utils'; @@ -22,6 +24,7 @@ const { nodes: initialNodes, edges: initialEdges } = getNodesAndEdges(25, 25); const StressFlow = () => { const [nodes, setNodes] = useState(initialNodes); const [edges, setEdges] = useState(initialEdges); + const { fitView } = useReactFlow(); const onConnect = useCallback((connection: Connection) => { setEdges((eds) => addEdge(connection, eds)); }, []); @@ -191,12 +194,13 @@ const StressFlow = () => { return { ...n, position: { - x: Math.random() * window.innerWidth, - y: Math.random() * window.innerHeight, + x: Math.random() * window.innerWidth * 4, + y: Math.random() * window.innerHeight * 4, }, }; }); }); + fitView(); }; const updateElements = () => { @@ -240,4 +244,10 @@ const StressFlow = () => { ); }; -export default StressFlow; +export default function StressFlowProvider() { + return ( + + + + ); +} diff --git a/packages/react/src/store/index.ts b/packages/react/src/store/index.ts index 909d8572..68d1dd24 100644 --- a/packages/react/src/store/index.ts +++ b/packages/react/src/store/index.ts @@ -109,7 +109,17 @@ const createStore = ({ * new dimensions and update the nodes. */ updateNodeInternals: (updates) => { - const { triggerNodeChanges, nodeLookup, parentLookup, domNode, nodeOrigin, nodeExtent, debug } = get(); + const { + triggerNodeChanges, + nodeLookup, + parentLookup, + domNode, + nodeOrigin, + nodeExtent, + debug, + panZoom, + fitViewQueued, + } = get(); const { changes, updatedInternals } = updateNodeInternalsSystem( updates, @@ -126,8 +136,28 @@ const createStore = ({ updateAbsolutePositions(nodeLookup, parentLookup, { nodeOrigin, nodeExtent }); - // we always want to trigger useStore calls whenever updateNodeInternals is called - set({}); + if (fitViewQueued && panZoom) { + const { fitViewOptions, fitViewResolver, width, height, minZoom, maxZoom } = get(); + const fitViewPromise = fitViewport( + { + nodes: nodeLookup, + width, + height, + panZoom, + minZoom, + maxZoom, + }, + fitViewOptions + ); + fitViewPromise.then((value) => { + fitViewResolver?.resolve(value); + set({ fitViewResolver: null }); + }); + set({ nodes, fitViewQueued: false, fitViewOptions: undefined }); + } else { + // we always want to trigger useStore calls whenever updateNodeInternals is called + set({}); + } if (changes?.length > 0) { if (debug) { diff --git a/packages/react/src/store/initialState.ts b/packages/react/src/store/initialState.ts index c63c9e9c..8be408b8 100644 --- a/packages/react/src/store/initialState.ts +++ b/packages/react/src/store/initialState.ts @@ -108,7 +108,7 @@ const getInitialState = ({ multiSelectionActive: false, - fitViewQueued: false, + fitViewQueued: fitView ?? false, fitViewOptions: undefined, fitViewResolver: null,