Files
xyflow/packages/react/src/components/EdgeWrapper/EdgeUpdateAnchors.tsx
T
Moritz KlackandGitHub 75acd24cee Rename updateEdge to reconnectEdge (#4373)
* refactor(edges): rename update to reconnect

* refactor(react): rename edge update to reconnect

* chore(examples): repair broken reconnect example

* chore(react): changelog
2024-06-19 16:57:30 +02:00

139 lines
4.1 KiB
TypeScript

// Reconnectable edges have a anchors around their handles to reconnect 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<EdgeType extends Edge = Edge> = {
edge: EdgeType;
isReconnectable: boolean | 'source' | 'target';
reconnectRadius: EdgeWrapperProps['reconnectRadius'];
sourceHandleId: Edge['sourceHandle'];
targetHandleId: Edge['targetHandle'];
onReconnect: EdgeWrapperProps<EdgeType>['onReconnect'];
onReconnectStart: EdgeWrapperProps<EdgeType>['onReconnectStart'];
onReconnectEnd: EdgeWrapperProps<EdgeType>['onReconnectEnd'];
setUpdateHover: (hover: boolean) => void;
setReconnecting: (updating: boolean) => void;
} & EdgePosition;
export function EdgeUpdateAnchors<EdgeType extends Edge = Edge>({
isReconnectable,
reconnectRadius,
edge,
targetHandleId,
sourceHandleId,
sourceX,
sourceY,
targetX,
targetY,
sourcePosition,
targetPosition,
onReconnect,
onReconnectStart,
onReconnectEnd,
setReconnecting,
setUpdateHover,
}: EdgeUpdateAnchorsProps<EdgeType>) {
const store = useStoreApi();
const handleEdgeUpdater = (event: React.MouseEvent<SVGGElement, 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,
nodeLookup,
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;
setReconnecting(true);
onReconnectStart?.(event, edge, handleType);
const _onReconnectEnd = (evt: MouseEvent | TouchEvent) => {
setReconnecting(false);
onReconnectEnd?.(evt, edge, handleType);
};
const onConnectEdge = (connection: Connection) => onReconnect?.(edge, connection);
XYHandle.onPointerDown(event.nativeEvent, {
autoPanOnConnect,
connectionMode,
connectionRadius,
domNode,
handleId,
nodeId,
nodeLookup,
isTarget,
edgeUpdaterType: handleType,
lib,
flowId,
cancelConnection,
panBy,
isValidConnection,
onConnect: onConnectEdge,
onConnectStart,
onConnectEnd,
onReconnectEnd: _onReconnectEnd,
updateConnection,
getTransform: () => store.getState().transform,
getConnectionStartHandle: () => store.getState().connectionStartHandle,
});
};
const onReconnectSourceMouseDown = (event: React.MouseEvent<SVGGElement, MouseEvent>): void =>
handleEdgeUpdater(event, true);
const onReconnectTargetMouseDown = (event: React.MouseEvent<SVGGElement, MouseEvent>): void =>
handleEdgeUpdater(event, false);
const onReconnectMouseEnter = () => setUpdateHover(true);
const onReconnectMouseOut = () => setUpdateHover(false);
return (
<>
{(isReconnectable === 'source' || isReconnectable === true) && (
<EdgeAnchor
position={sourcePosition}
centerX={sourceX}
centerY={sourceY}
radius={reconnectRadius}
onMouseDown={onReconnectSourceMouseDown}
onMouseEnter={onReconnectMouseEnter}
onMouseOut={onReconnectMouseOut}
type="source"
/>
)}
{(isReconnectable === 'target' || isReconnectable === true) && (
<EdgeAnchor
position={targetPosition}
centerX={targetX}
centerY={targetY}
radius={reconnectRadius}
onMouseDown={onReconnectTargetMouseDown}
onMouseEnter={onReconnectMouseEnter}
onMouseOut={onReconnectMouseOut}
type="target"
/>
)}
</>
);
}