use-selection-interactions.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. import type { MouseEvent } from 'react'
  2. import {
  3. useCallback,
  4. } from 'react'
  5. import produce from 'immer'
  6. import type {
  7. OnSelectionChangeFunc,
  8. } from 'reactflow'
  9. import { useStoreApi } from 'reactflow'
  10. import { useWorkflowStore } from '../store'
  11. import type { Node } from '../types'
  12. export const useSelectionInteractions = () => {
  13. const store = useStoreApi()
  14. const workflowStore = useWorkflowStore()
  15. const handleSelectionStart = useCallback(() => {
  16. const {
  17. getNodes,
  18. setNodes,
  19. edges,
  20. setEdges,
  21. userSelectionRect,
  22. } = store.getState()
  23. if (!userSelectionRect?.width || !userSelectionRect?.height) {
  24. const nodes = getNodes()
  25. const newNodes = produce(nodes, (draft) => {
  26. draft.forEach((node) => {
  27. if (node.data._isBundled)
  28. node.data._isBundled = false
  29. })
  30. })
  31. setNodes(newNodes)
  32. const newEdges = produce(edges, (draft) => {
  33. draft.forEach((edge) => {
  34. if (edge.data._isBundled)
  35. edge.data._isBundled = false
  36. })
  37. })
  38. setEdges(newEdges)
  39. }
  40. }, [store])
  41. const handleSelectionChange = useCallback<OnSelectionChangeFunc>(({ nodes: nodesInSelection, edges: edgesInSelection }) => {
  42. const {
  43. getNodes,
  44. setNodes,
  45. edges,
  46. setEdges,
  47. userSelectionRect,
  48. } = store.getState()
  49. const nodes = getNodes()
  50. if (!userSelectionRect?.width || !userSelectionRect?.height)
  51. return
  52. const newNodes = produce(nodes, (draft) => {
  53. draft.forEach((node) => {
  54. const nodeInSelection = nodesInSelection.find(n => n.id === node.id)
  55. if (nodeInSelection)
  56. node.data._isBundled = true
  57. else
  58. node.data._isBundled = false
  59. })
  60. })
  61. setNodes(newNodes)
  62. const newEdges = produce(edges, (draft) => {
  63. draft.forEach((edge) => {
  64. const edgeInSelection = edgesInSelection.find(e => e.id === edge.id)
  65. if (edgeInSelection)
  66. edge.data._isBundled = true
  67. else
  68. edge.data._isBundled = false
  69. })
  70. })
  71. setEdges(newEdges)
  72. }, [store])
  73. const handleSelectionDrag = useCallback((_: MouseEvent, nodesWithDrag: Node[]) => {
  74. const {
  75. getNodes,
  76. setNodes,
  77. } = store.getState()
  78. workflowStore.setState({
  79. nodeAnimation: false,
  80. })
  81. const nodes = getNodes()
  82. const newNodes = produce(nodes, (draft) => {
  83. draft.forEach((node) => {
  84. const dragNode = nodesWithDrag.find(n => n.id === node.id)
  85. if (dragNode)
  86. node.position = dragNode.position
  87. })
  88. })
  89. setNodes(newNodes)
  90. }, [store, workflowStore])
  91. const handleSelectionCancel = useCallback(() => {
  92. const {
  93. getNodes,
  94. setNodes,
  95. edges,
  96. setEdges,
  97. } = store.getState()
  98. store.setState({
  99. userSelectionRect: null,
  100. userSelectionActive: true,
  101. })
  102. const nodes = getNodes()
  103. const newNodes = produce(nodes, (draft) => {
  104. draft.forEach((node) => {
  105. if (node.data._isBundled)
  106. node.data._isBundled = false
  107. })
  108. })
  109. setNodes(newNodes)
  110. const newEdges = produce(edges, (draft) => {
  111. draft.forEach((edge) => {
  112. if (edge.data._isBundled)
  113. edge.data._isBundled = false
  114. })
  115. })
  116. setEdges(newEdges)
  117. }, [store])
  118. return {
  119. handleSelectionStart,
  120. handleSelectionChange,
  121. handleSelectionDrag,
  122. handleSelectionCancel,
  123. }
  124. }