/** Delay between reveal frames. */ export declare const TYPEWRITER_FRAME_MS = 22; /** * Ceiling on frames for one reply, whatever its length. * * Without it a long answer reveals one character per frame and takes minutes. * The step widens instead, so a 5,000-character answer and a 200-character one * both finish in about the same time. */ export declare const TYPEWRITER_MAX_FRAMES = 260; export interface TypewriterMessage { id: string; text: string; displayText?: string; typing?: boolean; footprints?: unknown; } export interface TypewriterHost { messages(): M[]; setMessages(next: M[]): void; /** Injectable for tests; defaults to the browser's. */ setTimeout?(fn: () => void, ms: number): number; clearTimeout?(id: number): void; /** Injectable for tests; defaults to the media query. */ prefersReducedMotion?(): boolean; } /** * How many units to reveal per frame so the whole text fits in the frame budget. * Never below one, or a text longer than the budget would never finish. */ export declare function revealStep(totalUnits: number, maxFrames?: number): number; export declare function createTypewriter(host: TypewriterHost): { appendToken: (messageId: string, delta: string) => void; shouldAnimate: (text: string) => boolean; addReply: (message: M) => void; clear: (messageId: string) => void; clearAll: () => void; /** Messages still revealing. Exposed for tests and leak checks. */ readonly pending: number; };