UNPKG

reakeys

Version:
118 lines (117 loc) 4.48 kB
import { useState, useLayoutEffect, useEffect } from "react"; import { keys } from "ctrl-keys"; function isMac() { try { return navigator.platform.toUpperCase().indexOf("MAC") >= 0; } catch { return false; } } function getModifierKey() { return isMac() ? "⌘" : "CTRL"; } const MODIFIER_KEY = getModifierKey(); function getHotkeyText(hotkey) { return hotkey.toLowerCase().replace("modifier", getModifierKey()).replace("mod", getModifierKey()).replace("shift", "⇧"); } let isGlobalListenersBinded = false; const keypressGlobalHandler = keys(); const keyupGlobalHandler = keys(); const keydownGlobalHandler = keys(); const handlers = /* @__PURE__ */ new Map(); let hotkeys = []; const extractKeys = (keys2) => { const normalizedKeys = Array.isArray(keys2) ? keys2.map((key) => key.toLowerCase()) : [keys2.toLowerCase()]; const modKey = isMac() ? "meta" : "ctrl"; return normalizedKeys.map((key) => key.replace("modifier", modKey).replace("mod", modKey)); }; const focusInputWrapper = (callback) => (event) => { const target = event.target; const isInput = target.tagName === "INPUT" && !["checkbox", "radio", "range", "button", "file", "reset", "submit", "color"].includes(target.type); if (target.isContentEditable || (isInput || target.tagName === "TEXTAREA" || target.tagName === "SELECT") && !target.readOnly) { return; } return callback(event); }; const registerGlobalShortcut = (shortcut) => { if (!shortcut.action || shortcut.action === "keypress") { keypressGlobalHandler.add(...extractKeys(shortcut.keys), shortcut.callback); } if (shortcut.action === "keyup") { keyupGlobalHandler.add(...extractKeys(shortcut.keys), shortcut.callback); } if (shortcut.action === "keydown") { keydownGlobalHandler.add(...extractKeys(shortcut.keys), shortcut.callback); } }; const removeGlobalShortcut = (shortcut) => { if (!shortcut.action || shortcut.action === "keypress") { keypressGlobalHandler.remove(...extractKeys(shortcut.keys), shortcut.callback); } if (shortcut.action === "keyup") { keyupGlobalHandler.remove(...extractKeys(shortcut.keys), shortcut.callback); } if (shortcut.action === "keydown") { keydownGlobalHandler.remove(...extractKeys(shortcut.keys), shortcut.callback); } }; const registerElementShortcut = (shortcut) => { var _a, _b, _c; const handler = keys(); handler.add(...extractKeys(shortcut.keys), shortcut.callback); (_b = (_a = shortcut.ref) == null ? void 0 : _a.current) == null ? void 0 : _b.addEventListener(shortcut.action ?? "keypress", handler.handle); handlers.set((_c = shortcut.ref) == null ? void 0 : _c.current, handler); }; const removeElementShortcut = (shortcut) => { var _a, _b, _c, _d; if (((_a = shortcut.ref) == null ? void 0 : _a.current) && !shortcut.disabled) { const handler = handlers.get((_b = shortcut.ref) == null ? void 0 : _b.current); handler == null ? void 0 : handler.remove(...extractKeys(shortcut.keys), shortcut.callback); (_d = (_c = shortcut.ref) == null ? void 0 : _c.current) == null ? void 0 : _d.removeEventListener(shortcut.action ?? "keypress", handler.handle); } }; const useHotkeys = (shortcuts = []) => { const [registered, setRegistered] = useState([]); useLayoutEffect(() => { if (!isGlobalListenersBinded && window !== void 0) { window.addEventListener("keypress", keypressGlobalHandler.handle); window.addEventListener("keyup", keyupGlobalHandler.handle); window.addEventListener("keydown", keydownGlobalHandler.handle); isGlobalListenersBinded = true; } }, []); useLayoutEffect(() => { shortcuts.map((shortcut) => { var _a; if (shortcut.disabled) { return; } shortcut.callback = focusInputWrapper(shortcut.callback); if ((_a = shortcut.ref) == null ? void 0 : _a.current) { registerElementShortcut(shortcut); hotkeys = [...hotkeys, shortcut]; } else if (!shortcut.ref) { registerGlobalShortcut(shortcut); hotkeys = [...hotkeys, shortcut]; } }); return () => { shortcuts.map((shortcut) => { removeElementShortcut(shortcut); removeGlobalShortcut(shortcut); hotkeys = hotkeys.filter((hotkey) => shortcut !== hotkey); }); }; }, [shortcuts]); useEffect(() => { setRegistered(hotkeys); }, []); return registered; }; export { MODIFIER_KEY, getHotkeyText, isMac, useHotkeys }; //# sourceMappingURL=index.js.map