termcast 1.3.9 → 1.3.16

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 (559) hide show
  1. package/dist/action-utils.js +1 -1
  2. package/dist/action-utils.js.map +1 -1
  3. package/dist/apis/ai.js +1 -1
  4. package/dist/apis/ai.js.map +1 -1
  5. package/dist/apis/clipboard.js +2 -2
  6. package/dist/apis/clipboard.js.map +1 -1
  7. package/dist/apis/hud.d.ts +2 -2
  8. package/dist/apis/hud.d.ts.map +1 -1
  9. package/dist/apis/hud.js +5 -5
  10. package/dist/apis/hud.js.map +1 -1
  11. package/dist/apis/oauth.d.ts +1 -1
  12. package/dist/apis/oauth.d.ts.map +1 -1
  13. package/dist/apis/oauth.js +8 -8
  14. package/dist/apis/oauth.js.map +1 -1
  15. package/dist/apis/preferences.js +4 -4
  16. package/dist/apis/preferences.js.map +1 -1
  17. package/dist/apis/toast.d.ts +1 -5
  18. package/dist/apis/toast.d.ts.map +1 -1
  19. package/dist/apis/toast.js +26 -20
  20. package/dist/apis/toast.js.map +1 -1
  21. package/dist/build.d.ts +2 -0
  22. package/dist/build.d.ts.map +1 -1
  23. package/dist/build.js +9 -8
  24. package/dist/build.js.map +1 -1
  25. package/dist/cli.js +44 -2
  26. package/dist/cli.js.map +1 -1
  27. package/dist/colors.d.ts +8 -1
  28. package/dist/colors.d.ts.map +1 -1
  29. package/dist/colors.js +12 -0
  30. package/dist/colors.js.map +1 -1
  31. package/dist/compile.d.ts +30 -0
  32. package/dist/compile.d.ts.map +1 -0
  33. package/dist/compile.js +156 -0
  34. package/dist/compile.js.map +1 -0
  35. package/dist/components/actions.d.ts +2 -1
  36. package/dist/components/actions.d.ts.map +1 -1
  37. package/dist/components/actions.js +11 -8
  38. package/dist/components/actions.js.map +1 -1
  39. package/dist/components/alert.js +4 -4
  40. package/dist/components/alert.js.map +1 -1
  41. package/dist/components/command-arguments.d.ts +9 -0
  42. package/dist/components/command-arguments.d.ts.map +1 -0
  43. package/dist/components/command-arguments.js +21 -0
  44. package/dist/components/command-arguments.js.map +1 -0
  45. package/dist/components/detail.d.ts +3 -3
  46. package/dist/components/detail.d.ts.map +1 -1
  47. package/dist/components/detail.js +20 -42
  48. package/dist/components/detail.js.map +1 -1
  49. package/dist/components/dropdown.d.ts +2 -1
  50. package/dist/components/dropdown.d.ts.map +1 -1
  51. package/dist/components/dropdown.js +81 -25
  52. package/dist/components/dropdown.js.map +1 -1
  53. package/dist/components/extension-preferences.d.ts.map +1 -1
  54. package/dist/components/extension-preferences.js +23 -33
  55. package/dist/components/extension-preferences.js.map +1 -1
  56. package/dist/components/form/checkbox.d.ts.map +1 -1
  57. package/dist/components/form/checkbox.js +11 -4
  58. package/dist/components/form/checkbox.js.map +1 -1
  59. package/dist/components/form/date-picker.d.ts.map +1 -1
  60. package/dist/components/form/date-picker.js +18 -31
  61. package/dist/components/form/date-picker.js.map +1 -1
  62. package/dist/components/form/description.d.ts +2 -0
  63. package/dist/components/form/description.d.ts.map +1 -1
  64. package/dist/components/form/description.js +21 -3
  65. package/dist/components/form/description.js.map +1 -1
  66. package/dist/components/form/dropdown.d.ts.map +1 -1
  67. package/dist/components/form/dropdown.js +17 -32
  68. package/dist/components/form/dropdown.js.map +1 -1
  69. package/dist/components/form/file-autocomplete.d.ts +7 -4
  70. package/dist/components/form/file-autocomplete.d.ts.map +1 -1
  71. package/dist/components/form/file-autocomplete.js +56 -48
  72. package/dist/components/form/file-autocomplete.js.map +1 -1
  73. package/dist/components/form/file-picker.d.ts +5 -0
  74. package/dist/components/form/file-picker.d.ts.map +1 -1
  75. package/dist/components/form/file-picker.js +48 -51
  76. package/dist/components/form/file-picker.js.map +1 -1
  77. package/dist/components/form/form-end.js +1 -1
  78. package/dist/components/form/form-end.js.map +1 -1
  79. package/dist/components/form/form-ref.d.ts +43 -0
  80. package/dist/components/form/form-ref.d.ts.map +1 -0
  81. package/dist/components/form/form-ref.js +53 -0
  82. package/dist/components/form/form-ref.js.map +1 -0
  83. package/dist/components/form/index.d.ts +16 -0
  84. package/dist/components/form/index.d.ts.map +1 -1
  85. package/dist/components/form/index.js +90 -27
  86. package/dist/components/form/index.js.map +1 -1
  87. package/dist/components/form/password-field.d.ts.map +1 -1
  88. package/dist/components/form/password-field.js +33 -17
  89. package/dist/components/form/password-field.js.map +1 -1
  90. package/dist/components/form/separator.js +1 -1
  91. package/dist/components/form/separator.js.map +1 -1
  92. package/dist/components/form/tagpicker.d.ts +1 -1
  93. package/dist/components/form/tagpicker.d.ts.map +1 -1
  94. package/dist/components/form/text-area.d.ts.map +1 -1
  95. package/dist/components/form/text-area.js +33 -16
  96. package/dist/components/form/text-area.js.map +1 -1
  97. package/dist/components/form/text-field.d.ts.map +1 -1
  98. package/dist/components/form/text-field.js +38 -18
  99. package/dist/components/form/text-field.js.map +1 -1
  100. package/dist/components/form/use-form-navigation.d.ts +4 -0
  101. package/dist/components/form/use-form-navigation.d.ts.map +1 -1
  102. package/dist/components/form/use-form-navigation.js +35 -18
  103. package/dist/components/form/use-form-navigation.js.map +1 -1
  104. package/dist/components/form/with-left-border.d.ts.map +1 -1
  105. package/dist/components/form/with-left-border.js +3 -3
  106. package/dist/components/form/with-left-border.js.map +1 -1
  107. package/dist/components/icon.d.ts +3 -1
  108. package/dist/components/icon.d.ts.map +1 -1
  109. package/dist/components/icon.js +494 -469
  110. package/dist/components/icon.js.map +1 -1
  111. package/dist/components/image.js +1 -1
  112. package/dist/components/image.js.map +1 -1
  113. package/dist/components/list.d.ts +12 -8
  114. package/dist/components/list.d.ts.map +1 -1
  115. package/dist/components/list.js +172 -40
  116. package/dist/components/list.js.map +1 -1
  117. package/dist/components/loading-bar.js +2 -2
  118. package/dist/components/loading-bar.js.map +1 -1
  119. package/dist/components/menubar-extra.d.ts +1 -1
  120. package/dist/components/menubar-extra.d.ts.map +1 -1
  121. package/dist/components/menubar-extra.js +2 -2
  122. package/dist/components/menubar-extra.js.map +1 -1
  123. package/dist/descendants.d.ts.map +1 -1
  124. package/dist/descendants.js +8 -5
  125. package/dist/descendants.js.map +1 -1
  126. package/dist/e2e-node.d.ts +2 -0
  127. package/dist/e2e-node.d.ts.map +1 -1
  128. package/dist/e2e-node.js +14 -0
  129. package/dist/e2e-node.js.map +1 -1
  130. package/dist/examples/action-show-in-finder.js +3 -3
  131. package/dist/examples/action-show-in-finder.js.map +1 -1
  132. package/dist/examples/environment-test.js +4 -4
  133. package/dist/examples/environment-test.js.map +1 -1
  134. package/dist/examples/error-boundary.js +5 -5
  135. package/dist/examples/error-boundary.js.map +1 -1
  136. package/dist/examples/form-basic.d.ts.map +1 -1
  137. package/dist/examples/form-basic.js +6 -6
  138. package/dist/examples/form-basic.js.map +1 -1
  139. package/dist/examples/form-dropdown.js +3 -3
  140. package/dist/examples/form-dropdown.js.map +1 -1
  141. package/dist/examples/form-scroll.d.ts +2 -0
  142. package/dist/examples/form-scroll.d.ts.map +1 -0
  143. package/dist/examples/form-scroll.js +8 -0
  144. package/dist/examples/form-scroll.js.map +1 -0
  145. package/dist/examples/form-tagpicker.js +3 -3
  146. package/dist/examples/form-tagpicker.js.map +1 -1
  147. package/dist/examples/internal/descendants-filtering.js +10 -5
  148. package/dist/examples/internal/descendants-filtering.js.map +1 -1
  149. package/dist/examples/internal/descendants.js +13 -6
  150. package/dist/examples/internal/descendants.js.map +1 -1
  151. package/dist/examples/internal/rhf-custom-ref.d.ts +2 -0
  152. package/dist/examples/internal/rhf-custom-ref.d.ts.map +1 -0
  153. package/dist/examples/internal/rhf-custom-ref.js +67 -0
  154. package/dist/examples/internal/rhf-custom-ref.js.map +1 -0
  155. package/dist/examples/internal/scrollbox-demo.js +4 -8
  156. package/dist/examples/internal/scrollbox-demo.js.map +1 -1
  157. package/dist/examples/internal/scrollbox-with-descendants.d.ts +2 -0
  158. package/dist/examples/internal/scrollbox-with-descendants.d.ts.map +1 -0
  159. package/dist/examples/internal/scrollbox-with-descendants.js +63 -0
  160. package/dist/examples/internal/scrollbox-with-descendants.js.map +1 -0
  161. package/dist/examples/internal/simple-dialog.js +7 -7
  162. package/dist/examples/internal/simple-dialog.js.map +1 -1
  163. package/dist/examples/internal/simple-scrollbox.d.ts +2 -0
  164. package/dist/examples/internal/simple-scrollbox.d.ts.map +1 -0
  165. package/dist/examples/internal/simple-scrollbox.js +25 -0
  166. package/dist/examples/internal/simple-scrollbox.js.map +1 -0
  167. package/dist/examples/internal/text-stacking.js +4 -2
  168. package/dist/examples/internal/text-stacking.js.map +1 -1
  169. package/dist/examples/list-dropdown-default.js +3 -3
  170. package/dist/examples/list-dropdown-default.js.map +1 -1
  171. package/dist/examples/list-fetch-data.js +3 -3
  172. package/dist/examples/list-fetch-data.js.map +1 -1
  173. package/dist/examples/list-scrollbox.d.ts +2 -0
  174. package/dist/examples/list-scrollbox.d.ts.map +1 -0
  175. package/dist/examples/list-scrollbox.js +29 -0
  176. package/dist/examples/list-scrollbox.js.map +1 -0
  177. package/dist/examples/list-with-detail.js +2 -2
  178. package/dist/examples/list-with-detail.js.map +1 -1
  179. package/dist/examples/list-with-dropdown.js +2 -2
  180. package/dist/examples/list-with-dropdown.js.map +1 -1
  181. package/dist/examples/list-with-sections.js +6 -6
  182. package/dist/examples/list-with-sections.js.map +1 -1
  183. package/dist/examples/miscellaneous.js +14 -14
  184. package/dist/examples/miscellaneous.js.map +1 -1
  185. package/dist/examples/nested-navigation.js +9 -7
  186. package/dist/examples/nested-navigation.js.map +1 -1
  187. package/dist/examples/preferences-test.js +4 -4
  188. package/dist/examples/preferences-test.js.map +1 -1
  189. package/dist/examples/simple-dropdown.js +4 -4
  190. package/dist/examples/simple-dropdown.js.map +1 -1
  191. package/dist/examples/simple-file-picker.js +3 -3
  192. package/dist/examples/simple-file-picker.js.map +1 -1
  193. package/dist/examples/simple-grid.js +2 -2
  194. package/dist/examples/simple-grid.js.map +1 -1
  195. package/dist/examples/simple-hud.js +4 -4
  196. package/dist/examples/simple-hud.js.map +1 -1
  197. package/dist/examples/simple-list-search.js +21 -5
  198. package/dist/examples/simple-list-search.js.map +1 -1
  199. package/dist/examples/simple-list.js +4 -4
  200. package/dist/examples/simple-list.js.map +1 -1
  201. package/dist/examples/simple-navigation.js +9 -7
  202. package/dist/examples/simple-navigation.js.map +1 -1
  203. package/dist/examples/store.js +1 -1
  204. package/dist/examples/store.js.map +1 -1
  205. package/dist/examples/submodule-diff.d.ts +2 -0
  206. package/dist/examples/submodule-diff.d.ts.map +1 -0
  207. package/dist/examples/submodule-diff.js +99 -0
  208. package/dist/examples/submodule-diff.js.map +1 -0
  209. package/dist/examples/tanstack-demo.js +3 -3
  210. package/dist/examples/tanstack-demo.js.map +1 -1
  211. package/dist/examples/use-promise-demo.js +3 -3
  212. package/dist/examples/use-promise-demo.js.map +1 -1
  213. package/dist/extensions/dev.d.ts +8 -0
  214. package/dist/extensions/dev.d.ts.map +1 -1
  215. package/dist/extensions/dev.js +60 -35
  216. package/dist/extensions/dev.js.map +1 -1
  217. package/dist/extensions/home.d.ts.map +1 -1
  218. package/dist/extensions/home.js +22 -97
  219. package/dist/extensions/home.js.map +1 -1
  220. package/dist/extensions/store.js +2 -2
  221. package/dist/extensions/store.js.map +1 -1
  222. package/dist/globals.js +1 -1
  223. package/dist/globals.js.map +1 -1
  224. package/dist/hooks/index.d.ts +1 -1
  225. package/dist/hooks/index.d.ts.map +1 -1
  226. package/dist/hooks/index.js +1 -1
  227. package/dist/hooks/index.js.map +1 -1
  228. package/dist/hooks/use-action-panel.js +1 -1
  229. package/dist/hooks/use-action-panel.js.map +1 -1
  230. package/dist/hooks/use-unstable-ai.js +1 -1
  231. package/dist/hooks/use-unstable-ai.js.map +1 -1
  232. package/dist/index.d.ts +57 -55
  233. package/dist/index.d.ts.map +1 -1
  234. package/dist/index.js +42 -38
  235. package/dist/index.js.map +1 -1
  236. package/dist/internal/date-picker-widget.d.ts.map +1 -1
  237. package/dist/internal/date-picker-widget.js +56 -48
  238. package/dist/internal/date-picker-widget.js.map +1 -1
  239. package/dist/internal/dialog.d.ts +3 -3
  240. package/dist/internal/dialog.d.ts.map +1 -1
  241. package/dist/internal/dialog.js +10 -10
  242. package/dist/internal/dialog.js.map +1 -1
  243. package/dist/internal/error-handler.js +2 -2
  244. package/dist/internal/error-handler.js.map +1 -1
  245. package/dist/internal/focus-context.d.ts +1 -1
  246. package/dist/internal/focus-context.d.ts.map +1 -1
  247. package/dist/internal/navigation.d.ts +1 -1
  248. package/dist/internal/navigation.d.ts.map +1 -1
  249. package/dist/internal/navigation.js +2 -2
  250. package/dist/internal/navigation.js.map +1 -1
  251. package/dist/internal/providers.d.ts +2 -2
  252. package/dist/internal/providers.d.ts.map +1 -1
  253. package/dist/internal/providers.js +9 -9
  254. package/dist/internal/providers.js.map +1 -1
  255. package/dist/internal/scrollbox.d.ts +12 -0
  256. package/dist/internal/scrollbox.d.ts.map +1 -0
  257. package/dist/internal/scrollbox.js +34 -0
  258. package/dist/internal/scrollbox.js.map +1 -0
  259. package/dist/preload.js +1 -1
  260. package/dist/preload.js.map +1 -1
  261. package/dist/release.d.ts +11 -0
  262. package/dist/release.d.ts.map +1 -0
  263. package/dist/release.js +113 -0
  264. package/dist/release.js.map +1 -0
  265. package/dist/state.d.ts +1 -0
  266. package/dist/state.d.ts.map +1 -1
  267. package/dist/state.js +1 -0
  268. package/dist/state.js.map +1 -1
  269. package/dist/theme.d.ts +11 -8
  270. package/dist/theme.d.ts.map +1 -1
  271. package/dist/theme.js +31 -8
  272. package/dist/theme.js.map +1 -1
  273. package/dist/utils/run-command.d.ts +22 -0
  274. package/dist/utils/run-command.d.ts.map +1 -0
  275. package/dist/utils/run-command.js +127 -0
  276. package/dist/utils/run-command.js.map +1 -0
  277. package/dist/utils.d.ts +1 -1
  278. package/dist/utils.d.ts.map +1 -1
  279. package/dist/utils.js +6 -4
  280. package/dist/utils.js.map +1 -1
  281. package/package.json +13 -8
  282. package/src/apis/toast.tsx +38 -17
  283. package/src/build.tsx +5 -3
  284. package/src/cli.tsx +46 -0
  285. package/src/colors.tsx +22 -1
  286. package/src/compile.tsx +219 -0
  287. package/src/components/actions.tsx +7 -1
  288. package/src/components/command-arguments.tsx +81 -0
  289. package/src/components/detail.tsx +26 -58
  290. package/src/components/dropdown.tsx +108 -23
  291. package/src/components/extension-preferences.tsx +55 -35
  292. package/src/components/form/checkbox.tsx +13 -5
  293. package/src/components/form/date-picker.tsx +24 -29
  294. package/src/components/form/description.tsx +35 -7
  295. package/src/components/form/dropdown.tsx +16 -30
  296. package/src/components/form/file-autocomplete.tsx +87 -77
  297. package/src/components/form/file-picker.tsx +69 -57
  298. package/src/components/form/form-ref.tsx +68 -0
  299. package/src/components/form/index.tsx +152 -41
  300. package/src/components/form/password-field.tsx +35 -22
  301. package/src/components/form/text-area.tsx +78 -58
  302. package/src/components/form/text-field.tsx +82 -61
  303. package/src/components/form/use-form-navigation.tsx +43 -23
  304. package/src/components/form/with-left-border.tsx +2 -1
  305. package/src/components/icon.tsx +497 -469
  306. package/src/components/list.tsx +279 -112
  307. package/src/components/loading-bar.tsx +1 -1
  308. package/src/descendants.tsx +15 -5
  309. package/src/e2e-node.tsx +16 -0
  310. package/src/examples/action-show-in-finder.tsx +1 -1
  311. package/src/examples/environment-test.tsx +1 -1
  312. package/src/examples/error-boundary.tsx +1 -1
  313. package/src/examples/file-autocomplete.vitest.tsx +245 -0
  314. package/src/examples/form-basic.tsx +12 -12
  315. package/src/examples/form-basic.vitest.tsx +297 -671
  316. package/src/examples/form-dropdown.tsx +1 -1
  317. package/src/examples/form-dropdown.vitest.tsx +353 -221
  318. package/src/examples/form-scroll.tsx +56 -0
  319. package/src/examples/form-scroll.vitest.tsx +228 -0
  320. package/src/examples/form-tagpicker.tsx +1 -1
  321. package/src/examples/form-tagpicker.vitest.tsx +438 -193
  322. package/src/examples/internal/descendants-filtering.tsx +13 -5
  323. package/src/examples/internal/descendants.tsx +17 -5
  324. package/src/examples/internal/rhf-custom-ref.tsx +152 -0
  325. package/src/examples/internal/scrollbox-demo.tsx +15 -7
  326. package/src/examples/internal/scrollbox-with-descendants.tsx +94 -0
  327. package/src/examples/internal/simple-dialog.tsx +1 -1
  328. package/src/examples/internal/simple-scrollbox.tsx +58 -0
  329. package/src/examples/internal/simple-scrollbox.vitest.tsx +104 -0
  330. package/src/examples/internal/text-stacking.tsx +4 -2
  331. package/src/examples/list-dropdown-default.tsx +1 -1
  332. package/src/examples/list-dropdown-default.vitest.tsx +136 -71
  333. package/src/examples/list-fetch-data.tsx +1 -1
  334. package/src/examples/list-fetch-data.vitest.tsx +42 -33
  335. package/src/examples/list-scrollbox.tsx +46 -0
  336. package/src/examples/list-scrollbox.vitest.tsx +103 -0
  337. package/src/examples/list-with-detail.tsx +1 -1
  338. package/src/examples/list-with-detail.vitest.tsx +290 -294
  339. package/src/examples/list-with-dropdown.tsx +1 -1
  340. package/src/examples/list-with-dropdown.vitest.tsx +190 -150
  341. package/src/examples/list-with-sections.tsx +12 -1
  342. package/src/examples/list-with-sections.vitest.tsx +390 -218
  343. package/src/examples/miscellaneous.tsx +1 -1
  344. package/src/examples/nested-navigation.tsx +7 -5
  345. package/src/examples/preferences-test.tsx +1 -1
  346. package/src/examples/simple-dropdown.tsx +1 -1
  347. package/src/examples/simple-file-picker.tsx +1 -1
  348. package/src/examples/simple-file-picker.vitest.tsx +533 -127
  349. package/src/examples/simple-grid.tsx +1 -1
  350. package/src/examples/simple-grid.vitest.tsx +258 -234
  351. package/src/examples/simple-hud.tsx +1 -1
  352. package/src/examples/simple-list-search.tsx +42 -1
  353. package/src/examples/simple-list.tsx +1 -1
  354. package/src/examples/simple-navigation.tsx +7 -5
  355. package/src/examples/simple-navigation.vitest.tsx +434 -238
  356. package/src/examples/store.tsx +1 -1
  357. package/src/examples/store.vitest.tsx +31 -14
  358. package/src/examples/submodule-diff.tsx +153 -0
  359. package/src/examples/tanstack-demo.tsx +1 -1
  360. package/src/examples/use-promise-demo.tsx +1 -1
  361. package/src/extensions/dev.tsx +76 -38
  362. package/src/extensions/dev.vitest.tsx +220 -0
  363. package/src/extensions/home.tsx +20 -121
  364. package/src/globals.ts +1 -1
  365. package/src/index.tsx +12 -25
  366. package/src/internal/date-picker-widget.tsx +56 -46
  367. package/src/internal/dialog.tsx +6 -6
  368. package/src/internal/providers.tsx +1 -1
  369. package/src/internal/scrollbox.tsx +63 -0
  370. package/src/release.tsx +159 -0
  371. package/src/state.tsx +2 -0
  372. package/src/store-api/search.test.tsx +4 -13
  373. package/src/theme.tsx +33 -8
  374. package/src/utils/run-command.tsx +204 -0
  375. package/src/utils.tsx +6 -4
  376. package/dist/ai.d.ts +0 -104
  377. package/dist/ai.d.ts.map +0 -1
  378. package/dist/ai.js +0 -135
  379. package/dist/ai.js.map +0 -1
  380. package/dist/apis/cache.test.d.ts +0 -2
  381. package/dist/apis/cache.test.d.ts.map +0 -1
  382. package/dist/apis/cache.test.js +0 -246
  383. package/dist/apis/cache.test.js.map +0 -1
  384. package/dist/apis/localstorage.test.d.ts +0 -2
  385. package/dist/apis/localstorage.test.d.ts.map +0 -1
  386. package/dist/apis/localstorage.test.js +0 -131
  387. package/dist/apis/localstorage.test.js.map +0 -1
  388. package/dist/apis/toast.test.d.ts +0 -2
  389. package/dist/apis/toast.test.d.ts.map +0 -1
  390. package/dist/apis/toast.test.js +0 -67
  391. package/dist/apis/toast.test.js.map +0 -1
  392. package/dist/build.test.d.ts +0 -2
  393. package/dist/build.test.d.ts.map +0 -1
  394. package/dist/build.test.js +0 -73
  395. package/dist/build.test.js.map +0 -1
  396. package/dist/cache.d.ts +0 -32
  397. package/dist/cache.d.ts.map +0 -1
  398. package/dist/cache.js +0 -205
  399. package/dist/cache.js.map +0 -1
  400. package/dist/cache.test.d.ts +0 -2
  401. package/dist/cache.test.d.ts.map +0 -1
  402. package/dist/cache.test.js +0 -246
  403. package/dist/cache.test.js.map +0 -1
  404. package/dist/clipboard.d.ts +0 -36
  405. package/dist/clipboard.d.ts.map +0 -1
  406. package/dist/clipboard.js +0 -154
  407. package/dist/clipboard.js.map +0 -1
  408. package/dist/components/form/form-type-only.d.ts +0 -174
  409. package/dist/components/form/form-type-only.d.ts.map +0 -1
  410. package/dist/components/form/form-type-only.js +0 -2
  411. package/dist/components/form/form-type-only.js.map +0 -1
  412. package/dist/components/form/use-form-handling.d.ts +0 -4
  413. package/dist/components/form/use-form-handling.d.ts.map +0 -1
  414. package/dist/components/form/use-form-handling.js +0 -37
  415. package/dist/components/form/use-form-handling.js.map +0 -1
  416. package/dist/dev-ui.d.ts +0 -7
  417. package/dist/dev-ui.d.ts.map +0 -1
  418. package/dist/dev-ui.js +0 -118
  419. package/dist/dev-ui.js.map +0 -1
  420. package/dist/environment.d.ts +0 -63
  421. package/dist/environment.d.ts.map +0 -1
  422. package/dist/environment.js +0 -189
  423. package/dist/environment.js.map +0 -1
  424. package/dist/examples/datepicker.d.ts +0 -2
  425. package/dist/examples/datepicker.d.ts.map +0 -1
  426. package/dist/examples/datepicker.js +0 -344
  427. package/dist/examples/datepicker.js.map +0 -1
  428. package/dist/examples/form-basic-arrow-keys.vitest.d.ts +0 -2
  429. package/dist/examples/form-basic-arrow-keys.vitest.d.ts.map +0 -1
  430. package/dist/examples/form-basic-arrow-keys.vitest.js +0 -46
  431. package/dist/examples/form-basic-arrow-keys.vitest.js.map +0 -1
  432. package/dist/examples/form-basic.vitest.d.ts +0 -2
  433. package/dist/examples/form-basic.vitest.d.ts.map +0 -1
  434. package/dist/examples/form-basic.vitest.js +0 -995
  435. package/dist/examples/form-basic.vitest.js.map +0 -1
  436. package/dist/examples/form-dropdown-with-sections.d.ts +0 -2
  437. package/dist/examples/form-dropdown-with-sections.d.ts.map +0 -1
  438. package/dist/examples/form-dropdown-with-sections.js +0 -13
  439. package/dist/examples/form-dropdown-with-sections.js.map +0 -1
  440. package/dist/examples/form-dropdown-with-sections.vitest.d.ts +0 -2
  441. package/dist/examples/form-dropdown-with-sections.vitest.d.ts.map +0 -1
  442. package/dist/examples/form-dropdown-with-sections.vitest.js +0 -75
  443. package/dist/examples/form-dropdown-with-sections.vitest.js.map +0 -1
  444. package/dist/examples/form-dropdown.vitest.d.ts +0 -2
  445. package/dist/examples/form-dropdown.vitest.d.ts.map +0 -1
  446. package/dist/examples/form-dropdown.vitest.js +0 -722
  447. package/dist/examples/form-dropdown.vitest.js.map +0 -1
  448. package/dist/examples/form-multiselect-dropdown.d.ts +0 -2
  449. package/dist/examples/form-multiselect-dropdown.d.ts.map +0 -1
  450. package/dist/examples/form-multiselect-dropdown.js +0 -13
  451. package/dist/examples/form-multiselect-dropdown.js.map +0 -1
  452. package/dist/examples/form-tagpicker.vitest.d.ts +0 -2
  453. package/dist/examples/form-tagpicker.vitest.d.ts.map +0 -1
  454. package/dist/examples/form-tagpicker.vitest.js +0 -491
  455. package/dist/examples/form-tagpicker.vitest.js.map +0 -1
  456. package/dist/examples/internal/nested-boxes.d.ts +0 -2
  457. package/dist/examples/internal/nested-boxes.d.ts.map +0 -1
  458. package/dist/examples/internal/nested-boxes.js +0 -7
  459. package/dist/examples/internal/nested-boxes.js.map +0 -1
  460. package/dist/examples/internal/unicode-square-repro.d.ts +0 -2
  461. package/dist/examples/internal/unicode-square-repro.d.ts.map +0 -1
  462. package/dist/examples/internal/unicode-square-repro.js +0 -7
  463. package/dist/examples/internal/unicode-square-repro.js.map +0 -1
  464. package/dist/examples/list-dropdown-default.vitest.d.ts +0 -2
  465. package/dist/examples/list-dropdown-default.vitest.d.ts.map +0 -1
  466. package/dist/examples/list-dropdown-default.vitest.js +0 -164
  467. package/dist/examples/list-dropdown-default.vitest.js.map +0 -1
  468. package/dist/examples/list-fetch-data.vitest.d.ts +0 -2
  469. package/dist/examples/list-fetch-data.vitest.d.ts.map +0 -1
  470. package/dist/examples/list-fetch-data.vitest.js +0 -103
  471. package/dist/examples/list-fetch-data.vitest.js.map +0 -1
  472. package/dist/examples/list-filter-navigation.d.ts +0 -2
  473. package/dist/examples/list-filter-navigation.d.ts.map +0 -1
  474. package/dist/examples/list-filter-navigation.js +0 -8
  475. package/dist/examples/list-filter-navigation.js.map +0 -1
  476. package/dist/examples/list-with-detail.vitest.d.ts +0 -2
  477. package/dist/examples/list-with-detail.vitest.d.ts.map +0 -1
  478. package/dist/examples/list-with-detail.vitest.js +0 -438
  479. package/dist/examples/list-with-detail.vitest.js.map +0 -1
  480. package/dist/examples/list-with-dropdown.vitest.d.ts +0 -2
  481. package/dist/examples/list-with-dropdown.vitest.d.ts.map +0 -1
  482. package/dist/examples/list-with-dropdown.vitest.js +0 -297
  483. package/dist/examples/list-with-dropdown.vitest.js.map +0 -1
  484. package/dist/examples/list-with-sections.vitest.d.ts +0 -2
  485. package/dist/examples/list-with-sections.vitest.d.ts.map +0 -1
  486. package/dist/examples/list-with-sections.vitest.js +0 -441
  487. package/dist/examples/list-with-sections.vitest.js.map +0 -1
  488. package/dist/examples/simple-file-picker.vitest.d.ts +0 -2
  489. package/dist/examples/simple-file-picker.vitest.d.ts.map +0 -1
  490. package/dist/examples/simple-file-picker.vitest.js +0 -277
  491. package/dist/examples/simple-file-picker.vitest.js.map +0 -1
  492. package/dist/examples/simple-grid.vitest.d.ts +0 -2
  493. package/dist/examples/simple-grid.vitest.d.ts.map +0 -1
  494. package/dist/examples/simple-grid.vitest.js +0 -498
  495. package/dist/examples/simple-grid.vitest.js.map +0 -1
  496. package/dist/examples/simple-navigation.vitest.d.ts +0 -2
  497. package/dist/examples/simple-navigation.vitest.d.ts.map +0 -1
  498. package/dist/examples/simple-navigation.vitest.js +0 -522
  499. package/dist/examples/simple-navigation.vitest.js.map +0 -1
  500. package/dist/examples/store.vitest.d.ts +0 -2
  501. package/dist/examples/store.vitest.d.ts.map +0 -1
  502. package/dist/examples/store.vitest.js +0 -52
  503. package/dist/examples/store.vitest.js.map +0 -1
  504. package/dist/home-command.d.ts +0 -8
  505. package/dist/home-command.d.ts.map +0 -1
  506. package/dist/home-command.js +0 -181
  507. package/dist/home-command.js.map +0 -1
  508. package/dist/hooks/hooks.test.d.ts +0 -2
  509. package/dist/hooks/hooks.test.d.ts.map +0 -1
  510. package/dist/hooks/hooks.test.js +0 -37
  511. package/dist/hooks/hooks.test.js.map +0 -1
  512. package/dist/hover-repro.d.ts +0 -2
  513. package/dist/hover-repro.d.ts.map +0 -1
  514. package/dist/hover-repro.js +0 -20
  515. package/dist/hover-repro.js.map +0 -1
  516. package/dist/localstorage.d.ts +0 -13
  517. package/dist/localstorage.d.ts.map +0 -1
  518. package/dist/localstorage.js +0 -190
  519. package/dist/localstorage.js.map +0 -1
  520. package/dist/localstorage.test.d.ts +0 -2
  521. package/dist/localstorage.test.d.ts.map +0 -1
  522. package/dist/localstorage.test.js +0 -131
  523. package/dist/localstorage.test.js.map +0 -1
  524. package/dist/oauth.d.ts +0 -142
  525. package/dist/oauth.d.ts.map +0 -1
  526. package/dist/oauth.js +0 -551
  527. package/dist/oauth.js.map +0 -1
  528. package/dist/preferences.d.ts +0 -23
  529. package/dist/preferences.d.ts.map +0 -1
  530. package/dist/preferences.js +0 -105
  531. package/dist/preferences.js.map +0 -1
  532. package/dist/store-api/download.test.d.ts +0 -2
  533. package/dist/store-api/download.test.d.ts.map +0 -1
  534. package/dist/store-api/download.test.js +0 -36
  535. package/dist/store-api/download.test.js.map +0 -1
  536. package/dist/store-api/extension.test.d.ts +0 -2
  537. package/dist/store-api/extension.test.d.ts.map +0 -1
  538. package/dist/store-api/extension.test.js +0 -22
  539. package/dist/store-api/extension.test.js.map +0 -1
  540. package/dist/store-api/search.test.d.ts +0 -2
  541. package/dist/store-api/search.test.d.ts.map +0 -1
  542. package/dist/store-api/search.test.js +0 -45
  543. package/dist/store-api/search.test.js.map +0 -1
  544. package/dist/store.d.ts +0 -21
  545. package/dist/store.d.ts.map +0 -1
  546. package/dist/store.js +0 -84
  547. package/dist/store.js.map +0 -1
  548. package/dist/toast.d.ts +0 -44
  549. package/dist/toast.d.ts.map +0 -1
  550. package/dist/toast.js +0 -221
  551. package/dist/toast.js.map +0 -1
  552. package/dist/utils.test.d.ts +0 -2
  553. package/dist/utils.test.d.ts.map +0 -1
  554. package/dist/utils.test.js +0 -152
  555. package/dist/utils.test.js.map +0 -1
  556. package/dist/window.d.ts +0 -12
  557. package/dist/window.d.ts.map +0 -1
  558. package/dist/window.js +0 -48
  559. package/dist/window.js.map +0 -1
@@ -1,8 +1,9 @@
1
1
  // This example shows how to filter descendants by passing search query via context
2
2
  // Items conditionally render null when they don't match the search
3
3
  import { useKeyboard } from '@opentui/react'
4
+ import { TextareaRenderable } from '@opentui/core'
4
5
  import { createDescendants } from 'termcast/src/descendants'
5
- import { createContext, useContext, useState } from 'react'
6
+ import { createContext, useContext, useState, useRef } from 'react'
6
7
  import { renderWithProviders } from '../../utils'
7
8
  import { logger } from 'termcast/src/logger'
8
9
 
@@ -36,6 +37,7 @@ const Menu = ({ children }: { children: React.ReactNode }) => {
36
37
  const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set())
37
38
  const [selectedTitles, setSelectedTitles] = useState<string[]>([])
38
39
  const [searchQuery, setSearchQuery] = useState('')
40
+ const inputRef = useRef<TextareaRenderable>(null)
39
41
 
40
42
  useKeyboard((evt) => {
41
43
  const items = Object.values(descendantsContext.map.current).filter(
@@ -125,9 +127,15 @@ const Menu = ({ children }: { children: React.ReactNode }) => {
125
127
  <box flexDirection='column'>
126
128
  <box flexDirection='column' borderStyle='single' padding={1}>
127
129
  <text marginBottom={1}>Filter Menu</text>
128
- <input
129
- value={searchQuery}
130
- onInput={(value) => {
130
+ <textarea
131
+ ref={inputRef}
132
+ height={1}
133
+ keyBindings={[
134
+ { name: 'return', action: 'submit' },
135
+ { name: 'linefeed', action: 'submit' },
136
+ ]}
137
+ onContentChange={() => {
138
+ const value = inputRef.current?.plainText || ''
131
139
  setSearchQuery(value)
132
140
  // Reset focus to first item when search changes
133
141
  setFocusedIndex(0)
@@ -220,4 +228,4 @@ const Example = () => {
220
228
  )
221
229
  }
222
230
 
223
- renderWithProviders(<Example />)
231
+ await renderWithProviders(<Example />)
@@ -1,9 +1,10 @@
1
1
  // read src/descendants.tsx to understand the core hooks that make this example possible
2
2
  //
3
3
  import { useKeyboard } from '@opentui/react'
4
+ import { TextareaRenderable } from '@opentui/core'
4
5
  import { createDescendants } from 'termcast/src/descendants'
5
6
  import { useIsInFocus } from 'termcast/src/internal/focus-context'
6
- import { createContext, useContext, useState } from 'react'
7
+ import { createContext, useContext, useState, useRef, useLayoutEffect } from 'react'
7
8
  import { renderWithProviders } from '../../utils'
8
9
  import { logger } from 'termcast/src/logger'
9
10
 
@@ -167,6 +168,7 @@ const Item = ({ title }: { title: string; key?: any }) => {
167
168
 
168
169
  const Example = () => {
169
170
  const [searchQuery, setSearchQuery] = useState('')
171
+ const inputRef = useRef<TextareaRenderable>(null)
170
172
  const allItems = [
171
173
  'First Item',
172
174
  'Second Item',
@@ -182,6 +184,7 @@ const Example = () => {
182
184
  'Twelfth Item',
183
185
  ]
184
186
 
187
+
185
188
  // Filter items based on search query
186
189
  const filteredItems = allItems.filter((title) =>
187
190
  title.toLowerCase().includes(searchQuery.toLowerCase()),
@@ -189,9 +192,18 @@ const Example = () => {
189
192
 
190
193
  return (
191
194
  <box flexDirection='column'>
192
- <input
193
- value={searchQuery}
194
- onInput={setSearchQuery}
195
+ <textarea
196
+ ref={inputRef}
197
+ height={1}
198
+ keyBindings={[
199
+ { name: 'return', action: 'submit' },
200
+ { name: 'linefeed', action: 'submit' },
201
+ ]}
202
+ initialValue={searchQuery}
203
+ onContentChange={() => {
204
+ const value = inputRef.current?.plainText || ''
205
+ setSearchQuery(value)
206
+ }}
195
207
  focused
196
208
  placeholder='Search items...'
197
209
  marginBottom={1}
@@ -205,4 +217,4 @@ const Example = () => {
205
217
  )
206
218
  }
207
219
 
208
- renderWithProviders(<Example />)
220
+ await renderWithProviders(<Example />)
@@ -0,0 +1,152 @@
1
+ import React, { useRef, useState, useCallback } from 'react'
2
+ import { TextareaRenderable } from '@opentui/core'
3
+ import { useForm } from 'react-hook-form'
4
+ import { useKeyboard } from '@opentui/react'
5
+ import { renderWithProviders } from '../../utils'
6
+ import { Theme } from 'termcast/src/theme'
7
+ import { logger } from 'termcast/src/logger'
8
+ import { createTextareaFormRef } from 'termcast/src/components/form/form-ref'
9
+
10
+ interface FormData {
11
+ username: string
12
+ message: string
13
+ }
14
+
15
+ function RHFCustomRefExample() {
16
+ const textareaRef1 = useRef<TextareaRenderable>(null)
17
+ const textareaRef2 = useRef<TextareaRenderable>(null)
18
+ const [focusedField, setFocusedField] = useState<'username' | 'message'>('username')
19
+
20
+ const { register, handleSubmit, formState, reset, setValue, getValues, watch } =
21
+ useForm<FormData>({
22
+ defaultValues: {
23
+ username: '',
24
+ message: '',
25
+ },
26
+ })
27
+
28
+ const formValues = watch()
29
+
30
+ const onSubmit = (data: FormData) => {
31
+ logger.log('Form submitted:', data)
32
+ }
33
+
34
+ // Get register props
35
+ const usernameRegistration = register('username', { required: 'Username is required' })
36
+ const messageRegistration = register('message', { required: 'Message is required' })
37
+
38
+ // Create form ref adapters with onContentChange handlers
39
+ const { formRef: usernameFormRef, onContentChange: onUsernameChange } =
40
+ createTextareaFormRef('username', textareaRef1, usernameRegistration)
41
+ const { formRef: messageFormRef, onContentChange: onMessageChange } =
42
+ createTextareaFormRef('message', textareaRef2, messageRegistration)
43
+
44
+ // Memoize ref callbacks - register() returns new object every render,
45
+ // so we must not pass registration.ref directly to avoid re-renders
46
+ const handleUsernameRef = useCallback((el: TextareaRenderable | null) => {
47
+ textareaRef1.current = el
48
+ usernameRegistration.ref(usernameFormRef)
49
+ }, [])
50
+
51
+ const handleMessageRef = useCallback((el: TextareaRenderable | null) => {
52
+ textareaRef2.current = el
53
+ messageRegistration.ref(messageFormRef)
54
+ }, [])
55
+
56
+ useKeyboard((evt) => {
57
+ if (evt.name === 'escape') {
58
+ reset()
59
+ logger.log('Form reset')
60
+ }
61
+ if (evt.ctrl && evt.name === 's') {
62
+ handleSubmit(onSubmit)()
63
+ }
64
+ if (evt.ctrl && evt.name === 'v') {
65
+ setValue('username', 'test-user')
66
+ setValue('message', 'Hello from setValue!')
67
+ logger.log('Set values programmatically')
68
+ }
69
+ if (evt.ctrl && evt.name === 'g') {
70
+ logger.log('Current values:', getValues())
71
+ }
72
+ })
73
+
74
+ return (
75
+ <box flexDirection="column" gap={1}>
76
+ <text fg={Theme.accent}>React Hook Form with Custom Ref Adapter</text>
77
+ <text fg={Theme.textMuted}>
78
+ This example uses register() directly with opentui textarea
79
+ </text>
80
+
81
+ <box flexDirection="column">
82
+ <text
83
+ fg={Theme.text}
84
+ onMouseDown={() => {
85
+ setFocusedField('username')
86
+ }}
87
+ >
88
+ Username:
89
+ </text>
90
+ <textarea
91
+ ref={handleUsernameRef}
92
+ height={1}
93
+ placeholder="Enter username..."
94
+ onContentChange={onUsernameChange}
95
+ onMouseDown={() => {
96
+ setFocusedField('username')
97
+ }}
98
+ focused={focusedField === 'username'}
99
+ />
100
+ {formState.errors.username && (
101
+ <text fg={Theme.error}>{formState.errors.username.message}</text>
102
+ )}
103
+ </box>
104
+
105
+ <box flexDirection="column">
106
+ <text
107
+ fg={Theme.text}
108
+ onMouseDown={() => {
109
+ setFocusedField('message')
110
+ }}
111
+ >
112
+ Message:
113
+ </text>
114
+ <textarea
115
+ ref={handleMessageRef}
116
+ height={2}
117
+ placeholder="Enter message..."
118
+ onContentChange={onMessageChange}
119
+ onMouseDown={() => {
120
+ setFocusedField('message')
121
+ }}
122
+ focused={focusedField === 'message'}
123
+ />
124
+ {formState.errors.message && (
125
+ <text fg={Theme.error}>{formState.errors.message.message}</text>
126
+ )}
127
+ </box>
128
+
129
+ <box flexDirection="column" marginTop={1}>
130
+ <text fg={Theme.textMuted}>Controls:</text>
131
+ <text fg={Theme.textMuted}>• Ctrl+S: Submit form</text>
132
+ <text fg={Theme.textMuted}>• Ctrl+V: Set values programmatically</text>
133
+ <text fg={Theme.textMuted}>• Ctrl+G: Get current values</text>
134
+ <text fg={Theme.textMuted}>• ESC: Reset form</text>
135
+ </box>
136
+
137
+ <box marginTop={1}>
138
+ <text fg={Theme.textMuted}>
139
+ isDirty: {String(formState.isDirty)} | isValid:{' '}
140
+ {String(formState.isValid)} | submitCount: {formState.submitCount}
141
+ </text>
142
+ </box>
143
+
144
+ <box marginTop={1} flexDirection="column">
145
+ <text fg={Theme.accent}>Form values:</text>
146
+ <text fg={Theme.text}>{JSON.stringify(formValues, null, 2)}</text>
147
+ </box>
148
+ </box>
149
+ )
150
+ }
151
+
152
+ renderWithProviders(<RHFCustomRefExample />)
@@ -1,7 +1,6 @@
1
1
  import React, { useState, useRef, useEffect } from 'react'
2
2
  import { renderWithProviders } from 'termcast'
3
3
  import { useKeyboard } from '@opentui/react'
4
- import { fg, bold } from '@opentui/core'
5
4
 
6
5
  function ScrollBoxListDemo(): any {
7
6
  const [selectedIndex, setSelectedIndex] = useState(0)
@@ -81,7 +80,11 @@ function ScrollBoxListDemo(): any {
81
80
  return (
82
81
  <box flexDirection='column' width='100%' height='100%'>
83
82
  <box padding={1} backgroundColor='#2e3440'>
84
- <text>{bold(fg('#88c0d0')('ScrollBox Demo'))}</text>
83
+ <text>
84
+ <strong>
85
+ <span fg='#88c0d0'>ScrollBox Demo</span>
86
+ </strong>
87
+ </text>
85
88
  <text fg='#d8dee9'>
86
89
  ↑↓ Navigate | PgUp/PgDn Jump | Home/End First/Last
87
90
  </text>
@@ -89,6 +92,7 @@ function ScrollBoxListDemo(): any {
89
92
 
90
93
  <scrollbox
91
94
  ref={scrollBoxRef}
95
+ focused={true}
92
96
  flexGrow={1}
93
97
  flexShrink={1}
94
98
  style={{
@@ -105,7 +109,7 @@ function ScrollBoxListDemo(): any {
105
109
  flexShrink: 0,
106
110
  },
107
111
  scrollbarOptions: {
108
- visible: true,
112
+
109
113
  showArrows: true,
110
114
  },
111
115
  }}
@@ -123,9 +127,13 @@ function ScrollBoxListDemo(): any {
123
127
  marginBottom={0.5}
124
128
  >
125
129
  <text>
126
- {isSelected
127
- ? bold(fg('#eceff4')(`▶ ${item.title}`))
128
- : fg('#d8dee9')(` ${item.title}`)}
130
+ {isSelected ? (
131
+ <strong>
132
+ <span fg='#eceff4'>{`▶ ${item.title}`}</span>
133
+ </strong>
134
+ ) : (
135
+ <span fg='#d8dee9'>{` ${item.title}`}</span>
136
+ )}
129
137
  </text>
130
138
  <text fg={isSelected ? '#e5e9f0' : '#81a1c1'}>
131
139
  {item.description}
@@ -145,5 +153,5 @@ function ScrollBoxListDemo(): any {
145
153
  }
146
154
 
147
155
  if (import.meta.main) {
148
- renderWithProviders(<ScrollBoxListDemo />)
156
+ await renderWithProviders(<ScrollBoxListDemo />)
149
157
  }
@@ -0,0 +1,94 @@
1
+ import * as React from 'react'
2
+ import { useKeyboard } from '@opentui/react'
3
+ import { createDescendants } from 'termcast/src/descendants'
4
+ import { renderWithProviders } from 'termcast/src/utils'
5
+
6
+ interface ItemDescendant {
7
+ title: string
8
+ elementRef?: { y: number; height: number } | null
9
+ }
10
+
11
+ const { DescendantsProvider, useDescendants, useDescendant } =
12
+ createDescendants<ItemDescendant>()
13
+
14
+ function ScrollboxWithDescendants() {
15
+ const context = useDescendants()
16
+ const [selectedIndex, setSelectedIndex] = React.useState(0)
17
+ const scrollBoxRef = React.useRef<any>(null)
18
+
19
+ const scrollToItem = (item: { props?: ItemDescendant }) => {
20
+ const scrollBox = scrollBoxRef.current
21
+ const elementRef = item.props?.elementRef
22
+ if (!scrollBox || !elementRef) return
23
+
24
+ const contentY = scrollBox.content?.y || 0
25
+ const viewportHeight = scrollBox.viewport?.height || 10
26
+ const currentScrollTop = scrollBox.scrollTop || 0
27
+
28
+ const itemTop = elementRef.y - contentY
29
+ const itemBottom = itemTop + elementRef.height
30
+
31
+ if (itemTop < currentScrollTop) {
32
+ scrollBox.scrollTo(itemTop)
33
+ } else if (itemBottom > currentScrollTop + viewportHeight) {
34
+ scrollBox.scrollTo(itemBottom - viewportHeight)
35
+ }
36
+ }
37
+
38
+ const move = (direction: -1 | 1) => {
39
+ const items = Object.values(context.map.current)
40
+ .filter((item) => item.index !== -1)
41
+ .sort((a, b) => a.index - b.index)
42
+
43
+ if (items.length === 0) return
44
+
45
+ let nextIndex = selectedIndex + direction
46
+ if (nextIndex < 0) nextIndex = items.length - 1
47
+ if (nextIndex >= items.length) nextIndex = 0
48
+
49
+ const nextItem = items[nextIndex]
50
+ if (nextItem) {
51
+ setSelectedIndex(nextIndex)
52
+ scrollToItem(nextItem)
53
+ }
54
+ }
55
+
56
+ useKeyboard((evt) => {
57
+ if (evt.name === 'up') move(-1)
58
+ if (evt.name === 'down') move(1)
59
+ })
60
+
61
+ const items = Array.from({ length: 20 }, (_, i) => `Item ${i + 1}`)
62
+
63
+ return (
64
+ <DescendantsProvider value={context}>
65
+ <box style={{ flexDirection: 'column', height: 10 }}>
66
+ <scrollbox ref={scrollBoxRef} focused={true} flexGrow={1} flexShrink={1}>
67
+ {items.map((title, i) => (
68
+ <Item key={i} title={title} isSelected={selectedIndex === i} />
69
+ ))}
70
+ </scrollbox>
71
+ <text>↑↓ to navigate</text>
72
+ </box>
73
+ </DescendantsProvider>
74
+ )
75
+ }
76
+
77
+ function Item(props: { title: string; isSelected: boolean }) {
78
+ const elementRef = React.useRef<any>(null)
79
+ const { index } = useDescendant({
80
+ title: props.title,
81
+ elementRef: elementRef.current,
82
+ })
83
+
84
+ return (
85
+ <box ref={elementRef}>
86
+ <text>
87
+ {props.isSelected ? '›' : ' '}
88
+ {props.title}
89
+ </text>
90
+ </box>
91
+ )
92
+ }
93
+
94
+ await renderWithProviders(<ScrollboxWithDescendants />)
@@ -121,4 +121,4 @@ function App(): any {
121
121
  )
122
122
  }
123
123
 
124
- renderWithProviders(<App />)
124
+ await renderWithProviders(<App />)
@@ -0,0 +1,58 @@
1
+ import React from 'react'
2
+ import { renderWithProviders } from 'termcast'
3
+ import { useKeyboard } from '@opentui/react'
4
+ import { ScrollBox } from 'termcast/src/internal/scrollbox'
5
+
6
+ function SimpleScrollBoxDemo(): any {
7
+ useKeyboard((evt) => {
8
+ if (evt.name === 'q' || evt.name === 'escape') {
9
+ process.exit(0)
10
+ }
11
+ })
12
+
13
+ const colors = [
14
+ '#e06c75',
15
+ '#98c379',
16
+ '#e5c07b',
17
+ '#61afef',
18
+ '#c678dd',
19
+ '#56b6c2',
20
+ '#abb2bf',
21
+ ]
22
+
23
+ return (
24
+ <box flexDirection="column" width="100%" height="100%">
25
+ <box padding={1} backgroundColor="#282c34">
26
+ <text>
27
+ <strong>
28
+ <span fg='#61afef'>Simple ScrollBox Demo</span>
29
+ </strong>
30
+ </text>
31
+ </box>
32
+
33
+ <ScrollBox focused flexGrow={1} flexShrink={1}>
34
+ {Array.from({ length: 30 }, (_, i) => (
35
+ <box
36
+ key={i}
37
+ padding={1}
38
+ backgroundColor={colors[i % colors.length]}
39
+ marginBottom={1}
40
+ >
41
+ <text fg="#282c34">
42
+ <strong>{`Item ${i + 1}`}</strong> - This is content for item number{' '}
43
+ {i + 1}. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
44
+ </text>
45
+ </box>
46
+ ))}
47
+ </ScrollBox>
48
+
49
+ <box padding={1} backgroundColor="#282c34">
50
+ <text fg="#abb2bf">Use mouse scroll or arrow keys | Press [q] to quit</text>
51
+ </box>
52
+ </box>
53
+ )
54
+ }
55
+
56
+ if (import.meta.main) {
57
+ await renderWithProviders(<SimpleScrollBoxDemo />)
58
+ }
@@ -0,0 +1,104 @@
1
+ import { expect, test } from 'vitest'
2
+ import { launchTerminal, Session } from 'tuistory/src'
3
+
4
+ test('simple scrollbox navigation and scrolling', async () => {
5
+ const session = await launchTerminal({
6
+ command: 'bun',
7
+ args: ['src/examples/internal/simple-scrollbox.tsx'],
8
+ })
9
+
10
+ await session.text({
11
+ waitFor: (text) => text.includes('Simple ScrollBox Demo'),
12
+ })
13
+
14
+ const initialText = await session.text()
15
+ expect(initialText).toMatchInlineSnapshot(`
16
+ "
17
+
18
+
19
+
20
+ Simple ScrollBox Demo
21
+
22
+ Item 1 - This is content for item number 1. Lorem ipsum dolor sit amet,
23
+ consectetur adipiscing elit.
24
+
25
+
26
+
27
+ Item 2 - This is content for item number 2. Lorem ipsum dolor sit amet,
28
+ consectetur adipiscing elit.
29
+
30
+
31
+
32
+ Item 3 - This is content for item number 3. Lorem ipsum dolor sit amet,
33
+ consectetur adipiscing elit.
34
+
35
+
36
+
37
+
38
+ Use mouse scroll or arrow keys | Press [q] to quit"
39
+ `)
40
+
41
+ // Scroll down to see more items
42
+ await session.scrollDown(3)
43
+
44
+ const afterScrollDownSnapshot = await session.text()
45
+ expect(afterScrollDownSnapshot).toMatchInlineSnapshot(`
46
+ "
47
+
48
+
49
+
50
+ Simple ScrollBox Demo
51
+
52
+
53
+
54
+ Item 2 - This is content for item number 2. Lorem ipsum dolor sit amet,
55
+ consectetur adipiscing elit.
56
+
57
+
58
+
59
+ Item 3 - This is content for item number 3. Lorem ipsum dolor sit amet,
60
+ consectetur adipiscing elit.
61
+
62
+
63
+
64
+ Item 4 - This is content for item number 4. Lorem ipsum dolor sit amet,
65
+ consectetur adipiscing elit.
66
+
67
+
68
+ Use mouse scroll or arrow keys | Press [q] to quit"
69
+ `)
70
+
71
+ // Scroll back up
72
+ await session.scrollUp(2)
73
+
74
+ const afterScrollUpSnapshot = await session.text()
75
+ expect(afterScrollUpSnapshot).toMatchInlineSnapshot(`
76
+ "
77
+
78
+
79
+
80
+ Simple ScrollBox Demo
81
+ Item 1 - This is content for item number 1. Lorem ipsum dolor sit amet, ▀
82
+ consectetur adipiscing elit.
83
+
84
+
85
+
86
+ Item 2 - This is content for item number 2. Lorem ipsum dolor sit amet,
87
+ consectetur adipiscing elit.
88
+
89
+
90
+
91
+ Item 3 - This is content for item number 3. Lorem ipsum dolor sit amet,
92
+ consectetur adipiscing elit.
93
+
94
+
95
+
96
+ Item 4 - This is content for item number 4. Lorem ipsum dolor sit amet,
97
+
98
+ Use mouse scroll or arrow keys | Press [q] to quit"
99
+ `)
100
+
101
+ await session.press('esc')
102
+
103
+ session.close()
104
+ }, 30000)
@@ -1,4 +1,5 @@
1
- import { render } from '@opentui/react'
1
+ import { createRoot } from '@opentui/react'
2
+ import { createCliRenderer } from '@opentui/core'
2
3
 
3
4
  function TextStackingExample() {
4
5
  const items = [
@@ -87,4 +88,5 @@ function TextStackingExample() {
87
88
  )
88
89
  }
89
90
 
90
- render(<TextStackingExample />)
91
+ const renderer = await createCliRenderer()
92
+ createRoot(renderer).render(<TextStackingExample />)
@@ -66,4 +66,4 @@ function ListDropdownDefaultExample() {
66
66
  )
67
67
  }
68
68
 
69
- renderWithProviders(<ListDropdownDefaultExample />)
69
+ await renderWithProviders(<ListDropdownDefaultExample />)