The keyboard event to check.
The shortcut definition to match against.
True if event matches the shortcut; false otherwise.
export function matchesShortcut(
event: KeyboardEvent,
shortcut: Shortcut,
): boolean {
const checkKey = (keyDef: ShortcutKey): boolean => {
// Normalize the keys for comparison (case-insensitive for letters)
const eventKeyLower = event.key.toLowerCase();
const defKeyLower = keyDef.key.toLowerCase();
// Check key match - handle special characters and letters
if (eventKeyLower !== defKeyLower) {
return false;
}
// Compute expected modifier set from the definition
const expectedCtrl = keyDef.ctrl === true;
const expectedMeta = keyDef.meta === true;
const expectedShift = keyDef.shift === true;
const expectedAlt = keyDef.alt === true;
// On Mac, Cmd is treated equivalently to Ctrl
const hasCtrl = event.ctrlKey;
const hasMeta = event.metaKey;
const expectedCtrlOrMeta = expectedCtrl || expectedMeta;
const hasCtrlOrMeta = hasCtrl || hasMeta;
// Require Ctrl/Cmd only if specified
if (expectedCtrlOrMeta && !hasCtrlOrMeta) {
return false;
}
// Forbid Ctrl/Cmd if not specified
if (!expectedCtrlOrMeta && hasCtrlOrMeta) {
return false;
}
// Require Shift only if specified
if (expectedShift && !event.shiftKey) {
return false;
}
// Exception: allow Shift for symbol keys that may require it on some layouts
// (e.g., '?' is Shift+/ on US layouts)
const isSymbolKey = /[!@#$%^&*()_+=[\]{};:'",.<>?/\\|`~-]/.test(keyDef.key);
if (!expectedShift && event.shiftKey && !isSymbolKey) {
return false;
}
// Require Alt only if specified
if (expectedAlt && !event.altKey) {
return false;
}
// Forbid Alt if not specified
if (!expectedAlt && event.altKey) {
return false;
}
return true;
};
// Check primary key combination
if (checkKey(shortcut.keys)) {
return true;
}
// Check alternative key combinations
if (shortcut.altKeys) {
for (const altKey of shortcut.altKeys) {
if (checkKey(altKey)) {
return true;
}
}
}
return false;
}
Checks if keyboard event matches shortcut definition; supports primary and alternative key combinations. Enforces exact modifier matching (only specified modifiers required; unspecified forbidden except for symbol Shift).