import { Ref } from 'vue'; import { StreamState } from './types'; export interface StreamPacerOptions { /** Units available now; grows as content arrives. */ total: () => number; /** The source is still producing. */ streaming: () => boolean; wordMs?: () => number | undefined; maxLagMs?: () => number | undefined; drainMs?: () => number | undefined; pauseMs?: () => number | undefined; /** How long a released unit stays fresh (its entrance time); 0 settles at once. */ settleMs?: () => number; /** * Content already there at setup enters too, instead of showing as it is. * For a stream that mounts mid-answer with words already due, as the parts * of a TxStreamElement do. Read once. */ appear?: boolean; /** * `false` releases every unit the moment it arrives; units still stay fresh * for `settleMs`. Used when a parent paces (TxStreamElement) and under * reduced motion. */ paced?: () => boolean; onState?: (state: StreamState, previous: StreamState) => void; now?: () => number; /** `null` runs without a clock, as on a server: everything shows and settles at once. */ requestFrame?: ((callback: (time: number) => void) => number) | null; cancelFrame?: (id: number) => void; setTimer?: (callback: () => void, ms: number) => unknown; clearTimer?: (id: unknown) => void; } export interface StreamPacer { /** Units shown. */ revealed: Readonly>; /** Units whose entrance has finished; always ≤ `revealed`. */ settled: Readonly>; state: Readonly>; /** Plays everything again from the first unit at the normal cadence. */ replay: () => void; /** Shows everything now, without entrances. */ skip: () => void; /** Content was rewritten from `index`: units from there on are released again. */ rewind: (index: number) => void; stop: () => void; } /** * The stream clock. It releases units one `wordMs` apart and speeds up whenever * the backlog would take longer than `maxLagMs` to show, so bursty tokens come * out as a steady flow that never falls far behind the source. When the source * finishes it releases the rest at a fixed rate that clears it within * `drainMs`. It also tracks when each unit was released, so the renderer can * turn a unit into plain text once its entrance has played (`settled`). * * One `requestAnimationFrame` loop, running only while something is left to * release or settle. Without a window (SSR) everything is released and settled * at once. */ export declare function useStreamPacer(options: StreamPacerOptions): StreamPacer;