### Start Development Server for Library Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/AGENTS.md Starts the development server specifically for the library package. ```bash npm run -w packages/react-hotkeys-hook dev ``` -------------------------------- ### Install Dependencies Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/README.md Run this command to install all project dependencies. ```bash $ yarn ``` -------------------------------- ### Start Local Development Server Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/README.md Starts a local development server with live reloading enabled. ```bash $ yarn start ``` -------------------------------- ### Install via Bun Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/installation.mdx Use this command to add react-hotkeys-hook to your project using Bun. ```shell bun i react-hotkeys-hook ``` -------------------------------- ### Install ts-key-enum Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/advanced-usage.mdx Install the ts-key-enum library to get type-safe key names for your hotkeys. ```bash npm install ts-key-enum ``` -------------------------------- ### Start Function Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/api/use-record-hotkeys.mdx The 'start' function, used to begin recording keystrokes. ```typescript start: () => void ``` -------------------------------- ### Install via NPM Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/installation.mdx Use this command to add react-hotkeys-hook to your project using NPM. ```shell npm i react-hotkeys-hook ``` -------------------------------- ### Install via Yarn Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/installation.mdx Use this command to add react-hotkeys-hook to your project using Yarn. ```shell yarn add react-hotkeys-hook ``` -------------------------------- ### Global Hotkeys Example Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/useHotkeys/scoping-hotkeys.mdx Demonstrates how two separate components listening for the same hotkey ('c') will both trigger when the key is pressed, as hotkeys are global by default. ```jsx function UnscopedHotkey() { const [count, setCount] = useState(0) useHotkeys('c', () => setCount(prevCount => prevCount + 1)) return (

The count is {count}.

) } function SecondUnscopedHotkey() { const [count, setCount] = useState(0) useHotkeys('c', () => setCount(prevCount => prevCount + 1)) return (

The count is {count}.

) } render(
) ``` -------------------------------- ### Example Usage of useRecordHotkeys with Blacklist Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/api/use-record-hotkeys.mdx An example of using useRecordHotkeys with a specified blacklist to ignore 'tab' and 'enter' keys. ```javascript const [keys, { start, stop }] = useRecordHotkeys(false, ['tab', 'enter']); ``` -------------------------------- ### Basic useRecordHotkeys Example Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/use-record-hotkeys.mdx Demonstrates the basic usage of useRecordHotkeys to record and display pressed keys. It returns a Set of keys and controls to manage the recording process. ```jsx function ExampleComponent() { const [keys, { start, stop, isRecording }] = useRecordHotkeys() return (

Is recording: {isRecording ? 'yes' : 'no'}

Recorded keys: {Array.from(keys).join(' + ')}


) } ``` -------------------------------- ### Developer Warning Example Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/AGENTS.md Shows how to use `console.warn` for developer-facing warnings that should appear in production code. ```javascript console.warn ``` -------------------------------- ### Basic Hotkey Combination Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/useHotkeys/basic-usage.mdx This example demonstrates how to use `useHotkeys` to listen for multiple key combinations. It increments a counter each time one of the specified hotkeys is pressed. Ensure you have `useState` imported from React. ```jsx function ExampleComponent() { const [count, setCount] = useState(0) useHotkeys( 'ctrl+shift+a+c, c, shift+c, alt+n, ctrl+d, meta+d', () => setCount(prevCount => prevCount + 1) ) return ( Received the combination {count} times. ) } ``` -------------------------------- ### Listen to Physical Key '!' (Shift+1) Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/useHotkeys/ignore-layouts.mdx This example demonstrates the default behavior of listening to the physical key combination 'shift+1' to trigger a hotkey. It's layout-independent. ```jsx function ExampleComponent() { const [count, setCount] = useState(0) useHotkeys('shift+1', () => setCount(prevCount => prevCount + 1)) return ( Pressed the '!' key {count} times. ) } ``` -------------------------------- ### Main Hook Export Example Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/AGENTS.md Illustrates the pattern of exporting the main hook as the default export from the library's entry point. ```typescript export default function useHotkeys() ``` -------------------------------- ### Define Hotkeys with Descriptions and Metadata Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/advanced-usage.mdx Register hotkeys with descriptions and custom metadata to build dynamic help panels. This example shows how to structure hotkey data and render it. ```tsx function useActiveHotkeys() { // You would collect this from your components or a registry const hotkeys = [ { keys: 'ctrl+s', description: 'Save document', scope: 'editor' }, { keys: 'ctrl+z', description: 'Undo', scope: 'editor' }, { keys: 'esc', description: 'Close modal', scope: 'modal' }, ]; return hotkeys; } function HelpPanel() { const hotkeys = useActiveHotkeys(); return (

Keyboard Shortcuts

); } ``` ```tsx useHotkeys('ctrl+s', handleSave, { description: 'Save the current document', metadata: { category: 'file' }, }); ``` -------------------------------- ### Basic Hotkey Usage Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/README.md Register a hotkey ('ctrl+k') to increment a counter. This example demonstrates the fundamental use of the `useHotkeys` hook. ```jsx import { useHotkeys } from 'react-hotkeys-hook' export const ExampleComponent = () => { const [count, setCount] = useState(0) useHotkeys('ctrl+k', () => setCount(prevCount => prevCount + 1)) return (

Pressed {count} times.

) } ``` -------------------------------- ### Optional Chaining Example Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/AGENTS.md Demonstrates the use of optional chaining (`?.`) to safely access nested properties that might be null or undefined. ```javascript e.target?.isContentEditable ``` -------------------------------- ### Listen to Produced Character '?' Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/useHotkeys/ignore-layouts.mdx This example uses `useKey: true` to listen for the produced character '?'. This is useful when the character itself is important, regardless of the physical keys pressed. ```jsx function ExampleComponent() { const [count, setCount] = useState(0) useHotkeys('?', () => setCount(prevCount => prevCount + 1), { useKey: true }) return ( Pressed '?' {count} times. ) } ``` -------------------------------- ### Stale State Example Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/useHotkeys/setting-callback-dependencies.mdx This example demonstrates the stale state problem where a hotkey callback references a state variable directly, leading to outdated values being used after the first update. ```jsx function ExampleComponent() { const [count, setCount] = useState(0) const ref = useHotkeys('b', () => setCount(count + 1)) return ( Pressed the 'b' key {count} times. ) } ``` -------------------------------- ### Listen to Produced Character '!' Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/useHotkeys/ignore-layouts.mdx This example uses the `useKey: true` option to listen for the produced character '!' regardless of the physical keys pressed. This approach is layout-dependent. ```jsx function ExampleComponent() { const [count, setCount] = useState(0) useHotkeys('!', () => setCount(prevCount => prevCount + 1), { useKey: true }) return ( Pressed the '!' key {count} times. ) } ``` -------------------------------- ### TODO Comment Example Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/AGENTS.md Example of a TODO comment used to mark future improvements or areas for refactoring. ```javascript // TODO: Make modifiers work with sequences ``` -------------------------------- ### Listen to '+' Character with Custom Split Key Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/useHotkeys/ignore-layouts.mdx This example demonstrates how to listen for the '+' character when it's used as a hotkey by changing the `splitKey` option to '-' to avoid conflicts with the default '+' split key. ```js // Listen to the '+' character by changing the splitKey useHotkeys('ctrl-+', addItem, { splitKey: '-' }) ``` -------------------------------- ### Listen to Physical Key ';' Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/useHotkeys/ignore-layouts.mdx This example shows how to listen to the physical key code 'Semicolon' to trigger a hotkey, ensuring layout independence. The code name is case-insensitive. ```jsx function ExampleComponent() { const [count, setCount] = useState(0) useHotkeys('Semicolon', () => setCount(prevCount => prevCount + 1)) return ( Pressed the ';' key {count} times. ) } ``` -------------------------------- ### Type-Only Import Example Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/AGENTS.md Demonstrates the use of `import type` for importing types only, which does not affect the JavaScript output. ```typescript import type { Hotkey } from './types' ``` -------------------------------- ### Basic Usage of useHotkeys Hook Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/intro.mdx Use the useHotkeys hook to bind a keyboard shortcut ('a') to a callback function that increments a counter. This example demonstrates a simple counter that updates when the 'a' key is pressed. ```jsx function MyComponent() { const [count, setCount] = useState(0); useHotkeys('a', () => setCount(count => count + 1)); return ( Pressed the 'a' key {count} times. ); } ``` -------------------------------- ### Biome Ignore Comment Example Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/AGENTS.md Demonstrates how to use a `biome-ignore` comment to bypass specific linting rules for a line of code. ```javascript // biome-ignore lint/correctness/useExhaustiveDependencies ``` -------------------------------- ### Type Guard Example Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/AGENTS.md Illustrates the use of a type guard function to narrow down the type of a variable within a conditional block. ```typescript isReadonlyArray(enabledOnTags) ``` -------------------------------- ### Create Custom Hooks for Editor Shortcuts Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/advanced-usage.mdx Encapsulate related hotkeys within a custom hook to maintain clean components and enforce consistent behavior. This example defines editor-specific shortcuts. ```tsx function useEditorShortcuts() { const { enableScope, disableScope } = useHotkeysContext(); useHotkeys('ctrl+s', saveDocument, { scopes: 'editor', preventDefault: true, description: 'Save document', }); useHotkeys('ctrl+z', undo, { scopes: 'editor', preventDefault: true, description: 'Undo', }); useHotkeys('ctrl+shift+z', redo, { scopes: 'editor', preventDefault: true, description: 'Redo', }); return { enableScope, disableScope }; } function Editor() { useEditorShortcuts(); return
{/* editor content */}
; } ``` -------------------------------- ### Generic Ref Example Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/AGENTS.md Shows how to use TypeScript generics with `useRef` to provide type safety for DOM elements or mutable values. ```typescript useRef(null) ``` -------------------------------- ### Custom Key Splitter for Key Combinations Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/api/use-hotkeys.mdx Change the default '+' character used to join keys in a combination if you need to listen for the '+' key itself. This example uses '-' as the splitter. ```javascript useHotkeys('ctrl-+', zoomIn, { splitKey: '-' }) ``` -------------------------------- ### Bind Hotkeys to a Specific Document in an Iframe Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/api/use-hotkeys.mdx This example demonstrates binding hotkey event listeners to a specific Document object obtained from within an iframe, useful for isolated contexts. ```javascript import FrameComponent from 'react-frame-component' const InsideFrameComponent = () => { const { document } = useFrame() useHotkeys("s", () => console.log("Triggered inside iframe"), { document }) return
....
} ``` -------------------------------- ### Control Scopes Programmatically Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/hotkeys-provider.mdx Use the `useHotkeysContext` hook to get functions for enabling, disabling, and toggling scopes. This allows for dynamic control over which hotkey groups are active. ```jsx import { useHotkeysContext } from 'react-hotkeys-hook'; function MyComponent() { const { enableScope, disableScope, toggleScope } = useHotkeysContext(); return (
) } ``` -------------------------------- ### Pass Custom Event Listener Options Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/advanced-usage.mdx Provide custom options to the underlying `addEventListener` call for fine-grained control over event propagation and behavior. This example sets `passive` and `capture` options. ```tsx useHotkeys('ctrl+s', handleSave, { eventListenerOptions: { passive: true, capture: true }, }); ``` -------------------------------- ### Build Documentation Site Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/AGENTS.md Builds the documentation site for the project. ```bash npm run build:documentation ``` -------------------------------- ### useHotkeys Function Signature Overloads Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/api/use-hotkeys.mdx Demonstrates how to pass a dependency array when no options are needed. ```APIDOC ## Function signature overloads If you want to pass a dependency array but do not need any options, you can pass the array as the third argument instead of the fourth: ```ts function useHotkeys( keys: string, callback: (event: KeyboardEvent, handler: HotkeysEvent) => void, deps: any[] = [] ): React.RefCallback ``` So instead of: ```js useHotkeys('a', () => someDependency, undefined, [someDependency]); ``` You can write: ```js useHotkeys('a', () => someDependency, [someDependency]); ``` ``` -------------------------------- ### Readonly Array Example Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/AGENTS.md Illustrates the use of the `readonly` modifier for arrays that should not be modified after initialization. ```typescript readonly FormTags[] ``` -------------------------------- ### Listen to Physical Key Combinations Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/useHotkeys/ignore-layouts.mdx Demonstrates listening to physical key combinations like 'ctrl+Equal', 'ctrl+Minus', and 'mod+Slash'. These are layout-independent. ```js useHotkeys('ctrl+Equal', zoomIn, { preventDefault: true }) useHotkeys('ctrl+Minus', zoomOut, { preventDefault: true }) useHotkeys('mod+Slash', toggleComment) ``` -------------------------------- ### useKey Parameter Explanation Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/api/use-record-hotkeys.mdx Demonstrates the behavior of the 'useKey' parameter, which determines whether to record physical keys or produced characters. ```typescript useKey: boolean // default: false ``` -------------------------------- ### Use Hotkeys with Dependency Array Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/README.md Demonstrates using the `useHotkeys` hook with a dependency array as the third parameter when no special options are needed. ```javascript useHotkeys('ctrl+k', () => console.log(counter + 1), [counter]) ``` -------------------------------- ### Build Main Library Package Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/AGENTS.md Builds the main library package located in packages/react-hotkeys-hook. ```bash npm run build ``` -------------------------------- ### useHotkeys Hook with Dependencies Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/react-hotkeys-hook/README.md Demonstrates the use of the useHotkeys hook with a dependency list. The callback is memoized, so external variables used within it should be included in the dependency array to ensure updates. ```javascript import { useHotkeys } from 'react-hotkeys-hook'; function MyComponent() { const [count, setCount] = React.useState(0); useHotkeys('ctrl+s', () => { console.log('The count is: ', count); }, [count]); return ( ); } ``` -------------------------------- ### Build Static Content Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/README.md Generates static files in the build directory for production hosting. ```bash $ yarn build ``` -------------------------------- ### Listen to Produced Characters for Symbols Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/useHotkeys/ignore-layouts.mdx Shows how to listen for produced characters like '+', '=', and '/' using `useKey: true`. This approach is layout-dependent. ```js useHotkeys('+', addItem, { useKey: true }) useHotkeys('=', resetZoom, { useKey: true }) useHotkeys('/', focusSearch, { useKey: true }) ``` -------------------------------- ### Deploy to GitHub Pages Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/README.md Commands to deploy the site to the gh-pages branch, with options for SSH or HTTPS authentication. ```bash $ USE_SSH=true yarn deploy ``` ```bash $ GIT_USER= yarn deploy ``` -------------------------------- ### Scoping Hotkeys to an Element Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/api/use-hotkeys.mdx Attach the ref callback returned by `useHotkeys` to an element to make the hotkey only active when that element or its children have focus. This example demonstrates scoping hotkeys to a specific button. ```jsx function App() { const [count, setCount] = useState(0); const ref = useHotkeys("s", () => setCount((prevCount) => prevCount + 1)); return (
Count: {count}
); } ``` -------------------------------- ### Simplified useHotkeys Signature with Dependency Array Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/api/use-hotkeys.mdx When only a dependency array is needed and no options, it can be passed as the third argument instead of the fourth. This simplifies the signature for common cases. ```ts function useHotkeys( keys: string, callback: (event: KeyboardEvent, handler: HotkeysEvent) => void, deps: any[] = [] ): React.RefCallback // Instead of: // useHotkeys('a', () => someDependency, undefined, [someDependency]); // You can write: // useHotkeys('a', () => someDependency, [someDependency]); ``` -------------------------------- ### Listen to All Keys Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/api/use-hotkeys.mdx Use the '*' wildcard to listen for any key press. The handler provides information about the pressed key. ```jsx useHotkeys('*', (_, handler) => alert(handler.key)) ``` -------------------------------- ### useHotkeys Options Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/api/use-hotkeys.mdx Configuration options for the useHotkeys hook. ```APIDOC ## `enabled` ### Description Determines if the callback should be triggered. Pass `false` to disable the hotkey entirely, or a function that receives the keyboard event and returns `true` or `false`. When `enabled` is a boolean `false`, the event listeners are removed from the DOM. When `enabled` is a function that returns `false`, the listeners stay attached but the callback is skipped. ### Type `Trigger` (boolean | (e: KeyboardEvent) => boolean) ### Default `true` ## `enableOnFormTags` ### Description By default, hotkeys are disabled while the user is focused on a form element. Set this to `true` to enable hotkeys on all form tags, or pass an array of specific tags. ### Type `FormTags[] | boolean` ### Default `false` ### Example ```js useHotkeys('ctrl+s', save, { enableOnFormTags: ['input', 'textarea', 'select'] }) ``` ## `enableOnContentEditable` ### Description Enable hotkeys on elements with the `contentEditable` attribute. ### Type `boolean` ### Default `false` ## `ignoreEventWhen` ### Description Fine-grained control over which events to ignore. Return `true` from the function to skip handling the event. ### Type `(e: KeyboardEvent) => boolean` ### Example ```js useHotkeys('a', someCallback, { ignoreEventWhen: (e) => { return e.target.className.includes('special-element') }, }) ``` ## `splitKey` ### Description The character that joins keys within a single combination. The default is `+`, so `shift+a` triggers when the user presses Shift **and** A together. Change this if you need to listen for the `+` key itself. ### Type `string` ### Default `"+"` ### Example ```js useHotkeys('ctrl-+', zoomIn, { splitKey: '-' }) ``` ## `delimiter` ### Description The character that separates different hotkey combinations mapped to the same callback. The default is `,`, so `ctrl+a, shift+b` listens for either combination. ### Type `string` ### Default `","` ## `sequenceSplitKey` ### Description The character that separates keys in a sequential hotkey. The default is `>`, so `g>h>i` requires pressing G, then H, then I in sequence. ### Type `string` ### Default `">"` ## `scopes` ### Description Assign the hotkey to one or more scopes. Scopes let you group hotkeys and enable or disable them together via `HotkeysProvider`. See the [Grouping Hotkeys](/docs/documentation/hotkeys-provider) documentation for details. ### Type `string | string[]` ### Default `"*"` ## `keyup` ### Description Trigger the callback on the browser's `keyup` event. ### Type `boolean` ### Default `false` ## `keydown` ### Description Trigger the callback on the browser's `keydown` event. This is the default. ### Type `boolean` ### Default `true` ### Tip Listening to both `keydown` and `keyup` If you set `keyup: true` without explicitly setting `keydown`, the hook assumes you only want `keyup`. To listen to both, set both options: ```js useHotkeys('a', callback, { keydown: true, keyup: true }) ``` ## `preventDefault` ### Description Prevent the browser's default behavior for the matched keystroke. Useful for overriding shortcuts like `meta+s` (save page). ### Type `Trigger` (boolean | (e: KeyboardEvent) => boolean) ### Default `false` ### Example ```js useHotkeys('meta+s', someCallback, { preventDefault: true, }); ``` ## `description` ### Description A human-readable description of what the hotkey does. Useful for building help panels or shortcut reference lists. ### Type `string` ### Default `undefined` ## `document` ### Description Bind the event listeners to a specific `Document` object instead of the global `document`. Useful for apps running inside iframes. ### Type `Document` ### Default `undefined` ### Example ```js import FrameComponent from 'react-frame-component' const InsideFrameComponent = () => { const { document } = useFrame() useHotkeys("s", () => console.log("Triggered inside iframe"), { document }) return
....
} ``` ``` -------------------------------- ### Run Biome Linter with Auto-fix Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/AGENTS.md Runs the Biome linter across all packages and automatically fixes linting issues. ```bash npm run lint ``` -------------------------------- ### Build Library Package Only Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/AGENTS.md Builds only the library package using TypeScript and Vite. ```bash npm run -w packages/react-hotkeys-hook build ``` -------------------------------- ### Making Non-focusable Elements Focusable for Hotkeys Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/api/use-hotkeys.mdx For non-focusable elements like `div` or `span`, add the `tabIndex={0}` prop to allow them to receive focus and thus trigger scoped hotkeys. This example shows how to make divs focusable. ```jsx function App() { const [count, setCount] = useState(0); const ref = useHotkeys("s", () => setCount((prevCount) => prevCount + 1)); return (
Count: {count}
Focusing this area won't trigger the hotkey.
Focusing this area will trigger the hotkey.
); } ``` -------------------------------- ### Run All Tests Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/AGENTS.md Executes all tests in the project, which are run using Vitest in the packages/react-hotkeys-hook package. ```bash npm run test ``` -------------------------------- ### Check for Pressed Modifier Keys in Callbacks Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/is-hotkey-pressed.mdx Use isHotkeyPressed within event callbacks to conditionally alter behavior based on modifier key states. For example, modify a click handler's action if the 'shift' key is held. ```jsx function ExampleComponent() { const [count, setCount] = useState(0); const onClick = () => isHotkeyPressed('shift') ? setCount(count => count - 1) : setCount(count => count + 1); return (

The count is: {count}

Hold Shift while clicking to decrease.

) } ``` -------------------------------- ### Custom Metadata for Hotkeys Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/typescript.mdx Demonstrates attaching custom metadata, such as a description and category, to hotkeys for use cases like building a help panel. ```typescript useHotkeys('ctrl+s', handleSave, { description: 'Save the current document', metadata: { category: 'file', showInHelp: true }, }); ``` -------------------------------- ### Run Biome Formatter Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/AGENTS.md Runs the Biome formatter across all packages to ensure consistent code style. ```bash npm run format ``` -------------------------------- ### Import Hook via CDN Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/installation.mdx Import the ES Module directly from unpkg.com for use in your project. ```js import { useHotkeys } from 'https://unpkg.com/react-hotkeys-hook@latest/dist/react-hotkeys-hook.esm.js'; ``` -------------------------------- ### Listen to Produced Character (v5 with useKey) Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/migrate-to-5.mdx To replicate v4's behavior of listening to the produced character (layout-dependent), set the `useKey` option to `true` in v5. ```javascript useHotkeys('!', callback, { useKey: true }) ``` -------------------------------- ### Format Packages with Write Directly Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/AGENTS.md Formats the packages directory and writes changes directly to the files. ```bash npx @biomejs/biome format --write packages ``` -------------------------------- ### useHotkeys Options Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/api/use-hotkeys.mdx Configuration options for the useHotkeys hook to customize its behavior. ```APIDOC ## `ignoreModifiers` ```ts ignoreModifiers: boolean // default: false ``` Ignore modifier keys (`shift`, `alt`, `ctrl`, `meta`) when matching hotkeys. Useful when you want to listen for a character regardless of how it is typed — for example, listening for `/` to focus a search field, whether the user presses the dedicated `/` key or `shift+7` on some layouts. ## `useKey` ```ts useKey: boolean // default: false ``` Listen to the produced character instead of the physical key code. Useful when you want to match a specific symbol (like `!` or `?`) regardless of which physical keys produce it on the user's layout. ## `sequenceTimeoutMs` ```ts sequenceTimeoutMs: number // default: 1000 ``` The time window in milliseconds for sequential hotkeys. If the user does not press the next key within this window, the sequence resets. ## `eventListenerOptions` ```ts eventListenerOptions: EventListenerOptions // default: undefined ``` Pass custom options to the underlying `addEventListener` call, such as `{ passive: true }` or `{ capture: true }`. ## `metadata` ```ts metadata: Record // default: undefined ``` Attach arbitrary custom data to the hotkey. You can retrieve it from the `handler` object in the callback (`handler.metadata`). Useful for building dynamic shortcut registries or help panels. ## `deps` ```ts deps: any[] // default: [] ``` Dependency array for the callback, just like React's `useCallback` or `useMemo`. If your callback references unstable or changing values, add them here so the callback stays up to date. ``` -------------------------------- ### Typed Options for Hotkey Configuration Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/typescript.mdx Illustrates the fully typed `options` object, providing autocomplete and type checking for configuration properties like `enabled`, `preventDefault`, `scopes`, and `enableOnFormTags`. ```typescript useHotkeys('ctrl+s', handleSave, { enabled: true, preventDefault: true, scopes: ['editor'], enableOnFormTags: ['input', 'textarea'], }); ``` -------------------------------- ### useRecordHotkeys with Blacklist Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/use-record-hotkeys.mdx Shows how to use useRecordHotkeys while ignoring specific keys like 'tab' and 'enter' by passing a blacklist array. Blacklisted keys retain their default behavior. ```jsx function ExampleWithBlacklist() { const [keys, { start, stop, resetKeys, isRecording }] = useRecordHotkeys(false, ['tab', 'enter']); return (

Recording (ignoring Tab and Enter): {isRecording ? 'yes' : 'no'}

Recorded keys: {Array.from(keys).join(' + ')}

); } ``` -------------------------------- ### Listen to Physical Keystroke (v5 Default) Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/migrate-to-5.mdx In v5, useHotkeys listens to physical key codes by default. Use this when you want layout-independent hotkey detection. ```javascript useHotkeys('shift+1', callback) ``` -------------------------------- ### Set Initially Active Scopes Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/hotkeys-provider.mdx Initialize the `HotkeysProvider` with specific scopes already active by passing an array of scope names to the `initiallyActiveScopes` prop. Remember to include '*' if you want the wildcard scope to be active by default. ```jsx import { HotkeysProvider } from 'react-hotkeys-hook'; function App() { return (

My App

) } ``` -------------------------------- ### Bind Key Combinations Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/useHotkeys/basic-usage.mdx Listen for key combinations, such as 'Shift+C', to trigger a callback. This is useful for shortcuts like creating new items. ```jsx function CreateIssue() { const [showIssueCreatorModal, setShowIssueCreatorModal] = useState(false) useHotkeys('shift+c', () => setShowIssueCreatorModal(true)) return ( <> {showIssueCreatorModal &&
MODAL CONTENT
} {!showIssueCreatorModal &&
issue list
} ) } ``` -------------------------------- ### Run Tests Once (No Watch Mode) Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/AGENTS.md Runs tests in the library package once without entering watch mode. ```bash npm run -w packages/react-hotkeys-hook vitest run ``` -------------------------------- ### Migrate useHotkeys Options: combinationKey and splitKey Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/migrate-to-5.mdx In v5, `combinationKey` is renamed to `splitKey` and `splitKey` is renamed to `delimiter`. This snippet shows the v4 to v5 option mapping. ```javascript // v4 useHotkeys('ctrl+a, shift+b', callback, { combinationKey: '-', splitKey: ';' }) // v5 useHotkeys('ctrl+a, shift+b', callback, { splitKey: '-', delimiter: ';' }) ``` -------------------------------- ### Listen to Both Keydown and Keyup Events Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/api/use-hotkeys.mdx To trigger callbacks on both 'keydown' and 'keyup' events, explicitly set both options to true. If only 'keyup' is true, 'keydown' is implicitly false. ```javascript useHotkeys('a', callback, { keydown: true, keyup: true }) ``` -------------------------------- ### Combine 'enabled' and 'preventDefault' Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/useHotkeys/disable-hotkeys.mdx Demonstrates combining the 'enabled' option (set to always return false) with 'preventDefault: true'. This ensures the hotkey is disabled and default browser behavior is prevented. ```jsx function ExampleComponent() { useHotkeys('meta+s', () => alert('We saved your progress!'), { enabled: () => false, preventDefault: true, }) return (

Press cmd+s (or ctrl+s on non-Mac) to open the custom save dialog.

) } ``` -------------------------------- ### Blacklist Parameter Explanation Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/api/use-record-hotkeys.mdx Details the 'blacklist' parameter, an array of key names to ignore during recording. ```typescript blacklist: string[] // default: [] ``` -------------------------------- ### useHotkeys(keys, callback) Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/README.md The useHotkeys hook allows you to easily bind keyboard shortcuts to functions within your React components. It takes a keys argument, which can be a single key or an array of keys, and a callback function that will be executed when the keys are pressed. The dependencies array ensures that the callback is memoized correctly, similar to React's useCallback hook. ```APIDOC ## useHotkeys(keys, callback) ### Description This hook binds keyboard shortcuts to a callback function. The `keys` argument specifies which key combination triggers the callback, and the `callback` function contains the logic to be executed. A `dependencies` array is used for memoization, ensuring the callback updates when referenced variables change. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **keys**: (string | string[]) - Required - The key or array of keys to listen for. - **callback**: (function) - Required - The function to execute when the keys are pressed. - **dependencies**: (DependencyList) - Optional - An array of dependencies for the callback, similar to `useCallback`. ### Request Example ```javascript useHotkeys('ctrl+s', () => { console.log('Saved!'); }, [someVariable]); ``` ### Response This hook does not return a value directly. Its effect is to bind the hotkey. #### Success Response (200) N/A #### Response Example N/A ``` -------------------------------- ### Typing the Ref for Scoped Hotkeys Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/typescript.mdx Shows how to type the returned ref using `useHotkeys` for full type safety when scoping hotkeys to a specific element. ```tsx import { useHotkeys } from "react-hotkeys-hook"; import { useState } from "react"; interface Props { hotKey: string; } const MyComponent = ({ hotKey }: Props) => { const [count, setCount] = useState(0); const ref = useHotkeys( hotKey, () => setCount(prevCount => prevCount + 1) ); return (
The count is {count}.
) } ``` -------------------------------- ### Use Function Keys Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/api/use-hotkeys.mdx Bind actions to function keys like F1, F5, etc. ```jsx useHotkeys('f5', () => alert('F5 was pressed')) ``` -------------------------------- ### Run Tests Matching Name Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/AGENTS.md Executes tests whose names match the specified string. ```bash npx vitest run -t "should listen to key presses" ``` -------------------------------- ### Importing useRecordHotkeys Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/use-record-hotkeys.mdx Import the useRecordHotkeys hook from the 'react-hotkeys-hook' package. ```javascript import { useRecordHotkeys } from 'react-hotkeys-hook'; ``` -------------------------------- ### Run Single Test Matching Pattern Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/AGENTS.md Executes a single test whose name matches the provided pattern. ```bash npx vitest run --testNamePattern "test name" ``` -------------------------------- ### useRecordHotkeys Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/api/use-record-hotkeys.mdx Records keystrokes and provides controls to manage the recording process. It returns a Set of recorded keys and an object with methods to control recording. ```APIDOC ## `useRecordHotkeys` ### Description Records keystrokes and provides controls to manage the recording process. It returns a Set of recorded keys and an object with methods to control recording. ### Signature ```ts function useRecordHotkeys(useKey?: boolean, blacklist?: string[]): [Set, { start: () => void, stop: () => void, resetKeys: () => void, isRecording: boolean }] ``` ### Parameters #### `useKey` - **Type**: `boolean` - **Default**: `false` - **Description**: If `true`, records the produced character instead of the physical key code. For example, `useKey: false` records "shift+1" for Shift+1, while `useKey: true` records "!" for Shift+1 on a US layout. #### `blacklist` - **Type**: `string[]` - **Default**: `[]` - **Description**: An array of key names to ignore while recording. Blacklisted keys retain their default behavior and are not added to the recorded set. ### Return Value Returns a tuple containing: 1. **`keys`** (`Set`): A `Set` of the keys that have been recorded. Each key appears only once. Use `Array.from(keys)` to convert it to an array. 2. **`controls`** (`object`): An object with the following methods and properties: * **`start`** (`() => void`): Begins recording keystrokes. * **`stop`** (`() => void`): Stops recording keystrokes. * **`resetKeys`** (`() => void`): Clears the recorded keys. * **`isRecording`** (`boolean`): `true` while recording is active, `false` otherwise. ### Example ```js const [keys, { start, stop, resetKeys, isRecording }] = useRecordHotkeys(false, ['tab', 'enter']); ``` ``` -------------------------------- ### Hotkey Scopes with HotkeysProvider Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/README.md Use scopes to group hotkeys and manage their activation. The `HotkeysProvider` must wrap the application or relevant part of it. ```jsx const App = () => { return ( ) } export const ExampleComponent = () => { const [count, setCount] = useState(0) useHotkeys('ctrl+k', () => setCount(prevCount => prevCount + 1), { scopes: ['settings'] }) return (

Pressed {count} times.

) } ``` -------------------------------- ### useHotkeys(keys, callback) Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/README.md The useHotkeys hook allows you to easily define keyboard shortcuts within your React components. It accepts a keys configuration, a callback function to execute when the keys are pressed, and optional configuration options. ```APIDOC ## useHotkeys(keys, callback) ### Description This hook registers keyboard shortcuts within a React component. It listens for specified key combinations and executes a provided callback function when those combinations are detected. ### Method `useHotkeys` (Hook) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters #### `keys` - **Type**: `string` or `string[]` - **Required**: Yes - **Description**: Defines the hotkeys to listen for. Can be a single key, multiple keys separated by commas, or an array of key strings. Modifier combinations are supported. #### `callback` - **Type**: `(event: KeyboardEvent, handler: HotkeysEvent) => void` - **Required**: Yes - **Description**: The function to be executed when the specified hotkeys are pressed. It receives the native `KeyboardEvent` and a `HotkeysEvent` object. #### `options` - **Type**: `Options` - **Required**: No - **Default value**: `{}` - **Description**: An object to customize the hook's behavior. Refer to the library's documentation for available options. #### `deps` - **Type**: `DependencyList` - **Required**: No - **Default value**: `[]` - **Description**: An array of dependencies, similar to React's `useEffect` hook, to control when the hotkey listener should re-register. ### Request Example ```javascript useHotkeys('ctrl+s, meta+s', (event, handler) => { // Handle save action console.log('Save shortcut pressed!'); }, [saveAction]); ``` ### Response This hook does not return a value directly, but triggers the callback function when hotkeys are pressed. ``` -------------------------------- ### Using Dependency Array with useHotkeys Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/useHotkeys/setting-callback-dependencies.mdx Provide a dependency array to useHotkeys to ensure the callback uses the latest values of external references like memoized values, props, or state. This prevents stale state issues when the callback relies on values that change over time. ```jsx function ExampleComponent() { const [count, setCount] = useState(0) const squaredCount = useMemo(() => count * 2, [count]) const ref = useHotkeys('b', () => setCount(squaredCount + 1), [squaredCount]) return ( Pressed the 'b' key {squaredCount} times. ) } ``` -------------------------------- ### Run Specific Test File Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/AGENTS.md Executes all tests contained within a specific test file. ```bash npx vitest run src/test/useHotkeys.test.tsx ``` -------------------------------- ### Multiple Key Combinations Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/api/use-hotkeys.mdx Define a single callback for multiple independent key combinations. ```jsx useHotkeys('w, a, s, d', () => alert('Player moved!')) ``` -------------------------------- ### Differentiate Hotkeys with Object Values Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/api/use-hotkeys.mdx Use an object to define hotkeys and their corresponding actions. The `hotkey` property in the handler identifies the matched shortcut. ```jsx const HOTKEYS = { ACTION_A: 'ctrl+a', ACTION_B: 'shift+b', } useHotkeys(Object.values(HOTKEYS), (_, { hotkey }) => { switch (hotkey) { case HOTKEYS.ACTION_A: alert('You pressed ctrl+a!'); break; case HOTKEYS.ACTION_B: alert('You pressed shift+b!'); break; } }) ``` -------------------------------- ### Run Tests in Library Package Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/AGENTS.md Executes tests specifically within the library package. ```bash npm run -w packages/react-hotkeys-hook test ``` -------------------------------- ### Sequential Hotkeys Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/useHotkeys/basic-usage.mdx Listen for keys pressed in sequence using the '>' character. The callback is triggered only after the entire sequence is completed. ```jsx function ExampleComponent() { const [count, setCount] = useState(0) useHotkeys('g>h>i', () => setCount(prevCount => prevCount + 1)) return ( Received the combination {count} times. ) } ``` -------------------------------- ### Recording Produced Characters with useRecordHotkeys Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/use-record-hotkeys.mdx Configures useRecordHotkeys to record the produced characters (e.g., '!') instead of key codes (e.g., 'shift+1') by passing true as the first argument. ```jsx const [keys, controls] = useRecordHotkeys(true); // records characters like "!" instead of "shift+1" ``` -------------------------------- ### Import isHotkeyPressed Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/is-hotkey-pressed.mdx Import the isHotkeyPressed function from the 'react-hotkeys-hook' package before use. ```javascript import { isHotkeyPressed } from 'react-hotkeys-hook'; ``` -------------------------------- ### Type-Safe Key Names with TypeScript Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/typescript.mdx Demonstrates how TypeScript catches incorrect types for the `keys` argument at compile time. Ensure the `hotKey` prop is a string or array of strings. ```tsx import { useHotkeys } from "react-hotkeys-hook"; import { useState } from "react"; interface Props { hotKey: number; // ❌ wrong type } const MyComponent = ({ hotKey }: Props) => { const [count, setCount] = useState(0); // TypeScript error: hotKey must be a string useHotkeys(hotKey, () => setCount(prevCount => prevCount + 1)); return (
The count is {count}.
) } ``` -------------------------------- ### Migrate HotkeysProvider Context: enabledScopes to activeScopes Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/migrate-to-5.mdx The `enabledScopes` property from `useHotkeysContext` has been renamed to `activeScopes` in v5 to avoid confusion. ```javascript // v4 const { enabledScopes } = useHotkeysContext() // v5 const { activeScopes } = useHotkeysContext() ``` -------------------------------- ### Bind Multiple Keys to One Callback Source: https://github.com/johannesklauss/react-hotkeys-hook/blob/main/packages/documentation/docs/documentation/useHotkeys/basic-usage.mdx Bind several different key combinations to the same callback function by separating them with a comma or by passing an array. ```jsx function ExampleComponent() { const [count, setCount] = useState(0) useHotkeys('ctrl+shift+a+c, c, shift+c', () => setCount(prevCount => prevCount + 1)) return ( Received the combination {count} times. ) } ```