@fairyhunter13/opentui-core 0.1.88 → 0.1.90

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 (570) hide show
  1. package/dev/keypress-debug-renderer.ts +148 -0
  2. package/dev/keypress-debug.ts +43 -0
  3. package/dev/print-env-vars.ts +32 -0
  4. package/dev/test-tmux-graphics-334.sh +68 -0
  5. package/dev/thai-debug-test.ts +68 -0
  6. package/docs/development.md +141 -0
  7. package/docs/env-vars.md +140 -0
  8. package/docs/getting-started.md +353 -0
  9. package/docs/renderables-vs-constructs.md +159 -0
  10. package/docs/tree-sitter.md +311 -0
  11. package/package.json +61 -52
  12. package/scripts/build.ts +400 -0
  13. package/scripts/publish.ts +60 -0
  14. package/src/3d/SpriteResourceManager.ts +286 -0
  15. package/src/3d/SpriteUtils.ts +71 -0
  16. package/src/3d/TextureUtils.ts +196 -0
  17. package/src/3d/ThreeRenderable.ts +197 -0
  18. package/src/3d/WGPURenderer.ts +294 -0
  19. package/src/3d/animation/ExplodingSpriteEffect.ts +513 -0
  20. package/src/3d/animation/PhysicsExplodingSpriteEffect.ts +429 -0
  21. package/src/3d/animation/SpriteAnimator.ts +633 -0
  22. package/src/3d/animation/SpriteParticleGenerator.ts +435 -0
  23. package/src/3d/canvas.ts +464 -0
  24. package/src/3d/index.ts +12 -0
  25. package/src/3d/physics/PlanckPhysicsAdapter.ts +72 -0
  26. package/src/3d/physics/RapierPhysicsAdapter.ts +66 -0
  27. package/src/3d/physics/physics-interface.ts +31 -0
  28. package/src/3d/shaders/supersampling.wgsl +201 -0
  29. package/src/3d.ts +3 -0
  30. package/src/NativeSpanFeed.ts +300 -0
  31. package/src/Renderable.ts +1698 -0
  32. package/src/__snapshots__/buffer.test.ts.snap +28 -0
  33. package/src/animation/Timeline.test.ts +2709 -0
  34. package/src/animation/Timeline.ts +598 -0
  35. package/src/ansi.ts +18 -0
  36. package/src/benchmark/latest-all-bench-run.json +707 -0
  37. package/src/benchmark/latest-async-bench-run.json +336 -0
  38. package/src/benchmark/latest-default-bench-run.json +657 -0
  39. package/src/benchmark/latest-large-bench-run.json +707 -0
  40. package/src/benchmark/latest-quick-bench-run.json +207 -0
  41. package/src/benchmark/markdown-benchmark.ts +1804 -0
  42. package/src/benchmark/native-span-feed-async-benchmark.ts +355 -0
  43. package/src/benchmark/native-span-feed-benchmark.md +56 -0
  44. package/src/benchmark/native-span-feed-benchmark.ts +596 -0
  45. package/src/benchmark/native-span-feed-compare.ts +280 -0
  46. package/src/benchmark/renderer-benchmark.ts +754 -0
  47. package/src/benchmark/text-table-benchmark.ts +947 -0
  48. package/src/buffer.test.ts +291 -0
  49. package/src/buffer.ts +519 -0
  50. package/src/console.test.ts +612 -0
  51. package/src/console.ts +1255 -0
  52. package/src/edit-buffer.test.ts +1769 -0
  53. package/src/edit-buffer.ts +411 -0
  54. package/src/editor-view.test.ts +1032 -0
  55. package/src/editor-view.ts +284 -0
  56. package/src/examples/ascii-font-selection-demo.ts +245 -0
  57. package/src/examples/assets/Water_2_M_Normal.jpg +0 -0
  58. package/src/examples/assets/concrete.png +0 -0
  59. package/src/examples/assets/crate.png +0 -0
  60. package/src/examples/assets/crate_emissive.png +0 -0
  61. package/src/examples/assets/forrest_background.png +0 -0
  62. package/src/examples/assets/hast-example.json +1018 -0
  63. package/src/examples/assets/heart.png +0 -0
  64. package/src/examples/assets/main_char_heavy_attack.png +0 -0
  65. package/src/examples/assets/main_char_idle.png +0 -0
  66. package/src/examples/assets/main_char_jump_end.png +0 -0
  67. package/src/examples/assets/main_char_jump_landing.png +0 -0
  68. package/src/examples/assets/main_char_jump_start.png +0 -0
  69. package/src/examples/assets/main_char_run_loop.png +0 -0
  70. package/src/examples/assets/roughness_map.jpg +0 -0
  71. package/src/examples/build.ts +115 -0
  72. package/src/examples/code-demo.ts +584 -0
  73. package/src/examples/console-demo.ts +358 -0
  74. package/src/examples/core-plugin-slots-demo.ts +759 -0
  75. package/src/examples/diff-demo.ts +699 -0
  76. package/src/examples/draggable-three-demo.ts +259 -0
  77. package/src/examples/editor-demo.ts +322 -0
  78. package/src/examples/extmarks-demo.ts +204 -0
  79. package/src/examples/focus-restore-demo.ts +310 -0
  80. package/src/examples/fonts.ts +245 -0
  81. package/src/examples/fractal-shader-demo.ts +268 -0
  82. package/src/examples/framebuffer-demo.ts +674 -0
  83. package/src/examples/full-unicode-demo.ts +181 -0
  84. package/src/examples/golden-star-demo.ts +933 -0
  85. package/src/examples/grayscale-buffer-demo.ts +249 -0
  86. package/src/examples/hast-syntax-highlighting-demo.ts +129 -0
  87. package/src/examples/index.ts +925 -0
  88. package/src/examples/input-demo.ts +377 -0
  89. package/src/examples/input-select-layout-demo.ts +425 -0
  90. package/src/examples/install.sh +143 -0
  91. package/src/examples/keypress-debug-demo.ts +452 -0
  92. package/src/examples/lib/HexList.ts +122 -0
  93. package/src/examples/lib/PaletteGrid.ts +125 -0
  94. package/src/examples/lib/standalone-keys.ts +25 -0
  95. package/src/examples/lib/tab-controller.ts +243 -0
  96. package/src/examples/lights-phong-demo.ts +290 -0
  97. package/src/examples/link-demo.ts +220 -0
  98. package/src/examples/live-state-demo.ts +480 -0
  99. package/src/examples/markdown-demo.ts +620 -0
  100. package/src/examples/mouse-interaction-demo.ts +428 -0
  101. package/src/examples/nested-zindex-demo.ts +357 -0
  102. package/src/examples/opacity-example.ts +235 -0
  103. package/src/examples/opentui-demo.ts +1057 -0
  104. package/src/examples/physx-planck-2d-demo.ts +507 -0
  105. package/src/examples/physx-rapier-2d-demo.ts +526 -0
  106. package/src/examples/relative-positioning-demo.ts +323 -0
  107. package/src/examples/scroll-example.ts +214 -0
  108. package/src/examples/scrollbox-mouse-test.ts +112 -0
  109. package/src/examples/scrollbox-overlay-hit-test.ts +206 -0
  110. package/src/examples/select-demo.ts +237 -0
  111. package/src/examples/shader-cube-demo.ts +772 -0
  112. package/src/examples/simple-layout-example.ts +591 -0
  113. package/src/examples/slider-demo.ts +617 -0
  114. package/src/examples/split-mode-demo.ts +445 -0
  115. package/src/examples/sprite-animation-demo.ts +443 -0
  116. package/src/examples/sprite-particle-generator-demo.ts +486 -0
  117. package/src/examples/static-sprite-demo.ts +193 -0
  118. package/src/examples/sticky-scroll-example.ts +308 -0
  119. package/src/examples/styled-text-demo.ts +282 -0
  120. package/src/examples/tab-select-demo.ts +219 -0
  121. package/src/examples/terminal-title.ts +29 -0
  122. package/src/examples/terminal.ts +305 -0
  123. package/src/examples/text-node-demo.ts +416 -0
  124. package/src/examples/text-selection-demo.ts +377 -0
  125. package/src/examples/text-table-demo.ts +503 -0
  126. package/src/examples/text-truncation-demo.ts +481 -0
  127. package/src/examples/text-wrap.ts +757 -0
  128. package/src/examples/texture-loading-demo.ts +259 -0
  129. package/src/examples/timeline-example.ts +670 -0
  130. package/src/examples/transparency-demo.ts +241 -0
  131. package/src/examples/vnode-composition-demo.ts +404 -0
  132. package/src/index.ts +22 -0
  133. package/src/lib/KeyHandler.integration.test.ts +292 -0
  134. package/src/lib/KeyHandler.stopPropagation.test.ts +289 -0
  135. package/src/lib/KeyHandler.test.ts +662 -0
  136. package/src/lib/KeyHandler.ts +222 -0
  137. package/src/lib/RGBA.test.ts +984 -0
  138. package/src/lib/RGBA.ts +204 -0
  139. package/src/lib/ascii.font.ts +330 -0
  140. package/src/lib/border.test.ts +83 -0
  141. package/src/lib/border.ts +168 -0
  142. package/src/lib/bunfs.test.ts +27 -0
  143. package/src/lib/bunfs.ts +18 -0
  144. package/src/lib/clipboard.test.ts +41 -0
  145. package/src/lib/clipboard.ts +47 -0
  146. package/src/lib/clock.ts +31 -0
  147. package/src/lib/data-paths.test.ts +133 -0
  148. package/src/lib/data-paths.ts +109 -0
  149. package/src/lib/debounce.ts +106 -0
  150. package/src/lib/detect-links.test.ts +98 -0
  151. package/src/lib/detect-links.ts +56 -0
  152. package/src/lib/env.test.ts +228 -0
  153. package/src/lib/env.ts +209 -0
  154. package/src/lib/extmarks-history.ts +51 -0
  155. package/src/lib/extmarks-multiwidth.test.ts +322 -0
  156. package/src/lib/extmarks.test.ts +3457 -0
  157. package/src/lib/extmarks.ts +843 -0
  158. package/src/lib/fonts/block.json +405 -0
  159. package/src/lib/fonts/grid.json +265 -0
  160. package/src/lib/fonts/huge.json +741 -0
  161. package/src/lib/fonts/pallet.json +314 -0
  162. package/src/lib/fonts/shade.json +591 -0
  163. package/src/lib/fonts/slick.json +321 -0
  164. package/src/lib/fonts/tiny.json +69 -0
  165. package/src/lib/hast-styled-text.ts +59 -0
  166. package/src/lib/index.ts +21 -0
  167. package/src/lib/keymapping.test.ts +280 -0
  168. package/src/lib/keymapping.ts +87 -0
  169. package/src/lib/objects-in-viewport.test.ts +787 -0
  170. package/src/lib/objects-in-viewport.ts +153 -0
  171. package/src/lib/output.capture.ts +58 -0
  172. package/src/lib/parse.keypress-kitty.protocol.test.ts +340 -0
  173. package/src/lib/parse.keypress-kitty.test.ts +663 -0
  174. package/src/lib/parse.keypress-kitty.ts +439 -0
  175. package/src/lib/parse.keypress.test.ts +1849 -0
  176. package/src/lib/parse.keypress.ts +397 -0
  177. package/src/lib/parse.mouse.test.ts +552 -0
  178. package/src/lib/parse.mouse.ts +232 -0
  179. package/src/lib/paste.ts +16 -0
  180. package/src/lib/queue.ts +65 -0
  181. package/src/lib/renderable.validations.test.ts +87 -0
  182. package/src/lib/renderable.validations.ts +83 -0
  183. package/src/lib/scroll-acceleration.ts +98 -0
  184. package/src/lib/selection.ts +240 -0
  185. package/src/lib/singleton.ts +28 -0
  186. package/src/lib/stdin-parser.test.ts +1676 -0
  187. package/src/lib/stdin-parser.ts +1248 -0
  188. package/src/lib/styled-text.ts +178 -0
  189. package/src/lib/terminal-capability-detection.test.ts +202 -0
  190. package/src/lib/terminal-capability-detection.ts +79 -0
  191. package/src/lib/terminal-palette.test.ts +878 -0
  192. package/src/lib/terminal-palette.ts +383 -0
  193. package/src/lib/tree-sitter/assets/README.md +118 -0
  194. package/src/lib/tree-sitter/assets/update.ts +331 -0
  195. package/src/lib/tree-sitter/assets.d.ts +9 -0
  196. package/src/lib/tree-sitter/cache.test.ts +270 -0
  197. package/src/lib/tree-sitter/client.test.ts +1061 -0
  198. package/src/lib/tree-sitter/client.ts +615 -0
  199. package/src/lib/tree-sitter/default-parsers.ts +80 -0
  200. package/src/lib/tree-sitter/download-utils.ts +148 -0
  201. package/src/lib/tree-sitter/index.ts +28 -0
  202. package/src/lib/tree-sitter/parser.worker.ts +1001 -0
  203. package/src/lib/tree-sitter/parsers-config.ts +75 -0
  204. package/src/lib/tree-sitter/resolve-ft.ts +62 -0
  205. package/src/lib/tree-sitter/types.ts +81 -0
  206. package/src/lib/tree-sitter-styled-text.test.ts +1253 -0
  207. package/src/lib/tree-sitter-styled-text.ts +306 -0
  208. package/src/lib/validate-dir-name.ts +55 -0
  209. package/src/lib/yoga.options.test.ts +628 -0
  210. package/src/lib/yoga.options.ts +346 -0
  211. package/src/plugins/core-slot.ts +579 -0
  212. package/src/plugins/registry.ts +377 -0
  213. package/src/plugins/types.ts +46 -0
  214. package/src/post/filters.ts +888 -0
  215. package/src/renderables/ASCIIFont.ts +219 -0
  216. package/src/renderables/Box.test.ts +160 -0
  217. package/src/renderables/Box.ts +295 -0
  218. package/src/renderables/Code.test.ts +2062 -0
  219. package/src/renderables/Code.ts +357 -0
  220. package/src/renderables/Diff.regression.test.ts +226 -0
  221. package/src/renderables/Diff.test.ts +3027 -0
  222. package/src/renderables/Diff.ts +1209 -0
  223. package/src/renderables/EditBufferRenderable.ts +764 -0
  224. package/src/renderables/FrameBuffer.ts +47 -0
  225. package/src/renderables/Input.test.ts +1228 -0
  226. package/src/renderables/Input.ts +245 -0
  227. package/src/renderables/LineNumberRenderable.ts +675 -0
  228. package/src/renderables/Markdown.ts +1106 -0
  229. package/src/renderables/ScrollBar.ts +422 -0
  230. package/src/renderables/ScrollBox.ts +883 -0
  231. package/src/renderables/Select.test.ts +1010 -0
  232. package/src/renderables/Select.ts +523 -0
  233. package/src/renderables/Slider.test.ts +456 -0
  234. package/src/renderables/Slider.ts +347 -0
  235. package/src/renderables/TabSelect.test.ts +197 -0
  236. package/src/renderables/TabSelect.ts +455 -0
  237. package/src/renderables/Text.selection-buffer.test.ts +123 -0
  238. package/src/renderables/Text.test.ts +2660 -0
  239. package/src/renderables/Text.ts +147 -0
  240. package/src/renderables/TextBufferRenderable.ts +518 -0
  241. package/src/renderables/TextNode.test.ts +1058 -0
  242. package/src/renderables/TextNode.ts +325 -0
  243. package/src/renderables/TextTable.test.ts +1421 -0
  244. package/src/renderables/TextTable.ts +1344 -0
  245. package/src/renderables/Textarea.ts +732 -0
  246. package/src/renderables/TimeToFirstDraw.ts +89 -0
  247. package/src/renderables/__snapshots__/Code.test.ts.snap +13 -0
  248. package/src/renderables/__snapshots__/Diff.test.ts.snap +785 -0
  249. package/src/renderables/__snapshots__/Text.test.ts.snap +421 -0
  250. package/src/renderables/__snapshots__/TextTable.test.ts.snap +215 -0
  251. package/src/renderables/__tests__/LineNumberRenderable.scrollbox-simple.test.ts +144 -0
  252. package/src/renderables/__tests__/LineNumberRenderable.scrollbox.test.ts +816 -0
  253. package/src/renderables/__tests__/LineNumberRenderable.test.ts +1787 -0
  254. package/src/renderables/__tests__/LineNumberRenderable.wrapping.test.ts +85 -0
  255. package/src/renderables/__tests__/Markdown.test.ts +2287 -0
  256. package/src/renderables/__tests__/MultiRenderable.selection.test.ts +87 -0
  257. package/src/renderables/__tests__/Textarea.buffer.test.ts +682 -0
  258. package/src/renderables/__tests__/Textarea.destroyed-events.test.ts +675 -0
  259. package/src/renderables/__tests__/Textarea.editing.test.ts +2041 -0
  260. package/src/renderables/__tests__/Textarea.error-handling.test.ts +35 -0
  261. package/src/renderables/__tests__/Textarea.events.test.ts +738 -0
  262. package/src/renderables/__tests__/Textarea.highlights.test.ts +590 -0
  263. package/src/renderables/__tests__/Textarea.keybinding.test.ts +3149 -0
  264. package/src/renderables/__tests__/Textarea.paste.test.ts +357 -0
  265. package/src/renderables/__tests__/Textarea.rendering.test.ts +1864 -0
  266. package/src/renderables/__tests__/Textarea.scroll.test.ts +733 -0
  267. package/src/renderables/__tests__/Textarea.selection.test.ts +1590 -0
  268. package/src/renderables/__tests__/Textarea.stress.test.ts +670 -0
  269. package/src/renderables/__tests__/Textarea.undo-redo.test.ts +383 -0
  270. package/src/renderables/__tests__/Textarea.visual-lines.test.ts +310 -0
  271. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.code.test.ts.snap +221 -0
  272. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox-simple.test.ts.snap +89 -0
  273. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox.test.ts.snap +457 -0
  274. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.test.ts.snap +158 -0
  275. package/src/renderables/__tests__/__snapshots__/Textarea.rendering.test.ts.snap +387 -0
  276. package/src/renderables/__tests__/markdown-parser.test.ts +217 -0
  277. package/src/renderables/__tests__/renderable-test-utils.ts +60 -0
  278. package/src/renderables/composition/README.md +8 -0
  279. package/src/renderables/composition/VRenderable.ts +32 -0
  280. package/src/renderables/composition/constructs.ts +127 -0
  281. package/src/renderables/composition/vnode.ts +289 -0
  282. package/src/renderables/index.ts +22 -0
  283. package/src/renderables/markdown-parser.ts +66 -0
  284. package/src/renderer.ts +2363 -0
  285. package/src/runtime-plugin-support.ts +39 -0
  286. package/src/runtime-plugin.ts +144 -0
  287. package/src/syntax-style.test.ts +841 -0
  288. package/src/syntax-style.ts +264 -0
  289. package/src/testing/README.md +210 -0
  290. package/src/testing/capture-spans.test.ts +194 -0
  291. package/src/testing/integration.test.ts +276 -0
  292. package/src/testing/manual-clock.ts +106 -0
  293. package/src/testing/mock-keys.test.ts +1356 -0
  294. package/src/testing/mock-keys.ts +449 -0
  295. package/src/testing/mock-mouse.test.ts +218 -0
  296. package/src/testing/mock-mouse.ts +247 -0
  297. package/src/testing/mock-tree-sitter-client.ts +73 -0
  298. package/src/testing/spy.ts +13 -0
  299. package/src/testing/test-recorder.test.ts +415 -0
  300. package/src/testing/test-recorder.ts +145 -0
  301. package/src/testing/test-renderer.ts +116 -0
  302. package/src/testing.ts +7 -0
  303. package/src/tests/__snapshots__/absolute-positioning.snapshot.test.ts.snap +481 -0
  304. package/src/tests/__snapshots__/renderable.snapshot.test.ts.snap +19 -0
  305. package/src/tests/__snapshots__/scrollbox.test.ts.snap +29 -0
  306. package/src/tests/absolute-positioning.snapshot.test.ts +638 -0
  307. package/src/tests/allocator-stats.test.ts +38 -0
  308. package/src/tests/destroy-during-render.test.ts +200 -0
  309. package/src/tests/hover-cursor.test.ts +98 -0
  310. package/src/tests/native-span-feed-async.test.ts +173 -0
  311. package/src/tests/native-span-feed-close.test.ts +120 -0
  312. package/src/tests/native-span-feed-coverage.test.ts +227 -0
  313. package/src/tests/native-span-feed-edge-cases.test.ts +352 -0
  314. package/src/tests/native-span-feed-use-after-free.test.ts +45 -0
  315. package/src/tests/opacity.test.ts +123 -0
  316. package/src/tests/renderable.snapshot.test.ts +524 -0
  317. package/src/tests/renderable.test.ts +1281 -0
  318. package/src/tests/renderer.console-startup.test.ts +65 -0
  319. package/src/tests/renderer.control.test.ts +364 -0
  320. package/src/tests/renderer.core-slot-binding.test.ts +952 -0
  321. package/src/tests/renderer.cursor.test.ts +26 -0
  322. package/src/tests/renderer.destroy-during-render.test.ts +110 -0
  323. package/src/tests/renderer.focus-restore.test.ts +228 -0
  324. package/src/tests/renderer.focus.test.ts +251 -0
  325. package/src/tests/renderer.idle.test.ts +219 -0
  326. package/src/tests/renderer.input.test.ts +2145 -0
  327. package/src/tests/renderer.kitty-flags.test.ts +195 -0
  328. package/src/tests/renderer.mouse.test.ts +1269 -0
  329. package/src/tests/renderer.palette.test.ts +629 -0
  330. package/src/tests/renderer.selection.test.ts +49 -0
  331. package/src/tests/renderer.slot-registry.test.ts +649 -0
  332. package/src/tests/renderer.useMouse.test.ts +50 -0
  333. package/src/tests/runtime-plugin-support.fixture.ts +11 -0
  334. package/src/tests/runtime-plugin-support.test.ts +28 -0
  335. package/src/tests/runtime-plugin.fixture.ts +40 -0
  336. package/src/tests/runtime-plugin.test.ts +190 -0
  337. package/src/tests/scrollbox-culling-bug.test.ts +114 -0
  338. package/src/tests/scrollbox-hitgrid-resize.test.ts +136 -0
  339. package/src/tests/scrollbox-hitgrid.test.ts +909 -0
  340. package/src/tests/scrollbox.test.ts +1530 -0
  341. package/src/tests/wrap-resize-perf.test.ts +229 -0
  342. package/src/tests/yoga-setters.test.ts +921 -0
  343. package/src/text-buffer-view.test.ts +705 -0
  344. package/src/text-buffer-view.ts +189 -0
  345. package/src/text-buffer.test.ts +347 -0
  346. package/src/text-buffer.ts +250 -0
  347. package/src/types.ts +152 -0
  348. package/src/utils.ts +88 -0
  349. package/src/zig/ansi.zig +268 -0
  350. package/src/zig/bench/README.md +50 -0
  351. package/src/zig/bench/buffer-draw-text-buffer_bench.zig +887 -0
  352. package/src/zig/bench/edit-buffer_bench.zig +476 -0
  353. package/src/zig/bench/native-span-feed_bench.zig +100 -0
  354. package/src/zig/bench/rope-markers_bench.zig +713 -0
  355. package/src/zig/bench/rope_bench.zig +514 -0
  356. package/src/zig/bench/styled-text_bench.zig +470 -0
  357. package/src/zig/bench/text-buffer-coords_bench.zig +362 -0
  358. package/src/zig/bench/text-buffer-view_bench.zig +459 -0
  359. package/src/zig/bench/text-chunk-graphemes_bench.zig +273 -0
  360. package/src/zig/bench/utf8_bench.zig +799 -0
  361. package/src/zig/bench-utils.zig +431 -0
  362. package/src/zig/bench.zig +217 -0
  363. package/src/zig/buffer.zig +2223 -0
  364. package/src/zig/build.zig +289 -0
  365. package/src/zig/build.zig.zon +16 -0
  366. package/src/zig/edit-buffer.zig +825 -0
  367. package/src/zig/editor-view.zig +802 -0
  368. package/src/zig/event-bus.zig +13 -0
  369. package/src/zig/event-emitter.zig +65 -0
  370. package/src/zig/file-logger.zig +92 -0
  371. package/src/zig/grapheme.zig +599 -0
  372. package/src/zig/lib.zig +1834 -0
  373. package/src/zig/link.zig +333 -0
  374. package/src/zig/logger.zig +43 -0
  375. package/src/zig/mem-registry.zig +125 -0
  376. package/src/zig/native-span-feed-bench-lib.zig +7 -0
  377. package/src/zig/native-span-feed.zig +708 -0
  378. package/src/zig/renderer.zig +1386 -0
  379. package/src/zig/rope.zig +1220 -0
  380. package/src/zig/syntax-style.zig +161 -0
  381. package/src/zig/terminal.zig +975 -0
  382. package/src/zig/test.zig +70 -0
  383. package/src/zig/tests/README.md +18 -0
  384. package/src/zig/tests/buffer_test.zig +2526 -0
  385. package/src/zig/tests/edit-buffer-history_test.zig +271 -0
  386. package/src/zig/tests/edit-buffer_test.zig +1689 -0
  387. package/src/zig/tests/editor-view_test.zig +3299 -0
  388. package/src/zig/tests/event-emitter_test.zig +249 -0
  389. package/src/zig/tests/grapheme_test.zig +1304 -0
  390. package/src/zig/tests/link_test.zig +190 -0
  391. package/src/zig/tests/mem-registry_test.zig +473 -0
  392. package/src/zig/tests/memory_leak_regression_test.zig +159 -0
  393. package/src/zig/tests/native-span-feed_test.zig +1264 -0
  394. package/src/zig/tests/renderer_test.zig +1010 -0
  395. package/src/zig/tests/rope-nested_test.zig +712 -0
  396. package/src/zig/tests/rope_fuzz_test.zig +238 -0
  397. package/src/zig/tests/rope_test.zig +2362 -0
  398. package/src/zig/tests/segment-merge.test.zig +148 -0
  399. package/src/zig/tests/syntax-style_test.zig +557 -0
  400. package/src/zig/tests/terminal_test.zig +719 -0
  401. package/src/zig/tests/text-buffer-drawing_test.zig +3237 -0
  402. package/src/zig/tests/text-buffer-highlights_test.zig +666 -0
  403. package/src/zig/tests/text-buffer-iterators_test.zig +776 -0
  404. package/src/zig/tests/text-buffer-segment_test.zig +320 -0
  405. package/src/zig/tests/text-buffer-selection_test.zig +1035 -0
  406. package/src/zig/tests/text-buffer-selection_viewport_test.zig +358 -0
  407. package/src/zig/tests/text-buffer-view_test.zig +3649 -0
  408. package/src/zig/tests/text-buffer_test.zig +2191 -0
  409. package/src/zig/tests/unicode-width-map.zon +3909 -0
  410. package/src/zig/tests/utf8_no_zwj_test.zig +260 -0
  411. package/src/zig/tests/utf8_test.zig +4057 -0
  412. package/src/zig/tests/utf8_wcwidth_cursor_test.zig +267 -0
  413. package/src/zig/tests/utf8_wcwidth_test.zig +357 -0
  414. package/src/zig/tests/word-wrap-editing_test.zig +498 -0
  415. package/src/zig/tests/wrap-cache-perf_test.zig +113 -0
  416. package/src/zig/text-buffer-iterators.zig +499 -0
  417. package/src/zig/text-buffer-segment.zig +404 -0
  418. package/src/zig/text-buffer-view.zig +1371 -0
  419. package/src/zig/text-buffer.zig +1180 -0
  420. package/src/zig/utf8.zig +1948 -0
  421. package/src/zig/utils.zig +9 -0
  422. package/src/zig-structs.ts +261 -0
  423. package/src/zig.ts +3843 -0
  424. package/tsconfig.build.json +22 -0
  425. package/tsconfig.json +28 -0
  426. package/3d/SpriteResourceManager.d.ts +0 -74
  427. package/3d/SpriteUtils.d.ts +0 -13
  428. package/3d/TextureUtils.d.ts +0 -24
  429. package/3d/ThreeRenderable.d.ts +0 -40
  430. package/3d/WGPURenderer.d.ts +0 -61
  431. package/3d/animation/ExplodingSpriteEffect.d.ts +0 -71
  432. package/3d/animation/PhysicsExplodingSpriteEffect.d.ts +0 -76
  433. package/3d/animation/SpriteAnimator.d.ts +0 -124
  434. package/3d/animation/SpriteParticleGenerator.d.ts +0 -62
  435. package/3d/canvas.d.ts +0 -44
  436. package/3d/index.d.ts +0 -12
  437. package/3d/physics/PlanckPhysicsAdapter.d.ts +0 -19
  438. package/3d/physics/RapierPhysicsAdapter.d.ts +0 -19
  439. package/3d/physics/physics-interface.d.ts +0 -27
  440. package/3d.d.ts +0 -2
  441. package/3d.js +0 -34042
  442. package/3d.js.map +0 -155
  443. package/LICENSE +0 -21
  444. package/NativeSpanFeed.d.ts +0 -41
  445. package/Renderable.d.ts +0 -334
  446. package/animation/Timeline.d.ts +0 -126
  447. package/ansi.d.ts +0 -13
  448. package/buffer.d.ts +0 -107
  449. package/console.d.ts +0 -143
  450. package/edit-buffer.d.ts +0 -98
  451. package/editor-view.d.ts +0 -73
  452. package/index-e4hzc2j2.js +0 -113
  453. package/index-e4hzc2j2.js.map +0 -10
  454. package/index-nkrr8a4c.js +0 -18415
  455. package/index-nkrr8a4c.js.map +0 -64
  456. package/index-nyw5p3ep.js +0 -12619
  457. package/index-nyw5p3ep.js.map +0 -43
  458. package/index.d.ts +0 -21
  459. package/index.js +0 -430
  460. package/index.js.map +0 -9
  461. package/lib/KeyHandler.d.ts +0 -61
  462. package/lib/RGBA.d.ts +0 -25
  463. package/lib/ascii.font.d.ts +0 -508
  464. package/lib/border.d.ts +0 -49
  465. package/lib/bunfs.d.ts +0 -7
  466. package/lib/clipboard.d.ts +0 -17
  467. package/lib/clock.d.ts +0 -15
  468. package/lib/data-paths.d.ts +0 -26
  469. package/lib/debounce.d.ts +0 -42
  470. package/lib/detect-links.d.ts +0 -6
  471. package/lib/env.d.ts +0 -42
  472. package/lib/extmarks-history.d.ts +0 -17
  473. package/lib/extmarks.d.ts +0 -89
  474. package/lib/hast-styled-text.d.ts +0 -17
  475. package/lib/index.d.ts +0 -21
  476. package/lib/keymapping.d.ts +0 -25
  477. package/lib/objects-in-viewport.d.ts +0 -24
  478. package/lib/output.capture.d.ts +0 -24
  479. package/lib/parse.keypress-kitty.d.ts +0 -2
  480. package/lib/parse.keypress.d.ts +0 -26
  481. package/lib/parse.mouse.d.ts +0 -30
  482. package/lib/paste.d.ts +0 -7
  483. package/lib/queue.d.ts +0 -15
  484. package/lib/renderable.validations.d.ts +0 -12
  485. package/lib/scroll-acceleration.d.ts +0 -43
  486. package/lib/selection.d.ts +0 -63
  487. package/lib/singleton.d.ts +0 -7
  488. package/lib/stdin-parser.d.ts +0 -76
  489. package/lib/styled-text.d.ts +0 -63
  490. package/lib/terminal-capability-detection.d.ts +0 -30
  491. package/lib/terminal-palette.d.ts +0 -50
  492. package/lib/tree-sitter/assets/update.d.ts +0 -11
  493. package/lib/tree-sitter/client.d.ts +0 -47
  494. package/lib/tree-sitter/default-parsers.d.ts +0 -2
  495. package/lib/tree-sitter/download-utils.d.ts +0 -21
  496. package/lib/tree-sitter/index.d.ts +0 -8
  497. package/lib/tree-sitter/parser.worker.d.ts +0 -1
  498. package/lib/tree-sitter/parsers-config.d.ts +0 -38
  499. package/lib/tree-sitter/resolve-ft.d.ts +0 -2
  500. package/lib/tree-sitter/types.d.ts +0 -81
  501. package/lib/tree-sitter-styled-text.d.ts +0 -14
  502. package/lib/validate-dir-name.d.ts +0 -1
  503. package/lib/yoga.options.d.ts +0 -32
  504. package/parser.worker.js +0 -869
  505. package/parser.worker.js.map +0 -12
  506. package/plugins/core-slot.d.ts +0 -72
  507. package/plugins/registry.d.ts +0 -38
  508. package/plugins/types.d.ts +0 -34
  509. package/post/filters.d.ts +0 -105
  510. package/renderables/ASCIIFont.d.ts +0 -52
  511. package/renderables/Box.d.ts +0 -72
  512. package/renderables/Code.d.ts +0 -78
  513. package/renderables/Diff.d.ts +0 -142
  514. package/renderables/EditBufferRenderable.d.ts +0 -162
  515. package/renderables/FrameBuffer.d.ts +0 -16
  516. package/renderables/Input.d.ts +0 -67
  517. package/renderables/LineNumberRenderable.d.ts +0 -74
  518. package/renderables/Markdown.d.ts +0 -173
  519. package/renderables/ScrollBar.d.ts +0 -77
  520. package/renderables/ScrollBox.d.ts +0 -124
  521. package/renderables/Select.d.ts +0 -115
  522. package/renderables/Slider.d.ts +0 -44
  523. package/renderables/TabSelect.d.ts +0 -96
  524. package/renderables/Text.d.ts +0 -36
  525. package/renderables/TextBufferRenderable.d.ts +0 -105
  526. package/renderables/TextNode.d.ts +0 -91
  527. package/renderables/TextTable.d.ts +0 -140
  528. package/renderables/Textarea.d.ts +0 -114
  529. package/renderables/TimeToFirstDraw.d.ts +0 -24
  530. package/renderables/__tests__/renderable-test-utils.d.ts +0 -12
  531. package/renderables/composition/VRenderable.d.ts +0 -16
  532. package/renderables/composition/constructs.d.ts +0 -35
  533. package/renderables/composition/vnode.d.ts +0 -46
  534. package/renderables/index.d.ts +0 -22
  535. package/renderables/markdown-parser.d.ts +0 -10
  536. package/renderer.d.ts +0 -388
  537. package/runtime-plugin-support.d.ts +0 -3
  538. package/runtime-plugin-support.js +0 -29
  539. package/runtime-plugin-support.js.map +0 -10
  540. package/runtime-plugin.d.ts +0 -11
  541. package/runtime-plugin.js +0 -16
  542. package/runtime-plugin.js.map +0 -9
  543. package/syntax-style.d.ts +0 -54
  544. package/testing/manual-clock.d.ts +0 -16
  545. package/testing/mock-keys.d.ts +0 -81
  546. package/testing/mock-mouse.d.ts +0 -38
  547. package/testing/mock-tree-sitter-client.d.ts +0 -23
  548. package/testing/spy.d.ts +0 -7
  549. package/testing/test-recorder.d.ts +0 -61
  550. package/testing/test-renderer.d.ts +0 -23
  551. package/testing.d.ts +0 -6
  552. package/testing.js +0 -675
  553. package/testing.js.map +0 -15
  554. package/text-buffer-view.d.ts +0 -42
  555. package/text-buffer.d.ts +0 -67
  556. package/types.d.ts +0 -131
  557. package/utils.d.ts +0 -14
  558. package/zig-structs.d.ts +0 -155
  559. package/zig.d.ts +0 -351
  560. /package/{assets → src/lib/tree-sitter/assets}/javascript/highlights.scm +0 -0
  561. /package/{assets → src/lib/tree-sitter/assets}/javascript/tree-sitter-javascript.wasm +0 -0
  562. /package/{assets → src/lib/tree-sitter/assets}/markdown/highlights.scm +0 -0
  563. /package/{assets → src/lib/tree-sitter/assets}/markdown/injections.scm +0 -0
  564. /package/{assets → src/lib/tree-sitter/assets}/markdown/tree-sitter-markdown.wasm +0 -0
  565. /package/{assets → src/lib/tree-sitter/assets}/markdown_inline/highlights.scm +0 -0
  566. /package/{assets → src/lib/tree-sitter/assets}/markdown_inline/tree-sitter-markdown_inline.wasm +0 -0
  567. /package/{assets → src/lib/tree-sitter/assets}/typescript/highlights.scm +0 -0
  568. /package/{assets → src/lib/tree-sitter/assets}/typescript/tree-sitter-typescript.wasm +0 -0
  569. /package/{assets → src/lib/tree-sitter/assets}/zig/highlights.scm +0 -0
  570. /package/{assets → src/lib/tree-sitter/assets}/zig/tree-sitter-zig.wasm +0 -0
@@ -0,0 +1,455 @@
1
+ import { Renderable, type RenderableOptions } from "../Renderable.js"
2
+ import { OptimizedBuffer } from "../buffer.js"
3
+ import { RGBA, parseColor, type ColorInput } from "../lib/RGBA.js"
4
+ import type { KeyEvent } from "../lib/KeyHandler.js"
5
+ import type { RenderContext } from "../types.js"
6
+ import {
7
+ type KeyBinding as BaseKeyBinding,
8
+ mergeKeyBindings,
9
+ getKeyBindingKey,
10
+ buildKeyBindingsMap,
11
+ type KeyAliasMap,
12
+ defaultKeyAliases,
13
+ mergeKeyAliases,
14
+ } from "../lib/keymapping.js"
15
+
16
+ export interface TabSelectOption {
17
+ name: string
18
+ description: string
19
+ value?: any
20
+ }
21
+
22
+ export type TabSelectAction = "move-left" | "move-right" | "select-current"
23
+
24
+ export type TabSelectKeyBinding = BaseKeyBinding<TabSelectAction>
25
+
26
+ const defaultTabSelectKeybindings: TabSelectKeyBinding[] = [
27
+ { name: "left", action: "move-left" },
28
+ { name: "[", action: "move-left" },
29
+ { name: "right", action: "move-right" },
30
+ { name: "]", action: "move-right" },
31
+ { name: "return", action: "select-current" },
32
+ { name: "linefeed", action: "select-current" },
33
+ ]
34
+
35
+ export interface TabSelectRenderableOptions extends Omit<RenderableOptions<TabSelectRenderable>, "height"> {
36
+ height?: number
37
+ options?: TabSelectOption[]
38
+ tabWidth?: number
39
+ backgroundColor?: ColorInput
40
+ textColor?: ColorInput
41
+ focusedBackgroundColor?: ColorInput
42
+ focusedTextColor?: ColorInput
43
+ selectedBackgroundColor?: ColorInput
44
+ selectedTextColor?: ColorInput
45
+ selectedDescriptionColor?: ColorInput
46
+ showScrollArrows?: boolean
47
+ showDescription?: boolean
48
+ showUnderline?: boolean
49
+ wrapSelection?: boolean
50
+ keyBindings?: TabSelectKeyBinding[]
51
+ keyAliasMap?: KeyAliasMap
52
+ }
53
+
54
+ export enum TabSelectRenderableEvents {
55
+ SELECTION_CHANGED = "selectionChanged",
56
+ ITEM_SELECTED = "itemSelected",
57
+ }
58
+
59
+ function calculateDynamicHeight(showUnderline: boolean, showDescription: boolean): number {
60
+ let height = 1
61
+
62
+ if (showUnderline) {
63
+ height += 1
64
+ }
65
+
66
+ if (showDescription) {
67
+ height += 1
68
+ }
69
+
70
+ return height
71
+ }
72
+
73
+ export class TabSelectRenderable extends Renderable {
74
+ protected _focusable: boolean = true
75
+
76
+ private _options: TabSelectOption[] = []
77
+ private selectedIndex: number = 0
78
+ private scrollOffset: number = 0
79
+ private _tabWidth: number
80
+ private maxVisibleTabs: number
81
+
82
+ private _backgroundColor: RGBA
83
+ private _textColor: RGBA
84
+ private _focusedBackgroundColor: RGBA
85
+ private _focusedTextColor: RGBA
86
+ private _selectedBackgroundColor: RGBA
87
+ private _selectedTextColor: RGBA
88
+ private _selectedDescriptionColor: RGBA
89
+ private _showScrollArrows: boolean
90
+ private _showDescription: boolean
91
+ private _showUnderline: boolean
92
+ private _wrapSelection: boolean
93
+ private _keyBindingsMap: Map<string, TabSelectAction>
94
+ private _keyAliasMap: KeyAliasMap
95
+ private _keyBindings: TabSelectKeyBinding[]
96
+
97
+ constructor(ctx: RenderContext, options: TabSelectRenderableOptions) {
98
+ const calculatedHeight = calculateDynamicHeight(options.showUnderline ?? true, options.showDescription ?? true)
99
+
100
+ super(ctx, { ...options, height: calculatedHeight, buffered: true })
101
+
102
+ this._backgroundColor = parseColor(options.backgroundColor || "transparent")
103
+ this._textColor = parseColor(options.textColor || "#FFFFFF")
104
+ this._focusedBackgroundColor = parseColor(options.focusedBackgroundColor || options.backgroundColor || "#1a1a1a")
105
+ this._focusedTextColor = parseColor(options.focusedTextColor || options.textColor || "#FFFFFF")
106
+ this._options = options.options || []
107
+ this._tabWidth = options.tabWidth || 20
108
+ this._showDescription = options.showDescription ?? true
109
+ this._showUnderline = options.showUnderline ?? true
110
+ this._showScrollArrows = options.showScrollArrows ?? true
111
+ this._wrapSelection = options.wrapSelection ?? false
112
+
113
+ this.maxVisibleTabs = Math.max(1, Math.floor(this.width / this._tabWidth))
114
+
115
+ this._selectedBackgroundColor = parseColor(options.selectedBackgroundColor || "#334455")
116
+ this._selectedTextColor = parseColor(options.selectedTextColor || "#FFFF00")
117
+ this._selectedDescriptionColor = parseColor(options.selectedDescriptionColor || "#CCCCCC")
118
+
119
+ this._keyAliasMap = mergeKeyAliases(defaultKeyAliases, options.keyAliasMap || {})
120
+ this._keyBindings = options.keyBindings || []
121
+ const mergedBindings = mergeKeyBindings(defaultTabSelectKeybindings, this._keyBindings)
122
+ this._keyBindingsMap = buildKeyBindingsMap(mergedBindings, this._keyAliasMap)
123
+ }
124
+
125
+ private calculateDynamicHeight(): number {
126
+ return calculateDynamicHeight(this._showUnderline, this._showDescription)
127
+ }
128
+
129
+ protected renderSelf(buffer: OptimizedBuffer, deltaTime: number): void {
130
+ if (!this.visible || !this.frameBuffer) return
131
+
132
+ if (this.isDirty) {
133
+ this.refreshFrameBuffer()
134
+ }
135
+ }
136
+
137
+ private refreshFrameBuffer(): void {
138
+ if (!this.frameBuffer) return
139
+ // Use focused colors if focused
140
+ const bgColor = this._focused ? this._focusedBackgroundColor : this._backgroundColor
141
+ this.frameBuffer.clear(bgColor)
142
+ if (this._options.length === 0) return
143
+
144
+ const contentX = 0
145
+ const contentY = 0
146
+ const contentWidth = this.width
147
+ const contentHeight = this.height
148
+
149
+ const visibleOptions = this._options.slice(this.scrollOffset, this.scrollOffset + this.maxVisibleTabs)
150
+
151
+ // Render tab names
152
+ for (let i = 0; i < visibleOptions.length; i++) {
153
+ const actualIndex = this.scrollOffset + i
154
+ const option = visibleOptions[i]
155
+ const isSelected = actualIndex === this.selectedIndex
156
+ const tabX = contentX + i * this._tabWidth
157
+
158
+ if (tabX >= contentX + contentWidth) break
159
+
160
+ const actualTabWidth = Math.min(this._tabWidth, contentWidth - i * this._tabWidth)
161
+
162
+ if (isSelected) {
163
+ this.frameBuffer.fillRect(tabX, contentY, actualTabWidth, 1, this._selectedBackgroundColor)
164
+ }
165
+
166
+ const baseTextColor = this._focused ? this._focusedTextColor : this._textColor
167
+ const nameColor = isSelected ? this._selectedTextColor : baseTextColor
168
+ const nameContent = this.truncateText(option.name, actualTabWidth - 2)
169
+ this.frameBuffer.drawText(nameContent, tabX + 1, contentY, nameColor)
170
+
171
+ if (isSelected && this._showUnderline && contentHeight >= 2) {
172
+ const underlineY = contentY + 1
173
+ const underlineBg = isSelected ? this._selectedBackgroundColor : bgColor
174
+ this.frameBuffer.drawText("▬".repeat(actualTabWidth), tabX, underlineY, nameColor, underlineBg)
175
+ }
176
+ }
177
+
178
+ if (this._showDescription && contentHeight >= (this._showUnderline ? 3 : 2)) {
179
+ const selectedOption = this.getSelectedOption()
180
+ if (selectedOption) {
181
+ const descriptionY = contentY + (this._showUnderline ? 2 : 1)
182
+ const descColor = this._selectedDescriptionColor
183
+ const descContent = this.truncateText(selectedOption.description, contentWidth - 2)
184
+ this.frameBuffer.drawText(descContent, contentX + 1, descriptionY, descColor)
185
+ }
186
+ }
187
+
188
+ if (this._showScrollArrows && this._options.length > this.maxVisibleTabs) {
189
+ this.renderScrollArrowsToFrameBuffer(contentX, contentY, contentWidth, contentHeight)
190
+ }
191
+ }
192
+
193
+ private truncateText(text: string, maxWidth: number): string {
194
+ if (text.length <= maxWidth) return text
195
+ return text.substring(0, Math.max(0, maxWidth - 1)) + "…"
196
+ }
197
+
198
+ private renderScrollArrowsToFrameBuffer(
199
+ contentX: number,
200
+ contentY: number,
201
+ contentWidth: number,
202
+ contentHeight: number,
203
+ ): void {
204
+ if (!this.frameBuffer) return
205
+
206
+ const hasMoreLeft = this.scrollOffset > 0
207
+ const hasMoreRight = this.scrollOffset + this.maxVisibleTabs < this._options.length
208
+
209
+ if (hasMoreLeft) {
210
+ this.frameBuffer.drawText("‹", contentX, contentY, parseColor("#AAAAAA"))
211
+ }
212
+
213
+ if (hasMoreRight) {
214
+ this.frameBuffer.drawText("›", contentX + contentWidth - 1, contentY, parseColor("#AAAAAA"))
215
+ }
216
+ }
217
+
218
+ public setOptions(options: TabSelectOption[]): void {
219
+ this._options = options
220
+ this.selectedIndex = Math.min(this.selectedIndex, Math.max(0, options.length - 1))
221
+ this.updateScrollOffset()
222
+ this.requestRender()
223
+ }
224
+
225
+ public getSelectedOption(): TabSelectOption | null {
226
+ return this._options[this.selectedIndex] || null
227
+ }
228
+
229
+ public getSelectedIndex(): number {
230
+ return this.selectedIndex
231
+ }
232
+
233
+ public moveLeft(): void {
234
+ if (this.selectedIndex > 0) {
235
+ this.selectedIndex--
236
+ } else if (this._wrapSelection && this._options.length > 0) {
237
+ this.selectedIndex = this._options.length - 1
238
+ } else {
239
+ return
240
+ }
241
+
242
+ this.updateScrollOffset()
243
+ this.requestRender()
244
+ this.emit(TabSelectRenderableEvents.SELECTION_CHANGED, this.selectedIndex, this.getSelectedOption())
245
+ }
246
+
247
+ public moveRight(): void {
248
+ if (this.selectedIndex < this._options.length - 1) {
249
+ this.selectedIndex++
250
+ } else if (this._wrapSelection && this._options.length > 0) {
251
+ this.selectedIndex = 0
252
+ } else {
253
+ return
254
+ }
255
+
256
+ this.updateScrollOffset()
257
+ this.requestRender()
258
+ this.emit(TabSelectRenderableEvents.SELECTION_CHANGED, this.selectedIndex, this.getSelectedOption())
259
+ }
260
+
261
+ public selectCurrent(): void {
262
+ const selected = this.getSelectedOption()
263
+ if (selected) {
264
+ this.emit(TabSelectRenderableEvents.ITEM_SELECTED, this.selectedIndex, selected)
265
+ }
266
+ }
267
+
268
+ public setSelectedIndex(index: number): void {
269
+ if (index >= 0 && index < this._options.length) {
270
+ this.selectedIndex = index
271
+ this.updateScrollOffset()
272
+ this.requestRender()
273
+ this.emit(TabSelectRenderableEvents.SELECTION_CHANGED, this.selectedIndex, this.getSelectedOption())
274
+ }
275
+ }
276
+
277
+ private updateScrollOffset(): void {
278
+ const halfVisible = Math.floor(this.maxVisibleTabs / 2)
279
+ const newScrollOffset = Math.max(
280
+ 0,
281
+ Math.min(this.selectedIndex - halfVisible, this._options.length - this.maxVisibleTabs),
282
+ )
283
+
284
+ if (newScrollOffset !== this.scrollOffset) {
285
+ this.scrollOffset = newScrollOffset
286
+ this.requestRender()
287
+ }
288
+ }
289
+
290
+ protected onResize(width: number, height: number): void {
291
+ this.maxVisibleTabs = Math.max(1, Math.floor(width / this._tabWidth))
292
+ this.updateScrollOffset()
293
+ this.requestRender()
294
+ }
295
+
296
+ public setTabWidth(tabWidth: number): void {
297
+ if (this._tabWidth === tabWidth) return
298
+
299
+ this._tabWidth = tabWidth
300
+ this.maxVisibleTabs = Math.max(1, Math.floor(this.width / this._tabWidth))
301
+
302
+ this.updateScrollOffset()
303
+ this.requestRender()
304
+ }
305
+
306
+ public getTabWidth(): number {
307
+ return this._tabWidth
308
+ }
309
+
310
+ public handleKeyPress(key: KeyEvent): boolean {
311
+ const bindingKey = getKeyBindingKey({
312
+ name: key.name,
313
+ ctrl: key.ctrl,
314
+ shift: key.shift,
315
+ meta: key.meta,
316
+ super: key.super,
317
+ action: "move-left" as TabSelectAction,
318
+ })
319
+
320
+ const action = this._keyBindingsMap.get(bindingKey)
321
+
322
+ if (action) {
323
+ switch (action) {
324
+ case "move-left":
325
+ this.moveLeft()
326
+ return true
327
+ case "move-right":
328
+ this.moveRight()
329
+ return true
330
+ case "select-current":
331
+ this.selectCurrent()
332
+ return true
333
+ }
334
+ }
335
+
336
+ return false
337
+ }
338
+
339
+ public get options(): TabSelectOption[] {
340
+ return this._options
341
+ }
342
+
343
+ public set options(options: TabSelectOption[]) {
344
+ this._options = options
345
+ this.selectedIndex = Math.min(this.selectedIndex, Math.max(0, options.length - 1))
346
+ this.updateScrollOffset()
347
+ this.requestRender()
348
+ }
349
+
350
+ public set backgroundColor(color: ColorInput) {
351
+ this._backgroundColor = parseColor(color)
352
+ this.requestRender()
353
+ }
354
+
355
+ public set textColor(color: ColorInput) {
356
+ this._textColor = parseColor(color)
357
+ this.requestRender()
358
+ }
359
+
360
+ public set focusedBackgroundColor(color: ColorInput) {
361
+ this._focusedBackgroundColor = parseColor(color)
362
+ this.requestRender()
363
+ }
364
+
365
+ public set focusedTextColor(color: ColorInput) {
366
+ this._focusedTextColor = parseColor(color)
367
+ this.requestRender()
368
+ }
369
+
370
+ public set selectedBackgroundColor(color: ColorInput) {
371
+ this._selectedBackgroundColor = parseColor(color)
372
+ this.requestRender()
373
+ }
374
+
375
+ public set selectedTextColor(color: ColorInput) {
376
+ this._selectedTextColor = parseColor(color)
377
+ this.requestRender()
378
+ }
379
+
380
+ public set selectedDescriptionColor(color: ColorInput) {
381
+ this._selectedDescriptionColor = parseColor(color)
382
+ this.requestRender()
383
+ }
384
+
385
+ public get showDescription(): boolean {
386
+ return this._showDescription
387
+ }
388
+
389
+ public set showDescription(show: boolean) {
390
+ if (this._showDescription !== show) {
391
+ this._showDescription = show
392
+ const newHeight = this.calculateDynamicHeight()
393
+ this.height = newHeight
394
+ this.requestRender()
395
+ }
396
+ }
397
+
398
+ public get showUnderline(): boolean {
399
+ return this._showUnderline
400
+ }
401
+
402
+ public set showUnderline(show: boolean) {
403
+ if (this._showUnderline !== show) {
404
+ this._showUnderline = show
405
+ const newHeight = this.calculateDynamicHeight()
406
+ this.height = newHeight
407
+ this.requestRender()
408
+ }
409
+ }
410
+
411
+ public get showScrollArrows(): boolean {
412
+ return this._showScrollArrows
413
+ }
414
+
415
+ public set showScrollArrows(show: boolean) {
416
+ if (this._showScrollArrows !== show) {
417
+ this._showScrollArrows = show
418
+ this.requestRender()
419
+ }
420
+ }
421
+
422
+ public get wrapSelection(): boolean {
423
+ return this._wrapSelection
424
+ }
425
+
426
+ public set wrapSelection(wrap: boolean) {
427
+ this._wrapSelection = wrap
428
+ }
429
+
430
+ public get tabWidth(): number {
431
+ return this._tabWidth
432
+ }
433
+
434
+ public set tabWidth(tabWidth: number) {
435
+ if (this._tabWidth === tabWidth) return
436
+
437
+ this._tabWidth = tabWidth
438
+ this.maxVisibleTabs = Math.max(1, Math.floor(this.width / this._tabWidth))
439
+
440
+ this.updateScrollOffset()
441
+ this.requestRender()
442
+ }
443
+
444
+ public set keyBindings(bindings: TabSelectKeyBinding[]) {
445
+ this._keyBindings = bindings
446
+ const mergedBindings = mergeKeyBindings(defaultTabSelectKeybindings, bindings)
447
+ this._keyBindingsMap = buildKeyBindingsMap(mergedBindings, this._keyAliasMap)
448
+ }
449
+
450
+ public set keyAliasMap(aliases: KeyAliasMap) {
451
+ this._keyAliasMap = mergeKeyAliases(defaultKeyAliases, aliases)
452
+ const mergedBindings = mergeKeyBindings(defaultTabSelectKeybindings, this._keyBindings)
453
+ this._keyBindingsMap = buildKeyBindingsMap(mergedBindings, this._keyAliasMap)
454
+ }
455
+ }
@@ -0,0 +1,123 @@
1
+ import { describe, expect, it, beforeEach, afterEach } from "bun:test"
2
+ import { TextRenderable } from "./Text.js"
3
+ import { RGBA } from "../lib/RGBA.js"
4
+ import { createTestRenderer, type MockMouse, type TestRenderer } from "../testing/test-renderer.js"
5
+ import { BoxRenderable } from "./Box.js"
6
+
7
+ let currentRenderer: TestRenderer
8
+ let renderOnce: () => Promise<void>
9
+ let currentMouse: MockMouse
10
+
11
+ describe("TextRenderable Selection - Buffer Validation", () => {
12
+ beforeEach(async () => {
13
+ ;({
14
+ renderer: currentRenderer,
15
+ renderOnce,
16
+ mockMouse: currentMouse,
17
+ } = await createTestRenderer({
18
+ width: 50,
19
+ height: 10,
20
+ }))
21
+ })
22
+
23
+ afterEach(() => {
24
+ currentRenderer.destroy()
25
+ })
26
+
27
+ it("applies selection background colors to selected text renderables", async () => {
28
+ const box1 = new BoxRenderable(currentRenderer, {
29
+ id: "box1",
30
+ left: 2,
31
+ top: 2,
32
+ width: 45,
33
+ height: 7,
34
+ backgroundColor: "#1e2936",
35
+ borderColor: "#58a6ff",
36
+ title: "Document Section 1",
37
+ flexDirection: "column",
38
+ padding: 1,
39
+ border: true,
40
+ })
41
+ currentRenderer.root.add(box1)
42
+
43
+ const text1 = new TextRenderable(currentRenderer, {
44
+ id: "text1",
45
+ content: "This is a paragraph in the first box.",
46
+ fg: "#f0f6fc",
47
+ selectionBg: "#4a5568",
48
+ selectionFg: "#ffffff",
49
+ })
50
+ box1.add(text1)
51
+
52
+ const text2 = new TextRenderable(currentRenderer, {
53
+ id: "text2",
54
+ content: "It contains multiple lines of text",
55
+ fg: "#f0f6fc",
56
+ selectionBg: "#4a5568",
57
+ selectionFg: "#ffffff",
58
+ })
59
+ box1.add(text2)
60
+
61
+ const text3 = new TextRenderable(currentRenderer, {
62
+ id: "text3",
63
+ content: "that can be selected independently.",
64
+ fg: "#f0f6fc",
65
+ selectionBg: "#4a5568",
66
+ selectionFg: "#ffffff",
67
+ })
68
+ box1.add(text3)
69
+
70
+ await renderOnce()
71
+
72
+ await currentMouse.drag(text1.x, text1.y, text2.x + 10, text2.y)
73
+ await renderOnce()
74
+
75
+ expect(text1.hasSelection()).toBe(true)
76
+ expect(text2.hasSelection()).toBe(true)
77
+ expect(text3.hasSelection()).toBe(false)
78
+
79
+ expect(text1.getSelectedText()).toBe("This is a paragraph in the first box.")
80
+ expect(text2.getSelectedText()).toBe("It contain")
81
+
82
+ const buffers = currentRenderer.currentRenderBuffer.buffers
83
+ const width = currentRenderer.currentRenderBuffer.width
84
+ const expectedBg = RGBA.fromHex("#4a5568")
85
+
86
+ const getBgAt = (x: number, y: number) => {
87
+ const index = y * width + x
88
+ return RGBA.fromValues(
89
+ buffers.bg[index * 4],
90
+ buffers.bg[index * 4 + 1],
91
+ buffers.bg[index * 4 + 2],
92
+ buffers.bg[index * 4 + 3],
93
+ )
94
+ }
95
+
96
+ for (let col = text1.x; col < text1.x + text1.plainText.length; col++) {
97
+ const bg = getBgAt(col, text1.y)
98
+ const bgMatches =
99
+ Math.abs(bg.r - expectedBg.r) < 0.01 &&
100
+ Math.abs(bg.g - expectedBg.g) < 0.01 &&
101
+ Math.abs(bg.b - expectedBg.b) < 0.01
102
+ expect(bgMatches).toBe(true)
103
+ }
104
+
105
+ for (let col = text2.x; col < text2.x + 10; col++) {
106
+ const bg = getBgAt(col, text2.y)
107
+ const bgMatches =
108
+ Math.abs(bg.r - expectedBg.r) < 0.01 &&
109
+ Math.abs(bg.g - expectedBg.g) < 0.01 &&
110
+ Math.abs(bg.b - expectedBg.b) < 0.01
111
+ expect(bgMatches).toBe(true)
112
+ }
113
+
114
+ for (let col = text2.x + 10; col < text2.x + text2.plainText.length; col++) {
115
+ const bg = getBgAt(col, text2.y)
116
+ const bgMatches =
117
+ Math.abs(bg.r - expectedBg.r) < 0.01 &&
118
+ Math.abs(bg.g - expectedBg.g) < 0.01 &&
119
+ Math.abs(bg.b - expectedBg.b) < 0.01
120
+ expect(bgMatches).toBe(false)
121
+ }
122
+ })
123
+ })