| 
									
										
										
										
											2024-05-09 17:18:51 +08:00
										 |  |  | import { | 
					
						
							|  |  |  |   memo, | 
					
						
							|  |  |  | } from 'react' | 
					
						
							|  |  |  | import produce from 'immer' | 
					
						
							|  |  |  | import { | 
					
						
							|  |  |  |   useReactFlow, | 
					
						
							|  |  |  |   useStoreApi, | 
					
						
							|  |  |  |   useViewport, | 
					
						
							|  |  |  | } from 'reactflow' | 
					
						
							|  |  |  | import { useEventListener } from 'ahooks' | 
					
						
							|  |  |  | import { | 
					
						
							|  |  |  |   useStore, | 
					
						
							|  |  |  |   useWorkflowStore, | 
					
						
							|  |  |  | } from './store' | 
					
						
							| 
									
										
										
										
											2024-06-26 08:37:12 +02:00
										 |  |  | import { WorkflowHistoryEvent, useNodesInteractions, useWorkflowHistory } from './hooks' | 
					
						
							| 
									
										
										
										
											2024-06-14 17:08:11 +08:00
										 |  |  | import { CUSTOM_NODE } from './constants' | 
					
						
							| 
									
										
										
										
											2024-05-09 17:18:51 +08:00
										 |  |  | import CustomNode from './nodes' | 
					
						
							| 
									
										
										
										
											2024-06-14 17:08:11 +08:00
										 |  |  | import CustomNoteNode from './note-node' | 
					
						
							|  |  |  | import { CUSTOM_NOTE_NODE } from './note-node/constants' | 
					
						
							| 
									
										
										
										
											2024-05-09 17:18:51 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | const CandidateNode = () => { | 
					
						
							|  |  |  |   const store = useStoreApi() | 
					
						
							|  |  |  |   const reactflow = useReactFlow() | 
					
						
							|  |  |  |   const workflowStore = useWorkflowStore() | 
					
						
							|  |  |  |   const candidateNode = useStore(s => s.candidateNode) | 
					
						
							|  |  |  |   const mousePosition = useStore(s => s.mousePosition) | 
					
						
							|  |  |  |   const { zoom } = useViewport() | 
					
						
							| 
									
										
										
										
											2024-06-14 17:08:11 +08:00
										 |  |  |   const { handleNodeSelect } = useNodesInteractions() | 
					
						
							| 
									
										
										
										
											2024-06-26 08:37:12 +02:00
										 |  |  |   const { saveStateToHistory } = useWorkflowHistory() | 
					
						
							| 
									
										
										
										
											2024-05-09 17:18:51 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   useEventListener('click', (e) => { | 
					
						
							|  |  |  |     const { candidateNode, mousePosition } = workflowStore.getState() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (candidateNode) { | 
					
						
							|  |  |  |       e.preventDefault() | 
					
						
							|  |  |  |       const { | 
					
						
							|  |  |  |         getNodes, | 
					
						
							|  |  |  |         setNodes, | 
					
						
							|  |  |  |       } = store.getState() | 
					
						
							|  |  |  |       const { screenToFlowPosition } = reactflow | 
					
						
							|  |  |  |       const nodes = getNodes() | 
					
						
							|  |  |  |       const { x, y } = screenToFlowPosition({ x: mousePosition.pageX, y: mousePosition.pageY }) | 
					
						
							|  |  |  |       const newNodes = produce(nodes, (draft) => { | 
					
						
							|  |  |  |         draft.push({ | 
					
						
							|  |  |  |           ...candidateNode, | 
					
						
							|  |  |  |           data: { | 
					
						
							|  |  |  |             ...candidateNode.data, | 
					
						
							|  |  |  |             _isCandidate: false, | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |           position: { | 
					
						
							|  |  |  |             x, | 
					
						
							|  |  |  |             y, | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |       setNodes(newNodes) | 
					
						
							| 
									
										
										
										
											2024-06-26 08:37:12 +02:00
										 |  |  |       if (candidateNode.type === CUSTOM_NOTE_NODE) | 
					
						
							|  |  |  |         saveStateToHistory(WorkflowHistoryEvent.NoteAdd) | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         saveStateToHistory(WorkflowHistoryEvent.NodeAdd) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-09 17:18:51 +08:00
										 |  |  |       workflowStore.setState({ candidateNode: undefined }) | 
					
						
							| 
									
										
										
										
											2024-06-14 17:08:11 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       if (candidateNode.type === CUSTOM_NOTE_NODE) | 
					
						
							|  |  |  |         handleNodeSelect(candidateNode.id) | 
					
						
							| 
									
										
										
										
											2024-05-09 17:18:51 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |   }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   useEventListener('contextmenu', (e) => { | 
					
						
							|  |  |  |     const { candidateNode } = workflowStore.getState() | 
					
						
							|  |  |  |     if (candidateNode) { | 
					
						
							|  |  |  |       e.preventDefault() | 
					
						
							|  |  |  |       workflowStore.setState({ candidateNode: undefined }) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!candidateNode) | 
					
						
							|  |  |  |     return null | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return ( | 
					
						
							|  |  |  |     <div | 
					
						
							|  |  |  |       className='absolute z-10' | 
					
						
							|  |  |  |       style={{ | 
					
						
							|  |  |  |         left: mousePosition.elementX, | 
					
						
							|  |  |  |         top: mousePosition.elementY, | 
					
						
							|  |  |  |         transform: `scale(${zoom})`, | 
					
						
							|  |  |  |         transformOrigin: '0 0', | 
					
						
							|  |  |  |       }} | 
					
						
							|  |  |  |     > | 
					
						
							| 
									
										
										
										
											2024-06-14 17:08:11 +08:00
										 |  |  |       { | 
					
						
							|  |  |  |         candidateNode.type === CUSTOM_NODE && ( | 
					
						
							|  |  |  |           <CustomNode {...candidateNode as any} /> | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         candidateNode.type === CUSTOM_NOTE_NODE && ( | 
					
						
							|  |  |  |           <CustomNoteNode {...candidateNode as any} /> | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2024-05-09 17:18:51 +08:00
										 |  |  |     </div> | 
					
						
							|  |  |  |   ) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export default memo(CandidateNode) |