@effect-tui/react 0.1.3 → 0.1.5

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 (442) hide show
  1. package/dist/jsx-runtime.d.ts +13 -0
  2. package/dist/jsx-runtime.d.ts.map +1 -1
  3. package/dist/jsx-runtime.js.map +1 -1
  4. package/dist/src/codeblock.d.ts.map +1 -1
  5. package/dist/src/codeblock.js.map +1 -1
  6. package/dist/src/components/Divider.d.ts +18 -0
  7. package/dist/src/components/Divider.d.ts.map +1 -0
  8. package/dist/src/components/Divider.js +17 -0
  9. package/dist/src/components/Divider.js.map +1 -0
  10. package/dist/src/components/Markdown.d.ts +66 -0
  11. package/dist/src/components/Markdown.d.ts.map +1 -0
  12. package/dist/src/components/Markdown.js +226 -0
  13. package/dist/src/components/Markdown.js.map +1 -0
  14. package/dist/src/components/MultilineTextInput.d.ts +65 -0
  15. package/dist/src/components/MultilineTextInput.d.ts.map +1 -0
  16. package/dist/src/components/MultilineTextInput.js +607 -0
  17. package/dist/src/components/MultilineTextInput.js.map +1 -0
  18. package/dist/src/components/Overlay.d.ts +46 -0
  19. package/dist/src/components/Overlay.d.ts.map +1 -0
  20. package/dist/src/components/Overlay.js +11 -0
  21. package/dist/src/components/Overlay.js.map +1 -0
  22. package/dist/src/components/Static.d.ts +44 -0
  23. package/dist/src/components/Static.d.ts.map +1 -0
  24. package/dist/src/components/Static.js +53 -0
  25. package/dist/src/components/Static.js.map +1 -0
  26. package/dist/src/components/TextInput.d.ts +55 -0
  27. package/dist/src/components/TextInput.d.ts.map +1 -0
  28. package/dist/src/components/TextInput.js +277 -0
  29. package/dist/src/components/TextInput.js.map +1 -0
  30. package/dist/src/components/index.d.ts +7 -0
  31. package/dist/src/components/index.d.ts.map +1 -0
  32. package/dist/src/components/index.js +7 -0
  33. package/dist/src/components/index.js.map +1 -0
  34. package/dist/src/components/text-editing.d.ts +62 -0
  35. package/dist/src/components/text-editing.d.ts.map +1 -0
  36. package/dist/src/components/text-editing.js +385 -0
  37. package/dist/src/components/text-editing.js.map +1 -0
  38. package/dist/src/console/ConsoleCapture.d.ts +36 -0
  39. package/dist/src/console/ConsoleCapture.d.ts.map +1 -0
  40. package/dist/src/console/ConsoleCapture.js +210 -0
  41. package/dist/src/console/ConsoleCapture.js.map +1 -0
  42. package/dist/src/console/ConsolePopover.d.ts +18 -0
  43. package/dist/src/console/ConsolePopover.d.ts.map +1 -0
  44. package/dist/src/console/ConsolePopover.js +324 -0
  45. package/dist/src/console/ConsolePopover.js.map +1 -0
  46. package/dist/src/console/clipboard.d.ts +10 -0
  47. package/dist/src/console/clipboard.d.ts.map +1 -0
  48. package/dist/src/console/clipboard.js +74 -0
  49. package/dist/src/console/clipboard.js.map +1 -0
  50. package/dist/src/console/index.d.ts +5 -0
  51. package/dist/src/console/index.d.ts.map +1 -0
  52. package/dist/src/console/index.js +33 -0
  53. package/dist/src/console/index.js.map +1 -0
  54. package/dist/src/console/useConsole.d.ts +44 -0
  55. package/dist/src/console/useConsole.d.ts.map +1 -0
  56. package/dist/src/console/useConsole.js +91 -0
  57. package/dist/src/console/useConsole.js.map +1 -0
  58. package/dist/src/debug/DebugOverlay.d.ts +49 -0
  59. package/dist/src/debug/DebugOverlay.d.ts.map +1 -0
  60. package/dist/src/debug/DebugOverlay.js +438 -0
  61. package/dist/src/debug/DebugOverlay.js.map +1 -0
  62. package/dist/src/debug/DiagnosticsPanel.d.ts.map +1 -1
  63. package/dist/src/debug/DiagnosticsPanel.js.map +1 -1
  64. package/dist/src/dev/Toast.d.ts +19 -0
  65. package/dist/src/dev/Toast.d.ts.map +1 -0
  66. package/dist/src/dev/Toast.js +72 -0
  67. package/dist/src/dev/Toast.js.map +1 -0
  68. package/dist/src/dev/index.d.ts +2 -0
  69. package/dist/src/dev/index.d.ts.map +1 -0
  70. package/dist/src/dev/index.js +3 -0
  71. package/dist/src/dev/index.js.map +1 -0
  72. package/dist/src/dev.d.ts +114 -0
  73. package/dist/src/dev.d.ts.map +1 -0
  74. package/dist/src/dev.js +373 -0
  75. package/dist/src/dev.js.map +1 -0
  76. package/dist/src/highlight.d.ts +3 -3
  77. package/dist/src/highlight.d.ts.map +1 -1
  78. package/dist/src/highlight.js.map +1 -1
  79. package/dist/src/hmr-plugin.d.ts +2 -0
  80. package/dist/src/hmr-plugin.d.ts.map +1 -0
  81. package/dist/src/hmr-plugin.js +53 -0
  82. package/dist/src/hmr-plugin.js.map +1 -0
  83. package/dist/src/hooks/index.d.ts +4 -0
  84. package/dist/src/hooks/index.d.ts.map +1 -1
  85. package/dist/src/hooks/index.js +2 -0
  86. package/dist/src/hooks/index.js.map +1 -1
  87. package/dist/src/hooks/use-keyboard.d.ts +11 -0
  88. package/dist/src/hooks/use-keyboard.d.ts.map +1 -1
  89. package/dist/src/hooks/use-keyboard.js +22 -4
  90. package/dist/src/hooks/use-keyboard.js.map +1 -1
  91. package/dist/src/hooks/use-mouse.d.ts +24 -0
  92. package/dist/src/hooks/use-mouse.d.ts.map +1 -0
  93. package/dist/src/hooks/use-mouse.js +41 -0
  94. package/dist/src/hooks/use-mouse.js.map +1 -0
  95. package/dist/src/hooks/use-paste.d.ts +11 -0
  96. package/dist/src/hooks/use-paste.d.ts.map +1 -1
  97. package/dist/src/hooks/use-paste.js +17 -3
  98. package/dist/src/hooks/use-paste.js.map +1 -1
  99. package/dist/src/hooks/use-scroll.d.ts +79 -0
  100. package/dist/src/hooks/use-scroll.d.ts.map +1 -0
  101. package/dist/src/hooks/use-scroll.js +239 -0
  102. package/dist/src/hooks/use-scroll.js.map +1 -0
  103. package/dist/src/hooks/useFrameStats.js.map +1 -1
  104. package/dist/src/hosts/base.d.ts +62 -1
  105. package/dist/src/hosts/base.d.ts.map +1 -1
  106. package/dist/src/hosts/base.js +118 -5
  107. package/dist/src/hosts/base.js.map +1 -1
  108. package/dist/src/hosts/box.d.ts +7 -7
  109. package/dist/src/hosts/box.d.ts.map +1 -1
  110. package/dist/src/hosts/box.js +30 -23
  111. package/dist/src/hosts/box.js.map +1 -1
  112. package/dist/src/hosts/canvas.d.ts +16 -8
  113. package/dist/src/hosts/canvas.d.ts.map +1 -1
  114. package/dist/src/hosts/canvas.js +27 -22
  115. package/dist/src/hosts/canvas.js.map +1 -1
  116. package/dist/src/hosts/codeblock.d.ts +7 -7
  117. package/dist/src/hosts/codeblock.d.ts.map +1 -1
  118. package/dist/src/hosts/codeblock.js +11 -20
  119. package/dist/src/hosts/codeblock.js.map +1 -1
  120. package/dist/src/hosts/flex-container.d.ts +45 -0
  121. package/dist/src/hosts/flex-container.d.ts.map +1 -0
  122. package/dist/src/hosts/flex-container.js +90 -0
  123. package/dist/src/hosts/flex-container.js.map +1 -0
  124. package/dist/src/hosts/hstack.d.ts +6 -11
  125. package/dist/src/hosts/hstack.d.ts.map +1 -1
  126. package/dist/src/hosts/hstack.js +6 -41
  127. package/dist/src/hosts/hstack.js.map +1 -1
  128. package/dist/src/hosts/index.d.ts +4 -0
  129. package/dist/src/hosts/index.d.ts.map +1 -1
  130. package/dist/src/hosts/index.js +10 -0
  131. package/dist/src/hosts/index.js.map +1 -1
  132. package/dist/src/hosts/overlay-item.d.ts +32 -0
  133. package/dist/src/hosts/overlay-item.d.ts.map +1 -0
  134. package/dist/src/hosts/overlay-item.js +54 -0
  135. package/dist/src/hosts/overlay-item.js.map +1 -0
  136. package/dist/src/hosts/overlay.d.ts +30 -0
  137. package/dist/src/hosts/overlay.d.ts.map +1 -0
  138. package/dist/src/hosts/overlay.js +105 -0
  139. package/dist/src/hosts/overlay.js.map +1 -0
  140. package/dist/src/hosts/scroll.d.ts +56 -0
  141. package/dist/src/hosts/scroll.d.ts.map +1 -0
  142. package/dist/src/hosts/scroll.js +204 -0
  143. package/dist/src/hosts/scroll.js.map +1 -0
  144. package/dist/src/hosts/single-child.d.ts +16 -0
  145. package/dist/src/hosts/single-child.d.ts.map +1 -0
  146. package/dist/src/hosts/single-child.js +45 -0
  147. package/dist/src/hosts/single-child.js.map +1 -0
  148. package/dist/src/hosts/spacer.d.ts.map +1 -1
  149. package/dist/src/hosts/spacer.js +7 -3
  150. package/dist/src/hosts/spacer.js.map +1 -1
  151. package/dist/src/hosts/text.d.ts +9 -6
  152. package/dist/src/hosts/text.d.ts.map +1 -1
  153. package/dist/src/hosts/text.js +49 -22
  154. package/dist/src/hosts/text.js.map +1 -1
  155. package/dist/src/hosts/vstack.d.ts +6 -11
  156. package/dist/src/hosts/vstack.d.ts.map +1 -1
  157. package/dist/src/hosts/vstack.js +6 -41
  158. package/dist/src/hosts/vstack.js.map +1 -1
  159. package/dist/src/hosts/zstack.d.ts.map +1 -1
  160. package/dist/src/hosts/zstack.js +16 -5
  161. package/dist/src/hosts/zstack.js.map +1 -1
  162. package/dist/src/index.d.ts +9 -2
  163. package/dist/src/index.d.ts.map +1 -1
  164. package/dist/src/index.js +10 -2
  165. package/dist/src/index.js.map +1 -1
  166. package/dist/src/inline/index.d.ts.map +1 -1
  167. package/dist/src/inline/index.js.map +1 -1
  168. package/dist/src/motion/color-motion-value.d.ts.map +1 -1
  169. package/dist/src/motion/color-motion-value.js.map +1 -1
  170. package/dist/src/motion/color.d.ts +1 -29
  171. package/dist/src/motion/color.d.ts.map +1 -1
  172. package/dist/src/motion/color.js +2 -170
  173. package/dist/src/motion/color.js.map +1 -1
  174. package/dist/src/motion/color.test.js.map +1 -1
  175. package/dist/src/motion/event-emitter.d.ts.map +1 -1
  176. package/dist/src/motion/event-emitter.js.map +1 -1
  177. package/dist/src/motion/frame.js.map +1 -1
  178. package/dist/src/motion/hooks.d.ts.map +1 -1
  179. package/dist/src/motion/hooks.js +8 -3
  180. package/dist/src/motion/hooks.js.map +1 -1
  181. package/dist/src/motion/index.d.ts.map +1 -1
  182. package/dist/src/motion/index.js.map +1 -1
  183. package/dist/src/motion/motion-value.d.ts.map +1 -1
  184. package/dist/src/motion/motion-value.js.map +1 -1
  185. package/dist/src/motion/motion-value.test.js.map +1 -1
  186. package/dist/src/motion/spring-math.d.ts +6 -1
  187. package/dist/src/motion/spring-math.d.ts.map +1 -1
  188. package/dist/src/motion/spring-math.js +6 -1
  189. package/dist/src/motion/spring-math.js.map +1 -1
  190. package/dist/src/motion/types.d.ts.map +1 -1
  191. package/dist/src/motion/types.js.map +1 -1
  192. package/dist/src/profiler.js.map +1 -1
  193. package/dist/src/reconciler/host-config.d.ts +5 -5
  194. package/dist/src/reconciler/host-config.d.ts.map +1 -1
  195. package/dist/src/reconciler/host-config.js +43 -51
  196. package/dist/src/reconciler/host-config.js.map +1 -1
  197. package/dist/src/reconciler/noop-methods.d.ts +29 -0
  198. package/dist/src/reconciler/noop-methods.d.ts.map +1 -0
  199. package/dist/src/reconciler/noop-methods.js +43 -0
  200. package/dist/src/reconciler/noop-methods.js.map +1 -0
  201. package/dist/src/reconciler/types.d.ts +68 -14
  202. package/dist/src/reconciler/types.d.ts.map +1 -1
  203. package/dist/src/remote/Procedures.d.ts +22 -0
  204. package/dist/src/remote/Procedures.d.ts.map +1 -0
  205. package/dist/src/remote/Procedures.js +42 -0
  206. package/dist/src/remote/Procedures.js.map +1 -0
  207. package/dist/src/remote/Router.d.ts +20 -0
  208. package/dist/src/remote/Router.d.ts.map +1 -0
  209. package/dist/src/remote/Router.js +26 -0
  210. package/dist/src/remote/Router.js.map +1 -0
  211. package/dist/src/remote/Server.d.ts +6 -0
  212. package/dist/src/remote/Server.d.ts.map +1 -0
  213. package/dist/src/remote/Server.js +53 -0
  214. package/dist/src/remote/Server.js.map +1 -0
  215. package/dist/src/remote/index.d.ts +18 -0
  216. package/dist/src/remote/index.d.ts.map +1 -0
  217. package/dist/src/remote/index.js +74 -0
  218. package/dist/src/remote/index.js.map +1 -0
  219. package/dist/src/renderer/core/FrameBuilder.d.ts +18 -0
  220. package/dist/src/renderer/core/FrameBuilder.d.ts.map +1 -0
  221. package/dist/src/renderer/core/FrameBuilder.js +38 -0
  222. package/dist/src/renderer/core/FrameBuilder.js.map +1 -0
  223. package/dist/src/renderer/core/RendererState.d.ts +41 -0
  224. package/dist/src/renderer/core/RendererState.d.ts.map +1 -0
  225. package/dist/src/renderer/core/RendererState.js +70 -0
  226. package/dist/src/renderer/core/RendererState.js.map +1 -0
  227. package/dist/src/renderer/core/index.d.ts +3 -0
  228. package/dist/src/renderer/core/index.d.ts.map +1 -0
  229. package/dist/src/renderer/core/index.js +3 -0
  230. package/dist/src/renderer/core/index.js.map +1 -0
  231. package/dist/src/renderer/input/InputProcessor.d.ts +25 -0
  232. package/dist/src/renderer/input/InputProcessor.d.ts.map +1 -0
  233. package/dist/src/renderer/input/InputProcessor.js +81 -0
  234. package/dist/src/renderer/input/InputProcessor.js.map +1 -0
  235. package/dist/src/renderer/input/index.d.ts +2 -0
  236. package/dist/src/renderer/input/index.d.ts.map +1 -0
  237. package/dist/src/renderer/input/index.js +2 -0
  238. package/dist/src/renderer/input/index.js.map +1 -0
  239. package/dist/src/renderer/lifecycle/EventBus.d.ts +41 -0
  240. package/dist/src/renderer/lifecycle/EventBus.d.ts.map +1 -0
  241. package/dist/src/renderer/lifecycle/EventBus.js +78 -0
  242. package/dist/src/renderer/lifecycle/EventBus.js.map +1 -0
  243. package/dist/src/renderer/lifecycle/ResizeManager.d.ts +34 -0
  244. package/dist/src/renderer/lifecycle/ResizeManager.d.ts.map +1 -0
  245. package/dist/src/renderer/lifecycle/ResizeManager.js +47 -0
  246. package/dist/src/renderer/lifecycle/ResizeManager.js.map +1 -0
  247. package/dist/src/renderer/lifecycle/TerminalSetup.d.ts +36 -0
  248. package/dist/src/renderer/lifecycle/TerminalSetup.d.ts.map +1 -0
  249. package/dist/src/renderer/lifecycle/TerminalSetup.js +82 -0
  250. package/dist/src/renderer/lifecycle/TerminalSetup.js.map +1 -0
  251. package/dist/src/renderer/lifecycle/index.d.ts +4 -0
  252. package/dist/src/renderer/lifecycle/index.d.ts.map +1 -0
  253. package/dist/src/renderer/lifecycle/index.js +4 -0
  254. package/dist/src/renderer/lifecycle/index.js.map +1 -0
  255. package/dist/src/renderer/modes/FullscreenRenderer.d.ts +12 -0
  256. package/dist/src/renderer/modes/FullscreenRenderer.d.ts.map +1 -0
  257. package/dist/src/renderer/modes/FullscreenRenderer.js +52 -0
  258. package/dist/src/renderer/modes/FullscreenRenderer.js.map +1 -0
  259. package/dist/src/renderer/modes/InlineRenderer.d.ts +25 -0
  260. package/dist/src/renderer/modes/InlineRenderer.d.ts.map +1 -0
  261. package/dist/src/renderer/modes/InlineRenderer.js +161 -0
  262. package/dist/src/renderer/modes/InlineRenderer.js.map +1 -0
  263. package/dist/src/renderer/modes/RendererMode.d.ts +42 -0
  264. package/dist/src/renderer/modes/RendererMode.d.ts.map +1 -0
  265. package/dist/src/renderer/modes/RendererMode.js +2 -0
  266. package/dist/src/renderer/modes/RendererMode.js.map +1 -0
  267. package/dist/src/renderer/modes/StaticContentRenderer.d.ts +25 -0
  268. package/dist/src/renderer/modes/StaticContentRenderer.d.ts.map +1 -0
  269. package/dist/src/renderer/modes/StaticContentRenderer.js +47 -0
  270. package/dist/src/renderer/modes/StaticContentRenderer.js.map +1 -0
  271. package/dist/src/renderer/modes/index.d.ts +5 -0
  272. package/dist/src/renderer/modes/index.d.ts.map +1 -0
  273. package/dist/src/renderer/modes/index.js +4 -0
  274. package/dist/src/renderer/modes/index.js.map +1 -0
  275. package/dist/src/renderer-context.d.ts +9 -0
  276. package/dist/src/renderer-context.d.ts.map +1 -0
  277. package/dist/src/renderer-context.js +22 -0
  278. package/dist/src/renderer-context.js.map +1 -0
  279. package/dist/src/renderer-types.d.ts +103 -0
  280. package/dist/src/renderer-types.d.ts.map +1 -0
  281. package/dist/src/renderer-types.js +2 -0
  282. package/dist/src/renderer-types.js.map +1 -0
  283. package/dist/src/renderer.d.ts +4 -86
  284. package/dist/src/renderer.d.ts.map +1 -1
  285. package/dist/src/renderer.js +214 -384
  286. package/dist/src/renderer.js.map +1 -1
  287. package/dist/src/test/index.d.ts.map +1 -1
  288. package/dist/src/test/index.js.map +1 -1
  289. package/dist/src/test/mock-streams.d.ts.map +1 -1
  290. package/dist/src/test/mock-streams.js.map +1 -1
  291. package/dist/src/test/render-tui.d.ts.map +1 -1
  292. package/dist/src/test/render-tui.js +2 -5
  293. package/dist/src/test/render-tui.js.map +1 -1
  294. package/dist/src/trace/SpanTree.d.ts.map +1 -1
  295. package/dist/src/trace/SpanTree.js +21 -11
  296. package/dist/src/trace/SpanTree.js.map +1 -1
  297. package/dist/src/trace/format-value.d.ts +15 -0
  298. package/dist/src/trace/format-value.d.ts.map +1 -0
  299. package/dist/src/trace/format-value.js +77 -0
  300. package/dist/src/trace/format-value.js.map +1 -0
  301. package/dist/src/trace/index.d.ts.map +1 -1
  302. package/dist/src/trace/index.js.map +1 -1
  303. package/dist/src/trace/location.js +1 -1
  304. package/dist/src/trace/location.js.map +1 -1
  305. package/dist/src/trace/span-processor.d.ts.map +1 -1
  306. package/dist/src/trace/span-processor.js.map +1 -1
  307. package/dist/src/trace/span-state.d.ts +19 -2
  308. package/dist/src/trace/span-state.d.ts.map +1 -1
  309. package/dist/src/trace/span-state.js +62 -31
  310. package/dist/src/trace/span-state.js.map +1 -1
  311. package/dist/src/trace/tui-logger.js.map +1 -1
  312. package/dist/src/utils/border.d.ts +1 -1
  313. package/dist/src/utils/border.d.ts.map +1 -1
  314. package/dist/src/utils/border.js +6 -0
  315. package/dist/src/utils/border.js.map +1 -1
  316. package/dist/src/utils/flex-layout.d.ts +2 -1
  317. package/dist/src/utils/flex-layout.d.ts.map +1 -1
  318. package/dist/src/utils/flex-layout.js +22 -33
  319. package/dist/src/utils/flex-layout.js.map +1 -1
  320. package/dist/src/utils/index.d.ts +1 -1
  321. package/dist/src/utils/index.d.ts.map +1 -1
  322. package/dist/src/utils/index.js +1 -1
  323. package/dist/src/utils/index.js.map +1 -1
  324. package/dist/src/utils/padding.d.ts.map +1 -1
  325. package/dist/src/utils/padding.js.map +1 -1
  326. package/dist/src/utils/styles.d.ts +20 -1
  327. package/dist/src/utils/styles.d.ts.map +1 -1
  328. package/dist/src/utils/styles.js +36 -1
  329. package/dist/src/utils/styles.js.map +1 -1
  330. package/dist/src/visualize/index.d.ts +8 -19
  331. package/dist/src/visualize/index.d.ts.map +1 -1
  332. package/dist/src/visualize/index.js +11 -25
  333. package/dist/src/visualize/index.js.map +1 -1
  334. package/dist/tsconfig.tsbuildinfo +1 -1
  335. package/jsx-dev-runtime.ts +5 -0
  336. package/jsx-runtime.ts +54 -0
  337. package/package.json +124 -92
  338. package/src/codeblock.tsx +34 -34
  339. package/src/components/Divider.tsx +23 -0
  340. package/src/components/Markdown.tsx +380 -0
  341. package/src/components/MultilineTextInput.tsx +749 -0
  342. package/src/components/Overlay.tsx +56 -0
  343. package/src/components/Static.tsx +68 -0
  344. package/src/components/TextInput.tsx +356 -0
  345. package/src/components/index.ts +6 -0
  346. package/src/components/text-editing.ts +464 -0
  347. package/src/console/ConsoleCapture.ts +272 -0
  348. package/src/console/ConsolePopover.tsx +487 -0
  349. package/src/console/clipboard.ts +81 -0
  350. package/src/console/index.ts +42 -0
  351. package/src/console/useConsole.ts +129 -0
  352. package/src/debug/DebugOverlay.ts +557 -0
  353. package/src/debug/DiagnosticsPanel.tsx +27 -27
  354. package/src/dev/Toast.tsx +117 -0
  355. package/src/dev/index.ts +2 -0
  356. package/src/dev.tsx +489 -0
  357. package/src/highlight.ts +46 -46
  358. package/src/hmr-plugin.ts +61 -0
  359. package/src/hooks/index.ts +4 -0
  360. package/src/hooks/use-keyboard.ts +44 -24
  361. package/src/hooks/use-mouse.ts +51 -0
  362. package/src/hooks/use-paste.ts +21 -6
  363. package/src/hooks/use-scroll.ts +386 -0
  364. package/src/hooks/useFrameStats.ts +17 -17
  365. package/src/hosts/base.ts +180 -59
  366. package/src/hosts/box.ts +117 -94
  367. package/src/hosts/canvas.ts +170 -141
  368. package/src/hosts/codeblock.ts +117 -133
  369. package/src/hosts/flex-container.ts +124 -0
  370. package/src/hosts/hstack.ts +11 -59
  371. package/src/hosts/index.ts +24 -14
  372. package/src/hosts/overlay-item.ts +72 -0
  373. package/src/hosts/overlay.ts +125 -0
  374. package/src/hosts/scroll.ts +255 -0
  375. package/src/hosts/single-child.ts +52 -0
  376. package/src/hosts/spacer.ts +30 -26
  377. package/src/hosts/text.ts +198 -164
  378. package/src/hosts/vstack.ts +11 -59
  379. package/src/hosts/zstack.ts +79 -67
  380. package/src/index.ts +44 -19
  381. package/src/inline/index.tsx +123 -123
  382. package/src/motion/color-motion-value.ts +67 -67
  383. package/src/motion/color.test.ts +107 -107
  384. package/src/motion/color.ts +9 -190
  385. package/src/motion/event-emitter.ts +20 -20
  386. package/src/motion/frame.ts +35 -35
  387. package/src/motion/hooks.ts +144 -139
  388. package/src/motion/index.ts +10 -10
  389. package/src/motion/motion-value.test.ts +207 -207
  390. package/src/motion/motion-value.ts +112 -112
  391. package/src/motion/spring-math.ts +88 -83
  392. package/src/motion/types.ts +25 -25
  393. package/src/profiler.ts +50 -50
  394. package/src/reconciler/host-config.ts +152 -174
  395. package/src/reconciler/noop-methods.ts +55 -0
  396. package/src/reconciler/types.ts +112 -46
  397. package/src/remote/Procedures.ts +52 -0
  398. package/src/remote/Router.ts +58 -0
  399. package/src/remote/Server.ts +76 -0
  400. package/src/remote/index.ts +90 -0
  401. package/src/renderer/core/FrameBuilder.ts +49 -0
  402. package/src/renderer/core/RendererState.ts +80 -0
  403. package/src/renderer/core/index.ts +2 -0
  404. package/src/renderer/input/InputProcessor.ts +94 -0
  405. package/src/renderer/input/index.ts +1 -0
  406. package/src/renderer/lifecycle/EventBus.ts +90 -0
  407. package/src/renderer/lifecycle/ResizeManager.ts +65 -0
  408. package/src/renderer/lifecycle/TerminalSetup.ts +105 -0
  409. package/src/renderer/lifecycle/index.ts +3 -0
  410. package/src/renderer/modes/FullscreenRenderer.ts +53 -0
  411. package/src/renderer/modes/InlineRenderer.ts +186 -0
  412. package/src/renderer/modes/RendererMode.ts +46 -0
  413. package/src/renderer/modes/StaticContentRenderer.ts +56 -0
  414. package/src/renderer/modes/index.ts +4 -0
  415. package/src/renderer-context.ts +27 -0
  416. package/src/renderer-types.ts +109 -0
  417. package/src/renderer.ts +392 -642
  418. package/src/test/index.ts +5 -5
  419. package/src/test/mock-streams.ts +115 -115
  420. package/src/test/render-tui.ts +84 -87
  421. package/src/utils/border.ts +79 -73
  422. package/src/utils/flex-layout.ts +80 -93
  423. package/src/utils/index.ts +1 -1
  424. package/src/utils/padding.ts +27 -27
  425. package/src/utils/styles.ts +50 -7
  426. package/src/visualize/index.tsx +225 -240
  427. package/dist/src/output.d.ts +0 -47
  428. package/dist/src/output.d.ts.map +0 -1
  429. package/dist/src/output.js +0 -125
  430. package/dist/src/output.js.map +0 -1
  431. package/dist/src/terminal.d.ts +0 -37
  432. package/dist/src/terminal.d.ts.map +0 -1
  433. package/dist/src/terminal.js +0 -65
  434. package/dist/src/terminal.js.map +0 -1
  435. package/src/output.ts +0 -156
  436. package/src/terminal.ts +0 -67
  437. package/src/trace/SpanTree.tsx +0 -195
  438. package/src/trace/index.tsx +0 -205
  439. package/src/trace/location.ts +0 -90
  440. package/src/trace/span-processor.ts +0 -65
  441. package/src/trace/span-state.ts +0 -286
  442. package/src/trace/tui-logger.ts +0 -72
@@ -0,0 +1,105 @@
1
+ import { ANSI, Terminal } from "@effect-tui/core"
2
+ import type { TuiWriteStream, TuiReadStream } from "../../renderer-types.js"
3
+
4
+ export interface TerminalSetupConfig {
5
+ mode: "fullscreen" | "inline"
6
+ enablePaste: boolean
7
+ enableMouse: boolean
8
+ skipTerminalSetup: boolean
9
+ /**
10
+ * Enable Kitty keyboard protocol for enhanced modifier detection.
11
+ * When enabled, Ctrl+Shift+C can be distinguished from Ctrl+C.
12
+ * Supported by: Kitty, iTerm2 3.5+, WezTerm, Ghostty, foot, Contour, rio.
13
+ * Gracefully ignored by terminals that don't support it.
14
+ * @default true
15
+ */
16
+ enableKittyKeyboard?: boolean
17
+ }
18
+
19
+ /**
20
+ * Manages terminal setup and teardown sequences.
21
+ * Handles fullscreen mode, cursor visibility, paste bracketing, mouse tracking, and raw mode.
22
+ */
23
+ export class TerminalSetup {
24
+ constructor(
25
+ private stdout: TuiWriteStream,
26
+ private stdin: TuiReadStream,
27
+ private config: TerminalSetupConfig,
28
+ ) {}
29
+
30
+ /**
31
+ * Set up terminal for rendering.
32
+ * Call this before starting the render loop.
33
+ */
34
+ setup(): void {
35
+ if (this.config.skipTerminalSetup) return
36
+
37
+ if (this.config.mode === "fullscreen") {
38
+ this.stdout.write(Terminal.enterFullscreen)
39
+ } else {
40
+ // Inline mode: try to disable reflow (DEC mode 2028)
41
+ // Supported by Contour, some others. Ignored by unsupported terminals.
42
+ this.stdout.write(ANSI.reflow.disable)
43
+ }
44
+
45
+ // Hide cursor during rendering (both modes)
46
+ this.stdout.write(Terminal.hideCursor)
47
+
48
+ if (this.config.enablePaste) {
49
+ this.stdout.write(ANSI.paste.enable)
50
+ }
51
+
52
+ if (this.config.enableMouse) {
53
+ this.stdout.write(ANSI.mouse.enable)
54
+ }
55
+
56
+ // Enable enhanced keyboard protocols for modifier detection
57
+ // This allows distinguishing Ctrl+Shift+C from Ctrl+C on supported terminals
58
+ // NOTE: Many terminals intercept Ctrl+Shift+C for their own copy function!
59
+ if (this.config.enableKittyKeyboard !== false) {
60
+ this.stdout.write(ANSI.keyboard.enable(1)) // Kitty protocol (flag 1 = disambiguate)
61
+ this.stdout.write(ANSI.modifyOtherKeys.enable) // xterm protocol (mode 2)
62
+ }
63
+
64
+ if (this.stdin.isTTY && this.stdin.setRawMode) {
65
+ this.stdin.setRawMode(true)
66
+ this.stdin.resume?.()
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Restore terminal to normal state.
72
+ * Call this when stopping the renderer.
73
+ */
74
+ teardown(): void {
75
+ if (this.config.skipTerminalSetup) return
76
+
77
+ if (this.config.mode === "fullscreen") {
78
+ this.stdout.write(Terminal.exitFullscreen)
79
+ } else {
80
+ // Re-enable reflow on exit
81
+ this.stdout.write(ANSI.reflow.enable)
82
+ this.stdout.write("\r\n")
83
+ }
84
+
85
+ if (this.config.enablePaste) {
86
+ this.stdout.write(ANSI.paste.disable)
87
+ }
88
+
89
+ if (this.config.enableMouse) {
90
+ this.stdout.write(ANSI.mouse.disable)
91
+ }
92
+
93
+ // Disable enhanced keyboard protocols
94
+ if (this.config.enableKittyKeyboard !== false) {
95
+ this.stdout.write(ANSI.keyboard.disable)
96
+ this.stdout.write(ANSI.modifyOtherKeys.disable)
97
+ }
98
+
99
+ this.stdout.write(Terminal.showCursor)
100
+
101
+ if (this.stdin.isTTY && this.stdin.setRawMode) {
102
+ this.stdin.setRawMode(false)
103
+ }
104
+ }
105
+ }
@@ -0,0 +1,3 @@
1
+ export { EventBus } from "./EventBus.js"
2
+ export { TerminalSetup, type TerminalSetupConfig } from "./TerminalSetup.js"
3
+ export { ResizeManager, type ResizeState, type ResizeResult } from "./ResizeManager.js"
@@ -0,0 +1,53 @@
1
+ import { ANSI, emitRowWithReset, findChangeWindow } from "@effect-tui/core"
2
+ import type { RendererMode, RenderContext, RenderOutput } from "./RendererMode.js"
3
+
4
+ /**
5
+ * Fullscreen rendering mode using alternate buffer.
6
+ * Supports line-by-line diffing for efficient updates.
7
+ */
8
+ export class FullscreenRenderer implements RendererMode {
9
+ private needsFullClear = false
10
+
11
+ generateOutput(ctx: RenderContext): RenderOutput {
12
+ const { nextBuffer, prevBuffer, palette, frameWidth, frameHeight, enableDiff } = ctx
13
+ let output = ""
14
+
15
+ // If a full clear was requested (e.g., on resize), prepend it to output
16
+ // so clear + content are written atomically (no visible flash)
17
+ if (this.needsFullClear) {
18
+ output += ANSI.cursor.to(1, 1)
19
+ this.needsFullClear = false
20
+ // After clear, we must redraw everything - can't rely on diff
21
+ for (let y = 0; y < frameHeight; y++) {
22
+ if (y > 0) output += ANSI.cursor.to(1, y + 1)
23
+ output += emitRowWithReset(nextBuffer, palette, y, frameWidth)
24
+ }
25
+ } else if (enableDiff && prevBuffer) {
26
+ // Diff per line for minimal writes
27
+ for (let y = 0; y < frameHeight; y++) {
28
+ const change = findChangeWindow(prevBuffer, nextBuffer, y, frameWidth)
29
+ if (!change) continue
30
+ output += ANSI.cursor.to(change.left + 1, y + 1)
31
+ output += emitRowWithReset(nextBuffer, palette, y, frameWidth, change.left, change.right + 1)
32
+ }
33
+ } else {
34
+ // Full redraw (tests/manual mode)
35
+ output += ANSI.cursor.to(1, 1) + palette.sgr(0)
36
+ for (let y = 0; y < frameHeight; y++) {
37
+ output += emitRowWithReset(nextBuffer, palette, y, frameWidth)
38
+ if (y < frameHeight - 1) output += "\r\n"
39
+ }
40
+ }
41
+
42
+ return { output, contentHeight: frameHeight }
43
+ }
44
+
45
+ handleResize(_newWidth: number, _newHeight: number, _prevWidth: number): void {
46
+ // Defer clear to generateOutput so it's written atomically with content
47
+ this.needsFullClear = true
48
+ }
49
+
50
+ reset(): void {
51
+ // Nothing to reset for fullscreen mode
52
+ }
53
+ }
@@ -0,0 +1,186 @@
1
+ import { ANSI, emitRowWithReset, rowContentWidth, findChangeWindow } from "@effect-tui/core"
2
+ import type { RendererMode, RenderContext, RenderOutput } from "./RendererMode.js"
3
+
4
+ /**
5
+ * Inline rendering mode that renders in-place without alternate buffer.
6
+ * When content exceeds terminal height, shows the bottom portion (bottom-aligned truncation).
7
+ */
8
+ export class InlineRenderer implements RendererMode {
9
+ private previousHeight = 0
10
+ private previousStartRow = 0 // Track which row we started from (for truncation)
11
+ private _needsFullRerender = false
12
+ private printedWidths: number[] = []
13
+ private _forceFullOutput = false
14
+
15
+ generateOutput(ctx: RenderContext): RenderOutput {
16
+ const { prevBuffer, frameHeight, contentHeight } = ctx
17
+ let output = ""
18
+
19
+ // Calculate visible region (bottom-aligned when overflowing)
20
+ const isOverflowing = contentHeight > frameHeight
21
+ const visibleHeight = Math.min(contentHeight, frameHeight)
22
+ const startRow = isOverflowing ? contentHeight - frameHeight : 0
23
+
24
+ // Detect if viewport shifted (content grew/shrank affecting visible region)
25
+ const startRowChanged = startRow !== this.previousStartRow
26
+ const needsFullRedraw = this.previousHeight >= frameHeight || startRowChanged
27
+
28
+ // Need full redraw if: at terminal limit, or viewport shifted
29
+ if (needsFullRedraw) {
30
+ // Clear visible area and redraw (prepend to output for atomic write)
31
+ if (this.previousHeight > 0) {
32
+ output += ANSI.cursor.up(this.previousHeight)
33
+ }
34
+ output += ANSI.cursor.startOfLine
35
+ this.previousStartRow = startRow
36
+ this.printedWidths = []
37
+ } else if (this.previousHeight > 0) {
38
+ // Normal case: move cursor up to start of previous output
39
+ output += ANSI.cursor.up(this.previousHeight)
40
+ output += ANSI.cursor.startOfLine
41
+ }
42
+
43
+ // Generate output for visible region
44
+ // Force full output after static content handling (diff mode cursor tracking gets desynchronized)
45
+ if (prevBuffer && !needsFullRedraw && !this._forceFullOutput) {
46
+ output += this.generateDiffOutput(ctx, visibleHeight, startRow)
47
+ } else {
48
+ output += this.generateFullOutput(ctx, visibleHeight, startRow, startRow + visibleHeight)
49
+ this._forceFullOutput = false
50
+ }
51
+
52
+ this.previousHeight = visibleHeight
53
+ this.previousStartRow = startRow
54
+ return { output, contentHeight: visibleHeight }
55
+ }
56
+
57
+ private generateDiffOutput(ctx: RenderContext, visibleHeight: number, startRow: number): string {
58
+ const { nextBuffer, prevBuffer, palette, frameWidth } = ctx
59
+ if (!prevBuffer) return ""
60
+
61
+ let output = ""
62
+ const rowsToProcess = Math.max(visibleHeight, this.previousHeight)
63
+ let cursorRow = 0
64
+
65
+ const moveToRow = (targetRow: number) => {
66
+ const delta = targetRow - cursorRow
67
+ if (delta > 0) {
68
+ output += ANSI.cursor.down(delta)
69
+ } else if (delta < 0) {
70
+ output += ANSI.cursor.up(-delta)
71
+ }
72
+ cursorRow = targetRow
73
+ }
74
+
75
+ for (let screenY = 0; screenY < rowsToProcess; screenY++) {
76
+ const bufferY = startRow + screenY
77
+
78
+ // Rows beyond visible height: clear if previously printed
79
+ if (screenY >= visibleHeight) {
80
+ const prevW = this.printedWidths[screenY] ?? 0
81
+ if (prevW > 0) {
82
+ moveToRow(screenY)
83
+ output += ANSI.cursor.toCol(1) + palette.sgr(0) + " ".repeat(prevW)
84
+ this.printedWidths[screenY] = 0
85
+ }
86
+ continue
87
+ }
88
+
89
+ const change = findChangeWindow(prevBuffer, nextBuffer, bufferY, frameWidth)
90
+ const newW = rowContentWidth(nextBuffer, bufferY, frameWidth)
91
+ const prevW = this.printedWidths[screenY] ?? 0
92
+
93
+ if (!change) {
94
+ // No change; maybe need to clear tail if content shrunk
95
+ if (prevW > newW) {
96
+ moveToRow(screenY)
97
+ output += ANSI.cursor.toCol(newW + 1) + palette.sgr(0) + " ".repeat(prevW - newW)
98
+ this.printedWidths[screenY] = newW
99
+ }
100
+ continue
101
+ }
102
+
103
+ // Emit changed region [left..right]
104
+ moveToRow(screenY)
105
+ output += ANSI.cursor.toCol(change.left + 1)
106
+ output += emitRowWithReset(nextBuffer, palette, bufferY, frameWidth, change.left, change.right + 1)
107
+
108
+ // Clear tail if shrunk
109
+ const effectiveW = Math.max(newW, change.right + 1)
110
+ if (prevW > effectiveW) {
111
+ output += ANSI.cursor.toCol(effectiveW + 1) + palette.sgr(0) + " ".repeat(prevW - effectiveW)
112
+ }
113
+ this.printedWidths[screenY] = newW
114
+ }
115
+
116
+ // Ensure cursor ends just after the dynamic block for next frame positioning
117
+ moveToRow(visibleHeight)
118
+ output += ANSI.cursor.toCol(1)
119
+
120
+ return output
121
+ }
122
+
123
+ private generateFullOutput(ctx: RenderContext, rowCount: number, startRow: number, endRow: number): string {
124
+ const { nextBuffer, palette, frameWidth } = ctx
125
+ let output = ""
126
+
127
+ // Full redraw inline: clear each line first, then emit content
128
+ for (let bufferY = startRow; bufferY < endRow; bufferY++) {
129
+ const screenY = bufferY - startRow
130
+ const trimmedWidth = rowContentWidth(nextBuffer, bufferY, frameWidth)
131
+ // Full-width emit avoids reliance on line clears.
132
+ output += emitRowWithReset(nextBuffer, palette, bufferY, frameWidth, 0, frameWidth)
133
+ output += "\r\n"
134
+ // Track line widths for resize reflow calculation
135
+ this.printedWidths[screenY] = trimmedWidth
136
+ }
137
+
138
+ // Clear any extra lines if content shrank
139
+ for (let screenY = rowCount; screenY < this.previousHeight; screenY++) {
140
+ output += palette.sgr(0) + " ".repeat(frameWidth) + "\r\n"
141
+ this.printedWidths[screenY] = 0
142
+ }
143
+
144
+ // Move cursor back up to end of content
145
+ if (this.previousHeight > rowCount) {
146
+ output += ANSI.cursor.up(this.previousHeight - rowCount)
147
+ }
148
+
149
+ return output
150
+ }
151
+
152
+ handleResize(newWidth: number, _newHeight: number, prevWidth: number): void {
153
+ // Any width change triggers full rerender (Ink-style: clear + replay static)
154
+ if (newWidth !== prevWidth) {
155
+ this._needsFullRerender = true
156
+ }
157
+ }
158
+
159
+ /** Check if full rerender is needed (clear screen + replay static) */
160
+ needsFullRerender(): boolean {
161
+ return this._needsFullRerender
162
+ }
163
+
164
+ /** Clear the full rerender flag after handling */
165
+ clearFullRerenderFlag(): void {
166
+ this._needsFullRerender = false
167
+ this.previousHeight = 0
168
+ this.previousStartRow = 0
169
+ this.printedWidths = []
170
+ }
171
+
172
+ reset(): void {
173
+ this.previousHeight = 0
174
+ this.previousStartRow = 0
175
+ this.printedWidths = []
176
+ }
177
+
178
+ /** Force full output on the next frame (needed after static content to resync cursor tracking) */
179
+ forceFullOutputOnce(): void {
180
+ this._forceFullOutput = true
181
+ }
182
+
183
+ getPreviousHeight(): number {
184
+ return this.previousHeight
185
+ }
186
+ }
@@ -0,0 +1,46 @@
1
+ import type { CellBuffer, Palette } from "@effect-tui/core"
2
+ import type { TuiWriteStream } from "../../renderer-types.js"
3
+
4
+ /**
5
+ * Context passed to render mode output generation.
6
+ */
7
+ export interface RenderContext {
8
+ nextBuffer: CellBuffer
9
+ prevBuffer: CellBuffer | null
10
+ palette: Palette
11
+ frameWidth: number
12
+ /** Terminal height (viewport) */
13
+ frameHeight: number
14
+ /** Actual content height (may exceed frameHeight in inline mode) */
15
+ contentHeight: number
16
+ enableDiff: boolean
17
+ stdout: TuiWriteStream
18
+ }
19
+
20
+ /**
21
+ * Result of generating output for a frame.
22
+ */
23
+ export interface RenderOutput {
24
+ output: string
25
+ contentHeight: number
26
+ }
27
+
28
+ /**
29
+ * Interface for render mode implementations.
30
+ */
31
+ export interface RendererMode {
32
+ /**
33
+ * Generate ANSI output for the current frame.
34
+ */
35
+ generateOutput(ctx: RenderContext): RenderOutput
36
+
37
+ /**
38
+ * Handle a resize event. Returns true if a full clear is needed.
39
+ */
40
+ handleResize(newWidth: number, newHeight: number, prevWidth: number): void
41
+
42
+ /**
43
+ * Reset any mode-specific state (e.g., after static content flush).
44
+ */
45
+ reset(): void
46
+ }
@@ -0,0 +1,56 @@
1
+ import { CellBuffer, emitRowWithReset, rowContentWidth, type Palette } from "@effect-tui/core"
2
+ import type { HostInstance } from "../../reconciler/types.js"
3
+ import type { TuiWriteStream } from "../../renderer-types.js"
4
+
5
+ /**
6
+ * Renders static content to scrollback (inline mode only).
7
+ * Static content is rendered once and doesn't update with the dynamic section.
8
+ * Caches all output for replay on resize (Ink-style).
9
+ */
10
+ export class StaticContentRenderer {
11
+ private cachedOutput = "" // Accumulates all static content for replay
12
+
13
+ constructor(
14
+ _stdout: TuiWriteStream, // Kept for API compatibility, not used (writes are atomic in renderer.ts)
15
+ private palette: Palette,
16
+ ) {}
17
+
18
+ /** Get all cached static output for replay on resize */
19
+ getCachedOutput(): string {
20
+ return this.cachedOutput
21
+ }
22
+
23
+ /** Clear the cache (call after full terminal clear + replay) */
24
+ clearCache(): void {
25
+ this.cachedOutput = ""
26
+ }
27
+
28
+ /**
29
+ * Render a static node and return the output string.
30
+ * Static content is append-only - no cursor positioning needed.
31
+ * Caller clears dynamic area first, then appends this output.
32
+ */
33
+ render(staticNode: HostInstance, frameWidth: number): string {
34
+ // Measure and layout static content
35
+ const staticSize = staticNode.measure(frameWidth, Number.MAX_SAFE_INTEGER)
36
+ staticNode.layout({ x: 0, y: 0, w: frameWidth, h: staticSize.h })
37
+
38
+ // Render to a temporary buffer
39
+ const staticBuffer = new CellBuffer(frameWidth, staticSize.h)
40
+ staticBuffer.clear(0)
41
+ staticNode.render(staticBuffer, this.palette)
42
+
43
+ // Build content lines - append-only, no cursor movement
44
+ let contentLines = ""
45
+ for (let y = 0; y < staticSize.h; y++) {
46
+ const trimmedWidth = rowContentWidth(staticBuffer, y, frameWidth)
47
+ const line = emitRowWithReset(staticBuffer, this.palette, y, frameWidth, 0, trimmedWidth)
48
+ contentLines += line + "\n"
49
+ }
50
+
51
+ // Cache the content for replay on resize
52
+ this.cachedOutput += contentLines
53
+
54
+ return contentLines
55
+ }
56
+ }
@@ -0,0 +1,4 @@
1
+ export type { RendererMode, RenderContext, RenderOutput } from "./RendererMode.js"
2
+ export { FullscreenRenderer } from "./FullscreenRenderer.js"
3
+ export { InlineRenderer } from "./InlineRenderer.js"
4
+ export { StaticContentRenderer } from "./StaticContentRenderer.js"
@@ -0,0 +1,27 @@
1
+ import { createContext, useContext, useState, useEffect } from "react"
2
+ import type { TuiRenderer } from "./renderer-types.js"
3
+
4
+ // Context for accessing renderer in components
5
+ export const RendererContext = createContext<TuiRenderer | null>(null)
6
+
7
+ export function useRenderer(): TuiRenderer {
8
+ const renderer = useContext(RendererContext)
9
+ if (!renderer) {
10
+ throw new Error("useRenderer must be used within a TUI renderer")
11
+ }
12
+ return renderer
13
+ }
14
+
15
+ /** Hook that returns terminal size and re-renders on resize */
16
+ export function useTerminalSize(): { width: number; height: number } {
17
+ const renderer = useRenderer()
18
+ const [size, setSize] = useState({ width: renderer.width, height: renderer.height })
19
+
20
+ useEffect(() => {
21
+ return renderer.onResize((width, height) => {
22
+ setSize({ width, height })
23
+ })
24
+ }, [renderer])
25
+
26
+ return size
27
+ }
@@ -0,0 +1,109 @@
1
+ import type { KeyMsg, MouseMsg } from "@effect-tui/core"
2
+ import type { HostInstance, HostContext } from "./reconciler/types.js"
3
+
4
+ /** Minimal write stream interface for renderer output */
5
+ export interface TuiWriteStream {
6
+ write(s: string): void
7
+ columns: number
8
+ rows: number
9
+ on(event: string, cb: () => void): void
10
+ removeListener(event: string, cb: () => void): void
11
+ }
12
+
13
+ /** Minimal read stream interface for renderer input */
14
+ export interface TuiReadStream {
15
+ isTTY?: boolean
16
+ setRawMode?(mode: boolean): void
17
+ resume?(): void
18
+ on(event: string, cb: (data: Buffer) => void): void
19
+ removeListener(event: string, cb: (data: Buffer) => void): void
20
+ }
21
+
22
+ export interface TuiRenderer {
23
+ /** Terminal width */
24
+ width: number
25
+ /** Terminal height */
26
+ height: number
27
+ /** Request a re-render */
28
+ requestRender(): void
29
+ /** Subscribe to per-frame stats (if enabled). */
30
+ onFrameStats?(handler: (stats: FrameStats) => void): () => void
31
+ /** Subscribe to keyboard events */
32
+ onKey(handler: (key: KeyMsg) => void): () => void
33
+ /** Subscribe to mouse events (clicks, scroll, etc.) */
34
+ onMouse(handler: (mouse: MouseMsg) => void): () => void
35
+ /** Subscribe to paste events (bracketed paste mode). */
36
+ onPaste?(handler: (text: string) => void): () => void
37
+ /** Subscribe to resize events */
38
+ onResize(handler: (width: number, height: number) => void): () => void
39
+ /** Stop the renderer */
40
+ stop(): void
41
+ /** Manually trigger one render frame (only in manualMode) */
42
+ flush(): void
43
+ /**
44
+ * Get the current screen as ANSI string (for screenshots/debugging).
45
+ * Returns the last rendered frame with all ANSI color codes intact.
46
+ */
47
+ getScreenshot(): string
48
+ /** Dispatch a key event (for remote control) */
49
+ dispatchKey?(key: KeyMsg): void
50
+ /** Dispatch a paste event (for remote control) */
51
+ dispatchPaste?(text: string): void
52
+ /** Dispatch a resize event (for remote control) */
53
+ dispatchResize?(width: number, height: number): void
54
+ }
55
+
56
+ /** Internal renderer type with container reference */
57
+ export interface TuiRendererInternal extends TuiRenderer {
58
+ _container: Container | null
59
+ }
60
+
61
+ export interface Container {
62
+ root: HostInstance | null
63
+ ctx: HostContext
64
+ /** @internal Static content root node (for Static component) */
65
+ staticRoot?: HostInstance | null
66
+ /** @internal Flag indicating static content needs flushing */
67
+ staticDirty?: boolean
68
+ }
69
+
70
+ export interface RendererOptions {
71
+ fps?: number
72
+ stdout?: NodeJS.WriteStream | TuiWriteStream
73
+ stdin?: NodeJS.ReadStream | TuiReadStream
74
+ /** Render mode: "fullscreen" uses alternate buffer, "inline" renders in-place */
75
+ mode?: "fullscreen" | "inline"
76
+ /** Exit the process on Ctrl+C unless preventDefault was called. Defaults to true. */
77
+ exitOnCtrlC?: boolean
78
+ /** Enable diffed rendering (per-line). Defaults to true in runtime, false in manualMode (tests). */
79
+ diff?: boolean
80
+ /** Skip automatic render loop. Call flush() manually to render frames. */
81
+ manualMode?: boolean
82
+ /** Skip fullscreen/raw mode setup (for testing) */
83
+ skipTerminalSetup?: boolean
84
+ /** Enable bracketed paste (default true). */
85
+ enablePaste?: boolean
86
+ /** Enable mouse mode for scroll wheel events (default true in fullscreen). */
87
+ enableMouse?: boolean
88
+ /** Optional per-frame diagnostics hook. Called after each frame is written. */
89
+ debug?: {
90
+ onFrame?: (stats: FrameStats) => void
91
+ }
92
+ }
93
+
94
+ export interface FrameStats {
95
+ mode: "fullscreen" | "inline"
96
+ width: number
97
+ height: number
98
+ contentHeight: number
99
+ bytes: number
100
+ frameMs: number
101
+ phases: {
102
+ clear: number
103
+ layout: number
104
+ render: number
105
+ diffAnsi: number
106
+ write: number
107
+ }
108
+ timestamp: number
109
+ }