221 lines
6.9 KiB
TypeScript
221 lines
6.9 KiB
TypeScript
import { useEffect } from 'react';
|
|
import { StoreApi } from 'zustand';
|
|
import { shallow } from 'zustand/shallow';
|
|
import { devWarn, type CoordinateExtent } from '@xyflow/system';
|
|
|
|
import { useStore, useStoreApi } from '../../hooks/useStore';
|
|
import type { Node, Edge, ReactFlowState, ReactFlowProps, ReactFlowStore } from '../../types';
|
|
|
|
type StoreUpdaterProps = Pick<
|
|
ReactFlowProps,
|
|
| 'nodes'
|
|
| 'edges'
|
|
| 'defaultNodes'
|
|
| 'defaultEdges'
|
|
| 'onConnect'
|
|
| 'onConnectStart'
|
|
| 'onConnectEnd'
|
|
| 'onClickConnectStart'
|
|
| 'onClickConnectEnd'
|
|
| 'nodesDraggable'
|
|
| 'nodesConnectable'
|
|
| 'nodesFocusable'
|
|
| 'edgesFocusable'
|
|
| 'edgesUpdatable'
|
|
| 'minZoom'
|
|
| 'maxZoom'
|
|
| 'nodeExtent'
|
|
| 'onNodesChange'
|
|
| 'onEdgesChange'
|
|
| 'elementsSelectable'
|
|
| 'connectionMode'
|
|
| 'snapToGrid'
|
|
| 'snapGrid'
|
|
| 'translateExtent'
|
|
| 'connectOnClick'
|
|
| 'defaultEdgeOptions'
|
|
| 'fitView'
|
|
| 'fitViewOptions'
|
|
| 'onNodesDelete'
|
|
| 'onEdgesDelete'
|
|
| 'onNodeDragStart'
|
|
| 'onNodeDrag'
|
|
| 'onNodeDragStop'
|
|
| 'onSelectionDragStart'
|
|
| 'onSelectionDrag'
|
|
| 'onSelectionDragStop'
|
|
| 'onMove'
|
|
| 'onMoveStart'
|
|
| 'onMoveEnd'
|
|
| 'noPanClassName'
|
|
| 'nodeOrigin'
|
|
| 'elevateNodesOnSelect'
|
|
| 'autoPanOnConnect'
|
|
| 'autoPanOnNodeDrag'
|
|
| 'onError'
|
|
| 'connectionRadius'
|
|
| 'isValidConnection'
|
|
| 'selectNodesOnDrag'
|
|
| 'nodeDragThreshold'
|
|
> & { rfId: string };
|
|
|
|
const selector = (s: ReactFlowState) => ({
|
|
setNodes: s.setNodes,
|
|
setEdges: s.setEdges,
|
|
setDefaultNodesAndEdges: s.setDefaultNodesAndEdges,
|
|
setMinZoom: s.setMinZoom,
|
|
setMaxZoom: s.setMaxZoom,
|
|
setTranslateExtent: s.setTranslateExtent,
|
|
setNodeExtent: s.setNodeExtent,
|
|
reset: s.reset,
|
|
});
|
|
|
|
function useStoreUpdater<T>(value: T | undefined, setStoreState: (param: T) => void) {
|
|
useEffect(() => {
|
|
if (typeof value !== 'undefined') {
|
|
setStoreState(value);
|
|
}
|
|
}, [value]);
|
|
}
|
|
|
|
// updates with values in store that don't have a dedicated setter function
|
|
function useDirectStoreUpdater(
|
|
key: keyof ReactFlowStore,
|
|
value: unknown,
|
|
setState: StoreApi<ReactFlowState>['setState']
|
|
) {
|
|
useEffect(() => {
|
|
if (typeof value !== 'undefined') {
|
|
setState({ [key]: value });
|
|
}
|
|
}, [value]);
|
|
}
|
|
|
|
const StoreUpdater = ({
|
|
nodes,
|
|
edges,
|
|
defaultNodes,
|
|
defaultEdges,
|
|
onConnect,
|
|
onConnectStart,
|
|
onConnectEnd,
|
|
onClickConnectStart,
|
|
onClickConnectEnd,
|
|
nodesDraggable,
|
|
nodesConnectable,
|
|
nodesFocusable,
|
|
edgesFocusable,
|
|
edgesUpdatable,
|
|
elevateNodesOnSelect,
|
|
minZoom,
|
|
maxZoom,
|
|
nodeExtent,
|
|
onNodesChange,
|
|
onEdgesChange,
|
|
elementsSelectable,
|
|
connectionMode,
|
|
snapGrid,
|
|
snapToGrid,
|
|
translateExtent,
|
|
connectOnClick,
|
|
defaultEdgeOptions,
|
|
fitView,
|
|
fitViewOptions,
|
|
onNodesDelete,
|
|
onEdgesDelete,
|
|
onNodeDrag,
|
|
onNodeDragStart,
|
|
onNodeDragStop,
|
|
onSelectionDrag,
|
|
onSelectionDragStart,
|
|
onSelectionDragStop,
|
|
onMoveStart,
|
|
onMove,
|
|
onMoveEnd,
|
|
noPanClassName,
|
|
nodeOrigin,
|
|
rfId,
|
|
autoPanOnConnect,
|
|
autoPanOnNodeDrag,
|
|
onError,
|
|
connectionRadius,
|
|
isValidConnection,
|
|
selectNodesOnDrag,
|
|
nodeDragThreshold,
|
|
}: StoreUpdaterProps) => {
|
|
const {
|
|
setNodes,
|
|
setEdges,
|
|
setDefaultNodesAndEdges,
|
|
setMinZoom,
|
|
setMaxZoom,
|
|
setTranslateExtent,
|
|
setNodeExtent,
|
|
reset,
|
|
} = useStore(selector, shallow);
|
|
const store = useStoreApi();
|
|
|
|
useEffect(() => {
|
|
const edgesWithDefaults = defaultEdges?.map((e) => ({ ...e, ...defaultEdgeOptions }));
|
|
setDefaultNodesAndEdges(defaultNodes, edgesWithDefaults);
|
|
|
|
return () => {
|
|
reset();
|
|
};
|
|
}, []);
|
|
|
|
useDirectStoreUpdater('defaultEdgeOptions', defaultEdgeOptions, store.setState);
|
|
useDirectStoreUpdater('connectionMode', connectionMode, store.setState);
|
|
useDirectStoreUpdater('onConnect', onConnect, store.setState);
|
|
useDirectStoreUpdater('onConnectStart', onConnectStart, store.setState);
|
|
useDirectStoreUpdater('onConnectEnd', onConnectEnd, store.setState);
|
|
useDirectStoreUpdater('onClickConnectStart', onClickConnectStart, store.setState);
|
|
useDirectStoreUpdater('onClickConnectEnd', onClickConnectEnd, store.setState);
|
|
useDirectStoreUpdater('nodesDraggable', nodesDraggable, store.setState);
|
|
useDirectStoreUpdater('nodesConnectable', nodesConnectable, store.setState);
|
|
useDirectStoreUpdater('nodesFocusable', nodesFocusable, store.setState);
|
|
useDirectStoreUpdater('edgesFocusable', edgesFocusable, store.setState);
|
|
useDirectStoreUpdater('edgesUpdatable', edgesUpdatable, store.setState);
|
|
useDirectStoreUpdater('elementsSelectable', elementsSelectable, store.setState);
|
|
useDirectStoreUpdater('elevateNodesOnSelect', elevateNodesOnSelect, store.setState);
|
|
useDirectStoreUpdater('snapToGrid', snapToGrid, store.setState);
|
|
useDirectStoreUpdater('snapGrid', snapGrid, store.setState);
|
|
useDirectStoreUpdater('onNodesChange', onNodesChange, store.setState);
|
|
useDirectStoreUpdater('onEdgesChange', onEdgesChange, store.setState);
|
|
useDirectStoreUpdater('connectOnClick', connectOnClick, store.setState);
|
|
useDirectStoreUpdater('fitViewOnInit', fitView, store.setState);
|
|
useDirectStoreUpdater('fitViewOnInitOptions', fitViewOptions, store.setState);
|
|
useDirectStoreUpdater('onNodesDelete', onNodesDelete, store.setState);
|
|
useDirectStoreUpdater('onEdgesDelete', onEdgesDelete, store.setState);
|
|
useDirectStoreUpdater('onNodeDrag', onNodeDrag, store.setState);
|
|
useDirectStoreUpdater('onNodeDragStart', onNodeDragStart, store.setState);
|
|
useDirectStoreUpdater('onNodeDragStop', onNodeDragStop, store.setState);
|
|
useDirectStoreUpdater('onSelectionDrag', onSelectionDrag, store.setState);
|
|
useDirectStoreUpdater('onSelectionDragStart', onSelectionDragStart, store.setState);
|
|
useDirectStoreUpdater('onSelectionDragStop', onSelectionDragStop, store.setState);
|
|
useDirectStoreUpdater('onMove', onMove, store.setState);
|
|
useDirectStoreUpdater('onMoveStart', onMoveStart, store.setState);
|
|
useDirectStoreUpdater('onMoveEnd', onMoveEnd, store.setState);
|
|
useDirectStoreUpdater('noPanClassName', noPanClassName, store.setState);
|
|
useDirectStoreUpdater('nodeOrigin', nodeOrigin, store.setState);
|
|
useDirectStoreUpdater('rfId', rfId, store.setState);
|
|
useDirectStoreUpdater('autoPanOnConnect', autoPanOnConnect, store.setState);
|
|
useDirectStoreUpdater('autoPanOnNodeDrag', autoPanOnNodeDrag, store.setState);
|
|
useDirectStoreUpdater('onError', onError || devWarn, store.setState);
|
|
useDirectStoreUpdater('connectionRadius', connectionRadius, store.setState);
|
|
useDirectStoreUpdater('isValidConnection', isValidConnection, store.setState);
|
|
useDirectStoreUpdater('selectNodesOnDrag', selectNodesOnDrag, store.setState);
|
|
useDirectStoreUpdater('nodeDragThreshold', nodeDragThreshold, store.setState);
|
|
|
|
useStoreUpdater<Node[]>(nodes, setNodes);
|
|
useStoreUpdater<Edge[]>(edges, setEdges);
|
|
useStoreUpdater<number>(minZoom, setMinZoom);
|
|
useStoreUpdater<number>(maxZoom, setMaxZoom);
|
|
useStoreUpdater<CoordinateExtent>(translateExtent, setTranslateExtent);
|
|
useStoreUpdater<CoordinateExtent>(nodeExtent, setNodeExtent);
|
|
|
|
return null;
|
|
};
|
|
|
|
export default StoreUpdater;
|