@xincli/opentui-core 0.4.6

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 (476) hide show
  1. package/README.md +63 -0
  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/test-tmux-theme-queries.sh +151 -0
  7. package/dev/thai-debug-test.ts +68 -0
  8. package/dev/theme-mode.ts +290 -0
  9. package/docs/development.md +144 -0
  10. package/package.json +102 -0
  11. package/prebuilt/aarch64-android/libopentui.so +0 -0
  12. package/scripts/build-android.ts +226 -0
  13. package/scripts/build-native-termux.sh +525 -0
  14. package/scripts/build.ts +530 -0
  15. package/scripts/dist-test.ts +312 -0
  16. package/scripts/package-prebuilt.ts +110 -0
  17. package/scripts/publish.ts +60 -0
  18. package/scripts/test-node-hook.mjs +16 -0
  19. package/scripts/test-node.ts +241 -0
  20. package/scripts/vendor-deps.sh +73 -0
  21. package/src/NativeSpanFeed.ts +375 -0
  22. package/src/Renderable.ts +1878 -0
  23. package/src/__snapshots__/buffer.test.ts.snap +28 -0
  24. package/src/animation/Timeline.test.ts +2709 -0
  25. package/src/animation/Timeline.ts +598 -0
  26. package/src/ansi.ts +22 -0
  27. package/src/audio.ts +479 -0
  28. package/src/benchmark/attenuation-benchmark.ts +81 -0
  29. package/src/benchmark/audio-playback-benchmark.ts +344 -0
  30. package/src/benchmark/box-draw-benchmark.ts +1042 -0
  31. package/src/benchmark/colormatrix-benchmark.ts +123 -0
  32. package/src/benchmark/gain-benchmark.ts +80 -0
  33. package/src/benchmark/latest-all-bench-run.json +707 -0
  34. package/src/benchmark/latest-async-bench-run.json +336 -0
  35. package/src/benchmark/latest-default-bench-run.json +657 -0
  36. package/src/benchmark/latest-large-bench-run.json +707 -0
  37. package/src/benchmark/latest-quick-bench-run.json +207 -0
  38. package/src/benchmark/layout-benchmark.ts +2547 -0
  39. package/src/benchmark/markdown-benchmark.ts +1796 -0
  40. package/src/benchmark/native-span-feed-async-benchmark.ts +355 -0
  41. package/src/benchmark/native-span-feed-benchmark.md +56 -0
  42. package/src/benchmark/native-span-feed-benchmark.ts +596 -0
  43. package/src/benchmark/native-span-feed-compare.ts +280 -0
  44. package/src/benchmark/render-traversal-benchmark.ts +928 -0
  45. package/src/benchmark/text-buffer-render-benchmark.ts +874 -0
  46. package/src/benchmark/text-table-benchmark.ts +948 -0
  47. package/src/buffer.test.ts +292 -0
  48. package/src/buffer.ts +564 -0
  49. package/src/console.test.ts +629 -0
  50. package/src/console.ts +1253 -0
  51. package/src/edit-buffer.test.ts +1852 -0
  52. package/src/edit-buffer.ts +417 -0
  53. package/src/editor-view.test.ts +1056 -0
  54. package/src/editor-view.ts +290 -0
  55. package/src/index.ts +25 -0
  56. package/src/lib/KeyHandler.integration.test.ts +292 -0
  57. package/src/lib/KeyHandler.stopPropagation.test.ts +289 -0
  58. package/src/lib/KeyHandler.test.ts +662 -0
  59. package/src/lib/KeyHandler.ts +222 -0
  60. package/src/lib/RGBA.test.ts +60 -0
  61. package/src/lib/RGBA.ts +343 -0
  62. package/src/lib/ascii.font.ts +330 -0
  63. package/src/lib/border.test.ts +83 -0
  64. package/src/lib/border.ts +170 -0
  65. package/src/lib/bunfs.test.ts +27 -0
  66. package/src/lib/bunfs.ts +18 -0
  67. package/src/lib/clipboard.test.ts +63 -0
  68. package/src/lib/clipboard.ts +41 -0
  69. package/src/lib/clock.ts +35 -0
  70. package/src/lib/data-paths.test.ts +133 -0
  71. package/src/lib/data-paths.ts +109 -0
  72. package/src/lib/debounce.ts +106 -0
  73. package/src/lib/detect-links.test.ts +98 -0
  74. package/src/lib/detect-links.ts +56 -0
  75. package/src/lib/env.test.ts +228 -0
  76. package/src/lib/env.ts +209 -0
  77. package/src/lib/extmarks-history.ts +51 -0
  78. package/src/lib/extmarks-multiwidth.test.ts +324 -0
  79. package/src/lib/extmarks.test.ts +3547 -0
  80. package/src/lib/extmarks.ts +861 -0
  81. package/src/lib/fonts/block.json +405 -0
  82. package/src/lib/fonts/grid.json +265 -0
  83. package/src/lib/fonts/huge.json +741 -0
  84. package/src/lib/fonts/pallet.json +314 -0
  85. package/src/lib/fonts/shade.json +591 -0
  86. package/src/lib/fonts/slick.json +321 -0
  87. package/src/lib/fonts/tiny.json +69 -0
  88. package/src/lib/hast-styled-text.ts +59 -0
  89. package/src/lib/index.ts +22 -0
  90. package/src/lib/keybinding.internal.test.ts +342 -0
  91. package/src/lib/keybinding.internal.ts +182 -0
  92. package/src/lib/objects-in-viewport.test.ts +789 -0
  93. package/src/lib/objects-in-viewport.ts +153 -0
  94. package/src/lib/output.capture.ts +58 -0
  95. package/src/lib/parse.keypress-kitty.protocol.test.ts +347 -0
  96. package/src/lib/parse.keypress-kitty.test.ts +712 -0
  97. package/src/lib/parse.keypress-kitty.ts +470 -0
  98. package/src/lib/parse.keypress.test.ts +2020 -0
  99. package/src/lib/parse.keypress.ts +480 -0
  100. package/src/lib/parse.mouse.test.ts +552 -0
  101. package/src/lib/parse.mouse.ts +232 -0
  102. package/src/lib/paste.ts +18 -0
  103. package/src/lib/queue.ts +65 -0
  104. package/src/lib/render-geometry.ts +36 -0
  105. package/src/lib/renderable.validations.test.ts +87 -0
  106. package/src/lib/renderable.validations.ts +83 -0
  107. package/src/lib/scroll-acceleration.ts +98 -0
  108. package/src/lib/selection.ts +261 -0
  109. package/src/lib/singleton.ts +34 -0
  110. package/src/lib/stdin-parser.test.ts +2439 -0
  111. package/src/lib/stdin-parser.ts +2007 -0
  112. package/src/lib/styled-text.ts +178 -0
  113. package/src/lib/terminal-capability-detection.test.ts +226 -0
  114. package/src/lib/terminal-capability-detection.ts +98 -0
  115. package/src/lib/terminal-palette.test.ts +954 -0
  116. package/src/lib/terminal-palette.ts +441 -0
  117. package/src/lib/tree-sitter/assets/README.md +119 -0
  118. package/src/lib/tree-sitter/assets/javascript/highlights.scm +205 -0
  119. package/src/lib/tree-sitter/assets/javascript/tree-sitter-javascript.wasm +0 -0
  120. package/src/lib/tree-sitter/assets/markdown/highlights.scm +150 -0
  121. package/src/lib/tree-sitter/assets/markdown/injections.scm +27 -0
  122. package/src/lib/tree-sitter/assets/markdown/tree-sitter-markdown.wasm +0 -0
  123. package/src/lib/tree-sitter/assets/markdown_inline/highlights.scm +115 -0
  124. package/src/lib/tree-sitter/assets/markdown_inline/tree-sitter-markdown_inline.wasm +0 -0
  125. package/src/lib/tree-sitter/assets/typescript/highlights.scm +604 -0
  126. package/src/lib/tree-sitter/assets/typescript/tree-sitter-typescript.wasm +0 -0
  127. package/src/lib/tree-sitter/assets/update.ts +360 -0
  128. package/src/lib/tree-sitter/assets/zig/highlights.scm +284 -0
  129. package/src/lib/tree-sitter/assets/zig/tree-sitter-zig.wasm +0 -0
  130. package/src/lib/tree-sitter/assets.d.ts +9 -0
  131. package/src/lib/tree-sitter/cache.test.ts +291 -0
  132. package/src/lib/tree-sitter/client.test.ts +1434 -0
  133. package/src/lib/tree-sitter/client.ts +847 -0
  134. package/src/lib/tree-sitter/default-parsers.ts +133 -0
  135. package/src/lib/tree-sitter/download-utils.ts +148 -0
  136. package/src/lib/tree-sitter/index.ts +75 -0
  137. package/src/lib/tree-sitter/parser.worker.ts +1098 -0
  138. package/src/lib/tree-sitter/parsers-config.ts +81 -0
  139. package/src/lib/tree-sitter/resolve-ft.test.ts +55 -0
  140. package/src/lib/tree-sitter/resolve-ft.ts +189 -0
  141. package/src/lib/tree-sitter/types.ts +132 -0
  142. package/src/lib/tree-sitter/update-assets.ts +10 -0
  143. package/src/lib/tree-sitter-styled-text.test.ts +1253 -0
  144. package/src/lib/tree-sitter-styled-text.ts +314 -0
  145. package/src/lib/validate-dir-name.ts +55 -0
  146. package/src/lib/yoga.options.test.ts +628 -0
  147. package/src/lib/yoga.options.ts +346 -0
  148. package/src/native-event-worker-repro.test.ts +48 -0
  149. package/src/native-event-worker-repro.worker.ts +9 -0
  150. package/src/native-handle.test.ts +221 -0
  151. package/src/platform/ffi.test.ts +516 -0
  152. package/src/platform/ffi.ts +653 -0
  153. package/src/platform/runtime.test.ts +52 -0
  154. package/src/platform/runtime.ts +121 -0
  155. package/src/platform/test.ts +45 -0
  156. package/src/platform/worker-handler-cleanup.fixture.ts +12 -0
  157. package/src/platform/worker-onmessage-startup.fixture.ts +10 -0
  158. package/src/platform/worker-startup.fixture.ts +9 -0
  159. package/src/platform/worker.node-test.ts +153 -0
  160. package/src/platform/worker.ts +425 -0
  161. package/src/plugins/core-slot.ts +579 -0
  162. package/src/plugins/registry.ts +402 -0
  163. package/src/plugins/types.ts +46 -0
  164. package/src/post/effects.ts +948 -0
  165. package/src/post/filters.ts +512 -0
  166. package/src/post/matrices.ts +288 -0
  167. package/src/renderables/ASCIIFont.ts +219 -0
  168. package/src/renderables/Box.test.ts +474 -0
  169. package/src/renderables/Box.ts +353 -0
  170. package/src/renderables/Code.test.ts +2388 -0
  171. package/src/renderables/Code.ts +555 -0
  172. package/src/renderables/Diff.regression.test.ts +381 -0
  173. package/src/renderables/Diff.test.ts +3212 -0
  174. package/src/renderables/Diff.ts +1278 -0
  175. package/src/renderables/EditBufferRenderable.test.ts +288 -0
  176. package/src/renderables/EditBufferRenderable.ts +1152 -0
  177. package/src/renderables/FrameBuffer.ts +47 -0
  178. package/src/renderables/Input.test.ts +1310 -0
  179. package/src/renderables/Input.ts +273 -0
  180. package/src/renderables/LineNumberRenderable.ts +725 -0
  181. package/src/renderables/Markdown.ts +2144 -0
  182. package/src/renderables/ScrollBar.ts +423 -0
  183. package/src/renderables/ScrollBox.ts +903 -0
  184. package/src/renderables/Select.test.ts +1134 -0
  185. package/src/renderables/Select.ts +535 -0
  186. package/src/renderables/Slider.test.ts +456 -0
  187. package/src/renderables/Slider.ts +342 -0
  188. package/src/renderables/TabSelect.test.ts +238 -0
  189. package/src/renderables/TabSelect.ts +447 -0
  190. package/src/renderables/Text.selection-buffer.test.ts +118 -0
  191. package/src/renderables/Text.test.ts +2662 -0
  192. package/src/renderables/Text.ts +147 -0
  193. package/src/renderables/TextBufferRenderable.ts +504 -0
  194. package/src/renderables/TextNode.test.ts +1137 -0
  195. package/src/renderables/TextNode.ts +379 -0
  196. package/src/renderables/TextTable.test.ts +1411 -0
  197. package/src/renderables/TextTable.ts +1434 -0
  198. package/src/renderables/Textarea.ts +425 -0
  199. package/src/renderables/TimeToFirstDraw.ts +89 -0
  200. package/src/renderables/__snapshots__/Code.test.ts.snap +13 -0
  201. package/src/renderables/__snapshots__/Diff.test.ts.snap +785 -0
  202. package/src/renderables/__snapshots__/Text.test.ts.snap +421 -0
  203. package/src/renderables/__snapshots__/TextTable.test.ts.snap +215 -0
  204. package/src/renderables/__tests__/Code.test.ts +55 -0
  205. package/src/renderables/__tests__/LineNumberRenderable.scrollbox-simple.test.ts +144 -0
  206. package/src/renderables/__tests__/LineNumberRenderable.scrollbox.test.ts +827 -0
  207. package/src/renderables/__tests__/LineNumberRenderable.test.ts +1906 -0
  208. package/src/renderables/__tests__/LineNumberRenderable.wrapping.test.ts +85 -0
  209. package/src/renderables/__tests__/Markdown.code-colors.test.ts +288 -0
  210. package/src/renderables/__tests__/Markdown.test.ts +4175 -0
  211. package/src/renderables/__tests__/MultiRenderable.selection.test.ts +87 -0
  212. package/src/renderables/__tests__/Textarea.buffer.test.ts +683 -0
  213. package/src/renderables/__tests__/Textarea.destroyed-events.test.ts +675 -0
  214. package/src/renderables/__tests__/Textarea.editing.test.ts +2120 -0
  215. package/src/renderables/__tests__/Textarea.error-handling.test.ts +35 -0
  216. package/src/renderables/__tests__/Textarea.events.test.ts +738 -0
  217. package/src/renderables/__tests__/Textarea.highlights.test.ts +590 -0
  218. package/src/renderables/__tests__/Textarea.keybinding.test.ts +3275 -0
  219. package/src/renderables/__tests__/Textarea.paste.test.ts +357 -0
  220. package/src/renderables/__tests__/Textarea.rendering.test.ts +1927 -0
  221. package/src/renderables/__tests__/Textarea.scroll.test.ts +733 -0
  222. package/src/renderables/__tests__/Textarea.selection.test.ts +1589 -0
  223. package/src/renderables/__tests__/Textarea.stress.test.ts +670 -0
  224. package/src/renderables/__tests__/Textarea.undo-redo.test.ts +383 -0
  225. package/src/renderables/__tests__/Textarea.visual-lines.test.ts +310 -0
  226. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.code.test.ts.snap +221 -0
  227. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox-simple.test.ts.snap +89 -0
  228. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox.test.ts.snap +457 -0
  229. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.test.ts.snap +158 -0
  230. package/src/renderables/__tests__/__snapshots__/Textarea.rendering.test.ts.snap +387 -0
  231. package/src/renderables/__tests__/markdown-parser.test.ts +241 -0
  232. package/src/renderables/__tests__/renderable-test-utils.ts +60 -0
  233. package/src/renderables/composition/README.md +8 -0
  234. package/src/renderables/composition/VRenderable.ts +32 -0
  235. package/src/renderables/composition/constructs.ts +127 -0
  236. package/src/renderables/composition/vnode.ts +277 -0
  237. package/src/renderables/index.ts +23 -0
  238. package/src/renderables/markdown-parser.ts +79 -0
  239. package/src/renderer-theme-mode.ts +199 -0
  240. package/src/renderer.ts +4975 -0
  241. package/src/runtime-plugin-support-configure.ts +63 -0
  242. package/src/runtime-plugin-support.ts +13 -0
  243. package/src/runtime-plugin.ts +626 -0
  244. package/src/specs/terminal-startup.md +64 -0
  245. package/src/syntax-style.test.ts +841 -0
  246. package/src/syntax-style.ts +274 -0
  247. package/src/testing/README.md +219 -0
  248. package/src/testing/bun-test-node.ts +880 -0
  249. package/src/testing/capture-spans.test.ts +216 -0
  250. package/src/testing/integration.test.ts +276 -0
  251. package/src/testing/manual-clock.ts +117 -0
  252. package/src/testing/mock-keys.test.ts +1378 -0
  253. package/src/testing/mock-keys.ts +457 -0
  254. package/src/testing/mock-mouse.test.ts +218 -0
  255. package/src/testing/mock-mouse.ts +247 -0
  256. package/src/testing/mock-tree-sitter-client.ts +81 -0
  257. package/src/testing/spy.ts +13 -0
  258. package/src/testing/terminal-capabilities.ts +47 -0
  259. package/src/testing/test-recorder.test.ts +410 -0
  260. package/src/testing/test-recorder.ts +133 -0
  261. package/src/testing/test-renderer.ts +375 -0
  262. package/src/testing/test-renderer.wait.test.ts +278 -0
  263. package/src/testing/test-streams.ts +31 -0
  264. package/src/testing.ts +9 -0
  265. package/src/tests/__snapshots__/absolute-positioning.snapshot.test.ts.snap +481 -0
  266. package/src/tests/__snapshots__/renderable.snapshot.test.ts.snap +19 -0
  267. package/src/tests/__snapshots__/scrollbox.test.ts.snap +29 -0
  268. package/src/tests/absolute-positioning.snapshot.test.ts +638 -0
  269. package/src/tests/allocator-stats.test.ts +53 -0
  270. package/src/tests/audio.test.ts +303 -0
  271. package/src/tests/destroy-during-render.test.ts +200 -0
  272. package/src/tests/destroy-on-exit.fixture.ts +36 -0
  273. package/src/tests/destroy-on-exit.test.ts +62 -0
  274. package/src/tests/ffi-borrowed-pointer-callsites.test.ts +153 -0
  275. package/src/tests/hover-cursor.test.ts +98 -0
  276. package/src/tests/native-backed-measurement-lifecycle.test.ts +133 -0
  277. package/src/tests/native-backed-measurement-parity.test.ts +322 -0
  278. package/src/tests/native-span-feed-async.test.ts +173 -0
  279. package/src/tests/native-span-feed-close.test.ts +120 -0
  280. package/src/tests/native-span-feed-coverage.test.ts +227 -0
  281. package/src/tests/native-span-feed-edge-cases.test.ts +384 -0
  282. package/src/tests/native-span-feed-use-after-free.test.ts +45 -0
  283. package/src/tests/opacity.test.ts +123 -0
  284. package/src/tests/renderable.snapshot.test.ts +524 -0
  285. package/src/tests/renderable.test.ts +1851 -0
  286. package/src/tests/renderer.clock.test.ts +270 -0
  287. package/src/tests/renderer.console-startup.test.ts +2151 -0
  288. package/src/tests/renderer.control.test.ts +458 -0
  289. package/src/tests/renderer.core-slot-binding.test.ts +962 -0
  290. package/src/tests/renderer.cursor.test.ts +26 -0
  291. package/src/tests/renderer.custom-stdout.test.ts +1112 -0
  292. package/src/tests/renderer.destroy-during-render.test.ts +147 -0
  293. package/src/tests/renderer.focus-restore.test.ts +257 -0
  294. package/src/tests/renderer.focus.test.ts +329 -0
  295. package/src/tests/renderer.idle.test.ts +219 -0
  296. package/src/tests/renderer.input.test.ts +2615 -0
  297. package/src/tests/renderer.kitty-flags.test.ts +195 -0
  298. package/src/tests/renderer.lifecycle.test.ts +34 -0
  299. package/src/tests/renderer.mouse.test.ts +1315 -0
  300. package/src/tests/renderer.notifications.test.ts +27 -0
  301. package/src/tests/renderer.palette.test.ts +1199 -0
  302. package/src/tests/renderer.remote.test.ts +247 -0
  303. package/src/tests/renderer.render-stats.test.ts +146 -0
  304. package/src/tests/renderer.scrollback-surface.test.ts +474 -0
  305. package/src/tests/renderer.selection.test.ts +138 -0
  306. package/src/tests/renderer.slot-registry.test.ts +684 -0
  307. package/src/tests/renderer.tracker.test.ts +202 -0
  308. package/src/tests/renderer.useMouse.test.ts +83 -0
  309. package/src/tests/runtime-plugin-node-modules-cycle.fixture.ts +76 -0
  310. package/src/tests/runtime-plugin-node-modules-import-like-string.fixture.ts +48 -0
  311. package/src/tests/runtime-plugin-node-modules-mjs.fixture.ts +43 -0
  312. package/src/tests/runtime-plugin-node-modules-no-bare-rewrite.fixture.ts +67 -0
  313. package/src/tests/runtime-plugin-node-modules-package-type-cache.fixture.ts +72 -0
  314. package/src/tests/runtime-plugin-node-modules-runtime-specifier.fixture.ts +44 -0
  315. package/src/tests/runtime-plugin-node-modules-scoped-package-bare-rewrite.fixture.ts +85 -0
  316. package/src/tests/runtime-plugin-path-alias.fixture.ts +43 -0
  317. package/src/tests/runtime-plugin-resolve-roots.fixture.ts +65 -0
  318. package/src/tests/runtime-plugin-support-configure.fixture.ts +31 -0
  319. package/src/tests/runtime-plugin-support-late-addition.fixture.ts +17 -0
  320. package/src/tests/runtime-plugin-support.fixture.ts +11 -0
  321. package/src/tests/runtime-plugin-support.test.ts +54 -0
  322. package/src/tests/runtime-plugin-windows-file-url.fixture.ts +30 -0
  323. package/src/tests/runtime-plugin.fixture.ts +40 -0
  324. package/src/tests/runtime-plugin.test.ts +369 -0
  325. package/src/tests/scrollbox-culling-bug.test.ts +114 -0
  326. package/src/tests/scrollbox-hitgrid-resize.test.ts +136 -0
  327. package/src/tests/scrollbox-hitgrid.test.ts +909 -0
  328. package/src/tests/scrollbox.test.ts +1895 -0
  329. package/src/tests/wrap-resize-perf.test.ts +276 -0
  330. package/src/tests/yoga-api-coverage.test.ts +409 -0
  331. package/src/tests/yoga-callback-stress.test.ts +122 -0
  332. package/src/tests/yoga-ffi.test.ts +117 -0
  333. package/src/tests/yoga-setters.test.ts +921 -0
  334. package/src/tests/yoga-upstream/YGAlignBaselineTest.test.ts +124 -0
  335. package/src/tests/yoga-upstream/YGComputedBorderTest.test.ts +27 -0
  336. package/src/tests/yoga-upstream/YGComputedMarginTest.test.ts +27 -0
  337. package/src/tests/yoga-upstream/YGComputedPaddingTest.test.ts +27 -0
  338. package/src/tests/yoga-upstream/YGDirtiedTest.test.ts +157 -0
  339. package/src/tests/yoga-upstream/YGErrataTest.test.ts +40 -0
  340. package/src/tests/yoga-upstream/YGFlexBasisAuto.test.ts +23 -0
  341. package/src/tests/yoga-upstream/YGHasNewLayout.test.ts +81 -0
  342. package/src/tests/yoga-upstream/YGMeasureCacheTest.test.ts +31 -0
  343. package/src/tests/yoga-upstream/YGMeasureTest.test.ts +70 -0
  344. package/src/tests/yoga-upstream/generated/YGAbsolutePositionTest.test.ts +1864 -0
  345. package/src/tests/yoga-upstream/generated/YGAlignContentTest.test.ts +5829 -0
  346. package/src/tests/yoga-upstream/generated/YGAlignItemsTest.test.ts +2444 -0
  347. package/src/tests/yoga-upstream/generated/YGAlignSelfTest.test.ts +293 -0
  348. package/src/tests/yoga-upstream/generated/YGAndroidNewsFeed.test.ts +315 -0
  349. package/src/tests/yoga-upstream/generated/YGAspectRatioTest.test.ts +231 -0
  350. package/src/tests/yoga-upstream/generated/YGAutoTest.test.ts +347 -0
  351. package/src/tests/yoga-upstream/generated/YGBorderTest.test.ts +256 -0
  352. package/src/tests/yoga-upstream/generated/YGBoxSizingTest.test.ts +2747 -0
  353. package/src/tests/yoga-upstream/generated/YGDimensionTest.test.ts +129 -0
  354. package/src/tests/yoga-upstream/generated/YGDisplayContentsTest.test.ts +109 -0
  355. package/src/tests/yoga-upstream/generated/YGDisplayTest.test.ts +1097 -0
  356. package/src/tests/yoga-upstream/generated/YGFlexDirectionTest.test.ts +4562 -0
  357. package/src/tests/yoga-upstream/generated/YGFlexTest.test.ts +677 -0
  358. package/src/tests/yoga-upstream/generated/YGFlexWrapTest.test.ts +2071 -0
  359. package/src/tests/yoga-upstream/generated/YGGapTest.test.ts +3303 -0
  360. package/src/tests/yoga-upstream/generated/YGIntrinsicSizeTest.test.ts +582 -0
  361. package/src/tests/yoga-upstream/generated/YGJustifyContentTest.test.ts +2150 -0
  362. package/src/tests/yoga-upstream/generated/YGMarginTest.test.ts +1963 -0
  363. package/src/tests/yoga-upstream/generated/YGMinMaxDimensionTest.test.ts +1446 -0
  364. package/src/tests/yoga-upstream/generated/YGPaddingTest.test.ts +354 -0
  365. package/src/tests/yoga-upstream/generated/YGPercentageTest.test.ts +1760 -0
  366. package/src/tests/yoga-upstream/generated/YGRoundingTest.test.ts +1161 -0
  367. package/src/tests/yoga-upstream/generated/YGSizeOverflowTest.test.ts +207 -0
  368. package/src/tests/yoga-upstream/generated/YGStaticPositionTest.test.ts +6338 -0
  369. package/src/tests/yoga-upstream/tools/MeasureCounter.ts +54 -0
  370. package/src/tests/yoga-upstream/tools/utils.ts +81 -0
  371. package/src/text-buffer-view.test.ts +722 -0
  372. package/src/text-buffer-view.ts +193 -0
  373. package/src/text-buffer.test.ts +512 -0
  374. package/src/text-buffer.ts +250 -0
  375. package/src/types.ts +199 -0
  376. package/src/utils.ts +88 -0
  377. package/src/yoga.ts +1146 -0
  378. package/src/zig/ansi.zig +502 -0
  379. package/src/zig/audio.zig +1206 -0
  380. package/src/zig/bench/README.md +50 -0
  381. package/src/zig/bench/buffer-color-blending_bench.zig +350 -0
  382. package/src/zig/bench/buffer-draw-box_bench.zig +786 -0
  383. package/src/zig/bench/buffer-draw-text-buffer_bench.zig +894 -0
  384. package/src/zig/bench/edit-buffer_bench.zig +476 -0
  385. package/src/zig/bench/editor-view_bench.zig +169 -0
  386. package/src/zig/bench/native-span-feed_bench.zig +107 -0
  387. package/src/zig/bench/rope-markers_bench.zig +713 -0
  388. package/src/zig/bench/rope_bench.zig +514 -0
  389. package/src/zig/bench/styled-text_bench.zig +476 -0
  390. package/src/zig/bench/text-buffer-coords_bench.zig +362 -0
  391. package/src/zig/bench/text-buffer-view_bench.zig +459 -0
  392. package/src/zig/bench/text-chunk-graphemes_bench.zig +272 -0
  393. package/src/zig/bench/utf8_bench.zig +799 -0
  394. package/src/zig/bench-utils.zig +431 -0
  395. package/src/zig/bench.zig +223 -0
  396. package/src/zig/buffer-methods.zig +215 -0
  397. package/src/zig/buffer.zig +2515 -0
  398. package/src/zig/build.zig +700 -0
  399. package/src/zig/build.zig.zon +19 -0
  400. package/src/zig/edit-buffer.zig +900 -0
  401. package/src/zig/editor-view.zig +812 -0
  402. package/src/zig/event-bus.zig +28 -0
  403. package/src/zig/event-emitter.zig +65 -0
  404. package/src/zig/file-logger.zig +92 -0
  405. package/src/zig/grapheme.zig +838 -0
  406. package/src/zig/handles.zig +267 -0
  407. package/src/zig/lib.zig +2813 -0
  408. package/src/zig/link.zig +349 -0
  409. package/src/zig/logger.zig +43 -0
  410. package/src/zig/mem-registry.zig +126 -0
  411. package/src/zig/miniaudio_shim.c +21 -0
  412. package/src/zig/native-renderable.zig +112 -0
  413. package/src/zig/native-span-feed-bench-lib.zig +7 -0
  414. package/src/zig/native-span-feed.zig +747 -0
  415. package/src/zig/renderer-output.zig +677 -0
  416. package/src/zig/renderer.zig +2106 -0
  417. package/src/zig/rope.zig +1220 -0
  418. package/src/zig/split-scrollback.zig +88 -0
  419. package/src/zig/syntax-style.zig +174 -0
  420. package/src/zig/terminal.zig +1652 -0
  421. package/src/zig/test.zig +82 -0
  422. package/src/zig/tests/README.md +18 -0
  423. package/src/zig/tests/ansi_test.zig +18 -0
  424. package/src/zig/tests/audio_test.zig +439 -0
  425. package/src/zig/tests/buffer-methods_test.zig +1111 -0
  426. package/src/zig/tests/buffer_test.zig +2926 -0
  427. package/src/zig/tests/edit-buffer-history_test.zig +299 -0
  428. package/src/zig/tests/edit-buffer_test.zig +1688 -0
  429. package/src/zig/tests/editor-view_test.zig +3454 -0
  430. package/src/zig/tests/event-emitter_test.zig +249 -0
  431. package/src/zig/tests/grapheme_test.zig +1329 -0
  432. package/src/zig/tests/handles_test.zig +123 -0
  433. package/src/zig/tests/link_test.zig +220 -0
  434. package/src/zig/tests/mem-registry_test.zig +473 -0
  435. package/src/zig/tests/memory_leak_regression_test.zig +234 -0
  436. package/src/zig/tests/native-renderable_test.zig +16 -0
  437. package/src/zig/tests/native-span-feed_test.zig +1266 -0
  438. package/src/zig/tests/renderer_test.zig +2604 -0
  439. package/src/zig/tests/rope-nested_test.zig +712 -0
  440. package/src/zig/tests/rope_fuzz_test.zig +238 -0
  441. package/src/zig/tests/rope_test.zig +2362 -0
  442. package/src/zig/tests/segment-merge.test.zig +148 -0
  443. package/src/zig/tests/split-scrollback_test.zig +70 -0
  444. package/src/zig/tests/syntax-style_test.zig +558 -0
  445. package/src/zig/tests/terminal_test.zig +1489 -0
  446. package/src/zig/tests/test-renderer.zig +126 -0
  447. package/src/zig/tests/text-buffer-drawing_test.zig +3291 -0
  448. package/src/zig/tests/text-buffer-highlights_test.zig +706 -0
  449. package/src/zig/tests/text-buffer-iterators_test.zig +776 -0
  450. package/src/zig/tests/text-buffer-segment_test.zig +320 -0
  451. package/src/zig/tests/text-buffer-selection_test.zig +1056 -0
  452. package/src/zig/tests/text-buffer-selection_viewport_test.zig +358 -0
  453. package/src/zig/tests/text-buffer-view_test.zig +3672 -0
  454. package/src/zig/tests/text-buffer_test.zig +2191 -0
  455. package/src/zig/tests/unicode-width-map.zon +3909 -0
  456. package/src/zig/tests/utf8_no_zwj_test.zig +260 -0
  457. package/src/zig/tests/utf8_test.zig +4060 -0
  458. package/src/zig/tests/utf8_wcwidth_cursor_test.zig +267 -0
  459. package/src/zig/tests/utf8_wcwidth_test.zig +357 -0
  460. package/src/zig/tests/word-wrap-editing_test.zig +498 -0
  461. package/src/zig/tests/wrap-cache-perf_test.zig +113 -0
  462. package/src/zig/tests/yoga_test.zig +65 -0
  463. package/src/zig/text-buffer-iterators.zig +496 -0
  464. package/src/zig/text-buffer-segment.zig +403 -0
  465. package/src/zig/text-buffer-view.zig +1428 -0
  466. package/src/zig/text-buffer.zig +1272 -0
  467. package/src/zig/utf8.zig +1954 -0
  468. package/src/zig/utils.zig +12 -0
  469. package/src/zig/uucode-stub.zig +76 -0
  470. package/src/zig/vendor/miniaudio/miniaudio.h +93468 -0
  471. package/src/zig/yoga.zig +658 -0
  472. package/src/zig-structs.ts +381 -0
  473. package/src/zig.ts +5260 -0
  474. package/tsconfig.build.json +17 -0
  475. package/tsconfig.json +27 -0
  476. package/tsconfig.node-test.json +138 -0
@@ -0,0 +1,535 @@
1
+ import { OptimizedBuffer } from "../buffer.js"
2
+ import { fonts, measureText, renderFontToFrameBuffer } from "../lib/ascii.font.js"
3
+ import type { KeyEvent } from "../lib/KeyHandler.js"
4
+ import { RGBA, parseColor, type ColorInput } from "../lib/RGBA.js"
5
+ import { Renderable, type RenderableOptions } from "../Renderable.js"
6
+ import type { RenderContext } from "../types.js"
7
+ import {
8
+ type KeyBinding as BaseKeyBinding,
9
+ mergeKeyBindings,
10
+ buildKeyBindingsMap,
11
+ getKeyBindingAction,
12
+ defaultKeyAliases,
13
+ mergeKeyAliases,
14
+ } from "../lib/keybinding.internal.js"
15
+
16
+ type KeyAliasMap = Record<string, string>
17
+
18
+ export interface SelectOption {
19
+ name: string
20
+ description: string
21
+ value?: any
22
+ }
23
+
24
+ export type SelectAction = "move-up" | "move-down" | "move-up-fast" | "move-down-fast" | "select-current"
25
+
26
+ export type SelectKeyBinding = BaseKeyBinding<SelectAction>
27
+
28
+ const defaultSelectKeybindings: SelectKeyBinding[] = [
29
+ { name: "up", action: "move-up" },
30
+ { name: "k", action: "move-up" },
31
+ { name: "down", action: "move-down" },
32
+ { name: "j", action: "move-down" },
33
+ { name: "up", shift: true, action: "move-up-fast" },
34
+ { name: "down", shift: true, action: "move-down-fast" },
35
+ { name: "return", action: "select-current" },
36
+ { name: "linefeed", action: "select-current" },
37
+ ]
38
+
39
+ export interface SelectRenderableOptions extends RenderableOptions<SelectRenderable> {
40
+ backgroundColor?: ColorInput
41
+ textColor?: ColorInput
42
+ focusedBackgroundColor?: ColorInput
43
+ focusedTextColor?: ColorInput
44
+ options?: SelectOption[]
45
+ selectedIndex?: number
46
+ selectedBackgroundColor?: ColorInput
47
+ selectedTextColor?: ColorInput
48
+ descriptionColor?: ColorInput
49
+ selectedDescriptionColor?: ColorInput
50
+ showScrollIndicator?: boolean
51
+ wrapSelection?: boolean
52
+ showDescription?: boolean
53
+ showSelectionIndicator?: boolean
54
+ font?: keyof typeof fonts
55
+ itemSpacing?: number
56
+ fastScrollStep?: number
57
+ keyBindings?: SelectKeyBinding[]
58
+ keyAliasMap?: KeyAliasMap
59
+ }
60
+
61
+ export enum SelectRenderableEvents {
62
+ SELECTION_CHANGED = "selectionChanged",
63
+ ITEM_SELECTED = "itemSelected",
64
+ }
65
+
66
+ export class SelectRenderable extends Renderable {
67
+ protected _focusable: boolean = true
68
+
69
+ private _options: SelectOption[] = []
70
+ private _selectedIndex: number = 0
71
+ private scrollOffset: number = 0
72
+ private maxVisibleItems: number
73
+
74
+ private _backgroundColor: RGBA
75
+ private _textColor: RGBA
76
+ private _focusedBackgroundColor: RGBA
77
+ private _focusedTextColor: RGBA
78
+ private _selectedBackgroundColor: RGBA
79
+ private _selectedTextColor: RGBA
80
+ private _descriptionColor: RGBA
81
+ private _selectedDescriptionColor: RGBA
82
+ private _showScrollIndicator: boolean
83
+ private _wrapSelection: boolean
84
+ private _showDescription: boolean
85
+ private _showSelectionIndicator: boolean
86
+ private _font?: keyof typeof fonts
87
+ private _itemSpacing: number
88
+ private linesPerItem: number
89
+ private fontHeight: number
90
+ private _fastScrollStep: number
91
+ private _keyBindingsMap: Map<string, SelectAction>
92
+ private _keyAliasMap: KeyAliasMap
93
+ private _keyBindings: SelectKeyBinding[]
94
+
95
+ protected _defaultOptions = {
96
+ backgroundColor: "transparent",
97
+ textColor: "#FFFFFF",
98
+ focusedBackgroundColor: "#1a1a1a",
99
+ focusedTextColor: "#FFFFFF",
100
+ selectedBackgroundColor: "#334455",
101
+ selectedTextColor: "#FFFF00",
102
+ selectedIndex: 0,
103
+ descriptionColor: "#888888",
104
+ selectedDescriptionColor: "#CCCCCC",
105
+ showScrollIndicator: false,
106
+ wrapSelection: false,
107
+ showDescription: true,
108
+ showSelectionIndicator: true,
109
+ itemSpacing: 0,
110
+ fastScrollStep: 5,
111
+ } satisfies Partial<SelectRenderableOptions>
112
+
113
+ constructor(ctx: RenderContext, options: SelectRenderableOptions) {
114
+ super(ctx, { ...options, buffered: true })
115
+ this._options = options.options || []
116
+ const requestedIndex = options.selectedIndex ?? this._defaultOptions.selectedIndex
117
+ this._selectedIndex = this._options.length > 0 ? Math.min(requestedIndex, this._options.length - 1) : 0
118
+ this._backgroundColor = parseColor(options.backgroundColor || this._defaultOptions.backgroundColor)
119
+ this._textColor = parseColor(options.textColor || this._defaultOptions.textColor)
120
+ this._focusedBackgroundColor = parseColor(
121
+ options.focusedBackgroundColor || this._defaultOptions.focusedBackgroundColor,
122
+ )
123
+ this._focusedTextColor = parseColor(options.focusedTextColor || this._defaultOptions.focusedTextColor)
124
+
125
+ this._showScrollIndicator = options.showScrollIndicator ?? this._defaultOptions.showScrollIndicator
126
+ this._wrapSelection = options.wrapSelection ?? this._defaultOptions.wrapSelection
127
+ this._showDescription = options.showDescription ?? this._defaultOptions.showDescription
128
+ this._showSelectionIndicator = options.showSelectionIndicator ?? this._defaultOptions.showSelectionIndicator
129
+ this._font = options.font
130
+ this._itemSpacing = options.itemSpacing || this._defaultOptions.itemSpacing
131
+
132
+ this.fontHeight = this._font ? measureText({ text: "A", font: this._font }).height : 1
133
+ this.linesPerItem = this._showDescription
134
+ ? this._font
135
+ ? this.fontHeight + 1
136
+ : 2
137
+ : this._font
138
+ ? this.fontHeight
139
+ : 1
140
+ this.linesPerItem += this._itemSpacing
141
+
142
+ this.maxVisibleItems = Math.max(1, Math.floor(this.height / this.linesPerItem))
143
+
144
+ this._selectedBackgroundColor = parseColor(
145
+ options.selectedBackgroundColor || this._defaultOptions.selectedBackgroundColor,
146
+ )
147
+ this._selectedTextColor = parseColor(options.selectedTextColor || this._defaultOptions.selectedTextColor)
148
+ this._descriptionColor = parseColor(options.descriptionColor || this._defaultOptions.descriptionColor)
149
+ this._selectedDescriptionColor = parseColor(
150
+ options.selectedDescriptionColor || this._defaultOptions.selectedDescriptionColor,
151
+ )
152
+ this._fastScrollStep = options.fastScrollStep || this._defaultOptions.fastScrollStep
153
+
154
+ this._keyAliasMap = mergeKeyAliases(defaultKeyAliases, options.keyAliasMap || {})
155
+ this._keyBindings = options.keyBindings || []
156
+ const mergedBindings = mergeKeyBindings(defaultSelectKeybindings, this._keyBindings)
157
+ this._keyBindingsMap = buildKeyBindingsMap(mergedBindings, this._keyAliasMap)
158
+
159
+ this.updateScrollOffset()
160
+ this.requestRender() // Initial render needed
161
+ }
162
+
163
+ protected renderSelf(buffer: OptimizedBuffer, deltaTime: number): void {
164
+ if (!this.visible || !this.frameBuffer) return
165
+
166
+ if (this.isDirty) {
167
+ this.refreshFrameBuffer()
168
+ }
169
+ }
170
+
171
+ private refreshFrameBuffer(): void {
172
+ if (!this.frameBuffer) return
173
+
174
+ const bgColor = this._focused ? this._focusedBackgroundColor : this._backgroundColor
175
+ this.frameBuffer.clear(bgColor)
176
+ if (this._options.length === 0) return
177
+
178
+ const contentX = 0
179
+ const contentY = 0
180
+ const contentWidth = this.width
181
+ const contentHeight = this.height
182
+
183
+ const visibleOptions = this._options.slice(this.scrollOffset, this.scrollOffset + this.maxVisibleItems)
184
+
185
+ for (let i = 0; i < visibleOptions.length; i++) {
186
+ const actualIndex = this.scrollOffset + i
187
+ const option = visibleOptions[i]
188
+ const isSelected = actualIndex === this._selectedIndex
189
+ const itemY = contentY + i * this.linesPerItem
190
+
191
+ if (itemY + this.linesPerItem - 1 >= contentY + contentHeight) break
192
+
193
+ if (isSelected) {
194
+ const contentHeight = this.linesPerItem - this._itemSpacing
195
+ this.frameBuffer.fillRect(contentX, itemY, contentWidth, contentHeight, this._selectedBackgroundColor)
196
+ }
197
+
198
+ const indicator = this._showSelectionIndicator ? (isSelected ? "▶ " : " ") : ""
199
+ const indicatorWidth = this._showSelectionIndicator ? 2 : 0
200
+ const nameContent = `${indicator}${option.name}`
201
+ const baseTextColor = this._focused ? this._focusedTextColor : this._textColor
202
+ const nameColor = isSelected ? this._selectedTextColor : baseTextColor
203
+ const textX = contentX + 1 + indicatorWidth
204
+
205
+ if (this._font) {
206
+ if (indicator) {
207
+ this.frameBuffer.drawText(indicator, contentX + 1, itemY, nameColor)
208
+ }
209
+
210
+ renderFontToFrameBuffer(this.frameBuffer, {
211
+ text: option.name,
212
+ x: textX,
213
+ y: itemY,
214
+ color: nameColor,
215
+ backgroundColor: isSelected ? this._selectedBackgroundColor : bgColor,
216
+ font: this._font,
217
+ })
218
+ } else {
219
+ this.frameBuffer.drawText(nameContent, contentX + 1, itemY, nameColor)
220
+ }
221
+
222
+ if (this._showDescription && itemY + this.fontHeight < contentY + contentHeight) {
223
+ const descColor = isSelected ? this._selectedDescriptionColor : this._descriptionColor
224
+ this.frameBuffer.drawText(option.description, textX, itemY + this.fontHeight, descColor)
225
+ }
226
+ }
227
+
228
+ if (this._showScrollIndicator && this._options.length > this.maxVisibleItems) {
229
+ this.renderScrollIndicatorToFrameBuffer(contentX, contentY, contentWidth, contentHeight)
230
+ }
231
+ }
232
+
233
+ private renderScrollIndicatorToFrameBuffer(
234
+ contentX: number,
235
+ contentY: number,
236
+ contentWidth: number,
237
+ contentHeight: number,
238
+ ): void {
239
+ if (!this.frameBuffer) return
240
+
241
+ const maxScrollOffset = this._options.length - this.maxVisibleItems
242
+ const scrollPercent = this.scrollOffset / maxScrollOffset
243
+ const indicatorHeight = Math.max(1, contentHeight - 2)
244
+ const indicatorY = contentY + 1 + Math.floor(scrollPercent * indicatorHeight)
245
+ const indicatorX = contentX + contentWidth - 1
246
+
247
+ this.frameBuffer.drawText("█", indicatorX, indicatorY, parseColor("#666666"))
248
+ }
249
+
250
+ public get options(): SelectOption[] {
251
+ return this._options
252
+ }
253
+
254
+ public set options(options: SelectOption[]) {
255
+ this._options = options
256
+ this._selectedIndex = Math.min(this._selectedIndex, Math.max(0, options.length - 1))
257
+ this.updateScrollOffset()
258
+ this.requestRender()
259
+ }
260
+
261
+ public getSelectedOption(): SelectOption | null {
262
+ return this._options[this._selectedIndex] || null
263
+ }
264
+
265
+ public getSelectedIndex(): number {
266
+ return this._selectedIndex
267
+ }
268
+
269
+ public moveUp(steps: number = 1): void {
270
+ const newIndex = this._selectedIndex - steps
271
+
272
+ if (newIndex >= 0) {
273
+ this._selectedIndex = newIndex
274
+ } else if (this._wrapSelection && this._options.length > 0) {
275
+ this._selectedIndex = this._options.length - 1
276
+ } else {
277
+ this._selectedIndex = 0
278
+ }
279
+
280
+ this.updateScrollOffset()
281
+ this.requestRender()
282
+ this.emit(SelectRenderableEvents.SELECTION_CHANGED, this._selectedIndex, this.getSelectedOption())
283
+ }
284
+
285
+ public moveDown(steps: number = 1): void {
286
+ const newIndex = this._selectedIndex + steps
287
+
288
+ if (newIndex < this._options.length) {
289
+ this._selectedIndex = newIndex
290
+ } else if (this._wrapSelection && this._options.length > 0) {
291
+ this._selectedIndex = 0
292
+ } else {
293
+ this._selectedIndex = this._options.length - 1
294
+ }
295
+
296
+ this.updateScrollOffset()
297
+ this.requestRender()
298
+ this.emit(SelectRenderableEvents.SELECTION_CHANGED, this._selectedIndex, this.getSelectedOption())
299
+ }
300
+
301
+ public selectCurrent(): void {
302
+ const selected = this.getSelectedOption()
303
+ if (selected) {
304
+ this.emit(SelectRenderableEvents.ITEM_SELECTED, this._selectedIndex, selected)
305
+ }
306
+ }
307
+
308
+ public setSelectedIndex(index: number): void {
309
+ if (index >= 0 && index < this._options.length) {
310
+ this._selectedIndex = index
311
+ this.updateScrollOffset()
312
+ this.requestRender()
313
+ this.emit(SelectRenderableEvents.SELECTION_CHANGED, this._selectedIndex, this.getSelectedOption())
314
+ }
315
+ }
316
+
317
+ private updateScrollOffset(): void {
318
+ if (!this._options) return
319
+
320
+ const halfVisible = Math.floor(this.maxVisibleItems / 2)
321
+ const newScrollOffset = Math.max(
322
+ 0,
323
+ Math.min(this._selectedIndex - halfVisible, this._options.length - this.maxVisibleItems),
324
+ )
325
+
326
+ if (newScrollOffset !== this.scrollOffset) {
327
+ this.scrollOffset = newScrollOffset
328
+ this.requestRender()
329
+ }
330
+ }
331
+
332
+ protected onResize(width: number, height: number): void {
333
+ this.maxVisibleItems = Math.max(1, Math.floor(height / this.linesPerItem))
334
+ this.updateScrollOffset()
335
+ this.requestRender()
336
+ }
337
+
338
+ public handleKeyPress(key: KeyEvent): boolean {
339
+ const action = getKeyBindingAction(this._keyBindingsMap, key)
340
+
341
+ if (action) {
342
+ switch (action) {
343
+ case "move-up":
344
+ this.moveUp(1)
345
+ return true
346
+ case "move-down":
347
+ this.moveDown(1)
348
+ return true
349
+ case "move-up-fast":
350
+ this.moveUp(this._fastScrollStep)
351
+ return true
352
+ case "move-down-fast":
353
+ this.moveDown(this._fastScrollStep)
354
+ return true
355
+ case "select-current":
356
+ this.selectCurrent()
357
+ return true
358
+ }
359
+ }
360
+
361
+ return false
362
+ }
363
+
364
+ public get showScrollIndicator(): boolean {
365
+ return this._showScrollIndicator
366
+ }
367
+
368
+ public set showScrollIndicator(show: boolean) {
369
+ this._showScrollIndicator = show
370
+ this.requestRender()
371
+ }
372
+
373
+ public get showDescription(): boolean {
374
+ return this._showDescription
375
+ }
376
+
377
+ public set showDescription(show: boolean) {
378
+ if (this._showDescription !== show) {
379
+ this._showDescription = show
380
+ this.linesPerItem = this._showDescription
381
+ ? this._font
382
+ ? this.fontHeight + 1
383
+ : 2
384
+ : this._font
385
+ ? this.fontHeight
386
+ : 1
387
+ this.linesPerItem += this._itemSpacing
388
+
389
+ this.maxVisibleItems = Math.max(1, Math.floor(this.height / this.linesPerItem))
390
+ this.updateScrollOffset()
391
+ this.requestRender()
392
+ }
393
+ }
394
+
395
+ public get showSelectionIndicator(): boolean {
396
+ return this._showSelectionIndicator
397
+ }
398
+
399
+ public set showSelectionIndicator(show: boolean | null | undefined) {
400
+ const next = show ?? this._defaultOptions.showSelectionIndicator
401
+ if (this._showSelectionIndicator !== next) {
402
+ this._showSelectionIndicator = next
403
+ this.requestRender()
404
+ }
405
+ }
406
+
407
+ public get wrapSelection(): boolean {
408
+ return this._wrapSelection
409
+ }
410
+
411
+ public set wrapSelection(wrap: boolean) {
412
+ this._wrapSelection = wrap
413
+ }
414
+
415
+ public set backgroundColor(value: ColorInput) {
416
+ const newColor = parseColor(value ?? this._defaultOptions.backgroundColor)
417
+ if (this._backgroundColor !== newColor) {
418
+ this._backgroundColor = newColor
419
+ this.requestRender()
420
+ }
421
+ }
422
+
423
+ public set textColor(value: ColorInput) {
424
+ const newColor = parseColor(value ?? this._defaultOptions.textColor)
425
+ if (this._textColor !== newColor) {
426
+ this._textColor = newColor
427
+ this.requestRender()
428
+ }
429
+ }
430
+
431
+ public set focusedBackgroundColor(value: ColorInput) {
432
+ const newColor = parseColor(value ?? this._defaultOptions.focusedBackgroundColor)
433
+ if (this._focusedBackgroundColor !== newColor) {
434
+ this._focusedBackgroundColor = newColor
435
+ this.requestRender()
436
+ }
437
+ }
438
+
439
+ public set focusedTextColor(value: ColorInput) {
440
+ const newColor = parseColor(value ?? this._defaultOptions.focusedTextColor)
441
+ if (this._focusedTextColor !== newColor) {
442
+ this._focusedTextColor = newColor
443
+ this.requestRender()
444
+ }
445
+ }
446
+
447
+ public set selectedBackgroundColor(value: ColorInput) {
448
+ const newColor = parseColor(value ?? this._defaultOptions.selectedBackgroundColor)
449
+ if (this._selectedBackgroundColor !== newColor) {
450
+ this._selectedBackgroundColor = newColor
451
+ this.requestRender()
452
+ }
453
+ }
454
+
455
+ public set selectedTextColor(value: ColorInput) {
456
+ const newColor = parseColor(value ?? this._defaultOptions.selectedTextColor)
457
+ if (this._selectedTextColor !== newColor) {
458
+ this._selectedTextColor = newColor
459
+ this.requestRender()
460
+ }
461
+ }
462
+
463
+ public set descriptionColor(value: ColorInput) {
464
+ const newColor = parseColor(value ?? this._defaultOptions.descriptionColor)
465
+ if (this._descriptionColor !== newColor) {
466
+ this._descriptionColor = newColor
467
+ this.requestRender()
468
+ }
469
+ }
470
+
471
+ public set selectedDescriptionColor(value: ColorInput) {
472
+ const newColor = parseColor(value ?? this._defaultOptions.selectedDescriptionColor)
473
+ if (this._selectedDescriptionColor !== newColor) {
474
+ this._selectedDescriptionColor = newColor
475
+ this.requestRender()
476
+ }
477
+ }
478
+
479
+ public set font(font: keyof typeof fonts) {
480
+ this._font = font
481
+ this.fontHeight = measureText({ text: "A", font: this._font }).height
482
+ this.linesPerItem = this._showDescription
483
+ ? this._font
484
+ ? this.fontHeight + 1
485
+ : 2
486
+ : this._font
487
+ ? this.fontHeight
488
+ : 1
489
+ this.linesPerItem += this._itemSpacing
490
+ this.maxVisibleItems = Math.max(1, Math.floor(this.height / this.linesPerItem))
491
+ this.updateScrollOffset()
492
+ this.requestRender()
493
+ }
494
+
495
+ public set itemSpacing(spacing: number) {
496
+ this._itemSpacing = spacing
497
+ this.linesPerItem = this._showDescription
498
+ ? this._font
499
+ ? this.fontHeight + 1
500
+ : 2
501
+ : this._font
502
+ ? this.fontHeight
503
+ : 1
504
+ this.linesPerItem += this._itemSpacing
505
+ this.maxVisibleItems = Math.max(1, Math.floor(this.height / this.linesPerItem))
506
+ this.updateScrollOffset()
507
+ this.requestRender()
508
+ }
509
+
510
+ public set fastScrollStep(step: number) {
511
+ this._fastScrollStep = step
512
+ }
513
+
514
+ public set keyBindings(bindings: SelectKeyBinding[]) {
515
+ this._keyBindings = bindings
516
+ const mergedBindings = mergeKeyBindings(defaultSelectKeybindings, bindings)
517
+ this._keyBindingsMap = buildKeyBindingsMap(mergedBindings, this._keyAliasMap)
518
+ }
519
+
520
+ public set keyAliasMap(aliases: KeyAliasMap) {
521
+ this._keyAliasMap = mergeKeyAliases(defaultKeyAliases, aliases)
522
+ const mergedBindings = mergeKeyBindings(defaultSelectKeybindings, this._keyBindings)
523
+ this._keyBindingsMap = buildKeyBindingsMap(mergedBindings, this._keyAliasMap)
524
+ }
525
+
526
+ public set selectedIndex(value: number) {
527
+ const newIndex = value ?? this._defaultOptions.selectedIndex
528
+ const clampedIndex = this._options.length > 0 ? Math.min(Math.max(0, newIndex), this._options.length - 1) : 0
529
+ if (this._selectedIndex !== clampedIndex) {
530
+ this._selectedIndex = clampedIndex
531
+ this.updateScrollOffset()
532
+ this.requestRender()
533
+ }
534
+ }
535
+ }