@tooee/commands 0.1.19 → 0.1.21
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 +33 -0
- package/dist/command-store.d.ts +147 -0
- package/dist/command-store.d.ts.map +1 -0
- package/dist/command-store.js +367 -0
- package/dist/command-store.js.map +1 -0
- package/dist/context.d.ts +52 -3
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +244 -153
- package/dist/context.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/match.d.ts.map +1 -1
- package/dist/match.js +2 -0
- package/dist/match.js.map +1 -1
- package/dist/mode.d.ts +7 -1
- package/dist/mode.d.ts.map +1 -1
- package/dist/mode.js +12 -3
- package/dist/mode.js.map +1 -1
- package/dist/parse.d.ts.map +1 -1
- package/dist/parse.js +17 -5
- package/dist/parse.js.map +1 -1
- package/dist/sequence.d.ts +17 -2
- package/dist/sequence.d.ts.map +1 -1
- package/dist/sequence.js +66 -45
- package/dist/sequence.js.map +1 -1
- package/dist/types.d.ts +51 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/use-actions.d.ts.map +1 -1
- package/dist/use-actions.js +6 -3
- package/dist/use-actions.js.map +1 -1
- package/dist/use-command.d.ts.map +1 -1
- package/dist/use-command.js +12 -4
- package/dist/use-command.js.map +1 -1
- package/package.json +5 -1
- package/src/command-store.ts +554 -0
- package/src/context.tsx +353 -165
- package/src/index.ts +27 -1
- package/src/match.ts +1 -0
- package/src/mode.tsx +31 -3
- package/src/parse.ts +20 -5
- package/src/sequence.ts +80 -52
- package/src/types.ts +56 -3
- package/src/use-actions.ts +5 -3
- package/src/use-command.ts +13 -4
package/README.md
CHANGED
|
@@ -3,3 +3,36 @@
|
|
|
3
3
|
Vim-inspired modal command system for Tooee.
|
|
4
4
|
|
|
5
5
|
Part of the [Tooee](https://github.com/gingerhendrix/tooee) monorepo. See the main repo for documentation.
|
|
6
|
+
|
|
7
|
+
## Raw `useKeyboard` policy
|
|
8
|
+
|
|
9
|
+
App-level `useKeyboard` handlers MUST guard against active overlays — either
|
|
10
|
+
stand down while an overlay is open, or be ported to `useCommand` registrations
|
|
11
|
+
so the dispatcher arbitrates them:
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
const hasOverlay = useHasOverlay() // from @tooee/overlays
|
|
15
|
+
|
|
16
|
+
useKeyboard((key) => {
|
|
17
|
+
if (hasOverlay) return
|
|
18
|
+
// ...
|
|
19
|
+
})
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Why `key.preventDefault()` is **not** sufficient:
|
|
23
|
+
|
|
24
|
+
- `useKeyboard` subscribes in an effect, and React runs child effects before
|
|
25
|
+
parent effects, so app-level raw handlers fire **before** the command
|
|
26
|
+
dispatcher. A modal surface's `preventDefault` cannot reach them even in
|
|
27
|
+
principle.
|
|
28
|
+
- The dispatcher only calls `preventDefault()` on keys a command **matches**;
|
|
29
|
+
keys a modal surface merely swallows are never marked, so raw listeners see
|
|
30
|
+
them unprevented.
|
|
31
|
+
|
|
32
|
+
An unguarded raw handler therefore double-handles keys while a modal overlay
|
|
33
|
+
(theme picker, command palette, choose/ask overlays) is open — e.g. Escape
|
|
34
|
+
exiting the app underneath an open picker. Inside `@tooee/commands` itself,
|
|
35
|
+
`useActiveCommandSurface()` can serve as the guard where `@tooee/overlays` is
|
|
36
|
+
not available. There is a regression test documenting this hazard in
|
|
37
|
+
`test/surface.test.tsx` ("raw useKeyboard consumers bypass surface
|
|
38
|
+
arbitration").
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import type { KeyEvent } from "@opentui/core";
|
|
2
|
+
import type { Command, CommandContext, CommandRegistry, CommandSequenceState, CommandSurfaceRole, ParsedStep, RegisteredCommandGroup } from "./types.js";
|
|
3
|
+
import type { Mode } from "./mode.js";
|
|
4
|
+
export declare const ROOT_SURFACE_ID = "__root";
|
|
5
|
+
/**
|
|
6
|
+
* A surface as tracked by the store. The root app is `surfaces[0]`, always
|
|
7
|
+
* present, with role `"root"` — it never arbitrates as modal.
|
|
8
|
+
*
|
|
9
|
+
* Commands are NOT stored on the record: React mounts children (whose
|
|
10
|
+
* `useCommand` effects register commands) before the surface's own register
|
|
11
|
+
* effect pushes the record, and unmount cleanup pops the record before the
|
|
12
|
+
* children unregister. Per-surface command maps therefore live in
|
|
13
|
+
* `commandsBySurface`, keyed by surface id, independent of the stack.
|
|
14
|
+
*/
|
|
15
|
+
export interface SurfaceRecord {
|
|
16
|
+
id: string;
|
|
17
|
+
role: CommandSurfaceRole | "root";
|
|
18
|
+
/** Nesting depth (root = 0). */
|
|
19
|
+
depth: number;
|
|
20
|
+
/** Monotonic registration order (tie-break), assigned by the wrapper on push. */
|
|
21
|
+
order: number;
|
|
22
|
+
/** Reads this surface's current local mode (mode stays in ModeProvider React state). */
|
|
23
|
+
getMode: () => Mode;
|
|
24
|
+
/** Builds the command context handed to this surface's handlers. */
|
|
25
|
+
buildCtx: () => CommandContext;
|
|
26
|
+
}
|
|
27
|
+
export type ContextGetter = () => Partial<CommandContext>;
|
|
28
|
+
export interface CommandStoreContext {
|
|
29
|
+
/** Surface stack ordered by registration; `surfaces[0]` is the root record. */
|
|
30
|
+
surfaces: readonly SurfaceRecord[];
|
|
31
|
+
/** Per-surface command maps, keyed by surface id (see SurfaceRecord docs). */
|
|
32
|
+
commandsBySurface: ReadonlyMap<string, ReadonlyMap<string, Command>>;
|
|
33
|
+
/** Command groups keyed by prefixKey. */
|
|
34
|
+
groups: ReadonlyMap<string, RegisteredCommandGroup>;
|
|
35
|
+
contextSources: ReadonlyMap<string, ContextGetter>;
|
|
36
|
+
/** Renderable pending-sequence display state (which-key input). */
|
|
37
|
+
sequence: CommandSequenceState | null;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The topmost modal surface: role === "modal", max depth, then max order.
|
|
41
|
+
* Passive surfaces and the root never win.
|
|
42
|
+
*/
|
|
43
|
+
export declare function selectActiveModalSurface(ctx: CommandStoreContext): SurfaceRecord | null;
|
|
44
|
+
/**
|
|
45
|
+
* Commands registered on a surface. Returns a fresh array; memoize against
|
|
46
|
+
* `selectSurfaceCommandMap` identity in render paths.
|
|
47
|
+
*/
|
|
48
|
+
export declare function selectSurfaceCommands(ctx: CommandStoreContext, surfaceId: string): readonly Command[];
|
|
49
|
+
/** Identity-stable per-surface command map (undefined when none registered). */
|
|
50
|
+
export declare function selectSurfaceCommandMap(ctx: CommandStoreContext, surfaceId: string): ReadonlyMap<string, Command> | undefined;
|
|
51
|
+
export declare function selectSequence(ctx: CommandStoreContext): CommandSequenceState | null;
|
|
52
|
+
export declare function selectGroups(ctx: CommandStoreContext): ReadonlyMap<string, RegisteredCommandGroup>;
|
|
53
|
+
export declare function stepsKey(steps: readonly ParsedStep[]): string;
|
|
54
|
+
export declare function formatStepKey(step: ParsedStep): string;
|
|
55
|
+
declare function createBaseStore(initialContext: CommandStoreContext): import("@xstate/store").Store<CommandStoreContext, {
|
|
56
|
+
commandRegistered: {
|
|
57
|
+
surfaceId: string;
|
|
58
|
+
command: Command;
|
|
59
|
+
};
|
|
60
|
+
commandUnregistered: {
|
|
61
|
+
surfaceId: string;
|
|
62
|
+
command: Command;
|
|
63
|
+
};
|
|
64
|
+
groupRegistered: {
|
|
65
|
+
group: RegisteredCommandGroup;
|
|
66
|
+
};
|
|
67
|
+
groupUnregistered: {
|
|
68
|
+
group: RegisteredCommandGroup;
|
|
69
|
+
};
|
|
70
|
+
contextSourceRegistered: {
|
|
71
|
+
id: string;
|
|
72
|
+
getter: ContextGetter;
|
|
73
|
+
};
|
|
74
|
+
contextSourceUnregistered: {
|
|
75
|
+
id: string;
|
|
76
|
+
};
|
|
77
|
+
surfacePushed: {
|
|
78
|
+
surface: SurfaceRecord;
|
|
79
|
+
};
|
|
80
|
+
surfacePopped: {
|
|
81
|
+
surface: SurfaceRecord;
|
|
82
|
+
};
|
|
83
|
+
modeChanged: {
|
|
84
|
+
surfaceId: string;
|
|
85
|
+
};
|
|
86
|
+
sequencePending: {
|
|
87
|
+
state: CommandSequenceState;
|
|
88
|
+
};
|
|
89
|
+
sequenceReset: unknown;
|
|
90
|
+
}, never>;
|
|
91
|
+
export type CommandStoreInstance = ReturnType<typeof createBaseStore>;
|
|
92
|
+
export interface KeyDispatchResult {
|
|
93
|
+
handled: boolean;
|
|
94
|
+
/**
|
|
95
|
+
* Present on a full command match. The caller (the `useKeyboard` effect)
|
|
96
|
+
* calls `preventDefault()` and then `invoke()` synchronously, preserving
|
|
97
|
+
* today's dispatch order and `event.defaultPrevented` semantics.
|
|
98
|
+
*/
|
|
99
|
+
invoke?: () => void;
|
|
100
|
+
}
|
|
101
|
+
export interface CommandStoreConfig {
|
|
102
|
+
leader?: string;
|
|
103
|
+
keymap?: Record<string, string>;
|
|
104
|
+
sequenceTimeoutMs?: number;
|
|
105
|
+
}
|
|
106
|
+
export interface CreateCommandStoreOptions extends CommandStoreConfig {
|
|
107
|
+
/** Root surface accessors, provided by the command provider/dispatcher. */
|
|
108
|
+
root: {
|
|
109
|
+
getMode: () => Mode;
|
|
110
|
+
buildCtx: () => CommandContext;
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* The single writer around the store. Owns the two pieces of IO-adjacent,
|
|
115
|
+
* non-render state: the key buffer (not render state — putting it in store
|
|
116
|
+
* context would notify subscribers on every keystroke) and the sequence
|
|
117
|
+
* timeout timer. The renderable `sequence` display state lives in the store.
|
|
118
|
+
*/
|
|
119
|
+
export interface CommandStore {
|
|
120
|
+
/** The underlying @xstate/store instance (subscribe/getSnapshot/trigger). */
|
|
121
|
+
store: CommandStoreInstance;
|
|
122
|
+
/** The always-present root surface record (`surfaces[0]`). */
|
|
123
|
+
rootRecord: SurfaceRecord;
|
|
124
|
+
/**
|
|
125
|
+
* Feed a key event: arbitrates the active surface, filters candidates by
|
|
126
|
+
* mode/when, runs the pure sequence matchers against the internal buffer,
|
|
127
|
+
* triggers sequencePending/sequenceReset as needed, schedules/clears the
|
|
128
|
+
* timeout, and returns what happened so the caller can preventDefault and
|
|
129
|
+
* invoke synchronously.
|
|
130
|
+
*/
|
|
131
|
+
key: (event: KeyEvent) => KeyDispatchResult;
|
|
132
|
+
/** Clears buffer + timer and triggers sequenceReset. Idempotent. */
|
|
133
|
+
reset: () => void;
|
|
134
|
+
/** Clears buffer + timer permanently, without touching store state. Called on dispatcher unmount. */
|
|
135
|
+
dispose: () => void;
|
|
136
|
+
/** Push a surface record; assigns registration order. Returns the pop cleanup. */
|
|
137
|
+
pushSurface: (surface: SurfaceRecord) => () => void;
|
|
138
|
+
/** Notify a (root or surface-local) mode change: clears buffer + pending sequence. */
|
|
139
|
+
modeChanged: (surfaceId: string) => void;
|
|
140
|
+
/** Back-compat CommandRegistry facade for a surface record (stable per record). */
|
|
141
|
+
registryFor: (record: SurfaceRecord) => CommandRegistry;
|
|
142
|
+
/** Update live config (leader/keymap/timeout are read per dispatch, as before). */
|
|
143
|
+
setConfig: (config: CommandStoreConfig) => void;
|
|
144
|
+
}
|
|
145
|
+
export declare function createCommandStore(options: CreateCommandStoreOptions): CommandStore;
|
|
146
|
+
export {};
|
|
147
|
+
//# sourceMappingURL=command-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-store.d.ts","sourceRoot":"","sources":["../src/command-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
import { createStore } from "@xstate/store";
|
|
2
|
+
import { parseHotkey } from "./parse.js";
|
|
3
|
+
import { matchStep } from "./match.js";
|
|
4
|
+
import { DEFAULT_SEQUENCE_TIMEOUT_MS, findPendingMatch, matchesBuffer, pruneBuffer, } from "./sequence.js";
|
|
5
|
+
export const ROOT_SURFACE_ID = "__root";
|
|
6
|
+
const DEFAULT_MODES = ["cursor"];
|
|
7
|
+
// --- Selectors ---------------------------------------------------------------
|
|
8
|
+
/**
|
|
9
|
+
* The topmost modal surface: role === "modal", max depth, then max order.
|
|
10
|
+
* Passive surfaces and the root never win.
|
|
11
|
+
*/
|
|
12
|
+
export function selectActiveModalSurface(ctx) {
|
|
13
|
+
let best = null;
|
|
14
|
+
for (const record of ctx.surfaces) {
|
|
15
|
+
if (record.role !== "modal")
|
|
16
|
+
continue;
|
|
17
|
+
if (best === null ||
|
|
18
|
+
record.depth > best.depth ||
|
|
19
|
+
(record.depth === best.depth && record.order > best.order)) {
|
|
20
|
+
best = record;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return best;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Commands registered on a surface. Returns a fresh array; memoize against
|
|
27
|
+
* `selectSurfaceCommandMap` identity in render paths.
|
|
28
|
+
*/
|
|
29
|
+
export function selectSurfaceCommands(ctx, surfaceId) {
|
|
30
|
+
const commands = ctx.commandsBySurface.get(surfaceId);
|
|
31
|
+
return commands ? Array.from(commands.values()) : [];
|
|
32
|
+
}
|
|
33
|
+
/** Identity-stable per-surface command map (undefined when none registered). */
|
|
34
|
+
export function selectSurfaceCommandMap(ctx, surfaceId) {
|
|
35
|
+
return ctx.commandsBySurface.get(surfaceId);
|
|
36
|
+
}
|
|
37
|
+
export function selectSequence(ctx) {
|
|
38
|
+
return ctx.sequence;
|
|
39
|
+
}
|
|
40
|
+
export function selectGroups(ctx) {
|
|
41
|
+
return ctx.groups;
|
|
42
|
+
}
|
|
43
|
+
// --- Step-key helpers (shared by key dispatch and group registration) --------
|
|
44
|
+
export function stepsKey(steps) {
|
|
45
|
+
return steps.map(formatStepKey).join(" ");
|
|
46
|
+
}
|
|
47
|
+
export function formatStepKey(step) {
|
|
48
|
+
const modifiers = [];
|
|
49
|
+
if (step.ctrl)
|
|
50
|
+
modifiers.push("ctrl");
|
|
51
|
+
if (step.meta)
|
|
52
|
+
modifiers.push("meta");
|
|
53
|
+
if (step.option)
|
|
54
|
+
modifiers.push("option");
|
|
55
|
+
if (step.shift)
|
|
56
|
+
modifiers.push("shift");
|
|
57
|
+
if (step.super)
|
|
58
|
+
modifiers.push("super");
|
|
59
|
+
modifiers.push(step.key);
|
|
60
|
+
return modifiers.join("+");
|
|
61
|
+
}
|
|
62
|
+
// --- Store -------------------------------------------------------------------
|
|
63
|
+
/**
|
|
64
|
+
* Sequence-clear rule for surface transitions: a pending chord (display state)
|
|
65
|
+
* is cleared exactly when the transition changes which surface record owns
|
|
66
|
+
* keyboard input. Pushing/popping a passive surface (e.g. which-key) keeps the
|
|
67
|
+
* sequence it is displaying; replacing the active modal surface with a same-id
|
|
68
|
+
* record clears it (F-09) because the record identity changes.
|
|
69
|
+
*/
|
|
70
|
+
function sequenceAfterStackChange(before, after, sequence) {
|
|
71
|
+
return before === after ? sequence : null;
|
|
72
|
+
}
|
|
73
|
+
function createBaseStore(initialContext) {
|
|
74
|
+
return createStore({
|
|
75
|
+
context: initialContext,
|
|
76
|
+
on: {
|
|
77
|
+
commandRegistered: (ctx, event) => {
|
|
78
|
+
const existing = ctx.commandsBySurface.get(event.surfaceId);
|
|
79
|
+
const commands = new Map(existing ?? []);
|
|
80
|
+
commands.set(event.command.id, event.command);
|
|
81
|
+
const commandsBySurface = new Map(ctx.commandsBySurface);
|
|
82
|
+
commandsBySurface.set(event.surfaceId, commands);
|
|
83
|
+
return { ...ctx, commandsBySurface };
|
|
84
|
+
},
|
|
85
|
+
commandUnregistered: (ctx, event) => {
|
|
86
|
+
// Identity-guarded (R-05): with duplicate ids the map holds the last
|
|
87
|
+
// writer, and the first registrant's unmount must not delete the
|
|
88
|
+
// second's live command.
|
|
89
|
+
const existing = ctx.commandsBySurface.get(event.surfaceId);
|
|
90
|
+
if (!existing || existing.get(event.command.id) !== event.command)
|
|
91
|
+
return ctx;
|
|
92
|
+
const commands = new Map(existing);
|
|
93
|
+
commands.delete(event.command.id);
|
|
94
|
+
const commandsBySurface = new Map(ctx.commandsBySurface);
|
|
95
|
+
if (commands.size === 0) {
|
|
96
|
+
commandsBySurface.delete(event.surfaceId);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
commandsBySurface.set(event.surfaceId, commands);
|
|
100
|
+
}
|
|
101
|
+
return { ...ctx, commandsBySurface };
|
|
102
|
+
},
|
|
103
|
+
groupRegistered: (ctx, event) => {
|
|
104
|
+
const groups = new Map(ctx.groups);
|
|
105
|
+
groups.set(event.group.prefixKey, event.group);
|
|
106
|
+
return { ...ctx, groups };
|
|
107
|
+
},
|
|
108
|
+
groupUnregistered: (ctx, event) => {
|
|
109
|
+
// Identity-guarded, as for commands.
|
|
110
|
+
if (ctx.groups.get(event.group.prefixKey) !== event.group)
|
|
111
|
+
return ctx;
|
|
112
|
+
const groups = new Map(ctx.groups);
|
|
113
|
+
groups.delete(event.group.prefixKey);
|
|
114
|
+
return { ...ctx, groups };
|
|
115
|
+
},
|
|
116
|
+
contextSourceRegistered: (ctx, event) => {
|
|
117
|
+
const contextSources = new Map(ctx.contextSources);
|
|
118
|
+
contextSources.set(event.id, event.getter);
|
|
119
|
+
return { ...ctx, contextSources };
|
|
120
|
+
},
|
|
121
|
+
contextSourceUnregistered: (ctx, event) => {
|
|
122
|
+
if (!ctx.contextSources.has(event.id))
|
|
123
|
+
return ctx;
|
|
124
|
+
const contextSources = new Map(ctx.contextSources);
|
|
125
|
+
contextSources.delete(event.id);
|
|
126
|
+
return { ...ctx, contextSources };
|
|
127
|
+
},
|
|
128
|
+
surfacePushed: (ctx, event) => {
|
|
129
|
+
const before = selectActiveModalSurface(ctx);
|
|
130
|
+
const surfaces = [...ctx.surfaces, event.surface];
|
|
131
|
+
const after = selectActiveModalSurface({ ...ctx, surfaces });
|
|
132
|
+
return { ...ctx, surfaces, sequence: sequenceAfterStackChange(before, after, ctx.sequence) };
|
|
133
|
+
},
|
|
134
|
+
surfacePopped: (ctx, event) => {
|
|
135
|
+
// Identity-based removal: only the exact pushed record is removed.
|
|
136
|
+
const surfaces = ctx.surfaces.filter((record) => record !== event.surface);
|
|
137
|
+
if (surfaces.length === ctx.surfaces.length)
|
|
138
|
+
return ctx;
|
|
139
|
+
const before = selectActiveModalSurface(ctx);
|
|
140
|
+
const after = selectActiveModalSurface({ ...ctx, surfaces });
|
|
141
|
+
return { ...ctx, surfaces, sequence: sequenceAfterStackChange(before, after, ctx.sequence) };
|
|
142
|
+
},
|
|
143
|
+
modeChanged: (ctx, _event) => {
|
|
144
|
+
// A mode change is a transition, not a post-render repair: any pending
|
|
145
|
+
// chord is invalidated (F-08 — including surface-local mode changes).
|
|
146
|
+
return ctx.sequence === null ? ctx : { ...ctx, sequence: null };
|
|
147
|
+
},
|
|
148
|
+
sequencePending: (ctx, event) => {
|
|
149
|
+
return { ...ctx, sequence: event.state };
|
|
150
|
+
},
|
|
151
|
+
sequenceReset: (ctx) => {
|
|
152
|
+
return ctx.sequence === null ? ctx : { ...ctx, sequence: null };
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
export function createCommandStore(options) {
|
|
158
|
+
const rootRecord = {
|
|
159
|
+
id: ROOT_SURFACE_ID,
|
|
160
|
+
role: "root",
|
|
161
|
+
depth: 0,
|
|
162
|
+
order: 0,
|
|
163
|
+
getMode: options.root.getMode,
|
|
164
|
+
buildCtx: options.root.buildCtx,
|
|
165
|
+
};
|
|
166
|
+
const store = createBaseStore({
|
|
167
|
+
surfaces: [rootRecord],
|
|
168
|
+
commandsBySurface: new Map(),
|
|
169
|
+
groups: new Map(),
|
|
170
|
+
contextSources: new Map(),
|
|
171
|
+
sequence: null,
|
|
172
|
+
});
|
|
173
|
+
let config = {
|
|
174
|
+
leader: options.leader,
|
|
175
|
+
keymap: options.keymap,
|
|
176
|
+
sequenceTimeoutMs: options.sequenceTimeoutMs,
|
|
177
|
+
};
|
|
178
|
+
// IO-adjacent wrapper state: key buffer, timer, parse cache, order counter.
|
|
179
|
+
let buffer = [];
|
|
180
|
+
let timer = null;
|
|
181
|
+
const parseCache = new Map();
|
|
182
|
+
const registries = new Map();
|
|
183
|
+
let orderCounter = 1;
|
|
184
|
+
function clearTimer() {
|
|
185
|
+
if (timer !== null) {
|
|
186
|
+
clearTimeout(timer);
|
|
187
|
+
timer = null;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
function armTimer() {
|
|
191
|
+
clearTimer();
|
|
192
|
+
timer = setTimeout(reset, config.sequenceTimeoutMs ?? DEFAULT_SEQUENCE_TIMEOUT_MS);
|
|
193
|
+
}
|
|
194
|
+
function clearBufferAndTimer() {
|
|
195
|
+
buffer = [];
|
|
196
|
+
clearTimer();
|
|
197
|
+
}
|
|
198
|
+
function reset() {
|
|
199
|
+
clearBufferAndTimer();
|
|
200
|
+
store.trigger.sequenceReset();
|
|
201
|
+
}
|
|
202
|
+
function dispose() {
|
|
203
|
+
clearBufferAndTimer();
|
|
204
|
+
}
|
|
205
|
+
function getParsedHotkey(hotkey) {
|
|
206
|
+
const cacheKey = `${hotkey}:${config.leader ?? ""}`;
|
|
207
|
+
let parsed = parseCache.get(cacheKey);
|
|
208
|
+
if (!parsed) {
|
|
209
|
+
parsed = parseHotkey(hotkey, config.leader);
|
|
210
|
+
parseCache.set(cacheKey, parsed);
|
|
211
|
+
}
|
|
212
|
+
return parsed;
|
|
213
|
+
}
|
|
214
|
+
function key(event) {
|
|
215
|
+
const ctx = store.getSnapshot().context;
|
|
216
|
+
// Arbitration: a topmost modal surface owns input; otherwise the root app.
|
|
217
|
+
const surface = selectActiveModalSurface(ctx) ?? rootRecord;
|
|
218
|
+
const currentMode = surface.getMode();
|
|
219
|
+
const cmdCtx = surface.buildCtx();
|
|
220
|
+
const commands = ctx.commandsBySurface.get(surface.id);
|
|
221
|
+
// Collect eligible commands with their parsed hotkeys
|
|
222
|
+
const singleStepCandidates = [];
|
|
223
|
+
const multiStepCandidates = [];
|
|
224
|
+
if (commands) {
|
|
225
|
+
for (const command of commands.values()) {
|
|
226
|
+
const commandModes = command.modes ?? DEFAULT_MODES;
|
|
227
|
+
if (!commandModes.includes(currentMode))
|
|
228
|
+
continue;
|
|
229
|
+
if (command.when && !command.when(cmdCtx))
|
|
230
|
+
continue;
|
|
231
|
+
const hotkey = config.keymap?.[command.id] ?? command.defaultHotkey;
|
|
232
|
+
if (!hotkey)
|
|
233
|
+
continue;
|
|
234
|
+
const parsed = getParsedHotkey(hotkey);
|
|
235
|
+
// Unmatchable hotkeys (e.g. <leader> with no configured leader) register
|
|
236
|
+
// nothing rather than matching everything.
|
|
237
|
+
if (parsed.steps.length === 0)
|
|
238
|
+
continue;
|
|
239
|
+
if (parsed.steps.length === 1) {
|
|
240
|
+
singleStepCandidates.push({ command, parsed });
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
multiStepCandidates.push({ command, hotkey, parsed });
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
// Check multi-step sequences first (they consume buffer state)
|
|
248
|
+
if (multiStepCandidates.length > 0) {
|
|
249
|
+
const hotkeys = multiStepCandidates.map((candidate) => candidate.parsed);
|
|
250
|
+
buffer = [...buffer, event];
|
|
251
|
+
armTimer();
|
|
252
|
+
let matchedIndex = -1;
|
|
253
|
+
for (let i = 0; i < hotkeys.length; i++) {
|
|
254
|
+
if (matchesBuffer(buffer, hotkeys[i])) {
|
|
255
|
+
matchedIndex = i;
|
|
256
|
+
break;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
if (matchedIndex >= 0) {
|
|
260
|
+
clearBufferAndTimer();
|
|
261
|
+
store.trigger.sequenceReset();
|
|
262
|
+
const matched = multiStepCandidates[matchedIndex].command;
|
|
263
|
+
return { handled: true, invoke: () => matched.handler(cmdCtx) };
|
|
264
|
+
}
|
|
265
|
+
buffer = pruneBuffer(buffer, hotkeys);
|
|
266
|
+
const pending = findPendingMatch(buffer, hotkeys);
|
|
267
|
+
if (pending) {
|
|
268
|
+
const firstCandidate = multiStepCandidates[pending.indexes[0]];
|
|
269
|
+
const state = {
|
|
270
|
+
prefix: firstCandidate.parsed.steps.slice(0, pending.prefixLength),
|
|
271
|
+
candidates: pending.indexes
|
|
272
|
+
.map((idx) => multiStepCandidates[idx])
|
|
273
|
+
.filter(({ command }) => !command.hidden)
|
|
274
|
+
.map(({ command, hotkey, parsed }) => ({
|
|
275
|
+
command,
|
|
276
|
+
hotkey,
|
|
277
|
+
steps: parsed.steps,
|
|
278
|
+
remainingSteps: parsed.steps.slice(pending.prefixLength),
|
|
279
|
+
nextStep: parsed.steps[pending.prefixLength],
|
|
280
|
+
group: ctx.groups.get(stepsKey(parsed.steps.slice(0, pending.prefixLength + 1))),
|
|
281
|
+
})),
|
|
282
|
+
};
|
|
283
|
+
store.trigger.sequencePending({ state });
|
|
284
|
+
return { handled: true };
|
|
285
|
+
}
|
|
286
|
+
store.trigger.sequenceReset();
|
|
287
|
+
}
|
|
288
|
+
// Check single-step matches
|
|
289
|
+
for (const { command, parsed } of singleStepCandidates) {
|
|
290
|
+
if (matchStep(event, parsed.steps[0])) {
|
|
291
|
+
store.trigger.sequenceReset();
|
|
292
|
+
return { handled: true, invoke: () => command.handler(cmdCtx) };
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
// A modal surface swallows unhandled keys: dispatch never falls through to
|
|
296
|
+
// the root app while a modal surface is topmost. (The caller does not
|
|
297
|
+
// preventDefault unmatched keys — same as today.)
|
|
298
|
+
return { handled: false };
|
|
299
|
+
}
|
|
300
|
+
function pushSurface(surface) {
|
|
301
|
+
surface.order = orderCounter++;
|
|
302
|
+
const before = selectActiveModalSurface(store.getSnapshot().context);
|
|
303
|
+
store.trigger.surfacePushed({ surface });
|
|
304
|
+
const after = selectActiveModalSurface(store.getSnapshot().context);
|
|
305
|
+
// Keep the wrapper buffer consistent with the transition's sequence-clear
|
|
306
|
+
// rule: clear exactly when keyboard ownership changed.
|
|
307
|
+
if (before !== after)
|
|
308
|
+
clearBufferAndTimer();
|
|
309
|
+
return () => {
|
|
310
|
+
const beforePop = selectActiveModalSurface(store.getSnapshot().context);
|
|
311
|
+
store.trigger.surfacePopped({ surface });
|
|
312
|
+
const afterPop = selectActiveModalSurface(store.getSnapshot().context);
|
|
313
|
+
if (beforePop !== afterPop)
|
|
314
|
+
clearBufferAndTimer();
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
function modeChanged(surfaceId) {
|
|
318
|
+
clearBufferAndTimer();
|
|
319
|
+
store.trigger.modeChanged({ surfaceId });
|
|
320
|
+
}
|
|
321
|
+
function registryFor(record) {
|
|
322
|
+
let registry = registries.get(record);
|
|
323
|
+
if (!registry) {
|
|
324
|
+
registry = {
|
|
325
|
+
get commands() {
|
|
326
|
+
const current = store.getSnapshot().context.commandsBySurface.get(record.id);
|
|
327
|
+
// The registry contract exposes a Map; the store's per-surface maps
|
|
328
|
+
// are Maps at runtime (readonly-typed). Consumers must not mutate.
|
|
329
|
+
return (current ?? new Map());
|
|
330
|
+
},
|
|
331
|
+
register(command) {
|
|
332
|
+
store.trigger.commandRegistered({ surfaceId: record.id, command });
|
|
333
|
+
return () => {
|
|
334
|
+
store.trigger.commandUnregistered({ surfaceId: record.id, command });
|
|
335
|
+
};
|
|
336
|
+
},
|
|
337
|
+
invoke(id) {
|
|
338
|
+
const ctx = store.getSnapshot().context;
|
|
339
|
+
const cmd = ctx.commandsBySurface.get(record.id)?.get(id);
|
|
340
|
+
if (!cmd)
|
|
341
|
+
return;
|
|
342
|
+
const cmdCtx = record.buildCtx();
|
|
343
|
+
if (!cmd.when || cmd.when(cmdCtx)) {
|
|
344
|
+
cmd.handler(cmdCtx);
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
};
|
|
348
|
+
registries.set(record, registry);
|
|
349
|
+
}
|
|
350
|
+
return registry;
|
|
351
|
+
}
|
|
352
|
+
function setConfig(next) {
|
|
353
|
+
config = next;
|
|
354
|
+
}
|
|
355
|
+
return {
|
|
356
|
+
store,
|
|
357
|
+
rootRecord,
|
|
358
|
+
key,
|
|
359
|
+
reset,
|
|
360
|
+
dispose,
|
|
361
|
+
pushSurface,
|
|
362
|
+
modeChanged,
|
|
363
|
+
registryFor,
|
|
364
|
+
setConfig,
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
//# sourceMappingURL=command-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-store.js","sourceRoot":"","sources":["../src/command-store.ts"],"names":[],"mappings":"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"}
|
package/dist/context.d.ts
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
|
-
import type { Command, CommandContext, CommandGroup, CommandRegistry, CommandSequenceState, RegisteredCommandGroup } from "./types.js";
|
|
2
|
+
import type { ActiveCommandSurface, Command, CommandContext, CommandGroup, CommandRegistry, CommandSequenceState, CommandSurfaceRole, RegisteredCommandGroup } from "./types.js";
|
|
3
3
|
import type { Mode } from "./mode.js";
|
|
4
|
-
type ContextGetter
|
|
4
|
+
import { type CommandStore, type ContextGetter, type SurfaceRecord } from "./command-store.js";
|
|
5
5
|
interface CommandContextValue {
|
|
6
6
|
registry: CommandRegistry;
|
|
7
7
|
leaderKey?: string;
|
|
8
8
|
contextSources: Map<string, ContextGetter>;
|
|
9
9
|
groups: Map<string, RegisteredCommandGroup>;
|
|
10
10
|
}
|
|
11
|
-
|
|
11
|
+
/** Internal provider value: the store plus the surface this subtree registers to. */
|
|
12
|
+
interface CommandStoreContextValue {
|
|
13
|
+
commandStore: CommandStore;
|
|
14
|
+
/** The surface record `useCommand` registrations under this subtree target. */
|
|
15
|
+
surface: SurfaceRecord;
|
|
16
|
+
leaderKey?: string;
|
|
17
|
+
}
|
|
18
|
+
declare const CommandContext: import("react").Context<CommandStoreContextValue | null>;
|
|
12
19
|
export interface CommandProviderProps {
|
|
13
20
|
children: ReactNode;
|
|
14
21
|
leader?: string;
|
|
@@ -17,12 +24,54 @@ export interface CommandProviderProps {
|
|
|
17
24
|
sequenceTimeoutMs?: number;
|
|
18
25
|
}
|
|
19
26
|
export declare function CommandProvider({ children, leader, keymap, initialMode, sequenceTimeoutMs, }: CommandProviderProps): ReactNode;
|
|
27
|
+
export interface CommandSurfaceProviderProps {
|
|
28
|
+
children: ReactNode;
|
|
29
|
+
/** Stable id for the surface (typically the overlay id). */
|
|
30
|
+
id: string;
|
|
31
|
+
/** Interaction role (default "modal"). */
|
|
32
|
+
role?: CommandSurfaceRole;
|
|
33
|
+
/** Initial local mode for this surface (default "cursor"). */
|
|
34
|
+
initialMode?: Mode;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Mounts an overlay-owned command surface. Children registered via `useCommand`
|
|
38
|
+
* target this surface's local registry, and `useMode`/`useSetMode` read/write
|
|
39
|
+
* this surface's local mode instead of the root app's mode.
|
|
40
|
+
*
|
|
41
|
+
* While a `modal` surface is topmost it owns keyboard input and suspends the
|
|
42
|
+
* parent app's commands; a `passive` surface never becomes the keyboard owner.
|
|
43
|
+
*/
|
|
44
|
+
export declare function CommandSurfaceProvider({ children, id, role, initialMode, }: CommandSurfaceProviderProps): ReactNode;
|
|
20
45
|
export declare function useCommandContext(): {
|
|
21
46
|
commands: Command[];
|
|
22
47
|
invoke: (id: string) => void;
|
|
23
48
|
};
|
|
49
|
+
/**
|
|
50
|
+
* Internal: the stable registry facade for the nearest surface, without
|
|
51
|
+
* subscribing to store changes. Registration hooks (useCommand/useActions)
|
|
52
|
+
* only need the facade; subscribing them would re-render every command host
|
|
53
|
+
* on unrelated group/context-source registrations.
|
|
54
|
+
*/
|
|
55
|
+
export declare function useSurfaceRegistry(): CommandRegistry;
|
|
24
56
|
export declare function useCommandRegistry(): CommandContextValue;
|
|
25
57
|
export declare function useCommandSequenceState(): CommandSequenceState | null;
|
|
58
|
+
/**
|
|
59
|
+
* Metadata for the topmost modal command surface, or null when the root app is
|
|
60
|
+
* the active surface. Intended for which-key/help to read shortcuts from the
|
|
61
|
+
* active interaction surface. `commands` is reactive (F-13).
|
|
62
|
+
*/
|
|
63
|
+
export declare function useActiveCommandSurface(): ActiveCommandSurface | null;
|
|
64
|
+
/**
|
|
65
|
+
* Commands registered on a surface (reactive). Defaults to the active modal
|
|
66
|
+
* surface, falling back to the root surface when none is active.
|
|
67
|
+
*/
|
|
68
|
+
export declare function useSurfaceCommands(surfaceId?: string): readonly Command[];
|
|
69
|
+
/**
|
|
70
|
+
* Advanced/internal — subject to change. The command store instance backing
|
|
71
|
+
* this provider tree, for bridges that must reach the dispatch machinery
|
|
72
|
+
* (e.g. the shell's overlay-replacement sequence reset).
|
|
73
|
+
*/
|
|
74
|
+
export declare function useCommandStore(): CommandStore;
|
|
26
75
|
export declare function useCommandGroup(group: CommandGroup): void;
|
|
27
76
|
export declare function useProvideCommandContext(getter: () => Partial<CommandContext>): void;
|
|
28
77
|
export {};
|