@opentui/keymap 0.0.0-20260423-76a94f40

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.
Files changed (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +54 -0
  3. package/addons/index.js +4390 -0
  4. package/addons/opentui/index.js +4712 -0
  5. package/html.js +4151 -0
  6. package/index.js +3631 -0
  7. package/opentui.js +3996 -0
  8. package/package.json +85 -0
  9. package/react/index.js +151 -0
  10. package/solid/index.js +119 -0
  11. package/src/addons/index.d.ts +1 -0
  12. package/src/addons/opentui/base-layout.d.ts +7 -0
  13. package/src/addons/opentui/edit-buffer-bindings.d.ts +38 -0
  14. package/src/addons/opentui/index.d.ts +4 -0
  15. package/src/addons/universal/aliases.d.ts +7 -0
  16. package/src/addons/universal/backspace-pops-pending-sequence.d.ts +13 -0
  17. package/src/addons/universal/comma-bindings.d.ts +6 -0
  18. package/src/addons/universal/dead-bindings.d.ts +6 -0
  19. package/src/addons/universal/default-parser.d.ts +16 -0
  20. package/src/addons/universal/emacs-bindings.d.ts +5 -0
  21. package/src/addons/universal/enabled.d.ts +16 -0
  22. package/src/addons/universal/escape-clears-pending-sequence.d.ts +14 -0
  23. package/src/addons/universal/ex-commands.d.ts +16 -0
  24. package/src/addons/universal/index.d.ts +21 -0
  25. package/src/addons/universal/leader.d.ts +9 -0
  26. package/src/addons/universal/metadata.d.ts +6 -0
  27. package/src/addons/universal/timed-leader.d.ts +12 -0
  28. package/src/addons/universal/unresolved-commands.d.ts +6 -0
  29. package/src/html.d.ts +21 -0
  30. package/src/index.d.ts +3 -0
  31. package/src/keymap-benchmark.d.ts +1 -0
  32. package/src/keymap.d.ts +73 -0
  33. package/src/lib/emitter.d.ts +13 -0
  34. package/src/lib/registry.d.ts +28 -0
  35. package/src/opentui.d.ts +7 -0
  36. package/src/react/index.d.ts +42 -0
  37. package/src/schema.d.ts +3 -0
  38. package/src/services/activation.d.ts +44 -0
  39. package/src/services/command-catalog.d.ts +49 -0
  40. package/src/services/command-executor.d.ts +22 -0
  41. package/src/services/compiler.d.ts +21 -0
  42. package/src/services/conditions.d.ts +20 -0
  43. package/src/services/dispatch.d.ts +34 -0
  44. package/src/services/environment.d.ts +25 -0
  45. package/src/services/keys.d.ts +18 -0
  46. package/src/services/layers.d.ts +34 -0
  47. package/src/services/notify.d.ts +18 -0
  48. package/src/services/primitives/active-layers.d.ts +5 -0
  49. package/src/services/primitives/binding-inputs.d.ts +4 -0
  50. package/src/services/primitives/field-invariants.d.ts +3 -0
  51. package/src/services/runtime.d.ts +15 -0
  52. package/src/services/state.d.ts +102 -0
  53. package/src/services/values.d.ts +7 -0
  54. package/src/solid/index.d.ts +45 -0
  55. package/src/types.d.ts +497 -0
@@ -0,0 +1,45 @@
1
+ import type { KeyEvent, Renderable } from "@opentui/core";
2
+ import { type Keymap, type LayerFields, type ReactiveMatcher } from "../index.js";
3
+ import { type Accessor, type JSX } from "solid-js";
4
+ type OpenTuiKeymap = Keymap<Renderable, KeyEvent>;
5
+ export interface KeymapProviderProps {
6
+ keymap: OpenTuiKeymap;
7
+ children: JSX.Element;
8
+ }
9
+ export declare function KeymapProvider(props: KeymapProviderProps): JSX.Element;
10
+ export type UseBindingsTarget<TRenderable extends Renderable = Renderable> = TRenderable | null | undefined | (() => TRenderable | null | undefined);
11
+ type UseBindingsLayerBase = LayerFields<Renderable, KeyEvent>;
12
+ export type BindingsRef<TRenderable extends Renderable = Renderable> = (value: TRenderable) => void;
13
+ export interface UseGlobalBindingsLayer extends UseBindingsLayerBase {
14
+ scope?: "global";
15
+ target?: undefined;
16
+ }
17
+ export interface UseFocusBindingsLayer<TRenderable extends Renderable = Renderable> extends UseBindingsLayerBase {
18
+ scope: "focus";
19
+ target?: UseBindingsTarget<TRenderable>;
20
+ }
21
+ export interface UseFocusWithinBindingsLayer<TRenderable extends Renderable = Renderable> extends UseBindingsLayerBase {
22
+ scope: "focus-within";
23
+ target?: UseBindingsTarget<TRenderable>;
24
+ }
25
+ export interface UseInferredFocusWithinBindingsLayer<TRenderable extends Renderable = Renderable> extends UseBindingsLayerBase {
26
+ scope?: undefined;
27
+ target: UseBindingsTarget<TRenderable>;
28
+ }
29
+ export type UseTargetBindingsLayer<TRenderable extends Renderable = Renderable> = UseFocusBindingsLayer<TRenderable> | UseFocusWithinBindingsLayer<TRenderable> | UseInferredFocusWithinBindingsLayer<TRenderable>;
30
+ export type UseBindingsLayer<TRenderable extends Renderable = Renderable> = UseGlobalBindingsLayer | UseTargetBindingsLayer<TRenderable>;
31
+ export declare const useKeymap: () => OpenTuiKeymap;
32
+ /**
33
+ * Reactively derives any view from the current keymap by re-running `selector`
34
+ * on each batched keymap state change.
35
+ */
36
+ export declare const useKeymapSelector: <T>(selector: (keymap: OpenTuiKeymap) => T) => Accessor<T>;
37
+ export declare function useBindings<TRenderable extends Renderable = Renderable>(createLayer: () => UseGlobalBindingsLayer): BindingsRef<TRenderable>;
38
+ export declare function useBindings<TRenderable extends Renderable = Renderable>(createLayer: () => UseTargetBindingsLayer<TRenderable>): BindingsRef<TRenderable>;
39
+ /**
40
+ * Adapts a Solid accessor to `ReactiveMatcher`. The subscription
41
+ * lives in a disposable reactive root so unregistering the layer tears it
42
+ * down. Pass `predicate` when the accessor value is not already boolean.
43
+ */
44
+ export declare function reactiveMatcherFromSignal<T>(accessor: Accessor<T>, predicate?: (value: T) => boolean): ReactiveMatcher;
45
+ export {};
package/src/types.d.ts ADDED
@@ -0,0 +1,497 @@
1
+ import type { Keymap } from "./keymap.js";
2
+ export interface KeymapEvent {
3
+ name: string;
4
+ ctrl: boolean;
5
+ shift: boolean;
6
+ meta: boolean;
7
+ super?: boolean;
8
+ hyper?: boolean;
9
+ preventDefault(): void;
10
+ stopPropagation(): void;
11
+ readonly propagationStopped: boolean;
12
+ }
13
+ export interface KeymapHost<TTarget extends object, TEvent extends KeymapEvent = KeymapEvent> {
14
+ readonly rootTarget: TTarget;
15
+ readonly isDestroyed: boolean;
16
+ getFocusedTarget(): TTarget | null;
17
+ getParentTarget(target: TTarget): TTarget | null;
18
+ isTargetDestroyed(target: TTarget): boolean;
19
+ onKeyPress(listener: (event: TEvent) => void): () => void;
20
+ onKeyRelease(listener: (event: TEvent) => void): () => void;
21
+ onFocusChange(listener: (target: TTarget | null) => void): () => void;
22
+ /** Optional for hosts whose lifetime is managed by GC or root reachability. */
23
+ onDestroy?(listener: () => void): () => void;
24
+ onTargetDestroy(target: TTarget, listener: () => void): () => void;
25
+ onRawInput?(listener: (sequence: string) => boolean): () => void;
26
+ createCommandEvent(): TEvent;
27
+ }
28
+ export type EventData = Record<string, unknown>;
29
+ export type Attributes = Record<string, unknown>;
30
+ export interface KeyStrokeInput {
31
+ name: string;
32
+ ctrl?: boolean;
33
+ shift?: boolean;
34
+ meta?: boolean;
35
+ super?: boolean;
36
+ hyper?: boolean;
37
+ }
38
+ export interface NormalizedKeyStroke extends KeyStrokeInput {
39
+ ctrl: boolean;
40
+ shift: boolean;
41
+ meta: boolean;
42
+ super: boolean;
43
+ }
44
+ export type KeyMatch = symbol;
45
+ export interface EventMatchResolverContext {
46
+ resolveKey(key: KeyLike): KeyMatch;
47
+ }
48
+ export type EventMatchResolver<TEvent extends KeymapEvent = KeymapEvent> = (event: TEvent, ctx: EventMatchResolverContext) => readonly KeyMatch[] | undefined;
49
+ export interface ResolvedKeyToken {
50
+ stroke: NormalizedKeyStroke;
51
+ match: KeyMatch;
52
+ }
53
+ export interface KeySequencePart {
54
+ stroke: NormalizedKeyStroke;
55
+ display: string;
56
+ match: KeyMatch;
57
+ tokenName?: string;
58
+ }
59
+ export interface StringifyOptions {
60
+ preferDisplay?: boolean;
61
+ }
62
+ export type KeyStringifyInput = KeyStrokeInput | NormalizedKeyStroke | KeySequencePart | {
63
+ stroke: NormalizedKeyStroke;
64
+ display?: string;
65
+ };
66
+ export type KeyLike = string | KeyStrokeInput;
67
+ /**
68
+ * Read-only view of a registered command. `fields` is raw registration
69
+ * metadata; `attrs` is compiled command-field metadata.
70
+ */
71
+ export interface CommandRecord {
72
+ name: string;
73
+ fields: Readonly<Record<string, unknown>>;
74
+ attrs?: Readonly<Attributes>;
75
+ }
76
+ export type CommandQueryValue = unknown | readonly unknown[] | ((value: unknown, command: CommandRecord) => boolean);
77
+ export type CommandFilter = Readonly<Record<string, CommandQueryValue>> | ((command: CommandRecord) => boolean);
78
+ export interface CommandQuery<TTarget extends object = object> {
79
+ visibility?: "reachable" | "active" | "registered";
80
+ focused?: TTarget | null;
81
+ namespace?: string | readonly string[];
82
+ search?: string;
83
+ searchIn?: readonly string[];
84
+ filter?: CommandFilter;
85
+ }
86
+ export interface RunCommandOptions<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> {
87
+ event?: TEvent;
88
+ focused?: TTarget | null;
89
+ target?: TTarget | null;
90
+ includeCommand?: boolean;
91
+ }
92
+ export type RunCommandResult = {
93
+ ok: true;
94
+ command?: CommandRecord;
95
+ } | {
96
+ ok: false;
97
+ reason: "not-found";
98
+ } | {
99
+ ok: false;
100
+ reason: "invalid-args" | "rejected" | "error";
101
+ command?: CommandRecord;
102
+ };
103
+ export interface CommandContext<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> {
104
+ keymap: Keymap<TTarget, TEvent>;
105
+ event: TEvent;
106
+ focused: TTarget | null;
107
+ target: TTarget | null;
108
+ data: Readonly<EventData>;
109
+ command?: CommandRecord;
110
+ }
111
+ export type CommandResult = boolean | void | Promise<boolean | void>;
112
+ export type CommandResolutionStatus = "resolved" | "unresolved" | "error";
113
+ export type CommandHandler<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> = (ctx: CommandContext<TTarget, TEvent>) => CommandResult;
114
+ export type BindingCommand<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> = string | CommandHandler<TTarget, TEvent>;
115
+ export type BindingEvent = "press" | "release";
116
+ export interface BindingInput<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> {
117
+ key: KeyLike;
118
+ cmd?: BindingCommand<TTarget, TEvent>;
119
+ event?: BindingEvent;
120
+ /**
121
+ * Default `true`. Calls `event.preventDefault()` and
122
+ * `event.stopPropagation()` so the matched key does not reach the focused
123
+ * target or later host listeners. Independent of `fallthrough`, which only
124
+ * controls dispatch inside the keymap. Set `preventDefault: false` if you
125
+ * want a fallthrough binding to keep matching inside the keymap and still let
126
+ * the key escape to later handlers.
127
+ */
128
+ preventDefault?: boolean;
129
+ /**
130
+ * Default `false`. Continues to later matching bindings in the same
131
+ * dispatch chain after this command runs. Independent of `preventDefault`,
132
+ * which controls whether the key event leaves the keymap.
133
+ */
134
+ fallthrough?: boolean;
135
+ [key: string]: unknown;
136
+ }
137
+ export type BindingShorthand<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> = Record<string, BindingCommand<TTarget, TEvent>>;
138
+ export type Bindings<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> = BindingInput<TTarget, TEvent>[] | BindingShorthand<TTarget, TEvent>;
139
+ export type Scope = "global" | "focus" | "focus-within";
140
+ export interface LayerFields<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> {
141
+ priority?: number;
142
+ bindings?: Bindings<TTarget, TEvent>;
143
+ commands?: readonly CommandDefinition<TTarget, TEvent>[];
144
+ [key: string]: unknown;
145
+ }
146
+ export interface GlobalLayer<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> extends LayerFields<TTarget, TEvent> {
147
+ target?: undefined;
148
+ scope?: "global";
149
+ }
150
+ export interface FocusWithinLayer<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> extends LayerFields<TTarget, TEvent> {
151
+ target: TTarget;
152
+ scope?: "focus-within";
153
+ }
154
+ export interface FocusLayer<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> extends LayerFields<TTarget, TEvent> {
155
+ target: TTarget;
156
+ scope: "focus";
157
+ }
158
+ export type TargetLayer<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> = FocusWithinLayer<TTarget, TEvent> | FocusLayer<TTarget, TEvent>;
159
+ export type Layer<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> = GlobalLayer<TTarget, TEvent> | TargetLayer<TTarget, TEvent>;
160
+ export interface ParsedCommand {
161
+ input: string;
162
+ name: string;
163
+ args: string[];
164
+ }
165
+ export interface CommandResolverContext {
166
+ getCommandAttrs(name: string): Readonly<Attributes> | undefined;
167
+ getCommandRecord(name: string): CommandRecord | undefined;
168
+ }
169
+ /**
170
+ * Resolver output. `run` executes the command, `attrs` / `record` expose
171
+ * metadata, and `rejectedResult` overrides the default rejected result.
172
+ */
173
+ export interface ResolvedBindingCommand<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> {
174
+ run: CommandHandler<TTarget, TEvent>;
175
+ attrs?: Readonly<Attributes>;
176
+ record?: CommandRecord;
177
+ rejectedResult?: Extract<RunCommandResult, {
178
+ ok: false;
179
+ }>;
180
+ }
181
+ export type CommandResolver<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> = (command: string, ctx: CommandResolverContext) => ResolvedBindingCommand<TTarget, TEvent> | undefined;
182
+ /**
183
+ * Layer command registration input. Extra fields stay on `fields` and can be
184
+ * compiled into `attrs` by command-field addons.
185
+ */
186
+ export interface CommandDefinition<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> {
187
+ name: string;
188
+ run: CommandHandler<TTarget, TEvent>;
189
+ [key: string]: unknown;
190
+ }
191
+ export interface KeyToken {
192
+ name: string;
193
+ key: KeyLike;
194
+ }
195
+ export interface ActiveBinding<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> {
196
+ sequence: KeySequencePart[];
197
+ command?: BindingCommand<TTarget, TEvent>;
198
+ commandAttrs?: Readonly<Attributes>;
199
+ attrs?: Readonly<Attributes>;
200
+ event: BindingEvent;
201
+ preventDefault: boolean;
202
+ fallthrough: boolean;
203
+ }
204
+ /**
205
+ * Command metadata together with the bindings that invoke it in a given query
206
+ * projection.
207
+ */
208
+ export interface CommandEntry<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> {
209
+ command: CommandRecord;
210
+ bindings: readonly ActiveBinding<TTarget, TEvent>[];
211
+ }
212
+ export interface ActiveKeyOptions {
213
+ includeBindings?: boolean;
214
+ includeMetadata?: boolean;
215
+ }
216
+ export interface ActiveKey<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> {
217
+ stroke: NormalizedKeyStroke;
218
+ display: string;
219
+ tokenName?: string;
220
+ bindings?: ActiveBinding<TTarget, TEvent>[];
221
+ bindingAttrs?: Readonly<Attributes>;
222
+ commandAttrs?: Readonly<Attributes>;
223
+ command?: BindingCommand<TTarget, TEvent>;
224
+ continues: boolean;
225
+ }
226
+ /**
227
+ * Boolean source with subscription-based invalidation. `ctx.activeWhen(...)`
228
+ * subscribes at registration time and unsubscribes when the owning
229
+ * layer or binding is removed.
230
+ */
231
+ export interface ReactiveMatcher {
232
+ get(): boolean;
233
+ subscribe(onChange: () => void): () => void;
234
+ }
235
+ export interface BindingFieldContext {
236
+ require(name: string, value: unknown): void;
237
+ attr(name: string, value: unknown): void;
238
+ /**
239
+ * Registers a runtime matcher. Raw callbacks re-run on every read;
240
+ * reactive matchers stay cached until they notify.
241
+ */
242
+ activeWhen(matcher: (() => boolean) | ReactiveMatcher): void;
243
+ }
244
+ export type BindingFieldCompiler = (value: unknown, ctx: BindingFieldContext) => void;
245
+ export interface LayerFieldContext {
246
+ require(name: string, value: unknown): void;
247
+ /**
248
+ * Registers a runtime matcher. Raw callbacks re-run on every read;
249
+ * reactive matchers stay cached until they notify.
250
+ */
251
+ activeWhen(matcher: (() => boolean) | ReactiveMatcher): void;
252
+ }
253
+ export type LayerFieldCompiler = (value: unknown, ctx: LayerFieldContext) => void;
254
+ export interface LayerAnalysisContext<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> {
255
+ scope: Scope;
256
+ target?: TTarget;
257
+ order: number;
258
+ bindingInputs: readonly BindingInput<TTarget, TEvent>[];
259
+ bindings: readonly LayerBindingAnalysis<TTarget, TEvent>[];
260
+ hasTokenBindings: boolean;
261
+ checkCommandResolution(command: string): CommandResolutionStatus;
262
+ warn(code: string, warning: unknown, message: string): void;
263
+ warnOnce(key: string, code: string, warning: unknown, message: string): void;
264
+ error(code: string, error: unknown, message: string): void;
265
+ }
266
+ export interface LayerBindingAnalysis<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> {
267
+ sequence: KeySequencePart[];
268
+ command?: BindingCommand<TTarget, TEvent>;
269
+ attrs?: Readonly<Attributes>;
270
+ event: BindingEvent;
271
+ preventDefault: boolean;
272
+ fallthrough: boolean;
273
+ sourceBinding: ParsedBindingInput<TTarget, TEvent>;
274
+ sourceScope: Scope;
275
+ sourceTarget?: TTarget;
276
+ sourceLayerOrder: number;
277
+ sourceBindingIndex: number;
278
+ hasCommandAtSequence: boolean;
279
+ hasContinuations: boolean;
280
+ }
281
+ export type LayerAnalyzer<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> = (ctx: LayerAnalysisContext<TTarget, TEvent>) => void;
282
+ export interface BindingParserContext {
283
+ input: string;
284
+ index: number;
285
+ layer: Readonly<Record<string, unknown>>;
286
+ tokens: ReadonlyMap<string, ResolvedKeyToken>;
287
+ normalizeTokenName(token: string): string;
288
+ createMatch(id: string): KeyMatch;
289
+ parseObjectKey(key: KeyStrokeInput, options?: {
290
+ display?: string;
291
+ match?: KeyMatch;
292
+ tokenName?: string;
293
+ }): KeySequencePart;
294
+ }
295
+ export interface BindingExpanderContext {
296
+ input: string;
297
+ layer: Readonly<Record<string, unknown>>;
298
+ }
299
+ export interface BindingParserResult {
300
+ parts: KeySequencePart[];
301
+ nextIndex: number;
302
+ usedTokens?: readonly string[];
303
+ unknownTokens?: readonly string[];
304
+ }
305
+ export type BindingParser = (ctx: BindingParserContext) => BindingParserResult | undefined;
306
+ export type BindingExpander = (ctx: BindingExpanderContext) => readonly string[] | undefined;
307
+ export interface ParsedBindingInput<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> {
308
+ key: KeyLike;
309
+ sequence: KeySequencePart[];
310
+ cmd?: BindingCommand<TTarget, TEvent>;
311
+ event?: BindingEvent;
312
+ preventDefault?: boolean;
313
+ fallthrough?: boolean;
314
+ [key: string]: unknown;
315
+ }
316
+ export interface BindingTransformerContext<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> {
317
+ layer: Readonly<Record<string, unknown>>;
318
+ parseKey(key: KeyLike): KeySequencePart;
319
+ add(binding: ParsedBindingInput<TTarget, TEvent>): void;
320
+ skipOriginal(): void;
321
+ }
322
+ export type BindingTransformer<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> = (binding: ParsedBindingInput<TTarget, TEvent>, ctx: BindingTransformerContext<TTarget, TEvent>) => void;
323
+ export interface CommandFieldContext {
324
+ require(name: string, value: unknown): void;
325
+ attr(name: string, value: unknown): void;
326
+ /**
327
+ * Registers a runtime matcher. Raw callbacks re-run on every read;
328
+ * reactive matchers stay cached until they notify.
329
+ */
330
+ activeWhen(matcher: (() => boolean) | ReactiveMatcher): void;
331
+ }
332
+ export type CommandFieldCompiler = (value: unknown, ctx: CommandFieldContext) => void;
333
+ export interface KeyInputContext<TEvent extends KeymapEvent = KeymapEvent> {
334
+ event: TEvent;
335
+ setData: (name: string, value: unknown) => void;
336
+ getData: (name: string) => unknown;
337
+ consume: (options?: {
338
+ preventDefault?: boolean;
339
+ stopPropagation?: boolean;
340
+ }) => void;
341
+ }
342
+ export interface RawInputContext {
343
+ sequence: string;
344
+ stop: () => void;
345
+ }
346
+ export type Hooks<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> = {
347
+ /**
348
+ * Batched "derived state may have changed" signal. Re-read through getters;
349
+ * framework adapters should use this event.
350
+ */
351
+ state: void;
352
+ /**
353
+ * Synchronous pending-sequence updates, including clear. Payload is the
354
+ * current sequence.
355
+ */
356
+ pendingSequence: readonly KeySequencePart[];
357
+ };
358
+ export type HookName = keyof Hooks;
359
+ export type Listener<TValue> = [TValue] extends [void] ? () => void : (value: TValue) => void;
360
+ export interface WarningEvent {
361
+ code: string;
362
+ message: string;
363
+ warning: unknown;
364
+ }
365
+ export interface ErrorEvent {
366
+ code: string;
367
+ message: string;
368
+ error: unknown;
369
+ }
370
+ /** Events exposed by `keymap.on(...)`. `state` is batched and `pendingSequence` is synchronous. */
371
+ export type Events<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> = Hooks<TTarget, TEvent> & {
372
+ warning: WarningEvent;
373
+ error: ErrorEvent;
374
+ };
375
+ export type EventName = keyof Events;
376
+ export type Intercepts<TEvent extends KeymapEvent = KeymapEvent> = {
377
+ key: KeyInputContext<TEvent>;
378
+ raw: RawInputContext;
379
+ };
380
+ export type InterceptName = keyof Intercepts;
381
+ export interface KeyInterceptOptions {
382
+ priority?: number;
383
+ release?: boolean;
384
+ }
385
+ export interface RawInterceptOptions {
386
+ priority?: number;
387
+ }
388
+ export type { Keymap };
389
+ export type KeymapActiveKey<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> = ActiveKey<TTarget, TEvent>;
390
+ export type KeymapBindingInput<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> = BindingInput<TTarget, TEvent>;
391
+ export type KeymapCommandDefinition<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> = CommandDefinition<TTarget, TEvent>;
392
+ export type KeymapCommandRecord = CommandRecord;
393
+ export type KeymapCommandEntry<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> = CommandEntry<TTarget, TEvent>;
394
+ export interface RuntimeMatcher {
395
+ source: string;
396
+ match: () => boolean;
397
+ /**
398
+ * False for raw callbacks with no subscription or data dependency, so the
399
+ * owner must re-evaluate on every read.
400
+ */
401
+ cacheable: boolean;
402
+ /**
403
+ * Present for reactive matchers; wired during registration and torn down via
404
+ * `dispose`.
405
+ */
406
+ subscribe?: (onChange: () => void) => () => void;
407
+ dispose?: () => void;
408
+ }
409
+ export interface RuntimeMatchable {
410
+ requires: readonly [name: string, value: unknown][];
411
+ matchers: readonly RuntimeMatcher[];
412
+ /** Data keys referenced via `require(...)`; used for `setData` invalidation. */
413
+ conditionKeys: readonly string[];
414
+ /** True when any matcher is a raw callback and therefore cannot be cached. */
415
+ hasUnkeyedMatchers: boolean;
416
+ matchCacheDirty?: boolean;
417
+ matchCache?: boolean;
418
+ }
419
+ export interface CompiledBinding<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> extends ActiveBinding<TTarget, TEvent>, RuntimeMatchable {
420
+ run?: CommandHandler<TTarget, TEvent>;
421
+ sourceBinding: ParsedBindingInput<TTarget, TEvent>;
422
+ sourceScope: Scope;
423
+ sourceTarget?: TTarget;
424
+ sourceLayerOrder: number;
425
+ sourceBindingIndex: number;
426
+ }
427
+ export interface ActiveKeySelection<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> {
428
+ display: string;
429
+ tokenName?: string;
430
+ continues: boolean;
431
+ firstBinding?: CompiledBinding<TTarget, TEvent>;
432
+ commandBinding?: CompiledBinding<TTarget, TEvent>;
433
+ bindings?: readonly CompiledBinding<TTarget, TEvent>[];
434
+ stop: boolean;
435
+ }
436
+ export interface ActiveKeyState<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> {
437
+ stroke: NormalizedKeyStroke;
438
+ display: string;
439
+ tokenName?: string;
440
+ continues: boolean;
441
+ firstBinding?: CompiledBinding<TTarget, TEvent>;
442
+ commandBinding?: CompiledBinding<TTarget, TEvent>;
443
+ bindings?: CompiledBinding<TTarget, TEvent>[];
444
+ }
445
+ export interface RegisteredCommand<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> extends CommandRecord, RuntimeMatchable {
446
+ run: (ctx: CommandContext<TTarget, TEvent>) => CommandResult;
447
+ runner?: CommandHandler<TTarget, TEvent>;
448
+ resolved?: ResolvedBindingCommand<TTarget, TEvent>;
449
+ resolvedWithRecord?: ResolvedBindingCommand<TTarget, TEvent>;
450
+ record?: CommandRecord;
451
+ }
452
+ export interface CompiledBindingsResult<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> {
453
+ root: SequenceNode<TTarget, TEvent>;
454
+ bindings: readonly CompiledBinding<TTarget, TEvent>[];
455
+ hasTokenBindings: boolean;
456
+ }
457
+ export interface SequenceNode<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> {
458
+ parent: SequenceNode<TTarget, TEvent> | null;
459
+ depth: number;
460
+ stroke: NormalizedKeyStroke | null;
461
+ match: KeyMatch | null;
462
+ children: Map<KeyMatch, SequenceNode<TTarget, TEvent>>;
463
+ bindings: CompiledBinding<TTarget, TEvent>[];
464
+ reachableBindings: CompiledBinding<TTarget, TEvent>[];
465
+ }
466
+ export interface RegisteredLayer<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> {
467
+ order: number;
468
+ target?: TTarget;
469
+ indexTarget: TTarget;
470
+ scope: Scope;
471
+ priority: number;
472
+ requires: readonly [name: string, value: unknown][];
473
+ matchers: readonly RuntimeMatcher[];
474
+ conditionKeys: readonly string[];
475
+ hasUnkeyedMatchers: boolean;
476
+ matchCacheDirty?: boolean;
477
+ matchCache?: boolean;
478
+ compileFields?: Readonly<Record<string, unknown>>;
479
+ commands: readonly RegisteredCommand<TTarget, TEvent>[];
480
+ commandLookup?: ReadonlyMap<string, RegisteredCommand<TTarget, TEvent>>;
481
+ bindingInputs: readonly BindingInput<TTarget, TEvent>[];
482
+ compiledBindings: readonly CompiledBinding<TTarget, TEvent>[];
483
+ hasUnkeyedCommands: boolean;
484
+ hasUnkeyedBindings: boolean;
485
+ hasTokenBindings: boolean;
486
+ root: SequenceNode<TTarget, TEvent>;
487
+ offTargetDestroy?: () => void;
488
+ bucket?: RegisteredLayerBucket<TTarget, TEvent>;
489
+ }
490
+ export interface RegisteredLayerBucket<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> {
491
+ focusLayers: RegisteredLayer<TTarget, TEvent>[];
492
+ focusWithinLayers: RegisteredLayer<TTarget, TEvent>[];
493
+ }
494
+ export interface PendingSequenceState<TTarget extends object = object, TEvent extends KeymapEvent = KeymapEvent> {
495
+ layer: RegisteredLayer<TTarget, TEvent>;
496
+ node: SequenceNode<TTarget, TEvent>;
497
+ }