// Updatable edges have a anchors around their handles to update the edge. import { XYHandle, type Connection, EdgePosition } from '@xyflow/system'; import { EdgeAnchor } from '../Edges/EdgeAnchor'; import type { EdgeWrapperProps, Edge } from '../../types/edges'; import { useStoreApi } from '../../hooks/useStore'; type EdgeUpdateAnchorsProps = { edge: EdgeType; isUpdatable: boolean | 'source' | 'target'; edgeUpdaterRadius: EdgeWrapperProps['edgeUpdaterRadius']; sourceHandleId: Edge['sourceHandle']; targetHandleId: Edge['targetHandle']; onEdgeUpdate: EdgeWrapperProps['onEdgeUpdate']; onEdgeUpdateStart: EdgeWrapperProps['onEdgeUpdateStart']; onEdgeUpdateEnd: EdgeWrapperProps['onEdgeUpdateEnd']; setUpdateHover: (hover: boolean) => void; setUpdating: (updating: boolean) => void; } & EdgePosition; export function EdgeUpdateAnchors({ isUpdatable, edgeUpdaterRadius, edge, targetHandleId, sourceHandleId, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, onEdgeUpdate, onEdgeUpdateStart, onEdgeUpdateEnd, setUpdating, setUpdateHover, }: EdgeUpdateAnchorsProps) { const store = useStoreApi(); const handleEdgeUpdater = (event: React.MouseEvent, isSourceHandle: boolean) => { // avoid triggering edge updater if mouse btn is not left if (event.button !== 0) { return; } const { autoPanOnConnect, domNode, isValidConnection, connectionMode, connectionRadius, lib, onConnectStart, onConnectEnd, cancelConnection, nodes, rfId: flowId, panBy, updateConnection, } = store.getState(); const nodeId = isSourceHandle ? edge.target : edge.source; const handleId = (isSourceHandle ? targetHandleId : sourceHandleId) || null; const handleType = isSourceHandle ? 'target' : 'source'; const isTarget = isSourceHandle; setUpdating(true); onEdgeUpdateStart?.(event, edge, handleType); const _onEdgeUpdateEnd = (evt: MouseEvent | TouchEvent) => { setUpdating(false); onEdgeUpdateEnd?.(evt, edge, handleType); }; const onConnectEdge = (connection: Connection) => onEdgeUpdate?.(edge, connection); XYHandle.onPointerDown(event.nativeEvent, { autoPanOnConnect, connectionMode, connectionRadius, domNode, handleId, nodeId, nodes, isTarget, edgeUpdaterType: handleType, lib, flowId, cancelConnection, panBy, isValidConnection, onConnect: onConnectEdge, onConnectStart, onConnectEnd, onEdgeUpdateEnd: _onEdgeUpdateEnd, updateConnection, getTransform: () => store.getState().transform, getConnectionStartHandle: () => store.getState().connectionStartHandle, }); }; const onEdgeUpdaterSourceMouseDown = (event: React.MouseEvent): void => handleEdgeUpdater(event, true); const onEdgeUpdaterTargetMouseDown = (event: React.MouseEvent): void => handleEdgeUpdater(event, false); const onEdgeUpdaterMouseEnter = () => setUpdateHover(true); const onEdgeUpdaterMouseOut = () => setUpdateHover(false); return ( <> {(isUpdatable === 'source' || isUpdatable === true) && ( )} {(isUpdatable === 'target' || isUpdatable === true) && ( )} ); }