@fairyhunter13/opentui-core 0.1.89 → 0.1.91

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 (571) hide show
  1. package/README.md +2 -2
  2. package/dev/keypress-debug-renderer.ts +148 -0
  3. package/dev/keypress-debug.ts +43 -0
  4. package/dev/print-env-vars.ts +32 -0
  5. package/dev/test-tmux-graphics-334.sh +68 -0
  6. package/dev/thai-debug-test.ts +68 -0
  7. package/docs/development.md +141 -0
  8. package/docs/env-vars.md +140 -0
  9. package/docs/getting-started.md +353 -0
  10. package/docs/renderables-vs-constructs.md +159 -0
  11. package/docs/tree-sitter.md +311 -0
  12. package/package.json +61 -52
  13. package/scripts/build.ts +400 -0
  14. package/scripts/publish.ts +60 -0
  15. package/src/3d/SpriteResourceManager.ts +286 -0
  16. package/src/3d/SpriteUtils.ts +71 -0
  17. package/src/3d/TextureUtils.ts +196 -0
  18. package/src/3d/ThreeRenderable.ts +197 -0
  19. package/src/3d/WGPURenderer.ts +294 -0
  20. package/src/3d/animation/ExplodingSpriteEffect.ts +513 -0
  21. package/src/3d/animation/PhysicsExplodingSpriteEffect.ts +429 -0
  22. package/src/3d/animation/SpriteAnimator.ts +633 -0
  23. package/src/3d/animation/SpriteParticleGenerator.ts +435 -0
  24. package/src/3d/canvas.ts +464 -0
  25. package/src/3d/index.ts +12 -0
  26. package/src/3d/physics/PlanckPhysicsAdapter.ts +72 -0
  27. package/src/3d/physics/RapierPhysicsAdapter.ts +66 -0
  28. package/src/3d/physics/physics-interface.ts +31 -0
  29. package/src/3d/shaders/supersampling.wgsl +201 -0
  30. package/src/3d.ts +3 -0
  31. package/src/NativeSpanFeed.ts +300 -0
  32. package/src/Renderable.ts +1698 -0
  33. package/src/__snapshots__/buffer.test.ts.snap +28 -0
  34. package/src/animation/Timeline.test.ts +2709 -0
  35. package/src/animation/Timeline.ts +598 -0
  36. package/src/ansi.ts +18 -0
  37. package/src/benchmark/latest-all-bench-run.json +707 -0
  38. package/src/benchmark/latest-async-bench-run.json +336 -0
  39. package/src/benchmark/latest-default-bench-run.json +657 -0
  40. package/src/benchmark/latest-large-bench-run.json +707 -0
  41. package/src/benchmark/latest-quick-bench-run.json +207 -0
  42. package/src/benchmark/markdown-benchmark.ts +1804 -0
  43. package/src/benchmark/native-span-feed-async-benchmark.ts +355 -0
  44. package/src/benchmark/native-span-feed-benchmark.md +56 -0
  45. package/src/benchmark/native-span-feed-benchmark.ts +596 -0
  46. package/src/benchmark/native-span-feed-compare.ts +280 -0
  47. package/src/benchmark/renderer-benchmark.ts +754 -0
  48. package/src/benchmark/text-table-benchmark.ts +947 -0
  49. package/src/buffer.test.ts +291 -0
  50. package/src/buffer.ts +519 -0
  51. package/src/console.test.ts +612 -0
  52. package/src/console.ts +1255 -0
  53. package/src/edit-buffer.test.ts +1769 -0
  54. package/src/edit-buffer.ts +411 -0
  55. package/src/editor-view.test.ts +1032 -0
  56. package/src/editor-view.ts +284 -0
  57. package/src/examples/ascii-font-selection-demo.ts +245 -0
  58. package/src/examples/assets/Water_2_M_Normal.jpg +0 -0
  59. package/src/examples/assets/concrete.png +0 -0
  60. package/src/examples/assets/crate.png +0 -0
  61. package/src/examples/assets/crate_emissive.png +0 -0
  62. package/src/examples/assets/forrest_background.png +0 -0
  63. package/src/examples/assets/hast-example.json +1018 -0
  64. package/src/examples/assets/heart.png +0 -0
  65. package/src/examples/assets/main_char_heavy_attack.png +0 -0
  66. package/src/examples/assets/main_char_idle.png +0 -0
  67. package/src/examples/assets/main_char_jump_end.png +0 -0
  68. package/src/examples/assets/main_char_jump_landing.png +0 -0
  69. package/src/examples/assets/main_char_jump_start.png +0 -0
  70. package/src/examples/assets/main_char_run_loop.png +0 -0
  71. package/src/examples/assets/roughness_map.jpg +0 -0
  72. package/src/examples/build.ts +115 -0
  73. package/src/examples/code-demo.ts +584 -0
  74. package/src/examples/console-demo.ts +358 -0
  75. package/src/examples/core-plugin-slots-demo.ts +759 -0
  76. package/src/examples/diff-demo.ts +699 -0
  77. package/src/examples/draggable-three-demo.ts +259 -0
  78. package/src/examples/editor-demo.ts +322 -0
  79. package/src/examples/extmarks-demo.ts +204 -0
  80. package/src/examples/focus-restore-demo.ts +310 -0
  81. package/src/examples/fonts.ts +245 -0
  82. package/src/examples/fractal-shader-demo.ts +268 -0
  83. package/src/examples/framebuffer-demo.ts +674 -0
  84. package/src/examples/full-unicode-demo.ts +181 -0
  85. package/src/examples/golden-star-demo.ts +933 -0
  86. package/src/examples/grayscale-buffer-demo.ts +249 -0
  87. package/src/examples/hast-syntax-highlighting-demo.ts +129 -0
  88. package/src/examples/index.ts +925 -0
  89. package/src/examples/input-demo.ts +377 -0
  90. package/src/examples/input-select-layout-demo.ts +425 -0
  91. package/src/examples/install.sh +143 -0
  92. package/src/examples/keypress-debug-demo.ts +452 -0
  93. package/src/examples/lib/HexList.ts +122 -0
  94. package/src/examples/lib/PaletteGrid.ts +125 -0
  95. package/src/examples/lib/standalone-keys.ts +25 -0
  96. package/src/examples/lib/tab-controller.ts +243 -0
  97. package/src/examples/lights-phong-demo.ts +290 -0
  98. package/src/examples/link-demo.ts +220 -0
  99. package/src/examples/live-state-demo.ts +480 -0
  100. package/src/examples/markdown-demo.ts +620 -0
  101. package/src/examples/mouse-interaction-demo.ts +428 -0
  102. package/src/examples/nested-zindex-demo.ts +357 -0
  103. package/src/examples/opacity-example.ts +235 -0
  104. package/src/examples/opentui-demo.ts +1057 -0
  105. package/src/examples/physx-planck-2d-demo.ts +507 -0
  106. package/src/examples/physx-rapier-2d-demo.ts +526 -0
  107. package/src/examples/relative-positioning-demo.ts +323 -0
  108. package/src/examples/scroll-example.ts +214 -0
  109. package/src/examples/scrollbox-mouse-test.ts +112 -0
  110. package/src/examples/scrollbox-overlay-hit-test.ts +206 -0
  111. package/src/examples/select-demo.ts +237 -0
  112. package/src/examples/shader-cube-demo.ts +772 -0
  113. package/src/examples/simple-layout-example.ts +591 -0
  114. package/src/examples/slider-demo.ts +617 -0
  115. package/src/examples/split-mode-demo.ts +445 -0
  116. package/src/examples/sprite-animation-demo.ts +443 -0
  117. package/src/examples/sprite-particle-generator-demo.ts +486 -0
  118. package/src/examples/static-sprite-demo.ts +193 -0
  119. package/src/examples/sticky-scroll-example.ts +308 -0
  120. package/src/examples/styled-text-demo.ts +282 -0
  121. package/src/examples/tab-select-demo.ts +219 -0
  122. package/src/examples/terminal-title.ts +29 -0
  123. package/src/examples/terminal.ts +305 -0
  124. package/src/examples/text-node-demo.ts +416 -0
  125. package/src/examples/text-selection-demo.ts +377 -0
  126. package/src/examples/text-table-demo.ts +503 -0
  127. package/src/examples/text-truncation-demo.ts +481 -0
  128. package/src/examples/text-wrap.ts +757 -0
  129. package/src/examples/texture-loading-demo.ts +259 -0
  130. package/src/examples/timeline-example.ts +670 -0
  131. package/src/examples/transparency-demo.ts +241 -0
  132. package/src/examples/vnode-composition-demo.ts +404 -0
  133. package/src/index.ts +22 -0
  134. package/src/lib/KeyHandler.integration.test.ts +292 -0
  135. package/src/lib/KeyHandler.stopPropagation.test.ts +289 -0
  136. package/src/lib/KeyHandler.test.ts +662 -0
  137. package/src/lib/KeyHandler.ts +222 -0
  138. package/src/lib/RGBA.test.ts +984 -0
  139. package/src/lib/RGBA.ts +204 -0
  140. package/src/lib/ascii.font.ts +330 -0
  141. package/src/lib/border.test.ts +83 -0
  142. package/src/lib/border.ts +168 -0
  143. package/src/lib/bunfs.test.ts +27 -0
  144. package/src/lib/bunfs.ts +18 -0
  145. package/src/lib/clipboard.test.ts +41 -0
  146. package/src/lib/clipboard.ts +47 -0
  147. package/src/lib/clock.ts +31 -0
  148. package/src/lib/data-paths.test.ts +133 -0
  149. package/src/lib/data-paths.ts +109 -0
  150. package/src/lib/debounce.ts +106 -0
  151. package/src/lib/detect-links.test.ts +98 -0
  152. package/src/lib/detect-links.ts +56 -0
  153. package/src/lib/env.test.ts +228 -0
  154. package/src/lib/env.ts +209 -0
  155. package/src/lib/extmarks-history.ts +51 -0
  156. package/src/lib/extmarks-multiwidth.test.ts +322 -0
  157. package/src/lib/extmarks.test.ts +3457 -0
  158. package/src/lib/extmarks.ts +843 -0
  159. package/src/lib/fonts/block.json +405 -0
  160. package/src/lib/fonts/grid.json +265 -0
  161. package/src/lib/fonts/huge.json +741 -0
  162. package/src/lib/fonts/pallet.json +314 -0
  163. package/src/lib/fonts/shade.json +591 -0
  164. package/src/lib/fonts/slick.json +321 -0
  165. package/src/lib/fonts/tiny.json +69 -0
  166. package/src/lib/hast-styled-text.ts +59 -0
  167. package/src/lib/index.ts +21 -0
  168. package/src/lib/keymapping.test.ts +280 -0
  169. package/src/lib/keymapping.ts +87 -0
  170. package/src/lib/objects-in-viewport.test.ts +787 -0
  171. package/src/lib/objects-in-viewport.ts +153 -0
  172. package/src/lib/output.capture.ts +58 -0
  173. package/src/lib/parse.keypress-kitty.protocol.test.ts +340 -0
  174. package/src/lib/parse.keypress-kitty.test.ts +663 -0
  175. package/src/lib/parse.keypress-kitty.ts +439 -0
  176. package/src/lib/parse.keypress.test.ts +1849 -0
  177. package/src/lib/parse.keypress.ts +397 -0
  178. package/src/lib/parse.mouse.test.ts +552 -0
  179. package/src/lib/parse.mouse.ts +232 -0
  180. package/src/lib/paste.ts +16 -0
  181. package/src/lib/queue.ts +65 -0
  182. package/src/lib/renderable.validations.test.ts +87 -0
  183. package/src/lib/renderable.validations.ts +83 -0
  184. package/src/lib/scroll-acceleration.ts +98 -0
  185. package/src/lib/selection.ts +240 -0
  186. package/src/lib/singleton.ts +28 -0
  187. package/src/lib/stdin-parser.test.ts +1676 -0
  188. package/src/lib/stdin-parser.ts +1248 -0
  189. package/src/lib/styled-text.ts +178 -0
  190. package/src/lib/terminal-capability-detection.test.ts +202 -0
  191. package/src/lib/terminal-capability-detection.ts +79 -0
  192. package/src/lib/terminal-palette.test.ts +878 -0
  193. package/src/lib/terminal-palette.ts +383 -0
  194. package/src/lib/tree-sitter/assets/README.md +118 -0
  195. package/src/lib/tree-sitter/assets/update.ts +331 -0
  196. package/src/lib/tree-sitter/assets.d.ts +9 -0
  197. package/src/lib/tree-sitter/cache.test.ts +270 -0
  198. package/src/lib/tree-sitter/client.test.ts +1061 -0
  199. package/src/lib/tree-sitter/client.ts +615 -0
  200. package/src/lib/tree-sitter/default-parsers.ts +80 -0
  201. package/src/lib/tree-sitter/download-utils.ts +148 -0
  202. package/src/lib/tree-sitter/index.ts +28 -0
  203. package/src/lib/tree-sitter/parser.worker.ts +1001 -0
  204. package/src/lib/tree-sitter/parsers-config.ts +75 -0
  205. package/src/lib/tree-sitter/resolve-ft.ts +62 -0
  206. package/src/lib/tree-sitter/types.ts +81 -0
  207. package/src/lib/tree-sitter-styled-text.test.ts +1253 -0
  208. package/src/lib/tree-sitter-styled-text.ts +306 -0
  209. package/src/lib/validate-dir-name.ts +55 -0
  210. package/src/lib/yoga.options.test.ts +628 -0
  211. package/src/lib/yoga.options.ts +346 -0
  212. package/src/plugins/core-slot.ts +579 -0
  213. package/src/plugins/registry.ts +377 -0
  214. package/src/plugins/types.ts +46 -0
  215. package/src/post/filters.ts +888 -0
  216. package/src/renderables/ASCIIFont.ts +219 -0
  217. package/src/renderables/Box.test.ts +160 -0
  218. package/src/renderables/Box.ts +295 -0
  219. package/src/renderables/Code.test.ts +2062 -0
  220. package/src/renderables/Code.ts +357 -0
  221. package/src/renderables/Diff.regression.test.ts +226 -0
  222. package/src/renderables/Diff.test.ts +3027 -0
  223. package/src/renderables/Diff.ts +1209 -0
  224. package/src/renderables/EditBufferRenderable.ts +764 -0
  225. package/src/renderables/FrameBuffer.ts +47 -0
  226. package/src/renderables/Input.test.ts +1228 -0
  227. package/src/renderables/Input.ts +245 -0
  228. package/src/renderables/LineNumberRenderable.ts +675 -0
  229. package/src/renderables/Markdown.ts +1106 -0
  230. package/src/renderables/ScrollBar.ts +422 -0
  231. package/src/renderables/ScrollBox.ts +883 -0
  232. package/src/renderables/Select.test.ts +1010 -0
  233. package/src/renderables/Select.ts +523 -0
  234. package/src/renderables/Slider.test.ts +456 -0
  235. package/src/renderables/Slider.ts +347 -0
  236. package/src/renderables/TabSelect.test.ts +197 -0
  237. package/src/renderables/TabSelect.ts +455 -0
  238. package/src/renderables/Text.selection-buffer.test.ts +123 -0
  239. package/src/renderables/Text.test.ts +2660 -0
  240. package/src/renderables/Text.ts +147 -0
  241. package/src/renderables/TextBufferRenderable.ts +518 -0
  242. package/src/renderables/TextNode.test.ts +1058 -0
  243. package/src/renderables/TextNode.ts +325 -0
  244. package/src/renderables/TextTable.test.ts +1421 -0
  245. package/src/renderables/TextTable.ts +1344 -0
  246. package/src/renderables/Textarea.ts +732 -0
  247. package/src/renderables/TimeToFirstDraw.ts +89 -0
  248. package/src/renderables/__snapshots__/Code.test.ts.snap +13 -0
  249. package/src/renderables/__snapshots__/Diff.test.ts.snap +785 -0
  250. package/src/renderables/__snapshots__/Text.test.ts.snap +421 -0
  251. package/src/renderables/__snapshots__/TextTable.test.ts.snap +215 -0
  252. package/src/renderables/__tests__/LineNumberRenderable.scrollbox-simple.test.ts +144 -0
  253. package/src/renderables/__tests__/LineNumberRenderable.scrollbox.test.ts +816 -0
  254. package/src/renderables/__tests__/LineNumberRenderable.test.ts +1787 -0
  255. package/src/renderables/__tests__/LineNumberRenderable.wrapping.test.ts +85 -0
  256. package/src/renderables/__tests__/Markdown.test.ts +2287 -0
  257. package/src/renderables/__tests__/MultiRenderable.selection.test.ts +87 -0
  258. package/src/renderables/__tests__/Textarea.buffer.test.ts +682 -0
  259. package/src/renderables/__tests__/Textarea.destroyed-events.test.ts +675 -0
  260. package/src/renderables/__tests__/Textarea.editing.test.ts +2041 -0
  261. package/src/renderables/__tests__/Textarea.error-handling.test.ts +35 -0
  262. package/src/renderables/__tests__/Textarea.events.test.ts +738 -0
  263. package/src/renderables/__tests__/Textarea.highlights.test.ts +590 -0
  264. package/src/renderables/__tests__/Textarea.keybinding.test.ts +3149 -0
  265. package/src/renderables/__tests__/Textarea.paste.test.ts +357 -0
  266. package/src/renderables/__tests__/Textarea.rendering.test.ts +1864 -0
  267. package/src/renderables/__tests__/Textarea.scroll.test.ts +733 -0
  268. package/src/renderables/__tests__/Textarea.selection.test.ts +1590 -0
  269. package/src/renderables/__tests__/Textarea.stress.test.ts +670 -0
  270. package/src/renderables/__tests__/Textarea.undo-redo.test.ts +383 -0
  271. package/src/renderables/__tests__/Textarea.visual-lines.test.ts +310 -0
  272. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.code.test.ts.snap +221 -0
  273. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox-simple.test.ts.snap +89 -0
  274. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox.test.ts.snap +457 -0
  275. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.test.ts.snap +158 -0
  276. package/src/renderables/__tests__/__snapshots__/Textarea.rendering.test.ts.snap +387 -0
  277. package/src/renderables/__tests__/markdown-parser.test.ts +217 -0
  278. package/src/renderables/__tests__/renderable-test-utils.ts +60 -0
  279. package/src/renderables/composition/README.md +8 -0
  280. package/src/renderables/composition/VRenderable.ts +32 -0
  281. package/src/renderables/composition/constructs.ts +127 -0
  282. package/src/renderables/composition/vnode.ts +289 -0
  283. package/src/renderables/index.ts +22 -0
  284. package/src/renderables/markdown-parser.ts +66 -0
  285. package/src/renderer.ts +2363 -0
  286. package/src/runtime-plugin-support.ts +39 -0
  287. package/src/runtime-plugin.ts +144 -0
  288. package/src/syntax-style.test.ts +841 -0
  289. package/src/syntax-style.ts +264 -0
  290. package/src/testing/README.md +210 -0
  291. package/src/testing/capture-spans.test.ts +194 -0
  292. package/src/testing/integration.test.ts +276 -0
  293. package/src/testing/manual-clock.ts +106 -0
  294. package/src/testing/mock-keys.test.ts +1356 -0
  295. package/src/testing/mock-keys.ts +449 -0
  296. package/src/testing/mock-mouse.test.ts +218 -0
  297. package/src/testing/mock-mouse.ts +247 -0
  298. package/src/testing/mock-tree-sitter-client.ts +73 -0
  299. package/src/testing/spy.ts +13 -0
  300. package/src/testing/test-recorder.test.ts +415 -0
  301. package/src/testing/test-recorder.ts +145 -0
  302. package/src/testing/test-renderer.ts +116 -0
  303. package/src/testing.ts +7 -0
  304. package/src/tests/__snapshots__/absolute-positioning.snapshot.test.ts.snap +481 -0
  305. package/src/tests/__snapshots__/renderable.snapshot.test.ts.snap +19 -0
  306. package/src/tests/__snapshots__/scrollbox.test.ts.snap +29 -0
  307. package/src/tests/absolute-positioning.snapshot.test.ts +638 -0
  308. package/src/tests/allocator-stats.test.ts +38 -0
  309. package/src/tests/destroy-during-render.test.ts +200 -0
  310. package/src/tests/hover-cursor.test.ts +98 -0
  311. package/src/tests/native-span-feed-async.test.ts +173 -0
  312. package/src/tests/native-span-feed-close.test.ts +120 -0
  313. package/src/tests/native-span-feed-coverage.test.ts +227 -0
  314. package/src/tests/native-span-feed-edge-cases.test.ts +352 -0
  315. package/src/tests/native-span-feed-use-after-free.test.ts +45 -0
  316. package/src/tests/opacity.test.ts +123 -0
  317. package/src/tests/renderable.snapshot.test.ts +524 -0
  318. package/src/tests/renderable.test.ts +1281 -0
  319. package/src/tests/renderer.console-startup.test.ts +65 -0
  320. package/src/tests/renderer.control.test.ts +364 -0
  321. package/src/tests/renderer.core-slot-binding.test.ts +952 -0
  322. package/src/tests/renderer.cursor.test.ts +26 -0
  323. package/src/tests/renderer.destroy-during-render.test.ts +110 -0
  324. package/src/tests/renderer.focus-restore.test.ts +228 -0
  325. package/src/tests/renderer.focus.test.ts +251 -0
  326. package/src/tests/renderer.idle.test.ts +219 -0
  327. package/src/tests/renderer.input.test.ts +2145 -0
  328. package/src/tests/renderer.kitty-flags.test.ts +195 -0
  329. package/src/tests/renderer.mouse.test.ts +1269 -0
  330. package/src/tests/renderer.palette.test.ts +629 -0
  331. package/src/tests/renderer.selection.test.ts +49 -0
  332. package/src/tests/renderer.slot-registry.test.ts +649 -0
  333. package/src/tests/renderer.useMouse.test.ts +50 -0
  334. package/src/tests/runtime-plugin-support.fixture.ts +11 -0
  335. package/src/tests/runtime-plugin-support.test.ts +28 -0
  336. package/src/tests/runtime-plugin.fixture.ts +40 -0
  337. package/src/tests/runtime-plugin.test.ts +190 -0
  338. package/src/tests/scrollbox-culling-bug.test.ts +114 -0
  339. package/src/tests/scrollbox-hitgrid-resize.test.ts +136 -0
  340. package/src/tests/scrollbox-hitgrid.test.ts +909 -0
  341. package/src/tests/scrollbox.test.ts +1530 -0
  342. package/src/tests/wrap-resize-perf.test.ts +229 -0
  343. package/src/tests/yoga-setters.test.ts +921 -0
  344. package/src/text-buffer-view.test.ts +705 -0
  345. package/src/text-buffer-view.ts +189 -0
  346. package/src/text-buffer.test.ts +347 -0
  347. package/src/text-buffer.ts +250 -0
  348. package/src/types.ts +152 -0
  349. package/src/utils.ts +88 -0
  350. package/src/zig/ansi.zig +268 -0
  351. package/src/zig/bench/README.md +50 -0
  352. package/src/zig/bench/buffer-draw-text-buffer_bench.zig +887 -0
  353. package/src/zig/bench/edit-buffer_bench.zig +476 -0
  354. package/src/zig/bench/native-span-feed_bench.zig +100 -0
  355. package/src/zig/bench/rope-markers_bench.zig +713 -0
  356. package/src/zig/bench/rope_bench.zig +514 -0
  357. package/src/zig/bench/styled-text_bench.zig +470 -0
  358. package/src/zig/bench/text-buffer-coords_bench.zig +362 -0
  359. package/src/zig/bench/text-buffer-view_bench.zig +459 -0
  360. package/src/zig/bench/text-chunk-graphemes_bench.zig +273 -0
  361. package/src/zig/bench/utf8_bench.zig +799 -0
  362. package/src/zig/bench-utils.zig +431 -0
  363. package/src/zig/bench.zig +217 -0
  364. package/src/zig/buffer.zig +2223 -0
  365. package/src/zig/build.zig +289 -0
  366. package/src/zig/build.zig.zon +16 -0
  367. package/src/zig/edit-buffer.zig +825 -0
  368. package/src/zig/editor-view.zig +802 -0
  369. package/src/zig/event-bus.zig +13 -0
  370. package/src/zig/event-emitter.zig +65 -0
  371. package/src/zig/file-logger.zig +92 -0
  372. package/src/zig/grapheme.zig +599 -0
  373. package/src/zig/lib.zig +1834 -0
  374. package/src/zig/link.zig +333 -0
  375. package/src/zig/logger.zig +43 -0
  376. package/src/zig/mem-registry.zig +125 -0
  377. package/src/zig/native-span-feed-bench-lib.zig +7 -0
  378. package/src/zig/native-span-feed.zig +708 -0
  379. package/src/zig/renderer.zig +1386 -0
  380. package/src/zig/rope.zig +1220 -0
  381. package/src/zig/syntax-style.zig +161 -0
  382. package/src/zig/terminal.zig +975 -0
  383. package/src/zig/test.zig +70 -0
  384. package/src/zig/tests/README.md +18 -0
  385. package/src/zig/tests/buffer_test.zig +2526 -0
  386. package/src/zig/tests/edit-buffer-history_test.zig +271 -0
  387. package/src/zig/tests/edit-buffer_test.zig +1689 -0
  388. package/src/zig/tests/editor-view_test.zig +3299 -0
  389. package/src/zig/tests/event-emitter_test.zig +249 -0
  390. package/src/zig/tests/grapheme_test.zig +1304 -0
  391. package/src/zig/tests/link_test.zig +190 -0
  392. package/src/zig/tests/mem-registry_test.zig +473 -0
  393. package/src/zig/tests/memory_leak_regression_test.zig +159 -0
  394. package/src/zig/tests/native-span-feed_test.zig +1264 -0
  395. package/src/zig/tests/renderer_test.zig +1010 -0
  396. package/src/zig/tests/rope-nested_test.zig +712 -0
  397. package/src/zig/tests/rope_fuzz_test.zig +238 -0
  398. package/src/zig/tests/rope_test.zig +2362 -0
  399. package/src/zig/tests/segment-merge.test.zig +148 -0
  400. package/src/zig/tests/syntax-style_test.zig +557 -0
  401. package/src/zig/tests/terminal_test.zig +719 -0
  402. package/src/zig/tests/text-buffer-drawing_test.zig +3237 -0
  403. package/src/zig/tests/text-buffer-highlights_test.zig +666 -0
  404. package/src/zig/tests/text-buffer-iterators_test.zig +776 -0
  405. package/src/zig/tests/text-buffer-segment_test.zig +320 -0
  406. package/src/zig/tests/text-buffer-selection_test.zig +1035 -0
  407. package/src/zig/tests/text-buffer-selection_viewport_test.zig +358 -0
  408. package/src/zig/tests/text-buffer-view_test.zig +3649 -0
  409. package/src/zig/tests/text-buffer_test.zig +2191 -0
  410. package/src/zig/tests/unicode-width-map.zon +3909 -0
  411. package/src/zig/tests/utf8_no_zwj_test.zig +260 -0
  412. package/src/zig/tests/utf8_test.zig +4057 -0
  413. package/src/zig/tests/utf8_wcwidth_cursor_test.zig +267 -0
  414. package/src/zig/tests/utf8_wcwidth_test.zig +357 -0
  415. package/src/zig/tests/word-wrap-editing_test.zig +498 -0
  416. package/src/zig/tests/wrap-cache-perf_test.zig +113 -0
  417. package/src/zig/text-buffer-iterators.zig +499 -0
  418. package/src/zig/text-buffer-segment.zig +404 -0
  419. package/src/zig/text-buffer-view.zig +1371 -0
  420. package/src/zig/text-buffer.zig +1180 -0
  421. package/src/zig/utf8.zig +1948 -0
  422. package/src/zig/utils.zig +9 -0
  423. package/src/zig-structs.ts +261 -0
  424. package/src/zig.ts +3843 -0
  425. package/tsconfig.build.json +22 -0
  426. package/tsconfig.json +28 -0
  427. package/3d/SpriteResourceManager.d.ts +0 -74
  428. package/3d/SpriteUtils.d.ts +0 -13
  429. package/3d/TextureUtils.d.ts +0 -24
  430. package/3d/ThreeRenderable.d.ts +0 -40
  431. package/3d/WGPURenderer.d.ts +0 -61
  432. package/3d/animation/ExplodingSpriteEffect.d.ts +0 -71
  433. package/3d/animation/PhysicsExplodingSpriteEffect.d.ts +0 -76
  434. package/3d/animation/SpriteAnimator.d.ts +0 -124
  435. package/3d/animation/SpriteParticleGenerator.d.ts +0 -62
  436. package/3d/canvas.d.ts +0 -44
  437. package/3d/index.d.ts +0 -12
  438. package/3d/physics/PlanckPhysicsAdapter.d.ts +0 -19
  439. package/3d/physics/RapierPhysicsAdapter.d.ts +0 -19
  440. package/3d/physics/physics-interface.d.ts +0 -27
  441. package/3d.d.ts +0 -2
  442. package/3d.js +0 -34042
  443. package/3d.js.map +0 -155
  444. package/LICENSE +0 -21
  445. package/NativeSpanFeed.d.ts +0 -41
  446. package/Renderable.d.ts +0 -334
  447. package/animation/Timeline.d.ts +0 -126
  448. package/ansi.d.ts +0 -13
  449. package/buffer.d.ts +0 -107
  450. package/console.d.ts +0 -143
  451. package/edit-buffer.d.ts +0 -98
  452. package/editor-view.d.ts +0 -73
  453. package/index-e4hzc2j2.js +0 -113
  454. package/index-e4hzc2j2.js.map +0 -10
  455. package/index-nkrr8a4c.js +0 -18415
  456. package/index-nkrr8a4c.js.map +0 -64
  457. package/index-nyw5p3ep.js +0 -12619
  458. package/index-nyw5p3ep.js.map +0 -43
  459. package/index.d.ts +0 -21
  460. package/index.js +0 -430
  461. package/index.js.map +0 -9
  462. package/lib/KeyHandler.d.ts +0 -61
  463. package/lib/RGBA.d.ts +0 -25
  464. package/lib/ascii.font.d.ts +0 -508
  465. package/lib/border.d.ts +0 -49
  466. package/lib/bunfs.d.ts +0 -7
  467. package/lib/clipboard.d.ts +0 -17
  468. package/lib/clock.d.ts +0 -15
  469. package/lib/data-paths.d.ts +0 -26
  470. package/lib/debounce.d.ts +0 -42
  471. package/lib/detect-links.d.ts +0 -6
  472. package/lib/env.d.ts +0 -42
  473. package/lib/extmarks-history.d.ts +0 -17
  474. package/lib/extmarks.d.ts +0 -89
  475. package/lib/hast-styled-text.d.ts +0 -17
  476. package/lib/index.d.ts +0 -21
  477. package/lib/keymapping.d.ts +0 -25
  478. package/lib/objects-in-viewport.d.ts +0 -24
  479. package/lib/output.capture.d.ts +0 -24
  480. package/lib/parse.keypress-kitty.d.ts +0 -2
  481. package/lib/parse.keypress.d.ts +0 -26
  482. package/lib/parse.mouse.d.ts +0 -30
  483. package/lib/paste.d.ts +0 -7
  484. package/lib/queue.d.ts +0 -15
  485. package/lib/renderable.validations.d.ts +0 -12
  486. package/lib/scroll-acceleration.d.ts +0 -43
  487. package/lib/selection.d.ts +0 -63
  488. package/lib/singleton.d.ts +0 -7
  489. package/lib/stdin-parser.d.ts +0 -76
  490. package/lib/styled-text.d.ts +0 -63
  491. package/lib/terminal-capability-detection.d.ts +0 -30
  492. package/lib/terminal-palette.d.ts +0 -50
  493. package/lib/tree-sitter/assets/update.d.ts +0 -11
  494. package/lib/tree-sitter/client.d.ts +0 -47
  495. package/lib/tree-sitter/default-parsers.d.ts +0 -2
  496. package/lib/tree-sitter/download-utils.d.ts +0 -21
  497. package/lib/tree-sitter/index.d.ts +0 -8
  498. package/lib/tree-sitter/parser.worker.d.ts +0 -1
  499. package/lib/tree-sitter/parsers-config.d.ts +0 -38
  500. package/lib/tree-sitter/resolve-ft.d.ts +0 -2
  501. package/lib/tree-sitter/types.d.ts +0 -81
  502. package/lib/tree-sitter-styled-text.d.ts +0 -14
  503. package/lib/validate-dir-name.d.ts +0 -1
  504. package/lib/yoga.options.d.ts +0 -32
  505. package/parser.worker.js +0 -869
  506. package/parser.worker.js.map +0 -12
  507. package/plugins/core-slot.d.ts +0 -72
  508. package/plugins/registry.d.ts +0 -38
  509. package/plugins/types.d.ts +0 -34
  510. package/post/filters.d.ts +0 -105
  511. package/renderables/ASCIIFont.d.ts +0 -52
  512. package/renderables/Box.d.ts +0 -72
  513. package/renderables/Code.d.ts +0 -78
  514. package/renderables/Diff.d.ts +0 -142
  515. package/renderables/EditBufferRenderable.d.ts +0 -162
  516. package/renderables/FrameBuffer.d.ts +0 -16
  517. package/renderables/Input.d.ts +0 -67
  518. package/renderables/LineNumberRenderable.d.ts +0 -74
  519. package/renderables/Markdown.d.ts +0 -173
  520. package/renderables/ScrollBar.d.ts +0 -77
  521. package/renderables/ScrollBox.d.ts +0 -124
  522. package/renderables/Select.d.ts +0 -115
  523. package/renderables/Slider.d.ts +0 -44
  524. package/renderables/TabSelect.d.ts +0 -96
  525. package/renderables/Text.d.ts +0 -36
  526. package/renderables/TextBufferRenderable.d.ts +0 -105
  527. package/renderables/TextNode.d.ts +0 -91
  528. package/renderables/TextTable.d.ts +0 -140
  529. package/renderables/Textarea.d.ts +0 -114
  530. package/renderables/TimeToFirstDraw.d.ts +0 -24
  531. package/renderables/__tests__/renderable-test-utils.d.ts +0 -12
  532. package/renderables/composition/VRenderable.d.ts +0 -16
  533. package/renderables/composition/constructs.d.ts +0 -35
  534. package/renderables/composition/vnode.d.ts +0 -46
  535. package/renderables/index.d.ts +0 -22
  536. package/renderables/markdown-parser.d.ts +0 -10
  537. package/renderer.d.ts +0 -388
  538. package/runtime-plugin-support.d.ts +0 -3
  539. package/runtime-plugin-support.js +0 -29
  540. package/runtime-plugin-support.js.map +0 -10
  541. package/runtime-plugin.d.ts +0 -11
  542. package/runtime-plugin.js +0 -16
  543. package/runtime-plugin.js.map +0 -9
  544. package/syntax-style.d.ts +0 -54
  545. package/testing/manual-clock.d.ts +0 -16
  546. package/testing/mock-keys.d.ts +0 -81
  547. package/testing/mock-mouse.d.ts +0 -38
  548. package/testing/mock-tree-sitter-client.d.ts +0 -23
  549. package/testing/spy.d.ts +0 -7
  550. package/testing/test-recorder.d.ts +0 -61
  551. package/testing/test-renderer.d.ts +0 -23
  552. package/testing.d.ts +0 -6
  553. package/testing.js +0 -675
  554. package/testing.js.map +0 -15
  555. package/text-buffer-view.d.ts +0 -42
  556. package/text-buffer.d.ts +0 -67
  557. package/types.d.ts +0 -131
  558. package/utils.d.ts +0 -14
  559. package/zig-structs.d.ts +0 -155
  560. package/zig.d.ts +0 -351
  561. /package/{assets → src/lib/tree-sitter/assets}/javascript/highlights.scm +0 -0
  562. /package/{assets → src/lib/tree-sitter/assets}/javascript/tree-sitter-javascript.wasm +0 -0
  563. /package/{assets → src/lib/tree-sitter/assets}/markdown/highlights.scm +0 -0
  564. /package/{assets → src/lib/tree-sitter/assets}/markdown/injections.scm +0 -0
  565. /package/{assets → src/lib/tree-sitter/assets}/markdown/tree-sitter-markdown.wasm +0 -0
  566. /package/{assets → src/lib/tree-sitter/assets}/markdown_inline/highlights.scm +0 -0
  567. /package/{assets → src/lib/tree-sitter/assets}/markdown_inline/tree-sitter-markdown_inline.wasm +0 -0
  568. /package/{assets → src/lib/tree-sitter/assets}/typescript/highlights.scm +0 -0
  569. /package/{assets → src/lib/tree-sitter/assets}/typescript/tree-sitter-typescript.wasm +0 -0
  570. /package/{assets → src/lib/tree-sitter/assets}/zig/highlights.scm +0 -0
  571. /package/{assets → src/lib/tree-sitter/assets}/zig/tree-sitter-zig.wasm +0 -0
@@ -0,0 +1,353 @@
1
+ # Getting Started with OpenTUI
2
+
3
+ OpenTUI is a native terminal UI core written in Zig with TypeScript bindings. The native core exposes a C ABI and can be used from any language. OpenTUI powers OpenCode in production today and will also power terminal.shop. It is an extensible core with a focus on correctness, stability, and high performance. It provides a component-based architecture with flexible layout capabilities, allowing you to create complex terminal applications.
4
+
5
+ ## Core Concepts
6
+
7
+ ### Renderer
8
+
9
+ The `CliRenderer` is the heart of OpenTUI. It manages the terminal output, handles input events, and orchestrates the rendering loop. Think of it as the canvas that draws your interface to the terminal. It can run in a "live" mode, when calling `renderer.start()`, which runs a loop capped at the specified target FPS. It also just works without calling `renderer.start()`, which will only re-render when the renderable tree or layout changes.
10
+
11
+ By default, left-clicking auto-focuses the closest focusable renderable. Disable this with `createCliRenderer({ autoFocus: false })` if you need manual focus control.
12
+
13
+ ### Theme Mode
14
+
15
+ OpenTUI can detect the terminal's preferred color scheme (dark or light) when the terminal supports DEC mode 2031 color scheme updates. Read the current mode via `renderer.themeMode` and subscribe to `theme_mode` to react to changes. Possible values are `"dark"`, `"light"`, or `null` when unsupported, and no events fire in the unsupported case.
16
+
17
+ ```typescript
18
+ import { type ThemeMode } from "@fairyhunter13/opentui-core"
19
+
20
+ const mode = renderer.themeMode
21
+
22
+ renderer.on("theme_mode", (nextMode: ThemeMode) => {
23
+ console.log("Theme mode changed:", nextMode)
24
+ })
25
+ ```
26
+
27
+ ### FrameBuffer (OptimizedBuffer)
28
+
29
+ The `FrameBuffer` is a low-level rendering surface for custom graphics and complex visual effects. It is a 2D array of cells that can be drawn to using the `setCell`, `setCellWithAlphaBlending`, `drawText`, `fillRect`, and `drawFrameBuffer` methods. It is optimized for performance and memory usage. It allows for transparent cells and alpha blending, down to the viewport framebuffer.
30
+
31
+ ### Renderables
32
+
33
+ Renderables are the building blocks of your UI - hierarchical objects that can be positioned, styled, and nested within each other. Each Renderable represents a visual element (like text, boxes, or input fields) and uses the Yoga layout engine for flexible positioning and sizing.
34
+
35
+ ### Constructs (Components)
36
+
37
+ Constructs look just like React or Solid components, but are not render functions. You can think of them as constructors, a way to create new renderables by composing existing ones. They provide a more declarative way to build your UI. See a comparison on [this page](./renderables-vs-constructs.md).
38
+
39
+ ### Console
40
+
41
+ OpenTUI includes a built-in console overlay that captures all `console.log`, `console.info`, `console.warn`, `console.error`, and `console.debug` calls. The console appears as a visual overlay that can be positioned at any edge of the terminal, with scrolling and focus management. It's particularly useful for debugging TUI applications without disrupting the main interface.
42
+
43
+ ## Basic Setup
44
+
45
+ ```typescript
46
+ import { createCliRenderer, TextRenderable, Text } from "@fairyhunter13/opentui-core"
47
+
48
+ const renderer = await createCliRenderer()
49
+
50
+ // Raw Renderable
51
+ const greeting = new TextRenderable(renderer, {
52
+ id: "greeting",
53
+ content: "Hello, OpenTUI!",
54
+ fg: "#00FF00",
55
+ position: "absolute",
56
+ left: 10,
57
+ top: 5,
58
+ })
59
+
60
+ renderer.root.add(greeting)
61
+
62
+ // Construct/Component (VNode)
63
+ const greeting2 = Text({
64
+ content: "Hello, OpenTUI!",
65
+ fg: "#00FF00",
66
+ position: "absolute",
67
+ left: 10,
68
+ top: 5,
69
+ })
70
+
71
+ renderer.root.add(greeting)
72
+ ```
73
+
74
+ ## Console
75
+
76
+ When focused, you can use your arrow keys to scroll through the console. `renderer.console.toggle()` will toggle the console overlay, when open but not focused, it will focus the console. `+` and `-` will increase and decrease the size of the console.
77
+
78
+ ```typescript
79
+ import { createCliRenderer, ConsolePosition } from "@fairyhunter13/opentui-core"
80
+
81
+ const renderer = await createCliRenderer({
82
+ consoleOptions: {
83
+ position: ConsolePosition.BOTTOM,
84
+ sizePercent: 30,
85
+ colorInfo: "#00FFFF",
86
+ colorWarn: "#FFFF00",
87
+ colorError: "#FF0000",
88
+ startInDebugMode: false,
89
+ },
90
+ })
91
+
92
+ console.log("This appears in the overlay")
93
+ console.error("Errors are color-coded red")
94
+ console.warn("Warnings appear in yellow")
95
+
96
+ renderer.console.toggle()
97
+ ```
98
+
99
+ ## Colors: RGBA
100
+
101
+ OpenTUI uses the `RGBA` class for consistent color representation throughout the library. Colors are internally stored as normalized float values (0.0-1.0) for efficient processing, but the class provides convenient methods for working with different color formats.
102
+
103
+ ```typescript
104
+ import { RGBA } from "@fairyhunter13/opentui-core"
105
+
106
+ const redFromInts = RGBA.fromInts(255, 0, 0, 255) // RGB integers (0-255)
107
+ const blueFromValues = RGBA.fromValues(0.0, 0.0, 1.0, 1.0) // Float values (0.0-1.0)
108
+ const greenFromHex = RGBA.fromHex("#00FF00") // Hex strings
109
+ const transparent = RGBA.fromValues(1.0, 1.0, 1.0, 0.5) // Semi-transparent white
110
+ ```
111
+
112
+ The `parseColor()` utility function accepts both RGBA objects and color strings (hex, CSS color names, "transparent") for flexible color input throughout the API.
113
+
114
+ ## Keyboard
115
+
116
+ OpenTUI provides a keyboard handler that parses terminal input and provides structured key events. Get the handler via `renderer.keyInput`, an EventEmitter that emits `keypress` and `paste` events with detailed key information.
117
+
118
+ ```typescript
119
+ import { type KeyEvent } from "@fairyhunter13/opentui-core"
120
+
121
+ const keyHandler = renderer.keyInput
122
+
123
+ keyHandler.on("keypress", (key: KeyEvent) => {
124
+ console.log("Key name:", key.name)
125
+ console.log("Sequence:", key.sequence)
126
+ console.log("Ctrl pressed:", key.ctrl)
127
+ console.log("Shift pressed:", key.shift)
128
+ console.log("Alt pressed:", key.meta)
129
+ console.log("Option pressed:", key.option)
130
+
131
+ if (key.name === "escape") {
132
+ console.log("Escape pressed!")
133
+ } else if (key.ctrl && key.name === "c") {
134
+ console.log("Ctrl+C pressed!")
135
+ } else if (key.shift && key.name === "f1") {
136
+ console.log("Shift+F1 pressed!")
137
+ }
138
+ })
139
+ ```
140
+
141
+ ## Available Renderables
142
+
143
+ OpenTUI provides several primitive components that you can use to build your interfaces:
144
+
145
+ ### Text
146
+
147
+ Display styled text content with support for colors, attributes, and text selection.
148
+
149
+ ```typescript
150
+ import { TextRenderable, TextAttributes, t, bold, underline, fg } from "@fairyhunter13/opentui-core"
151
+
152
+ const plainText = new TextRenderable(renderer, {
153
+ id: "plain-text",
154
+ content: "Important Message",
155
+ fg: "#FFFF00",
156
+ attributes: TextAttributes.BOLD | TextAttributes.UNDERLINE, // bitwise OR to combine attributes
157
+ position: "absolute",
158
+ left: 5,
159
+ top: 2,
160
+ })
161
+
162
+ // You can also use the `t` template literal to create more complex styled text:
163
+ const styledTextRenderable = new TextRenderable(renderer, {
164
+ id: "styled-text",
165
+ content: t`${bold("Important Message")} ${fg("#FF0000")(underline("Important Message"))}`,
166
+ position: "absolute",
167
+ left: 5,
168
+ top: 3,
169
+ })
170
+ ```
171
+
172
+ ### Box
173
+
174
+ A container component with borders, background colors, and layout capabilities. Perfect for creating panels, frames, and organized sections.
175
+
176
+ ```typescript
177
+ import { BoxRenderable } from "@fairyhunter13/opentui-core"
178
+
179
+ const panel = new BoxRenderable(renderer, {
180
+ id: "panel",
181
+ width: 30,
182
+ height: 10,
183
+ backgroundColor: "#333366",
184
+ borderStyle: "double",
185
+ borderColor: "#FFFFFF",
186
+ title: "Settings Panel",
187
+ titleAlignment: "center",
188
+ position: "absolute",
189
+ left: 10,
190
+ top: 5,
191
+ })
192
+ ```
193
+
194
+ ### Input
195
+
196
+ Text input field with cursor support, placeholder text, and focus states for user interaction.
197
+ Has to be focused to receive input.
198
+
199
+ ```typescript
200
+ import { InputRenderable, InputRenderableEvents } from "@fairyhunter13/opentui-core"
201
+
202
+ const nameInput = new InputRenderable(renderer, {
203
+ id: "name-input",
204
+ width: 25,
205
+ placeholder: "Enter your name...",
206
+ focusedBackgroundColor: "#1a1a1a",
207
+ position: "absolute",
208
+ left: 10,
209
+ top: 8,
210
+ })
211
+
212
+ // The change event is currently emitted when pressing return or enter. (this will be fixed in the future)
213
+ nameInput.on(InputRenderableEvents.CHANGE, (value) => {
214
+ console.log("Input changed:", value)
215
+ })
216
+ nameInput.focus()
217
+ ```
218
+
219
+ ### Select
220
+
221
+ A list selection component for choosing from multiple options.
222
+ Has to be focused to receive input. Default keybindings are `up/k` and `down/j` to navigate the list, `enter` to select.
223
+
224
+ ```typescript
225
+ import { SelectRenderable, SelectRenderableEvents } from "@fairyhunter13/opentui-core"
226
+
227
+ const menu = new SelectRenderable(renderer, {
228
+ id: "menu",
229
+ width: 30,
230
+ height: 8,
231
+ options: [
232
+ { name: "New File", description: "Create a new file" },
233
+ { name: "Open File", description: "Open an existing file" },
234
+ { name: "Save", description: "Save current file" },
235
+ { name: "Exit", description: "Exit the application" },
236
+ ],
237
+ position: "absolute",
238
+ left: 5,
239
+ top: 3,
240
+ })
241
+
242
+ menu.on(SelectRenderableEvents.ITEM_SELECTED, (index, option) => {
243
+ console.log("Selected:", option.name)
244
+ })
245
+ menu.focus()
246
+ ```
247
+
248
+ ### TabSelect
249
+
250
+ Horizontal tab-based selection component with descriptions and scroll support.
251
+ Has to be focused to receive input. Default keybindings are `left/[` and `right/]` to navigate the tabs, `enter` to select.
252
+
253
+ ```typescript
254
+ import { TabSelectRenderable, TabSelectRenderableEvents } from "@fairyhunter13/opentui-core"
255
+
256
+ const tabs = new TabSelectRenderable(renderer, {
257
+ id: "tabs",
258
+ width: 60,
259
+ options: [
260
+ { name: "Home", description: "Dashboard and overview" },
261
+ { name: "Files", description: "File management" },
262
+ { name: "Settings", description: "Application settings" },
263
+ ],
264
+ tabWidth: 20,
265
+ position: "absolute",
266
+ left: 2,
267
+ top: 1,
268
+ })
269
+
270
+ tabs.on(TabSelectRenderableEvents.ITEM_SELECTED, (index, option) => {
271
+ console.log("Selected:", option.name)
272
+ })
273
+
274
+ tabs.focus()
275
+ ```
276
+
277
+ ### ASCIIFont
278
+
279
+ Display text using ASCII art fonts with multiple font styles available.
280
+
281
+ ```typescript
282
+ import { ASCIIFontRenderable, RGBA } from "@fairyhunter13/opentui-core"
283
+
284
+ const title = new ASCIIFontRenderable(renderer, {
285
+ id: "title",
286
+ text: "OPENTUI",
287
+ font: "tiny",
288
+ color: RGBA.fromInts(255, 255, 255, 255),
289
+ position: "absolute",
290
+ left: 10,
291
+ top: 2,
292
+ })
293
+ ```
294
+
295
+ ### FrameBuffer
296
+
297
+ A low-level rendering surface for custom graphics and complex visual effects.
298
+
299
+ ```typescript
300
+ import { FrameBufferRenderable, RGBA } from "@fairyhunter13/opentui-core"
301
+
302
+ const canvas = new FrameBufferRenderable(renderer, {
303
+ id: "canvas",
304
+ width: 50,
305
+ height: 20,
306
+ position: "absolute",
307
+ left: 5,
308
+ top: 5,
309
+ })
310
+
311
+ // Custom rendering in the frame buffer
312
+ canvas.frameBuffer.fillRect(10, 5, 20, 8, RGBA.fromHex("#FF0000"))
313
+ canvas.frameBuffer.drawText("Custom Graphics", 12, 7, RGBA.fromHex("#FFFFFF"))
314
+ ```
315
+
316
+ ## Layout System
317
+
318
+ OpenTUI uses the Yoga layout engine, providing CSS Flexbox-like capabilities for responsive layouts:
319
+
320
+ ```typescript
321
+ import { BoxRenderable } from "@fairyhunter13/opentui-core"
322
+
323
+ const container = new BoxRenderable(renderer, {
324
+ id: "container",
325
+ flexDirection: "row",
326
+ justifyContent: "space-between",
327
+ alignItems: "center",
328
+ width: "100%",
329
+ height: 10,
330
+ })
331
+
332
+ const leftPanel = new BoxRenderable(renderer, {
333
+ id: "left",
334
+ flexGrow: 1,
335
+ height: 10,
336
+ backgroundColor: "#444",
337
+ })
338
+
339
+ const rightPanel = new BoxRenderable(renderer, {
340
+ id: "right",
341
+ width: 20,
342
+ height: 10,
343
+ backgroundColor: "#666",
344
+ })
345
+
346
+ container.add(leftPanel)
347
+ container.add(rightPanel)
348
+ ```
349
+
350
+ ## Next Steps
351
+
352
+ - Explore the [examples](../src/examples) directory for more complex use cases
353
+ - Check out the React and Solid integrations for declarative UI development
@@ -0,0 +1,159 @@
1
+ # Renderables vs Constructs
2
+
3
+ Lets look at two ways of composing Renderables, imperative and declarative.
4
+ Assume we want to create a simple "login" form with a username and password input.
5
+
6
+ ## Imperative
7
+
8
+ Creates concrete `Renderable` instances with a `RenderContext` and composes via `add()`. State/behavior are mutated directly on instances (setters/methods), with mouse/key events bubbling upward through `processMouseEvent` for example.
9
+
10
+ ```typescript
11
+ import { BoxRenderable, TextRenderable, InputRenderable, createCliRenderer, type RenderContext } from "@fairyhunter13/opentui-core"
12
+
13
+ const renderer = await createCliRenderer()
14
+
15
+ const loginForm = new BoxRenderable(renderer, {
16
+ id: "login-form",
17
+ width: 20,
18
+ height: 10,
19
+ padding: 1,
20
+ })
21
+
22
+ // Compose renderables to a single renderable.
23
+ // Needs a RendererContext at creation time.
24
+ function createLabeledInput(renderer: RenderContext, props: { label: string; placeholder: string; id: string }) {
25
+ const labeledInput = new BoxRenderable(renderer, {
26
+ id: `${props.id}-labeled-input`,
27
+ flexDirection: "row",
28
+ backgroundColor: "gray",
29
+ })
30
+
31
+ labeledInput.add(
32
+ new TextRenderable(renderer, {
33
+ id: `${props.id}-label`,
34
+ content: props.label + " ",
35
+ }),
36
+ )
37
+ labeledInput.add(
38
+ new InputRenderable(renderer, {
39
+ id: `${props.id}-input`,
40
+ placeholder: props.placeholder,
41
+ backgroundColor: "white",
42
+ textColor: "black",
43
+ cursorColor: "blue",
44
+ focusedBackgroundColor: "orange",
45
+ width: 20,
46
+ }),
47
+ )
48
+
49
+ return labeledInput
50
+ }
51
+
52
+ const labeledUsername = createLabeledInput(renderer, {
53
+ id: "username",
54
+ label: "Username:",
55
+ placeholder: "Enter your username...",
56
+ })
57
+ loginForm.add(labeledUsername)
58
+
59
+ // Now it becomse difficult to focus. because it is in a container.
60
+ // This does not work:
61
+ labeledUsername.focus()
62
+
63
+ // Needs to be:
64
+ labeledUsername.getRenderable("username-input")?.focus()
65
+
66
+ const labeledPassword = createLabeledInput(renderer, {
67
+ id: "password",
68
+ label: "Password:",
69
+ placeholder: "Enter your password...",
70
+ })
71
+ loginForm.add(labeledPassword)
72
+
73
+ // Compose a button component
74
+ function createButton(props: { content: string; onClick: () => void; id: string }) {
75
+ const box = new BoxRenderable(renderer, {
76
+ id: `${props.id}-button`,
77
+ border: true,
78
+ backgroundColor: "gray",
79
+ onMouseDown: props.onClick,
80
+ })
81
+ const text = new TextRenderable(renderer, {
82
+ id: `${props.id}-button-text`,
83
+ content: props.content,
84
+ selectable: false,
85
+ })
86
+ box.add(text)
87
+ return box
88
+ }
89
+
90
+ const buttons = new BoxRenderable(renderer, {
91
+ id: "buttons",
92
+ flexDirection: "row",
93
+ padding: 1,
94
+ width: 20,
95
+ })
96
+ buttons.add(createButton({ id: "register", content: "Register", onClick: () => {} }))
97
+ buttons.add(createButton({ id: "login", content: "Login", onClick: () => {} }))
98
+ loginForm.add(buttons)
99
+
100
+ renderer.root.add(loginForm)
101
+ ```
102
+
103
+ ## Declarative
104
+
105
+ Builds an allegedly lightweight VNode graph using functional constructs that return VNodes; no instances exist until `instantiate(ctx, vnode)` is called. During instantiation, children are flattened, renderables are created and added, and any chained method/property calls made on VNodes are replayed on the created instance. `delegate(mapping, vnode)` can annotate the VNode so selected APIs (e.g., `focus`, `add`) are later routed to a specific descendant when the instance is created.
106
+
107
+ ```typescript
108
+ import { Text, Input, Box, createCliRenderer, delegate, instantiate } from "@fairyhunter13/opentui-core"
109
+
110
+ const renderer = await createCliRenderer()
111
+
112
+ function LabeledInput(props: { id: string; label: string; placeholder: string }) {
113
+ return delegate(
114
+ {
115
+ focus: `${props.id}-input`,
116
+ },
117
+ Box(
118
+ { flexDirection: "row" },
119
+ Text({ content: props.label + " " }),
120
+ Input({
121
+ id: `${props.id}-input`,
122
+ placeholder: props.placeholder,
123
+ width: 20,
124
+ backgroundColor: "white",
125
+ textColor: "black",
126
+ cursorColor: "blue",
127
+ focusedBackgroundColor: "orange",
128
+ }),
129
+ ),
130
+ )
131
+ }
132
+
133
+ function Button(props: { id: string; content: string; onClick: () => void }) {
134
+ return Box(
135
+ {
136
+ border: true,
137
+ backgroundColor: "gray",
138
+ onMouseDown: props.onClick,
139
+ },
140
+ Text({ content: props.content, selectable: false }),
141
+ )
142
+ }
143
+
144
+ const usernameInput = LabeledInput({ id: "username", label: "Username:", placeholder: "Enter your username..." })
145
+ usernameInput.focus()
146
+
147
+ const loginForm = Box(
148
+ { width: 20, height: 10, padding: 1 },
149
+ usernameInput,
150
+ LabeledInput({ id: "password", label: "Password:", placeholder: "Enter your password..." }),
151
+ Box(
152
+ { flexDirection: "row", padding: 1, width: 20 },
153
+ Button({ id: "login", content: "Login", onClick: () => {} }),
154
+ Button({ id: "register", content: "Register", onClick: () => {} }),
155
+ ),
156
+ )
157
+
158
+ renderer.root.add(loginForm)
159
+ ```