/**
 * Minimal TUI implementation with differential rendering
 */
import type { Terminal } from './terminal.js';
import { visibleWidth } from './utils.js';
/**
 * Component interface - all components must implement this
 */
export interface Component {
  /**
   * Render the component to lines for the given viewport width
   * @param width - Current viewport width
   * @returns Array of strings, each representing a line
   */
  render(width: number): string[];
  /**
   * Optional handler for keyboard input when component has focus
   */
  handleInput?(data: string): void;
  /**
   * If true, component receives key release events (Kitty protocol).
   * Default is false - release events are filtered out.
   */
  wantsKeyRelease?: boolean;
  /**
   * Invalidate any cached rendering state.
   * Called when theme changes or when component needs to re-render from scratch.
   */
  invalidate(): void;
}
type InputListenerResult =
  | {
      consume?: boolean;
      data?: string;
    }
  | undefined;
type InputListener = (data: string) => InputListenerResult;
/**
 * Interface for components that can receive focus and display a hardware cursor.
 * When focused, the component should emit CURSOR_MARKER at the cursor position
 * in its render output. TUI will find this marker and position the hardware
 * cursor there for proper IME candidate window positioning.
 */
export interface Focusable {
  /** Set by TUI when focus changes. Component should emit CURSOR_MARKER when true. */
  focused: boolean;
}
/** Type guard to check if a component implements Focusable */
export declare function isFocusable(
  component: Component | null
): component is Component & Focusable;
/**
 * Cursor position marker - APC (Application Program Command) sequence.
 * This is a zero-width escape sequence that terminals ignore.
 * Components emit this at the cursor position when focused.
 * TUI finds and strips this marker, then positions the hardware cursor there.
 */
export declare const CURSOR_MARKER = '\u001B_pi:c\u0007';
export { visibleWidth };
/**
 * Anchor position for overlays
 */
export type OverlayAnchor =
  | 'center'
  | 'top-left'
  | 'top-right'
  | 'bottom-left'
  | 'bottom-right'
  | 'top-center'
  | 'bottom-center'
  | 'left-center'
  | 'right-center';
/**
 * Margin configuration for overlays
 */
export interface OverlayMargin {
  top?: number;
  right?: number;
  bottom?: number;
  left?: number;
}
/** Value that can be absolute (number) or percentage (string like "50%") */
export type SizeValue = number | `${number}%`;
/**
 * Options for overlay positioning and sizing.
 * Values can be absolute numbers or percentage strings (e.g., "50%").
 */
export interface OverlayOptions {
  /** Width in columns, or percentage of terminal width (e.g., "50%") */
  width?: SizeValue;
  /** Minimum width in columns */
  minWidth?: number;
  /** Maximum height in rows, or percentage of terminal height (e.g., "50%") */
  maxHeight?: SizeValue;
  /** Anchor point for positioning (default: 'center') */
  anchor?: OverlayAnchor;
  /** Horizontal offset from anchor position (positive = right) */
  offsetX?: number;
  /** Vertical offset from anchor position (positive = down) */
  offsetY?: number;
  /** Row position: absolute number, or percentage (e.g., "25%" = 25% from top) */
  row?: SizeValue;
  /** Column position: absolute number, or percentage (e.g., "50%" = centered horizontally) */
  col?: SizeValue;
  /** Margin from terminal edges. Number applies to all sides. */
  margin?: OverlayMargin | number;
  /**
   * When true, treat the overlay region as opaque instead of letting
   * underlying content remain visible outside the rendered line lengths.
   * If maxHeight is set, the compositor pads the overlay to that height.
   */
  opaque?: boolean;
  /**
   * Control overlay visibility based on terminal dimensions.
   * If provided, overlay is only rendered when this returns true.
   * Called each render cycle with current terminal dimensions.
   */
  visible?: (termWidth: number, termHeight: number) => boolean;
}
/**
 * Handle returned by showOverlay for controlling the overlay
 */
export interface OverlayHandle {
  /** Permanently remove the overlay (cannot be shown again) */
  hide(): void;
  /** Temporarily hide or show the overlay */
  setHidden(hidden: boolean): void;
  /** Check if overlay is temporarily hidden */
  isHidden(): boolean;
}
/**
 * Container - a component that contains other components
 */
export declare class Container implements Component {
  children: Component[];
  addChild(component: Component): void;
  removeChild(component: Component): void;
  clear(): void;
  invalidate(): void;
  render(width: number): string[];
}
/**
 * ScrollContainer - clips a child component to a fixed-height viewport.
 */
export declare class ScrollContainer implements Component {
  private child;
  private viewportHeight;
  private scrollTop;
  private sticky;
  private contentHeight;
  constructor(child: Component);
  setViewportHeight(height: number): void;
  getViewportHeight(): number;
  getScrollTop(): number;
  getContentHeight(): number;
  isAtBottom(): boolean;
  scrollTo(scrollTop: number): void;
  scrollBy(delta: number): void;
  scrollPage(direction: number): void;
  scrollToBottom(): void;
  invalidate(): void;
  render(width: number): string[];
}
export interface RenderTraceSink {
  recordEvent(type: string, payload?: Record<string, unknown>): void;
  recordFrame(payload: Record<string, unknown>): void;
}
/**
 * TUI - Main class for managing terminal UI with differential rendering
 */
export declare class TUI extends Container {
  terminal: Terminal;
  private previousLines;
  private previousWidth;
  private focusedComponent;
  private inputListeners;
  /** Global callback for debug key (Shift+Ctrl+D). Called before input is forwarded to focused component. */
  onDebug?: () => void;
  private renderRequested;
  renderSuspended: boolean;
  private cursorRow;
  private hardwareCursorRow;
  private inputBuffer;
  private cellSizeQueryPending;
  private showHardwareCursor;
  private clearOnShrink;
  private maxLinesRendered;
  private previousViewportTop;
  private previousHeight;
  private fullRedrawCount;
  private stopped;
  private renderTrace;
  private renderSequence;
  private overlayStack;
  constructor(terminal: Terminal, showHardwareCursor?: boolean);
  get fullRedraws(): number;
  setRenderTrace(renderTrace: RenderTraceSink | undefined): void;
  private traceEvent;
  private traceFrame;
  private describeOverlaysForTrace;
  getShowHardwareCursor(): boolean;
  setShowHardwareCursor(enabled: boolean): void;
  getClearOnShrink(): boolean;
  /**
   * Set whether to trigger full re-render when content shrinks.
   * When true (default), empty rows are cleared when content shrinks.
   * When false, empty rows remain (reduces redraws on slower terminals).
   */
  setClearOnShrink(enabled: boolean): void;
  setFocus(component: Component | null): void;
  getFocusedComponent(): Component | null;
  /**
   * Show an overlay component with configurable positioning and sizing.
   * Returns a handle to control the overlay's visibility.
   */
  showOverlay(component: Component, options?: OverlayOptions): OverlayHandle;
  /** Hide the topmost overlay and restore previous focus. */
  hideOverlay(): void;
  /** Check if there are any visible overlays */
  hasOverlay(): boolean;
  /** Check if an overlay entry is currently visible */
  private isOverlayVisible;
  /** Find the topmost visible overlay, if any */
  private getTopmostVisibleOverlay;
  invalidate(): void;
  start(): void;
  addInputListener(listener: InputListener): () => void;
  removeInputListener(listener: InputListener): void;
  private queryCellSize;
  stop(): void;
  requestRender(force?: boolean): void;
  private handleInput;
  private parseCellSizeResponse;
  /**
   * Resolve overlay layout from options.
   * Returns { width, row, col, maxHeight } for rendering.
   */
  private resolveOverlayLayout;
  private resolveAnchorRow;
  private resolveAnchorCol;
  /** Composite all overlays into content lines (in stack order, later = on top). */
  private compositeOverlays;
  private static readonly SEGMENT_RESET;
  private applyLineResets;
  /** Splice overlay content into a base line at a specific column. Single-pass optimized. */
  private compositeLineAt;
  /**
   * Find and extract cursor position from rendered lines.
   * Searches for CURSOR_MARKER, calculates its position, and strips it from the output.
   * Only scans the bottom terminal height lines (visible viewport).
   * @param lines - Rendered lines to search
   * @param height - Terminal height (visible viewport size)
   * @returns Cursor position { row, col } or null if no marker found
   */
  private extractCursorPosition;
  private doRender;
  /**
   * Position the hardware cursor for IME candidate window.
   * @param cursorPos The cursor position extracted from rendered output, or null
   * @param totalLines Total number of rendered lines
   */
  private positionHardwareCursor;
}
//# sourceMappingURL=tui.d.ts.map
