A simple micro-library for defining and dispatching keyboard shortcuts with no dependencies
npx @tessl/cli install tessl/npm-hotkeys-js@3.13.00
# Hotkeys-js
1
2
Hotkeys-js is a simple micro-library for defining and dispatching keyboard shortcuts in web applications. It provides a comprehensive API for capturing keyboard events with support for modifier keys, key combinations, scopes for context-specific shortcuts, and flexible filtering options.
3
4
## Package Information
5
6
- **Package Name**: hotkeys-js
7
- **Package Type**: npm
8
- **Language**: JavaScript/TypeScript
9
- **Installation**: `npm install hotkeys-js`
10
11
## Core Imports
12
13
ES Modules:
14
```javascript
15
import hotkeys from 'hotkeys-js';
16
```
17
18
CommonJS:
19
```javascript
20
const hotkeys = require('hotkeys-js');
21
```
22
23
Browser (CDN):
24
```html
25
<script src="https://unpkg.com/hotkeys-js/dist/hotkeys.min.js"></script>
26
```
27
28
## Basic Usage
29
30
```javascript
31
import hotkeys from 'hotkeys-js';
32
33
// Simple shortcut
34
hotkeys('ctrl+a', function (event, handler) {
35
console.log('Select all triggered');
36
});
37
38
// Multiple key combinations
39
hotkeys('ctrl+s, command+s', function (event, handler) {
40
event.preventDefault();
41
console.log('Save triggered');
42
});
43
44
// With scope for context-specific shortcuts
45
hotkeys('enter', 'editing', function (event, handler) {
46
console.log('Enter pressed in editing mode');
47
});
48
49
// Set active scope
50
hotkeys.setScope('editing');
51
```
52
53
## Architecture
54
55
Hotkeys-js is built around several key architectural components:
56
57
- **Event System**: Global keyboard event listeners with element-specific binding support
58
- **Key Mapping Engine**: Comprehensive key code translation supporting special keys, modifiers, and cross-browser compatibility
59
- **Scope Management**: Context-aware shortcut system allowing the same keys to perform different actions in different application states
60
- **Handler Registry**: Efficient storage and lookup system for registered keyboard shortcuts with support for key combinations and modifier keys
61
- **Filtering System**: Customizable event filtering to control when shortcuts are active (e.g., excluding form inputs by default)
62
- **State Tracking**: Real-time tracking of pressed keys and modifier states for advanced use cases
63
64
## Capabilities
65
66
### Main Hotkey Function
67
68
Define keyboard shortcuts with flexible options for key combinations, scopes, and handler functions.
69
70
```javascript { .api }
71
/**
72
* Register a keyboard shortcut with a handler function
73
* @param key - Key combination string (e.g., 'ctrl+s', 'f1', 'ctrl+shift+a')
74
* @param method - Handler function called when shortcut is triggered
75
*/
76
hotkeys(key: string, method: KeyHandler): void;
77
78
/**
79
* Register a keyboard shortcut with a specific scope
80
* @param key - Key combination string
81
* @param scope - Scope name for context-specific shortcuts
82
* @param method - Handler function called when shortcut is triggered
83
*/
84
hotkeys(key: string, scope: string, method: KeyHandler): void;
85
86
/**
87
* Register a keyboard shortcut with advanced options
88
* @param key - Key combination string
89
* @param options - Configuration options for the shortcut
90
* @param method - Handler function called when shortcut is triggered
91
*/
92
hotkeys(key: string, options: Options, method: KeyHandler): void;
93
```
94
95
### Scope Management
96
97
Manage different contexts for keyboard shortcuts, allowing the same keys to perform different actions in different application states.
98
99
```javascript { .api }
100
/**
101
* Set the current active scope. Only shortcuts in 'all' and active scope will trigger
102
* @param scopeName - Name of the scope to activate
103
*/
104
setScope(scopeName: string): void;
105
106
/**
107
* Get the current active scope name
108
* @returns The current scope name (defaults to 'all')
109
*/
110
getScope(): string;
111
112
/**
113
* Delete a scope and all associated shortcuts
114
* @param scopeName - Name of the scope to delete
115
* @param newScopeName - Optional new scope to set after deletion
116
*/
117
deleteScope(scopeName: string, newScopeName?: string): void;
118
```
119
120
### Key State Queries
121
122
Check the current state of pressed keys and retrieve information about active shortcuts.
123
124
```javascript { .api }
125
/**
126
* Check if a specific key is currently pressed
127
* @param keyCode - Key code number or key string to check
128
* @returns True if the key is currently pressed
129
*/
130
isPressed(keyCode: number | string): boolean;
131
132
/**
133
* Get array of key codes currently pressed
134
* @returns Array of numeric key codes for currently pressed keys
135
*/
136
getPressedKeyCodes(): number[];
137
138
/**
139
* Get array of key string representations currently pressed
140
* @returns Array of string representations of currently pressed keys
141
*/
142
getPressedKeyString(): string[];
143
144
/**
145
* Get list of all registered shortcut key combinations with their metadata
146
* @returns Array of registered shortcuts with scope, shortcut, mods, and keys
147
*/
148
getAllKeyCodes(): Omit<HotkeysEvent, 'method' | 'key'>[];
149
```
150
151
### Event Management
152
153
Control shortcut bindings and programmatically trigger shortcuts.
154
155
```javascript { .api }
156
/**
157
* Remove all keyboard shortcut bindings
158
*/
159
unbind(): void;
160
161
/**
162
* Remove keyboard shortcut bindings for a specific key
163
* @param key - Key combination to unbind
164
*/
165
unbind(key: string): void;
166
167
/**
168
* Remove keyboard shortcut bindings for a key in a specific scope
169
* @param key - Key combination to unbind
170
* @param scopeName - Scope name to unbind from
171
*/
172
unbind(key: string, scopeName: string): void;
173
174
/**
175
* Remove a specific handler for a key in a specific scope
176
* @param key - Key combination to unbind
177
* @param scopeName - Scope name to unbind from
178
* @param method - Specific handler function to remove
179
*/
180
unbind(key: string, scopeName: string, method: KeyHandler): void;
181
182
/**
183
* Remove a specific handler for a key
184
* @param key - Key combination to unbind
185
* @param method - Specific handler function to remove
186
*/
187
unbind(key: string, method: KeyHandler): void;
188
189
/**
190
* Programmatically trigger a keyboard shortcut
191
* @param shortcut - Shortcut string to trigger
192
* @param scope - Optional scope to trigger within
193
*/
194
trigger(shortcut: string, scope?: string): void;
195
196
/**
197
* Filter function to determine if hotkeys should be active for given events
198
* Can be overridden to customize filtering behavior
199
* @param event - Keyboard event to filter
200
* @returns True if hotkeys should be active, false otherwise
201
*/
202
filter(event: KeyboardEvent): boolean;
203
```
204
205
### Utility Methods
206
207
Additional utility functions for library management and conflict resolution.
208
209
```javascript { .api }
210
/**
211
* Release control of global 'hotkeys' variable and return hotkeys reference
212
* @param deep - Optional flag for deep conflict resolution
213
* @returns Reference to the hotkeys function
214
*/
215
noConflict(deep?: boolean): Hotkeys;
216
```
217
218
## Properties
219
220
### Modifier Key State Flags
221
222
Boolean properties indicating the current state of modifier keys.
223
224
```javascript { .api }
225
hotkeys.shift: boolean; // Shift key state
226
hotkeys.ctrl: boolean; // Ctrl key state
227
hotkeys.alt: boolean; // Alt key state
228
hotkeys.option: boolean; // Option key state (alias for alt)
229
hotkeys.control: boolean; // Control key state (alias for ctrl)
230
hotkeys.cmd: boolean; // Command key state
231
hotkeys.command: boolean; // Command key state (alias for cmd)
232
```
233
234
### Key Mapping Objects
235
236
Objects containing mappings between key names and key codes.
237
238
```javascript { .api }
239
hotkeys.keyMap: Record<string, number>; // Map of key names to key codes
240
hotkeys.modifier: Record<string, number>; // Map of modifier key names to codes
241
hotkeys.modifierMap: Record<string, number | string>; // Bidirectional modifier mapping
242
```
243
244
## Types
245
246
```typescript { .api }
247
interface HotkeysEvent {
248
key: string; // The pressed key
249
keys: number[]; // Array of pressed key codes
250
method: KeyHandler; // The handler function
251
mods: number[]; // Modifier key codes
252
scope: string; // Current scope
253
shortcut: string; // The shortcut string
254
}
255
256
type KeyHandler = (keyboardEvent: KeyboardEvent, hotkeysEvent: HotkeysEvent) => void | boolean;
257
258
type Options = {
259
scope?: string; // Scope name
260
element?: HTMLElement | null; // Target element
261
keyup?: boolean | null; // Listen to keyup events
262
keydown?: boolean | null; // Listen to keydown events
263
capture?: boolean; // Use capture phase
264
splitKey?: string; // Key combination separator
265
single?: boolean; // Single callback only
266
}
267
```
268
269
## Supported Keys
270
271
### Special Keys
272
- **Navigation**: `left`, `right`, `up`, `down`, `arrowup`, `arrowdown`, `arrowleft`, `arrowright`
273
- **Function Keys**: `f1` through `f19`
274
- **Editing**: `backspace`, `delete`, `del`, `insert`, `ins`, `home`, `end`, `pageup`, `pagedown`
275
- **Control**: `tab`, `enter`, `return`, `esc`, `escape`, `space`, `clear`, `capslock`
276
- **Numpad**: `num_0` through `num_9`, `num_multiply`, `num_add`, `num_enter`, `num_subtract`, `num_decimal`, `num_divide`
277
278
### Modifier Keys
279
- **Shift**: `shift`, `⇧`
280
- **Alt/Option**: `alt`, `option`, `⌥`
281
- **Control**: `ctrl`, `control`, `⌃`
282
- **Command/Meta**: `cmd`, `command`, `meta`, `⌘`
283
284
### Key Combinations
285
Use `+` to combine keys: `ctrl+s`, `ctrl+shift+z`, `command+option+i`
286
287
Use `,` to define multiple shortcuts for the same handler: `ctrl+s, command+s`
288
289
## Usage Examples
290
291
### Scope Management
292
```javascript
293
// Define shortcuts with different scopes
294
hotkeys('ctrl+z', 'editing', function() {
295
console.log('Undo in editing mode');
296
});
297
298
hotkeys('ctrl+z', 'viewing', function() {
299
console.log('Undo in viewing mode');
300
});
301
302
// Switch between scopes
303
hotkeys.setScope('editing'); // Only 'all' and 'editing' shortcuts active
304
hotkeys.setScope('viewing'); // Only 'all' and 'viewing' shortcuts active
305
```
306
307
### Advanced Options
308
```javascript
309
// Listen only to keyup events
310
hotkeys('space', { keyup: true }, function(event, handler) {
311
console.log('Space released');
312
});
313
314
// Target specific element
315
hotkeys('enter', {
316
element: document.getElementById('search-input'),
317
scope: 'search'
318
}, function(event, handler) {
319
console.log('Enter in search input');
320
});
321
```
322
323
### Filtering Events
324
```javascript
325
// Customize filtering to allow hotkeys in contentEditable elements
326
hotkeys.filter = function(event) {
327
const target = event.target || event.srcElement;
328
const tagName = target.tagName;
329
// Allow hotkeys in contentEditable but not in inputs
330
return !(tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA');
331
};
332
```
333
334
### Key State Checking
335
```javascript
336
hotkeys('ctrl+shift+d', function(event, handler) {
337
// Check what other keys are pressed
338
const pressedCodes = hotkeys.getPressedKeyCodes();
339
const pressedKeys = hotkeys.getPressedKeyString();
340
341
console.log('Pressed key codes:', pressedCodes);
342
console.log('Pressed keys:', pressedKeys);
343
344
// Check specific key
345
if (hotkeys.isPressed('m')) {
346
console.log('M key is also pressed');
347
}
348
});
349
```
350
351
## Browser Compatibility
352
353
- Internet Explorer 6+
354
- Chrome (all versions)
355
- Firefox (all versions)
356
- Safari (all versions)
357
- Opera (all versions)
358
359
## Features
360
361
- **Zero Dependencies**: No external dependencies required
362
- **Small Footprint**: ~6kB uncompressed, 2.8kB gzipped
363
- **TypeScript Support**: Complete type definitions included
364
- **Flexible API**: Multiple ways to define shortcuts and options
365
- **Scope Management**: Context-aware shortcut handling
366
- **Cross-browser**: Works across all major browsers
367
- **Customizable Filtering**: Override default behavior for form elements
368
- **Programmatic Control**: Trigger shortcuts programmatically and check key states