(
id: string,
config: ShortcutConfig,
callback: ShortcutCallback,
options: UseShortcutOptions = {}
)
| 23 | * @param options Optional description, priority, enabled flag |
| 24 | */ |
| 25 | export function useShortcut( |
| 26 | id: string, |
| 27 | config: ShortcutConfig, |
| 28 | callback: ShortcutCallback, |
| 29 | options: UseShortcutOptions = {} |
| 30 | ): void { |
| 31 | const { description, priority, enabled = true } = options; |
| 32 | |
| 33 | // Keep the latest callback in a ref so changes don't trigger re-registration. |
| 34 | const callbackRef = useRef<ShortcutCallback>(callback); |
| 35 | callbackRef.current = callback; |
| 36 | |
| 37 | // Stable wrapper that delegates to the current callback ref. |
| 38 | const stableCallback = useRef<ShortcutCallback>((e) => callbackRef.current(e)); |
| 39 | |
| 40 | // Serialize config to a stable string for the dependency array. |
| 41 | const configKey = JSON.stringify({ |
| 42 | key: config.key, |
| 43 | ctrl: config.ctrl, |
| 44 | shift: config.shift, |
| 45 | alt: config.alt, |
| 46 | meta: config.meta, |
| 47 | scope: config.scope, |
| 48 | allowInInput: config.allowInInput, |
| 49 | }); |
| 50 | |
| 51 | useEffect(() => { |
| 52 | if (!enabled) return; |
| 53 | |
| 54 | const unregister = shortcutManager.register(id, config, stableCallback.current, { |
| 55 | description, |
| 56 | priority, |
| 57 | }); |
| 58 | |
| 59 | return unregister; |
| 60 | // eslint-disable-next-line react-hooks/exhaustive-deps |
| 61 | }, [id, configKey, enabled, description, priority]); |
| 62 | } |
no test coverage detected