All files / web/src/hooks use-keyboard-shortcuts.ts

100% Statements 58/58
96.96% Branches 32/33
100% Functions 5/5
100% Lines 58/58

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86    1x     1x 20x 19x   19x   19x 19x 19x   3x 20x 20x     1x 4x   4x 4x 4x 1x 4x 1x 4x 1x 4x 1x 4x 4x 4x     1x 18x 18x 18x 18x 10x 10x 18x 18x                 1x 11x 11x 11x 11x 11x   11x 11x   10x   6x     5x 6x 4x 4x 4x 4x 6x   10x   10x 10x 10x 11x 11x  
'use client';
 
import { useEffect, useMemo } from 'react';
 
// Detect user's operating system
export const useOperatingSystem = () => {
  return useMemo(() => {
    if (typeof window === 'undefined') return 'unknown';
 
    const userAgent = window.navigator.userAgent.toLowerCase();
 
    if (userAgent.includes('mac')) return 'mac';
    if (userAgent.includes('win')) return 'windows';
    if (userAgent.includes('linux')) return 'linux';
 
    return 'unknown';
  }, []);
};
 
// Get the appropriate modifier key symbol
export const useModifierKey = () => {
  const os = useOperatingSystem();
 
  return useMemo(() => {
    switch (os) {
      case 'mac':
        return '⌘';
      case 'windows':
        return 'Ctrl';
      case 'linux':
        return 'Ctrl';
      default:
        return 'Ctrl';
    }
  }, [os]);
};
 
// Check if the correct modifier key is pressed
export const isModifierPressed = (
  event: KeyboardEvent,
  os: string,
): boolean => {
  if (os === 'mac') {
    return event.metaKey && !event.ctrlKey && !event.altKey && !event.shiftKey;
  }
  return event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey;
};
 
// Hook for handling keyboard shortcuts
interface UseKeyboardShortcutsOptions {
  onShortcutAction: (key: string) => void;
  shortcuts: string[];
  enabled?: boolean;
}
 
export const useKeyboardShortcuts = ({
  onShortcutAction,
  shortcuts,
  enabled = true,
}: UseKeyboardShortcutsOptions) => {
  const os = useOperatingSystem();
 
  useEffect(() => {
    if (!enabled) return;
 
    const handleKeyDown = (event: KeyboardEvent) => {
      // Only handle shortcuts when modifier is pressed
      if (!isModifierPressed(event, os)) return;
 
      // Check if the pressed key matches any of our shortcuts
      const key = event.key.toLowerCase();
      if (shortcuts.includes(key)) {
        event.preventDefault();
        event.stopPropagation();
        onShortcutAction(key);
      }
    };
 
    document.addEventListener('keydown', handleKeyDown);
 
    return () => {
      document.removeEventListener('keydown', handleKeyDown);
    };
  }, [onShortcutAction, shortcuts, enabled, os]);
};