@fairyhunter13/opentui-core 0.1.88 → 0.1.90

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