UNPKG

@mirawision/reactive-hooks

Version:

A comprehensive collection of 50+ React hooks for state management, UI interactions, device APIs, async operations, drag & drop, audio/speech, and more. Full TypeScript support with SSR safety.

66 lines (65 loc) 2.37 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useShortcuts = useShortcuts; const react_1 = require("react"); const use_event_listener_1 = require("./use-event-listener"); /** * Parses a shortcut combo string into its components. * Format: "Ctrl+Alt+Shift+Meta+K" or simpler "Ctrl+K" */ function parseShortcut(combo) { const parts = combo.toLowerCase().split('+'); const key = parts.pop() || ''; return { key: key.length === 1 ? key : key.charAt(0).toUpperCase() + key.slice(1), ctrl: parts.includes('ctrl'), alt: parts.includes('alt'), shift: parts.includes('shift'), meta: parts.includes('meta'), }; } /** * Checks if a keyboard event matches a parsed shortcut. */ function matchesShortcut(event, shortcut) { // Handle special cases for different keyboard layouts const eventKey = event.key.toLowerCase(); const shortcutKey = shortcut.key.toLowerCase(); const keyMatches = eventKey === shortcutKey || event.code.toLowerCase() === `key${shortcutKey}`; return (keyMatches && event.ctrlKey === shortcut.ctrl && event.altKey === shortcut.alt && event.shiftKey === shortcut.shift && event.metaKey === shortcut.meta); } /** * A hook that sets up keyboard shortcuts with modifier key support. * @param shortcuts Array of shortcuts with combo strings and handlers * @param opts Options for target element * * @example * useShortcuts([ * { combo: 'Ctrl+S', handler: (e) => save(e) }, * { combo: 'Ctrl+Shift+Z', handler: (e) => redo(e) } * ]); */ function useShortcuts(shortcuts, opts = {}) { // Parse shortcuts once const parsedShortcuts = shortcuts.map(s => ({ ...s, parsed: parseShortcut(s.combo), })); // Handle keyboard events const handleKeyDown = (0, react_1.useCallback)((event) => { // Find matching shortcut const matchingShortcut = parsedShortcuts.find(s => matchesShortcut(event, s.parsed)); if (matchingShortcut) { event.preventDefault(); matchingShortcut.handler(event); } }, [parsedShortcuts]); // Set up event listener const target = opts.target || (typeof window !== 'undefined' ? window : undefined); (0, use_event_listener_1.useEventListener)(target, 'keydown', handleKeyDown); }