react-hotkeys-hook 4.1.0-0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,56 +15,32 @@ function _extends() {
15
15
  };
16
16
  return _extends.apply(this, arguments);
17
17
  }
18
- function _unsupportedIterableToArray(o, minLen) {
19
- if (!o) return;
20
- if (typeof o === "string") return _arrayLikeToArray(o, minLen);
21
- var n = Object.prototype.toString.call(o).slice(8, -1);
22
- if (n === "Object" && o.constructor) n = o.constructor.name;
23
- if (n === "Map" || n === "Set") return Array.from(o);
24
- if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
25
- }
26
- function _arrayLikeToArray(arr, len) {
27
- if (len == null || len > arr.length) len = arr.length;
28
- for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
29
- return arr2;
30
- }
31
- function _createForOfIteratorHelperLoose(o, allowArrayLike) {
32
- var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
33
- if (it) return (it = it.call(o)).next.bind(it);
34
- if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
35
- if (it) o = it;
36
- var i = 0;
37
- return function () {
38
- if (i >= o.length) return {
39
- done: true
40
- };
41
- return {
42
- done: false,
43
- value: o[i++]
44
- };
45
- };
46
- }
47
- throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
48
- }
49
18
 
50
19
  var reservedModifierKeywords = ['shift', 'alt', 'meta', 'mod'];
51
20
  var mappedKeys = {
52
21
  esc: 'escape',
53
22
  "return": 'enter',
54
- left: 'arrowleft',
55
- up: 'arrowup',
56
- right: 'arrowright',
57
- down: 'arrowdown',
58
- '1': 'digit1',
59
- '2': 'digit2',
60
- '3': 'digit3',
61
- '4': 'digit4',
62
- '5': 'digit5',
63
- '6': 'digit6',
64
- '7': 'digit7',
65
- '8': 'digit8',
66
- '9': 'digit9'
23
+ '.': 'period',
24
+ ',': 'comma',
25
+ '-': 'slash',
26
+ ' ': 'space',
27
+ '#': 'backslash',
28
+ '+': 'bracketright',
29
+ 'ShiftLeft': 'shift',
30
+ 'ShiftRight': 'shift',
31
+ 'AltLeft': 'alt',
32
+ 'AltRight': 'alt',
33
+ 'MetaLeft': 'meta',
34
+ 'MetaRight': 'meta',
35
+ 'ControlLeft': 'ctrl',
36
+ 'ControlRight': 'ctrl'
67
37
  };
38
+ function mapKey(key) {
39
+ return (mappedKeys[key] || key).trim().toLowerCase().replace('key', '').replace('digit', '').replace('numpad', '').replace('arrow', '');
40
+ }
41
+ function isHotkeyModifier(key) {
42
+ return reservedModifierKeywords.includes(key);
43
+ }
68
44
  function parseKeysHookInput(keys, splitKey) {
69
45
  if (splitKey === void 0) {
70
46
  splitKey = ',';
@@ -79,9 +55,7 @@ function parseHotkey(hotkey, combinationKey) {
79
55
  combinationKey = '+';
80
56
  }
81
57
  var keys = hotkey.toLocaleLowerCase().split(combinationKey).map(function (k) {
82
- return k.trim();
83
- }).map(function (k) {
84
- return mappedKeys[k] || k;
58
+ return mapKey(k);
85
59
  });
86
60
  var modifiers = {
87
61
  alt: keys.includes('alt'),
@@ -97,15 +71,6 @@ function parseHotkey(hotkey, combinationKey) {
97
71
  });
98
72
  }
99
73
 
100
- function deepEqual(x, y) {
101
- //@ts-ignore
102
- return x && y && typeof x === 'object' && typeof y === 'object'
103
- //@ts-ignore
104
- ? Object.keys(x).length === Object.keys(y).length && Object.keys(x).reduce(function (isEqual, key) {
105
- return isEqual && deepEqual(x[key], y[key]);
106
- }, true) : x === y;
107
- }
108
-
109
74
  var currentlyPressedKeys = /*#__PURE__*/new Set();
110
75
  function isHotkeyPressed(key, splitKey) {
111
76
  if (splitKey === void 0) {
@@ -113,52 +78,52 @@ function isHotkeyPressed(key, splitKey) {
113
78
  }
114
79
  var hotkeyArray = Array.isArray(key) ? key : key.split(splitKey);
115
80
  return hotkeyArray.every(function (hotkey) {
116
- var parsedHotkey = parseHotkey(hotkey);
117
- for (var _iterator = _createForOfIteratorHelperLoose(currentlyPressedKeys), _step; !(_step = _iterator()).done;) {
118
- var pressedHotkey = _step.value;
119
- if (deepEqual(parsedHotkey, pressedHotkey)) {
120
- return true;
121
- }
122
- }
81
+ return currentlyPressedKeys.has(hotkey.trim().toLowerCase());
123
82
  });
124
83
  }
125
84
  function pushToCurrentlyPressedKeys(key) {
126
85
  var hotkeyArray = Array.isArray(key) ? key : [key];
86
+ /*
87
+ Due to a weird behavior on macOS we need to clear the set if the user pressed down the meta key and presses another key.
88
+ https://stackoverflow.com/questions/11818637/why-does-javascript-drop-keyup-events-when-the-metakey-is-pressed-on-mac-browser
89
+ Otherwise the set will hold all ever pressed keys while the meta key is down which leads to wrong results.
90
+ */
91
+ if (currentlyPressedKeys.has('meta')) {
92
+ currentlyPressedKeys.forEach(function (key) {
93
+ return !isHotkeyModifier(key) && currentlyPressedKeys["delete"](key);
94
+ });
95
+ }
127
96
  hotkeyArray.forEach(function (hotkey) {
128
- return currentlyPressedKeys.add(parseHotkey(hotkey));
97
+ return currentlyPressedKeys.add(hotkey.toLowerCase());
129
98
  });
130
99
  }
131
100
  function removeFromCurrentlyPressedKeys(key) {
132
- var hotkeyArray = Array.isArray(key) ? key : [key];
133
- hotkeyArray.forEach(function (hotkey) {
134
- var parsedHotkey = parseHotkey(hotkey);
135
- for (var _iterator2 = _createForOfIteratorHelperLoose(currentlyPressedKeys), _step2; !(_step2 = _iterator2()).done;) {
136
- var pressedHotkey = _step2.value;
137
- if (deepEqual(parsedHotkey, pressedHotkey)) {
138
- currentlyPressedKeys["delete"](pressedHotkey);
139
- }
140
- }
141
- });
101
+ /*
102
+ Due to a weird behavior on macOS we need to clear the set if the user pressed down the meta key and presses another key.
103
+ https://stackoverflow.com/questions/11818637/why-does-javascript-drop-keyup-events-when-the-metakey-is-pressed-on-mac-browser
104
+ Otherwise the set will hold all ever pressed keys while the meta key is down which leads to wrong results.
105
+ */
106
+ if (key === 'meta') {
107
+ currentlyPressedKeys.clear();
108
+ } else {
109
+ currentlyPressedKeys["delete"](key);
110
+ }
142
111
  }
143
112
  (function () {
144
- if (typeof window !== 'undefined') {
145
- window.addEventListener('DOMContentLoaded', function () {
146
- document.addEventListener('keydown', function (e) {
147
- if (e.key === undefined) {
148
- // Synthetic event (e.g., Chrome autofill). Ignore.
149
- return;
150
- }
151
- pushToCurrentlyPressedKeys(e.key);
152
- });
153
- document.addEventListener('keyup', function (e) {
154
- if (e.key === undefined) {
155
- // Synthetic event (e.g., Chrome autofill). Ignore.
156
- return;
157
- }
158
- removeFromCurrentlyPressedKeys(e.key);
159
- });
160
- });
161
- }
113
+ document.addEventListener('keydown', function (e) {
114
+ if (e.key === undefined) {
115
+ // Synthetic event (e.g., Chrome autofill). Ignore.
116
+ return;
117
+ }
118
+ pushToCurrentlyPressedKeys(mapKey(e.code));
119
+ });
120
+ document.addEventListener('keyup', function (e) {
121
+ if (e.key === undefined) {
122
+ // Synthetic event (e.g., Chrome autofill). Ignore.
123
+ return;
124
+ }
125
+ removeFromCurrentlyPressedKeys(mapKey(e.code));
126
+ });
162
127
  })();
163
128
 
164
129
  function maybePreventDefault(e, hotkey, preventDefault) {
@@ -200,7 +165,7 @@ function isScopeActive(activeScopes, scopes) {
200
165
  return scopes.includes(scope);
201
166
  }) || activeScopes.includes('*');
202
167
  }
203
- var isHotkeyMatchingKeyboardEvent = function isHotkeyMatchingKeyboardEvent(e, hotkey, pressedDownKeys) {
168
+ var isHotkeyMatchingKeyboardEvent = function isHotkeyMatchingKeyboardEvent(e, hotkey) {
204
169
  var alt = hotkey.alt,
205
170
  meta = hotkey.meta,
206
171
  mod = hotkey.mod,
@@ -212,7 +177,7 @@ var isHotkeyMatchingKeyboardEvent = function isHotkeyMatchingKeyboardEvent(e, ho
212
177
  var shiftKey = isHotkeyPressed('shift');
213
178
  var metaKey = isHotkeyPressed('meta');
214
179
  var ctrlKey = isHotkeyPressed('ctrl');
215
- var keyCode = code.toLowerCase().replace('key', '');
180
+ var keyCode = mapKey(code);
216
181
  var pressedKey = pressedKeyUppercase.toLowerCase();
217
182
  if (altKey !== alt && pressedKey !== 'alt') {
218
183
  return false;
@@ -236,9 +201,7 @@ var isHotkeyMatchingKeyboardEvent = function isHotkeyMatchingKeyboardEvent(e, ho
236
201
  return true;
237
202
  } else if (keys) {
238
203
  // Check if all keys are present in pressedDownKeys set
239
- return keys.every(function (key) {
240
- return pressedDownKeys.has(key);
241
- });
204
+ return isHotkeyPressed(keys);
242
205
  } else if (!keys) {
243
206
  // If the key is not set, we only listen for modifiers, that check went alright, so we return true
244
207
  return true;
@@ -264,6 +227,15 @@ function BoundHotkeysProxyProviderProvider(_ref) {
264
227
  });
265
228
  }
266
229
 
230
+ function deepEqual(x, y) {
231
+ //@ts-ignore
232
+ return x && y && typeof x === 'object' && typeof y === 'object'
233
+ //@ts-ignore
234
+ ? Object.keys(x).length === Object.keys(y).length && Object.keys(x).reduce(function (isEqual, key) {
235
+ return isEqual && deepEqual(x[key], y[key]);
236
+ }, true) : x === y;
237
+ }
238
+
267
239
  var HotkeysContext = /*#__PURE__*/createContext({
268
240
  hotkeys: [],
269
241
  enabledScopes: [],
@@ -367,9 +339,9 @@ var stopPropagation = function stopPropagation(e) {
367
339
  e.stopImmediatePropagation();
368
340
  };
369
341
  var useSafeLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;
370
- var pressedDownKeys = /*#__PURE__*/new Set();
371
342
  function useHotkeys(keys, callback, options, dependencies) {
372
343
  var ref = useRef(null);
344
+ var hasTriggeredRef = useRef(false);
373
345
  var _options = !(options instanceof Array) ? options : !(dependencies instanceof Array) ? dependencies : undefined;
374
346
  var _deps = options instanceof Array ? options : dependencies instanceof Array ? dependencies : [];
375
347
  var cb = useCallback(callback, [].concat(_deps));
@@ -398,12 +370,14 @@ function useHotkeys(keys, callback, options, dependencies) {
398
370
  parseKeysHookInput(keys, memoisedOptions == null ? void 0 : memoisedOptions.splitKey).forEach(function (key) {
399
371
  var _hotkey$keys;
400
372
  var hotkey = parseHotkey(key, memoisedOptions == null ? void 0 : memoisedOptions.combinationKey);
401
- if (isHotkeyMatchingKeyboardEvent(e, hotkey, pressedDownKeys) || (_hotkey$keys = hotkey.keys) != null && _hotkey$keys.includes('*')) {
373
+ if ((isHotkeyMatchingKeyboardEvent(e, hotkey) || (_hotkey$keys = hotkey.keys) != null && _hotkey$keys.includes('*')) && !hasTriggeredRef.current) {
374
+ hasTriggeredRef.current = true;
402
375
  maybePreventDefault(e, hotkey, memoisedOptions == null ? void 0 : memoisedOptions.preventDefault);
403
376
  if (!isHotkeyEnabled(e, hotkey, memoisedOptions == null ? void 0 : memoisedOptions.enabled)) {
404
377
  stopPropagation(e);
405
378
  return;
406
379
  }
380
+ // Execute the user callback for that hotkey
407
381
  cb(e, hotkey);
408
382
  }
409
383
  });
@@ -413,7 +387,6 @@ function useHotkeys(keys, callback, options, dependencies) {
413
387
  // Synthetic event (e.g., Chrome autofill). Ignore.
414
388
  return;
415
389
  }
416
- pressedDownKeys.add(event.key.toLowerCase());
417
390
  if ((memoisedOptions == null ? void 0 : memoisedOptions.keydown) === undefined && (memoisedOptions == null ? void 0 : memoisedOptions.keyup) !== true || memoisedOptions != null && memoisedOptions.keydown) {
418
391
  listener(event);
419
392
  }
@@ -423,12 +396,7 @@ function useHotkeys(keys, callback, options, dependencies) {
423
396
  // Synthetic event (e.g., Chrome autofill). Ignore.
424
397
  return;
425
398
  }
426
- if (event.key.toLowerCase() !== 'meta') {
427
- pressedDownKeys["delete"](event.key.toLowerCase());
428
- } else {
429
- // On macOS pressing down the meta key prevents triggering the keyup event for any other key https://stackoverflow.com/a/57153300/735226.
430
- pressedDownKeys.clear();
431
- }
399
+ hasTriggeredRef.current = false;
432
400
  if (memoisedOptions != null && memoisedOptions.keyup) {
433
401
  listener(event);
434
402
  }
@@ -1 +1 @@
1
- {"version":3,"file":"react-hotkeys-hook.esm.js","sources":["../src/parseHotkeys.ts","../src/deepEqual.ts","../src/isHotkeyPressed.ts","../src/validators.ts","../src/BoundHotkeysProxyProvider.tsx","../src/HotkeysProvider.tsx","../src/useDeepEqualMemo.ts","../src/useHotkeys.ts"],"sourcesContent":["import { Hotkey, KeyboardModifiers, Keys } from './types'\n\nconst reservedModifierKeywords = ['shift', 'alt', 'meta', 'mod']\n\nconst mappedKeys: Record<string, string> = {\n esc: 'escape',\n return: 'enter',\n left: 'arrowleft',\n up: 'arrowup',\n right: 'arrowright',\n down: 'arrowdown',\n '1': 'digit1',\n '2': 'digit2',\n '3': 'digit3',\n '4': 'digit4',\n '5': 'digit5',\n '6': 'digit6',\n '7': 'digit7',\n '8': 'digit8',\n '9': 'digit9',\n}\n\nexport function parseKeysHookInput(keys: Keys, splitKey: string = ','): string[] {\n if (typeof keys === 'string') {\n return keys.split(splitKey)\n }\n\n return keys\n}\n\nexport function parseHotkey(hotkey: string, combinationKey: string = '+'): Hotkey {\n const keys = hotkey\n .toLocaleLowerCase()\n .split(combinationKey)\n .map(k => k.trim())\n .map(k => mappedKeys[k] || k)\n\n const modifiers: KeyboardModifiers = {\n alt: keys.includes('alt'),\n shift: keys.includes('shift'),\n meta: keys.includes('meta'),\n mod: keys.includes('mod'),\n }\n\n const singleCharKeys = keys.filter((k) => !reservedModifierKeywords.includes(k))\n\n return {\n ...modifiers,\n keys: singleCharKeys,\n }\n}\n","export default function deepEqual(x: any, y: any): boolean {\n //@ts-ignore\n return (x && y && typeof x === 'object' && typeof y === 'object')\n //@ts-ignore\n ? (Object.keys(x).length === Object.keys(y).length) && Object.keys(x).reduce(function(isEqual, key) {\n return isEqual && deepEqual(x[key], y[key])\n }, true)\n : (x === y)\n}\n","import { Hotkey } from './types'\nimport { parseHotkey } from './parseHotkeys'\nimport deepEqual from './deepEqual'\n\nconst currentlyPressedKeys: Set<Hotkey> = new Set<Hotkey>()\n\nexport function isHotkeyPressed(key: string | string[], splitKey: string = ','): boolean {\n const hotkeyArray = Array.isArray(key) ? key : key.split(splitKey)\n\n return hotkeyArray.every((hotkey) => {\n const parsedHotkey = parseHotkey(hotkey)\n\n for (const pressedHotkey of currentlyPressedKeys) {\n if (deepEqual(parsedHotkey, pressedHotkey)) {\n return true\n }\n }\n })\n}\n\nfunction pushToCurrentlyPressedKeys(key: string | string[]): void {\n const hotkeyArray = Array.isArray(key) ? key : [key]\n\n hotkeyArray.forEach(hotkey => currentlyPressedKeys.add(parseHotkey(hotkey)))\n}\n\nfunction removeFromCurrentlyPressedKeys(key: string | string[]): void {\n const hotkeyArray = Array.isArray(key) ? key : [key]\n\n hotkeyArray.forEach((hotkey) => {\n const parsedHotkey = parseHotkey(hotkey)\n\n for (const pressedHotkey of currentlyPressedKeys) {\n if (deepEqual(parsedHotkey, pressedHotkey)) {\n currentlyPressedKeys.delete(pressedHotkey)\n }\n }\n })\n}\n\n(() => {\n if (typeof window !== 'undefined') {\n window.addEventListener('DOMContentLoaded', () => {\n document.addEventListener('keydown', e => {\n if (e.key === undefined) {\n // Synthetic event (e.g., Chrome autofill). Ignore.\n return\n }\n\n pushToCurrentlyPressedKeys(e.key)\n })\n\n document.addEventListener('keyup', e => {\n if (e.key === undefined) {\n // Synthetic event (e.g., Chrome autofill). Ignore.\n return\n }\n\n removeFromCurrentlyPressedKeys(e.key)\n })\n })\n }\n})()\n","import { FormTags, Hotkey, Scopes, Trigger } from './types'\nimport { isHotkeyPressed } from './isHotkeyPressed'\n\nexport function maybePreventDefault(e: KeyboardEvent, hotkey: Hotkey, preventDefault?: Trigger): void {\n if ((typeof preventDefault === 'function' && preventDefault(e, hotkey)) || preventDefault === true) {\n e.preventDefault()\n }\n}\n\nexport function isHotkeyEnabled(e: KeyboardEvent, hotkey: Hotkey, enabled?: Trigger): boolean {\n if (typeof enabled === 'function') {\n return enabled(e, hotkey)\n }\n\n return enabled === true || enabled === undefined\n}\n\nexport function isKeyboardEventTriggeredByInput(ev: KeyboardEvent): boolean {\n return isHotkeyEnabledOnTag(ev, ['input', 'textarea', 'select'])\n}\n\nexport function isHotkeyEnabledOnTag({ target }: KeyboardEvent, enabledOnTags: FormTags[] | boolean = false): boolean {\n const targetTagName = target && (target as HTMLElement).tagName\n\n if (enabledOnTags instanceof Array) {\n return Boolean(targetTagName && enabledOnTags && enabledOnTags.some(tag => tag.toLowerCase() === targetTagName.toLowerCase()))\n }\n\n return Boolean(targetTagName && enabledOnTags && enabledOnTags === true)\n}\n\nexport function isScopeActive(activeScopes: string[], scopes?: Scopes): boolean {\n if (activeScopes.length === 0 && scopes) {\n console.warn(\n 'A hotkey has the \"scopes\" option set, however no active scopes were found. If you want to use the global scopes feature, you need to wrap your app in a <HotkeysProvider>'\n )\n\n return true\n }\n\n if (!scopes) {\n return true\n }\n\n return activeScopes.some(scope => scopes.includes(scope)) || activeScopes.includes('*')\n}\n\nexport const isHotkeyMatchingKeyboardEvent = (e: KeyboardEvent, hotkey: Hotkey, pressedDownKeys: Set<string>): boolean => {\n const { alt, meta, mod, shift, keys } = hotkey\n const { key: pressedKeyUppercase, code } = e\n\n const altKey = isHotkeyPressed('alt')\n const shiftKey = isHotkeyPressed('shift')\n const metaKey = isHotkeyPressed('meta')\n const ctrlKey = isHotkeyPressed('ctrl')\n\n const keyCode = code.toLowerCase().replace('key', '')\n const pressedKey = pressedKeyUppercase.toLowerCase()\n\n if (altKey !== alt && pressedKey !== 'alt') {\n return false\n }\n\n if (shiftKey !== shift && pressedKey !== 'shift') {\n return false\n }\n\n // Mod is a special key name that is checking for meta on macOS and ctrl on other platforms\n if (mod) {\n if (!metaKey && !ctrlKey) {\n return false\n }\n } else {\n if (metaKey !== meta && ctrlKey !== meta && keyCode !== 'meta' && keyCode !== 'ctrl') {\n return false\n }\n }\n\n // All modifiers are correct, now check the key\n // If the key is set, we check for the key\n if (keys && keys.length === 1 && (keys.includes(pressedKey) || keys.includes(keyCode))) {\n return true\n } else if (keys) {\n // Check if all keys are present in pressedDownKeys set\n return keys.every(key => pressedDownKeys.has(key))\n }\n else if (!keys) {\n // If the key is not set, we only listen for modifiers, that check went alright, so we return true\n return true\n }\n\n // There is nothing that matches.\n return false\n}\n","import { createContext, ReactNode, useContext } from 'react'\nimport { Hotkey } from './types'\n\ntype BoundHotkeysProxyProviderType = {\n addHotkey: (hotkey: Hotkey) => void,\n removeHotkey: (hotkey: Hotkey) => void,\n}\n\nconst BoundHotkeysProxyProvider = createContext<BoundHotkeysProxyProviderType | undefined>(undefined)\n\nexport const useBoundHotkeysProxy = () => {\n return useContext(BoundHotkeysProxyProvider)\n}\n\ninterface Props {\n children: ReactNode\n addHotkey: (hotkey: Hotkey) => void\n removeHotkey: (hotkey: Hotkey) => void\n}\n\nexport default function BoundHotkeysProxyProviderProvider({ addHotkey, removeHotkey, children }: Props) {\n return <BoundHotkeysProxyProvider.Provider value={{addHotkey, removeHotkey}}>{children}</BoundHotkeysProxyProvider.Provider>\n}\n","import { Hotkey } from './types'\nimport { createContext, ReactNode, useState, useContext, useCallback } from 'react'\nimport BoundHotkeysProxyProviderProvider from './BoundHotkeysProxyProvider'\nimport deepEqual from './deepEqual'\n\nexport type HotkeysContextType = {\n hotkeys: ReadonlyArray<Hotkey>\n enabledScopes: string[]\n toggleScope: (scope: string) => void\n enableScope: (scope: string) => void\n disableScope: (scope: string) => void\n}\n\n// The context is only needed for special features like global scoping, so we use a graceful default fallback\nconst HotkeysContext = createContext<HotkeysContextType>({\n hotkeys: [],\n enabledScopes: [], // This array has to be empty instead of containing '*' as default, to check if the provider is set or not\n toggleScope: () => {},\n enableScope: () => {},\n disableScope: () => {},\n})\n\nexport const useHotkeysContext = () => {\n return useContext(HotkeysContext)\n}\n\ninterface Props {\n initiallyActiveScopes?: string[]\n children: ReactNode\n}\n\nexport const HotkeysProvider = ({initiallyActiveScopes = ['*'], children}: Props) => {\n const [internalActiveScopes, setInternalActiveScopes] = useState(initiallyActiveScopes?.length > 0 ? initiallyActiveScopes : ['*'])\n const [boundHotkeys, setBoundHotkeys] = useState<Hotkey[]>([]);\n\n const enableScope = useCallback((scope: string) => {\n setInternalActiveScopes((prev) => {\n if (prev.includes('*')) {\n return [scope]\n }\n\n return Array.from(new Set([...prev, scope]))\n })\n }, [])\n\n const disableScope = useCallback((scope: string) => {\n setInternalActiveScopes((prev) => {\n if (prev.filter(s => s !== scope).length === 0) {\n return ['*']\n } else {\n return prev.filter(s => s !== scope)\n }\n })\n }, [])\n\n const toggleScope = useCallback((scope: string) => {\n setInternalActiveScopes((prev) => {\n if (prev.includes(scope)) {\n if (prev.filter(s => s !== scope).length === 0) {\n return ['*']\n } else {\n return prev.filter(s => s !== scope)\n }\n } else {\n if (prev.includes('*')) {\n return [scope]\n }\n\n return Array.from(new Set([...prev, scope]))\n }\n })\n }, [])\n\n const addBoundHotkey = useCallback((hotkey: Hotkey) => {\n setBoundHotkeys((prev) => [...prev, hotkey])\n }, [])\n\n const removeBoundHotkey = useCallback((hotkey: Hotkey) => {\n setBoundHotkeys((prev) => prev.filter(h => !deepEqual(h, hotkey)))\n }, [])\n\n return (\n <HotkeysContext.Provider value={{enabledScopes: internalActiveScopes, hotkeys: boundHotkeys, enableScope, disableScope, toggleScope}}>\n <BoundHotkeysProxyProviderProvider addHotkey={addBoundHotkey} removeHotkey={removeBoundHotkey}>\n {children}\n </BoundHotkeysProxyProviderProvider>\n </HotkeysContext.Provider>\n )\n}\n","import { useRef } from 'react'\nimport deepEqual from './deepEqual'\n\nexport default function useDeepEqualMemo<T>(value: T) {\n const ref = useRef<T | undefined>(undefined)\n\n if (!deepEqual(ref.current, value)) {\n ref.current = value\n }\n\n return ref.current\n}\n","import { HotkeyCallback, Keys, Options, OptionsOrDependencyArray, RefType } from './types'\nimport { DependencyList, useCallback, useEffect, useLayoutEffect, useRef } from 'react'\nimport { parseHotkey, parseKeysHookInput } from './parseHotkeys'\nimport {\n isHotkeyEnabled,\n isHotkeyEnabledOnTag,\n isHotkeyMatchingKeyboardEvent,\n isKeyboardEventTriggeredByInput,\n isScopeActive,\n maybePreventDefault,\n} from './validators'\nimport { useHotkeysContext } from './HotkeysProvider'\nimport { useBoundHotkeysProxy } from './BoundHotkeysProxyProvider'\nimport useDeepEqualMemo from './useDeepEqualMemo'\n\nconst stopPropagation = (e: KeyboardEvent): void => {\n e.stopPropagation()\n e.preventDefault()\n e.stopImmediatePropagation()\n}\n\nconst useSafeLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect\n\nconst pressedDownKeys = new Set<string>()\n\nexport default function useHotkeys<T extends HTMLElement>(\n keys: Keys,\n callback: HotkeyCallback,\n options?: OptionsOrDependencyArray,\n dependencies?: OptionsOrDependencyArray,\n) {\n const ref = useRef<RefType<T>>(null)\n\n const _options: Options | undefined = !(options instanceof Array) ? (options as Options) : !(dependencies instanceof Array) ? (dependencies as Options) : undefined\n const _deps: DependencyList = options instanceof Array ? options : dependencies instanceof Array ? dependencies : []\n\n const cb = useCallback(callback, [..._deps])\n const memoisedOptions = useDeepEqualMemo(_options)\n\n const { enabledScopes } = useHotkeysContext()\n const proxy = useBoundHotkeysProxy()\n\n useSafeLayoutEffect(() => {\n if (memoisedOptions?.enabled === false || !isScopeActive(enabledScopes, memoisedOptions?.scopes)) {\n return\n }\n\n const listener = (e: KeyboardEvent) => {\n if (isKeyboardEventTriggeredByInput(e) && !isHotkeyEnabledOnTag(e, memoisedOptions?.enableOnFormTags)) {\n return\n }\n\n // TODO: SINCE THE EVENT IS NOW ATTACHED TO THE REF, THE ACTIVE ELEMENT CAN NEVER BE INSIDE THE REF. THE HOTKEY ONLY TRIGGERS IF THE\n // REF IS THE ACTIVE ELEMENT. THIS IS A PROBLEM SINCE FOCUSED SUB COMPONENTS WON'T TRIGGER THE HOTKEY.\n if (ref.current !== null && document.activeElement !== ref.current && !ref.current.contains(document.activeElement)) {\n stopPropagation(e)\n\n return\n }\n\n if (((e.target as HTMLElement)?.isContentEditable && !memoisedOptions?.enableOnContentEditable)) {\n return\n }\n\n parseKeysHookInput(keys, memoisedOptions?.splitKey).forEach((key) => {\n const hotkey = parseHotkey(key, memoisedOptions?.combinationKey)\n\n if (isHotkeyMatchingKeyboardEvent(e, hotkey, pressedDownKeys) || hotkey.keys?.includes('*')) {\n maybePreventDefault(e, hotkey, memoisedOptions?.preventDefault)\n\n if (!isHotkeyEnabled(e, hotkey, memoisedOptions?.enabled)) {\n stopPropagation(e)\n\n return\n }\n\n cb(e, hotkey)\n }\n })\n }\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === undefined) {\n // Synthetic event (e.g., Chrome autofill). Ignore.\n return\n }\n\n pressedDownKeys.add(event.key.toLowerCase())\n\n if ((memoisedOptions?.keydown === undefined && memoisedOptions?.keyup !== true) || memoisedOptions?.keydown) {\n listener(event)\n }\n }\n\n const handleKeyUp = (event: KeyboardEvent) => {\n if (event.key === undefined) {\n // Synthetic event (e.g., Chrome autofill). Ignore.\n return\n }\n\n if (event.key.toLowerCase() !== 'meta') {\n pressedDownKeys.delete(event.key.toLowerCase())\n } else {\n // On macOS pressing down the meta key prevents triggering the keyup event for any other key https://stackoverflow.com/a/57153300/735226.\n pressedDownKeys.clear()\n }\n\n if (memoisedOptions?.keyup) {\n listener(event)\n }\n }\n\n // @ts-ignore\n (ref.current || document).addEventListener('keyup', handleKeyUp);\n // @ts-ignore\n (ref.current || document).addEventListener('keydown', handleKeyDown)\n\n if (proxy) {\n parseKeysHookInput(keys, memoisedOptions?.splitKey).forEach((key) => proxy.addHotkey(parseHotkey(key, memoisedOptions?.combinationKey)))\n }\n\n return () => {\n // @ts-ignore\n (ref.current || document).removeEventListener('keyup', handleKeyUp);\n // @ts-ignore\n (ref.current || document).removeEventListener('keydown', handleKeyDown)\n\n if (proxy) {\n parseKeysHookInput(keys, memoisedOptions?.splitKey).forEach((key) => proxy.removeHotkey(parseHotkey(key, memoisedOptions?.combinationKey)))\n }\n }\n }, [keys, cb, memoisedOptions, enabledScopes])\n\n return ref\n}\n"],"names":["reservedModifierKeywords","mappedKeys","esc","left","up","right","down","parseKeysHookInput","keys","splitKey","split","parseHotkey","hotkey","combinationKey","toLocaleLowerCase","map","k","trim","modifiers","alt","includes","shift","meta","mod","singleCharKeys","filter","deepEqual","x","y","Object","length","reduce","isEqual","key","currentlyPressedKeys","Set","isHotkeyPressed","hotkeyArray","Array","isArray","every","parsedHotkey","pressedHotkey","pushToCurrentlyPressedKeys","forEach","add","removeFromCurrentlyPressedKeys","window","addEventListener","document","e","undefined","maybePreventDefault","preventDefault","isHotkeyEnabled","enabled","isKeyboardEventTriggeredByInput","ev","isHotkeyEnabledOnTag","enabledOnTags","target","targetTagName","tagName","Boolean","some","tag","toLowerCase","isScopeActive","activeScopes","scopes","console","warn","scope","isHotkeyMatchingKeyboardEvent","pressedDownKeys","pressedKeyUppercase","code","altKey","shiftKey","metaKey","ctrlKey","keyCode","replace","pressedKey","has","BoundHotkeysProxyProvider","createContext","useBoundHotkeysProxy","useContext","BoundHotkeysProxyProviderProvider","addHotkey","removeHotkey","children","_jsx","HotkeysContext","hotkeys","enabledScopes","toggleScope","enableScope","disableScope","useHotkeysContext","HotkeysProvider","initiallyActiveScopes","useState","internalActiveScopes","setInternalActiveScopes","boundHotkeys","setBoundHotkeys","useCallback","prev","from","s","addBoundHotkey","removeBoundHotkey","h","useDeepEqualMemo","value","ref","useRef","current","stopPropagation","stopImmediatePropagation","useSafeLayoutEffect","useLayoutEffect","useEffect","useHotkeys","callback","options","dependencies","_options","_deps","cb","memoisedOptions","proxy","listener","enableOnFormTags","activeElement","contains","isContentEditable","enableOnContentEditable","handleKeyDown","event","keydown","keyup","handleKeyUp","clear","removeEventListener"],"mappings":"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"}
1
+ {"version":3,"file":"react-hotkeys-hook.esm.js","sources":["../src/parseHotkeys.ts","../src/isHotkeyPressed.ts","../src/validators.ts","../src/BoundHotkeysProxyProvider.tsx","../src/deepEqual.ts","../src/HotkeysProvider.tsx","../src/useDeepEqualMemo.ts","../src/useHotkeys.ts"],"sourcesContent":["import { Hotkey, KeyboardModifiers, Keys } from './types'\n\nconst reservedModifierKeywords = ['shift', 'alt', 'meta', 'mod']\n\nconst mappedKeys: Record<string, string> = {\n esc: 'escape',\n return: 'enter',\n '.': 'period',\n ',': 'comma',\n '-': 'slash',\n ' ': 'space',\n '#': 'backslash',\n '+': 'bracketright',\n 'ShiftLeft': 'shift',\n 'ShiftRight': 'shift',\n 'AltLeft': 'alt',\n 'AltRight': 'alt',\n 'MetaLeft': 'meta',\n 'MetaRight': 'meta',\n 'ControlLeft': 'ctrl',\n 'ControlRight': 'ctrl',\n}\n\nexport function mapKey(key: string): string {\n return (mappedKeys[key] || key)\n .trim()\n .toLowerCase()\n .replace('key', '')\n .replace('digit', '')\n .replace('numpad', '')\n .replace('arrow', '')\n}\n\nexport function isHotkeyModifier(key: string) {\n return reservedModifierKeywords.includes(key)\n}\n\nexport function parseKeysHookInput(keys: Keys, splitKey: string = ','): string[] {\n if (typeof keys === 'string') {\n return keys.split(splitKey)\n }\n\n return keys\n}\n\nexport function parseHotkey(hotkey: string, combinationKey: string = '+'): Hotkey {\n const keys = hotkey\n .toLocaleLowerCase()\n .split(combinationKey)\n .map(k => mapKey(k))\n\n const modifiers: KeyboardModifiers = {\n alt: keys.includes('alt'),\n shift: keys.includes('shift'),\n meta: keys.includes('meta'),\n mod: keys.includes('mod'),\n }\n\n const singleCharKeys = keys.filter((k) => !reservedModifierKeywords.includes(k))\n\n return {\n ...modifiers,\n keys: singleCharKeys,\n }\n}\n","import { isHotkeyModifier, mapKey } from './parseHotkeys'\n\nconst currentlyPressedKeys: Set<string> = new Set<string>()\n\nexport function isHotkeyPressed(key: string | string[], splitKey: string = ','): boolean {\n const hotkeyArray = Array.isArray(key) ? key : key.split(splitKey)\n\n return hotkeyArray.every((hotkey) => currentlyPressedKeys.has(hotkey.trim().toLowerCase()))\n}\n\nfunction pushToCurrentlyPressedKeys(key: string | string[]): void {\n const hotkeyArray = Array.isArray(key) ? key : [key]\n\n /*\n Due to a weird behavior on macOS we need to clear the set if the user pressed down the meta key and presses another key.\n https://stackoverflow.com/questions/11818637/why-does-javascript-drop-keyup-events-when-the-metakey-is-pressed-on-mac-browser\n Otherwise the set will hold all ever pressed keys while the meta key is down which leads to wrong results.\n */\n if (currentlyPressedKeys.has('meta')) {\n currentlyPressedKeys.forEach(key => !isHotkeyModifier(key) && currentlyPressedKeys.delete(key))\n }\n\n hotkeyArray.forEach(hotkey => currentlyPressedKeys.add(hotkey.toLowerCase()))\n}\n\nfunction removeFromCurrentlyPressedKeys(key: string): void {\n /*\n Due to a weird behavior on macOS we need to clear the set if the user pressed down the meta key and presses another key.\n https://stackoverflow.com/questions/11818637/why-does-javascript-drop-keyup-events-when-the-metakey-is-pressed-on-mac-browser\n Otherwise the set will hold all ever pressed keys while the meta key is down which leads to wrong results.\n */\n if (key === 'meta') {\n currentlyPressedKeys.clear()\n } else {\n currentlyPressedKeys.delete(key)\n }\n}\n\n(() => {\n document.addEventListener('keydown', e => {\n if (e.key === undefined) {\n // Synthetic event (e.g., Chrome autofill). Ignore.\n return\n }\n\n pushToCurrentlyPressedKeys(mapKey(e.code))\n })\n\n document.addEventListener('keyup', e => {\n if (e.key === undefined) {\n // Synthetic event (e.g., Chrome autofill). Ignore.\n return\n }\n\n removeFromCurrentlyPressedKeys(mapKey(e.code))\n })\n})()\n","import { FormTags, Hotkey, Scopes, Trigger } from './types'\nimport { isHotkeyPressed } from './isHotkeyPressed'\nimport { mapKey } from './parseHotkeys'\n\nexport function maybePreventDefault(e: KeyboardEvent, hotkey: Hotkey, preventDefault?: Trigger): void {\n if ((typeof preventDefault === 'function' && preventDefault(e, hotkey)) || preventDefault === true) {\n e.preventDefault()\n }\n}\n\nexport function isHotkeyEnabled(e: KeyboardEvent, hotkey: Hotkey, enabled?: Trigger): boolean {\n if (typeof enabled === 'function') {\n return enabled(e, hotkey)\n }\n\n return enabled === true || enabled === undefined\n}\n\nexport function isKeyboardEventTriggeredByInput(ev: KeyboardEvent): boolean {\n return isHotkeyEnabledOnTag(ev, ['input', 'textarea', 'select'])\n}\n\nexport function isHotkeyEnabledOnTag({ target }: KeyboardEvent, enabledOnTags: FormTags[] | boolean = false): boolean {\n const targetTagName = target && (target as HTMLElement).tagName\n\n if (enabledOnTags instanceof Array) {\n return Boolean(targetTagName && enabledOnTags && enabledOnTags.some(tag => tag.toLowerCase() === targetTagName.toLowerCase()))\n }\n\n return Boolean(targetTagName && enabledOnTags && enabledOnTags === true)\n}\n\nexport function isScopeActive(activeScopes: string[], scopes?: Scopes): boolean {\n if (activeScopes.length === 0 && scopes) {\n console.warn(\n 'A hotkey has the \"scopes\" option set, however no active scopes were found. If you want to use the global scopes feature, you need to wrap your app in a <HotkeysProvider>'\n )\n\n return true\n }\n\n if (!scopes) {\n return true\n }\n\n return activeScopes.some(scope => scopes.includes(scope)) || activeScopes.includes('*')\n}\n\nexport const isHotkeyMatchingKeyboardEvent = (e: KeyboardEvent, hotkey: Hotkey): boolean => {\n const { alt, meta, mod, shift, keys } = hotkey\n const { key: pressedKeyUppercase, code } = e\n\n const altKey = isHotkeyPressed('alt')\n const shiftKey = isHotkeyPressed('shift')\n const metaKey = isHotkeyPressed('meta')\n const ctrlKey = isHotkeyPressed('ctrl')\n\n const keyCode = mapKey(code)\n const pressedKey = pressedKeyUppercase.toLowerCase()\n\n if (altKey !== alt && pressedKey !== 'alt') {\n return false\n }\n\n if (shiftKey !== shift && pressedKey !== 'shift') {\n return false\n }\n\n // Mod is a special key name that is checking for meta on macOS and ctrl on other platforms\n if (mod) {\n if (!metaKey && !ctrlKey) {\n return false\n }\n } else {\n if (metaKey !== meta && ctrlKey !== meta && keyCode !== 'meta' && keyCode !== 'ctrl') {\n return false\n }\n }\n\n // All modifiers are correct, now check the key\n // If the key is set, we check for the key\n if (keys && keys.length === 1 && (keys.includes(pressedKey) || keys.includes(keyCode))) {\n return true\n } else if (keys) {\n // Check if all keys are present in pressedDownKeys set\n return isHotkeyPressed(keys)\n }\n else if (!keys) {\n // If the key is not set, we only listen for modifiers, that check went alright, so we return true\n return true\n }\n\n // There is nothing that matches.\n return false\n}\n","import { createContext, ReactNode, useContext } from 'react'\nimport { Hotkey } from './types'\n\ntype BoundHotkeysProxyProviderType = {\n addHotkey: (hotkey: Hotkey) => void,\n removeHotkey: (hotkey: Hotkey) => void,\n}\n\nconst BoundHotkeysProxyProvider = createContext<BoundHotkeysProxyProviderType | undefined>(undefined)\n\nexport const useBoundHotkeysProxy = () => {\n return useContext(BoundHotkeysProxyProvider)\n}\n\ninterface Props {\n children: ReactNode\n addHotkey: (hotkey: Hotkey) => void\n removeHotkey: (hotkey: Hotkey) => void\n}\n\nexport default function BoundHotkeysProxyProviderProvider({ addHotkey, removeHotkey, children }: Props) {\n return <BoundHotkeysProxyProvider.Provider value={{addHotkey, removeHotkey}}>{children}</BoundHotkeysProxyProvider.Provider>\n}\n","export default function deepEqual(x: any, y: any): boolean {\n //@ts-ignore\n return (x && y && typeof x === 'object' && typeof y === 'object')\n //@ts-ignore\n ? (Object.keys(x).length === Object.keys(y).length) && Object.keys(x).reduce(function(isEqual, key) {\n return isEqual && deepEqual(x[key], y[key])\n }, true)\n : (x === y)\n}\n","import { Hotkey } from './types'\nimport { createContext, ReactNode, useState, useContext, useCallback } from 'react'\nimport BoundHotkeysProxyProviderProvider from './BoundHotkeysProxyProvider'\nimport deepEqual from './deepEqual'\n\nexport type HotkeysContextType = {\n hotkeys: ReadonlyArray<Hotkey>\n enabledScopes: string[]\n toggleScope: (scope: string) => void\n enableScope: (scope: string) => void\n disableScope: (scope: string) => void\n}\n\n// The context is only needed for special features like global scoping, so we use a graceful default fallback\nconst HotkeysContext = createContext<HotkeysContextType>({\n hotkeys: [],\n enabledScopes: [], // This array has to be empty instead of containing '*' as default, to check if the provider is set or not\n toggleScope: () => {},\n enableScope: () => {},\n disableScope: () => {},\n})\n\nexport const useHotkeysContext = () => {\n return useContext(HotkeysContext)\n}\n\ninterface Props {\n initiallyActiveScopes?: string[]\n children: ReactNode\n}\n\nexport const HotkeysProvider = ({initiallyActiveScopes = ['*'], children}: Props) => {\n const [internalActiveScopes, setInternalActiveScopes] = useState(initiallyActiveScopes?.length > 0 ? initiallyActiveScopes : ['*'])\n const [boundHotkeys, setBoundHotkeys] = useState<Hotkey[]>([]);\n\n const enableScope = useCallback((scope: string) => {\n setInternalActiveScopes((prev) => {\n if (prev.includes('*')) {\n return [scope]\n }\n\n return Array.from(new Set([...prev, scope]))\n })\n }, [])\n\n const disableScope = useCallback((scope: string) => {\n setInternalActiveScopes((prev) => {\n if (prev.filter(s => s !== scope).length === 0) {\n return ['*']\n } else {\n return prev.filter(s => s !== scope)\n }\n })\n }, [])\n\n const toggleScope = useCallback((scope: string) => {\n setInternalActiveScopes((prev) => {\n if (prev.includes(scope)) {\n if (prev.filter(s => s !== scope).length === 0) {\n return ['*']\n } else {\n return prev.filter(s => s !== scope)\n }\n } else {\n if (prev.includes('*')) {\n return [scope]\n }\n\n return Array.from(new Set([...prev, scope]))\n }\n })\n }, [])\n\n const addBoundHotkey = useCallback((hotkey: Hotkey) => {\n setBoundHotkeys((prev) => [...prev, hotkey])\n }, [])\n\n const removeBoundHotkey = useCallback((hotkey: Hotkey) => {\n setBoundHotkeys((prev) => prev.filter(h => !deepEqual(h, hotkey)))\n }, [])\n\n return (\n <HotkeysContext.Provider value={{enabledScopes: internalActiveScopes, hotkeys: boundHotkeys, enableScope, disableScope, toggleScope}}>\n <BoundHotkeysProxyProviderProvider addHotkey={addBoundHotkey} removeHotkey={removeBoundHotkey}>\n {children}\n </BoundHotkeysProxyProviderProvider>\n </HotkeysContext.Provider>\n )\n}\n","import { useRef } from 'react'\nimport deepEqual from './deepEqual'\n\nexport default function useDeepEqualMemo<T>(value: T) {\n const ref = useRef<T | undefined>(undefined)\n\n if (!deepEqual(ref.current, value)) {\n ref.current = value\n }\n\n return ref.current\n}\n","import { HotkeyCallback, Keys, Options, OptionsOrDependencyArray, RefType } from './types'\nimport { DependencyList, useCallback, useEffect, useLayoutEffect, useRef } from 'react'\nimport { parseHotkey, parseKeysHookInput } from './parseHotkeys'\nimport {\n isHotkeyEnabled,\n isHotkeyEnabledOnTag,\n isHotkeyMatchingKeyboardEvent,\n isKeyboardEventTriggeredByInput,\n isScopeActive,\n maybePreventDefault,\n} from './validators'\nimport { useHotkeysContext } from './HotkeysProvider'\nimport { useBoundHotkeysProxy } from './BoundHotkeysProxyProvider'\nimport useDeepEqualMemo from './useDeepEqualMemo'\n\nconst stopPropagation = (e: KeyboardEvent): void => {\n e.stopPropagation()\n e.preventDefault()\n e.stopImmediatePropagation()\n}\n\nconst useSafeLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect\n\nexport default function useHotkeys<T extends HTMLElement>(\n keys: Keys,\n callback: HotkeyCallback,\n options?: OptionsOrDependencyArray,\n dependencies?: OptionsOrDependencyArray,\n) {\n const ref = useRef<RefType<T>>(null)\n const hasTriggeredRef = useRef(false)\n\n const _options: Options | undefined = !(options instanceof Array) ? (options as Options) : !(dependencies instanceof Array) ? (dependencies as Options) : undefined\n const _deps: DependencyList = options instanceof Array ? options : dependencies instanceof Array ? dependencies : []\n\n const cb = useCallback(callback, [..._deps])\n const memoisedOptions = useDeepEqualMemo(_options)\n\n const { enabledScopes } = useHotkeysContext()\n const proxy = useBoundHotkeysProxy()\n\n useSafeLayoutEffect(() => {\n if (memoisedOptions?.enabled === false || !isScopeActive(enabledScopes, memoisedOptions?.scopes)) {\n return\n }\n\n const listener = (e: KeyboardEvent) => {\n if (isKeyboardEventTriggeredByInput(e) && !isHotkeyEnabledOnTag(e, memoisedOptions?.enableOnFormTags)) {\n return\n }\n\n // TODO: SINCE THE EVENT IS NOW ATTACHED TO THE REF, THE ACTIVE ELEMENT CAN NEVER BE INSIDE THE REF. THE HOTKEY ONLY TRIGGERS IF THE\n // REF IS THE ACTIVE ELEMENT. THIS IS A PROBLEM SINCE FOCUSED SUB COMPONENTS WON'T TRIGGER THE HOTKEY.\n if (ref.current !== null && document.activeElement !== ref.current && !ref.current.contains(document.activeElement)) {\n stopPropagation(e)\n\n return\n }\n\n if (((e.target as HTMLElement)?.isContentEditable && !memoisedOptions?.enableOnContentEditable)) {\n return\n }\n\n parseKeysHookInput(keys, memoisedOptions?.splitKey).forEach((key) => {\n const hotkey = parseHotkey(key, memoisedOptions?.combinationKey)\n\n if ((isHotkeyMatchingKeyboardEvent(e, hotkey) || hotkey.keys?.includes('*')) && !hasTriggeredRef.current) {\n hasTriggeredRef.current = true\n\n maybePreventDefault(e, hotkey, memoisedOptions?.preventDefault)\n\n if (!isHotkeyEnabled(e, hotkey, memoisedOptions?.enabled)) {\n stopPropagation(e)\n\n return\n }\n\n // Execute the user callback for that hotkey\n cb(e, hotkey)\n }\n })\n }\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === undefined) {\n // Synthetic event (e.g., Chrome autofill). Ignore.\n return\n }\n\n if ((memoisedOptions?.keydown === undefined && memoisedOptions?.keyup !== true) || memoisedOptions?.keydown) {\n listener(event)\n }\n }\n\n const handleKeyUp = (event: KeyboardEvent) => {\n if (event.key === undefined) {\n // Synthetic event (e.g., Chrome autofill). Ignore.\n return\n }\n\n hasTriggeredRef.current = false\n\n if (memoisedOptions?.keyup) {\n listener(event)\n }\n }\n\n // @ts-ignore\n (ref.current || document).addEventListener('keyup', handleKeyUp);\n // @ts-ignore\n (ref.current || document).addEventListener('keydown', handleKeyDown)\n\n if (proxy) {\n parseKeysHookInput(keys, memoisedOptions?.splitKey).forEach((key) => proxy.addHotkey(parseHotkey(key, memoisedOptions?.combinationKey)))\n }\n\n return () => {\n // @ts-ignore\n (ref.current || document).removeEventListener('keyup', handleKeyUp);\n // @ts-ignore\n (ref.current || document).removeEventListener('keydown', handleKeyDown)\n\n if (proxy) {\n parseKeysHookInput(keys, memoisedOptions?.splitKey).forEach((key) => proxy.removeHotkey(parseHotkey(key, memoisedOptions?.combinationKey)))\n }\n }\n }, [keys, cb, memoisedOptions, enabledScopes])\n\n return ref\n}\n"],"names":["reservedModifierKeywords","mappedKeys","esc","mapKey","key","trim","toLowerCase","replace","isHotkeyModifier","includes","parseKeysHookInput","keys","splitKey","split","parseHotkey","hotkey","combinationKey","toLocaleLowerCase","map","k","modifiers","alt","shift","meta","mod","singleCharKeys","filter","currentlyPressedKeys","Set","isHotkeyPressed","hotkeyArray","Array","isArray","every","has","pushToCurrentlyPressedKeys","forEach","add","removeFromCurrentlyPressedKeys","clear","document","addEventListener","e","undefined","code","maybePreventDefault","preventDefault","isHotkeyEnabled","enabled","isKeyboardEventTriggeredByInput","ev","isHotkeyEnabledOnTag","enabledOnTags","target","targetTagName","tagName","Boolean","some","tag","isScopeActive","activeScopes","scopes","length","console","warn","scope","isHotkeyMatchingKeyboardEvent","pressedKeyUppercase","altKey","shiftKey","metaKey","ctrlKey","keyCode","pressedKey","BoundHotkeysProxyProvider","createContext","useBoundHotkeysProxy","useContext","BoundHotkeysProxyProviderProvider","addHotkey","removeHotkey","children","_jsx","deepEqual","x","y","Object","reduce","isEqual","HotkeysContext","hotkeys","enabledScopes","toggleScope","enableScope","disableScope","useHotkeysContext","HotkeysProvider","initiallyActiveScopes","useState","internalActiveScopes","setInternalActiveScopes","boundHotkeys","setBoundHotkeys","useCallback","prev","from","s","addBoundHotkey","removeBoundHotkey","h","useDeepEqualMemo","value","ref","useRef","current","stopPropagation","stopImmediatePropagation","useSafeLayoutEffect","window","useLayoutEffect","useEffect","useHotkeys","callback","options","dependencies","hasTriggeredRef","_options","_deps","cb","memoisedOptions","proxy","listener","enableOnFormTags","activeElement","contains","isContentEditable","enableOnContentEditable","handleKeyDown","event","keydown","keyup","handleKeyUp","removeEventListener"],"mappings":"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"}
@@ -4,4 +4,4 @@ export declare function isHotkeyEnabled(e: KeyboardEvent, hotkey: Hotkey, enable
4
4
  export declare function isKeyboardEventTriggeredByInput(ev: KeyboardEvent): boolean;
5
5
  export declare function isHotkeyEnabledOnTag({ target }: KeyboardEvent, enabledOnTags?: FormTags[] | boolean): boolean;
6
6
  export declare function isScopeActive(activeScopes: string[], scopes?: Scopes): boolean;
7
- export declare const isHotkeyMatchingKeyboardEvent: (e: KeyboardEvent, hotkey: Hotkey, pressedDownKeys: Set<string>) => boolean;
7
+ export declare const isHotkeyMatchingKeyboardEvent: (e: KeyboardEvent, hotkey: Hotkey) => boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-hotkeys-hook",
3
- "version": "4.1.0-0",
3
+ "version": "4.1.0",
4
4
  "repository": "https://JohannesKlauss@github.com/JohannesKlauss/react-keymap-hook.git",
5
5
  "homepage": "https://johannesklauss.github.io/react-hotkeys-hook/",
6
6
  "author": "Johannes Klauss",
@@ -1,63 +1,57 @@
1
- import { Hotkey } from './types'
2
- import { parseHotkey } from './parseHotkeys'
3
- import deepEqual from './deepEqual'
1
+ import { isHotkeyModifier, mapKey } from './parseHotkeys'
4
2
 
5
- const currentlyPressedKeys: Set<Hotkey> = new Set<Hotkey>()
3
+ const currentlyPressedKeys: Set<string> = new Set<string>()
6
4
 
7
5
  export function isHotkeyPressed(key: string | string[], splitKey: string = ','): boolean {
8
6
  const hotkeyArray = Array.isArray(key) ? key : key.split(splitKey)
9
7
 
10
- return hotkeyArray.every((hotkey) => {
11
- const parsedHotkey = parseHotkey(hotkey)
12
-
13
- for (const pressedHotkey of currentlyPressedKeys) {
14
- if (deepEqual(parsedHotkey, pressedHotkey)) {
15
- return true
16
- }
17
- }
18
- })
8
+ return hotkeyArray.every((hotkey) => currentlyPressedKeys.has(hotkey.trim().toLowerCase()))
19
9
  }
20
10
 
21
11
  function pushToCurrentlyPressedKeys(key: string | string[]): void {
22
12
  const hotkeyArray = Array.isArray(key) ? key : [key]
23
13
 
24
- hotkeyArray.forEach(hotkey => currentlyPressedKeys.add(parseHotkey(hotkey)))
25
- }
14
+ /*
15
+ Due to a weird behavior on macOS we need to clear the set if the user pressed down the meta key and presses another key.
16
+ https://stackoverflow.com/questions/11818637/why-does-javascript-drop-keyup-events-when-the-metakey-is-pressed-on-mac-browser
17
+ Otherwise the set will hold all ever pressed keys while the meta key is down which leads to wrong results.
18
+ */
19
+ if (currentlyPressedKeys.has('meta')) {
20
+ currentlyPressedKeys.forEach(key => !isHotkeyModifier(key) && currentlyPressedKeys.delete(key))
21
+ }
26
22
 
27
- function removeFromCurrentlyPressedKeys(key: string | string[]): void {
28
- const hotkeyArray = Array.isArray(key) ? key : [key]
23
+ hotkeyArray.forEach(hotkey => currentlyPressedKeys.add(hotkey.toLowerCase()))
24
+ }
29
25
 
30
- hotkeyArray.forEach((hotkey) => {
31
- const parsedHotkey = parseHotkey(hotkey)
26
+ function removeFromCurrentlyPressedKeys(key: string): void {
27
+ /*
28
+ Due to a weird behavior on macOS we need to clear the set if the user pressed down the meta key and presses another key.
29
+ https://stackoverflow.com/questions/11818637/why-does-javascript-drop-keyup-events-when-the-metakey-is-pressed-on-mac-browser
30
+ Otherwise the set will hold all ever pressed keys while the meta key is down which leads to wrong results.
31
+ */
32
+ if (key === 'meta') {
33
+ currentlyPressedKeys.clear()
34
+ } else {
35
+ currentlyPressedKeys.delete(key)
36
+ }
37
+ }
32
38
 
33
- for (const pressedHotkey of currentlyPressedKeys) {
34
- if (deepEqual(parsedHotkey, pressedHotkey)) {
35
- currentlyPressedKeys.delete(pressedHotkey)
36
- }
39
+ (() => {
40
+ document.addEventListener('keydown', e => {
41
+ if (e.key === undefined) {
42
+ // Synthetic event (e.g., Chrome autofill). Ignore.
43
+ return
37
44
  }
45
+
46
+ pushToCurrentlyPressedKeys(mapKey(e.code))
38
47
  })
39
- }
40
48
 
41
- (() => {
42
- if (typeof window !== 'undefined') {
43
- window.addEventListener('DOMContentLoaded', () => {
44
- document.addEventListener('keydown', e => {
45
- if (e.key === undefined) {
46
- // Synthetic event (e.g., Chrome autofill). Ignore.
47
- return
48
- }
49
-
50
- pushToCurrentlyPressedKeys(e.key)
51
- })
52
-
53
- document.addEventListener('keyup', e => {
54
- if (e.key === undefined) {
55
- // Synthetic event (e.g., Chrome autofill). Ignore.
56
- return
57
- }
58
-
59
- removeFromCurrentlyPressedKeys(e.key)
60
- })
61
- })
62
- }
49
+ document.addEventListener('keyup', e => {
50
+ if (e.key === undefined) {
51
+ // Synthetic event (e.g., Chrome autofill). Ignore.
52
+ return
53
+ }
54
+
55
+ removeFromCurrentlyPressedKeys(mapKey(e.code))
56
+ })
63
57
  })()
@@ -5,19 +5,34 @@ const reservedModifierKeywords = ['shift', 'alt', 'meta', 'mod']
5
5
  const mappedKeys: Record<string, string> = {
6
6
  esc: 'escape',
7
7
  return: 'enter',
8
- left: 'arrowleft',
9
- up: 'arrowup',
10
- right: 'arrowright',
11
- down: 'arrowdown',
12
- '1': 'digit1',
13
- '2': 'digit2',
14
- '3': 'digit3',
15
- '4': 'digit4',
16
- '5': 'digit5',
17
- '6': 'digit6',
18
- '7': 'digit7',
19
- '8': 'digit8',
20
- '9': 'digit9',
8
+ '.': 'period',
9
+ ',': 'comma',
10
+ '-': 'slash',
11
+ ' ': 'space',
12
+ '#': 'backslash',
13
+ '+': 'bracketright',
14
+ 'ShiftLeft': 'shift',
15
+ 'ShiftRight': 'shift',
16
+ 'AltLeft': 'alt',
17
+ 'AltRight': 'alt',
18
+ 'MetaLeft': 'meta',
19
+ 'MetaRight': 'meta',
20
+ 'ControlLeft': 'ctrl',
21
+ 'ControlRight': 'ctrl',
22
+ }
23
+
24
+ export function mapKey(key: string): string {
25
+ return (mappedKeys[key] || key)
26
+ .trim()
27
+ .toLowerCase()
28
+ .replace('key', '')
29
+ .replace('digit', '')
30
+ .replace('numpad', '')
31
+ .replace('arrow', '')
32
+ }
33
+
34
+ export function isHotkeyModifier(key: string) {
35
+ return reservedModifierKeywords.includes(key)
21
36
  }
22
37
 
23
38
  export function parseKeysHookInput(keys: Keys, splitKey: string = ','): string[] {
@@ -32,8 +47,7 @@ export function parseHotkey(hotkey: string, combinationKey: string = '+'): Hotke
32
47
  const keys = hotkey
33
48
  .toLocaleLowerCase()
34
49
  .split(combinationKey)
35
- .map(k => k.trim())
36
- .map(k => mappedKeys[k] || k)
50
+ .map(k => mapKey(k))
37
51
 
38
52
  const modifiers: KeyboardModifiers = {
39
53
  alt: keys.includes('alt'),