Merge pull request #4395 from xyflow/enhance-connection

Enhance connection
This commit is contained in:
Moritz Klack
2024-06-26 17:00:00 +02:00
committed by GitHub
15 changed files with 129 additions and 124 deletions
@@ -7,7 +7,6 @@ import {
ConnectionMode, ConnectionMode,
getBezierPath, getBezierPath,
getSmoothStepPath, getSmoothStepPath,
type ConnectionStatus,
type HandleType, type HandleType,
} from '@xyflow/system'; } from '@xyflow/system';
@@ -15,13 +14,21 @@ import { useStore } from '../../hooks/useStore';
import { getSimpleBezierPath } from '../Edges/SimpleBezierEdge'; import { getSimpleBezierPath } from '../Edges/SimpleBezierEdge';
import type { ConnectionLineComponent, ReactFlowState, ReactFlowStore } from '../../types'; import type { ConnectionLineComponent, ReactFlowState, ReactFlowStore } from '../../types';
function getConnectionStatus(isValid: boolean | null) {
if (isValid === null) {
return null;
}
return isValid ? 'valid' : 'invalid';
}
type ConnectionLineProps = { type ConnectionLineProps = {
nodeId: string; nodeId: string;
handleType: HandleType; handleType: HandleType;
type: ConnectionLineType; type: ConnectionLineType;
style?: CSSProperties; style?: CSSProperties;
CustomComponent?: ConnectionLineComponent; CustomComponent?: ConnectionLineComponent;
connectionStatus: ConnectionStatus | null; isValid: boolean | null;
}; };
const oppositePosition = { const oppositePosition = {
@@ -37,18 +44,17 @@ const ConnectionLine = ({
style, style,
type = ConnectionLineType.Bezier, type = ConnectionLineType.Bezier,
CustomComponent, CustomComponent,
connectionStatus, isValid,
}: ConnectionLineProps) => { }: ConnectionLineProps) => {
const { fromNode, handleId, toX, toY, connectionMode, endPosition, isValid } = useStore( const { fromNode, startHandle, endHandle, toX, toY, connectionMode } = useStore(
useCallback( useCallback(
(s: ReactFlowStore) => ({ (s: ReactFlowStore) => ({
fromNode: s.nodeLookup.get(nodeId), fromNode: s.nodeLookup.get(nodeId),
handleId: s.connectionStartHandle?.handleId, startHandle: s.connection.fromHandle,
toX: (s.connectionPosition.x - s.transform[0]) / s.transform[2], endHandle: s.connection.toHandle,
toY: (s.connectionPosition.y - s.transform[1]) / s.transform[2], toX: (s.connection.position.x - s.transform[0]) / s.transform[2],
toY: (s.connection.position.y - s.transform[1]) / s.transform[2],
connectionMode: s.connectionMode, connectionMode: s.connectionMode,
endPosition: s.connectionEndHandle?.position,
isValid: s.connectionStatus === 'valid',
}), }),
[nodeId] [nodeId]
), ),
@@ -66,13 +72,15 @@ const ConnectionLine = ({
return null; return null;
} }
const handleId = startHandle?.handleId;
const fromHandle = handleId ? handleBounds.find((d) => d.id === handleId) : handleBounds[0]; const fromHandle = handleId ? handleBounds.find((d) => d.id === handleId) : handleBounds[0];
const fromHandleX = fromHandle ? fromHandle.x + fromHandle.width / 2 : (fromNode.measured.width ?? 0) / 2; const fromHandleX = fromHandle ? fromHandle.x + fromHandle.width / 2 : (fromNode.measured.width ?? 0) / 2;
const fromHandleY = fromHandle ? fromHandle.y + fromHandle.height / 2 : fromNode.measured.height ?? 0; const fromHandleY = fromHandle ? fromHandle.y + fromHandle.height / 2 : fromNode.measured.height ?? 0;
const fromX = fromNode.internals.positionAbsolute.x + fromHandleX; const fromX = fromNode.internals.positionAbsolute.x + fromHandleX;
const fromY = fromNode.internals.positionAbsolute.y + fromHandleY; const fromY = fromNode.internals.positionAbsolute.y + fromHandleY;
const fromPosition = fromHandle?.position; const fromPosition = fromHandle?.position;
const toPosition = isValid && endPosition ? endPosition : fromPosition ? oppositePosition[fromPosition] : null; const toPosition =
isValid && endHandle?.position ? endHandle.position : fromPosition ? oppositePosition[fromPosition] : null;
if (!fromPosition || !toPosition) { if (!fromPosition || !toPosition) {
return null; return null;
@@ -83,7 +91,7 @@ const ConnectionLine = ({
<CustomComponent <CustomComponent
connectionLineType={type} connectionLineType={type}
connectionLineStyle={style} connectionLineStyle={style}
fromNode={fromNode} fromNode={fromNode.internals.userNode}
fromHandle={fromHandle} fromHandle={fromHandle}
fromX={fromX} fromX={fromX}
fromY={fromY} fromY={fromY}
@@ -91,7 +99,7 @@ const ConnectionLine = ({
toY={toY} toY={toY}
fromPosition={fromPosition} fromPosition={fromPosition}
toPosition={toPosition} toPosition={toPosition}
connectionStatus={connectionStatus} connectionStatus={getConnectionStatus(isValid)}
/> />
); );
} }
@@ -136,19 +144,19 @@ type ConnectionLineWrapperProps = {
}; };
const selector = (s: ReactFlowState) => ({ const selector = (s: ReactFlowState) => ({
nodeId: s.connectionStartHandle?.nodeId, nodeId: s.connection.fromHandle?.nodeId,
handleType: s.connectionStartHandle?.type, handleType: s.connection.fromHandle?.type,
nodesConnectable: s.nodesConnectable, nodesConnectable: s.nodesConnectable,
connectionStatus: s.connectionStatus, isValid: s.connection.isValid,
width: s.width, width: s.width,
height: s.height, height: s.height,
}); });
export function ConnectionLineWrapper({ containerStyle, style, type, component }: ConnectionLineWrapperProps) { export function ConnectionLineWrapper({ containerStyle, style, type, component }: ConnectionLineWrapperProps) {
const { nodeId, handleType, nodesConnectable, width, height, connectionStatus } = useStore(selector, shallow); const { nodeId, handleType, nodesConnectable, width, height, isValid } = useStore(selector, shallow);
const isValid = !!(nodeId && handleType && width && nodesConnectable); const renderConnectionLine = !!(nodeId && handleType && width && nodesConnectable);
if (!isValid) { if (!renderConnectionLine) {
return null; return null;
} }
@@ -159,14 +167,14 @@ export function ConnectionLineWrapper({ containerStyle, style, type, component }
height={height} height={height}
className="react-flow__connectionline react-flow__container" className="react-flow__connectionline react-flow__container"
> >
<g className={cc(['react-flow__connection', connectionStatus])}> <g className={cc(['react-flow__connection', getConnectionStatus(isValid)])}>
<ConnectionLine <ConnectionLine
nodeId={nodeId} nodeId={nodeId}
handleType={handleType} handleType={handleType}
style={style} style={style}
type={type} type={type}
CustomComponent={component} CustomComponent={component}
connectionStatus={connectionStatus} isValid={isValid}
/> />
</g> </g>
</svg> </svg>
@@ -96,7 +96,7 @@ export function EdgeUpdateAnchors<EdgeType extends Edge = Edge>({
onReconnectEnd: _onReconnectEnd, onReconnectEnd: _onReconnectEnd,
updateConnection, updateConnection,
getTransform: () => store.getState().transform, getTransform: () => store.getState().transform,
getConnectionStartHandle: () => store.getState().connectionStartHandle, getFromHandle: () => store.getState().connection.fromHandle,
}); });
}; };
+10 -15
View File
@@ -39,28 +39,23 @@ const selector = (s: ReactFlowState) => ({
const connectingSelector = const connectingSelector =
(nodeId: string | null, handleId: string | null, type: HandleType) => (state: ReactFlowState) => { (nodeId: string | null, handleId: string | null, type: HandleType) => (state: ReactFlowState) => {
const { const { connectionClickStartHandle: clickHandle, connectionMode, connection } = state;
connectionStartHandle: startHandle,
connectionEndHandle: endHandle,
connectionClickStartHandle: clickHandle,
connectionMode,
connectionStatus,
} = state;
const connectingTo = endHandle?.nodeId === nodeId && endHandle?.handleId === handleId && endHandle?.type === type; const { fromHandle, toHandle, isValid } = connection;
const connectingTo = toHandle?.nodeId === nodeId && toHandle?.handleId === handleId && toHandle?.type === type;
return { return {
connectingFrom: connectingFrom: fromHandle?.nodeId === nodeId && fromHandle?.handleId === handleId && fromHandle?.type === type,
startHandle?.nodeId === nodeId && startHandle?.handleId === handleId && startHandle?.type === type,
connectingTo, connectingTo,
clickConnecting: clickConnecting:
clickHandle?.nodeId === nodeId && clickHandle?.handleId === handleId && clickHandle?.type === type, clickHandle?.nodeId === nodeId && clickHandle?.handleId === handleId && clickHandle?.type === type,
isPossibleEndHandle: isPossibleEndHandle:
connectionMode === ConnectionMode.Strict connectionMode === ConnectionMode.Strict
? startHandle?.type !== type ? fromHandle?.type !== type
: nodeId !== startHandle?.nodeId || handleId !== startHandle?.handleId, : nodeId !== fromHandle?.nodeId || handleId !== fromHandle?.handleId,
connectionInProcess: !!startHandle, connectionInProcess: !!fromHandle,
valid: connectingTo && connectionStatus === 'valid', valid: connectingTo && isValid,
}; };
}; };
@@ -144,7 +139,7 @@ function HandleComponent(
onConnect: onConnectExtended, onConnect: onConnectExtended,
isValidConnection: isValidConnection || currentStore.isValidConnection, isValidConnection: isValidConnection || currentStore.isValidConnection,
getTransform: () => store.getState().transform, getTransform: () => store.getState().transform,
getConnectionStartHandle: () => store.getState().connectionStartHandle, getFromHandle: () => store.getState().connection.fromHandle,
}); });
} }
+5 -19
View File
@@ -2,33 +2,19 @@ import { shallow } from 'zustand/shallow';
import { useStore } from './useStore'; import { useStore } from './useStore';
import type { ReactFlowStore } from '../types/store'; import type { ReactFlowStore } from '../types/store';
import { ConnectionState } from '@xyflow/system';
const selector = (s: ReactFlowStore) => ({ const selector = (s: ReactFlowStore) => ({
startHandle: s.connectionStartHandle, ...s.connection,
endHandle: s.connectionEndHandle, inProgress: s.connection.fromHandle !== null,
status: s.connectionStatus,
position: s.connectionStartHandle ? s.connectionPosition : null,
}); });
type UseConnectionResult = {
/** The start handle where the user interaction started or null */
startHandle: ReactFlowStore['connectionStartHandle'];
/** The target handle that's inside the connection radius or null */
endHandle: ReactFlowStore['connectionEndHandle'];
/** The current connection status 'valid', 'invalid' or null*/
status: ReactFlowStore['connectionStatus'];
/** The current connection position or null */
position: ReactFlowStore['connectionPosition'] | null;
};
/** /**
* Hook for accessing the ongoing connection. * Hook for accessing the ongoing connection.
* *
* @public * @public
* @returns ongoing connection * @returns ongoing connection
*/ */
export function useConnection(): UseConnectionResult { export function useConnection(): ConnectionState & { inProgress: boolean } {
const ongoingConnection = useStore(selector, shallow); return useStore(selector, shallow);
return ongoingConnection;
} }
-1
View File
@@ -49,7 +49,6 @@ export {
type OnMoveStart, type OnMoveStart,
type OnMoveEnd, type OnMoveEnd,
type Connection, type Connection,
type ConnectionStatus,
ConnectionMode, ConnectionMode,
type OnConnectStartParams, type OnConnectStartParams,
type OnConnectStart, type OnConnectStart,
+15 -8
View File
@@ -307,18 +307,25 @@ const createStore = ({
options options
); );
}, },
cancelConnection: () => cancelConnection: () => {
const { connection } = get();
set({ set({
connectionStatus: null, connection: {
connectionStartHandle: null, position: connection.position,
connectionEndHandle: null, fromHandle: null,
}), toHandle: null,
isValid: null,
},
});
},
updateConnection: (params) => { updateConnection: (params) => {
const { connectionPosition } = get(); const { connection } = get();
const currentConnection = { const currentConnection = {
...params, connection: {
connectionPosition: params.connectionPosition ?? connectionPosition, ...params,
position: params.position ?? connection.position,
},
}; };
set(currentConnection); set(currentConnection);
+6 -4
View File
@@ -76,8 +76,6 @@ const getInitialState = ({
nodesSelectionActive: false, nodesSelectionActive: false,
userSelectionActive: false, userSelectionActive: false,
userSelectionRect: null, userSelectionRect: null,
connectionPosition: { x: 0, y: 0 },
connectionStatus: null,
connectionMode: ConnectionMode.Strict, connectionMode: ConnectionMode.Strict,
domNode: null, domNode: null,
paneDragging: false, paneDragging: false,
@@ -103,8 +101,12 @@ const getInitialState = ({
multiSelectionActive: false, multiSelectionActive: false,
connectionStartHandle: null, connection: {
connectionEndHandle: null, fromHandle: null,
toHandle: null,
position: { x: 0, y: 0 },
isValid: null,
},
connectionClickStartHandle: null, connectionClickStartHandle: null,
connectOnClick: true, connectOnClick: true,
+1 -2
View File
@@ -11,7 +11,6 @@ import type {
Connection, Connection,
ConnectionLineType, ConnectionLineType,
HandleElement, HandleElement,
ConnectionStatus,
EdgePosition, EdgePosition,
StepPathOptions, StepPathOptions,
OnError, OnError,
@@ -202,7 +201,7 @@ export type ConnectionLineComponentProps = {
toY: number; toY: number;
fromPosition: Position; fromPosition: Position;
toPosition: Position; toPosition: Position;
connectionStatus: ConnectionStatus | null; connectionStatus: 'valid' | 'invalid' | null;
}; };
export type ConnectionLineComponent = ComponentType<ConnectionLineComponentProps>; export type ConnectionLineComponent = ComponentType<ConnectionLineComponentProps>;
+5 -10
View File
@@ -1,6 +1,6 @@
import { import {
ConnectionMode, ConnectionMode,
type ConnectionStatus, type ConnectionState,
type CoordinateExtent, type CoordinateExtent,
type InternalNodeUpdate, type InternalNodeUpdate,
type UpdateNodePositions, type UpdateNodePositions,
@@ -12,7 +12,6 @@ import {
type SnapGrid, type SnapGrid,
type ConnectingHandle, type ConnectingHandle,
type Transform, type Transform,
type XYPosition,
type PanZoomInstance, type PanZoomInstance,
type PanBy, type PanBy,
type OnConnectStart, type OnConnectStart,
@@ -25,8 +24,8 @@ import {
type EdgeLookup, type EdgeLookup,
type ConnectionLookup, type ConnectionLookup,
type NodeLookup, type NodeLookup,
NodeChange, type NodeChange,
EdgeChange, type EdgeChange,
} from '@xyflow/system'; } from '@xyflow/system';
import type { import type {
@@ -78,9 +77,9 @@ export type ReactFlowStore<NodeType extends Node = Node, EdgeType extends Edge =
userSelectionActive: boolean; userSelectionActive: boolean;
userSelectionRect: SelectionRect | null; userSelectionRect: SelectionRect | null;
connectionPosition: XYPosition; connection: ConnectionState;
connectionStatus: ConnectionStatus | null;
connectionMode: ConnectionMode; connectionMode: ConnectionMode;
connectionClickStartHandle: ConnectingHandle | null;
snapToGrid: boolean; snapToGrid: boolean;
snapGrid: SnapGrid; snapGrid: SnapGrid;
@@ -97,10 +96,6 @@ export type ReactFlowStore<NodeType extends Node = Node, EdgeType extends Edge =
multiSelectionActive: boolean; multiSelectionActive: boolean;
connectionStartHandle: ConnectingHandle | null;
connectionEndHandle: ConnectingHandle | null;
connectionClickStartHandle: ConnectingHandle | null;
onNodeDragStart?: OnNodeDrag<NodeType>; onNodeDragStart?: OnNodeDrag<NodeType>;
onNodeDrag?: OnNodeDrag<NodeType>; onNodeDrag?: OnNodeDrag<NodeType>;
onNodeDragStop?: OnNodeDrag<NodeType>; onNodeDragStop?: OnNodeDrag<NodeType>;
@@ -103,7 +103,7 @@
$onConnectEndAction?.(event); $onConnectEndAction?.(event);
}, },
getTransform: () => [$viewport.x, $viewport.y, $viewport.zoom], getTransform: () => [$viewport.x, $viewport.y, $viewport.zoom],
getConnectionStartHandle: () => $connection.startHandle getFromHandle: () => $connection.startHandle
}); });
} }
} }
-1
View File
@@ -70,7 +70,6 @@ export {
type OnMoveStart, type OnMoveStart,
type OnMoveEnd, type OnMoveEnd,
type Connection, type Connection,
type ConnectionStatus,
ConnectionMode, ConnectionMode,
type OnConnectStartParams, type OnConnectStartParams,
type OnConnectStart, type OnConnectStart,
+10 -4
View File
@@ -14,7 +14,8 @@ import {
type XYPosition, type XYPosition,
type CoordinateExtent, type CoordinateExtent,
type UpdateConnection, type UpdateConnection,
errorMessages errorMessages,
type ConnectionState
} from '@xyflow/system'; } from '@xyflow/system';
import type { EdgeTypes, NodeTypes, Node, Edge, FitViewOptions, ConnectionData } from '$lib/types'; import type { EdgeTypes, NodeTypes, Node, Edge, FitViewOptions, ConnectionData } from '$lib/types';
@@ -340,12 +341,17 @@ export function createStore({
// by creating an internal, unexposed store and using a derived store // by creating an internal, unexposed store and using a derived store
// we prevent using slow get() calls // we prevent using slow get() calls
const currentConnection = writable<ConnectionData>(initConnectionUpdateData); const currentConnection = writable<ConnectionData>(initConnectionUpdateData);
const updateConnection: UpdateConnection = (newConnection: ConnectionData) => { const updateConnection: UpdateConnection = (newConnection: ConnectionState) => {
currentConnection.set(newConnection); currentConnection.set({
connectionStartHandle: newConnection.fromHandle,
connectionEndHandle: newConnection.toHandle,
connectionPosition: newConnection.position,
connectionStatus: newConnection.isValid ? 'valid' : 'invalid'
});
}; };
function cancelConnection() { function cancelConnection() {
updateConnection(initConnectionUpdateData); currentConnection.set(initConnectionUpdateData);
} }
function reset() { function reset() {
+17 -8
View File
@@ -37,8 +37,6 @@ export type HandleConnection = Connection & {
edgeId: string; edgeId: string;
}; };
export type ConnectionStatus = 'valid' | 'invalid';
export enum ConnectionMode { export enum ConnectionMode {
Strict = 'strict', Strict = 'strict',
Loose = 'loose', Loose = 'loose',
@@ -135,12 +133,23 @@ export type OnError = (id: string, message: string) => void;
export type UpdateNodePositions = (dragItems: Map<string, NodeDragItem | InternalNodeBase>, dragging?: boolean) => void; export type UpdateNodePositions = (dragItems: Map<string, NodeDragItem | InternalNodeBase>, dragging?: boolean) => void;
export type PanBy = (delta: XYPosition) => boolean; export type PanBy = (delta: XYPosition) => boolean;
export type UpdateConnection = (params: { export type NoConnectionInProgress = {
connectionPosition: XYPosition | null; position: XYPosition;
connectionStatus: ConnectionStatus | null; isValid: null;
connectionStartHandle: ConnectingHandle | null; fromHandle: null;
connectionEndHandle: ConnectingHandle | null; toHandle: null;
}) => void; };
export type ConnectionInProgress = {
position: XYPosition;
isValid: boolean | null;
fromHandle: ConnectingHandle;
toHandle: ConnectingHandle | null;
};
export type ConnectionState = ConnectionInProgress | NoConnectionInProgress;
export type UpdateConnection = (params: ConnectionState) => void;
export type ColorModeClass = 'light' | 'dark'; export type ColorModeClass = 'light' | 'dark';
export type ColorMode = ColorModeClass | 'system'; export type ColorMode = ColorModeClass | 'system';
+25 -24
View File
@@ -16,7 +16,7 @@ import {
Position, Position,
} from '../types'; } from '../types';
import { getClosestHandle, getConnectionStatus, getHandleLookup, getHandleType } from './utils'; import { getClosestHandle, isConnectionValid, getHandleLookup, getHandleType } from './utils';
export type OnPointerDownParams = { export type OnPointerDownParams = {
autoPanOnConnect: boolean; autoPanOnConnect: boolean;
@@ -39,7 +39,7 @@ export type OnPointerDownParams = {
isValidConnection?: IsValidConnection; isValidConnection?: IsValidConnection;
onReconnectEnd?: (evt: MouseEvent | TouchEvent) => void; onReconnectEnd?: (evt: MouseEvent | TouchEvent) => void;
getTransform: () => Transform; getTransform: () => Transform;
getConnectionStartHandle: () => ConnectingHandle | null; getFromHandle: () => ConnectingHandle | null;
}; };
export type IsValidParams = { export type IsValidParams = {
@@ -63,12 +63,12 @@ type Result = {
handleDomNode: Element | null; handleDomNode: Element | null;
isValid: boolean; isValid: boolean;
connection: Connection | null; connection: Connection | null;
endHandle: ConnectingHandle | null; toHandle: ConnectingHandle | null;
}; };
const alwaysValid = () => true; const alwaysValid = () => true;
let connectionStartHandle: ConnectingHandle | null = null; let fromHandle: ConnectingHandle | null = null;
function onPointerDown( function onPointerDown(
event: MouseEvent | TouchEvent, event: MouseEvent | TouchEvent,
@@ -93,7 +93,7 @@ function onPointerDown(
onReconnectEnd, onReconnectEnd,
updateConnection, updateConnection,
getTransform, getTransform,
getConnectionStartHandle, getFromHandle,
}: OnPointerDownParams }: OnPointerDownParams
) { ) {
// when xyflow is used inside a shadow root we can't use document // when xyflow is used inside a shadow root we can't use document
@@ -110,7 +110,7 @@ function onPointerDown(
return; return;
} }
let connectionPosition = getEventPosition(event, containerBounds); let position = getEventPosition(event, containerBounds);
let autoPanStarted = false; let autoPanStarted = false;
let connection: Connection | null = null; let connection: Connection | null = null;
let isValid = false; let isValid = false;
@@ -128,38 +128,39 @@ function onPointerDown(
if (!autoPanOnConnect || !containerBounds) { if (!autoPanOnConnect || !containerBounds) {
return; return;
} }
const [x, y] = calcAutoPan(connectionPosition, containerBounds); const [x, y] = calcAutoPan(position, containerBounds);
panBy({ x, y }); panBy({ x, y });
autoPanId = requestAnimationFrame(autoPan); autoPanId = requestAnimationFrame(autoPan);
} }
// Stays the same for all consecutive pointermove events // Stays the same for all consecutive pointermove events
connectionStartHandle = { fromHandle = {
nodeId, nodeId,
handleId, handleId,
type: handleType, type: handleType,
position: (clickedHandle?.getAttribute('data-handlepos') as Position) || Position.Top, position: (clickedHandle?.getAttribute('data-handlepos') as Position) ?? Position.Top,
}; };
updateConnection({ updateConnection({
connectionPosition, position,
connectionStatus: null, isValid: null,
connectionStartHandle, fromHandle,
connectionEndHandle: null, toHandle: null,
}); });
onConnectStart?.(event, { nodeId, handleId, handleType }); onConnectStart?.(event, { nodeId, handleId, handleType });
function onPointerMove(event: MouseEvent | TouchEvent) { function onPointerMove(event: MouseEvent | TouchEvent) {
if (!getConnectionStartHandle()) { if (!getFromHandle() || !fromHandle) {
onPointerUp(event); onPointerUp(event);
return;
} }
const transform = getTransform(); const transform = getTransform();
connectionPosition = getEventPosition(event, containerBounds); position = getEventPosition(event, containerBounds);
closestHandle = getClosestHandle( closestHandle = getClosestHandle(
pointToRendererPoint(connectionPosition, transform, false, [1, 1]), pointToRendererPoint(position, transform, false, [1, 1]),
connectionRadius, connectionRadius,
handleLookup handleLookup
); );
@@ -186,8 +187,8 @@ function onPointerDown(
isValid = result.isValid; isValid = result.isValid;
updateConnection({ updateConnection({
connectionStartHandle, fromHandle,
connectionPosition: position:
closestHandle && isValid closestHandle && isValid
? rendererPointToPoint( ? rendererPointToPoint(
{ {
@@ -196,9 +197,9 @@ function onPointerDown(
}, },
transform transform
) )
: connectionPosition, : position,
connectionStatus: getConnectionStatus(!!closestHandle, isValid), isValid: isConnectionValid(!!closestHandle, isValid),
connectionEndHandle: result.endHandle, toHandle: result.toHandle,
}); });
} }
@@ -221,7 +222,7 @@ function onPointerDown(
isValid = false; isValid = false;
connection = null; connection = null;
handleDomNode = null; handleDomNode = null;
connectionStartHandle = null; fromHandle = null;
doc.removeEventListener('mousemove', onPointerMove as EventListener); doc.removeEventListener('mousemove', onPointerMove as EventListener);
doc.removeEventListener('mouseup', onPointerUp as EventListener); doc.removeEventListener('mouseup', onPointerUp as EventListener);
@@ -267,7 +268,7 @@ function isValidHandle(
handleDomNode: handleToCheck, handleDomNode: handleToCheck,
isValid: false, isValid: false,
connection: null, connection: null,
endHandle: null, toHandle: null,
}; };
if (handleToCheck) { if (handleToCheck) {
@@ -300,7 +301,7 @@ function isValidHandle(
result.isValid = isValid && isValidConnection(connection); result.isValid = isValid && isValidConnection(connection);
result.endHandle = { result.toHandle = {
nodeId: handleNodeId as string, nodeId: handleNodeId as string,
handleId, handleId,
type: handleType as HandleType, type: handleType as HandleType,
+5 -6
View File
@@ -1,6 +1,5 @@
import { getHandlePosition } from '../utils'; import { getHandlePosition } from '../utils';
import { import {
ConnectionStatus,
type HandleType, type HandleType,
type NodeHandleBounds, type NodeHandleBounds,
type XYPosition, type XYPosition,
@@ -105,14 +104,14 @@ export function getHandleType(
return null; return null;
} }
export function getConnectionStatus(isInsideConnectionRadius: boolean, isHandleValid: boolean) { export function isConnectionValid(isInsideConnectionRadius: boolean, isHandleValid: boolean) {
let connectionStatus = null; let isValid: boolean | null = null;
if (isHandleValid) { if (isHandleValid) {
connectionStatus = 'valid'; isValid = true;
} else if (isInsideConnectionRadius && !isHandleValid) { } else if (isInsideConnectionRadius && !isHandleValid) {
connectionStatus = 'invalid'; isValid = false;
} }
return connectionStatus as ConnectionStatus; return isValid;
} }