Merge pull request #2469 from Alireza29675/feat/cancel-connection-example

feat(examples): example added for cancelConnection
This commit is contained in:
Moritz Klack
2022-10-04 17:41:43 +02:00
committed by GitHub
9 changed files with 199 additions and 0 deletions
+1
View File
@@ -13,6 +13,7 @@
"test-e2e": "start-server-and-test 'pnpm serve' http-get://localhost:3000 'pnpm test-e2e-cypress'"
},
"dependencies": {
"classcat": "^5.0.3",
"dagre": "^0.8.5",
"localforage": "^1.10.0",
"react": "^18.2.0",
+5
View File
@@ -35,6 +35,7 @@ import UseReactFlow from '../examples/UseReactFlow';
import Validation from '../examples/Validation';
import UseKeyPress from '../examples/UseKeyPress';
import EdgeRouting from '../examples/EdgeRouting';
import CancelConnection from '../examples/CancelConnection';
const routes = [
{
@@ -173,6 +174,10 @@ const routes = [
path: '/use-key-press',
component: UseKeyPress,
},
{
path: '/cancel-connection',
component: CancelConnection
}
];
const Header = () => {
@@ -0,0 +1,31 @@
.Timer {
position: absolute;
bottom: 0;
transition-duration: 0.3s;
left: 50%;
transform: translate(-50%, 100%);
font-size: 1.5rem;
z-index: 999;
background: linear-gradient(#fff, #fff, #f5f5f5);
padding: 0.8rem 1.5rem;
border-radius: 5px;
border: 1px solid #ccc;
box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.2);
}
.Timer.show {
transform: translate(-50%, 0%) translateY(-15px);
}
.progress {
display: none;
position: absolute;
bottom: 0;
left: 0;
height: 5px;
background: linear-gradient(to right, #42df96, #16dfed);
}
.Timer.show .progress {
display: block;
}
@@ -0,0 +1,28 @@
import cc from 'classcat';
import styles from './Timer.module.css';
interface Props {
duration: number;
remaining: number;
show: boolean;
}
export default function Timer({
duration,
remaining,
show,
}: Props) {
const percentage = 100 - (remaining / duration) * 100;
return (
<div className={cc({
[styles.Timer]: true,
[styles.show]: show,
})}>
<div className={styles.progress} style={{
width: `${percentage}%`,
}} />
Connection will be canceled in {remaining} seconds
</div>
)
}
@@ -0,0 +1,34 @@
import { Edge, Node } from 'reactflow';
export const initialNodes: Node[] = [
{
id: '1',
type: 'input',
data: { label: 'Node 1' },
position: { x: 250, y: 5 },
className: 'light',
},
{
id: '2',
data: { label: 'Node 2' },
position: { x: 100, y: 100 },
className: 'light',
},
{
id: '3',
data: { label: 'Node 3' },
position: { x: 400, y: 100 },
className: 'light',
},
{
id: '4',
data: { label: 'Node 4' },
position: { x: 400, y: 200 },
className: 'light',
},
];
export const initialEdges: Edge[] = [
{ id: 'e1-2', source: '1', target: '2', animated: true },
{ id: 'e1-3', source: '1', target: '3' },
];
@@ -0,0 +1,35 @@
import { useRef, useState } from 'react';
const useCountdown = (callback: () => void) => {
const interval = useRef<NodeJS.Timer>();
const [remaining, setRemaining] = useState(0);
const start = (duration: number) => {
setRemaining(duration);
interval.current = setInterval(() => {
setRemaining((prev) => {
if (prev === 1) {
clearInterval(interval.current);
callback();
}
return prev - 1;
});
}, 1000);
};
const stop = () => {
clearInterval(interval.current);
setRemaining(0);
};
return {
start,
remaining,
stop,
counting: remaining > 0,
};
};
export default useCountdown;
@@ -0,0 +1,62 @@
import ReactFlow, {
Background,
MiniMap,
addEdge,
ReactFlowProvider,
Connection,
Edge,
useNodesState,
useEdgesState,
OnConnectStart,
OnConnectEnd,
useStore,
} from 'reactflow';
import useCountdown from './hooks/useCountdown';
import { initialEdges, initialNodes } from './data';
import Timer from './Timer';
const CANCEL_AFTER = 5; // seconds
const CancelConnection = () => {
const [nodes, _, onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
const cancelConnection = useStore(state => state.cancelConnection)
// Cancels connection after 5 seconds
const countdown = useCountdown(() => cancelConnection());
const onConnectStart: OnConnectStart = () => countdown.start(CANCEL_AFTER);
const onConnectEnd: OnConnectEnd = () => countdown.stop();
const onConnect = (params: Connection | Edge) => setEdges((eds) => addEdge(params, eds));
return (
<>
<Timer
duration={CANCEL_AFTER}
show={countdown.counting}
remaining={countdown.remaining}
/>
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onConnectStart={onConnectStart}
onConnectEnd={onConnectEnd}
onConnect={onConnect}
fitView
maxZoom={2}
>
<Background />
<MiniMap />
</ReactFlow>
</>
);
}
export default () => (
<ReactFlowProvider>
<CancelConnection />
</ReactFlowProvider>
);
+1
View File
@@ -224,6 +224,7 @@ export type ReactFlowActions = {
setMaxZoom: (maxZoom: number) => void;
setTranslateExtent: (translateExtent: CoordinateExtent) => void;
setNodeExtent: (nodeExtent: CoordinateExtent) => void;
cancelConnection: () => void;
reset: () => void;
};
+2
View File
@@ -60,6 +60,7 @@ importers:
'@types/react': ^18.0.17
'@types/react-dom': ^18.0.6
'@vitejs/plugin-react': ^2.1.0
classcat: ^5.0.3
cypress: ^10.6.0
cypress-real-events: ^1.7.1
dagre: ^0.8.5
@@ -72,6 +73,7 @@ importers:
typescript: ^4.8.3
vite: ^3.1.0
dependencies:
classcat: registry.npmjs.org/classcat/5.0.4
dagre: registry.npmjs.org/dagre/0.8.5
localforage: registry.npmjs.org/localforage/1.10.0
react: registry.npmjs.org/react/18.2.0