| 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, |
| } |
| } |
|
|