@tooee/commands 0.1.20 → 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.
Files changed (46) hide show
  1. package/README.md +33 -0
  2. package/dist/command-store.d.ts +147 -0
  3. package/dist/command-store.d.ts.map +1 -0
  4. package/dist/command-store.js +367 -0
  5. package/dist/command-store.js.map +1 -0
  6. package/dist/context.d.ts +28 -3
  7. package/dist/context.d.ts.map +1 -1
  8. package/dist/context.js +189 -233
  9. package/dist/context.js.map +1 -1
  10. package/dist/index.d.ts +3 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +2 -1
  13. package/dist/index.js.map +1 -1
  14. package/dist/match.d.ts.map +1 -1
  15. package/dist/match.js +2 -0
  16. package/dist/match.js.map +1 -1
  17. package/dist/mode.d.ts +7 -1
  18. package/dist/mode.d.ts.map +1 -1
  19. package/dist/mode.js +12 -3
  20. package/dist/mode.js.map +1 -1
  21. package/dist/parse.d.ts.map +1 -1
  22. package/dist/parse.js +17 -5
  23. package/dist/parse.js.map +1 -1
  24. package/dist/sequence.d.ts +17 -2
  25. package/dist/sequence.d.ts.map +1 -1
  26. package/dist/sequence.js +66 -45
  27. package/dist/sequence.js.map +1 -1
  28. package/dist/types.d.ts +20 -1
  29. package/dist/types.d.ts.map +1 -1
  30. package/dist/use-actions.d.ts.map +1 -1
  31. package/dist/use-actions.js +6 -3
  32. package/dist/use-actions.js.map +1 -1
  33. package/dist/use-command.d.ts.map +1 -1
  34. package/dist/use-command.js +12 -4
  35. package/dist/use-command.js.map +1 -1
  36. package/package.json +5 -1
  37. package/src/command-store.ts +554 -0
  38. package/src/context.tsx +252 -276
  39. package/src/index.ts +21 -0
  40. package/src/match.ts +1 -0
  41. package/src/mode.tsx +31 -3
  42. package/src/parse.ts +20 -5
  43. package/src/sequence.ts +80 -52
  44. package/src/types.ts +22 -3
  45. package/src/use-actions.ts +5 -3
  46. 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
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 = () => Partial<CommandContext>;
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
- declare const CommandContext: import("react").Context<CommandContextValue | null>;
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;
@@ -39,14 +46,32 @@ export declare function useCommandContext(): {
39
46
  commands: Command[];
40
47
  invoke: (id: string) => void;
41
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;
42
56
  export declare function useCommandRegistry(): CommandContextValue;
43
57
  export declare function useCommandSequenceState(): CommandSequenceState | null;
44
58
  /**
45
59
  * Metadata for the topmost modal command surface, or null when the root app is
46
60
  * the active surface. Intended for which-key/help to read shortcuts from the
47
- * active interaction surface.
61
+ * active interaction surface. `commands` is reactive (F-13).
48
62
  */
49
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;
50
75
  export declare function useCommandGroup(group: CommandGroup): void;
51
76
  export declare function useProvideCommandContext(getter: () => Partial<CommandContext>): void;
52
77
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.tsx"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,SAAS,EACf,MAAM,OAAO,CAAA;AAEd,OAAO,KAAK,EACV,oBAAoB,EACpB,OAAO,EACP,cAAc,EACd,YAAY,EACZ,eAAe,EACf,oBAAoB,EAEpB,kBAAkB,EAGlB,sBAAsB,EACvB,MAAM,YAAY,CAAA;AACnB,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAQrC,KAAK,aAAa,GAAG,MAAM,OAAO,CAAC,cAAc,CAAC,CAAA;AAElD,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,eAAe,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;IAC1C,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAA;CAC5C;AAWD,QAAA,MAAM,cAAc,qDAAkD,CAAA;AA+BtE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,SAAS,CAAA;IACnB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,WAAW,CAAC,EAAE,IAAI,CAAA;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,MAAM,EACN,MAAM,EACN,WAAW,EACX,iBAAiB,GAClB,EAAE,oBAAoB,aAQtB;AAqOD,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,EAAE,SAAS,CAAA;IACnB,4DAA4D;IAC5D,EAAE,EAAE,MAAM,CAAA;IACV,0CAA0C;IAC1C,IAAI,CAAC,EAAE,kBAAkB,CAAA;IACzB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,IAAI,CAAA;CACnB;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,EAAE,EACF,IAAc,EACd,WAAsB,GACvB,EAAE,2BAA2B,aAQ7B;AAmFD,wBAAgB,iBAAiB,IAAI;IAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;IAAC,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,CAazF;AAED,wBAAgB,kBAAkB,IAAI,mBAAmB,CAMxD;AAED,wBAAgB,uBAAuB,IAAI,oBAAoB,GAAG,IAAI,CAErE;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,IAAI,oBAAoB,GAAG,IAAI,CAGrE;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CA8BzD;AAkBD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,CAuBpF"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAA;AAGd,OAAO,KAAK,EACV,oBAAoB,EACpB,OAAO,EACP,cAAc,EACd,YAAY,EACZ,eAAe,EACf,oBAAoB,EACpB,kBAAkB,EAClB,sBAAsB,EACvB,MAAM,YAAY,CAAA;AACnB,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAGrC,OAAO,EAOL,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,aAAa,EACnB,MAAM,oBAAoB,CAAA;AAE3B,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,eAAe,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;IAC1C,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAA;CAC5C;AAED,qFAAqF;AACrF,UAAU,wBAAwB;IAChC,YAAY,EAAE,YAAY,CAAA;IAC1B,+EAA+E;IAC/E,OAAO,EAAE,aAAa,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,QAAA,MAAM,cAAc,0DAAuD,CAAA;AAwB3E,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,SAAS,CAAA;IACnB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,WAAW,CAAC,EAAE,IAAI,CAAA;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B;AAOD,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,MAAM,EACN,MAAM,EACN,WAAW,EACX,iBAAiB,GAClB,EAAE,oBAAoB,aAmDtB;AA+ED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,EAAE,SAAS,CAAA;IACnB,4DAA4D;IAC5D,EAAE,EAAE,MAAM,CAAA;IACV,0CAA0C;IAC1C,IAAI,CAAC,EAAE,kBAAkB,CAAA;IACzB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,IAAI,CAAA;CACnB;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,EAAE,EACF,IAAc,EACd,WAAsB,GACvB,EAAE,2BAA2B,aAkB7B;AAqFD,wBAAgB,iBAAiB,IAAI;IAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;IAAC,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,CAqBzF;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,eAAe,CAMpD;AAED,wBAAgB,kBAAkB,IAAI,mBAAmB,CAsBxD;AAED,wBAAgB,uBAAuB,IAAI,oBAAoB,GAAG,IAAI,CAErE;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,IAAI,oBAAoB,GAAG,IAAI,CAkBrE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,OAAO,EAAE,CAUzE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,YAAY,CAM9C;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CA+BzD;AAID,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,CA0BpF"}