feat(deletion): add onBeforeDelete handler

This commit is contained in:
moklick
2023-12-23 11:57:18 +01:00
parent 5e406875ea
commit 84147be699
19 changed files with 165 additions and 115 deletions
@@ -64,6 +64,7 @@ const reactFlowFieldsToTrack = [
'isValidConnection',
'selectNodesOnDrag',
'nodeDragThreshold',
'onBeforeDelete',
] as const;
type ReactFlowFieldsToTrack = (typeof reactFlowFieldsToTrack)[number];
@@ -70,6 +70,7 @@ const ReactFlow = forwardRef<ReactFlowRefType, ReactFlowProps>(
onSelectionContextMenu,
onSelectionStart,
onSelectionEnd,
onBeforeDelete,
connectionMode,
connectionLineType = ConnectionLineType.Bezier,
connectionLineStyle,
@@ -284,6 +285,7 @@ const ReactFlow = forwardRef<ReactFlowRefType, ReactFlowProps>(
isValidConnection={isValidConnection}
selectNodesOnDrag={selectNodesOnDrag}
nodeDragThreshold={nodeDragThreshold}
onBeforeDelete={onBeforeDelete}
/>
<SelectionListener onSelectionChange={onSelectionChange} />
{children}
@@ -30,8 +30,8 @@ export default ({
useEffect(() => {
if (deleteKeyPressed) {
const { edges, nodes } = store.getState();
deleteElements({ nodes: nodes.filter(selected), edges: edges.filter(selected) });
const { edges, nodes, onBeforeDelete } = store.getState();
deleteElements({ nodes: nodes.filter(selected), edges: edges.filter(selected), onBeforeDelete });
store.setState({ nodesSelectionActive: false });
}
}, [deleteKeyPressed]);
+43 -46
View File
@@ -12,7 +12,6 @@ import type {
EdgeResetChange,
NodeRemoveChange,
EdgeRemoveChange,
NodeChange,
Node,
Edge,
} from '../types';
@@ -118,67 +117,65 @@ export default function useReactFlow<NodeType extends Node = Node, EdgeType exte
};
}, []);
const deleteElements = useCallback<Instance.DeleteElements>(({ nodes: nodesDeleted, edges: edgesDeleted }) => {
const {
nodes,
edges,
hasDefaultNodes,
hasDefaultEdges,
onNodesDelete,
onEdgesDelete,
onNodesChange,
onEdgesChange,
onDelete,
} = store.getState();
const { matchingNodes, matchingEdges } = getElementsToRemove<Node, Edge>({
nodesToRemove: nodesDeleted || [],
edgesToRemove: edgesDeleted || [],
nodes,
edges,
});
const deleteElements = useCallback<Instance.DeleteElements>(
({ nodes: nodesToRemove = [], edges: edgesToRemove = [], onBeforeDelete }) => {
const {
nodes,
edges,
hasDefaultNodes,
hasDefaultEdges,
onNodesDelete,
onEdgesDelete,
onNodesChange,
onEdgesChange,
onDelete,
} = store.getState();
const { nodes: matchingNodes, edges: matchingEdges } = getElementsToRemove({
nodesToRemove,
edgesToRemove,
nodes,
edges,
onBeforeDelete,
});
if (matchingNodes.length || matchingEdges.length) {
if (hasDefaultEdges || hasDefaultNodes) {
const hasMatchingEdges = matchingEdges.length > 0;
const hasMatchingNodes = matchingNodes.length > 0;
if (hasMatchingEdges) {
if (hasDefaultEdges) {
store.setState({
edges: edges.filter((e) => !matchingEdges.some((mE) => mE.id === e.id)),
});
}
onEdgesDelete?.(matchingEdges);
onEdgesChange?.(
matchingEdges.map((edge) => ({
id: edge.id,
type: 'remove',
}))
);
}
if (hasMatchingNodes) {
if (hasDefaultNodes) {
store.setState({
nodes: nodes.filter((n) => !matchingNodes.some((mN) => mN.id === n.id)),
});
}
onNodesDelete?.(matchingNodes);
onNodesChange?.(matchingNodes.map((node) => ({ id: node.id, type: 'remove' })));
}
if (matchingEdges.length > 0) {
onEdgesDelete?.(matchingEdges);
if (onEdgesChange) {
onEdgesChange(
matchingEdges.map((edge) => ({
id: edge.id,
type: 'remove',
}))
);
}
if (hasMatchingNodes || hasMatchingEdges) {
onDelete?.({ nodes: matchingNodes, edges: matchingEdges });
}
if (matchingNodes.length > 0) {
onNodesDelete?.(matchingNodes as Node[]);
if (onNodesChange) {
const nodeChanges: NodeChange[] = matchingNodes.map((node) => ({ id: node.id, type: 'remove' }));
onNodesChange(nodeChanges);
}
}
onDelete?.({ nodes: matchingNodes, edges: matchingEdges });
}
return { deletedNodes: matchingNodes, deletedEdges: matchingEdges };
}, []);
return { deletedNodes: matchingNodes, deletedEdges: matchingEdges };
},
[]
);
const getNodeRect = useCallback(
(nodeOrRect: NodeType | { id: Node['id'] } | Rect): [Rect | null, NodeType | null | undefined, boolean] => {
+1
View File
@@ -79,6 +79,7 @@ export {
type ColorMode,
type ColorModeClass,
type HandleType,
type OnBeforeDelete,
} from '@xyflow/system';
// system utils
@@ -21,6 +21,7 @@ import type {
IsValidConnection,
ColorMode,
SnapGrid,
OnBeforeDelete,
} from '@xyflow/system';
import type {
@@ -100,6 +101,7 @@ export type ReactFlowProps = Omit<HTMLAttributes<HTMLDivElement>, 'onError'> & {
onPaneMouseEnter?: (event: ReactMouseEvent) => void;
onPaneMouseMove?: (event: ReactMouseEvent) => void;
onPaneMouseLeave?: (event: ReactMouseEvent) => void;
onBeforeDelete?: OnBeforeDelete;
nodeTypes?: NodeTypes;
edgeTypes?: EdgeTypes;
connectionLineType?: ConnectionLineType;
+3 -2
View File
@@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-namespace */
import type { Rect, Viewport } from '@xyflow/system';
import type { OnBeforeDelete, Rect, Viewport } from '@xyflow/system';
import type { Node, Edge, ViewportHelperFunctions } from '.';
export type ReactFlowJsonObject<NodeType extends Node = Node, EdgeType extends Edge = Edge> = {
@@ -12,6 +12,7 @@ export type ReactFlowJsonObject<NodeType extends Node = Node, EdgeType extends E
export type DeleteElementsOptions = {
nodes?: (Node | { id: Node['id'] })[];
edges?: (Edge | { id: Edge['id'] })[];
onBeforeDelete?: OnBeforeDelete;
};
export namespace Instance {
@@ -31,7 +32,7 @@ export namespace Instance {
NodeType,
EdgeType
>;
export type DeleteElements = ({ nodes, edges }: DeleteElementsOptions) => {
export type DeleteElements = (params: DeleteElementsOptions) => {
deletedNodes: Node[];
deletedEdges: Edge[];
};
+2
View File
@@ -27,6 +27,7 @@ import {
type EdgeLookup,
type ConnectionLookup,
type NodeLookup,
OnBeforeDelete,
} from '@xyflow/system';
import type {
@@ -132,6 +133,7 @@ export type ReactFlowStore = {
onViewportChangeStart?: OnViewportChange;
onViewportChange?: OnViewportChange;
onViewportChangeEnd?: OnViewportChange;
onBeforeDelete?: OnBeforeDelete;
onSelectionChangeHandlers: OnSelectionChangeFunc[];