export interface Position {
  position: number;
  extent: number;
  content: string;
  line: number;
  /**
   * Set only when this position originates from an undo/redo navigation, naming
   * the direction. On `'undo'` the caret is the PRE-edit position (it did not
   * move as forward typing would), so derived state (e.g. the comment/highlight
   * map) must reverse the edit rather than assume a post-edit caret. Absent for
   * a fresh edit.
   */
  history?: 'undo' | 'redo';
  /**
   * On an `'undo'`, the 0-indexed line the reversed edit was anchored at — its
   * POST-edit caret line, which can differ from this (destination) caret when
   * the edit ran over a selection that didn't start at the caret (e.g. Select
   * All). Lets derived state reverse the edit at the exact line the forward
   * edit pivoted on instead of guessing from the destination caret.
   */
  historyPivotLine?: number;
  /**
   * Set when the edit removed whole lines starting at the very beginning of a
   * line (a selection delete whose start was at column 0). The post-edit caret
   * then sits on the line that shifted up from BELOW the deletion, so the edit's
   * anchor is one line higher than the caret implies. Derived state (comment
   * map) must drop its anchor by one or markers on the deleted first line are
   * stranded. Rides through undo as well so the reversal anchors identically.
   */
  deletedFromLineStart?: boolean;
  /**
   * Set when the tracked selection is a BACKWARD range — its focus (the moving
   * end) sits at the range START, above/before the anchor. `position`/`extent`
   * only describe the range's extent, not which end is the focus, so a backward
   * Shift+Arrow selection that survives a host re-render would otherwise be
   * rebuilt as a forward range (focus flipped to the bottom), making the next
   * Shift+Arrow extend from the wrong end. The restore honors this flag by
   * collapsing to the anchor then extending back to the focus. Absent for a
   * collapsed caret or a forward selection.
   */
  backward?: boolean;
}
export declare const getCurrentRange: () => Range;
export declare const setCurrentRange: (range: Range) => void;
/**
 * Narrow a `Node | null` to `Element | null` using a runtime check so
 * downstream code can reason about element-only APIs without a cast.
 */
export declare const asElement: (node: Node | null | undefined) => Element | null;
/**
 * Pull the next element out of a `SHOW_ELEMENT` `TreeWalker` with a
 * runtime check rather than a type cast. Tree walkers configured for
 * `SHOW_ELEMENT` only emit elements in practice, but the DOM type
 * exposes `Node | null`.
 */
export declare const nextElement: (walker: TreeWalker) => Element | null;
export declare const isUndoRedoKey: (event: KeyboardEvent) => boolean;
export declare const isPlaintextInputKey: (event: KeyboardEvent) => boolean;
export declare const toString: (element: HTMLElement) => string;
export interface LineInfo {
  /** Full text of the requested line. */
  currentLine: string;
  /** Full text of `lineIndex - 1`. Empty when `lineIndex <= 0`. */
  prevLine: string;
  /** Full text of `lineIndex + 1`. Empty when there is no next line. */
  nextLine: string;
  /**
   * True when a real line follows `currentLine` — including a blank
   * line. False when the document ends at `currentLine` (matching the
   * old `toString(element).split('\n').slice(0, -1)` semantics where
   * the phantom empty entry after the trailing `\n` does not count as
   * a next line).
   */
  hasNextLine: boolean;
}
/**
 * Walk text nodes to extract the requested line plus its immediate
 * neighbors without materializing the full document text or splitting
 * it into a per-line array. Used by per-keystroke handlers (arrow keys,
 * Backspace, gutter snapping) so they stay O(chars-on-touched-lines)
 * instead of O(document-length) on every event.
 *
 * Walks each text node in document order and slices contiguous segments
 * directly into the relevant accumulator (`prevLine` / `currentLine` /
 * `nextLine`). Skips chunks belonging to lines we don't care about and
 * exits as soon as the trailing `\n` of `lineIndex + 1` is consumed.
 *
 * Mirrors `toString(element).split('\n').slice(0, -1)` semantics:
 *
 * - `hasNextLine` is `true` whenever a real line follows `currentLine`,
 *   even if that line is blank — `"a\n\nb\n"` reports a next line for
 *   row 0. The phantom empty entry that `split` produces after the
 *   document's trailing `\n` is intentionally ignored.
 * - The implicit trailing newline that `toString` appends when the DOM
 *   doesn't end with one has no effect: we walk raw text content.
 */
export declare const getLineInfo: (element: HTMLElement, lineIndex: number) => LineInfo;
/**
 * Convert a `(row, column)` coordinate into an absolute character offset
 * by counting newlines through the editable's text nodes, exiting the
 * moment we land on the requested row. Avoids the
 * `toString(element).split('\n').slice(0, row).join('\n').length`
 * round-trip — that pattern allocates the full document string and a
 * full per-line array on every `edit.move({row, column})` call.
 *
 * If the row is past the end of the document, returns the document
 * length plus `column` so the eventual `makeRange` clamps gracefully.
 */
export declare const getOffsetAtLineColumn: (element: HTMLElement, row: number, column: number) => number;
export declare const repairUnexpectedLineMerge: (newContent: string, previousContent: string | null, position: Position) => string;
export declare const getPosition: (element: HTMLElement) => Position;
export declare const makeRange: (element: HTMLElement, start: number, end?: number) => Range;
/**
 * After makeRange positions a collapsed cursor at a newline boundary via
 * setStartAfter(textNode), the cursor ends up inside the *previous* line span
 * (after the '\n').  This adjusts the range forward to offset 0 of the
 * next text node so the cursor renders on the correct visual line.
 */
export declare const adjustCursorAtNewlineBoundary: (range: Range) => void;
/**
 * Rebuild the browser selection from a tracked {@link Position} after a host
 * re-render. Recreates the `[position, position + extent]` range (collapsed when
 * `extent` is 0) and applies the newline-boundary nudge.
 *
 * When `position.backward` is set, the range is restored as a BACKWARD selection
 * — anchor at the range end, focus at the range start — by collapsing to the end
 * and extending back to the start. A range added via `Selection.addRange` is
 * always forward, so without this a backward Shift+Arrow selection would have its
 * focus flipped to the bottom end on every restore. Forward and collapsed
 * positions take the plain `addRange` path unchanged.
 */
export declare const restoreSelection: (element: HTMLElement, position: Position) => void;