@fairyhunter13/opentui-core 0.1.112 → 0.1.114

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (591) hide show
  1. package/dev/keypress-debug-renderer.ts +148 -0
  2. package/dev/keypress-debug.ts +43 -0
  3. package/dev/print-env-vars.ts +32 -0
  4. package/dev/test-tmux-graphics-334.sh +68 -0
  5. package/dev/thai-debug-test.ts +68 -0
  6. package/docs/development.md +144 -0
  7. package/package.json +63 -51
  8. package/scripts/build.ts +400 -0
  9. package/scripts/publish.ts +60 -0
  10. package/src/3d/SpriteResourceManager.ts +286 -0
  11. package/src/3d/SpriteUtils.ts +70 -0
  12. package/src/3d/TextureUtils.ts +196 -0
  13. package/src/3d/ThreeRenderable.ts +197 -0
  14. package/src/3d/WGPURenderer.ts +294 -0
  15. package/src/3d/animation/ExplodingSpriteEffect.ts +513 -0
  16. package/src/3d/animation/PhysicsExplodingSpriteEffect.ts +429 -0
  17. package/src/3d/animation/SpriteAnimator.ts +633 -0
  18. package/src/3d/animation/SpriteParticleGenerator.ts +435 -0
  19. package/src/3d/canvas.ts +464 -0
  20. package/src/3d/index.ts +12 -0
  21. package/src/3d/physics/PlanckPhysicsAdapter.ts +72 -0
  22. package/src/3d/physics/RapierPhysicsAdapter.ts +66 -0
  23. package/src/3d/physics/physics-interface.ts +31 -0
  24. package/src/3d/shaders/supersampling.wgsl +201 -0
  25. package/src/3d.ts +3 -0
  26. package/src/NativeSpanFeed.ts +300 -0
  27. package/src/Renderable.ts +1704 -0
  28. package/src/__snapshots__/buffer.test.ts.snap +28 -0
  29. package/src/animation/Timeline.test.ts +2709 -0
  30. package/src/animation/Timeline.ts +598 -0
  31. package/src/ansi.ts +18 -0
  32. package/src/benchmark/attenuation-benchmark.ts +81 -0
  33. package/src/benchmark/colormatrix-benchmark.ts +128 -0
  34. package/src/benchmark/gain-benchmark.ts +80 -0
  35. package/src/benchmark/latest-all-bench-run.json +707 -0
  36. package/src/benchmark/latest-async-bench-run.json +336 -0
  37. package/src/benchmark/latest-default-bench-run.json +657 -0
  38. package/src/benchmark/latest-large-bench-run.json +707 -0
  39. package/src/benchmark/latest-quick-bench-run.json +207 -0
  40. package/src/benchmark/markdown-benchmark.ts +1796 -0
  41. package/src/benchmark/native-span-feed-async-benchmark.ts +355 -0
  42. package/src/benchmark/native-span-feed-benchmark.md +56 -0
  43. package/src/benchmark/native-span-feed-benchmark.ts +596 -0
  44. package/src/benchmark/native-span-feed-compare.ts +280 -0
  45. package/src/benchmark/renderer-benchmark.ts +754 -0
  46. package/src/benchmark/text-table-benchmark.ts +948 -0
  47. package/src/buffer.test.ts +291 -0
  48. package/src/buffer.ts +554 -0
  49. package/src/console.test.ts +612 -0
  50. package/src/console.ts +1254 -0
  51. package/src/edit-buffer.test.ts +1769 -0
  52. package/src/edit-buffer.ts +411 -0
  53. package/src/editor-view.test.ts +1032 -0
  54. package/src/editor-view.ts +284 -0
  55. package/src/examples/ascii-font-selection-demo.ts +245 -0
  56. package/src/examples/assets/Water_2_M_Normal.jpg +0 -0
  57. package/src/examples/assets/concrete.png +0 -0
  58. package/src/examples/assets/crate.png +0 -0
  59. package/src/examples/assets/crate_emissive.png +0 -0
  60. package/src/examples/assets/forrest_background.png +0 -0
  61. package/src/examples/assets/hast-example.json +1018 -0
  62. package/src/examples/assets/heart.png +0 -0
  63. package/src/examples/assets/main_char_heavy_attack.png +0 -0
  64. package/src/examples/assets/main_char_idle.png +0 -0
  65. package/src/examples/assets/main_char_jump_end.png +0 -0
  66. package/src/examples/assets/main_char_jump_landing.png +0 -0
  67. package/src/examples/assets/main_char_jump_start.png +0 -0
  68. package/src/examples/assets/main_char_run_loop.png +0 -0
  69. package/src/examples/assets/roughness_map.jpg +0 -0
  70. package/src/examples/build.ts +115 -0
  71. package/src/examples/code-demo.ts +924 -0
  72. package/src/examples/console-demo.ts +358 -0
  73. package/src/examples/core-plugin-slots-demo.ts +759 -0
  74. package/src/examples/diff-demo.ts +701 -0
  75. package/src/examples/draggable-three-demo.ts +259 -0
  76. package/src/examples/editor-demo.ts +322 -0
  77. package/src/examples/extmarks-demo.ts +196 -0
  78. package/src/examples/focus-restore-demo.ts +310 -0
  79. package/src/examples/fonts.ts +245 -0
  80. package/src/examples/fractal-shader-demo.ts +268 -0
  81. package/src/examples/framebuffer-demo.ts +674 -0
  82. package/src/examples/full-unicode-demo.ts +241 -0
  83. package/src/examples/golden-star-demo.ts +933 -0
  84. package/src/examples/grayscale-buffer-demo.ts +249 -0
  85. package/src/examples/hast-syntax-highlighting-demo.ts +129 -0
  86. package/src/examples/index.ts +926 -0
  87. package/src/examples/input-demo.ts +377 -0
  88. package/src/examples/input-select-layout-demo.ts +425 -0
  89. package/src/examples/install.sh +143 -0
  90. package/src/examples/keypress-debug-demo.ts +452 -0
  91. package/src/examples/lib/HexList.ts +122 -0
  92. package/src/examples/lib/PaletteGrid.ts +125 -0
  93. package/src/examples/lib/standalone-keys.ts +25 -0
  94. package/src/examples/lib/tab-controller.ts +243 -0
  95. package/src/examples/lights-phong-demo.ts +290 -0
  96. package/src/examples/link-demo.ts +220 -0
  97. package/src/examples/live-state-demo.ts +480 -0
  98. package/src/examples/markdown-demo.ts +725 -0
  99. package/src/examples/mouse-interaction-demo.ts +428 -0
  100. package/src/examples/nested-zindex-demo.ts +357 -0
  101. package/src/examples/opacity-example.ts +235 -0
  102. package/src/examples/opentui-demo.ts +1057 -0
  103. package/src/examples/physx-planck-2d-demo.ts +623 -0
  104. package/src/examples/physx-rapier-2d-demo.ts +655 -0
  105. package/src/examples/relative-positioning-demo.ts +323 -0
  106. package/src/examples/scroll-example.ts +214 -0
  107. package/src/examples/scrollbox-mouse-test.ts +112 -0
  108. package/src/examples/scrollbox-overlay-hit-test.ts +206 -0
  109. package/src/examples/select-demo.ts +237 -0
  110. package/src/examples/shader-cube-demo.ts +1015 -0
  111. package/src/examples/simple-layout-example.ts +591 -0
  112. package/src/examples/slider-demo.ts +617 -0
  113. package/src/examples/split-mode-demo.ts +453 -0
  114. package/src/examples/sprite-animation-demo.ts +443 -0
  115. package/src/examples/sprite-particle-generator-demo.ts +486 -0
  116. package/src/examples/static-sprite-demo.ts +193 -0
  117. package/src/examples/sticky-scroll-example.ts +308 -0
  118. package/src/examples/styled-text-demo.ts +282 -0
  119. package/src/examples/tab-select-demo.ts +219 -0
  120. package/src/examples/terminal-title.ts +29 -0
  121. package/src/examples/terminal.ts +305 -0
  122. package/src/examples/text-node-demo.ts +416 -0
  123. package/src/examples/text-selection-demo.ts +377 -0
  124. package/src/examples/text-table-demo.ts +503 -0
  125. package/src/examples/text-truncation-demo.ts +481 -0
  126. package/src/examples/text-wrap.ts +757 -0
  127. package/src/examples/texture-loading-demo.ts +259 -0
  128. package/src/examples/timeline-example.ts +670 -0
  129. package/src/examples/transparency-demo.ts +400 -0
  130. package/src/examples/vnode-composition-demo.ts +404 -0
  131. package/src/examples/wide-grapheme-overlay-demo.ts +280 -0
  132. package/src/index.ts +24 -0
  133. package/src/lib/KeyHandler.integration.test.ts +292 -0
  134. package/src/lib/KeyHandler.stopPropagation.test.ts +289 -0
  135. package/src/lib/KeyHandler.test.ts +662 -0
  136. package/src/lib/KeyHandler.ts +222 -0
  137. package/src/lib/RGBA.test.ts +984 -0
  138. package/src/lib/RGBA.ts +204 -0
  139. package/src/lib/ascii.font.ts +330 -0
  140. package/src/lib/border.test.ts +83 -0
  141. package/src/lib/border.ts +170 -0
  142. package/src/lib/bunfs.test.ts +27 -0
  143. package/src/lib/bunfs.ts +18 -0
  144. package/src/lib/clipboard.test.ts +41 -0
  145. package/src/lib/clipboard.ts +47 -0
  146. package/src/lib/clock.ts +35 -0
  147. package/src/lib/data-paths.test.ts +133 -0
  148. package/src/lib/data-paths.ts +109 -0
  149. package/src/lib/debounce.ts +106 -0
  150. package/src/lib/detect-links.test.ts +98 -0
  151. package/src/lib/detect-links.ts +56 -0
  152. package/src/lib/env.test.ts +228 -0
  153. package/src/lib/env.ts +209 -0
  154. package/src/lib/extmarks-history.ts +51 -0
  155. package/src/lib/extmarks-multiwidth.test.ts +322 -0
  156. package/src/lib/extmarks.test.ts +3457 -0
  157. package/src/lib/extmarks.ts +843 -0
  158. package/src/lib/fonts/block.json +405 -0
  159. package/src/lib/fonts/grid.json +265 -0
  160. package/src/lib/fonts/huge.json +741 -0
  161. package/src/lib/fonts/pallet.json +314 -0
  162. package/src/lib/fonts/shade.json +591 -0
  163. package/src/lib/fonts/slick.json +321 -0
  164. package/src/lib/fonts/tiny.json +69 -0
  165. package/src/lib/hast-styled-text.ts +59 -0
  166. package/src/lib/index.ts +21 -0
  167. package/src/lib/keymapping.test.ts +317 -0
  168. package/src/lib/keymapping.ts +115 -0
  169. package/src/lib/objects-in-viewport.test.ts +787 -0
  170. package/src/lib/objects-in-viewport.ts +153 -0
  171. package/src/lib/output.capture.ts +58 -0
  172. package/src/lib/parse.keypress-kitty.protocol.test.ts +340 -0
  173. package/src/lib/parse.keypress-kitty.test.ts +663 -0
  174. package/src/lib/parse.keypress-kitty.ts +439 -0
  175. package/src/lib/parse.keypress.test.ts +1849 -0
  176. package/src/lib/parse.keypress.ts +397 -0
  177. package/src/lib/parse.mouse.test.ts +552 -0
  178. package/src/lib/parse.mouse.ts +232 -0
  179. package/src/lib/paste.ts +16 -0
  180. package/src/lib/queue.ts +65 -0
  181. package/src/lib/renderable.validations.test.ts +87 -0
  182. package/src/lib/renderable.validations.ts +83 -0
  183. package/src/lib/scroll-acceleration.ts +98 -0
  184. package/src/lib/selection.ts +240 -0
  185. package/src/lib/singleton.ts +28 -0
  186. package/src/lib/stdin-parser.test.ts +2290 -0
  187. package/src/lib/stdin-parser.ts +1810 -0
  188. package/src/lib/styled-text.ts +178 -0
  189. package/src/lib/terminal-capability-detection.test.ts +202 -0
  190. package/src/lib/terminal-capability-detection.ts +79 -0
  191. package/src/lib/terminal-palette.test.ts +878 -0
  192. package/src/lib/terminal-palette.ts +383 -0
  193. package/src/lib/tree-sitter/assets/README.md +118 -0
  194. package/src/lib/tree-sitter/assets/update.ts +334 -0
  195. package/src/lib/tree-sitter/assets.d.ts +9 -0
  196. package/src/lib/tree-sitter/cache.test.ts +273 -0
  197. package/src/lib/tree-sitter/client.test.ts +1165 -0
  198. package/src/lib/tree-sitter/client.ts +607 -0
  199. package/src/lib/tree-sitter/default-parsers.ts +86 -0
  200. package/src/lib/tree-sitter/download-utils.ts +148 -0
  201. package/src/lib/tree-sitter/index.ts +28 -0
  202. package/src/lib/tree-sitter/parser.worker.ts +1042 -0
  203. package/src/lib/tree-sitter/parsers-config.ts +81 -0
  204. package/src/lib/tree-sitter/resolve-ft.test.ts +55 -0
  205. package/src/lib/tree-sitter/resolve-ft.ts +189 -0
  206. package/src/lib/tree-sitter/types.ts +82 -0
  207. package/src/lib/tree-sitter-styled-text.test.ts +1253 -0
  208. package/src/lib/tree-sitter-styled-text.ts +306 -0
  209. package/src/lib/validate-dir-name.ts +55 -0
  210. package/src/lib/yoga.options.test.ts +628 -0
  211. package/src/lib/yoga.options.ts +346 -0
  212. package/src/plugins/core-slot.ts +579 -0
  213. package/src/plugins/registry.ts +402 -0
  214. package/src/plugins/types.ts +46 -0
  215. package/src/post/effects.ts +930 -0
  216. package/src/post/filters.ts +489 -0
  217. package/src/post/matrices.ts +288 -0
  218. package/src/renderables/ASCIIFont.ts +219 -0
  219. package/src/renderables/Box.test.ts +205 -0
  220. package/src/renderables/Box.ts +326 -0
  221. package/src/renderables/Code.test.ts +2062 -0
  222. package/src/renderables/Code.ts +357 -0
  223. package/src/renderables/Diff.regression.test.ts +226 -0
  224. package/src/renderables/Diff.test.ts +3101 -0
  225. package/src/renderables/Diff.ts +1211 -0
  226. package/src/renderables/EditBufferRenderable.test.ts +288 -0
  227. package/src/renderables/EditBufferRenderable.ts +1166 -0
  228. package/src/renderables/FrameBuffer.ts +47 -0
  229. package/src/renderables/Input.test.ts +1228 -0
  230. package/src/renderables/Input.ts +247 -0
  231. package/src/renderables/LineNumberRenderable.ts +724 -0
  232. package/src/renderables/Markdown.ts +1393 -0
  233. package/src/renderables/ScrollBar.ts +422 -0
  234. package/src/renderables/ScrollBox.ts +883 -0
  235. package/src/renderables/Select.test.ts +1033 -0
  236. package/src/renderables/Select.ts +524 -0
  237. package/src/renderables/Slider.test.ts +456 -0
  238. package/src/renderables/Slider.ts +342 -0
  239. package/src/renderables/TabSelect.test.ts +197 -0
  240. package/src/renderables/TabSelect.ts +455 -0
  241. package/src/renderables/Text.selection-buffer.test.ts +123 -0
  242. package/src/renderables/Text.test.ts +2660 -0
  243. package/src/renderables/Text.ts +147 -0
  244. package/src/renderables/TextBufferRenderable.ts +518 -0
  245. package/src/renderables/TextNode.test.ts +1058 -0
  246. package/src/renderables/TextNode.ts +325 -0
  247. package/src/renderables/TextTable.test.ts +1421 -0
  248. package/src/renderables/TextTable.ts +1344 -0
  249. package/src/renderables/Textarea.ts +430 -0
  250. package/src/renderables/TimeToFirstDraw.ts +89 -0
  251. package/src/renderables/__snapshots__/Code.test.ts.snap +13 -0
  252. package/src/renderables/__snapshots__/Diff.test.ts.snap +785 -0
  253. package/src/renderables/__snapshots__/Text.test.ts.snap +421 -0
  254. package/src/renderables/__snapshots__/TextTable.test.ts.snap +215 -0
  255. package/src/renderables/__tests__/LineNumberRenderable.scrollbox-simple.test.ts +144 -0
  256. package/src/renderables/__tests__/LineNumberRenderable.scrollbox.test.ts +816 -0
  257. package/src/renderables/__tests__/LineNumberRenderable.test.ts +1865 -0
  258. package/src/renderables/__tests__/LineNumberRenderable.wrapping.test.ts +85 -0
  259. package/src/renderables/__tests__/Markdown.code-colors.test.ts +242 -0
  260. package/src/renderables/__tests__/Markdown.test.ts +2518 -0
  261. package/src/renderables/__tests__/MultiRenderable.selection.test.ts +87 -0
  262. package/src/renderables/__tests__/Textarea.buffer.test.ts +682 -0
  263. package/src/renderables/__tests__/Textarea.destroyed-events.test.ts +675 -0
  264. package/src/renderables/__tests__/Textarea.editing.test.ts +2041 -0
  265. package/src/renderables/__tests__/Textarea.error-handling.test.ts +35 -0
  266. package/src/renderables/__tests__/Textarea.events.test.ts +738 -0
  267. package/src/renderables/__tests__/Textarea.highlights.test.ts +590 -0
  268. package/src/renderables/__tests__/Textarea.keybinding.test.ts +3149 -0
  269. package/src/renderables/__tests__/Textarea.paste.test.ts +357 -0
  270. package/src/renderables/__tests__/Textarea.rendering.test.ts +1866 -0
  271. package/src/renderables/__tests__/Textarea.scroll.test.ts +733 -0
  272. package/src/renderables/__tests__/Textarea.selection.test.ts +1590 -0
  273. package/src/renderables/__tests__/Textarea.stress.test.ts +670 -0
  274. package/src/renderables/__tests__/Textarea.undo-redo.test.ts +383 -0
  275. package/src/renderables/__tests__/Textarea.visual-lines.test.ts +310 -0
  276. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.code.test.ts.snap +221 -0
  277. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox-simple.test.ts.snap +89 -0
  278. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox.test.ts.snap +457 -0
  279. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.test.ts.snap +158 -0
  280. package/src/renderables/__tests__/__snapshots__/Textarea.rendering.test.ts.snap +387 -0
  281. package/src/renderables/__tests__/markdown-parser.test.ts +217 -0
  282. package/src/renderables/__tests__/renderable-test-utils.ts +60 -0
  283. package/src/renderables/composition/README.md +8 -0
  284. package/src/renderables/composition/VRenderable.ts +32 -0
  285. package/src/renderables/composition/constructs.ts +127 -0
  286. package/src/renderables/composition/vnode.ts +289 -0
  287. package/src/renderables/index.ts +23 -0
  288. package/src/renderables/markdown-parser.ts +66 -0
  289. package/src/renderer.ts +2681 -0
  290. package/src/runtime-plugin-support.ts +39 -0
  291. package/src/runtime-plugin.ts +615 -0
  292. package/src/syntax-style.test.ts +841 -0
  293. package/src/syntax-style.ts +257 -0
  294. package/src/testing/README.md +210 -0
  295. package/src/testing/capture-spans.test.ts +194 -0
  296. package/src/testing/integration.test.ts +276 -0
  297. package/src/testing/manual-clock.ts +117 -0
  298. package/src/testing/mock-keys.test.ts +1378 -0
  299. package/src/testing/mock-keys.ts +457 -0
  300. package/src/testing/mock-mouse.test.ts +218 -0
  301. package/src/testing/mock-mouse.ts +247 -0
  302. package/src/testing/mock-tree-sitter-client.ts +73 -0
  303. package/src/testing/spy.ts +13 -0
  304. package/src/testing/test-recorder.test.ts +415 -0
  305. package/src/testing/test-recorder.ts +145 -0
  306. package/src/testing/test-renderer.ts +132 -0
  307. package/src/testing.ts +7 -0
  308. package/src/tests/__snapshots__/absolute-positioning.snapshot.test.ts.snap +481 -0
  309. package/src/tests/__snapshots__/renderable.snapshot.test.ts.snap +19 -0
  310. package/src/tests/__snapshots__/scrollbox.test.ts.snap +29 -0
  311. package/src/tests/absolute-positioning.snapshot.test.ts +638 -0
  312. package/src/tests/allocator-stats.test.ts +38 -0
  313. package/src/tests/destroy-during-render.test.ts +200 -0
  314. package/src/tests/destroy-on-exit.fixture.ts +36 -0
  315. package/src/tests/destroy-on-exit.test.ts +41 -0
  316. package/src/tests/hover-cursor.test.ts +98 -0
  317. package/src/tests/native-span-feed-async.test.ts +173 -0
  318. package/src/tests/native-span-feed-close.test.ts +120 -0
  319. package/src/tests/native-span-feed-coverage.test.ts +227 -0
  320. package/src/tests/native-span-feed-edge-cases.test.ts +352 -0
  321. package/src/tests/native-span-feed-use-after-free.test.ts +45 -0
  322. package/src/tests/opacity.test.ts +123 -0
  323. package/src/tests/renderable.snapshot.test.ts +524 -0
  324. package/src/tests/renderable.test.ts +1281 -0
  325. package/src/tests/renderer.clock.test.ts +158 -0
  326. package/src/tests/renderer.console-startup.test.ts +185 -0
  327. package/src/tests/renderer.control.test.ts +425 -0
  328. package/src/tests/renderer.core-slot-binding.test.ts +952 -0
  329. package/src/tests/renderer.cursor.test.ts +26 -0
  330. package/src/tests/renderer.destroy-during-render.test.ts +147 -0
  331. package/src/tests/renderer.focus-restore.test.ts +257 -0
  332. package/src/tests/renderer.focus.test.ts +294 -0
  333. package/src/tests/renderer.idle.test.ts +219 -0
  334. package/src/tests/renderer.input.test.ts +2237 -0
  335. package/src/tests/renderer.kitty-flags.test.ts +195 -0
  336. package/src/tests/renderer.mouse.test.ts +1274 -0
  337. package/src/tests/renderer.palette.test.ts +629 -0
  338. package/src/tests/renderer.selection.test.ts +49 -0
  339. package/src/tests/renderer.slot-registry.test.ts +684 -0
  340. package/src/tests/renderer.useMouse.test.ts +47 -0
  341. package/src/tests/runtime-plugin-node-modules-cycle.fixture.ts +76 -0
  342. package/src/tests/runtime-plugin-node-modules-mjs.fixture.ts +43 -0
  343. package/src/tests/runtime-plugin-node-modules-no-bare-rewrite.fixture.ts +67 -0
  344. package/src/tests/runtime-plugin-node-modules-package-type-cache.fixture.ts +72 -0
  345. package/src/tests/runtime-plugin-node-modules-runtime-specifier.fixture.ts +44 -0
  346. package/src/tests/runtime-plugin-node-modules-scoped-package-bare-rewrite.fixture.ts +85 -0
  347. package/src/tests/runtime-plugin-path-alias.fixture.ts +43 -0
  348. package/src/tests/runtime-plugin-resolve-roots.fixture.ts +65 -0
  349. package/src/tests/runtime-plugin-support.fixture.ts +11 -0
  350. package/src/tests/runtime-plugin-support.test.ts +19 -0
  351. package/src/tests/runtime-plugin-windows-file-url.fixture.ts +30 -0
  352. package/src/tests/runtime-plugin.fixture.ts +40 -0
  353. package/src/tests/runtime-plugin.test.ts +354 -0
  354. package/src/tests/scrollbox-culling-bug.test.ts +114 -0
  355. package/src/tests/scrollbox-hitgrid-resize.test.ts +136 -0
  356. package/src/tests/scrollbox-hitgrid.test.ts +909 -0
  357. package/src/tests/scrollbox.test.ts +1530 -0
  358. package/src/tests/wrap-resize-perf.test.ts +276 -0
  359. package/src/tests/yoga-setters.test.ts +921 -0
  360. package/src/text-buffer-view.test.ts +705 -0
  361. package/src/text-buffer-view.ts +189 -0
  362. package/src/text-buffer.test.ts +347 -0
  363. package/src/text-buffer.ts +250 -0
  364. package/src/types.ts +161 -0
  365. package/src/utils.ts +88 -0
  366. package/src/zig/ansi.zig +268 -0
  367. package/src/zig/bench/README.md +50 -0
  368. package/src/zig/bench/buffer-draw-text-buffer_bench.zig +887 -0
  369. package/src/zig/bench/edit-buffer_bench.zig +476 -0
  370. package/src/zig/bench/native-span-feed_bench.zig +100 -0
  371. package/src/zig/bench/rope-markers_bench.zig +713 -0
  372. package/src/zig/bench/rope_bench.zig +514 -0
  373. package/src/zig/bench/styled-text_bench.zig +470 -0
  374. package/src/zig/bench/text-buffer-coords_bench.zig +362 -0
  375. package/src/zig/bench/text-buffer-view_bench.zig +459 -0
  376. package/src/zig/bench/text-chunk-graphemes_bench.zig +273 -0
  377. package/src/zig/bench/utf8_bench.zig +799 -0
  378. package/src/zig/bench-utils.zig +431 -0
  379. package/src/zig/bench.zig +217 -0
  380. package/src/zig/buffer-methods.zig +211 -0
  381. package/src/zig/buffer.zig +2281 -0
  382. package/src/zig/build.zig +289 -0
  383. package/src/zig/build.zig.zon +16 -0
  384. package/src/zig/edit-buffer.zig +825 -0
  385. package/src/zig/editor-view.zig +802 -0
  386. package/src/zig/event-bus.zig +13 -0
  387. package/src/zig/event-emitter.zig +65 -0
  388. package/src/zig/file-logger.zig +92 -0
  389. package/src/zig/grapheme.zig +599 -0
  390. package/src/zig/lib.zig +1854 -0
  391. package/src/zig/link.zig +333 -0
  392. package/src/zig/logger.zig +43 -0
  393. package/src/zig/mem-registry.zig +125 -0
  394. package/src/zig/native-span-feed-bench-lib.zig +7 -0
  395. package/src/zig/native-span-feed.zig +708 -0
  396. package/src/zig/renderer.zig +1393 -0
  397. package/src/zig/rope.zig +1220 -0
  398. package/src/zig/syntax-style.zig +161 -0
  399. package/src/zig/terminal.zig +987 -0
  400. package/src/zig/test.zig +72 -0
  401. package/src/zig/tests/README.md +18 -0
  402. package/src/zig/tests/buffer-methods_test.zig +1109 -0
  403. package/src/zig/tests/buffer_test.zig +2557 -0
  404. package/src/zig/tests/edit-buffer-history_test.zig +271 -0
  405. package/src/zig/tests/edit-buffer_test.zig +1689 -0
  406. package/src/zig/tests/editor-view_test.zig +3299 -0
  407. package/src/zig/tests/event-emitter_test.zig +249 -0
  408. package/src/zig/tests/grapheme_test.zig +1304 -0
  409. package/src/zig/tests/link_test.zig +190 -0
  410. package/src/zig/tests/mem-registry_test.zig +473 -0
  411. package/src/zig/tests/memory_leak_regression_test.zig +159 -0
  412. package/src/zig/tests/native-span-feed_test.zig +1264 -0
  413. package/src/zig/tests/renderer_test.zig +1017 -0
  414. package/src/zig/tests/rope-nested_test.zig +712 -0
  415. package/src/zig/tests/rope_fuzz_test.zig +238 -0
  416. package/src/zig/tests/rope_test.zig +2362 -0
  417. package/src/zig/tests/segment-merge.test.zig +148 -0
  418. package/src/zig/tests/syntax-style_test.zig +557 -0
  419. package/src/zig/tests/terminal_test.zig +754 -0
  420. package/src/zig/tests/text-buffer-drawing_test.zig +3237 -0
  421. package/src/zig/tests/text-buffer-highlights_test.zig +666 -0
  422. package/src/zig/tests/text-buffer-iterators_test.zig +776 -0
  423. package/src/zig/tests/text-buffer-segment_test.zig +320 -0
  424. package/src/zig/tests/text-buffer-selection_test.zig +1035 -0
  425. package/src/zig/tests/text-buffer-selection_viewport_test.zig +358 -0
  426. package/src/zig/tests/text-buffer-view_test.zig +3649 -0
  427. package/src/zig/tests/text-buffer_test.zig +2191 -0
  428. package/src/zig/tests/unicode-width-map.zon +3909 -0
  429. package/src/zig/tests/utf8_no_zwj_test.zig +260 -0
  430. package/src/zig/tests/utf8_test.zig +4057 -0
  431. package/src/zig/tests/utf8_wcwidth_cursor_test.zig +267 -0
  432. package/src/zig/tests/utf8_wcwidth_test.zig +357 -0
  433. package/src/zig/tests/word-wrap-editing_test.zig +498 -0
  434. package/src/zig/tests/wrap-cache-perf_test.zig +113 -0
  435. package/src/zig/text-buffer-iterators.zig +499 -0
  436. package/src/zig/text-buffer-segment.zig +404 -0
  437. package/src/zig/text-buffer-view.zig +1371 -0
  438. package/src/zig/text-buffer.zig +1180 -0
  439. package/src/zig/utf8.zig +1948 -0
  440. package/src/zig/utils.zig +9 -0
  441. package/src/zig-structs.ts +261 -0
  442. package/src/zig.ts +3884 -0
  443. package/tsconfig.build.json +24 -0
  444. package/tsconfig.json +27 -0
  445. package/3d/SpriteResourceManager.d.ts +0 -74
  446. package/3d/SpriteUtils.d.ts +0 -13
  447. package/3d/TextureUtils.d.ts +0 -24
  448. package/3d/ThreeRenderable.d.ts +0 -40
  449. package/3d/WGPURenderer.d.ts +0 -61
  450. package/3d/animation/ExplodingSpriteEffect.d.ts +0 -71
  451. package/3d/animation/PhysicsExplodingSpriteEffect.d.ts +0 -76
  452. package/3d/animation/SpriteAnimator.d.ts +0 -124
  453. package/3d/animation/SpriteParticleGenerator.d.ts +0 -62
  454. package/3d/canvas.d.ts +0 -44
  455. package/3d/index.d.ts +0 -12
  456. package/3d/physics/PlanckPhysicsAdapter.d.ts +0 -19
  457. package/3d/physics/RapierPhysicsAdapter.d.ts +0 -19
  458. package/3d/physics/physics-interface.d.ts +0 -27
  459. package/3d.d.ts +0 -2
  460. package/3d.js +0 -34041
  461. package/3d.js.map +0 -155
  462. package/LICENSE +0 -21
  463. package/NativeSpanFeed.d.ts +0 -41
  464. package/Renderable.d.ts +0 -334
  465. package/animation/Timeline.d.ts +0 -126
  466. package/ansi.d.ts +0 -13
  467. package/buffer.d.ts +0 -111
  468. package/console.d.ts +0 -144
  469. package/edit-buffer.d.ts +0 -98
  470. package/editor-view.d.ts +0 -73
  471. package/index-8fks7yv1.js +0 -411
  472. package/index-8fks7yv1.js.map +0 -10
  473. package/index-egy5e2rs.js +0 -12267
  474. package/index-egy5e2rs.js.map +0 -42
  475. package/index-tse8gzh0.js +0 -20614
  476. package/index-tse8gzh0.js.map +0 -67
  477. package/index.d.ts +0 -23
  478. package/index.js +0 -478
  479. package/index.js.map +0 -9
  480. package/lib/KeyHandler.d.ts +0 -61
  481. package/lib/RGBA.d.ts +0 -25
  482. package/lib/ascii.font.d.ts +0 -508
  483. package/lib/border.d.ts +0 -51
  484. package/lib/bunfs.d.ts +0 -7
  485. package/lib/clipboard.d.ts +0 -17
  486. package/lib/clock.d.ts +0 -15
  487. package/lib/data-paths.d.ts +0 -26
  488. package/lib/debounce.d.ts +0 -42
  489. package/lib/detect-links.d.ts +0 -6
  490. package/lib/env.d.ts +0 -42
  491. package/lib/extmarks-history.d.ts +0 -17
  492. package/lib/extmarks.d.ts +0 -89
  493. package/lib/hast-styled-text.d.ts +0 -17
  494. package/lib/index.d.ts +0 -21
  495. package/lib/keymapping.d.ts +0 -25
  496. package/lib/objects-in-viewport.d.ts +0 -24
  497. package/lib/output.capture.d.ts +0 -24
  498. package/lib/parse.keypress-kitty.d.ts +0 -2
  499. package/lib/parse.keypress.d.ts +0 -26
  500. package/lib/parse.mouse.d.ts +0 -30
  501. package/lib/paste.d.ts +0 -7
  502. package/lib/queue.d.ts +0 -15
  503. package/lib/renderable.validations.d.ts +0 -12
  504. package/lib/scroll-acceleration.d.ts +0 -43
  505. package/lib/selection.d.ts +0 -63
  506. package/lib/singleton.d.ts +0 -7
  507. package/lib/stdin-parser.d.ts +0 -87
  508. package/lib/styled-text.d.ts +0 -63
  509. package/lib/terminal-capability-detection.d.ts +0 -30
  510. package/lib/terminal-palette.d.ts +0 -50
  511. package/lib/tree-sitter/assets/update.d.ts +0 -11
  512. package/lib/tree-sitter/client.d.ts +0 -47
  513. package/lib/tree-sitter/default-parsers.d.ts +0 -2
  514. package/lib/tree-sitter/download-utils.d.ts +0 -21
  515. package/lib/tree-sitter/index.d.ts +0 -8
  516. package/lib/tree-sitter/parser.worker.d.ts +0 -1
  517. package/lib/tree-sitter/parsers-config.d.ts +0 -53
  518. package/lib/tree-sitter/resolve-ft.d.ts +0 -5
  519. package/lib/tree-sitter/types.d.ts +0 -82
  520. package/lib/tree-sitter-styled-text.d.ts +0 -14
  521. package/lib/validate-dir-name.d.ts +0 -1
  522. package/lib/yoga.options.d.ts +0 -32
  523. package/parser.worker.js +0 -899
  524. package/parser.worker.js.map +0 -12
  525. package/plugins/core-slot.d.ts +0 -72
  526. package/plugins/registry.d.ts +0 -42
  527. package/plugins/types.d.ts +0 -34
  528. package/post/effects.d.ts +0 -147
  529. package/post/filters.d.ts +0 -65
  530. package/post/matrices.d.ts +0 -20
  531. package/renderables/ASCIIFont.d.ts +0 -52
  532. package/renderables/Box.d.ts +0 -81
  533. package/renderables/Code.d.ts +0 -78
  534. package/renderables/Diff.d.ts +0 -142
  535. package/renderables/EditBufferRenderable.d.ts +0 -237
  536. package/renderables/FrameBuffer.d.ts +0 -16
  537. package/renderables/Input.d.ts +0 -67
  538. package/renderables/LineNumberRenderable.d.ts +0 -78
  539. package/renderables/Markdown.d.ts +0 -185
  540. package/renderables/ScrollBar.d.ts +0 -77
  541. package/renderables/ScrollBox.d.ts +0 -124
  542. package/renderables/Select.d.ts +0 -115
  543. package/renderables/Slider.d.ts +0 -47
  544. package/renderables/TabSelect.d.ts +0 -96
  545. package/renderables/Text.d.ts +0 -36
  546. package/renderables/TextBufferRenderable.d.ts +0 -105
  547. package/renderables/TextNode.d.ts +0 -91
  548. package/renderables/TextTable.d.ts +0 -140
  549. package/renderables/Textarea.d.ts +0 -63
  550. package/renderables/TimeToFirstDraw.d.ts +0 -24
  551. package/renderables/__tests__/renderable-test-utils.d.ts +0 -12
  552. package/renderables/composition/VRenderable.d.ts +0 -16
  553. package/renderables/composition/constructs.d.ts +0 -35
  554. package/renderables/composition/vnode.d.ts +0 -46
  555. package/renderables/index.d.ts +0 -23
  556. package/renderables/markdown-parser.d.ts +0 -10
  557. package/renderer.d.ts +0 -419
  558. package/runtime-plugin-support.d.ts +0 -3
  559. package/runtime-plugin-support.js +0 -29
  560. package/runtime-plugin-support.js.map +0 -10
  561. package/runtime-plugin.d.ts +0 -16
  562. package/runtime-plugin.js +0 -16
  563. package/runtime-plugin.js.map +0 -9
  564. package/syntax-style.d.ts +0 -54
  565. package/testing/manual-clock.d.ts +0 -17
  566. package/testing/mock-keys.d.ts +0 -81
  567. package/testing/mock-mouse.d.ts +0 -38
  568. package/testing/mock-tree-sitter-client.d.ts +0 -23
  569. package/testing/spy.d.ts +0 -7
  570. package/testing/test-recorder.d.ts +0 -61
  571. package/testing/test-renderer.d.ts +0 -23
  572. package/testing.d.ts +0 -6
  573. package/testing.js +0 -697
  574. package/testing.js.map +0 -15
  575. package/text-buffer-view.d.ts +0 -42
  576. package/text-buffer.d.ts +0 -67
  577. package/types.d.ts +0 -139
  578. package/utils.d.ts +0 -14
  579. package/zig-structs.d.ts +0 -155
  580. package/zig.d.ts +0 -353
  581. /package/{assets → src/lib/tree-sitter/assets}/javascript/highlights.scm +0 -0
  582. /package/{assets → src/lib/tree-sitter/assets}/javascript/tree-sitter-javascript.wasm +0 -0
  583. /package/{assets → src/lib/tree-sitter/assets}/markdown/highlights.scm +0 -0
  584. /package/{assets → src/lib/tree-sitter/assets}/markdown/injections.scm +0 -0
  585. /package/{assets → src/lib/tree-sitter/assets}/markdown/tree-sitter-markdown.wasm +0 -0
  586. /package/{assets → src/lib/tree-sitter/assets}/markdown_inline/highlights.scm +0 -0
  587. /package/{assets → src/lib/tree-sitter/assets}/markdown_inline/tree-sitter-markdown_inline.wasm +0 -0
  588. /package/{assets → src/lib/tree-sitter/assets}/typescript/highlights.scm +0 -0
  589. /package/{assets → src/lib/tree-sitter/assets}/typescript/tree-sitter-typescript.wasm +0 -0
  590. /package/{assets → src/lib/tree-sitter/assets}/zig/highlights.scm +0 -0
  591. /package/{assets → src/lib/tree-sitter/assets}/zig/tree-sitter-zig.wasm +0 -0
@@ -0,0 +1,123 @@
1
+ import { test, expect, beforeEach, afterEach, describe } from "bun:test"
2
+ import { Renderable, type RenderableOptions } from "../Renderable.js"
3
+ import { createTestRenderer, type TestRenderer } from "../testing/test-renderer.js"
4
+ import type { RenderContext } from "../types.js"
5
+
6
+ class TestRenderable extends Renderable {
7
+ constructor(ctx: RenderContext, options: RenderableOptions) {
8
+ super(ctx, options)
9
+ }
10
+ }
11
+
12
+ let testRenderer: TestRenderer
13
+ let renderOnce: () => Promise<void>
14
+
15
+ beforeEach(async () => {
16
+ ;({ renderer: testRenderer, renderOnce } = await createTestRenderer({}))
17
+ })
18
+
19
+ afterEach(() => {
20
+ testRenderer.destroy()
21
+ })
22
+
23
+ describe("Renderable - Opacity", () => {
24
+ test("defaults to 1.0", () => {
25
+ const renderable = new TestRenderable(testRenderer, { id: "test-opacity" })
26
+ expect(renderable.opacity).toBe(1.0)
27
+ })
28
+
29
+ test("accepts opacity in constructor options", () => {
30
+ const renderable = new TestRenderable(testRenderer, {
31
+ id: "test-opacity-options",
32
+ opacity: 0.5,
33
+ })
34
+ expect(renderable.opacity).toBe(0.5)
35
+ })
36
+
37
+ test("clamps opacity to 0-1 range via setter", () => {
38
+ const renderable = new TestRenderable(testRenderer, { id: "test-clamp" })
39
+
40
+ renderable.opacity = 1.5
41
+ expect(renderable.opacity).toBe(1.0)
42
+
43
+ renderable.opacity = -0.5
44
+ expect(renderable.opacity).toBe(0.0)
45
+
46
+ renderable.opacity = 0.7
47
+ expect(renderable.opacity).toBe(0.7)
48
+ })
49
+
50
+ test("clamps opacity from constructor options", () => {
51
+ const r1 = new TestRenderable(testRenderer, {
52
+ id: "test-clamp-high",
53
+ opacity: 2.0,
54
+ })
55
+ expect(r1.opacity).toBe(1.0)
56
+
57
+ const r2 = new TestRenderable(testRenderer, {
58
+ id: "test-clamp-low",
59
+ opacity: -1,
60
+ })
61
+ expect(r2.opacity).toBe(0.0)
62
+ })
63
+
64
+ test("handles opacity of 0 (fully transparent)", async () => {
65
+ const renderable = new TestRenderable(testRenderer, {
66
+ id: "invisible",
67
+ width: 10,
68
+ height: 5,
69
+ opacity: 0,
70
+ })
71
+ testRenderer.root.add(renderable)
72
+
73
+ expect(renderable.opacity).toBe(0)
74
+
75
+ // Render should not crash with zero opacity
76
+ await renderOnce()
77
+ })
78
+
79
+ test("nested renderables maintain independent opacity values", async () => {
80
+ const parent = new TestRenderable(testRenderer, {
81
+ id: "parent",
82
+ width: 20,
83
+ height: 10,
84
+ opacity: 0.5,
85
+ })
86
+
87
+ const child = new TestRenderable(testRenderer, {
88
+ id: "child",
89
+ width: 10,
90
+ height: 5,
91
+ opacity: 0.8,
92
+ })
93
+
94
+ parent.add(child)
95
+ testRenderer.root.add(parent)
96
+ await renderOnce()
97
+
98
+ expect(parent.opacity).toBe(0.5)
99
+ expect(child.opacity).toBe(0.8)
100
+ })
101
+
102
+ test("opacity changes trigger render request", () => {
103
+ const renderable = new TestRenderable(testRenderer, { id: "test-render" })
104
+ testRenderer.root.add(renderable)
105
+
106
+ const initialOpacity = renderable.opacity
107
+ renderable.opacity = 0.3
108
+
109
+ expect(renderable.opacity).not.toBe(initialOpacity)
110
+ expect(renderable.opacity).toBe(0.3)
111
+ })
112
+
113
+ test("setting same opacity value does not update", () => {
114
+ const renderable = new TestRenderable(testRenderer, {
115
+ id: "test-same",
116
+ opacity: 0.5,
117
+ })
118
+
119
+ // Set to same value - should not trigger change
120
+ renderable.opacity = 0.5
121
+ expect(renderable.opacity).toBe(0.5)
122
+ })
123
+ })
@@ -0,0 +1,524 @@
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
+
10
+ beforeEach(async () => {
11
+ ;({
12
+ renderer: testRenderer,
13
+ renderOnce,
14
+ captureCharFrame: captureFrame,
15
+ } = await createTestRenderer({
16
+ width: 10,
17
+ height: 5,
18
+ }))
19
+ })
20
+
21
+ afterEach(() => {
22
+ testRenderer.destroy()
23
+ })
24
+
25
+ describe("Renderable - insertBefore", () => {
26
+ test("reproduces insertBefore behavior with state change after timeout", async () => {
27
+ const container = new BoxRenderable(testRenderer, {
28
+ id: "container",
29
+ width: 10,
30
+ height: 5,
31
+ })
32
+
33
+ const bananaText = new TextRenderable(testRenderer, {
34
+ id: "banana",
35
+ content: "banana",
36
+ })
37
+
38
+ const appleText = new TextRenderable(testRenderer, {
39
+ id: "apple",
40
+ content: "apple",
41
+ })
42
+
43
+ const pearText = new TextRenderable(testRenderer, {
44
+ id: "pear",
45
+ content: "pear",
46
+ })
47
+
48
+ const separator = new BoxRenderable(testRenderer, {
49
+ id: "separator",
50
+ width: 20,
51
+ height: 1,
52
+ })
53
+
54
+ container.add(bananaText)
55
+ container.add(appleText)
56
+ container.add(pearText)
57
+ container.add(separator)
58
+
59
+ testRenderer.root.add(container)
60
+ await renderOnce()
61
+
62
+ const initialFrame = captureFrame()
63
+ expect(initialFrame).toMatchSnapshot("insertBefore initial state")
64
+
65
+ await new Promise((resolve) => setTimeout(resolve, 100))
66
+
67
+ container.insertBefore(appleText, separator)
68
+
69
+ await renderOnce()
70
+
71
+ const reorderedFrame = captureFrame()
72
+ expect(reorderedFrame).toMatchSnapshot("insertBefore reordered state")
73
+ })
74
+
75
+ test("ensure .add with index works correctly", async () => {
76
+ const container = new BoxRenderable(testRenderer, {
77
+ id: "container",
78
+ width: 20,
79
+ height: 10,
80
+ })
81
+
82
+ // Create 5 text renderables in order
83
+ const items = [
84
+ new TextRenderable(testRenderer, { id: "order-1", content: "First" }),
85
+ new TextRenderable(testRenderer, { id: "order-2", content: "Second" }),
86
+ new TextRenderable(testRenderer, { id: "order-3", content: "Third" }),
87
+ new TextRenderable(testRenderer, { id: "order-4", content: "Fourth" }),
88
+ new TextRenderable(testRenderer, { id: "order-5", content: "Fifth" }),
89
+ ]
90
+
91
+ // Add items in initial order [1, 2, 3, 4, 5]
92
+ for (const item of items) {
93
+ container.add(item)
94
+ }
95
+
96
+ testRenderer.root.add(container)
97
+ await renderOnce()
98
+
99
+ let children = container.getChildren()
100
+
101
+ expect(children.length).toBe(5)
102
+ expect(children[0]?.id).toBe("order-1")
103
+ expect(children[1]?.id).toBe("order-2")
104
+ expect(children[2]?.id).toBe("order-3")
105
+ expect(children[3]?.id).toBe("order-4")
106
+ expect(children[4]?.id).toBe("order-5")
107
+
108
+ // Reproduce the EXACT sequence from SolidJS reconciler output:
109
+ container.add(items[4]!, 1) // order-5 at index 1
110
+ container.add(items[0]!) // order-1 at index undefined
111
+ container.add(items[3]!, 2) // order-4 at index 2
112
+ container.add(items[1]!, 4) // order-2 at index 4
113
+
114
+ await renderOnce()
115
+
116
+ children = container.getChildren()
117
+
118
+ // Expected: [5, 4, 3, 2, 1]
119
+ expect(children.length).toBe(5)
120
+ expect(children[0]?.id).toBe("order-5")
121
+ expect(children[1]?.id).toBe("order-4")
122
+ expect(children[2]?.id).toBe("order-3")
123
+ expect(children[3]?.id).toBe("order-2")
124
+ expect(children[4]?.id).toBe("order-1")
125
+ })
126
+ })
127
+
128
+ describe("Renderable - add method", () => {
129
+ test("basic add appends to end", async () => {
130
+ const container = new BoxRenderable(testRenderer, {
131
+ id: "container",
132
+ width: 10,
133
+ height: 10,
134
+ })
135
+
136
+ const item1 = new TextRenderable(testRenderer, { id: "item-1", content: "A" })
137
+ const item2 = new TextRenderable(testRenderer, { id: "item-2", content: "B" })
138
+ const item3 = new TextRenderable(testRenderer, { id: "item-3", content: "C" })
139
+
140
+ container.add(item1)
141
+ container.add(item2)
142
+ container.add(item3)
143
+
144
+ const children = container.getChildren()
145
+ expect(children.length).toBe(3)
146
+ expect(children[0]?.id).toBe("item-1")
147
+ expect(children[1]?.id).toBe("item-2")
148
+ expect(children[2]?.id).toBe("item-3")
149
+ })
150
+
151
+ test("add with index 0 inserts at beginning", async () => {
152
+ const container = new BoxRenderable(testRenderer, {
153
+ id: "container",
154
+ width: 10,
155
+ height: 10,
156
+ })
157
+
158
+ const item1 = new TextRenderable(testRenderer, { id: "item-1", content: "A" })
159
+ const item2 = new TextRenderable(testRenderer, { id: "item-2", content: "B" })
160
+ const item3 = new TextRenderable(testRenderer, { id: "item-3", content: "C" })
161
+
162
+ container.add(item1)
163
+ container.add(item2)
164
+ container.add(item3, 0) // Insert at beginning
165
+
166
+ const children = container.getChildren()
167
+ expect(children.length).toBe(3)
168
+ expect(children[0]?.id).toBe("item-3")
169
+ expect(children[1]?.id).toBe("item-1")
170
+ expect(children[2]?.id).toBe("item-2")
171
+ })
172
+
173
+ test("add with middle index inserts correctly", async () => {
174
+ const container = new BoxRenderable(testRenderer, {
175
+ id: "container",
176
+ width: 10,
177
+ height: 10,
178
+ })
179
+
180
+ const item1 = new TextRenderable(testRenderer, { id: "item-1", content: "A" })
181
+ const item2 = new TextRenderable(testRenderer, { id: "item-2", content: "B" })
182
+ const item3 = new TextRenderable(testRenderer, { id: "item-3", content: "C" })
183
+
184
+ container.add(item1)
185
+ container.add(item2)
186
+ container.add(item3, 1) // Insert in middle
187
+
188
+ const children = container.getChildren()
189
+ expect(children.length).toBe(3)
190
+ expect(children[0]?.id).toBe("item-1")
191
+ expect(children[1]?.id).toBe("item-3")
192
+ expect(children[2]?.id).toBe("item-2")
193
+ })
194
+
195
+ test("add with large index appends to end", async () => {
196
+ const container = new BoxRenderable(testRenderer, {
197
+ id: "container",
198
+ width: 10,
199
+ height: 10,
200
+ })
201
+
202
+ const item1 = new TextRenderable(testRenderer, { id: "item-1", content: "A" })
203
+ const item2 = new TextRenderable(testRenderer, { id: "item-2", content: "B" })
204
+ const item3 = new TextRenderable(testRenderer, { id: "item-3", content: "C" })
205
+
206
+ container.add(item1)
207
+ container.add(item2)
208
+ container.add(item3, 999) // Out of bounds index
209
+
210
+ const children = container.getChildren()
211
+ expect(children.length).toBe(3)
212
+ expect(children[0]?.id).toBe("item-1")
213
+ expect(children[1]?.id).toBe("item-2")
214
+ expect(children[2]?.id).toBe("item-3")
215
+ })
216
+
217
+ test("add returns correct index", async () => {
218
+ const container = new BoxRenderable(testRenderer, {
219
+ id: "container",
220
+ width: 10,
221
+ height: 10,
222
+ })
223
+
224
+ const item1 = new TextRenderable(testRenderer, { id: "item-1", content: "A" })
225
+ const item2 = new TextRenderable(testRenderer, { id: "item-2", content: "B" })
226
+ const item3 = new TextRenderable(testRenderer, { id: "item-3", content: "C" })
227
+
228
+ const idx1 = container.add(item1)
229
+ const idx2 = container.add(item2)
230
+ const idx3 = container.add(item3, 1)
231
+
232
+ expect(idx1).toBe(0)
233
+ expect(idx2).toBe(1)
234
+ expect(idx3).toBe(1) // Inserted at index 1
235
+ })
236
+
237
+ test("add null/undefined returns -1", async () => {
238
+ const container = new BoxRenderable(testRenderer, {
239
+ id: "container",
240
+ width: 10,
241
+ height: 10,
242
+ })
243
+
244
+ const idx1 = container.add(null as any)
245
+ const idx2 = container.add(undefined as any)
246
+
247
+ expect(idx1).toBe(-1)
248
+ expect(idx2).toBe(-1)
249
+ expect(container.getChildrenCount()).toBe(0)
250
+ })
251
+
252
+ test("re-adding existing child moves it", async () => {
253
+ const container = new BoxRenderable(testRenderer, {
254
+ id: "container",
255
+ width: 10,
256
+ height: 10,
257
+ })
258
+
259
+ const item1 = new TextRenderable(testRenderer, { id: "item-1", content: "A" })
260
+ const item2 = new TextRenderable(testRenderer, { id: "item-2", content: "B" })
261
+ const item3 = new TextRenderable(testRenderer, { id: "item-3", content: "C" })
262
+
263
+ container.add(item1)
264
+ container.add(item2)
265
+ container.add(item3)
266
+
267
+ // Re-add item1 to end
268
+ container.add(item1)
269
+
270
+ let children = container.getChildren()
271
+ expect(children.length).toBe(3)
272
+ expect(children[0]?.id).toBe("item-2")
273
+ expect(children[1]?.id).toBe("item-3")
274
+ expect(children[2]?.id).toBe("item-1")
275
+
276
+ // Re-add item3 to beginning
277
+ container.add(item3, 0)
278
+
279
+ children = container.getChildren()
280
+ expect(children.length).toBe(3)
281
+ expect(children[0]?.id).toBe("item-3")
282
+ expect(children[1]?.id).toBe("item-2")
283
+ expect(children[2]?.id).toBe("item-1")
284
+ })
285
+
286
+ test("adding child from another parent removes it from old parent", async () => {
287
+ const container1 = new BoxRenderable(testRenderer, {
288
+ id: "container-1",
289
+ width: 10,
290
+ height: 10,
291
+ })
292
+
293
+ const container2 = new BoxRenderable(testRenderer, {
294
+ id: "container-2",
295
+ width: 10,
296
+ height: 10,
297
+ })
298
+
299
+ const item = new TextRenderable(testRenderer, { id: "item", content: "A" })
300
+
301
+ container1.add(item)
302
+ expect(container1.getChildrenCount()).toBe(1)
303
+ expect(item.parent).toBe(container1)
304
+
305
+ container2.add(item)
306
+ expect(container1.getChildrenCount()).toBe(0)
307
+ expect(container2.getChildrenCount()).toBe(1)
308
+ expect(item.parent).toBe(container2)
309
+ })
310
+ })
311
+
312
+ describe("Renderable - insertBefore method", () => {
313
+ test("insertBefore with null anchor appends to end", async () => {
314
+ const container = new BoxRenderable(testRenderer, {
315
+ id: "container",
316
+ width: 10,
317
+ height: 10,
318
+ })
319
+
320
+ const item1 = new TextRenderable(testRenderer, { id: "item-1", content: "A" })
321
+ const item2 = new TextRenderable(testRenderer, { id: "item-2", content: "B" })
322
+ const item3 = new TextRenderable(testRenderer, { id: "item-3", content: "C" })
323
+
324
+ container.add(item1)
325
+ container.add(item2)
326
+ container.insertBefore(item3, null as any)
327
+
328
+ const children = container.getChildren()
329
+ expect(children.length).toBe(3)
330
+ expect(children[2]?.id).toBe("item-3")
331
+ })
332
+
333
+ test("insertBefore inserts at correct position", async () => {
334
+ const container = new BoxRenderable(testRenderer, {
335
+ id: "container",
336
+ width: 10,
337
+ height: 10,
338
+ })
339
+
340
+ const item1 = new TextRenderable(testRenderer, { id: "item-1", content: "A" })
341
+ const item2 = new TextRenderable(testRenderer, { id: "item-2", content: "B" })
342
+ const item3 = new TextRenderable(testRenderer, { id: "item-3", content: "C" })
343
+
344
+ container.add(item1)
345
+ container.add(item3)
346
+ container.insertBefore(item2, item3) // Insert item2 before item3
347
+
348
+ const children = container.getChildren()
349
+ expect(children.length).toBe(3)
350
+ expect(children[0]?.id).toBe("item-1")
351
+ expect(children[1]?.id).toBe("item-2")
352
+ expect(children[2]?.id).toBe("item-3")
353
+ })
354
+
355
+ test("insertBefore at beginning", async () => {
356
+ const container = new BoxRenderable(testRenderer, {
357
+ id: "container",
358
+ width: 10,
359
+ height: 10,
360
+ })
361
+
362
+ const item1 = new TextRenderable(testRenderer, { id: "item-1", content: "A" })
363
+ const item2 = new TextRenderable(testRenderer, { id: "item-2", content: "B" })
364
+ const item3 = new TextRenderable(testRenderer, { id: "item-3", content: "C" })
365
+
366
+ container.add(item1)
367
+ container.add(item2)
368
+ container.insertBefore(item3, item1) // Insert before first item
369
+
370
+ const children = container.getChildren()
371
+ expect(children.length).toBe(3)
372
+ expect(children[0]?.id).toBe("item-3")
373
+ expect(children[1]?.id).toBe("item-1")
374
+ expect(children[2]?.id).toBe("item-2")
375
+ })
376
+
377
+ test("insertBefore moves existing child", async () => {
378
+ const container = new BoxRenderable(testRenderer, {
379
+ id: "container",
380
+ width: 10,
381
+ height: 10,
382
+ })
383
+
384
+ const item1 = new TextRenderable(testRenderer, { id: "item-1", content: "A" })
385
+ const item2 = new TextRenderable(testRenderer, { id: "item-2", content: "B" })
386
+ const item3 = new TextRenderable(testRenderer, { id: "item-3", content: "C" })
387
+
388
+ container.add(item1)
389
+ container.add(item2)
390
+ container.add(item3)
391
+
392
+ // Move item3 before item1
393
+ container.insertBefore(item3, item1)
394
+
395
+ let children = container.getChildren()
396
+ expect(children.length).toBe(3)
397
+ expect(children[0]?.id).toBe("item-3")
398
+ expect(children[1]?.id).toBe("item-1")
399
+ expect(children[2]?.id).toBe("item-2")
400
+
401
+ // Move item1 before item2
402
+ container.insertBefore(item1, item2)
403
+
404
+ children = container.getChildren()
405
+ expect(children.length).toBe(3)
406
+ expect(children[0]?.id).toBe("item-3")
407
+ expect(children[1]?.id).toBe("item-1")
408
+ expect(children[2]?.id).toBe("item-2")
409
+ })
410
+
411
+ test("insertBefore with invalid anchor returns -1", async () => {
412
+ const container = new BoxRenderable(testRenderer, {
413
+ id: "container",
414
+ width: 10,
415
+ height: 10,
416
+ })
417
+
418
+ const item1 = new TextRenderable(testRenderer, { id: "item-1", content: "A" })
419
+ const item2 = new TextRenderable(testRenderer, { id: "item-2", content: "B" })
420
+ const notAChild = new TextRenderable(testRenderer, { id: "not-child", content: "X" })
421
+
422
+ container.add(item1)
423
+
424
+ expect(container.insertBefore(item2, notAChild)).toBe(-1)
425
+ })
426
+
427
+ test("insertBefore returns correct index", async () => {
428
+ const container = new BoxRenderable(testRenderer, {
429
+ id: "container",
430
+ width: 10,
431
+ height: 10,
432
+ })
433
+
434
+ const item1 = new TextRenderable(testRenderer, { id: "item-1", content: "A" })
435
+ const item2 = new TextRenderable(testRenderer, { id: "item-2", content: "B" })
436
+ const item3 = new TextRenderable(testRenderer, { id: "item-3", content: "C" })
437
+
438
+ container.add(item1)
439
+ container.add(item3)
440
+
441
+ const idx = container.insertBefore(item2, item3)
442
+ expect(idx).toBe(1)
443
+ })
444
+
445
+ test("insertBefore with null object returns -1", async () => {
446
+ const container = new BoxRenderable(testRenderer, {
447
+ id: "container",
448
+ width: 10,
449
+ height: 10,
450
+ })
451
+
452
+ const anchor = new TextRenderable(testRenderer, { id: "anchor", content: "A" })
453
+ container.add(anchor)
454
+
455
+ const idx = container.insertBefore(null as any, anchor)
456
+ expect(idx).toBe(-1)
457
+ })
458
+
459
+ test("complex reordering scenario", async () => {
460
+ const container = new BoxRenderable(testRenderer, {
461
+ id: "container",
462
+ width: 10,
463
+ height: 10,
464
+ })
465
+
466
+ const items = [
467
+ new TextRenderable(testRenderer, { id: "A", content: "A" }),
468
+ new TextRenderable(testRenderer, { id: "B", content: "B" }),
469
+ new TextRenderable(testRenderer, { id: "C", content: "C" }),
470
+ new TextRenderable(testRenderer, { id: "D", content: "D" }),
471
+ new TextRenderable(testRenderer, { id: "E", content: "E" }),
472
+ ]
473
+
474
+ // Initial: A, B, C, D, E
475
+ items.forEach((item) => container.add(item))
476
+
477
+ let children = container.getChildren()
478
+ expect(children.map((c) => c.id)).toEqual(["A", "B", "C", "D", "E"])
479
+
480
+ // Move E before B: A, E, B, C, D
481
+ container.insertBefore(items[4]!, items[1]!)
482
+ children = container.getChildren()
483
+ expect(children.map((c) => c.id)).toEqual(["A", "E", "B", "C", "D"])
484
+
485
+ // Move A before D: E, B, C, A, D
486
+ container.insertBefore(items[0]!, items[3]!)
487
+ children = container.getChildren()
488
+ expect(children.map((c) => c.id)).toEqual(["E", "B", "C", "A", "D"])
489
+
490
+ // Move C before E: C, E, B, A, D
491
+ container.insertBefore(items[2]!, items[4]!)
492
+ children = container.getChildren()
493
+ expect(children.map((c) => c.id)).toEqual(["C", "E", "B", "A", "D"])
494
+ })
495
+
496
+ test("multiple sequential adds and inserts", async () => {
497
+ const container = new BoxRenderable(testRenderer, {
498
+ id: "container",
499
+ width: 10,
500
+ height: 10,
501
+ })
502
+
503
+ const items = [
504
+ new TextRenderable(testRenderer, { id: "1", content: "1" }),
505
+ new TextRenderable(testRenderer, { id: "2", content: "2" }),
506
+ new TextRenderable(testRenderer, { id: "3", content: "3" }),
507
+ new TextRenderable(testRenderer, { id: "4", content: "4" }),
508
+ ]
509
+
510
+ container.add(items[0]!)
511
+ container.add(items[1]!)
512
+ expect(container.getChildren().map((c) => c.id)).toEqual(["1", "2"])
513
+
514
+ container.insertBefore(items[2]!, items[1]!)
515
+ expect(container.getChildren().map((c) => c.id)).toEqual(["1", "3", "2"])
516
+
517
+ container.add(items[3]!, 0)
518
+ expect(container.getChildren().map((c) => c.id)).toEqual(["4", "1", "3", "2"])
519
+
520
+ // Move "2" before "4"
521
+ container.insertBefore(items[1]!, items[3]!)
522
+ expect(container.getChildren().map((c) => c.id)).toEqual(["2", "4", "1", "3"])
523
+ })
524
+ })