@dst0/p-tui 0.4.41 → 5.0.2

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 (387) hide show
  1. package/dist/autocomplete.d.ts.map +1 -1
  2. package/dist/autocomplete.js.map +1 -1
  3. package/dist/components/box.d.ts +3 -1
  4. package/dist/components/box.d.ts.map +1 -1
  5. package/dist/components/box.js +19 -10
  6. package/dist/components/box.js.map +1 -1
  7. package/dist/components/cancellable-loader.d.ts.map +1 -1
  8. package/dist/components/cancellable-loader.js.map +1 -1
  9. package/dist/components/editor/constants.d.ts +9 -0
  10. package/dist/components/editor/constants.d.ts.map +1 -0
  11. package/dist/components/editor/constants.js +12 -0
  12. package/dist/components/editor/constants.js.map +1 -0
  13. package/dist/components/editor/editor-methods/autocomplete-matching.d.ts +29 -0
  14. package/dist/components/editor/editor-methods/autocomplete-matching.d.ts.map +1 -0
  15. package/dist/components/editor/editor-methods/autocomplete-matching.js +104 -0
  16. package/dist/components/editor/editor-methods/autocomplete-matching.js.map +1 -0
  17. package/dist/components/editor/editor-methods/autocomplete-request.d.ts +14 -0
  18. package/dist/components/editor/editor-methods/autocomplete-request.d.ts.map +1 -0
  19. package/dist/components/editor/editor-methods/autocomplete-request.js +72 -0
  20. package/dist/components/editor/editor-methods/autocomplete-request.js.map +1 -0
  21. package/dist/components/editor/editor-methods/backspace-cursor.d.ts +9 -0
  22. package/dist/components/editor/editor-methods/backspace-cursor.d.ts.map +1 -0
  23. package/dist/components/editor/editor-methods/backspace-cursor.js +122 -0
  24. package/dist/components/editor/editor-methods/backspace-cursor.js.map +1 -0
  25. package/dist/components/editor/editor-methods/configuration.d.ts +17 -0
  26. package/dist/components/editor/editor-methods/configuration.d.ts.map +1 -0
  27. package/dist/components/editor/editor-methods/configuration.js +107 -0
  28. package/dist/components/editor/editor-methods/configuration.js.map +1 -0
  29. package/dist/components/editor/editor-methods/cursor-movement.d.ts +7 -0
  30. package/dist/components/editor/editor-methods/cursor-movement.d.ts.map +1 -0
  31. package/dist/components/editor/editor-methods/cursor-movement.js +112 -0
  32. package/dist/components/editor/editor-methods/cursor-movement.js.map +1 -0
  33. package/dist/components/editor/editor-methods/input-handling.d.ts +3 -0
  34. package/dist/components/editor/editor-methods/input-handling.d.ts.map +1 -0
  35. package/dist/components/editor/editor-methods/input-handling.js +257 -0
  36. package/dist/components/editor/editor-methods/input-handling.js.map +1 -0
  37. package/dist/components/editor/editor-methods/paste-submit.d.ts +7 -0
  38. package/dist/components/editor/editor-methods/paste-submit.d.ts.map +1 -0
  39. package/dist/components/editor/editor-methods/paste-submit.js +105 -0
  40. package/dist/components/editor/editor-methods/paste-submit.js.map +1 -0
  41. package/dist/components/editor/editor-methods/render.d.ts +3 -0
  42. package/dist/components/editor/editor-methods/render.d.ts.map +1 -0
  43. package/dist/components/editor/editor-methods/render.js +114 -0
  44. package/dist/components/editor/editor-methods/render.js.map +1 -0
  45. package/dist/components/editor/editor-methods/text-insertion.d.ts +4 -0
  46. package/dist/components/editor/editor-methods/text-insertion.d.ts.map +1 -0
  47. package/dist/components/editor/editor-methods/text-insertion.js +91 -0
  48. package/dist/components/editor/editor-methods/text-insertion.js.map +1 -0
  49. package/dist/components/editor/editor-methods/text-layout.d.ts +15 -0
  50. package/dist/components/editor/editor-methods/text-layout.d.ts.map +1 -0
  51. package/dist/components/editor/editor-methods/text-layout.js +129 -0
  52. package/dist/components/editor/editor-methods/text-layout.js.map +1 -0
  53. package/dist/components/editor/editor-methods/vertical-movement.d.ts +8 -0
  54. package/dist/components/editor/editor-methods/vertical-movement.d.ts.map +1 -0
  55. package/dist/components/editor/editor-methods/vertical-movement.js +123 -0
  56. package/dist/components/editor/editor-methods/vertical-movement.js.map +1 -0
  57. package/dist/components/editor/editor-methods/word-operations.d.ts +19 -0
  58. package/dist/components/editor/editor-methods/word-operations.d.ts.map +1 -0
  59. package/dist/components/editor/editor-methods/word-operations.js +122 -0
  60. package/dist/components/editor/editor-methods/word-operations.js.map +1 -0
  61. package/dist/components/editor/editor-methods/yank-undo.d.ts +11 -0
  62. package/dist/components/editor/editor-methods/yank-undo.d.ts.map +1 -0
  63. package/dist/components/editor/editor-methods/yank-undo.js +132 -0
  64. package/dist/components/editor/editor-methods/yank-undo.js.map +1 -0
  65. package/dist/components/editor/editor.d.ts +67 -0
  66. package/dist/components/editor/editor.d.ts.map +1 -0
  67. package/dist/components/editor/editor.js +93 -0
  68. package/dist/components/editor/editor.js.map +1 -0
  69. package/dist/components/editor/helpers.d.ts +3 -0
  70. package/dist/components/editor/helpers.d.ts.map +1 -0
  71. package/dist/components/editor/helpers.js +3 -0
  72. package/dist/components/editor/helpers.js.map +1 -0
  73. package/dist/components/editor/index.d.ts +4 -0
  74. package/dist/components/editor/index.d.ts.map +1 -0
  75. package/dist/components/editor/index.js +3 -0
  76. package/dist/components/editor/index.js.map +1 -0
  77. package/dist/components/editor/paste-marker.d.ts +5 -0
  78. package/dist/components/editor/paste-marker.d.ts.map +1 -0
  79. package/dist/components/editor/paste-marker.js +134 -0
  80. package/dist/components/editor/paste-marker.js.map +1 -0
  81. package/dist/components/editor/trigger-patterns.d.ts +4 -0
  82. package/dist/components/editor/trigger-patterns.d.ts.map +1 -0
  83. package/dist/components/editor/trigger-patterns.js +11 -0
  84. package/dist/components/editor/trigger-patterns.js.map +1 -0
  85. package/dist/components/editor/types.d.ts +25 -0
  86. package/dist/components/editor/types.d.ts.map +1 -0
  87. package/dist/components/editor/types.js +2 -0
  88. package/dist/components/editor/types.js.map +1 -0
  89. package/dist/components/editor.d.ts +1 -253
  90. package/dist/components/editor.d.ts.map +1 -1
  91. package/dist/components/editor.js +1 -1915
  92. package/dist/components/editor.js.map +1 -1
  93. package/dist/components/image.d.ts.map +1 -1
  94. package/dist/components/image.js.map +1 -1
  95. package/dist/components/input/constants.d.ts +2 -0
  96. package/dist/components/input/constants.d.ts.map +1 -0
  97. package/dist/components/input/constants.js +3 -0
  98. package/dist/components/input/constants.js.map +1 -0
  99. package/dist/components/input/index.d.ts +2 -0
  100. package/dist/components/input/index.d.ts.map +1 -0
  101. package/dist/components/input/index.js +2 -0
  102. package/dist/components/input/index.js.map +1 -0
  103. package/dist/components/input/input-methods/input-handling.d.ts +3 -0
  104. package/dist/components/input/input-methods/input-handling.d.ts.map +1 -0
  105. package/dist/components/input/input-methods/input-handling.js +145 -0
  106. package/dist/components/input/input-methods/input-handling.js.map +1 -0
  107. package/dist/components/input/input-methods/render.d.ts +3 -0
  108. package/dist/components/input/input-methods/render.d.ts.map +1 -0
  109. package/dist/components/input/input-methods/render.js +62 -0
  110. package/dist/components/input/input-methods/render.js.map +1 -0
  111. package/dist/components/input/input-methods/text-editing.d.ts +17 -0
  112. package/dist/components/input/input-methods/text-editing.d.ts.map +1 -0
  113. package/dist/components/input/input-methods/text-editing.js +145 -0
  114. package/dist/components/input/input-methods/text-editing.js.map +1 -0
  115. package/dist/components/input/input-methods/value-access.d.ts +4 -0
  116. package/dist/components/input/input-methods/value-access.d.ts.map +1 -0
  117. package/dist/components/input/input-methods/value-access.js +20 -0
  118. package/dist/components/input/input-methods/value-access.js.map +1 -0
  119. package/dist/components/input/input.d.ts +37 -0
  120. package/dist/components/input/input.d.ts.map +1 -0
  121. package/dist/components/input/input.js +77 -0
  122. package/dist/components/input/input.js.map +1 -0
  123. package/dist/components/input/types.d.ts +5 -0
  124. package/dist/components/input/types.d.ts.map +1 -0
  125. package/dist/components/input/types.js +2 -0
  126. package/dist/components/input/types.js.map +1 -0
  127. package/dist/components/input.d.ts +1 -36
  128. package/dist/components/input.d.ts.map +1 -1
  129. package/dist/components/input.js +1 -377
  130. package/dist/components/input.js.map +1 -1
  131. package/dist/components/loader.d.ts.map +1 -1
  132. package/dist/components/loader.js.map +1 -1
  133. package/dist/components/markdown/constants.d.ts +4 -0
  134. package/dist/components/markdown/constants.d.ts.map +1 -0
  135. package/dist/components/markdown/constants.js +8 -0
  136. package/dist/components/markdown/constants.js.map +1 -0
  137. package/dist/components/markdown/index.d.ts +3 -0
  138. package/dist/components/markdown/index.d.ts.map +1 -0
  139. package/dist/components/markdown/index.js +2 -0
  140. package/dist/components/markdown/index.js.map +1 -0
  141. package/dist/components/markdown/markdown-methods/inline-rendering.d.ts +7 -0
  142. package/dist/components/markdown/markdown-methods/inline-rendering.d.ts.map +1 -0
  143. package/dist/components/markdown/markdown-methods/inline-rendering.js +95 -0
  144. package/dist/components/markdown/markdown-methods/inline-rendering.js.map +1 -0
  145. package/dist/components/markdown/markdown-methods/list-table-helpers.d.ts +7 -0
  146. package/dist/components/markdown/markdown-methods/list-table-helpers.d.ts.map +1 -0
  147. package/dist/components/markdown/markdown-methods/list-table-helpers.js +61 -0
  148. package/dist/components/markdown/markdown-methods/list-table-helpers.js.map +1 -0
  149. package/dist/components/markdown/markdown-methods/table-rendering.d.ts +5 -0
  150. package/dist/components/markdown/markdown-methods/table-rendering.d.ts.map +1 -0
  151. package/dist/components/markdown/markdown-methods/table-rendering.js +146 -0
  152. package/dist/components/markdown/markdown-methods/table-rendering.js.map +1 -0
  153. package/dist/components/markdown/markdown-methods/text-rendering.d.ts +6 -0
  154. package/dist/components/markdown/markdown-methods/text-rendering.d.ts.map +1 -0
  155. package/dist/components/markdown/markdown-methods/text-rendering.js +115 -0
  156. package/dist/components/markdown/markdown-methods/text-rendering.js.map +1 -0
  157. package/dist/components/markdown/markdown-methods/theming.d.ts +6 -0
  158. package/dist/components/markdown/markdown-methods/theming.d.ts.map +1 -0
  159. package/dist/components/markdown/markdown-methods/theming.js +41 -0
  160. package/dist/components/markdown/markdown-methods/theming.js.map +1 -0
  161. package/dist/components/markdown/markdown-methods/token-rendering.d.ts +5 -0
  162. package/dist/components/markdown/markdown-methods/token-rendering.d.ts.map +1 -0
  163. package/dist/components/markdown/markdown-methods/token-rendering.js +142 -0
  164. package/dist/components/markdown/markdown-methods/token-rendering.js.map +1 -0
  165. package/dist/components/markdown/markdown.d.ts +32 -0
  166. package/dist/components/markdown/markdown.d.ts.map +1 -0
  167. package/dist/components/markdown/markdown.js +72 -0
  168. package/dist/components/markdown/markdown.js.map +1 -0
  169. package/dist/components/markdown/strictstrikethroughtokenizer.d.ts +6 -0
  170. package/dist/components/markdown/strictstrikethroughtokenizer.d.ts.map +1 -0
  171. package/dist/components/markdown/strictstrikethroughtokenizer.js +18 -0
  172. package/dist/components/markdown/strictstrikethroughtokenizer.js.map +1 -0
  173. package/dist/components/markdown/types.d.ts +42 -0
  174. package/dist/components/markdown/types.d.ts.map +1 -0
  175. package/dist/components/markdown/types.js +2 -0
  176. package/dist/components/markdown/types.js.map +1 -0
  177. package/dist/components/markdown.d.ts +1 -96
  178. package/dist/components/markdown.d.ts.map +1 -1
  179. package/dist/components/markdown.js +1 -653
  180. package/dist/components/markdown.js.map +1 -1
  181. package/dist/components/select-list.d.ts.map +1 -1
  182. package/dist/components/select-list.js +8 -3
  183. package/dist/components/select-list.js.map +1 -1
  184. package/dist/components/settings-list.d.ts.map +1 -1
  185. package/dist/components/settings-list.js +2 -6
  186. package/dist/components/settings-list.js.map +1 -1
  187. package/dist/components/spacer.d.ts.map +1 -1
  188. package/dist/components/spacer.js.map +1 -1
  189. package/dist/components/text.d.ts.map +1 -1
  190. package/dist/components/text.js +2 -2
  191. package/dist/components/text.js.map +1 -1
  192. package/dist/components/truncated-text.d.ts.map +1 -1
  193. package/dist/components/truncated-text.js.map +1 -1
  194. package/dist/editor-component.d.ts.map +1 -1
  195. package/dist/editor-component.js.map +1 -1
  196. package/dist/fuzzy.d.ts.map +1 -1
  197. package/dist/fuzzy.js.map +1 -1
  198. package/dist/index.d.ts +1 -1
  199. package/dist/index.d.ts.map +1 -1
  200. package/dist/index.js +1 -1
  201. package/dist/index.js.map +1 -1
  202. package/dist/keybindings.d.ts.map +1 -1
  203. package/dist/keybindings.js.map +1 -1
  204. package/dist/keys.d.ts.map +1 -1
  205. package/dist/keys.js +145 -14
  206. package/dist/keys.js.map +1 -1
  207. package/dist/kill-ring.d.ts.map +1 -1
  208. package/dist/kill-ring.js.map +1 -1
  209. package/dist/native-modifiers.d.ts +9 -0
  210. package/dist/native-modifiers.d.ts.map +1 -1
  211. package/dist/native-modifiers.js +5 -0
  212. package/dist/native-modifiers.js.map +1 -1
  213. package/dist/stdin-buffer.d.ts +3 -0
  214. package/dist/stdin-buffer.d.ts.map +1 -1
  215. package/dist/stdin-buffer.js +24 -21
  216. package/dist/stdin-buffer.js.map +1 -1
  217. package/dist/terminal/constants.d.ts +9 -0
  218. package/dist/terminal/constants.d.ts.map +1 -0
  219. package/dist/terminal/constants.js +10 -0
  220. package/dist/terminal/constants.js.map +1 -0
  221. package/dist/terminal/helpers.d.ts +6 -0
  222. package/dist/terminal/helpers.d.ts.map +1 -0
  223. package/dist/terminal/helpers.js +23 -0
  224. package/dist/terminal/helpers.js.map +1 -0
  225. package/dist/terminal/index.d.ts +4 -0
  226. package/dist/terminal/index.d.ts.map +1 -0
  227. package/dist/terminal/index.js +3 -0
  228. package/dist/terminal/index.js.map +1 -0
  229. package/dist/terminal/processterminal-methods/cursor-screen.d.ts +11 -0
  230. package/dist/terminal/processterminal-methods/cursor-screen.d.ts.map +1 -0
  231. package/dist/terminal/processterminal-methods/cursor-screen.js +50 -0
  232. package/dist/terminal/processterminal-methods/cursor-screen.js.map +1 -0
  233. package/dist/terminal/processterminal-methods/keyboard-protocol.d.ts +14 -0
  234. package/dist/terminal/processterminal-methods/keyboard-protocol.d.ts.map +1 -0
  235. package/dist/terminal/processterminal-methods/keyboard-protocol.js +147 -0
  236. package/dist/terminal/processterminal-methods/keyboard-protocol.js.map +1 -0
  237. package/dist/terminal/processterminal-methods/terminal-io.d.ts +9 -0
  238. package/dist/terminal/processterminal-methods/terminal-io.d.ts.map +1 -0
  239. package/dist/terminal/processterminal-methods/terminal-io.js +153 -0
  240. package/dist/terminal/processterminal-methods/terminal-io.js.map +1 -0
  241. package/dist/terminal/processterminal.d.ts +49 -0
  242. package/dist/terminal/processterminal.d.ts.map +1 -0
  243. package/dist/terminal/processterminal.js +129 -0
  244. package/dist/terminal/processterminal.js.map +1 -0
  245. package/dist/terminal/types.d.ts +31 -0
  246. package/dist/terminal/types.d.ts.map +1 -0
  247. package/dist/terminal/types.js +2 -0
  248. package/dist/terminal/types.js.map +1 -0
  249. package/dist/terminal-colors.d.ts +2 -0
  250. package/dist/terminal-colors.d.ts.map +1 -1
  251. package/dist/terminal-colors.js +17 -5
  252. package/dist/terminal-colors.js.map +1 -1
  253. package/dist/terminal-image.d.ts.map +1 -1
  254. package/dist/terminal-image.js.map +1 -1
  255. package/dist/terminal.d.ts +1 -109
  256. package/dist/terminal.d.ts.map +1 -1
  257. package/dist/terminal.js +1 -432
  258. package/dist/terminal.js.map +1 -1
  259. package/dist/tui/constants.d.ts +3 -0
  260. package/dist/tui/constants.d.ts.map +1 -0
  261. package/dist/tui/constants.js +3 -0
  262. package/dist/tui/constants.js.map +1 -0
  263. package/dist/tui/container.d.ts +10 -0
  264. package/dist/tui/container.d.ts.map +1 -0
  265. package/dist/tui/container.js +31 -0
  266. package/dist/tui/container.js.map +1 -0
  267. package/dist/tui/helpers.d.ts +8 -0
  268. package/dist/tui/helpers.d.ts.map +1 -0
  269. package/dist/tui/helpers.js +53 -0
  270. package/dist/tui/helpers.js.map +1 -0
  271. package/dist/tui/index.d.ts +6 -0
  272. package/dist/tui/index.d.ts.map +1 -0
  273. package/dist/tui/index.js +5 -0
  274. package/dist/tui/index.js.map +1 -0
  275. package/dist/tui/tui-methods/configuration.d.ts +20 -0
  276. package/dist/tui/tui-methods/configuration.d.ts.map +1 -0
  277. package/dist/tui/tui-methods/configuration.js +131 -0
  278. package/dist/tui/tui-methods/configuration.js.map +1 -0
  279. package/dist/tui/tui-methods/cursor-background.d.ts +10 -0
  280. package/dist/tui/tui-methods/cursor-background.d.ts.map +1 -0
  281. package/dist/tui/tui-methods/cursor-background.js +52 -0
  282. package/dist/tui/tui-methods/cursor-background.js.map +1 -0
  283. package/dist/tui/tui-methods/incremental-render.d.ts +17 -0
  284. package/dist/tui/tui-methods/incremental-render.d.ts.map +1 -0
  285. package/dist/tui/tui-methods/incremental-render.js +259 -0
  286. package/dist/tui/tui-methods/incremental-render.js.map +1 -0
  287. package/dist/tui/tui-methods/input-handling.d.ts +5 -0
  288. package/dist/tui/tui-methods/input-handling.d.ts.map +1 -0
  289. package/dist/tui/tui-methods/input-handling.js +111 -0
  290. package/dist/tui/tui-methods/input-handling.js.map +1 -0
  291. package/dist/tui/tui-methods/line-compositing.d.ts +7 -0
  292. package/dist/tui/tui-methods/line-compositing.d.ts.map +1 -0
  293. package/dist/tui/tui-methods/line-compositing.js +61 -0
  294. package/dist/tui/tui-methods/line-compositing.js.map +1 -0
  295. package/dist/tui/tui-methods/overlay-compositing.d.ts +12 -0
  296. package/dist/tui/tui-methods/overlay-compositing.d.ts.map +1 -0
  297. package/dist/tui/tui-methods/overlay-compositing.js +123 -0
  298. package/dist/tui/tui-methods/overlay-compositing.js.map +1 -0
  299. package/dist/tui/tui-methods/overlay-layout.d.ts +11 -0
  300. package/dist/tui/tui-methods/overlay-layout.d.ts.map +1 -0
  301. package/dist/tui/tui-methods/overlay-layout.js +124 -0
  302. package/dist/tui/tui-methods/overlay-layout.js.map +1 -0
  303. package/dist/tui/tui-methods/overlay-management.d.ts +11 -0
  304. package/dist/tui/tui-methods/overlay-management.d.ts.map +1 -0
  305. package/dist/tui/tui-methods/overlay-management.js +152 -0
  306. package/dist/tui/tui-methods/overlay-management.js.map +1 -0
  307. package/dist/tui/tui-methods/render-pipeline.d.ts +3 -0
  308. package/dist/tui/tui-methods/render-pipeline.d.ts.map +1 -0
  309. package/dist/tui/tui-methods/render-pipeline.js +176 -0
  310. package/dist/tui/tui-methods/render-pipeline.js.map +1 -0
  311. package/dist/tui/tui-methods/render-width-error.d.ts +3 -0
  312. package/dist/tui/tui-methods/render-width-error.d.ts.map +1 -0
  313. package/dist/tui/tui-methods/render-width-error.js +28 -0
  314. package/dist/tui/tui-methods/render-width-error.js.map +1 -0
  315. package/dist/tui/tui-methods/terminal-control.d.ts +8 -0
  316. package/dist/tui/tui-methods/terminal-control.d.ts.map +1 -0
  317. package/dist/tui/tui-methods/terminal-control.js +101 -0
  318. package/dist/tui/tui-methods/terminal-control.js.map +1 -0
  319. package/dist/tui/tui.d.ts +59 -0
  320. package/dist/tui/tui.d.ts.map +1 -0
  321. package/dist/tui/tui.js +78 -0
  322. package/dist/tui/tui.js.map +1 -0
  323. package/dist/tui/types.d.ts +124 -0
  324. package/dist/tui/types.d.ts.map +1 -0
  325. package/dist/tui/types.js +2 -0
  326. package/dist/tui/types.js.map +1 -0
  327. package/dist/tui.d.ts +1 -254
  328. package/dist/tui.d.ts.map +1 -1
  329. package/dist/tui.js +1 -1344
  330. package/dist/tui.js.map +1 -1
  331. package/dist/undo-stack.d.ts.map +1 -1
  332. package/dist/undo-stack.js.map +1 -1
  333. package/dist/utils/ansi-wrapping.d.ts +5 -0
  334. package/dist/utils/ansi-wrapping.d.ts.map +1 -0
  335. package/dist/utils/ansi-wrapping.js +52 -0
  336. package/dist/utils/ansi-wrapping.js.map +1 -0
  337. package/dist/utils/ansicodetracker.d.ts +27 -0
  338. package/dist/utils/ansicodetracker.d.ts.map +1 -0
  339. package/dist/utils/ansicodetracker.js +222 -0
  340. package/dist/utils/ansicodetracker.js.map +1 -0
  341. package/dist/utils/column-slicing.d.ts +12 -0
  342. package/dist/utils/column-slicing.d.ts.map +1 -0
  343. package/dist/utils/column-slicing.js +111 -0
  344. package/dist/utils/column-slicing.js.map +1 -0
  345. package/dist/utils/column-truncation.d.ts +2 -0
  346. package/dist/utils/column-truncation.d.ts.map +1 -0
  347. package/dist/utils/column-truncation.js +129 -0
  348. package/dist/utils/column-truncation.js.map +1 -0
  349. package/dist/utils/constants.d.ts +12 -0
  350. package/dist/utils/constants.d.ts.map +1 -0
  351. package/dist/utils/constants.js +12 -0
  352. package/dist/utils/constants.js.map +1 -0
  353. package/dist/utils/index.d.ts +8 -0
  354. package/dist/utils/index.d.ts.map +1 -0
  355. package/dist/utils/index.js +8 -0
  356. package/dist/utils/index.js.map +1 -0
  357. package/dist/utils/install-delegated-methods.d.ts +5 -0
  358. package/dist/utils/install-delegated-methods.d.ts.map +1 -0
  359. package/dist/utils/install-delegated-methods.js +27 -0
  360. package/dist/utils/install-delegated-methods.js.map +1 -0
  361. package/dist/utils/segmentation.d.ts +10 -0
  362. package/dist/utils/segmentation.d.ts.map +1 -0
  363. package/dist/utils/segmentation.js +111 -0
  364. package/dist/utils/segmentation.js.map +1 -0
  365. package/dist/utils/terminal-output.d.ts +10 -0
  366. package/dist/utils/terminal-output.d.ts.map +1 -0
  367. package/dist/utils/terminal-output.js +122 -0
  368. package/dist/utils/terminal-output.js.map +1 -0
  369. package/dist/utils/types.d.ts +7 -0
  370. package/dist/utils/types.d.ts.map +1 -0
  371. package/dist/utils/types.js +2 -0
  372. package/dist/utils/types.js.map +1 -0
  373. package/dist/utils/width-truncation.d.ts +6 -0
  374. package/dist/utils/width-truncation.d.ts.map +1 -0
  375. package/dist/utils/width-truncation.js +121 -0
  376. package/dist/utils/width-truncation.js.map +1 -0
  377. package/dist/utils/word-wrapping.d.ts +4 -0
  378. package/dist/utils/word-wrapping.d.ts.map +1 -0
  379. package/dist/utils/word-wrapping.js +139 -0
  380. package/dist/utils/word-wrapping.js.map +1 -0
  381. package/dist/utils.d.ts +1 -84
  382. package/dist/utils.d.ts.map +1 -1
  383. package/dist/utils.js +1 -1059
  384. package/dist/utils.js.map +1 -1
  385. package/dist/word-navigation.d.ts.map +1 -1
  386. package/dist/word-navigation.js.map +1 -1
  387. package/package.json +2 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"incremental-render.js","sourceRoot":"","sources":["../../../src/tui/tui-methods/incremental-render.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { isImageLine } from \"../../terminal-image.ts\";\nimport { visibleWidth } from \"../../utils.ts\";\nimport type { TUI } from \"../tui.ts\";\nimport { throwRenderWidthError } from \"./render-width-error.ts\";\n\nexport function renderIncremental(\n self: TUI,\n options: {\n computeLineDiff: (targetRow: number) => number;\n cursorPos: { row: number; col: number } | null;\n fullRender: (clear: boolean) => void;\n hardwareCursorRow: number;\n height: number;\n logRedraw: (reason: string) => void;\n newLines: string[];\n prevViewportTop: number;\n viewportTop: number;\n width: number;\n },\n): void {\n const { computeLineDiff, cursorPos, fullRender, height, logRedraw, newLines, width } = options;\n let { hardwareCursorRow, prevViewportTop, viewportTop } = options;\n // Find first and last changed lines\n let firstChanged = -1;\n let lastChanged = -1;\n const maxLines = Math.max(newLines.length, self.previousLines.length);\n for (let i = 0; i < maxLines; i++) {\n const oldLine = i < self.previousLines.length ? self.previousLines[i] : \"\";\n const newLine = i < newLines.length ? newLines[i] : \"\";\n\n if (oldLine !== newLine) {\n if (firstChanged === -1) {\n firstChanged = i;\n }\n lastChanged = i;\n }\n }\n const appendedLines = newLines.length > self.previousLines.length;\n if (appendedLines) {\n if (firstChanged === -1) {\n firstChanged = self.previousLines.length;\n }\n lastChanged = newLines.length - 1;\n }\n if (firstChanged !== -1) {\n const expandedRange = self.expandChangedRangeForKittyImages(firstChanged, lastChanged, newLines);\n firstChanged = expandedRange.firstChanged;\n lastChanged = expandedRange.lastChanged;\n }\n const appendStart = appendedLines && firstChanged === self.previousLines.length && firstChanged > 0;\n\n // No changes - but still need to update hardware cursor position if it moved\n if (firstChanged === -1) {\n self.positionHardwareCursor(cursorPos, newLines.length);\n self.previousViewportTop = prevViewportTop;\n self.previousHeight = height;\n return;\n }\n\n // All changes are in deleted lines (nothing to render, just clear)\n if (firstChanged >= newLines.length) {\n if (self.previousLines.length > newLines.length) {\n let buffer = \"\\x1b[?2026h\";\n buffer += self.deleteChangedKittyImages(firstChanged, lastChanged);\n // Move to end of new content (clamp to 0 for empty content)\n const targetRow = Math.max(0, newLines.length - 1);\n if (targetRow < prevViewportTop) {\n logRedraw(`deleted lines moved viewport up (${targetRow} < ${prevViewportTop})`);\n fullRender(true);\n return;\n }\n const lineDiff = computeLineDiff(targetRow);\n if (lineDiff > 0) buffer += `\\x1b[${lineDiff}B`;\n else if (lineDiff < 0) buffer += `\\x1b[${-lineDiff}A`;\n buffer += \"\\r\";\n // Clear extra lines without scrolling\n const extraLines = self.previousLines.length - newLines.length;\n if (extraLines > height) {\n logRedraw(`extraLines > height (${extraLines} > ${height})`);\n fullRender(true);\n return;\n }\n const clearStartOffset = newLines.length === 0 ? 0 : 1;\n if (extraLines > 0 && clearStartOffset > 0) {\n buffer += `\\x1b[${clearStartOffset}B`;\n }\n for (let i = 0; i < extraLines; i++) {\n buffer += \"\\r\\x1b[2K\";\n if (i < extraLines - 1) buffer += \"\\x1b[1B\";\n }\n const moveBack = Math.max(0, extraLines - 1 + clearStartOffset);\n if (moveBack > 0) {\n buffer += `\\x1b[${moveBack}A`;\n }\n buffer += \"\\x1b[?2026l\";\n self.terminal.write(buffer);\n self.cursorRow = targetRow;\n self.hardwareCursorRow = targetRow;\n }\n self.positionHardwareCursor(cursorPos, newLines.length);\n self.previousLines = newLines;\n self.previousKittyImageIds = self.collectKittyImageIds(newLines);\n self.previousWidth = width;\n self.previousHeight = height;\n self.previousViewportTop = prevViewportTop;\n return;\n }\n\n // Differential rendering can only touch what was actually visible.\n // If the first changed line is above the previous viewport, redraw only the visible screen rows\n // without clearing scrollback (\\x1b[3J) or replaying the full history into stdout / dumping visible screen (\\x1b[2J).\n if (firstChanged < prevViewportTop) {\n logRedraw(`firstChanged < viewportTop (${firstChanged} < ${prevViewportTop})`);\n self.fullRedrawCount += 1;\n // Preserve the user's scroll position by adjusting for lines added/removed above the viewport.\n // Do NOT scroll to bottom just because content above changed (e.g., tool output expansion).\n const lineDelta = newLines.length - self.previousLines.length;\n const newViewportTop = Math.max(0, Math.min(prevViewportTop + lineDelta, Math.max(0, newLines.length - height)));\n let buffer = \"\\x1b[?2026h\\x1b[H\";\n buffer += self.deleteChangedKittyImages(0, newLines.length - 1);\n const visibleEnd = Math.min(newLines.length, newViewportTop + height);\n for (let i = newViewportTop; i < visibleEnd; i++) {\n buffer += \"\\x1b[2K\";\n buffer += newLines[i];\n if (i < visibleEnd - 1) {\n buffer += \"\\r\\n\";\n }\n }\n const renderedCount = visibleEnd - newViewportTop;\n if (renderedCount < height) {\n for (let i = renderedCount; i < height; i++) {\n buffer += \"\\r\\n\\x1b[2K\";\n }\n const moveBack = height - renderedCount;\n if (moveBack > 0) {\n buffer += `\\x1b[${moveBack}A`;\n }\n }\n buffer += \"\\x1b[?2026l\";\n self.terminal.write(buffer);\n self.previousLines = newLines;\n self.previousKittyImageIds = self.collectKittyImageIds(newLines);\n self.previousWidth = width;\n self.previousHeight = height;\n self.previousViewportTop = newViewportTop;\n self.cursorRow = Math.max(0, visibleEnd - 1);\n self.hardwareCursorRow = self.cursorRow;\n self.maxLinesRendered = Math.max(self.maxLinesRendered, newLines.length);\n self.positionHardwareCursor(cursorPos, newLines.length);\n return;\n }\n\n // Render from first changed line to end\n // Build buffer with all updates wrapped in synchronized output\n let buffer = \"\\x1b[?2026h\"; // Begin synchronized output\n buffer += self.deleteChangedKittyImages(firstChanged, lastChanged);\n const prevViewportBottom = prevViewportTop + height - 1;\n const moveTargetRow = appendStart ? firstChanged - 1 : firstChanged;\n if (moveTargetRow > prevViewportBottom) {\n const currentScreenRow = Math.max(0, Math.min(height - 1, hardwareCursorRow - prevViewportTop));\n const moveToBottom = height - 1 - currentScreenRow;\n if (moveToBottom > 0) {\n buffer += `\\x1b[${moveToBottom}B`;\n }\n const scroll = moveTargetRow - prevViewportBottom;\n buffer += \"\\r\\n\".repeat(scroll);\n prevViewportTop += scroll;\n viewportTop += scroll;\n hardwareCursorRow = moveTargetRow;\n }\n\n // Move cursor to first changed line (use hardwareCursorRow for actual position)\n const lineDiff = computeLineDiff(moveTargetRow);\n if (lineDiff > 0) {\n buffer += `\\x1b[${lineDiff}B`; // Move down\n } else if (lineDiff < 0) {\n buffer += `\\x1b[${-lineDiff}A`; // Move up\n }\n\n buffer += appendStart ? \"\\r\\n\" : \"\\r\"; // Move to column 0\n\n // Only render changed lines (firstChanged to lastChanged), not all lines to end\n // This reduces flicker when only a single line changes (e.g., spinner animation)\n const renderEnd = Math.min(lastChanged, newLines.length - 1);\n for (let i = firstChanged; i <= renderEnd; i++) {\n if (i > firstChanged) buffer += \"\\r\\n\";\n const line = newLines[i];\n const isImage = isImageLine(line);\n const imageReservedRows = isImage ? self.getKittyImageReservedRows(newLines, i, renderEnd) : 1;\n if (imageReservedRows > 1) {\n const imageStartScreenRow = i - viewportTop;\n if (imageStartScreenRow < 0 || imageStartScreenRow + imageReservedRows > height) {\n logRedraw(`kitty image pre-clear would scroll (${imageStartScreenRow} + ${imageReservedRows} > ${height})`);\n fullRender(true);\n return;\n }\n\n buffer += \"\\x1b[2K\";\n for (let row = 1; row < imageReservedRows; row++) {\n buffer += \"\\r\\n\\x1b[2K\";\n }\n buffer += `\\x1b[${imageReservedRows - 1}A`;\n buffer += line;\n buffer += `\\x1b[${imageReservedRows - 1}B`;\n i += imageReservedRows - 1;\n continue;\n }\n\n buffer += \"\\x1b[2K\"; // Clear current line\n if (!isImage && visibleWidth(line) > width) {\n throwRenderWidthError(self, newLines, line, i, width);\n }\n buffer += line;\n }\n\n // Track where cursor ended up after rendering\n let finalCursorRow = renderEnd;\n\n // If we had more lines before, clear them and move cursor back\n if (self.previousLines.length > newLines.length) {\n // Move to end of new content first if we stopped before it\n if (renderEnd < newLines.length - 1) {\n const moveDown = newLines.length - 1 - renderEnd;\n buffer += `\\x1b[${moveDown}B`;\n finalCursorRow = newLines.length - 1;\n }\n const extraLines = self.previousLines.length - newLines.length;\n for (let i = newLines.length; i < self.previousLines.length; i++) {\n buffer += \"\\r\\n\\x1b[2K\";\n }\n // Move cursor back to end of new content\n buffer += `\\x1b[${extraLines}A`;\n }\n\n buffer += \"\\x1b[?2026l\"; // End synchronized output\n\n if (process.env.PI_TUI_DEBUG === \"1\") {\n const debugDir = \"/tmp/tui\";\n fs.mkdirSync(debugDir, { recursive: true });\n const debugPath = path.join(debugDir, `render-${Date.now()}-${Math.random().toString(36).slice(2)}.log`);\n const debugData = [\n `firstChanged: ${firstChanged}`,\n `viewportTop: ${viewportTop}`,\n `cursorRow: ${self.cursorRow}`,\n `height: ${height}`,\n `lineDiff: ${lineDiff}`,\n `hardwareCursorRow: ${hardwareCursorRow}`,\n `renderEnd: ${renderEnd}`,\n `finalCursorRow: ${finalCursorRow}`,\n `cursorPos: ${JSON.stringify(cursorPos)}`,\n `newLines.length: ${newLines.length}`,\n `previousLines.length: ${self.previousLines.length}`,\n \"\",\n \"=== newLines ===\",\n JSON.stringify(newLines, null, 2),\n \"\",\n \"=== previousLines ===\",\n JSON.stringify(self.previousLines, null, 2),\n \"\",\n \"=== buffer ===\",\n JSON.stringify(buffer),\n ].join(\"\\n\");\n fs.writeFileSync(debugPath, debugData);\n }\n\n // Write entire buffer at once\n self.terminal.write(buffer);\n\n // Track cursor position for next render\n // cursorRow tracks end of content (for viewport calculation)\n // hardwareCursorRow tracks actual terminal cursor position (for movement)\n self.cursorRow = Math.max(0, newLines.length - 1);\n self.hardwareCursorRow = finalCursorRow;\n // Track terminal's working area (grows but doesn't shrink unless cleared)\n self.maxLinesRendered = Math.max(self.maxLinesRendered, newLines.length);\n self.previousViewportTop = Math.max(prevViewportTop, finalCursorRow - height + 1);\n\n // Position hardware cursor for IME\n self.positionHardwareCursor(cursorPos, newLines.length);\n\n self.previousLines = newLines;\n self.previousKittyImageIds = self.collectKittyImageIds(newLines);\n self.previousWidth = width;\n self.previousHeight = height;\n}\n"]}
@@ -0,0 +1,5 @@
1
+ import type { TUI } from "../tui.ts";
2
+ export declare function do_handleInput(self: TUI, data: string): void;
3
+ export declare function do_consumeOsc11BackgroundResponse(self: TUI, data: string): boolean;
4
+ export declare function do_consumeCellSizeResponse(self: TUI, data: string): boolean;
5
+ //# sourceMappingURL=input-handling.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-handling.d.ts","sourceRoot":"","sources":["../../../src/tui/tui-methods/input-handling.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAErC,wBAAgB,cAAc,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAuE5D;AAED,wBAAgB,iCAAiC,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAsBlF;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAkB3E","sourcesContent":["import { isKeyRelease, matchesKey } from \"../../keys.ts\";\nimport { isOsc11BackgroundColorResponse, parseOsc11BackgroundColor } from \"../../terminal-colors.ts\";\nimport { setCellDimensions } from \"../../terminal-image.ts\";\nimport type { TUI } from \"../tui.ts\";\n\nexport function do_handleInput(self: TUI, data: string): void {\n if (self.consumeOsc11BackgroundResponse(data)) {\n return;\n }\n\n if (self.inputListeners.size > 0) {\n let current = data;\n for (const listener of self.inputListeners) {\n const result = listener(current);\n if (result?.consume) {\n return;\n }\n if (result?.data !== undefined) {\n current = result.data;\n }\n }\n if (current.length === 0) {\n return;\n }\n data = current;\n }\n\n // Consume terminal cell size responses without blocking unrelated input.\n if (self.consumeCellSizeResponse(data)) {\n return;\n }\n\n // Global debug key handler (Shift+Ctrl+D)\n if (matchesKey(data, \"shift+ctrl+d\") && self.onDebug) {\n self.onDebug();\n return;\n }\n\n // If focused component is an overlay, verify it's still visible\n // (visibility can change due to terminal resize or visible() callback)\n const focusedOverlay = self.overlayStack.find((o) => o.component === self.focusedComponent);\n if (focusedOverlay && !self.isOverlayVisible(focusedOverlay)) {\n // Focused overlay is no longer visible, redirect to topmost visible overlay\n const topVisible = self.getTopmostVisibleOverlay();\n if (topVisible) {\n self.setFocus(topVisible.component);\n } else {\n self.setFocusInternal({ component: focusedOverlay.preFocus, overlayFocusRestore: \"preserve\" });\n }\n }\n\n const focusIsOverlay = self.overlayStack.some((o) => o.component === self.focusedComponent);\n if (!focusIsOverlay) {\n const restoreState = self.getVisibleOverlayFocusRestore();\n if (restoreState.status === \"eligible\") {\n self.setFocus(restoreState.overlay.component);\n } else if (restoreState.status === \"blocked\" && restoreState.blockedBy !== self.focusedComponent) {\n if (restoreState.resume.status === \"restore-overlay\") {\n self.setFocus(restoreState.overlay.component);\n } else {\n self.clearOverlayFocusRestore();\n self.setFocus(restoreState.resume.target);\n }\n }\n }\n\n // Pass input to focused component (including Ctrl+C)\n // The focused component can decide how to handle Ctrl+C\n if (self.focusedComponent?.handleInput) {\n // Filter out key release events unless component opts in\n if (isKeyRelease(data) && !self.focusedComponent.wantsKeyRelease) {\n return;\n }\n self.focusedComponent.handleInput(data);\n self.requestRender();\n }\n}\n\nexport function do_consumeOsc11BackgroundResponse(self: TUI, data: string): boolean {\n if (self.pendingOsc11BackgroundReplies <= 0) {\n return false;\n }\n\n if (!isOsc11BackgroundColorResponse(data)) {\n return false;\n }\n\n const rgb = parseOsc11BackgroundColor(data);\n self.pendingOsc11BackgroundReplies -= 1;\n const query = self.pendingOsc11BackgroundQueries.shift();\n if (query && !query.settled) {\n query.settled = true;\n if (query.timer) {\n clearTimeout(query.timer);\n query.timer = undefined;\n }\n query.resolve?.(rgb);\n query.resolve = undefined;\n }\n return true;\n}\n\nexport function do_consumeCellSizeResponse(self: TUI, data: string): boolean {\n // Response format: ESC [ 6 ; height ; width t\n const match = data.match(/^\\x1b\\[6;(\\d+);(\\d+)t$/);\n if (!match) {\n return false;\n }\n\n const heightPx = parseInt(match[1], 10);\n const widthPx = parseInt(match[2], 10);\n if (heightPx <= 0 || widthPx <= 0) {\n return true;\n }\n\n setCellDimensions({ widthPx, heightPx });\n // Invalidate all components so images re-render with correct dimensions.\n self.invalidate();\n self.requestRender();\n return true;\n}\n"]}
@@ -0,0 +1,111 @@
1
+ import { isKeyRelease, matchesKey } from "../../keys.js";
2
+ import { isOsc11BackgroundColorResponse, parseOsc11BackgroundColor } from "../../terminal-colors.js";
3
+ import { setCellDimensions } from "../../terminal-image.js";
4
+ export function do_handleInput(self, data) {
5
+ if (self.consumeOsc11BackgroundResponse(data)) {
6
+ return;
7
+ }
8
+ if (self.inputListeners.size > 0) {
9
+ let current = data;
10
+ for (const listener of self.inputListeners) {
11
+ const result = listener(current);
12
+ if (result?.consume) {
13
+ return;
14
+ }
15
+ if (result?.data !== undefined) {
16
+ current = result.data;
17
+ }
18
+ }
19
+ if (current.length === 0) {
20
+ return;
21
+ }
22
+ data = current;
23
+ }
24
+ // Consume terminal cell size responses without blocking unrelated input.
25
+ if (self.consumeCellSizeResponse(data)) {
26
+ return;
27
+ }
28
+ // Global debug key handler (Shift+Ctrl+D)
29
+ if (matchesKey(data, "shift+ctrl+d") && self.onDebug) {
30
+ self.onDebug();
31
+ return;
32
+ }
33
+ // If focused component is an overlay, verify it's still visible
34
+ // (visibility can change due to terminal resize or visible() callback)
35
+ const focusedOverlay = self.overlayStack.find((o) => o.component === self.focusedComponent);
36
+ if (focusedOverlay && !self.isOverlayVisible(focusedOverlay)) {
37
+ // Focused overlay is no longer visible, redirect to topmost visible overlay
38
+ const topVisible = self.getTopmostVisibleOverlay();
39
+ if (topVisible) {
40
+ self.setFocus(topVisible.component);
41
+ }
42
+ else {
43
+ self.setFocusInternal({ component: focusedOverlay.preFocus, overlayFocusRestore: "preserve" });
44
+ }
45
+ }
46
+ const focusIsOverlay = self.overlayStack.some((o) => o.component === self.focusedComponent);
47
+ if (!focusIsOverlay) {
48
+ const restoreState = self.getVisibleOverlayFocusRestore();
49
+ if (restoreState.status === "eligible") {
50
+ self.setFocus(restoreState.overlay.component);
51
+ }
52
+ else if (restoreState.status === "blocked" && restoreState.blockedBy !== self.focusedComponent) {
53
+ if (restoreState.resume.status === "restore-overlay") {
54
+ self.setFocus(restoreState.overlay.component);
55
+ }
56
+ else {
57
+ self.clearOverlayFocusRestore();
58
+ self.setFocus(restoreState.resume.target);
59
+ }
60
+ }
61
+ }
62
+ // Pass input to focused component (including Ctrl+C)
63
+ // The focused component can decide how to handle Ctrl+C
64
+ if (self.focusedComponent?.handleInput) {
65
+ // Filter out key release events unless component opts in
66
+ if (isKeyRelease(data) && !self.focusedComponent.wantsKeyRelease) {
67
+ return;
68
+ }
69
+ self.focusedComponent.handleInput(data);
70
+ self.requestRender();
71
+ }
72
+ }
73
+ export function do_consumeOsc11BackgroundResponse(self, data) {
74
+ if (self.pendingOsc11BackgroundReplies <= 0) {
75
+ return false;
76
+ }
77
+ if (!isOsc11BackgroundColorResponse(data)) {
78
+ return false;
79
+ }
80
+ const rgb = parseOsc11BackgroundColor(data);
81
+ self.pendingOsc11BackgroundReplies -= 1;
82
+ const query = self.pendingOsc11BackgroundQueries.shift();
83
+ if (query && !query.settled) {
84
+ query.settled = true;
85
+ if (query.timer) {
86
+ clearTimeout(query.timer);
87
+ query.timer = undefined;
88
+ }
89
+ query.resolve?.(rgb);
90
+ query.resolve = undefined;
91
+ }
92
+ return true;
93
+ }
94
+ export function do_consumeCellSizeResponse(self, data) {
95
+ // Response format: ESC [ 6 ; height ; width t
96
+ const match = data.match(/^\x1b\[6;(\d+);(\d+)t$/);
97
+ if (!match) {
98
+ return false;
99
+ }
100
+ const heightPx = parseInt(match[1], 10);
101
+ const widthPx = parseInt(match[2], 10);
102
+ if (heightPx <= 0 || widthPx <= 0) {
103
+ return true;
104
+ }
105
+ setCellDimensions({ widthPx, heightPx });
106
+ // Invalidate all components so images re-render with correct dimensions.
107
+ self.invalidate();
108
+ self.requestRender();
109
+ return true;
110
+ }
111
+ //# sourceMappingURL=input-handling.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-handling.js","sourceRoot":"","sources":["../../../src/tui/tui-methods/input-handling.ts"],"names":[],"mappings":"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","sourcesContent":["import { isKeyRelease, matchesKey } from \"../../keys.ts\";\nimport { isOsc11BackgroundColorResponse, parseOsc11BackgroundColor } from \"../../terminal-colors.ts\";\nimport { setCellDimensions } from \"../../terminal-image.ts\";\nimport type { TUI } from \"../tui.ts\";\n\nexport function do_handleInput(self: TUI, data: string): void {\n if (self.consumeOsc11BackgroundResponse(data)) {\n return;\n }\n\n if (self.inputListeners.size > 0) {\n let current = data;\n for (const listener of self.inputListeners) {\n const result = listener(current);\n if (result?.consume) {\n return;\n }\n if (result?.data !== undefined) {\n current = result.data;\n }\n }\n if (current.length === 0) {\n return;\n }\n data = current;\n }\n\n // Consume terminal cell size responses without blocking unrelated input.\n if (self.consumeCellSizeResponse(data)) {\n return;\n }\n\n // Global debug key handler (Shift+Ctrl+D)\n if (matchesKey(data, \"shift+ctrl+d\") && self.onDebug) {\n self.onDebug();\n return;\n }\n\n // If focused component is an overlay, verify it's still visible\n // (visibility can change due to terminal resize or visible() callback)\n const focusedOverlay = self.overlayStack.find((o) => o.component === self.focusedComponent);\n if (focusedOverlay && !self.isOverlayVisible(focusedOverlay)) {\n // Focused overlay is no longer visible, redirect to topmost visible overlay\n const topVisible = self.getTopmostVisibleOverlay();\n if (topVisible) {\n self.setFocus(topVisible.component);\n } else {\n self.setFocusInternal({ component: focusedOverlay.preFocus, overlayFocusRestore: \"preserve\" });\n }\n }\n\n const focusIsOverlay = self.overlayStack.some((o) => o.component === self.focusedComponent);\n if (!focusIsOverlay) {\n const restoreState = self.getVisibleOverlayFocusRestore();\n if (restoreState.status === \"eligible\") {\n self.setFocus(restoreState.overlay.component);\n } else if (restoreState.status === \"blocked\" && restoreState.blockedBy !== self.focusedComponent) {\n if (restoreState.resume.status === \"restore-overlay\") {\n self.setFocus(restoreState.overlay.component);\n } else {\n self.clearOverlayFocusRestore();\n self.setFocus(restoreState.resume.target);\n }\n }\n }\n\n // Pass input to focused component (including Ctrl+C)\n // The focused component can decide how to handle Ctrl+C\n if (self.focusedComponent?.handleInput) {\n // Filter out key release events unless component opts in\n if (isKeyRelease(data) && !self.focusedComponent.wantsKeyRelease) {\n return;\n }\n self.focusedComponent.handleInput(data);\n self.requestRender();\n }\n}\n\nexport function do_consumeOsc11BackgroundResponse(self: TUI, data: string): boolean {\n if (self.pendingOsc11BackgroundReplies <= 0) {\n return false;\n }\n\n if (!isOsc11BackgroundColorResponse(data)) {\n return false;\n }\n\n const rgb = parseOsc11BackgroundColor(data);\n self.pendingOsc11BackgroundReplies -= 1;\n const query = self.pendingOsc11BackgroundQueries.shift();\n if (query && !query.settled) {\n query.settled = true;\n if (query.timer) {\n clearTimeout(query.timer);\n query.timer = undefined;\n }\n query.resolve?.(rgb);\n query.resolve = undefined;\n }\n return true;\n}\n\nexport function do_consumeCellSizeResponse(self: TUI, data: string): boolean {\n // Response format: ESC [ 6 ; height ; width t\n const match = data.match(/^\\x1b\\[6;(\\d+);(\\d+)t$/);\n if (!match) {\n return false;\n }\n\n const heightPx = parseInt(match[1], 10);\n const widthPx = parseInt(match[2], 10);\n if (heightPx <= 0 || widthPx <= 0) {\n return true;\n }\n\n setCellDimensions({ widthPx, heightPx });\n // Invalidate all components so images re-render with correct dimensions.\n self.invalidate();\n self.requestRender();\n return true;\n}\n"]}
@@ -0,0 +1,7 @@
1
+ import { TUI } from "../tui.ts";
2
+ export declare function do_compositeLineAt(_self: TUI, baseLine: string, overlayLine: string, startCol: number, overlayWidth: number, totalWidth: number): string;
3
+ export declare function do_extractCursorPosition(_self: TUI, lines: string[], height: number): {
4
+ row: number;
5
+ col: number;
6
+ } | null;
7
+ //# sourceMappingURL=line-compositing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"line-compositing.d.ts","sourceRoot":"","sources":["../../../src/tui/tui-methods/line-compositing.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAEhC,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,GAAG,EACV,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GACjB,MAAM,CA2CR;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,GAAG,EACV,KAAK,EAAE,MAAM,EAAE,EACf,MAAM,EAAE,MAAM,GACb;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAkBrC","sourcesContent":["import { isImageLine } from \"../../terminal-image.ts\";\nimport { extractSegments, sliceByColumn, sliceWithWidth, visibleWidth } from \"../../utils.ts\";\nimport { CURSOR_MARKER } from \"../constants.ts\";\nimport { TUI } from \"../tui.ts\";\n\nexport function do_compositeLineAt(\n _self: TUI,\n baseLine: string,\n overlayLine: string,\n startCol: number,\n overlayWidth: number,\n totalWidth: number,\n): string {\n if (isImageLine(baseLine)) return baseLine;\n\n // Single pass through baseLine extracts both before and after segments\n const afterStart = startCol + overlayWidth;\n const base = extractSegments(baseLine, startCol, afterStart, totalWidth - afterStart, true);\n\n // Extract overlay with width tracking (strict=true to exclude wide chars at boundary)\n const overlay = sliceWithWidth(overlayLine, 0, overlayWidth, true);\n\n // Pad segments to target widths\n const beforePad = Math.max(0, startCol - base.beforeWidth);\n const overlayPad = Math.max(0, overlayWidth - overlay.width);\n const actualBeforeWidth = Math.max(startCol, base.beforeWidth);\n const actualOverlayWidth = Math.max(overlayWidth, overlay.width);\n const afterTarget = Math.max(0, totalWidth - actualBeforeWidth - actualOverlayWidth);\n const afterPad = Math.max(0, afterTarget - base.afterWidth);\n\n // Compose result\n const r = TUI.SEGMENT_RESET;\n const result =\n base.before +\n \" \".repeat(beforePad) +\n r +\n overlay.text +\n \" \".repeat(overlayPad) +\n r +\n base.after +\n \" \".repeat(afterPad) +\n r;\n\n // CRITICAL: Always verify and truncate to terminal width.\n // This is the final safeguard against width overflow which would crash the TUI.\n // Width tracking can drift from actual visible width due to:\n // - Complex ANSI/OSC sequences (hyperlinks, colors)\n // - Wide characters at segment boundaries\n // - Edge cases in segment extraction\n const resultWidth = visibleWidth(result);\n if (resultWidth <= totalWidth) {\n return result;\n }\n // Truncate with strict=true to ensure we don't exceed totalWidth\n return sliceByColumn(result, 0, totalWidth, true);\n}\n\nexport function do_extractCursorPosition(\n _self: TUI,\n lines: string[],\n height: number,\n): { row: number; col: number } | null {\n // Only scan the bottom `height` lines (visible viewport)\n const viewportTop = Math.max(0, lines.length - height);\n for (let row = lines.length - 1; row >= viewportTop; row--) {\n const line = lines[row];\n const markerIndex = line.indexOf(CURSOR_MARKER);\n if (markerIndex !== -1) {\n // Calculate visual column (width of text before marker)\n const beforeMarker = line.slice(0, markerIndex);\n const col = visibleWidth(beforeMarker);\n\n // Strip marker from the line\n lines[row] = line.slice(0, markerIndex) + line.slice(markerIndex + CURSOR_MARKER.length);\n\n return { row, col };\n }\n }\n return null;\n}\n"]}
@@ -0,0 +1,61 @@
1
+ import { isImageLine } from "../../terminal-image.js";
2
+ import { extractSegments, sliceByColumn, sliceWithWidth, visibleWidth } from "../../utils.js";
3
+ import { CURSOR_MARKER } from "../constants.js";
4
+ import { TUI } from "../tui.js";
5
+ export function do_compositeLineAt(_self, baseLine, overlayLine, startCol, overlayWidth, totalWidth) {
6
+ if (isImageLine(baseLine))
7
+ return baseLine;
8
+ // Single pass through baseLine extracts both before and after segments
9
+ const afterStart = startCol + overlayWidth;
10
+ const base = extractSegments(baseLine, startCol, afterStart, totalWidth - afterStart, true);
11
+ // Extract overlay with width tracking (strict=true to exclude wide chars at boundary)
12
+ const overlay = sliceWithWidth(overlayLine, 0, overlayWidth, true);
13
+ // Pad segments to target widths
14
+ const beforePad = Math.max(0, startCol - base.beforeWidth);
15
+ const overlayPad = Math.max(0, overlayWidth - overlay.width);
16
+ const actualBeforeWidth = Math.max(startCol, base.beforeWidth);
17
+ const actualOverlayWidth = Math.max(overlayWidth, overlay.width);
18
+ const afterTarget = Math.max(0, totalWidth - actualBeforeWidth - actualOverlayWidth);
19
+ const afterPad = Math.max(0, afterTarget - base.afterWidth);
20
+ // Compose result
21
+ const r = TUI.SEGMENT_RESET;
22
+ const result = base.before +
23
+ " ".repeat(beforePad) +
24
+ r +
25
+ overlay.text +
26
+ " ".repeat(overlayPad) +
27
+ r +
28
+ base.after +
29
+ " ".repeat(afterPad) +
30
+ r;
31
+ // CRITICAL: Always verify and truncate to terminal width.
32
+ // This is the final safeguard against width overflow which would crash the TUI.
33
+ // Width tracking can drift from actual visible width due to:
34
+ // - Complex ANSI/OSC sequences (hyperlinks, colors)
35
+ // - Wide characters at segment boundaries
36
+ // - Edge cases in segment extraction
37
+ const resultWidth = visibleWidth(result);
38
+ if (resultWidth <= totalWidth) {
39
+ return result;
40
+ }
41
+ // Truncate with strict=true to ensure we don't exceed totalWidth
42
+ return sliceByColumn(result, 0, totalWidth, true);
43
+ }
44
+ export function do_extractCursorPosition(_self, lines, height) {
45
+ // Only scan the bottom `height` lines (visible viewport)
46
+ const viewportTop = Math.max(0, lines.length - height);
47
+ for (let row = lines.length - 1; row >= viewportTop; row--) {
48
+ const line = lines[row];
49
+ const markerIndex = line.indexOf(CURSOR_MARKER);
50
+ if (markerIndex !== -1) {
51
+ // Calculate visual column (width of text before marker)
52
+ const beforeMarker = line.slice(0, markerIndex);
53
+ const col = visibleWidth(beforeMarker);
54
+ // Strip marker from the line
55
+ lines[row] = line.slice(0, markerIndex) + line.slice(markerIndex + CURSOR_MARKER.length);
56
+ return { row, col };
57
+ }
58
+ }
59
+ return null;
60
+ }
61
+ //# sourceMappingURL=line-compositing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"line-compositing.js","sourceRoot":"","sources":["../../../src/tui/tui-methods/line-compositing.ts"],"names":[],"mappings":"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","sourcesContent":["import { isImageLine } from \"../../terminal-image.ts\";\nimport { extractSegments, sliceByColumn, sliceWithWidth, visibleWidth } from \"../../utils.ts\";\nimport { CURSOR_MARKER } from \"../constants.ts\";\nimport { TUI } from \"../tui.ts\";\n\nexport function do_compositeLineAt(\n _self: TUI,\n baseLine: string,\n overlayLine: string,\n startCol: number,\n overlayWidth: number,\n totalWidth: number,\n): string {\n if (isImageLine(baseLine)) return baseLine;\n\n // Single pass through baseLine extracts both before and after segments\n const afterStart = startCol + overlayWidth;\n const base = extractSegments(baseLine, startCol, afterStart, totalWidth - afterStart, true);\n\n // Extract overlay with width tracking (strict=true to exclude wide chars at boundary)\n const overlay = sliceWithWidth(overlayLine, 0, overlayWidth, true);\n\n // Pad segments to target widths\n const beforePad = Math.max(0, startCol - base.beforeWidth);\n const overlayPad = Math.max(0, overlayWidth - overlay.width);\n const actualBeforeWidth = Math.max(startCol, base.beforeWidth);\n const actualOverlayWidth = Math.max(overlayWidth, overlay.width);\n const afterTarget = Math.max(0, totalWidth - actualBeforeWidth - actualOverlayWidth);\n const afterPad = Math.max(0, afterTarget - base.afterWidth);\n\n // Compose result\n const r = TUI.SEGMENT_RESET;\n const result =\n base.before +\n \" \".repeat(beforePad) +\n r +\n overlay.text +\n \" \".repeat(overlayPad) +\n r +\n base.after +\n \" \".repeat(afterPad) +\n r;\n\n // CRITICAL: Always verify and truncate to terminal width.\n // This is the final safeguard against width overflow which would crash the TUI.\n // Width tracking can drift from actual visible width due to:\n // - Complex ANSI/OSC sequences (hyperlinks, colors)\n // - Wide characters at segment boundaries\n // - Edge cases in segment extraction\n const resultWidth = visibleWidth(result);\n if (resultWidth <= totalWidth) {\n return result;\n }\n // Truncate with strict=true to ensure we don't exceed totalWidth\n return sliceByColumn(result, 0, totalWidth, true);\n}\n\nexport function do_extractCursorPosition(\n _self: TUI,\n lines: string[],\n height: number,\n): { row: number; col: number } | null {\n // Only scan the bottom `height` lines (visible viewport)\n const viewportTop = Math.max(0, lines.length - height);\n for (let row = lines.length - 1; row >= viewportTop; row--) {\n const line = lines[row];\n const markerIndex = line.indexOf(CURSOR_MARKER);\n if (markerIndex !== -1) {\n // Calculate visual column (width of text before marker)\n const beforeMarker = line.slice(0, markerIndex);\n const col = visibleWidth(beforeMarker);\n\n // Strip marker from the line\n lines[row] = line.slice(0, markerIndex) + line.slice(markerIndex + CURSOR_MARKER.length);\n\n return { row, col };\n }\n }\n return null;\n}\n"]}
@@ -0,0 +1,12 @@
1
+ import { TUI } from "../tui.ts";
2
+ export declare function do_compositeOverlays(self: TUI, lines: string[], termWidth: number, termHeight: number): string[];
3
+ export declare function do_applyLineResets(_self: TUI, lines: string[]): string[];
4
+ export declare function do_collectKittyImageIds(_self: TUI, lines: string[]): Set<number>;
5
+ export declare function do_deleteKittyImages(_self: TUI, ids: Iterable<number>): string;
6
+ export declare function do_getKittyImageReservedRows(_self: TUI, lines: string[], index: number, maxIndex?: number): number;
7
+ export declare function do_expandChangedRangeForKittyImages(self: TUI, firstChanged: number, lastChanged: number, newLines: string[]): {
8
+ firstChanged: number;
9
+ lastChanged: number;
10
+ };
11
+ export declare function do_deleteChangedKittyImages(self: TUI, firstChanged: number, lastChanged: number): string;
12
+ //# sourceMappingURL=overlay-compositing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overlay-compositing.d.ts","sourceRoot":"","sources":["../../../src/tui/tui-methods/overlay-compositing.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAEhC,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CA2DhH;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CASxE;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAQhF;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,MAAM,CAM9E;AAED,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,GAAG,EACV,KAAK,EAAE,MAAM,EAAE,EACf,KAAK,EAAE,MAAM,EACb,QAAQ,SAAmB,GAC1B,MAAM,CAYR;AAED,wBAAgB,mCAAmC,CACjD,IAAI,EAAE,GAAG,EACT,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAAE,GACjB;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAiB/C;AAED,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAYxG","sourcesContent":["import { deleteKittyImage, isImageLine } from \"../../terminal-image.ts\";\nimport { normalizeTerminalOutput, sliceByColumn, visibleWidth } from \"../../utils.ts\";\nimport { extractKittyImageIds, extractKittyImageRows } from \"../helpers.ts\";\nimport { TUI } from \"../tui.ts\";\n\nexport function do_compositeOverlays(self: TUI, lines: string[], termWidth: number, termHeight: number): string[] {\n if (self.overlayStack.length === 0) return lines;\n const result = [...lines];\n\n // Pre-render all visible overlays and calculate positions\n const rendered: { overlayLines: string[]; row: number; col: number; w: number }[] = [];\n let minLinesNeeded = result.length;\n\n const visibleEntries = self.overlayStack.filter((e) => self.isOverlayVisible(e));\n visibleEntries.sort((a, b) => a.focusOrder - b.focusOrder);\n for (const entry of visibleEntries) {\n const { component, options } = entry;\n\n // Get layout with height=0 first to determine width and maxHeight\n // (width and maxHeight don't depend on overlay height)\n const { width, maxHeight } = self.resolveOverlayLayout(options, 0, termWidth, termHeight);\n\n // Render component at calculated width\n let overlayLines = component.render(width);\n\n // Apply maxHeight if specified\n if (maxHeight !== undefined && overlayLines.length > maxHeight) {\n overlayLines = overlayLines.slice(0, maxHeight);\n }\n\n // Get final row/col with actual overlay height\n const { row, col } = self.resolveOverlayLayout(options, overlayLines.length, termWidth, termHeight);\n\n rendered.push({ overlayLines, row, col, w: width });\n minLinesNeeded = Math.max(minLinesNeeded, row + overlayLines.length);\n }\n\n // Pad to at least terminal height so overlays have screen-relative positions.\n // Excludes maxLinesRendered: the historical high-water mark caused self-reinforcing\n // inflation that pushed content into scrollback on terminal widen.\n const workingHeight = Math.max(result.length, termHeight, minLinesNeeded);\n\n // Extend result with empty lines if content is too short for overlay placement or working area\n while (result.length < workingHeight) {\n result.push(\"\");\n }\n\n const viewportStart = Math.max(0, workingHeight - termHeight);\n\n // Composite each overlay\n for (const { overlayLines, row, col, w } of rendered) {\n for (let i = 0; i < overlayLines.length; i++) {\n const idx = viewportStart + row + i;\n if (idx >= 0 && idx < result.length) {\n // Defensive: truncate overlay line to declared width before compositing\n // (components should already respect width, but self ensures it)\n const truncatedOverlayLine =\n visibleWidth(overlayLines[i]) > w ? sliceByColumn(overlayLines[i], 0, w, true) : overlayLines[i];\n result[idx] = self.compositeLineAt(result[idx], truncatedOverlayLine, col, w, termWidth);\n }\n }\n }\n\n return result;\n}\n\nexport function do_applyLineResets(_self: TUI, lines: string[]): string[] {\n const reset = TUI.SEGMENT_RESET;\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (!isImageLine(line)) {\n lines[i] = normalizeTerminalOutput(line) + reset;\n }\n }\n return lines;\n}\n\nexport function do_collectKittyImageIds(_self: TUI, lines: string[]): Set<number> {\n const ids = new Set<number>();\n for (const line of lines) {\n for (const id of extractKittyImageIds(line)) {\n ids.add(id);\n }\n }\n return ids;\n}\n\nexport function do_deleteKittyImages(_self: TUI, ids: Iterable<number>): string {\n let buffer = \"\";\n for (const id of ids) {\n buffer += deleteKittyImage(id);\n }\n return buffer;\n}\n\nexport function do_getKittyImageReservedRows(\n _self: TUI,\n lines: string[],\n index: number,\n maxIndex = lines.length - 1,\n): number {\n const rows = extractKittyImageRows(lines[index] ?? \"\");\n if (rows <= 1) return 1;\n\n const maxRows = Math.min(rows, maxIndex - index + 1, lines.length - index);\n let reservedRows = 1;\n while (reservedRows < maxRows) {\n const line = lines[index + reservedRows] ?? \"\";\n if (isImageLine(line) || visibleWidth(line) > 0) break;\n reservedRows++;\n }\n return reservedRows;\n}\n\nexport function do_expandChangedRangeForKittyImages(\n self: TUI,\n firstChanged: number,\n lastChanged: number,\n newLines: string[],\n): { firstChanged: number; lastChanged: number } {\n let expandedFirstChanged = firstChanged;\n let expandedLastChanged = lastChanged;\n const expandForLines = (lines: string[]): void => {\n for (let i = 0; i < lines.length; i++) {\n if (extractKittyImageIds(lines[i]).length === 0) continue;\n const blockEnd = i + self.getKittyImageReservedRows(lines, i) - 1;\n if (i >= firstChanged || (i <= lastChanged && blockEnd >= firstChanged)) {\n expandedFirstChanged = Math.min(expandedFirstChanged, i);\n expandedLastChanged = Math.max(expandedLastChanged, blockEnd);\n }\n }\n };\n\n expandForLines(self.previousLines);\n expandForLines(newLines);\n return { firstChanged: expandedFirstChanged, lastChanged: expandedLastChanged };\n}\n\nexport function do_deleteChangedKittyImages(self: TUI, firstChanged: number, lastChanged: number): string {\n if (firstChanged < 0 || lastChanged < firstChanged) return \"\";\n\n const ids = new Set<number>();\n const maxLine = Math.min(lastChanged, self.previousLines.length - 1);\n for (let i = firstChanged; i <= maxLine; i++) {\n for (const id of extractKittyImageIds(self.previousLines[i] ?? \"\")) {\n ids.add(id);\n }\n }\n\n return self.deleteKittyImages(ids);\n}\n"]}
@@ -0,0 +1,123 @@
1
+ import { deleteKittyImage, isImageLine } from "../../terminal-image.js";
2
+ import { normalizeTerminalOutput, sliceByColumn, visibleWidth } from "../../utils.js";
3
+ import { extractKittyImageIds, extractKittyImageRows } from "../helpers.js";
4
+ import { TUI } from "../tui.js";
5
+ export function do_compositeOverlays(self, lines, termWidth, termHeight) {
6
+ if (self.overlayStack.length === 0)
7
+ return lines;
8
+ const result = [...lines];
9
+ // Pre-render all visible overlays and calculate positions
10
+ const rendered = [];
11
+ let minLinesNeeded = result.length;
12
+ const visibleEntries = self.overlayStack.filter((e) => self.isOverlayVisible(e));
13
+ visibleEntries.sort((a, b) => a.focusOrder - b.focusOrder);
14
+ for (const entry of visibleEntries) {
15
+ const { component, options } = entry;
16
+ // Get layout with height=0 first to determine width and maxHeight
17
+ // (width and maxHeight don't depend on overlay height)
18
+ const { width, maxHeight } = self.resolveOverlayLayout(options, 0, termWidth, termHeight);
19
+ // Render component at calculated width
20
+ let overlayLines = component.render(width);
21
+ // Apply maxHeight if specified
22
+ if (maxHeight !== undefined && overlayLines.length > maxHeight) {
23
+ overlayLines = overlayLines.slice(0, maxHeight);
24
+ }
25
+ // Get final row/col with actual overlay height
26
+ const { row, col } = self.resolveOverlayLayout(options, overlayLines.length, termWidth, termHeight);
27
+ rendered.push({ overlayLines, row, col, w: width });
28
+ minLinesNeeded = Math.max(minLinesNeeded, row + overlayLines.length);
29
+ }
30
+ // Pad to at least terminal height so overlays have screen-relative positions.
31
+ // Excludes maxLinesRendered: the historical high-water mark caused self-reinforcing
32
+ // inflation that pushed content into scrollback on terminal widen.
33
+ const workingHeight = Math.max(result.length, termHeight, minLinesNeeded);
34
+ // Extend result with empty lines if content is too short for overlay placement or working area
35
+ while (result.length < workingHeight) {
36
+ result.push("");
37
+ }
38
+ const viewportStart = Math.max(0, workingHeight - termHeight);
39
+ // Composite each overlay
40
+ for (const { overlayLines, row, col, w } of rendered) {
41
+ for (let i = 0; i < overlayLines.length; i++) {
42
+ const idx = viewportStart + row + i;
43
+ if (idx >= 0 && idx < result.length) {
44
+ // Defensive: truncate overlay line to declared width before compositing
45
+ // (components should already respect width, but self ensures it)
46
+ const truncatedOverlayLine = visibleWidth(overlayLines[i]) > w ? sliceByColumn(overlayLines[i], 0, w, true) : overlayLines[i];
47
+ result[idx] = self.compositeLineAt(result[idx], truncatedOverlayLine, col, w, termWidth);
48
+ }
49
+ }
50
+ }
51
+ return result;
52
+ }
53
+ export function do_applyLineResets(_self, lines) {
54
+ const reset = TUI.SEGMENT_RESET;
55
+ for (let i = 0; i < lines.length; i++) {
56
+ const line = lines[i];
57
+ if (!isImageLine(line)) {
58
+ lines[i] = normalizeTerminalOutput(line) + reset;
59
+ }
60
+ }
61
+ return lines;
62
+ }
63
+ export function do_collectKittyImageIds(_self, lines) {
64
+ const ids = new Set();
65
+ for (const line of lines) {
66
+ for (const id of extractKittyImageIds(line)) {
67
+ ids.add(id);
68
+ }
69
+ }
70
+ return ids;
71
+ }
72
+ export function do_deleteKittyImages(_self, ids) {
73
+ let buffer = "";
74
+ for (const id of ids) {
75
+ buffer += deleteKittyImage(id);
76
+ }
77
+ return buffer;
78
+ }
79
+ export function do_getKittyImageReservedRows(_self, lines, index, maxIndex = lines.length - 1) {
80
+ const rows = extractKittyImageRows(lines[index] ?? "");
81
+ if (rows <= 1)
82
+ return 1;
83
+ const maxRows = Math.min(rows, maxIndex - index + 1, lines.length - index);
84
+ let reservedRows = 1;
85
+ while (reservedRows < maxRows) {
86
+ const line = lines[index + reservedRows] ?? "";
87
+ if (isImageLine(line) || visibleWidth(line) > 0)
88
+ break;
89
+ reservedRows++;
90
+ }
91
+ return reservedRows;
92
+ }
93
+ export function do_expandChangedRangeForKittyImages(self, firstChanged, lastChanged, newLines) {
94
+ let expandedFirstChanged = firstChanged;
95
+ let expandedLastChanged = lastChanged;
96
+ const expandForLines = (lines) => {
97
+ for (let i = 0; i < lines.length; i++) {
98
+ if (extractKittyImageIds(lines[i]).length === 0)
99
+ continue;
100
+ const blockEnd = i + self.getKittyImageReservedRows(lines, i) - 1;
101
+ if (i >= firstChanged || (i <= lastChanged && blockEnd >= firstChanged)) {
102
+ expandedFirstChanged = Math.min(expandedFirstChanged, i);
103
+ expandedLastChanged = Math.max(expandedLastChanged, blockEnd);
104
+ }
105
+ }
106
+ };
107
+ expandForLines(self.previousLines);
108
+ expandForLines(newLines);
109
+ return { firstChanged: expandedFirstChanged, lastChanged: expandedLastChanged };
110
+ }
111
+ export function do_deleteChangedKittyImages(self, firstChanged, lastChanged) {
112
+ if (firstChanged < 0 || lastChanged < firstChanged)
113
+ return "";
114
+ const ids = new Set();
115
+ const maxLine = Math.min(lastChanged, self.previousLines.length - 1);
116
+ for (let i = firstChanged; i <= maxLine; i++) {
117
+ for (const id of extractKittyImageIds(self.previousLines[i] ?? "")) {
118
+ ids.add(id);
119
+ }
120
+ }
121
+ return self.deleteKittyImages(ids);
122
+ }
123
+ //# sourceMappingURL=overlay-compositing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overlay-compositing.js","sourceRoot":"","sources":["../../../src/tui/tui-methods/overlay-compositing.ts"],"names":[],"mappings":"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","sourcesContent":["import { deleteKittyImage, isImageLine } from \"../../terminal-image.ts\";\nimport { normalizeTerminalOutput, sliceByColumn, visibleWidth } from \"../../utils.ts\";\nimport { extractKittyImageIds, extractKittyImageRows } from \"../helpers.ts\";\nimport { TUI } from \"../tui.ts\";\n\nexport function do_compositeOverlays(self: TUI, lines: string[], termWidth: number, termHeight: number): string[] {\n if (self.overlayStack.length === 0) return lines;\n const result = [...lines];\n\n // Pre-render all visible overlays and calculate positions\n const rendered: { overlayLines: string[]; row: number; col: number; w: number }[] = [];\n let minLinesNeeded = result.length;\n\n const visibleEntries = self.overlayStack.filter((e) => self.isOverlayVisible(e));\n visibleEntries.sort((a, b) => a.focusOrder - b.focusOrder);\n for (const entry of visibleEntries) {\n const { component, options } = entry;\n\n // Get layout with height=0 first to determine width and maxHeight\n // (width and maxHeight don't depend on overlay height)\n const { width, maxHeight } = self.resolveOverlayLayout(options, 0, termWidth, termHeight);\n\n // Render component at calculated width\n let overlayLines = component.render(width);\n\n // Apply maxHeight if specified\n if (maxHeight !== undefined && overlayLines.length > maxHeight) {\n overlayLines = overlayLines.slice(0, maxHeight);\n }\n\n // Get final row/col with actual overlay height\n const { row, col } = self.resolveOverlayLayout(options, overlayLines.length, termWidth, termHeight);\n\n rendered.push({ overlayLines, row, col, w: width });\n minLinesNeeded = Math.max(minLinesNeeded, row + overlayLines.length);\n }\n\n // Pad to at least terminal height so overlays have screen-relative positions.\n // Excludes maxLinesRendered: the historical high-water mark caused self-reinforcing\n // inflation that pushed content into scrollback on terminal widen.\n const workingHeight = Math.max(result.length, termHeight, minLinesNeeded);\n\n // Extend result with empty lines if content is too short for overlay placement or working area\n while (result.length < workingHeight) {\n result.push(\"\");\n }\n\n const viewportStart = Math.max(0, workingHeight - termHeight);\n\n // Composite each overlay\n for (const { overlayLines, row, col, w } of rendered) {\n for (let i = 0; i < overlayLines.length; i++) {\n const idx = viewportStart + row + i;\n if (idx >= 0 && idx < result.length) {\n // Defensive: truncate overlay line to declared width before compositing\n // (components should already respect width, but self ensures it)\n const truncatedOverlayLine =\n visibleWidth(overlayLines[i]) > w ? sliceByColumn(overlayLines[i], 0, w, true) : overlayLines[i];\n result[idx] = self.compositeLineAt(result[idx], truncatedOverlayLine, col, w, termWidth);\n }\n }\n }\n\n return result;\n}\n\nexport function do_applyLineResets(_self: TUI, lines: string[]): string[] {\n const reset = TUI.SEGMENT_RESET;\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (!isImageLine(line)) {\n lines[i] = normalizeTerminalOutput(line) + reset;\n }\n }\n return lines;\n}\n\nexport function do_collectKittyImageIds(_self: TUI, lines: string[]): Set<number> {\n const ids = new Set<number>();\n for (const line of lines) {\n for (const id of extractKittyImageIds(line)) {\n ids.add(id);\n }\n }\n return ids;\n}\n\nexport function do_deleteKittyImages(_self: TUI, ids: Iterable<number>): string {\n let buffer = \"\";\n for (const id of ids) {\n buffer += deleteKittyImage(id);\n }\n return buffer;\n}\n\nexport function do_getKittyImageReservedRows(\n _self: TUI,\n lines: string[],\n index: number,\n maxIndex = lines.length - 1,\n): number {\n const rows = extractKittyImageRows(lines[index] ?? \"\");\n if (rows <= 1) return 1;\n\n const maxRows = Math.min(rows, maxIndex - index + 1, lines.length - index);\n let reservedRows = 1;\n while (reservedRows < maxRows) {\n const line = lines[index + reservedRows] ?? \"\";\n if (isImageLine(line) || visibleWidth(line) > 0) break;\n reservedRows++;\n }\n return reservedRows;\n}\n\nexport function do_expandChangedRangeForKittyImages(\n self: TUI,\n firstChanged: number,\n lastChanged: number,\n newLines: string[],\n): { firstChanged: number; lastChanged: number } {\n let expandedFirstChanged = firstChanged;\n let expandedLastChanged = lastChanged;\n const expandForLines = (lines: string[]): void => {\n for (let i = 0; i < lines.length; i++) {\n if (extractKittyImageIds(lines[i]).length === 0) continue;\n const blockEnd = i + self.getKittyImageReservedRows(lines, i) - 1;\n if (i >= firstChanged || (i <= lastChanged && blockEnd >= firstChanged)) {\n expandedFirstChanged = Math.min(expandedFirstChanged, i);\n expandedLastChanged = Math.max(expandedLastChanged, blockEnd);\n }\n }\n };\n\n expandForLines(self.previousLines);\n expandForLines(newLines);\n return { firstChanged: expandedFirstChanged, lastChanged: expandedLastChanged };\n}\n\nexport function do_deleteChangedKittyImages(self: TUI, firstChanged: number, lastChanged: number): string {\n if (firstChanged < 0 || lastChanged < firstChanged) return \"\";\n\n const ids = new Set<number>();\n const maxLine = Math.min(lastChanged, self.previousLines.length - 1);\n for (let i = firstChanged; i <= maxLine; i++) {\n for (const id of extractKittyImageIds(self.previousLines[i] ?? \"\")) {\n ids.add(id);\n }\n }\n\n return self.deleteKittyImages(ids);\n}\n"]}
@@ -0,0 +1,11 @@
1
+ import type { TUI } from "../tui.ts";
2
+ import type { OverlayAnchor, OverlayOptions } from "../types.ts";
3
+ export declare function do_resolveOverlayLayout(self: TUI, options: OverlayOptions | undefined, overlayHeight: number, termWidth: number, termHeight: number): {
4
+ width: number;
5
+ row: number;
6
+ col: number;
7
+ maxHeight: number | undefined;
8
+ };
9
+ export declare function do_resolveAnchorRow(_self: TUI, anchor: OverlayAnchor, height: number, availHeight: number, marginTop: number): number;
10
+ export declare function do_resolveAnchorCol(_self: TUI, anchor: OverlayAnchor, width: number, availWidth: number, marginLeft: number): number;
11
+ //# sourceMappingURL=overlay-layout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overlay-layout.d.ts","sourceRoot":"","sources":["../../../src/tui/tui-methods/overlay-layout.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEjE,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,GAAG,EACT,OAAO,EAAE,cAAc,GAAG,SAAS,EACnC,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CA6F5E;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,GAAG,EACV,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,MAAM,CAeR;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,GAAG,EACV,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,MAAM,CAeR","sourcesContent":["import { parseSizeValue } from \"../helpers.ts\";\nimport type { TUI } from \"../tui.ts\";\nimport type { OverlayAnchor, OverlayOptions } from \"../types.ts\";\n\nexport function do_resolveOverlayLayout(\n self: TUI,\n options: OverlayOptions | undefined,\n overlayHeight: number,\n termWidth: number,\n termHeight: number,\n): { width: number; row: number; col: number; maxHeight: number | undefined } {\n const opt = options ?? {};\n\n // Parse margin (clamp to non-negative)\n const margin =\n typeof opt.margin === \"number\"\n ? { top: opt.margin, right: opt.margin, bottom: opt.margin, left: opt.margin }\n : (opt.margin ?? {});\n const marginTop = Math.max(0, margin.top ?? 0);\n const marginRight = Math.max(0, margin.right ?? 0);\n const marginBottom = Math.max(0, margin.bottom ?? 0);\n const marginLeft = Math.max(0, margin.left ?? 0);\n\n // Available space after margins\n const availWidth = Math.max(1, termWidth - marginLeft - marginRight);\n const availHeight = Math.max(1, termHeight - marginTop - marginBottom);\n\n // === Resolve width ===\n let width = parseSizeValue(opt.width, termWidth) ?? Math.min(80, availWidth);\n // Apply minWidth\n if (opt.minWidth !== undefined) {\n width = Math.max(width, opt.minWidth);\n }\n // Clamp to available space\n width = Math.max(1, Math.min(width, availWidth));\n\n // === Resolve maxHeight ===\n let maxHeight = parseSizeValue(opt.maxHeight, termHeight);\n // Clamp to available space\n if (maxHeight !== undefined) {\n maxHeight = Math.max(1, Math.min(maxHeight, availHeight));\n }\n\n // Effective overlay height (may be clamped by maxHeight)\n const effectiveHeight = maxHeight !== undefined ? Math.min(overlayHeight, maxHeight) : overlayHeight;\n\n // === Resolve position ===\n let row: number;\n let col: number;\n\n if (opt.row !== undefined) {\n if (typeof opt.row === \"string\") {\n // Percentage: 0% = top, 100% = bottom (overlay stays within bounds)\n const match = opt.row.match(/^(\\d+(?:\\.\\d+)?)%$/);\n if (match) {\n const maxRow = Math.max(0, availHeight - effectiveHeight);\n const percent = parseFloat(match[1]) / 100;\n row = marginTop + Math.floor(maxRow * percent);\n } else {\n // Invalid format, fall back to center\n row = self.resolveAnchorRow(\"center\", effectiveHeight, availHeight, marginTop);\n }\n } else {\n // Absolute row position\n row = opt.row;\n }\n } else {\n // Anchor-based (default: center)\n const anchor = opt.anchor ?? \"center\";\n row = self.resolveAnchorRow(anchor, effectiveHeight, availHeight, marginTop);\n }\n\n if (opt.col !== undefined) {\n if (typeof opt.col === \"string\") {\n // Percentage: 0% = left, 100% = right (overlay stays within bounds)\n const match = opt.col.match(/^(\\d+(?:\\.\\d+)?)%$/);\n if (match) {\n const maxCol = Math.max(0, availWidth - width);\n const percent = parseFloat(match[1]) / 100;\n col = marginLeft + Math.floor(maxCol * percent);\n } else {\n // Invalid format, fall back to center\n col = self.resolveAnchorCol(\"center\", width, availWidth, marginLeft);\n }\n } else {\n // Absolute column position\n col = opt.col;\n }\n } else {\n // Anchor-based (default: center)\n const anchor = opt.anchor ?? \"center\";\n col = self.resolveAnchorCol(anchor, width, availWidth, marginLeft);\n }\n\n // Apply offsets\n if (opt.offsetY !== undefined) row += opt.offsetY;\n if (opt.offsetX !== undefined) col += opt.offsetX;\n\n // Clamp to terminal bounds (respecting margins)\n row = Math.max(marginTop, Math.min(row, termHeight - marginBottom - effectiveHeight));\n col = Math.max(marginLeft, Math.min(col, termWidth - marginRight - width));\n\n return { width, row, col, maxHeight };\n}\n\nexport function do_resolveAnchorRow(\n _self: TUI,\n anchor: OverlayAnchor,\n height: number,\n availHeight: number,\n marginTop: number,\n): number {\n switch (anchor) {\n case \"top-left\":\n case \"top-center\":\n case \"top-right\":\n return marginTop;\n case \"bottom-left\":\n case \"bottom-center\":\n case \"bottom-right\":\n return marginTop + availHeight - height;\n case \"left-center\":\n case \"center\":\n case \"right-center\":\n return marginTop + Math.floor((availHeight - height) / 2);\n }\n}\n\nexport function do_resolveAnchorCol(\n _self: TUI,\n anchor: OverlayAnchor,\n width: number,\n availWidth: number,\n marginLeft: number,\n): number {\n switch (anchor) {\n case \"top-left\":\n case \"left-center\":\n case \"bottom-left\":\n return marginLeft;\n case \"top-right\":\n case \"right-center\":\n case \"bottom-right\":\n return marginLeft + availWidth - width;\n case \"top-center\":\n case \"center\":\n case \"bottom-center\":\n return marginLeft + Math.floor((availWidth - width) / 2);\n }\n}\n"]}
@@ -0,0 +1,124 @@
1
+ import { parseSizeValue } from "../helpers.js";
2
+ export function do_resolveOverlayLayout(self, options, overlayHeight, termWidth, termHeight) {
3
+ const opt = options ?? {};
4
+ // Parse margin (clamp to non-negative)
5
+ const margin = typeof opt.margin === "number"
6
+ ? { top: opt.margin, right: opt.margin, bottom: opt.margin, left: opt.margin }
7
+ : (opt.margin ?? {});
8
+ const marginTop = Math.max(0, margin.top ?? 0);
9
+ const marginRight = Math.max(0, margin.right ?? 0);
10
+ const marginBottom = Math.max(0, margin.bottom ?? 0);
11
+ const marginLeft = Math.max(0, margin.left ?? 0);
12
+ // Available space after margins
13
+ const availWidth = Math.max(1, termWidth - marginLeft - marginRight);
14
+ const availHeight = Math.max(1, termHeight - marginTop - marginBottom);
15
+ // === Resolve width ===
16
+ let width = parseSizeValue(opt.width, termWidth) ?? Math.min(80, availWidth);
17
+ // Apply minWidth
18
+ if (opt.minWidth !== undefined) {
19
+ width = Math.max(width, opt.minWidth);
20
+ }
21
+ // Clamp to available space
22
+ width = Math.max(1, Math.min(width, availWidth));
23
+ // === Resolve maxHeight ===
24
+ let maxHeight = parseSizeValue(opt.maxHeight, termHeight);
25
+ // Clamp to available space
26
+ if (maxHeight !== undefined) {
27
+ maxHeight = Math.max(1, Math.min(maxHeight, availHeight));
28
+ }
29
+ // Effective overlay height (may be clamped by maxHeight)
30
+ const effectiveHeight = maxHeight !== undefined ? Math.min(overlayHeight, maxHeight) : overlayHeight;
31
+ // === Resolve position ===
32
+ let row;
33
+ let col;
34
+ if (opt.row !== undefined) {
35
+ if (typeof opt.row === "string") {
36
+ // Percentage: 0% = top, 100% = bottom (overlay stays within bounds)
37
+ const match = opt.row.match(/^(\d+(?:\.\d+)?)%$/);
38
+ if (match) {
39
+ const maxRow = Math.max(0, availHeight - effectiveHeight);
40
+ const percent = parseFloat(match[1]) / 100;
41
+ row = marginTop + Math.floor(maxRow * percent);
42
+ }
43
+ else {
44
+ // Invalid format, fall back to center
45
+ row = self.resolveAnchorRow("center", effectiveHeight, availHeight, marginTop);
46
+ }
47
+ }
48
+ else {
49
+ // Absolute row position
50
+ row = opt.row;
51
+ }
52
+ }
53
+ else {
54
+ // Anchor-based (default: center)
55
+ const anchor = opt.anchor ?? "center";
56
+ row = self.resolveAnchorRow(anchor, effectiveHeight, availHeight, marginTop);
57
+ }
58
+ if (opt.col !== undefined) {
59
+ if (typeof opt.col === "string") {
60
+ // Percentage: 0% = left, 100% = right (overlay stays within bounds)
61
+ const match = opt.col.match(/^(\d+(?:\.\d+)?)%$/);
62
+ if (match) {
63
+ const maxCol = Math.max(0, availWidth - width);
64
+ const percent = parseFloat(match[1]) / 100;
65
+ col = marginLeft + Math.floor(maxCol * percent);
66
+ }
67
+ else {
68
+ // Invalid format, fall back to center
69
+ col = self.resolveAnchorCol("center", width, availWidth, marginLeft);
70
+ }
71
+ }
72
+ else {
73
+ // Absolute column position
74
+ col = opt.col;
75
+ }
76
+ }
77
+ else {
78
+ // Anchor-based (default: center)
79
+ const anchor = opt.anchor ?? "center";
80
+ col = self.resolveAnchorCol(anchor, width, availWidth, marginLeft);
81
+ }
82
+ // Apply offsets
83
+ if (opt.offsetY !== undefined)
84
+ row += opt.offsetY;
85
+ if (opt.offsetX !== undefined)
86
+ col += opt.offsetX;
87
+ // Clamp to terminal bounds (respecting margins)
88
+ row = Math.max(marginTop, Math.min(row, termHeight - marginBottom - effectiveHeight));
89
+ col = Math.max(marginLeft, Math.min(col, termWidth - marginRight - width));
90
+ return { width, row, col, maxHeight };
91
+ }
92
+ export function do_resolveAnchorRow(_self, anchor, height, availHeight, marginTop) {
93
+ switch (anchor) {
94
+ case "top-left":
95
+ case "top-center":
96
+ case "top-right":
97
+ return marginTop;
98
+ case "bottom-left":
99
+ case "bottom-center":
100
+ case "bottom-right":
101
+ return marginTop + availHeight - height;
102
+ case "left-center":
103
+ case "center":
104
+ case "right-center":
105
+ return marginTop + Math.floor((availHeight - height) / 2);
106
+ }
107
+ }
108
+ export function do_resolveAnchorCol(_self, anchor, width, availWidth, marginLeft) {
109
+ switch (anchor) {
110
+ case "top-left":
111
+ case "left-center":
112
+ case "bottom-left":
113
+ return marginLeft;
114
+ case "top-right":
115
+ case "right-center":
116
+ case "bottom-right":
117
+ return marginLeft + availWidth - width;
118
+ case "top-center":
119
+ case "center":
120
+ case "bottom-center":
121
+ return marginLeft + Math.floor((availWidth - width) / 2);
122
+ }
123
+ }
124
+ //# sourceMappingURL=overlay-layout.js.map