Files
Pien-Studio/apps/web/hooks/use-editor-shortcuts.ts
T

82 lines
2.2 KiB
TypeScript
Raw Normal View History

2026-05-10 03:06:54 +07:00
import React from "react";
type UseEditorShortcutsOptions = {
onSave: () => void;
2026-05-21 00:02:12 +07:00
onUndo: () => void;
onRedo: () => void;
2026-05-10 03:06:54 +07:00
onCopy: () => void;
onCut: () => void;
2026-05-21 00:02:12 +07:00
onPaste: (e?: ClipboardEvent) => void;
2026-05-10 03:06:54 +07:00
onDelete: () => void;
};
2026-05-21 00:02:12 +07:00
function isEditableTarget(e: Event) {
return e.target instanceof HTMLElement && /^(input|textarea|select)$/i.test(e.target.tagName);
}
2026-05-10 03:06:54 +07:00
export function useEditorShortcuts(options: UseEditorShortcutsOptions) {
2026-05-21 00:02:12 +07:00
const { onSave, onUndo, onRedo, onCopy, onCut, onPaste, onDelete } = options;
2026-05-10 03:06:54 +07:00
React.useEffect(() => {
function handleKeyDown(e: KeyboardEvent) {
if (e.ctrlKey || e.metaKey) {
if (e.key.toLowerCase() === "s") {
e.preventDefault();
onSave();
return;
}
2026-05-21 00:02:12 +07:00
if (e.key.toLowerCase() === "z" && !e.shiftKey) {
2026-05-10 03:06:54 +07:00
e.preventDefault();
2026-05-21 00:02:12 +07:00
onUndo();
2026-05-10 03:06:54 +07:00
return;
}
2026-05-21 00:02:12 +07:00
if (e.key.toLowerCase() === "z" && e.shiftKey) {
2026-05-10 03:06:54 +07:00
e.preventDefault();
2026-05-21 00:02:12 +07:00
onRedo();
2026-05-10 03:06:54 +07:00
return;
}
2026-05-21 00:02:12 +07:00
if (e.key.toLowerCase() === "y") {
2026-05-10 03:06:54 +07:00
e.preventDefault();
2026-05-21 00:02:12 +07:00
onRedo();
2026-05-10 03:06:54 +07:00
return;
}
}
if (e.key === "Delete" || e.key === "Backspace") {
2026-05-21 00:02:12 +07:00
if (isEditableTarget(e)) return;
2026-05-10 03:06:54 +07:00
e.preventDefault();
onDelete();
}
}
2026-05-21 00:02:12 +07:00
function handleCopy(e: ClipboardEvent) {
if (isEditableTarget(e)) return;
e.preventDefault();
onCopy();
}
function handleCut(e: ClipboardEvent) {
if (isEditableTarget(e)) return;
e.preventDefault();
onCut();
}
function handlePaste(e: ClipboardEvent) {
if (isEditableTarget(e)) return;
e.preventDefault();
onPaste(e);
}
2026-05-10 03:06:54 +07:00
window.addEventListener("keydown", handleKeyDown);
2026-05-21 00:02:12 +07:00
window.addEventListener("copy", handleCopy);
window.addEventListener("cut", handleCut);
window.addEventListener("paste", handlePaste);
return () => {
window.removeEventListener("keydown", handleKeyDown);
window.removeEventListener("copy", handleCopy);
window.removeEventListener("cut", handleCut);
window.removeEventListener("paste", handlePaste);
};
}, [onCopy, onCut, onDelete, onPaste, onRedo, onSave, onUndo]);
2026-05-10 03:06:54 +07:00
}