package(core): use system fitView

This commit is contained in:
moklick
2023-02-19 16:15:26 +01:00
parent 6f8782bbf6
commit 0f62a3d07a
3 changed files with 49 additions and 75 deletions
+23 -3
View File
@@ -1,11 +1,10 @@
import { useMemo } from 'react';
import { zoomIdentity } from 'd3-zoom';
import { shallow } from 'zustand/shallow';
import { pointToRendererPoint, getTransformForBounds, getD3Transition } from '@reactflow/utils';
import { pointToRendererPoint, getTransformForBounds, getD3Transition, fitView } from '@reactflow/utils';
import type { ViewportHelperFunctions, ReactFlowState, XYPosition } from '@reactflow/system';
import { useStoreApi, useStore } from '../hooks/useStore';
import { fitView } from '../store/utils';
// eslint-disable-next-line @typescript-eslint/no-empty-function
const noop = () => {};
@@ -51,7 +50,28 @@ const useViewportHelper = (): ViewportHelperFunctions => {
const [x, y, zoom] = store.getState().transform;
return { x, y, zoom };
},
fitView: (options) => fitView(store.getState, options),
fitView: (options) => {
const { getNodes, width, height, nodeOrigin, minZoom, maxZoom, d3Selection, d3Zoom } = store.getState();
const d3Initialized = d3Selection && d3Zoom;
if (!d3Initialized) {
return false;
}
return fitView(
{
nodes: getNodes(),
width,
height,
nodeOrigin,
minZoom,
maxZoom,
d3Selection,
d3Zoom,
},
options
);
},
setCenter: (x, y, options) => {
const { width, height, maxZoom } = store.getState();
const nextZoom = typeof options?.zoom !== 'undefined' ? options.zoom : maxZoom;
+25 -3
View File
@@ -1,6 +1,6 @@
import { createStore } from 'zustand';
import { zoomIdentity } from 'd3-zoom';
import { clampPosition, getDimensions } from '@reactflow/utils';
import { clampPosition, getDimensions, fitView } from '@reactflow/utils';
import {
internalsSymbol,
type ReactFlowState,
@@ -20,7 +20,7 @@ import {
import { applyNodeChanges, createSelectionChange, getSelectionChanges } from '../utils/changes';
import { getHandleBounds } from '../components/Nodes/utils';
import { createNodeInternals, fitView, updateAbsoluteNodePositions, updateNodesAndEdgesSelections } from './utils';
import { createNodeInternals, updateAbsoluteNodePositions, updateNodesAndEdgesSelections } from './utils';
import initialState from './initialState';
const createRFStore = () =>
@@ -57,6 +57,12 @@ const createRFStore = () =>
fitViewOnInitOptions,
domNode,
nodeOrigin,
width,
height,
minZoom,
maxZoom,
d3Selection,
d3Zoom,
} = get();
const viewportNode = domNode?.querySelector('.react-flow__viewport');
@@ -106,7 +112,23 @@ const createRFStore = () =>
const nextFitViewOnInitDone =
fitViewOnInitDone ||
(fitViewOnInit && !fitViewOnInitDone && fitView(get, { initial: true, ...fitViewOnInitOptions }));
(fitViewOnInit &&
!fitViewOnInitDone &&
!!d3Zoom &&
!!d3Selection &&
fitView(
{
nodes: Array.from(nodeInternals.values()),
width,
height,
d3Zoom,
d3Selection,
minZoom,
maxZoom,
nodeOrigin,
},
fitViewOnInitOptions
));
set({ nodeInternals: new Map(nodeInternals), fitViewOnInitDone: nextFitViewOnInitDone });
if (changes?.length > 0) {
+1 -69
View File
@@ -1,4 +1,3 @@
import { zoomIdentity } from 'd3-zoom';
import type { StoreApi } from 'zustand';
import {
internalsSymbol,
@@ -9,16 +8,9 @@ import {
type NodeSelectionChange,
type ReactFlowState,
type XYZPosition,
type FitViewOptions,
type NodeOrigin,
} from '@reactflow/system';
import {
isNumeric,
getD3Transition,
getRectOfNodes,
getTransformForBounds,
getNodePositionWithOrigin,
} from '@reactflow/utils';
import { isNumeric, getNodePositionWithOrigin } from '@reactflow/utils';
type ParentNodes = Record<string, boolean>;
@@ -126,66 +118,6 @@ export function createNodeInternals(
return nextNodeInternals;
}
type InternalFitViewOptions = {
initial?: boolean;
} & FitViewOptions;
export function fitView(get: StoreApi<ReactFlowState>['getState'], options: InternalFitViewOptions = {}) {
const {
getNodes,
width,
height,
minZoom,
maxZoom,
d3Zoom,
d3Selection,
fitViewOnInitDone,
fitViewOnInit,
nodeOrigin,
} = get();
const isInitialFitView = options.initial && !fitViewOnInitDone && fitViewOnInit;
const d3initialized = d3Zoom && d3Selection;
if (d3initialized && (isInitialFitView || !options.initial)) {
const nodes = getNodes().filter((n) => {
const isVisible = options.includeHiddenNodes ? n.width && n.height : !n.hidden;
if (options.nodes?.length) {
return isVisible && options.nodes.some((optionNode) => optionNode.id === n.id);
}
return isVisible;
});
const nodesInitialized = nodes.every((n) => n.width && n.height);
if (nodes.length > 0 && nodesInitialized) {
const bounds = getRectOfNodes(nodes, nodeOrigin);
const [x, y, zoom] = getTransformForBounds(
bounds,
width,
height,
options.minZoom ?? minZoom,
options.maxZoom ?? maxZoom,
options.padding ?? 0.1
);
const nextTransform = zoomIdentity.translate(x, y).scale(zoom);
if (typeof options.duration === 'number' && options.duration > 0) {
d3Zoom.transform(getD3Transition(d3Selection, options.duration), nextTransform);
} else {
d3Zoom.transform(d3Selection, nextTransform);
}
return true;
}
}
return false;
}
export function handleControlledNodeSelectionChange(nodeChanges: NodeSelectionChange[], nodeInternals: NodeInternals) {
nodeChanges.forEach((change) => {
const node = nodeInternals.get(change.id);