|
| 1 | +/** |
| 2 | + * Keyboard utility functions for handling keyboard events |
| 3 | + */ |
| 4 | + |
| 5 | +/** |
| 6 | + * Extract a consistent key name from a KeyboardEvent |
| 7 | + * This function replaces the keycode library and provides better support |
| 8 | + * for extended function keys (F14+) and cross-platform compatibility |
| 9 | + */ |
| 10 | +export const getKeyName = (e: KeyboardEvent): string => { |
| 11 | + // Handle special cases first |
| 12 | + if (e.code) { |
| 13 | + const code = e.code; |
| 14 | + |
| 15 | + // Handle function keys (F1-F24) |
| 16 | + if (code.match(/^F\d+$/)) { |
| 17 | + return code.toLowerCase(); // F1, F2, ..., F14, F15, etc. |
| 18 | + } |
| 19 | + |
| 20 | + // Handle regular letter keys (KeyA -> a) |
| 21 | + if (code.match(/^Key[A-Z]$/)) { |
| 22 | + return code.replace("Key", "").toLowerCase(); |
| 23 | + } |
| 24 | + |
| 25 | + // Handle digit keys (Digit0 -> 0) |
| 26 | + if (code.match(/^Digit\d$/)) { |
| 27 | + return code.replace("Digit", ""); |
| 28 | + } |
| 29 | + |
| 30 | + // Handle numpad digit keys (Numpad0 -> numpad 0) |
| 31 | + if (code.match(/^Numpad\d$/)) { |
| 32 | + return code.replace("Numpad", "numpad ").toLowerCase(); |
| 33 | + } |
| 34 | + |
| 35 | + // Handle modifier keys - normalize left/right variants |
| 36 | + const modifierMap: Record<string, string> = { |
| 37 | + ShiftLeft: "shift", |
| 38 | + ShiftRight: "shift", |
| 39 | + ControlLeft: "ctrl", |
| 40 | + ControlRight: "ctrl", |
| 41 | + AltLeft: "alt", |
| 42 | + AltRight: "alt", |
| 43 | + MetaLeft: "command", |
| 44 | + MetaRight: "command", |
| 45 | + OSLeft: "command", |
| 46 | + OSRight: "command", |
| 47 | + CapsLock: "caps lock", |
| 48 | + Tab: "tab", |
| 49 | + Enter: "enter", |
| 50 | + Space: "space", |
| 51 | + Backspace: "backspace", |
| 52 | + Delete: "delete", |
| 53 | + Escape: "esc", |
| 54 | + ArrowUp: "up", |
| 55 | + ArrowDown: "down", |
| 56 | + ArrowLeft: "left", |
| 57 | + ArrowRight: "right", |
| 58 | + Home: "home", |
| 59 | + End: "end", |
| 60 | + PageUp: "page up", |
| 61 | + PageDown: "page down", |
| 62 | + Insert: "insert", |
| 63 | + PrintScreen: "print screen", |
| 64 | + ScrollLock: "scroll lock", |
| 65 | + Pause: "pause", |
| 66 | + ContextMenu: "menu", |
| 67 | + NumpadMultiply: "numpad *", |
| 68 | + NumpadAdd: "numpad +", |
| 69 | + NumpadSubtract: "numpad -", |
| 70 | + NumpadDecimal: "numpad .", |
| 71 | + NumpadDivide: "numpad /", |
| 72 | + NumLock: "num lock", |
| 73 | + }; |
| 74 | + |
| 75 | + if (modifierMap[code]) { |
| 76 | + return modifierMap[code]; |
| 77 | + } |
| 78 | + |
| 79 | + // Handle punctuation and special characters |
| 80 | + const punctuationMap: Record<string, string> = { |
| 81 | + Semicolon: ";", |
| 82 | + Equal: "=", |
| 83 | + Comma: ",", |
| 84 | + Minus: "-", |
| 85 | + Period: ".", |
| 86 | + Slash: "/", |
| 87 | + Backquote: "`", |
| 88 | + BracketLeft: "[", |
| 89 | + Backslash: "\\", |
| 90 | + BracketRight: "]", |
| 91 | + Quote: "'", |
| 92 | + }; |
| 93 | + |
| 94 | + if (punctuationMap[code]) { |
| 95 | + return punctuationMap[code]; |
| 96 | + } |
| 97 | + |
| 98 | + // For any other codes, try to convert to a reasonable format |
| 99 | + return code.toLowerCase().replace(/([a-z])([A-Z])/g, "$1 $2"); |
| 100 | + } |
| 101 | + |
| 102 | + // Fallback to e.key if e.code is not available |
| 103 | + if (e.key) { |
| 104 | + const key = e.key; |
| 105 | + |
| 106 | + // Handle special key names |
| 107 | + const keyMap: Record<string, string> = { |
| 108 | + Control: "ctrl", |
| 109 | + Alt: "alt", |
| 110 | + Shift: "shift", |
| 111 | + Meta: "command", |
| 112 | + OS: "command", |
| 113 | + CapsLock: "caps lock", |
| 114 | + ArrowUp: "up", |
| 115 | + ArrowDown: "down", |
| 116 | + ArrowLeft: "left", |
| 117 | + ArrowRight: "right", |
| 118 | + Escape: "esc", |
| 119 | + " ": "space", |
| 120 | + }; |
| 121 | + |
| 122 | + if (keyMap[key]) { |
| 123 | + return keyMap[key]; |
| 124 | + } |
| 125 | + |
| 126 | + return key.toLowerCase(); |
| 127 | + } |
| 128 | + |
| 129 | + // Last resort fallback |
| 130 | + return `unknown-${e.keyCode || e.which || 0}`; |
| 131 | +}; |
0 commit comments