/**
 * Text Buffer - Core text editing buffer with visual line wrapping
 */
import type { Key } from '../../hooks/useKeypress.js';
export type Direction = 'left' | 'right' | 'up' | 'down' | 'wordLeft' | 'wordRight' | 'home' | 'end';
export declare const findNextWordStartInLine: (line: string, col: number) => number | null;
export declare const findPrevWordStartInLine: (line: string, col: number) => number | null;
export declare const findWordEndInLine: (line: string, col: number) => number | null;
export declare const findNextWordAcrossLines: (lines: string[], cursorRow: number, cursorCol: number, searchForWordStart: boolean) => {
    row: number;
    col: number;
} | null;
export declare const findPrevWordAcrossLines: (lines: string[], cursorRow: number, cursorCol: number) => {
    row: number;
    col: number;
} | null;
export declare const getPositionFromOffsets: (startOffset: number, endOffset: number, lines: string[]) => {
    startRow: number;
    startCol: number;
    endRow: number;
    endCol: number;
};
export declare const getLineRangeOffsets: (startRow: number, lineCount: number, lines: string[]) => {
    startOffset: number;
    endOffset: number;
};
export declare const replaceRangeInternal: (state: TextBufferState, startRow: number, startCol: number, endRow: number, endCol: number, text: string) => TextBufferState;
export interface Viewport {
    height: number;
    width: number;
}
interface UseTextBufferProps {
    initialText?: string;
    initialCursorOffset?: number;
    viewport: Viewport;
    onChange?: (text: string) => void;
    inputFilter?: (text: string) => string;
    singleLine?: boolean;
}
interface UndoHistoryEntry {
    lines: string[];
    cursorRow: number;
    cursorCol: number;
}
export declare function offsetToLogicalPos(text: string, offset: number): [number, number];
/**
 * Converts logical row/col position to absolute text offset
 * Inverse operation of offsetToLogicalPos
 */
export declare function logicalPosToOffset(lines: string[], row: number, col: number): number;
export interface VisualLayout {
    visualLines: string[];
    logicalToVisualMap: Array<Array<[number, number]>>;
    visualToLogicalMap: Array<[number, number]>;
}
export interface TextBufferState {
    lines: string[];
    cursorRow: number;
    cursorCol: number;
    preferredCol: number | null;
    undoStack: UndoHistoryEntry[];
    redoStack: UndoHistoryEntry[];
    viewportWidth: number;
    viewportHeight: number;
    visualLayout: VisualLayout;
}
export declare const pushUndo: (currentState: TextBufferState) => TextBufferState;
export type TextBufferAction = {
    type: 'set_text';
    payload: string;
    pushToUndo?: boolean;
} | {
    type: 'insert';
    payload: string;
} | {
    type: 'backspace';
} | {
    type: 'move';
    payload: {
        dir: Direction;
    };
} | {
    type: 'set_cursor';
    payload: {
        cursorRow: number;
        cursorCol: number;
        preferredCol: number | null;
    };
} | {
    type: 'delete';
} | {
    type: 'delete_word_left';
} | {
    type: 'delete_word_right';
} | {
    type: 'kill_line_right';
} | {
    type: 'kill_line_left';
} | {
    type: 'undo';
} | {
    type: 'redo';
} | {
    type: 'replace_range';
    payload: {
        startRow: number;
        startCol: number;
        endRow: number;
        endCol: number;
        text: string;
    };
} | {
    type: 'move_to_offset';
    payload: {
        offset: number;
    };
} | {
    type: 'create_undo_snapshot';
} | {
    type: 'set_viewport';
    payload: {
        width: number;
        height: number;
    };
};
export interface TextBufferOptions {
    inputFilter?: ((text: string) => string) | undefined;
    singleLine?: boolean | undefined;
}
export declare function textBufferReducer(state: TextBufferState, action: TextBufferAction, options?: TextBufferOptions): TextBufferState;
export declare function useTextBuffer({ initialText, initialCursorOffset, viewport, onChange, inputFilter, singleLine, }: UseTextBufferProps): TextBuffer;
export interface TextBuffer {
    lines: string[];
    text: string;
    cursor: [number, number];
    /**
     * When the user moves the caret vertically we try to keep their original
     * horizontal column even when passing through shorter lines. We remember
     * that *preferred* column in this field while the user is still travelling
     * vertically. Any explicit horizontal movement resets the preference.
     */
    preferredCol: number | null;
    allVisualLines: string[];
    viewportVisualLines: string[];
    visualCursor: [number, number];
    visualScrollRow: number;
    /**
     * For each visual line (by absolute index in allVisualLines) provides a tuple
     * [logicalLineIndex, startColInLogical] that maps where that visual line
     * begins within the logical buffer. Indices are code-point based.
     */
    visualToLogicalMap: Array<[number, number]>;
    /** Replaces the entire buffer content with the provided text. Undoable. */
    setText: (text: string) => void;
    /** Insert a single character or string. */
    insert: (ch: string, opts?: {
        paste?: boolean;
    }) => void;
    newline: () => void;
    backspace: () => void;
    del: () => void;
    move: (dir: Direction) => void;
    undo: () => void;
    redo: () => void;
    /** Replaces the text within the specified range with new text. */
    replaceRange: (startRow: number, startCol: number, endRow: number, endCol: number, text: string) => void;
    /** Delete the word to the left of the caret. */
    deleteWordLeft: () => void;
    /** Delete the word to the right of the caret. */
    deleteWordRight: () => void;
    /** Deletes text from the cursor to the end of the current line. */
    killLineRight: () => void;
    /** Deletes text from the start of the current line to the cursor. */
    killLineLeft: () => void;
    /** High level "handleInput" – receives what Ink gives us. */
    handleInput: (key: Key) => void;
    replaceRangeByOffset: (startOffset: number, endOffset: number, replacementText: string) => void;
    getOffset: () => number;
    moveToOffset(offset: number): void;
    moveToVisualPosition(visualRow: number, visualCol: number): void;
    /** Update the viewport dimensions. */
    setViewport: (width: number, height: number) => void;
}
export {};
//# sourceMappingURL=text-buffer.d.ts.map