feat: Added reconnectable edges
Modified edges to support being disconnected and reconnected upon dragging their connection away from the currently connected node. ref: N25B-114
This commit is contained in:
@@ -1,14 +1,17 @@
|
||||
import './VisProgUI.css'
|
||||
|
||||
import { useState, useCallback } from 'react';
|
||||
import {
|
||||
useCallback,
|
||||
useRef
|
||||
} from 'react';
|
||||
import {
|
||||
Background,
|
||||
Controls,
|
||||
ReactFlow,
|
||||
applyNodeChanges,
|
||||
applyEdgeChanges,
|
||||
addEdge,
|
||||
type NodeChange,
|
||||
type EdgeChange,
|
||||
type Edge, type Connection
|
||||
useNodesState,
|
||||
useEdgesState,
|
||||
reconnectEdge,
|
||||
addEdge, type Edge, type Connection,
|
||||
} from '@xyflow/react';
|
||||
import '@xyflow/react/dist/style.css';
|
||||
|
||||
@@ -18,39 +21,55 @@ const initialNodes = [
|
||||
];
|
||||
const initialEdges = [{id: 'n1-n2', source: 'n1', target: 'n2'}];
|
||||
|
||||
export default function App() {
|
||||
const [nodes, setNodes] = useState(initialNodes);
|
||||
const [edges, setEdges] = useState(initialEdges);
|
||||
const VisualProgrammingUI = ()=> {
|
||||
const edgeReconnectSuccessful = useRef(true);
|
||||
const [nodes, , onNodesChange] = useNodesState(initialNodes);
|
||||
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
|
||||
|
||||
|
||||
const onNodesChange = useCallback(
|
||||
(changes: NodeChange<{
|
||||
id: string;
|
||||
position: { x: number; y: number; };
|
||||
data: { label: string; };
|
||||
}>[]) => setNodes((nodesSnapshot) => applyNodeChanges(changes, nodesSnapshot)),
|
||||
[],
|
||||
);
|
||||
const onEdgesChange = useCallback(
|
||||
(changes: EdgeChange<{ id: string; source: string; target: string; }>[]) => setEdges((edgesSnapshot) => applyEdgeChanges(changes, edgesSnapshot)),
|
||||
[],
|
||||
);
|
||||
|
||||
|
||||
const onConnect = useCallback(
|
||||
(params: Edge | Connection) => setEdges((edgesSnapshot) => addEdge(params, edgesSnapshot)),
|
||||
[],
|
||||
(params: Edge | Connection) => setEdges((els) => addEdge(params, els)),
|
||||
[setEdges],
|
||||
);
|
||||
|
||||
const onReconnectStart = useCallback(() => {
|
||||
edgeReconnectSuccessful.current = false;
|
||||
}, []);
|
||||
|
||||
const onReconnect = useCallback((oldEdge: Edge, newConnection: Connection) => {
|
||||
edgeReconnectSuccessful.current = true;
|
||||
setEdges((els) => reconnectEdge(oldEdge, newConnection, els));
|
||||
}, [setEdges]);
|
||||
|
||||
const onReconnectEnd = useCallback((_: unknown, edge: { id: string; }) => {
|
||||
if (!edgeReconnectSuccessful.current) {
|
||||
setEdges((eds) => eds.filter((e) => e.id !== edge.id));
|
||||
}
|
||||
|
||||
edgeReconnectSuccessful.current = true;
|
||||
}, [setEdges]);
|
||||
|
||||
return (
|
||||
<div style={{ width: '100vw', height: '100vh' }}>
|
||||
<div style={{ width: '90vw', height: '90vh' }}>
|
||||
<ReactFlow
|
||||
nodes={nodes}
|
||||
edges={edges}
|
||||
onNodesChange={onNodesChange}
|
||||
onEdgesChange={onEdgesChange}
|
||||
snapToGrid
|
||||
onReconnect={onReconnect}
|
||||
onReconnectStart={onReconnectStart}
|
||||
onReconnectEnd={onReconnectEnd}
|
||||
onConnect={onConnect}
|
||||
fitView
|
||||
/>
|
||||
attributionPosition="top-right"
|
||||
>
|
||||
<Controls />
|
||||
<Background />
|
||||
</ReactFlow>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default VisualProgrammingUI
|
||||
@@ -1,10 +1,12 @@
|
||||
import { StrictMode } from 'react'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import './index.css'
|
||||
import App from './VisualProgrammingUI/VisProgUI.tsx'
|
||||
import App from './App.tsx'
|
||||
import VisualProgrammingUI from "./VisualProgrammingUI/VisProgUI.tsx";
|
||||
|
||||
createRoot(document.getElementById('root')!).render(
|
||||
<StrictMode>
|
||||
<App />
|
||||
<VisualProgrammingUI />
|
||||
</StrictMode>,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user