fix(editor): Delete/Backspace key removes selected node + orphan edges
React Flow's built-in keyboard handling was silently no-op'd because deleteKeyCode wasn't set (v12 defaults it to null when the prop is absent in the strict TS types we consume). Set it to ['Delete', 'Backspace'] and add an onNodesDelete handler that filters edges whose endpoints just vanished — applyNodeChanges only touches nodes, so without this the graph kept dangling edges. Also fixes a tsc regression the same touch caught in ConnectionsPage.test where a request.json() cast leaked 'never' back into a later access.
This commit is contained in:
@@ -4,6 +4,8 @@ import {
|
||||
useReactFlow, type Connection, type Edge, type Node, type NodeChange, type EdgeChange,
|
||||
applyNodeChanges, applyEdgeChanges,
|
||||
} from "@xyflow/react";
|
||||
|
||||
const DELETE_KEYS = ["Delete", "Backspace"];
|
||||
import { nodeTypes as vcNodeTypes } from "./customNode";
|
||||
import type { VcNodeData } from "./graphAdapter";
|
||||
|
||||
@@ -51,6 +53,14 @@ function Inner({
|
||||
onEdgesChange={handleEdges}
|
||||
onConnect={onConnect}
|
||||
onSelectionChange={({ nodes: sel }) => onSelectNode(sel[0]?.id ?? null)}
|
||||
onNodesDelete={(deleted) => {
|
||||
// React Flow removes the nodes via applyNodeChanges above; it does
|
||||
// NOT auto-remove edges whose endpoints just vanished. Filter here
|
||||
// so the graph stays valid.
|
||||
const gone = new Set(deleted.map((n) => n.id));
|
||||
onEdgesChange(edges.filter((e) => !gone.has(e.source) && !gone.has(e.target)));
|
||||
}}
|
||||
deleteKeyCode={DELETE_KEYS}
|
||||
nodeTypes={vcNodeTypes}
|
||||
fitView
|
||||
>
|
||||
|
||||
@@ -38,9 +38,10 @@ describe("ConnectionsPage", () => {
|
||||
{ id: "c1", providerId: "nats", name: "local", config: { url: "nats://old" } },
|
||||
] as never)),
|
||||
http.put("/api/connections/c1", async ({ request }) => {
|
||||
latestPut = await request.json() as never;
|
||||
const body = await request.json() as { name?: string; config?: { url?: string; pass?: string } };
|
||||
latestPut = body;
|
||||
return HttpResponse.json({
|
||||
id: "c1", providerId: "nats", name: latestPut!.name, config: { url: latestPut!.config?.url },
|
||||
id: "c1", providerId: "nats", name: body.name, config: { url: body.config?.url },
|
||||
} as never);
|
||||
}),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user