| 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<OnSelectionChangeFunc>(({ 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, | |
| } | |
| } | |