editor: add core hotkeys (copy/paste/select-all/esc)
This commit is contained in:
parent
e4b25a66a0
commit
4e4b0e428d
@ -1,9 +1,35 @@
|
||||
import type { EditorAction } from './store';
|
||||
|
||||
function isEditableTarget(target: EventTarget | null): boolean {
|
||||
if (!target) return false;
|
||||
if (!(target instanceof HTMLElement)) return false;
|
||||
|
||||
// If the focus is inside inputs/textareas or contenteditable, let the browser handle hotkeys.
|
||||
const el = target;
|
||||
if (el.isContentEditable) return true;
|
||||
|
||||
const tag = el.tagName.toLowerCase();
|
||||
if (tag === 'input' || tag === 'textarea' || tag === 'select') return true;
|
||||
|
||||
// Some components nest the real input.
|
||||
if (el.closest('input, textarea, select, [contenteditable="true"]')) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export function bindEditorHotkeys(getShift: () => boolean, dispatch: (a: EditorAction) => void) {
|
||||
const onKeyDown = (e: KeyboardEvent) => {
|
||||
const ctrl = e.ctrlKey || e.metaKey;
|
||||
|
||||
// Esc: clear selection (and closes context menu via selection parity effect).
|
||||
if (e.key === 'Escape') {
|
||||
dispatch({ type: 'selectSingle', id: undefined });
|
||||
return;
|
||||
}
|
||||
|
||||
// Do not steal common hotkeys while typing in an input/editor.
|
||||
if (isEditableTarget(e.target)) return;
|
||||
|
||||
// Undo/redo
|
||||
if (ctrl && e.key.toLowerCase() === 'z') {
|
||||
e.preventDefault();
|
||||
@ -16,8 +42,28 @@ export function bindEditorHotkeys(getShift: () => boolean, dispatch: (a: EditorA
|
||||
return;
|
||||
}
|
||||
|
||||
// Select all
|
||||
if (ctrl && e.key.toLowerCase() === 'a') {
|
||||
e.preventDefault();
|
||||
dispatch({ type: 'selectAll' });
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy/paste
|
||||
if (ctrl && e.key.toLowerCase() === 'c') {
|
||||
e.preventDefault();
|
||||
dispatch({ type: 'copySelected' });
|
||||
return;
|
||||
}
|
||||
if (ctrl && e.key.toLowerCase() === 'v') {
|
||||
e.preventDefault();
|
||||
dispatch({ type: 'pasteClipboard' });
|
||||
return;
|
||||
}
|
||||
|
||||
// Delete
|
||||
if (e.key === 'Delete' || e.key === 'Backspace') {
|
||||
e.preventDefault();
|
||||
dispatch({ type: 'deleteSelected' });
|
||||
return;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user