UNPKG

@acusti/use-keyboard-events

Version:

React hook that takes keyboard event handlers and attaches them to the document

88 lines (78 loc) 2.69 kB
import { useEffect } from 'react'; import { addHandler, addHandlers, type Handler } from './handlers.js'; export { isEventTargetUsingKeyEvent, isPrimaryModifierPressed, usesKeyEvents, } from './handlers.js'; type Props = { ignoreUsedKeyboardEvents?: boolean; onKeyDown?: Handler; onKeyPress?: Handler; onKeyUp?: Handler; /** * Priority defines what order handlers should be invoked and defaults to 0. * It can be any number between -50 (lowest priority) and 50 (highest priority). */ priority?: number; }; export default function useKeyboardEvents({ ignoreUsedKeyboardEvents, onKeyDown, onKeyPress, onKeyUp, priority, }: Props) { useEffect(() => { addHandlers(document); document.querySelectorAll('iframe').forEach((iframe: HTMLIFrameElement) => { if (!isSameOriginFrame(iframe) || !iframe.contentDocument) return; addHandlers(iframe.contentDocument); }); }, []); useEffect( () => addHandler({ eventType: 'keydown', handler: onKeyDown, ignoreUsedKeyboardEvents, priority, }), [ignoreUsedKeyboardEvents, onKeyDown, priority], ); useEffect( () => addHandler({ eventType: 'keypress', handler: onKeyPress, ignoreUsedKeyboardEvents, priority, }), [ignoreUsedKeyboardEvents, onKeyPress, priority], ); useEffect( () => addHandler({ eventType: 'keyup', handler: onKeyUp, ignoreUsedKeyboardEvents, priority, }), [ignoreUsedKeyboardEvents, onKeyUp, priority], ); } // https://github.com/facebook/react/blob/main/packages/react-dom-bindings/src/client/ReactInputSelection.js function isSameOriginFrame(iframe: HTMLIFrameElement) { try { // Accessing the contentDocument of an HTMLIframeElement can cause the // browser to throw, e.g. if it has a cross-origin src attribute. // Safari will show a “Blocked a frame with origin…” error in the // console on e.g. iframe.contentDocument.defaultView if cross-origin. // To avoid this, try a cross-origin property, like location, which can // throw a “SecurityError” DOM Exception that’s compatible with Safari. // https://html.spec.whatwg.org/multipage/browsers.html#integration-with-idl return typeof iframe.contentWindow!.location.href === 'string'; } catch (err) { return false; } }