@rwh/keystrokes
Advanced tools
Comparing version 1.0.2 to 1.1.0
@@ -15,2 +15,3 @@ import type { KeyEvent, Handler } from './handler-state'; | ||
get isPressed(): boolean; | ||
get sequenceIndex(): number; | ||
private _normalizedKeyCombo; | ||
@@ -17,0 +18,0 @@ private _parsedKeyCombo; |
@@ -16,3 +16,4 @@ import { Handler, KeyEvent } from './handler-state'; | ||
}; | ||
export type KeystrokesOptions<OriginalEvent = KeyboardEvent, KeyEventProps = MaybeBrowserKeyEventProps<OriginalEvent>, KeyComboEventProps = MaybeBrowserKeyComboEventProps<OriginalEvent>> = { | ||
export type KeystrokesOptions<OriginalEvent = KeyboardEvent, KeyEventProps = MaybeBrowserKeyEventProps<OriginalEvent>, KeyComboEventProps = MaybeBrowserKeyComboEventProps<OriginalEvent>> = BindEnvironmentOptions<OriginalEvent, KeyEventProps, KeyComboEventProps>; | ||
export type BindEnvironmentOptions<OriginalEvent = KeyboardEvent, KeyEventProps = MaybeBrowserKeyEventProps<OriginalEvent>, KeyComboEventProps = MaybeBrowserKeyComboEventProps<OriginalEvent>> = { | ||
onActive?: OnActiveEventBinder; | ||
@@ -52,4 +53,6 @@ onInactive?: OnActiveEventBinder; | ||
checkKeyCombo(keyCombo: string): boolean; | ||
bindEnvironment(): void; | ||
checkKeyComboSequenceIndex(keyCombo: string): number; | ||
bindEnvironment(options?: BindEnvironmentOptions<OriginalEvent, KeyEventProps, KeyComboEventProps>): void; | ||
unbindEnvironment(): void; | ||
private _ensureCachedKeyComboState; | ||
private _handleKeyPress; | ||
@@ -56,0 +59,0 @@ private _handleKeyRelease; |
var w = Object.defineProperty; | ||
var E = (n, e, t) => e in n ? w(n, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[e] = t; | ||
var a = (n, e, t) => (E(n, typeof e != "symbol" ? e + "" : e, t), t); | ||
var E = (i, e, t) => e in i ? w(i, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : i[e] = t; | ||
var o = (i, e, t) => (E(i, typeof e != "symbol" ? e + "" : e, t), t); | ||
class v { | ||
constructor(e) { | ||
a(this, "_onPressed"); | ||
a(this, "_onPressedWithRepeat"); | ||
a(this, "_onReleased"); | ||
a(this, "_isPressed"); | ||
a(this, "_identity"); | ||
o(this, "_onPressed"); | ||
o(this, "_onPressedWithRepeat"); | ||
o(this, "_onReleased"); | ||
o(this, "_isPressed"); | ||
o(this, "_identity"); | ||
this._isPressed = !1, this._identity = e, typeof e == "function" ? this._onPressedWithRepeat = e : (this._onPressed = e.onPressed, this._onPressedWithRepeat = e.onPressedWithRepeat, this._onReleased = e.onReleased); | ||
@@ -20,4 +20,4 @@ } | ||
executePressed(e) { | ||
var t, i; | ||
this._isPressed || (t = this._onPressed) == null || t.call(this, e), this._isPressed = !0, (i = this._onPressedWithRepeat) == null || i.call(this, e); | ||
var t, n; | ||
this._isPressed || (t = this._onPressed) == null || t.call(this, e), this._isPressed = !0, (n = this._onPressedWithRepeat) == null || n.call(this, e); | ||
} | ||
@@ -30,11 +30,11 @@ executeReleased(e) { | ||
const c = class c { | ||
constructor(e, t, i = {}) { | ||
a(this, "_normalizedKeyCombo"); | ||
a(this, "_parsedKeyCombo"); | ||
a(this, "_handlerState"); | ||
a(this, "_lastActiveKeyPresses"); | ||
a(this, "_isPressedWithFinalKey"); | ||
a(this, "_sequenceIndex"); | ||
a(this, "_keyComboEventMapper"); | ||
this._normalizedKeyCombo = c.normalizeKeyCombo(e), this._parsedKeyCombo = c.parseKeyCombo(e), this._handlerState = new v(i), this._keyComboEventMapper = t, this._lastActiveKeyPresses = [], this._isPressedWithFinalKey = null, this._sequenceIndex = 0; | ||
constructor(e, t, n = {}) { | ||
o(this, "_normalizedKeyCombo"); | ||
o(this, "_parsedKeyCombo"); | ||
o(this, "_handlerState"); | ||
o(this, "_lastActiveKeyPresses"); | ||
o(this, "_isPressedWithFinalKey"); | ||
o(this, "_sequenceIndex"); | ||
o(this, "_keyComboEventMapper"); | ||
this._normalizedKeyCombo = c.normalizeKeyCombo(e), this._parsedKeyCombo = c.parseKeyCombo(e), this._handlerState = new v(n), this._keyComboEventMapper = t, this._lastActiveKeyPresses = [], this._isPressedWithFinalKey = null, this._sequenceIndex = 0; | ||
} | ||
@@ -45,7 +45,7 @@ static parseKeyCombo(e) { | ||
const t = e.toLowerCase(); | ||
let i = "", s = [], r = [s], o = [r]; | ||
const l = [o]; | ||
let n = "", s = [], r = [s], a = [r]; | ||
const l = [a]; | ||
let y = !1; | ||
for (let h = 0; h < e.length; h += 1) | ||
t[h] === "\\" ? y = !0 : (t[h] === "+" || t[h] === ">" || t[h] === ",") && !y ? i = t[h] : t[h].match(/[^\s]/) && (i && (i === "," ? (s = [], r = [s], o = [r], l.push(o)) : i === ">" ? (s = [], r = [s], o.push(r)) : i === "+" && (s = [], r.push(s)), i = ""), y = !1, s.push(t[h])); | ||
t[h] === "\\" ? y = !0 : (t[h] === "+" || t[h] === ">" || t[h] === ",") && !y ? n = t[h] : t[h].match(/[^\s]/) && (n && (n === "," ? (s = [], r = [s], a = [r], l.push(a)) : n === ">" ? (s = [], r = [s], a.push(r)) : n === "+" && (s = [], r.push(s)), n = ""), y = !1, s.push(t[h])); | ||
const K = l.map((h) => h.map((k) => k.map((g) => g.join("")))); | ||
@@ -55,3 +55,3 @@ return c._parseCache[e] = K, K; | ||
static stringifyKeyCombo(e) { | ||
return e.map((t) => t.map((i) => i.map((s) => s === "+" ? "\\+" : s === ">" ? "\\>" : s === "," ? "\\," : s).join("+")).join(">")).join(","); | ||
return e.map((t) => t.map((n) => n.map((s) => s === "+" ? "\\+" : s === ">" ? "\\>" : s === "," ? "\\," : s).join("+")).join(">")).join(","); | ||
} | ||
@@ -67,2 +67,5 @@ static normalizeKeyCombo(e) { | ||
} | ||
get sequenceIndex() { | ||
return this.isPressed ? this._parsedKeyCombo.length : this._sequenceIndex; | ||
} | ||
isOwnHandler(e) { | ||
@@ -81,10 +84,10 @@ return this._handlerState.isOwnHandler(e); | ||
const t = this._parsedKeyCombo[this._sequenceIndex]; | ||
let i = 0; | ||
let n = 0; | ||
for (const s of t) { | ||
let r = i; | ||
for (const o of s) { | ||
let r = n; | ||
for (const a of s) { | ||
let l = !1; | ||
for (let y = i; y < e.length; y += 1) { | ||
for (let y = n; y < e.length; y += 1) { | ||
const K = e[y]; | ||
if (o === K.key) { | ||
if (a === K.key) { | ||
y > r && (r = y), l = !0; | ||
@@ -99,8 +102,8 @@ break; | ||
} | ||
i = r; | ||
n = r; | ||
} | ||
for (const s of e) { | ||
let r = !1; | ||
for (const o of t) | ||
for (const l of o) | ||
for (const a of t) | ||
for (const l of a) | ||
if (s.key === l) { | ||
@@ -130,3 +133,3 @@ r = !0; | ||
}; | ||
a(c, "_parseCache", {}), a(c, "_normalizationCache", {}); | ||
o(c, "_parseCache", {}), o(c, "_normalizationCache", {}); | ||
let d = c; | ||
@@ -139,7 +142,7 @@ const R = { | ||
*/ | ||
addEventListener: (...n) => { | ||
addEventListener: (...i) => { | ||
}, | ||
removeEventListener: (...n) => { | ||
removeEventListener: (...i) => { | ||
}, | ||
dispatchEvent: (...n) => { | ||
dispatchEvent: (...i) => { | ||
} | ||
@@ -155,8 +158,8 @@ /* | ||
let m = ""; | ||
const W = (n) => { | ||
!f || n.key !== "Meta" || (m = n.code); | ||
}, L = (n) => !(!f || n.key !== "Meta"), C = () => { | ||
const B = (i) => { | ||
!f || i.key !== "Meta" || (m = i.code); | ||
}, I = (i) => !(!f || i.key !== "Meta"), C = () => { | ||
if (!f || !m) | ||
return; | ||
const n = new KeyboardEvent("keyup", { | ||
const i = new KeyboardEvent("keyup", { | ||
key: "Meta", | ||
@@ -167,6 +170,6 @@ code: m, | ||
}); | ||
m = "", u().dispatchEvent(n); | ||
}, B = (n) => { | ||
m = "", u().dispatchEvent(i); | ||
}, W = (i) => { | ||
try { | ||
const e = () => n(); | ||
const e = () => i(); | ||
return addEventListener("focus", e), () => { | ||
@@ -177,5 +180,5 @@ removeEventListener("focus", e); | ||
} | ||
}, O = (n) => { | ||
}, L = (i) => { | ||
try { | ||
const e = () => n(); | ||
const e = () => i(); | ||
return C(), addEventListener("blur", e), () => { | ||
@@ -186,10 +189,10 @@ removeEventListener("blur", e); | ||
} | ||
}, z = (n) => { | ||
}, O = (i) => { | ||
try { | ||
const e = (t) => { | ||
const i = t.composedPath(); | ||
return W(t), n({ | ||
const n = t.composedPath(); | ||
return B(t), i({ | ||
key: t.key, | ||
originalEvent: t, | ||
composedPath: () => i | ||
composedPath: () => n | ||
}); | ||
@@ -202,11 +205,11 @@ }; | ||
} | ||
}, I = (n) => { | ||
}, q = (i) => { | ||
try { | ||
const e = (t) => { | ||
const i = t.composedPath(); | ||
if (C(), !L(t)) | ||
return n({ | ||
const n = t.composedPath(); | ||
if (C(), !I(t)) | ||
return i({ | ||
key: t.key, | ||
originalEvent: t, | ||
composedPath: () => i | ||
composedPath: () => n | ||
}); | ||
@@ -219,22 +222,26 @@ }; | ||
} | ||
}, M = typeof requestAnimationFrame == "function" ? (n) => requestAnimationFrame(n) : (n) => setTimeout(n, 0), b = () => new Promise((n) => M(n)); | ||
}, z = typeof requestAnimationFrame == "function" ? (i) => requestAnimationFrame(i) : (i) => setTimeout(i, 0), b = () => new Promise((i) => z(i)); | ||
class P { | ||
constructor(e = {}) { | ||
a(this, "_isActive"); | ||
a(this, "_isUpdatingKeyComboState"); | ||
a(this, "_unbinder"); | ||
a(this, "_onActiveBinder"); | ||
a(this, "_onInactiveBinder"); | ||
a(this, "_onKeyPressedBinder"); | ||
a(this, "_onKeyReleasedBinder"); | ||
a(this, "_keyComboEventMapper"); | ||
a(this, "_selfReleasingKeys"); | ||
a(this, "_keyRemap"); | ||
a(this, "_handlerStates"); | ||
a(this, "_keyComboStates"); | ||
a(this, "_keyComboStatesArray"); | ||
a(this, "_activeKeyPresses"); | ||
a(this, "_activeKeySet"); | ||
a(this, "_watchedKeyComboStates"); | ||
this._isActive = !0, this._isUpdatingKeyComboState = !1, this._onActiveBinder = e.onActive ?? B, this._onInactiveBinder = e.onInactive ?? O, this._onKeyPressedBinder = e.onKeyPressed ?? z, this._onKeyReleasedBinder = e.onKeyReleased ?? I, this._keyComboEventMapper = e.mapKeyComboEvent ?? (() => ({})), this._selfReleasingKeys = e.selfReleasingKeys ?? [], this._keyRemap = e.keyRemap ?? {}, this._handlerStates = {}, this._keyComboStates = {}, this._keyComboStatesArray = [], this._activeKeyPresses = [], this._activeKeySet = /* @__PURE__ */ new Set(), this._watchedKeyComboStates = {}, this.bindEnvironment(); | ||
o(this, "_isActive"); | ||
o(this, "_isUpdatingKeyComboState"); | ||
o(this, "_unbinder"); | ||
o(this, "_onActiveBinder"); | ||
o(this, "_onInactiveBinder"); | ||
o(this, "_onKeyPressedBinder"); | ||
o(this, "_onKeyReleasedBinder"); | ||
o(this, "_keyComboEventMapper"); | ||
o(this, "_selfReleasingKeys"); | ||
o(this, "_keyRemap"); | ||
o(this, "_handlerStates"); | ||
o(this, "_keyComboStates"); | ||
o(this, "_keyComboStatesArray"); | ||
o(this, "_activeKeyPresses"); | ||
o(this, "_activeKeySet"); | ||
o(this, "_watchedKeyComboStates"); | ||
this._isActive = !0, this._isUpdatingKeyComboState = !1, this._onActiveBinder = () => { | ||
}, this._onInactiveBinder = () => { | ||
}, this._onKeyPressedBinder = () => { | ||
}, this._onKeyReleasedBinder = () => { | ||
}, this._keyComboEventMapper = () => ({}), this._selfReleasingKeys = [], this._keyRemap = {}, this._handlerStates = {}, this._keyComboStates = {}, this._keyComboStatesArray = [], this._activeKeyPresses = [], this._activeKeySet = /* @__PURE__ */ new Set(), this._watchedKeyComboStates = {}, this.bindEnvironment(e); | ||
} | ||
@@ -247,14 +254,14 @@ get pressedKeys() { | ||
e = e.toLowerCase(); | ||
const i = new v(t); | ||
(s = this._handlerStates)[e] ?? (s[e] = []), this._handlerStates[e].push(i); | ||
const n = new v(t); | ||
(s = this._handlerStates)[e] ?? (s[e] = []), this._handlerStates[e].push(n); | ||
} | ||
unbindKey(e, t) { | ||
e = e.toLowerCase(); | ||
const i = this._handlerStates[e]; | ||
if (i) | ||
const n = this._handlerStates[e]; | ||
if (n) | ||
if (t) | ||
for (let s = 0; s < i.length; s += 1) | ||
i[s].isOwnHandler(t) && (i.splice(s, 1), s -= 1); | ||
for (let s = 0; s < n.length; s += 1) | ||
n[s].isOwnHandler(t) && (n.splice(s, 1), s -= 1); | ||
else | ||
i.length = 0; | ||
n.length = 0; | ||
} | ||
@@ -264,18 +271,18 @@ bindKeyCombo(e, t) { | ||
e = d.normalizeKeyCombo(e); | ||
const i = new d(e, this._keyComboEventMapper, t); | ||
(s = this._keyComboStates)[e] ?? (s[e] = []), this._keyComboStates[e].push(i), this._keyComboStatesArray.push(i); | ||
const n = new d(e, this._keyComboEventMapper, t); | ||
(s = this._keyComboStates)[e] ?? (s[e] = []), this._keyComboStates[e].push(n), this._keyComboStatesArray.push(n); | ||
} | ||
unbindKeyCombo(e, t) { | ||
e = d.normalizeKeyCombo(e); | ||
const i = this._keyComboStates[e]; | ||
if (i) | ||
const n = this._keyComboStates[e]; | ||
if (n) | ||
if (t) { | ||
for (let s = 0; s < i.length; s += 1) | ||
if (i[s].isOwnHandler(t)) { | ||
for (let s = 0; s < n.length; s += 1) | ||
if (n[s].isOwnHandler(t)) { | ||
for (let r = 0; r < this._keyComboStatesArray.length; r += 1) | ||
this._keyComboStatesArray[r] === i[s] && (this._keyComboStatesArray.splice(r, 1), r -= 1); | ||
i.splice(s, 1), s -= 1; | ||
this._keyComboStatesArray[r] === n[s] && (this._keyComboStatesArray.splice(r, 1), r -= 1); | ||
n.splice(s, 1), s -= 1; | ||
} | ||
} else | ||
i.length = 0; | ||
n.length = 0; | ||
} | ||
@@ -286,19 +293,20 @@ checkKey(e) { | ||
checkKeyCombo(e) { | ||
e = d.normalizeKeyCombo(e), this._watchedKeyComboStates[e] || (this._watchedKeyComboStates[e] = new d(e, this._keyComboEventMapper)); | ||
const t = this._watchedKeyComboStates[e]; | ||
return t.updateState(this._activeKeyPresses), t.isPressed; | ||
return this._ensureCachedKeyComboState(e).isPressed; | ||
} | ||
bindEnvironment() { | ||
this.unbindEnvironment(); | ||
const e = this._onActiveBinder(() => { | ||
checkKeyComboSequenceIndex(e) { | ||
return this._ensureCachedKeyComboState(e).sequenceIndex; | ||
} | ||
bindEnvironment(e = {}) { | ||
this.unbindEnvironment(), this._onActiveBinder = e.onActive ?? W, this._onInactiveBinder = e.onInactive ?? L, this._onKeyPressedBinder = e.onKeyPressed ?? O, this._onKeyReleasedBinder = e.onKeyReleased ?? q, this._keyComboEventMapper = e.mapKeyComboEvent ?? (() => ({})), this._selfReleasingKeys = e.selfReleasingKeys ?? []; | ||
const t = this._onActiveBinder(() => { | ||
this._isActive = !0; | ||
}), t = this._onInactiveBinder(() => { | ||
}), n = this._onInactiveBinder(() => { | ||
this._isActive = !1; | ||
}), i = this._onKeyPressedBinder((r) => { | ||
this._handleKeyPress(r); | ||
}), s = this._onKeyReleasedBinder((r) => { | ||
this._handleKeyRelease(r); | ||
}), s = this._onKeyPressedBinder((a) => { | ||
this._handleKeyPress(a); | ||
}), r = this._onKeyReleasedBinder((a) => { | ||
this._handleKeyRelease(a); | ||
}); | ||
this._unbinder = () => { | ||
e == null || e(), t == null || t(), i == null || i(), s == null || s(); | ||
t == null || t(), n == null || n(), s == null || s(), r == null || r(); | ||
}; | ||
@@ -310,2 +318,7 @@ } | ||
} | ||
_ensureCachedKeyComboState(e) { | ||
e = d.normalizeKeyCombo(e), this._watchedKeyComboStates[e] || (this._watchedKeyComboStates[e] = new d(e, this._keyComboEventMapper)); | ||
const t = this._watchedKeyComboStates[e]; | ||
return t.updateState(this._activeKeyPresses), t; | ||
} | ||
_handleKeyPress(e) { | ||
@@ -316,4 +329,4 @@ (async () => { | ||
let t = e.key.toLowerCase(); | ||
const i = this._keyRemap[t]; | ||
i && (t = i); | ||
const n = this._keyRemap[t]; | ||
n && (t = n); | ||
const s = this._handlerStates[t]; | ||
@@ -335,5 +348,5 @@ if (s) | ||
(async () => { | ||
const t = e.key.toLowerCase(), i = this._handlerStates[t]; | ||
if (i) | ||
for (const s of i) | ||
const t = e.key.toLowerCase(), n = this._handlerStates[t]; | ||
if (n) | ||
for (const s of n) | ||
s.executeReleased(e); | ||
@@ -370,21 +383,21 @@ if (this._activeKeySet.has(t)) { | ||
let S, p; | ||
const q = (n) => { | ||
p = n ?? new P(S); | ||
}, _ = () => (p || q(), p), H = (n) => { | ||
S = n; | ||
}, U = (...n) => _().bindKey(...n), j = (...n) => _().unbindKey(...n), T = (...n) => _().bindKeyCombo(...n), D = (...n) => _().unbindKeyCombo(...n), G = (...n) => _().checkKey(...n), N = (...n) => _().checkKeyCombo(...n), J = d.normalizeKeyCombo, Q = d.stringifyKeyCombo, V = d.parseKeyCombo, X = (n = {}) => { | ||
let e, t, i, s; | ||
const M = (i) => { | ||
p = i ?? new P(S); | ||
}, _ = () => (p || M(), p), H = (i) => { | ||
S = i; | ||
}, U = (...i) => _().bindKey(...i), j = (...i) => _().unbindKey(...i), T = (...i) => _().bindKeyCombo(...i), D = (...i) => _().unbindKeyCombo(...i), G = (...i) => _().checkKey(...i), N = (...i) => _().checkKeyCombo(...i), J = d.normalizeKeyCombo, Q = d.stringifyKeyCombo, V = d.parseKeyCombo, X = (i = {}) => { | ||
let e, t, n, s; | ||
return Object.assign(new P({ | ||
...n, | ||
onActive(o) { | ||
e = o; | ||
...i, | ||
onActive(a) { | ||
e = a; | ||
}, | ||
onInactive(o) { | ||
t = o; | ||
onInactive(a) { | ||
t = a; | ||
}, | ||
onKeyPressed(o) { | ||
i = o; | ||
onKeyPressed(a) { | ||
n = a; | ||
}, | ||
onKeyReleased(o) { | ||
s = o; | ||
onKeyReleased(a) { | ||
s = a; | ||
} | ||
@@ -398,7 +411,7 @@ }), { | ||
}, | ||
press(o) { | ||
i({ composedPath: () => [], ...o }); | ||
press(a) { | ||
n({ composedPath: () => [], ...a }); | ||
}, | ||
release(o) { | ||
s({ composedPath: () => [], ...o }); | ||
release(a) { | ||
s({ composedPath: () => [], ...a }); | ||
} | ||
@@ -417,3 +430,3 @@ }); | ||
V as parseKeyCombo, | ||
q as setGlobalKeystrokes, | ||
M as setGlobalKeystrokes, | ||
H as setGlobalKeystrokesOptions, | ||
@@ -420,0 +433,0 @@ Q as stringifyKeyCombo, |
{ | ||
"name": "@rwh/keystrokes", | ||
"version": "1.0.2", | ||
"version": "1.1.0", | ||
"description": "Keystrokes is an easy to use library for binding functions to keys and key combos. It can be used with any TypeScript or JavaScript project, even in non-browser environments.", | ||
@@ -5,0 +5,0 @@ "type": "module", |
@@ -59,3 +59,6 @@ <h1 align="center"> | ||
```html | ||
<script src="https://unpkg.com/browse/@rwh/keystrokes@latest/keystrokes.js"> | ||
<!-- ESM --> | ||
<script src="https://unpkg.com/browse/@rwh/keystrokes@latest/dist/keystrokes.js"> | ||
<!-- UMD --> | ||
<script src="https://unpkg.com/browse/@rwh/keystrokes@latest/dist/keystrokes.umd.cjs"> | ||
<script> | ||
@@ -303,3 +306,3 @@ keystrokes.bindKey('a', () => console.log('you pressed a')) | ||
```js | ||
import assert from 'assert' | ||
import { describe, it, expect } from 'vitest' | ||
import { createTestKeystrokes, setGlobalKeystrokes } from '@rwh/keystrokes' | ||
@@ -319,3 +322,3 @@ | ||
assert(app.didComboBoundThing) | ||
expect(app.didComboBoundThing).toBe(true) | ||
}) | ||
@@ -364,3 +367,3 @@ }) | ||
------------------|------------------------------------------ | ||
selfReleasingKeys | Some environments may not properly fire release events for all keys. Adding them to this array will ensure they are released automatically when no other keys are pressed. | ||
selfReleasingKeys | Key names added to selfReleasingKeys will be marked as released after any other key is released. Provided to deal with buggy platforms. | ||
keyRemap | An object of key value pairs with the key being the key to rename, and the value being the new name. | ||
@@ -367,0 +370,0 @@ onActive | A binder to track viewport focus. See [Non Browser Environments](#non-browser-environments) for details. |
Sorry, the diff of this file is not supported yet
50459
605
474