{"id":15652877,"url":"https://github.com/blakeembrey/keyboard-manager","last_synced_at":"2025-04-30T07:05:08.221Z","repository":{"id":48071380,"uuid":"103583626","full_name":"blakeembrey/keyboard-manager","owner":"blakeembrey","description":"Small keyboard shortcut management for DOM-based applications","archived":false,"fork":false,"pushed_at":"2023-12-12T06:55:54.000Z","size":378,"stargazers_count":30,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-30T07:03:22.354Z","etag":null,"topics":["character","dom","keyboard-manager","keyboard-shortcuts","reactjs","typescript"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/blakeembrey.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-09-14T21:30:41.000Z","updated_at":"2024-01-11T22:42:04.000Z","dependencies_parsed_at":"2024-06-19T16:03:26.392Z","dependency_job_id":"60f122de-e3fc-400c-b445-876245f43a33","html_url":"https://github.com/blakeembrey/keyboard-manager","commit_stats":{"total_commits":40,"total_committers":4,"mean_commits":10.0,"dds":0.25,"last_synced_commit":"9c96266af9911f82492c7721892ef5f85683acf4"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blakeembrey%2Fkeyboard-manager","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blakeembrey%2Fkeyboard-manager/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blakeembrey%2Fkeyboard-manager/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blakeembrey%2Fkeyboard-manager/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/blakeembrey","download_url":"https://codeload.github.com/blakeembrey/keyboard-manager/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251658201,"owners_count":21622819,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["character","dom","keyboard-manager","keyboard-shortcuts","reactjs","typescript"],"created_at":"2024-10-03T12:44:08.296Z","updated_at":"2025-04-30T07:05:08.183Z","avatar_url":"https://github.com/blakeembrey.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Keyboard Manager\n\n[![NPM version][npm-image]][npm-url]\n[![NPM downloads][downloads-image]][downloads-url]\n[![Build status][build-image]][build-url]\n[![Build coverage][coverage-image]][coverage-url]\n[![Bundle size][size-image]][size-url]\n\n\u003e Small keyboard shortcut management for DOM-based applications.\n\n## Installation\n\n```\nnpm install keyboard-manager --save\n```\n\n## Usage\n\n**Keyboard Manager** uses a simple queue, processed from newest to oldest, of listener functions to execute keyboard shortcuts. Keyboard event propagation stops when handled, but returning `true` from the listener will continue propagation to older listeners.\n\n```js\nimport { Keyboard, stringifyKey, createShortcuts } from \"keyboard-manager\";\n\nconst keyboard = new Keyboard();\nconst shortcut1 = stringifyKey(\"cmd\", \"a\"); //=\u003e \"65 91\"\nconst shortcut2 = stringifyKey(\"cmd\", \"up\"); //=\u003e \"38 91\"\n\n// Bind event listeners to all combos or specific keys using `createShortcuts`.\nkeyboard.addListener(\n  createShortcuts({\n    [shortcut1]: (e) =\u003e e.preventDefault(),\n    [shortcut2]: (e) =\u003e e.preventDefault(),\n  })\n);\n\n// Attach event listener to document.\nwindow.addEventListener(\"keydown\", keyboard.getHandler(), false);\n\n// Mount a keyboard inside another listener.\nnew Keyboard().addListener(keyboard.getListener());\n```\n\n### Stringify Key\n\nThe `stringifyKey(...keys)` function returns a consistent identity string for the keyboard shortcut. Internally, `keyboardEventCombo(e)` will map keyboard events to the matching string.\n\n### Create Shortcuts\n\nThe `createShortcuts(map [, returnValue])` function accepts a map of keyboard shortcut functions and returns a single listener function for mounting with `keyboard.addListener(callback)`.\n\n**Tip:** `returnValue` defaults to `true` for propagation. Setting to `false` will stop propagation, effectively creating a new shortcut \"scope\". This is useful for features, such as full-screen modals or recording keyboard shortcuts, where key presses should not interact with the rest of the document.\n\n### Filter Input Event\n\nWrap any listener in `filterInputEvent(callback)` to automatically ignore and propagate events originating from an input-like element (`\u003cinput /\u003e`, `\u003cselect /\u003e`, `\u003ctextarea /\u003e` or content-editable elements).\n\n```js\nimport {\n  stringifyKey,\n  createShortcuts,\n  filterInputEvent,\n} from \"keyboard-manager\";\n\nconst listener = createShortcuts({\n  [stringifyKey(\"a\")]: filterInputEvent((e) =\u003e e.preventDefault()),\n});\n```\n\n### Combined Shortcuts Pattern\n\n```js\nconst dispatcher = new Keyboard()\n\n// Create two `Keyboard` instances, allowing globally unhandled shortcuts\n// to propagate into application shortcuts (i.e. OS-like functionality).\nconst appKeyboard = new Keyboard()\nconst globalKeyboard = new Keyboard()\n\n// Dispatch order is determined by listeners, recent listeners execute first.\ndispatcher.addListener(appKeyboard.getListener())\ndispatcher.addListener(globalKeyboard.getListener()))\n```\n\n## How?\n\n**Keyboard Manager** serializes each `keydown` event to the character (`e.key`) and modifiers (`e.shiftKey`, `e.ctrlKey`, `e.altKey`, `e.metaKey`). For example, `cmd + a` maps to `meta a`.\n\n### Why not use `keydown` and `keyup` for infinite key combos?\n\n1. Mac OS doesn't emit `keyup` events while `cmd` is pressed.\n2. The DOM won't receive a `keyup` event when you lose focus on the window.\n3. Keyboard shortcuts don't need to combine non-modifier characters.\n\n## TypeScript\n\nThis project is written using [TypeScript](https://github.com/Microsoft/TypeScript) and publishes the definitions directly to NPM.\n\n## License\n\nApache 2.0\n\n[npm-image]: https://img.shields.io/npm/v/keyboard-manager\n[npm-url]: https://npmjs.org/package/keyboard-manager\n[downloads-image]: https://img.shields.io/npm/dm/keyboard-manager\n[downloads-url]: https://npmjs.org/package/keyboard-manager\n[build-image]: https://img.shields.io/github/workflow/status/blakeembrey/keyboard-manager/CI/main\n[build-url]: https://github.com/blakeembrey/keyboard-manager/actions/workflows/ci.yml?query=branch%3Amain\n[coverage-image]: https://img.shields.io/codecov/c/gh/blakeembrey/keyboard-manager\n[coverage-url]: https://codecov.io/gh/blakeembrey/keyboard-manager\n[size-image]: https://img.shields.io/bundlephobia/minzip/keyboard-manager\n[size-url]: https://bundlephobia.com/result?p=keyboard-manager\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblakeembrey%2Fkeyboard-manager","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fblakeembrey%2Fkeyboard-manager","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblakeembrey%2Fkeyboard-manager/lists"}