diff --git a/packages/editor/src/editor/Canvas.tsx b/packages/editor/src/editor/Canvas.tsx index 4d37546..6ece543 100644 --- a/packages/editor/src/editor/Canvas.tsx +++ b/packages/editor/src/editor/Canvas.tsx @@ -65,6 +65,23 @@ export function Canvas(props: CanvasProps) { const selectionAllLocked = selection.length > 0 && selection.every((n) => n.locked); const selectionAllHidden = selection.length > 0 && selection.every((n) => n.hidden); + const ctxMenuPos = useMemo(() => { + if (!ctx) return null; + + // Rough clamp so the menu stays inside the viewport. + // (We don't measure actual size to keep this simple + stable.) + const w = 220; + const h = 320; + + const vw = typeof window === 'undefined' ? 10_000 : window.innerWidth; + const vh = typeof window === 'undefined' ? 10_000 : window.innerHeight; + + return { + x: Math.max(8, Math.min(ctx.clientX, vw - w - 8)), + y: Math.max(8, Math.min(ctx.clientY, vh - h - 8)), + }; + }, [ctx]); + const clientToCanvas = useCallback((clientX: number, clientY: number) => { const el = ref.current; if (!el) return null; @@ -175,14 +192,21 @@ export function Canvas(props: CanvasProps) { const p = clientToWorld(e.clientX, e.clientY); if (!p) return; - if (targetId && !props.selectionIds.includes(targetId)) { - // goView-ish: right click selects the item. - // Ctrl/Cmd keeps multi-select parity (add to selection instead of replacing). - if ((e as React.MouseEvent).ctrlKey || (e as React.MouseEvent).metaKey) { - props.onToggleSelect(targetId); - } else { - props.onSelectSingle(targetId); + const additive = (e as React.MouseEvent).ctrlKey || (e as React.MouseEvent).metaKey; + + if (targetId) { + if (!props.selectionIds.includes(targetId)) { + // goView-ish: right click selects the item. + // Ctrl/Cmd keeps multi-select parity (add to selection instead of replacing). + if (additive) { + props.onToggleSelect(targetId); + } else { + props.onSelectSingle(targetId); + } } + } else { + // Editor parity: right-click on empty space clears selection (unless additive). + if (!additive) props.onSelectSingle(undefined); } setCtx({ clientX: e.clientX, clientY: e.clientY, worldX: p.x, worldY: p.y, targetId }); @@ -264,12 +288,12 @@ export function Canvas(props: CanvasProps) { cursor: props.keyboard.space ? 'grab' : 'default', }} > - {ctx && ( + {ctx && ctxMenuPos && (