Files
thrilltrack-explorer/src-old/hooks/useKeyboardShortcuts.ts

66 lines
1.8 KiB
TypeScript

import { useEffect, useCallback } from 'react';
interface KeyboardShortcut {
key: string;
ctrlOrCmd?: boolean;
shift?: boolean;
alt?: boolean;
handler: () => void;
description: string;
}
interface UseKeyboardShortcutsOptions {
shortcuts: KeyboardShortcut[];
enabled?: boolean;
}
/**
* Hook for registering keyboard shortcuts
* Automatically handles Cmd (Mac) vs Ctrl (Windows/Linux)
*/
export function useKeyboardShortcuts({ shortcuts, enabled = true }: UseKeyboardShortcutsOptions) {
const handleKeyDown = useCallback(
(event: KeyboardEvent) => {
if (!enabled) return;
// Ignore shortcuts when typing in input fields
const target = event.target as HTMLElement;
if (
target.tagName === 'INPUT' ||
target.tagName === 'TEXTAREA' ||
target.isContentEditable
) {
return;
}
for (const shortcut of shortcuts) {
const matchesKey = event.key.toLowerCase() === shortcut.key.toLowerCase();
const matchesCtrl = !shortcut.ctrlOrCmd || (event.ctrlKey || event.metaKey);
const matchesShift = !shortcut.shift || event.shiftKey;
const matchesAlt = !shortcut.alt || event.altKey;
if (matchesKey && matchesCtrl && matchesShift && matchesAlt) {
event.preventDefault();
shortcut.handler();
break;
}
}
},
[shortcuts, enabled]
);
useEffect(() => {
if (!enabled) return;
window.addEventListener('keydown', handleKeyDown);
return () => window.removeEventListener('keydown', handleKeyDown);
}, [handleKeyDown, enabled]);
return {
shortcuts: shortcuts.map(s => ({
...s,
displayKey: `${s.ctrlOrCmd ? '⌘/Ctrl + ' : ''}${s.shift ? 'Shift + ' : ''}${s.alt ? 'Alt + ' : ''}${s.key.toUpperCase()}`,
})),
};
}