react-hotkeys-hook 4.3.4 → 4.3.6-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.
@@ -12,14 +12,16 @@ const mappedKeys: Record<string, string> = {
12
12
  '`': 'backquote',
13
13
  '#': 'backslash',
14
14
  '+': 'bracketright',
15
- 'ShiftLeft': 'shift',
16
- 'ShiftRight': 'shift',
17
- 'AltLeft': 'alt',
18
- 'AltRight': 'alt',
19
- 'MetaLeft': 'meta',
20
- 'MetaRight': 'meta',
21
- 'ControlLeft': 'ctrl',
22
- 'ControlRight': 'ctrl',
15
+ ShiftLeft: 'shift',
16
+ ShiftRight: 'shift',
17
+ AltLeft: 'alt',
18
+ AltRight: 'alt',
19
+ MetaLeft: 'meta',
20
+ MetaRight: 'meta',
21
+ OSLeft: 'meta',
22
+ OSRight: 'meta',
23
+ ControlLeft: 'ctrl',
24
+ ControlRight: 'ctrl',
23
25
  }
24
26
 
25
27
  export function mapKey(key: string): string {
@@ -36,7 +38,7 @@ export function isHotkeyModifier(key: string) {
36
38
  return reservedModifierKeywords.includes(key)
37
39
  }
38
40
 
39
- export function parseKeysHookInput(keys: Keys, splitKey: string = ','): string[] {
41
+ export function parseKeysHookInput(keys: Keys, splitKey = ','): string[] {
40
42
  if (typeof keys === 'string') {
41
43
  return keys.split(splitKey)
42
44
  }
@@ -44,11 +46,11 @@ export function parseKeysHookInput(keys: Keys, splitKey: string = ','): string[]
44
46
  return keys
45
47
  }
46
48
 
47
- export function parseHotkey(hotkey: string, combinationKey: string = '+'): Hotkey {
49
+ export function parseHotkey(hotkey: string, combinationKey = '+'): Hotkey {
48
50
  const keys = hotkey
49
51
  .toLocaleLowerCase()
50
52
  .split(combinationKey)
51
- .map(k => mapKey(k))
53
+ .map((k) => mapKey(k))
52
54
 
53
55
  const modifiers: KeyboardModifiers = {
54
56
  alt: keys.includes('alt'),
package/src/types.ts CHANGED
@@ -19,7 +19,7 @@ export type Hotkey = KeyboardModifiers & {
19
19
  scopes?: Scopes
20
20
  }
21
21
 
22
- export type HotkeysEvent = Hotkey & {}
22
+ export type HotkeysEvent = Hotkey
23
23
 
24
24
  export type HotkeyCallback = (keyboardEvent: KeyboardEvent, hotkeysEvent: HotkeysEvent) => void
25
25
 
package/src/useHotkeys.ts CHANGED
@@ -26,15 +26,28 @@ export default function useHotkeys<T extends HTMLElement>(
26
26
  keys: Keys,
27
27
  callback: HotkeyCallback,
28
28
  options?: OptionsOrDependencyArray,
29
- dependencies?: OptionsOrDependencyArray,
29
+ dependencies?: OptionsOrDependencyArray
30
30
  ) {
31
31
  const ref = useRef<RefType<T>>(null)
32
32
  const hasTriggeredRef = useRef(false)
33
33
 
34
- const _options: Options | undefined = !(options instanceof Array) ? (options as Options) : !(dependencies instanceof Array) ? (dependencies as Options) : undefined
35
- const _deps: DependencyList = options instanceof Array ? options : dependencies instanceof Array ? dependencies : []
34
+ const _options: Options | undefined = !(options instanceof Array)
35
+ ? (options as Options)
36
+ : !(dependencies instanceof Array)
37
+ ? (dependencies as Options)
38
+ : undefined
39
+ const _deps: DependencyList | undefined =
40
+ options instanceof Array ? options : dependencies instanceof Array ? dependencies : undefined
41
+
42
+ const memoisedCB = useCallback(callback, _deps ?? [])
43
+ const cbRef = useRef<HotkeyCallback>(memoisedCB)
44
+
45
+ if (_deps) {
46
+ cbRef.current = memoisedCB
47
+ } else {
48
+ cbRef.current = callback
49
+ }
36
50
 
37
- const cb = useCallback(callback, [..._deps])
38
51
  const memoisedOptions = useDeepEqualMemo(_options)
39
52
 
40
53
  const { enabledScopes } = useHotkeysContext()
@@ -45,20 +58,24 @@ export default function useHotkeys<T extends HTMLElement>(
45
58
  return
46
59
  }
47
60
 
48
- const listener = (e: KeyboardEvent, isKeyUp: boolean = false) => {
61
+ const listener = (e: KeyboardEvent, isKeyUp = false) => {
49
62
  if (isKeyboardEventTriggeredByInput(e) && !isHotkeyEnabledOnTag(e, memoisedOptions?.enableOnFormTags)) {
50
63
  return
51
64
  }
52
65
 
53
66
  // 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
54
67
  // REF IS THE ACTIVE ELEMENT. THIS IS A PROBLEM SINCE FOCUSED SUB COMPONENTS WON'T TRIGGER THE HOTKEY.
55
- if (ref.current !== null && document.activeElement !== ref.current && !ref.current.contains(document.activeElement)) {
68
+ if (
69
+ ref.current !== null &&
70
+ document.activeElement !== ref.current &&
71
+ !ref.current.contains(document.activeElement)
72
+ ) {
56
73
  stopPropagation(e)
57
74
 
58
75
  return
59
76
  }
60
77
 
61
- if (((e.target as HTMLElement)?.isContentEditable && !memoisedOptions?.enableOnContentEditable)) {
78
+ if ((e.target as HTMLElement)?.isContentEditable && !memoisedOptions?.enableOnContentEditable) {
62
79
  return
63
80
  }
64
81
 
@@ -79,7 +96,7 @@ export default function useHotkeys<T extends HTMLElement>(
79
96
  }
80
97
 
81
98
  // Execute the user callback for that hotkey
82
- cb(e, hotkey)
99
+ cbRef.current(e, hotkey)
83
100
 
84
101
  if (!isKeyUp) {
85
102
  hasTriggeredRef.current = true
@@ -116,26 +133,32 @@ export default function useHotkeys<T extends HTMLElement>(
116
133
  }
117
134
  }
118
135
 
136
+ const domNode = ref.current || _options?.document || document
137
+
119
138
  // @ts-ignore
120
- (ref.current || _options?.document || document).addEventListener('keyup', handleKeyUp);
139
+ domNode.addEventListener('keyup', handleKeyUp)
121
140
  // @ts-ignore
122
- (ref.current || _options?.document || document).addEventListener('keydown', handleKeyDown)
141
+ domNode.addEventListener('keydown', handleKeyDown)
123
142
 
124
143
  if (proxy) {
125
- parseKeysHookInput(keys, memoisedOptions?.splitKey).forEach((key) => proxy.addHotkey(parseHotkey(key, memoisedOptions?.combinationKey)))
144
+ parseKeysHookInput(keys, memoisedOptions?.splitKey).forEach((key) =>
145
+ proxy.addHotkey(parseHotkey(key, memoisedOptions?.combinationKey))
146
+ )
126
147
  }
127
148
 
128
149
  return () => {
129
150
  // @ts-ignore
130
- (ref.current || _options?.document || document).removeEventListener('keyup', handleKeyUp);
151
+ domNode.removeEventListener('keyup', handleKeyUp)
131
152
  // @ts-ignore
132
- (ref.current || _options?.document || document).removeEventListener('keydown', handleKeyDown)
153
+ domNode.removeEventListener('keydown', handleKeyDown)
133
154
 
134
155
  if (proxy) {
135
- parseKeysHookInput(keys, memoisedOptions?.splitKey).forEach((key) => proxy.removeHotkey(parseHotkey(key, memoisedOptions?.combinationKey)))
156
+ parseKeysHookInput(keys, memoisedOptions?.splitKey).forEach((key) =>
157
+ proxy.removeHotkey(parseHotkey(key, memoisedOptions?.combinationKey))
158
+ )
136
159
  }
137
160
  }
138
- }, [keys, cb, memoisedOptions, enabledScopes])
161
+ }, [keys, memoisedOptions, enabledScopes])
139
162
 
140
163
  return ref
141
164
  }
@@ -3,7 +3,7 @@ import { mapKey } from './parseHotkeys'
3
3
 
4
4
  export default function useRecordHotkeys() {
5
5
  const [keys, setKeys] = useState(new Set<string>())
6
- const [isRecording, setIsRecording] = useState(false);
6
+ const [isRecording, setIsRecording] = useState(false)
7
7
 
8
8
  const handler = useCallback((event: KeyboardEvent) => {
9
9
  if (event.key === undefined) {
@@ -14,7 +14,7 @@ export default function useRecordHotkeys() {
14
14
  event.preventDefault()
15
15
  event.stopPropagation()
16
16
 
17
- setKeys(prev => {
17
+ setKeys((prev) => {
18
18
  const newKeys = new Set(prev)
19
19
 
20
20
  newKeys.add(mapKey(event.code))
package/src/validators.ts CHANGED
@@ -24,7 +24,9 @@ export function isHotkeyEnabledOnTag({ target }: KeyboardEvent, enabledOnTags: F
24
24
  const targetTagName = target && (target as HTMLElement).tagName
25
25
 
26
26
  if (enabledOnTags instanceof Array) {
27
- return Boolean(targetTagName && enabledOnTags && enabledOnTags.some(tag => tag.toLowerCase() === targetTagName.toLowerCase()))
27
+ return Boolean(
28
+ targetTagName && enabledOnTags && enabledOnTags.some((tag) => tag.toLowerCase() === targetTagName.toLowerCase())
29
+ )
28
30
  }
29
31
 
30
32
  return Boolean(targetTagName && enabledOnTags && enabledOnTags === true)
@@ -33,7 +35,7 @@ export function isHotkeyEnabledOnTag({ target }: KeyboardEvent, enabledOnTags: F
33
35
  export function isScopeActive(activeScopes: string[], scopes?: Scopes): boolean {
34
36
  if (activeScopes.length === 0 && scopes) {
35
37
  console.warn(
36
- '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>',
38
+ '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>'
37
39
  )
38
40
 
39
41
  return true
@@ -43,10 +45,10 @@ export function isScopeActive(activeScopes: string[], scopes?: Scopes): boolean
43
45
  return true
44
46
  }
45
47
 
46
- return activeScopes.some(scope => scopes.includes(scope)) || activeScopes.includes('*')
48
+ return activeScopes.some((scope) => scopes.includes(scope)) || activeScopes.includes('*')
47
49
  }
48
50
 
49
- export const isHotkeyMatchingKeyboardEvent = (e: KeyboardEvent, hotkey: Hotkey, ignoreModifiers: boolean = false): boolean => {
51
+ export const isHotkeyMatchingKeyboardEvent = (e: KeyboardEvent, hotkey: Hotkey, ignoreModifiers = false): boolean => {
50
52
  const { alt, meta, mod, shift, ctrl, keys } = hotkey
51
53
  const { key: pressedKeyUppercase, code, ctrlKey, metaKey, shiftKey, altKey } = e
52
54