import type { ReactNode } from 'react'; export type TerminalUiAttachment = Readonly<{ id: string; baseUrl: string; mode: 'observe' | 'control'; /** Opaque catalog id; never a tmux target or socket handle. */ sessionId?: string; }>; export type TerminalUiSession = Readonly<{ id: string; label: string; cwd: string | null; activeCommand: string | null; owned: boolean; size?: Readonly<{ columns: number; rows: number }> | null; }>; export type TerminalUiState = Readonly<{ available: boolean; canOpenLocal: boolean; error: string | null; sessions: readonly TerminalUiSession[]; attachment: TerminalUiAttachment | null; }>; export function normalizeTerminalUiState(value: unknown): TerminalUiState; export function terminalWorkspaceShortcut(event: Readonly<{ altKey: boolean; shiftKey: boolean; ctrlKey: boolean; metaKey: boolean; code: string; }>): Readonly< | { action: 'new' | 'detach' | 'previous' | 'next' } | { action: 'tab'; index: number } > | null; export type TerminalCreateAction = Readonly<{ id: string; label: string; icon?: ReactNode }>; export type TerminalPanelLabels = Readonly<{ title?: string; subtitle?: string; refresh?: string; view?: string; control?: string; stop?: string; open?: string; back?: string; empty?: string; /** What a session with no observed cwd or command is; `tmux session` by default. */ session?: string; }>; export type TerminalPanelProps = Readonly<{ state: TerminalUiState; createActions?: readonly TerminalCreateAction[]; labels?: TerminalPanelLabels; className?: string; renderViewer?(attachment: TerminalUiAttachment): ReactNode; onClose(): void; onRefresh(): void | Promise; onCreate?(actionId: string): void | Promise; onAttach(sessionId: string, mode: 'observe' | 'control'): void | Promise; onStop(sessionId: string): void | Promise; onOpen?(sessionId: string): void | Promise; onDismiss(): void | Promise; }>; export function terminalPath(value: string): Readonly<{ leading: string; separator: string; trailing: string; }>; export function TerminalPath(props: Readonly<{ value: string }>): ReactNode; export function TerminalViewer(props: Readonly<{ active?: boolean; connect?: TerminalConnector; /** Convert bare LF output to CRLF for streams without PTY line discipline. */ convertEol?: boolean; onReady?(handle: { focus(): void }): void; attachment: TerminalUiAttachment; onActivity?(): void; onBell?(): void; onOpenLink?(url: string): void; onRetry?(): void; onStatus?(status: string): void; onTitle?(title: string): void; }>): ReactNode; export function TerminalPanel(props: TerminalPanelProps): ReactNode; export type TerminalWorkspaceLabels = TerminalPanelLabels & Readonly<{ attach?: string; closeTab?: string; newTerminal?: string; noTabs?: string; sessions?: string; terminal?: string; fitViewport?: string; scaleViewport?: string; }>; export type TerminalWorkspaceProps = Omit & Readonly<{ labels?: TerminalWorkspaceLabels; viewportMode?: 'scale' | 'fit'; onViewportModeChange?(mode: 'scale' | 'fit'): void | Promise; renderViewer?( attachment: TerminalUiAttachment, context: Readonly<{ active: boolean; onActivity(): void; onBell(): void; onStatus(status: string): void; onTitle(title: string): void; retry(): void; }>, ): ReactNode; }>; export function TerminalWorkspace(props: TerminalWorkspaceProps): ReactNode; /** Stream adapters own process lifetime. Closing a viewer only detaches its stream. */ export interface TerminalStreamHandlers { onOpen(): void; onOutput(data: string): void; onResize(cols: number, rows: number): void; onError(message: string): void; onExit(): void; onClose(): void; } export type TerminalConnector = ( attachment: TerminalUiAttachment, handlers: TerminalStreamHandlers, size: { cols: number; rows: number }, ) => { write(data: string): void; resize(cols: number, rows: number): void; close(): void };