import { type ReactNode } from "react"; import { type ReadStream, type WriteStream } from "../types/io.js"; import { type IncrementalRenderingOption } from "./incremental-rendering.js"; /** * Performance metrics for a render operation. */ export interface RenderMetrics { /** * Time spent rendering in milliseconds. */ renderTime: number; } /** * Configuration options for the Tinky instance. */ export interface Options { /** * Output stream where the app will be rendered. */ stdout: WriteStream; /** * Input stream where the app will listen for input. */ stdin: ReadStream; /** * Error stream. */ stderr: WriteStream; /** * If true, each update will be rendered as separate output, without * replacing the previous one. */ debug: boolean; /** * Configure whether Tinky should listen for Ctrl+C keyboard input and exit. */ exitOnCtrlC: boolean; /** * Patch console methods to ensure console output doesn't mix with Tinky's. */ patchConsole: boolean; /** * Callback to run after each render and re-render. * * @param metrics - Performance metrics of the render. */ onRender?: (metrics: RenderMetrics) => void; /** * Enable screen reader support. */ isScreenReaderEnabled?: boolean; /** * Returns a promise that resolves when the app is unmounted. */ waitUntilExit?: () => Promise; /** * Maximum frames per second for render updates. * Controls how frequently UI can update to prevent excessive re-rendering. * Set to 0 or negative to disable throttling. */ maxFps?: number; /** * Configure incremental rendering mode. * * - `true`: Enables run-diff incremental rendering. * - `false` or omitted: Disables incremental rendering. * - `{ enabled: false }`: Disables incremental rendering. * - `{ strategy: "line" }`: Enables line-diff incremental rendering. * - `{ strategy: "run" }` (or omitted strategy): Enables run-diff rendering. */ incrementalRendering?: IncrementalRenderingOption; /** * Environment variables. */ env?: Record; } /** * Tinky core class responsible for managing the React tree rendering, * lifecycle, and terminal output. */ export declare class Tinky { /** Configuration options for this instance. */ private readonly options; /** Log update instance for output. */ private readonly log; /** Throttled log update instance for output. */ private readonly throttledLog; /** Whether screen reader support is enabled. */ private readonly isScreenReaderEnabled; /** Whether the app has been unmounted. */ private isUnmounted; /** Last output string that was rendered. */ private lastOutput; /** Height of the last output in lines. */ private lastOutputHeight; /** Width of the terminal at last render. */ private lastTerminalWidth; /** React reconciler container. */ private readonly container; /** Root DOM element for the React tree. */ private readonly rootNode; /** Full static output for debug mode. */ private fullStaticOutput; /** Raw entries from the last rendered frame. */ private lastRawEntries; /** Height of the last frame used to place raw output. */ private lastRawFrameHeight; /** Raw suffix from the last rendered frame. */ private lastRawSuffix; /** Promise that resolves when the app exits. */ private exitPromise?; /** Function to restore console after patching. */ private restoreConsole?; /** Function to unsubscribe from resize events. */ private readonly unsubscribeResize?; /** Whether we are running in a CI environment. */ private readonly isCI; /** Whether run-diff incremental rendering is active for this instance. */ private readonly usesRunIncrementalRendering; /** Run-diff log updater. */ private readonly cellLog?; /** Shared style registry for run buffers. */ private readonly styleRegistry?; /** Previous rendered frame for run-diff strategy. */ private frontBuffer?; /** Current frame render target for run-diff strategy. */ private backBuffer?; /** * Creates an instance of Tinky. * * @param options - Configuration options. */ constructor(options: Options); /** * Gets the terminal width. * * @returns The number of columns in the terminal, or 80 if undefined or 0. */ getTerminalWidth: () => number; /** * Handles terminal resize events. * Clears the screen when width decreases to prevent overlapping re-renders. */ resized: () => void; /** Resolves the exit promise when the app unmounts. */ resolveExitPromise: () => void; /** Rejects the exit promise with an error. */ rejectExitPromise: (reason?: Error) => void; /** Unsubscribes from the exit event. */ unsubscribeExit: () => void; /** Error that occurred during rendering, if any. */ renderError: Error | null; /** * Calculates the layout of the UI (TaffyLayout). */ calculateLayout: () => void; /** * Performs the render operation. * Handles string generation, static output, screen reader logic, and writing. */ onRender: () => void; /** * Swaps front and back buffers. After swap, the caller's newly-rendered * frame becomes the front buffer. The old front becomes the back buffer * and will be cleared by cellRenderer (resize + clear) at the start of * the next render cycle. */ private swapRunBuffers; private updateRawState; private clearRawState; private buildRawSuffix; private writeRawSuffix; private redrawRunBuffer; /** * Renders the given React node. * * @param node - The React node to render. */ render(node: ReactNode): void; /** * Writes data to stdout. * * @param data - The data to write. */ writeToStdout(data: string): void; /** * Writes data to stderr. * * @param data - The data to write. */ writeToStderr(data: string): void; /** * Unmounts the Tinky app. * * @param error - Optional error object or exit code. */ unmount(error?: Error | number | null): void; /** * Waits until the app exits. * * @returns A promise that resolves when the app exits. */ waitUntilExit(): Promise; /** * Clears the output. */ clear(): void; /** * Patches console methods to ensure they coexist correctly with Tinky output. */ patchConsole(): void; }