@@ -18,6 +18,7 @@ import {
1818 NodeChange ,
1919 NodeMouseHandler ,
2020 OnConnect ,
21+ OnNodesDelete ,
2122 ReactFlowInstance ,
2223 addEdge ,
2324 useEdgesState ,
@@ -59,6 +60,7 @@ type FlowCtx = {
5960 setNodes : React . Dispatch < React . SetStateAction < Node < any > [ ] > >
6061 setEdges : React . Dispatch < React . SetStateAction < Edge < any > [ ] > >
6162 handleDeleteEdgeById : ( id : string ) => void
63+ handleNodesDelete : OnNodesDelete
6264}
6365
6466const FlowContext = createContext < FlowCtx | undefined > ( undefined )
@@ -135,6 +137,8 @@ export const FlowProvider = ({ children, flow }: Props) => {
135137 selectedEdge,
136138 selectedNode,
137139 flows : nodes . map ( ( node ) => node . data ) ,
140+ nodes,
141+ edges,
138142 } )
139143
140144 const [ reactFlowInstance , setReactFlowInstance ] = useState < ReactFlowInstance <
@@ -584,6 +588,33 @@ export const FlowProvider = ({ children, flow }: Props) => {
584588 } )
585589 } , [ ] )
586590
591+ /**
592+ * Finds a node in the given array of nodes that has the specified node as its next action.
593+ * @param nodes - The array of nodes to search in.
594+ * @param node - The node to find the next action for.
595+ * @returns The node that has the specified node as its next action, or undefined if not found.
596+ */
597+ const findNodeIsNextAction = useCallback ( ( nodes : Node [ ] , node : Node < any > ) => {
598+ return nodes . find ( ( nd ) => {
599+ return (
600+ nd . data ?. nextAction === node . id ||
601+ nd . data ?. nextActions ?. some ( ( na : any ) => na . id === node . id )
602+ )
603+ } )
604+ } , [ ] )
605+
606+ const findNodeContainNextAction = useCallback (
607+ ( nodes : Node [ ] , node : Node < any > ) => {
608+ return nodes . find ( ( nd ) => {
609+ return (
610+ nd . data ?. nextAction === node . id ||
611+ nd . data ?. nextActions ?. some ( ( na : any ) => na . id === node . id )
612+ )
613+ } )
614+ } ,
615+ [ ] ,
616+ )
617+
587618 /**
588619 * Retrieves the complete flows from the given nodes.
589620 * A complete flow is a sequence of nodes where each node has a next action or is a final node.
@@ -594,20 +625,6 @@ export const FlowProvider = ({ children, flow }: Props) => {
594625 const getCompleteFlows = useCallback ( ( ) => {
595626 let clonedNodes = _ . cloneDeep ( nodes )
596627
597- /**
598- * Checks if a given node is the next action of any of the cloned nodes.
599- * @param node - The node to check.
600- * @returns True if the node is the next action of any cloned node, false otherwise.
601- */
602- const nodeIsNextAction = ( node : Node < any > ) => {
603- return clonedNodes . some ( ( nd ) => {
604- return (
605- nd . data ?. nextAction === node . id ||
606- nd . data ?. nextActions ?. some ( ( na : any ) => na . id === node . id )
607- )
608- } )
609- }
610-
611628 /**
612629 * Checks if a node is to be removed.
613630 * @param node - The node to check.
@@ -622,7 +639,7 @@ export const FlowProvider = ({ children, flow }: Props) => {
622639 }
623640
624641 if (
625- ! nodeIsNextAction ( node ) &&
642+ ! findNodeIsNextAction ( clonedNodes , node ) &&
626643 ( ! node . data ?. nextAction || ! node . data ?. nextActions )
627644 ) {
628645 return true
@@ -643,8 +660,59 @@ export const FlowProvider = ({ children, flow }: Props) => {
643660 }
644661
645662 return clonedNodes . map ( ( node ) => node . data )
646- } , [ nodes ] )
663+ } , [ findNodeIsNextAction , nodes ] )
664+
665+ /**
666+ * Handles the deletion of nodes.
667+ * @param nodeDels - The nodes to be deleted.
668+ */
669+ const handleNodesDelete : OnNodesDelete = useCallback (
670+ ( nodeDels ) => {
671+ const nodeToDelete = nodeDels [ 0 ]
672+
673+ // get node is have next action to remove this next action
674+ const nodeIsHaveNextAction = findNodeIsNextAction ( nodes , nodeToDelete )
675+
676+ if ( ! nodeIsHaveNextAction ) {
677+ return
678+ }
679+
680+ // remove next action from node is have next action
681+ if ( nodeIsHaveNextAction ?. data . nextAction ) {
682+ delete nodeIsHaveNextAction . data . nextAction
683+ }
684+
685+ // remove next actions from node is have next action
686+ if ( nodeIsHaveNextAction ?. data . nextActions ) {
687+ // remove next action from next actions
688+ nodeIsHaveNextAction . data . nextActions =
689+ nodeIsHaveNextAction . data . nextActions . filter (
690+ ( na : any ) => na . id !== nodeToDelete . id ,
691+ )
647692
693+ // remove next actions if it empty
694+ if ( nodeIsHaveNextAction . data . nextActions . length === 0 ) {
695+ delete nodeIsHaveNextAction . data . nextActions
696+ }
697+ }
698+
699+ setNodes ( ( nodes ) => {
700+ return nodes . map ( ( node ) => {
701+ if ( node . id === nodeIsHaveNextAction . id ) {
702+ return nodeIsHaveNextAction
703+ }
704+
705+ return node
706+ } )
707+ } )
708+ } ,
709+ [ findNodeIsNextAction , nodes , setNodes ] ,
710+ )
711+
712+ /**
713+ * Deletes an edge by its ID.
714+ * @param id - The ID of the edge to delete.
715+ */
648716 const handleDeleteEdgeById = useCallback (
649717 ( id : string ) => {
650718 const edge = getEdge ( id )
@@ -727,6 +795,7 @@ export const FlowProvider = ({ children, flow }: Props) => {
727795 setNodes,
728796 setEdges,
729797 handleDeleteEdgeById,
798+ handleNodesDelete,
730799 } }
731800 >
732801 { children }
0 commit comments