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.

67 lines (64 loc) 2.5 kB
import { jsx, Fragment } from 'react/jsx-runtime'; import React from 'react'; import { useKeybindy } from './useKeybindy.js'; const KeybindyComponent = ({ scope = 'global', shortcuts = [], children, disabled, onShortcutFired, logs = false, }) => { const { register, unregister, manager, pushScope, popScope, getScopes, setScope } = useKeybindy({ onShortcutFired, logs, }); // Memoize a stable representation of shortcuts, excluding the handler. // This prevents the effect from re-running unnecessarily. const stableShortcuts = React.useMemo(() => { return shortcuts.map(({ keys, options }) => ({ keys, options })); }, [JSON.stringify(shortcuts.map(s => ({ keys: s.keys, options: s.options })))]); // Use a ref to store the latest handlers, preventing re-renders from causing issues. const handlersRef = React.useRef({}); React.useEffect(() => { handlersRef.current = shortcuts.reduce((acc, { keys, handler }) => { const key = JSON.stringify(keys); acc[key] = handler; return acc; }, {}); }); React.useEffect(() => { if (!manager) { return; } if (!getScopes()?.includes(scope)) { pushScope(scope); } setScope(scope); // Register shortcuts using the stable definitions. stableShortcuts.forEach(({ keys, options }) => { const stableHandler = (event, state) => { const key = JSON.stringify(keys); const currentHandler = handlersRef.current[key]; if (currentHandler) { currentHandler(event, state); } }; register(keys, stableHandler, { ...options, scope }); }); if (disabled) { manager.disableAll(scope); } else { manager.enableAll(scope); } return () => { // Unregister using the same stable definitions. stableShortcuts.forEach(({ keys }) => { if (Array.isArray(keys[0])) { keys.forEach(key => unregister(key, scope)); } else { unregister(keys, scope); } }); popScope(); }; }, [scope, manager, disabled, stableShortcuts]); return jsx(Fragment, { children: children }); }; const Keybindy = React.memo(KeybindyComponent); export { Keybindy };