import { BaseEdge, type EdgeProps, getBezierPath, getSimpleBezierPath, type InternalNode, type Node, Position, useInternalNode, } from "@xyflow/react"; const Temporary = ({ id, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, }: EdgeProps) => { const [edgePath] = getSimpleBezierPath({ sourceX, sourceY, sourcePosition, targetX, targetY, targetPosition, }); return ( ); }; const getHandleCoordsByPosition = ( node: InternalNode, handlePosition: Position ) => { // Choose the handle type based on position - Left is for target, Right is for source const handleType = handlePosition === Position.Left ? "target" : "source"; const handle = node.internals.handleBounds?.[handleType]?.find( (h) => h.position === handlePosition ); if (!handle) { return [0, 0]; } let offsetX = handle.width / 2; let offsetY = handle.height / 2; // this is a tiny detail to make the markerEnd of an edge visible. // The handle position that gets calculated has the origin top-left, so depending which side we are using, we add a little offset // when the handlePosition is Position.Right for example, we need to add an offset as big as the handle itself in order to get the correct position switch (handlePosition) { case Position.Left: offsetX = 0; break; case Position.Right: offsetX = handle.width; break; case Position.Top: offsetY = 0; break; case Position.Bottom: offsetY = handle.height; break; default: throw new Error(`Invalid handle position: ${handlePosition}`); } const x = node.internals.positionAbsolute.x + handle.x + offsetX; const y = node.internals.positionAbsolute.y + handle.y + offsetY; return [x, y]; }; const getEdgeParams = ( source: InternalNode, target: InternalNode ) => { const sourcePos = Position.Right; const [sx, sy] = getHandleCoordsByPosition(source, sourcePos); const targetPos = Position.Left; const [tx, ty] = getHandleCoordsByPosition(target, targetPos); return { sx, sy, tx, ty, sourcePos, targetPos, }; }; const Animated = ({ id, source, target, markerEnd, style }: EdgeProps) => { const sourceNode = useInternalNode(source); const targetNode = useInternalNode(target); if (!(sourceNode && targetNode)) { return null; } const { sx, sy, tx, ty, sourcePos, targetPos } = getEdgeParams( sourceNode, targetNode ); const [edgePath] = getBezierPath({ sourceX: sx, sourceY: sy, sourcePosition: sourcePos, targetX: tx, targetY: ty, targetPosition: targetPos, }); return ( <> ); }; export const Edge = { Temporary, Animated, };