hotkey-router 0.2.3 → 0.3.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.
package/README.md CHANGED
@@ -3,8 +3,9 @@
3
3
  [![npm](https://img.shields.io/npm/v/hotkey-router)](https://www.npmjs.com/package/hotkey-router)
4
4
  [![downloads](https://img.shields.io/npm/dm/hotkey-router)](https://www.npmjs.com/package/hotkey-router)
5
5
  [![bundle size](https://img.shields.io/bundlephobia/minzip/hotkey-router)](https://bundlephobia.com/package/hotkey-router)
6
- [![license](https://img.shields.io/npm/l/hotkey-router)](https://github.com/iWhatty/hotkey-router-js/blob/main/LICENSE)
7
- [![stars](https://img.shields.io/github/stars/iWhatty/hotkey-router-js?style=social)](https://github.com/iWhatty/hotkey-router-js)
6
+ [![license](https://img.shields.io/npm/l/hotkey-router)](https://github.com/iWhatty/hotkey-router/blob/main/LICENSE)
7
+ [![stars](https://img.shields.io/github/stars/iWhatty/hotkey-router?style=social)](https://github.com/iWhatty/hotkey-router)
8
+ [![types](https://img.shields.io/npm/types/hotkey-router)](https://www.npmjs.com/package/hotkey-router)
8
9
 
9
10
  A tiny, deterministic keyboard routing engine for modern web apps. Not a key utility, a predictable plugin-first routing layer for keyboard shortcuts.
10
11
 
@@ -113,9 +114,17 @@ off()
113
114
  allowIn?: (event) => boolean
114
115
  priority?: number // default 0
115
116
  warnOnReserved?: boolean // only read when conflict warnings are installed
117
+ capture?: boolean // v0.3.0+: run in the capture phase, before the page's listeners
118
+ altGraph?: boolean // v0.3.0+: also fire on an AltGr keystroke that types a character
119
+ composing?: boolean // v0.3.0+: also fire during IME composition
116
120
  }
117
121
  ```
118
122
 
123
+ By default (v0.3.0+), a binding is skipped when the keystroke is AltGr typing
124
+ a character (Windows reports AltGr as Ctrl+Alt, so `ctrl+alt+code:Comma`
125
+ would otherwise swallow the `<` a Polish or Czech user typed) and while an
126
+ IME is composing.
127
+
119
128
  **Examples**
120
129
 
121
130
  Ignore repeat keydown (default behavior):
@@ -218,6 +227,27 @@ hotkeys.init({
218
227
 
219
228
  Auto-initializes on `window` by default (browser environments).
220
229
 
230
+ With `capture: false` (the default), bindings run in the bubble phase except
231
+ those bound with `{ capture: true }`, which a second, capture-phase listener
232
+ handles (v0.3.0+). `capture: true` here runs every binding in the capture
233
+ phase.
234
+
235
+ ### `parseHotkey(hotkey)` / `comboFromEvent(event, options?)` (v0.3.0+)
236
+
237
+ Named exports (also on the default object). `comboFromEvent` turns a
238
+ keyboard event into a hotkey string for a "press your keys" recorder:
239
+ physical by default, `{ useMod: true }` writes the platform's primary
240
+ modifier as `mod`, and it returns `null` while only a modifier is held.
241
+
242
+ ```js
243
+ import { comboFromEvent } from 'hotkey-router'
244
+
245
+ input.addEventListener('keydown', (e) => {
246
+ const combo = comboFromEvent(e, { useMod: true }) // 'mod+shift+code:Period'
247
+ if (combo) save(combo)
248
+ })
249
+ ```
250
+
221
251
  ### `destroy()`
222
252
 
223
253
  Removes all listeners and clears internal state.
@@ -363,6 +393,73 @@ const off = hotkeys.onBind(({ combo, raw, options, plugin, id }) => {
363
393
  // off() unsubscribes.
364
394
  ```
365
395
 
396
+ ### Website shortcuts (v0.3.0+)
397
+
398
+ Apps that run on other people's pages (browser extensions, embedded widgets)
399
+ collide with the page's own shortcuts: Google Docs uses Ctrl+Shift+. for font
400
+ size, GitHub for "quote". Unlike browser keys, those reach the page, so the
401
+ app can choose. `hotkey-router/sites` knows which popular sites use which
402
+ chords in the Ctrl/Cmd+Shift, Ctrl/Cmd+Alt, Shift+Alt and Ctrl/Cmd+Alt+Shift
403
+ families ([docs/site-hotkeys.md](docs/site-hotkeys.md), sourced data in
404
+ `data/site-hotkeys.json`) and builds a `when()` gate that yields to the site
405
+ unless the user is focused on the app:
406
+
407
+ ```js
408
+ import hotkeys from 'hotkey-router'
409
+ import { siteAware } from 'hotkey-router/sites'
410
+
411
+ hotkeys.bind('mod+shift+code:Period', nextTypo, null, {
412
+ capture: true, // see the key before the page's editor
413
+ preventDefault: true,
414
+ stopPropagation: true, // when we take it, the page doesn't run it too
415
+ allowIn: () => true,
416
+ when: siteAware('mod+shift+code:Period', {
417
+ engaged: () => popupIsOpen() || panelHasFocus(),
418
+ }),
419
+ })
420
+ ```
421
+
422
+ On sites that don't use the chord the gate is always true. On sites that do
423
+ (Docs, Slides, Confluence, GitHub, WordPress ...), it returns `engaged()`;
424
+ when that is false, the router leaves the event untouched and the site's
425
+ shortcut runs.
426
+
427
+ Also exported: `lookupSiteConflicts(combo, { url, platform, verifiedOnly })`,
428
+ `matchSites(url)`, `siteLookupKey(combo, platform)`, `detectSitePlatform()`
429
+ and `listSites()`. Platforms: `windows` (also used for Linux), `mac`,
430
+ `chromeos`. The runtime table is ~7 KB gzipped and imports nothing from the
431
+ core, so it never creates a second router.
432
+
433
+ ### Validating a recorded combo (v0.3.0+)
434
+
435
+ For a "press your keys" setting: record with `comboFromEvent`, then check
436
+ with `hotkey-router/validate` before saving. Reasons come in plain language,
437
+ ready to show.
438
+
439
+ ```js
440
+ import { comboFromEvent } from 'hotkey-router'
441
+ import { validateCombo } from 'hotkey-router/validate'
442
+
443
+ field.addEventListener('keydown', (e) => {
444
+ e.preventDefault()
445
+ const combo = comboFromEvent(e, { useMod: true })
446
+ if (!combo) return // still holding modifiers
447
+ const { ok, reasons } = validateCombo(combo, {
448
+ requirePrimary: true, // must include Ctrl (Cmd on macOS)
449
+ minModifiers: 2,
450
+ taken: ['mod+shift+code:Space'],
451
+ })
452
+ show(reasons.map((r) => r.message))
453
+ if (ok) save(combo)
454
+ })
455
+ ```
456
+
457
+ Errors (`ok: false`): no key, no modifier, Alt as the only modifier on
458
+ Windows/Linux, a rule you asked for (`requirePrimary`, `minModifiers`),
459
+ already in `taken`, or reserved by a browser/OS (never reaches the page).
460
+ Warnings (`ok: true`): reserved only in some situations, Ctrl+Alt acting as
461
+ AltGr on some Windows layouts, and sites that use the same keys.
462
+
366
463
  ### Supported syntax
367
464
 
368
465
  **Standard:**