diff --git a/examples/vite-app/package.json b/examples/vite-app/package.json index 7a87f510..5b5d4762 100644 --- a/examples/vite-app/package.json +++ b/examples/vite-app/package.json @@ -21,7 +21,8 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.3.0", - "reactflow": "workspace:*" + "reactflow": "workspace:*", + "zustand": "^4.3.1" }, "devDependencies": { "@cypress/skip-test": "^2.6.1", diff --git a/examples/vite-app/src/examples/Validation/ConnectionStatus.tsx b/examples/vite-app/src/examples/Validation/ConnectionStatus.tsx new file mode 100644 index 00000000..4102b9a7 --- /dev/null +++ b/examples/vite-app/src/examples/Validation/ConnectionStatus.tsx @@ -0,0 +1,42 @@ +import { ReactFlowState, useStore } from 'reactflow'; +import { shallow } from 'zustand/shallow'; + +import styles from './validation.module.css'; + +const selector = (state: ReactFlowState) => ({ + connectionPosition: state.connectionPosition, + connectionStatus: state.connectionStatus, + connectionNodeId: state.connectionNodeId, + connectionTargetNodeId: state.connectionTargetNodeId, +}); + +function ConnectionStatus() { + const { connectionPosition, connectionStatus, connectionNodeId, connectionTargetNodeId } = useStore( + selector, + shallow + ); + + if (!connectionPosition) { + return null; + } + + return ( +
+ {connectionNodeId ? ( + <> +
+ connection info +
+
position: {JSON.stringify(connectionPosition)}
+
status: {JSON.stringify(connectionStatus)}
+
source node id: {JSON.stringify(connectionNodeId)}
+
target node id: {JSON.stringify(connectionTargetNodeId)}
+ + ) : ( + 'no connection data' + )} +
+ ); +} + +export default ConnectionStatus; diff --git a/examples/vite-app/src/examples/Validation/index.tsx b/examples/vite-app/src/examples/Validation/index.tsx index c55d8178..ed2b5419 100644 --- a/examples/vite-app/src/examples/Validation/index.tsx +++ b/examples/vite-app/src/examples/Validation/index.tsx @@ -16,6 +16,8 @@ import ReactFlow, { Edge, } from 'reactflow'; +import ConnectionStatus from './ConnectionStatus'; + import styles from './validation.module.css'; const initialNodes: Node[] = [ @@ -96,7 +98,9 @@ const ValidationFlow = () => { onEdgeUpdate={onEdgeUpdate} isValidConnection={isValidConnection} fitView - /> + > + + ); }; diff --git a/examples/vite-app/src/examples/Validation/validation.module.css b/examples/vite-app/src/examples/Validation/validation.module.css index 63d58eee..c19a8723 100644 --- a/examples/vite-app/src/examples/Validation/validation.module.css +++ b/examples/vite-app/src/examples/Validation/validation.module.css @@ -39,3 +39,10 @@ .validationflow :global .invalid .react-flow__connection-path { stroke: #ff6060; } + +.connectionstatus { + position: absolute; + bottom: 20px; + left: 50%; + transform: translateX(-50%); +} diff --git a/packages/core/src/components/Handle/handler.ts b/packages/core/src/components/Handle/handler.ts index 46cc64e9..84effd91 100644 --- a/packages/core/src/components/Handle/handler.ts +++ b/packages/core/src/components/Handle/handler.ts @@ -93,6 +93,8 @@ export function handlePointerDown({ connectionHandleId: handleId, connectionHandleType: handleType, connectionStatus: null, + connectionTargetNodeId: null, + connectionTargetHandeId: null, }); onConnectStart?.(event, { nodeId, handleId, handleType }); @@ -139,6 +141,8 @@ export function handlePointerDown({ ) : connectionPosition, connectionStatus: getConnectionStatus(!!prevClosestHandle, isValid), + connectionTargetNodeId: connection.target, + connectionTargetHandleId: connection.targetHandle, }); if (!prevClosestHandle && !isValid && !handleDomNode) { diff --git a/packages/core/src/store/index.ts b/packages/core/src/store/index.ts index c85225db..58cc5080 100644 --- a/packages/core/src/store/index.ts +++ b/packages/core/src/store/index.ts @@ -275,6 +275,8 @@ const createRFStore = () => connectionHandleId: initialState.connectionHandleId, connectionHandleType: initialState.connectionHandleType, connectionStatus: initialState.connectionStatus, + connectionTargetNodeId: initialState.connectionTargetNodeId, + connectionTargetHandleId: initialState.connectionTargetHandleId, }), reset: () => set({ ...initialState }), })); diff --git a/packages/core/src/store/initialState.ts b/packages/core/src/store/initialState.ts index 55aca27f..2722038d 100644 --- a/packages/core/src/store/initialState.ts +++ b/packages/core/src/store/initialState.ts @@ -31,6 +31,8 @@ const initialState: ReactFlowStore = { connectionNodeId: null, connectionHandleId: null, connectionHandleType: 'source', + connectionTargetNodeId: null, + connectionTargetHandleId: null, connectionPosition: { x: 0, y: 0 }, connectionStatus: null, connectionMode: ConnectionMode.Strict, diff --git a/packages/core/src/types/general.ts b/packages/core/src/types/general.ts index 549228a8..fab391d0 100644 --- a/packages/core/src/types/general.ts +++ b/packages/core/src/types/general.ts @@ -169,6 +169,8 @@ export type ReactFlowStore = { connectionNodeId: string | null; connectionHandleId: string | null; + connectionTargetNodeId: string | null; + connectionTargetHandleId: string | null; connectionHandleType: HandleType | null; connectionPosition: XYPosition; connectionStatus: ConnectionStatus | null; @@ -284,4 +286,4 @@ export type OnError = (id: string, message: string) => void; export interface UpdateEdgeOptions { shouldReplaceId?: boolean; -} \ No newline at end of file +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a1a1c3d2..3c4975fe 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -74,6 +74,7 @@ importers: start-server-and-test: ^1.14.0 typescript: ^4.9.4 vite: ^4.0.4 + zustand: ^4.3.1 dependencies: '@reactflow/node-resizer': link:../../packages/node-resizer classcat: registry.npmjs.org/classcat/5.0.4 @@ -83,6 +84,7 @@ importers: react-dom: registry.npmjs.org/react-dom/18.2.0_react@18.2.0 react-router-dom: registry.npmjs.org/react-router-dom/6.3.0_biqbaboplfbrettd7655fr4n2y reactflow: link:../../packages/reactflow + zustand: registry.npmjs.org/zustand/4.3.1_react@18.2.0 devDependencies: '@cypress/skip-test': registry.npmjs.org/@cypress/skip-test/2.6.1 '@types/dagre': registry.npmjs.org/@types/dagre/0.7.48