diff --git a/app/src/views/DesignCanvas.tsx b/app/src/views/DesignCanvas.tsx index 26dbfc7..feed48a 100644 --- a/app/src/views/DesignCanvas.tsx +++ b/app/src/views/DesignCanvas.tsx @@ -33,7 +33,7 @@ export default function DesignCanvas({ const { state, addObject, - removeObject: _removeObject, + removeObject, updateObject, selectObjects, deselectAll, @@ -170,6 +170,59 @@ export default function DesignCanvas({ setZoomLevel(1); }, []); + // -- Keyboard shortcuts --------------------------------------------------- + + useEffect(() => { + const handleKeyDown = (e: KeyboardEvent) => { + // Don't fire shortcuts when typing in an input/textarea + const tag = (document.activeElement?.tagName ?? '').toLowerCase(); + if (tag === 'input' || tag === 'textarea' || tag === 'select') return; + + const ctrl = e.ctrlKey || e.metaKey; + + if (ctrl && e.shiftKey && e.key.toLowerCase() === 'z') { + e.preventDefault(); + redo(); + return; + } + + if (ctrl && e.key.toLowerCase() === 'z') { + e.preventDefault(); + undo(); + return; + } + + if (ctrl && e.key.toLowerCase() === 'y') { + e.preventDefault(); + redo(); + return; + } + + if (ctrl && e.key.toLowerCase() === 'a') { + e.preventDefault(); + selectObjects(state.objects.map((o) => o.id)); + return; + } + + if (e.key === 'Delete' || e.key === 'Backspace') { + e.preventDefault(); + for (const id of state.selectedIds) { + removeObject(id); + } + return; + } + + if (e.key === 'Escape') { + e.preventDefault(); + deselectAll(); + return; + } + }; + + window.addEventListener('keydown', handleKeyDown); + return () => window.removeEventListener('keydown', handleKeyDown); + }, [undo, redo, removeObject, selectObjects, deselectAll, state.objects, state.selectedIds]); + // -- Selected object for properties panel --------------------------------- const selectedObject = useMemo(() => {