feat(rf): add fitViewOnInit option
This commit is contained in:
@@ -0,0 +1,51 @@
|
|||||||
|
import React, { MutableRefObject, useEffect, useRef } from 'react';
|
||||||
|
|
||||||
|
import { Node } from '../../types';
|
||||||
|
import { getRectOfNodes, getTransformForBounds } from '../../utils/graph';
|
||||||
|
import { useStoreApi } from '../../store';
|
||||||
|
import useZoomPanHelper from '../../hooks/useZoomPanHelper';
|
||||||
|
|
||||||
|
type ViewFitterInnerProps = {
|
||||||
|
nodes: Node[];
|
||||||
|
viewFitted: MutableRefObject<boolean>;
|
||||||
|
};
|
||||||
|
|
||||||
|
function ViewFitterInner({ nodes, viewFitted }: ViewFitterInnerProps) {
|
||||||
|
const store = useStoreApi();
|
||||||
|
const { setTransform } = useZoomPanHelper();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (nodes.length > 0 && !viewFitted.current) {
|
||||||
|
const nodesInitialized = nodes.every((n) => n.width && n.height);
|
||||||
|
|
||||||
|
if (nodesInitialized) {
|
||||||
|
const { width, height, minZoom, maxZoom } = store.getState();
|
||||||
|
const bounds = getRectOfNodes(nodes);
|
||||||
|
const [x, y, zoom] = getTransformForBounds(bounds, width, height, minZoom ?? 0.5, maxZoom ?? 2);
|
||||||
|
|
||||||
|
viewFitted.current = true;
|
||||||
|
setTransform({ x, y, zoom });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [nodes]);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ViewFitterProps = {
|
||||||
|
nodes: Node[];
|
||||||
|
};
|
||||||
|
|
||||||
|
function ViewFitter({ nodes }: ViewFitterProps) {
|
||||||
|
// we are storing the viewFitted in this wrapper to get rid of the useEffect of the inner component
|
||||||
|
// that needs to check if the nodes changed after we fitted the view.
|
||||||
|
const viewFitted = useRef<boolean>(false);
|
||||||
|
|
||||||
|
if (viewFitted.current) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <ViewFitterInner nodes={nodes} viewFitted={viewFitted} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ViewFitter;
|
||||||
@@ -19,6 +19,7 @@ import SelectionListener from '../../components/SelectionListener';
|
|||||||
import { BezierEdge, StepEdge, SmoothStepEdge, StraightEdge } from '../../components/Edges';
|
import { BezierEdge, StepEdge, SmoothStepEdge, StraightEdge } from '../../components/Edges';
|
||||||
import { createEdgeTypes } from '../EdgeRenderer/utils';
|
import { createEdgeTypes } from '../EdgeRenderer/utils';
|
||||||
import Wrapper from './Wrapper';
|
import Wrapper from './Wrapper';
|
||||||
|
import ViewFitter from '../../components/ViewFitter';
|
||||||
import {
|
import {
|
||||||
OnSelectionChangeFunc,
|
OnSelectionChangeFunc,
|
||||||
NodeTypesType,
|
NodeTypesType,
|
||||||
@@ -133,6 +134,7 @@ export interface ReactFlowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'on
|
|||||||
noDragClassName?: string;
|
noDragClassName?: string;
|
||||||
noWheelClassName?: string;
|
noWheelClassName?: string;
|
||||||
noPanClassName?: string;
|
noPanClassName?: string;
|
||||||
|
fitViewOnInit?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ReactFlowRefType = HTMLDivElement;
|
export type ReactFlowRefType = HTMLDivElement;
|
||||||
@@ -219,6 +221,7 @@ const ReactFlow: FunctionComponent<ReactFlowProps> = forwardRef<ReactFlowRefType
|
|||||||
noDragClassName = 'nodrag',
|
noDragClassName = 'nodrag',
|
||||||
noWheelClassName = 'nowheel',
|
noWheelClassName = 'nowheel',
|
||||||
noPanClassName = 'nopan',
|
noPanClassName = 'nopan',
|
||||||
|
fitViewOnInit = false,
|
||||||
...rest
|
...rest
|
||||||
},
|
},
|
||||||
ref
|
ref
|
||||||
@@ -307,7 +310,7 @@ const ReactFlow: FunctionComponent<ReactFlowProps> = forwardRef<ReactFlowRefType
|
|||||||
connectionMode={connectionMode}
|
connectionMode={connectionMode}
|
||||||
translateExtent={translateExtent}
|
translateExtent={translateExtent}
|
||||||
/>
|
/>
|
||||||
|
{fitViewOnInit && <ViewFitter nodes={nodes} />}
|
||||||
{onSelectionChange && <SelectionListener onSelectionChange={onSelectionChange} />}
|
{onSelectionChange && <SelectionListener onSelectionChange={onSelectionChange} />}
|
||||||
{children}
|
{children}
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
|
|||||||
Reference in New Issue
Block a user