@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,347 @@
1
+ import {
2
+ type ColorInput,
3
+ OptimizedBuffer,
4
+ parseColor,
5
+ Renderable,
6
+ type RenderableOptions,
7
+ type RenderContext,
8
+ RGBA,
9
+ } from "../index.js"
10
+
11
+ const defaultThumbBackgroundColor = RGBA.fromHex("#9a9ea3")
12
+ const defaultTrackBackgroundColor = RGBA.fromHex("#252527")
13
+
14
+ export interface SliderOptions extends RenderableOptions<SliderRenderable> {
15
+ orientation: "vertical" | "horizontal"
16
+ value?: number
17
+ min?: number
18
+ max?: number
19
+ viewPortSize?: number
20
+ backgroundColor?: ColorInput
21
+ foregroundColor?: ColorInput
22
+ onChange?: (value: number) => void
23
+ }
24
+
25
+ export class SliderRenderable extends Renderable {
26
+ public readonly orientation: "vertical" | "horizontal"
27
+ private _value: number
28
+ private _min: number
29
+ private _max: number
30
+ private _viewPortSize: number
31
+ private _backgroundColor: RGBA
32
+ private _foregroundColor: RGBA
33
+ private _onChange?: (value: number) => void
34
+
35
+ constructor(ctx: RenderContext, options: SliderOptions) {
36
+ super(ctx, { flexShrink: 0, ...options })
37
+ this.orientation = options.orientation
38
+ this._min = options.min ?? 0
39
+ this._max = options.max ?? 100
40
+ this._value = options.value ?? this._min
41
+ this._viewPortSize = options.viewPortSize ?? Math.max(1, (this._max - this._min) * 0.1)
42
+ this._onChange = options.onChange
43
+ this._backgroundColor = options.backgroundColor ? parseColor(options.backgroundColor) : defaultTrackBackgroundColor
44
+ this._foregroundColor = options.foregroundColor ? parseColor(options.foregroundColor) : defaultThumbBackgroundColor
45
+
46
+ this.setupMouseHandling()
47
+ }
48
+
49
+ get value(): number {
50
+ return this._value
51
+ }
52
+
53
+ set value(newValue: number) {
54
+ const clamped = Math.max(this._min, Math.min(this._max, newValue))
55
+ if (clamped !== this._value) {
56
+ this._value = clamped
57
+ this._onChange?.(clamped)
58
+ this.emit("change", { value: clamped })
59
+ this.requestRender()
60
+ }
61
+ }
62
+
63
+ get min(): number {
64
+ return this._min
65
+ }
66
+
67
+ set min(newMin: number) {
68
+ if (newMin !== this._min) {
69
+ this._min = newMin
70
+ if (this._value < newMin) {
71
+ this.value = newMin
72
+ }
73
+ this.requestRender()
74
+ }
75
+ }
76
+
77
+ get max(): number {
78
+ return this._max
79
+ }
80
+
81
+ set max(newMax: number) {
82
+ if (newMax !== this._max) {
83
+ this._max = newMax
84
+ if (this._value > newMax) {
85
+ this.value = newMax
86
+ }
87
+ this.requestRender()
88
+ }
89
+ }
90
+
91
+ set viewPortSize(size: number) {
92
+ const clampedSize = Math.max(0.01, Math.min(size, this._max - this._min))
93
+ if (clampedSize !== this._viewPortSize) {
94
+ this._viewPortSize = clampedSize
95
+ this.requestRender()
96
+ }
97
+ }
98
+
99
+ get viewPortSize(): number {
100
+ return this._viewPortSize
101
+ }
102
+
103
+ get backgroundColor(): RGBA {
104
+ return this._backgroundColor
105
+ }
106
+
107
+ set backgroundColor(value: ColorInput) {
108
+ this._backgroundColor = parseColor(value)
109
+ this.requestRender()
110
+ }
111
+
112
+ get foregroundColor(): RGBA {
113
+ return this._foregroundColor
114
+ }
115
+
116
+ set foregroundColor(value: ColorInput) {
117
+ this._foregroundColor = parseColor(value)
118
+ this.requestRender()
119
+ }
120
+
121
+ private calculateDragOffsetVirtual(event: any): number {
122
+ const trackStart = this.orientation === "vertical" ? this.y : this.x
123
+ const mousePos = (this.orientation === "vertical" ? event.y : event.x) - trackStart
124
+ const virtualMousePos = Math.max(
125
+ 0,
126
+ Math.min((this.orientation === "vertical" ? this.height : this.width) * 2, mousePos * 2),
127
+ )
128
+ const virtualThumbStart = this.getVirtualThumbStart()
129
+ const virtualThumbSize = this.getVirtualThumbSize()
130
+
131
+ return Math.max(0, Math.min(virtualThumbSize, virtualMousePos - virtualThumbStart))
132
+ }
133
+
134
+ private setupMouseHandling(): void {
135
+ let isDragging = false
136
+ let dragOffsetVirtual = 0
137
+
138
+ this.onMouseDown = (event) => {
139
+ event.stopPropagation()
140
+ event.preventDefault()
141
+
142
+ const thumb = this.getThumbRect()
143
+ const inThumb =
144
+ event.x >= thumb.x && event.x < thumb.x + thumb.width && event.y >= thumb.y && event.y < thumb.y + thumb.height
145
+
146
+ if (inThumb) {
147
+ isDragging = true
148
+
149
+ dragOffsetVirtual = this.calculateDragOffsetVirtual(event)
150
+ } else {
151
+ this.updateValueFromMouseDirect(event)
152
+ isDragging = true
153
+
154
+ dragOffsetVirtual = this.calculateDragOffsetVirtual(event)
155
+ }
156
+ }
157
+
158
+ this.onMouseDrag = (event) => {
159
+ if (!isDragging) return
160
+ event.stopPropagation()
161
+ this.updateValueFromMouseWithOffset(event, dragOffsetVirtual)
162
+ }
163
+
164
+ this.onMouseUp = (event) => {
165
+ if (isDragging) {
166
+ this.updateValueFromMouseWithOffset(event, dragOffsetVirtual)
167
+ }
168
+ isDragging = false
169
+ }
170
+ }
171
+
172
+ private updateValueFromMouseDirect(event: any): void {
173
+ const trackStart = this.orientation === "vertical" ? this.y : this.x
174
+ const trackSize = this.orientation === "vertical" ? this.height : this.width
175
+ const mousePos = this.orientation === "vertical" ? event.y : event.x
176
+
177
+ const relativeMousePos = mousePos - trackStart
178
+ const clampedMousePos = Math.max(0, Math.min(trackSize, relativeMousePos))
179
+ const ratio = trackSize === 0 ? 0 : clampedMousePos / trackSize
180
+ const range = this._max - this._min
181
+ const newValue = this._min + ratio * range
182
+
183
+ this.value = newValue
184
+ }
185
+
186
+ private updateValueFromMouseWithOffset(event: any, offsetVirtual: number): void {
187
+ const trackStart = this.orientation === "vertical" ? this.y : this.x
188
+ const trackSize = this.orientation === "vertical" ? this.height : this.width
189
+ const mousePos = this.orientation === "vertical" ? event.y : event.x
190
+
191
+ const virtualTrackSize = trackSize * 2
192
+ const relativeMousePos = mousePos - trackStart
193
+ const clampedMousePos = Math.max(0, Math.min(trackSize, relativeMousePos))
194
+ const virtualMousePos = clampedMousePos * 2
195
+
196
+ const virtualThumbSize = this.getVirtualThumbSize()
197
+ const maxThumbStart = Math.max(0, virtualTrackSize - virtualThumbSize)
198
+
199
+ let desiredThumbStart = virtualMousePos - offsetVirtual
200
+ desiredThumbStart = Math.max(0, Math.min(maxThumbStart, desiredThumbStart))
201
+
202
+ const ratio = maxThumbStart === 0 ? 0 : desiredThumbStart / maxThumbStart
203
+ const range = this._max - this._min
204
+ const newValue = this._min + ratio * range
205
+
206
+ this.value = newValue
207
+ }
208
+
209
+ private getThumbRect(): { x: number; y: number; width: number; height: number } {
210
+ const virtualThumbSize = this.getVirtualThumbSize()
211
+ const virtualThumbStart = this.getVirtualThumbStart()
212
+
213
+ const realThumbStart = Math.floor(virtualThumbStart / 2)
214
+ const realThumbSize = Math.ceil((virtualThumbStart + virtualThumbSize) / 2) - realThumbStart
215
+
216
+ if (this.orientation === "vertical") {
217
+ return {
218
+ x: this.x,
219
+ y: this.y + realThumbStart,
220
+ width: this.width,
221
+ height: Math.max(1, realThumbSize),
222
+ }
223
+ } else {
224
+ return {
225
+ x: this.x + realThumbStart,
226
+ y: this.y,
227
+ width: Math.max(1, realThumbSize),
228
+ height: this.height,
229
+ }
230
+ }
231
+ }
232
+
233
+ protected renderSelf(buffer: OptimizedBuffer): void {
234
+ if (this.orientation === "horizontal") {
235
+ this.renderHorizontal(buffer)
236
+ } else {
237
+ this.renderVertical(buffer)
238
+ }
239
+ }
240
+
241
+ private renderHorizontal(buffer: OptimizedBuffer): void {
242
+ const virtualThumbSize = this.getVirtualThumbSize()
243
+ const virtualThumbStart = this.getVirtualThumbStart()
244
+ const virtualThumbEnd = virtualThumbStart + virtualThumbSize
245
+
246
+ buffer.fillRect(this.x, this.y, this.width, this.height, this._backgroundColor)
247
+
248
+ const realStartCell = Math.floor(virtualThumbStart / 2)
249
+ const realEndCell = Math.ceil(virtualThumbEnd / 2) - 1
250
+ const startX = Math.max(0, realStartCell)
251
+ const endX = Math.min(this.width - 1, realEndCell)
252
+
253
+ for (let realX = startX; realX <= endX; realX++) {
254
+ const virtualCellStart = realX * 2
255
+ const virtualCellEnd = virtualCellStart + 2
256
+
257
+ const thumbStartInCell = Math.max(virtualThumbStart, virtualCellStart)
258
+ const thumbEndInCell = Math.min(virtualThumbEnd, virtualCellEnd)
259
+ const coverage = thumbEndInCell - thumbStartInCell
260
+
261
+ let char = " "
262
+
263
+ if (coverage >= 2) {
264
+ char = "█"
265
+ } else {
266
+ const isLeftHalf = thumbStartInCell === virtualCellStart
267
+ if (isLeftHalf) {
268
+ char = "▌"
269
+ } else {
270
+ char = "▐"
271
+ }
272
+ }
273
+
274
+ for (let y = 0; y < this.height; y++) {
275
+ buffer.setCellWithAlphaBlending(this.x + realX, this.y + y, char, this._foregroundColor, this._backgroundColor)
276
+ }
277
+ }
278
+ }
279
+
280
+ private renderVertical(buffer: OptimizedBuffer): void {
281
+ const virtualThumbSize = this.getVirtualThumbSize()
282
+ const virtualThumbStart = this.getVirtualThumbStart()
283
+ const virtualThumbEnd = virtualThumbStart + virtualThumbSize
284
+
285
+ buffer.fillRect(this.x, this.y, this.width, this.height, this._backgroundColor)
286
+
287
+ const realStartCell = Math.floor(virtualThumbStart / 2)
288
+ const realEndCell = Math.ceil(virtualThumbEnd / 2) - 1
289
+ const startY = Math.max(0, realStartCell)
290
+ const endY = Math.min(this.height - 1, realEndCell)
291
+
292
+ for (let realY = startY; realY <= endY; realY++) {
293
+ const virtualCellStart = realY * 2
294
+ const virtualCellEnd = virtualCellStart + 2
295
+
296
+ const thumbStartInCell = Math.max(virtualThumbStart, virtualCellStart)
297
+ const thumbEndInCell = Math.min(virtualThumbEnd, virtualCellEnd)
298
+ const coverage = thumbEndInCell - thumbStartInCell
299
+
300
+ let char = " "
301
+
302
+ if (coverage >= 2) {
303
+ char = "█"
304
+ } else if (coverage > 0) {
305
+ const virtualPositionInCell = thumbStartInCell - virtualCellStart
306
+ if (virtualPositionInCell === 0) {
307
+ char = "▀"
308
+ } else {
309
+ char = "▄"
310
+ }
311
+ }
312
+
313
+ for (let x = 0; x < this.width; x++) {
314
+ buffer.setCellWithAlphaBlending(this.x + x, this.y + realY, char, this._foregroundColor, this._backgroundColor)
315
+ }
316
+ }
317
+ }
318
+
319
+ private getVirtualThumbSize(): number {
320
+ const virtualTrackSize = this.orientation === "vertical" ? this.height * 2 : this.width * 2
321
+ const range = this._max - this._min
322
+
323
+ if (range === 0) return virtualTrackSize
324
+
325
+ const viewportSize = Math.max(1, this._viewPortSize)
326
+ const contentSize = range + viewportSize
327
+
328
+ if (contentSize <= viewportSize) return virtualTrackSize
329
+
330
+ const thumbRatio = viewportSize / contentSize
331
+ const calculatedSize = Math.floor(virtualTrackSize * thumbRatio)
332
+
333
+ return Math.max(1, Math.min(calculatedSize, virtualTrackSize))
334
+ }
335
+
336
+ private getVirtualThumbStart(): number {
337
+ const virtualTrackSize = this.orientation === "vertical" ? this.height * 2 : this.width * 2
338
+ const range = this._max - this._min
339
+
340
+ if (range === 0) return 0
341
+
342
+ const valueRatio = (this._value - this._min) / range
343
+ const virtualThumbSize = this.getVirtualThumbSize()
344
+
345
+ return Math.round(valueRatio * (virtualTrackSize - virtualThumbSize))
346
+ }
347
+ }
@@ -0,0 +1,197 @@
1
+ import { test, expect, describe, beforeEach, afterEach } from "bun:test"
2
+ import {
3
+ TabSelectRenderable,
4
+ type TabSelectRenderableOptions,
5
+ TabSelectRenderableEvents,
6
+ type TabSelectOption,
7
+ } from "./TabSelect.js"
8
+ import { createTestRenderer, type MockInput, type TestRenderer } from "../testing/test-renderer.js"
9
+ import { ManualClock } from "../testing/manual-clock.js"
10
+
11
+ let currentRenderer: TestRenderer
12
+ let currentMockInput: MockInput
13
+ let renderOnce: () => Promise<void>
14
+ let currentClock: ManualClock
15
+
16
+ const sampleOptions: TabSelectOption[] = [
17
+ { name: "Tab 1", description: "First tab" },
18
+ { name: "Tab 2", description: "Second tab" },
19
+ { name: "Tab 3", description: "Third tab" },
20
+ { name: "Tab 4", description: "Fourth tab" },
21
+ { name: "Tab 5", description: "Fifth tab" },
22
+ ]
23
+
24
+ async function createTabSelectRenderable(
25
+ renderer: TestRenderer,
26
+ options: TabSelectRenderableOptions,
27
+ ): Promise<{ tabSelect: TabSelectRenderable; root: any }> {
28
+ const tabSelectRenderable = new TabSelectRenderable(renderer, { left: 0, top: 0, ...options })
29
+ renderer.root.add(tabSelectRenderable)
30
+ await renderOnce()
31
+
32
+ return { tabSelect: tabSelectRenderable, root: renderer.root }
33
+ }
34
+
35
+ beforeEach(async () => {
36
+ currentClock = new ManualClock()
37
+ ;({
38
+ renderer: currentRenderer,
39
+ mockInput: currentMockInput,
40
+ renderOnce,
41
+ } = await createTestRenderer({
42
+ clock: currentClock,
43
+ }))
44
+ })
45
+
46
+ afterEach(() => {
47
+ currentRenderer.destroy()
48
+ })
49
+
50
+ describe("TabSelectRenderable", () => {
51
+ describe("Key Bindings and Aliases", () => {
52
+ test("should support custom key bindings", async () => {
53
+ const { tabSelect } = await createTabSelectRenderable(currentRenderer, {
54
+ width: 100,
55
+ options: sampleOptions,
56
+ keyBindings: [
57
+ { name: "h", action: "move-left" },
58
+ { name: "l", action: "move-right" },
59
+ ],
60
+ })
61
+
62
+ tabSelect.focus()
63
+ expect(tabSelect.getSelectedIndex()).toBe(0)
64
+
65
+ // L should move right
66
+ currentMockInput.pressKey("l")
67
+ expect(tabSelect.getSelectedIndex()).toBe(1)
68
+
69
+ // H should move left
70
+ currentMockInput.pressKey("h")
71
+ expect(tabSelect.getSelectedIndex()).toBe(0)
72
+ })
73
+
74
+ test("should support key aliases", async () => {
75
+ const { tabSelect } = await createTabSelectRenderable(currentRenderer, {
76
+ width: 100,
77
+ options: sampleOptions,
78
+ keyAliasMap: {
79
+ enter: "return",
80
+ },
81
+ })
82
+
83
+ tabSelect.focus()
84
+ tabSelect.setSelectedIndex(1)
85
+
86
+ let itemSelected = false
87
+ tabSelect.on(TabSelectRenderableEvents.ITEM_SELECTED, () => {
88
+ itemSelected = true
89
+ })
90
+
91
+ currentMockInput.pressEnter()
92
+ expect(itemSelected).toBe(true)
93
+ })
94
+
95
+ test("should merge custom bindings with defaults", async () => {
96
+ const { tabSelect } = await createTabSelectRenderable(currentRenderer, {
97
+ width: 100,
98
+ options: sampleOptions,
99
+ keyBindings: [{ name: "n", action: "move-right" }],
100
+ })
101
+
102
+ tabSelect.focus()
103
+ expect(tabSelect.getSelectedIndex()).toBe(0)
104
+
105
+ // Default binding should still work
106
+ currentMockInput.pressArrow("right")
107
+ expect(tabSelect.getSelectedIndex()).toBe(1)
108
+
109
+ // Custom binding should also work
110
+ currentMockInput.pressKey("n")
111
+ expect(tabSelect.getSelectedIndex()).toBe(2)
112
+ })
113
+
114
+ test("should override default bindings with custom ones", async () => {
115
+ const { tabSelect } = await createTabSelectRenderable(currentRenderer, {
116
+ width: 100,
117
+ options: sampleOptions,
118
+ keyBindings: [
119
+ { name: "[", action: "move-right" }, // Override [ to move right instead of left
120
+ ],
121
+ })
122
+
123
+ tabSelect.focus()
124
+ expect(tabSelect.getSelectedIndex()).toBe(0)
125
+
126
+ currentMockInput.pressKey("[")
127
+ currentClock.advance(10)
128
+ expect(tabSelect.getSelectedIndex()).toBe(1)
129
+ })
130
+
131
+ test("should allow updating key bindings dynamically", async () => {
132
+ const { tabSelect } = await createTabSelectRenderable(currentRenderer, {
133
+ width: 100,
134
+ options: sampleOptions,
135
+ })
136
+
137
+ tabSelect.focus()
138
+ expect(tabSelect.getSelectedIndex()).toBe(0)
139
+
140
+ // Move right with default binding
141
+ currentMockInput.pressArrow("right")
142
+ expect(tabSelect.getSelectedIndex()).toBe(1)
143
+
144
+ // Update bindings
145
+ tabSelect.keyBindings = [{ name: "space", action: "move-right" }]
146
+
147
+ // Space should now move right
148
+ currentMockInput.pressKey(" ")
149
+ expect(tabSelect.getSelectedIndex()).toBe(2)
150
+ })
151
+
152
+ test("should handle modifiers in custom bindings", async () => {
153
+ const { tabSelect } = await createTabSelectRenderable(currentRenderer, {
154
+ width: 100,
155
+ options: sampleOptions,
156
+ keyBindings: [
157
+ { name: "left", ctrl: true, action: "move-right" },
158
+ { name: "right", ctrl: true, action: "move-left" },
159
+ ],
160
+ })
161
+
162
+ tabSelect.focus()
163
+ tabSelect.setSelectedIndex(2)
164
+
165
+ // Ctrl+Right should move left
166
+ currentMockInput.pressArrow("right", { ctrl: true })
167
+ expect(tabSelect.getSelectedIndex()).toBe(1)
168
+
169
+ // Ctrl+Left should move right
170
+ currentMockInput.pressArrow("left", { ctrl: true })
171
+ expect(tabSelect.getSelectedIndex()).toBe(2)
172
+ })
173
+
174
+ test("should handle wrap selection with custom bindings", async () => {
175
+ const { tabSelect } = await createTabSelectRenderable(currentRenderer, {
176
+ width: 100,
177
+ options: sampleOptions,
178
+ wrapSelection: true,
179
+ keyBindings: [
180
+ { name: "n", action: "move-right" },
181
+ { name: "p", action: "move-left" },
182
+ ],
183
+ })
184
+
185
+ tabSelect.focus()
186
+ expect(tabSelect.getSelectedIndex()).toBe(0)
187
+
188
+ // P should wrap to end
189
+ currentMockInput.pressKey("p")
190
+ expect(tabSelect.getSelectedIndex()).toBe(4)
191
+
192
+ // N should wrap to start
193
+ currentMockInput.pressKey("n")
194
+ expect(tabSelect.getSelectedIndex()).toBe(0)
195
+ })
196
+ })
197
+ })