Refactor fitView
This commit is contained in:
@@ -1,7 +1,5 @@
|
||||
import { createWithEqualityFn } from 'zustand/traditional';
|
||||
import {
|
||||
getFitViewNodes,
|
||||
fitView as fitViewSystem,
|
||||
adoptUserNodes,
|
||||
updateAbsolutePositions,
|
||||
panBy as panBySystem,
|
||||
@@ -15,11 +13,12 @@ import {
|
||||
initialConnection,
|
||||
NodeOrigin,
|
||||
CoordinateExtent,
|
||||
fitViewport,
|
||||
} from '@xyflow/system';
|
||||
|
||||
import { applyEdgeChanges, applyNodeChanges, createSelectionChange, getSelectionChanges } from '../utils/changes';
|
||||
import getInitialState from './initialState';
|
||||
import type { ReactFlowState, Node, Edge, UnselectNodesAndEdgesParams, FitViewOptions } from '../types';
|
||||
import type { ReactFlowState, Node, Edge, UnselectNodesAndEdgesParams } from '../types';
|
||||
|
||||
const createStore = ({
|
||||
nodes,
|
||||
@@ -46,7 +45,7 @@ const createStore = ({
|
||||
(set, get) => ({
|
||||
...getInitialState({ nodes, edges, width, height, fitView, nodeOrigin, nodeExtent, defaultNodes, defaultEdges }),
|
||||
setNodes: (nodes: Node[]) => {
|
||||
const { nodeLookup, parentLookup, nodeOrigin, elevateNodesOnSelect } = get();
|
||||
const { nodeLookup, parentLookup, nodeOrigin, elevateNodesOnSelect, fitViewQueued, panZoom } = get();
|
||||
/*
|
||||
* setNodes() is called exclusively in response to user actions:
|
||||
* - either when the `<ReactFlow nodes>` prop is updated in the controlled ReactFlow setup,
|
||||
@@ -55,14 +54,35 @@ const createStore = ({
|
||||
* When this happens, we take the note objects passed by the user and extend them with fields
|
||||
* relevant for internal React Flow operations.
|
||||
*/
|
||||
adoptUserNodes(nodes, nodeLookup, parentLookup, {
|
||||
|
||||
const nodesInitialized = adoptUserNodes(nodes, nodeLookup, parentLookup, {
|
||||
nodeOrigin,
|
||||
nodeExtent,
|
||||
elevateNodesOnSelect,
|
||||
checkEquality: true,
|
||||
});
|
||||
|
||||
set({ nodes });
|
||||
let viewportFitted = false;
|
||||
if (fitViewQueued && nodesInitialized && panZoom) {
|
||||
const { fitViewOptions, width, height, minZoom, maxZoom } = get();
|
||||
viewportFitted = fitViewport(
|
||||
{
|
||||
nodes: nodeLookup,
|
||||
width,
|
||||
height,
|
||||
panZoom,
|
||||
minZoom,
|
||||
maxZoom,
|
||||
},
|
||||
fitViewOptions
|
||||
);
|
||||
}
|
||||
|
||||
if (viewportFitted) {
|
||||
set({ nodes, fitViewQueued: false, fitViewOptions: undefined });
|
||||
} else {
|
||||
set({ nodes });
|
||||
}
|
||||
},
|
||||
setEdges: (edges: Edge[]) => {
|
||||
const { connectionLookup, edgeLookup } = get();
|
||||
@@ -88,20 +108,8 @@ const createStore = ({
|
||||
* changes its dimensions, this function is called to measure the
|
||||
* new dimensions and update the nodes.
|
||||
*/
|
||||
updateNodeInternals: (updates, params = { triggerFitView: true }) => {
|
||||
const {
|
||||
triggerNodeChanges,
|
||||
nodeLookup,
|
||||
parentLookup,
|
||||
fitViewOnInit,
|
||||
fitViewDone,
|
||||
fitViewOnInitOptions,
|
||||
domNode,
|
||||
nodeOrigin,
|
||||
nodeExtent,
|
||||
debug,
|
||||
fitViewSync,
|
||||
} = get();
|
||||
updateNodeInternals: (updates) => {
|
||||
const { triggerNodeChanges, nodeLookup, parentLookup, domNode, nodeOrigin, nodeExtent, debug } = get();
|
||||
|
||||
const { changes, updatedInternals } = updateNodeInternalsSystem(
|
||||
updates,
|
||||
@@ -118,29 +126,8 @@ const createStore = ({
|
||||
|
||||
updateAbsolutePositions(nodeLookup, parentLookup, { nodeOrigin, nodeExtent });
|
||||
|
||||
if (params.triggerFitView) {
|
||||
// we call fitView once initially after all dimensions are set
|
||||
let nextFitViewDone = fitViewDone;
|
||||
|
||||
if (!fitViewDone && fitViewOnInit) {
|
||||
nextFitViewDone = fitViewSync({
|
||||
...fitViewOnInitOptions,
|
||||
nodes: fitViewOnInitOptions?.nodes,
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* here we are cirmumventing the onNodesChange handler
|
||||
* in order to be able to display nodes even if the user
|
||||
* has not provided an onNodesChange handler.
|
||||
* Nodes are only rendered if they have a width and height
|
||||
* attribute which they get from this handler.
|
||||
*/
|
||||
set({ fitViewDone: nextFitViewDone });
|
||||
} else {
|
||||
// we always want to trigger useStore calls whenever updateNodeInternals is called
|
||||
set({});
|
||||
}
|
||||
// we always want to trigger useStore calls whenever updateNodeInternals is called
|
||||
set({});
|
||||
|
||||
if (changes?.length > 0) {
|
||||
if (debug) {
|
||||
@@ -332,54 +319,6 @@ const createStore = ({
|
||||
|
||||
return panBySystem({ delta, panZoom, transform, translateExtent, width, height });
|
||||
},
|
||||
fitView: (options?: FitViewOptions): Promise<boolean> => {
|
||||
const { panZoom, width, height, minZoom, maxZoom, nodeLookup } = get();
|
||||
|
||||
if (!panZoom) {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
const fitViewNodes = getFitViewNodes(nodeLookup, options);
|
||||
|
||||
return fitViewSystem(
|
||||
{
|
||||
nodes: fitViewNodes,
|
||||
width,
|
||||
height,
|
||||
panZoom,
|
||||
minZoom,
|
||||
maxZoom,
|
||||
},
|
||||
options
|
||||
);
|
||||
},
|
||||
/*
|
||||
* we can't call an asnychronous function in updateNodeInternals
|
||||
* for that we created this sync version of fitView
|
||||
*/
|
||||
fitViewSync: (options?: FitViewOptions): boolean => {
|
||||
const { panZoom, width, height, minZoom, maxZoom, nodeLookup } = get();
|
||||
|
||||
if (!panZoom) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const fitViewNodes = getFitViewNodes(nodeLookup, options);
|
||||
|
||||
fitViewSystem(
|
||||
{
|
||||
nodes: fitViewNodes,
|
||||
width,
|
||||
height,
|
||||
panZoom,
|
||||
minZoom,
|
||||
maxZoom,
|
||||
},
|
||||
options
|
||||
);
|
||||
|
||||
return fitViewNodes.size > 0;
|
||||
},
|
||||
cancelConnection: () => {
|
||||
set({
|
||||
connection: { ...initialConnection },
|
||||
|
||||
@@ -104,13 +104,13 @@ const getInitialState = ({
|
||||
elementsSelectable: true,
|
||||
elevateNodesOnSelect: true,
|
||||
elevateEdgesOnSelect: false,
|
||||
fitViewOnInit: false,
|
||||
fitViewDone: false,
|
||||
fitViewOnInitOptions: undefined,
|
||||
selectNodesOnDrag: true,
|
||||
|
||||
multiSelectionActive: false,
|
||||
|
||||
fitViewQueued: false,
|
||||
fitViewOptions: undefined,
|
||||
|
||||
connection: { ...initialConnection },
|
||||
connectionClickStartHandle: null,
|
||||
connectOnClick: true,
|
||||
|
||||
Reference in New Issue
Block a user