Skip to content

Commit 2707798

Browse files
committed
Replace react-hotkeys-hook with custom hook
1 parent e553b95 commit 2707798

6 files changed

Lines changed: 168 additions & 123 deletions

File tree

dist/index.js

Lines changed: 86 additions & 86 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package-lock.json

Lines changed: 0 additions & 22 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@
6868
"node-schedule": "^2.1.1",
6969
"normalize-url": "^9.0.0",
7070
"request-ip": "^3.3.0",
71-
"rxjs": "^7.8.2",
7271
"sanitize-filename": "^1.6.3",
7372
"signale": "^1.4.0",
7473
"uuid": "^13.0.0"
@@ -94,10 +93,10 @@
9493
"react-apollo-network-status": "^6.0.0",
9594
"react-dom": "^19.0.0",
9695
"react-fast-compare": "^3.2.2",
97-
"react-hotkeys-hook": "^3.4.7",
9896
"react-use": "^17.6.0",
9997
"rosid-handler-js-next": "^2.0.0",
10098
"rosid-handler-sass": "^9.0.0",
99+
"rxjs": "^7.8.2",
101100
"s-ago": "^2.2.0",
102101
"shortid": "^2.2.17",
103102
"test-listen": "^1.1.0",

src/ui/scripts/components/Dashboard.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { createElement as h } from 'react'
2-
import { useHotkeys } from 'react-hotkeys-hook'
32

43
import useDomains from '../api/hooks/domains/useDomains.js'
54
import * as routes from '../constants/routes.js'
5+
import useHotkey from '../hooks/useHotkey.js'
66
import useRoute from '../hooks/useRoute.js'
77
import whenBelow from '../utils/whenBelow.js'
88

@@ -48,14 +48,14 @@ const Dashboard = (props) => {
4848
const currentRoute = useRoute(props.route)
4949
const domains = useDomains()
5050

51-
useHotkeys('o', () => props.setRoute('/'))
52-
useHotkeys('v', () => props.setRoute('/insights/views'))
53-
useHotkeys('p', () => props.setRoute('/insights/pages'))
54-
useHotkeys('r', () => props.setRoute('/insights/referrers'))
55-
useHotkeys('d', () => props.setRoute('/insights/durations'))
56-
useHotkeys('e', () => props.setRoute('/insights/events'))
57-
useHotkeys('s', () => props.setRoute('/settings'))
58-
useHotkeys('0,1,2,3,4,5,6,7,8,9', (e, { key }) => gotoDomainWhenDefined(domains.value, props.setRoute, key), [
51+
useHotkey('o', () => props.setRoute('/'))
52+
useHotkey('v', () => props.setRoute('/insights/views'))
53+
useHotkey('p', () => props.setRoute('/insights/pages'))
54+
useHotkey('r', () => props.setRoute('/insights/referrers'))
55+
useHotkey('d', () => props.setRoute('/insights/durations'))
56+
useHotkey('e', () => props.setRoute('/insights/events'))
57+
useHotkey('s', () => props.setRoute('/settings'))
58+
useHotkey('0,1,2,3,4,5,6,7,8,9', (e, { key }) => gotoDomainWhenDefined(domains.value, props.setRoute, key), {}, [
5959
domains.value,
6060
])
6161

src/ui/scripts/components/modals/Modal.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import classNames from 'classnames'
22
import PropTypes from 'prop-types'
33
import { createElement as h } from 'react'
4-
import { useHotkeys } from 'react-hotkeys-hook'
54

5+
import useHotkey from '../../hooks/useHotkey.js'
66
import commonModalProps from '../../utils/commonModalProps.js'
77

88
const Modal = (props) => {
9-
useHotkeys('esc', props.closeModal, {
10-
filter: () => props.current === true,
11-
enableOnTags: ['INPUT', 'SELECT', 'TEXTAREA'],
9+
useHotkey('escape', props.closeModal, {
10+
enabled: props.current === true,
11+
enabledOnInput: true,
1212
})
1313

1414
return h(

src/ui/scripts/hooks/useHotkey.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { useCallback, useEffect } from 'react'
2+
3+
const hotkeyManager = (() => {
4+
const handlers = new Set()
5+
6+
const handleKeyDown = (event) => {
7+
const pressedKey = event.key.toLowerCase()
8+
const targetTag = event.target.tagName
9+
10+
for (const handler of handlers) {
11+
handler(event, pressedKey, targetTag)
12+
}
13+
}
14+
15+
globalThis.addEventListener('keydown', handleKeyDown)
16+
17+
return {
18+
register: (handler) => {
19+
handlers.add(handler)
20+
},
21+
unregister: (handler) => {
22+
handlers.delete(handler)
23+
},
24+
}
25+
})()
26+
27+
/**
28+
* Custom hook for handling keyboard shortcuts
29+
*
30+
* @param {string} keys - Single key or comma-separated keys (e.g., 'escape', 'a,b,c')
31+
* @param {Function} callback - Function to call when key is pressed. Receives (event, { key })
32+
* @param {object} options - Configuration options
33+
* @param {boolean} options.enabled - Whether the hotkey is enabled (default: true)
34+
* @param {boolean} options.enabledOnInput - Whether to allow hotkey on form inputs (default: false)
35+
* @param {Array} deps - Dependencies array for the callback
36+
*/
37+
const useHotkey = (keys, callback, options = {}, deps = []) => {
38+
const { enabled = true, enabledOnInput = false } = options
39+
40+
const memoizedCallback = useCallback(callback, deps)
41+
42+
useEffect(() => {
43+
const keySet = new Set(keys.split(',').map((key) => key.trim().toLowerCase()))
44+
45+
const handler = (event, pressedKey, targetTag) => {
46+
// Check if hotkey is enabled
47+
if (!enabled) return
48+
49+
// Check if the hotkey should be blocked on form inputs
50+
const isFormElement = ['INPUT', 'SELECT', 'TEXTAREA'].includes(targetTag)
51+
if (isFormElement && !enabledOnInput) return
52+
53+
// Check if the pressed key matches any of the configured keys
54+
if (keySet.has(pressedKey)) {
55+
event.preventDefault()
56+
memoizedCallback(event, { key: pressedKey })
57+
}
58+
}
59+
60+
hotkeyManager.register(handler)
61+
62+
return () => {
63+
hotkeyManager.unregister(handler)
64+
}
65+
}, [keys, enabled, enabledOnInput, memoizedCallback])
66+
}
67+
68+
export default useHotkey

0 commit comments

Comments
 (0)