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,13 +1,14 @@
1
1
  import React, { ReactNode, useMemo, ReactElement } from 'react'
2
2
  import { TextAttributes } from '@opentui/core'
3
3
  import { useKeyboard } from '@opentui/react'
4
- import { Theme } from 'termcast/src/theme'
4
+ import { Theme, markdownSyntaxStyle } from 'termcast/src/theme'
5
5
  import { InFocus, useIsInFocus } from 'termcast/src/internal/focus-context'
6
6
  import { ActionPanel, Action } from 'termcast/src/components/actions'
7
7
  import { Image } from 'termcast/src/components/list'
8
- import { Color } from 'termcast/src/colors'
9
- import { useStore } from 'termcast/src/state'
8
+ import { Color, resolveColor } from 'termcast/src/colors'
9
+
10
10
  import { useDialog } from 'termcast/src/internal/dialog'
11
+ import { ScrollBox } from 'termcast/src/internal/scrollbox'
11
12
 
12
13
  interface ActionsInterface {
13
14
  actions?: ReactNode
@@ -39,7 +40,7 @@ interface LabelProps {
39
40
  | string
40
41
  | {
41
42
  value: string
42
- color?: Color | null
43
+ color?: Color.ColorLike | null
43
44
  }
44
45
  }
45
46
 
@@ -84,7 +85,7 @@ const DetailMetadataLabel = (props: LabelProps): any => {
84
85
  <text fg={Theme.textMuted} style={{ minWidth: 15 }}>
85
86
  {props.title}:
86
87
  </text>
87
- <text fg={textColor || Theme.text}>{textValue || '—'}</text>
88
+ <text fg={resolveColor(textColor) || Theme.text}>{textValue || '—'}</text>
88
89
  </box>
89
90
  )
90
91
  }
@@ -125,7 +126,7 @@ const DetailMetadataTagListItem = (props: TagListItemProps): any => {
125
126
 
126
127
  return (
127
128
  <text
128
- fg={props.color || Theme.text}
129
+ fg={resolveColor(props.color) || Theme.text}
129
130
  style={{
130
131
  paddingRight: 1,
131
132
  paddingLeft: props.icon ? 1 : 0,
@@ -172,10 +173,11 @@ const DetailMetadata: DetailMetadataType = (props) => {
172
173
  <box
173
174
  style={{
174
175
  flexDirection: 'column',
175
- paddingTop: 2,
176
- paddingLeft: 2,
177
- paddingRight: 2,
176
+ paddingTop: 1,
178
177
  }}
178
+ border={['top']}
179
+ borderStyle='single'
180
+ borderColor={Theme.border}
179
181
  >
180
182
  {props.children}
181
183
  </box>
@@ -194,24 +196,6 @@ function DetailFooter({
194
196
  hasActions?: boolean
195
197
  firstActionTitle?: string
196
198
  }): any {
197
- const toast = useStore((state) => state.toast)
198
-
199
- if (toast) {
200
- return (
201
- <box
202
- border={false}
203
- style={{
204
- paddingLeft: 1,
205
- paddingRight: 1,
206
- paddingTop: 1,
207
- marginTop: 1,
208
- }}
209
- >
210
- {toast}
211
- </box>
212
- )
213
- }
214
-
215
199
  return (
216
200
  <box
217
201
  border={false}
@@ -285,17 +269,10 @@ const Detail: DetailType = (props) => {
285
269
  const dialog = useDialog()
286
270
  const inFocus = useIsInFocus()
287
271
 
288
- const markdownLines = useMemo(() => {
289
- if (!props.markdown) return []
290
- // TODO: Implement proper markdown parsing
291
- return props.markdown.split('\n')
292
- }, [props.markdown])
293
-
294
272
  const firstActionTitle = useMemo(() => {
295
273
  return actions ? getFirstActionTitle(actions) : undefined
296
274
  }, [actions])
297
275
 
298
- // Handle Ctrl+K and Return to show actions
299
276
  useKeyboard((evt) => {
300
277
  if (!inFocus) return
301
278
 
@@ -307,43 +284,34 @@ const Detail: DetailType = (props) => {
307
284
  })
308
285
 
309
286
  const content = (
310
- <box
287
+ <ScrollBox
288
+ focused={true}
289
+ flexGrow={1}
290
+ flexShrink={1}
311
291
  style={{
312
- flexDirection: 'row',
313
- flexGrow: 1,
314
- width: '100%',
292
+ rootOptions: {
293
+ backgroundColor: undefined,
294
+ },
295
+
315
296
  }}
316
297
  >
317
298
  <box
318
299
  style={{
319
- flexGrow: 1,
320
300
  flexDirection: 'column',
321
301
  paddingTop: 2,
322
- // paddingLeft: 2,
323
- paddingRight: props.metadata ? 1 : 2,
302
+ paddingRight: 2,
324
303
  }}
325
304
  >
326
- {markdownLines.map((line, index) => (
327
- <text key={index} fg={Theme.text}>
328
- {line || ' '}
329
- </text>
330
- ))}
305
+ {props.markdown && (
306
+ <code content={props.markdown} conceal filetype="markdown" syntaxStyle={markdownSyntaxStyle} drawUnstyledText={false} />
307
+ )}
308
+ {props.metadata}
331
309
  </box>
332
- {props.metadata && (
333
- <box
334
- style={{
335
- flexShrink: 0,
336
- width: 40,
337
- }}
338
- >
339
- {props.metadata}
340
- </box>
341
- )}
342
- </box>
310
+ </ScrollBox>
343
311
  )
344
312
 
345
313
  return (
346
- <box style={{ flexDirection: 'column', height: '100%' }}>
314
+ <box style={{ flexDirection: 'column', height: '100%', flexGrow: 1 }}>
347
315
  {content}
348
316
  <DetailFooter
349
317
  hasActions={!!actions}
@@ -8,12 +8,17 @@ import React, {
8
8
  useContext,
9
9
  } from 'react'
10
10
  import { useKeyboard } from '@opentui/react'
11
- import { TextAttributes } from '@opentui/core'
11
+ import {
12
+ TextAttributes,
13
+ ScrollBoxRenderable,
14
+ TextareaRenderable,
15
+ } from '@opentui/core'
12
16
  import { Theme } from 'termcast/src/theme'
13
17
  import { logger } from 'termcast/src/logger'
14
18
  import { useIsInFocus } from 'termcast/src/internal/focus-context'
15
19
  import { CommonProps } from 'termcast/src/utils'
16
20
  import { createDescendants } from 'termcast/src/descendants'
21
+ import { ScrollBox } from 'termcast/src/internal/scrollbox'
17
22
 
18
23
  // SearchBarInterface provides the common search bar props
19
24
  interface SearchBarInterface {
@@ -41,6 +46,7 @@ export interface DropdownItemProps extends CommonProps {
41
46
 
42
47
  keywords?: string[]
43
48
  label?: string
49
+ color?: string
44
50
  }
45
51
 
46
52
  export interface DropdownSectionProps extends CommonProps {
@@ -53,6 +59,7 @@ interface DropdownItemDescendant {
53
59
  value: string
54
60
  title: string
55
61
  hidden?: boolean
62
+ elementRef?: { y: number; height: number } | null
56
63
  }
57
64
 
58
65
  const {
@@ -70,6 +77,7 @@ interface DropdownContextValue {
70
77
  setSelectedIndex?: (index: number) => void
71
78
  currentValue?: string
72
79
  onChange?: (value: string) => void
80
+ scrollBoxRef?: React.RefObject<ScrollBoxRenderable | null>
73
81
  }
74
82
 
75
83
  const DropdownContext = createContext<DropdownContextValue>({
@@ -100,15 +108,45 @@ const Dropdown: DropdownType = (props) => {
100
108
  } = props
101
109
 
102
110
  const [selected, setSelected] = useState(0)
103
- const [searchText, setSearchText] = useState('')
111
+ const [searchText, setSearchTextState] = useState('')
104
112
  const [currentValue, setCurrentValue] = useState<string | undefined>(
105
113
  value || defaultValue,
106
114
  )
107
- const inputRef = useRef<any>(null)
115
+ const inputRef = useRef<TextareaRenderable>(null)
108
116
  const lastSearchTextRef = useRef('')
109
117
  const throttleTimeoutRef = useRef<NodeJS.Timeout | undefined>(undefined)
118
+ const scrollBoxRef = useRef<ScrollBoxRenderable>(null)
110
119
  const descendantsContext = useDropdownDescendants()
111
120
 
121
+ // Update textarea and reset selection - single source of truth is the ref
122
+ const setSearchText = (text: string) => {
123
+ inputRef.current?.setText(text)
124
+ setSearchTextState(text)
125
+ setSelected(0)
126
+ }
127
+
128
+ const scrollToItem = (item: { props?: DropdownItemDescendant }) => {
129
+ const scrollBox = scrollBoxRef.current
130
+ const elementRef = item.props?.elementRef
131
+ if (!scrollBox || !elementRef) return
132
+
133
+ const contentY = scrollBox.content?.y || 0
134
+ const viewportHeight = scrollBox.viewport?.height || 10
135
+ const currentScrollTop = scrollBox.scrollTop || 0
136
+
137
+ const itemTop = elementRef.y - contentY
138
+ const itemBottom = itemTop + elementRef.height
139
+
140
+ const visibleTop = currentScrollTop
141
+ const visibleBottom = currentScrollTop + viewportHeight
142
+
143
+ if (itemTop < visibleTop) {
144
+ scrollBox.scrollTo(itemTop)
145
+ } else if (itemBottom > visibleBottom) {
146
+ scrollBox.scrollTo(itemBottom - viewportHeight)
147
+ }
148
+ }
149
+
112
150
  // Create context value for children
113
151
  const contextValue = useMemo<DropdownContextValue>(
114
152
  () => ({
@@ -119,6 +157,7 @@ const Dropdown: DropdownType = (props) => {
119
157
  setSelectedIndex: setSelected,
120
158
  currentValue,
121
159
  onChange: (value: string) => selectItem(value),
160
+ scrollBoxRef,
122
161
  }),
123
162
  [searchText, filtering, selected, currentValue],
124
163
  )
@@ -130,16 +169,13 @@ const Dropdown: DropdownType = (props) => {
130
169
  }
131
170
  }, [value])
132
171
 
133
- // Reset selected index when search changes
134
- useEffect(() => {
135
- setSelected(0)
136
- }, [searchText])
137
-
138
- // Handle search text change with throttling
172
+ // Handle search text change from textarea - called by onContentChange
139
173
  const handleSearchTextChange = (text: string) => {
140
174
  if (!inFocus) return
141
175
 
142
- setSearchText(text)
176
+ // Update state for context and reset selection
177
+ setSearchTextState(text)
178
+ setSelected(0)
143
179
 
144
180
  if (onSearchTextChange) {
145
181
  if (throttle) {
@@ -157,15 +193,31 @@ const Dropdown: DropdownType = (props) => {
157
193
 
158
194
  const move = (direction: -1 | 1) => {
159
195
  const items = Object.values(descendantsContext.map.current)
160
- .filter((item: any) => item.index !== -1)
196
+ .filter((item: any) => item.index !== -1 && !item.props?.hidden)
161
197
  .sort((a: any, b: any) => a.index - b.index)
162
198
 
163
199
  if (items.length === 0) return
164
200
 
165
- let next = selected + direction
166
- if (next < 0) next = items.length - 1
167
- if (next >= items.length) next = 0
168
- setSelected(next)
201
+ let currentVisibleIndex = items.findIndex(
202
+ (item) => item.index === selected,
203
+ )
204
+ if (currentVisibleIndex === -1) {
205
+ if (items[0]) {
206
+ setSelected(items[0].index)
207
+ scrollToItem(items[0])
208
+ }
209
+ return
210
+ }
211
+
212
+ let nextVisibleIndex = currentVisibleIndex + direction
213
+ if (nextVisibleIndex < 0) nextVisibleIndex = items.length - 1
214
+ if (nextVisibleIndex >= items.length) nextVisibleIndex = 0
215
+
216
+ const nextItem = items[nextVisibleIndex]
217
+ if (nextItem) {
218
+ setSelected(nextItem.index)
219
+ scrollToItem(nextItem)
220
+ }
169
221
  }
170
222
 
171
223
  const selectItem = (itemValue: string) => {
@@ -220,22 +272,46 @@ const Dropdown: DropdownType = (props) => {
220
272
  <text fg={Theme.textMuted}>esc</text>
221
273
  </box>
222
274
  <box style={{ paddingTop: 1, paddingBottom: 1 }}>
223
- <input
275
+ <textarea
224
276
  ref={inputRef}
225
- onInput={(value) => handleSearchTextChange(value)}
277
+ height={1}
278
+ keyBindings={[
279
+ { name: 'return', action: 'submit' },
280
+ { name: 'linefeed', action: 'submit' },
281
+ ]}
282
+ onContentChange={() => {
283
+ const value = inputRef.current?.plainText || ''
284
+ handleSearchTextChange(value)
285
+ }}
226
286
  placeholder={placeholder}
227
287
  focused={inFocus}
228
- value={searchText}
288
+ initialValue=""
229
289
  focusedBackgroundColor={Theme.backgroundPanel}
230
290
  cursorColor={Theme.primary}
231
291
  focusedTextColor={Theme.textMuted}
232
292
  />
233
293
  </box>
234
294
  </box>
235
- <box style={{ paddingBottom: 1 }}>
295
+ <ScrollBox
296
+ ref={scrollBoxRef}
297
+ focused={false}
298
+ flexGrow={1}
299
+ flexShrink={1}
300
+ style={{
301
+ rootOptions: {
302
+ backgroundColor: undefined,
303
+ maxHeight: 10,
304
+ },
305
+ scrollbarOptions: {
306
+
307
+ showArrows: false,
308
+
309
+ },
310
+ }}
311
+ >
236
312
  {/* Render children - they will register as descendants and render themselves */}
237
313
  {children}
238
- </box>
314
+ </ScrollBox>
239
315
  </box>
240
316
  <box
241
317
  border={false}
@@ -268,13 +344,16 @@ function ItemOption(props: {
268
344
  active?: boolean
269
345
  current?: boolean
270
346
  label?: string
347
+ color?: string
271
348
  onMouseDown?: () => void
272
349
  onMouseMove?: () => void
350
+ elementRef?: React.Ref<any>
273
351
  }) {
274
352
  const [isHovered, setIsHovered] = useState(false)
275
353
 
276
354
  return (
277
355
  <box
356
+ ref={props.elementRef}
278
357
  style={{
279
358
  flexDirection: 'row',
280
359
  backgroundColor: props.active
@@ -312,9 +391,11 @@ function ItemOption(props: {
312
391
  fg={
313
392
  props.active
314
393
  ? Theme.background
315
- : props.current
316
- ? Theme.primary
317
- : Theme.text
394
+ : props.color
395
+ ? props.color
396
+ : props.current
397
+ ? Theme.primary
398
+ : Theme.text
318
399
  }
319
400
  attributes={props.active ? TextAttributes.BOLD : undefined}
320
401
  selectable={false}
@@ -337,6 +418,7 @@ function ItemOption(props: {
337
418
 
338
419
  const DropdownItem: (props: DropdownItemProps) => any = (props) => {
339
420
  const context = useContext(DropdownContext)
421
+ const elementRef = useRef<{ y: number; height: number } | null>(null)
340
422
  if (!context) return null
341
423
 
342
424
  const { searchText, filtering, currentSection, selectedIndex, currentValue } =
@@ -358,6 +440,7 @@ const DropdownItem: (props: DropdownItemProps) => any = (props) => {
358
440
  value: props.value,
359
441
  title: props.title,
360
442
  hidden: shouldHide,
443
+ elementRef: elementRef.current,
361
444
  })
362
445
 
363
446
  // Don't render if hidden
@@ -394,8 +477,10 @@ const DropdownItem: (props: DropdownItemProps) => any = (props) => {
394
477
  active={isActive}
395
478
  current={isCurrent}
396
479
  label={props.label}
480
+ color={props.color}
397
481
  onMouseMove={handleMouseMove}
398
482
  onMouseDown={handleMouseDown}
483
+ elementRef={elementRef}
399
484
  />
400
485
  )
401
486
  }
@@ -1,7 +1,10 @@
1
- import React, { useState, useEffect } from 'react'
1
+ import React from 'react'
2
2
  import fs from 'node:fs'
3
3
  import path from 'node:path'
4
- import { Form, showToast, Toast, ActionPanel, Action } from 'termcast'
4
+ import { useQuery } from '@tanstack/react-query'
5
+ import { Form } from './form'
6
+ import { showToast, Toast } from '../apis/toast'
7
+ import { ActionPanel, Action } from './actions'
5
8
  import { LocalStorage } from 'termcast/src/apis/localstorage'
6
9
  import { useNavigation } from 'termcast/src/internal/navigation'
7
10
  import { logger } from 'termcast/src/logger'
@@ -37,15 +40,12 @@ export function ExtensionPreferences({
37
40
  commandName,
38
41
  onSubmit,
39
42
  }: ExtensionPreferencesProps): any {
40
- const [preferences, setPreferences] = useState<PreferenceManifest[]>([])
41
- const [savedValues, setSavedValues] = useState<Record<string, any>>({})
42
- const [isLoading, setIsLoading] = useState(true)
43
43
  const { pop } = useNavigation()
44
44
 
45
- useEffect(() => {
46
- const loadPreferences = async () => {
45
+ const { data, isLoading } = useQuery({
46
+ queryKey: ['extension-preferences', extensionName, commandName],
47
+ queryFn: async () => {
47
48
  try {
48
- // Get extension package.json to read preference manifest
49
49
  const storeDir = getStoreDirectory()
50
50
  const extensionDir = path.join(storeDir, extensionName)
51
51
  const packageJsonPath = path.join(extensionDir, 'package.json')
@@ -58,11 +58,9 @@ export function ExtensionPreferences({
58
58
  fs.readFileSync(packageJsonPath, 'utf-8'),
59
59
  )
60
60
 
61
- // Get preferences based on whether this is for a command or extension
62
61
  let prefsToUse: PreferenceManifest[] = []
63
62
 
64
63
  if (commandName) {
65
- // Look for command-specific preferences
66
64
  const command = packageJson.commands?.find(
67
65
  (cmd) => cmd.name === commandName,
68
66
  )
@@ -70,40 +68,38 @@ export function ExtensionPreferences({
70
68
  prefsToUse = command.preferences || []
71
69
  }
72
70
  } else {
73
- // Get extension preferences (shared across all commands)
74
71
  prefsToUse = packageJson.preferences || []
75
72
  }
76
73
 
77
- // Load saved values from LocalStorage
78
74
  const preferencesKey = commandName
79
75
  ? `preferences.${extensionName}.${commandName}`
80
76
  : `preferences.${extensionName}`
81
77
  const saved = await LocalStorage.getItem(preferencesKey)
82
78
 
79
+ let savedValues: Record<string, any> = {}
83
80
  if (saved && typeof saved === 'string') {
84
81
  try {
85
- const parsed = JSON.parse(saved)
86
- setSavedValues(parsed)
82
+ savedValues = JSON.parse(saved)
87
83
  } catch (e) {
88
84
  logger.error('Failed to parse saved preferences:', e)
89
85
  }
90
86
  }
91
87
 
92
- setPreferences(prefsToUse)
88
+ return { preferences: prefsToUse, savedValues }
93
89
  } catch (error) {
94
90
  logger.error(`Failed to load preferences for ${extensionName}:`, error)
95
- await showToast({
91
+ showToast({
96
92
  style: Toast.Style.Failure,
97
93
  title: 'Failed to load preferences',
98
94
  message: String(error),
99
95
  })
100
- } finally {
101
- setIsLoading(false)
96
+ return { preferences: [], savedValues: {} }
102
97
  }
103
- }
98
+ },
99
+ })
104
100
 
105
- loadPreferences()
106
- }, [extensionName])
101
+ const preferences = data?.preferences ?? []
102
+ const savedValues = data?.savedValues ?? {}
107
103
 
108
104
  const handleSubmit = async (values: Record<string, any>) => {
109
105
  try {
@@ -235,27 +231,51 @@ export function ExtensionPreferences({
235
231
  </Form.Dropdown>
236
232
  )
237
233
 
238
- // TODO: Implement file and directory pickers and appPicker
239
234
  case 'file':
235
+ return (
236
+ <Form.FilePicker
237
+ key={pref.name}
238
+ id={pref.name}
239
+ title={pref.title}
240
+ placeholder={pref.placeholder || 'Select a file'}
241
+ defaultValue={defaultValue ? [defaultValue] : []}
242
+ info={pref.description}
243
+ allowMultipleSelection={false}
244
+ canChooseFiles={true}
245
+ canChooseDirectories={false}
246
+ storeValue
247
+ />
248
+ )
249
+
240
250
  case 'directory':
251
+ return (
252
+ <Form.FilePicker
253
+ key={pref.name}
254
+ id={pref.name}
255
+ title={pref.title}
256
+ placeholder={pref.placeholder || 'Select a folder'}
257
+ defaultValue={defaultValue ? [defaultValue] : []}
258
+ info={pref.description}
259
+ allowMultipleSelection={false}
260
+ canChooseFiles={false}
261
+ canChooseDirectories={true}
262
+ storeValue
263
+ />
264
+ )
265
+
241
266
  case 'appPicker':
242
267
  return (
243
- <Form.TextField
268
+ <Form.FilePicker
244
269
  key={pref.name}
245
270
  id={pref.name}
246
271
  title={pref.title}
247
- placeholder={
248
- pref.type === 'file'
249
- ? 'Enter file path'
250
- : pref.type === 'directory'
251
- ? 'Enter directory path'
252
- : 'Enter application name'
253
- }
254
- defaultValue={defaultValue}
255
- info={
256
- pref.description ||
257
- `Select a ${pref.type.replace('appPicker', 'application')}`
258
- }
272
+ placeholder={pref.placeholder || 'Select an application'}
273
+ defaultValue={defaultValue ? [defaultValue] : []}
274
+ info={pref.description || 'Select an application'}
275
+ allowMultipleSelection={false}
276
+ canChooseFiles={true}
277
+ canChooseDirectories={false}
278
+ initialDirectory='/Applications'
259
279
  storeValue
260
280
  />
261
281
  )
@@ -1,8 +1,8 @@
1
- import React from 'react'
2
- import { TextAttributes } from '@opentui/core'
1
+ import React, { useRef } from 'react'
2
+ import { TextAttributes, BoxRenderable } from '@opentui/core'
3
3
  import { useKeyboard } from '@opentui/react'
4
4
  import { useFormContext, Controller } from 'react-hook-form'
5
- import { useFocusContext } from './index'
5
+ import { useFocusContext, useFormFieldDescendant } from './index'
6
6
  import { FormItemProps, FormItemRef } from './types'
7
7
  import { logger } from 'termcast/src/logger'
8
8
  import { Theme } from 'termcast/src/theme'
@@ -22,6 +22,14 @@ export const Checkbox = (props: CheckboxProps): any => {
22
22
  const isFocused = focusedField === props.id
23
23
  const isInFocus = useIsInFocus()
24
24
 
25
+ const elementRef = useRef<BoxRenderable>(null)
26
+
27
+ // Register as form field descendant for scroll support
28
+ useFormFieldDescendant({
29
+ id: props.id,
30
+ elementRef: elementRef.current,
31
+ })
32
+
25
33
  // Use form navigation hook
26
34
  useFormNavigation(props.id)
27
35
  const handleToggle = () => {
@@ -48,10 +56,10 @@ export const Checkbox = (props: CheckboxProps): any => {
48
56
  defaultValue={props.defaultValue || props.value || false}
49
57
  render={({ field, fieldState, formState }) => {
50
58
  return (
51
- <box flexDirection='column'>
59
+ <box ref={elementRef} flexDirection='column'>
52
60
  <WithLeftBorder withDiamond isFocused={isFocused}>
53
61
  <text
54
- fg={Theme.text}
62
+ fg={isFocused ? Theme.primary : Theme.text}
55
63
  onMouseDown={() => {
56
64
  // Always focus the field when clicked
57
65
  if (!isFocused) {