@fairyhunter13/opentui-core 0.1.89 → 0.1.91

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (571) hide show
  1. package/README.md +2 -2
  2. package/dev/keypress-debug-renderer.ts +148 -0
  3. package/dev/keypress-debug.ts +43 -0
  4. package/dev/print-env-vars.ts +32 -0
  5. package/dev/test-tmux-graphics-334.sh +68 -0
  6. package/dev/thai-debug-test.ts +68 -0
  7. package/docs/development.md +141 -0
  8. package/docs/env-vars.md +140 -0
  9. package/docs/getting-started.md +353 -0
  10. package/docs/renderables-vs-constructs.md +159 -0
  11. package/docs/tree-sitter.md +311 -0
  12. package/package.json +61 -52
  13. package/scripts/build.ts +400 -0
  14. package/scripts/publish.ts +60 -0
  15. package/src/3d/SpriteResourceManager.ts +286 -0
  16. package/src/3d/SpriteUtils.ts +71 -0
  17. package/src/3d/TextureUtils.ts +196 -0
  18. package/src/3d/ThreeRenderable.ts +197 -0
  19. package/src/3d/WGPURenderer.ts +294 -0
  20. package/src/3d/animation/ExplodingSpriteEffect.ts +513 -0
  21. package/src/3d/animation/PhysicsExplodingSpriteEffect.ts +429 -0
  22. package/src/3d/animation/SpriteAnimator.ts +633 -0
  23. package/src/3d/animation/SpriteParticleGenerator.ts +435 -0
  24. package/src/3d/canvas.ts +464 -0
  25. package/src/3d/index.ts +12 -0
  26. package/src/3d/physics/PlanckPhysicsAdapter.ts +72 -0
  27. package/src/3d/physics/RapierPhysicsAdapter.ts +66 -0
  28. package/src/3d/physics/physics-interface.ts +31 -0
  29. package/src/3d/shaders/supersampling.wgsl +201 -0
  30. package/src/3d.ts +3 -0
  31. package/src/NativeSpanFeed.ts +300 -0
  32. package/src/Renderable.ts +1698 -0
  33. package/src/__snapshots__/buffer.test.ts.snap +28 -0
  34. package/src/animation/Timeline.test.ts +2709 -0
  35. package/src/animation/Timeline.ts +598 -0
  36. package/src/ansi.ts +18 -0
  37. package/src/benchmark/latest-all-bench-run.json +707 -0
  38. package/src/benchmark/latest-async-bench-run.json +336 -0
  39. package/src/benchmark/latest-default-bench-run.json +657 -0
  40. package/src/benchmark/latest-large-bench-run.json +707 -0
  41. package/src/benchmark/latest-quick-bench-run.json +207 -0
  42. package/src/benchmark/markdown-benchmark.ts +1804 -0
  43. package/src/benchmark/native-span-feed-async-benchmark.ts +355 -0
  44. package/src/benchmark/native-span-feed-benchmark.md +56 -0
  45. package/src/benchmark/native-span-feed-benchmark.ts +596 -0
  46. package/src/benchmark/native-span-feed-compare.ts +280 -0
  47. package/src/benchmark/renderer-benchmark.ts +754 -0
  48. package/src/benchmark/text-table-benchmark.ts +947 -0
  49. package/src/buffer.test.ts +291 -0
  50. package/src/buffer.ts +519 -0
  51. package/src/console.test.ts +612 -0
  52. package/src/console.ts +1255 -0
  53. package/src/edit-buffer.test.ts +1769 -0
  54. package/src/edit-buffer.ts +411 -0
  55. package/src/editor-view.test.ts +1032 -0
  56. package/src/editor-view.ts +284 -0
  57. package/src/examples/ascii-font-selection-demo.ts +245 -0
  58. package/src/examples/assets/Water_2_M_Normal.jpg +0 -0
  59. package/src/examples/assets/concrete.png +0 -0
  60. package/src/examples/assets/crate.png +0 -0
  61. package/src/examples/assets/crate_emissive.png +0 -0
  62. package/src/examples/assets/forrest_background.png +0 -0
  63. package/src/examples/assets/hast-example.json +1018 -0
  64. package/src/examples/assets/heart.png +0 -0
  65. package/src/examples/assets/main_char_heavy_attack.png +0 -0
  66. package/src/examples/assets/main_char_idle.png +0 -0
  67. package/src/examples/assets/main_char_jump_end.png +0 -0
  68. package/src/examples/assets/main_char_jump_landing.png +0 -0
  69. package/src/examples/assets/main_char_jump_start.png +0 -0
  70. package/src/examples/assets/main_char_run_loop.png +0 -0
  71. package/src/examples/assets/roughness_map.jpg +0 -0
  72. package/src/examples/build.ts +115 -0
  73. package/src/examples/code-demo.ts +584 -0
  74. package/src/examples/console-demo.ts +358 -0
  75. package/src/examples/core-plugin-slots-demo.ts +759 -0
  76. package/src/examples/diff-demo.ts +699 -0
  77. package/src/examples/draggable-three-demo.ts +259 -0
  78. package/src/examples/editor-demo.ts +322 -0
  79. package/src/examples/extmarks-demo.ts +204 -0
  80. package/src/examples/focus-restore-demo.ts +310 -0
  81. package/src/examples/fonts.ts +245 -0
  82. package/src/examples/fractal-shader-demo.ts +268 -0
  83. package/src/examples/framebuffer-demo.ts +674 -0
  84. package/src/examples/full-unicode-demo.ts +181 -0
  85. package/src/examples/golden-star-demo.ts +933 -0
  86. package/src/examples/grayscale-buffer-demo.ts +249 -0
  87. package/src/examples/hast-syntax-highlighting-demo.ts +129 -0
  88. package/src/examples/index.ts +925 -0
  89. package/src/examples/input-demo.ts +377 -0
  90. package/src/examples/input-select-layout-demo.ts +425 -0
  91. package/src/examples/install.sh +143 -0
  92. package/src/examples/keypress-debug-demo.ts +452 -0
  93. package/src/examples/lib/HexList.ts +122 -0
  94. package/src/examples/lib/PaletteGrid.ts +125 -0
  95. package/src/examples/lib/standalone-keys.ts +25 -0
  96. package/src/examples/lib/tab-controller.ts +243 -0
  97. package/src/examples/lights-phong-demo.ts +290 -0
  98. package/src/examples/link-demo.ts +220 -0
  99. package/src/examples/live-state-demo.ts +480 -0
  100. package/src/examples/markdown-demo.ts +620 -0
  101. package/src/examples/mouse-interaction-demo.ts +428 -0
  102. package/src/examples/nested-zindex-demo.ts +357 -0
  103. package/src/examples/opacity-example.ts +235 -0
  104. package/src/examples/opentui-demo.ts +1057 -0
  105. package/src/examples/physx-planck-2d-demo.ts +507 -0
  106. package/src/examples/physx-rapier-2d-demo.ts +526 -0
  107. package/src/examples/relative-positioning-demo.ts +323 -0
  108. package/src/examples/scroll-example.ts +214 -0
  109. package/src/examples/scrollbox-mouse-test.ts +112 -0
  110. package/src/examples/scrollbox-overlay-hit-test.ts +206 -0
  111. package/src/examples/select-demo.ts +237 -0
  112. package/src/examples/shader-cube-demo.ts +772 -0
  113. package/src/examples/simple-layout-example.ts +591 -0
  114. package/src/examples/slider-demo.ts +617 -0
  115. package/src/examples/split-mode-demo.ts +445 -0
  116. package/src/examples/sprite-animation-demo.ts +443 -0
  117. package/src/examples/sprite-particle-generator-demo.ts +486 -0
  118. package/src/examples/static-sprite-demo.ts +193 -0
  119. package/src/examples/sticky-scroll-example.ts +308 -0
  120. package/src/examples/styled-text-demo.ts +282 -0
  121. package/src/examples/tab-select-demo.ts +219 -0
  122. package/src/examples/terminal-title.ts +29 -0
  123. package/src/examples/terminal.ts +305 -0
  124. package/src/examples/text-node-demo.ts +416 -0
  125. package/src/examples/text-selection-demo.ts +377 -0
  126. package/src/examples/text-table-demo.ts +503 -0
  127. package/src/examples/text-truncation-demo.ts +481 -0
  128. package/src/examples/text-wrap.ts +757 -0
  129. package/src/examples/texture-loading-demo.ts +259 -0
  130. package/src/examples/timeline-example.ts +670 -0
  131. package/src/examples/transparency-demo.ts +241 -0
  132. package/src/examples/vnode-composition-demo.ts +404 -0
  133. package/src/index.ts +22 -0
  134. package/src/lib/KeyHandler.integration.test.ts +292 -0
  135. package/src/lib/KeyHandler.stopPropagation.test.ts +289 -0
  136. package/src/lib/KeyHandler.test.ts +662 -0
  137. package/src/lib/KeyHandler.ts +222 -0
  138. package/src/lib/RGBA.test.ts +984 -0
  139. package/src/lib/RGBA.ts +204 -0
  140. package/src/lib/ascii.font.ts +330 -0
  141. package/src/lib/border.test.ts +83 -0
  142. package/src/lib/border.ts +168 -0
  143. package/src/lib/bunfs.test.ts +27 -0
  144. package/src/lib/bunfs.ts +18 -0
  145. package/src/lib/clipboard.test.ts +41 -0
  146. package/src/lib/clipboard.ts +47 -0
  147. package/src/lib/clock.ts +31 -0
  148. package/src/lib/data-paths.test.ts +133 -0
  149. package/src/lib/data-paths.ts +109 -0
  150. package/src/lib/debounce.ts +106 -0
  151. package/src/lib/detect-links.test.ts +98 -0
  152. package/src/lib/detect-links.ts +56 -0
  153. package/src/lib/env.test.ts +228 -0
  154. package/src/lib/env.ts +209 -0
  155. package/src/lib/extmarks-history.ts +51 -0
  156. package/src/lib/extmarks-multiwidth.test.ts +322 -0
  157. package/src/lib/extmarks.test.ts +3457 -0
  158. package/src/lib/extmarks.ts +843 -0
  159. package/src/lib/fonts/block.json +405 -0
  160. package/src/lib/fonts/grid.json +265 -0
  161. package/src/lib/fonts/huge.json +741 -0
  162. package/src/lib/fonts/pallet.json +314 -0
  163. package/src/lib/fonts/shade.json +591 -0
  164. package/src/lib/fonts/slick.json +321 -0
  165. package/src/lib/fonts/tiny.json +69 -0
  166. package/src/lib/hast-styled-text.ts +59 -0
  167. package/src/lib/index.ts +21 -0
  168. package/src/lib/keymapping.test.ts +280 -0
  169. package/src/lib/keymapping.ts +87 -0
  170. package/src/lib/objects-in-viewport.test.ts +787 -0
  171. package/src/lib/objects-in-viewport.ts +153 -0
  172. package/src/lib/output.capture.ts +58 -0
  173. package/src/lib/parse.keypress-kitty.protocol.test.ts +340 -0
  174. package/src/lib/parse.keypress-kitty.test.ts +663 -0
  175. package/src/lib/parse.keypress-kitty.ts +439 -0
  176. package/src/lib/parse.keypress.test.ts +1849 -0
  177. package/src/lib/parse.keypress.ts +397 -0
  178. package/src/lib/parse.mouse.test.ts +552 -0
  179. package/src/lib/parse.mouse.ts +232 -0
  180. package/src/lib/paste.ts +16 -0
  181. package/src/lib/queue.ts +65 -0
  182. package/src/lib/renderable.validations.test.ts +87 -0
  183. package/src/lib/renderable.validations.ts +83 -0
  184. package/src/lib/scroll-acceleration.ts +98 -0
  185. package/src/lib/selection.ts +240 -0
  186. package/src/lib/singleton.ts +28 -0
  187. package/src/lib/stdin-parser.test.ts +1676 -0
  188. package/src/lib/stdin-parser.ts +1248 -0
  189. package/src/lib/styled-text.ts +178 -0
  190. package/src/lib/terminal-capability-detection.test.ts +202 -0
  191. package/src/lib/terminal-capability-detection.ts +79 -0
  192. package/src/lib/terminal-palette.test.ts +878 -0
  193. package/src/lib/terminal-palette.ts +383 -0
  194. package/src/lib/tree-sitter/assets/README.md +118 -0
  195. package/src/lib/tree-sitter/assets/update.ts +331 -0
  196. package/src/lib/tree-sitter/assets.d.ts +9 -0
  197. package/src/lib/tree-sitter/cache.test.ts +270 -0
  198. package/src/lib/tree-sitter/client.test.ts +1061 -0
  199. package/src/lib/tree-sitter/client.ts +615 -0
  200. package/src/lib/tree-sitter/default-parsers.ts +80 -0
  201. package/src/lib/tree-sitter/download-utils.ts +148 -0
  202. package/src/lib/tree-sitter/index.ts +28 -0
  203. package/src/lib/tree-sitter/parser.worker.ts +1001 -0
  204. package/src/lib/tree-sitter/parsers-config.ts +75 -0
  205. package/src/lib/tree-sitter/resolve-ft.ts +62 -0
  206. package/src/lib/tree-sitter/types.ts +81 -0
  207. package/src/lib/tree-sitter-styled-text.test.ts +1253 -0
  208. package/src/lib/tree-sitter-styled-text.ts +306 -0
  209. package/src/lib/validate-dir-name.ts +55 -0
  210. package/src/lib/yoga.options.test.ts +628 -0
  211. package/src/lib/yoga.options.ts +346 -0
  212. package/src/plugins/core-slot.ts +579 -0
  213. package/src/plugins/registry.ts +377 -0
  214. package/src/plugins/types.ts +46 -0
  215. package/src/post/filters.ts +888 -0
  216. package/src/renderables/ASCIIFont.ts +219 -0
  217. package/src/renderables/Box.test.ts +160 -0
  218. package/src/renderables/Box.ts +295 -0
  219. package/src/renderables/Code.test.ts +2062 -0
  220. package/src/renderables/Code.ts +357 -0
  221. package/src/renderables/Diff.regression.test.ts +226 -0
  222. package/src/renderables/Diff.test.ts +3027 -0
  223. package/src/renderables/Diff.ts +1209 -0
  224. package/src/renderables/EditBufferRenderable.ts +764 -0
  225. package/src/renderables/FrameBuffer.ts +47 -0
  226. package/src/renderables/Input.test.ts +1228 -0
  227. package/src/renderables/Input.ts +245 -0
  228. package/src/renderables/LineNumberRenderable.ts +675 -0
  229. package/src/renderables/Markdown.ts +1106 -0
  230. package/src/renderables/ScrollBar.ts +422 -0
  231. package/src/renderables/ScrollBox.ts +883 -0
  232. package/src/renderables/Select.test.ts +1010 -0
  233. package/src/renderables/Select.ts +523 -0
  234. package/src/renderables/Slider.test.ts +456 -0
  235. package/src/renderables/Slider.ts +347 -0
  236. package/src/renderables/TabSelect.test.ts +197 -0
  237. package/src/renderables/TabSelect.ts +455 -0
  238. package/src/renderables/Text.selection-buffer.test.ts +123 -0
  239. package/src/renderables/Text.test.ts +2660 -0
  240. package/src/renderables/Text.ts +147 -0
  241. package/src/renderables/TextBufferRenderable.ts +518 -0
  242. package/src/renderables/TextNode.test.ts +1058 -0
  243. package/src/renderables/TextNode.ts +325 -0
  244. package/src/renderables/TextTable.test.ts +1421 -0
  245. package/src/renderables/TextTable.ts +1344 -0
  246. package/src/renderables/Textarea.ts +732 -0
  247. package/src/renderables/TimeToFirstDraw.ts +89 -0
  248. package/src/renderables/__snapshots__/Code.test.ts.snap +13 -0
  249. package/src/renderables/__snapshots__/Diff.test.ts.snap +785 -0
  250. package/src/renderables/__snapshots__/Text.test.ts.snap +421 -0
  251. package/src/renderables/__snapshots__/TextTable.test.ts.snap +215 -0
  252. package/src/renderables/__tests__/LineNumberRenderable.scrollbox-simple.test.ts +144 -0
  253. package/src/renderables/__tests__/LineNumberRenderable.scrollbox.test.ts +816 -0
  254. package/src/renderables/__tests__/LineNumberRenderable.test.ts +1787 -0
  255. package/src/renderables/__tests__/LineNumberRenderable.wrapping.test.ts +85 -0
  256. package/src/renderables/__tests__/Markdown.test.ts +2287 -0
  257. package/src/renderables/__tests__/MultiRenderable.selection.test.ts +87 -0
  258. package/src/renderables/__tests__/Textarea.buffer.test.ts +682 -0
  259. package/src/renderables/__tests__/Textarea.destroyed-events.test.ts +675 -0
  260. package/src/renderables/__tests__/Textarea.editing.test.ts +2041 -0
  261. package/src/renderables/__tests__/Textarea.error-handling.test.ts +35 -0
  262. package/src/renderables/__tests__/Textarea.events.test.ts +738 -0
  263. package/src/renderables/__tests__/Textarea.highlights.test.ts +590 -0
  264. package/src/renderables/__tests__/Textarea.keybinding.test.ts +3149 -0
  265. package/src/renderables/__tests__/Textarea.paste.test.ts +357 -0
  266. package/src/renderables/__tests__/Textarea.rendering.test.ts +1864 -0
  267. package/src/renderables/__tests__/Textarea.scroll.test.ts +733 -0
  268. package/src/renderables/__tests__/Textarea.selection.test.ts +1590 -0
  269. package/src/renderables/__tests__/Textarea.stress.test.ts +670 -0
  270. package/src/renderables/__tests__/Textarea.undo-redo.test.ts +383 -0
  271. package/src/renderables/__tests__/Textarea.visual-lines.test.ts +310 -0
  272. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.code.test.ts.snap +221 -0
  273. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox-simple.test.ts.snap +89 -0
  274. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox.test.ts.snap +457 -0
  275. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.test.ts.snap +158 -0
  276. package/src/renderables/__tests__/__snapshots__/Textarea.rendering.test.ts.snap +387 -0
  277. package/src/renderables/__tests__/markdown-parser.test.ts +217 -0
  278. package/src/renderables/__tests__/renderable-test-utils.ts +60 -0
  279. package/src/renderables/composition/README.md +8 -0
  280. package/src/renderables/composition/VRenderable.ts +32 -0
  281. package/src/renderables/composition/constructs.ts +127 -0
  282. package/src/renderables/composition/vnode.ts +289 -0
  283. package/src/renderables/index.ts +22 -0
  284. package/src/renderables/markdown-parser.ts +66 -0
  285. package/src/renderer.ts +2363 -0
  286. package/src/runtime-plugin-support.ts +39 -0
  287. package/src/runtime-plugin.ts +144 -0
  288. package/src/syntax-style.test.ts +841 -0
  289. package/src/syntax-style.ts +264 -0
  290. package/src/testing/README.md +210 -0
  291. package/src/testing/capture-spans.test.ts +194 -0
  292. package/src/testing/integration.test.ts +276 -0
  293. package/src/testing/manual-clock.ts +106 -0
  294. package/src/testing/mock-keys.test.ts +1356 -0
  295. package/src/testing/mock-keys.ts +449 -0
  296. package/src/testing/mock-mouse.test.ts +218 -0
  297. package/src/testing/mock-mouse.ts +247 -0
  298. package/src/testing/mock-tree-sitter-client.ts +73 -0
  299. package/src/testing/spy.ts +13 -0
  300. package/src/testing/test-recorder.test.ts +415 -0
  301. package/src/testing/test-recorder.ts +145 -0
  302. package/src/testing/test-renderer.ts +116 -0
  303. package/src/testing.ts +7 -0
  304. package/src/tests/__snapshots__/absolute-positioning.snapshot.test.ts.snap +481 -0
  305. package/src/tests/__snapshots__/renderable.snapshot.test.ts.snap +19 -0
  306. package/src/tests/__snapshots__/scrollbox.test.ts.snap +29 -0
  307. package/src/tests/absolute-positioning.snapshot.test.ts +638 -0
  308. package/src/tests/allocator-stats.test.ts +38 -0
  309. package/src/tests/destroy-during-render.test.ts +200 -0
  310. package/src/tests/hover-cursor.test.ts +98 -0
  311. package/src/tests/native-span-feed-async.test.ts +173 -0
  312. package/src/tests/native-span-feed-close.test.ts +120 -0
  313. package/src/tests/native-span-feed-coverage.test.ts +227 -0
  314. package/src/tests/native-span-feed-edge-cases.test.ts +352 -0
  315. package/src/tests/native-span-feed-use-after-free.test.ts +45 -0
  316. package/src/tests/opacity.test.ts +123 -0
  317. package/src/tests/renderable.snapshot.test.ts +524 -0
  318. package/src/tests/renderable.test.ts +1281 -0
  319. package/src/tests/renderer.console-startup.test.ts +65 -0
  320. package/src/tests/renderer.control.test.ts +364 -0
  321. package/src/tests/renderer.core-slot-binding.test.ts +952 -0
  322. package/src/tests/renderer.cursor.test.ts +26 -0
  323. package/src/tests/renderer.destroy-during-render.test.ts +110 -0
  324. package/src/tests/renderer.focus-restore.test.ts +228 -0
  325. package/src/tests/renderer.focus.test.ts +251 -0
  326. package/src/tests/renderer.idle.test.ts +219 -0
  327. package/src/tests/renderer.input.test.ts +2145 -0
  328. package/src/tests/renderer.kitty-flags.test.ts +195 -0
  329. package/src/tests/renderer.mouse.test.ts +1269 -0
  330. package/src/tests/renderer.palette.test.ts +629 -0
  331. package/src/tests/renderer.selection.test.ts +49 -0
  332. package/src/tests/renderer.slot-registry.test.ts +649 -0
  333. package/src/tests/renderer.useMouse.test.ts +50 -0
  334. package/src/tests/runtime-plugin-support.fixture.ts +11 -0
  335. package/src/tests/runtime-plugin-support.test.ts +28 -0
  336. package/src/tests/runtime-plugin.fixture.ts +40 -0
  337. package/src/tests/runtime-plugin.test.ts +190 -0
  338. package/src/tests/scrollbox-culling-bug.test.ts +114 -0
  339. package/src/tests/scrollbox-hitgrid-resize.test.ts +136 -0
  340. package/src/tests/scrollbox-hitgrid.test.ts +909 -0
  341. package/src/tests/scrollbox.test.ts +1530 -0
  342. package/src/tests/wrap-resize-perf.test.ts +229 -0
  343. package/src/tests/yoga-setters.test.ts +921 -0
  344. package/src/text-buffer-view.test.ts +705 -0
  345. package/src/text-buffer-view.ts +189 -0
  346. package/src/text-buffer.test.ts +347 -0
  347. package/src/text-buffer.ts +250 -0
  348. package/src/types.ts +152 -0
  349. package/src/utils.ts +88 -0
  350. package/src/zig/ansi.zig +268 -0
  351. package/src/zig/bench/README.md +50 -0
  352. package/src/zig/bench/buffer-draw-text-buffer_bench.zig +887 -0
  353. package/src/zig/bench/edit-buffer_bench.zig +476 -0
  354. package/src/zig/bench/native-span-feed_bench.zig +100 -0
  355. package/src/zig/bench/rope-markers_bench.zig +713 -0
  356. package/src/zig/bench/rope_bench.zig +514 -0
  357. package/src/zig/bench/styled-text_bench.zig +470 -0
  358. package/src/zig/bench/text-buffer-coords_bench.zig +362 -0
  359. package/src/zig/bench/text-buffer-view_bench.zig +459 -0
  360. package/src/zig/bench/text-chunk-graphemes_bench.zig +273 -0
  361. package/src/zig/bench/utf8_bench.zig +799 -0
  362. package/src/zig/bench-utils.zig +431 -0
  363. package/src/zig/bench.zig +217 -0
  364. package/src/zig/buffer.zig +2223 -0
  365. package/src/zig/build.zig +289 -0
  366. package/src/zig/build.zig.zon +16 -0
  367. package/src/zig/edit-buffer.zig +825 -0
  368. package/src/zig/editor-view.zig +802 -0
  369. package/src/zig/event-bus.zig +13 -0
  370. package/src/zig/event-emitter.zig +65 -0
  371. package/src/zig/file-logger.zig +92 -0
  372. package/src/zig/grapheme.zig +599 -0
  373. package/src/zig/lib.zig +1834 -0
  374. package/src/zig/link.zig +333 -0
  375. package/src/zig/logger.zig +43 -0
  376. package/src/zig/mem-registry.zig +125 -0
  377. package/src/zig/native-span-feed-bench-lib.zig +7 -0
  378. package/src/zig/native-span-feed.zig +708 -0
  379. package/src/zig/renderer.zig +1386 -0
  380. package/src/zig/rope.zig +1220 -0
  381. package/src/zig/syntax-style.zig +161 -0
  382. package/src/zig/terminal.zig +975 -0
  383. package/src/zig/test.zig +70 -0
  384. package/src/zig/tests/README.md +18 -0
  385. package/src/zig/tests/buffer_test.zig +2526 -0
  386. package/src/zig/tests/edit-buffer-history_test.zig +271 -0
  387. package/src/zig/tests/edit-buffer_test.zig +1689 -0
  388. package/src/zig/tests/editor-view_test.zig +3299 -0
  389. package/src/zig/tests/event-emitter_test.zig +249 -0
  390. package/src/zig/tests/grapheme_test.zig +1304 -0
  391. package/src/zig/tests/link_test.zig +190 -0
  392. package/src/zig/tests/mem-registry_test.zig +473 -0
  393. package/src/zig/tests/memory_leak_regression_test.zig +159 -0
  394. package/src/zig/tests/native-span-feed_test.zig +1264 -0
  395. package/src/zig/tests/renderer_test.zig +1010 -0
  396. package/src/zig/tests/rope-nested_test.zig +712 -0
  397. package/src/zig/tests/rope_fuzz_test.zig +238 -0
  398. package/src/zig/tests/rope_test.zig +2362 -0
  399. package/src/zig/tests/segment-merge.test.zig +148 -0
  400. package/src/zig/tests/syntax-style_test.zig +557 -0
  401. package/src/zig/tests/terminal_test.zig +719 -0
  402. package/src/zig/tests/text-buffer-drawing_test.zig +3237 -0
  403. package/src/zig/tests/text-buffer-highlights_test.zig +666 -0
  404. package/src/zig/tests/text-buffer-iterators_test.zig +776 -0
  405. package/src/zig/tests/text-buffer-segment_test.zig +320 -0
  406. package/src/zig/tests/text-buffer-selection_test.zig +1035 -0
  407. package/src/zig/tests/text-buffer-selection_viewport_test.zig +358 -0
  408. package/src/zig/tests/text-buffer-view_test.zig +3649 -0
  409. package/src/zig/tests/text-buffer_test.zig +2191 -0
  410. package/src/zig/tests/unicode-width-map.zon +3909 -0
  411. package/src/zig/tests/utf8_no_zwj_test.zig +260 -0
  412. package/src/zig/tests/utf8_test.zig +4057 -0
  413. package/src/zig/tests/utf8_wcwidth_cursor_test.zig +267 -0
  414. package/src/zig/tests/utf8_wcwidth_test.zig +357 -0
  415. package/src/zig/tests/word-wrap-editing_test.zig +498 -0
  416. package/src/zig/tests/wrap-cache-perf_test.zig +113 -0
  417. package/src/zig/text-buffer-iterators.zig +499 -0
  418. package/src/zig/text-buffer-segment.zig +404 -0
  419. package/src/zig/text-buffer-view.zig +1371 -0
  420. package/src/zig/text-buffer.zig +1180 -0
  421. package/src/zig/utf8.zig +1948 -0
  422. package/src/zig/utils.zig +9 -0
  423. package/src/zig-structs.ts +261 -0
  424. package/src/zig.ts +3843 -0
  425. package/tsconfig.build.json +22 -0
  426. package/tsconfig.json +28 -0
  427. package/3d/SpriteResourceManager.d.ts +0 -74
  428. package/3d/SpriteUtils.d.ts +0 -13
  429. package/3d/TextureUtils.d.ts +0 -24
  430. package/3d/ThreeRenderable.d.ts +0 -40
  431. package/3d/WGPURenderer.d.ts +0 -61
  432. package/3d/animation/ExplodingSpriteEffect.d.ts +0 -71
  433. package/3d/animation/PhysicsExplodingSpriteEffect.d.ts +0 -76
  434. package/3d/animation/SpriteAnimator.d.ts +0 -124
  435. package/3d/animation/SpriteParticleGenerator.d.ts +0 -62
  436. package/3d/canvas.d.ts +0 -44
  437. package/3d/index.d.ts +0 -12
  438. package/3d/physics/PlanckPhysicsAdapter.d.ts +0 -19
  439. package/3d/physics/RapierPhysicsAdapter.d.ts +0 -19
  440. package/3d/physics/physics-interface.d.ts +0 -27
  441. package/3d.d.ts +0 -2
  442. package/3d.js +0 -34042
  443. package/3d.js.map +0 -155
  444. package/LICENSE +0 -21
  445. package/NativeSpanFeed.d.ts +0 -41
  446. package/Renderable.d.ts +0 -334
  447. package/animation/Timeline.d.ts +0 -126
  448. package/ansi.d.ts +0 -13
  449. package/buffer.d.ts +0 -107
  450. package/console.d.ts +0 -143
  451. package/edit-buffer.d.ts +0 -98
  452. package/editor-view.d.ts +0 -73
  453. package/index-e4hzc2j2.js +0 -113
  454. package/index-e4hzc2j2.js.map +0 -10
  455. package/index-nkrr8a4c.js +0 -18415
  456. package/index-nkrr8a4c.js.map +0 -64
  457. package/index-nyw5p3ep.js +0 -12619
  458. package/index-nyw5p3ep.js.map +0 -43
  459. package/index.d.ts +0 -21
  460. package/index.js +0 -430
  461. package/index.js.map +0 -9
  462. package/lib/KeyHandler.d.ts +0 -61
  463. package/lib/RGBA.d.ts +0 -25
  464. package/lib/ascii.font.d.ts +0 -508
  465. package/lib/border.d.ts +0 -49
  466. package/lib/bunfs.d.ts +0 -7
  467. package/lib/clipboard.d.ts +0 -17
  468. package/lib/clock.d.ts +0 -15
  469. package/lib/data-paths.d.ts +0 -26
  470. package/lib/debounce.d.ts +0 -42
  471. package/lib/detect-links.d.ts +0 -6
  472. package/lib/env.d.ts +0 -42
  473. package/lib/extmarks-history.d.ts +0 -17
  474. package/lib/extmarks.d.ts +0 -89
  475. package/lib/hast-styled-text.d.ts +0 -17
  476. package/lib/index.d.ts +0 -21
  477. package/lib/keymapping.d.ts +0 -25
  478. package/lib/objects-in-viewport.d.ts +0 -24
  479. package/lib/output.capture.d.ts +0 -24
  480. package/lib/parse.keypress-kitty.d.ts +0 -2
  481. package/lib/parse.keypress.d.ts +0 -26
  482. package/lib/parse.mouse.d.ts +0 -30
  483. package/lib/paste.d.ts +0 -7
  484. package/lib/queue.d.ts +0 -15
  485. package/lib/renderable.validations.d.ts +0 -12
  486. package/lib/scroll-acceleration.d.ts +0 -43
  487. package/lib/selection.d.ts +0 -63
  488. package/lib/singleton.d.ts +0 -7
  489. package/lib/stdin-parser.d.ts +0 -76
  490. package/lib/styled-text.d.ts +0 -63
  491. package/lib/terminal-capability-detection.d.ts +0 -30
  492. package/lib/terminal-palette.d.ts +0 -50
  493. package/lib/tree-sitter/assets/update.d.ts +0 -11
  494. package/lib/tree-sitter/client.d.ts +0 -47
  495. package/lib/tree-sitter/default-parsers.d.ts +0 -2
  496. package/lib/tree-sitter/download-utils.d.ts +0 -21
  497. package/lib/tree-sitter/index.d.ts +0 -8
  498. package/lib/tree-sitter/parser.worker.d.ts +0 -1
  499. package/lib/tree-sitter/parsers-config.d.ts +0 -38
  500. package/lib/tree-sitter/resolve-ft.d.ts +0 -2
  501. package/lib/tree-sitter/types.d.ts +0 -81
  502. package/lib/tree-sitter-styled-text.d.ts +0 -14
  503. package/lib/validate-dir-name.d.ts +0 -1
  504. package/lib/yoga.options.d.ts +0 -32
  505. package/parser.worker.js +0 -869
  506. package/parser.worker.js.map +0 -12
  507. package/plugins/core-slot.d.ts +0 -72
  508. package/plugins/registry.d.ts +0 -38
  509. package/plugins/types.d.ts +0 -34
  510. package/post/filters.d.ts +0 -105
  511. package/renderables/ASCIIFont.d.ts +0 -52
  512. package/renderables/Box.d.ts +0 -72
  513. package/renderables/Code.d.ts +0 -78
  514. package/renderables/Diff.d.ts +0 -142
  515. package/renderables/EditBufferRenderable.d.ts +0 -162
  516. package/renderables/FrameBuffer.d.ts +0 -16
  517. package/renderables/Input.d.ts +0 -67
  518. package/renderables/LineNumberRenderable.d.ts +0 -74
  519. package/renderables/Markdown.d.ts +0 -173
  520. package/renderables/ScrollBar.d.ts +0 -77
  521. package/renderables/ScrollBox.d.ts +0 -124
  522. package/renderables/Select.d.ts +0 -115
  523. package/renderables/Slider.d.ts +0 -44
  524. package/renderables/TabSelect.d.ts +0 -96
  525. package/renderables/Text.d.ts +0 -36
  526. package/renderables/TextBufferRenderable.d.ts +0 -105
  527. package/renderables/TextNode.d.ts +0 -91
  528. package/renderables/TextTable.d.ts +0 -140
  529. package/renderables/Textarea.d.ts +0 -114
  530. package/renderables/TimeToFirstDraw.d.ts +0 -24
  531. package/renderables/__tests__/renderable-test-utils.d.ts +0 -12
  532. package/renderables/composition/VRenderable.d.ts +0 -16
  533. package/renderables/composition/constructs.d.ts +0 -35
  534. package/renderables/composition/vnode.d.ts +0 -46
  535. package/renderables/index.d.ts +0 -22
  536. package/renderables/markdown-parser.d.ts +0 -10
  537. package/renderer.d.ts +0 -388
  538. package/runtime-plugin-support.d.ts +0 -3
  539. package/runtime-plugin-support.js +0 -29
  540. package/runtime-plugin-support.js.map +0 -10
  541. package/runtime-plugin.d.ts +0 -11
  542. package/runtime-plugin.js +0 -16
  543. package/runtime-plugin.js.map +0 -9
  544. package/syntax-style.d.ts +0 -54
  545. package/testing/manual-clock.d.ts +0 -16
  546. package/testing/mock-keys.d.ts +0 -81
  547. package/testing/mock-mouse.d.ts +0 -38
  548. package/testing/mock-tree-sitter-client.d.ts +0 -23
  549. package/testing/spy.d.ts +0 -7
  550. package/testing/test-recorder.d.ts +0 -61
  551. package/testing/test-renderer.d.ts +0 -23
  552. package/testing.d.ts +0 -6
  553. package/testing.js +0 -675
  554. package/testing.js.map +0 -15
  555. package/text-buffer-view.d.ts +0 -42
  556. package/text-buffer.d.ts +0 -67
  557. package/types.d.ts +0 -131
  558. package/utils.d.ts +0 -14
  559. package/zig-structs.d.ts +0 -155
  560. package/zig.d.ts +0 -351
  561. /package/{assets → src/lib/tree-sitter/assets}/javascript/highlights.scm +0 -0
  562. /package/{assets → src/lib/tree-sitter/assets}/javascript/tree-sitter-javascript.wasm +0 -0
  563. /package/{assets → src/lib/tree-sitter/assets}/markdown/highlights.scm +0 -0
  564. /package/{assets → src/lib/tree-sitter/assets}/markdown/injections.scm +0 -0
  565. /package/{assets → src/lib/tree-sitter/assets}/markdown/tree-sitter-markdown.wasm +0 -0
  566. /package/{assets → src/lib/tree-sitter/assets}/markdown_inline/highlights.scm +0 -0
  567. /package/{assets → src/lib/tree-sitter/assets}/markdown_inline/tree-sitter-markdown_inline.wasm +0 -0
  568. /package/{assets → src/lib/tree-sitter/assets}/typescript/highlights.scm +0 -0
  569. /package/{assets → src/lib/tree-sitter/assets}/typescript/tree-sitter-typescript.wasm +0 -0
  570. /package/{assets → src/lib/tree-sitter/assets}/zig/highlights.scm +0 -0
  571. /package/{assets → src/lib/tree-sitter/assets}/zig/tree-sitter-zig.wasm +0 -0
@@ -0,0 +1,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 override 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
+ })