diff --git a/src/App.tsx b/src/App.tsx index 15ef3eb..6492a03 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -23,13 +23,15 @@ import { useTheme } from './lib/themeContext' import { ContextMenu, ContextMenuContent, - ContextMenuGroup, ContextMenuItem, - ContextMenuLabel, + ContextMenuSub, + ContextMenuSubContent, + ContextMenuSubTrigger, ContextMenuTrigger, + ContextMenuGroup } from "@/components/ui/context-menu" import { Button } from '@/components/ui/button' -import { Moon, Sun } from 'lucide-react' +import { Code2, Moon, ScrollText, Sparkles, Sun, Variable } from 'lucide-react' // Generate short unique node ids when missing const genId = () => `node_${Math.random().toString(36).slice(2, 9)}` @@ -118,14 +120,13 @@ export default function App() { const click = contextTarget ?? lastClickRef.current const clientX = click?.clientX ?? window.innerWidth / 2 const clientY = click?.clientY ?? window.innerHeight / 2 - const rect = wrapperRef.current?.getBoundingClientRect() - const point = rect ? { x: clientX - rect.left, y: clientY - rect.top } : { x: clientX, y: clientY } - let position = point + let position: { x: number; y: number } try { - // project to flow coords when possible - position = rfInstance.project ? rfInstance.project(point) : point - } catch (e) { - // ignore and use raw point + // Convert screen (client) coordinates to flow coordinates — same position as where the context menu opened + const screenToFlow = rfInstance.screenToFlowPosition ?? rfInstance.project + position = screenToFlow.call(rfInstance, { x: clientX, y: clientY }) + } catch { + position = { x: clientX, y: clientY } } position = snapToGrid(position.x, position.y) @@ -154,7 +155,7 @@ export default function App() { lastClickRef.current = null setContextTarget(null) }, - [rfInstance, setNodes] + [rfInstance, setNodes, contextTarget] ) const deleteNode = React.useCallback((id: string | undefined) => { @@ -182,46 +183,64 @@ export default function App() {