fix: loop error condition and edge design (#5869)

* Changed math to show better edge when loop source is on the left side of the target

* Added logic to only allow loops if it comes from a loop edge

* Removed unused console log
This commit is contained in:
Lucas Oliveira 2025-01-22 14:12:25 -03:00 • committed by GitHub
commit 1f004560ec
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 36 additions and 6 deletions

View file

@ -24,10 +24,25 @@ export function DefaultEdge({
(sourceNode?.position.x ?? 0) + (sourceNode?.measured?.width ?? 0);
const targetXNew = targetNode?.position.x ?? 0;
const distance = 200 + 0.1 * (Math.abs(sourceXNew - targetXNew) / 2);
const distanceY = 200 + 0.3 * Math.abs(sourceY - targetY);
const distance = 200 + 0.1 * ((sourceXNew - targetXNew) / 2);
const edgePathLoop = `M ${sourceXNew} ${sourceY} C ${sourceXNew + distance} ${sourceY + distanceY}, ${targetXNew - distance} ${targetY + distanceY}, ${targetXNew} ${targetY}`;
const zeroOnNegative =
(1 +
(1 - Math.exp(-0.01 * Math.abs(sourceXNew - targetXNew))) *
(sourceXNew - targetXNew >= 0 ? 1 : -1)) /
2;
const distanceY =
200 -
200 * (1 - zeroOnNegative) +
0.3 * Math.abs(targetY - sourceY) * zeroOnNegative;
const sourceDistanceY =
200 -
200 * (1 - zeroOnNegative) +
0.3 * Math.abs(sourceY - targetY) * zeroOnNegative;
const edgePathLoop = `M ${sourceXNew} ${sourceY} C ${sourceXNew + distance} ${sourceY + sourceDistanceY}, ${targetXNew - distance} ${targetY + distanceY}, ${targetXNew} ${targetY}`;
const [edgePath] = getBezierPath({
sourceX: sourceXNew,

View file

@ -581,14 +581,29 @@ function hasLoop(
// Check if this connection would create a cycle
const targetNode = nodes.find((n) => n.id === target);
const hasCycle = (node, visited = new Set()): boolean => {
const hasCycle = (
node,
visited = new Set(),
firstEdge: EdgeType | null = null,
): boolean => {
if (visited.has(node.id)) return false;
visited.add(node.id);
for (const outgoer of getOutgoers(node, nodes, edges)) {
if (outgoer.id === source) return true;
if (hasCycle(outgoer, visited)) return true;
const edge = edges.find(
(e) => e.source === node.id && e.target === outgoer.id,
);
if (outgoer.id === source) {
const sourceHandleObject = scapeJSONParse(
firstEdge?.sourceHandle ?? edge?.sourceHandle ?? "",
);
const sourceHandleParsed = scapedJSONStringfy(sourceHandleObject);
if (sourceHandleParsed === e.targetHandle) {
return true;
}
}
if (hasCycle(outgoer, visited, firstEdge || edge)) return true;
}
return false;
};