@pyreon/hotkeys 0.6.0 → 0.7.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.
@@ -1,198 +1,130 @@
1
- import { onUnmount } from "@pyreon/core";
2
- import { signal } from "@pyreon/reactivity";
3
-
4
- //#region src/parse.ts
1
+ import { Signal } from "@pyreon/reactivity";
5
2
 
3
+ //#region src/types.d.ts
6
4
  /**
7
- * Parse a shortcut string like 'ctrl+shift+s' into a KeyCombo.
8
- * Supports aliases (esc, del, space, etc.) and mod (ctrl on Windows/Linux, meta on Mac).
9
- */
10
- function parseShortcut(shortcut) {
11
- const parts = shortcut.toLowerCase().trim().split("+");
12
- const combo = {
13
- ctrl: false,
14
- shift: false,
15
- alt: false,
16
- meta: false,
17
- key: ""
18
- };
19
- for (const part of parts) {
20
- const p = part.trim();
21
- if (p === "ctrl" || p === "control") combo.ctrl = true;else if (p === "shift") combo.shift = true;else if (p === "alt") combo.alt = true;else if (p === "meta" || p === "cmd" || p === "command") combo.meta = true;else if (p === "mod") {
22
- if (isMac()) combo.meta = true;else combo.ctrl = true;
23
- } else combo.key = KEY_ALIASES[p] ?? p;
24
- }
25
- return combo;
5
+ * A parsed key combination.
6
+ * Example: 'ctrl+shift+s' { ctrl: true, shift: true, alt: false, meta: false, key: 's' }
7
+ */
8
+ interface KeyCombo {
9
+ ctrl: boolean;
10
+ shift: boolean;
11
+ alt: boolean;
12
+ meta: boolean;
13
+ key: string;
26
14
  }
27
15
  /**
28
- * Check if a KeyboardEvent matches a KeyCombo.
29
- */
30
- function matchesCombo(event, combo) {
31
- if (event.ctrlKey !== combo.ctrl) return false;
32
- if (event.shiftKey !== combo.shift) return false;
33
- if (event.altKey !== combo.alt) return false;
34
- if (event.metaKey !== combo.meta) return false;
35
- return event.key.toLowerCase() === combo.key;
16
+ * Options for registering a hotkey.
17
+ */
18
+ interface HotkeyOptions {
19
+ /** Scope for the hotkey — only active when this scope is active. Default: 'global' */
20
+ scope?: string;
21
+ /** Whether to prevent default browser behavior — default: true */
22
+ preventDefault?: boolean;
23
+ /** Whether to stop event propagation — default: false */
24
+ stopPropagation?: boolean;
25
+ /** Whether the hotkey fires when an input/textarea/contenteditable is focused — default: false */
26
+ enableOnInputs?: boolean;
27
+ /** Description of what this hotkey does — useful for help dialogs */
28
+ description?: string;
29
+ /** Whether the hotkey is enabled — default: true */
30
+ enabled?: boolean | (() => boolean);
36
31
  }
37
32
  /**
38
- * Format a KeyCombo back to a human-readable string.
39
- */
40
- function formatCombo(combo) {
41
- const parts = [];
42
- if (combo.ctrl) parts.push("Ctrl");
43
- if (combo.shift) parts.push("Shift");
44
- if (combo.alt) parts.push("Alt");
45
- if (combo.meta) parts.push(isMac() ? "⌘" : "Meta");
46
- parts.push(combo.key.length === 1 ? combo.key.toUpperCase() : capitalize(combo.key));
47
- return parts.join("+");
48
- }
49
- function capitalize(s) {
50
- return s.charAt(0).toUpperCase() + s.slice(1);
51
- }
52
- function isMac() {
53
- if (typeof navigator === "undefined") return false;
54
- return /mac|iphone|ipad|ipod/i.test(navigator.userAgent);
33
+ * A registered hotkey entry.
34
+ */
35
+ interface HotkeyEntry {
36
+ /** The original shortcut string (e.g. 'ctrl+s') */
37
+ shortcut: string;
38
+ /** Parsed key combination */
39
+ combo: KeyCombo;
40
+ /** The callback to invoke */
41
+ handler: (event: KeyboardEvent) => void;
42
+ /** Options */
43
+ options: Required<Pick<HotkeyOptions, 'scope' | 'preventDefault' | 'stopPropagation' | 'enableOnInputs' | 'enabled'>> & {
44
+ description?: string;
45
+ };
55
46
  }
56
-
57
47
  //#endregion
58
- //#region src/registry.ts
59
-
60
- function isInputFocused(event) {
61
- const target = event.target;
62
- if (!target) return false;
63
- if (INPUT_TAGS.has(target.tagName)) return true;
64
- if (target.isContentEditable) return true;
65
- return false;
66
- }
67
- function attachListener() {
68
- if (listenerAttached) return;
69
- if (typeof window === "undefined") return;
70
- listenerAttached = true;
71
- window.addEventListener("keydown", event => {
72
- const scopes = activeScopes.peek();
73
- for (const entry of entries) {
74
- if (!scopes.has(entry.options.scope)) continue;
75
- if (!(typeof entry.options.enabled === "function" ? entry.options.enabled() : entry.options.enabled)) continue;
76
- if (!entry.options.enableOnInputs && isInputFocused(event)) continue;
77
- if (!matchesCombo(event, entry.combo)) continue;
78
- if (entry.options.preventDefault) event.preventDefault();
79
- if (entry.options.stopPropagation) event.stopPropagation();
80
- entry.handler(event);
81
- }
82
- });
83
- }
48
+ //#region src/use-hotkey.d.ts
84
49
  /**
85
- * Register a keyboard shortcut. Returns an unregister function.
86
- *
87
- * @example
88
- * ```ts
89
- * const unregister = registerHotkey('ctrl+s', (e) => save(), { description: 'Save' })
90
- * // later: unregister()
91
- * ```
92
- */
93
- function registerHotkey(shortcut, handler, options) {
94
- attachListener();
95
- const entry = {
96
- shortcut,
97
- combo: parseShortcut(shortcut),
98
- handler,
99
- options: {
100
- scope: options?.scope ?? "global",
101
- preventDefault: options?.preventDefault !== false,
102
- stopPropagation: options?.stopPropagation === true,
103
- enableOnInputs: options?.enableOnInputs === true,
104
- enabled: options?.enabled ?? true,
105
- description: options?.description
106
- }
107
- };
108
- entries.push(entry);
109
- return () => {
110
- const idx = entries.indexOf(entry);
111
- if (idx !== -1) entries.splice(idx, 1);
112
- };
113
- }
50
+ * Register a keyboard shortcut scoped to a component's lifecycle.
51
+ * Automatically unregisters when the component unmounts.
52
+ *
53
+ * @example
54
+ * ```ts
55
+ * function Editor() {
56
+ * useHotkey('ctrl+s', () => save(), { description: 'Save document' })
57
+ * useHotkey('ctrl+z', () => undo())
58
+ * useHotkey('ctrl+shift+z', () => redo())
59
+ * // ...
60
+ * }
61
+ * ```
62
+ */
63
+ declare function useHotkey(shortcut: string, handler: (event: KeyboardEvent) => void, options?: HotkeyOptions): void;
64
+ //#endregion
65
+ //#region src/use-hotkey-scope.d.ts
114
66
  /**
115
- * Activate a hotkey scope. 'global' is always active.
116
- */
117
- function enableScope(scope) {
118
- const current = activeScopes.peek();
119
- if (current.has(scope)) return;
120
- const next = new Set(current);
121
- next.add(scope);
122
- activeScopes.set(next);
123
- }
67
+ * Activate a hotkey scope for the lifetime of a component.
68
+ * When the component unmounts, the scope is deactivated.
69
+ *
70
+ * @example
71
+ * ```tsx
72
+ * function Modal() {
73
+ * useHotkeyScope('modal')
74
+ * useHotkey('escape', () => closeModal(), { scope: 'modal' })
75
+ * // ...
76
+ * }
77
+ * ```
78
+ */
79
+ declare function useHotkeyScope(scope: string): void;
80
+ //#endregion
81
+ //#region src/registry.d.ts
124
82
  /**
125
- * Deactivate a hotkey scope. Cannot deactivate 'global'.
126
- */
127
- function disableScope(scope) {
128
- if (scope === "global") return;
129
- const current = activeScopes.peek();
130
- if (!current.has(scope)) return;
131
- const next = new Set(current);
132
- next.delete(scope);
133
- activeScopes.set(next);
134
- }
83
+ * Register a keyboard shortcut. Returns an unregister function.
84
+ *
85
+ * @example
86
+ * ```ts
87
+ * const unregister = registerHotkey('ctrl+s', (e) => save(), { description: 'Save' })
88
+ * // later: unregister()
89
+ * ```
90
+ */
91
+ declare function registerHotkey(shortcut: string, handler: (event: KeyboardEvent) => void, options?: HotkeyOptions): () => void;
135
92
  /**
136
- * Get the currently active scopes as a reactive signal.
137
- */
138
- function getActiveScopes() {
139
- return activeScopes;
140
- }
93
+ * Activate a hotkey scope. 'global' is always active.
94
+ */
95
+ declare function enableScope(scope: string): void;
141
96
  /**
142
- * Get all registered hotkeys (for building help dialogs).
143
- */
144
- function getRegisteredHotkeys() {
145
- return entries.map(e => ({
146
- shortcut: e.shortcut,
147
- scope: e.options.scope,
148
- description: e.options.description
149
- }));
150
- }
151
- function _resetHotkeys() {
152
- entries.length = 0;
153
- activeScopes.set(new Set(["global"]));
154
- }
155
-
156
- //#endregion
157
- //#region src/use-hotkey.ts
97
+ * Deactivate a hotkey scope. Cannot deactivate 'global'.
98
+ */
99
+ declare function disableScope(scope: string): void;
158
100
  /**
159
- * Register a keyboard shortcut scoped to a component's lifecycle.
160
- * Automatically unregisters when the component unmounts.
161
- *
162
- * @example
163
- * ```ts
164
- * function Editor() {
165
- * useHotkey('ctrl+s', () => save(), { description: 'Save document' })
166
- * useHotkey('ctrl+z', () => undo())
167
- * useHotkey('ctrl+shift+z', () => redo())
168
- * // ...
169
- * }
170
- * ```
171
- */
172
- function useHotkey(shortcut, handler, options) {
173
- onUnmount(registerHotkey(shortcut, handler, options));
174
- }
175
-
101
+ * Get the currently active scopes as a reactive signal.
102
+ */
103
+ declare function getActiveScopes(): Signal<Set<string>>;
104
+ /**
105
+ * Get all registered hotkeys (for building help dialogs).
106
+ */
107
+ declare function getRegisteredHotkeys(): ReadonlyArray<{
108
+ shortcut: string;
109
+ scope: string;
110
+ description?: string;
111
+ }>;
112
+ declare function _resetHotkeys(): void;
176
113
  //#endregion
177
- //#region src/use-hotkey-scope.ts
114
+ //#region src/parse.d.ts
178
115
  /**
179
- * Activate a hotkey scope for the lifetime of a component.
180
- * When the component unmounts, the scope is deactivated.
181
- *
182
- * @example
183
- * ```tsx
184
- * function Modal() {
185
- * useHotkeyScope('modal')
186
- * useHotkey('escape', () => closeModal(), { scope: 'modal' })
187
- * // ...
188
- * }
189
- * ```
190
- */
191
- function useHotkeyScope(scope) {
192
- enableScope(scope);
193
- onUnmount(() => disableScope(scope));
194
- }
195
-
116
+ * Parse a shortcut string like 'ctrl+shift+s' into a KeyCombo.
117
+ * Supports aliases (esc, del, space, etc.) and mod (ctrl on Windows/Linux, meta on Mac).
118
+ */
119
+ declare function parseShortcut(shortcut: string): KeyCombo;
120
+ /**
121
+ * Check if a KeyboardEvent matches a KeyCombo.
122
+ */
123
+ declare function matchesCombo(event: KeyboardEvent, combo: KeyCombo): boolean;
124
+ /**
125
+ * Format a KeyCombo back to a human-readable string.
126
+ */
127
+ declare function formatCombo(combo: KeyCombo): string;
196
128
  //#endregion
197
- export { _resetHotkeys, disableScope, enableScope, formatCombo, getActiveScopes, getRegisteredHotkeys, matchesCombo, parseShortcut, registerHotkey, useHotkey, useHotkeyScope };
198
- //# sourceMappingURL=index.d.ts.map
129
+ export { type HotkeyEntry, type HotkeyOptions, type KeyCombo, _resetHotkeys, disableScope, enableScope, formatCombo, getActiveScopes, getRegisteredHotkeys, matchesCombo, parseShortcut, registerHotkey, useHotkey, useHotkeyScope };
130
+ //# sourceMappingURL=index2.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/parse.ts","../../src/registry.ts","../../src/use-hotkey.ts","../../src/use-hotkey-scope.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index2.d.ts","names":[],"sources":["../../../src/types.ts","../../../src/use-hotkey.ts","../../../src/use-hotkey-scope.ts","../../../src/registry.ts","../../../src/parse.ts"],"mappings":";;;;;;AAMA;UAAiB,QAAA;EACf,IAAA;EACA,KAAA;EACA,GAAA;EACA,IAAA;EACA,GAAA;AAAA;;;;UAMe,aAAA;EAAa;EAE5B,KAAA;EAF4B;EAI5B,cAAA;EAAA;EAEA,eAAA;EAEA;EAAA,cAAA;EAIA;EAFA,WAAA;EAEO;EAAP,OAAA;AAAA;;;;UAMe,WAAA;EASb;EAPF,QAAA;EAMiB;EAJjB,KAAA,EAAO,QAAA;EAFP;EAIA,OAAA,GAAU,KAAA,EAAO,aAAA;EAFV;EAIP,OAAA,EAAS,QAAA,CACP,IAAA,CACE,aAAA;IAOE,WAAA;EAAA;AAAA;;;;;AA9CR;;;;;;;;;;;AAWA;iBCCgB,SAAA,CACd,QAAA,UACA,OAAA,GAAU,KAAA,EAAO,aAAA,WACjB,OAAA,GAAU,aAAA;;;;;;ADfZ;;;;;;;;;;iBEUgB,cAAA,CAAe,KAAA;;;;AFV/B;;;;;;;;iBG+DgB,cAAA,CACd,QAAA,UACA,OAAA,GAAU,KAAA,EAAO,aAAA,WACjB,OAAA,GAAU,aAAA;;;AHvDZ;iBGsFgB,WAAA,CAAY,KAAA;;;;iBAWZ,YAAA,CAAa,KAAA;;;;iBAYb,eAAA,CAAA,GAAmB,MAAA,CAAO,GAAA;;;AH3F1C;iBGkGgB,oBAAA,CAAA,GAAwB,aAAA;EACtC,QAAA;EACA,KAAA;EACA,WAAA;AAAA;AAAA,iBAWc,aAAA,CAAA;;;;;AH7IhB;;iBIgBgB,aAAA,CAAc,QAAA,WAAmB,QAAA;;;;iBAsCjC,YAAA,CAAa,KAAA,EAAO,aAAA,EAAe,KAAA,EAAO,QAAA;;;;iBAa1C,WAAA,CAAY,KAAA,EAAO,QAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pyreon/hotkeys",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Reactive keyboard shortcut management for Pyreon — scope-aware, conflict detection",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -42,11 +42,5 @@
42
42
  "peerDependencies": {
43
43
  "@pyreon/core": ">=0.5.0 <1.0.0",
44
44
  "@pyreon/reactivity": ">=0.5.0 <1.0.0"
45
- },
46
- "devDependencies": {
47
- "@happy-dom/global-registrator": "^20.8.3",
48
- "@pyreon/core": ">=0.5.0 <1.0.0",
49
- "@pyreon/reactivity": ">=0.5.0 <1.0.0",
50
- "@vitus-labs/tools-lint": "^1.11.0"
51
45
  }
52
46
  }
@@ -1,130 +0,0 @@
1
- import { Signal } from "@pyreon/reactivity";
2
-
3
- //#region src/types.d.ts
4
- /**
5
- * A parsed key combination.
6
- * Example: 'ctrl+shift+s' → { ctrl: true, shift: true, alt: false, meta: false, key: 's' }
7
- */
8
- interface KeyCombo {
9
- ctrl: boolean;
10
- shift: boolean;
11
- alt: boolean;
12
- meta: boolean;
13
- key: string;
14
- }
15
- /**
16
- * Options for registering a hotkey.
17
- */
18
- interface HotkeyOptions {
19
- /** Scope for the hotkey — only active when this scope is active. Default: 'global' */
20
- scope?: string;
21
- /** Whether to prevent default browser behavior — default: true */
22
- preventDefault?: boolean;
23
- /** Whether to stop event propagation — default: false */
24
- stopPropagation?: boolean;
25
- /** Whether the hotkey fires when an input/textarea/contenteditable is focused — default: false */
26
- enableOnInputs?: boolean;
27
- /** Description of what this hotkey does — useful for help dialogs */
28
- description?: string;
29
- /** Whether the hotkey is enabled — default: true */
30
- enabled?: boolean | (() => boolean);
31
- }
32
- /**
33
- * A registered hotkey entry.
34
- */
35
- interface HotkeyEntry {
36
- /** The original shortcut string (e.g. 'ctrl+s') */
37
- shortcut: string;
38
- /** Parsed key combination */
39
- combo: KeyCombo;
40
- /** The callback to invoke */
41
- handler: (event: KeyboardEvent) => void;
42
- /** Options */
43
- options: Required<Pick<HotkeyOptions, 'scope' | 'preventDefault' | 'stopPropagation' | 'enableOnInputs' | 'enabled'>> & {
44
- description?: string;
45
- };
46
- }
47
- //#endregion
48
- //#region src/use-hotkey.d.ts
49
- /**
50
- * Register a keyboard shortcut scoped to a component's lifecycle.
51
- * Automatically unregisters when the component unmounts.
52
- *
53
- * @example
54
- * ```ts
55
- * function Editor() {
56
- * useHotkey('ctrl+s', () => save(), { description: 'Save document' })
57
- * useHotkey('ctrl+z', () => undo())
58
- * useHotkey('ctrl+shift+z', () => redo())
59
- * // ...
60
- * }
61
- * ```
62
- */
63
- declare function useHotkey(shortcut: string, handler: (event: KeyboardEvent) => void, options?: HotkeyOptions): void;
64
- //#endregion
65
- //#region src/use-hotkey-scope.d.ts
66
- /**
67
- * Activate a hotkey scope for the lifetime of a component.
68
- * When the component unmounts, the scope is deactivated.
69
- *
70
- * @example
71
- * ```tsx
72
- * function Modal() {
73
- * useHotkeyScope('modal')
74
- * useHotkey('escape', () => closeModal(), { scope: 'modal' })
75
- * // ...
76
- * }
77
- * ```
78
- */
79
- declare function useHotkeyScope(scope: string): void;
80
- //#endregion
81
- //#region src/registry.d.ts
82
- /**
83
- * Register a keyboard shortcut. Returns an unregister function.
84
- *
85
- * @example
86
- * ```ts
87
- * const unregister = registerHotkey('ctrl+s', (e) => save(), { description: 'Save' })
88
- * // later: unregister()
89
- * ```
90
- */
91
- declare function registerHotkey(shortcut: string, handler: (event: KeyboardEvent) => void, options?: HotkeyOptions): () => void;
92
- /**
93
- * Activate a hotkey scope. 'global' is always active.
94
- */
95
- declare function enableScope(scope: string): void;
96
- /**
97
- * Deactivate a hotkey scope. Cannot deactivate 'global'.
98
- */
99
- declare function disableScope(scope: string): void;
100
- /**
101
- * Get the currently active scopes as a reactive signal.
102
- */
103
- declare function getActiveScopes(): Signal<Set<string>>;
104
- /**
105
- * Get all registered hotkeys (for building help dialogs).
106
- */
107
- declare function getRegisteredHotkeys(): ReadonlyArray<{
108
- shortcut: string;
109
- scope: string;
110
- description?: string;
111
- }>;
112
- declare function _resetHotkeys(): void;
113
- //#endregion
114
- //#region src/parse.d.ts
115
- /**
116
- * Parse a shortcut string like 'ctrl+shift+s' into a KeyCombo.
117
- * Supports aliases (esc, del, space, etc.) and mod (ctrl on Windows/Linux, meta on Mac).
118
- */
119
- declare function parseShortcut(shortcut: string): KeyCombo;
120
- /**
121
- * Check if a KeyboardEvent matches a KeyCombo.
122
- */
123
- declare function matchesCombo(event: KeyboardEvent, combo: KeyCombo): boolean;
124
- /**
125
- * Format a KeyCombo back to a human-readable string.
126
- */
127
- declare function formatCombo(combo: KeyCombo): string;
128
- //#endregion
129
- export { type HotkeyEntry, type HotkeyOptions, type KeyCombo, _resetHotkeys, disableScope, enableScope, formatCombo, getActiveScopes, getRegisteredHotkeys, matchesCombo, parseShortcut, registerHotkey, useHotkey, useHotkeyScope };
130
- //# sourceMappingURL=index2.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index2.d.ts","names":[],"sources":["../../src/types.ts","../../src/use-hotkey.ts","../../src/use-hotkey-scope.ts","../../src/registry.ts","../../src/parse.ts"],"mappings":";;;;;;AAMA;UAAiB,QAAA;EACf,IAAA;EACA,KAAA;EACA,GAAA;EACA,IAAA;EACA,GAAA;AAAA;;;;UAMe,aAAA;EAAa;EAE5B,KAAA;EAF4B;EAI5B,cAAA;EAAA;EAEA,eAAA;EAEA;EAAA,cAAA;EAIA;EAFA,WAAA;EAEO;EAAP,OAAA;AAAA;;;;UAMe,WAAA;EASb;EAPF,QAAA;EAMiB;EAJjB,KAAA,EAAO,QAAA;EAFP;EAIA,OAAA,GAAU,KAAA,EAAO,aAAA;EAFV;EAIP,OAAA,EAAS,QAAA,CACP,IAAA,CACE,aAAA;IAOE,WAAA;EAAA;AAAA;;;;;AA9CR;;;;;;;;;;;AAWA;iBCCgB,SAAA,CACd,QAAA,UACA,OAAA,GAAU,KAAA,EAAO,aAAA,WACjB,OAAA,GAAU,aAAA;;;;;;ADfZ;;;;;;;;;;iBEUgB,cAAA,CAAe,KAAA;;;;AFV/B;;;;;;;;iBG+DgB,cAAA,CACd,QAAA,UACA,OAAA,GAAU,KAAA,EAAO,aAAA,WACjB,OAAA,GAAU,aAAA;;;AHvDZ;iBGsFgB,WAAA,CAAY,KAAA;;;;iBAWZ,YAAA,CAAa,KAAA;;;;iBAYb,eAAA,CAAA,GAAmB,MAAA,CAAO,GAAA;;;AH3F1C;iBGkGgB,oBAAA,CAAA,GAAwB,aAAA;EACtC,QAAA;EACA,KAAA;EACA,WAAA;AAAA;AAAA,iBAWc,aAAA,CAAA;;;;;AH7IhB;;iBIgBgB,aAAA,CAAc,QAAA,WAAmB,QAAA;;;;iBAsCjC,YAAA,CAAa,KAAA,EAAO,aAAA,EAAe,KAAA,EAAO,QAAA;;;;iBAa1C,WAAA,CAAY,KAAA,EAAO,QAAA"}