diff --git a/examples/vite-app/src/examples/Basic/index.tsx b/examples/vite-app/src/examples/Basic/index.tsx
index f3f74dda..c157ce23 100644
--- a/examples/vite-app/src/examples/Basic/index.tsx
+++ b/examples/vite-app/src/examples/Basic/index.tsx
@@ -78,10 +78,6 @@ const BasicFlow = () => {
);
};
- const deleteElements = () => {
- instance.deleteSelectedElements()
- }
-
return (
{
toggle classnames
-
);
diff --git a/examples/vite-app/src/examples/UseReactFlow/index.tsx b/examples/vite-app/src/examples/UseReactFlow/index.tsx
index 7133cec9..87a610b5 100644
--- a/examples/vite-app/src/examples/UseReactFlow/index.tsx
+++ b/examples/vite-app/src/examples/UseReactFlow/index.tsx
@@ -43,6 +43,7 @@ const initialNodes: Node[] = [
const initialEdges: Edge[] = [
{ id: 'e1-2', source: '1', target: '2', animated: true },
{ id: 'e1-3', source: '1', target: '3' },
+ // { id: 'e3-4', source: '3', target: '4' }
];
let id = 5;
@@ -64,6 +65,8 @@ const UseZoomPanHelperFlow = () => {
addEdges,
getNodes,
getEdges,
+ deleteSelectedElements,
+ deleteElements
} = useReactFlow();
const onPaneClick = useCallback(
@@ -111,7 +114,22 @@ const UseZoomPanHelperFlow = () => {
console.log('edges', getEdges());
}, [getNodes, getEdges]);
+ const deleteSelectedElements1 = useCallback(() => {
+ const selectedNodes = nodes.filter(node => node.selected).map(node => node.id);
+ const selectedEdges = edges.filter(edge => edge.selected).map(edge => edge.id);
+ deleteElements(selectedNodes, selectedEdges);
+ }, [deleteElements, nodes, edges])
+
+ const deleteSelectedElements2 = useCallback(() => {
+ deleteSelectedElements();
+ }, [deleteSelectedElements])
+
+ const deleteSomeElements = useCallback(() => {
+ deleteElements(['2'],['e1-3'])
+ }, [])
+
useEffect(() => {
+ // called twice in strict mode of development mode
addEdges({ id: 'e3-4', source: '3', target: '4' });
}, [addEdges]);
@@ -137,6 +155,9 @@ const UseZoomPanHelperFlow = () => {
+
+
+
diff --git a/packages/core/src/hooks/useGlobalKeyHandler.ts b/packages/core/src/hooks/useGlobalKeyHandler.ts
index 3d563941..52d918dc 100644
--- a/packages/core/src/hooks/useGlobalKeyHandler.ts
+++ b/packages/core/src/hooks/useGlobalKeyHandler.ts
@@ -12,14 +12,23 @@ interface HookParams {
export default ({ deleteKeyCode, multiSelectionKeyCode }: HookParams): void => {
const store = useStoreApi();
- const { deleteSelectedElements } = useReactFlow();
+ const { deleteElements } = useReactFlow();
+ // const { deleteSelectedElements } = useReactFlow();
const deleteKeyPressed = useKeyPress(deleteKeyCode);
const multiSelectionKeyPressed = useKeyPress(multiSelectionKeyCode);
useEffect(() => {
if (deleteKeyPressed) {
- deleteSelectedElements();
+ const {
+ nodeInternals,
+ edges,
+ } = store.getState();
+ const nodes = Array.from(nodeInternals.values());
+ const nodeIds = nodes.filter(node => node.selected).map(node => node.id);
+ const edgeIds = edges.filter(edge => edge.selected).map(edge => edge.id);
+ deleteElements(nodeIds, edgeIds);
+ store.setState({ nodesSelectionActive: false });
}
}, [deleteKeyPressed]);
diff --git a/packages/core/src/hooks/useReactFlow.ts b/packages/core/src/hooks/useReactFlow.ts
index 76043a2e..0e1ed6bb 100644
--- a/packages/core/src/hooks/useReactFlow.ts
+++ b/packages/core/src/hooks/useReactFlow.ts
@@ -192,6 +192,81 @@ export default function useReactFlow(): ReactFlo
}
}, []);
+ const deleteElements = useCallback((nodeIds, edgeIds) => {
+ const {
+ nodeInternals,
+ edges,
+ hasDefaultNodes,
+ hasDefaultEdges,
+ onNodesDelete,
+ onEdgesDelete,
+ onNodesChange,
+ onEdgesChange,
+ } = store.getState();
+ const nodes = Array.from(nodeInternals.values());
+ const nodesToRemove = nodes.reduce((res, node) => {
+ const parentHit = !nodeIds.includes(node.id) && node.parentNode && res.find((n) => n.id === node.parentNode);
+ const deletable = typeof node.deletable === 'boolean' ? node.deletable : true;
+ if (deletable && (nodeIds.includes(node.id) || parentHit)) {
+ res.push(node);
+ }
+
+ return res;
+ }, []);
+ const deletableEdges = edges.filter((e) => (typeof e.deletable === 'boolean' ? e.deletable : true));
+ const initialHitEdges = deletableEdges.filter((e) => edgeIds.includes(e.id));
+ if (nodesToRemove || initialHitEdges) {
+ const connectedEdges = getConnectedEdges(nodesToRemove, deletableEdges);
+ const edgesToRemove = [...initialHitEdges, ...connectedEdges];
+ const edgeIdsToRemove = edgesToRemove.reduce((res, edge) => {
+ if (!res.includes(edge.id)) {
+ res.push(edge.id);
+ }
+ return res;
+ }, []);
+
+ if (hasDefaultEdges || hasDefaultNodes) {
+ if (hasDefaultEdges) {
+ store.setState({
+ edges: edges.filter((e) => !edgeIdsToRemove.includes(e.id)),
+ });
+ }
+
+ if (hasDefaultNodes) {
+ nodesToRemove.forEach((node) => {
+ nodeInternals.delete(node.id);
+ });
+
+ store.setState({
+ nodeInternals: new Map(nodeInternals),
+ });
+ }
+ }
+
+ if (edgeIdsToRemove.length > 0) {
+ onEdgesDelete?.(edgesToRemove);
+
+ if (onEdgesChange) {
+ onEdgesChange(
+ edgeIdsToRemove.map((id) => ({
+ id,
+ type: 'remove',
+ }))
+ );
+ }
+ }
+
+ if (nodesToRemove.length > 0) {
+ onNodesDelete?.(nodesToRemove);
+
+ if (onNodesChange) {
+ const nodeChanges: NodeChange[] = nodesToRemove.map((n) => ({ id: n.id, type: 'remove' }));
+ onNodesChange(nodeChanges);
+ }
+ }
+ }
+ }, []);
+
return useMemo(() => {
return {
...viewportHelper,
@@ -205,6 +280,7 @@ export default function useReactFlow(): ReactFlo
addEdges,
toObject,
deleteSelectedElements,
+ deleteElements,
};
}, [
viewportHelper,
@@ -218,5 +294,6 @@ export default function useReactFlow(): ReactFlo
addEdges,
toObject,
deleteSelectedElements,
+ deleteElements,
]);
}
diff --git a/packages/core/src/types/instance.ts b/packages/core/src/types/instance.ts
index 058da326..deffc86c 100644
--- a/packages/core/src/types/instance.ts
+++ b/packages/core/src/types/instance.ts
@@ -25,6 +25,7 @@ export namespace Instance {
export type AddEdges = (payload: Edge[] | Edge) => void;
export type ToObject = () => ReactFlowJsonObject;
export type DeleteSelectedElements = () => void;
+ export type DeleteElements = (nodeIds: string[], edgeIds: string[]) => void
}
export type ReactFlowInstance = {
@@ -37,6 +38,7 @@ export type ReactFlowInstance = {
addEdges: Instance.AddEdges;
getEdge: Instance.GetEdge;
toObject: Instance.ToObject;
+ deleteElements: Instance.DeleteElements;
deleteSelectedElements: Instance.DeleteSelectedElements;
viewportInitialized: boolean;
} & Omit;