diff --git a/src/parseHotkeys.ts b/src/parseHotkeys.ts index b7e20c8f..5edf80bb 100644 --- a/src/parseHotkeys.ts +++ b/src/parseHotkeys.ts @@ -2,6 +2,15 @@ import { Hotkey, KeyboardModifiers, Keys } from './types' const reservedModifierKeywords = ['ctrl', 'shift', 'alt', 'meta', 'mod'] +const mappedKeys: Record = { + esc: 'escape', + return: 'enter', + left: 'arrowleft', + up: 'arrowup', + right: 'arrowright', + down: 'arrowdown', +} + export function parseKeysHookInput(keys: Keys, splitKey: string = ','): string[] { if (typeof keys === 'string') { return keys.split(splitKey) @@ -15,8 +24,7 @@ export function parseHotkey(hotkey: string, combinationKey: string = '+'): Hotke .toLocaleLowerCase() .split(combinationKey) .map(k => k.trim()) - .map(k => k === 'esc' ? 'escape' : k) - .map(k => k === 'return' ? 'enter' : k) + .map(k => mappedKeys[k] || k) const modifiers: KeyboardModifiers = { alt: keys.includes('alt'), diff --git a/tests/useHotkeys.test.tsx b/tests/useHotkeys.test.tsx index 413c1e50..bd52066a 100644 --- a/tests/useHotkeys.test.tsx +++ b/tests/useHotkeys.test.tsx @@ -7,8 +7,8 @@ import { createEvent, fireEvent, render, screen } from '@testing-library/react' const wrapper = (initialScopes: string[]): WrapperComponent => - ({ children }: { children?: ReactNode }) => - {children} + ({ children }: { children?: ReactNode }) => + {children} type HookParameters = { keys: Keys @@ -48,7 +48,7 @@ test('should log a warning when trying to set a scope without a wrapped provider renderHook(() => useHotkeys('a', callback, { scopes: 'foo' })) expect(console.warn).toHaveBeenCalledWith( - 'A hotkey has the "scopes" option set, however no active scopes were found. If you want to use the global scopes feature, you need to wrap your app in a ' + 'A hotkey has the "scopes" option set, however no active scopes were found. If you want to use the global scopes feature, you need to wrap your app in a ', ) expect(callback).not.toHaveBeenCalled() }) @@ -327,7 +327,7 @@ test('should reflect set splitKey character', async () => { ({ keys, options }) => useHotkeys(keys, callback, options), { initialProps: { keys: 'a, b', options: undefined }, - } + }, ) await user.keyboard('A') @@ -720,7 +720,8 @@ test('should allow named keys like arrow keys, space, enter, backspace, etc.', a expect(callback).toHaveBeenCalledTimes(7) }) -test.skip('should trigger when used in portals', async () => {}) +test.skip('should trigger when used in portals', async () => { +}) test('should parse options and dependencies correctly no matter their position', async () => { const user = userEvent.setup() @@ -965,7 +966,8 @@ test('should call preventDefault option function with hotkey and keyboard event' const user = userEvent.setup() const preventDefault = jest.fn() - renderHook(() => useHotkeys('a', async () => {}, { preventDefault })) + renderHook(() => useHotkeys('a', async () => { + }, { preventDefault })) await user.keyboard('A') @@ -990,3 +992,21 @@ test('Should listen to space key', async () => { expect(callback).toHaveBeenCalledTimes(1) }) + +test.each([ + ['esc', 'Escape'], + ['return', 'Enter'], + ['left', 'ArrowLeft'], + ['up', 'ArrowUp'], + ['right', 'ArrowRight'], + ['down', 'ArrowDown'] +])('Should map key %s to %s', async (hotkey, keyboardKey) => { + const user = userEvent.setup() + const callback = jest.fn() + + renderHook(() => useHotkeys(hotkey, callback)) + + await user.keyboard(`{${keyboardKey}}`) + + expect(callback).toHaveBeenCalledTimes(1) +})