Merge pull request #5594 from xyflow/enhance/connection-snapping

Enhance/connection snapping
This commit is contained in:
Moritz Klack
2025-10-30 21:19:38 +01:00
committed by GitHub
7 changed files with 21 additions and 20 deletions

View File

@@ -0,0 +1,7 @@
---
'@xyflow/react': minor
'@xyflow/svelte': minor
'@xyflow/system': patch
---
Pass current pointer position to connection

View File

@@ -1,6 +1,7 @@
import { ConnectionLineComponentProps } from '@xyflow/react'; import { ConnectionLineComponentProps } from '@xyflow/react';
function ConnectionLine({ fromX, fromY, toX, toY }: ConnectionLineComponentProps) { function ConnectionLine({ fromX, fromY, toX, toY, pointer }: ConnectionLineComponentProps) {
console.log('pointer', pointer);
return ( return (
<> <>
<path <path

View File

@@ -19,6 +19,8 @@
} }
return null; return null;
}); });
$inspect(connection.current.pointer);
</script> </script>
{#if connection.current.inProgress} {#if connection.current.inProgress}

View File

@@ -69,7 +69,7 @@ const ConnectionLine = <NodeType extends Node = Node>({
CustomComponent, CustomComponent,
isValid, isValid,
}: ConnectionLineProps<NodeType>) => { }: ConnectionLineProps<NodeType>) => {
const { inProgress, from, fromNode, fromHandle, fromPosition, to, toNode, toHandle, toPosition } = const { inProgress, from, fromNode, fromHandle, fromPosition, to, toNode, toHandle, toPosition, pointer } =
useConnection<NodeType>(); useConnection<NodeType>();
if (!inProgress) { if (!inProgress) {
@@ -92,6 +92,7 @@ const ConnectionLine = <NodeType extends Node = Node>({
connectionStatus={getConnectionStatus(isValid)} connectionStatus={getConnectionStatus(isValid)}
toNode={toNode} toNode={toNode}
toHandle={toHandle} toHandle={toHandle}
pointer={pointer}
/> />
); );
} }

View File

@@ -22,6 +22,7 @@ import type {
OnError, OnError,
OnReconnect, OnReconnect,
FinalConnectionState, FinalConnectionState,
XYPosition,
} from '@xyflow/system'; } from '@xyflow/system';
import { EdgeTypes, InternalNode, Node } from '.'; import { EdgeTypes, InternalNode, Node } from '.';
@@ -279,6 +280,7 @@ export type ConnectionLineComponentProps<NodeType extends Node = Node> = {
connectionStatus: 'valid' | 'invalid' | null; connectionStatus: 'valid' | 'invalid' | null;
toNode: InternalNode<NodeType> | null; toNode: InternalNode<NodeType> | null;
toHandle: Handle | null; toHandle: Handle | null;
pointer: XYPosition;
}; };
export type ConnectionLineComponent<NodeType extends Node = Node> = ComponentType< export type ConnectionLineComponent<NodeType extends Node = Node> = ComponentType<

View File

@@ -292,6 +292,7 @@ export const initialConnection: NoConnection = {
toHandle: null, toHandle: null,
toPosition: null, toPosition: null,
toNode: null, toNode: null,
pointer: null,
}; };
export type NoConnection = { export type NoConnection = {
@@ -305,6 +306,7 @@ export type NoConnection = {
toHandle: null; toHandle: null;
toPosition: null; toPosition: null;
toNode: null; toNode: null;
pointer: null;
}; };
export type ConnectionInProgress<NodeType extends InternalNodeBase = InternalNodeBase> = { export type ConnectionInProgress<NodeType extends InternalNodeBase = InternalNodeBase> = {
/** Indicates whether a connection is currently in progress. */ /** Indicates whether a connection is currently in progress. */
@@ -330,6 +332,8 @@ export type ConnectionInProgress<NodeType extends InternalNodeBase = InternalNod
toPosition: Position; toPosition: Position;
/** Returns the end node or `null` if no connection is in progress. */ /** Returns the end node or `null` if no connection is in progress. */
toNode: NodeType | null; toNode: NodeType | null;
/** Returns the pointer position or `null` if no connection is in progress. */
pointer: XYPosition;
}; };
/** /**

View File

@@ -109,6 +109,7 @@ function onPointerDown(
toHandle: null, toHandle: null,
toPosition: oppositePosition[fromHandle.position], toPosition: oppositePosition[fromHandle.position],
toNode: null, toNode: null,
pointer: position,
}; };
function startConnection() { function startConnection() {
@@ -182,26 +183,9 @@ function onPointerDown(
toHandle: result.toHandle, toHandle: result.toHandle,
toPosition: isValid && result.toHandle ? result.toHandle.position : oppositePosition[fromHandle.position], toPosition: isValid && result.toHandle ? result.toHandle.position : oppositePosition[fromHandle.position],
toNode: result.toHandle ? nodeLookup.get(result.toHandle.nodeId)! : null, toNode: result.toHandle ? nodeLookup.get(result.toHandle.nodeId)! : null,
pointer: position,
}; };
/*
* we don't want to trigger an update when the connection
* is snapped to the same handle as before
*/
if (
isValid &&
closestHandle &&
previousConnection.toHandle &&
newConnection.toHandle &&
previousConnection.toHandle.type === newConnection.toHandle.type &&
previousConnection.toHandle.nodeId === newConnection.toHandle.nodeId &&
previousConnection.toHandle.id === newConnection.toHandle.id &&
previousConnection.to.x === newConnection.to.x &&
previousConnection.to.y === newConnection.to.y
) {
return;
}
updateConnection(newConnection); updateConnection(newConnection);
previousConnection = newConnection; previousConnection = newConnection;
} }