import { useCallback } from 'react'; import useViewportHelper from './useViewportHelper'; import { useStoreApi } from '../store'; import { ReactFlowInstance, Instance, NodeAddChange, EdgeAddChange, NodeResetChange, EdgeResetChange } from '../types'; export default function useReactFlow(): ReactFlowInstance { const { initialized: viewportInitialized, ...viewportHelperFunctions } = useViewportHelper(); const store = useStoreApi(); const getNodes = useCallback>(() => { const { nodeInternals } = store.getState(); const nodes = Array.from(nodeInternals.values()); return nodes.map((n) => ({ ...n })); }, []); const getNode = useCallback>((id) => { const { nodeInternals } = store.getState(); return nodeInternals.get(id); }, []); const getEdges = useCallback>(() => { const { edges = [] } = store.getState(); return edges.map((e) => ({ ...e })); }, []); const getEdge = useCallback>((id) => { const { edges = [] } = store.getState(); return edges.find((e) => e.id === id); }, []); const setNodes = useCallback>((payload) => { const { nodeInternals, setNodes, hasDefaultNodes, onNodesChange } = store.getState(); const nodes = Array.from(nodeInternals.values()); const nextNodes = typeof payload === 'function' ? payload(nodes) : payload; if (hasDefaultNodes) { setNodes(nextNodes); } else if (onNodesChange) { const changes = nextNodes.map((node) => ({ item: node, type: 'reset' } as NodeResetChange)); onNodesChange(changes); } }, []); const setEdges = useCallback>((payload) => { const { edges = [], setEdges, hasDefaultEdges, onEdgesChange } = store.getState(); const nextEdges = typeof payload === 'function' ? payload(edges) : payload; if (hasDefaultEdges) { setEdges(nextEdges); } else if (onEdgesChange) { const changes = nextEdges.map((edge) => ({ item: edge, type: 'reset' } as EdgeResetChange)); onEdgesChange(changes); } }, []); const addNodes = useCallback>((payload) => { const nodes = Array.isArray(payload) ? payload : [payload]; const { nodeInternals, setNodes, hasDefaultNodes, onNodesChange } = store.getState(); if (hasDefaultNodes) { const currentNodes = Array.from(nodeInternals.values()); const nextNodes = [...currentNodes, ...nodes]; setNodes(nextNodes); } else if (onNodesChange) { const changes = nodes.map((node) => ({ item: node, type: 'add' } as NodeAddChange)); onNodesChange(changes); } }, []); const addEdges = useCallback>((payload) => { const nextEdges = Array.isArray(payload) ? payload : [payload]; const { edges = [], setEdges, hasDefaultEdges, onEdgesChange } = store.getState(); if (hasDefaultEdges) { setEdges([...edges, ...nextEdges]); } else if (onEdgesChange) { const changes = nextEdges.map((edge) => ({ item: edge, type: 'add' } as EdgeAddChange)); onEdgesChange(changes); } }, []); const toObject = useCallback>(() => { const { nodeInternals, edges = [], transform } = store.getState(); const nodes = Array.from(nodeInternals.values()); const [x, y, zoom] = transform; return { nodes: nodes.map((n) => ({ ...n })), edges: edges.map((e) => ({ ...e })), viewport: { x, y, zoom, }, }; }, []); return { ...viewportHelperFunctions, viewportInitialized, getNodes, getNode, getEdges, getEdge, setNodes, setEdges, addNodes, addEdges, toObject, }; }