From 941898b97d824273ac1cfd6cf9f4c7ee1c94588c Mon Sep 17 00:00:00 2001 From: peterkogo Date: Thu, 27 Jun 2024 13:44:30 +0200 Subject: [PATCH] fixed connectionLine not updating correctly on auto pan --- .../src/components/ConnectionLine/index.tsx | 8 +++----- packages/react/src/hooks/useConnection.ts | 11 ++++++----- packages/svelte/src/lib/store/index.ts | 18 ++++++++++++++---- packages/svelte/src/lib/store/initial-store.ts | 2 +- packages/system/src/xyhandle/XYHandle.ts | 15 +++++++++++---- 5 files changed, 35 insertions(+), 19 deletions(-) diff --git a/packages/react/src/components/ConnectionLine/index.tsx b/packages/react/src/components/ConnectionLine/index.tsx index ee816622..a5f7e1e2 100644 --- a/packages/react/src/components/ConnectionLine/index.tsx +++ b/packages/react/src/components/ConnectionLine/index.tsx @@ -12,6 +12,7 @@ import { import { useStore } from '../../hooks/useStore'; import { getSimpleBezierPath } from '../Edges/SimpleBezierEdge'; import type { ConnectionLineComponent, ReactFlowState } from '../../types'; +import { useConnection } from '../../hooks/useConnection'; type ConnectionLineWrapperProps = { type: ConnectionLineType; @@ -58,10 +59,7 @@ type ConnectionLineProps = { }; const ConnectionLine = ({ style, type = ConnectionLineType.Bezier, CustomComponent, isValid }: ConnectionLineProps) => { - const { inProgress, from, fromNode, fromHandle, fromPosition, to, toNode, toHandle, toPosition } = useStore( - (s: ReactFlowState) => s.connection, - shallow - ); + const { inProgress, from, fromNode, fromHandle, fromPosition, to, toNode, toHandle, toPosition } = useConnection(); if (!inProgress) { return; @@ -121,4 +119,4 @@ const ConnectionLine = ({ style, type = ConnectionLineType.Bezier, CustomCompone return ; }; -ConnectionLine.displayName = 'ConnectionLine'; \ No newline at end of file +ConnectionLine.displayName = 'ConnectionLine'; diff --git a/packages/react/src/hooks/useConnection.ts b/packages/react/src/hooks/useConnection.ts index 0756344e..8a4b377b 100644 --- a/packages/react/src/hooks/useConnection.ts +++ b/packages/react/src/hooks/useConnection.ts @@ -2,12 +2,13 @@ import { shallow } from 'zustand/shallow'; import { useStore } from './useStore'; import type { ReactFlowStore } from '../types/store'; -import { ConnectionState } from '@xyflow/system'; - -const selector = (s: ReactFlowStore) => ({ - ...s.connection, -}); +import { ConnectionState, pointToRendererPoint } from '@xyflow/system'; +const selector = (s: ReactFlowStore): ConnectionState => { + return s.connection.inProgress + ? { ...s.connection, to: pointToRendererPoint(s.connection.to, s.transform) } + : { ...s.connection }; +}; /** * Hook for accessing the connection state. * diff --git a/packages/svelte/src/lib/store/index.ts b/packages/svelte/src/lib/store/index.ts index 1f040cb0..f408c756 100644 --- a/packages/svelte/src/lib/store/index.ts +++ b/packages/svelte/src/lib/store/index.ts @@ -1,5 +1,5 @@ import { getContext, setContext } from 'svelte'; -import { derived, get } from 'svelte/store'; +import { derived, get, writable } from 'svelte/store'; import { createMarkerIds, fitView as fitViewSystem, @@ -16,7 +16,8 @@ import { type XYPosition, type CoordinateExtent, type UpdateConnection, - type ConnectionState + type ConnectionState, + pointToRendererPoint } from '@xyflow/system'; import type { EdgeTypes, NodeTypes, Node, Edge, FitViewOptions } from '$lib/types'; @@ -331,12 +332,13 @@ export function createStore({ }); } + const _connection = writable(initialConnection); const updateConnection: UpdateConnection = (newConnection: ConnectionState) => { - store.connection.set({ ...newConnection }); + _connection.set({ ...newConnection }); }; function cancelConnection() { - store.connection.set(initialConnection); + _connection.set(initialConnection); } function reset() { @@ -357,6 +359,14 @@ export function createStore({ // derived state visibleEdges: getVisibleEdges(store), visibleNodes: getVisibleNodes(store), + connection: derived([_connection, store.viewport], ([connection, viewport]) => { + return connection.inProgress + ? { + ...connection, + to: pointToRendererPoint(connection.to, [viewport.x, viewport.y, viewport.zoom]) + } + : { ...connection }; + }), markers: derived( [store.edges, store.defaultMarkerColor, store.flowId], ([edges, defaultColor, id]) => createMarkerIds(edges, { defaultColor, id }) diff --git a/packages/svelte/src/lib/store/initial-store.ts b/packages/svelte/src/lib/store/initial-store.ts index 8b6bee25..ce17627f 100644 --- a/packages/svelte/src/lib/store/initial-store.ts +++ b/packages/svelte/src/lib/store/initial-store.ts @@ -143,7 +143,7 @@ export const getInitialStore = ({ viewport: writable(viewport), connectionMode: writable(ConnectionMode.Strict), domNode: writable(null), - connection: writable(initialConnection), + connection: readable(initialConnection), connectionLineType: writable(ConnectionLineType.Bezier), connectionRadius: writable(20), isValidConnection: writable(() => true), diff --git a/packages/system/src/xyhandle/XYHandle.ts b/packages/system/src/xyhandle/XYHandle.ts index 7244d8d3..4ecf0cce 100644 --- a/packages/system/src/xyhandle/XYHandle.ts +++ b/packages/system/src/xyhandle/XYHandle.ts @@ -1,4 +1,11 @@ -import { pointToRendererPoint, getHostForElement, calcAutoPan, getEventPosition, getHandlePosition } from '../utils'; +import { + pointToRendererPoint, + getHostForElement, + calcAutoPan, + getEventPosition, + getHandlePosition, + rendererPointToPoint, +} from '../utils'; import { ConnectionMode, Position, @@ -98,7 +105,7 @@ function onPointerDown( fromPosition: fromHandle.position, fromNode: fromNodeInternal.internals.userNode, - to: pointToRendererPoint(position, getTransform()), + to: position, toHandle: null, toPosition: oppositePosition[fromHandle.position], toNode: null, @@ -151,8 +158,8 @@ function onPointerDown( isValid, to: closestHandle && isValid - ? { x: closestHandle.x, y: closestHandle.y } - : pointToRendererPoint(position, transform), + ? rendererPointToPoint({ x: closestHandle.x, y: closestHandle.y }, transform) + : position, toHandle: result.toHandle, toPosition: isValid && result.toHandle ? result.toHandle.position : oppositePosition[fromHandle.position], toNode: result.toHandle ? nodeLookup.get(result.toHandle.nodeId)!.internals.userNode : null,