UNPKG

@keybindy/react

Version:

Keybindy for React: Simple, scoped keyboard shortcuts that require little setup. designed to smoothly blend in with your React applications, allowing for robust keybinding functionality without the overhead.

75 lines (72 loc) 3.11 kB
import { jsx, Fragment } from 'react/jsx-runtime'; import React from 'react'; import { useKeybindy } from './useKeybindy.js'; /** * `<Keybindy />` is a React component that registers keyboard shortcuts within a given scope. It allows * users to define custom shortcuts and their associated handlers, while managing scope-based shortcut behavior. * The component listens for keyboard events and triggers the registered handler when the corresponding keys are pressed. * It also provides an optional callback (`onShortcutFired`) to notify users when a shortcut is triggered. * * @component * * @example * // Basic usage * <Keybindy scope="global" shortcuts={[{ keys: ['ctrl', 's'], handler: saveDocument }]} > * <div>Content with shortcuts</div> * </Keybindy> * * @example * // With custom callback for onShortcutFired * <Keybindy * scope="editor" * shortcuts={[{ keys: ['ctrl', 'e'], handler: editDocument }]} * onShortcutFired={(info) => console.log('Shortcut fired:', info)} * > * <div>Editor with shortcuts</div> * </Keybindy> * * @param {ShortcutProps} props - Props for the Shortcut component. * @param {string} props.scope - The scope under which the shortcuts should be active. * @param {ShortcutDefinition[]} [props.shortcuts] - An array of shortcut definitions, each containing keys, handler, and options. * @param {boolean} [props.disabled=false] - Whether the shortcuts should be disabled for this scope. * @param {(info: Shortcut) => void} [props.onShortcutFired] - Optional callback triggered when a shortcut is fired, providing the shortcut info. * @param {React.ReactNode} props.children - The children to be rendered inside the component, which can contain any JSX elements. * * @returns {JSX.Element} The rendered component with registered shortcuts within the provided scope. */ const Keybindy = ({ scope, shortcuts = [], children, disabled, onShortcutFired, logs = false, }) => { const { register, unregister, manager, pushScope, popScope, getScopes, setScope } = useKeybindy({ onShortcutFired, logs, }); const prevScope = React.useRef(null); React.useEffect(() => { prevScope.current = manager.getActiveScope(); // Add scope if doesn't exist if (!getScopes()?.includes(scope)) { pushScope(scope); } // Set this scope as active setScope(scope); // Register all shortcuts for this scope shortcuts.forEach(({ keys, handler, options }) => { register(keys, handler, { ...options, scope }); }); if (disabled) { manager.disableAll(scope); } return () => { shortcuts.forEach(({ keys }) => { if (Array.isArray(keys[0])) { keys.forEach(key => unregister(key, scope)); } else { unregister(keys, scope); } }); popScope(); }; }, [scope, JSON.stringify(shortcuts)]); return jsx(Fragment, { children: children }); }; export { Keybindy };