refactor(fitView): use same fitView function for viewport helper and initial prop
This commit is contained in:
@@ -63,7 +63,7 @@ const BasicFlow = () => {
|
|||||||
defaultZoom={1.5}
|
defaultZoom={1.5}
|
||||||
minZoom={0.2}
|
minZoom={0.2}
|
||||||
maxZoom={4}
|
maxZoom={4}
|
||||||
fitViewOnInit
|
fitView
|
||||||
>
|
>
|
||||||
<Background variant={BackgroundVariant.Lines} />
|
<Background variant={BackgroundVariant.Lines} />
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ const ControlledUncontrolled = () => {
|
|||||||
onNodesChange={onNodesChange}
|
onNodesChange={onNodesChange}
|
||||||
onEdgesChange={onEdgesChange}
|
onEdgesChange={onEdgesChange}
|
||||||
defaultEdgeOptions={defaultEdgeOptions}
|
defaultEdgeOptions={defaultEdgeOptions}
|
||||||
fitViewOnInit
|
fitView
|
||||||
>
|
>
|
||||||
<Background variant={BackgroundVariant.Lines} />
|
<Background variant={BackgroundVariant.Lines} />
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import ReactFlow, {
|
|||||||
|
|
||||||
import ColorSelectorNode from './ColorSelectorNode';
|
import ColorSelectorNode from './ColorSelectorNode';
|
||||||
|
|
||||||
const onPaneReady = (reactFlowInstance: ReactFlowInstance) => {
|
const onInit = (reactFlowInstance: ReactFlowInstance) => {
|
||||||
console.log('flow loaded:', reactFlowInstance);
|
console.log('flow loaded:', reactFlowInstance);
|
||||||
reactFlowInstance.fitView();
|
reactFlowInstance.fitView();
|
||||||
};
|
};
|
||||||
@@ -111,13 +111,13 @@ const CustomNodeFlow = () => {
|
|||||||
onConnect={onConnect}
|
onConnect={onConnect}
|
||||||
onNodeDragStop={onNodeDragStop}
|
onNodeDragStop={onNodeDragStop}
|
||||||
style={{ background: bgColor }}
|
style={{ background: bgColor }}
|
||||||
onPaneReady={onPaneReady}
|
onInit={onInit}
|
||||||
nodeTypes={nodeTypes}
|
nodeTypes={nodeTypes}
|
||||||
connectionLineStyle={connectionLineStyle}
|
connectionLineStyle={connectionLineStyle}
|
||||||
snapToGrid={true}
|
snapToGrid={true}
|
||||||
snapGrid={snapGrid}
|
snapGrid={snapGrid}
|
||||||
defaultZoom={1.5}
|
defaultZoom={1.5}
|
||||||
fitViewOnInit
|
fitView
|
||||||
>
|
>
|
||||||
<MiniMap
|
<MiniMap
|
||||||
nodeStrokeColor={(n: Node): string => {
|
nodeStrokeColor={(n: Node): string => {
|
||||||
|
|||||||
@@ -55,12 +55,7 @@ const DefaultNodes = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ReactFlow
|
<ReactFlow defaultNodes={defaultNodes} defaultEdges={defaultEdges} defaultEdgeOptions={defaultEdgeOptions} fitView>
|
||||||
defaultNodes={defaultNodes}
|
|
||||||
defaultEdges={defaultEdges}
|
|
||||||
defaultEdgeOptions={defaultEdgeOptions}
|
|
||||||
fitViewOnInit
|
|
||||||
>
|
|
||||||
<Background variant={BackgroundVariant.Lines} />
|
<Background variant={BackgroundVariant.Lines} />
|
||||||
|
|
||||||
<div style={{ position: 'absolute', right: 10, top: 10, zIndex: 4 }}>
|
<div style={{ position: 'absolute', right: 10, top: 10, zIndex: 4 }}>
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ const DnDFlow = () => {
|
|||||||
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
|
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
|
||||||
|
|
||||||
const onConnect = (params: Connection | Edge) => setEdges((eds) => addEdge(params, eds));
|
const onConnect = (params: Connection | Edge) => setEdges((eds) => addEdge(params, eds));
|
||||||
const onPaneReady = (rfi: ReactFlowInstance) => setReactFlowInstance(rfi);
|
const onInit = (rfi: ReactFlowInstance) => setReactFlowInstance(rfi);
|
||||||
|
|
||||||
const onDrop = (event: DragEvent) => {
|
const onDrop = (event: DragEvent) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@@ -60,7 +60,7 @@ const DnDFlow = () => {
|
|||||||
onEdgesChange={onEdgesChange}
|
onEdgesChange={onEdgesChange}
|
||||||
onNodesChange={onNodesChange}
|
onNodesChange={onNodesChange}
|
||||||
onConnect={onConnect}
|
onConnect={onConnect}
|
||||||
onPaneReady={onPaneReady}
|
onInit={onInit}
|
||||||
onDrop={onDrop}
|
onDrop={onDrop}
|
||||||
onDragOver={onDragOver}
|
onDragOver={onDragOver}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import ReactFlow, {
|
|||||||
} from 'react-flow-renderer';
|
} from 'react-flow-renderer';
|
||||||
import { getElements } from './utils';
|
import { getElements } from './utils';
|
||||||
|
|
||||||
const onPaneReady = (reactFlowInstance: ReactFlowInstance) => {
|
const onInit = (reactFlowInstance: ReactFlowInstance) => {
|
||||||
reactFlowInstance.fitView();
|
reactFlowInstance.fitView();
|
||||||
console.log(reactFlowInstance.getNodes());
|
console.log(reactFlowInstance.getNodes());
|
||||||
};
|
};
|
||||||
@@ -36,7 +36,7 @@ const EdgeTypesFlow = () => {
|
|||||||
edges={edges}
|
edges={edges}
|
||||||
onNodesChange={onNodesChange}
|
onNodesChange={onNodesChange}
|
||||||
onEdgesChange={onEdgesChange}
|
onEdgesChange={onEdgesChange}
|
||||||
onPaneReady={onPaneReady}
|
onInit={onInit}
|
||||||
onConnect={onConnect}
|
onConnect={onConnect}
|
||||||
minZoom={0.2}
|
minZoom={0.2}
|
||||||
zoomOnScroll={false}
|
zoomOnScroll={false}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import ReactFlow, {
|
|||||||
import CustomEdge from './CustomEdge';
|
import CustomEdge from './CustomEdge';
|
||||||
import CustomEdge2 from './CustomEdge2';
|
import CustomEdge2 from './CustomEdge2';
|
||||||
|
|
||||||
const onPaneReady = (reactFlowInstance: ReactFlowInstance) => reactFlowInstance.fitView();
|
const onInit = (reactFlowInstance: ReactFlowInstance) => reactFlowInstance.fitView();
|
||||||
const onNodeDragStop = (_: MouseEvent, node: Node) => console.log('drag stop', node);
|
const onNodeDragStop = (_: MouseEvent, node: Node) => console.log('drag stop', node);
|
||||||
const onNodeClick = (_: MouseEvent, node: Node) => console.log('click', node);
|
const onNodeClick = (_: MouseEvent, node: Node) => console.log('click', node);
|
||||||
|
|
||||||
@@ -121,7 +121,7 @@ const EdgesFlow = () => {
|
|||||||
onNodeClick={onNodeClick}
|
onNodeClick={onNodeClick}
|
||||||
onConnect={onConnect}
|
onConnect={onConnect}
|
||||||
onNodeDragStop={onNodeDragStop}
|
onNodeDragStop={onNodeDragStop}
|
||||||
onPaneReady={onPaneReady}
|
onInit={onInit}
|
||||||
snapToGrid={true}
|
snapToGrid={true}
|
||||||
edgeTypes={edgeTypes}
|
edgeTypes={edgeTypes}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import ReactFlow, {
|
|||||||
ReactFlowInstance,
|
ReactFlowInstance,
|
||||||
} from 'react-flow-renderer';
|
} from 'react-flow-renderer';
|
||||||
|
|
||||||
const onPaneReady = (reactFlowInstance: ReactFlowInstance) => console.log('flow loaded:', reactFlowInstance);
|
const onInit = (reactFlowInstance: ReactFlowInstance) => console.log('flow loaded:', reactFlowInstance);
|
||||||
const onNodeClick = (_: MouseEvent, node: Node) => console.log('click', node);
|
const onNodeClick = (_: MouseEvent, node: Node) => console.log('click', node);
|
||||||
const onNodeDragStop = (_: MouseEvent, node: Node) => console.log('drag stop', node);
|
const onNodeDragStop = (_: MouseEvent, node: Node) => console.log('drag stop', node);
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ const EmptyFlow = () => {
|
|||||||
<ReactFlow
|
<ReactFlow
|
||||||
nodes={nodes}
|
nodes={nodes}
|
||||||
edges={edges}
|
edges={edges}
|
||||||
onPaneReady={onPaneReady}
|
onInit={onInit}
|
||||||
onNodesChange={onNodesChange}
|
onNodesChange={onNodesChange}
|
||||||
onEdgesChange={onEdgesChange}
|
onEdgesChange={onEdgesChange}
|
||||||
onNodeClick={onNodeClick}
|
onNodeClick={onNodeClick}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import FloatingEdge from './FloatingEdge';
|
|||||||
import FloatingConnectionLine from './FloatingConnectionLine';
|
import FloatingConnectionLine from './FloatingConnectionLine';
|
||||||
import { createElements } from './utils';
|
import { createElements } from './utils';
|
||||||
|
|
||||||
const onPaneReady = (reactFlowInstance: ReactFlowInstance) => reactFlowInstance.fitView();
|
const onInit = (reactFlowInstance: ReactFlowInstance) => reactFlowInstance.fitView();
|
||||||
|
|
||||||
const { nodes: initialNodes, edges: initialEdges } = createElements();
|
const { nodes: initialNodes, edges: initialEdges } = createElements();
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ const FloatingEdges = () => {
|
|||||||
onNodesChange={onNodesChange}
|
onNodesChange={onNodesChange}
|
||||||
onEdgesChange={onEdgesChange}
|
onEdgesChange={onEdgesChange}
|
||||||
onConnect={onConnect}
|
onConnect={onConnect}
|
||||||
onPaneReady={onPaneReady}
|
onInit={onInit}
|
||||||
edgeTypes={edgeTypes}
|
edgeTypes={edgeTypes}
|
||||||
connectionLineComponent={FloatingConnectionLine}
|
connectionLineComponent={FloatingConnectionLine}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ const LayoutFlow = () => {
|
|||||||
edges={edges}
|
edges={edges}
|
||||||
onConnect={onConnect}
|
onConnect={onConnect}
|
||||||
nodeExtent={nodeExtent}
|
nodeExtent={nodeExtent}
|
||||||
onPaneReady={() => onLayout('TB')}
|
onInit={() => onLayout('TB')}
|
||||||
onNodesChange={onNodesChange}
|
onNodesChange={onNodesChange}
|
||||||
onEdgesChange={onEdgesChange}
|
onEdgesChange={onEdgesChange}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ const NestedFlow = () => {
|
|||||||
const onConnect = useCallback((connection: Connection) => {
|
const onConnect = useCallback((connection: Connection) => {
|
||||||
setEdges((eds) => addEdge(connection, eds));
|
setEdges((eds) => addEdge(connection, eds));
|
||||||
}, []);
|
}, []);
|
||||||
const onPaneReady = useCallback((reactFlowInstance: ReactFlowInstance) => setRfInstance(reactFlowInstance), []);
|
const onInit = useCallback((reactFlowInstance: ReactFlowInstance) => setRfInstance(reactFlowInstance), []);
|
||||||
|
|
||||||
const updatePos = () => {
|
const updatePos = () => {
|
||||||
setNodes((nds) => {
|
setNodes((nds) => {
|
||||||
@@ -131,7 +131,7 @@ const NestedFlow = () => {
|
|||||||
<ReactFlow
|
<ReactFlow
|
||||||
nodes={nodes}
|
nodes={nodes}
|
||||||
edges={edges}
|
edges={edges}
|
||||||
onPaneReady={onPaneReady}
|
onInit={onInit}
|
||||||
onNodesChange={onNodesChange}
|
onNodesChange={onNodesChange}
|
||||||
onEdgesChange={onEdgesChange}
|
onEdgesChange={onEdgesChange}
|
||||||
onNodeClick={onNodeClick}
|
onNodeClick={onNodeClick}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ const NodeTypeChangeFlow = () => {
|
|||||||
onNodesChange={onNodesChange}
|
onNodesChange={onNodesChange}
|
||||||
onEdgesChange={onEdgesChange}
|
onEdgesChange={onEdgesChange}
|
||||||
onConnect={onConnect}
|
onConnect={onConnect}
|
||||||
fitViewOnInit
|
fitView
|
||||||
>
|
>
|
||||||
<button onClick={changeType} style={buttonStyle}>
|
<button onClick={changeType} style={buttonStyle}>
|
||||||
change type
|
change type
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ const onSelectionContextMenu = (event: MouseEvent, nodes: Node[]) => {
|
|||||||
const onNodeClick = (_: MouseEvent, node: Node) => console.log('node click:', node);
|
const onNodeClick = (_: MouseEvent, node: Node) => console.log('node click:', node);
|
||||||
|
|
||||||
const onSelectionChange = ({ nodes, edges }: OnSelectionChangeParams) => console.log('selection change', nodes, edges);
|
const onSelectionChange = ({ nodes, edges }: OnSelectionChangeParams) => console.log('selection change', nodes, edges);
|
||||||
const onPaneReady = (reactFlowInstance: ReactFlowInstance) => {
|
const onInit = (reactFlowInstance: ReactFlowInstance) => {
|
||||||
console.log('pane ready:', reactFlowInstance);
|
console.log('pane ready:', reactFlowInstance);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -183,7 +183,7 @@ const OverviewFlow = () => {
|
|||||||
onSelectionChange={onSelectionChange}
|
onSelectionChange={onSelectionChange}
|
||||||
onMoveStart={onMoveStart}
|
onMoveStart={onMoveStart}
|
||||||
onMoveEnd={onMoveEnd}
|
onMoveEnd={onMoveEnd}
|
||||||
onPaneReady={onPaneReady}
|
onInit={onInit}
|
||||||
connectionLineStyle={connectionLineStyle}
|
connectionLineStyle={connectionLineStyle}
|
||||||
snapToGrid={true}
|
snapToGrid={true}
|
||||||
snapGrid={snapGrid}
|
snapGrid={snapGrid}
|
||||||
@@ -192,8 +192,10 @@ const OverviewFlow = () => {
|
|||||||
onEdgeMouseMove={onEdgeMouseMove}
|
onEdgeMouseMove={onEdgeMouseMove}
|
||||||
onEdgeMouseLeave={onEdgeMouseLeave}
|
onEdgeMouseLeave={onEdgeMouseLeave}
|
||||||
onEdgeDoubleClick={onEdgeDoubleClick}
|
onEdgeDoubleClick={onEdgeDoubleClick}
|
||||||
fitViewOnInit
|
fitView
|
||||||
|
fitViewOptions={{ padding: 0.2 }}
|
||||||
attributionPosition="top-right"
|
attributionPosition="top-right"
|
||||||
|
maxZoom={Infinity}
|
||||||
>
|
>
|
||||||
<MiniMap nodeStrokeColor={nodeStrokeColor} nodeColor={nodeColor} nodeBorderRadius={2} />
|
<MiniMap nodeStrokeColor={nodeStrokeColor} nodeColor={nodeColor} nodeBorderRadius={2} />
|
||||||
<Controls />
|
<Controls />
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import Sidebar from './Sidebar';
|
|||||||
import './provider.css';
|
import './provider.css';
|
||||||
|
|
||||||
const onNodeClick = (_: MouseEvent, node: Node) => console.log('click', node);
|
const onNodeClick = (_: MouseEvent, node: Node) => console.log('click', node);
|
||||||
const onPaneReady = (reactFlowInstance: ReactFlowInstance) => console.log('pane ready:', reactFlowInstance);
|
const onInit = (reactFlowInstance: ReactFlowInstance) => console.log('pane ready:', reactFlowInstance);
|
||||||
|
|
||||||
const initialNodes: Node[] = [
|
const initialNodes: Node[] = [
|
||||||
{ id: '1', type: 'input', data: { label: 'Node 1' }, position: { x: 250, y: 5 } },
|
{ id: '1', type: 'input', data: { label: 'Node 1' }, position: { x: 250, y: 5 } },
|
||||||
@@ -48,7 +48,7 @@ const ProviderFlow = () => {
|
|||||||
onEdgesChange={onEdgesChange}
|
onEdgesChange={onEdgesChange}
|
||||||
onNodeClick={onNodeClick}
|
onNodeClick={onNodeClick}
|
||||||
onConnect={onConnect}
|
onConnect={onConnect}
|
||||||
onPaneReady={onPaneReady}
|
onInit={onInit}
|
||||||
connectionMode={ConnectionMode.Loose}
|
connectionMode={ConnectionMode.Loose}
|
||||||
>
|
>
|
||||||
<Controls />
|
<Controls />
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ const SaveRestore = () => {
|
|||||||
onNodesChange={onNodesChange}
|
onNodesChange={onNodesChange}
|
||||||
onEdgesChange={onEdgesChange}
|
onEdgesChange={onEdgesChange}
|
||||||
onConnect={onConnect}
|
onConnect={onConnect}
|
||||||
onPaneReady={setRfInstance}
|
onInit={setRfInstance}
|
||||||
>
|
>
|
||||||
<Controls rfInstance={rfInstance} setNodes={setNodes} setEdges={setEdges} />
|
<Controls rfInstance={rfInstance} setNodes={setNodes} setEdges={setEdges} />
|
||||||
</ReactFlow>
|
</ReactFlow>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { getNodesAndEdges } from './utils';
|
|||||||
|
|
||||||
const buttonWrapperStyles: CSSProperties = { position: 'absolute', right: 10, top: 10, zIndex: 4 };
|
const buttonWrapperStyles: CSSProperties = { position: 'absolute', right: 10, top: 10, zIndex: 4 };
|
||||||
|
|
||||||
const onPaneReady = (reactFlowInstance: ReactFlowInstance) => {
|
const onInit = (reactFlowInstance: ReactFlowInstance) => {
|
||||||
reactFlowInstance.fitView();
|
reactFlowInstance.fitView();
|
||||||
console.log(reactFlowInstance.getNodes());
|
console.log(reactFlowInstance.getNodes());
|
||||||
};
|
};
|
||||||
@@ -55,13 +55,7 @@ const StressFlow = () => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ReactFlow
|
<ReactFlow nodes={nodes} edges={edges} onInit={onInit} onConnect={onConnect} onNodesChange={onNodesChange}>
|
||||||
nodes={nodes}
|
|
||||||
edges={edges}
|
|
||||||
onPaneReady={onPaneReady}
|
|
||||||
onConnect={onConnect}
|
|
||||||
onNodesChange={onNodesChange}
|
|
||||||
>
|
|
||||||
<MiniMap />
|
<MiniMap />
|
||||||
<Controls />
|
<Controls />
|
||||||
<Background />
|
<Background />
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ const BasicFlow = () => {
|
|||||||
const onConnect = useCallback((connection: Connection) => {
|
const onConnect = useCallback((connection: Connection) => {
|
||||||
setEdges((eds) => addEdge(connection, eds));
|
setEdges((eds) => addEdge(connection, eds));
|
||||||
}, []);
|
}, []);
|
||||||
const onPaneReady = useCallback((reactFlowInstance: ReactFlowInstance) => setRfInstance(reactFlowInstance), []);
|
const onInit = useCallback((reactFlowInstance: ReactFlowInstance) => setRfInstance(reactFlowInstance), []);
|
||||||
|
|
||||||
const updatePos = () => {
|
const updatePos = () => {
|
||||||
setNodes((nds) => {
|
setNodes((nds) => {
|
||||||
@@ -155,7 +155,7 @@ const BasicFlow = () => {
|
|||||||
<ReactFlow
|
<ReactFlow
|
||||||
nodes={nodes}
|
nodes={nodes}
|
||||||
edges={edges}
|
edges={edges}
|
||||||
onPaneReady={onPaneReady}
|
onInit={onInit}
|
||||||
onNodesChange={onNodesChange}
|
onNodesChange={onNodesChange}
|
||||||
onEdgesChange={onEdgesChange}
|
onEdgesChange={onEdgesChange}
|
||||||
onNodeClick={onNodeClick}
|
onNodeClick={onNodeClick}
|
||||||
@@ -168,7 +168,7 @@ const BasicFlow = () => {
|
|||||||
maxZoom={4}
|
maxZoom={4}
|
||||||
onlyRenderVisibleElements={false}
|
onlyRenderVisibleElements={false}
|
||||||
nodeTypes={nodeTypes}
|
nodeTypes={nodeTypes}
|
||||||
fitViewOnInit
|
fitView
|
||||||
>
|
>
|
||||||
<MiniMap />
|
<MiniMap />
|
||||||
<Controls />
|
<Controls />
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ const initialNodes: Node[] = [
|
|||||||
|
|
||||||
const initialEdges = [{ id: 'e1-2', source: '1', target: '2', label: 'This is a draggable edge' }];
|
const initialEdges = [{ id: 'e1-2', source: '1', target: '2', label: 'This is a draggable edge' }];
|
||||||
|
|
||||||
const onPaneReady = (reactFlowInstance: ReactFlowInstance) => reactFlowInstance.fitView();
|
const onInit = (reactFlowInstance: ReactFlowInstance) => reactFlowInstance.fitView();
|
||||||
const onEdgeUpdateStart = (_: React.MouseEvent, edge: Edge) => console.log('start update', edge);
|
const onEdgeUpdateStart = (_: React.MouseEvent, edge: Edge) => console.log('start update', edge);
|
||||||
const onEdgeUpdateEnd = (_: MouseEvent, edge: Edge) => console.log('end update', edge);
|
const onEdgeUpdateEnd = (_: MouseEvent, edge: Edge) => console.log('end update', edge);
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ const UpdatableEdge = () => {
|
|||||||
edges={edges}
|
edges={edges}
|
||||||
onNodesChange={onNodesChange}
|
onNodesChange={onNodesChange}
|
||||||
onEdgesChange={onEdgesChange}
|
onEdgesChange={onEdgesChange}
|
||||||
onPaneReady={onPaneReady}
|
onInit={onInit}
|
||||||
snapToGrid={true}
|
snapToGrid={true}
|
||||||
onEdgeUpdate={onEdgeUpdate}
|
onEdgeUpdate={onEdgeUpdate}
|
||||||
onConnect={onConnect}
|
onConnect={onConnect}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ const UseZoomPanHelperFlow = () => {
|
|||||||
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
|
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
|
||||||
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
|
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
|
||||||
const onConnect = (params: Connection | Edge) => setEdges((eds) => addEdge(params, eds));
|
const onConnect = (params: Connection | Edge) => setEdges((eds) => addEdge(params, eds));
|
||||||
const { project, setCenter, zoomIn, zoomOut } = useReactFlow();
|
const { project, setCenter, zoomIn, zoomOut, fitView } = useReactFlow();
|
||||||
|
|
||||||
const onPaneClick = useCallback(
|
const onPaneClick = useCallback(
|
||||||
(evt) => {
|
(evt) => {
|
||||||
@@ -55,7 +55,7 @@ const UseZoomPanHelperFlow = () => {
|
|||||||
const onNodeClick = useCallback(
|
const onNodeClick = useCallback(
|
||||||
(_, element) => {
|
(_, element) => {
|
||||||
const { x, y } = element.position;
|
const { x, y } = element.position;
|
||||||
setCenter(x, y, { zoom: 1 });
|
setCenter(x, y, { zoom: 1, duration: 1200 });
|
||||||
},
|
},
|
||||||
[setCenter]
|
[setCenter]
|
||||||
);
|
);
|
||||||
@@ -69,10 +69,14 @@ const UseZoomPanHelperFlow = () => {
|
|||||||
onNodeClick={onNodeClick}
|
onNodeClick={onNodeClick}
|
||||||
onConnect={onConnect}
|
onConnect={onConnect}
|
||||||
onPaneClick={onPaneClick}
|
onPaneClick={onPaneClick}
|
||||||
|
fitView
|
||||||
|
fitViewOptions={{ duration: 1200, padding: 0.2 }}
|
||||||
|
maxZoom={Infinity}
|
||||||
>
|
>
|
||||||
<div style={{ position: 'absolute', left: 0, top: 0, zIndex: 100 }}>
|
<div style={{ position: 'absolute', left: 0, top: 0, zIndex: 100 }}>
|
||||||
<button onClick={() => zoomIn({ duration: 1200 })}>zoomIn</button>
|
<button onClick={() => zoomIn({ duration: 1200 })}>zoomIn</button>
|
||||||
<button onClick={() => zoomOut({ duration: 0 })}>zoomOut</button>
|
<button onClick={() => zoomOut({ duration: 0 })}>zoomOut</button>
|
||||||
|
<button onClick={() => fitView({ duration: 1200, padding: 0.3 })}>fitView</button>
|
||||||
</div>
|
</div>
|
||||||
<Background />
|
<Background />
|
||||||
<MiniMap />
|
<MiniMap />
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ const ValidationFlow = () => {
|
|||||||
onConnectStart={onConnectStart}
|
onConnectStart={onConnectStart}
|
||||||
onConnectStop={onConnectStop}
|
onConnectStop={onConnectStop}
|
||||||
onConnectEnd={onConnectEnd}
|
onConnectEnd={onConnectEnd}
|
||||||
fitViewOnInit
|
fitView
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Generated
+1
-1
@@ -14,7 +14,7 @@
|
|||||||
"d3-selection": "^3.0.0",
|
"d3-selection": "^3.0.0",
|
||||||
"d3-zoom": "^3.0.0",
|
"d3-zoom": "^3.0.0",
|
||||||
"react-draggable": "^4.4.4",
|
"react-draggable": "^4.4.4",
|
||||||
"zustand": "^3.6.7"
|
"zustand": "^3.6.9"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.16.5",
|
"@babel/core": "^7.16.5",
|
||||||
|
|||||||
+1
-1
@@ -36,7 +36,7 @@
|
|||||||
"d3-selection": "^3.0.0",
|
"d3-selection": "^3.0.0",
|
||||||
"d3-zoom": "^3.0.0",
|
"d3-zoom": "^3.0.0",
|
||||||
"react-draggable": "^4.4.4",
|
"react-draggable": "^4.4.4",
|
||||||
"zustand": "^3.6.7"
|
"zustand": "^3.6.9"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.16.5",
|
"@babel/core": "^7.16.5",
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ const Controls: FC<ControlProps> = ({
|
|||||||
showZoom = true,
|
showZoom = true,
|
||||||
showFitView = true,
|
showFitView = true,
|
||||||
showInteractive = true,
|
showInteractive = true,
|
||||||
fitViewParams,
|
fitViewOptions,
|
||||||
onZoomIn,
|
onZoomIn,
|
||||||
onZoomOut,
|
onZoomOut,
|
||||||
onFitView,
|
onFitView,
|
||||||
@@ -51,9 +51,9 @@ const Controls: FC<ControlProps> = ({
|
|||||||
}, [zoomOut, onZoomOut]);
|
}, [zoomOut, onZoomOut]);
|
||||||
|
|
||||||
const onFitViewHandler = useCallback(() => {
|
const onFitViewHandler = useCallback(() => {
|
||||||
fitView?.(fitViewParams);
|
fitView?.(fitViewOptions);
|
||||||
onFitView?.();
|
onFitView?.();
|
||||||
}, [fitView, fitViewParams, onFitView]);
|
}, [fitView, fitViewOptions, onFitView]);
|
||||||
|
|
||||||
const onInteractiveChangeHandler = useCallback(() => {
|
const onInteractiveChangeHandler = useCallback(() => {
|
||||||
store.setState({
|
store.setState({
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import shallow from 'zustand/shallow';
|
|||||||
import MiniMapNode from './MiniMapNode';
|
import MiniMapNode from './MiniMapNode';
|
||||||
|
|
||||||
import { useStore } from '../../store';
|
import { useStore } from '../../store';
|
||||||
import { getRectOfNodeInternals } from '../../utils/graph';
|
import { getRectOfNodes } from '../../utils/graph';
|
||||||
import { getBoundsofRects } from '../../utils';
|
import { getBoundsofRects } from '../../utils';
|
||||||
|
|
||||||
import { MiniMapProps, GetMiniMapNodeAttribute, ReactFlowState, Rect } from '../../types';
|
import { MiniMapProps, GetMiniMapNodeAttribute, ReactFlowState, Rect } from '../../types';
|
||||||
@@ -48,7 +48,7 @@ const MiniMap = ({
|
|||||||
const hasNodes = nodeInternals && nodeInternals.size > 0;
|
const hasNodes = nodeInternals && nodeInternals.size > 0;
|
||||||
// @TODO: work with nodeInternals instead of converting it to an array
|
// @TODO: work with nodeInternals instead of converting it to an array
|
||||||
const nodes = Array.from(nodeInternals).map(([_, node]) => node);
|
const nodes = Array.from(nodeInternals).map(([_, node]) => node);
|
||||||
const bb = getRectOfNodeInternals(nodes);
|
const bb = getRectOfNodes(nodes);
|
||||||
const viewBB: Rect = {
|
const viewBB: Rect = {
|
||||||
x: -tX / tScale,
|
x: -tX / tScale,
|
||||||
y: -tY / tScale,
|
y: -tY / tScale,
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ import cc from 'classcat';
|
|||||||
import { AttributionPosition, ProOptions } from '../../types';
|
import { AttributionPosition, ProOptions } from '../../types';
|
||||||
|
|
||||||
type AttributionProps = {
|
type AttributionProps = {
|
||||||
pro?: ProOptions;
|
proOptions?: ProOptions;
|
||||||
position?: AttributionPosition;
|
position?: AttributionPosition;
|
||||||
};
|
};
|
||||||
|
|
||||||
function Attribution({ pro, position = 'bottom-right' }: AttributionProps) {
|
function Attribution({ proOptions, position = 'bottom-right' }: AttributionProps) {
|
||||||
if (pro?.account === 'paid-subscription' && pro?.hideAttribution) {
|
if (proOptions?.account === 'paid-subscription' && proOptions?.hideAttribution) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ export default (NodeComponent: ComponentType<NodeProps>) => {
|
|||||||
sourcePosition,
|
sourcePosition,
|
||||||
targetPosition,
|
targetPosition,
|
||||||
hidden,
|
hidden,
|
||||||
isInitialized,
|
|
||||||
snapToGrid,
|
snapToGrid,
|
||||||
snapGrid,
|
snapGrid,
|
||||||
dragging,
|
dragging,
|
||||||
@@ -60,11 +59,9 @@ export default (NodeComponent: ComponentType<NodeProps>) => {
|
|||||||
zIndex,
|
zIndex,
|
||||||
transform: `translate(${xPos}px,${yPos}px)`,
|
transform: `translate(${xPos}px,${yPos}px)`,
|
||||||
pointerEvents: hasPointerEvents ? 'all' : 'none',
|
pointerEvents: hasPointerEvents ? 'all' : 'none',
|
||||||
// prevents jumping of nodes on start
|
|
||||||
opacity: isInitialized ? 1 : 0,
|
|
||||||
...style,
|
...style,
|
||||||
}),
|
}),
|
||||||
[zIndex, xPos, yPos, hasPointerEvents, isInitialized, style]
|
[zIndex, xPos, yPos, hasPointerEvents, style]
|
||||||
);
|
);
|
||||||
|
|
||||||
const node = useMemo(() => ({ id, type, position: { x: xPos, y: yPos }, data }), [id, type, xPos, yPos, data]);
|
const node = useMemo(() => ({ id, type, position: { x: xPos, y: yPos }, data }), [id, type, xPos, yPos, data]);
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import shallow from 'zustand/shallow';
|
|||||||
|
|
||||||
import { useStore } from '../../store';
|
import { useStore } from '../../store';
|
||||||
import { Node, ReactFlowState } from '../../types';
|
import { Node, ReactFlowState } from '../../types';
|
||||||
import { getRectOfNodeInternals } from '../../utils/graph';
|
import { getRectOfNodes } from '../../utils/graph';
|
||||||
|
|
||||||
export interface NodesSelectionProps {
|
export interface NodesSelectionProps {
|
||||||
onSelectionDragStart?: (event: MouseEvent, nodes: Node[]) => void;
|
onSelectionDragStart?: (event: MouseEvent, nodes: Node[]) => void;
|
||||||
@@ -55,7 +55,7 @@ function NodesSelection({
|
|||||||
[tX, tY, tScale]
|
[tX, tY, tScale]
|
||||||
);
|
);
|
||||||
|
|
||||||
const selectedNodesBbox = useMemo(() => getRectOfNodeInternals(selectedNodes), [selectedNodes]);
|
const selectedNodesBbox = useMemo(() => getRectOfNodes(selectedNodes), [selectedNodes]);
|
||||||
|
|
||||||
const innerStyle = useMemo(
|
const innerStyle = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import {
|
|||||||
ConnectionMode,
|
ConnectionMode,
|
||||||
SnapGrid,
|
SnapGrid,
|
||||||
DefaultEdgeOptions,
|
DefaultEdgeOptions,
|
||||||
|
FitViewOptions,
|
||||||
} from '../../types';
|
} from '../../types';
|
||||||
|
|
||||||
interface StoreUpdaterProps {
|
interface StoreUpdaterProps {
|
||||||
@@ -40,9 +41,10 @@ interface StoreUpdaterProps {
|
|||||||
snapToGrid?: boolean;
|
snapToGrid?: boolean;
|
||||||
snapGrid?: SnapGrid;
|
snapGrid?: SnapGrid;
|
||||||
translateExtent?: CoordinateExtent;
|
translateExtent?: CoordinateExtent;
|
||||||
fitViewOnInit: boolean;
|
|
||||||
connectOnClick: boolean;
|
connectOnClick: boolean;
|
||||||
defaultEdgeOptions?: DefaultEdgeOptions;
|
defaultEdgeOptions?: DefaultEdgeOptions;
|
||||||
|
fitView?: boolean;
|
||||||
|
fitViewOptions?: FitViewOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
const selector = (s: ReactFlowState) => ({
|
const selector = (s: ReactFlowState) => ({
|
||||||
@@ -94,9 +96,10 @@ const StoreUpdater = ({
|
|||||||
snapGrid,
|
snapGrid,
|
||||||
snapToGrid,
|
snapToGrid,
|
||||||
translateExtent,
|
translateExtent,
|
||||||
fitViewOnInit,
|
|
||||||
connectOnClick,
|
connectOnClick,
|
||||||
defaultEdgeOptions,
|
defaultEdgeOptions,
|
||||||
|
fitView,
|
||||||
|
fitViewOptions,
|
||||||
}: StoreUpdaterProps) => {
|
}: StoreUpdaterProps) => {
|
||||||
const {
|
const {
|
||||||
setNodes,
|
setNodes,
|
||||||
@@ -127,12 +130,13 @@ const StoreUpdater = ({
|
|||||||
useDirectStoreUpdater('nodesDraggable', nodesDraggable, store.setState);
|
useDirectStoreUpdater('nodesDraggable', nodesDraggable, store.setState);
|
||||||
useDirectStoreUpdater('nodesConnectable', nodesConnectable, store.setState);
|
useDirectStoreUpdater('nodesConnectable', nodesConnectable, store.setState);
|
||||||
useDirectStoreUpdater('elementsSelectable', elementsSelectable, store.setState);
|
useDirectStoreUpdater('elementsSelectable', elementsSelectable, store.setState);
|
||||||
useDirectStoreUpdater('fitViewOnInit', fitViewOnInit, store.setState);
|
|
||||||
useDirectStoreUpdater('snapToGrid', snapToGrid, store.setState);
|
useDirectStoreUpdater('snapToGrid', snapToGrid, store.setState);
|
||||||
useDirectStoreUpdater('snapGrid', snapGrid, store.setState);
|
useDirectStoreUpdater('snapGrid', snapGrid, store.setState);
|
||||||
useDirectStoreUpdater('onNodesChange', onNodesChange, store.setState);
|
useDirectStoreUpdater('onNodesChange', onNodesChange, store.setState);
|
||||||
useDirectStoreUpdater('onEdgesChange', onEdgesChange, store.setState);
|
useDirectStoreUpdater('onEdgesChange', onEdgesChange, store.setState);
|
||||||
useDirectStoreUpdater('connectOnClick', connectOnClick, store.setState);
|
useDirectStoreUpdater('connectOnClick', connectOnClick, store.setState);
|
||||||
|
useDirectStoreUpdater('fitViewOnInit', fitView, store.setState);
|
||||||
|
useDirectStoreUpdater('fitViewOnInitOptions', fitViewOptions, store.setState);
|
||||||
|
|
||||||
useStoreUpdater<Node[]>(nodes, setNodes);
|
useStoreUpdater<Node[]>(nodes, setNodes);
|
||||||
useStoreUpdater<Edge[]>(edges, setEdges);
|
useStoreUpdater<Edge[]>(edges, setEdges);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import FlowRenderer from '../FlowRenderer';
|
|||||||
import NodeRenderer from '../NodeRenderer';
|
import NodeRenderer from '../NodeRenderer';
|
||||||
import EdgeRenderer from '../EdgeRenderer';
|
import EdgeRenderer from '../EdgeRenderer';
|
||||||
import Viewport from '../Viewport';
|
import Viewport from '../Viewport';
|
||||||
import useOnPaneReadyHandler from '../../hooks/useOnPaneReadyHandler';
|
import useOnInitHandler from '../../hooks/useOnInitHandler';
|
||||||
import { NodeTypesType, EdgeTypesType, ConnectionLineType, KeyCode, ReactFlowProps } from '../../types';
|
import { NodeTypesType, EdgeTypesType, ConnectionLineType, KeyCode, ReactFlowProps } from '../../types';
|
||||||
|
|
||||||
export interface GraphViewProps extends Omit<ReactFlowProps, 'onSelectionChange' | 'nodes' | 'edges'> {
|
export interface GraphViewProps extends Omit<ReactFlowProps, 'onSelectionChange' | 'nodes' | 'edges'> {
|
||||||
@@ -30,7 +30,7 @@ const GraphView = ({
|
|||||||
onMove,
|
onMove,
|
||||||
onMoveStart,
|
onMoveStart,
|
||||||
onMoveEnd,
|
onMoveEnd,
|
||||||
onPaneReady,
|
onInit,
|
||||||
onNodeClick,
|
onNodeClick,
|
||||||
onEdgeClick,
|
onEdgeClick,
|
||||||
onNodeDoubleClick,
|
onNodeDoubleClick,
|
||||||
@@ -82,7 +82,7 @@ const GraphView = ({
|
|||||||
noWheelClassName,
|
noWheelClassName,
|
||||||
noPanClassName,
|
noPanClassName,
|
||||||
}: GraphViewProps) => {
|
}: GraphViewProps) => {
|
||||||
useOnPaneReadyHandler(onPaneReady);
|
useOnInitHandler(onInit);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FlowRenderer
|
<FlowRenderer
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ const NodeRenderer = (props: NodeRendererProps) => {
|
|||||||
const { scale, nodesDraggable, nodesConnectable, elementsSelectable, updateNodeDimensions, snapGrid, snapToGrid } =
|
const { scale, nodesDraggable, nodesConnectable, elementsSelectable, updateNodeDimensions, snapGrid, snapToGrid } =
|
||||||
useStore(selector, shallow);
|
useStore(selector, shallow);
|
||||||
const nodes = useVisibleNodes(props.onlyRenderVisibleElements);
|
const nodes = useVisibleNodes(props.onlyRenderVisibleElements);
|
||||||
const reseizeObserverRef = useRef<ResizeObserver>();
|
const resizeObserverRef = useRef<ResizeObserver>();
|
||||||
|
|
||||||
const resizeObserver = useMemo(() => {
|
const resizeObserver = useMemo(() => {
|
||||||
if (typeof ResizeObserver === 'undefined') {
|
if (typeof ResizeObserver === 'undefined') {
|
||||||
@@ -54,14 +54,14 @@ const NodeRenderer = (props: NodeRendererProps) => {
|
|||||||
updateNodeDimensions(updates);
|
updateNodeDimensions(updates);
|
||||||
});
|
});
|
||||||
|
|
||||||
reseizeObserverRef.current = observer;
|
resizeObserverRef.current = observer;
|
||||||
|
|
||||||
return observer;
|
return observer;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => {
|
return () => {
|
||||||
reseizeObserverRef?.current?.disconnect();
|
resizeObserverRef?.current?.disconnect();
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -78,8 +78,6 @@ const NodeRenderer = (props: NodeRendererProps) => {
|
|||||||
const isDraggable = !!(node.draggable || (nodesDraggable && typeof node.draggable === 'undefined'));
|
const isDraggable = !!(node.draggable || (nodesDraggable && typeof node.draggable === 'undefined'));
|
||||||
const isSelectable = !!(node.selectable || (elementsSelectable && typeof node.selectable === 'undefined'));
|
const isSelectable = !!(node.selectable || (elementsSelectable && typeof node.selectable === 'undefined'));
|
||||||
const isConnectable = !!(node.connectable || (nodesConnectable && typeof node.connectable === 'undefined'));
|
const isConnectable = !!(node.connectable || (nodesConnectable && typeof node.connectable === 'undefined'));
|
||||||
const isInitialized =
|
|
||||||
node.width && node.height && typeof node.width !== 'undefined' && typeof node.height !== 'undefined';
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NodeComponent
|
<NodeComponent
|
||||||
@@ -95,7 +93,6 @@ const NodeRenderer = (props: NodeRendererProps) => {
|
|||||||
xPos={node.positionAbsolute?.x ?? 0}
|
xPos={node.positionAbsolute?.x ?? 0}
|
||||||
yPos={node.positionAbsolute?.y ?? 0}
|
yPos={node.positionAbsolute?.y ?? 0}
|
||||||
dragging={!!node.dragging}
|
dragging={!!node.dragging}
|
||||||
isInitialized={!!isInitialized}
|
|
||||||
snapGrid={snapGrid}
|
snapGrid={snapGrid}
|
||||||
snapToGrid={snapToGrid}
|
snapToGrid={snapToGrid}
|
||||||
selectNodesOnDrag={props.selectNodesOnDrag}
|
selectNodesOnDrag={props.selectNodesOnDrag}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ const ReactFlow: FunctionComponent<ReactFlowProps> = forwardRef<ReactFlowRefType
|
|||||||
edgeTypes = defaultEdgeTypes,
|
edgeTypes = defaultEdgeTypes,
|
||||||
onNodeClick,
|
onNodeClick,
|
||||||
onEdgeClick,
|
onEdgeClick,
|
||||||
onPaneReady,
|
onInit,
|
||||||
onMove,
|
onMove,
|
||||||
onMoveStart,
|
onMoveStart,
|
||||||
onMoveEnd,
|
onMoveEnd,
|
||||||
@@ -115,10 +115,11 @@ const ReactFlow: FunctionComponent<ReactFlowProps> = forwardRef<ReactFlowRefType
|
|||||||
noDragClassName = 'nodrag',
|
noDragClassName = 'nodrag',
|
||||||
noWheelClassName = 'nowheel',
|
noWheelClassName = 'nowheel',
|
||||||
noPanClassName = 'nopan',
|
noPanClassName = 'nopan',
|
||||||
fitViewOnInit = false,
|
fitView = false,
|
||||||
|
fitViewOptions,
|
||||||
connectOnClick = true,
|
connectOnClick = true,
|
||||||
attributionPosition,
|
attributionPosition,
|
||||||
pro,
|
proOptions,
|
||||||
defaultEdgeOptions,
|
defaultEdgeOptions,
|
||||||
...rest
|
...rest
|
||||||
},
|
},
|
||||||
@@ -132,7 +133,7 @@ const ReactFlow: FunctionComponent<ReactFlowProps> = forwardRef<ReactFlowRefType
|
|||||||
<div {...rest} ref={ref} className={reactFlowClasses}>
|
<div {...rest} ref={ref} className={reactFlowClasses}>
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<GraphView
|
<GraphView
|
||||||
onPaneReady={onPaneReady}
|
onInit={onInit}
|
||||||
onMove={onMove}
|
onMove={onMove}
|
||||||
onMoveStart={onMoveStart}
|
onMoveStart={onMoveStart}
|
||||||
onMoveEnd={onMoveEnd}
|
onMoveEnd={onMoveEnd}
|
||||||
@@ -209,13 +210,14 @@ const ReactFlow: FunctionComponent<ReactFlowProps> = forwardRef<ReactFlowRefType
|
|||||||
snapGrid={snapGrid}
|
snapGrid={snapGrid}
|
||||||
connectionMode={connectionMode}
|
connectionMode={connectionMode}
|
||||||
translateExtent={translateExtent}
|
translateExtent={translateExtent}
|
||||||
fitViewOnInit={fitViewOnInit}
|
|
||||||
connectOnClick={connectOnClick}
|
connectOnClick={connectOnClick}
|
||||||
defaultEdgeOptions={defaultEdgeOptions}
|
defaultEdgeOptions={defaultEdgeOptions}
|
||||||
|
fitView={fitView}
|
||||||
|
fitViewOptions={fitViewOptions}
|
||||||
/>
|
/>
|
||||||
{onSelectionChange && <SelectionListener onSelectionChange={onSelectionChange} />}
|
{onSelectionChange && <SelectionListener onSelectionChange={onSelectionChange} />}
|
||||||
{children}
|
{children}
|
||||||
<Attribution pro={pro} position={attributionPosition} />
|
<Attribution proOptions={proOptions} position={attributionPosition} />
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useRef } from 'react';
|
||||||
|
|
||||||
import useReactFlow from './useReactFlow';
|
import useReactFlow from './useReactFlow';
|
||||||
import { OnPaneReady } from '../types';
|
import { OnInit } from '../types';
|
||||||
|
|
||||||
function useOnPaneReadyHandler(onPaneReady: OnPaneReady<any> | undefined) {
|
function useOnInitHandler(onInit: OnInit<any> | undefined) {
|
||||||
const ReactFlowInstance = useReactFlow();
|
const ReactFlowInstance = useReactFlow();
|
||||||
const isInitialized = useRef<boolean>(false);
|
const isInitialized = useRef<boolean>(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isInitialized.current && ReactFlowInstance.viewportInitialized && onPaneReady) {
|
if (!isInitialized.current && ReactFlowInstance.viewportInitialized && onInit) {
|
||||||
onPaneReady(ReactFlowInstance);
|
setTimeout(() => onInit(ReactFlowInstance), 1);
|
||||||
|
|
||||||
isInitialized.current = true;
|
isInitialized.current = true;
|
||||||
}
|
}
|
||||||
}, [onPaneReady, ReactFlowInstance]);
|
}, [onInit, ReactFlowInstance.viewportInitialized]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default useOnPaneReadyHandler;
|
export default useOnInitHandler;
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { zoomIdentity } from 'd3-zoom';
|
import { zoomIdentity } from 'd3-zoom';
|
||||||
import shallow from 'zustand/shallow';
|
import shallow from 'zustand/shallow';
|
||||||
import { Selection as D3Selection } from 'd3';
|
|
||||||
|
|
||||||
import { useStoreApi, useStore } from '../store';
|
import { useStoreApi, useStore } from '../store';
|
||||||
import { getRectOfNodeInternals, pointToRendererPoint, getTransformForBounds } from '../utils/graph';
|
import { pointToRendererPoint, getTransformForBounds, getD3Transition } from '../utils/graph';
|
||||||
import { FitViewParams, Viewport, ViewportHelperFunctions, ReactFlowState, Rect, XYPosition } from '../types';
|
import { FitViewOptions, Viewport, ViewportHelperFunctions, ReactFlowState, Rect, XYPosition } from '../types';
|
||||||
|
import { fitView as fitViewStore } from '../store/utils';
|
||||||
|
|
||||||
const DEFAULT_PADDING = 0.1;
|
const DEFAULT_PADDING = 0.1;
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ const initialViewportHelper: ViewportHelperFunctions = {
|
|||||||
getZoom: () => 1,
|
getZoom: () => 1,
|
||||||
setViewport: (_: Viewport) => {},
|
setViewport: (_: Viewport) => {},
|
||||||
getViewport: () => ({ x: 0, y: 0, zoom: 1 }),
|
getViewport: () => ({ x: 0, y: 0, zoom: 1 }),
|
||||||
fitView: (_: FitViewParams = { padding: DEFAULT_PADDING, includeHiddenNodes: false }) => {},
|
fitView: (_: FitViewOptions = { padding: DEFAULT_PADDING, includeHiddenNodes: false }) => {},
|
||||||
setCenter: (_: number, __: number) => {},
|
setCenter: (_: number, __: number) => {},
|
||||||
fitBounds: (_: Rect) => {},
|
fitBounds: (_: Rect) => {},
|
||||||
project: (position: XYPosition) => position,
|
project: (position: XYPosition) => position,
|
||||||
@@ -28,10 +28,6 @@ const selector = (s: ReactFlowState) => ({
|
|||||||
d3Selection: s.d3Selection,
|
d3Selection: s.d3Selection,
|
||||||
});
|
});
|
||||||
|
|
||||||
const getTransition = (selection: D3Selection<Element, unknown, null, undefined>, duration: number = 0) => {
|
|
||||||
return selection.transition().duration(duration);
|
|
||||||
};
|
|
||||||
|
|
||||||
const useViewportHelper = (): ViewportHelperFunctions => {
|
const useViewportHelper = (): ViewportHelperFunctions => {
|
||||||
const store = useStoreApi();
|
const store = useStoreApi();
|
||||||
const { d3Zoom, d3Selection } = useStore(selector, shallow);
|
const { d3Zoom, d3Selection } = useStore(selector, shallow);
|
||||||
@@ -39,45 +35,22 @@ const useViewportHelper = (): ViewportHelperFunctions => {
|
|||||||
const viewportHelperFunctions = useMemo<ViewportHelperFunctions>(() => {
|
const viewportHelperFunctions = useMemo<ViewportHelperFunctions>(() => {
|
||||||
if (d3Selection && d3Zoom) {
|
if (d3Selection && d3Zoom) {
|
||||||
return {
|
return {
|
||||||
zoomIn: (options) => d3Zoom.scaleBy(getTransition(d3Selection, options?.duration), 1.2),
|
zoomIn: (options) => d3Zoom.scaleBy(getD3Transition(d3Selection, options?.duration), 1.2),
|
||||||
zoomOut: (options) => d3Zoom.scaleBy(getTransition(d3Selection, options?.duration), 1 / 1.2),
|
zoomOut: (options) => d3Zoom.scaleBy(getD3Transition(d3Selection, options?.duration), 1 / 1.2),
|
||||||
zoomTo: (zoomLevel, options) => d3Zoom.scaleTo(getTransition(d3Selection, options?.duration), zoomLevel),
|
zoomTo: (zoomLevel, options) => d3Zoom.scaleTo(getD3Transition(d3Selection, options?.duration), zoomLevel),
|
||||||
getZoom: () => {
|
getZoom: () => {
|
||||||
const [, , zoom] = store.getState().transform;
|
const [, , zoom] = store.getState().transform;
|
||||||
return zoom;
|
return zoom;
|
||||||
},
|
},
|
||||||
setViewport: (transform, options) => {
|
setViewport: (transform, options) => {
|
||||||
const nextTransform = zoomIdentity.translate(transform.x, transform.y).scale(transform.zoom);
|
const nextTransform = zoomIdentity.translate(transform.x, transform.y).scale(transform.zoom);
|
||||||
d3Zoom.transform(getTransition(d3Selection, options?.duration), nextTransform);
|
d3Zoom.transform(getD3Transition(d3Selection, options?.duration), nextTransform);
|
||||||
},
|
},
|
||||||
getViewport: () => {
|
getViewport: () => {
|
||||||
const [x, y, zoom] = store.getState().transform;
|
const [x, y, zoom] = store.getState().transform;
|
||||||
return { x, y, zoom };
|
return { x, y, zoom };
|
||||||
},
|
},
|
||||||
fitView: (options) => {
|
fitView: (options) => fitViewStore(store.getState, options),
|
||||||
const { nodeInternals, width, height, minZoom, maxZoom } = store.getState();
|
|
||||||
// @TODO: work with nodeInternals instead of converting it to an array
|
|
||||||
const nodes = Array.from(nodeInternals).map(([_, node]) => node);
|
|
||||||
|
|
||||||
if (!nodes.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const bounds = getRectOfNodeInternals(
|
|
||||||
options?.includeHiddenNodes ? nodes : nodes.filter((node) => !node.hidden)
|
|
||||||
);
|
|
||||||
const [x, y, zoom] = getTransformForBounds(
|
|
||||||
bounds,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
options?.minZoom ?? minZoom,
|
|
||||||
options?.maxZoom ?? maxZoom,
|
|
||||||
options?.padding ?? DEFAULT_PADDING
|
|
||||||
);
|
|
||||||
const transform = zoomIdentity.translate(x, y).scale(zoom);
|
|
||||||
|
|
||||||
d3Zoom.transform(getTransition(d3Selection, options?.duration), transform);
|
|
||||||
},
|
|
||||||
setCenter: (x, y, options) => {
|
setCenter: (x, y, options) => {
|
||||||
const { width, height, maxZoom } = store.getState();
|
const { width, height, maxZoom } = store.getState();
|
||||||
const nextZoom = typeof options?.zoom !== 'undefined' ? options.zoom : maxZoom;
|
const nextZoom = typeof options?.zoom !== 'undefined' ? options.zoom : maxZoom;
|
||||||
@@ -85,21 +58,14 @@ const useViewportHelper = (): ViewportHelperFunctions => {
|
|||||||
const centerY = height / 2 - y * nextZoom;
|
const centerY = height / 2 - y * nextZoom;
|
||||||
const transform = zoomIdentity.translate(centerX, centerY).scale(nextZoom);
|
const transform = zoomIdentity.translate(centerX, centerY).scale(nextZoom);
|
||||||
|
|
||||||
d3Zoom.transform(getTransition(d3Selection, options?.duration), transform);
|
d3Zoom.transform(getD3Transition(d3Selection, options?.duration), transform);
|
||||||
},
|
},
|
||||||
fitBounds: (bounds, options) => {
|
fitBounds: (bounds, options) => {
|
||||||
const { width, height, minZoom, maxZoom } = store.getState();
|
const { width, height, minZoom, maxZoom } = store.getState();
|
||||||
const [x, y, zoom] = getTransformForBounds(
|
const [x, y, zoom] = getTransformForBounds(bounds, width, height, minZoom, maxZoom, options?.padding ?? 0.1);
|
||||||
bounds,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
minZoom,
|
|
||||||
maxZoom,
|
|
||||||
options?.padding ?? DEFAULT_PADDING
|
|
||||||
);
|
|
||||||
const transform = zoomIdentity.translate(x, y).scale(zoom);
|
const transform = zoomIdentity.translate(x, y).scale(zoom);
|
||||||
|
|
||||||
d3Zoom.transform(getTransition(d3Selection, options?.duration), transform);
|
d3Zoom.transform(getD3Transition(d3Selection, options?.duration), transform);
|
||||||
},
|
},
|
||||||
project: (position: XYPosition) => {
|
project: (position: XYPosition) => {
|
||||||
const { transform, snapToGrid, snapGrid } = store.getState();
|
const { transform, snapToGrid, snapGrid } = store.getState();
|
||||||
|
|||||||
+7
-4
@@ -3,6 +3,7 @@ import createContext from 'zustand/context';
|
|||||||
|
|
||||||
import { clampPosition, getDimensions } from '../utils';
|
import { clampPosition, getDimensions } from '../utils';
|
||||||
import { applyNodeChanges } from '../utils/changes';
|
import { applyNodeChanges } from '../utils/changes';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ReactFlowState,
|
ReactFlowState,
|
||||||
Node,
|
Node,
|
||||||
@@ -20,10 +21,10 @@ import { createSelectionChange, getSelectionChanges } from '../utils/changes';
|
|||||||
import {
|
import {
|
||||||
createNodeInternals,
|
createNodeInternals,
|
||||||
createPositionChange,
|
createPositionChange,
|
||||||
fitView,
|
|
||||||
handleControlledEdgeSelectionChange,
|
handleControlledEdgeSelectionChange,
|
||||||
handleControlledNodeSelectionChange,
|
handleControlledNodeSelectionChange,
|
||||||
isParentSelected,
|
isParentSelected,
|
||||||
|
fitView,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
import initialState from './initialState';
|
import initialState from './initialState';
|
||||||
|
|
||||||
@@ -54,7 +55,7 @@ const createStore = () =>
|
|||||||
set({ nodeInternals, edges: nextEdges, hasDefaultNodes, hasDefaultEdges });
|
set({ nodeInternals, edges: nextEdges, hasDefaultNodes, hasDefaultEdges });
|
||||||
},
|
},
|
||||||
updateNodeDimensions: (updates: NodeDimensionUpdate[]) => {
|
updateNodeDimensions: (updates: NodeDimensionUpdate[]) => {
|
||||||
const { onNodesChange, transform, nodeInternals, fitViewOnInit } = get();
|
const { onNodesChange, transform, nodeInternals, fitViewOnInit, fitViewOnInitDone, fitViewOnInitOptions } = get();
|
||||||
|
|
||||||
const changes: NodeDimensionChange[] = updates.reduce<NodeDimensionChange[]>((res, update) => {
|
const changes: NodeDimensionChange[] = updates.reduce<NodeDimensionChange[]>((res, update) => {
|
||||||
const node = nodeInternals.get(update.id);
|
const node = nodeInternals.get(update.id);
|
||||||
@@ -86,8 +87,9 @@ const createStore = () =>
|
|||||||
return res;
|
return res;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const fitViewOnInitDone = fitViewOnInit && fitView(get);
|
const nextFitViewOnInitDone =
|
||||||
set({ nodeInternals: new Map(nodeInternals), fitViewOnInitDone });
|
fitViewOnInit && !fitViewOnInitDone && fitView(get, { initial: true, ...fitViewOnInitOptions });
|
||||||
|
set({ nodeInternals: new Map(nodeInternals), fitViewOnInitDone: nextFitViewOnInitDone });
|
||||||
|
|
||||||
if (changes?.length > 0) {
|
if (changes?.length > 0) {
|
||||||
onNodesChange?.(changes);
|
onNodesChange?.(changes);
|
||||||
@@ -186,6 +188,7 @@ const createStore = () =>
|
|||||||
onEdgesChange?.(edgesToUnselect);
|
onEdgesChange?.(edgesToUnselect);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
setMinZoom: (minZoom: number) => {
|
setMinZoom: (minZoom: number) => {
|
||||||
const { d3Zoom, maxZoom } = get();
|
const { d3Zoom, maxZoom } = get();
|
||||||
d3Zoom?.scaleExtent([minZoom, maxZoom]);
|
d3Zoom?.scaleExtent([minZoom, maxZoom]);
|
||||||
|
|||||||
@@ -37,14 +37,14 @@ const initialState: ReactFlowStore = {
|
|||||||
nodesDraggable: true,
|
nodesDraggable: true,
|
||||||
nodesConnectable: true,
|
nodesConnectable: true,
|
||||||
elementsSelectable: true,
|
elementsSelectable: true,
|
||||||
|
fitViewOnInit: false,
|
||||||
|
fitViewOnInitDone: false,
|
||||||
|
fitViewOnInitOptions: undefined,
|
||||||
|
|
||||||
multiSelectionActive: false,
|
multiSelectionActive: false,
|
||||||
|
|
||||||
reactFlowVersion: typeof __REACT_FLOW_VERSION__ !== 'undefined' ? __REACT_FLOW_VERSION__ : '-',
|
reactFlowVersion: typeof __REACT_FLOW_VERSION__ !== 'undefined' ? __REACT_FLOW_VERSION__ : '-',
|
||||||
|
|
||||||
fitViewOnInit: false,
|
|
||||||
fitViewOnInitDone: false,
|
|
||||||
|
|
||||||
connectionStartHandle: null,
|
connectionStartHandle: null,
|
||||||
connectOnClick: true,
|
connectOnClick: true,
|
||||||
};
|
};
|
||||||
|
|||||||
+35
-14
@@ -2,7 +2,7 @@ import { zoomIdentity } from 'd3-zoom';
|
|||||||
import { GetState } from 'zustand';
|
import { GetState } from 'zustand';
|
||||||
|
|
||||||
import { clampPosition, isNumeric } from '../utils';
|
import { clampPosition, isNumeric } from '../utils';
|
||||||
import { getRectOfNodes, getTransformForBounds } from '../utils/graph';
|
import { getD3Transition, getRectOfNodes, getTransformForBounds } from '../utils/graph';
|
||||||
import {
|
import {
|
||||||
CoordinateExtent,
|
CoordinateExtent,
|
||||||
Edge,
|
Edge,
|
||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
ReactFlowState,
|
ReactFlowState,
|
||||||
XYPosition,
|
XYPosition,
|
||||||
XYZPosition,
|
XYZPosition,
|
||||||
|
FitViewOptions,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
|
|
||||||
type ParentNodes = Record<string, boolean>;
|
type ParentNodes = Record<string, boolean>;
|
||||||
@@ -145,26 +146,46 @@ export function createPositionChange({
|
|||||||
return change;
|
return change;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fitView(get: GetState<ReactFlowState>) {
|
type InternalFitViewOptions = {
|
||||||
|
initial?: boolean;
|
||||||
|
} & FitViewOptions;
|
||||||
|
|
||||||
|
export function fitView(get: GetState<ReactFlowState>, options: InternalFitViewOptions = {}) {
|
||||||
let { nodeInternals, width, height, minZoom, maxZoom, d3Zoom, d3Selection, fitViewOnInitDone, fitViewOnInit } = get();
|
let { nodeInternals, width, height, minZoom, maxZoom, d3Zoom, d3Selection, fitViewOnInitDone, fitViewOnInit } = get();
|
||||||
|
|
||||||
if (fitViewOnInit && !fitViewOnInitDone && d3Zoom && d3Selection) {
|
if ((options.initial && !fitViewOnInitDone && fitViewOnInit) || !options.initial) {
|
||||||
const rootNodes = Array.from(nodeInternals)
|
if (d3Zoom && d3Selection) {
|
||||||
.filter(([_, n]) => !n.parentNode)
|
const nodes = Array.from(nodeInternals.values()).filter((n) =>
|
||||||
.map(([_, n]) => n);
|
options.includeHiddenNodes ? !n.parentNode && n.width && n.height : !n.parentNode && !n.hidden
|
||||||
const nodesInitialized = rootNodes.every((n) => n.width && n.height);
|
);
|
||||||
|
|
||||||
if (rootNodes.length > 0 && nodesInitialized) {
|
const nodesInitialized = nodes.every((n) => n.width && n.height);
|
||||||
const bounds = getRectOfNodes(rootNodes);
|
|
||||||
const [x, y, zoom] = getTransformForBounds(bounds, width, height, minZoom ?? 0.5, maxZoom ?? 2);
|
|
||||||
|
|
||||||
const nextTransform = zoomIdentity.translate(x, y).scale(zoom);
|
if (nodes.length > 0 && nodesInitialized) {
|
||||||
d3Zoom.transform(d3Selection, nextTransform);
|
const bounds = getRectOfNodes(nodes);
|
||||||
fitViewOnInitDone = true;
|
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 fitViewOnInitDone;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function handleControlledNodeSelectionChange(nodeChanges: NodeSelectionChange[], nodeInternals: NodeInternals) {
|
export function handleControlledNodeSelectionChange(nodeChanges: NodeSelectionChange[], nodeInternals: NodeInternals) {
|
||||||
|
|||||||
@@ -20,15 +20,15 @@ import {
|
|||||||
OnEdgeUpdateFunc,
|
OnEdgeUpdateFunc,
|
||||||
NodeChange,
|
NodeChange,
|
||||||
EdgeChange,
|
EdgeChange,
|
||||||
OnPaneReady,
|
OnInit,
|
||||||
ProOptions,
|
ProOptions,
|
||||||
AttributionPosition,
|
AttributionPosition,
|
||||||
DefaultEdgeOptions,
|
DefaultEdgeOptions,
|
||||||
FitViewParams,
|
FitViewOptions,
|
||||||
BackgroundVariant,
|
BackgroundVariant,
|
||||||
} from '.';
|
} from '.';
|
||||||
|
|
||||||
export interface ReactFlowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onPaneReady'> {
|
export interface ReactFlowProps extends HTMLAttributes<HTMLDivElement> {
|
||||||
nodes?: Node[];
|
nodes?: Node[];
|
||||||
edges?: Edge[];
|
edges?: Edge[];
|
||||||
defaultNodes?: Node[];
|
defaultNodes?: Node[];
|
||||||
@@ -50,7 +50,7 @@ export interface ReactFlowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'on
|
|||||||
onConnectStart?: OnConnectStart;
|
onConnectStart?: OnConnectStart;
|
||||||
onConnectStop?: OnConnectStop;
|
onConnectStop?: OnConnectStop;
|
||||||
onConnectEnd?: OnConnectEnd;
|
onConnectEnd?: OnConnectEnd;
|
||||||
onPaneReady?: OnPaneReady;
|
onInit?: OnInit;
|
||||||
onMove?: (viewport?: Viewport) => void;
|
onMove?: (viewport?: Viewport) => void;
|
||||||
onMoveStart?: (viewport?: Viewport) => void;
|
onMoveStart?: (viewport?: Viewport) => void;
|
||||||
onMoveEnd?: (viewport?: Viewport) => void;
|
onMoveEnd?: (viewport?: Viewport) => void;
|
||||||
@@ -106,10 +106,11 @@ export interface ReactFlowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'on
|
|||||||
noDragClassName?: string;
|
noDragClassName?: string;
|
||||||
noWheelClassName?: string;
|
noWheelClassName?: string;
|
||||||
noPanClassName?: string;
|
noPanClassName?: string;
|
||||||
fitViewOnInit?: boolean;
|
fitView?: boolean;
|
||||||
|
fitViewOptions?: FitViewOptions;
|
||||||
connectOnClick?: boolean;
|
connectOnClick?: boolean;
|
||||||
attributionPosition?: AttributionPosition;
|
attributionPosition?: AttributionPosition;
|
||||||
pro?: ProOptions;
|
proOptions?: ProOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ReactFlowRefType = HTMLDivElement;
|
export type ReactFlowRefType = HTMLDivElement;
|
||||||
@@ -129,7 +130,7 @@ export interface ControlProps extends HTMLAttributes<HTMLDivElement> {
|
|||||||
showZoom?: boolean;
|
showZoom?: boolean;
|
||||||
showFitView?: boolean;
|
showFitView?: boolean;
|
||||||
showInteractive?: boolean;
|
showInteractive?: boolean;
|
||||||
fitViewParams?: FitViewParams;
|
fitViewOptions?: FitViewOptions;
|
||||||
onZoomIn?: () => void;
|
onZoomIn?: () => void;
|
||||||
onZoomOut?: () => void;
|
onZoomOut?: () => void;
|
||||||
onFitView?: () => void;
|
onFitView?: () => void;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { ReactFlowInstance } from './instance';
|
|||||||
export type NodeTypesType = { [key: string]: ReactNode };
|
export type NodeTypesType = { [key: string]: ReactNode };
|
||||||
export type EdgeTypesType = NodeTypesType;
|
export type EdgeTypesType = NodeTypesType;
|
||||||
|
|
||||||
export type FitView = (fitViewOptions?: FitViewParams) => void;
|
export type FitView = (fitViewOptions?: FitViewOptions) => void;
|
||||||
|
|
||||||
export type Project = (position: XYPosition) => XYPosition;
|
export type Project = (position: XYPosition) => XYPosition;
|
||||||
|
|
||||||
@@ -28,9 +28,7 @@ export type SetViewport = (viewport: Viewport, options?: ViewportHelperFunctionO
|
|||||||
export type SetCenter = (x: number, y: number, options?: SetCenterOptions) => void;
|
export type SetCenter = (x: number, y: number, options?: SetCenterOptions) => void;
|
||||||
export type FitBounds = (bounds: Rect, options?: FitBoundsOptions) => void;
|
export type FitBounds = (bounds: Rect, options?: FitBoundsOptions) => void;
|
||||||
|
|
||||||
export type OnPaneReady<NodeData = any, EdgeData = any> = (
|
export type OnInit<NodeData = any, EdgeData = any> = (reactFlowInstance: ReactFlowInstance<NodeData, EdgeData>) => void;
|
||||||
reactFlowInstance: ReactFlowInstance<NodeData, EdgeData>
|
|
||||||
) => void;
|
|
||||||
|
|
||||||
export interface Connection {
|
export interface Connection {
|
||||||
source: string | null;
|
source: string | null;
|
||||||
@@ -46,7 +44,7 @@ export enum ConnectionMode {
|
|||||||
|
|
||||||
export type OnConnect = (connection: Connection) => void;
|
export type OnConnect = (connection: Connection) => void;
|
||||||
|
|
||||||
export type FitViewParams = {
|
export type FitViewOptions = {
|
||||||
padding?: number;
|
padding?: number;
|
||||||
includeHiddenNodes?: boolean;
|
includeHiddenNodes?: boolean;
|
||||||
minZoom?: number;
|
minZoom?: number;
|
||||||
@@ -153,9 +151,6 @@ export type ReactFlowStore = {
|
|||||||
|
|
||||||
reactFlowVersion: string;
|
reactFlowVersion: string;
|
||||||
|
|
||||||
fitViewOnInit: boolean;
|
|
||||||
fitViewOnInitDone: boolean;
|
|
||||||
|
|
||||||
connectionStartHandle: StartHandle | null;
|
connectionStartHandle: StartHandle | null;
|
||||||
|
|
||||||
onConnect?: OnConnect;
|
onConnect?: OnConnect;
|
||||||
@@ -165,6 +160,10 @@ export type ReactFlowStore = {
|
|||||||
|
|
||||||
connectOnClick: boolean;
|
connectOnClick: boolean;
|
||||||
defaultEdgeOptions?: DefaultEdgeOptions;
|
defaultEdgeOptions?: DefaultEdgeOptions;
|
||||||
|
|
||||||
|
fitViewOnInit: boolean;
|
||||||
|
fitViewOnInitDone: boolean;
|
||||||
|
fitViewOnInitOptions: FitViewOptions | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ReactFlowActions = {
|
export type ReactFlowActions = {
|
||||||
|
|||||||
@@ -81,7 +81,6 @@ export interface WrapNodeProps<T = any> {
|
|||||||
sourcePosition?: Position;
|
sourcePosition?: Position;
|
||||||
targetPosition?: Position;
|
targetPosition?: Position;
|
||||||
hidden?: boolean;
|
hidden?: boolean;
|
||||||
isInitialized?: boolean;
|
|
||||||
snapToGrid?: boolean;
|
snapToGrid?: boolean;
|
||||||
snapGrid?: SnapGrid;
|
snapGrid?: SnapGrid;
|
||||||
dragging: boolean;
|
dragging: boolean;
|
||||||
|
|||||||
+15
-13
@@ -1,3 +1,4 @@
|
|||||||
|
import { Selection as D3Selection } from 'd3';
|
||||||
import { boxToRect, clamp, getBoundsOfBoxes, rectToBox } from '../utils';
|
import { boxToRect, clamp, getBoundsOfBoxes, rectToBox } from '../utils';
|
||||||
|
|
||||||
import { Node, Edge, Connection, EdgeMarkerType, Transform, XYPosition, Rect, NodeInternals } from '../types';
|
import { Node, Edge, Connection, EdgeMarkerType, Transform, XYPosition, Rect, NodeInternals } from '../types';
|
||||||
@@ -124,21 +125,18 @@ export const pointToRendererPoint = (
|
|||||||
return position;
|
return position;
|
||||||
};
|
};
|
||||||
|
|
||||||
// @TODO: use one function for getRectOfNodes and getRectOfNodeInternals
|
|
||||||
export const getRectOfNodes = (nodes: Node[]): Rect => {
|
export const getRectOfNodes = (nodes: Node[]): Rect => {
|
||||||
const box = nodes.reduce(
|
const box = nodes.reduce(
|
||||||
(currBox, { position, width, height }) =>
|
(currBox, { positionAbsolute, position, width, height }) =>
|
||||||
getBoundsOfBoxes(currBox, rectToBox({ ...position, width: width || 0, height: height || 0 })),
|
getBoundsOfBoxes(
|
||||||
{ x: Infinity, y: Infinity, x2: -Infinity, y2: -Infinity }
|
currBox,
|
||||||
);
|
rectToBox({
|
||||||
|
x: positionAbsolute ? positionAbsolute.x : position.x,
|
||||||
return boxToRect(box);
|
y: positionAbsolute ? positionAbsolute.y : position.y,
|
||||||
};
|
width: width || 0,
|
||||||
|
height: height || 0,
|
||||||
export const getRectOfNodeInternals = (nodes: Node[]): Rect => {
|
})
|
||||||
const box = nodes.reduce(
|
),
|
||||||
(currBox, { positionAbsolute, width, height }) =>
|
|
||||||
getBoundsOfBoxes(currBox, rectToBox({ ...positionAbsolute!, width: width || 0, height: height || 0 })),
|
|
||||||
{ x: Infinity, y: Infinity, x2: -Infinity, y2: -Infinity }
|
{ x: Infinity, y: Infinity, x2: -Infinity, y2: -Infinity }
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -213,3 +211,7 @@ export const getTransformForBounds = (
|
|||||||
|
|
||||||
return [x, y, clampedZoom];
|
return [x, y, clampedZoom];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getD3Transition = (selection: D3Selection<Element, unknown, null, undefined>, duration: number = 0) => {
|
||||||
|
return selection.transition().duration(duration);
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user