From 295884fea9fa4cb2ea6e03d8e6d2b7d1206c15ae Mon Sep 17 00:00:00 2001 From: moklick Date: Tue, 12 Aug 2025 13:16:56 +0200 Subject: [PATCH] chore(handle): cleanup --- .changeset/funny-doors-travel.md | 1 + .../react/src/examples/DetachedHandle/index.tsx | 13 +++++++++++-- .../components/EdgeWrapper/EdgeUpdateAnchors.tsx | 11 ++++++----- packages/react/src/components/Handle/index.tsx | 5 ++--- .../EdgeReconnectAnchor/EdgeReconnectAnchor.svelte | 3 ++- .../svelte/src/lib/components/Handle/Handle.svelte | 5 +++-- packages/system/src/xyhandle/XYHandle.ts | 12 ++++++------ packages/system/src/xyhandle/types.ts | 3 ++- 8 files changed, 33 insertions(+), 20 deletions(-) diff --git a/.changeset/funny-doors-travel.md b/.changeset/funny-doors-travel.md index d4af2f2d..f7ad710c 100644 --- a/.changeset/funny-doors-travel.md +++ b/.changeset/funny-doors-travel.md @@ -1,6 +1,7 @@ --- '@xyflow/react': patch '@xyflow/system': patch +'@xyflow/svelte': patch --- Fix clicking on detached handle elements not initiating drawing of connections diff --git a/examples/react/src/examples/DetachedHandle/index.tsx b/examples/react/src/examples/DetachedHandle/index.tsx index 9ca20ddc..d3ca4515 100644 --- a/examples/react/src/examples/DetachedHandle/index.tsx +++ b/examples/react/src/examples/DetachedHandle/index.tsx @@ -1,4 +1,13 @@ -import { ReactFlow, Node, ReactFlowProvider, Background, BackgroundVariant, NodeProps, Handle, Position } from '@xyflow/react'; +import { + ReactFlow, + Node, + ReactFlowProvider, + Background, + BackgroundVariant, + NodeProps, + Handle, + Position, +} from '@xyflow/react'; import './style.css'; @@ -38,7 +47,7 @@ const nodeTypes = { const DetachedHandle = () => { return ( - + ); diff --git a/packages/react/src/components/EdgeWrapper/EdgeUpdateAnchors.tsx b/packages/react/src/components/EdgeWrapper/EdgeUpdateAnchors.tsx index 73a900f9..36a983aa 100644 --- a/packages/react/src/components/EdgeWrapper/EdgeUpdateAnchors.tsx +++ b/packages/react/src/components/EdgeWrapper/EdgeUpdateAnchors.tsx @@ -1,11 +1,11 @@ // Reconnectable edges have a anchors around their handles to reconnect the edge. import { XYHandle, + type EdgePosition, + type FinalConnectionState, + type HandleType, + type OnConnectStart, type Connection, - EdgePosition, - FinalConnectionState, - HandleType, - OnConnectStart, } from '@xyflow/system'; import { EdgeAnchor } from '../Edges/EdgeAnchor'; @@ -79,7 +79,7 @@ export function EdgeUpdateAnchors({ onConnectStart?.(_event, params); }; - XYHandle.onPointerDown(event.nativeEvent, event.currentTarget, { + XYHandle.onPointerDown(event.nativeEvent, { autoPanOnConnect, connectionMode, connectionRadius, @@ -102,6 +102,7 @@ export function EdgeUpdateAnchors({ getTransform: () => store.getState().transform, getFromHandle: () => store.getState().connection.fromHandle, dragThreshold: store.getState().connectionDragThreshold, + handleDomNode: event.currentTarget, }); }; diff --git a/packages/react/src/components/Handle/index.tsx b/packages/react/src/components/Handle/index.tsx index 601c0a31..dec2d242 100644 --- a/packages/react/src/components/Handle/index.tsx +++ b/packages/react/src/components/Handle/index.tsx @@ -114,13 +114,11 @@ function HandleComponent( onConnectAction?.(edgeParams); onConnect?.(edgeParams); }; - const onPointerDown = (event: ReactMouseEvent | ReactTouchEvent) => { if (!nodeId) { return; } - const handleElement = event.currentTarget const isMouseTriggered = isMouseEvent(event.nativeEvent); if ( @@ -129,7 +127,8 @@ function HandleComponent( ) { const currentStore = store.getState(); - XYHandle.onPointerDown(event.nativeEvent, handleElement, { + XYHandle.onPointerDown(event.nativeEvent, { + handleDomNode: event.currentTarget, autoPanOnConnect: currentStore.autoPanOnConnect, connectionMode: currentStore.connectionMode, connectionRadius: currentStore.connectionRadius, diff --git a/packages/svelte/src/lib/components/EdgeReconnectAnchor/EdgeReconnectAnchor.svelte b/packages/svelte/src/lib/components/EdgeReconnectAnchor/EdgeReconnectAnchor.svelte index c4b95fa5..d18bc2e8 100644 --- a/packages/svelte/src/lib/components/EdgeReconnectAnchor/EdgeReconnectAnchor.svelte +++ b/packages/svelte/src/lib/components/EdgeReconnectAnchor/EdgeReconnectAnchor.svelte @@ -102,7 +102,8 @@ updateConnection, getTransform: () => [store.viewport.x, store.viewport.y, store.viewport.zoom], getFromHandle: () => store.connection.fromHandle, - dragThreshold: dragThreshold ?? store.connectionDragThreshold + dragThreshold: dragThreshold ?? store.connectionDragThreshold, + handleDomNode: event.currentTarget as HTMLElement }); }; diff --git a/packages/svelte/src/lib/components/Handle/Handle.svelte b/packages/svelte/src/lib/components/Handle/Handle.svelte index d636f4cf..48946d41 100644 --- a/packages/svelte/src/lib/components/Handle/Handle.svelte +++ b/packages/svelte/src/lib/components/Handle/Handle.svelte @@ -111,7 +111,7 @@ function onpointerdown(event: MouseEvent | TouchEvent) { const isMouseTriggered = isMouseEvent(event); - if ((isMouseTriggered && event.button === 0) || !isMouseTriggered) { + if (event.currentTarget && ((isMouseTriggered && event.button === 0) || !isMouseTriggered)) { XYHandle.onPointerDown(event, { handleId, nodeId, @@ -140,7 +140,8 @@ }, getTransform: () => [store.viewport.x, store.viewport.y, store.viewport.zoom], getFromHandle: () => store.connection.fromHandle, - dragThreshold: store.connectionDragThreshold + dragThreshold: store.connectionDragThreshold, + handleDomNode: event.currentTarget as HTMLElement }); } } diff --git a/packages/system/src/xyhandle/XYHandle.ts b/packages/system/src/xyhandle/XYHandle.ts index dc470daf..aa71d49d 100644 --- a/packages/system/src/xyhandle/XYHandle.ts +++ b/packages/system/src/xyhandle/XYHandle.ts @@ -22,7 +22,6 @@ const alwaysValid = () => true; function onPointerDown( event: MouseEvent | TouchEvent, - handleElement: Element, { connectionMode, connectionRadius, @@ -47,6 +46,7 @@ function onPointerDown( getFromHandle, autoPanSpeed, dragThreshold = 1, + handleDomNode, }: OnPointerDownParams ) { // when xyflow is used inside a shadow root we can't use document @@ -55,7 +55,7 @@ function onPointerDown( let closestHandle: Handle | null; const { x, y } = getEventPosition(event); - const handleType = getHandleType(edgeUpdaterType, handleElement); + const handleType = getHandleType(edgeUpdaterType, handleDomNode); const containerBounds = domNode?.getBoundingClientRect(); let connectionStarted = false; @@ -72,7 +72,7 @@ function onPointerDown( let autoPanStarted = false; let connection: Connection | null = null; let isValid: boolean | null = false; - let handleDomNode: Element | null = null; + let resultHandleDomNode: Element | null = null; // when the user is moving the mouse close to the edge of the canvas while connecting we move the canvas function autoPan(): void { @@ -167,7 +167,7 @@ function onPointerDown( nodeLookup, }); - handleDomNode = result.handleDomNode; + resultHandleDomNode = result.handleDomNode; connection = result.connection; isValid = isConnectionValid(!!closestHandle, result.isValid); @@ -208,7 +208,7 @@ function onPointerDown( function onPointerUp(event: MouseEvent | TouchEvent) { if (connectionStarted) { - if ((closestHandle || handleDomNode) && connection && isValid) { + if ((closestHandle || resultHandleDomNode) && connection && isValid) { onConnect?.(connection); } @@ -235,7 +235,7 @@ function onPointerDown( autoPanStarted = false; isValid = false; connection = null; - handleDomNode = null; + resultHandleDomNode = null; doc.removeEventListener('mousemove', onPointerMove as EventListener); doc.removeEventListener('mouseup', onPointerUp as EventListener); diff --git a/packages/system/src/xyhandle/types.ts b/packages/system/src/xyhandle/types.ts index a71eb962..11d553ff 100644 --- a/packages/system/src/xyhandle/types.ts +++ b/packages/system/src/xyhandle/types.ts @@ -38,6 +38,7 @@ export type OnPointerDownParams = { getFromHandle: () => Handle | null; autoPanSpeed?: number; dragThreshold?: number; + handleDomNode: Element; }; export type IsValidParams = { @@ -54,7 +55,7 @@ export type IsValidParams = { }; export type XYHandleInstance = { - onPointerDown: (event: MouseEvent | TouchEvent, handleElement: Element, params: OnPointerDownParams) => void; + onPointerDown: (event: MouseEvent | TouchEvent, params: OnPointerDownParams) => void; isValid: (event: MouseEvent | TouchEvent, params: IsValidParams) => Result; };