hotkey-router 0.0.1 โ 0.0.3
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 +28 -10
- package/dist/hotkey-router.cjs +1 -1
- package/dist/hotkey-router.js +1 -1
- package/dist/hotkey-router.min.js +1 -1
- package/package.json +11 -10
package/README.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# hotkey-router
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/hotkey-router)
|
|
4
|
+
[](https://bundlephobia.com/package/hotkey-router)
|
|
5
|
+
[](https://github.com/iWhatty/hotkey-router-js)
|
|
6
|
+
|
|
3
7
|
**A tiny, deterministic keyboard routing engine for modern web apps.**
|
|
4
8
|
|
|
5
9
|
Hotkey Router is not a key utility.
|
|
@@ -10,7 +14,9 @@ It is a predictable, plugin-first routing layer for keyboard shortcuts.
|
|
|
10
14
|
* ๐ฏ Deterministic winner selection (priority + recency)
|
|
11
15
|
* ๐ Input-safe by default
|
|
12
16
|
* ๐งช Testable via `trigger()`
|
|
13
|
-
* ๐ฆ
|
|
17
|
+
* ๐ฆ 4.9 kB minified
|
|
18
|
+
* ๐ 2.2 kB minified + gzipped
|
|
19
|
+
* ๐ซ Zero dependencies
|
|
14
20
|
|
|
15
21
|
---
|
|
16
22
|
|
|
@@ -32,10 +38,22 @@ No keycodes. No legacy IE hacks. No hidden global scope state.
|
|
|
32
38
|
npm install hotkey-router
|
|
33
39
|
```
|
|
34
40
|
|
|
35
|
-
|
|
41
|
+
### ESM
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
import hotkeys from 'hotkey-router'
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### CommonJS
|
|
48
|
+
|
|
49
|
+
```js
|
|
50
|
+
const hotkeys = require('hotkey-router')
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### CDN (ESM)
|
|
36
54
|
|
|
37
55
|
```js
|
|
38
|
-
import hotkeys from 'https://cdn.
|
|
56
|
+
import hotkeys from 'https://cdn.jsdelivr.net/npm/hotkey-router/dist/hotkey-router.min.js'
|
|
39
57
|
```
|
|
40
58
|
|
|
41
59
|
---
|
|
@@ -216,7 +234,7 @@ hotkeys.init({
|
|
|
216
234
|
})
|
|
217
235
|
```
|
|
218
236
|
|
|
219
|
-
Auto-initializes on `window` by default.
|
|
237
|
+
Auto-initializes on `window` by default (browser environments).
|
|
220
238
|
|
|
221
239
|
---
|
|
222
240
|
|
|
@@ -241,7 +259,7 @@ Returns `true` if a handler ran.
|
|
|
241
259
|
|
|
242
260
|
# Supported Syntax
|
|
243
261
|
|
|
244
|
-
|
|
262
|
+
## Standard
|
|
245
263
|
|
|
246
264
|
* `ctrl+k`
|
|
247
265
|
* `shift+a`
|
|
@@ -249,7 +267,7 @@ Returns `true` if a handler ran.
|
|
|
249
267
|
* `mod+s` (meta on macOS, ctrl elsewhere)
|
|
250
268
|
* `ctrl++` or `ctrl+plus`
|
|
251
269
|
|
|
252
|
-
|
|
270
|
+
## AHK-Style Prefix Modifiers
|
|
253
271
|
|
|
254
272
|
* `^k` โ `ctrl+k`
|
|
255
273
|
* `!k` โ `alt+k`
|
|
@@ -259,9 +277,9 @@ Returns `true` if a handler ran.
|
|
|
259
277
|
|
|
260
278
|
Modifiers must appear before the base key.
|
|
261
279
|
|
|
262
|
-
|
|
280
|
+
## Aliases Supported
|
|
263
281
|
|
|
264
|
-
Modifiers
|
|
282
|
+
### Modifiers
|
|
265
283
|
|
|
266
284
|
* `ctrl`, `control`, `โ`
|
|
267
285
|
* `shift`, `โง`, `+`
|
|
@@ -269,7 +287,7 @@ Modifiers:
|
|
|
269
287
|
* `meta`, `cmd`, `command`, `win`, `โ`, `#`
|
|
270
288
|
* `mod` (meta on macOS, ctrl elsewhere)
|
|
271
289
|
|
|
272
|
-
Navigation / Special
|
|
290
|
+
### Navigation / Special Keys
|
|
273
291
|
|
|
274
292
|
* `escape`, `esc`
|
|
275
293
|
* `enter`, `return`
|
|
@@ -312,4 +330,4 @@ Chrome, Firefox, Safari, Edge.
|
|
|
312
330
|
|
|
313
331
|
# License
|
|
314
332
|
|
|
315
|
-
|
|
333
|
+
See LICENSE file for details.
|
package/dist/hotkey-router.cjs
CHANGED
package/dist/hotkey-router.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
// hotkey-router v0.0.
|
|
1
|
+
// hotkey-router v0.0.3 | SEE LICENSE IN LICENSE
|
|
2
2
|
|
|
3
3
|
function E(t,e,n,r){return t.addEventListener(e,n,r),()=>t.removeEventListener(e,n,r)}const C=typeof navigator<"u"&&/Mac|iPhone|iPad|iPod/.test(navigator.platform),L=new Set(["ctrl","shift","alt","meta"]),z=new Map([["^","ctrl"],["!","alt"],["+","shift"],["#","meta"]]),v=Object.freeze({esc:"escape",escape:"escape",space:" ",spacebar:" ",enter:"enter",return:"enter",del:"delete",delete:"delete",backspace:"backspace",tab:"tab",up:"arrowup",down:"arrowdown",left:"arrowleft",right:"arrowright",home:"home",end:"end",pageup:"pageup",pagedown:"pagedown",pgup:"pageup",pgdn:"pagedown",cmd:"meta",command:"meta",win:"meta",meta:"meta",control:"ctrl",ctrl:"ctrl",option:"alt",alt:"alt",shift:"shift","\u2318":"meta","\u2303":"ctrl","\u2325":"alt","\u21E7":"shift",mod:C?"meta":"ctrl",plus:"+"});let I=!0,h=typeof window<"u"?window:null;const u=new Map,d=new Map,p=new Map;let b=!1,D=1;function k(t){const e=String(t??"").trim(),n=e.toLowerCase();return v[n]??(e===" "?" ":n)}function g({ctrl:t,shift:e,alt:n,meta:r,key:i}){let o="";return t&&(o+="ctrl+"),e&&(o+="shift+"),n&&(o+="alt+"),r&&(o+="meta+"),o?o+i:i}function O(t){return g({ctrl:t.ctrlKey,shift:t.shiftKey,alt:t.altKey,meta:t.metaKey,key:k(t.key)})}function U(t){const e=k(t);return L.has(e)}function P(t){const e=String(t||"").trim(),r=e.toLowerCase().endsWith(" up");let i=(r?e.slice(0,-3):e).trim().toLowerCase();const o={ctrl:!1,shift:!1,alt:!1,meta:!1,key:null};for(;i.length;){const s=z.get(i[0])??null;if(!s)break;o[s]=!0,i=i.slice(1).trimStart()}const l=i.split("+").map(s=>s.trim()),a=l.filter(Boolean),f=l.some(s=>s==="")&&i.includes("++");if(!f){let s=!1;for(const c of a)if(U(c)){if(s)throw new Error(`Invalid hotkey "${t}": modifiers must come before the base key (e.g. "ctrl+k", not "k+ctrl")`)}else s||(s=!0)}for(const s of a){const c=v[s]??s;c==="ctrl"?o.ctrl=!0:c==="shift"?o.shift=!0:c==="alt"?o.alt=!0:c==="meta"?o.meta=!0:o.key=k(c)}if(!o.key&&f&&(o.key="+"),!o.key)throw new Error(`Invalid hotkey "${t}" (missing base key)`);return{combo:o,type:r?"keyup":"keydown",raw:t}}function B(t){const e=t?.target;if(!e)return!1;const n=String(e.tagName||"").toUpperCase();return e.isContentEditable||n==="INPUT"||n==="TEXTAREA"||n==="SELECT"||e.getAttribute?.("role")==="textbox"}function F(t,e){const n=e?{...e}:{};return t==="keydown"&&n.repeat==null&&(n.repeat=!1),n.priority==null&&(n.priority=0),n}function $(t,e){let n=u.get(t);n||(n=new Map,u.set(t,n));let r=n.get(e);return r||(r=[],n.set(e,r)),r}function m(t){const e=p.get(t);if(!e)return!1;const{comboStr:n,type:r}=e,i=u.get(n),o=i?.get(r);if(!o?.length)return p.delete(t),!1;const l=o.filter(a=>a.id!==t);return l.length?i.set(r,l):i.delete(r),i.size||u.delete(n),p.delete(t),!0}function K(t,e,n=null,r={}){const{combo:i,type:o,raw:l}=P(t),a=g(i),f=F(o,r),s={id:D++,comboStr:a,type:o,combo:i,handler:e,plugin:n,raw:l,options:f};$(a,o).push(s),p.set(s.id,{comboStr:a,type:o});const c=()=>m(s.id);return c.id=s.id,c.hotkey=l,c}function j(t,e){const{combo:n,type:r}=P(t),i=g(n),o=u.get(i);if(!o)return;const l=o.get(r);if(l?.length){if(e){const a=[];for(const f of l)f.handler===e?p.delete(f.id):a.push(f);a.length?o.set(r,a):o.delete(r)}else{for(const a of l)p.delete(a.id);o.delete(r)}o.size||u.delete(i)}}function N(t,e){if(d.has(t))throw new Error(`Plugin "${t}" already registered`);const n=[];for(const[r,i]of Object.entries(e)){const[o,l]=Array.isArray(i)?i:[i,{}],a=K(r,o,t,l);n.push(a.id)}return d.set(t,n),()=>M(t)}function M(t){const e=d.get(t);if(e){for(const n of e)m(n);d.delete(t)}}function W(){b=!0}function q(){b=!1}function H(t=!0){I=!!t}function R(t){h=t}function T(t){let e=null;for(const n of t)e?(n.options.priority>e.options.priority||n.options.priority===e.options.priority&&n.id>e.id)&&(e=n):e=n;return e}function S(t){return e=>{if(b)return;const n=I&&B(e),r=O(e),i=u.get(r)?.get(t);if(!i?.length)return;const o=[];for(const f of i){const s=f.options;n&&!s.allowIn?.(e)||t==="keydown"&&s.repeat===!1&&e.repeat||s.when&&s.when(e)===!1||o.push(f)}if(!o.length)return;const l=T(o),a=l.options;a.preventDefault&&e.preventDefault(),a.stopImmediatePropagation?e.stopImmediatePropagation():a.stopPropagation&&e.stopPropagation(),l.handler(e),a.once&&m(l.id)}}let y=null,w=null;function x({target:t=h,capture:e=!1}={}){if(!t)throw new Error("hotkeys.init() requires a target (e.g. window)");(y||w)&&A(),y=E(t,"keydown",S("keydown"),{capture:e}),w=E(t,"keyup",S("keyup"),{capture:e})}function A(){y?.(),w?.(),y=null,w=null,u.clear(),d.clear(),p.clear()}function X(t,{type:e}={}){const{combo:n,type:r}=P(t),i=g(n),o=e||r,l=u.get(i)?.get(o);if(!l?.length)return!1;const a={type:o,key:n.key,ctrlKey:!!n.ctrl,shiftKey:!!n.shift,altKey:!!n.alt,metaKey:!!n.meta,repeat:!1,preventDefault(){},stopPropagation(){},stopImmediatePropagation(){},target:null},f=T(l.filter(s=>s.options.when?s.options.when(a)!==!1:!0));return f?(f.handler(a),f.options.once&&m(f.id),!0):!1}h&&x();var G={init:x,destroy:A,setTarget:R,bind:K,unbind:j,registerPlugin:N,unregisterPlugin:M,pause:W,resume:q,ignoreInput:H,trigger:X};export{G as default};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hotkey-router",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "A tiny, deterministic keyboard routing engine for modern web apps.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "DR.WATT",
|
|
@@ -12,39 +12,40 @@
|
|
|
12
12
|
"router",
|
|
13
13
|
"javascript"
|
|
14
14
|
],
|
|
15
|
-
|
|
16
15
|
"main": "./dist/hotkey-router.cjs",
|
|
17
16
|
"module": "./dist/hotkey-router.js",
|
|
18
|
-
|
|
19
17
|
"exports": {
|
|
20
18
|
".": {
|
|
21
19
|
"import": "./dist/hotkey-router.js",
|
|
22
20
|
"require": "./dist/hotkey-router.cjs"
|
|
23
21
|
}
|
|
24
22
|
},
|
|
25
|
-
|
|
26
23
|
"sideEffects": false,
|
|
27
|
-
|
|
28
24
|
"files": [
|
|
29
25
|
"dist",
|
|
30
26
|
"README.md",
|
|
31
27
|
"LICENSE"
|
|
32
28
|
],
|
|
33
|
-
|
|
34
29
|
"scripts": {
|
|
35
30
|
"build": "node build.js",
|
|
36
31
|
"prepublishOnly": "npm run build",
|
|
37
32
|
"test": "vitest run --environment jsdom",
|
|
38
33
|
"test:watch": "vitest --environment jsdom"
|
|
39
34
|
},
|
|
40
|
-
|
|
41
35
|
"devDependencies": {
|
|
42
36
|
"esbuild": "^0.21.0",
|
|
43
37
|
"jsdom": "^24.0.0",
|
|
44
38
|
"vitest": "^3.1.2"
|
|
45
39
|
},
|
|
46
|
-
|
|
47
40
|
"engines": {
|
|
48
41
|
"node": ">=18"
|
|
49
|
-
}
|
|
50
|
-
|
|
42
|
+
},
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "git+https://github.com/iWhatty/hotkey-router-js.git"
|
|
46
|
+
},
|
|
47
|
+
"bugs": {
|
|
48
|
+
"url": "https://github.com/iWhatty/hotkey-router-js/issues"
|
|
49
|
+
},
|
|
50
|
+
"homepage": "https://github.com/iWhatty/hotkey-router-js#readme"
|
|
51
|
+
}
|