import type { MouseEvent } from 'react' import { useCallback, } from 'react' import produce from 'immer' import type { OnSelectionChangeFunc, } from 'reactflow' import { useStoreApi } from 'reactflow' import { useWorkflowStore } from '../store' import type { Node } from '../types' export const useSelectionInteractions = () => { const store = useStoreApi() const workflowStore = useWorkflowStore() const handleSelectionStart = useCallback(() => { const { getNodes, setNodes, edges, setEdges, userSelectionRect, } = store.getState() if (!userSelectionRect?.width || !userSelectionRect?.height) { const nodes = getNodes() const newNodes = produce(nodes, (draft) => { draft.forEach((node) => { if (node.data._isBundled) node.data._isBundled = false }) }) setNodes(newNodes) const newEdges = produce(edges, (draft) => { draft.forEach((edge) => { if (edge.data._isBundled) edge.data._isBundled = false }) }) setEdges(newEdges) } }, [store]) const handleSelectionChange = useCallback(({ nodes: nodesInSelection, edges: edgesInSelection }) => { const { getNodes, setNodes, edges, setEdges, userSelectionRect, } = store.getState() const nodes = getNodes() if (!userSelectionRect?.width || !userSelectionRect?.height) return const newNodes = produce(nodes, (draft) => { draft.forEach((node) => { const nodeInSelection = nodesInSelection.find(n => n.id === node.id) if (nodeInSelection) node.data._isBundled = true else node.data._isBundled = false }) }) setNodes(newNodes) const newEdges = produce(edges, (draft) => { draft.forEach((edge) => { const edgeInSelection = edgesInSelection.find(e => e.id === edge.id) if (edgeInSelection) edge.data._isBundled = true else edge.data._isBundled = false }) }) setEdges(newEdges) }, [store]) const handleSelectionDrag = useCallback((_: MouseEvent, nodesWithDrag: Node[]) => { const { getNodes, setNodes, } = store.getState() workflowStore.setState({ nodeAnimation: false, }) const nodes = getNodes() const newNodes = produce(nodes, (draft) => { draft.forEach((node) => { const dragNode = nodesWithDrag.find(n => n.id === node.id) if (dragNode) node.position = dragNode.position }) }) setNodes(newNodes) }, [store, workflowStore]) const handleSelectionCancel = useCallback(() => { const { getNodes, setNodes, edges, setEdges, } = store.getState() store.setState({ userSelectionRect: null, userSelectionActive: true, }) const nodes = getNodes() const newNodes = produce(nodes, (draft) => { draft.forEach((node) => { if (node.data._isBundled) node.data._isBundled = false }) }) setNodes(newNodes) const newEdges = produce(edges, (draft) => { draft.forEach((edge) => { if (edge.data._isBundled) edge.data._isBundled = false }) }) setEdges(newEdges) }, [store]) return { handleSelectionStart, handleSelectionChange, handleSelectionDrag, handleSelectionCancel, } }