/** * Pane-scoped selection owner (V2-060..064). * * Owns semantic anchors, drag state, keyboard extension, and explicit copy * (Ctrl+Shift+C). Auto-copy-on-release is off by default — OpenTUI native * selection must not be fought by delayed clipboard side-effects. */ import type { ClipboardPort } from "../../app/ports/clipboard-port.js"; import type { ActionId } from "../actions/action-id.js"; import { type SemanticAnchor, type SemanticDocument, type SemanticMovement, type SemanticRange } from "../state/semantic-document.js"; export type SelectionPane = "transcript" | "plan"; export type SelectionGranularity = "character" | "word" | "line"; export interface PointerPosition { readonly x: number; readonly y: number; } /** Native scroll primitives are injected to keep this controller renderer-independent. */ export interface DragEdgeScrollPort { startAutoScroll(x: number, y: number): void; updateAutoScroll(x: number, y: number): void; stopAutoScroll(): void; } export interface PaneSelectionRange extends SemanticRange { readonly pane: SelectionPane; } export interface SelectionState { readonly activePane: SelectionPane | undefined; readonly range: PaneSelectionRange | undefined; readonly dragging: boolean; readonly autoscrollPane: SelectionPane | undefined; } export type SelectionCopyResult = { readonly status: "copied"; readonly text: string; } | { readonly status: "empty"; } | { readonly status: "failed"; readonly error: unknown; }; export type SelectionListener = () => void; export interface SelectionControllerOptions { /** Auto-copy on mouse release. Default false (disabled — was breaking touch/TUI). */ readonly copyOnRelease?: boolean | undefined; } export declare class SelectionController { private readonly clipboard; private readonly documents; private readonly scrollPorts; private readonly listeners; private readonly copyOnRelease; private state; constructor(clipboard: ClipboardPort, options?: SelectionControllerOptions); getState(): SelectionState; subscribe(listener: SelectionListener): () => void; setDocument(pane: SelectionPane, document: SemanticDocument): void; registerScrollPort(pane: SelectionPane, port: DragEdgeScrollPort): () => void; beginDrag(pane: SelectionPane, requested: SemanticAnchor, pointer?: PointerPosition): boolean; dragTo(pane: SelectionPane, requested: SemanticAnchor, pointer?: PointerPosition): boolean; finishDrag(): void; click(pane: SelectionPane, requested: SemanticAnchor, granularity?: SelectionGranularity): boolean; extend(pane: SelectionPane, movement: SemanticMovement): boolean; selectAll(pane: SelectionPane): boolean; clear(): void; selectedText(): string; hasSelection(): boolean; copy(): Promise; handleAction(action: ActionId, pane: SelectionPane): boolean; dispose(): void; private maybeAutoCopy; private clamp; private startAutoscroll; private updateAutoscroll; private stopAutoscroll; private setState; }