@fairyhunter13/opentui-core 0.1.113 → 0.1.114

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 (591) 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 +144 -0
  7. package/package.json +62 -53
  8. package/scripts/build.ts +400 -0
  9. package/scripts/publish.ts +60 -0
  10. package/src/3d/SpriteResourceManager.ts +286 -0
  11. package/src/3d/SpriteUtils.ts +70 -0
  12. package/src/3d/TextureUtils.ts +196 -0
  13. package/src/3d/ThreeRenderable.ts +197 -0
  14. package/src/3d/WGPURenderer.ts +294 -0
  15. package/src/3d/animation/ExplodingSpriteEffect.ts +513 -0
  16. package/src/3d/animation/PhysicsExplodingSpriteEffect.ts +429 -0
  17. package/src/3d/animation/SpriteAnimator.ts +633 -0
  18. package/src/3d/animation/SpriteParticleGenerator.ts +435 -0
  19. package/src/3d/canvas.ts +464 -0
  20. package/src/3d/index.ts +12 -0
  21. package/src/3d/physics/PlanckPhysicsAdapter.ts +72 -0
  22. package/src/3d/physics/RapierPhysicsAdapter.ts +66 -0
  23. package/src/3d/physics/physics-interface.ts +31 -0
  24. package/src/3d/shaders/supersampling.wgsl +201 -0
  25. package/src/3d.ts +3 -0
  26. package/src/NativeSpanFeed.ts +300 -0
  27. package/src/Renderable.ts +1704 -0
  28. package/src/__snapshots__/buffer.test.ts.snap +28 -0
  29. package/src/animation/Timeline.test.ts +2709 -0
  30. package/src/animation/Timeline.ts +598 -0
  31. package/src/ansi.ts +18 -0
  32. package/src/benchmark/attenuation-benchmark.ts +81 -0
  33. package/src/benchmark/colormatrix-benchmark.ts +128 -0
  34. package/src/benchmark/gain-benchmark.ts +80 -0
  35. package/src/benchmark/latest-all-bench-run.json +707 -0
  36. package/src/benchmark/latest-async-bench-run.json +336 -0
  37. package/src/benchmark/latest-default-bench-run.json +657 -0
  38. package/src/benchmark/latest-large-bench-run.json +707 -0
  39. package/src/benchmark/latest-quick-bench-run.json +207 -0
  40. package/src/benchmark/markdown-benchmark.ts +1796 -0
  41. package/src/benchmark/native-span-feed-async-benchmark.ts +355 -0
  42. package/src/benchmark/native-span-feed-benchmark.md +56 -0
  43. package/src/benchmark/native-span-feed-benchmark.ts +596 -0
  44. package/src/benchmark/native-span-feed-compare.ts +280 -0
  45. package/src/benchmark/renderer-benchmark.ts +754 -0
  46. package/src/benchmark/text-table-benchmark.ts +948 -0
  47. package/src/buffer.test.ts +291 -0
  48. package/src/buffer.ts +554 -0
  49. package/src/console.test.ts +612 -0
  50. package/src/console.ts +1254 -0
  51. package/src/edit-buffer.test.ts +1769 -0
  52. package/src/edit-buffer.ts +411 -0
  53. package/src/editor-view.test.ts +1032 -0
  54. package/src/editor-view.ts +284 -0
  55. package/src/examples/ascii-font-selection-demo.ts +245 -0
  56. package/src/examples/assets/Water_2_M_Normal.jpg +0 -0
  57. package/src/examples/assets/concrete.png +0 -0
  58. package/src/examples/assets/crate.png +0 -0
  59. package/src/examples/assets/crate_emissive.png +0 -0
  60. package/src/examples/assets/forrest_background.png +0 -0
  61. package/src/examples/assets/hast-example.json +1018 -0
  62. package/src/examples/assets/heart.png +0 -0
  63. package/src/examples/assets/main_char_heavy_attack.png +0 -0
  64. package/src/examples/assets/main_char_idle.png +0 -0
  65. package/src/examples/assets/main_char_jump_end.png +0 -0
  66. package/src/examples/assets/main_char_jump_landing.png +0 -0
  67. package/src/examples/assets/main_char_jump_start.png +0 -0
  68. package/src/examples/assets/main_char_run_loop.png +0 -0
  69. package/src/examples/assets/roughness_map.jpg +0 -0
  70. package/src/examples/build.ts +115 -0
  71. package/src/examples/code-demo.ts +924 -0
  72. package/src/examples/console-demo.ts +358 -0
  73. package/src/examples/core-plugin-slots-demo.ts +759 -0
  74. package/src/examples/diff-demo.ts +701 -0
  75. package/src/examples/draggable-three-demo.ts +259 -0
  76. package/src/examples/editor-demo.ts +322 -0
  77. package/src/examples/extmarks-demo.ts +196 -0
  78. package/src/examples/focus-restore-demo.ts +310 -0
  79. package/src/examples/fonts.ts +245 -0
  80. package/src/examples/fractal-shader-demo.ts +268 -0
  81. package/src/examples/framebuffer-demo.ts +674 -0
  82. package/src/examples/full-unicode-demo.ts +241 -0
  83. package/src/examples/golden-star-demo.ts +933 -0
  84. package/src/examples/grayscale-buffer-demo.ts +249 -0
  85. package/src/examples/hast-syntax-highlighting-demo.ts +129 -0
  86. package/src/examples/index.ts +926 -0
  87. package/src/examples/input-demo.ts +377 -0
  88. package/src/examples/input-select-layout-demo.ts +425 -0
  89. package/src/examples/install.sh +143 -0
  90. package/src/examples/keypress-debug-demo.ts +452 -0
  91. package/src/examples/lib/HexList.ts +122 -0
  92. package/src/examples/lib/PaletteGrid.ts +125 -0
  93. package/src/examples/lib/standalone-keys.ts +25 -0
  94. package/src/examples/lib/tab-controller.ts +243 -0
  95. package/src/examples/lights-phong-demo.ts +290 -0
  96. package/src/examples/link-demo.ts +220 -0
  97. package/src/examples/live-state-demo.ts +480 -0
  98. package/src/examples/markdown-demo.ts +725 -0
  99. package/src/examples/mouse-interaction-demo.ts +428 -0
  100. package/src/examples/nested-zindex-demo.ts +357 -0
  101. package/src/examples/opacity-example.ts +235 -0
  102. package/src/examples/opentui-demo.ts +1057 -0
  103. package/src/examples/physx-planck-2d-demo.ts +623 -0
  104. package/src/examples/physx-rapier-2d-demo.ts +655 -0
  105. package/src/examples/relative-positioning-demo.ts +323 -0
  106. package/src/examples/scroll-example.ts +214 -0
  107. package/src/examples/scrollbox-mouse-test.ts +112 -0
  108. package/src/examples/scrollbox-overlay-hit-test.ts +206 -0
  109. package/src/examples/select-demo.ts +237 -0
  110. package/src/examples/shader-cube-demo.ts +1015 -0
  111. package/src/examples/simple-layout-example.ts +591 -0
  112. package/src/examples/slider-demo.ts +617 -0
  113. package/src/examples/split-mode-demo.ts +453 -0
  114. package/src/examples/sprite-animation-demo.ts +443 -0
  115. package/src/examples/sprite-particle-generator-demo.ts +486 -0
  116. package/src/examples/static-sprite-demo.ts +193 -0
  117. package/src/examples/sticky-scroll-example.ts +308 -0
  118. package/src/examples/styled-text-demo.ts +282 -0
  119. package/src/examples/tab-select-demo.ts +219 -0
  120. package/src/examples/terminal-title.ts +29 -0
  121. package/src/examples/terminal.ts +305 -0
  122. package/src/examples/text-node-demo.ts +416 -0
  123. package/src/examples/text-selection-demo.ts +377 -0
  124. package/src/examples/text-table-demo.ts +503 -0
  125. package/src/examples/text-truncation-demo.ts +481 -0
  126. package/src/examples/text-wrap.ts +757 -0
  127. package/src/examples/texture-loading-demo.ts +259 -0
  128. package/src/examples/timeline-example.ts +670 -0
  129. package/src/examples/transparency-demo.ts +400 -0
  130. package/src/examples/vnode-composition-demo.ts +404 -0
  131. package/src/examples/wide-grapheme-overlay-demo.ts +280 -0
  132. package/src/index.ts +24 -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 +170 -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 +35 -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 +317 -0
  168. package/src/lib/keymapping.ts +115 -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 +2290 -0
  187. package/src/lib/stdin-parser.ts +1810 -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 +334 -0
  195. package/src/lib/tree-sitter/assets.d.ts +9 -0
  196. package/src/lib/tree-sitter/cache.test.ts +273 -0
  197. package/src/lib/tree-sitter/client.test.ts +1165 -0
  198. package/src/lib/tree-sitter/client.ts +607 -0
  199. package/src/lib/tree-sitter/default-parsers.ts +86 -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 +1042 -0
  203. package/src/lib/tree-sitter/parsers-config.ts +81 -0
  204. package/src/lib/tree-sitter/resolve-ft.test.ts +55 -0
  205. package/src/lib/tree-sitter/resolve-ft.ts +189 -0
  206. package/src/lib/tree-sitter/types.ts +82 -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 +402 -0
  214. package/src/plugins/types.ts +46 -0
  215. package/src/post/effects.ts +930 -0
  216. package/src/post/filters.ts +489 -0
  217. package/src/post/matrices.ts +288 -0
  218. package/src/renderables/ASCIIFont.ts +219 -0
  219. package/src/renderables/Box.test.ts +205 -0
  220. package/src/renderables/Box.ts +326 -0
  221. package/src/renderables/Code.test.ts +2062 -0
  222. package/src/renderables/Code.ts +357 -0
  223. package/src/renderables/Diff.regression.test.ts +226 -0
  224. package/src/renderables/Diff.test.ts +3101 -0
  225. package/src/renderables/Diff.ts +1211 -0
  226. package/src/renderables/EditBufferRenderable.test.ts +288 -0
  227. package/src/renderables/EditBufferRenderable.ts +1166 -0
  228. package/src/renderables/FrameBuffer.ts +47 -0
  229. package/src/renderables/Input.test.ts +1228 -0
  230. package/src/renderables/Input.ts +247 -0
  231. package/src/renderables/LineNumberRenderable.ts +724 -0
  232. package/src/renderables/Markdown.ts +1393 -0
  233. package/src/renderables/ScrollBar.ts +422 -0
  234. package/src/renderables/ScrollBox.ts +883 -0
  235. package/src/renderables/Select.test.ts +1033 -0
  236. package/src/renderables/Select.ts +524 -0
  237. package/src/renderables/Slider.test.ts +456 -0
  238. package/src/renderables/Slider.ts +342 -0
  239. package/src/renderables/TabSelect.test.ts +197 -0
  240. package/src/renderables/TabSelect.ts +455 -0
  241. package/src/renderables/Text.selection-buffer.test.ts +123 -0
  242. package/src/renderables/Text.test.ts +2660 -0
  243. package/src/renderables/Text.ts +147 -0
  244. package/src/renderables/TextBufferRenderable.ts +518 -0
  245. package/src/renderables/TextNode.test.ts +1058 -0
  246. package/src/renderables/TextNode.ts +325 -0
  247. package/src/renderables/TextTable.test.ts +1421 -0
  248. package/src/renderables/TextTable.ts +1344 -0
  249. package/src/renderables/Textarea.ts +430 -0
  250. package/src/renderables/TimeToFirstDraw.ts +89 -0
  251. package/src/renderables/__snapshots__/Code.test.ts.snap +13 -0
  252. package/src/renderables/__snapshots__/Diff.test.ts.snap +785 -0
  253. package/src/renderables/__snapshots__/Text.test.ts.snap +421 -0
  254. package/src/renderables/__snapshots__/TextTable.test.ts.snap +215 -0
  255. package/src/renderables/__tests__/LineNumberRenderable.scrollbox-simple.test.ts +144 -0
  256. package/src/renderables/__tests__/LineNumberRenderable.scrollbox.test.ts +816 -0
  257. package/src/renderables/__tests__/LineNumberRenderable.test.ts +1865 -0
  258. package/src/renderables/__tests__/LineNumberRenderable.wrapping.test.ts +85 -0
  259. package/src/renderables/__tests__/Markdown.code-colors.test.ts +242 -0
  260. package/src/renderables/__tests__/Markdown.test.ts +2518 -0
  261. package/src/renderables/__tests__/MultiRenderable.selection.test.ts +87 -0
  262. package/src/renderables/__tests__/Textarea.buffer.test.ts +682 -0
  263. package/src/renderables/__tests__/Textarea.destroyed-events.test.ts +675 -0
  264. package/src/renderables/__tests__/Textarea.editing.test.ts +2041 -0
  265. package/src/renderables/__tests__/Textarea.error-handling.test.ts +35 -0
  266. package/src/renderables/__tests__/Textarea.events.test.ts +738 -0
  267. package/src/renderables/__tests__/Textarea.highlights.test.ts +590 -0
  268. package/src/renderables/__tests__/Textarea.keybinding.test.ts +3149 -0
  269. package/src/renderables/__tests__/Textarea.paste.test.ts +357 -0
  270. package/src/renderables/__tests__/Textarea.rendering.test.ts +1866 -0
  271. package/src/renderables/__tests__/Textarea.scroll.test.ts +733 -0
  272. package/src/renderables/__tests__/Textarea.selection.test.ts +1590 -0
  273. package/src/renderables/__tests__/Textarea.stress.test.ts +670 -0
  274. package/src/renderables/__tests__/Textarea.undo-redo.test.ts +383 -0
  275. package/src/renderables/__tests__/Textarea.visual-lines.test.ts +310 -0
  276. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.code.test.ts.snap +221 -0
  277. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox-simple.test.ts.snap +89 -0
  278. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox.test.ts.snap +457 -0
  279. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.test.ts.snap +158 -0
  280. package/src/renderables/__tests__/__snapshots__/Textarea.rendering.test.ts.snap +387 -0
  281. package/src/renderables/__tests__/markdown-parser.test.ts +217 -0
  282. package/src/renderables/__tests__/renderable-test-utils.ts +60 -0
  283. package/src/renderables/composition/README.md +8 -0
  284. package/src/renderables/composition/VRenderable.ts +32 -0
  285. package/src/renderables/composition/constructs.ts +127 -0
  286. package/src/renderables/composition/vnode.ts +289 -0
  287. package/src/renderables/index.ts +23 -0
  288. package/src/renderables/markdown-parser.ts +66 -0
  289. package/src/renderer.ts +2681 -0
  290. package/src/runtime-plugin-support.ts +39 -0
  291. package/src/runtime-plugin.ts +615 -0
  292. package/src/syntax-style.test.ts +841 -0
  293. package/src/syntax-style.ts +257 -0
  294. package/src/testing/README.md +210 -0
  295. package/src/testing/capture-spans.test.ts +194 -0
  296. package/src/testing/integration.test.ts +276 -0
  297. package/src/testing/manual-clock.ts +117 -0
  298. package/src/testing/mock-keys.test.ts +1378 -0
  299. package/src/testing/mock-keys.ts +457 -0
  300. package/src/testing/mock-mouse.test.ts +218 -0
  301. package/src/testing/mock-mouse.ts +247 -0
  302. package/src/testing/mock-tree-sitter-client.ts +73 -0
  303. package/src/testing/spy.ts +13 -0
  304. package/src/testing/test-recorder.test.ts +415 -0
  305. package/src/testing/test-recorder.ts +145 -0
  306. package/src/testing/test-renderer.ts +132 -0
  307. package/src/testing.ts +7 -0
  308. package/src/tests/__snapshots__/absolute-positioning.snapshot.test.ts.snap +481 -0
  309. package/src/tests/__snapshots__/renderable.snapshot.test.ts.snap +19 -0
  310. package/src/tests/__snapshots__/scrollbox.test.ts.snap +29 -0
  311. package/src/tests/absolute-positioning.snapshot.test.ts +638 -0
  312. package/src/tests/allocator-stats.test.ts +38 -0
  313. package/src/tests/destroy-during-render.test.ts +200 -0
  314. package/src/tests/destroy-on-exit.fixture.ts +36 -0
  315. package/src/tests/destroy-on-exit.test.ts +41 -0
  316. package/src/tests/hover-cursor.test.ts +98 -0
  317. package/src/tests/native-span-feed-async.test.ts +173 -0
  318. package/src/tests/native-span-feed-close.test.ts +120 -0
  319. package/src/tests/native-span-feed-coverage.test.ts +227 -0
  320. package/src/tests/native-span-feed-edge-cases.test.ts +352 -0
  321. package/src/tests/native-span-feed-use-after-free.test.ts +45 -0
  322. package/src/tests/opacity.test.ts +123 -0
  323. package/src/tests/renderable.snapshot.test.ts +524 -0
  324. package/src/tests/renderable.test.ts +1281 -0
  325. package/src/tests/renderer.clock.test.ts +158 -0
  326. package/src/tests/renderer.console-startup.test.ts +185 -0
  327. package/src/tests/renderer.control.test.ts +425 -0
  328. package/src/tests/renderer.core-slot-binding.test.ts +952 -0
  329. package/src/tests/renderer.cursor.test.ts +26 -0
  330. package/src/tests/renderer.destroy-during-render.test.ts +147 -0
  331. package/src/tests/renderer.focus-restore.test.ts +257 -0
  332. package/src/tests/renderer.focus.test.ts +294 -0
  333. package/src/tests/renderer.idle.test.ts +219 -0
  334. package/src/tests/renderer.input.test.ts +2237 -0
  335. package/src/tests/renderer.kitty-flags.test.ts +195 -0
  336. package/src/tests/renderer.mouse.test.ts +1274 -0
  337. package/src/tests/renderer.palette.test.ts +629 -0
  338. package/src/tests/renderer.selection.test.ts +49 -0
  339. package/src/tests/renderer.slot-registry.test.ts +684 -0
  340. package/src/tests/renderer.useMouse.test.ts +47 -0
  341. package/src/tests/runtime-plugin-node-modules-cycle.fixture.ts +76 -0
  342. package/src/tests/runtime-plugin-node-modules-mjs.fixture.ts +43 -0
  343. package/src/tests/runtime-plugin-node-modules-no-bare-rewrite.fixture.ts +67 -0
  344. package/src/tests/runtime-plugin-node-modules-package-type-cache.fixture.ts +72 -0
  345. package/src/tests/runtime-plugin-node-modules-runtime-specifier.fixture.ts +44 -0
  346. package/src/tests/runtime-plugin-node-modules-scoped-package-bare-rewrite.fixture.ts +85 -0
  347. package/src/tests/runtime-plugin-path-alias.fixture.ts +43 -0
  348. package/src/tests/runtime-plugin-resolve-roots.fixture.ts +65 -0
  349. package/src/tests/runtime-plugin-support.fixture.ts +11 -0
  350. package/src/tests/runtime-plugin-support.test.ts +19 -0
  351. package/src/tests/runtime-plugin-windows-file-url.fixture.ts +30 -0
  352. package/src/tests/runtime-plugin.fixture.ts +40 -0
  353. package/src/tests/runtime-plugin.test.ts +354 -0
  354. package/src/tests/scrollbox-culling-bug.test.ts +114 -0
  355. package/src/tests/scrollbox-hitgrid-resize.test.ts +136 -0
  356. package/src/tests/scrollbox-hitgrid.test.ts +909 -0
  357. package/src/tests/scrollbox.test.ts +1530 -0
  358. package/src/tests/wrap-resize-perf.test.ts +276 -0
  359. package/src/tests/yoga-setters.test.ts +921 -0
  360. package/src/text-buffer-view.test.ts +705 -0
  361. package/src/text-buffer-view.ts +189 -0
  362. package/src/text-buffer.test.ts +347 -0
  363. package/src/text-buffer.ts +250 -0
  364. package/src/types.ts +161 -0
  365. package/src/utils.ts +88 -0
  366. package/src/zig/ansi.zig +268 -0
  367. package/src/zig/bench/README.md +50 -0
  368. package/src/zig/bench/buffer-draw-text-buffer_bench.zig +887 -0
  369. package/src/zig/bench/edit-buffer_bench.zig +476 -0
  370. package/src/zig/bench/native-span-feed_bench.zig +100 -0
  371. package/src/zig/bench/rope-markers_bench.zig +713 -0
  372. package/src/zig/bench/rope_bench.zig +514 -0
  373. package/src/zig/bench/styled-text_bench.zig +470 -0
  374. package/src/zig/bench/text-buffer-coords_bench.zig +362 -0
  375. package/src/zig/bench/text-buffer-view_bench.zig +459 -0
  376. package/src/zig/bench/text-chunk-graphemes_bench.zig +273 -0
  377. package/src/zig/bench/utf8_bench.zig +799 -0
  378. package/src/zig/bench-utils.zig +431 -0
  379. package/src/zig/bench.zig +217 -0
  380. package/src/zig/buffer-methods.zig +211 -0
  381. package/src/zig/buffer.zig +2281 -0
  382. package/src/zig/build.zig +289 -0
  383. package/src/zig/build.zig.zon +16 -0
  384. package/src/zig/edit-buffer.zig +825 -0
  385. package/src/zig/editor-view.zig +802 -0
  386. package/src/zig/event-bus.zig +13 -0
  387. package/src/zig/event-emitter.zig +65 -0
  388. package/src/zig/file-logger.zig +92 -0
  389. package/src/zig/grapheme.zig +599 -0
  390. package/src/zig/lib.zig +1854 -0
  391. package/src/zig/link.zig +333 -0
  392. package/src/zig/logger.zig +43 -0
  393. package/src/zig/mem-registry.zig +125 -0
  394. package/src/zig/native-span-feed-bench-lib.zig +7 -0
  395. package/src/zig/native-span-feed.zig +708 -0
  396. package/src/zig/renderer.zig +1393 -0
  397. package/src/zig/rope.zig +1220 -0
  398. package/src/zig/syntax-style.zig +161 -0
  399. package/src/zig/terminal.zig +987 -0
  400. package/src/zig/test.zig +72 -0
  401. package/src/zig/tests/README.md +18 -0
  402. package/src/zig/tests/buffer-methods_test.zig +1109 -0
  403. package/src/zig/tests/buffer_test.zig +2557 -0
  404. package/src/zig/tests/edit-buffer-history_test.zig +271 -0
  405. package/src/zig/tests/edit-buffer_test.zig +1689 -0
  406. package/src/zig/tests/editor-view_test.zig +3299 -0
  407. package/src/zig/tests/event-emitter_test.zig +249 -0
  408. package/src/zig/tests/grapheme_test.zig +1304 -0
  409. package/src/zig/tests/link_test.zig +190 -0
  410. package/src/zig/tests/mem-registry_test.zig +473 -0
  411. package/src/zig/tests/memory_leak_regression_test.zig +159 -0
  412. package/src/zig/tests/native-span-feed_test.zig +1264 -0
  413. package/src/zig/tests/renderer_test.zig +1017 -0
  414. package/src/zig/tests/rope-nested_test.zig +712 -0
  415. package/src/zig/tests/rope_fuzz_test.zig +238 -0
  416. package/src/zig/tests/rope_test.zig +2362 -0
  417. package/src/zig/tests/segment-merge.test.zig +148 -0
  418. package/src/zig/tests/syntax-style_test.zig +557 -0
  419. package/src/zig/tests/terminal_test.zig +754 -0
  420. package/src/zig/tests/text-buffer-drawing_test.zig +3237 -0
  421. package/src/zig/tests/text-buffer-highlights_test.zig +666 -0
  422. package/src/zig/tests/text-buffer-iterators_test.zig +776 -0
  423. package/src/zig/tests/text-buffer-segment_test.zig +320 -0
  424. package/src/zig/tests/text-buffer-selection_test.zig +1035 -0
  425. package/src/zig/tests/text-buffer-selection_viewport_test.zig +358 -0
  426. package/src/zig/tests/text-buffer-view_test.zig +3649 -0
  427. package/src/zig/tests/text-buffer_test.zig +2191 -0
  428. package/src/zig/tests/unicode-width-map.zon +3909 -0
  429. package/src/zig/tests/utf8_no_zwj_test.zig +260 -0
  430. package/src/zig/tests/utf8_test.zig +4057 -0
  431. package/src/zig/tests/utf8_wcwidth_cursor_test.zig +267 -0
  432. package/src/zig/tests/utf8_wcwidth_test.zig +357 -0
  433. package/src/zig/tests/word-wrap-editing_test.zig +498 -0
  434. package/src/zig/tests/wrap-cache-perf_test.zig +113 -0
  435. package/src/zig/text-buffer-iterators.zig +499 -0
  436. package/src/zig/text-buffer-segment.zig +404 -0
  437. package/src/zig/text-buffer-view.zig +1371 -0
  438. package/src/zig/text-buffer.zig +1180 -0
  439. package/src/zig/utf8.zig +1948 -0
  440. package/src/zig/utils.zig +9 -0
  441. package/src/zig-structs.ts +261 -0
  442. package/src/zig.ts +3884 -0
  443. package/tsconfig.build.json +24 -0
  444. package/tsconfig.json +27 -0
  445. package/3d/SpriteResourceManager.d.ts +0 -74
  446. package/3d/SpriteUtils.d.ts +0 -13
  447. package/3d/TextureUtils.d.ts +0 -24
  448. package/3d/ThreeRenderable.d.ts +0 -40
  449. package/3d/WGPURenderer.d.ts +0 -61
  450. package/3d/animation/ExplodingSpriteEffect.d.ts +0 -71
  451. package/3d/animation/PhysicsExplodingSpriteEffect.d.ts +0 -76
  452. package/3d/animation/SpriteAnimator.d.ts +0 -124
  453. package/3d/animation/SpriteParticleGenerator.d.ts +0 -62
  454. package/3d/canvas.d.ts +0 -44
  455. package/3d/index.d.ts +0 -12
  456. package/3d/physics/PlanckPhysicsAdapter.d.ts +0 -19
  457. package/3d/physics/RapierPhysicsAdapter.d.ts +0 -19
  458. package/3d/physics/physics-interface.d.ts +0 -27
  459. package/3d.d.ts +0 -2
  460. package/3d.js +0 -34041
  461. package/3d.js.map +0 -155
  462. package/LICENSE +0 -21
  463. package/NativeSpanFeed.d.ts +0 -41
  464. package/Renderable.d.ts +0 -334
  465. package/animation/Timeline.d.ts +0 -126
  466. package/ansi.d.ts +0 -13
  467. package/buffer.d.ts +0 -111
  468. package/console.d.ts +0 -144
  469. package/edit-buffer.d.ts +0 -98
  470. package/editor-view.d.ts +0 -73
  471. package/index-9vwc3fg6.js +0 -12260
  472. package/index-9vwc3fg6.js.map +0 -42
  473. package/index-dcj62y8t.js +0 -20614
  474. package/index-dcj62y8t.js.map +0 -67
  475. package/index-f7n39gpy.js +0 -411
  476. package/index-f7n39gpy.js.map +0 -10
  477. package/index.d.ts +0 -23
  478. package/index.js +0 -478
  479. package/index.js.map +0 -9
  480. package/lib/KeyHandler.d.ts +0 -61
  481. package/lib/RGBA.d.ts +0 -25
  482. package/lib/ascii.font.d.ts +0 -508
  483. package/lib/border.d.ts +0 -51
  484. package/lib/bunfs.d.ts +0 -7
  485. package/lib/clipboard.d.ts +0 -17
  486. package/lib/clock.d.ts +0 -15
  487. package/lib/data-paths.d.ts +0 -26
  488. package/lib/debounce.d.ts +0 -42
  489. package/lib/detect-links.d.ts +0 -6
  490. package/lib/env.d.ts +0 -42
  491. package/lib/extmarks-history.d.ts +0 -17
  492. package/lib/extmarks.d.ts +0 -89
  493. package/lib/hast-styled-text.d.ts +0 -17
  494. package/lib/index.d.ts +0 -21
  495. package/lib/keymapping.d.ts +0 -25
  496. package/lib/objects-in-viewport.d.ts +0 -24
  497. package/lib/output.capture.d.ts +0 -24
  498. package/lib/parse.keypress-kitty.d.ts +0 -2
  499. package/lib/parse.keypress.d.ts +0 -26
  500. package/lib/parse.mouse.d.ts +0 -30
  501. package/lib/paste.d.ts +0 -7
  502. package/lib/queue.d.ts +0 -15
  503. package/lib/renderable.validations.d.ts +0 -12
  504. package/lib/scroll-acceleration.d.ts +0 -43
  505. package/lib/selection.d.ts +0 -63
  506. package/lib/singleton.d.ts +0 -7
  507. package/lib/stdin-parser.d.ts +0 -87
  508. package/lib/styled-text.d.ts +0 -63
  509. package/lib/terminal-capability-detection.d.ts +0 -30
  510. package/lib/terminal-palette.d.ts +0 -50
  511. package/lib/tree-sitter/assets/update.d.ts +0 -11
  512. package/lib/tree-sitter/client.d.ts +0 -47
  513. package/lib/tree-sitter/default-parsers.d.ts +0 -2
  514. package/lib/tree-sitter/download-utils.d.ts +0 -21
  515. package/lib/tree-sitter/index.d.ts +0 -8
  516. package/lib/tree-sitter/parser.worker.d.ts +0 -1
  517. package/lib/tree-sitter/parsers-config.d.ts +0 -53
  518. package/lib/tree-sitter/resolve-ft.d.ts +0 -5
  519. package/lib/tree-sitter/types.d.ts +0 -82
  520. package/lib/tree-sitter-styled-text.d.ts +0 -14
  521. package/lib/validate-dir-name.d.ts +0 -1
  522. package/lib/yoga.options.d.ts +0 -32
  523. package/parser.worker.js +0 -899
  524. package/parser.worker.js.map +0 -12
  525. package/plugins/core-slot.d.ts +0 -72
  526. package/plugins/registry.d.ts +0 -42
  527. package/plugins/types.d.ts +0 -34
  528. package/post/effects.d.ts +0 -147
  529. package/post/filters.d.ts +0 -65
  530. package/post/matrices.d.ts +0 -20
  531. package/renderables/ASCIIFont.d.ts +0 -52
  532. package/renderables/Box.d.ts +0 -81
  533. package/renderables/Code.d.ts +0 -78
  534. package/renderables/Diff.d.ts +0 -142
  535. package/renderables/EditBufferRenderable.d.ts +0 -237
  536. package/renderables/FrameBuffer.d.ts +0 -16
  537. package/renderables/Input.d.ts +0 -67
  538. package/renderables/LineNumberRenderable.d.ts +0 -78
  539. package/renderables/Markdown.d.ts +0 -185
  540. package/renderables/ScrollBar.d.ts +0 -77
  541. package/renderables/ScrollBox.d.ts +0 -124
  542. package/renderables/Select.d.ts +0 -115
  543. package/renderables/Slider.d.ts +0 -47
  544. package/renderables/TabSelect.d.ts +0 -96
  545. package/renderables/Text.d.ts +0 -36
  546. package/renderables/TextBufferRenderable.d.ts +0 -105
  547. package/renderables/TextNode.d.ts +0 -91
  548. package/renderables/TextTable.d.ts +0 -140
  549. package/renderables/Textarea.d.ts +0 -63
  550. package/renderables/TimeToFirstDraw.d.ts +0 -24
  551. package/renderables/__tests__/renderable-test-utils.d.ts +0 -12
  552. package/renderables/composition/VRenderable.d.ts +0 -16
  553. package/renderables/composition/constructs.d.ts +0 -35
  554. package/renderables/composition/vnode.d.ts +0 -46
  555. package/renderables/index.d.ts +0 -23
  556. package/renderables/markdown-parser.d.ts +0 -10
  557. package/renderer.d.ts +0 -419
  558. package/runtime-plugin-support.d.ts +0 -3
  559. package/runtime-plugin-support.js +0 -29
  560. package/runtime-plugin-support.js.map +0 -10
  561. package/runtime-plugin.d.ts +0 -16
  562. package/runtime-plugin.js +0 -16
  563. package/runtime-plugin.js.map +0 -9
  564. package/syntax-style.d.ts +0 -54
  565. package/testing/manual-clock.d.ts +0 -17
  566. package/testing/mock-keys.d.ts +0 -81
  567. package/testing/mock-mouse.d.ts +0 -38
  568. package/testing/mock-tree-sitter-client.d.ts +0 -23
  569. package/testing/spy.d.ts +0 -7
  570. package/testing/test-recorder.d.ts +0 -61
  571. package/testing/test-renderer.d.ts +0 -23
  572. package/testing.d.ts +0 -6
  573. package/testing.js +0 -697
  574. package/testing.js.map +0 -15
  575. package/text-buffer-view.d.ts +0 -42
  576. package/text-buffer.d.ts +0 -67
  577. package/types.d.ts +0 -139
  578. package/utils.d.ts +0 -14
  579. package/zig-structs.d.ts +0 -155
  580. package/zig.d.ts +0 -353
  581. /package/{assets → src/lib/tree-sitter/assets}/javascript/highlights.scm +0 -0
  582. /package/{assets → src/lib/tree-sitter/assets}/javascript/tree-sitter-javascript.wasm +0 -0
  583. /package/{assets → src/lib/tree-sitter/assets}/markdown/highlights.scm +0 -0
  584. /package/{assets → src/lib/tree-sitter/assets}/markdown/injections.scm +0 -0
  585. /package/{assets → src/lib/tree-sitter/assets}/markdown/tree-sitter-markdown.wasm +0 -0
  586. /package/{assets → src/lib/tree-sitter/assets}/markdown_inline/highlights.scm +0 -0
  587. /package/{assets → src/lib/tree-sitter/assets}/markdown_inline/tree-sitter-markdown_inline.wasm +0 -0
  588. /package/{assets → src/lib/tree-sitter/assets}/typescript/highlights.scm +0 -0
  589. /package/{assets → src/lib/tree-sitter/assets}/typescript/tree-sitter-typescript.wasm +0 -0
  590. /package/{assets → src/lib/tree-sitter/assets}/zig/highlights.scm +0 -0
  591. /package/{assets → src/lib/tree-sitter/assets}/zig/tree-sitter-zig.wasm +0 -0
@@ -0,0 +1,342 @@
1
+ import { type RenderableOptions, Renderable } from "../Renderable.js"
2
+ import { type RenderContext } from "../types.js"
3
+ import { type ColorInput, RGBA, parseColor } from "../lib/RGBA.js"
4
+ import { OptimizedBuffer } from "../buffer.js"
5
+
6
+ const defaultThumbBackgroundColor = RGBA.fromHex("#9a9ea3")
7
+ const defaultTrackBackgroundColor = RGBA.fromHex("#252527")
8
+
9
+ export interface SliderOptions extends RenderableOptions<SliderRenderable> {
10
+ orientation: "vertical" | "horizontal"
11
+ value?: number
12
+ min?: number
13
+ max?: number
14
+ viewPortSize?: number
15
+ backgroundColor?: ColorInput
16
+ foregroundColor?: ColorInput
17
+ onChange?: (value: number) => void
18
+ }
19
+
20
+ export class SliderRenderable extends Renderable {
21
+ public readonly orientation: "vertical" | "horizontal"
22
+ private _value: number
23
+ private _min: number
24
+ private _max: number
25
+ private _viewPortSize: number
26
+ private _backgroundColor: RGBA
27
+ private _foregroundColor: RGBA
28
+ private _onChange?: (value: number) => void
29
+
30
+ constructor(ctx: RenderContext, options: SliderOptions) {
31
+ super(ctx, { flexShrink: 0, ...options })
32
+ this.orientation = options.orientation
33
+ this._min = options.min ?? 0
34
+ this._max = options.max ?? 100
35
+ this._value = options.value ?? this._min
36
+ this._viewPortSize = options.viewPortSize ?? Math.max(1, (this._max - this._min) * 0.1)
37
+ this._onChange = options.onChange
38
+ this._backgroundColor = options.backgroundColor ? parseColor(options.backgroundColor) : defaultTrackBackgroundColor
39
+ this._foregroundColor = options.foregroundColor ? parseColor(options.foregroundColor) : defaultThumbBackgroundColor
40
+
41
+ this.setupMouseHandling()
42
+ }
43
+
44
+ get value(): number {
45
+ return this._value
46
+ }
47
+
48
+ set value(newValue: number) {
49
+ const clamped = Math.max(this._min, Math.min(this._max, newValue))
50
+ if (clamped !== this._value) {
51
+ this._value = clamped
52
+ this._onChange?.(clamped)
53
+ this.emit("change", { value: clamped })
54
+ this.requestRender()
55
+ }
56
+ }
57
+
58
+ get min(): number {
59
+ return this._min
60
+ }
61
+
62
+ set min(newMin: number) {
63
+ if (newMin !== this._min) {
64
+ this._min = newMin
65
+ if (this._value < newMin) {
66
+ this.value = newMin
67
+ }
68
+ this.requestRender()
69
+ }
70
+ }
71
+
72
+ get max(): number {
73
+ return this._max
74
+ }
75
+
76
+ set max(newMax: number) {
77
+ if (newMax !== this._max) {
78
+ this._max = newMax
79
+ if (this._value > newMax) {
80
+ this.value = newMax
81
+ }
82
+ this.requestRender()
83
+ }
84
+ }
85
+
86
+ set viewPortSize(size: number) {
87
+ const clampedSize = Math.max(0.01, Math.min(size, this._max - this._min))
88
+ if (clampedSize !== this._viewPortSize) {
89
+ this._viewPortSize = clampedSize
90
+ this.requestRender()
91
+ }
92
+ }
93
+
94
+ get viewPortSize(): number {
95
+ return this._viewPortSize
96
+ }
97
+
98
+ get backgroundColor(): RGBA {
99
+ return this._backgroundColor
100
+ }
101
+
102
+ set backgroundColor(value: ColorInput) {
103
+ this._backgroundColor = parseColor(value)
104
+ this.requestRender()
105
+ }
106
+
107
+ get foregroundColor(): RGBA {
108
+ return this._foregroundColor
109
+ }
110
+
111
+ set foregroundColor(value: ColorInput) {
112
+ this._foregroundColor = parseColor(value)
113
+ this.requestRender()
114
+ }
115
+
116
+ private calculateDragOffsetVirtual(event: any): number {
117
+ const trackStart = this.orientation === "vertical" ? this.y : this.x
118
+ const mousePos = (this.orientation === "vertical" ? event.y : event.x) - trackStart
119
+ const virtualMousePos = Math.max(
120
+ 0,
121
+ Math.min((this.orientation === "vertical" ? this.height : this.width) * 2, mousePos * 2),
122
+ )
123
+ const virtualThumbStart = this.getVirtualThumbStart()
124
+ const virtualThumbSize = this.getVirtualThumbSize()
125
+
126
+ return Math.max(0, Math.min(virtualThumbSize, virtualMousePos - virtualThumbStart))
127
+ }
128
+
129
+ private setupMouseHandling(): void {
130
+ let isDragging = false
131
+ let dragOffsetVirtual = 0
132
+
133
+ this.onMouseDown = (event) => {
134
+ event.stopPropagation()
135
+ event.preventDefault()
136
+
137
+ const thumb = this.getThumbRect()
138
+ const inThumb =
139
+ event.x >= thumb.x && event.x < thumb.x + thumb.width && event.y >= thumb.y && event.y < thumb.y + thumb.height
140
+
141
+ if (inThumb) {
142
+ isDragging = true
143
+
144
+ dragOffsetVirtual = this.calculateDragOffsetVirtual(event)
145
+ } else {
146
+ this.updateValueFromMouseDirect(event)
147
+ isDragging = true
148
+
149
+ dragOffsetVirtual = this.calculateDragOffsetVirtual(event)
150
+ }
151
+ }
152
+
153
+ this.onMouseDrag = (event) => {
154
+ if (!isDragging) return
155
+ event.stopPropagation()
156
+ this.updateValueFromMouseWithOffset(event, dragOffsetVirtual)
157
+ }
158
+
159
+ this.onMouseUp = (event) => {
160
+ if (isDragging) {
161
+ this.updateValueFromMouseWithOffset(event, dragOffsetVirtual)
162
+ }
163
+ isDragging = false
164
+ }
165
+ }
166
+
167
+ private updateValueFromMouseDirect(event: any): void {
168
+ const trackStart = this.orientation === "vertical" ? this.y : this.x
169
+ const trackSize = this.orientation === "vertical" ? this.height : this.width
170
+ const mousePos = this.orientation === "vertical" ? event.y : event.x
171
+
172
+ const relativeMousePos = mousePos - trackStart
173
+ const clampedMousePos = Math.max(0, Math.min(trackSize, relativeMousePos))
174
+ const ratio = trackSize === 0 ? 0 : clampedMousePos / trackSize
175
+ const range = this._max - this._min
176
+ const newValue = this._min + ratio * range
177
+
178
+ this.value = newValue
179
+ }
180
+
181
+ private updateValueFromMouseWithOffset(event: any, offsetVirtual: number): void {
182
+ const trackStart = this.orientation === "vertical" ? this.y : this.x
183
+ const trackSize = this.orientation === "vertical" ? this.height : this.width
184
+ const mousePos = this.orientation === "vertical" ? event.y : event.x
185
+
186
+ const virtualTrackSize = trackSize * 2
187
+ const relativeMousePos = mousePos - trackStart
188
+ const clampedMousePos = Math.max(0, Math.min(trackSize, relativeMousePos))
189
+ const virtualMousePos = clampedMousePos * 2
190
+
191
+ const virtualThumbSize = this.getVirtualThumbSize()
192
+ const maxThumbStart = Math.max(0, virtualTrackSize - virtualThumbSize)
193
+
194
+ let desiredThumbStart = virtualMousePos - offsetVirtual
195
+ desiredThumbStart = Math.max(0, Math.min(maxThumbStart, desiredThumbStart))
196
+
197
+ const ratio = maxThumbStart === 0 ? 0 : desiredThumbStart / maxThumbStart
198
+ const range = this._max - this._min
199
+ const newValue = this._min + ratio * range
200
+
201
+ this.value = newValue
202
+ }
203
+
204
+ private getThumbRect(): { x: number; y: number; width: number; height: number } {
205
+ const virtualThumbSize = this.getVirtualThumbSize()
206
+ const virtualThumbStart = this.getVirtualThumbStart()
207
+
208
+ const realThumbStart = Math.floor(virtualThumbStart / 2)
209
+ const realThumbSize = Math.ceil((virtualThumbStart + virtualThumbSize) / 2) - realThumbStart
210
+
211
+ if (this.orientation === "vertical") {
212
+ return {
213
+ x: this.x,
214
+ y: this.y + realThumbStart,
215
+ width: this.width,
216
+ height: Math.max(1, realThumbSize),
217
+ }
218
+ } else {
219
+ return {
220
+ x: this.x + realThumbStart,
221
+ y: this.y,
222
+ width: Math.max(1, realThumbSize),
223
+ height: this.height,
224
+ }
225
+ }
226
+ }
227
+
228
+ protected override renderSelf(buffer: OptimizedBuffer): void {
229
+ if (this.orientation === "horizontal") {
230
+ this.renderHorizontal(buffer)
231
+ } else {
232
+ this.renderVertical(buffer)
233
+ }
234
+ }
235
+
236
+ private renderHorizontal(buffer: OptimizedBuffer): void {
237
+ const virtualThumbSize = this.getVirtualThumbSize()
238
+ const virtualThumbStart = this.getVirtualThumbStart()
239
+ const virtualThumbEnd = virtualThumbStart + virtualThumbSize
240
+
241
+ buffer.fillRect(this.x, this.y, this.width, this.height, this._backgroundColor)
242
+
243
+ const realStartCell = Math.floor(virtualThumbStart / 2)
244
+ const realEndCell = Math.ceil(virtualThumbEnd / 2) - 1
245
+ const startX = Math.max(0, realStartCell)
246
+ const endX = Math.min(this.width - 1, realEndCell)
247
+
248
+ for (let realX = startX; realX <= endX; realX++) {
249
+ const virtualCellStart = realX * 2
250
+ const virtualCellEnd = virtualCellStart + 2
251
+
252
+ const thumbStartInCell = Math.max(virtualThumbStart, virtualCellStart)
253
+ const thumbEndInCell = Math.min(virtualThumbEnd, virtualCellEnd)
254
+ const coverage = thumbEndInCell - thumbStartInCell
255
+
256
+ let char = " "
257
+
258
+ if (coverage >= 2) {
259
+ char = "█"
260
+ } else {
261
+ const isLeftHalf = thumbStartInCell === virtualCellStart
262
+ if (isLeftHalf) {
263
+ char = "▌"
264
+ } else {
265
+ char = "▐"
266
+ }
267
+ }
268
+
269
+ for (let y = 0; y < this.height; y++) {
270
+ buffer.setCellWithAlphaBlending(this.x + realX, this.y + y, char, this._foregroundColor, this._backgroundColor)
271
+ }
272
+ }
273
+ }
274
+
275
+ private renderVertical(buffer: OptimizedBuffer): void {
276
+ const virtualThumbSize = this.getVirtualThumbSize()
277
+ const virtualThumbStart = this.getVirtualThumbStart()
278
+ const virtualThumbEnd = virtualThumbStart + virtualThumbSize
279
+
280
+ buffer.fillRect(this.x, this.y, this.width, this.height, this._backgroundColor)
281
+
282
+ const realStartCell = Math.floor(virtualThumbStart / 2)
283
+ const realEndCell = Math.ceil(virtualThumbEnd / 2) - 1
284
+ const startY = Math.max(0, realStartCell)
285
+ const endY = Math.min(this.height - 1, realEndCell)
286
+
287
+ for (let realY = startY; realY <= endY; realY++) {
288
+ const virtualCellStart = realY * 2
289
+ const virtualCellEnd = virtualCellStart + 2
290
+
291
+ const thumbStartInCell = Math.max(virtualThumbStart, virtualCellStart)
292
+ const thumbEndInCell = Math.min(virtualThumbEnd, virtualCellEnd)
293
+ const coverage = thumbEndInCell - thumbStartInCell
294
+
295
+ let char = " "
296
+
297
+ if (coverage >= 2) {
298
+ char = "█"
299
+ } else if (coverage > 0) {
300
+ const virtualPositionInCell = thumbStartInCell - virtualCellStart
301
+ if (virtualPositionInCell === 0) {
302
+ char = "▀"
303
+ } else {
304
+ char = "▄"
305
+ }
306
+ }
307
+
308
+ for (let x = 0; x < this.width; x++) {
309
+ buffer.setCellWithAlphaBlending(this.x + x, this.y + realY, char, this._foregroundColor, this._backgroundColor)
310
+ }
311
+ }
312
+ }
313
+
314
+ private getVirtualThumbSize(): number {
315
+ const virtualTrackSize = this.orientation === "vertical" ? this.height * 2 : this.width * 2
316
+ const range = this._max - this._min
317
+
318
+ if (range === 0) return virtualTrackSize
319
+
320
+ const viewportSize = Math.max(1, this._viewPortSize)
321
+ const contentSize = range + viewportSize
322
+
323
+ if (contentSize <= viewportSize) return virtualTrackSize
324
+
325
+ const thumbRatio = viewportSize / contentSize
326
+ const calculatedSize = Math.floor(virtualTrackSize * thumbRatio)
327
+
328
+ return Math.max(1, Math.min(calculatedSize, virtualTrackSize))
329
+ }
330
+
331
+ private getVirtualThumbStart(): number {
332
+ const virtualTrackSize = this.orientation === "vertical" ? this.height * 2 : this.width * 2
333
+ const range = this._max - this._min
334
+
335
+ if (range === 0) return 0
336
+
337
+ const valueRatio = (this._value - this._min) / range
338
+ const virtualThumbSize = this.getVirtualThumbSize()
339
+
340
+ return Math.round(valueRatio * (virtualTrackSize - virtualThumbSize))
341
+ }
342
+ }
@@ -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
+ })