chore(react): add addNodeOnEdgeDrop example

This commit is contained in:
moklick
2024-02-28 10:25:20 +01:00
parent e5c667d068
commit aead13f485
2 changed files with 105 additions and 0 deletions

View File

@@ -49,6 +49,7 @@ import UseConnection from '../examples/UseConnection';
import UseNodesInitialized from '../examples/UseNodesInit';
import UseNodesData from '../examples/UseNodesData';
import UseHandleConnections from '../examples/UseHandleConnections';
import AddNodeOnEdgeDrop from '../examples/AddNodeOnEdgeDrop';
export interface IRoute {
name: string;
@@ -57,6 +58,11 @@ export interface IRoute {
}
const routes: IRoute[] = [
{
name: 'Add Node on edge Drop',
path: 'add-node-edge-drop',
component: AddNodeOnEdgeDrop,
},
{
name: 'Basic',
path: 'basic',

View File

@@ -0,0 +1,99 @@
import { useCallback, useRef } from 'react';
import {
ReactFlow,
useNodesState,
useEdgesState,
addEdge,
useReactFlow,
ReactFlowProvider,
OnConnect,
OnConnectStart,
OnConnectEnd,
Node,
Edge,
} from '@xyflow/react';
import '@xyflow/react/dist/style.css';
const initialNodes: Node[] = [
{
id: '0',
type: 'input',
data: { label: 'Node' },
position: { x: 0, y: 50 },
},
];
const initialEdges: Edge[] = [];
let id = 1;
const getId = () => `${id++}`;
const AddNodeOnEdgeDrop = () => {
const reactFlowWrapper = useRef(null);
const connectingNodeId = useRef<string | null>(null);
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
const { screenToFlowPosition } = useReactFlow();
const onConnect: OnConnect = useCallback((params) => {
// reset the start node on connections
connectingNodeId.current = null;
setEdges((eds) => addEdge(params, eds));
}, []);
const onConnectStart: OnConnectStart = useCallback((_, { nodeId }) => {
connectingNodeId.current = nodeId;
}, []);
const onConnectEnd: OnConnectEnd = useCallback(
(event) => {
if (!connectingNodeId.current) return;
const targetIsPane = (event.target as HTMLDivElement)?.classList.contains('react-flow__pane');
if (targetIsPane && 'clientX' in event && 'clientY' in event) {
// we need to remove the wrapper bounds, in order to get the correct position
const id = getId();
const newNode: Node = {
id,
position: screenToFlowPosition({
x: event.clientX,
y: event.clientY,
}),
data: { label: `Node ${id}` },
origin: [0.5, 0.0],
};
const newEdge: Edge = {
id,
source: connectingNodeId.current,
target: id,
};
setNodes((nds) => nds.concat(newNode));
setEdges((eds) => eds.concat(newEdge));
}
},
[screenToFlowPosition]
);
return (
<div className="wrapper" ref={reactFlowWrapper} style={{ height: '100%' }}>
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onConnect={onConnect}
onConnectStart={onConnectStart}
onConnectEnd={onConnectEnd}
fitView
/>
</div>
);
};
export default () => (
<ReactFlowProvider>
<AddNodeOnEdgeDrop />
</ReactFlowProvider>
);