Custom smart edges
Create a custom edge and call getSmartEdge for path computation.
Required inputs
sourcePosition,targetPosition,sourceX,sourceY,targetX,targetY— same as custom edge propsnodes— fromuseNodes
Example with a button label
Like React Flow's edge with button example:
import { useNodes, BezierEdge } from "@xyflow/react";
import { getSmartEdge } from "@tisoap/react-flow-smart-edge";
import type { EdgeProps } from "@xyflow/react";
const foreignObjectSize = 200;
export function SmartEdgeWithButtonLabel(props: EdgeProps) {
const {
id,
sourcePosition,
targetPosition,
sourceX,
sourceY,
targetX,
targetY,
style,
markerStart,
markerEnd,
} = props;
const nodes = useNodes();
const smartResponse = getSmartEdge({
sourcePosition,
targetPosition,
sourceX,
sourceY,
targetX,
targetY,
nodes,
});
if (smartResponse instanceof Error) {
return <BezierEdge {...props} />;
}
const { edgeCenterX, edgeCenterY, svgPathString } = smartResponse;
return (
<>
<path
style={style}
className="react-flow__edge-path"
d={svgPathString}
markerEnd={markerEnd}
markerStart={markerStart}
/>
<foreignObject
width={foreignObjectSize}
height={foreignObjectSize}
x={edgeCenterX - foreignObjectSize / 2}
y={edgeCenterY - foreignObjectSize / 2}
requiredExtensions="http://www.w3.org/1999/xhtml"
>
<button
type="button"
onClick={(event) => {
event.stopPropagation();
alert(`remove ${id}`);
}}
>
X
</button>
</foreignObject>
</>
);
}
Advanced configuration
Pass an optional options object to tune pathfinding. See Options and getSmartEdge.
const result = getSmartEdge({
sourcePosition,
targetPosition,
sourceX,
sourceY,
targetX,
targetY,
nodes,
options: {
nodePadding: 20,
gridRatio: 15,
},
});
Use smartEdgePresets to match built-in edge behavior:
import { getSmartEdge, smartEdgePresets } from "@tisoap/react-flow-smart-edge";
const bezierResult = getSmartEdge({ /* ... */, options: smartEdgePresets.bezier });
const stepResult = getSmartEdge({ /* ... */, options: smartEdgePresets.step });