@inklu/keys 2.1.0 → 3.0.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 +106 -135
- package/dist/attributes.d.mts +1 -1
- package/dist/attributes.mjs +15 -18
- package/dist/index-BnB38jCF.d.mts +139 -0
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +2 -2
- package/dist/react.d.mts +19 -41
- package/dist/react.mjs +26 -145
- package/dist/src-CGKvYKjd.mjs +1333 -0
- package/dist/types-BxMI3b4a.d.mts +256 -0
- package/package.json +2 -3
- package/dist/index-3d9f54ln.d.mts +0 -156
- package/dist/src-B76YvObL.mjs +0 -1687
- package/dist/types-QEXldPnL.d.mts +0 -398
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
//#region src/chord.d.ts
|
|
2
|
+
/** Chords: reading one from text or a keypress, matching the two, and writing one back. */
|
|
3
|
+
/**
|
|
4
|
+
* The two kinds of keyboard: `"mac"` for Apple's (macOS, iPadOS, iOS), whose
|
|
5
|
+
* primary modifier is Command, and `"other"` for the rest, where it is Control.
|
|
6
|
+
*/
|
|
7
|
+
type Platform = "mac" | "other";
|
|
8
|
+
/** Named keys in the `Key` type, as `KeyboardEvent.key` spells them. Other names still work. */
|
|
9
|
+
declare const NAMED_KEYS: readonly ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Home", "End", "PageUp", "PageDown", "Enter", "Escape", "Space", "Tab", "Backspace", "Delete", "Insert", "CapsLock", "ContextMenu", "PrintScreen", "ScrollLock", "Pause", "NumLock", "Help", "Clear", "MediaPlayPause", "MediaStop", "MediaTrackNext", "MediaTrackPrevious", "AudioVolumeUp", "AudioVolumeDown", "AudioVolumeMute", "BrowserBack", "BrowserForward", "BrowserRefresh", "BrowserSearch", "BrowserHome"];
|
|
10
|
+
type Letter = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z";
|
|
11
|
+
type Digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
|
|
12
|
+
type FunctionKey = `F${Exclude<Digit, "0">}` | `F1${Digit}` | `F2${"0" | "1" | "2" | "3" | "4"}`;
|
|
13
|
+
type Punctuation = "/" | "[" | "]" | "\\" | "=" | "-" | "," | "." | ";" | "`" | "'" | "+" | "?" | "!" | "@" | "#" | "$" | "%" | "^" | "&" | "*" | "(" | ")" | "_" | "{" | "}" | "|" | ":" | '"' | "<" | ">" | "~";
|
|
14
|
+
/** The key of a chord: the character or named key it produces (`"K"`, `"Escape"`). */
|
|
15
|
+
type Key = Letter | Digit | FunctionKey | Punctuation | (typeof NAMED_KEYS)[number];
|
|
16
|
+
type Held<Modifier extends string> = "" | `${Modifier}+`;
|
|
17
|
+
type Modifiers = `${Held<"Control">}${Held<"Alt">}${Held<"Shift">}${Held<"Meta">}` | `Mod+${Held<"Alt">}${Held<"Shift">}`;
|
|
18
|
+
/**
|
|
19
|
+
* A single hotkey chord, e.g. `"Mod+K"`: modifiers in the order Control, Alt,
|
|
20
|
+
* Shift, Meta, then one key. `Mod` is Command on macOS and Control elsewhere.
|
|
21
|
+
*/
|
|
22
|
+
type Chord = `${Modifiers}${Key}`;
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/types.d.ts
|
|
25
|
+
/** A sequence of chords pressed in order, e.g. `G` then `I`. */
|
|
26
|
+
interface SequenceBinding {
|
|
27
|
+
readonly sequence: ReadonlyArray<Chord>;
|
|
28
|
+
}
|
|
29
|
+
/** A hotkey chord or sequence that triggers a command. */
|
|
30
|
+
type Binding = Chord | SequenceBinding;
|
|
31
|
+
/** One binding or an array of alternative bindings. */
|
|
32
|
+
type BindingInput = Binding | ReadonlyArray<Binding>;
|
|
33
|
+
/**
|
|
34
|
+
* Keys that differ by platform: `mac` on Apple keyboards (macOS, iPadOS and
|
|
35
|
+
* iOS), `other` everywhere else. A side left out is unbound there.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* keys: { mac: "Mod+Shift+Z", other: ["Mod+Y", "Mod+Shift+Z"] }
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
interface PlatformBindings {
|
|
43
|
+
readonly mac?: BindingInput;
|
|
44
|
+
readonly other?: BindingInput;
|
|
45
|
+
}
|
|
46
|
+
/** JSON-serializable form of a binding. */
|
|
47
|
+
type SerializedBinding = string | Array<string>;
|
|
48
|
+
/** An arbitrary JSON-compatible value, e.g. from `JSON.parse` or persisted storage. */
|
|
49
|
+
type Json = string | number | boolean | null | ReadonlyArray<Json> | {
|
|
50
|
+
readonly [key: string]: Json;
|
|
51
|
+
};
|
|
52
|
+
/** Trigger source for a command. */
|
|
53
|
+
type CommandSource = "keyboard" | "api" | "dom";
|
|
54
|
+
/** Context passed to a command's handler. */
|
|
55
|
+
interface CommandContext<Id extends string = string> {
|
|
56
|
+
/** ID of the command being run. */
|
|
57
|
+
readonly id: Id;
|
|
58
|
+
/** How the command was triggered. */
|
|
59
|
+
readonly source: CommandSource;
|
|
60
|
+
/** Originating DOM event, if triggered by user interaction. */
|
|
61
|
+
readonly event?: Event;
|
|
62
|
+
/** Specific binding that triggered the command. */
|
|
63
|
+
readonly binding?: Binding;
|
|
64
|
+
/** The registry, typed with its own ids. */
|
|
65
|
+
readonly commands: Commands<Id>;
|
|
66
|
+
}
|
|
67
|
+
/** What a command does when it runs. */
|
|
68
|
+
type CommandHandler<Id extends string = string> = (context: CommandContext<Id>) => void | Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* A command: what it is called, which keys reach it, and where it is live.
|
|
71
|
+
* `Id` is the registry's id union, which `createCommands` fills in.
|
|
72
|
+
*/
|
|
73
|
+
interface CommandDefinition<Id extends string = string> {
|
|
74
|
+
/** Human-readable title. */
|
|
75
|
+
title: string;
|
|
76
|
+
/**
|
|
77
|
+
* Default key binding(s). Write `{ mac, other }` where the platforms'
|
|
78
|
+
* conventions differ, as they do for redo and for back and forward.
|
|
79
|
+
*/
|
|
80
|
+
keys?: BindingInput | PlatformBindings;
|
|
81
|
+
/** Scope required for this command to fire. Omit for global, or `"*"` to bypass exclusive scopes. */
|
|
82
|
+
scope?: string;
|
|
83
|
+
/**
|
|
84
|
+
* Whether a text field keeps the keys: inputs, selects, contenteditable
|
|
85
|
+
* elements and widgets with a text-entry ARIA role. Defaults to `true`,
|
|
86
|
+
* except for `Escape`. Set `false` on a command that should fire there too.
|
|
87
|
+
*/
|
|
88
|
+
ignoreInputs?: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* What the command does, when that needs nothing a component owns. Otherwise
|
|
91
|
+
* attach it with `commands.handle()` or `useCommandHandler`. A command with
|
|
92
|
+
* no handler cannot run and leaves its key alone.
|
|
93
|
+
*/
|
|
94
|
+
run?: CommandHandler<Id>;
|
|
95
|
+
}
|
|
96
|
+
/** Resolved command snapshot including effective bindings, display tokens, and reachability. */
|
|
97
|
+
interface Command<Id extends string = string> {
|
|
98
|
+
readonly id: Id;
|
|
99
|
+
readonly title: string;
|
|
100
|
+
readonly scope?: string;
|
|
101
|
+
/** Active bindings after user overrides. */
|
|
102
|
+
readonly bindings: ReadonlyArray<Binding>;
|
|
103
|
+
/** Formatted display strings for active bindings. */
|
|
104
|
+
readonly display: ReadonlyArray<string>;
|
|
105
|
+
/** Formatted tokens per binding for rendering `<kbd>` elements. */
|
|
106
|
+
readonly tokens: ReadonlyArray<ReadonlyArray<string>>;
|
|
107
|
+
/** Value for the `aria-keyshortcuts` attribute. Chords only: it cannot express a sequence. */
|
|
108
|
+
readonly aria: string;
|
|
109
|
+
/** Whether its keys work right now: it has a handler and its scope is active. */
|
|
110
|
+
readonly reachable: boolean;
|
|
111
|
+
/** Whether the command has a user keymap override. */
|
|
112
|
+
readonly overridden: boolean;
|
|
113
|
+
}
|
|
114
|
+
/** Where user overrides are kept between visits. `webStorage()` makes one. */
|
|
115
|
+
interface KeymapStore {
|
|
116
|
+
/** The stored overrides by command id: empty when there are none, `null` when they cannot be read. */
|
|
117
|
+
read(): Map<string, ReadonlyArray<Binding>> | null;
|
|
118
|
+
write(overrides: ReadonlyMap<string, ReadonlyArray<Binding>>): void;
|
|
119
|
+
}
|
|
120
|
+
/** User overrides as JSON-safe data, keyed by command id. What `exportKeymap()` returns. */
|
|
121
|
+
type SerializedKeymap = {
|
|
122
|
+
version: 1;
|
|
123
|
+
overrides: Record<string, Array<SerializedBinding>>;
|
|
124
|
+
};
|
|
125
|
+
/** A registry's keymap: the keys in effect, and the user's changes to them. */
|
|
126
|
+
interface CommandKeymap<Id extends string = string> {
|
|
127
|
+
/** Active bindings in effect: the default, with any user override applied. */
|
|
128
|
+
get(id: Id): ReadonlyArray<Binding>;
|
|
129
|
+
/** Replaces a command's bindings. `null` unbinds it; exactly the default forgets the override. */
|
|
130
|
+
set(id: Id, input: BindingInput | null): void;
|
|
131
|
+
/** Resets user overrides back to defaults for a specific command or all commands. */
|
|
132
|
+
reset(id?: Id): void;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* A command in an overlapping scope whose keys stand in a binding's way: the
|
|
136
|
+
* same keys (`"exact"`), or one binding starting the other (`"prefix"`).
|
|
137
|
+
*/
|
|
138
|
+
interface Conflict<Id extends string = string> {
|
|
139
|
+
readonly kind: "exact" | "prefix";
|
|
140
|
+
/** ID of the conflicting command. */
|
|
141
|
+
readonly id: Id;
|
|
142
|
+
/** The conflicting command's binding. */
|
|
143
|
+
readonly binding: Binding;
|
|
144
|
+
/** Formatted display representation of that binding. */
|
|
145
|
+
readonly display: string;
|
|
146
|
+
/** The conflicting command's scope, if it has one. */
|
|
147
|
+
readonly scope?: string;
|
|
148
|
+
}
|
|
149
|
+
/** Options for conflict detection. */
|
|
150
|
+
interface ConflictOptions<Id extends string = string> {
|
|
151
|
+
/** Command ID to ignore during conflict checking. */
|
|
152
|
+
ignore?: Id;
|
|
153
|
+
/** Scope to evaluate conflicts in. Defaults to global. */
|
|
154
|
+
scope?: string;
|
|
155
|
+
}
|
|
156
|
+
/** Options for activating a scope. */
|
|
157
|
+
interface ScopeOptions {
|
|
158
|
+
/** Silence the keys of commands in lower scopes, including global commands. */
|
|
159
|
+
exclusive?: boolean;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Receives each keypress while the keyboard is captured: the event, and the
|
|
163
|
+
* chord it expresses (`null` for a modifier on its own).
|
|
164
|
+
*/
|
|
165
|
+
type KeyCapture = (event: KeyboardEvent, chord: Chord | null) => void;
|
|
166
|
+
/** Options passed when manually running a command. */
|
|
167
|
+
interface RunOptions {
|
|
168
|
+
/** Trigger source. Defaults to `"api"`. */
|
|
169
|
+
source?: CommandSource;
|
|
170
|
+
/** Originating DOM event. */
|
|
171
|
+
event?: Event;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Why a command cannot run: its id is not registered, nothing has attached a
|
|
175
|
+
* handler to it, or its scope is not open.
|
|
176
|
+
*/
|
|
177
|
+
type RunBlockReason = "unknown" | "unhandled" | "out-of-scope";
|
|
178
|
+
/** Configuration options for a commands registry. */
|
|
179
|
+
interface CommandsOptions<Id extends string = string> {
|
|
180
|
+
/**
|
|
181
|
+
* Replaces the default `keys` of commands, by id, for rebinding commands the
|
|
182
|
+
* app did not define. `null` ships a command unbound. A user's own rebinding
|
|
183
|
+
* still wins.
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* ```ts
|
|
187
|
+
* createCommands(commands, {
|
|
188
|
+
* bindings: { "palette.open": "Mod+P", "doc.publish": null },
|
|
189
|
+
* });
|
|
190
|
+
* ```
|
|
191
|
+
*/
|
|
192
|
+
bindings?: Partial<Record<Id, BindingInput | PlatformBindings | null>>;
|
|
193
|
+
/** Platform for modifier resolution and display formatting. Defaults to auto-detection. */
|
|
194
|
+
platform?: Platform;
|
|
195
|
+
/**
|
|
196
|
+
* Where to keep user keymap overrides between visits, such as
|
|
197
|
+
* `webStorage("my-app.keys")`. They load on the first `mount()`, so the
|
|
198
|
+
* server render and the client's first render agree.
|
|
199
|
+
*/
|
|
200
|
+
persist?: KeymapStore;
|
|
201
|
+
/**
|
|
202
|
+
* Whether single-key shortcuts (every step a printable character with no
|
|
203
|
+
* Control, Alt or Meta, such as `?` or `G then I`) are active. Defaults to
|
|
204
|
+
* `true`. WCAG 2.1.4 requires a way to turn them off.
|
|
205
|
+
*/
|
|
206
|
+
singleKeyShortcuts?: boolean;
|
|
207
|
+
/** Called before any command runs, for logging or analytics. */
|
|
208
|
+
onRun?: (context: CommandContext<Id>) => void;
|
|
209
|
+
}
|
|
210
|
+
/** The commands registry. */
|
|
211
|
+
interface Commands<Id extends string = string> {
|
|
212
|
+
/** Keymap holding default and user bindings. */
|
|
213
|
+
readonly keymap: CommandKeymap<Id>;
|
|
214
|
+
/** Retrieves a command's snapshot, or `undefined` if unregistered. */
|
|
215
|
+
get(id: Id): Command<Id> | undefined;
|
|
216
|
+
/** Returns all commands in definition order. */
|
|
217
|
+
list(): ReadonlyArray<Command<Id>>;
|
|
218
|
+
/**
|
|
219
|
+
* The list as the server rendered it: defaults only, and referentially
|
|
220
|
+
* stable. For a framework's server snapshot.
|
|
221
|
+
*/
|
|
222
|
+
serverList(): ReadonlyArray<Command<Id>>;
|
|
223
|
+
/**
|
|
224
|
+
* Runs a command by ID. Returns `true` if executed. Passes `exclusive`
|
|
225
|
+
* barriers, which silence keys, not commands.
|
|
226
|
+
*/
|
|
227
|
+
run(id: Id, options?: RunOptions): boolean;
|
|
228
|
+
/** Returns why `run` would refuse the command, or `null` if it would run. */
|
|
229
|
+
whyNotRun(id: Id): RunBlockReason | null;
|
|
230
|
+
/**
|
|
231
|
+
* Attaches what a command does until the returned function is called. The
|
|
232
|
+
* most recently attached handler runs.
|
|
233
|
+
*/
|
|
234
|
+
handle(id: Id, run: CommandHandler<Id>): () => void;
|
|
235
|
+
/** Activates a scope until the returned disposal function is called. */
|
|
236
|
+
pushScope(name: string, options?: ScopeOptions): () => void;
|
|
237
|
+
/**
|
|
238
|
+
* Takes the whole keyboard until the returned function is called: every
|
|
239
|
+
* keypress goes to `onKey` and no command runs.
|
|
240
|
+
*/
|
|
241
|
+
capture(onKey: KeyCapture): () => void;
|
|
242
|
+
/** Finds the commands in overlapping scopes whose keys collide with a binding. */
|
|
243
|
+
conflicts(binding: BindingInput, options?: ConflictOptions<Id>): Array<Conflict<Id>>;
|
|
244
|
+
/** Starts listening for key events. Returns an unmount function. */
|
|
245
|
+
mount(): () => void;
|
|
246
|
+
/** Subscribes to registry changes. Returns an unsubscribe function. */
|
|
247
|
+
subscribe(listener: () => void): () => void;
|
|
248
|
+
/** Whether single-key shortcuts are active. See `CommandsOptions.singleKeyShortcuts`. */
|
|
249
|
+
readonly singleKeyShortcuts: boolean;
|
|
250
|
+
/** Turns single-key shortcuts on or off for every command (WCAG 2.1.4). */
|
|
251
|
+
setSingleKeyShortcuts(enabled: boolean): void;
|
|
252
|
+
/** Tears down listeners and clears all commands. */
|
|
253
|
+
destroy(): void;
|
|
254
|
+
}
|
|
255
|
+
//#endregion
|
|
256
|
+
export { Chord as C, SerializedKeymap as S, Platform as T, RunBlockReason as _, CommandDefinition as a, SequenceBinding as b, CommandSource as c, Conflict as d, ConflictOptions as f, PlatformBindings as g, KeymapStore as h, CommandContext as i, Commands as l, KeyCapture as m, BindingInput as n, CommandHandler as o, Json as p, Command as r, CommandKeymap as s, Binding as t, CommandsOptions as u, RunOptions as v, Key as w, SerializedBinding as x, ScopeOptions as y };
|
package/package.json
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inklu/keys",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "A command system for the web
|
|
3
|
+
"version": "3.0.0",
|
|
4
|
+
"description": "A command system for the web: typed commands, portable keybindings, scopes, sequences, conflict detection, rebinding and platform-aware display.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"accessibility",
|
|
7
|
-
"command-palette",
|
|
8
7
|
"commands",
|
|
9
8
|
"hotkeys",
|
|
10
9
|
"keybindings",
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
import { C as SequenceBinding, D as Chord, a as CommandDefinition, d as Conflict, k as Platform, l as Commands, m as DisplayOptions, r as Command, t as Binding, u as CommandsOptions } from "./types-QEXldPnL.mjs";
|
|
2
|
-
//#region src/bindings.d.ts
|
|
3
|
-
/**
|
|
4
|
-
* Creates a sequence binding from ordered chords.
|
|
5
|
-
*
|
|
6
|
-
* @example
|
|
7
|
-
* ```ts
|
|
8
|
-
* keys: seq("G", "I")
|
|
9
|
-
* ```
|
|
10
|
-
*/
|
|
11
|
-
declare function seq(...steps: Array<Chord>): SequenceBinding;
|
|
12
|
-
/**
|
|
13
|
-
* Whether every step of a binding is a single printable character with no
|
|
14
|
-
* Control, Alt or Meta — the "character key shortcuts" WCAG 2.1.4 lets users
|
|
15
|
-
* turn off, since speech input and stray keypresses trigger them by accident.
|
|
16
|
-
*/
|
|
17
|
-
declare function isSingleKeyBinding(binding: Binding): boolean;
|
|
18
|
-
/** Validation result for a hotkey binding. */
|
|
19
|
-
interface BindingValidation {
|
|
20
|
-
readonly valid: boolean;
|
|
21
|
-
readonly errors: ReadonlyArray<string>;
|
|
22
|
-
readonly warnings: ReadonlyArray<string>;
|
|
23
|
-
}
|
|
24
|
-
/** Validates a binding's syntax without logging warnings or errors. */
|
|
25
|
-
declare function validateBinding(binding: Binding): BindingValidation;
|
|
26
|
-
//#endregion
|
|
27
|
-
//#region src/display.d.ts
|
|
28
|
-
/** Formats a binding for display on the target platform (e.g. `⌘ K` or `Ctrl+K`). */
|
|
29
|
-
declare function formatBinding(binding: Binding, options?: DisplayOptions): string;
|
|
30
|
-
/** Splits a binding into display tokens for rendering `<kbd>` elements. */
|
|
31
|
-
declare function bindingTokens(binding: Binding, options?: DisplayOptions): Array<string>;
|
|
32
|
-
/**
|
|
33
|
-
* Phrases a binding for a screen reader: `"Control+K"` for a chord,
|
|
34
|
-
* `"G then I"` for a sequence. `aria-keyshortcuts` cannot express a sequence
|
|
35
|
-
* (a space there means "or"), so this is how a sequence gets announced — put it
|
|
36
|
-
* in visually hidden text or `aria-description`.
|
|
37
|
-
*/
|
|
38
|
-
declare function spokenBinding(binding: Binding, platform?: Platform): string;
|
|
39
|
-
/** Generates an `aria-keyshortcuts` attribute string for a binding. */
|
|
40
|
-
declare function ariaKeyShortcuts(binding: Binding, platform?: Platform): string;
|
|
41
|
-
//#endregion
|
|
42
|
-
//#region src/rebind.d.ts
|
|
43
|
-
/** Hotkey capture mode: single `"chord"` or multi-step `"sequence"`. */
|
|
44
|
-
type RebindMode = "chord" | "sequence";
|
|
45
|
-
/** Current state of a rebinding session. */
|
|
46
|
-
interface RebindState<Id extends string = string> {
|
|
47
|
-
/** Whether keys are actively being recorded. */
|
|
48
|
-
readonly recording: boolean;
|
|
49
|
-
/** Most recently captured binding. */
|
|
50
|
-
readonly binding: Binding | null;
|
|
51
|
-
/** Captured steps in the current sequence session. */
|
|
52
|
-
readonly steps: ReadonlyArray<Chord>;
|
|
53
|
-
/** Conflicting commands for the captured binding. */
|
|
54
|
-
readonly conflicts: ReadonlyArray<Conflict<Id>>;
|
|
55
|
-
}
|
|
56
|
-
/** Options for creating a rebinder. */
|
|
57
|
-
interface RebindOptions<Id extends string = string> {
|
|
58
|
-
/** Capture mode. Defaults to `"chord"`. */
|
|
59
|
-
mode?: RebindMode;
|
|
60
|
-
/** Whether to write the recorded (or cleared) binding into the keymap. Defaults to `true`. */
|
|
61
|
-
apply?: boolean;
|
|
62
|
-
/** Whether to append rather than replace existing bindings. Defaults to `false`. */
|
|
63
|
-
add?: boolean;
|
|
64
|
-
/** Prevent applying bindings that conflict with other commands. Defaults to `false`. */
|
|
65
|
-
rejectConflicts?: boolean;
|
|
66
|
-
/** Ignore key events from inputs while recording. Defaults to `true`. */
|
|
67
|
-
ignoreInputs?: boolean;
|
|
68
|
-
/** Inactivity timeout in milliseconds before a sequence commits. */
|
|
69
|
-
idleTimeout?: number;
|
|
70
|
-
/** Callback fired when a binding is recorded. */
|
|
71
|
-
onRecord?: (binding: Binding, conflicts: ReadonlyArray<Conflict<Id>>) => void;
|
|
72
|
-
/** Callback fired when recording is cancelled. */
|
|
73
|
-
onCancel?: () => void;
|
|
74
|
-
/** Callback fired when Backspace or Delete clears the binding while recording. */
|
|
75
|
-
onClear?: () => void;
|
|
76
|
-
}
|
|
77
|
-
/** Controller instance for managing a rebinding session. */
|
|
78
|
-
interface Rebinder<Id extends string = string> {
|
|
79
|
-
/** Begins capturing keys. */
|
|
80
|
-
start: () => void;
|
|
81
|
-
/** Stops capturing keys without recording. */
|
|
82
|
-
stop: () => void;
|
|
83
|
-
/** Stops capturing keys and reports cancellation. */
|
|
84
|
-
cancel: () => void;
|
|
85
|
-
/** Commits the currently captured sequence steps. */
|
|
86
|
-
commit: () => void;
|
|
87
|
-
/** Current rebinder state. */
|
|
88
|
-
readonly state: RebindState<Id>;
|
|
89
|
-
/** Subscribes to rebinder state changes. Returns an unsubscribe function. */
|
|
90
|
-
subscribe: (listener: () => void) => () => void;
|
|
91
|
-
/** Destroys the rebinder and cleans up listeners. */
|
|
92
|
-
destroy: () => void;
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Creates a rebinder instance for capturing and remapping a command's keys.
|
|
96
|
-
* While it records it holds the whole keyboard, so no command runs on the
|
|
97
|
-
* keys being pressed. Escape cancels, Backspace removes the shortcut (or the
|
|
98
|
-
* last step of a sequence), and Enter finishes a sequence.
|
|
99
|
-
*
|
|
100
|
-
* @example
|
|
101
|
-
* ```ts
|
|
102
|
-
* const rebinder = createRebinder(commands, "palette.open", {
|
|
103
|
-
* onRecord: (binding, conflicts) => {
|
|
104
|
-
* if (conflicts.length) console.warn("Conflict with", conflicts[0].id);
|
|
105
|
-
* },
|
|
106
|
-
* });
|
|
107
|
-
* rebinder.start();
|
|
108
|
-
* ```
|
|
109
|
-
*/
|
|
110
|
-
declare function createRebinder<Id extends string>(registry: Commands<Id>, id: Id, options?: RebindOptions<Id>): Rebinder<Id>;
|
|
111
|
-
//#endregion
|
|
112
|
-
//#region src/registry.d.ts
|
|
113
|
-
/**
|
|
114
|
-
* Creates a command registry.
|
|
115
|
-
*
|
|
116
|
-
* @example
|
|
117
|
-
* ```ts
|
|
118
|
-
* export const commands = createCommands({
|
|
119
|
-
* "palette.open": { title: "Open command palette", keys: "Mod+K" },
|
|
120
|
-
* "nav.inbox": {
|
|
121
|
-
* title: "Go to inbox",
|
|
122
|
-
* keys: seq("G", "I"),
|
|
123
|
-
* run: () => router.navigate("/inbox"),
|
|
124
|
-
* },
|
|
125
|
-
* });
|
|
126
|
-
* ```
|
|
127
|
-
*/
|
|
128
|
-
declare function createCommands<Id extends string>(definitions: { [K in Id]: CommandDefinition<Id>; }, options?: CommandsOptions<NoInfer<Id>>): Commands<Id>;
|
|
129
|
-
/**
|
|
130
|
-
* Extracts command ID union from a Commands registry type.
|
|
131
|
-
*
|
|
132
|
-
* @example
|
|
133
|
-
* ```ts
|
|
134
|
-
* export const commands = createCommands({ … });
|
|
135
|
-
* export type AppCommandId = CommandId<typeof commands>;
|
|
136
|
-
* ```
|
|
137
|
-
*/
|
|
138
|
-
type CommandId<C> = C extends Commands<infer Id> ? Id : never;
|
|
139
|
-
//#endregion
|
|
140
|
-
//#region src/search.d.ts
|
|
141
|
-
/**
|
|
142
|
-
* Filters commands for a search query, as a command palette does, leaving
|
|
143
|
-
* out `hidden` ones. Every word of the query must appear somewhere in the
|
|
144
|
-
* command — title, description, group, keywords, id or displayed shortcut —
|
|
145
|
-
* in any order. Title matches come first: titles starting with the query,
|
|
146
|
-
* then titles containing every word, then the rest; each tier keeps the
|
|
147
|
-
* list's own order. An empty query returns every visible command.
|
|
148
|
-
*
|
|
149
|
-
* @example
|
|
150
|
-
* ```ts
|
|
151
|
-
* const results = matchCommands(commands.list(), "go inbox");
|
|
152
|
-
* ```
|
|
153
|
-
*/
|
|
154
|
-
declare function matchCommands<Id extends string>(commands: ReadonlyArray<Command<Id>>, query: string): Array<Command<Id>>;
|
|
155
|
-
//#endregion
|
|
156
|
-
export { RebindOptions as a, createRebinder as c, formatBinding as d, spokenBinding as f, validateBinding as g, seq as h, RebindMode as i, ariaKeyShortcuts as l, isSingleKeyBinding as m, CommandId as n, RebindState as o, BindingValidation as p, createCommands as r, Rebinder as s, matchCommands as t, bindingTokens as u };
|