feat(props): add onNodesDelete and onEdgesDelete handler
This commit is contained in:
@@ -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 onEdgeMouseMove = (_: MouseEvent, edge: Edge) => console.log('edge mouse move', edge);
|
||||||
const onEdgeMouseLeave = (_: MouseEvent, edge: Edge) => console.log('edge mouse leave', edge);
|
const onEdgeMouseLeave = (_: MouseEvent, edge: Edge) => console.log('edge mouse leave', edge);
|
||||||
const onEdgeDoubleClick = (_: MouseEvent, edge: Edge) => console.log('edge double click', 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[] = [
|
const initialNodes: Node[] = [
|
||||||
{
|
{
|
||||||
@@ -196,6 +198,8 @@ const OverviewFlow = () => {
|
|||||||
fitViewOptions={{ padding: 0.2 }}
|
fitViewOptions={{ padding: 0.2 }}
|
||||||
attributionPosition="top-right"
|
attributionPosition="top-right"
|
||||||
maxZoom={Infinity}
|
maxZoom={Infinity}
|
||||||
|
onNodesDelete={onNodesDelete}
|
||||||
|
onEdgesDelete={onEdgesDelete}
|
||||||
>
|
>
|
||||||
<MiniMap nodeStrokeColor={nodeStrokeColor} nodeColor={nodeColor} nodeBorderRadius={2} />
|
<MiniMap nodeStrokeColor={nodeStrokeColor} nodeColor={nodeColor} nodeBorderRadius={2} />
|
||||||
<Controls />
|
<Controls />
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ interface StoreUpdaterProps {
|
|||||||
defaultEdgeOptions?: DefaultEdgeOptions;
|
defaultEdgeOptions?: DefaultEdgeOptions;
|
||||||
fitView?: boolean;
|
fitView?: boolean;
|
||||||
fitViewOptions?: FitViewOptions;
|
fitViewOptions?: FitViewOptions;
|
||||||
|
onNodesDelete?: (nodes: Node[]) => void;
|
||||||
|
onEdgesDelete?: (edges: Edge[]) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const selector = (s: ReactFlowState) => ({
|
const selector = (s: ReactFlowState) => ({
|
||||||
@@ -100,6 +102,8 @@ const StoreUpdater = ({
|
|||||||
defaultEdgeOptions,
|
defaultEdgeOptions,
|
||||||
fitView,
|
fitView,
|
||||||
fitViewOptions,
|
fitViewOptions,
|
||||||
|
onNodesDelete,
|
||||||
|
onEdgesDelete,
|
||||||
}: StoreUpdaterProps) => {
|
}: StoreUpdaterProps) => {
|
||||||
const {
|
const {
|
||||||
setNodes,
|
setNodes,
|
||||||
@@ -137,6 +141,8 @@ const StoreUpdater = ({
|
|||||||
useDirectStoreUpdater('connectOnClick', connectOnClick, store.setState);
|
useDirectStoreUpdater('connectOnClick', connectOnClick, store.setState);
|
||||||
useDirectStoreUpdater('fitViewOnInit', fitView, store.setState);
|
useDirectStoreUpdater('fitViewOnInit', fitView, store.setState);
|
||||||
useDirectStoreUpdater('fitViewOnInitOptions', fitViewOptions, store.setState);
|
useDirectStoreUpdater('fitViewOnInitOptions', fitViewOptions, store.setState);
|
||||||
|
useDirectStoreUpdater('onNodesDelete', onNodesDelete, store.setState);
|
||||||
|
useDirectStoreUpdater('onEdgesDelete', onEdgesDelete, store.setState);
|
||||||
|
|
||||||
useStoreUpdater<Node[]>(nodes, setNodes);
|
useStoreUpdater<Node[]>(nodes, setNodes);
|
||||||
useStoreUpdater<Edge[]>(edges, setEdges);
|
useStoreUpdater<Edge[]>(edges, setEdges);
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ const ReactFlow = forwardRef<ReactFlowRefType, ReactFlowProps>(
|
|||||||
onNodeDragStart,
|
onNodeDragStart,
|
||||||
onNodeDrag,
|
onNodeDrag,
|
||||||
onNodeDragStop,
|
onNodeDragStop,
|
||||||
|
onNodesDelete,
|
||||||
|
onEdgesDelete,
|
||||||
onSelectionChange,
|
onSelectionChange,
|
||||||
onSelectionDragStart,
|
onSelectionDragStart,
|
||||||
onSelectionDrag,
|
onSelectionDrag,
|
||||||
@@ -214,6 +216,8 @@ const ReactFlow = forwardRef<ReactFlowRefType, ReactFlowProps>(
|
|||||||
defaultEdgeOptions={defaultEdgeOptions}
|
defaultEdgeOptions={defaultEdgeOptions}
|
||||||
fitView={fitView}
|
fitView={fitView}
|
||||||
fitViewOptions={fitViewOptions}
|
fitViewOptions={fitViewOptions}
|
||||||
|
onNodesDelete={onNodesDelete}
|
||||||
|
onEdgesDelete={onEdgesDelete}
|
||||||
/>
|
/>
|
||||||
{onSelectionChange && <SelectionListener onSelectionChange={onSelectionChange} />}
|
{onSelectionChange && <SelectionListener onSelectionChange={onSelectionChange} />}
|
||||||
{children}
|
{children}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export default ({ deleteKeyCode, multiSelectionKeyCode }: HookParams): void => {
|
|||||||
const multiSelectionKeyPressed = useKeyPress(multiSelectionKeyCode);
|
const multiSelectionKeyPressed = useKeyPress(multiSelectionKeyCode);
|
||||||
|
|
||||||
useEffect(() => {
|
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
|
// @TODO: work with nodeInternals instead of converting it to an array
|
||||||
const nodes = Array.from(nodeInternals).map(([_, node]) => node);
|
const nodes = Array.from(nodeInternals).map(([_, node]) => node);
|
||||||
const selectedNodes = nodes.filter((n) => n.selected);
|
const selectedNodes = nodes.filter((n) => n.selected);
|
||||||
@@ -33,7 +33,8 @@ export default ({ deleteKeyCode, multiSelectionKeyCode }: HookParams): void => {
|
|||||||
|
|
||||||
if (deleteKeyPressed && (selectedNodes || selectedEdges)) {
|
if (deleteKeyPressed && (selectedNodes || selectedEdges)) {
|
||||||
const connectedEdges = getConnectedEdges(selectedNodes, edges);
|
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) {
|
if (hasDefaultNodes) {
|
||||||
selectedNodes.forEach((node) => {
|
selectedNodes.forEach((node) => {
|
||||||
@@ -48,6 +49,9 @@ export default ({ deleteKeyCode, multiSelectionKeyCode }: HookParams): void => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onNodesDelete?.(selectedNodes);
|
||||||
|
onEdgesDelete?.(edgesToRemove);
|
||||||
|
|
||||||
if (onNodesChange) {
|
if (onNodesChange) {
|
||||||
const nodeChanges: NodeChange[] = selectedNodes.map((n) => ({ id: n.id, type: 'remove' }));
|
const nodeChanges: NodeChange[] = selectedNodes.map((n) => ({ id: n.id, type: 'remove' }));
|
||||||
onNodesChange(nodeChanges);
|
onNodesChange(nodeChanges);
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ export interface ReactFlowProps extends HTMLAttributes<HTMLDivElement> {
|
|||||||
onNodeDragStart?: (event: ReactMouseEvent, node: Node) => void;
|
onNodeDragStart?: (event: ReactMouseEvent, node: Node) => void;
|
||||||
onNodeDrag?: (event: ReactMouseEvent, node: Node) => void;
|
onNodeDrag?: (event: ReactMouseEvent, node: Node) => void;
|
||||||
onNodeDragStop?: (event: ReactMouseEvent, node: Node) => void;
|
onNodeDragStop?: (event: ReactMouseEvent, node: Node) => void;
|
||||||
|
onNodesDelete?: (nodes: Node[]) => void;
|
||||||
|
onEdgesDelete?: (edges: Edge[]) => void;
|
||||||
onConnect?: OnConnect;
|
onConnect?: OnConnect;
|
||||||
onConnectStart?: OnConnectStart;
|
onConnectStart?: OnConnectStart;
|
||||||
onConnectStop?: OnConnectStop;
|
onConnectStop?: OnConnectStop;
|
||||||
|
|||||||
@@ -164,6 +164,9 @@ export type ReactFlowStore = {
|
|||||||
fitViewOnInit: boolean;
|
fitViewOnInit: boolean;
|
||||||
fitViewOnInitDone: boolean;
|
fitViewOnInitDone: boolean;
|
||||||
fitViewOnInitOptions: FitViewOptions | undefined;
|
fitViewOnInitOptions: FitViewOptions | undefined;
|
||||||
|
|
||||||
|
onNodesDelete?: (nodes: Node[]) => void;
|
||||||
|
onEdgesDelete?: (edges: Edge[]) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ReactFlowActions = {
|
export type ReactFlowActions = {
|
||||||
|
|||||||
Reference in New Issue
Block a user