/** * Frame buffer: a 2D grid of terminal cells with differential rendering. * * Two buffers (current + previous) are maintained. After rendering nodes * into the current buffer, diffFrames() produces the minimal set of * changed runs. The ANSI serializer converts those runs into escape * sequences, tracking SGR state to minimize output bytes. */ export declare const Attr: { readonly None: 0; readonly Bold: 1; readonly Dim: 2; readonly Italic: 4; readonly Underline: 8; readonly Inverse: 16; readonly Strikethrough: 32; }; export type Attr = number; export declare const NO_COLOR = -1; export interface Cell { /** Attribute bitfield (bold, italic, etc.) */ attrs: Attr; /** Background color: 24-bit RGB packed as number, or NO_COLOR */ bg: number; /** Single character or grapheme cluster */ char: string; /** Foreground color: 24-bit RGB packed as number, or NO_COLOR */ fg: number; /** OSC 8 hyperlink URL, or empty string for no link */ link: string; /** Display width: 1 normal, 2 wide (CJK/emoji), 0 continuation cell */ width: number; } /** Display width of a single code-point string, memoized. */ export declare function charWidth(char: string): number; export declare function createCell(char?: string, fg?: number, bg?: number, attrs?: Attr, width?: number, link?: string): Cell; /** Rectangular clip region (exclusive right/bottom). */ export interface ClipRect { bottom: number; left: number; right: number; top: number; } export declare class FrameBuffer { readonly cols: number; readonly rows: number; /** The visible grid: each slot points at either SHARED_BLANK or its scratch. */ readonly cells: Cell[]; /** * One persistent, mutable Cell per slot, allocated once. Writing a slot * mutates its scratch cell in place and points `cells[i]` at it — so a frame * allocates zero new cells no matter how much it paints. Blank slots point at * the shared frozen blank instead, keeping the diff's identity fast path. */ private readonly scratch; /** Rows touched by set()/writeString()/fillRect() since last clear(). */ readonly dirtyRows: Set; constructor(cols: number, rows: number); /** Mutate the scratch cell for a slot in place and make it the visible cell. */ private writeCell; clear(): void; /** Reset only rows that were previously painted, then clear the dirty set. */ clearDirtyRows(): void; /** Find the last row that has non-empty content. Returns 0 if all empty. */ contentHeight(): number; get(col: number, row: number): Cell; /** * Return a writable cell for a slot, for callers that mutate it in place * (e.g. the selection-inverse overlay). A blank slot is first materialized * into its own scratch cell — never hand out the frozen shared blank — and * the row is marked dirty. Callers must pass in-bounds coordinates. */ getMutable(col: number, row: number): Cell; set(col: number, row: number, cell: Cell): void; /** Write a string at (col, row) with given attributes. Returns columns consumed. */ writeString(col: number, row: number, str: string, fg?: number, bg?: number, attrs?: Attr, clip?: ClipRect, link?: string): number; /** Fill a rectangular region with a cell value. */ fillRect(col: number, row: number, width: number, height: number, char?: string, fg?: number, bg?: number, attrs?: Attr, clip?: ClipRect): void; } export interface ChangedRun { /** Reference to the source cell array (no copy). */ cells: Cell[]; /** End index (exclusive) into cells. */ end: number; row: number; /** Start index into cells. */ start: number; startCol: number; } /** * Compare two frame buffers and produce the minimal set of changed runs. * Optionally restrict to a set of dirty rows for faster diffing. */ export declare function diffFrames(prev: FrameBuffer, curr: FrameBuffer, dirtyRows?: Set): ChangedRun[]; interface SGRState { attrs: Attr; bg: number; fg: number; } /** * Serialize changed runs into a minimal ANSI byte sequence. * Tracks SGR state across runs to avoid redundant attribute codes. */ export declare function serializeChanges(changes: ChangedRun[], initialState?: SGRState, enableLinks?: boolean): string; /** * Wrap frame data in synchronized output markers (DEC private mode 2026). * The terminal holds all rendering until ESU, then paints atomically. */ export declare function wrapSynchronized(data: string): string; /** * Resolve any ColorInput to a packed 24-bit RGB number for Cell fg/bg. * Accepts hex (#rgb, #rrggbb), named colors, rgb(), hsl(), numbers, etc. * Returns NO_COLOR for invalid input. */ export declare function color(input: Bun.ColorInput): number; export {}; //# sourceMappingURL=frame-buffer.d.ts.map