improve menus

This commit is contained in:
2026-03-07 21:49:15 +01:00
parent 65d4f216a8
commit 39719b1823
2 changed files with 64 additions and 44 deletions

View File

@@ -23,13 +23,15 @@ import { useTheme } from './lib/themeContext'
import { import {
ContextMenu, ContextMenu,
ContextMenuContent, ContextMenuContent,
ContextMenuGroup,
ContextMenuItem, ContextMenuItem,
ContextMenuLabel, ContextMenuSub,
ContextMenuSubContent,
ContextMenuSubTrigger,
ContextMenuTrigger, ContextMenuTrigger,
ContextMenuGroup
} from "@/components/ui/context-menu" } from "@/components/ui/context-menu"
import { Button } from '@/components/ui/button' 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 // Generate short unique node ids when missing
const genId = () => `node_${Math.random().toString(36).slice(2, 9)}` const genId = () => `node_${Math.random().toString(36).slice(2, 9)}`
@@ -118,14 +120,13 @@ export default function App() {
const click = contextTarget ?? lastClickRef.current const click = contextTarget ?? lastClickRef.current
const clientX = click?.clientX ?? window.innerWidth / 2 const clientX = click?.clientX ?? window.innerWidth / 2
const clientY = click?.clientY ?? window.innerHeight / 2 const clientY = click?.clientY ?? window.innerHeight / 2
const rect = wrapperRef.current?.getBoundingClientRect() let position: { x: number; y: number }
const point = rect ? { x: clientX - rect.left, y: clientY - rect.top } : { x: clientX, y: clientY }
let position = point
try { try {
// project to flow coords when possible // Convert screen (client) coordinates to flow coordinates — same position as where the context menu opened
position = rfInstance.project ? rfInstance.project(point) : point const screenToFlow = rfInstance.screenToFlowPosition ?? rfInstance.project
} catch (e) { position = screenToFlow.call(rfInstance, { x: clientX, y: clientY })
// ignore and use raw point } catch {
position = { x: clientX, y: clientY }
} }
position = snapToGrid(position.x, position.y) position = snapToGrid(position.x, position.y)
@@ -154,7 +155,7 @@ export default function App() {
lastClickRef.current = null lastClickRef.current = null
setContextTarget(null) setContextTarget(null)
}, },
[rfInstance, setNodes] [rfInstance, setNodes, contextTarget]
) )
const deleteNode = React.useCallback((id: string | undefined) => { const deleteNode = React.useCallback((id: string | undefined) => {
@@ -204,24 +205,42 @@ export default function App() {
</div> </div>
</ContextMenuTrigger> </ContextMenuTrigger>
<ContextMenuContent> <ContextMenuContent className="w-48">
{contextTarget?.type === 'node' ? ( {contextTarget?.type === 'node' ? (
<ContextMenuItem onSelect={() => deleteNode(contextTarget.nodeId)}>Delete</ContextMenuItem>
) : (
<>
<ContextMenuGroup> <ContextMenuGroup>
<ContextMenuLabel>New Node</ContextMenuLabel> <ContextMenuItem onSelect={() => deleteNode(contextTarget.nodeId)}>Delete</ContextMenuItem>
<ContextMenuItem onSelect={() => createNode('config')}>Config</ContextMenuItem> </ContextMenuGroup>
<ContextMenuItem onSelect={() => createNode('render')}>Renderer</ContextMenuItem> ) : (
<ContextMenuItem onSelect={() => createNode('variable')}>Variable</ContextMenuItem> <ContextMenuGroup>
<ContextMenuItem onSelect={() => createNode('function')}>Function</ContextMenuItem> <ContextMenuSub>
<ContextMenuSubTrigger>Create node</ContextMenuSubTrigger>
<ContextMenuSubContent className="w-44">
<ContextMenuGroup>
<ContextMenuItem onSelect={() => createNode('config')}>
<ScrollText className="mr-2 h-4 w-4" />
Config
</ContextMenuItem>
<ContextMenuItem onSelect={() => createNode('render')}>
<Sparkles className="mr-2 h-4 w-4" />
Renderer
</ContextMenuItem>
<ContextMenuItem onSelect={() => createNode('variable')}>
<Variable className="mr-2 h-4 w-4" />
Variable
</ContextMenuItem>
<ContextMenuItem onSelect={() => createNode('function')}>
<Code2 className="mr-2 h-4 w-4" />
Function
</ContextMenuItem>
</ContextMenuGroup>
</ContextMenuSubContent>
</ContextMenuSub>
</ContextMenuGroup> </ContextMenuGroup>
</>
)} )}
</ContextMenuContent> </ContextMenuContent>
</ContextMenu> </ContextMenu>
</FlowContext.Provider> </FlowContext.Provider>
</div> </div >
) )
} }

View File

@@ -44,11 +44,12 @@ body {
@keyframes edge-flow { @keyframes edge-flow {
from { from {
stroke-dashoffset: 0;
}
to {
stroke-dashoffset: 14; stroke-dashoffset: 14;
} }
to {
stroke-dashoffset: 0;
}
} }
/* Resize control: snappy drag, no transition or selection delay */ /* Resize control: snappy drag, no transition or selection delay */