import { useEffect, useCallback } from "react"; interface KeyboardShortcutsProps { selectedElementId: string | null; onDelete: () => void; onCopy: () => void; onPaste: () => void; onUndo?: () => void; onRedo?: () => void; enabled?: boolean; } /** * 대시보드 키보드 단축키 훅 * * 지원 단축키: * - Delete: 선택한 요소 삭제 * - Ctrl+C: 요소 복사 * - Ctrl+V: 요소 붙여넣기 * - Ctrl+Z: 실행 취소 (구현 예정) * - Ctrl+Shift+Z: 재실행 (구현 예정) */ export function useKeyboardShortcuts({ selectedElementId, onDelete, onCopy, onPaste, onUndo, onRedo, enabled = true, }: KeyboardShortcutsProps) { const handleKeyDown = useCallback( (e: KeyboardEvent) => { if (!enabled) return; // 입력 필드에서는 단축키 비활성화 const target = e.target as HTMLElement; if ( target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.contentEditable === "true" || target.closest('[role="dialog"]') || target.closest('[role="alertdialog"]') ) { return; } const isMac = navigator.platform.toUpperCase().indexOf("MAC") >= 0; const ctrlKey = isMac ? e.metaKey : e.ctrlKey; // Delete: 선택한 요소 삭제 if (e.key === "Delete" || e.key === "Backspace") { if (selectedElementId) { e.preventDefault(); onDelete(); } return; } // Ctrl+C: 복사 if (ctrlKey && e.key === "c") { if (selectedElementId) { e.preventDefault(); onCopy(); } return; } // Ctrl+V: 붙여넣기 if (ctrlKey && e.key === "v") { e.preventDefault(); onPaste(); return; } // Ctrl+Z: 실행 취소 if (ctrlKey && e.key === "z" && !e.shiftKey) { if (onUndo) { e.preventDefault(); onUndo(); } return; } // Ctrl+Shift+Z 또는 Ctrl+Y: 재실행 if ((ctrlKey && e.shiftKey && e.key === "z") || (ctrlKey && e.key === "y")) { if (onRedo) { e.preventDefault(); onRedo(); } return; } }, [enabled, selectedElementId, onDelete, onCopy, onPaste, onUndo, onRedo], ); useEffect(() => { if (!enabled) return; document.addEventListener("keydown", handleKeyDown); return () => { document.removeEventListener("keydown", handleKeyDown); }; }, [handleKeyDown, enabled]); }