diff --git a/example/src/Overview/index.tsx b/example/src/Overview/index.tsx index d2bda8ab..d4c0eea0 100644 --- a/example/src/Overview/index.tsx +++ b/example/src/Overview/index.tsx @@ -43,6 +43,8 @@ const onEdgeMouseEnter = (_: MouseEvent, edge: Edge) => console.log('edge mouse const onEdgeMouseMove = (_: MouseEvent, edge: Edge) => console.log('edge mouse move', edge); const onEdgeMouseLeave = (_: MouseEvent, edge: Edge) => console.log('edge mouse leave', edge); const onEdgeDoubleClick = (_: MouseEvent, edge: Edge) => console.log('edge double click', edge); +const onNodesDelete = (nodes: Node[]) => console.log('nodes delete', nodes); +const onEdgesDelete = (edges: Edge[]) => console.log('edges delete', edges); const initialNodes: Node[] = [ { @@ -196,6 +198,8 @@ const OverviewFlow = () => { fitViewOptions={{ padding: 0.2 }} attributionPosition="top-right" maxZoom={Infinity} + onNodesDelete={onNodesDelete} + onEdgesDelete={onEdgesDelete} > diff --git a/src/components/StoreUpdater/index.tsx b/src/components/StoreUpdater/index.tsx index 634e8bbd..57b12c7a 100644 --- a/src/components/StoreUpdater/index.tsx +++ b/src/components/StoreUpdater/index.tsx @@ -45,6 +45,8 @@ interface StoreUpdaterProps { defaultEdgeOptions?: DefaultEdgeOptions; fitView?: boolean; fitViewOptions?: FitViewOptions; + onNodesDelete?: (nodes: Node[]) => void; + onEdgesDelete?: (edges: Edge[]) => void; } const selector = (s: ReactFlowState) => ({ @@ -100,6 +102,8 @@ const StoreUpdater = ({ defaultEdgeOptions, fitView, fitViewOptions, + onNodesDelete, + onEdgesDelete, }: StoreUpdaterProps) => { const { setNodes, @@ -137,6 +141,8 @@ const StoreUpdater = ({ useDirectStoreUpdater('connectOnClick', connectOnClick, store.setState); useDirectStoreUpdater('fitViewOnInit', fitView, store.setState); useDirectStoreUpdater('fitViewOnInitOptions', fitViewOptions, store.setState); + useDirectStoreUpdater('onNodesDelete', onNodesDelete, store.setState); + useDirectStoreUpdater('onEdgesDelete', onEdgesDelete, store.setState); useStoreUpdater(nodes, setNodes); useStoreUpdater(edges, setEdges); diff --git a/src/container/ReactFlow/index.tsx b/src/container/ReactFlow/index.tsx index 7324eb0f..518858a6 100644 --- a/src/container/ReactFlow/index.tsx +++ b/src/container/ReactFlow/index.tsx @@ -62,6 +62,8 @@ const ReactFlow = forwardRef( onNodeDragStart, onNodeDrag, onNodeDragStop, + onNodesDelete, + onEdgesDelete, onSelectionChange, onSelectionDragStart, onSelectionDrag, @@ -214,6 +216,8 @@ const ReactFlow = forwardRef( defaultEdgeOptions={defaultEdgeOptions} fitView={fitView} fitViewOptions={fitViewOptions} + onNodesDelete={onNodesDelete} + onEdgesDelete={onEdgesDelete} /> {onSelectionChange && } {children} diff --git a/src/hooks/useGlobalKeyHandler.ts b/src/hooks/useGlobalKeyHandler.ts index d134fa59..3b979a86 100644 --- a/src/hooks/useGlobalKeyHandler.ts +++ b/src/hooks/useGlobalKeyHandler.ts @@ -25,7 +25,7 @@ export default ({ deleteKeyCode, multiSelectionKeyCode }: HookParams): void => { const multiSelectionKeyPressed = useKeyPress(multiSelectionKeyCode); useEffect(() => { - const { nodeInternals, edges, hasDefaultNodes, hasDefaultEdges } = store.getState(); + const { nodeInternals, edges, hasDefaultNodes, hasDefaultEdges, onNodesDelete, onEdgesDelete } = store.getState(); // @TODO: work with nodeInternals instead of converting it to an array const nodes = Array.from(nodeInternals).map(([_, node]) => node); const selectedNodes = nodes.filter((n) => n.selected); @@ -33,7 +33,8 @@ export default ({ deleteKeyCode, multiSelectionKeyCode }: HookParams): void => { if (deleteKeyPressed && (selectedNodes || selectedEdges)) { const connectedEdges = getConnectedEdges(selectedNodes, edges); - const edgeIdsToRemove = [...selectedEdges, ...connectedEdges].map((e) => e.id); + const edgesToRemove = [...selectedEdges, ...connectedEdges]; + const edgeIdsToRemove = edgesToRemove.map((e) => e.id); if (hasDefaultNodes) { selectedNodes.forEach((node) => { @@ -48,6 +49,9 @@ export default ({ deleteKeyCode, multiSelectionKeyCode }: HookParams): void => { }); } + onNodesDelete?.(selectedNodes); + onEdgesDelete?.(edgesToRemove); + if (onNodesChange) { const nodeChanges: NodeChange[] = selectedNodes.map((n) => ({ id: n.id, type: 'remove' })); onNodesChange(nodeChanges); diff --git a/src/types/component-props.ts b/src/types/component-props.ts index 894ae86d..e8ebf580 100644 --- a/src/types/component-props.ts +++ b/src/types/component-props.ts @@ -46,6 +46,8 @@ export interface ReactFlowProps extends HTMLAttributes { onNodeDragStart?: (event: ReactMouseEvent, node: Node) => void; onNodeDrag?: (event: ReactMouseEvent, node: Node) => void; onNodeDragStop?: (event: ReactMouseEvent, node: Node) => void; + onNodesDelete?: (nodes: Node[]) => void; + onEdgesDelete?: (edges: Edge[]) => void; onConnect?: OnConnect; onConnectStart?: OnConnectStart; onConnectStop?: OnConnectStop; diff --git a/src/types/general.ts b/src/types/general.ts index 271ed4de..ee8bd7fe 100644 --- a/src/types/general.ts +++ b/src/types/general.ts @@ -164,6 +164,9 @@ export type ReactFlowStore = { fitViewOnInit: boolean; fitViewOnInitDone: boolean; fitViewOnInitOptions: FitViewOptions | undefined; + + onNodesDelete?: (nodes: Node[]) => void; + onEdgesDelete?: (edges: Edge[]) => void; }; export type ReactFlowActions = {