react-hotkeys-hook 4.0.0-2 → 4.0.0-3

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.
@@ -0,0 +1 @@
1
+ export default function useDeepEqualMemo<T>(value: T): T | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-hotkeys-hook",
3
- "version": "4.0.0-2",
3
+ "version": "4.0.0-3",
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",
@@ -68,8 +68,11 @@
68
68
  "tslib": "2.4.0",
69
69
  "typescript": "4.7.4"
70
70
  },
71
+ "dependencies": {
72
+ "lodash": "4.17.11"
73
+ },
71
74
  "peerDependencies": {
72
- "lodash": ">=4.17.21",
75
+ "lodash": ">=4.17.0",
73
76
  "react": ">=16.8.1",
74
77
  "react-dom": ">=16.8.1"
75
78
  }
@@ -2,7 +2,7 @@ import { Hotkey } from './types'
2
2
  import { createContext, ReactNode, useMemo, useState, useContext } from 'react'
3
3
  import BoundHotkeysProxyProviderProvider from './BoundHotkeysProxyProvider'
4
4
 
5
- type HotkeysContextType = {
5
+ export type HotkeysContextType = {
6
6
  hotkeys: ReadonlyArray<Hotkey>
7
7
  activeScopes: string[]
8
8
  toggleScope: (scope: string) => void
@@ -0,0 +1,12 @@
1
+ import { useRef } from 'react'
2
+ import { isEqual } from 'lodash'
3
+
4
+ export default function useDeepEqualMemo<T>(value: T) {
5
+ const ref = useRef<T | undefined>(undefined)
6
+
7
+ if (!isEqual(ref.current, value)) {
8
+ ref.current = value
9
+ }
10
+
11
+ return ref.current
12
+ }
package/src/useHotkeys.ts CHANGED
@@ -11,6 +11,7 @@ import {
11
11
  } from './validators'
12
12
  import { useHotkeysContext } from './HotkeysProvider'
13
13
  import { useBoundHotkeysProxy } from './BoundHotkeysProxyProvider'
14
+ import useDeepEqualMemo from './useDeepEqualMemo'
14
15
 
15
16
  const stopPropagation = (e: KeyboardEvent): void => {
16
17
  e.stopPropagation()
@@ -31,37 +32,41 @@ export default function useHotkeys<T extends HTMLElement>(
31
32
  const _deps = options instanceof Array ? options : dependencies instanceof Array ? dependencies : []
32
33
 
33
34
  const cb = useCallback(callback, [..._deps])
34
- const ctx = useHotkeysContext()
35
+ const memoisedOptions = useDeepEqualMemo(_options)
35
36
 
37
+ const { activeScopes } = useHotkeysContext()
36
38
  const proxy = useBoundHotkeysProxy()
37
39
 
38
40
  useLayoutEffect(() => {
39
- if (_options?.enabled === false || !isScopeActive(ctx.activeScopes, _options?.scopes)) {
41
+ if (memoisedOptions?.enabled === false || !isScopeActive(activeScopes, memoisedOptions?.scopes)) {
40
42
  return
41
43
  }
42
44
 
43
45
  const listener = (e: KeyboardEvent) => {
44
- if (isKeyboardEventTriggeredByInput(e) && !isHotkeyEnabledOnTag(e, _options?.enableOnFormTags)) {
46
+ if (isKeyboardEventTriggeredByInput(e) && !isHotkeyEnabledOnTag(e, memoisedOptions?.enableOnFormTags)) {
45
47
  return
46
48
  }
47
49
 
50
+ // 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
51
+ // REF IS THE ACTIVE ELEMENT. THIS IS A PROBLEM SINCE FOCUSED SUB COMPONENTS WONT TRIGGER THE HOTKEY.
52
+
48
53
  if (ref.current !== null && document.activeElement !== ref.current && !ref.current.contains(document.activeElement)) {
49
54
  stopPropagation(e)
50
55
 
51
56
  return
52
57
  }
53
58
 
54
- if (((e.target as HTMLElement)?.isContentEditable && !_options?.enableOnContentEditable)) {
59
+ if (((e.target as HTMLElement)?.isContentEditable && !memoisedOptions?.enableOnContentEditable)) {
55
60
  return
56
61
  }
57
62
 
58
- parseKeysHookInput(keys, _options?.splitKey).forEach((key) => {
59
- const hotkey = parseHotkey(key, _options?.combinationKey)
63
+ parseKeysHookInput(keys, memoisedOptions?.splitKey).forEach((key) => {
64
+ const hotkey = parseHotkey(key, memoisedOptions?.combinationKey)
60
65
 
61
66
  if (isHotkeyMatchingKeyboardEvent(e, hotkey, pressedDownKeys) || hotkey.keys?.includes('*')) {
62
- maybePreventDefault(e, hotkey, _options?.preventDefault)
67
+ maybePreventDefault(e, hotkey, memoisedOptions?.preventDefault)
63
68
 
64
- if (!isHotkeyEnabled(e, hotkey, _options?.enabled)) {
69
+ if (!isHotkeyEnabled(e, hotkey, memoisedOptions?.enabled)) {
65
70
  stopPropagation(e)
66
71
 
67
72
  return
@@ -75,7 +80,7 @@ export default function useHotkeys<T extends HTMLElement>(
75
80
  const handleKeyDown = (event: KeyboardEvent) => {
76
81
  pressedDownKeys.add(event.key.toLowerCase())
77
82
 
78
- if ((_options?.keydown === undefined && _options?.keyup !== true) || _options?.keydown) {
83
+ if ((memoisedOptions?.keydown === undefined && memoisedOptions?.keyup !== true) || memoisedOptions?.keydown) {
79
84
  listener(event)
80
85
  }
81
86
  }
@@ -83,7 +88,7 @@ export default function useHotkeys<T extends HTMLElement>(
83
88
  const handleKeyUp = (event: KeyboardEvent) => {
84
89
  pressedDownKeys.delete(event.key.toLowerCase())
85
90
 
86
- if (_options?.keyup) {
91
+ if (memoisedOptions?.keyup) {
87
92
  listener(event)
88
93
  }
89
94
  }
@@ -94,7 +99,7 @@ export default function useHotkeys<T extends HTMLElement>(
94
99
  (ref.current || document).addEventListener('keydown', handleKeyDown)
95
100
 
96
101
  if (proxy) {
97
- parseKeysHookInput(keys, _options?.splitKey).forEach((key) => proxy.addHotkey(parseHotkey(key, _options?.combinationKey)))
102
+ parseKeysHookInput(keys, memoisedOptions?.splitKey).forEach((key) => proxy.addHotkey(parseHotkey(key, memoisedOptions?.combinationKey)))
98
103
  }
99
104
 
100
105
  return () => {
@@ -104,10 +109,10 @@ export default function useHotkeys<T extends HTMLElement>(
104
109
  (ref.current || document).removeEventListener('keydown', handleKeyDown)
105
110
 
106
111
  if (proxy) {
107
- parseKeysHookInput(keys, _options?.splitKey).forEach((key) => proxy.removeHotkey(parseHotkey(key, _options?.combinationKey)))
112
+ parseKeysHookInput(keys, memoisedOptions?.splitKey).forEach((key) => proxy.removeHotkey(parseHotkey(key, memoisedOptions?.combinationKey)))
108
113
  }
109
114
  }
110
- }, [keys, cb, _options])
115
+ }, [keys, cb, memoisedOptions, activeScopes])
111
116
 
112
117
  return ref
113
118
  }