From ab9e340b7b301fb7c84e42422c51c5c78fd3c3a7 Mon Sep 17 00:00:00 2001 From: Alireza Sheikholmolouki Date: Tue, 4 Oct 2022 14:24:57 +0200 Subject: [PATCH] feat(examples): added an example for cancelling the connection --- examples/vite-app/package.json | 1 + examples/vite-app/src/App/index.tsx | 5 ++ .../CancelConnection/Timer.module.css | 18 ++++++ .../src/examples/CancelConnection/Timer.tsx | 21 +++++++ .../src/examples/CancelConnection/data.ts | 34 +++++++++++ .../CancelConnection/hooks/useCountdown.ts | 35 +++++++++++ .../src/examples/CancelConnection/index.tsx | 59 +++++++++++++++++++ packages/core/src/types/general.ts | 1 + pnpm-lock.yaml | 2 + 9 files changed, 176 insertions(+) create mode 100644 examples/vite-app/src/examples/CancelConnection/Timer.module.css create mode 100644 examples/vite-app/src/examples/CancelConnection/Timer.tsx create mode 100644 examples/vite-app/src/examples/CancelConnection/data.ts create mode 100644 examples/vite-app/src/examples/CancelConnection/hooks/useCountdown.ts create mode 100644 examples/vite-app/src/examples/CancelConnection/index.tsx diff --git a/examples/vite-app/package.json b/examples/vite-app/package.json index a4e6eab8..cf31055e 100644 --- a/examples/vite-app/package.json +++ b/examples/vite-app/package.json @@ -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", diff --git a/examples/vite-app/src/App/index.tsx b/examples/vite-app/src/App/index.tsx index 67e46e55..4e6342cc 100644 --- a/examples/vite-app/src/App/index.tsx +++ b/examples/vite-app/src/App/index.tsx @@ -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 = () => { diff --git a/examples/vite-app/src/examples/CancelConnection/Timer.module.css b/examples/vite-app/src/examples/CancelConnection/Timer.module.css new file mode 100644 index 00000000..be36108e --- /dev/null +++ b/examples/vite-app/src/examples/CancelConnection/Timer.module.css @@ -0,0 +1,18 @@ +.Timer { + position: absolute; + bottom: 0; + transition-duration: 0.3s; + left: 50%; + transform: translate(-50%, 100%); + font-size: 1.5rem; + z-index: 999; + background-color: white; + padding: 0.5rem 1rem; + 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(-10px); +} \ No newline at end of file diff --git a/examples/vite-app/src/examples/CancelConnection/Timer.tsx b/examples/vite-app/src/examples/CancelConnection/Timer.tsx new file mode 100644 index 00000000..5c09ec44 --- /dev/null +++ b/examples/vite-app/src/examples/CancelConnection/Timer.tsx @@ -0,0 +1,21 @@ +import cc from 'classcat'; +import styles from './Timer.module.css'; + +interface Props { + remaining: number; + show: boolean; +} + +export default function Timer({ + remaining, + show, +}: Props) { + return ( +
+ Connection will be canceled in {remaining} seconds +
+ ) +} \ No newline at end of file diff --git a/examples/vite-app/src/examples/CancelConnection/data.ts b/examples/vite-app/src/examples/CancelConnection/data.ts new file mode 100644 index 00000000..821b79fe --- /dev/null +++ b/examples/vite-app/src/examples/CancelConnection/data.ts @@ -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' }, +]; diff --git a/examples/vite-app/src/examples/CancelConnection/hooks/useCountdown.ts b/examples/vite-app/src/examples/CancelConnection/hooks/useCountdown.ts new file mode 100644 index 00000000..eee7aec4 --- /dev/null +++ b/examples/vite-app/src/examples/CancelConnection/hooks/useCountdown.ts @@ -0,0 +1,35 @@ +import { useRef, useState } from 'react'; + +const useCountdown = (callback: () => void) => { + const interval = useRef(); + 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; diff --git a/examples/vite-app/src/examples/CancelConnection/index.tsx b/examples/vite-app/src/examples/CancelConnection/index.tsx new file mode 100644 index 00000000..845f3213 --- /dev/null +++ b/examples/vite-app/src/examples/CancelConnection/index.tsx @@ -0,0 +1,59 @@ +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 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(5); + const onConnectEnd: OnConnectEnd = () => countdown.stop(); + + const onConnect = (params: Connection | Edge) => setEdges((eds) => addEdge(params, eds)); + + return ( + <> + + + + + + + ); +} + +export default () => ( + + + +); diff --git a/packages/core/src/types/general.ts b/packages/core/src/types/general.ts index ba645b43..77dea3a5 100644 --- a/packages/core/src/types/general.ts +++ b/packages/core/src/types/general.ts @@ -222,6 +222,7 @@ export type ReactFlowActions = { setMaxZoom: (maxZoom: number) => void; setTranslateExtent: (translateExtent: CoordinateExtent) => void; setNodeExtent: (nodeExtent: CoordinateExtent) => void; + cancelConnection: () => void; reset: () => void; }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 113cb1b0..26177a37 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -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