fix(editor): delete graph edges via right-click context menu
Remove accidental edge deletion on click and document the new graph link workflow in help and docs. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -364,15 +364,19 @@ function SceneGraphCanvas({
|
||||
const ui = graphUi ?? DEFAULT_SCENE_GRAPH_UI;
|
||||
const { screenToFlowPosition } = useReactFlow();
|
||||
const [menu, setMenu] = useState<{ x: number; y: number; graphNodeId: GraphNodeId } | null>(null);
|
||||
const [edgeMenu, setEdgeMenu] = useState<{ x: number; y: number; edgeId: string } | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!menu) return;
|
||||
if (!menu && !edgeMenu) return;
|
||||
const onKey = (e: KeyboardEvent) => {
|
||||
if (e.key === 'Escape') setMenu(null);
|
||||
if (e.key === 'Escape') {
|
||||
setMenu(null);
|
||||
setEdgeMenu(null);
|
||||
}
|
||||
};
|
||||
window.addEventListener('keydown', onKey);
|
||||
return () => window.removeEventListener('keydown', onKey);
|
||||
}, [menu]);
|
||||
}, [edgeMenu, menu]);
|
||||
|
||||
const menuNodeIsStart = useMemo(() => {
|
||||
if (!menu) return false;
|
||||
@@ -439,6 +443,7 @@ function SceneGraphCanvas({
|
||||
target: e.targetGraphNodeId,
|
||||
type: 'smoothstep',
|
||||
animated: false,
|
||||
selectable: false,
|
||||
}));
|
||||
}, [currentSceneId, sceneGraphEdges, sceneGraphNodes]);
|
||||
|
||||
@@ -491,6 +496,16 @@ function SceneGraphCanvas({
|
||||
return { x, y };
|
||||
}, [menu]);
|
||||
|
||||
const edgeMenuPosition = useMemo(() => {
|
||||
if (!edgeMenu) return null;
|
||||
const pad = 8;
|
||||
const mw = 200;
|
||||
const mh = 48;
|
||||
const x = Math.max(pad, Math.min(edgeMenu.x, window.innerWidth - mw - pad));
|
||||
const y = Math.max(pad, Math.min(edgeMenu.y, window.innerHeight - mh - pad));
|
||||
return { x, y };
|
||||
}, [edgeMenu]);
|
||||
|
||||
return (
|
||||
<GraphUiContext.Provider value={ui}>
|
||||
<div className={styles.canvasWrap}>
|
||||
@@ -505,32 +520,33 @@ function SceneGraphCanvas({
|
||||
onEdgesChange={onEdgesChange}
|
||||
isValidConnection={isValidConnection}
|
||||
onConnect={onConnectInternal}
|
||||
onEdgesDelete={(eds) => {
|
||||
for (const ed of eds) {
|
||||
onDisconnect(ed.id);
|
||||
}
|
||||
}}
|
||||
onEdgeClick={(_, edge) => {
|
||||
onDisconnect(edge.id);
|
||||
onEdgeContextMenu={(e, edge) => {
|
||||
e.preventDefault();
|
||||
setMenu(null);
|
||||
setEdgeMenu({ x: e.clientX, y: e.clientY, edgeId: edge.id });
|
||||
}}
|
||||
onNodesDelete={(nds) => {
|
||||
onRemoveGraphNodes(nds.map((n) => n.id as GraphNodeId));
|
||||
}}
|
||||
onNodeClick={(_, node) => {
|
||||
setMenu(null);
|
||||
setEdgeMenu(null);
|
||||
const d = node.data as SceneCardData;
|
||||
onCurrentSceneChange(d.sceneId);
|
||||
}}
|
||||
onNodeContextMenu={(e, node) => {
|
||||
e.preventDefault();
|
||||
setEdgeMenu(null);
|
||||
setMenu({ x: e.clientX, y: e.clientY, graphNodeId: node.id as GraphNodeId });
|
||||
}}
|
||||
onPaneClick={() => {
|
||||
setMenu(null);
|
||||
setEdgeMenu(null);
|
||||
}}
|
||||
onPaneContextMenu={(e) => {
|
||||
e.preventDefault();
|
||||
setMenu(null);
|
||||
setEdgeMenu(null);
|
||||
}}
|
||||
onInit={(instance) => {
|
||||
instance.fitView({ padding: 0.25 });
|
||||
@@ -595,6 +611,41 @@ function SceneGraphCanvas({
|
||||
document.body,
|
||||
)
|
||||
: null}
|
||||
{edgeMenu && edgeMenuPosition
|
||||
? createPortal(
|
||||
<>
|
||||
<button
|
||||
type="button"
|
||||
aria-label={ui.closeMenu}
|
||||
className={styles.menuBackdrop}
|
||||
onClick={() => setEdgeMenu(null)}
|
||||
/>
|
||||
<div
|
||||
role="menu"
|
||||
tabIndex={-1}
|
||||
className={styles.ctxMenu}
|
||||
style={{ left: edgeMenuPosition.x, top: edgeMenuPosition.y }}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Escape') setEdgeMenu(null);
|
||||
}}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
className={styles.ctxItemDanger}
|
||||
onClick={() => {
|
||||
onDisconnect(edgeMenu.edgeId);
|
||||
setEdgeMenu(null);
|
||||
}}
|
||||
>
|
||||
{ui.delete}
|
||||
</button>
|
||||
</div>
|
||||
</>,
|
||||
document.body,
|
||||
)
|
||||
: null}
|
||||
</div>
|
||||
</GraphUiContext.Provider>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user