@schovest/pi-tui 0.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/README.md +791 -0
  2. package/dist/autocomplete.d.ts +57 -0
  3. package/dist/autocomplete.d.ts.map +1 -0
  4. package/dist/autocomplete.js +646 -0
  5. package/dist/autocomplete.js.map +1 -0
  6. package/dist/components/box.d.ts +22 -0
  7. package/dist/components/box.d.ts.map +1 -0
  8. package/dist/components/box.js +104 -0
  9. package/dist/components/box.js.map +1 -0
  10. package/dist/components/cancellable-loader.d.ts +22 -0
  11. package/dist/components/cancellable-loader.d.ts.map +1 -0
  12. package/dist/components/cancellable-loader.js +35 -0
  13. package/dist/components/cancellable-loader.js.map +1 -0
  14. package/dist/components/editor.d.ts +254 -0
  15. package/dist/components/editor.d.ts.map +1 -0
  16. package/dist/components/editor.js +1916 -0
  17. package/dist/components/editor.js.map +1 -0
  18. package/dist/components/image.d.ts +28 -0
  19. package/dist/components/image.d.ts.map +1 -0
  20. package/dist/components/image.js +89 -0
  21. package/dist/components/image.js.map +1 -0
  22. package/dist/components/input.d.ts +37 -0
  23. package/dist/components/input.d.ts.map +1 -0
  24. package/dist/components/input.js +385 -0
  25. package/dist/components/input.js.map +1 -0
  26. package/dist/components/loader.d.ts +31 -0
  27. package/dist/components/loader.d.ts.map +1 -0
  28. package/dist/components/loader.js +69 -0
  29. package/dist/components/loader.js.map +1 -0
  30. package/dist/components/markdown.d.ts +96 -0
  31. package/dist/components/markdown.d.ts.map +1 -0
  32. package/dist/components/markdown.js +648 -0
  33. package/dist/components/markdown.js.map +1 -0
  34. package/dist/components/select-list.d.ts +50 -0
  35. package/dist/components/select-list.d.ts.map +1 -0
  36. package/dist/components/select-list.js +161 -0
  37. package/dist/components/select-list.js.map +1 -0
  38. package/dist/components/settings-list.d.ts +50 -0
  39. package/dist/components/settings-list.d.ts.map +1 -0
  40. package/dist/components/settings-list.js +186 -0
  41. package/dist/components/settings-list.js.map +1 -0
  42. package/dist/components/spacer.d.ts +12 -0
  43. package/dist/components/spacer.d.ts.map +1 -0
  44. package/dist/components/spacer.js +23 -0
  45. package/dist/components/spacer.js.map +1 -0
  46. package/dist/components/text.d.ts +19 -0
  47. package/dist/components/text.d.ts.map +1 -0
  48. package/dist/components/text.js +89 -0
  49. package/dist/components/text.js.map +1 -0
  50. package/dist/components/truncated-text.d.ts +13 -0
  51. package/dist/components/truncated-text.d.ts.map +1 -0
  52. package/dist/components/truncated-text.js +51 -0
  53. package/dist/components/truncated-text.js.map +1 -0
  54. package/dist/editor-component.d.ts +39 -0
  55. package/dist/editor-component.d.ts.map +1 -0
  56. package/dist/editor-component.js +2 -0
  57. package/dist/editor-component.js.map +1 -0
  58. package/dist/fuzzy.d.ts +16 -0
  59. package/dist/fuzzy.d.ts.map +1 -0
  60. package/dist/fuzzy.js +110 -0
  61. package/dist/fuzzy.js.map +1 -0
  62. package/dist/index.d.ts +23 -0
  63. package/dist/index.d.ts.map +1 -0
  64. package/dist/index.js +32 -0
  65. package/dist/index.js.map +1 -0
  66. package/dist/keybindings.d.ts +193 -0
  67. package/dist/keybindings.d.ts.map +1 -0
  68. package/dist/keybindings.js +174 -0
  69. package/dist/keybindings.js.map +1 -0
  70. package/dist/keys.d.ts +184 -0
  71. package/dist/keys.d.ts.map +1 -0
  72. package/dist/keys.js +1181 -0
  73. package/dist/keys.js.map +1 -0
  74. package/dist/kill-ring.d.ts +28 -0
  75. package/dist/kill-ring.d.ts.map +1 -0
  76. package/dist/kill-ring.js +44 -0
  77. package/dist/kill-ring.js.map +1 -0
  78. package/dist/native-modifiers.d.ts +3 -0
  79. package/dist/native-modifiers.d.ts.map +1 -0
  80. package/dist/native-modifiers.js +53 -0
  81. package/dist/native-modifiers.js.map +1 -0
  82. package/dist/stdin-buffer.d.ts +60 -0
  83. package/dist/stdin-buffer.d.ts.map +1 -0
  84. package/dist/stdin-buffer.js +406 -0
  85. package/dist/stdin-buffer.js.map +1 -0
  86. package/dist/terminal-image.d.ts +90 -0
  87. package/dist/terminal-image.d.ts.map +1 -0
  88. package/dist/terminal-image.js +366 -0
  89. package/dist/terminal-image.js.map +1 -0
  90. package/dist/terminal.d.ts +121 -0
  91. package/dist/terminal.d.ts.map +1 -0
  92. package/dist/terminal.js +464 -0
  93. package/dist/terminal.js.map +1 -0
  94. package/dist/tui.d.ts +347 -0
  95. package/dist/tui.d.ts.map +1 -0
  96. package/dist/tui.js +1608 -0
  97. package/dist/tui.js.map +1 -0
  98. package/dist/undo-stack.d.ts +17 -0
  99. package/dist/undo-stack.d.ts.map +1 -0
  100. package/dist/undo-stack.js +25 -0
  101. package/dist/undo-stack.js.map +1 -0
  102. package/dist/utils.d.ts +101 -0
  103. package/dist/utils.d.ts.map +1 -0
  104. package/dist/utils.js +1108 -0
  105. package/dist/utils.js.map +1 -0
  106. package/dist/word-navigation.d.ts +25 -0
  107. package/dist/word-navigation.d.ts.map +1 -0
  108. package/dist/word-navigation.js +96 -0
  109. package/dist/word-navigation.js.map +1 -0
  110. package/native/darwin/prebuilds/darwin-arm64/darwin-modifiers.node +0 -0
  111. package/native/darwin/prebuilds/darwin-x64/darwin-modifiers.node +0 -0
  112. package/native/win32/prebuilds/win32-arm64/win32-console-mode.node +0 -0
  113. package/native/win32/prebuilds/win32-x64/win32-console-mode.node +0 -0
  114. package/package.json +47 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tui.js","sourceRoot":"","sources":["../src/tui.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Minimal TUI implementation with differential rendering\n */\n\nimport { performance } from \"node:perf_hooks\";\nimport { isKeyRelease, matchesKey } from \"./keys.ts\";\nimport type { MouseEvent } from \"./stdin-buffer.ts\";\nimport type { Terminal } from \"./terminal.ts\";\nimport { deleteKittyImage, getCapabilities, isImageLine, setCellDimensions } from \"./terminal-image.ts\";\nimport {\n\textractSegments,\n\tnormalizeTerminalOutput,\n\tsliceByColumn,\n\tsliceWithWidth,\n\tsnapColToGraphemeBoundary,\n\tstripAnsi,\n\tvisibleWidth,\n} from \"./utils.ts\";\n\nconst KITTY_SEQUENCE_PREFIX = \"\\x1b_G\";\n\nfunction extractKittyImageIds(line: string): number[] {\n\tconst sequenceStart = line.indexOf(KITTY_SEQUENCE_PREFIX);\n\tif (sequenceStart === -1) return [];\n\n\tconst paramsStart = sequenceStart + KITTY_SEQUENCE_PREFIX.length;\n\tconst paramsEnd = line.indexOf(\";\", paramsStart);\n\tif (paramsEnd === -1) return [];\n\n\tconst params = line.slice(paramsStart, paramsEnd);\n\tfor (const param of params.split(\",\")) {\n\t\tconst [key, value] = param.split(\"=\", 2);\n\t\tif (key !== \"i\" || value === undefined) continue;\n\t\tconst id = Number(value);\n\t\tif (Number.isInteger(id) && id > 0 && id <= 0xffffffff) {\n\t\t\treturn [id];\n\t\t}\n\t}\n\treturn [];\n}\n\n/**\n * Component interface - all components must implement this\n */\nexport interface Component {\n\t/**\n\t * Render the component to lines for the given viewport width\n\t * @param width - Current viewport width\n\t * @returns Array of strings, each representing a line\n\t */\n\trender(width: number): string[];\n\n\t/**\n\t * Optional handler for keyboard input when component has focus.\n\t * Return true to indicate the input was consumed and should not be processed further.\n\t * Return void or false to allow TUI to handle the input as a fallback.\n\t */\n\t// biome-ignore lint/suspicious/noConfusingVoidType: void is intentional - implementations may return nothing or boolean\n\thandleInput?(data: string): boolean | void;\n\n\t/**\n\t * If true, component receives key release events (Kitty protocol).\n\t * Default is false - release events are filtered out.\n\t */\n\twantsKeyRelease?: boolean;\n\n\t/**\n\t * Invalidate any cached rendering state.\n\t * Called when theme changes or when component needs to re-render from scratch.\n\t */\n\tinvalidate(): void;\n}\n\ntype InputListenerResult = { consume?: boolean; data?: string } | undefined;\ntype InputListener = (data: string) => InputListenerResult;\n\n/**\n * Interface for components that can receive focus and display a hardware cursor.\n * When focused, the component should emit CURSOR_MARKER at the cursor position\n * in its render output. TUI will find this marker and position the hardware\n * cursor there for proper IME candidate window positioning.\n */\nexport interface Focusable {\n\t/** Set by TUI when focus changes. Component should emit CURSOR_MARKER when true. */\n\tfocused: boolean;\n}\n\n/** Type guard to check if a component implements Focusable */\nexport function isFocusable(component: Component | null): component is Component & Focusable {\n\treturn component !== null && \"focused\" in component;\n}\n\n/**\n * Cursor position marker - APC (Application Program Command) sequence.\n * This is a zero-width escape sequence that terminals ignore.\n * Components emit this at the cursor position when focused.\n * TUI finds and strips this marker, then positions the hardware cursor there.\n */\nexport const CURSOR_MARKER = \"\\x1b_pi:c\\x07\";\n\nexport { visibleWidth };\n\nexport interface SelectionState {\n\tactive: boolean;\n\tanchorRow: number;\n\tanchorCol: number;\n\tfocusRow: number;\n\tfocusCol: number;\n}\n\nconst AUTO_SCROLL_INTERVAL_MS = 100;\nconst AUTO_SCROLL_ROWS = 3;\n\n/**\n * Anchor position for overlays\n */\nexport type OverlayAnchor =\n\t| \"center\"\n\t| \"top-left\"\n\t| \"top-right\"\n\t| \"bottom-left\"\n\t| \"bottom-right\"\n\t| \"top-center\"\n\t| \"bottom-center\"\n\t| \"left-center\"\n\t| \"right-center\";\n\n/**\n * Margin configuration for overlays\n */\nexport interface OverlayMargin {\n\ttop?: number;\n\tright?: number;\n\tbottom?: number;\n\tleft?: number;\n}\n\n/** Value that can be absolute (number) or percentage (string like \"50%\") */\nexport type SizeValue = number | `${number}%`;\n\n/** Parse a SizeValue into absolute value given a reference size */\nfunction parseSizeValue(value: SizeValue | undefined, referenceSize: number): number | undefined {\n\tif (value === undefined) return undefined;\n\tif (typeof value === \"number\") return value;\n\t// Parse percentage string like \"50%\"\n\tconst match = value.match(/^(\\d+(?:\\.\\d+)?)%$/);\n\tif (match) {\n\t\treturn Math.floor((referenceSize * parseFloat(match[1])) / 100);\n\t}\n\treturn undefined;\n}\n\nfunction isTermuxSession(): boolean {\n\treturn Boolean(process.env.TERMUX_VERSION);\n}\n\n/**\n * Options for overlay positioning and sizing.\n * Values can be absolute numbers or percentage strings (e.g., \"50%\").\n */\nexport interface OverlayOptions {\n\t// === Sizing ===\n\t/** Width in columns, or percentage of terminal width (e.g., \"50%\") */\n\twidth?: SizeValue;\n\t/** Minimum width in columns */\n\tminWidth?: number;\n\t/** Maximum height in rows, or percentage of terminal height (e.g., \"50%\") */\n\tmaxHeight?: SizeValue;\n\n\t// === Positioning - anchor-based ===\n\t/** Anchor point for positioning (default: 'center') */\n\tanchor?: OverlayAnchor;\n\t/** Horizontal offset from anchor position (positive = right) */\n\toffsetX?: number;\n\t/** Vertical offset from anchor position (positive = down) */\n\toffsetY?: number;\n\n\t// === Positioning - percentage or absolute ===\n\t/** Row position: absolute number, or percentage (e.g., \"25%\" = 25% from top) */\n\trow?: SizeValue;\n\t/** Column position: absolute number, or percentage (e.g., \"50%\" = centered horizontally) */\n\tcol?: SizeValue;\n\n\t// === Margin from terminal edges ===\n\t/** Margin from terminal edges. Number applies to all sides. */\n\tmargin?: OverlayMargin | number;\n\n\t// === Visibility ===\n\t/**\n\t * Control overlay visibility based on terminal dimensions.\n\t * If provided, overlay is only rendered when this returns true.\n\t * Called each render cycle with current terminal dimensions.\n\t */\n\tvisible?: (termWidth: number, termHeight: number) => boolean;\n\t/** If true, don't capture keyboard focus when shown */\n\tnonCapturing?: boolean;\n\t/** ANSI background sequence to fill behind overlay lines (e.g., \"\\x1b[48;5;235m\") */\n\tbackground?: string;\n\t/**\n\t * Restrict text selection (copy/highlight) to a specific column region within the overlay.\n\t * Called per screen row during selection extraction and highlight rendering.\n\t * Returns `{ col, width }` for the selectable region, or null to allow the full row.\n\t * This is used by overlays with internal column splits (e.g., left list + right detail)\n\t * to prevent the non-detail sidebar from being included in copy/highlight operations.\n\t */\n\tselectionClip?: (screenRow: number) => { col: number; width: number } | null;\n}\n\n/** Options for {@link OverlayHandle.unfocus}. */\nexport interface OverlayUnfocusOptions {\n\t/** Explicit target to focus after releasing this overlay. */\n\ttarget: Component | null;\n}\n\n/**\n * Handle returned by showOverlay for controlling the overlay\n */\nexport interface OverlayHandle {\n\t/** Permanently remove the overlay (cannot be shown again) */\n\thide(): void;\n\t/** Temporarily hide or show the overlay */\n\tsetHidden(hidden: boolean): void;\n\t/** Check if overlay is temporarily hidden */\n\tisHidden(): boolean;\n\t/** Focus this overlay and bring it to the visual front */\n\tfocus(): void;\n\t/** Release focus to the next visible capturing overlay or previous target, or to an explicit target when provided */\n\tunfocus(options?: OverlayUnfocusOptions): void;\n\t/** Check if this overlay currently has focus */\n\tisFocused(): boolean;\n}\n\ntype OverlayStackEntry = {\n\tcomponent: Component;\n\toptions?: OverlayOptions;\n\tpreFocus: Component | null;\n\thidden: boolean;\n\tfocusOrder: number;\n};\n\ntype OverlayBlockedFocusResume = { status: \"restore-overlay\" } | { status: \"focus-target\"; target: Component | null };\ntype EligibleOverlayFocusRestoreState = { status: \"eligible\"; overlay: OverlayStackEntry };\ntype BlockedOverlayFocusRestoreState = {\n\tstatus: \"blocked\";\n\toverlay: OverlayStackEntry;\n\tblockedBy: Component;\n\tresume: OverlayBlockedFocusResume;\n};\ntype ActiveOverlayFocusRestoreState = EligibleOverlayFocusRestoreState | BlockedOverlayFocusRestoreState;\ntype OverlayFocusRestoreState = { status: \"inactive\" } | ActiveOverlayFocusRestoreState;\ntype OverlayFocusRestorePolicy = \"clear\" | \"preserve\";\n\n/**\n * Container - a component that contains other components\n */\nexport class Container implements Component {\n\tchildren: Component[] = [];\n\n\taddChild(component: Component): void {\n\t\tthis.children.push(component);\n\t}\n\n\tremoveChild(component: Component): void {\n\t\tconst index = this.children.indexOf(component);\n\t\tif (index !== -1) {\n\t\t\tthis.children.splice(index, 1);\n\t\t}\n\t}\n\n\tclear(): void {\n\t\tthis.children = [];\n\t}\n\n\tinvalidate(): void {\n\t\tfor (const child of this.children) {\n\t\t\tchild.invalidate?.();\n\t\t}\n\t}\n\n\trender(width: number): string[] {\n\t\tconst lines: string[] = [];\n\t\tfor (const child of this.children) {\n\t\t\tconst childLines = child.render(width);\n\t\t\tfor (const line of childLines) {\n\t\t\t\tlines.push(line);\n\t\t\t}\n\t\t}\n\t\treturn lines;\n\t}\n}\n\n/**\n * TUI - Main class for managing terminal UI with differential rendering\n */\nexport class TUI extends Container {\n\tpublic terminal: Terminal;\n\tprivate previousLines: string[] = [];\n\tprivate previousKittyImageIds = new Set<number>();\n\tprivate previousWidth = 0;\n\tprivate previousHeight = 0;\n\tprivate focusedComponent: Component | null = null;\n\tprivate inputListeners = new Set<InputListener>();\n\n\t/** Global callback for debug key (Shift+Ctrl+D). Called before input is forwarded to focused component. */\n\tpublic onDebug?: () => void;\n\tprivate renderRequested = false;\n\tprivate renderTimer: NodeJS.Timeout | undefined;\n\tprivate lastRenderAt = 0;\n\tprivate static readonly MIN_RENDER_INTERVAL_MS = 16;\n\t// biome-ignore lint/correctness/noUnusedPrivateClassMembers: used in render and cursor positioning\n\tprivate cursorRow = 0; // Logical cursor row (end of rendered content)\n\tprivate hardwareCursorRow = 0; // Actual terminal cursor row (may differ due to IME positioning)\n\tprivate showHardwareCursor = process.env.PI_HARDWARE_CURSOR !== \"0\";\n\tprivate clearOnShrink = process.env.PI_CLEAR_ON_SHRINK === \"1\"; // Clear empty rows when content shrinks (default: off)\n\tprivate maxLinesRendered = 0; // Track terminal's working area (max lines ever rendered)\n\tprivate previousViewportTop = 0; // Track previous viewport top for resize-aware cursor moves\n\tprivate fullRedrawCount = 0;\n\tprivate stopped = false;\n\tprivate fixedBottomCount = 0;\n\t// Scrollable viewport top in the full-lines buffer; used for mouse coordinate mapping\n\tprivate currentScrollableViewportTop = 0;\n\t// Full-lines buffer (pre-overlay, pre-highlight) cached each render for selection\n\t// coordinate mapping and text extraction. Equals [...scrollableLines, ...fixedLines].\n\tprivate currentFullLines: string[] = [];\n\t// Overlay-composited lines (post-overlay, pre-highlight) cached each render for text extraction and grapheme snapping when an overlay covers a row\n\tprivate currentCompositedLines: string[] = [];\n\tprivate currentScrollableLinesLength: number = 0;\n\tprivate autoScrollDirection: -1 | 1 = -1;\n\tprivate selection: SelectionState | null = null;\n\tprivate scrollOffset = 0;\n\tprivate autoFollow = true;\n\tprivate previousScrollableLineCount = 0;\n\tprivate lastScrollableViewport = 0;\n\tprivate autoScrollTimer: ReturnType<typeof setInterval> | null = null;\n\tprivate mouseListenerRemover?: () => void;\n\t// Cached overlay layouts from the most recent render, used for selection clip\n\tprivate renderedOverlayLayouts: {\n\t\trow: number;\n\t\tcol: number;\n\t\twidth: number;\n\t\theight: number;\n\t\tselectionClip?: (screenRow: number) => { col: number; width: number } | null;\n\t}[] = [];\n\t// Scroll event debouncing: aggregate consecutive wheel events\n\tprivate pendingScrollDelta = 0;\n\tprivate scrollDebounceTimer: ReturnType<typeof setTimeout> | null = null;\n\tprivate static readonly SCROLL_DEBOUNCE_MS = 8;\n\t// Timestamp of the last mouse wheel event, used to suppress spurious\n\t// arrow-key sequences that some terminals emit alongside scroll events.\n\tprivate lastMouseWheelTime = 0;\n\tprivate static readonly MOUSE_WHEEL_SUPPRESS_MS = 50;\n\tonCopySelection?: (text: string) => void;\n\tonScrollOffsetChange?: (offset: number) => void;\n\n\t// Overlay stack for modal components rendered on top of base content\n\tprivate focusOrderCounter = 0;\n\tprivate overlayStack: OverlayStackEntry[] = [];\n\tprivate overlayFocusRestore: OverlayFocusRestoreState = { status: \"inactive\" };\n\n\tconstructor(terminal: Terminal, showHardwareCursor?: boolean) {\n\t\tsuper();\n\t\tthis.terminal = terminal;\n\t\tif (showHardwareCursor !== undefined) {\n\t\t\tthis.showHardwareCursor = showHardwareCursor;\n\t\t}\n\t}\n\n\tget fullRedraws(): number {\n\t\treturn this.fullRedrawCount;\n\t}\n\n\tgetShowHardwareCursor(): boolean {\n\t\treturn this.showHardwareCursor;\n\t}\n\n\tsetShowHardwareCursor(enabled: boolean): void {\n\t\tif (this.showHardwareCursor === enabled) return;\n\t\tthis.showHardwareCursor = enabled;\n\t\tif (enabled) {\n\t\t\t// Set steady bar cursor shape when enabling hardware cursor\n\t\t\tthis.terminal.write(\"\\x1b[6 q\");\n\t\t} else {\n\t\t\tthis.terminal.hideCursor();\n\t\t}\n\t\tthis.requestRender();\n\t}\n\n\tgetClearOnShrink(): boolean {\n\t\treturn this.clearOnShrink;\n\t}\n\n\t/**\n\t * Set whether to trigger full re-render when content shrinks.\n\t * When true (default), empty rows are cleared when content shrinks.\n\t * When false, empty rows remain (reduces redraws on slower terminals).\n\t */\n\tsetClearOnShrink(enabled: boolean): void {\n\t\tthis.clearOnShrink = enabled;\n\t}\n\n\tsetFocus(component: Component | null): void {\n\t\tthis.setFocusInternal({ component, overlayFocusRestore: \"clear\" });\n\t}\n\n\tprivate setFocusInternal({\n\t\tcomponent,\n\t\toverlayFocusRestore,\n\t}: {\n\t\tcomponent: Component | null;\n\t\toverlayFocusRestore: OverlayFocusRestorePolicy;\n\t}): void {\n\t\tconst previousFocus = this.focusedComponent;\n\t\tlet nextFocus = component;\n\t\tconst previousFocusedOverlay = previousFocus\n\t\t\t? this.overlayStack.find((entry) => entry.component === previousFocus && this.isOverlayVisible(entry))\n\t\t\t: undefined;\n\t\tconst nextFocusIsOverlay = nextFocus ? this.overlayStack.some((entry) => entry.component === nextFocus) : false;\n\t\tconst restoreState = this.getVisibleOverlayFocusRestore();\n\t\tif (nextFocus && !nextFocusIsOverlay) {\n\t\t\tif (restoreState.status === \"blocked\" && restoreState.blockedBy === previousFocus) {\n\t\t\t\tif (restoreState.resume.status === \"focus-target\" || !this.isComponentMounted(restoreState.blockedBy)) {\n\t\t\t\t\tnextFocus = this.resolveBlockedOverlayFocusResume(restoreState);\n\t\t\t\t} else {\n\t\t\t\t\tthis.overlayFocusRestore = {\n\t\t\t\t\t\tstatus: \"blocked\",\n\t\t\t\t\t\toverlay: restoreState.overlay,\n\t\t\t\t\t\tblockedBy: nextFocus,\n\t\t\t\t\t\tresume: restoreState.resume,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t} else if (\n\t\t\t\tpreviousFocusedOverlay &&\n\t\t\t\trestoreState.status !== \"inactive\" &&\n\t\t\t\trestoreState.overlay === previousFocusedOverlay &&\n\t\t\t\t!this.isOverlayFocusAncestor(previousFocusedOverlay, nextFocus)\n\t\t\t) {\n\t\t\t\tthis.overlayFocusRestore = {\n\t\t\t\t\tstatus: \"blocked\",\n\t\t\t\t\toverlay: previousFocusedOverlay,\n\t\t\t\t\tblockedBy: nextFocus,\n\t\t\t\t\tresume: { status: \"restore-overlay\" },\n\t\t\t\t};\n\t\t\t}\n\t\t} else if (nextFocus === null) {\n\t\t\tif (restoreState.status === \"blocked\" && restoreState.blockedBy === previousFocus) {\n\t\t\t\tnextFocus = this.resolveBlockedOverlayFocusResume(restoreState);\n\t\t\t} else if (overlayFocusRestore === \"clear\") {\n\t\t\t\tthis.clearOverlayFocusRestore();\n\t\t\t}\n\t\t}\n\n\t\tif (isFocusable(this.focusedComponent)) {\n\t\t\tthis.focusedComponent.focused = false;\n\t\t}\n\n\t\tthis.focusedComponent = nextFocus;\n\n\t\tif (isFocusable(nextFocus)) {\n\t\t\tnextFocus.focused = true;\n\t\t}\n\n\t\tconst focusedOverlay = nextFocus\n\t\t\t? this.overlayStack.find((entry) => entry.component === nextFocus && this.isOverlayVisible(entry))\n\t\t\t: undefined;\n\t\tif (focusedOverlay) {\n\t\t\tthis.overlayFocusRestore = { status: \"eligible\", overlay: focusedOverlay };\n\t\t}\n\t}\n\n\tprivate clearOverlayFocusRestore(): void {\n\t\tthis.overlayFocusRestore = { status: \"inactive\" };\n\t}\n\n\tprivate clearOverlayFocusRestoreFor(overlay: OverlayStackEntry): void {\n\t\tif (this.overlayFocusRestore.status !== \"inactive\" && this.overlayFocusRestore.overlay === overlay) {\n\t\t\tthis.clearOverlayFocusRestore();\n\t\t}\n\t}\n\n\tprivate resolveBlockedOverlayFocusResume(restoreState: BlockedOverlayFocusRestoreState): Component | null {\n\t\tif (restoreState.resume.status === \"restore-overlay\") return restoreState.overlay.component;\n\t\tthis.clearOverlayFocusRestore();\n\t\treturn restoreState.resume.target;\n\t}\n\n\tprivate getVisibleOverlayFocusRestore(): OverlayFocusRestoreState {\n\t\tconst restoreState = this.overlayFocusRestore;\n\t\tif (restoreState.status === \"inactive\") return restoreState;\n\t\tif (!this.overlayStack.includes(restoreState.overlay) || !this.isOverlayVisible(restoreState.overlay)) {\n\t\t\treturn { status: \"inactive\" };\n\t\t}\n\t\treturn restoreState;\n\t}\n\n\tprivate isOverlayFocusAncestor(entry: OverlayStackEntry, component: Component): boolean {\n\t\tconst visited = new Set<Component>();\n\t\tlet current = entry.preFocus;\n\t\twhile (current && !visited.has(current)) {\n\t\t\tvisited.add(current);\n\t\t\tif (current === component) return true;\n\t\t\tcurrent = this.overlayStack.find((overlay) => overlay.component === current)?.preFocus ?? null;\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate retargetOverlayPreFocus(removed: OverlayStackEntry): void {\n\t\tfor (const overlay of this.overlayStack) {\n\t\t\tif (overlay !== removed && overlay.preFocus === removed.component) {\n\t\t\t\toverlay.preFocus = removed.preFocus;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate isComponentMounted(component: Component): boolean {\n\t\treturn this.children.some((child) => this.containsComponent(child, component));\n\t}\n\n\tprivate containsComponent(root: Component, target: Component): boolean {\n\t\tif (root === target) return true;\n\t\tif (!(root instanceof Container)) return false;\n\t\treturn root.children.some((child) => this.containsComponent(child, target));\n\t}\n\n\t/**\n\t * Show an overlay component with configurable positioning and sizing.\n\t * Returns a handle to control the overlay's visibility.\n\t */\n\tshowOverlay(component: Component, options?: OverlayOptions): OverlayHandle {\n\t\tconst entry: OverlayStackEntry = {\n\t\t\tcomponent,\n\t\t\t...(options === undefined ? {} : { options }),\n\t\t\tpreFocus: this.focusedComponent,\n\t\t\thidden: false,\n\t\t\tfocusOrder: ++this.focusOrderCounter,\n\t\t};\n\t\tthis.overlayStack.push(entry);\n\t\t// Only focus if overlay is actually visible\n\t\tif (!options?.nonCapturing && this.isOverlayVisible(entry)) {\n\t\t\tthis.setFocus(component);\n\t\t}\n\t\tif (!this.showHardwareCursor) {\n\t\t\tthis.terminal.hideCursor();\n\t\t}\n\t\tthis.requestRender();\n\n\t\t// Return handle for controlling this overlay\n\t\treturn {\n\t\t\thide: () => {\n\t\t\t\tconst index = this.overlayStack.indexOf(entry);\n\t\t\t\tif (index !== -1) {\n\t\t\t\t\tthis.clearOverlayFocusRestoreFor(entry);\n\t\t\t\t\tthis.retargetOverlayPreFocus(entry);\n\t\t\t\t\tthis.overlayStack.splice(index, 1);\n\t\t\t\t\t// Restore focus if this overlay had focus\n\t\t\t\t\tif (this.focusedComponent === component) {\n\t\t\t\t\t\tconst topVisible = this.getTopmostVisibleOverlay();\n\t\t\t\t\t\tthis.setFocus(topVisible?.component ?? entry.preFocus);\n\t\t\t\t\t}\n\t\t\t\t\tif (this.overlayStack.length === 0 && !this.showHardwareCursor) {\n\t\t\t\t\t\tthis.terminal.hideCursor();\n\t\t\t\t\t}\n\t\t\t\t\tthis.requestRender();\n\t\t\t\t}\n\t\t\t},\n\t\t\tsetHidden: (hidden: boolean) => {\n\t\t\t\tif (entry.hidden === hidden) return;\n\t\t\t\tentry.hidden = hidden;\n\t\t\t\t// Update focus when hiding/showing\n\t\t\t\tif (hidden) {\n\t\t\t\t\tthis.clearOverlayFocusRestoreFor(entry);\n\t\t\t\t\t// If this overlay had focus, move focus to next visible or preFocus\n\t\t\t\t\tif (this.focusedComponent === component) {\n\t\t\t\t\t\tconst topVisible = this.getTopmostVisibleOverlay();\n\t\t\t\t\t\tthis.setFocus(topVisible?.component ?? entry.preFocus);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Restore focus to this overlay when showing (if it's actually visible)\n\t\t\t\t\tif (!options?.nonCapturing && this.isOverlayVisible(entry)) {\n\t\t\t\t\t\tentry.focusOrder = ++this.focusOrderCounter;\n\t\t\t\t\t\tthis.setFocus(component);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthis.requestRender();\n\t\t\t},\n\t\t\tisHidden: () => entry.hidden,\n\t\t\tfocus: () => {\n\t\t\t\tif (!this.overlayStack.includes(entry) || !this.isOverlayVisible(entry)) return;\n\t\t\t\tentry.focusOrder = ++this.focusOrderCounter;\n\t\t\t\tthis.setFocus(component);\n\t\t\t\tthis.requestRender();\n\t\t\t},\n\t\t\tunfocus: (unfocusOptions) => {\n\t\t\t\tconst isFocused = this.focusedComponent === component;\n\t\t\t\tconst restoreState = this.overlayFocusRestore;\n\t\t\t\tconst hasPendingRestore = restoreState.status !== \"inactive\" && restoreState.overlay === entry;\n\t\t\t\tif (!isFocused && !hasPendingRestore) return;\n\t\t\t\tif (\n\t\t\t\t\trestoreState.status === \"blocked\" &&\n\t\t\t\t\trestoreState.overlay === entry &&\n\t\t\t\t\tthis.focusedComponent === restoreState.blockedBy\n\t\t\t\t) {\n\t\t\t\t\tif (unfocusOptions) {\n\t\t\t\t\t\tthis.overlayFocusRestore = {\n\t\t\t\t\t\t\tstatus: \"blocked\",\n\t\t\t\t\t\t\toverlay: entry,\n\t\t\t\t\t\t\tblockedBy: restoreState.blockedBy,\n\t\t\t\t\t\t\tresume: { status: \"focus-target\", target: unfocusOptions.target },\n\t\t\t\t\t\t};\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.clearOverlayFocusRestore();\n\t\t\t\t\t}\n\t\t\t\t\tthis.requestRender();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.clearOverlayFocusRestoreFor(entry);\n\t\t\t\tif (isFocused || unfocusOptions) {\n\t\t\t\t\tconst topVisible = this.getTopmostVisibleOverlay();\n\t\t\t\t\tconst fallbackTarget = topVisible && topVisible !== entry ? topVisible.component : entry.preFocus;\n\t\t\t\t\tthis.setFocus(unfocusOptions ? unfocusOptions.target : fallbackTarget);\n\t\t\t\t}\n\t\t\t\tthis.requestRender();\n\t\t\t},\n\t\t\tisFocused: () => this.focusedComponent === component,\n\t\t};\n\t}\n\n\t/** Hide the topmost overlay and restore previous focus. */\n\thideOverlay(): void {\n\t\tconst overlay = this.overlayStack[this.overlayStack.length - 1];\n\t\tif (!overlay) return;\n\t\tthis.clearOverlayFocusRestoreFor(overlay);\n\t\tthis.retargetOverlayPreFocus(overlay);\n\t\tthis.overlayStack.pop();\n\t\tif (this.focusedComponent === overlay.component) {\n\t\t\t// Find topmost visible overlay, or fall back to preFocus\n\t\t\tconst topVisible = this.getTopmostVisibleOverlay();\n\t\t\tthis.setFocus(topVisible?.component ?? overlay.preFocus);\n\t\t}\n\t\tif (this.overlayStack.length === 0) this.terminal.hideCursor();\n\t\tthis.requestRender();\n\t}\n\n\t/** Check if there are any visible overlays */\n\thasOverlay(): boolean {\n\t\treturn this.overlayStack.some((o) => this.isOverlayVisible(o));\n\t}\n\n\t/** Check if an overlay entry is currently visible */\n\tprivate isOverlayVisible(entry: OverlayStackEntry): boolean {\n\t\tif (entry.hidden) return false;\n\t\tif (entry.options?.visible) {\n\t\t\treturn entry.options.visible(this.terminal.columns, this.terminal.rows);\n\t\t}\n\t\treturn true;\n\t}\n\n\t/** Find the visual-frontmost visible capturing overlay, if any */\n\tprivate getTopmostVisibleOverlay(): OverlayStackEntry | undefined {\n\t\tlet topmost: OverlayStackEntry | undefined;\n\t\tfor (const overlay of this.overlayStack) {\n\t\t\tif (overlay.options?.nonCapturing || !this.isOverlayVisible(overlay)) continue;\n\t\t\tif (!topmost || overlay.focusOrder > topmost.focusOrder) {\n\t\t\t\ttopmost = overlay;\n\t\t\t}\n\t\t}\n\t\treturn topmost;\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tfor (const overlay of this.overlayStack) overlay.component.invalidate?.();\n\t}\n\n\tstart(): void {\n\t\tthis.stopped = false;\n\t\tthis.terminal.start(\n\t\t\t(data) => this.handleInput(data),\n\t\t\t() => this.requestRender(),\n\t\t);\n\t\tif (!this.showHardwareCursor) {\n\t\t\tthis.terminal.hideCursor();\n\t\t}\n\t\tthis.queryCellSize();\n\t\tthis.setupMouseListener();\n\t\tthis.requestRender();\n\t}\n\n\taddInputListener(listener: InputListener): () => void {\n\t\tthis.inputListeners.add(listener);\n\t\treturn () => {\n\t\t\tthis.inputListeners.delete(listener);\n\t\t};\n\t}\n\n\tremoveInputListener(listener: InputListener): void {\n\t\tthis.inputListeners.delete(listener);\n\t}\n\n\tprivate queryCellSize(): void {\n\t\t// Only query if terminal supports images (cell size is only used for image rendering)\n\t\tif (!getCapabilities().images) {\n\t\t\treturn;\n\t\t}\n\t\t// Query terminal for cell size in pixels: CSI 16 t\n\t\t// Response format: CSI 6 ; height ; width t\n\t\tthis.terminal.write(\"\\x1b[16t\");\n\t}\n\n\tstop(): void {\n\t\tthis.stopped = true;\n\t\tif (this.renderTimer) {\n\t\t\tclearTimeout(this.renderTimer);\n\t\t\tthis.renderTimer = undefined;\n\t\t}\n\t\tif (this.scrollDebounceTimer) {\n\t\t\tclearTimeout(this.scrollDebounceTimer);\n\t\t\tthis.scrollDebounceTimer = null;\n\t\t}\n\t\tthis.clearAutoScrollTimer();\n\t\tthis.removeMouseListener();\n\t\t// Move cursor to the end of the content to prevent overwriting/artifacts on exit\n\t\tif (this.previousLines.length > 0) {\n\t\t\tconst targetRow = this.previousLines.length; // Line after the last content\n\t\t\tconst lineDiff = targetRow - this.hardwareCursorRow;\n\t\t\tif (lineDiff > 0) {\n\t\t\t\tthis.terminal.write(`\\x1b[${lineDiff}B`);\n\t\t\t} else if (lineDiff < 0) {\n\t\t\t\tthis.terminal.write(`\\x1b[${-lineDiff}A`);\n\t\t\t}\n\t\t\tthis.terminal.write(\"\\r\\n\");\n\t\t}\n\n\t\tthis.terminal.showCursor();\n\t\t// Reset cursor shape to user default on exit\n\t\tthis.terminal.write(\"\\x1b[0 q\");\n\t\tthis.terminal.stop();\n\t}\n\n\tprivate setupMouseListener(): void {\n\t\tconst stdinBuffer = this.terminal.stdinBuffer;\n\t\tif (!stdinBuffer) return;\n\t\tconst handler = (event: MouseEvent) => this.handleMouseEvent(event);\n\t\tstdinBuffer.on(\"mouse\", handler);\n\t\tthis.mouseListenerRemover = () => {\n\t\t\tstdinBuffer.removeListener(\"mouse\", handler);\n\t\t};\n\t}\n\n\tprivate removeMouseListener(): void {\n\t\tif (this.mouseListenerRemover) {\n\t\t\tthis.mouseListenerRemover();\n\t\t\tthis.mouseListenerRemover = undefined;\n\t\t}\n\t}\n\n\thandleMouseEvent(event: MouseEvent): void {\n\t\tif (event.type === \"mouseWheel\") {\n\t\t\tthis.lastMouseWheelTime = Date.now();\n\t\t\tif (this.focusedComponent?.handleInput) {\n\t\t\t\tconst direction = event.button === 64 ? \"scrollUp\" : \"scrollDown\";\n\t\t\t\tconst consumed = this.focusedComponent.handleInput(`\\x1b[${direction}`);\n\t\t\t\tthis.requestRender();\n\t\t\t\tif (consumed) return;\n\t\t\t}\n\t\t\t// Aggregate scroll delta for debouncing: first event flushes immediately,\n\t\t\t// subsequent events within the debounce window are accumulated and flushed once\n\t\t\tconst delta = event.button === 64 ? AUTO_SCROLL_ROWS : -AUTO_SCROLL_ROWS;\n\t\t\tthis.pendingScrollDelta += delta;\n\t\t\tif (!this.scrollDebounceTimer) {\n\t\t\t\t// First event: flush immediately for responsive feel\n\t\t\t\tthis.flushPendingScroll();\n\t\t\t\tthis.scrollDebounceTimer = setTimeout(() => {\n\t\t\t\t\tthis.scrollDebounceTimer = null;\n\t\t\t\t\tthis.flushPendingScroll();\n\t\t\t\t}, TUI.SCROLL_DEBOUNCE_MS);\n\t\t\t}\n\t\t\t// Otherwise: delta is accumulated, will be flushed when timer fires\n\t\t\treturn;\n\t\t}\n\t\tif (event.button !== 0) return;\n\t\tif (event.type === \"mouseDown\") {\n\t\t\tconst screenRow = event.row - 1;\n\t\t\tconst rawCol = event.col - 1;\n\t\t\tconst bufferRow = this.screenToBufferRow(screenRow);\n\t\t\tconst clip = this.getSelectionClipForRow(screenRow);\n\t\t\tconst line =\n\t\t\t\tclip != null && screenRow < this.currentCompositedLines.length\n\t\t\t\t\t? this.currentCompositedLines[screenRow]\n\t\t\t\t\t: this.currentFullLines[bufferRow];\n\t\t\tconst col = line != null ? snapColToGraphemeBoundary(line, rawCol) : rawCol;\n\t\t\tthis.selection = {\n\t\t\t\tactive: true,\n\t\t\t\tanchorRow: bufferRow,\n\t\t\t\tanchorCol: col,\n\t\t\t\tfocusRow: bufferRow,\n\t\t\t\tfocusCol: col,\n\t\t\t};\n\t\t\tthis.requestRender();\n\t\t} else if (event.type === \"mouseMove\" && this.selection) {\n\t\t\tconst screenRow = event.row - 1;\n\t\t\tconst rawCol = event.col - 1;\n\t\t\tconst bufferRow = this.screenToBufferRow(screenRow);\n\t\t\tconst clip = this.getSelectionClipForRow(screenRow);\n\t\t\tconst line =\n\t\t\t\tclip != null && screenRow < this.currentCompositedLines.length\n\t\t\t\t\t? this.currentCompositedLines[screenRow]\n\t\t\t\t\t: this.currentFullLines[bufferRow];\n\t\t\tconst col = line != null ? snapColToGraphemeBoundary(line, rawCol) : rawCol;\n\t\t\tthis.selection.focusRow = bufferRow;\n\t\t\tthis.selection.focusCol = col;\n\t\t\tif (event.row <= 1) {\n\t\t\t\tthis.startAutoScroll(-1);\n\t\t\t} else if (event.row >= this.lastScrollableViewport) {\n\t\t\t\t// Trigger downward autoScroll at the bottom of the scrollable area,\n\t\t\t\t// not the terminal bottom — the latter would require crossing any fixed\n\t\t\t\t// bottom region (e.g. the input box) before scrolling kicks in.\n\t\t\t\tthis.startAutoScroll(1);\n\t\t\t} else {\n\t\t\t\tthis.clearAutoScrollTimer();\n\t\t\t}\n\t\t\tthis.requestRender();\n\t\t} else if (event.type === \"mouseUp\" && this.selection) {\n\t\t\tconst sel = this.selection;\n\t\t\t// Skip copy on plain click (no drag) to avoid polluting clipboard\n\t\t\tconst hasDragged = sel.anchorRow !== sel.focusRow || sel.anchorCol !== sel.focusCol;\n\t\t\tconst text = hasDragged ? this.extractSelectionText() : \"\";\n\t\t\tthis.clearAutoScrollTimer();\n\t\t\tthis.selection = null;\n\t\t\tthis.requestRender();\n\t\t\tif (text.trim() && this.onCopySelection) {\n\t\t\t\tthis.onCopySelection(text);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate getMaxScrollOffset(): number {\n\t\tconst width = this.terminal.columns;\n\t\tconst height = this.terminal.rows;\n\t\tconst childLines: string[][] = [];\n\t\tfor (const child of this.children) {\n\t\t\tchildLines.push(child.render(width));\n\t\t}\n\t\tconst fixedCount = this.fixedBottomCount;\n\t\tlet scrollableLines = 0;\n\t\tlet fixedLines = 0;\n\t\tfor (let i = 0; i < childLines.length; i++) {\n\t\t\tif (i >= childLines.length - fixedCount) {\n\t\t\t\tfixedLines += childLines[i].length;\n\t\t\t} else {\n\t\t\t\tscrollableLines += childLines[i].length;\n\t\t\t}\n\t\t}\n\t\tconst scrollableViewport = Math.max(0, height - fixedLines);\n\t\treturn Math.max(0, scrollableLines - scrollableViewport);\n\t}\n\n\t/** Flush pending scroll delta and trigger a single render */\n\tprivate flushPendingScroll(): void {\n\t\tif (this.pendingScrollDelta === 0) return;\n\t\tconst delta = this.pendingScrollDelta;\n\t\tthis.pendingScrollDelta = 0;\n\t\tif (delta > 0) {\n\t\t\tthis.autoFollow = false;\n\t\t\tthis.scrollOffset = Math.min(this.getMaxScrollOffset(), this.scrollOffset + delta);\n\t\t} else {\n\t\t\tthis.scrollOffset = Math.max(0, this.scrollOffset + delta);\n\t\t\tif (this.scrollOffset === 0) this.autoFollow = true;\n\t\t}\n\t\tthis.onScrollOffsetChange?.(this.scrollOffset);\n\t\tthis.requestRender();\n\t}\n\n\tgetScrollOffset(): number {\n\t\treturn this.scrollOffset;\n\t}\n\n\tsetScrollOffset(offset: number): void {\n\t\tthis.scrollOffset = offset;\n\t\tthis.autoFollow = offset === 0;\n\t\tthis.onScrollOffsetChange?.(offset);\n\t\tthis.requestRender();\n\t}\n\n\tresetScrollOffset(): void {\n\t\tthis.scrollOffset = 0;\n\t\tthis.autoFollow = true;\n\t\tthis.onScrollOffsetChange?.(0);\n\t\tthis.requestRender();\n\t}\n\n\tgetAutoFollow(): boolean {\n\t\treturn this.autoFollow;\n\t}\n\n\tsetAutoFollow(value: boolean): void {\n\t\tif (this.autoFollow === value) return;\n\t\tthis.autoFollow = value;\n\t\tif (value) {\n\t\t\tthis.scrollOffset = 0;\n\t\t\tthis.onScrollOffsetChange?.(0);\n\t\t\tthis.requestRender();\n\t\t}\n\t}\n\n\tsetFixedBottomCount(count: number): void {\n\t\tthis.fixedBottomCount = count;\n\t}\n\n\tprivate startAutoScroll(direction: -1 | 1): void {\n\t\t// 同方向已运行则不重启,避免定时器堆积\n\t\tif (this.autoScrollTimer && this.autoScrollDirection === direction) return;\n\t\tthis.clearAutoScrollTimer();\n\t\tthis.autoFollow = false;\n\t\tthis.autoScrollDirection = direction;\n\t\tthis.autoScrollTimer = setInterval(() => {\n\t\t\tconst maxOffset = this.getMaxScrollOffset();\n\t\t\tif (direction < 0) {\n\t\t\t\t// 向旧内容方向滚动(视口顶向缓冲区起始扩展)\n\t\t\t\tif (this.scrollOffset >= maxOffset) return;\n\t\t\t\tthis.scrollOffset = Math.min(maxOffset, this.scrollOffset + AUTO_SCROLL_ROWS);\n\t\t\t\tif (this.selection) {\n\t\t\t\t\t// focus 指向视口顶行(刚滚入视野的更旧内容)\n\t\t\t\t\tthis.selection.focusRow = this.currentScrollableViewportTop;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// 向新内容方向滚动(视口顶向缓冲区末尾收缩)\n\t\t\t\tif (this.scrollOffset <= 0) return;\n\t\t\t\tthis.scrollOffset = Math.max(0, this.scrollOffset - AUTO_SCROLL_ROWS);\n\t\t\t\tif (this.selection) {\n\t\t\t\t\t// focus 指向视口底行(刚滚入视野的更新内容)\n\t\t\t\t\tthis.selection.focusRow = this.currentScrollableViewportTop + this.lastScrollableViewport - 1;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.onScrollOffsetChange?.(this.scrollOffset);\n\t\t\tthis.requestRender();\n\t\t}, AUTO_SCROLL_INTERVAL_MS);\n\t}\n\n\tprivate clearAutoScrollTimer(): void {\n\t\tif (this.autoScrollTimer) {\n\t\t\tclearInterval(this.autoScrollTimer);\n\t\t\tthis.autoScrollTimer = null;\n\t\t}\n\t}\n\n\t/**\n\t * Clear the current selection and stop any active autoScroll.\n\t * Called by overlays when their internal scroll changes, to prevent\n\t * stale selection highlighting on shifted content.\n\t */\n\tclearSelection(): void {\n\t\tthis.clearAutoScrollTimer();\n\t\tthis.selection = null;\n\t\tthis.requestRender();\n\t}\n\n\tprivate extractSelectionText(): string {\n\t\tif (!this.selection) return \"\";\n\t\tconst sel = this.selection;\n\t\tconst lines = this.currentFullLines;\n\t\tif (lines.length === 0) return \"\";\n\t\tconst startRow = Math.min(sel.anchorRow, sel.focusRow);\n\t\tconst endRow = Math.max(sel.anchorRow, sel.focusRow);\n\t\tlet startCol: number;\n\t\tlet endCol: number;\n\t\tif (startRow === endRow) {\n\t\t\tstartCol = Math.min(sel.anchorCol, sel.focusCol);\n\t\t\tendCol = Math.max(sel.anchorCol, sel.focusCol);\n\t\t} else {\n\t\t\tstartCol = startRow === sel.anchorRow ? sel.anchorCol : sel.focusCol;\n\t\t\tendCol = endRow === sel.anchorRow ? sel.anchorCol : sel.focusCol;\n\t\t}\n\t\tconst parts: string[] = [];\n\t\tfor (let row = startRow; row <= endRow; row++) {\n\t\t\tif (row < 0 || row >= lines.length) continue;\n\t\t\t// Apply selectionClip from overlays that cover this screen row\n\t\t\tconst screenRow = this.bufferToScreenRow(row);\n\t\t\tconst clip = screenRow >= 0 ? this.getSelectionClipForRow(screenRow) : null;\n\t\t\t// Overlay-covered rows: extract from composited lines (overlay content).\n\t\t\t// Non-overlay rows: extract from full buffer (supports cross-viewport selection).\n\t\t\tconst line =\n\t\t\t\tclip != null && screenRow >= 0 && screenRow < this.currentCompositedLines.length\n\t\t\t\t\t? this.currentCompositedLines[screenRow]\n\t\t\t\t\t: lines[row];\n\t\t\tconst rowStartCol = row === startRow ? startCol : 0;\n\t\t\tconst rowEndCol = row === endRow ? endCol : visibleWidth(line) - 1;\n\t\t\tlet clipStart = rowStartCol;\n\t\t\tlet clipEnd = rowEndCol;\n\t\t\tif (clip) {\n\t\t\t\t// Clip the selection range to the selectable region within the overlay\n\t\t\t\tclipStart = Math.max(clipStart, clip.col);\n\t\t\t\tclipEnd = Math.min(clipEnd, clip.col + clip.width - 1);\n\t\t\t}\n\t\t\tif (clipStart > clipEnd) continue;\n\t\t\tconst extracted = stripAnsi(sliceByColumn(line, clipStart, clipEnd - clipStart + 1));\n\t\t\t// Trim trailing whitespace from composited lines since compositeLineAt\n\t\t\t// pads them to terminal width with spaces, followed by ANSI resets.\n\t\t\tparts.push(clip ? extracted.trimEnd() : extracted);\n\t\t}\n\t\treturn parts.join(\"\\n\");\n\t}\n\n\t/**\n\t * Get the selection clip region for a given screen row.\n\t * If any overlay with a selectionClip callback covers this row,\n\t * returns the clip region to restrict selection to that area.\n\t */\n\tprivate getSelectionClipForRow(screenRow: number): { col: number; width: number } | null {\n\t\tfor (const layout of this.renderedOverlayLayouts) {\n\t\t\t// Check if this screen row falls within the overlay's row range\n\t\t\tif (screenRow >= layout.row && screenRow < layout.row + layout.height) {\n\t\t\t\tif (layout.selectionClip) {\n\t\t\t\t\tconst clip = layout.selectionClip(screenRow);\n\t\t\t\t\tif (clip) {\n\t\t\t\t\t\t// Adjust clip col to be relative to the overlay's position\n\t\t\t\t\t\treturn { col: layout.col + clip.col, width: clip.width };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t/**\n\t * Convert a screen row (0-indexed terminal row) to a buffer-absolute row index\n\t * in `this.currentFullLines`. Used by mouseDown/mouseMove to set selection\n\t * anchor/focus in stable buffer coordinates that survive scrolling.\n\t *\n\t * - Screen rows in the scrollable area map to:\n\t * currentScrollableViewportTop + screenRow\n\t * - Screen rows in the fixed area map to:\n\t * currentScrollableLinesLength + (screenRow - lastScrollableViewport)\n\t */\n\tprivate screenToBufferRow(screenRow: number): number {\n\t\tconst svp = this.lastScrollableViewport;\n\t\tif (screenRow < svp) {\n\t\t\treturn this.currentScrollableViewportTop + screenRow;\n\t\t}\n\t\treturn this.currentScrollableLinesLength + (screenRow - svp);\n\t}\n\n\t/**\n\t * Convert a buffer-absolute row index back to a screen row.\n\t * Returns -1 if the buffer row is a scrollable line currently outside the viewport.\n\t * Fixed-area buffer rows always map to a visible screen row.\n\t */\n\tprivate bufferToScreenRow(bufferRow: number): number {\n\t\tconst scrollableLen = this.currentScrollableLinesLength;\n\t\tif (bufferRow < scrollableLen) {\n\t\t\tconst screenRow = bufferRow - this.currentScrollableViewportTop;\n\t\t\tif (screenRow < 0 || screenRow >= this.lastScrollableViewport) return -1;\n\t\t\treturn screenRow;\n\t\t}\n\t\treturn this.lastScrollableViewport + (bufferRow - scrollableLen);\n\t}\n\n\tprivate applySelectionHighlight(newLines: string[], height: number): void {\n\t\tif (!this.selection) return;\n\t\tconst sel = this.selection;\n\t\tconst startBufferRow = Math.min(sel.anchorRow, sel.focusRow);\n\t\tconst endBufferRow = Math.max(sel.anchorRow, sel.focusRow);\n\t\tlet startCol: number;\n\t\tlet endCol: number;\n\t\tif (startBufferRow === endBufferRow) {\n\t\t\tstartCol = Math.min(sel.anchorCol, sel.focusCol);\n\t\t\tendCol = Math.max(sel.anchorCol, sel.focusCol);\n\t\t} else {\n\t\t\tstartCol = startBufferRow === sel.anchorRow ? sel.anchorCol : sel.focusCol;\n\t\t\tendCol = endBufferRow === sel.anchorRow ? sel.anchorCol : sel.focusCol;\n\t\t}\n\n\t\tfor (let bufferRow = startBufferRow; bufferRow <= endBufferRow; bufferRow++) {\n\t\t\tconst screenRow = this.bufferToScreenRow(bufferRow);\n\t\t\tif (screenRow < 0 || screenRow >= height) continue;\n\t\t\tif (bufferRow < 0 || bufferRow >= this.currentFullLines.length) continue;\n\t\t\tconst targetLine = newLines[screenRow];\n\t\t\tif (!targetLine || isImageLine(targetLine)) continue;\n\t\t\tconst lineVisibleWidth = visibleWidth(targetLine);\n\t\t\tlet colStart = bufferRow === startBufferRow ? Math.min(startCol, lineVisibleWidth) : 0;\n\t\t\tlet colEnd = bufferRow === endBufferRow ? Math.min(endCol, lineVisibleWidth - 1) : lineVisibleWidth - 1;\n\t\t\t// Apply selectionClip from overlays that cover this screen row\n\t\t\tconst clip = this.getSelectionClipForRow(screenRow);\n\t\t\tif (clip) {\n\t\t\t\tcolStart = Math.max(colStart, clip.col);\n\t\t\t\tcolEnd = Math.min(colEnd, clip.col + clip.width - 1);\n\t\t\t}\n\t\t\tif (colStart > colEnd) continue;\n\t\t\tconst before = sliceByColumn(targetLine, 0, colStart, true);\n\t\t\tconst highlighted = sliceByColumn(targetLine, colStart, colEnd - colStart + 1);\n\t\t\tconst after =\n\t\t\t\tcolEnd + 1 < lineVisibleWidth ? sliceByColumn(targetLine, colEnd + 1, lineVisibleWidth - colEnd - 1) : \"\";\n\t\t\t// Preserve reverse video across SGR resets inside the highlighted region.\n\t\t\t// \\x1b[0m resets ALL attributes including \\x1b[7m (reverse video),\n\t\t\t// which would break the selection highlight. Re-apply \\x1b[7m after each reset.\n\t\t\tconst preservedHighlight = highlighted.replace(/\\x1b\\[0m/g, \"\\x1b[0m\\x1b[7m\");\n\t\t\tnewLines[screenRow] = `${before}\\x1b[7m${preservedHighlight}\\x1b[27m${after}`;\n\t\t}\n\t}\n\n\trequestRender(force = false): void {\n\t\tif (force) {\n\t\t\tthis.previousLines = [];\n\t\t\tthis.previousWidth = -1; // -1 triggers widthChanged, forcing a full clear\n\t\t\tthis.previousHeight = -1; // -1 triggers heightChanged, forcing a full clear\n\t\t\tthis.cursorRow = 0;\n\t\t\tthis.hardwareCursorRow = 0;\n\t\t\tthis.maxLinesRendered = 0;\n\t\t\tthis.previousViewportTop = 0;\n\t\t\tif (this.renderTimer) {\n\t\t\t\tclearTimeout(this.renderTimer);\n\t\t\t\tthis.renderTimer = undefined;\n\t\t\t}\n\t\t\tthis.renderRequested = true;\n\t\t\tprocess.nextTick(() => {\n\t\t\t\tif (this.stopped || !this.renderRequested) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.renderRequested = false;\n\t\t\t\tthis.lastRenderAt = performance.now();\n\t\t\t\tthis.doRender();\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tif (this.renderRequested) return;\n\t\tthis.renderRequested = true;\n\t\tprocess.nextTick(() => this.scheduleRender());\n\t}\n\n\tprivate scheduleRender(): void {\n\t\tif (this.stopped || this.renderTimer || !this.renderRequested) {\n\t\t\treturn;\n\t\t}\n\t\tconst elapsed = performance.now() - this.lastRenderAt;\n\t\tconst delay = Math.max(0, TUI.MIN_RENDER_INTERVAL_MS - elapsed);\n\t\tthis.renderTimer = setTimeout(() => {\n\t\t\tthis.renderTimer = undefined;\n\t\t\tif (this.stopped || !this.renderRequested) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.renderRequested = false;\n\t\t\tthis.lastRenderAt = performance.now();\n\t\t\tthis.doRender();\n\t\t\tif (this.renderRequested) {\n\t\t\t\tthis.scheduleRender();\n\t\t\t}\n\t\t}, delay);\n\t}\n\n\tprivate handleInput(data: string): void {\n\t\tif (this.inputListeners.size > 0) {\n\t\t\tlet current = data;\n\t\t\tfor (const listener of this.inputListeners) {\n\t\t\t\tconst result = listener(current);\n\t\t\t\tif (result?.consume) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (result?.data !== undefined) {\n\t\t\t\t\tcurrent = result.data;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (current.length === 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdata = current;\n\t\t}\n\n\t\t// Consume terminal cell size responses without blocking unrelated input.\n\t\tif (this.consumeCellSizeResponse(data)) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Global debug key handler (Shift+Ctrl+D)\n\t\tif (matchesKey(data, \"shift+ctrl+d\") && this.onDebug) {\n\t\t\tthis.onDebug();\n\t\t\treturn;\n\t\t}\n\n\t\t// If focused component is an overlay, verify it's still visible\n\t\t// (visibility can change due to terminal resize or visible() callback)\n\t\tconst focusedOverlay = this.overlayStack.find((o) => o.component === this.focusedComponent);\n\t\tif (focusedOverlay && !this.isOverlayVisible(focusedOverlay)) {\n\t\t\t// Focused overlay is no longer visible, redirect to topmost visible overlay\n\t\t\tconst topVisible = this.getTopmostVisibleOverlay();\n\t\t\tif (topVisible) {\n\t\t\t\tthis.setFocus(topVisible.component);\n\t\t\t} else {\n\t\t\t\tthis.setFocusInternal({ component: focusedOverlay.preFocus, overlayFocusRestore: \"preserve\" });\n\t\t\t}\n\t\t}\n\n\t\tconst focusIsOverlay = this.overlayStack.some((o) => o.component === this.focusedComponent);\n\t\tif (!focusIsOverlay) {\n\t\t\tconst restoreState = this.getVisibleOverlayFocusRestore();\n\t\t\tif (restoreState.status === \"eligible\") {\n\t\t\t\tthis.setFocus(restoreState.overlay.component);\n\t\t\t} else if (restoreState.status === \"blocked\" && restoreState.blockedBy !== this.focusedComponent) {\n\t\t\t\tif (restoreState.resume.status === \"restore-overlay\") {\n\t\t\t\t\tthis.setFocus(restoreState.overlay.component);\n\t\t\t\t} else {\n\t\t\t\t\tthis.clearOverlayFocusRestore();\n\t\t\t\t\tthis.setFocus(restoreState.resume.target);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Suppress arrow keys that arrive shortly after a mouse wheel event.\n\t\t// Some terminals (or intermediate layers like tmux) occasionally convert\n\t\t// scroll events into arrow-key sequences; without this guard those\n\t\t// spurious keys trigger unwanted actions such as input-history navigation.\n\t\tif (\n\t\t\tDate.now() - this.lastMouseWheelTime < TUI.MOUSE_WHEEL_SUPPRESS_MS &&\n\t\t\t(matchesKey(data, \"up\") || matchesKey(data, \"down\"))\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Pass input to focused component first. If it returns true, it consumed the input.\n\t\tif (this.focusedComponent?.handleInput) {\n\t\t\t// Filter out key release events unless component opts in\n\t\t\tif (isKeyRelease(data) && !this.focusedComponent.wantsKeyRelease) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst consumed = this.focusedComponent.handleInput(data);\n\t\t\tthis.requestRender();\n\t\t\tif (consumed) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Fallback: TUI handles scroll keys when focused component didn't consume them\n\t\tif (matchesKey(data, \"pageUp\")) {\n\t\t\tconst pageSize = this.lastScrollableViewport || this.terminal.rows - 2;\n\t\t\tthis.setScrollOffset(this.scrollOffset + pageSize);\n\t\t\treturn;\n\t\t}\n\t\tif (matchesKey(data, \"pageDown\")) {\n\t\t\tconst pageSize = this.lastScrollableViewport || this.terminal.rows - 2;\n\t\t\tthis.setScrollOffset(Math.max(0, this.scrollOffset - pageSize));\n\t\t\treturn;\n\t\t}\n\t\t// Ctrl+Home / Ctrl+End: scroll to top/bottom of content\n\t\tif (matchesKey(data, \"ctrl+home\")) {\n\t\t\tthis.setScrollOffset(this.getMaxScrollOffset());\n\t\t\treturn;\n\t\t}\n\t\tif (matchesKey(data, \"ctrl+end\")) {\n\t\t\tthis.setScrollOffset(0);\n\t\t\treturn;\n\t\t}\n\t}\n\n\tprivate consumeCellSizeResponse(data: string): boolean {\n\t\t// Response format: ESC [ 6 ; height ; width t\n\t\tconst match = data.match(/^\\x1b\\[6;(\\d+);(\\d+)t$/);\n\t\tif (!match) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst heightPx = parseInt(match[1], 10);\n\t\tconst widthPx = parseInt(match[2], 10);\n\t\tif (heightPx <= 0 || widthPx <= 0) {\n\t\t\treturn true;\n\t\t}\n\n\t\tsetCellDimensions({ widthPx, heightPx });\n\t\t// Invalidate all components so images re-render with correct dimensions.\n\t\tthis.invalidate();\n\t\tthis.requestRender();\n\t\treturn true;\n\t}\n\n\t/**\n\t * Resolve overlay layout from options.\n\t * Returns { width, row, col, maxHeight } for rendering.\n\t */\n\tprivate resolveOverlayLayout(\n\t\toptions: OverlayOptions | undefined,\n\t\toverlayHeight: number,\n\t\ttermWidth: number,\n\t\ttermHeight: number,\n\t): { width: number; row: number; col: number; maxHeight: number | undefined } {\n\t\tconst opt = options ?? {};\n\n\t\t// Parse margin (clamp to non-negative)\n\t\tconst margin =\n\t\t\ttypeof opt.margin === \"number\"\n\t\t\t\t? { top: opt.margin, right: opt.margin, bottom: opt.margin, left: opt.margin }\n\t\t\t\t: (opt.margin ?? {});\n\t\tconst marginTop = Math.max(0, margin.top ?? 0);\n\t\tconst marginRight = Math.max(0, margin.right ?? 0);\n\t\tconst marginBottom = Math.max(0, margin.bottom ?? 0);\n\t\tconst marginLeft = Math.max(0, margin.left ?? 0);\n\n\t\t// Available space after margins\n\t\tconst availWidth = Math.max(1, termWidth - marginLeft - marginRight);\n\t\tconst availHeight = Math.max(1, termHeight - marginTop - marginBottom);\n\n\t\t// === Resolve width ===\n\t\tlet width = parseSizeValue(opt.width, termWidth) ?? Math.min(80, availWidth);\n\t\t// Apply minWidth\n\t\tif (opt.minWidth !== undefined) {\n\t\t\twidth = Math.max(width, opt.minWidth);\n\t\t}\n\t\t// Clamp to available space\n\t\twidth = Math.max(1, Math.min(width, availWidth));\n\n\t\t// === Resolve maxHeight ===\n\t\tlet maxHeight = parseSizeValue(opt.maxHeight, termHeight);\n\t\t// Clamp to available space\n\t\tif (maxHeight !== undefined) {\n\t\t\tmaxHeight = Math.max(1, Math.min(maxHeight, availHeight));\n\t\t}\n\n\t\t// Effective overlay height (may be clamped by maxHeight)\n\t\tconst effectiveHeight = maxHeight !== undefined ? Math.min(overlayHeight, maxHeight) : overlayHeight;\n\n\t\t// === Resolve position ===\n\t\tlet row: number;\n\t\tlet col: number;\n\n\t\tif (opt.row !== undefined) {\n\t\t\tif (typeof opt.row === \"string\") {\n\t\t\t\t// Percentage: 0% = top, 100% = bottom (overlay stays within bounds)\n\t\t\t\tconst match = opt.row.match(/^(\\d+(?:\\.\\d+)?)%$/);\n\t\t\t\tif (match) {\n\t\t\t\t\tconst maxRow = Math.max(0, availHeight - effectiveHeight);\n\t\t\t\t\tconst percent = parseFloat(match[1]) / 100;\n\t\t\t\t\trow = marginTop + Math.floor(maxRow * percent);\n\t\t\t\t} else {\n\t\t\t\t\t// Invalid format, fall back to center\n\t\t\t\t\trow = this.resolveAnchorRow(\"center\", effectiveHeight, availHeight, marginTop);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Absolute row position\n\t\t\t\trow = opt.row;\n\t\t\t}\n\t\t} else {\n\t\t\t// Anchor-based (default: center)\n\t\t\tconst anchor = opt.anchor ?? \"center\";\n\t\t\trow = this.resolveAnchorRow(anchor, effectiveHeight, availHeight, marginTop);\n\t\t}\n\n\t\tif (opt.col !== undefined) {\n\t\t\tif (typeof opt.col === \"string\") {\n\t\t\t\t// Percentage: 0% = left, 100% = right (overlay stays within bounds)\n\t\t\t\tconst match = opt.col.match(/^(\\d+(?:\\.\\d+)?)%$/);\n\t\t\t\tif (match) {\n\t\t\t\t\tconst maxCol = Math.max(0, availWidth - width);\n\t\t\t\t\tconst percent = parseFloat(match[1]) / 100;\n\t\t\t\t\tcol = marginLeft + Math.floor(maxCol * percent);\n\t\t\t\t} else {\n\t\t\t\t\t// Invalid format, fall back to center\n\t\t\t\t\tcol = this.resolveAnchorCol(\"center\", width, availWidth, marginLeft);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Absolute column position\n\t\t\t\tcol = opt.col;\n\t\t\t}\n\t\t} else {\n\t\t\t// Anchor-based (default: center)\n\t\t\tconst anchor = opt.anchor ?? \"center\";\n\t\t\tcol = this.resolveAnchorCol(anchor, width, availWidth, marginLeft);\n\t\t}\n\n\t\t// Apply offsets\n\t\tif (opt.offsetY !== undefined) row += opt.offsetY;\n\t\tif (opt.offsetX !== undefined) col += opt.offsetX;\n\n\t\t// Clamp to terminal bounds (respecting margins)\n\t\trow = Math.max(marginTop, Math.min(row, termHeight - marginBottom - effectiveHeight));\n\t\tcol = Math.max(marginLeft, Math.min(col, termWidth - marginRight - width));\n\n\t\treturn { width, row, col, maxHeight };\n\t}\n\n\tprivate resolveAnchorRow(anchor: OverlayAnchor, height: number, availHeight: number, marginTop: number): number {\n\t\tswitch (anchor) {\n\t\t\tcase \"top-left\":\n\t\t\tcase \"top-center\":\n\t\t\tcase \"top-right\":\n\t\t\t\treturn marginTop;\n\t\t\tcase \"bottom-left\":\n\t\t\tcase \"bottom-center\":\n\t\t\tcase \"bottom-right\":\n\t\t\t\treturn marginTop + availHeight - height;\n\t\t\tcase \"left-center\":\n\t\t\tcase \"center\":\n\t\t\tcase \"right-center\":\n\t\t\t\treturn marginTop + Math.floor((availHeight - height) / 2);\n\t\t}\n\t}\n\n\tprivate resolveAnchorCol(anchor: OverlayAnchor, width: number, availWidth: number, marginLeft: number): number {\n\t\tswitch (anchor) {\n\t\t\tcase \"top-left\":\n\t\t\tcase \"left-center\":\n\t\t\tcase \"bottom-left\":\n\t\t\t\treturn marginLeft;\n\t\t\tcase \"top-right\":\n\t\t\tcase \"right-center\":\n\t\t\tcase \"bottom-right\":\n\t\t\t\treturn marginLeft + availWidth - width;\n\t\t\tcase \"top-center\":\n\t\t\tcase \"center\":\n\t\t\tcase \"bottom-center\":\n\t\t\t\treturn marginLeft + Math.floor((availWidth - width) / 2);\n\t\t}\n\t}\n\n\t/** Composite all overlays into content lines (sorted by focusOrder, higher = on top). */\n\tprivate compositeOverlays(lines: string[], termWidth: number, termHeight: number): string[] {\n\t\tconst result = [...lines];\n\n\t\t// Pre-render all visible overlays and calculate positions\n\t\tconst rendered: {\n\t\t\toverlayLines: string[];\n\t\t\trow: number;\n\t\t\tcol: number;\n\t\t\tw: number;\n\t\t\tbackground?: string;\n\t\t\tselectionClip?: (screenRow: number) => { col: number; width: number } | null;\n\t\t}[] = [];\n\t\tlet minLinesNeeded = result.length;\n\n\t\tconst visibleEntries = this.overlayStack.filter((e) => this.isOverlayVisible(e));\n\t\tvisibleEntries.sort((a, b) => a.focusOrder - b.focusOrder);\n\t\tfor (const entry of visibleEntries) {\n\t\t\tconst { component, options } = entry;\n\n\t\t\t// Get layout with height=0 first to determine width and maxHeight\n\t\t\t// (width and maxHeight don't depend on overlay height)\n\t\t\tconst { width, maxHeight } = this.resolveOverlayLayout(options, 0, termWidth, termHeight);\n\n\t\t\t// Render component at calculated width\n\t\t\tlet overlayLines = component.render(width);\n\n\t\t\t// Apply maxHeight if specified\n\t\t\tif (maxHeight !== undefined && overlayLines.length > maxHeight) {\n\t\t\t\toverlayLines = overlayLines.slice(0, maxHeight);\n\t\t\t}\n\n\t\t\t// Get final row/col with actual overlay height\n\t\t\tconst { row, col } = this.resolveOverlayLayout(options, overlayLines.length, termWidth, termHeight);\n\n\t\t\trendered.push({\n\t\t\t\toverlayLines,\n\t\t\t\trow,\n\t\t\t\tcol,\n\t\t\t\tw: width,\n\t\t\t\tbackground: options?.background,\n\t\t\t\tselectionClip: options?.selectionClip,\n\t\t\t});\n\t\t\tminLinesNeeded = Math.max(minLinesNeeded, row + overlayLines.length);\n\t\t}\n\n\t\t// Cache overlay layouts for selection clip calculations\n\t\tthis.renderedOverlayLayouts = rendered.map(({ row, col, w, overlayLines, selectionClip }) => ({\n\t\t\trow,\n\t\t\tcol,\n\t\t\twidth: w,\n\t\t\theight: overlayLines.length,\n\t\t\tselectionClip,\n\t\t}));\n\n\t\t// Pad to at least terminal height so overlays have screen-relative positions.\n\t\t// Excludes maxLinesRendered: the historical high-water mark caused self-reinforcing\n\t\t// inflation that pushed content into scrollback on terminal widen.\n\t\tconst workingHeight = Math.max(result.length, termHeight, minLinesNeeded);\n\n\t\t// Extend result with empty lines if content is too short for overlay placement or working area\n\t\twhile (result.length < workingHeight) {\n\t\t\tresult.push(\"\");\n\t\t}\n\n\t\tconst viewportStart = Math.max(0, workingHeight - termHeight);\n\n\t\t// Composite each overlay\n\t\tfor (const { overlayLines, row, col, w, background: bg } of rendered) {\n\t\t\tfor (let i = 0; i < overlayLines.length; i++) {\n\t\t\t\tconst idx = viewportStart + row + i;\n\t\t\t\tif (idx >= 0 && idx < result.length) {\n\t\t\t\t\t// Defensive: truncate overlay line to declared width before compositing\n\t\t\t\t\t// (components should already respect width, but this ensures it)\n\t\t\t\t\tconst truncatedOverlayLine =\n\t\t\t\t\t\tvisibleWidth(overlayLines[i]) > w ? sliceByColumn(overlayLines[i], 0, w, true) : overlayLines[i];\n\t\t\t\t\tlet baseLine = result[idx];\n\t\t\t\t\tif (bg) {\n\t\t\t\t\t\tbaseLine = this.applyOverlayBackground(baseLine, col, w, bg, termWidth);\n\t\t\t\t\t}\n\t\t\t\t\tresult[idx] = this.compositeLineAt(baseLine, truncatedOverlayLine, col, w, termWidth);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate static readonly SEGMENT_RESET = \"\\x1b[0m\\x1b]8;;\\x07\";\n\n\tprivate applyLineResets(lines: string[]): string[] {\n\t\tconst reset = TUI.SEGMENT_RESET;\n\t\tfor (let i = 0; i < lines.length; i++) {\n\t\t\tconst line = lines[i];\n\t\t\tif (!isImageLine(line)) {\n\t\t\t\tlines[i] = normalizeTerminalOutput(line) + reset;\n\t\t\t}\n\t\t}\n\t\treturn lines;\n\t}\n\n\tprivate collectKittyImageIds(lines: string[]): Set<number> {\n\t\tconst ids = new Set<number>();\n\t\tfor (const line of lines) {\n\t\t\tfor (const id of extractKittyImageIds(line)) {\n\t\t\t\tids.add(id);\n\t\t\t}\n\t\t}\n\t\treturn ids;\n\t}\n\n\tprivate deleteKittyImages(ids: Iterable<number>): string {\n\t\tlet buffer = \"\";\n\t\tfor (const id of ids) {\n\t\t\tbuffer += deleteKittyImage(id);\n\t\t}\n\t\treturn buffer;\n\t}\n\n\tprivate expandLastChangedForKittyImages(firstChanged: number, lastChanged: number): number {\n\t\tlet expandedLastChanged = lastChanged;\n\t\tfor (let i = firstChanged; i < this.previousLines.length; i++) {\n\t\t\tif (extractKittyImageIds(this.previousLines[i]).length > 0) {\n\t\t\t\texpandedLastChanged = Math.max(expandedLastChanged, i);\n\t\t\t}\n\t\t}\n\t\treturn expandedLastChanged;\n\t}\n\n\tprivate deleteChangedKittyImages(firstChanged: number, lastChanged: number): string {\n\t\tif (firstChanged < 0 || lastChanged < firstChanged) return \"\";\n\n\t\tconst ids = new Set<number>();\n\t\tconst maxLine = Math.min(lastChanged, this.previousLines.length - 1);\n\t\tfor (let i = firstChanged; i <= maxLine; i++) {\n\t\t\tfor (const id of extractKittyImageIds(this.previousLines[i] ?? \"\")) {\n\t\t\t\tids.add(id);\n\t\t\t}\n\t\t}\n\n\t\treturn this.deleteKittyImages(ids);\n\t}\n\n\t/** Apply background fill to the overlay region of a base line. */\n\tprivate applyOverlayBackground(\n\t\tbaseLine: string,\n\t\tstartCol: number,\n\t\toverlayWidth: number,\n\t\tbg: string,\n\t\ttotalWidth: number,\n\t): string {\n\t\tif (isImageLine(baseLine)) return baseLine;\n\t\tconst afterStart = startCol + overlayWidth;\n\t\tconst segments = extractSegments(baseLine, startCol, afterStart, totalWidth - afterStart, true);\n\t\tconst r = TUI.SEGMENT_RESET;\n\t\tconst beforePad = Math.max(0, startCol - segments.beforeWidth);\n\t\tconst overlayFill = bg + \" \".repeat(overlayWidth) + r;\n\t\tconst afterTarget = Math.max(0, totalWidth - Math.max(startCol, segments.beforeWidth) - overlayWidth);\n\t\tconst afterPad = Math.max(0, afterTarget - segments.afterWidth);\n\t\treturn segments.before + \" \".repeat(beforePad) + r + overlayFill + segments.after + \" \".repeat(afterPad);\n\t}\n\n\t/** Splice overlay content into a base line at a specific column. Single-pass optimized. */\n\tprivate compositeLineAt(\n\t\tbaseLine: string,\n\t\toverlayLine: string,\n\t\tstartCol: number,\n\t\toverlayWidth: number,\n\t\ttotalWidth: number,\n\t): string {\n\t\tif (isImageLine(baseLine)) return baseLine;\n\n\t\t// Single pass through baseLine extracts both before and after segments\n\t\tconst afterStart = startCol + overlayWidth;\n\t\tconst base = extractSegments(baseLine, startCol, afterStart, totalWidth - afterStart, true);\n\n\t\t// Extract overlay with width tracking (strict=true to exclude wide chars at boundary)\n\t\tconst overlay = sliceWithWidth(overlayLine, 0, overlayWidth, true);\n\n\t\t// Pad segments to target widths\n\t\tconst beforePad = Math.max(0, startCol - base.beforeWidth);\n\t\tconst overlayPad = Math.max(0, overlayWidth - overlay.width);\n\t\tconst actualBeforeWidth = Math.max(startCol, base.beforeWidth);\n\t\tconst actualOverlayWidth = Math.max(overlayWidth, overlay.width);\n\t\tconst afterTarget = Math.max(0, totalWidth - actualBeforeWidth - actualOverlayWidth);\n\t\tconst afterPad = Math.max(0, afterTarget - base.afterWidth);\n\n\t\t// Compose result\n\t\tconst r = TUI.SEGMENT_RESET;\n\t\tconst result =\n\t\t\tbase.before +\n\t\t\t\" \".repeat(beforePad) +\n\t\t\tr +\n\t\t\toverlay.text +\n\t\t\t\" \".repeat(overlayPad) +\n\t\t\tr +\n\t\t\tbase.after +\n\t\t\t\" \".repeat(afterPad);\n\n\t\t// CRITICAL: Always verify and truncate to terminal width.\n\t\t// This is the final safeguard against width overflow which would crash the TUI.\n\t\t// Width tracking can drift from actual visible width due to:\n\t\t// - Complex ANSI/OSC sequences (hyperlinks, colors)\n\t\t// - Wide characters at segment boundaries\n\t\t// - Edge cases in segment extraction\n\t\tconst resultWidth = visibleWidth(result);\n\t\tif (resultWidth <= totalWidth) {\n\t\t\treturn result;\n\t\t}\n\t\t// Truncate with strict=true to ensure we don't exceed totalWidth\n\t\treturn sliceByColumn(result, 0, totalWidth, true);\n\t}\n\n\t/**\n\t * Find and extract cursor position from rendered lines.\n\t * Searches for CURSOR_MARKER, calculates its position, and strips it from the output.\n\t * Only scans the bottom terminal height lines (visible viewport).\n\t * @param lines - Rendered lines to search\n\t * @param height - Terminal height (visible viewport size)\n\t * @returns Cursor position { row, col } or null if no marker found\n\t */\n\tprivate extractCursorPosition(lines: string[], height: number): { row: number; col: number } | null {\n\t\t// Only scan the bottom `height` lines (visible viewport)\n\t\tconst viewportTop = Math.max(0, lines.length - height);\n\t\tfor (let row = lines.length - 1; row >= viewportTop; row--) {\n\t\t\tconst line = lines[row];\n\t\t\tconst markerIndex = line.indexOf(CURSOR_MARKER);\n\t\t\tif (markerIndex !== -1) {\n\t\t\t\t// Calculate visual column (width of text before marker)\n\t\t\t\tconst beforeMarker = line.slice(0, markerIndex);\n\t\t\t\tconst col = visibleWidth(beforeMarker);\n\n\t\t\t\t// Strip marker from the line\n\t\t\t\tlines[row] = line.slice(0, markerIndex) + line.slice(markerIndex + CURSOR_MARKER.length);\n\n\t\t\t\treturn { row, col };\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tprivate renderingSuspended = false;\n\n\tsuspendRendering(): void {\n\t\tthis.renderingSuspended = true;\n\t\tif (this.renderTimer) {\n\t\t\tclearTimeout(this.renderTimer);\n\t\t\tthis.renderTimer = undefined;\n\t\t}\n\t\tthis.renderRequested = false;\n\t}\n\n\tresumeRendering(): void {\n\t\tthis.renderingSuspended = false;\n\t\tthis.requestRender(true);\n\t}\n\n\tprivate doRender(): void {\n\t\tif (this.stopped || this.renderingSuspended) return;\n\t\tconst width = this.terminal.columns;\n\t\tconst height = this.terminal.rows;\n\n\t\t// Render all children to get full content\n\t\tconst childLines: string[][] = [];\n\t\tfor (const child of this.children) {\n\t\t\tchildLines.push(child.render(width));\n\t\t}\n\n\t\t// Split children into scrollable (top) and fixed (bottom)\n\t\t// The fixedBottomCount property determines how many trailing children\n\t\t// are always pinned to the bottom of the screen\n\t\tconst fixedCount = this.fixedBottomCount;\n\t\tconst scrollableLines: string[] = [];\n\t\tconst fixedLines: string[] = [];\n\t\tfor (let i = 0; i < childLines.length; i++) {\n\t\t\tif (i >= childLines.length - fixedCount) {\n\t\t\t\tfixedLines.push(...childLines[i]);\n\t\t\t} else {\n\t\t\t\tscrollableLines.push(...childLines[i]);\n\t\t\t}\n\t\t}\n\n\t\t// Calculate available space for scrollable area\n\t\tconst fixedHeight = fixedLines.length;\n\t\tconst scrollableViewport = Math.max(0, height - fixedHeight);\n\t\tthis.lastScrollableViewport = scrollableViewport;\n\n\t\t// Apply scrollOffset to scrollable content only\n\t\tconst maxScroll = Math.max(0, scrollableLines.length - scrollableViewport);\n\t\tconst lineCountDelta = scrollableLines.length - this.previousScrollableLineCount;\n\t\tif (lineCountDelta > 0) {\n\t\t\tif (this.autoFollow) {\n\t\t\t\tthis.scrollOffset = 0;\n\t\t\t} else if (this.scrollOffset > 0) {\n\t\t\t\tthis.scrollOffset += lineCountDelta;\n\t\t\t}\n\t\t}\n\t\tif (this.scrollOffset > maxScroll) this.scrollOffset = maxScroll;\n\t\tthis.previousScrollableLineCount = scrollableLines.length;\n\n\t\t// Cache full lines (pre-overlay, pre-highlight) for selection text extraction\n\t\t// and absolute-row coordinate mapping\n\t\tthis.currentFullLines = [...scrollableLines, ...fixedLines];\n\t\tthis.currentScrollableLinesLength = scrollableLines.length;\n\n\t\t// Determine visible scrollable lines\n\t\tconst scrollableViewportTop = Math.max(0, scrollableLines.length - scrollableViewport - this.scrollOffset);\n\t\tconst visibleScrollable = scrollableLines.slice(\n\t\t\tscrollableViewportTop,\n\t\t\tscrollableViewportTop + scrollableViewport,\n\t\t);\n\n\t\t// Combine: visible scrollable content + fixed bottom content\n\t\tlet newLines: string[] = [...visibleScrollable, ...fixedLines];\n\n\t\t// Pad to fill screen height if content is shorter\n\t\twhile (newLines.length < height) newLines.push(\"\");\n\n\t\t// Truncate to screen height\n\t\tnewLines = newLines.slice(0, height);\n\n\t\t// Composite overlays (clear stale layout cache first, then let compositeOverlays refill it)\n\t\tthis.renderedOverlayLayouts = [];\n\t\tif (this.overlayStack.length > 0) {\n\t\t\tnewLines = this.compositeOverlays([...newLines], width, height);\n\t\t}\n\n\t\t// Cache composited lines (post-overlay, pre-highlight) for overlay text extraction\n\t\tthis.currentCompositedLines = [...newLines];\n\n\t\tconst cursorPos = this.extractCursorPosition(newLines, height);\n\t\tnewLines = this.applyLineResets(newLines);\n\n\t\t// Update viewport-top state before selection highlight, so bufferToScreenRow\n\t\t// inside applySelectionHighlight uses the correct viewport offset.\n\t\tthis.currentScrollableViewportTop = scrollableViewportTop;\n\n\t\t// Selection highlight: buffer-absolute row iteration via bufferToScreenRow\n\t\tthis.applySelectionHighlight(newLines, height);\n\n\t\tconst renderChanged = (): void => {\n\t\t\tthis.fullRedrawCount += 1;\n\t\t\t// Sync mode + cursor home + sequential line output (no full screen clear).\n\t\t\t// \\x1b[?2026h defers display until \\x1b[?2026l for atomic update.\n\t\t\t// \\x1b[K clears to end-of-line after each line to remove residual content\n\t\t\t// from previous renders, replacing the flicker-causing \\x1b[2J clear screen.\n\t\t\t// Uses sequential \\r\\n output (like the original) for minimal bandwidth.\n\t\t\tlet buffer = `\\x1b[?2026h${TUI.CURSOR_HIDE_PREFIX}\\x1b[H`;\n\t\t\tbuffer += this.deleteKittyImages(this.previousKittyImageIds);\n\t\t\tfor (let i = 0; i < newLines.length; i++) {\n\t\t\t\tif (i > 0) buffer += \"\\r\\n\";\n\t\t\t\tbuffer += newLines[i];\n\t\t\t\tbuffer += \"\\x1b[K\";\n\t\t\t}\n\t\t\tbuffer += this.buildHardwareCursorSequence(cursorPos, newLines.length);\n\t\t\tbuffer += \"\\x1b[?2026l\";\n\t\t\tthis.terminal.write(buffer);\n\t\t\tthis.cursorRow = Math.max(0, newLines.length - 1);\n\t\t\tthis.maxLinesRendered = newLines.length;\n\t\t\tthis.previousViewportTop = scrollableViewportTop;\n\t\t\tthis.previousLines = newLines;\n\t\t\tthis.previousKittyImageIds = this.collectKittyImageIds(newLines);\n\t\t\tthis.previousWidth = width;\n\t\t\tthis.previousHeight = height;\n\t\t};\n\n\t\tconst widthChanged = this.previousWidth !== 0 && this.previousWidth !== width;\n\t\tconst heightChanged = this.previousHeight !== 0 && this.previousHeight !== height;\n\n\t\tif (this.previousLines.length === 0) {\n\t\t\trenderChanged();\n\t\t\treturn;\n\t\t}\n\n\t\tif (widthChanged || (heightChanged && !isTermuxSession())) {\n\t\t\trenderChanged();\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.clearOnShrink && newLines.length < this.maxLinesRendered && this.overlayStack.length === 0) {\n\t\t\trenderChanged();\n\t\t\treturn;\n\t\t}\n\n\t\tlet firstChanged = -1;\n\t\tlet lastChanged = -1;\n\t\tconst maxLines = Math.max(newLines.length, this.previousLines.length);\n\t\tfor (let i = 0; i < maxLines; i++) {\n\t\t\tconst oldLine = i < this.previousLines.length ? this.previousLines[i] : \"\";\n\t\t\tconst newLine = i < newLines.length ? newLines[i] : \"\";\n\t\t\tif (oldLine !== newLine) {\n\t\t\t\tif (firstChanged === -1) firstChanged = i;\n\t\t\t\tlastChanged = i;\n\t\t\t}\n\t\t}\n\t\tif (newLines.length > this.previousLines.length) {\n\t\t\tif (firstChanged === -1) firstChanged = this.previousLines.length;\n\t\t\tlastChanged = newLines.length - 1;\n\t\t}\n\t\tif (firstChanged !== -1) lastChanged = this.expandLastChangedForKittyImages(firstChanged, lastChanged);\n\n\t\tif (firstChanged === -1) {\n\t\t\t// No content changed, but cursor position may have — wrap in\n\t\t\t// sync mode so the cursor move is atomic with the frame.\n\t\t\tconst seq = this.buildHardwareCursorSequence(cursorPos, newLines.length);\n\t\t\tthis.terminal.write(`\\x1b[?2026h${TUI.CURSOR_HIDE_PREFIX}${seq}\\x1b[?2026l`);\n\t\t\tthis.previousViewportTop = scrollableViewportTop;\n\t\t\tthis.previousHeight = height;\n\t\t\treturn;\n\t\t}\n\n\t\t// If >50% of visible lines changed, do a full re-render (more efficient than incremental)\n\t\tif (lastChanged - firstChanged + 1 > height * 0.5 || firstChanged < 0) {\n\t\t\trenderChanged();\n\t\t\treturn;\n\t\t}\n\n\t\t// All changes are in deleted lines (nothing to render, just clear)\n\t\tif (firstChanged >= newLines.length) {\n\t\t\tif (this.previousLines.length > newLines.length) {\n\t\t\t\tlet buffer = \"\\x1b[?2026h\";\n\t\t\t\tbuffer += this.deleteChangedKittyImages(firstChanged, lastChanged);\n\t\t\t\t// Move to end of new content (clamp to 0 for empty content)\n\t\t\t\tconst targetRow = Math.max(0, newLines.length - 1);\n\t\t\t\tif (targetRow < this.previousViewportTop) {\n\t\t\t\t\trenderChanged();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst lineDiff = targetRow - this.hardwareCursorRow;\n\t\t\t\tif (lineDiff > 0) buffer += `\\x1b[${lineDiff}B`;\n\t\t\t\telse if (lineDiff < 0) buffer += `\\x1b[${-lineDiff}A`;\n\t\t\t\tbuffer += \"\\r\";\n\t\t\t\t// Clear extra lines without scrolling\n\t\t\t\tconst extraLines = this.previousLines.length - newLines.length;\n\t\t\t\tif (extraLines > height) {\n\t\t\t\t\trenderChanged();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst clearStartOffset = newLines.length === 0 ? 0 : 1;\n\t\t\t\tif (extraLines > 0 && clearStartOffset > 0) {\n\t\t\t\t\tbuffer += `\\x1b[${clearStartOffset}B`;\n\t\t\t\t}\n\t\t\t\tfor (let i = 0; i < extraLines; i++) {\n\t\t\t\t\tbuffer += \"\\r\\x1b[2K\";\n\t\t\t\t\tif (i < extraLines - 1) buffer += \"\\x1b[1B\";\n\t\t\t\t}\n\t\t\t\tconst moveBack = Math.max(0, extraLines - 1 + clearStartOffset);\n\t\t\t\tif (moveBack > 0) {\n\t\t\t\t\tbuffer += `\\x1b[${moveBack}A`;\n\t\t\t\t}\n\t\t\t\tbuffer += \"\\x1b[?2026l\";\n\t\t\t\tthis.terminal.write(buffer);\n\t\t\t\tthis.cursorRow = targetRow;\n\t\t\t\tthis.hardwareCursorRow = targetRow;\n\t\t\t}\n\t\t\tthis.terminal.write(this.buildHardwareCursorSequence(cursorPos, newLines.length));\n\t\t\tthis.previousLines = newLines;\n\t\t\tthis.previousKittyImageIds = this.collectKittyImageIds(newLines);\n\t\t\tthis.previousWidth = width;\n\t\t\tthis.previousHeight = height;\n\t\t\tthis.previousViewportTop = scrollableViewportTop;\n\t\t\treturn;\n\t\t}\n\n\t\tlet buffer = `\\x1b[?2026h${TUI.CURSOR_HIDE_PREFIX}`;\n\t\tbuffer += this.deleteChangedKittyImages(firstChanged, lastChanged);\n\t\tconst renderEnd = Math.min(lastChanged, newLines.length - 1);\n\t\tfor (let i = firstChanged; i <= renderEnd; i++) {\n\t\t\tbuffer += `\\x1b[${i + 1};1H\\x1b[2K\\x1b[0m${newLines[i]}`;\n\t\t}\n\t\tif (newLines.length < this.previousLines.length) {\n\t\t\tfor (let i = newLines.length; i < this.previousLines.length; i++) {\n\t\t\t\tbuffer += `\\x1b[${i + 1};1H\\x1b[2K`;\n\t\t\t}\n\t\t}\n\t\tbuffer += this.buildHardwareCursorSequence(cursorPos, newLines.length);\n\t\tbuffer += \"\\x1b[?2026l\";\n\t\tthis.terminal.write(buffer);\n\t\tthis.cursorRow = Math.max(0, newLines.length - 1);\n\t\tthis.previousLines = newLines;\n\t\tthis.previousKittyImageIds = this.collectKittyImageIds(newLines);\n\t\tthis.previousWidth = width;\n\t\tthis.previousHeight = height;\n\t\tthis.previousViewportTop = scrollableViewportTop;\n\t}\n\n\t/**\n\t * Build escape sequences for positioning the hardware cursor.\n\t * Returned string should be appended to the render buffer *before*\n\t * the sync-mode terminator (\\x1b[?2026l) so the cursor state change\n\t * is atomic with the content update and never causes a visible flash.\n\t * @param cursorPos The cursor position extracted from rendered output, or null\n\t * @param totalLines Total number of rendered lines\n\t */\n\tprivate buildHardwareCursorSequence(cursorPos: { row: number; col: number } | null, totalLines: number): string {\n\t\tif (!cursorPos || totalLines <= 0) {\n\t\t\treturn \"\\x1b[?25l\";\n\t\t}\n\n\t\tconst targetRow = Math.max(0, Math.min(cursorPos.row, totalLines - 1));\n\t\tconst targetCol = Math.max(0, cursorPos.col);\n\n\t\tthis.hardwareCursorRow = targetRow;\n\n\t\tif (this.showHardwareCursor) {\n\t\t\t// DECSCUSR Ps=6: steady bar cursor — non-blinking, unobtrusive,\n\t\t\t// and ensures IME frameworks track the cursor position reliably.\n\t\t\treturn `\\x1b[${targetRow + 1};${targetCol + 1}H\\x1b[6 q\\x1b[?25h`;\n\t\t}\n\t\t// Hide then move — both inside the sync-mode buffer so the\n\t\t// terminal never shows the cursor at an intermediate position.\n\t\treturn `\\x1b[?25l\\x1b[${targetRow + 1};${targetCol + 1}H`;\n\t}\n\n\t/**\n\t * Cursor-hide prefix to place at the start of every render buffer,\n\t * before any content updates. Guarantees the hardware cursor is\n\t * invisible before the terminal processes line changes, which\n\t * prevents the cursor from briefly appearing at stale positions\n\t * on terminals with imperfect sync-mode support.\n\t */\n\tprivate static readonly CURSOR_HIDE_PREFIX = \"\\x1b[?25l\";\n}\n"]}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Generic undo stack with clone-on-push semantics.
3
+ *
4
+ * Stores deep clones of state snapshots. Popped snapshots are returned
5
+ * directly (no re-cloning) since they are already detached.
6
+ */
7
+ export declare class UndoStack<S> {
8
+ private stack;
9
+ /** Push a deep clone of the given state onto the stack. */
10
+ push(state: S): void;
11
+ /** Pop and return the most recent snapshot, or undefined if empty. */
12
+ pop(): S | undefined;
13
+ /** Remove all snapshots. */
14
+ clear(): void;
15
+ get length(): number;
16
+ }
17
+ //# sourceMappingURL=undo-stack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"undo-stack.d.ts","sourceRoot":"","sources":["../src/undo-stack.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,qBAAa,SAAS,CAAC,CAAC;IACvB,OAAO,CAAC,KAAK,CAAW;IAExB,2DAA2D;IAC3D,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,CAEnB;IAED,sEAAsE;IACtE,GAAG,IAAI,CAAC,GAAG,SAAS,CAEnB;IAED,4BAA4B;IAC5B,KAAK,IAAI,IAAI,CAEZ;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;CACD","sourcesContent":["/**\n * Generic undo stack with clone-on-push semantics.\n *\n * Stores deep clones of state snapshots. Popped snapshots are returned\n * directly (no re-cloning) since they are already detached.\n */\nexport class UndoStack<S> {\n\tprivate stack: S[] = [];\n\n\t/** Push a deep clone of the given state onto the stack. */\n\tpush(state: S): void {\n\t\tthis.stack.push(structuredClone(state));\n\t}\n\n\t/** Pop and return the most recent snapshot, or undefined if empty. */\n\tpop(): S | undefined {\n\t\treturn this.stack.pop();\n\t}\n\n\t/** Remove all snapshots. */\n\tclear(): void {\n\t\tthis.stack.length = 0;\n\t}\n\n\tget length(): number {\n\t\treturn this.stack.length;\n\t}\n}\n"]}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Generic undo stack with clone-on-push semantics.
3
+ *
4
+ * Stores deep clones of state snapshots. Popped snapshots are returned
5
+ * directly (no re-cloning) since they are already detached.
6
+ */
7
+ export class UndoStack {
8
+ stack = [];
9
+ /** Push a deep clone of the given state onto the stack. */
10
+ push(state) {
11
+ this.stack.push(structuredClone(state));
12
+ }
13
+ /** Pop and return the most recent snapshot, or undefined if empty. */
14
+ pop() {
15
+ return this.stack.pop();
16
+ }
17
+ /** Remove all snapshots. */
18
+ clear() {
19
+ this.stack.length = 0;
20
+ }
21
+ get length() {
22
+ return this.stack.length;
23
+ }
24
+ }
25
+ //# sourceMappingURL=undo-stack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"undo-stack.js","sourceRoot":"","sources":["../src/undo-stack.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,OAAO,SAAS;IACb,KAAK,GAAQ,EAAE,CAAC;IAExB,2DAA2D;IAC3D,IAAI,CAAC,KAAQ,EAAQ;QACpB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC;IAAA,CACxC;IAED,sEAAsE;IACtE,GAAG,GAAkB;QACpB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;IAAA,CACxB;IAED,4BAA4B;IAC5B,KAAK,GAAS;QACb,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;IAAA,CACtB;IAED,IAAI,MAAM,GAAW;QACpB,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;IAAA,CACzB;CACD","sourcesContent":["/**\n * Generic undo stack with clone-on-push semantics.\n *\n * Stores deep clones of state snapshots. Popped snapshots are returned\n * directly (no re-cloning) since they are already detached.\n */\nexport class UndoStack<S> {\n\tprivate stack: S[] = [];\n\n\t/** Push a deep clone of the given state onto the stack. */\n\tpush(state: S): void {\n\t\tthis.stack.push(structuredClone(state));\n\t}\n\n\t/** Pop and return the most recent snapshot, or undefined if empty. */\n\tpop(): S | undefined {\n\t\treturn this.stack.pop();\n\t}\n\n\t/** Remove all snapshots. */\n\tclear(): void {\n\t\tthis.stack.length = 0;\n\t}\n\n\tget length(): number {\n\t\treturn this.stack.length;\n\t}\n}\n"]}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Get the shared grapheme segmenter instance.
3
+ */
4
+ export declare function getGraphemeSegmenter(): Intl.Segmenter;
5
+ /**
6
+ * Get the shared word segmenter instance.
7
+ */
8
+ export declare function getWordSegmenter(): Intl.Segmenter;
9
+ export declare const cjkBreakRegex: RegExp;
10
+ /**
11
+ * Calculate the visible width of a string in terminal columns.
12
+ */
13
+ export declare function stripAnsi(str: string): string;
14
+ export declare function visibleWidth(str: string): number;
15
+ export declare function normalizeTerminalOutput(str: string): string;
16
+ /**
17
+ * Extract ANSI escape sequences from a string at the given position.
18
+ */
19
+ export declare function extractAnsiCode(str: string, pos: number): {
20
+ code: string;
21
+ length: number;
22
+ } | null;
23
+ /**
24
+ * Wrap text with ANSI codes preserved.
25
+ *
26
+ * ONLY does word wrapping - NO padding, NO background colors.
27
+ * Returns lines where each line is <= width visible chars.
28
+ * Active ANSI codes are preserved across line breaks.
29
+ *
30
+ * @param text - Text to wrap (may contain ANSI codes and newlines)
31
+ * @param width - Maximum visible width per line
32
+ * @returns Array of wrapped lines (NOT padded to width)
33
+ */
34
+ export declare function wrapTextWithAnsi(text: string, width: number): string[];
35
+ export declare const PUNCTUATION_REGEX: RegExp;
36
+ /**
37
+ * Check if a character is whitespace.
38
+ */
39
+ export declare function isWhitespaceChar(char: string): boolean;
40
+ /**
41
+ * Check if a character is punctuation.
42
+ */
43
+ export declare function isPunctuationChar(char: string): boolean;
44
+ /**
45
+ * Apply background color to a line, padding to full width.
46
+ *
47
+ * @param line - Line of text (may contain ANSI codes)
48
+ * @param width - Total width to pad to
49
+ * @param bgFn - Background color function
50
+ * @returns Line with background applied and padded to width
51
+ */
52
+ export declare function applyBackgroundToLine(line: string, width: number, bgFn: (text: string) => string): string;
53
+ /**
54
+ * Truncate text to fit within a maximum visible width, adding ellipsis if needed.
55
+ * Optionally pad with spaces to reach exactly maxWidth.
56
+ * Properly handles ANSI escape codes (they don't count toward width).
57
+ *
58
+ * @param text - Text to truncate (may contain ANSI codes)
59
+ * @param maxWidth - Maximum visible width
60
+ * @param ellipsis - Ellipsis string to append when truncating (default: "...")
61
+ * @param pad - If true, pad result with spaces to exactly maxWidth (default: false)
62
+ * @returns Truncated text, optionally padded to exactly maxWidth
63
+ */
64
+ export declare function truncateToWidth(text: string, maxWidth: number, ellipsis?: string, pad?: boolean): string;
65
+ /**
66
+ * Snap a visible column position to the nearest grapheme cluster boundary.
67
+ *
68
+ * When a mouse click lands on the second column of a wide character (e.g. CJK
69
+ * character occupying columns 2-3, click at column 3), the column does not
70
+ * correspond to a real character start. This function walks the line's
71
+ * grapheme clusters and returns the start column of the grapheme that contains
72
+ * the given column, ensuring the column always points to a valid character
73
+ * boundary.
74
+ *
75
+ * @param line - The line of text (may contain ANSI codes)
76
+ * @param col - The visible column to snap
77
+ * @returns The nearest grapheme-start column that is <= col
78
+ */
79
+ export declare function snapColToGraphemeBoundary(line: string, col: number): number;
80
+ /**
81
+ * Extract a range of visible columns from a line. Handles ANSI codes and wide chars.
82
+ * @param strict - If true, exclude wide chars at boundary that would extend past the range
83
+ */
84
+ export declare function sliceByColumn(line: string, startCol: number, length: number, strict?: boolean): string;
85
+ /** Like sliceByColumn but also returns the actual visible width of the result. */
86
+ export declare function sliceWithWidth(line: string, startCol: number, length: number, strict?: boolean): {
87
+ text: string;
88
+ width: number;
89
+ };
90
+ /**
91
+ * Extract "before" and "after" segments from a line in a single pass.
92
+ * Used for overlay compositing where we need content before and after the overlay region.
93
+ * Preserves styling from before the overlay that should affect content after it.
94
+ */
95
+ export declare function extractSegments(line: string, beforeEnd: number, afterStart: number, afterLen: number, strictAfter?: boolean): {
96
+ before: string;
97
+ beforeWidth: number;
98
+ after: string;
99
+ afterWidth: number;
100
+ };
101
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAAC,SAAS,CAErD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAAC,SAAS,CAEjD;AA6BD,eAAO,MAAM,aAAa,QAC2H,CAAC;AAoKtJ;;GAEG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAO7C;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAuDhD;AAWD,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAG3D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAsCjG;AAmWD;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAuBtE;AAmFD,eAAO,MAAM,iBAAiB,QAAyC,CAAC;AAExE;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEvD;AAuED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,MAAM,CASzG;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC9B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,QAAQ,GAAE,MAAc,EACxB,GAAG,GAAE,OAAe,GAClB,MAAM,CAmIR;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAuB3E;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,UAAQ,GAAG,MAAM,CAEpG;AAED,kFAAkF;AAClF,wBAAgB,cAAc,CAC7B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,MAAM,UAAQ,GACZ;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAwCjC;AAKD;;;;GAIG;AACH,wBAAgB,eAAe,CAC9B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,WAAW,UAAQ,GACjB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAiE5E","sourcesContent":["import { eastAsianWidth } from \"get-east-asian-width\";\n\n// segmenters (shared instance)\nconst graphemeSegmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\nconst wordSegmenter = new Intl.Segmenter(undefined, { granularity: \"word\" });\n\n/**\n * Get the shared grapheme segmenter instance.\n */\nexport function getGraphemeSegmenter(): Intl.Segmenter {\n\treturn graphemeSegmenter;\n}\n\n/**\n * Get the shared word segmenter instance.\n */\nexport function getWordSegmenter(): Intl.Segmenter {\n\treturn wordSegmenter;\n}\n\n/**\n * Check if a grapheme cluster (after segmentation) could possibly be an RGI emoji.\n * This is a fast heuristic to avoid the expensive rgiEmojiRegex test.\n * The tested Unicode blocks are deliberately broad to account for future\n * Unicode additions.\n */\nfunction couldBeEmoji(segment: string): boolean {\n\tconst cp = segment.codePointAt(0)!;\n\treturn (\n\t\t(cp >= 0x1f000 && cp <= 0x1fbff) || // Emoji and Pictograph\n\t\t(cp >= 0x2300 && cp <= 0x23ff) || // Misc technical\n\t\t(cp >= 0x2600 && cp <= 0x27bf) || // Misc symbols, dingbats\n\t\t(cp >= 0x2b50 && cp <= 0x2b55) || // Specific stars/circles\n\t\tsegment.includes(\"\\uFE0F\") || // Contains VS16 (emoji presentation selector)\n\t\tsegment.length > 2 // Multi-codepoint sequences (ZWJ, skin tones, etc.)\n\t);\n}\n\n// Regexes for character classification (same as string-width library)\nconst zeroWidthRegex = /^(?:\\p{Default_Ignorable_Code_Point}|\\p{Control}|\\p{Mark}|\\p{Surrogate})+$/v;\nconst leadingNonPrintingRegex = /^[\\p{Default_Ignorable_Code_Point}\\p{Control}\\p{Format}\\p{Mark}\\p{Surrogate}]+/v;\nconst rgiEmojiRegex = /^\\p{RGI_Emoji}$/v;\n\n// Cache for non-ASCII strings\nconst WIDTH_CACHE_SIZE = 512;\nconst widthCache = new Map<string, number>();\n\nexport const cjkBreakRegex =\n\t/[\\p{Script_Extensions=Han}\\p{Script_Extensions=Hiragana}\\p{Script_Extensions=Katakana}\\p{Script_Extensions=Hangul}\\p{Script_Extensions=Bopomofo}]/u;\n\nfunction isPrintableAscii(str: string): boolean {\n\tfor (let i = 0; i < str.length; i++) {\n\t\tconst code = str.charCodeAt(i);\n\t\tif (code < 0x20 || code > 0x7e) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\nfunction truncateFragmentToWidth(text: string, maxWidth: number): { text: string; width: number } {\n\tif (maxWidth <= 0 || text.length === 0) {\n\t\treturn { text: \"\", width: 0 };\n\t}\n\n\tif (isPrintableAscii(text)) {\n\t\tconst clipped = text.slice(0, maxWidth);\n\t\treturn { text: clipped, width: clipped.length };\n\t}\n\n\tconst hasAnsi = text.includes(\"\\x1b\");\n\tconst hasTabs = text.includes(\"\\t\");\n\tif (!hasAnsi && !hasTabs) {\n\t\tlet result = \"\";\n\t\tlet width = 0;\n\t\tfor (const { segment } of graphemeSegmenter.segment(text)) {\n\t\t\tconst w = graphemeWidth(segment);\n\t\t\tif (width + w > maxWidth) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tresult += segment;\n\t\t\twidth += w;\n\t\t}\n\t\treturn { text: result, width };\n\t}\n\n\tlet result = \"\";\n\tlet width = 0;\n\tlet i = 0;\n\tlet pendingAnsi = \"\";\n\n\twhile (i < text.length) {\n\t\tconst ansi = extractAnsiCode(text, i);\n\t\tif (ansi) {\n\t\t\tpendingAnsi += ansi.code;\n\t\t\ti += ansi.length;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (text[i] === \"\\t\") {\n\t\t\tif (width + 3 > maxWidth) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (pendingAnsi) {\n\t\t\t\tresult += pendingAnsi;\n\t\t\t\tpendingAnsi = \"\";\n\t\t\t}\n\t\t\tresult += \"\\t\";\n\t\t\twidth += 3;\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tlet end = i;\n\t\twhile (end < text.length && text[end] !== \"\\t\") {\n\t\t\tconst nextAnsi = extractAnsiCode(text, end);\n\t\t\tif (nextAnsi) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tend++;\n\t\t}\n\n\t\tfor (const { segment } of graphemeSegmenter.segment(text.slice(i, end))) {\n\t\t\tconst w = graphemeWidth(segment);\n\t\t\tif (width + w > maxWidth) {\n\t\t\t\treturn { text: result, width };\n\t\t\t}\n\t\t\tif (pendingAnsi) {\n\t\t\t\tresult += pendingAnsi;\n\t\t\t\tpendingAnsi = \"\";\n\t\t\t}\n\t\t\tresult += segment;\n\t\t\twidth += w;\n\t\t}\n\t\ti = end;\n\t}\n\n\treturn { text: result, width };\n}\n\nfunction finalizeTruncatedResult(\n\tprefix: string,\n\tprefixWidth: number,\n\tellipsis: string,\n\tellipsisWidth: number,\n\tmaxWidth: number,\n\tpad: boolean,\n): string {\n\tconst reset = \"\\x1b[0m\";\n\tconst visibleWidth = prefixWidth + ellipsisWidth;\n\tlet result: string;\n\n\tif (ellipsis.length > 0) {\n\t\tresult = `${prefix}${reset}${ellipsis}${reset}`;\n\t} else {\n\t\tresult = `${prefix}${reset}`;\n\t}\n\n\treturn pad ? result + \" \".repeat(Math.max(0, maxWidth - visibleWidth)) : result;\n}\n\n/**\n * Calculate the terminal width of a single grapheme cluster.\n * Based on code from the string-width library, but includes a possible-emoji\n * check to avoid running the RGI_Emoji regex unnecessarily.\n */\nfunction graphemeWidth(segment: string): number {\n\tif (segment === \"\\t\") {\n\t\treturn 3;\n\t}\n\n\t// Zero-width clusters\n\tif (zeroWidthRegex.test(segment)) {\n\t\treturn 0;\n\t}\n\n\t// Emoji check with pre-filter\n\tif (couldBeEmoji(segment) && rgiEmojiRegex.test(segment)) {\n\t\treturn 2;\n\t}\n\n\t// Get base visible codepoint\n\tconst base = segment.replace(leadingNonPrintingRegex, \"\");\n\tconst cp = base.codePointAt(0);\n\tif (cp === undefined) {\n\t\treturn 0;\n\t}\n\n\t// Regional indicator symbols (U+1F1E6..U+1F1FF) are often rendered as\n\t// full-width emoji in terminals, even when isolated during streaming.\n\t// Keep width conservative (2) to avoid terminal auto-wrap drift artifacts.\n\tif (cp >= 0x1f1e6 && cp <= 0x1f1ff) {\n\t\treturn 2;\n\t}\n\n\tlet width = eastAsianWidth(cp);\n\n\t// Trailing halfwidth/fullwidth forms and AM vowels that segment with a base.\n\tif (segment.length > 1) {\n\t\tfor (const char of segment.slice(1)) {\n\t\t\tconst c = char.codePointAt(0)!;\n\t\t\tif (c >= 0xff00 && c <= 0xffef) {\n\t\t\t\twidth += eastAsianWidth(c);\n\t\t\t} else if (c === 0x0e33 || c === 0x0eb3) {\n\t\t\t\twidth += 1;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn width;\n}\n\n/**\n * Calculate the visible width of a string in terminal columns.\n */\nexport function stripAnsi(str: string): string {\n\t// eslint-disable-next-line no-control-regex\n\treturn str\n\t\t.replace(/\\x1b\\[[0-9;]*[a-zA-Z]/g, \"\")\n\t\t.replace(/\\x1b\\].*?\\x07/g, \"\")\n\t\t.replace(/\\x1b_.*?\\x07/g, \"\")\n\t\t.replace(/\\x1b\\[<[^>]*>/g, \"\");\n}\n\nexport function visibleWidth(str: string): number {\n\tif (str.length === 0) {\n\t\treturn 0;\n\t}\n\n\t// Fast path: pure ASCII printable\n\tif (isPrintableAscii(str)) {\n\t\treturn str.length;\n\t}\n\n\t// Check cache\n\tconst cached = widthCache.get(str);\n\tif (cached !== undefined) {\n\t\treturn cached;\n\t}\n\n\t// Normalize: tabs to 3 spaces, strip ANSI escape codes\n\tlet clean = str;\n\tif (str.includes(\"\\t\")) {\n\t\tclean = clean.replace(/\\t/g, \" \");\n\t}\n\tif (clean.includes(\"\\x1b\")) {\n\t\t// Strip supported ANSI/OSC/APC escape sequences in one pass.\n\t\t// This covers CSI styling/cursor codes, OSC hyperlinks and prompt markers,\n\t\t// and APC sequences like CURSOR_MARKER.\n\t\tlet stripped = \"\";\n\t\tlet i = 0;\n\t\twhile (i < clean.length) {\n\t\t\tconst ansi = extractAnsiCode(clean, i);\n\t\t\tif (ansi) {\n\t\t\t\ti += ansi.length;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tstripped += clean[i];\n\t\t\ti++;\n\t\t}\n\t\tclean = stripped;\n\t}\n\n\t// Calculate width\n\tlet width = 0;\n\tfor (const { segment } of graphemeSegmenter.segment(clean)) {\n\t\twidth += graphemeWidth(segment);\n\t}\n\n\t// Cache result\n\tif (widthCache.size >= WIDTH_CACHE_SIZE) {\n\t\tconst firstKey = widthCache.keys().next().value;\n\t\tif (firstKey !== undefined) {\n\t\t\twidthCache.delete(firstKey);\n\t\t}\n\t}\n\twidthCache.set(str, width);\n\n\treturn width;\n}\n\n/**\n * Normalize text for terminal output without changing logical editor content.\n * Some terminals render precomposed Thai/Lao AM vowels inconsistently during\n * differential repaint. Their compatibility decompositions have the same cell\n * width but avoid stale-cell artifacts in terminal renderers.\n */\nconst THAI_LAO_AM_REGEX = /[\\u0e33\\u0eb3]/;\nconst THAI_LAO_AM_GLOBAL_REGEX = /[\\u0e33\\u0eb3]/g;\n\nexport function normalizeTerminalOutput(str: string): string {\n\tif (!THAI_LAO_AM_REGEX.test(str)) return str;\n\treturn str.replace(THAI_LAO_AM_GLOBAL_REGEX, (char) => (char === \"\\u0e33\" ? \"\\u0e4d\\u0e32\" : \"\\u0ecd\\u0eb2\"));\n}\n\n/**\n * Extract ANSI escape sequences from a string at the given position.\n */\nexport function extractAnsiCode(str: string, pos: number): { code: string; length: number } | null {\n\tif (pos >= str.length || str[pos] !== \"\\x1b\") return null;\n\n\tconst next = str[pos + 1];\n\n\t// CSI sequence: ESC [ ... m/G/K/H/J\n\tif (next === \"[\") {\n\t\tlet j = pos + 2;\n\t\twhile (j < str.length && !/[mGKHJ]/.test(str[j]!)) j++;\n\t\tif (j < str.length) return { code: str.substring(pos, j + 1), length: j + 1 - pos };\n\t\treturn null;\n\t}\n\n\t// OSC sequence: ESC ] ... BEL or ESC ] ... ST (ESC \\)\n\t// Used for hyperlinks (OSC 8), window titles, etc.\n\tif (next === \"]\") {\n\t\tlet j = pos + 2;\n\t\twhile (j < str.length) {\n\t\t\tif (str[j] === \"\\x07\") return { code: str.substring(pos, j + 1), length: j + 1 - pos };\n\t\t\tif (str[j] === \"\\x1b\" && str[j + 1] === \"\\\\\") return { code: str.substring(pos, j + 2), length: j + 2 - pos };\n\t\t\tj++;\n\t\t}\n\t\treturn null;\n\t}\n\n\t// APC sequence: ESC _ ... BEL or ESC _ ... ST (ESC \\)\n\t// Used for cursor marker and application-specific commands\n\tif (next === \"_\") {\n\t\tlet j = pos + 2;\n\t\twhile (j < str.length) {\n\t\t\tif (str[j] === \"\\x07\") return { code: str.substring(pos, j + 1), length: j + 1 - pos };\n\t\t\tif (str[j] === \"\\x1b\" && str[j + 1] === \"\\\\\") return { code: str.substring(pos, j + 2), length: j + 2 - pos };\n\t\t\tj++;\n\t\t}\n\t\treturn null;\n\t}\n\n\treturn null;\n}\n\ntype Osc8Terminator = \"\\x07\" | \"\\x1b\\\\\";\n\ninterface ActiveHyperlink {\n\tparams: string;\n\turl: string;\n\tterminator: Osc8Terminator;\n}\n\nfunction parseOsc8Hyperlink(ansiCode: string): ActiveHyperlink | null | undefined {\n\tif (!ansiCode.startsWith(\"\\x1b]8;\")) {\n\t\treturn undefined;\n\t}\n\n\tconst terminator: Osc8Terminator = ansiCode.endsWith(\"\\x07\") ? \"\\x07\" : \"\\x1b\\\\\";\n\tconst body = ansiCode.slice(4, terminator === \"\\x07\" ? -1 : -2);\n\tconst separatorIndex = body.indexOf(\";\");\n\tif (separatorIndex === -1) {\n\t\treturn undefined;\n\t}\n\n\tconst params = body.slice(0, separatorIndex);\n\tconst url = body.slice(separatorIndex + 1);\n\tif (!url) {\n\t\treturn null;\n\t}\n\treturn { params, url, terminator };\n}\n\nfunction formatOsc8Hyperlink(hyperlink: ActiveHyperlink): string {\n\treturn `\\x1b]8;${hyperlink.params};${hyperlink.url}${hyperlink.terminator}`;\n}\n\nfunction formatOsc8Close(terminator: Osc8Terminator): string {\n\treturn `\\x1b]8;;${terminator}`;\n}\n\n/**\n * Track active ANSI SGR codes to preserve styling across line breaks.\n */\nclass AnsiCodeTracker {\n\t// Track individual attributes separately so we can reset them specifically\n\tprivate bold = false;\n\tprivate dim = false;\n\tprivate italic = false;\n\tprivate underline = false;\n\tprivate blink = false;\n\tprivate inverse = false;\n\tprivate hidden = false;\n\tprivate strikethrough = false;\n\tprivate fgColor: string | null = null; // Stores the full code like \"31\" or \"38;5;240\"\n\tprivate bgColor: string | null = null; // Stores the full code like \"41\" or \"48;5;240\"\n\tprivate activeHyperlink: ActiveHyperlink | null = null;\n\n\tprocess(ansiCode: string): void {\n\t\t// OSC 8 hyperlink: \\x1b]8;;<url>\\x1b\\\\ (open) or \\x1b]8;;\\x1b\\\\ (close).\n\t\t// Preserve the original terminator because some terminals only make BEL-terminated\n\t\t// links clickable. OAuth login URLs use BEL, so reopening wrapped lines with ST\n\t\t// made only the first physical line clickable in those terminals.\n\t\tconst hyperlink = parseOsc8Hyperlink(ansiCode);\n\t\tif (hyperlink !== undefined) {\n\t\t\tthis.activeHyperlink = hyperlink;\n\t\t\treturn;\n\t\t}\n\n\t\tif (!ansiCode.endsWith(\"m\")) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Extract the parameters between \\x1b[ and m\n\t\tconst match = ansiCode.match(/\\x1b\\[([\\d;]*)m/);\n\t\tif (!match) return;\n\n\t\tconst params = match[1];\n\t\tif (params === \"\" || params === \"0\") {\n\t\t\t// Full reset\n\t\t\tthis.reset();\n\t\t\treturn;\n\t\t}\n\n\t\t// Parse parameters (can be semicolon-separated)\n\t\tconst parts = params.split(\";\");\n\t\tlet i = 0;\n\t\twhile (i < parts.length) {\n\t\t\tconst code = Number.parseInt(parts[i], 10);\n\n\t\t\t// Handle 256-color and RGB codes which consume multiple parameters\n\t\t\tif (code === 38 || code === 48) {\n\t\t\t\t// 38;5;N (256 color fg) or 38;2;R;G;B (RGB fg)\n\t\t\t\t// 48;5;N (256 color bg) or 48;2;R;G;B (RGB bg)\n\t\t\t\tif (parts[i + 1] === \"5\" && parts[i + 2] !== undefined) {\n\t\t\t\t\t// 256 color: 38;5;N or 48;5;N\n\t\t\t\t\tconst colorCode = `${parts[i]};${parts[i + 1]};${parts[i + 2]}`;\n\t\t\t\t\tif (code === 38) {\n\t\t\t\t\t\tthis.fgColor = colorCode;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.bgColor = colorCode;\n\t\t\t\t\t}\n\t\t\t\t\ti += 3;\n\t\t\t\t\tcontinue;\n\t\t\t\t} else if (parts[i + 1] === \"2\" && parts[i + 4] !== undefined) {\n\t\t\t\t\t// RGB color: 38;2;R;G;B or 48;2;R;G;B\n\t\t\t\t\tconst colorCode = `${parts[i]};${parts[i + 1]};${parts[i + 2]};${parts[i + 3]};${parts[i + 4]}`;\n\t\t\t\t\tif (code === 38) {\n\t\t\t\t\t\tthis.fgColor = colorCode;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.bgColor = colorCode;\n\t\t\t\t\t}\n\t\t\t\t\ti += 5;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Standard SGR codes\n\t\t\tswitch (code) {\n\t\t\t\tcase 0:\n\t\t\t\t\tthis.reset();\n\t\t\t\t\tbreak;\n\t\t\t\tcase 1:\n\t\t\t\t\tthis.bold = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tthis.dim = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:\n\t\t\t\t\tthis.italic = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 4:\n\t\t\t\t\tthis.underline = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 5:\n\t\t\t\t\tthis.blink = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 7:\n\t\t\t\t\tthis.inverse = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 8:\n\t\t\t\t\tthis.hidden = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 9:\n\t\t\t\t\tthis.strikethrough = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 21:\n\t\t\t\t\tthis.bold = false;\n\t\t\t\t\tbreak; // Some terminals\n\t\t\t\tcase 22:\n\t\t\t\t\tthis.bold = false;\n\t\t\t\t\tthis.dim = false;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 23:\n\t\t\t\t\tthis.italic = false;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 24:\n\t\t\t\t\tthis.underline = false;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 25:\n\t\t\t\t\tthis.blink = false;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 27:\n\t\t\t\t\tthis.inverse = false;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 28:\n\t\t\t\t\tthis.hidden = false;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 29:\n\t\t\t\t\tthis.strikethrough = false;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 39:\n\t\t\t\t\tthis.fgColor = null;\n\t\t\t\t\tbreak; // Default fg\n\t\t\t\tcase 49:\n\t\t\t\t\tthis.bgColor = null;\n\t\t\t\t\tbreak; // Default bg\n\t\t\t\tdefault:\n\t\t\t\t\t// Standard foreground colors 30-37, 90-97\n\t\t\t\t\tif ((code >= 30 && code <= 37) || (code >= 90 && code <= 97)) {\n\t\t\t\t\t\tthis.fgColor = String(code);\n\t\t\t\t\t}\n\t\t\t\t\t// Standard background colors 40-47, 100-107\n\t\t\t\t\telse if ((code >= 40 && code <= 47) || (code >= 100 && code <= 107)) {\n\t\t\t\t\t\tthis.bgColor = String(code);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\ti++;\n\t\t}\n\t}\n\n\tprivate reset(): void {\n\t\tthis.bold = false;\n\t\tthis.dim = false;\n\t\tthis.italic = false;\n\t\tthis.underline = false;\n\t\tthis.blink = false;\n\t\tthis.inverse = false;\n\t\tthis.hidden = false;\n\t\tthis.strikethrough = false;\n\t\tthis.fgColor = null;\n\t\tthis.bgColor = null;\n\t\t// SGR reset does not affect OSC 8 hyperlink state\n\t}\n\n\t/** Clear all state for reuse. */\n\tclear(): void {\n\t\tthis.reset();\n\t\tthis.activeHyperlink = null;\n\t}\n\n\tgetActiveCodes(): string {\n\t\tconst codes: string[] = [];\n\t\tif (this.bold) codes.push(\"1\");\n\t\tif (this.dim) codes.push(\"2\");\n\t\tif (this.italic) codes.push(\"3\");\n\t\tif (this.underline) codes.push(\"4\");\n\t\tif (this.blink) codes.push(\"5\");\n\t\tif (this.inverse) codes.push(\"7\");\n\t\tif (this.hidden) codes.push(\"8\");\n\t\tif (this.strikethrough) codes.push(\"9\");\n\t\tif (this.fgColor) codes.push(this.fgColor);\n\t\tif (this.bgColor) codes.push(this.bgColor);\n\n\t\tlet result = codes.length > 0 ? `\\x1b[${codes.join(\";\")}m` : \"\";\n\t\tif (this.activeHyperlink) {\n\t\t\tresult += formatOsc8Hyperlink(this.activeHyperlink);\n\t\t}\n\t\treturn result;\n\t}\n\n\thasActiveCodes(): boolean {\n\t\treturn (\n\t\t\tthis.bold ||\n\t\t\tthis.dim ||\n\t\t\tthis.italic ||\n\t\t\tthis.underline ||\n\t\t\tthis.blink ||\n\t\t\tthis.inverse ||\n\t\t\tthis.hidden ||\n\t\t\tthis.strikethrough ||\n\t\t\tthis.fgColor !== null ||\n\t\t\tthis.bgColor !== null ||\n\t\t\tthis.activeHyperlink !== null\n\t\t);\n\t}\n\n\t/**\n\t * Get reset codes for attributes that need to be turned off at line end.\n\t * Underline must be closed to prevent bleeding into padding.\n\t * Active OSC 8 hyperlinks must be closed and re-opened on the next line.\n\t * Returns empty string if no attributes need closing.\n\t */\n\tgetLineEndReset(): string {\n\t\tlet result = \"\";\n\t\tif (this.underline) {\n\t\t\tresult += \"\\x1b[24m\"; // Underline off only\n\t\t}\n\t\tif (this.activeHyperlink) {\n\t\t\tresult += formatOsc8Close(this.activeHyperlink.terminator); // Re-opened at line start via getActiveCodes()\n\t\t}\n\t\treturn result;\n\t}\n}\n\nfunction updateTrackerFromText(text: string, tracker: AnsiCodeTracker): void {\n\tlet i = 0;\n\twhile (i < text.length) {\n\t\tconst ansiResult = extractAnsiCode(text, i);\n\t\tif (ansiResult) {\n\t\t\ttracker.process(ansiResult.code);\n\t\t\ti += ansiResult.length;\n\t\t} else {\n\t\t\ti++;\n\t\t}\n\t}\n}\n\n/**\n * Split text into words while keeping ANSI codes attached.\n */\nfunction splitIntoTokensWithAnsi(text: string): string[] {\n\tconst tokens: string[] = [];\n\tlet current = \"\";\n\tlet pendingAnsi = \"\"; // ANSI codes waiting to be attached to next visible content\n\tlet currentKind: \"space\" | \"word\" | null = null;\n\tlet i = 0;\n\n\tconst flushCurrent = (): void => {\n\t\tif (!current) {\n\t\t\treturn;\n\t\t}\n\t\ttokens.push(current);\n\t\tcurrent = \"\";\n\t\tcurrentKind = null;\n\t};\n\n\twhile (i < text.length) {\n\t\tconst ansiResult = extractAnsiCode(text, i);\n\t\tif (ansiResult) {\n\t\t\t// Hold ANSI codes separately - they'll be attached to the next visible char\n\t\t\tpendingAnsi += ansiResult.code;\n\t\t\ti += ansiResult.length;\n\t\t\tcontinue;\n\t\t}\n\n\t\tlet end = i;\n\t\twhile (end < text.length && !extractAnsiCode(text, end)) {\n\t\t\tend++;\n\t\t}\n\n\t\tfor (const { segment } of graphemeSegmenter.segment(text.slice(i, end))) {\n\t\t\tconst segmentIsSpace = segment === \" \";\n\t\t\tif (!segmentIsSpace && cjkBreakRegex.test(segment)) {\n\t\t\t\tflushCurrent();\n\t\t\t\tconst token = pendingAnsi + segment;\n\t\t\t\tpendingAnsi = \"\";\n\t\t\t\ttokens.push(token);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst segmentKind = segmentIsSpace ? \"space\" : \"word\";\n\t\t\tif (current && currentKind !== segmentKind) {\n\t\t\t\tflushCurrent();\n\t\t\t}\n\n\t\t\t// Attach any pending ANSI codes to this visible character\n\t\t\tif (pendingAnsi) {\n\t\t\t\tcurrent += pendingAnsi;\n\t\t\t\tpendingAnsi = \"\";\n\t\t\t}\n\n\t\t\tcurrentKind = segmentKind;\n\t\t\tcurrent += segment;\n\t\t}\n\n\t\ti = end;\n\t}\n\n\t// Handle any remaining pending ANSI codes (attach to last token)\n\tif (pendingAnsi) {\n\t\tif (current) {\n\t\t\tcurrent += pendingAnsi;\n\t\t} else if (tokens.length > 0) {\n\t\t\ttokens[tokens.length - 1] += pendingAnsi;\n\t\t} else {\n\t\t\tcurrent = pendingAnsi;\n\t\t}\n\t}\n\n\tif (current) {\n\t\ttokens.push(current);\n\t}\n\n\treturn tokens;\n}\n\n/**\n * Wrap text with ANSI codes preserved.\n *\n * ONLY does word wrapping - NO padding, NO background colors.\n * Returns lines where each line is <= width visible chars.\n * Active ANSI codes are preserved across line breaks.\n *\n * @param text - Text to wrap (may contain ANSI codes and newlines)\n * @param width - Maximum visible width per line\n * @returns Array of wrapped lines (NOT padded to width)\n */\nexport function wrapTextWithAnsi(text: string, width: number): string[] {\n\tif (!text) {\n\t\treturn [\"\"];\n\t}\n\n\t// Handle newlines by processing each line separately\n\t// Track ANSI state across lines so styles carry over after literal newlines\n\tconst inputLines = text.split(\"\\n\");\n\tconst result: string[] = [];\n\tconst tracker = new AnsiCodeTracker();\n\n\tfor (const inputLine of inputLines) {\n\t\t// Prepend active ANSI codes from previous lines (except for first line)\n\t\tconst prefix = result.length > 0 ? tracker.getActiveCodes() : \"\";\n\t\tconst wrappedLines = wrapSingleLine(prefix + inputLine, width);\n\t\tfor (const wrappedLine of wrappedLines) {\n\t\t\tresult.push(wrappedLine);\n\t\t}\n\t\t// Update tracker with codes from this line for next iteration\n\t\tupdateTrackerFromText(inputLine, tracker);\n\t}\n\n\treturn result.length > 0 ? result : [\"\"];\n}\n\nfunction wrapSingleLine(line: string, width: number): string[] {\n\tif (!line) {\n\t\treturn [\"\"];\n\t}\n\n\tconst visibleLength = visibleWidth(line);\n\tif (visibleLength <= width) {\n\t\treturn [line];\n\t}\n\n\tconst wrapped: string[] = [];\n\tconst tracker = new AnsiCodeTracker();\n\tconst tokens = splitIntoTokensWithAnsi(line);\n\n\tlet currentLine = \"\";\n\tlet currentVisibleLength = 0;\n\n\tfor (const token of tokens) {\n\t\tconst tokenVisibleLength = visibleWidth(token);\n\t\tconst isWhitespace = token.trim() === \"\";\n\n\t\t// Token itself is too long - break it character by character\n\t\tif (tokenVisibleLength > width && !isWhitespace) {\n\t\t\tif (currentLine) {\n\t\t\t\t// Add specific reset for underline only (preserves background)\n\t\t\t\tconst lineEndReset = tracker.getLineEndReset();\n\t\t\t\tif (lineEndReset) {\n\t\t\t\t\tcurrentLine += lineEndReset;\n\t\t\t\t}\n\t\t\t\twrapped.push(currentLine);\n\t\t\t\tcurrentLine = \"\";\n\t\t\t\tcurrentVisibleLength = 0;\n\t\t\t}\n\n\t\t\t// Break long token - breakLongWord handles its own resets\n\t\t\tconst broken = breakLongWord(token, width, tracker);\n\t\t\tfor (let i = 0; i < broken.length - 1; i++) {\n\t\t\t\twrapped.push(broken[i]!);\n\t\t\t}\n\t\t\tcurrentLine = broken[broken.length - 1];\n\t\t\tcurrentVisibleLength = visibleWidth(currentLine);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Check if adding this token would exceed width\n\t\tconst totalNeeded = currentVisibleLength + tokenVisibleLength;\n\n\t\tif (totalNeeded > width && currentVisibleLength > 0) {\n\t\t\t// Trim trailing whitespace, then add underline reset (not full reset, to preserve background)\n\t\t\tlet lineToWrap = currentLine.trimEnd();\n\t\t\tconst lineEndReset = tracker.getLineEndReset();\n\t\t\tif (lineEndReset) {\n\t\t\t\tlineToWrap += lineEndReset;\n\t\t\t}\n\t\t\twrapped.push(lineToWrap);\n\t\t\tif (isWhitespace) {\n\t\t\t\t// Don't start new line with whitespace\n\t\t\t\tcurrentLine = tracker.getActiveCodes();\n\t\t\t\tcurrentVisibleLength = 0;\n\t\t\t} else {\n\t\t\t\tcurrentLine = tracker.getActiveCodes() + token;\n\t\t\t\tcurrentVisibleLength = tokenVisibleLength;\n\t\t\t}\n\t\t} else {\n\t\t\t// Add to current line\n\t\t\tcurrentLine += token;\n\t\t\tcurrentVisibleLength += tokenVisibleLength;\n\t\t}\n\n\t\tupdateTrackerFromText(token, tracker);\n\t}\n\n\tif (currentLine) {\n\t\t// No reset at end of final line - let caller handle it\n\t\twrapped.push(currentLine);\n\t}\n\n\t// Trailing whitespace can cause lines to exceed the requested width\n\treturn wrapped.length > 0 ? wrapped.map((line) => line.trimEnd()) : [\"\"];\n}\n\nexport const PUNCTUATION_REGEX = /[(){}[\\]<>.,;:'\"!?+\\-=*/\\\\|&%^$#@~`]/;\n\n/**\n * Check if a character is whitespace.\n */\nexport function isWhitespaceChar(char: string): boolean {\n\treturn /\\s/.test(char);\n}\n\n/**\n * Check if a character is punctuation.\n */\nexport function isPunctuationChar(char: string): boolean {\n\treturn PUNCTUATION_REGEX.test(char);\n}\n\nfunction breakLongWord(word: string, width: number, tracker: AnsiCodeTracker): string[] {\n\tconst lines: string[] = [];\n\tlet currentLine = tracker.getActiveCodes();\n\tlet currentWidth = 0;\n\n\t// First, separate ANSI codes from visible content\n\t// We need to handle ANSI codes specially since they're not graphemes\n\tlet i = 0;\n\tconst segments: Array<{ type: \"ansi\" | \"grapheme\"; value: string }> = [];\n\n\twhile (i < word.length) {\n\t\tconst ansiResult = extractAnsiCode(word, i);\n\t\tif (ansiResult) {\n\t\t\tsegments.push({ type: \"ansi\", value: ansiResult.code });\n\t\t\ti += ansiResult.length;\n\t\t} else {\n\t\t\t// Find the next ANSI code or end of string\n\t\t\tlet end = i;\n\t\t\twhile (end < word.length) {\n\t\t\t\tconst nextAnsi = extractAnsiCode(word, end);\n\t\t\t\tif (nextAnsi) break;\n\t\t\t\tend++;\n\t\t\t}\n\t\t\t// Segment this non-ANSI portion into graphemes\n\t\t\tconst textPortion = word.slice(i, end);\n\t\t\tfor (const seg of graphemeSegmenter.segment(textPortion)) {\n\t\t\t\tsegments.push({ type: \"grapheme\", value: seg.segment });\n\t\t\t}\n\t\t\ti = end;\n\t\t}\n\t}\n\n\t// Now process segments\n\tfor (const seg of segments) {\n\t\tif (seg.type === \"ansi\") {\n\t\t\tcurrentLine += seg.value;\n\t\t\ttracker.process(seg.value);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst grapheme = seg.value;\n\t\t// Skip empty graphemes to avoid issues with string-width calculation\n\t\tif (!grapheme) continue;\n\n\t\tconst graphemeWidth = visibleWidth(grapheme);\n\n\t\tif (currentWidth + graphemeWidth > width) {\n\t\t\t// Add specific reset for underline only (preserves background)\n\t\t\tconst lineEndReset = tracker.getLineEndReset();\n\t\t\tif (lineEndReset) {\n\t\t\t\tcurrentLine += lineEndReset;\n\t\t\t}\n\t\t\tlines.push(currentLine);\n\t\t\tcurrentLine = tracker.getActiveCodes();\n\t\t\tcurrentWidth = 0;\n\t\t}\n\n\t\tcurrentLine += grapheme;\n\t\tcurrentWidth += graphemeWidth;\n\t}\n\n\tif (currentLine) {\n\t\t// No reset at end of final segment - caller handles continuation\n\t\tlines.push(currentLine);\n\t}\n\n\treturn lines.length > 0 ? lines : [\"\"];\n}\n\n/**\n * Apply background color to a line, padding to full width.\n *\n * @param line - Line of text (may contain ANSI codes)\n * @param width - Total width to pad to\n * @param bgFn - Background color function\n * @returns Line with background applied and padded to width\n */\nexport function applyBackgroundToLine(line: string, width: number, bgFn: (text: string) => string): string {\n\t// Calculate padding needed\n\tconst visibleLen = visibleWidth(line);\n\tconst paddingNeeded = Math.max(0, width - visibleLen);\n\tconst padding = \" \".repeat(paddingNeeded);\n\n\t// Apply background to content + padding\n\tconst withPadding = line + padding;\n\treturn bgFn(withPadding);\n}\n\n/**\n * Truncate text to fit within a maximum visible width, adding ellipsis if needed.\n * Optionally pad with spaces to reach exactly maxWidth.\n * Properly handles ANSI escape codes (they don't count toward width).\n *\n * @param text - Text to truncate (may contain ANSI codes)\n * @param maxWidth - Maximum visible width\n * @param ellipsis - Ellipsis string to append when truncating (default: \"...\")\n * @param pad - If true, pad result with spaces to exactly maxWidth (default: false)\n * @returns Truncated text, optionally padded to exactly maxWidth\n */\nexport function truncateToWidth(\n\ttext: string,\n\tmaxWidth: number,\n\tellipsis: string = \"...\",\n\tpad: boolean = false,\n): string {\n\tif (maxWidth <= 0) {\n\t\treturn \"\";\n\t}\n\n\tif (text.length === 0) {\n\t\treturn pad ? \" \".repeat(maxWidth) : \"\";\n\t}\n\n\tconst ellipsisWidth = visibleWidth(ellipsis);\n\tif (ellipsisWidth >= maxWidth) {\n\t\tconst textWidth = visibleWidth(text);\n\t\tif (textWidth <= maxWidth) {\n\t\t\treturn pad ? text + \" \".repeat(maxWidth - textWidth) : text;\n\t\t}\n\n\t\tconst clippedEllipsis = truncateFragmentToWidth(ellipsis, maxWidth);\n\t\tif (clippedEllipsis.width === 0) {\n\t\t\treturn pad ? \" \".repeat(maxWidth) : \"\";\n\t\t}\n\t\treturn finalizeTruncatedResult(\"\", 0, clippedEllipsis.text, clippedEllipsis.width, maxWidth, pad);\n\t}\n\n\tif (isPrintableAscii(text)) {\n\t\tif (text.length <= maxWidth) {\n\t\t\treturn pad ? text + \" \".repeat(maxWidth - text.length) : text;\n\t\t}\n\t\tconst targetWidth = maxWidth - ellipsisWidth;\n\t\treturn finalizeTruncatedResult(text.slice(0, targetWidth), targetWidth, ellipsis, ellipsisWidth, maxWidth, pad);\n\t}\n\n\tconst targetWidth = maxWidth - ellipsisWidth;\n\tlet result = \"\";\n\tlet pendingAnsi = \"\";\n\tlet visibleSoFar = 0;\n\tlet keptWidth = 0;\n\tlet keepContiguousPrefix = true;\n\tlet overflowed = false;\n\tlet exhaustedInput = false;\n\tconst hasAnsi = text.includes(\"\\x1b\");\n\tconst hasTabs = text.includes(\"\\t\");\n\n\tif (!hasAnsi && !hasTabs) {\n\t\tfor (const { segment } of graphemeSegmenter.segment(text)) {\n\t\t\tconst width = graphemeWidth(segment);\n\t\t\tif (keepContiguousPrefix && keptWidth + width <= targetWidth) {\n\t\t\t\tresult += segment;\n\t\t\t\tkeptWidth += width;\n\t\t\t} else {\n\t\t\t\tkeepContiguousPrefix = false;\n\t\t\t}\n\t\t\tvisibleSoFar += width;\n\t\t\tif (visibleSoFar > maxWidth) {\n\t\t\t\toverflowed = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\texhaustedInput = !overflowed;\n\t} else {\n\t\tlet i = 0;\n\t\twhile (i < text.length) {\n\t\t\tconst ansi = extractAnsiCode(text, i);\n\t\t\tif (ansi) {\n\t\t\t\tpendingAnsi += ansi.code;\n\t\t\t\ti += ansi.length;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (text[i] === \"\\t\") {\n\t\t\t\tif (keepContiguousPrefix && keptWidth + 3 <= targetWidth) {\n\t\t\t\t\tif (pendingAnsi) {\n\t\t\t\t\t\tresult += pendingAnsi;\n\t\t\t\t\t\tpendingAnsi = \"\";\n\t\t\t\t\t}\n\t\t\t\t\tresult += \"\\t\";\n\t\t\t\t\tkeptWidth += 3;\n\t\t\t\t} else {\n\t\t\t\t\tkeepContiguousPrefix = false;\n\t\t\t\t\tpendingAnsi = \"\";\n\t\t\t\t}\n\t\t\t\tvisibleSoFar += 3;\n\t\t\t\tif (visibleSoFar > maxWidth) {\n\t\t\t\t\toverflowed = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\ti++;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tlet end = i;\n\t\t\twhile (end < text.length && text[end] !== \"\\t\") {\n\t\t\t\tconst nextAnsi = extractAnsiCode(text, end);\n\t\t\t\tif (nextAnsi) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tend++;\n\t\t\t}\n\n\t\t\tfor (const { segment } of graphemeSegmenter.segment(text.slice(i, end))) {\n\t\t\t\tconst width = graphemeWidth(segment);\n\t\t\t\tif (keepContiguousPrefix && keptWidth + width <= targetWidth) {\n\t\t\t\t\tif (pendingAnsi) {\n\t\t\t\t\t\tresult += pendingAnsi;\n\t\t\t\t\t\tpendingAnsi = \"\";\n\t\t\t\t\t}\n\t\t\t\t\tresult += segment;\n\t\t\t\t\tkeptWidth += width;\n\t\t\t\t} else {\n\t\t\t\t\tkeepContiguousPrefix = false;\n\t\t\t\t\tpendingAnsi = \"\";\n\t\t\t\t}\n\n\t\t\t\tvisibleSoFar += width;\n\t\t\t\tif (visibleSoFar > maxWidth) {\n\t\t\t\t\toverflowed = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (overflowed) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\ti = end;\n\t\t}\n\t\texhaustedInput = i >= text.length;\n\t}\n\n\tif (!overflowed && exhaustedInput) {\n\t\treturn pad ? text + \" \".repeat(Math.max(0, maxWidth - visibleSoFar)) : text;\n\t}\n\n\treturn finalizeTruncatedResult(result, keptWidth, ellipsis, ellipsisWidth, maxWidth, pad);\n}\n\n/**\n * Snap a visible column position to the nearest grapheme cluster boundary.\n *\n * When a mouse click lands on the second column of a wide character (e.g. CJK\n * character occupying columns 2-3, click at column 3), the column does not\n * correspond to a real character start. This function walks the line's\n * grapheme clusters and returns the start column of the grapheme that contains\n * the given column, ensuring the column always points to a valid character\n * boundary.\n *\n * @param line - The line of text (may contain ANSI codes)\n * @param col - The visible column to snap\n * @returns The nearest grapheme-start column that is <= col\n */\nexport function snapColToGraphemeBoundary(line: string, col: number): number {\n\tif (col <= 0) return 0;\n\tlet currentCol = 0;\n\tlet i = 0;\n\twhile (i < line.length) {\n\t\tconst ansi = extractAnsiCode(line, i);\n\t\tif (ansi) {\n\t\t\ti += ansi.length;\n\t\t\tcontinue;\n\t\t}\n\t\tlet textEnd = i;\n\t\twhile (textEnd < line.length && !extractAnsiCode(line, textEnd)) textEnd++;\n\t\tfor (const { segment } of graphemeSegmenter.segment(line.slice(i, textEnd))) {\n\t\t\tconst w = graphemeWidth(segment);\n\t\t\tif (currentCol + w > col) {\n\t\t\t\t// col falls within this grapheme — snap to its start\n\t\t\t\treturn currentCol;\n\t\t\t}\n\t\t\tcurrentCol += w;\n\t\t}\n\t\ti = textEnd;\n\t}\n\treturn currentCol;\n}\n\n/**\n * Extract a range of visible columns from a line. Handles ANSI codes and wide chars.\n * @param strict - If true, exclude wide chars at boundary that would extend past the range\n */\nexport function sliceByColumn(line: string, startCol: number, length: number, strict = false): string {\n\treturn sliceWithWidth(line, startCol, length, strict).text;\n}\n\n/** Like sliceByColumn but also returns the actual visible width of the result. */\nexport function sliceWithWidth(\n\tline: string,\n\tstartCol: number,\n\tlength: number,\n\tstrict = false,\n): { text: string; width: number } {\n\tif (length <= 0) return { text: \"\", width: 0 };\n\tconst endCol = startCol + length;\n\tlet result = \"\",\n\t\tresultWidth = 0,\n\t\tcurrentCol = 0,\n\t\ti = 0,\n\t\tpendingAnsi = \"\";\n\n\twhile (i < line.length) {\n\t\tconst ansi = extractAnsiCode(line, i);\n\t\tif (ansi) {\n\t\t\tif (currentCol >= startCol && currentCol < endCol) result += ansi.code;\n\t\t\telse if (currentCol < startCol) pendingAnsi += ansi.code;\n\t\t\ti += ansi.length;\n\t\t\tcontinue;\n\t\t}\n\n\t\tlet textEnd = i;\n\t\twhile (textEnd < line.length && !extractAnsiCode(line, textEnd)) textEnd++;\n\n\t\tfor (const { segment } of graphemeSegmenter.segment(line.slice(i, textEnd))) {\n\t\t\tconst w = graphemeWidth(segment);\n\t\t\tconst inRange = currentCol >= startCol && currentCol < endCol;\n\t\t\tconst fits = !strict || currentCol + w <= endCol;\n\t\t\tif (inRange && fits) {\n\t\t\t\tif (pendingAnsi) {\n\t\t\t\t\tresult += pendingAnsi;\n\t\t\t\t\tpendingAnsi = \"\";\n\t\t\t\t}\n\t\t\t\tresult += segment;\n\t\t\t\tresultWidth += w;\n\t\t\t}\n\t\t\tcurrentCol += w;\n\t\t\tif (currentCol >= endCol) break;\n\t\t}\n\t\ti = textEnd;\n\t\tif (currentCol >= endCol) break;\n\t}\n\treturn { text: result, width: resultWidth };\n}\n\n// Pooled tracker instance for extractSegments (avoids allocation per call)\nconst pooledStyleTracker = new AnsiCodeTracker();\n\n/**\n * Extract \"before\" and \"after\" segments from a line in a single pass.\n * Used for overlay compositing where we need content before and after the overlay region.\n * Preserves styling from before the overlay that should affect content after it.\n */\nexport function extractSegments(\n\tline: string,\n\tbeforeEnd: number,\n\tafterStart: number,\n\tafterLen: number,\n\tstrictAfter = false,\n): { before: string; beforeWidth: number; after: string; afterWidth: number } {\n\tlet before = \"\",\n\t\tbeforeWidth = 0,\n\t\tafter = \"\",\n\t\tafterWidth = 0;\n\tlet currentCol = 0,\n\t\ti = 0;\n\tlet pendingAnsiBefore = \"\";\n\tlet afterStarted = false;\n\tconst afterEnd = afterStart + afterLen;\n\n\t// Track styling state so \"after\" inherits styling from before the overlay\n\tpooledStyleTracker.clear();\n\n\twhile (i < line.length) {\n\t\tconst ansi = extractAnsiCode(line, i);\n\t\tif (ansi) {\n\t\t\t// Track all SGR codes to know styling state at afterStart\n\t\t\tpooledStyleTracker.process(ansi.code);\n\t\t\t// Include ANSI codes in their respective segments\n\t\t\tif (currentCol < beforeEnd) {\n\t\t\t\tpendingAnsiBefore += ansi.code;\n\t\t\t} else if (currentCol >= afterStart && currentCol < afterEnd && afterStarted) {\n\t\t\t\t// Only include after we've started \"after\" (styling already prepended)\n\t\t\t\tafter += ansi.code;\n\t\t\t}\n\t\t\ti += ansi.length;\n\t\t\tcontinue;\n\t\t}\n\n\t\tlet textEnd = i;\n\t\twhile (textEnd < line.length && !extractAnsiCode(line, textEnd)) textEnd++;\n\n\t\tfor (const { segment } of graphemeSegmenter.segment(line.slice(i, textEnd))) {\n\t\t\tconst w = graphemeWidth(segment);\n\n\t\t\tif (currentCol < beforeEnd) {\n\t\t\t\tif (pendingAnsiBefore) {\n\t\t\t\t\tbefore += pendingAnsiBefore;\n\t\t\t\t\tpendingAnsiBefore = \"\";\n\t\t\t\t}\n\t\t\t\tbefore += segment;\n\t\t\t\tbeforeWidth += w;\n\t\t\t} else if (currentCol >= afterStart && currentCol < afterEnd) {\n\t\t\t\tconst fits = !strictAfter || currentCol + w <= afterEnd;\n\t\t\t\tif (fits) {\n\t\t\t\t\t// On first \"after\" grapheme, prepend inherited styling from before overlay\n\t\t\t\t\tif (!afterStarted) {\n\t\t\t\t\t\tafter += pooledStyleTracker.getActiveCodes();\n\t\t\t\t\t\tafterStarted = true;\n\t\t\t\t\t}\n\t\t\t\t\tafter += segment;\n\t\t\t\t\tafterWidth += w;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcurrentCol += w;\n\t\t\t// Early exit: done with \"before\" only, or done with both segments\n\t\t\tif (afterLen <= 0 ? currentCol >= beforeEnd : currentCol >= afterEnd) break;\n\t\t}\n\t\ti = textEnd;\n\t\tif (afterLen <= 0 ? currentCol >= beforeEnd : currentCol >= afterEnd) break;\n\t}\n\n\treturn { before, beforeWidth, after, afterWidth };\n}\n"]}