From b8afafcfcaef64d6c4173e6b549dbac7e6018ee5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Thu, 6 May 2021 12:15:14 +0200 Subject: [PATCH] fix: do not wrap global handler in a div document.body can be used as a target instead. --- src/component/KbsProvider.tsx | 48 ++++++++++++++----------------- src/component/types.ts | 4 ++- src/component/utils/macInterop.ts | 2 +- src/component/utils/makeKey.ts | 4 ++- 4 files changed, 28 insertions(+), 30 deletions(-) diff --git a/src/component/KbsProvider.tsx b/src/component/KbsProvider.tsx index b1abc73..2e354e4 100644 --- a/src/component/KbsProvider.tsx +++ b/src/component/KbsProvider.tsx @@ -4,7 +4,7 @@ import { useContext, useReducer, Dispatch, - KeyboardEvent, + useEffect, } from 'react'; import { KbsDefinition } from './types'; @@ -76,40 +76,34 @@ function kbsReducer(state: KbsState, action: KbsAction): KbsState { } } -const divStyle = { - outline: 'none', -}; - export function KbsProvider(props: KbsProviderProps) { const [kbsState, kbsDispatch] = useReducer(kbsReducer, initialKbsState); - function handleKeyDown(event: KeyboardEvent) { - if (!(event.target as HTMLDivElement).hasAttribute('data-kbs-receiver')) { - return; - } - const key = eventToKey(event); - const shortcut = kbsState.combinedShortcuts[key]; - if (shortcut) { - event.stopPropagation(); - event.preventDefault(); - shortcut.handler(event); + useEffect(() => { + if (kbsState.disableCount !== 0) return; + function handleKeyDown(event: KeyboardEvent) { + if ( + event.target !== document.body && + !(event.target as HTMLDivElement).hasAttribute('data-kbs-receiver') + ) { + return; + } + const key = eventToKey(event); + const shortcut = kbsState.combinedShortcuts[key]; + if (shortcut) { + event.stopPropagation(); + event.preventDefault(); + shortcut.handler(event); + } } - } - - const divProps = - kbsState.disableCount === 0 - ? { - tabIndex: 0, - style: divStyle, - onKeyDown: handleKeyDown, - 'data-kbs-receiver': true, - } - : null; + document.body.addEventListener('keydown', handleKeyDown); + return () => document.body.removeEventListener('keydown', handleKeyDown); + }, [kbsState.disableCount, kbsState.combinedShortcuts]); return ( -
{props.children}
+ {props.children}
); diff --git a/src/component/types.ts b/src/component/types.ts index 2dc976f..4b48af7 100644 --- a/src/component/types.ts +++ b/src/component/types.ts @@ -9,6 +9,8 @@ export interface KbsKeyDefinition { export interface KbsDefinition { shortcut: string | KbsKeyDefinition | Array; - handler: (event: KeyboardEvent) => void; + handler: ( + event: KeyboardEvent | globalThis.KeyboardEvent, + ) => void; description?: string; } diff --git a/src/component/utils/macInterop.ts b/src/component/utils/macInterop.ts index ebc07cf..35f8eac 100644 --- a/src/component/utils/macInterop.ts +++ b/src/component/utils/macInterop.ts @@ -4,7 +4,7 @@ const isMac = typeof navigator !== 'undefined' && navigator.platform === 'MacIntel'; export function isMultiplatformCtrlKey( - event: MouseEvent | KeyboardEvent, + event: MouseEvent | KeyboardEvent | globalThis.KeyboardEvent, ): boolean { return isMac ? event.metaKey : event.ctrlKey; } diff --git a/src/component/utils/makeKey.ts b/src/component/utils/makeKey.ts index b1d0930..619761c 100644 --- a/src/component/utils/makeKey.ts +++ b/src/component/utils/makeKey.ts @@ -45,7 +45,9 @@ export function shortcutElementToKey(shortcut: string, modifiers: Modifiers) { } } -export function eventToKey(event: KeyboardEvent): string { +export function eventToKey( + event: KeyboardEvent | globalThis.KeyboardEvent, +): string { return `key[${event.key.toLowerCase()}]_ctrl[${boolToString( isMultiplatformCtrlKey(event), )}]_alt[${boolToString(event.altKey)}]_shift[${boolToString(