From 6e880963ab4ab079864a6c338773a412c9c46562 Mon Sep 17 00:00:00 2001 From: NikitaKalitov Date: Mon, 20 Jul 2026 13:07:57 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A4=D0=B8=D0=BA=D1=81=20=D1=81=D1=82=D1=80?= =?UTF-8?q?=D0=B5=D0=BB=D0=BE=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/DiagramEditor.tsx | 31 +++++++++++++++++++------------ src/diagram.css | 9 ++++++++- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/DiagramEditor.tsx b/src/DiagramEditor.tsx index 40f17b3..7cd4e99 100644 --- a/src/DiagramEditor.tsx +++ b/src/DiagramEditor.tsx @@ -129,18 +129,25 @@ function toRfNodes(doc: DiagramDocument | null): Node[] { } function toRfEdges(doc: DiagramDocument | null): Edge[] { - return (doc?.edges ?? []).map((edge) => ({ - id: edge.id, - source: edge.source, - target: edge.target, - sourceHandle: edge.sourceHandle, - targetHandle: edge.targetHandle, - type: edge.type ?? DEFAULT_EDGE_TYPE, - markerEnd: DEFAULT_MARKER_END, - label: edge.label, - zIndex: edge.zIndex, - data: edge.data, - })); + const nodeIds = new Set((doc?.nodes ?? []).map((node) => node.id)); + // Defends against documents saved by an older/buggy version, or edited by + // hand — an edge pointing at a node id that no longer exists renders as a + // degenerate path (xyflow falls back to position (0, 0) for the missing + // endpoint), which is exactly the "arrows in the corner" bug. + return (doc?.edges ?? []) + .filter((edge) => nodeIds.has(edge.source) && nodeIds.has(edge.target)) + .map((edge) => ({ + id: edge.id, + source: edge.source, + target: edge.target, + sourceHandle: edge.sourceHandle, + targetHandle: edge.targetHandle, + type: edge.type ?? DEFAULT_EDGE_TYPE, + markerEnd: DEFAULT_MARKER_END, + label: edge.label, + zIndex: edge.zIndex, + data: edge.data, + })); } function isEditableTarget(target: EventTarget | null): boolean { diff --git a/src/diagram.css b/src/diagram.css index e451b70..f266eaf 100644 --- a/src/diagram.css +++ b/src/diagram.css @@ -30,8 +30,15 @@ background: color-mix(in srgb, canvastext 8%, canvas); } +/* + * opacity/pointer-events, not display:none — hiding via display collapses the + * handle to 0x0, and xyflow computes edge paths from the handle's actual + * layout position, so every edge that references a handle id would snap to + * a degenerate point the moment view mode hid it. + */ .diagram-flow--view-mode .react-flow__handle { - display: none; + opacity: 0; + pointer-events: none; } /*