OptionaldefaultTimeout: numberOptionalvalueSchema: ValueSchemaCancel the current pending chain immediately (no timeout).
Clears the pending timer (no stale timeout callback will fire),
resets the context to { value: undefined, lastFlag: null, steps: [] },
and sets the engine's compositionEngineHandle flag to false so
pipeline processors stop treating the chain as pending. No-op when
no chain is pending.
Register a mapping key entry — vim-style key mapping that maps an
external key sequence (base) to an internal composition key chain
(target).
Entries are stored in this.mapping (a Map<string, Set<MappingKeyEntry>>)
keyed by base[0]. When a key event matches base[0]:
base.length === 1) execute their target chain
immediately;Mapping-key pending and ordinary composition pending are mutually
exclusive, and mapping keys take priority: they are checked inside
startPending before single-key composition startup.
The external trigger key sequence (what the user presses).
The internal composition key chain to execute in order.
Optionaloptions: Omit<MappingKeyEntry<TComponent>, "keys" | "target">
Optional fields forwarded to the stored MappingKeyEntry:
exclusive, KeyReleaseWhenChainInterrupted, when, affectOverlay,
mode, category, executeWhenNoOverlay.
true if registered, false if base is empty, any target
key is not registered in keyMappingTable, or an identical
base sequence already exists.
engine.registryCompositionKey({
key: 't', flags: [], alternativeFlag: 'times',
optional: true, needs: [],
execute: (ctx) => ({ ...ctx, lastFlag: 'times', steps: [...ctx.steps, 't'] }),
});
engine.registryCompositionKey({
key: 'd', flags: [], alternativeFlag: 'action',
needs: ['times'],
execute: (ctx) => ({ ...ctx, lastFlag: 'action', steps: [...ctx.steps, 'd'] }),
});
// Map 'g b' → 't d'
engine.composition.addMapping(['g', 'b'], ['t', 'd']);
// Single-key mapping and exclusive multi-key mapping
engine.composition.addMapping(['q'], ['t']);
engine.composition.addMapping(['g', 'd'], ['t'], { exclusive: true });
// Remove a mapping
engine.composition.removeMappingKey(['g', 'b']);
Number of completed sequences available for undo.
Remove every registered composition key (clears the entire mapping table). Does not cancel an active pending chain — see removeCompositionKey.
Clear all buffered undo history.
Return a copy of the current composition context — the chain's
accumulated value, lastFlag, and steps history.
The copy is shallow: the steps array is a fresh array copy, but
value is a reference (not deep-cloned), and modifying the returned
object does not affect the engine's internal state.
Return the most recent CompositionEvent, or null if nothing
has happened yet. Useful for displaying diagnostic context (e.g.
"Chain started with key '3'" or "Broke on key 'x'").
Return the most recent MappingKeyEvent, or null if no
mapping-key event has happened yet.
Whether the engine currently has an active pending chain.
A chain is "pending" from the moment the first key starts it until it completes naturally, a key is pressed with no matching entry, or the timeout expires.
Register a composition key entry. Semantically equivalent duplicates (same fingerprint) are skipped.
Each entry is a node in a composition chain: when the entry's key
is pressed, the engine either continues the pending chain (if the
entry's needs are satisfied by the preceding lastFlag) or starts
a new chain (if the entry is a head key — optional: true or empty
needs). Multiple entries can share the same key name; they are
stored in a Map<string, Set<CompositioKey>> (duplicate identities
are not added twice) and the best match is resolved at runtime via
resolveCompositionKey.
engine.registryCompositionKey({
key: '3',
alternativeFlag: 'times',
needs: [],
optional: true,
execute: (ctx) => ({
value: 3,
lastFlag: 'times',
steps: [...ctx.steps, '3'],
}),
});
engine.registryCompositionKey({
key: '3',
alternativeFlag: 'action',
needs: ['times'],
execute: (ctx) => {
const count = ctx.value as number;
// Fire the compound action after the first timed press
console.log(`Repeated ${count} times`);
return null; // End the chain
},
});
Remove all entries registered under key — the entire set is deleted
from the mapping table.
Does NOT cancel an active pending chain: if a chain is pending when its entries are removed, it continues with its already-started context until the timeout expires. Call abort to cancel it.
true if an entry was removed, false if none existed.
Remove all mapping key entries whose head key matches firstKey.
true if any entries were removed, false otherwise.
Remove a mapping key entry by its exact key sequence.
true if found and removed, false otherwise.
Set or replace the runtime value schema for composition chain validation.
The schema replaces the previous one entirely (no merging). For each
composition key event the engine validates the input value before
execute runs (against the lastFlag's guard) and the output value
afterwards (against the current flag's guard). Flags without a guard
entry pass through silently. Validation failures clear the pending
chain and emit a console.warn in development.
Guard functions keyed by flag name.
Process a key event through the composition subsystem: first advance an in-progress pending chain, then attempt to start a new chain.
The current pipeline context.
Whether the calling pipeline phase is overlay mode.
true if the key was consumed by the composition subsystem.
Subscribe to composition state changes. The callback fires whenever the
chain starts, advances, breaks, completes, or is undone. Use it to
trigger a framework re-render (e.g. React useState setter).
An unsubscribe function.
Subscribe to mapping-key state changes. The callback fires whenever a mapping-key sequence starts, advances, breaks, is consumed (exclusive), or completes. Independent from subscribe so composition subscribers are not notified by mapping-key events.
An unsubscribe function.
Record the normalized key names of the current event for matching against registered composition and mapping keys.
Undo one or more completed composition sequences.
Each completed chain is stored as a separate entry in the undo buffer.
Passing steps undoes that many sequences, executing every key's
CompositioKey#undoAction in reverse order.
Number of past sequences to undo. Defaults to 1.
When options.byKey is true, steps counts individual keys instead.
Optionaloptions: { byKey?: boolean; isolated?: boolean }
OptionalbyKey?: booleanWhen true, steps counts individual keys
instead of whole sequences. Orthogonal to isolated.
Defaults to false.
Optionalisolated?: booleanWhen true, each sequence's undo starts from
its own saved context — ctx does NOT propagate across sequences.
Defaults to false (flat propagation).
The final context after all undo actions, or null if
nothing was undone.
Update a registered entry identified by key + flags.
The old entry is removed and a merged entry (old fields + updates,
preserving key and flags) is re-registered. Together key and
flags uniquely identify the entry (compared via areFlagsEqual),
so entries sharing a key name can be targeted individually instead
of removing all entries for that key.
true if the entry was found and updated, false if no
entry matched.
State machine for multi-key composition chains (vim-style key sequences).
Builds "flag → needs → execute" chains: pressing key "A" sets
lastFlag: "A"and produces a value; the next key "B" (withneeds: ["A"]) receives that value via itsexecute(ctx)callback, transforms it, and passes it forward. The chain continues until a key with no matching entry is pressed or the timeout expires.Entry resolution uses
needsmatching: when a pending chain exists, only keys whoseneedsincludelastFlagare eligible; when no chain is pending, only keys withoptional: trueor emptyneedscan start one.Owns the key mapping table, pending chain state, mapping-key sequences, and undo buffers. Driven by the composition pipeline processors; exposed on KeyboardEngine for direct registration and inspection.