react-better-hotkeys 0.2.0 → 0.4.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
@@ -1,4 +1,4 @@
1
- React Better Hotkeyss
1
+ React Better Hotkeys
2
2
  ======================
3
3
 
4
4
  A tiny, typed helper for registering global hotkeys in React. It supports both **chords** (e.g. `Shift + Alt + A`) and **key sequences** (e.g. `g` then `h`), respects platform-specific modifier keys, and cleans up registrations automatically.
@@ -1,12 +1,27 @@
1
+ import { HotKeyDef } from './types/hotkey/HotKeyDef';
2
+ import { HotKeyType } from './types/hotkey/HotkeyType';
3
+ import { ResolvedKeyStatus } from './types/hotkey/renderer/ResolvedKeyStatus';
1
4
  import { PrimaryKeyCode } from './types/key/PrimaryKeyCode';
2
5
  export declare class HotkeyTextResolver {
3
- symbolMap: Partial<Record<string, string>>;
6
+ symbolMap: Partial<Record<PrimaryKeyCode, string>>;
7
+ invalidSymbolMap: Set<PrimaryKeyCode>;
8
+ chordDelimiter: string;
9
+ sequnceDelimiter: string;
10
+ id: number;
4
11
  private nextSubscriberId;
5
12
  private subscribers;
6
- constructor(symbolMap?: Partial<Record<PrimaryKeyCode, string>>);
13
+ constructor(symbolMap?: Partial<Record<PrimaryKeyCode, string>>, chordDelimiter?: string, sequenceDelimiter?: string);
14
+ private insertCustomMap;
15
+ private stringifyState;
16
+ private buildInitialMap;
17
+ private parseState;
18
+ private storeState;
19
+ private loadState;
7
20
  setSymbol(code: string, symbol: string): void;
8
- resolve(code: PrimaryKeyCode): string;
21
+ resolve(code: PrimaryKeyCode): [string, ResolvedKeyStatus] | undefined;
9
22
  subscribe(code: PrimaryKeyCode, callback: (newSymbol: string) => void): () => void;
10
23
  unsubscribe(code: PrimaryKeyCode, subscriberId: number): void;
24
+ delimiterForType(type: HotKeyType): string;
25
+ toString(hotkey: HotKeyDef): string;
11
26
  }
12
27
  //# sourceMappingURL=HotkeyTextResolver.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"HotkeyTextResolver.d.ts","sourceRoot":"","sources":["../src/lib/HotkeyTextResolver.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAOjE,qBAAa,kBAAkB;IAC7B,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAM;IAEhD,OAAO,CAAC,gBAAgB,CAAK;IAE7B,OAAO,CAAC,WAAW,CAEZ;gBAEK,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;IAiBxD,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IActC,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM;IAKrC,SAAS,CACd,IAAI,EAAE,cAAc,EACpB,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,GACpC,MAAM,IAAI;IAmBN,WAAW,CAAC,IAAI,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;CAUrE"}
1
+ {"version":3,"file":"HotkeyTextResolver.d.ts","sourceRoot":"","sources":["../src/lib/HotkeyTextResolver.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2CAA2C,CAAC;AACnF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAcjE,qBAAa,kBAAkB;IAC7B,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,CAAM;IACxD,gBAAgB,EAAE,GAAG,CAAC,cAAc,CAAC,CAAa;IAElD,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IAEzB,EAAE,EAAE,MAAM,CAAiB;IAE3B,OAAO,CAAC,gBAAgB,CAAK;IAE7B,OAAO,CAAC,WAAW,CAEZ;gBAGL,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,EACnD,cAAc,CAAC,EAAE,MAAM,EACvB,iBAAiB,CAAC,EAAE,MAAM;IAW5B,OAAO,CAAC,eAAe;IAiBvB,OAAO,CAAC,cAAc;IAOtB,OAAO,CAAC,eAAe;IAwBvB,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,SAAS;IAUV,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAiCtC,OAAO,CACZ,IAAI,EAAE,cAAc,GACnB,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAAG,SAAS;IAOnC,SAAS,CACd,IAAI,EAAE,cAAc,EACpB,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,GACpC,MAAM,IAAI;IAcN,WAAW,CAAC,IAAI,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IAW7D,gBAAgB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM;IAK1C,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM;CAI3C"}
@@ -1,45 +1,95 @@
1
- import { KeyMap as b } from "./definitions/KeyMap.js";
2
- class o {
1
+ import { KeyMap as a } from "./definitions/KeyMap.js";
2
+ const o = "rbh-symbols-cache";
3
+ class c {
3
4
  symbolMap = {};
5
+ invalidSymbolMap = /* @__PURE__ */ new Set();
6
+ chordDelimiter;
7
+ sequnceDelimiter;
8
+ id = Math.random();
4
9
  nextSubscriberId = 0;
5
10
  subscribers = {};
6
- constructor(s) {
7
- const e = Object.entries(b).reduce(
8
- (t, r) => {
9
- if (r[1].on === "key") {
10
- const i = r[0].slice(3);
11
- t[i] = r[1].value.match(/[a-z]/) ? r[1].value.toUpperCase() : r[1].value;
11
+ constructor(t, e, s) {
12
+ this.chordDelimiter = e ?? "+", this.sequnceDelimiter = s ?? ">", this.loadState() || (this.symbolMap = { ...this.buildInitialMap() }), t && this.insertCustomMap(t);
13
+ }
14
+ insertCustomMap(t) {
15
+ let e = [];
16
+ for (const [s, i] of Object.entries(t))
17
+ this.symbolMap[s] !== i && (this.symbolMap[s] = i.length === 1 ? i.toLocaleUpperCase() : i, e.push(s));
18
+ e.length > 0 && this.storeState(e);
19
+ }
20
+ stringifyState() {
21
+ return JSON.stringify({
22
+ symbolMap: this.symbolMap,
23
+ invalidSymbolMap: Array.from(this.invalidSymbolMap)
24
+ });
25
+ }
26
+ buildInitialMap() {
27
+ return {
28
+ ...Object.entries(a).reduce((t, e) => (e[1].on === "code" && (t[e[0]] = e[1].value.length === 1 ? e[1].value.toUpperCase() : e[1].value), t), {}),
29
+ ...Object.entries(a).reduce((t, e) => {
30
+ if (e[1].on === "key") {
31
+ const s = e[0].slice(3);
32
+ t[s] = e[1].value.length === 1 ? e[1].value.toUpperCase() : e[1].value;
12
33
  }
13
34
  return t;
14
- },
15
- {}
35
+ }, {})
36
+ };
37
+ }
38
+ parseState(t) {
39
+ this.symbolMap = t.symbolMap, this.invalidSymbolMap = new Set(t.invalidSymbolMap);
40
+ }
41
+ storeState(t) {
42
+ for (const e of t) this.invalidSymbolMap.delete(e);
43
+ localStorage.setItem(o, this.stringifyState());
44
+ }
45
+ loadState() {
46
+ const t = localStorage.getItem(o);
47
+ if (t) {
48
+ const e = JSON.parse(t);
49
+ return this.parseState(e), !0;
50
+ }
51
+ return !1;
52
+ }
53
+ setSymbol(t, e) {
54
+ const s = Object.entries(a).find(
55
+ (r) => r[1].on === "code" && r[1].value === t
56
+ );
57
+ if (s == null)
58
+ return;
59
+ const i = s[0];
60
+ if (this.symbolMap[i] === e) return;
61
+ this.symbolMap[i] = e.length === 1 ? e.toLocaleUpperCase() : e;
62
+ const n = Object.entries(this.symbolMap).find(
63
+ ([r, b]) => r !== i && b === this.symbolMap[i]
16
64
  );
17
- console.log(e), this.symbolMap = { ...e, ...s };
18
- }
19
- setSymbol(s, e) {
20
- if (this.symbolMap[s] === e) return;
21
- this.symbolMap[s] = e;
22
- const r = this.subscribers[s];
23
- if (r)
24
- for (const i of r.values())
25
- i.callback(e);
26
- }
27
- resolve(s) {
28
- return console.log("resolve", s, this.symbolMap[s] ?? b[s].value), this.symbolMap[s] ?? b[s].value;
29
- }
30
- subscribe(s, e) {
31
- const t = this.nextSubscriberId++;
32
- this.subscribers[s] || (this.subscribers[s] = /* @__PURE__ */ new Map()), this.subscribers[s].set(t, { id: t, callback: e });
33
- const r = this.symbolMap[s];
34
- return r !== void 0 && e(r), () => {
35
- this.unsubscribe(s, t);
65
+ n && this.invalidSymbolMap.add(n[0]), this.storeState([i]);
66
+ const l = this.subscribers[i];
67
+ if (l)
68
+ for (const r of l.values())
69
+ r.callback(e);
70
+ }
71
+ resolve(t) {
72
+ const e = this.symbolMap[t];
73
+ return e != null ? [e, this.invalidSymbolMap.has(t) ? "invalid" : "valid"] : void 0;
74
+ }
75
+ subscribe(t, e) {
76
+ const s = this.nextSubscriberId++;
77
+ return this.subscribers[t] || (this.subscribers[t] = /* @__PURE__ */ new Map()), this.subscribers[t].set(s, { id: s, callback: e }), () => {
78
+ this.unsubscribe(t, s);
36
79
  };
37
80
  }
38
- unsubscribe(s, e) {
39
- const t = this.subscribers[s];
40
- t && (t.delete(e), t.size === 0 && Reflect.deleteProperty(this.subscribe, s));
81
+ unsubscribe(t, e) {
82
+ const s = this.subscribers[t];
83
+ s && (s.delete(e), s.size === 0 && Reflect.deleteProperty(this.subscribe, t));
84
+ }
85
+ delimiterForType(t) {
86
+ return t === "chord" ? this.chordDelimiter : this.sequnceDelimiter;
87
+ }
88
+ toString(t) {
89
+ const e = t.toParts();
90
+ return e[0].map((s) => s[0]).join(e[1]);
41
91
  }
42
92
  }
43
93
  export {
44
- o as HotkeyTextResolver
94
+ c as HotkeyTextResolver
45
95
  };
@@ -1,4 +1,4 @@
1
1
  import { PropsWithChildren } from 'react';
2
2
  import { HotkeyProviderProps } from '../types/hotkey/provider/HotkeyProviderProps';
3
- export declare function HotkeyProvider({ children, sequenceTimeout, chordTimeout, }: PropsWithChildren<HotkeyProviderProps>): import("react/jsx-runtime").JSX.Element;
3
+ export declare function HotkeyProvider({ children, sequenceTimeout, chordTimeout, sequenceDelimiter, chordDelimiter, customSymbolMap, }: PropsWithChildren<HotkeyProviderProps>): import("react/jsx-runtime").JSX.Element;
4
4
  //# sourceMappingURL=HotkeyProvider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"HotkeyProvider.d.ts","sourceRoot":"","sources":["../../src/lib/context/HotkeyProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAI/C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8CAA8C,CAAC;AAGxF,wBAAgB,cAAc,CAAC,EAC7B,QAAQ,EACR,eAAe,EACf,YAAY,GACb,EAAE,iBAAiB,CAAC,mBAAmB,CAAC,2CA6BxC"}
1
+ {"version":3,"file":"HotkeyProvider.d.ts","sourceRoot":"","sources":["../../src/lib/context/HotkeyProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAK/C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8CAA8C,CAAC;AAGxF,wBAAgB,cAAc,CAAC,EAC7B,QAAQ,EACR,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,eAAe,GAChB,EAAE,iBAAiB,CAAC,mBAAmB,CAAC,2CAoCxC"}
@@ -1,31 +1,35 @@
1
- import { jsx as u } from "react/jsx-runtime";
2
- import { useContext as v, useState as s, useEffect as a } from "react";
3
- import { HotkeyContext as d } from "./HotkeyContext.js";
4
- import { HotkeyRegistry as l } from "../HotkeyRegistry.js";
5
- import { HotkeyTextResolver as f } from "../HotkeyTextResolver.js";
6
- function K({
7
- children: y,
1
+ import { jsx as p } from "react/jsx-runtime";
2
+ import { useContext as a, useState as c, useEffect as f } from "react";
3
+ import { HotkeyContext as n } from "./HotkeyContext.js";
4
+ import { HotkeyRegistry as k } from "../HotkeyRegistry.js";
5
+ import { HotkeyTextResolver as l } from "../HotkeyTextResolver.js";
6
+ function H({
7
+ children: s,
8
8
  sequenceTimeout: i,
9
- chordTimeout: m
9
+ chordTimeout: y,
10
+ sequenceDelimiter: d,
11
+ chordDelimiter: m,
12
+ customSymbolMap: u
10
13
  }) {
11
- const p = v(d), [o] = s(
12
- p?.textResolver ?? new f()
13
- ), [e] = s(
14
- new l(i, m, o)
15
- );
16
- return a(() => {
17
- const n = (t) => e.handleKeydown(t), r = (t) => e.handleKeyup(t);
18
- return addEventListener("keydown", n), addEventListener("keyup", r), () => {
19
- removeEventListener("keydown", n), removeEventListener("keyup", r);
14
+ const v = a(n), [t] = c(() => {
15
+ const e = v?.textResolver ?? new l(
16
+ u,
17
+ m,
18
+ d
19
+ );
20
+ return { registry: new k(
21
+ i,
22
+ y,
23
+ e
24
+ ), textResolver: e };
25
+ });
26
+ return f(() => {
27
+ const e = (o) => t.registry.handleKeydown(o), r = (o) => t.registry.handleKeyup(o);
28
+ return addEventListener("keydown", e), addEventListener("keyup", r), () => {
29
+ removeEventListener("keydown", e), removeEventListener("keyup", r);
20
30
  };
21
- }, [e, e.handleKeydown, e.handleKeyup]), /* @__PURE__ */ u(
22
- d.Provider,
23
- {
24
- value: { registry: e, textResolver: o },
25
- children: y
26
- }
27
- );
31
+ }, [t.registry]), /* @__PURE__ */ p(n.Provider, { value: t, children: s });
28
32
  }
29
33
  export {
30
- K as HotkeyProvider
34
+ H as HotkeyProvider
31
35
  };
@@ -1 +1 @@
1
- {"version":3,"file":"Chord.d.ts","sourceRoot":"","sources":["../../src/lib/definitions/Chord.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAGpE,eAAO,MAAM,wBAAwB,GACnC,MAAM,eAAe,EAAE,KACtB,SAAS,CAAC,eAAe,EAAE,cAAc,GAAG,eAAe,CAkCK,CAAC"}
1
+ {"version":3,"file":"Chord.d.ts","sourceRoot":"","sources":["../../src/lib/definitions/Chord.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAIpE,eAAO,MAAM,wBAAwB,GACnC,MAAM,eAAe,EAAE,KACtB,SAAS,CAAC,eAAe,EAAE,cAAc,GAAG,eAAe,CAoCK,CAAC"}
@@ -1,32 +1,33 @@
1
- import { detectOS as i } from "../util/detectOS.js";
2
- import { ALL_MODIFIER_KEY_CODES as n } from "./ModifierKeyCodes.js";
3
- import { KeyMap as a } from "./KeyMap.js";
4
- const l = (r) => new Proxy(
1
+ import { detectOS as n } from "../util/detectOS.js";
2
+ import { ALL_MODIFIER_KEY_CODES as a } from "./ModifierKeyCodes.js";
3
+ import { KeyMap as l } from "./KeyMap.js";
4
+ const s = (r) => new Proxy(
5
5
  {},
6
6
  {
7
- get(s, e) {
7
+ get(c, e) {
8
8
  if (typeof e == "string") {
9
- if (n.indexOf(e) === -1) {
10
- const o = a[e], t = {
11
- Meta: !1,
9
+ if (a.indexOf(e) === -1) {
10
+ const o = e, f = l[o], t = {
11
+ Shift: !1,
12
12
  Alt: !1,
13
13
  Control: !1,
14
- Shift: !1
14
+ Meta: !1
15
15
  };
16
- return r.forEach((f) => {
17
- f === "Mod" ? t[i() === "macOS" ? "Meta" : "Control"] = !0 : t[f] = !0;
16
+ return r.forEach((i) => {
17
+ i === "Mod" ? t[n() === "macOS" ? "Meta" : "Control"] = !0 : t[i] = !0;
18
18
  }), {
19
19
  type: "chord",
20
20
  modifier: t,
21
- resolve: o.on,
22
- primaryValue: o.value
21
+ keyId: o,
22
+ resolve: f.on,
23
+ primaryValue: f.value
23
24
  };
24
25
  }
25
- return l([...r, e]);
26
+ return s([...r, e]);
26
27
  }
27
28
  }
28
29
  }
29
30
  );
30
31
  export {
31
- l as createHotkeyChordBuilder
32
+ s as createHotkeyChordBuilder
32
33
  };
@@ -1 +1 @@
1
- {"version":3,"file":"useHotkey.d.ts","sourceRoot":"","sources":["../../src/lib/hooks/useHotkey.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AACnF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAMnE,KAAK,OAAO,GAAG,kBAAkB,CAAC;AAClC,KAAK,UAAU,GAAG,qBAAqB,CAAC;AACxC,KAAK,QAAQ,GAAG,cAAc,CAAC;AAC/B,KAAK,WAAW,GAAG,iBAAiB,CAAC;AAKrC,KAAK,aAAa,CAAC,CAAC,SAAS,SAAS,CAAC,OAAO,GAAG,UAAU,CAAC,EAAE,IAAI;KAC/D,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,OAAO,GAAG,QAAQ,GAAG,WAAW;CAC9D,CAAC;AAOF,wBAAgB,SAAS,CACvB,MAAM,EAAE,OAAO,EACf,QAAQ,EAAE,cAAc,EACxB,YAAY,CAAC,EAAE,OAAO,EAAE,EACxB,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAC/B,QAAQ,CAAC;AACZ,wBAAgB,SAAS,CACvB,MAAM,EAAE,UAAU,EAClB,QAAQ,EAAE,cAAc,EACxB,YAAY,CAAC,EAAE,OAAO,EAAE,EACxB,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAC/B,WAAW,CAAC;AACf,wBAAgB,SAAS,CAAC,KAAK,CAAC,CAAC,SAAS,SAAS,CAAC,OAAO,GAAG,UAAU,CAAC,EAAE,EACzE,MAAM,EAAE,CAAC,EACT,QAAQ,EAAE,cAAc,EACxB,YAAY,CAAC,EAAE,OAAO,EAAE,EACxB,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAC/B,aAAa,CAAC,OAAO,MAAM,CAAC,CAAC"}
1
+ {"version":3,"file":"useHotkey.d.ts","sourceRoot":"","sources":["../../src/lib/hooks/useHotkey.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AACnF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAenE,KAAK,OAAO,GAAG,kBAAkB,CAAC;AAClC,KAAK,UAAU,GAAG,qBAAqB,CAAC;AACxC,KAAK,QAAQ,GAAG,cAAc,CAAC;AAC/B,KAAK,WAAW,GAAG,iBAAiB,CAAC;AAKrC,KAAK,aAAa,CAAC,CAAC,SAAS,SAAS,CAAC,OAAO,GAAG,UAAU,CAAC,EAAE,IAAI;KAC/D,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,OAAO,GAAG,QAAQ,GAAG,WAAW;CAC9D,CAAC;AAOF,wBAAgB,SAAS,CACvB,MAAM,EAAE,OAAO,EACf,QAAQ,EAAE,cAAc,EACxB,YAAY,CAAC,EAAE,OAAO,EAAE,EACxB,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAC/B,QAAQ,CAAC;AACZ,wBAAgB,SAAS,CACvB,MAAM,EAAE,UAAU,EAClB,QAAQ,EAAE,cAAc,EACxB,YAAY,CAAC,EAAE,OAAO,EAAE,EACxB,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAC/B,WAAW,CAAC;AACf,wBAAgB,SAAS,CAAC,KAAK,CAAC,CAAC,SAAS,SAAS,CAAC,OAAO,GAAG,UAAU,CAAC,EAAE,EACzE,MAAM,EAAE,CAAC,EACT,QAAQ,EAAE,cAAc,EACxB,YAAY,CAAC,EAAE,OAAO,EAAE,EACxB,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAC/B,aAAa,CAAC,OAAO,MAAM,CAAC,CAAC"}
@@ -1,66 +1,79 @@
1
- import { useLayoutEffect as m, useEffect as c, useContext as l, useId as v, useMemo as y } from "react";
2
- import { HotkeyContext as H } from "../context/HotkeyContext.js";
3
- import { KeyMap as p } from "../definitions/KeyMap.js";
4
- import { isPrimaryKeyCode as C } from "../util/isPrimaryKeyCode.js";
5
- const x = typeof window < "u" ? m : c;
6
- function g(r) {
7
- return Array.isArray(r);
1
+ import { useLayoutEffect as C, useEffect as H, useContext as g, useId as R, useMemo as m, useCallback as c } from "react";
2
+ import { HotkeyContext as S } from "../context/HotkeyContext.js";
3
+ import { KeyMap as x } from "../definitions/KeyMap.js";
4
+ import { isPrimaryKeyCode as E } from "../util/isPrimaryKeyCode.js";
5
+ const w = typeof window < "u" ? C : H;
6
+ function A(o) {
7
+ return Array.isArray(o);
8
8
  }
9
- function $(r, i, d, f) {
10
- const t = l(H), n = v(), u = y(
9
+ function q(o, y, p, v) {
10
+ const r = g(S), n = R(), a = m(
11
11
  () => ({
12
12
  preventDefault: !0,
13
13
  enableOnContentEditable: !1,
14
14
  disabled: !1,
15
- ...f
15
+ ...v
16
16
  }),
17
- [f]
18
- ), s = y(() => g(r) ? r.map(
19
- (o, e) => o.type === "chord" ? {
20
- ...o,
21
- options: u,
22
- id: `${n}-${e}`,
23
- callback: i,
24
- toParts: () => [[], ""],
25
- toString: () => ""
26
- } : {
27
- ...o,
28
- options: u,
29
- id: `${n}-${e}`,
30
- callback: i,
31
- toParts: () => [
32
- o.keys.map(
33
- (a) => C(a) ? t?.textResolver.resolve(a) ?? p[a].value : p[a].value
34
- ),
35
- ""
36
- ],
37
- toString: () => ""
38
- }
39
- ) : {
40
- ...r,
41
- options: u,
42
- id: n,
43
- callback: i,
44
- toParts: () => [[], ""],
45
- toString: () => ""
46
- }, [u, i, r, t?.textResolver, n]);
47
- return x(() => {
48
- if (t == null) {
17
+ [v]
18
+ ), d = c(
19
+ (e) => E(e) ? r?.textResolver.resolve(e) ?? [
20
+ x[`Key${e}`].value,
21
+ "unknown"
22
+ ] : [x[e].value, "unknown"],
23
+ [r?.textResolver]
24
+ ), l = c(
25
+ (e, t) => {
26
+ const i = {
27
+ ...e,
28
+ options: a,
29
+ id: t == null ? n : `${n}-${t}`,
30
+ callback: y,
31
+ toParts: () => [
32
+ e.keys.map((u) => d(u)),
33
+ r?.textResolver.delimiterForType(e.type) ?? ""
34
+ ],
35
+ toString: () => r?.textResolver.toString(i) ?? ""
36
+ };
37
+ return i;
38
+ },
39
+ [a, y, r?.textResolver, n, d]
40
+ ), f = c(
41
+ (e, t) => {
42
+ const i = {
43
+ ...e,
44
+ options: a,
45
+ id: t == null ? n : `${n}-${t}`,
46
+ callback: y,
47
+ toParts: () => [
48
+ [
49
+ ...Object.entries(e.modifier).filter((u) => u[1]).map((u) => [u[0], "valid"]),
50
+ d(e.keyId)
51
+ ],
52
+ r?.textResolver.delimiterForType(e.type) ?? ""
53
+ ],
54
+ toString: () => r?.textResolver.toString(i) ?? ""
55
+ };
56
+ return i;
57
+ },
58
+ [a, y, r?.textResolver, n, d]
59
+ ), s = m(() => A(o) ? o.map((e, t) => e.type === "chord" ? f(e, t) : l(e, t)) : o.type === "chord" ? f(o) : l(o), [f, l, o]);
60
+ return w(() => {
61
+ if (r == null) {
49
62
  console.warn(
50
63
  "No HotkeyContext provided. Use <HotkeyProvider> to provide a HotkeyContext"
51
64
  );
52
65
  return;
53
66
  }
54
- const o = Array.isArray(s) ? s : [s];
55
- return o.forEach((e) => {
56
- e.type === "chord" ? t.registry.addChordHotkey(e) : t.registry.addSequenceHotkey(e);
67
+ const e = Array.isArray(s) ? s : [s];
68
+ return e.forEach((t) => {
69
+ t.type === "chord" ? r.registry.addChordHotkey(t) : r.registry.addSequenceHotkey(t);
57
70
  }), () => {
58
- o.forEach((e) => {
59
- e.type === "chord" ? t.registry.removeChordHotkey(e.id) : t.registry.removeSequenceHotkey(e.id);
71
+ e.forEach((t) => {
72
+ t.type === "chord" ? r.registry.removeChordHotkey(t.id) : r.registry.removeSequenceHotkey(t.id);
60
73
  });
61
74
  };
62
- }, [s, ...d || []]), s;
75
+ }, [s, ...p || []]), s;
63
76
  }
64
77
  export {
65
- $ as useHotkey
78
+ q as useHotkey
66
79
  };
@@ -0,0 +1,7 @@
1
+ import { HotKeyDef } from '../types/hotkey/HotKeyDef';
2
+ import { HotkeyTextParts } from '../types/hotkey/HotkeyTextParts';
3
+ export declare function useRenderedHotkey(hotkey: HotKeyDef): {
4
+ asString: string;
5
+ asParts: HotkeyTextParts;
6
+ };
7
+ //# sourceMappingURL=useRenderedHotkey.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRenderedHotkey.d.ts","sourceRoot":"","sources":["../../src/lib/hooks/useRenderedHotkey.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAG3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAEvE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS;cAIrC,MAAM;aACP,eAAe;EAiC3B"}
@@ -0,0 +1,31 @@
1
+ import { useContext as a, useState as u, useEffect as c } from "react";
2
+ import { HotkeyContext as d } from "../context/HotkeyContext.js";
3
+ import { toPrimaryKeyCode as o } from "../util/toPrimaryKeyCode.js";
4
+ function P(r) {
5
+ const t = a(d), [i, n] = u({
6
+ asString: r.toString(),
7
+ asParts: r.toParts()
8
+ });
9
+ return c(() => {
10
+ if (t == null) return;
11
+ let e;
12
+ return r.type === "chord" ? e = [
13
+ t.textResolver.subscribe(o(r.keyId), () => {
14
+ n({
15
+ asParts: r.toParts(),
16
+ asString: r.toString()
17
+ });
18
+ })
19
+ ] : e = r.keys.map(
20
+ (s) => t.textResolver.subscribe(o(s), () => {
21
+ n({
22
+ asParts: r.toParts(),
23
+ asString: r.toString()
24
+ });
25
+ })
26
+ ), () => e.forEach((s) => s());
27
+ }, [t, r]), i;
28
+ }
29
+ export {
30
+ P as useRenderedHotkey
31
+ };
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ import { HotkeyContext } from './context/HotkeyContext';
2
2
  import { HotkeyProvider } from './context/HotkeyProvider';
3
3
  import { Hotkey } from './definitions/Hotkey';
4
4
  import { useHotkey } from './hooks/useHotkey';
5
+ import { useRenderedHotkey } from './hooks/useRenderedHotkey';
5
6
  import { detectOS } from './util/detectOS';
6
- export { Hotkey, useHotkey, HotkeyContext, HotkeyProvider, detectOS };
7
+ export { Hotkey, useHotkey, useRenderedHotkey, HotkeyContext, HotkeyProvider, detectOS, };
7
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/lib/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE3C,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/lib/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE3C,OAAO,EACL,MAAM,EACN,SAAS,EACT,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,QAAQ,GACT,CAAC"}
package/dist/index.js CHANGED
@@ -1,12 +1,14 @@
1
- import { HotkeyContext as t } from "./context/HotkeyContext.js";
1
+ import { HotkeyContext as r } from "./context/HotkeyContext.js";
2
2
  import { HotkeyProvider as x } from "./context/HotkeyProvider.js";
3
3
  import { Hotkey as m } from "./definitions/Hotkey.js";
4
4
  import { useHotkey as k } from "./hooks/useHotkey.js";
5
- import { detectOS as H } from "./util/detectOS.js";
5
+ import { useRenderedHotkey as H } from "./hooks/useRenderedHotkey.js";
6
+ import { detectOS as n } from "./util/detectOS.js";
6
7
  export {
7
8
  m as Hotkey,
8
- t as HotkeyContext,
9
+ r as HotkeyContext,
9
10
  x as HotkeyProvider,
10
- H as detectOS,
11
- k as useHotkey
11
+ n as detectOS,
12
+ k as useHotkey,
13
+ H as useRenderedHotkey
12
14
  };
@@ -1,8 +1,10 @@
1
1
  import { KeyValueType } from '../key/KeyValueType';
2
2
  import { ModifierKeyCode } from '../key/ModifierKeyCode';
3
+ import { PrimaryKey } from '../key/PrimaryKey';
3
4
  export type HotKeyDefChordBase = {
4
5
  type: "chord";
5
6
  resolve: KeyValueType;
7
+ keyId: PrimaryKey;
6
8
  primaryValue: string;
7
9
  modifier: Record<Exclude<ModifierKeyCode, "Mod">, boolean>;
8
10
  };
@@ -1 +1 @@
1
- {"version":3,"file":"HotKeyDefChordBase.d.ts","sourceRoot":"","sources":["../../../src/lib/types/hotkey/HotKeyDefChordBase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,YAAY,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,eAAe,EAAE,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC;CAC5D,CAAC"}
1
+ {"version":3,"file":"HotKeyDefChordBase.d.ts","sourceRoot":"","sources":["../../../src/lib/types/hotkey/HotKeyDefChordBase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,YAAY,CAAC;IACtB,KAAK,EAAE,UAAU,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,eAAe,EAAE,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC;CAC5D,CAAC"}
@@ -1,2 +1,3 @@
1
- export type HotkeyTextParts = [string[], string];
1
+ import { ResolvedKeyStatus } from './renderer/ResolvedKeyStatus';
2
+ export type HotkeyTextParts = [[string, ResolvedKeyStatus][], string];
2
3
  //# sourceMappingURL=HotkeyTextParts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"HotkeyTextParts.d.ts","sourceRoot":"","sources":["../../../src/lib/types/hotkey/HotkeyTextParts.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG,CAAC,MAAM,EAAE,EAAE,MAAM,CAAC,CAAC"}
1
+ {"version":3,"file":"HotkeyTextParts.d.ts","sourceRoot":"","sources":["../../../src/lib/types/hotkey/HotkeyTextParts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAEtE,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,EAAE,iBAAiB,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC"}
@@ -1,3 +1,4 @@
1
+ import { PrimaryKeyCode } from '../../key/PrimaryKeyCode';
1
2
  /**
2
3
  * All options regarding an entire hotkey scope
3
4
  */
@@ -12,5 +13,20 @@ export type HotkeyProviderProps = {
12
13
  * @default 100
13
14
  */
14
15
  chordTimeout?: number;
16
+ /**
17
+ * Defines what string will be used in stringified sequence hotkeys
18
+ * @default ">"
19
+ */
20
+ sequenceDelimiter?: string;
21
+ /**
22
+ * Defines what string will be used in stringified chord hotkeys
23
+ * @default "+"
24
+ */
25
+ chordDelimiter?: string;
26
+ /**
27
+ * Defines custom key code mappings for text representation of hotkey for alternative keyboard layouts. (e.g. German: KeyY -> Z)
28
+ * @default undefined
29
+ */
30
+ customSymbolMap?: Partial<Record<PrimaryKeyCode, string>>;
15
31
  };
16
32
  //# sourceMappingURL=HotkeyProviderProps.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"HotkeyProviderProps.d.ts","sourceRoot":"","sources":["../../../../src/lib/types/hotkey/provider/HotkeyProviderProps.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC"}
1
+ {"version":3,"file":"HotkeyProviderProps.d.ts","sourceRoot":"","sources":["../../../../src/lib/types/hotkey/provider/HotkeyProviderProps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE/D;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC;CAC3D,CAAC"}
@@ -0,0 +1,2 @@
1
+ export type ResolvedKeyStatus = "invalid" | "valid" | "unknown";
2
+ //# sourceMappingURL=ResolvedKeyStatus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ResolvedKeyStatus.d.ts","sourceRoot":"","sources":["../../../../src/lib/types/hotkey/renderer/ResolvedKeyStatus.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { PrimaryKey } from '../types/key/PrimaryKey';
2
+ import { PrimaryKeyCode } from '../types/key/PrimaryKeyCode';
3
+ export declare function toPrimaryKeyCode(keyId: PrimaryKey): PrimaryKeyCode;
4
+ //# sourceMappingURL=toPrimaryKeyCode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toPrimaryKeyCode.d.ts","sourceRoot":"","sources":["../../src/lib/util/toPrimaryKeyCode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAGlE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,cAAc,CAElE"}
@@ -0,0 +1,7 @@
1
+ import { isPrimaryKeyCode as o } from "./isPrimaryKeyCode.js";
2
+ function e(r) {
3
+ return o(r) ? r : r.slice(3);
4
+ }
5
+ export {
6
+ e as toPrimaryKeyCode
7
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-better-hotkeys",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "author": "Christopher Haindl",
6
6
  "repository": {