@cartridge-engine/keyboard-engine
    Preparing search index...

    Interface EngineProps<TComponent>

    Configuration passed to KeyboardEngine at construction time.

    interface EngineProps<TComponent> {
        autoTab?: boolean;
        defaultMode?: string;
        defaultTimeout?: number;
        isNormalChar: (key: unknown) => boolean;
        modes?: string[];
        normalizeKeyNames: (input: string, key: unknown) => string[];
        processors?: KeyboardProcessorProps<TComponent>[];
        releaseFocusWhenEmpty?: boolean;
        tabKey?: string;
        valueSchema?: ValueSchema;
    }

    Type Parameters

    • TComponent
    Index
    autoTab?: boolean

    Whether the engine automatically handles Tab / Shift+Tab for focus rotation. Defaults to false.

    When true, the engine intercepts Tab/Shift+Tab and cycles focus automatically. When false or undefined, developers must call focusNext / focusPrev manually.

    defaultMode?: string

    Default mode — must be null (no-mode) or a member of modes.

    defaultTimeout?: number

    Default composition chain timeout in ms. Defaults to 400.

    isNormalChar: (key: unknown) => boolean

    Determines whether a key is a special key (NOT a normal character).

    Required so the engine stays framework-agnostic — each host framework provides its own adapter that inspects its native Key shape.

    isNormalChar: (key) => {
    const k = key as Record<string, unknown>;
    return k.upArrow || k.downArrow || k.leftArrow || k.rightArrow
    || k.pageDown || k.pageUp || k.home || k.end
    || k.return || k.escape || k.tab || k.backspace || k.delete
    || k.ctrl || k.meta || k.super || k.hyper
    || k.eventType === 'release';
    }
    modes?: string[]

    Registered mode names (e.g. ["normal", "insert"]).

    normalizeKeyNames: (input: string, key: unknown) => string[]

    Converts a framework-specific key event into normalized key-name strings for matching. Required so the engine stays framework-agnostic — each host framework provides its own adapter.

    normalizeKeyNames: (input, key) => normalizeKeyNames(input, key as Key)
    
    normalizeKeyNames: (input, key) => {
    const e = key as KeyboardEvent
    return [e.key.toLowerCase()]
    }

    Per-instance custom processors injected into the pipeline at init time.

    releaseFocusWhenEmpty?: boolean

    Remove a focus target automatically once nothing binds to it any more.

    Off by default. When on, the cleanup returned by boundKeyboard, boundSequence, penetration, stop, and allowModal drops the reference it holds; the last holder to let go removes the target and focus moves to the group's first remaining target.

    A component that re-binds releases before it re-registers (React runs the previous cleanup before the new effect). When its group has no other target, the re-created one claims that group's focus back; when it does, focus has already moved to a sibling and stays there.

    false
    
    tabKey?: string

    Override the key name used for automatic focus rotation when autoTab is true.

    The value must be a key name that normalizeKeyNames can produce — the engine matches via eventNames.includes(thisKey), so the string must exactly match a normalized name the adapter emits.

    When omitted, the engine defaults to "tab" (and "shift+tab" for reverse rotation). Provide a custom value when your host framework's key normalizer produces a different name (e.g. "Tab" with capital T, or "<Tab>").

    // Ink's normalizeKeyNames emits lowercase "tab", so the default works.
    // A framework that normalizes to "Tab" would need:
    new KeyboardEngine({
    normalizeKeyNames,
    autoTab: true,
    tabKey: "Tab",
    });
    valueSchema?: ValueSchema

    Optional runtime type schema for composition chain value validation.

    Maps flag names to type guard functions. When provided, the CompositionEngine validates every execute callback's input and output values at runtime. Validation failures clear the pending chain and emit a console.warn in development.

    const engine = new KeyboardEngine({
    normalizeKeyNames,
    valueSchema: {
    times: (v): v is number => typeof v === 'number',
    action: (v): v is number => typeof v === 'number',
    },
    });