termcast 1.3.19 → 1.3.24

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 (412) hide show
  1. package/dist/ai.d.ts +104 -0
  2. package/dist/ai.d.ts.map +1 -0
  3. package/dist/ai.js +135 -0
  4. package/dist/ai.js.map +1 -0
  5. package/dist/apis/browser-extension.d.ts +18 -0
  6. package/dist/apis/browser-extension.d.ts.map +1 -0
  7. package/dist/apis/browser-extension.js +14 -0
  8. package/dist/apis/browser-extension.js.map +1 -0
  9. package/dist/apis/localstorage.d.ts.map +1 -1
  10. package/dist/apis/localstorage.js +4 -7
  11. package/dist/apis/localstorage.js.map +1 -1
  12. package/dist/apis/oauth.d.ts.map +1 -1
  13. package/dist/apis/oauth.js +5 -1
  14. package/dist/apis/oauth.js.map +1 -1
  15. package/dist/apis/preferences.d.ts.map +1 -1
  16. package/dist/apis/preferences.js +38 -19
  17. package/dist/apis/preferences.js.map +1 -1
  18. package/dist/build.d.ts.map +1 -1
  19. package/dist/build.js +2 -1
  20. package/dist/build.js.map +1 -1
  21. package/dist/cache.d.ts +32 -0
  22. package/dist/cache.d.ts.map +1 -0
  23. package/dist/cache.js +205 -0
  24. package/dist/cache.js.map +1 -0
  25. package/dist/cli.d.ts.map +1 -1
  26. package/dist/cli.js +69 -33
  27. package/dist/cli.js.map +1 -1
  28. package/dist/clipboard.d.ts +36 -0
  29. package/dist/clipboard.d.ts.map +1 -0
  30. package/dist/clipboard.js +154 -0
  31. package/dist/clipboard.js.map +1 -0
  32. package/dist/compile.d.ts.map +1 -1
  33. package/dist/compile.js +24 -6
  34. package/dist/compile.js.map +1 -1
  35. package/dist/components/actions.d.ts.map +1 -1
  36. package/dist/components/actions.js +56 -30
  37. package/dist/components/actions.js.map +1 -1
  38. package/dist/components/detail.d.ts.map +1 -1
  39. package/dist/components/detail.js +4 -0
  40. package/dist/components/detail.js.map +1 -1
  41. package/dist/components/dropdown.d.ts.map +1 -1
  42. package/dist/components/dropdown.js +38 -15
  43. package/dist/components/dropdown.js.map +1 -1
  44. package/dist/components/extension-preferences.d.ts.map +1 -1
  45. package/dist/components/extension-preferences.js +40 -13
  46. package/dist/components/extension-preferences.js.map +1 -1
  47. package/dist/components/form/checkbox.d.ts.map +1 -1
  48. package/dist/components/form/checkbox.js +5 -3
  49. package/dist/components/form/checkbox.js.map +1 -1
  50. package/dist/components/form/date-picker.d.ts.map +1 -1
  51. package/dist/components/form/date-picker.js +5 -3
  52. package/dist/components/form/date-picker.js.map +1 -1
  53. package/dist/components/form/description.d.ts.map +1 -1
  54. package/dist/components/form/description.js +2 -2
  55. package/dist/components/form/description.js.map +1 -1
  56. package/dist/components/form/dropdown.d.ts.map +1 -1
  57. package/dist/components/form/dropdown.js +84 -80
  58. package/dist/components/form/dropdown.js.map +1 -1
  59. package/dist/components/form/file-autocomplete.d.ts +3 -6
  60. package/dist/components/form/file-autocomplete.d.ts.map +1 -1
  61. package/dist/components/form/file-autocomplete.js +61 -66
  62. package/dist/components/form/file-autocomplete.js.map +1 -1
  63. package/dist/components/form/file-picker.d.ts.map +1 -1
  64. package/dist/components/form/file-picker.js +33 -30
  65. package/dist/components/form/file-picker.js.map +1 -1
  66. package/dist/components/form/form-end.d.ts.map +1 -1
  67. package/dist/components/form/form-end.js +21 -1
  68. package/dist/components/form/form-end.js.map +1 -1
  69. package/dist/components/form/form-type-only.d.ts +174 -0
  70. package/dist/components/form/form-type-only.d.ts.map +1 -0
  71. package/dist/components/form/form-type-only.js +2 -0
  72. package/dist/components/form/form-type-only.js.map +1 -0
  73. package/dist/components/form/index.d.ts +3 -1
  74. package/dist/components/form/index.d.ts.map +1 -1
  75. package/dist/components/form/index.js +100 -28
  76. package/dist/components/form/index.js.map +1 -1
  77. package/dist/components/form/password-field.d.ts.map +1 -1
  78. package/dist/components/form/password-field.js +5 -3
  79. package/dist/components/form/password-field.js.map +1 -1
  80. package/dist/components/form/text-area.d.ts.map +1 -1
  81. package/dist/components/form/text-area.js +5 -3
  82. package/dist/components/form/text-area.js.map +1 -1
  83. package/dist/components/form/text-field.d.ts.map +1 -1
  84. package/dist/components/form/text-field.js +6 -4
  85. package/dist/components/form/text-field.js.map +1 -1
  86. package/dist/components/form/types.d.ts +5 -0
  87. package/dist/components/form/types.d.ts.map +1 -1
  88. package/dist/components/form/use-form-handling.d.ts +4 -0
  89. package/dist/components/form/use-form-handling.d.ts.map +1 -0
  90. package/dist/components/form/use-form-handling.js +37 -0
  91. package/dist/components/form/use-form-handling.js.map +1 -0
  92. package/dist/components/form/with-left-border.d.ts +2 -1
  93. package/dist/components/form/with-left-border.d.ts.map +1 -1
  94. package/dist/components/form/with-left-border.js +27 -3
  95. package/dist/components/form/with-left-border.js.map +1 -1
  96. package/dist/components/icon.d.ts +1 -0
  97. package/dist/components/icon.d.ts.map +1 -1
  98. package/dist/components/icon.js +24 -8
  99. package/dist/components/icon.js.map +1 -1
  100. package/dist/components/list.d.ts +2 -2
  101. package/dist/components/list.d.ts.map +1 -1
  102. package/dist/components/list.js +140 -62
  103. package/dist/components/list.js.map +1 -1
  104. package/dist/components/loading-bar.d.ts.map +1 -1
  105. package/dist/components/loading-bar.js +2 -2
  106. package/dist/components/loading-bar.js.map +1 -1
  107. package/dist/components/loading-text.d.ts +8 -0
  108. package/dist/components/loading-text.d.ts.map +1 -0
  109. package/dist/components/loading-text.js +58 -0
  110. package/dist/components/loading-text.js.map +1 -0
  111. package/dist/descendants.js +1 -1
  112. package/dist/descendants.js.map +1 -1
  113. package/dist/dev-ui.d.ts +7 -0
  114. package/dist/dev-ui.d.ts.map +1 -0
  115. package/dist/dev-ui.js +118 -0
  116. package/dist/dev-ui.js.map +1 -0
  117. package/dist/environment.d.ts +63 -0
  118. package/dist/environment.d.ts.map +1 -0
  119. package/dist/environment.js +189 -0
  120. package/dist/environment.js.map +1 -0
  121. package/dist/examples/datepicker.d.ts +2 -0
  122. package/dist/examples/datepicker.d.ts.map +1 -0
  123. package/dist/examples/datepicker.js +344 -0
  124. package/dist/examples/datepicker.js.map +1 -0
  125. package/dist/examples/file-autocomplete.vitest.d.ts +2 -0
  126. package/dist/examples/file-autocomplete.vitest.d.ts.map +1 -0
  127. package/dist/examples/file-autocomplete.vitest.js +223 -0
  128. package/dist/examples/file-autocomplete.vitest.js.map +1 -0
  129. package/dist/examples/form-basic-arrow-keys.vitest.d.ts +2 -0
  130. package/dist/examples/form-basic-arrow-keys.vitest.d.ts.map +1 -0
  131. package/dist/examples/form-basic-arrow-keys.vitest.js +46 -0
  132. package/dist/examples/form-basic-arrow-keys.vitest.js.map +1 -0
  133. package/dist/examples/form-basic.vitest.d.ts +2 -0
  134. package/dist/examples/form-basic.vitest.d.ts.map +1 -0
  135. package/dist/examples/form-basic.vitest.js +630 -0
  136. package/dist/examples/form-basic.vitest.js.map +1 -0
  137. package/dist/examples/form-dropdown-with-sections.d.ts +2 -0
  138. package/dist/examples/form-dropdown-with-sections.d.ts.map +1 -0
  139. package/dist/examples/form-dropdown-with-sections.js +13 -0
  140. package/dist/examples/form-dropdown-with-sections.js.map +1 -0
  141. package/dist/examples/form-dropdown-with-sections.vitest.d.ts +2 -0
  142. package/dist/examples/form-dropdown-with-sections.vitest.d.ts.map +1 -0
  143. package/dist/examples/form-dropdown-with-sections.vitest.js +75 -0
  144. package/dist/examples/form-dropdown-with-sections.vitest.js.map +1 -0
  145. package/dist/examples/form-dropdown.vitest.d.ts +2 -0
  146. package/dist/examples/form-dropdown.vitest.d.ts.map +1 -0
  147. package/dist/examples/form-dropdown.vitest.js +854 -0
  148. package/dist/examples/form-dropdown.vitest.js.map +1 -0
  149. package/dist/examples/form-multiselect-dropdown.d.ts +2 -0
  150. package/dist/examples/form-multiselect-dropdown.d.ts.map +1 -0
  151. package/dist/examples/form-multiselect-dropdown.js +13 -0
  152. package/dist/examples/form-multiselect-dropdown.js.map +1 -0
  153. package/dist/examples/form-scroll.d.ts.map +1 -1
  154. package/dist/examples/form-scroll.js +7 -1
  155. package/dist/examples/form-scroll.js.map +1 -1
  156. package/dist/examples/form-scroll.vitest.d.ts +2 -0
  157. package/dist/examples/form-scroll.vitest.d.ts.map +1 -0
  158. package/dist/examples/form-scroll.vitest.js +211 -0
  159. package/dist/examples/form-scroll.vitest.js.map +1 -0
  160. package/dist/examples/form-tagpicker.vitest.d.ts +2 -0
  161. package/dist/examples/form-tagpicker.vitest.d.ts.map +1 -0
  162. package/dist/examples/form-tagpicker.vitest.js +736 -0
  163. package/dist/examples/form-tagpicker.vitest.js.map +1 -0
  164. package/dist/examples/internal/descendants-filtering.js +1 -1
  165. package/dist/examples/internal/descendants-filtering.js.map +1 -1
  166. package/dist/examples/internal/descendants.js +1 -1
  167. package/dist/examples/internal/descendants.js.map +1 -1
  168. package/dist/examples/internal/nested-boxes.d.ts +2 -0
  169. package/dist/examples/internal/nested-boxes.d.ts.map +1 -0
  170. package/dist/examples/internal/nested-boxes.js +7 -0
  171. package/dist/examples/internal/nested-boxes.js.map +1 -0
  172. package/dist/examples/internal/rhf-custom-ref.js +2 -2
  173. package/dist/examples/internal/rhf-custom-ref.js.map +1 -1
  174. package/dist/examples/internal/scrollbox-demo.js +3 -22
  175. package/dist/examples/internal/scrollbox-demo.js.map +1 -1
  176. package/dist/examples/internal/scrollbox-descendants.d.ts +2 -0
  177. package/dist/examples/internal/scrollbox-descendants.d.ts.map +1 -0
  178. package/dist/examples/internal/scrollbox-descendants.js +83 -0
  179. package/dist/examples/internal/scrollbox-descendants.js.map +1 -0
  180. package/dist/examples/internal/scrollbox-with-descendants.js +4 -8
  181. package/dist/examples/internal/scrollbox-with-descendants.js.map +1 -1
  182. package/dist/examples/internal/simple-scrollbox.vitest.d.ts +2 -0
  183. package/dist/examples/internal/simple-scrollbox.vitest.d.ts.map +1 -0
  184. package/dist/examples/internal/simple-scrollbox.vitest.js +96 -0
  185. package/dist/examples/internal/simple-scrollbox.vitest.js.map +1 -0
  186. package/dist/examples/internal/unicode-square-repro.d.ts +2 -0
  187. package/dist/examples/internal/unicode-square-repro.d.ts.map +1 -0
  188. package/dist/examples/internal/unicode-square-repro.js +7 -0
  189. package/dist/examples/internal/unicode-square-repro.js.map +1 -0
  190. package/dist/examples/list-detail-metadata.d.ts +2 -0
  191. package/dist/examples/list-detail-metadata.d.ts.map +1 -0
  192. package/dist/examples/list-detail-metadata.js +8 -0
  193. package/dist/examples/list-detail-metadata.js.map +1 -0
  194. package/dist/examples/list-dropdown-default.vitest.d.ts +2 -0
  195. package/dist/examples/list-dropdown-default.vitest.d.ts.map +1 -0
  196. package/dist/examples/list-dropdown-default.vitest.js +234 -0
  197. package/dist/examples/list-dropdown-default.vitest.js.map +1 -0
  198. package/dist/examples/list-fetch-data.vitest.d.ts +2 -0
  199. package/dist/examples/list-fetch-data.vitest.d.ts.map +1 -0
  200. package/dist/examples/list-fetch-data.vitest.js +111 -0
  201. package/dist/examples/list-fetch-data.vitest.js.map +1 -0
  202. package/dist/examples/list-filter-navigation.d.ts +2 -0
  203. package/dist/examples/list-filter-navigation.d.ts.map +1 -0
  204. package/dist/examples/list-filter-navigation.js +8 -0
  205. package/dist/examples/list-filter-navigation.js.map +1 -0
  206. package/dist/examples/list-scrollbox.vitest.d.ts +2 -0
  207. package/dist/examples/list-scrollbox.vitest.d.ts.map +1 -0
  208. package/dist/examples/list-scrollbox.vitest.js +93 -0
  209. package/dist/examples/list-scrollbox.vitest.js.map +1 -0
  210. package/dist/examples/list-with-detail-long.d.ts +2 -0
  211. package/dist/examples/list-with-detail-long.d.ts.map +1 -0
  212. package/dist/examples/list-with-detail-long.js +53 -0
  213. package/dist/examples/list-with-detail-long.js.map +1 -0
  214. package/dist/examples/list-with-detail.vitest.d.ts +2 -0
  215. package/dist/examples/list-with-detail.vitest.d.ts.map +1 -0
  216. package/dist/examples/list-with-detail.vitest.js +434 -0
  217. package/dist/examples/list-with-detail.vitest.js.map +1 -0
  218. package/dist/examples/list-with-dropdown.vitest.d.ts +2 -0
  219. package/dist/examples/list-with-dropdown.vitest.d.ts.map +1 -0
  220. package/dist/examples/list-with-dropdown.vitest.js +337 -0
  221. package/dist/examples/list-with-dropdown.vitest.js.map +1 -0
  222. package/dist/examples/list-with-sections.js +5 -1
  223. package/dist/examples/list-with-sections.js.map +1 -1
  224. package/dist/examples/list-with-sections.vitest.d.ts +2 -0
  225. package/dist/examples/list-with-sections.vitest.d.ts.map +1 -0
  226. package/dist/examples/list-with-sections.vitest.js +601 -0
  227. package/dist/examples/list-with-sections.vitest.js.map +1 -0
  228. package/dist/examples/scrollbox-vertical-centering.d.ts +6 -0
  229. package/dist/examples/scrollbox-vertical-centering.d.ts.map +1 -0
  230. package/dist/examples/scrollbox-vertical-centering.js +17 -0
  231. package/dist/examples/scrollbox-vertical-centering.js.map +1 -0
  232. package/dist/examples/simple-file-picker.vitest.d.ts +2 -0
  233. package/dist/examples/simple-file-picker.vitest.d.ts.map +1 -0
  234. package/dist/examples/simple-file-picker.vitest.js +678 -0
  235. package/dist/examples/simple-file-picker.vitest.js.map +1 -0
  236. package/dist/examples/simple-grid.vitest.d.ts +2 -0
  237. package/dist/examples/simple-grid.vitest.d.ts.map +1 -0
  238. package/dist/examples/simple-grid.vitest.js +521 -0
  239. package/dist/examples/simple-grid.vitest.js.map +1 -0
  240. package/dist/examples/simple-navigation.js +10 -4
  241. package/dist/examples/simple-navigation.js.map +1 -1
  242. package/dist/examples/simple-navigation.vitest.d.ts +2 -0
  243. package/dist/examples/simple-navigation.vitest.d.ts.map +1 -0
  244. package/dist/examples/simple-navigation.vitest.js +718 -0
  245. package/dist/examples/simple-navigation.vitest.js.map +1 -0
  246. package/dist/examples/store.vitest.d.ts +2 -0
  247. package/dist/examples/store.vitest.d.ts.map +1 -0
  248. package/dist/examples/store.vitest.js +69 -0
  249. package/dist/examples/store.vitest.js.map +1 -0
  250. package/dist/extensions/dev.d.ts +4 -2
  251. package/dist/extensions/dev.d.ts.map +1 -1
  252. package/dist/extensions/dev.js +61 -10
  253. package/dist/extensions/dev.js.map +1 -1
  254. package/dist/extensions/dev.vitest.d.ts +2 -0
  255. package/dist/extensions/dev.vitest.d.ts.map +1 -0
  256. package/dist/extensions/dev.vitest.js +197 -0
  257. package/dist/extensions/dev.vitest.js.map +1 -0
  258. package/dist/extensions/home.d.ts.map +1 -1
  259. package/dist/extensions/home.js +3 -0
  260. package/dist/extensions/home.js.map +1 -1
  261. package/dist/home-command.d.ts +8 -0
  262. package/dist/home-command.d.ts.map +1 -0
  263. package/dist/home-command.js +181 -0
  264. package/dist/home-command.js.map +1 -0
  265. package/dist/hover-repro.d.ts +2 -0
  266. package/dist/hover-repro.d.ts.map +1 -0
  267. package/dist/hover-repro.js +20 -0
  268. package/dist/hover-repro.js.map +1 -0
  269. package/dist/index.d.ts +1 -0
  270. package/dist/index.d.ts.map +1 -1
  271. package/dist/index.js +2 -0
  272. package/dist/index.js.map +1 -1
  273. package/dist/internal/dialog.d.ts +1 -0
  274. package/dist/internal/dialog.d.ts.map +1 -1
  275. package/dist/internal/dialog.js +27 -18
  276. package/dist/internal/dialog.js.map +1 -1
  277. package/dist/internal/navigation.d.ts +9 -1
  278. package/dist/internal/navigation.d.ts.map +1 -1
  279. package/dist/internal/navigation.js +5 -5
  280. package/dist/internal/navigation.js.map +1 -1
  281. package/dist/internal/offscreen.d.ts +6 -0
  282. package/dist/internal/offscreen.d.ts.map +1 -0
  283. package/dist/internal/offscreen.js +10 -0
  284. package/dist/internal/offscreen.js.map +1 -0
  285. package/dist/internal/providers.d.ts.map +1 -1
  286. package/dist/internal/providers.js +2 -2
  287. package/dist/internal/providers.js.map +1 -1
  288. package/dist/internal/scrollbox.d.ts +1 -10
  289. package/dist/internal/scrollbox.d.ts.map +1 -1
  290. package/dist/internal/scrollbox.js +2 -1
  291. package/dist/internal/scrollbox.js.map +1 -1
  292. package/dist/localstorage.d.ts +13 -0
  293. package/dist/localstorage.d.ts.map +1 -0
  294. package/dist/localstorage.js +190 -0
  295. package/dist/localstorage.js.map +1 -0
  296. package/dist/oauth.d.ts +142 -0
  297. package/dist/oauth.d.ts.map +1 -0
  298. package/dist/oauth.js +551 -0
  299. package/dist/oauth.js.map +1 -0
  300. package/dist/preferences.d.ts +23 -0
  301. package/dist/preferences.d.ts.map +1 -0
  302. package/dist/preferences.js +105 -0
  303. package/dist/preferences.js.map +1 -0
  304. package/dist/state.d.ts +2 -0
  305. package/dist/state.d.ts.map +1 -1
  306. package/dist/state.js +3 -0
  307. package/dist/state.js.map +1 -1
  308. package/dist/store.d.ts +21 -0
  309. package/dist/store.d.ts.map +1 -0
  310. package/dist/store.js +84 -0
  311. package/dist/store.js.map +1 -0
  312. package/dist/swift-loader.d.ts +3 -0
  313. package/dist/swift-loader.d.ts.map +1 -0
  314. package/dist/swift-loader.js +193 -0
  315. package/dist/swift-loader.js.map +1 -0
  316. package/dist/swift-runtime.d.ts +2 -0
  317. package/dist/swift-runtime.d.ts.map +1 -0
  318. package/dist/swift-runtime.js +27 -0
  319. package/dist/swift-runtime.js.map +1 -0
  320. package/dist/toast.d.ts +44 -0
  321. package/dist/toast.d.ts.map +1 -0
  322. package/dist/toast.js +221 -0
  323. package/dist/toast.js.map +1 -0
  324. package/dist/utils/file-system.d.ts +9 -0
  325. package/dist/utils/file-system.d.ts.map +1 -1
  326. package/dist/utils/file-system.js +49 -0
  327. package/dist/utils/file-system.js.map +1 -1
  328. package/dist/utils/run-command.d.ts +25 -1
  329. package/dist/utils/run-command.d.ts.map +1 -1
  330. package/dist/utils/run-command.js +47 -4
  331. package/dist/utils/run-command.js.map +1 -1
  332. package/dist/window.d.ts +12 -0
  333. package/dist/window.d.ts.map +1 -0
  334. package/dist/window.js +48 -0
  335. package/dist/window.js.map +1 -0
  336. package/package.json +13 -11
  337. package/src/apis/browser-extension.tsx +29 -0
  338. package/src/apis/localstorage.test.ts +14 -6
  339. package/src/apis/localstorage.tsx +8 -5
  340. package/src/apis/oauth.tsx +5 -1
  341. package/src/apis/preferences.tsx +48 -22
  342. package/src/build.test.tsx +52 -0
  343. package/src/build.tsx +2 -1
  344. package/src/cli.tsx +80 -39
  345. package/src/compile.tsx +24 -6
  346. package/src/components/actions.tsx +94 -32
  347. package/src/components/detail.tsx +4 -0
  348. package/src/components/dropdown.tsx +47 -14
  349. package/src/components/extension-preferences.tsx +44 -16
  350. package/src/components/form/checkbox.tsx +12 -6
  351. package/src/components/form/date-picker.tsx +12 -6
  352. package/src/components/form/description.tsx +7 -2
  353. package/src/components/form/dropdown.tsx +131 -119
  354. package/src/components/form/file-autocomplete.tsx +90 -108
  355. package/src/components/form/file-picker.tsx +54 -43
  356. package/src/components/form/form-end.tsx +23 -2
  357. package/src/components/form/index.tsx +152 -34
  358. package/src/components/form/password-field.tsx +12 -6
  359. package/src/components/form/text-area.tsx +13 -6
  360. package/src/components/form/text-field.tsx +13 -6
  361. package/src/components/form/types.tsx +6 -0
  362. package/src/components/form/with-left-border.tsx +41 -8
  363. package/src/components/icon.tsx +27 -8
  364. package/src/components/list.tsx +193 -74
  365. package/src/components/loading-bar.tsx +3 -2
  366. package/src/components/loading-text.tsx +79 -0
  367. package/src/descendants.tsx +1 -0
  368. package/src/examples/file-autocomplete.vitest.tsx +130 -125
  369. package/src/examples/form-basic.vitest.tsx +376 -176
  370. package/src/examples/form-dropdown.vitest.tsx +126 -126
  371. package/src/examples/form-scroll.tsx +2 -0
  372. package/src/examples/form-scroll.vitest.tsx +58 -58
  373. package/src/examples/form-tagpicker.vitest.tsx +99 -99
  374. package/src/examples/internal/descendants-filtering.tsx +1 -0
  375. package/src/examples/internal/descendants.tsx +1 -0
  376. package/src/examples/internal/rhf-custom-ref.tsx +2 -0
  377. package/src/examples/internal/scrollbox-demo.tsx +3 -27
  378. package/src/examples/internal/scrollbox-with-descendants.tsx +4 -7
  379. package/src/examples/internal/simple-scrollbox.vitest.tsx +7 -5
  380. package/src/examples/list-detail-metadata.tsx +49 -0
  381. package/src/examples/list-detail-metadata.vitest.tsx +88 -0
  382. package/src/examples/list-dropdown-default.vitest.tsx +51 -51
  383. package/src/examples/list-fetch-data.vitest.tsx +4 -4
  384. package/src/examples/list-scrollbox.vitest.tsx +73 -14
  385. package/src/examples/list-with-detail-long.tsx +70 -0
  386. package/src/examples/list-with-detail.vitest.tsx +198 -92
  387. package/src/examples/list-with-dropdown.vitest.tsx +53 -53
  388. package/src/examples/list-with-sections.tsx +1 -0
  389. package/src/examples/list-with-sections.vitest.tsx +213 -89
  390. package/src/examples/list-with-toast.vitest.tsx +4 -4
  391. package/src/examples/simple-file-picker.vitest.tsx +61 -471
  392. package/src/examples/simple-grid.vitest.tsx +238 -233
  393. package/src/examples/simple-navigation.tsx +15 -7
  394. package/src/examples/simple-navigation.vitest.tsx +121 -210
  395. package/src/examples/store.vitest.tsx +1 -1
  396. package/src/examples/swift-extension.vitest.tsx +148 -0
  397. package/src/examples/synonyms.vitest.tsx +159 -0
  398. package/src/extensions/dev.tsx +74 -7
  399. package/src/extensions/dev.vitest.tsx +97 -31
  400. package/src/extensions/home.tsx +6 -0
  401. package/src/index.tsx +3 -0
  402. package/src/internal/dialog.tsx +43 -30
  403. package/src/internal/navigation.tsx +3 -1
  404. package/src/internal/offscreen.tsx +15 -0
  405. package/src/internal/providers.tsx +4 -2
  406. package/src/internal/scrollbox.tsx +4 -8
  407. package/src/keyboard.test.tsx +69 -0
  408. package/src/state.tsx +7 -0
  409. package/src/swift-loader.tsx +239 -0
  410. package/src/swift-runtime.tsx +36 -0
  411. package/src/utils/file-system.ts +61 -0
  412. package/src/utils/run-command.tsx +75 -6
@@ -17,8 +17,12 @@ import {
17
17
  moveToTrash,
18
18
  } from 'termcast/src/action-utils'
19
19
  import { useDialog } from 'termcast/src/internal/dialog'
20
+ import { useNavigation } from 'termcast/src/internal/navigation'
20
21
  import { Dropdown } from 'termcast/src/components/dropdown'
22
+ import { ExtensionPreferences } from 'termcast/src/components/extension-preferences'
23
+ import { useStore } from 'termcast/src/state'
21
24
  import { useIsInFocus } from 'termcast/src/internal/focus-context'
25
+ import { useIsOffscreen } from 'termcast/src/internal/offscreen'
22
26
  import { CommonProps } from 'termcast/src/utils'
23
27
  import type {
24
28
  KeyboardShortcut,
@@ -180,7 +184,7 @@ const Action: ActionType = (props) => {
180
184
 
181
185
  const isDestructive = props.style === ActionStyle.Destructive
182
186
 
183
- // Render as Dropdown.Item
187
+ // Render as Dropdown.Item (handles offscreen check internally)
184
188
  return (
185
189
  <Dropdown.Item
186
190
  title={props.title}
@@ -210,7 +214,7 @@ Action.Push = (props) => {
210
214
  },
211
215
  })
212
216
 
213
- // Render as Dropdown.Item
217
+ // Render as Dropdown.Item (handles offscreen check internally)
214
218
  return (
215
219
  <Dropdown.Item
216
220
  title={props.title}
@@ -243,7 +247,7 @@ Action.CopyToClipboard = (props) => {
243
247
  },
244
248
  })
245
249
 
246
- // Render as Dropdown.Item
250
+ // Render as Dropdown.Item (handles offscreen check internally)
247
251
  return (
248
252
  <Dropdown.Item
249
253
  title={props.title}
@@ -270,7 +274,7 @@ Action.OpenInBrowser = (props) => {
270
274
  },
271
275
  })
272
276
 
273
- // Render as Dropdown.Item
277
+ // Render as Dropdown.Item (handles offscreen check internally)
274
278
  return (
275
279
  <Dropdown.Item
276
280
  title={props.title}
@@ -298,7 +302,7 @@ Action.Open = (props) => {
298
302
  },
299
303
  })
300
304
 
301
- // Render as Dropdown.Item
305
+ // Render as Dropdown.Item (handles offscreen check internally)
302
306
  return (
303
307
  <Dropdown.Item
304
308
  title={props.title}
@@ -328,7 +332,7 @@ Action.Paste = (props) => {
328
332
  },
329
333
  })
330
334
 
331
- // Render as Dropdown.Item
335
+ // Render as Dropdown.Item (handles offscreen check internally)
332
336
  return (
333
337
  <Dropdown.Item
334
338
  title={props.title}
@@ -355,7 +359,7 @@ Action.ShowInFinder = (props) => {
355
359
  },
356
360
  })
357
361
 
358
- // Render as Dropdown.Item
362
+ // Render as Dropdown.Item (handles offscreen check internally)
359
363
  return (
360
364
  <Dropdown.Item
361
365
  title={props.title || 'Show in Finder'}
@@ -382,7 +386,7 @@ Action.OpenWith = (props) => {
382
386
  },
383
387
  })
384
388
 
385
- // Render as Dropdown.Item
389
+ // Render as Dropdown.Item (handles offscreen check internally)
386
390
  return (
387
391
  <Dropdown.Item
388
392
  title={props.title || `Open with ${props.application}`}
@@ -413,7 +417,7 @@ Action.Trash = (props) => {
413
417
  },
414
418
  })
415
419
 
416
- // Render as Dropdown.Item
420
+ // Render as Dropdown.Item (handles offscreen check internally)
417
421
  return (
418
422
  <Dropdown.Item
419
423
  title={props.title || 'Move to Trash'}
@@ -448,7 +452,7 @@ Action.SubmitForm = (props) => {
448
452
  },
449
453
  })
450
454
 
451
- // Render as Dropdown.Item
455
+ // Render as Dropdown.Item (handles offscreen check internally)
452
456
  return (
453
457
  <Dropdown.Item
454
458
  title={props.title || 'Submit'}
@@ -480,7 +484,7 @@ Action.CreateSnippet = (props) => {
480
484
  },
481
485
  })
482
486
 
483
- // Render as Dropdown.Item
487
+ // Render as Dropdown.Item (handles offscreen check internally)
484
488
  return (
485
489
  <Dropdown.Item
486
490
  title={props.title || 'Create Snippet'}
@@ -510,7 +514,7 @@ Action.CreateQuicklink = (props) => {
510
514
  },
511
515
  })
512
516
 
513
- // Render as Dropdown.Item
517
+ // Render as Dropdown.Item (handles offscreen check internally)
514
518
  return (
515
519
  <Dropdown.Item
516
520
  title={props.title || 'Create Quicklink'}
@@ -540,7 +544,7 @@ Action.ToggleQuickLook = (props) => {
540
544
  },
541
545
  })
542
546
 
543
- // Render as Dropdown.Item
547
+ // Render as Dropdown.Item (handles offscreen check internally)
544
548
  return (
545
549
  <Dropdown.Item
546
550
  title={props.title || 'Quick Look'}
@@ -552,8 +556,6 @@ Action.ToggleQuickLook = (props) => {
552
556
  }
553
557
 
554
558
  Action.PickDate = (props) => {
555
- const dialog = useDialog()
556
-
557
559
  // Register as descendant with execute function
558
560
  useActionDescendant({
559
561
  title: props.title || 'Pick Date',
@@ -570,7 +572,7 @@ Action.PickDate = (props) => {
570
572
  },
571
573
  })
572
574
 
573
- // Render as Dropdown.Item
575
+ // Render as Dropdown.Item (handles offscreen check internally)
574
576
  return (
575
577
  <Dropdown.Item
576
578
  title={props.title || 'Pick Date'}
@@ -631,31 +633,55 @@ function formatShortcut(
631
633
  const ActionPanel: ActionPanelType = (props) => {
632
634
  const { children, title } = props
633
635
  const dialog = useDialog()
636
+ const { push } = useNavigation()
634
637
  const inFocus = useIsInFocus()
638
+ const isOffscreen = useIsOffscreen()
635
639
  const descendantsContext = useActionDescendants()
636
640
 
641
+ // Get extension and command info for configure actions
642
+ const extensionPackageJson = useStore((state) => state.extensionPackageJson)
643
+ const currentCommandName = useStore((state) => state.currentCommandName)
644
+
645
+ const hasExtensionPrefs =
646
+ (extensionPackageJson?.preferences?.length ?? 0) > 0
647
+ const currentCommand = extensionPackageJson?.commands?.find(
648
+ (c) => c.name === currentCommandName,
649
+ )
650
+ const hasCommandPrefs = (currentCommand?.preferences?.length ?? 0) > 0
651
+
637
652
  // Create context value
638
653
  const contextValue = useMemo<ActionPanelContextValue>(
639
654
  () => ({ currentSection: undefined }),
640
655
  [],
641
656
  )
642
657
 
643
- // prevent showing actions if no dialog is shown
644
- if (!dialog.stack.length) return null
645
- // if (!inFocus) return
646
-
647
- // Check if there's only one action and execute it immediately
658
+ // Auto-execute first action if flag is set (triggered by enter/ctrl+enter)
659
+ // Also report first action title when rendered offscreen
648
660
  useLayoutEffect(() => {
649
661
  const allActions = Object.values(descendantsContext.map.current)
650
662
  .filter((item: any) => item.index !== -1)
651
663
  .map((item: any) => item.props as ActionDescendant)
652
664
 
653
- if (allActions.length === 1) {
654
- logger.log(`Auto-executing single action: ${allActions[0].title}`)
665
+ // When offscreen, just report first action title for footer display
666
+ if (isOffscreen) {
667
+ useStore.setState({ firstActionTitle: allActions[0]?.title ?? '' })
668
+ return
669
+ }
670
+
671
+ const shouldExecute = useStore.getState().shouldAutoExecuteFirstAction
672
+ useStore.setState({ shouldAutoExecuteFirstAction: false })
673
+
674
+ if (!shouldExecute) return
675
+
676
+ if (allActions[0]) {
677
+ logger.log(`Auto-executing first action: ${allActions[0].title}`)
655
678
  dialog.clear()
656
679
  allActions[0].execute()
657
680
  }
658
- }, [descendantsContext.map, dialog])
681
+ }, [descendantsContext.map, dialog, isOffscreen])
682
+
683
+ // prevent showing actions if no dialog is shown (must be after hooks)
684
+ if (!dialog.stack.length && !isOffscreen) return null
659
685
 
660
686
  // ActionPanel renders as Dropdown with children
661
687
  return (
@@ -680,6 +706,38 @@ const ActionPanel: ActionPanelType = (props) => {
680
706
  }}
681
707
  >
682
708
  {children}
709
+ {(hasExtensionPrefs || hasCommandPrefs) && (
710
+ <ActionPanel.Section title="Settings">
711
+ {hasExtensionPrefs && (
712
+ <Action
713
+ title="Configure Extension..."
714
+ shortcut={{ modifiers: ['cmd', 'shift'], key: ',' }}
715
+ onAction={() => {
716
+ dialog.clear()
717
+ push(
718
+ <ExtensionPreferences
719
+ extensionName={extensionPackageJson!.name}
720
+ />,
721
+ )
722
+ }}
723
+ />
724
+ )}
725
+ {hasCommandPrefs && (
726
+ <Action
727
+ title="Configure Command..."
728
+ onAction={() => {
729
+ dialog.clear()
730
+ push(
731
+ <ExtensionPreferences
732
+ extensionName={extensionPackageJson!.name}
733
+ commandName={currentCommandName!}
734
+ />,
735
+ )
736
+ }}
737
+ />
738
+ )}
739
+ </ActionPanel.Section>
740
+ )}
683
741
  </Dropdown>
684
742
  </ActionPanelContext.Provider>
685
743
  </ActionDescendantsProvider>
@@ -698,11 +756,13 @@ ActionPanel.Section = (props) => {
698
756
  [parentContext, props.title],
699
757
  )
700
758
 
701
- // Section provides context to its children
759
+ // Section renders Dropdown.Section and provides context to its children
702
760
  return (
703
- <ActionPanelContext.Provider value={sectionContextValue}>
704
- {props.children}
705
- </ActionPanelContext.Provider>
761
+ <Dropdown.Section title={props.title}>
762
+ <ActionPanelContext.Provider value={sectionContextValue}>
763
+ {props.children}
764
+ </ActionPanelContext.Provider>
765
+ </Dropdown.Section>
706
766
  )
707
767
  }
708
768
 
@@ -718,11 +778,13 @@ ActionPanel.Submenu = (props) => {
718
778
  [parentContext, props.title],
719
779
  )
720
780
 
721
- // Submenu provides context to its children
781
+ // Submenu renders Dropdown.Section and provides context to its children
722
782
  return (
723
- <ActionPanelContext.Provider value={submenuContextValue}>
724
- {props.children}
725
- </ActionPanelContext.Provider>
783
+ <Dropdown.Section title={props.title}>
784
+ <ActionPanelContext.Provider value={submenuContextValue}>
785
+ {props.children}
786
+ </ActionPanelContext.Provider>
787
+ </Dropdown.Section>
726
788
  )
727
789
  }
728
790
 
@@ -9,6 +9,7 @@ import { Color, resolveColor } from 'termcast/src/colors'
9
9
 
10
10
  import { useDialog } from 'termcast/src/internal/dialog'
11
11
  import { ScrollBox } from 'termcast/src/internal/scrollbox'
12
+ import { useStore } from 'termcast/src/state'
12
13
 
13
14
  interface ActionsInterface {
14
15
  actions?: ReactNode
@@ -277,8 +278,11 @@ const Detail: DetailType = (props) => {
277
278
  if (!inFocus) return
278
279
 
279
280
  if (evt.name === 'k' && evt.ctrl && actions) {
281
+ // Ctrl+K shows actions (always show sheet)
280
282
  dialog.push(actions, 'bottom-right')
281
283
  } else if (evt.name === 'return' && actions) {
284
+ // Enter executes first action directly
285
+ useStore.setState({ shouldAutoExecuteFirstAction: true })
282
286
  dialog.push(actions, 'bottom-right')
283
287
  }
284
288
  })
@@ -16,6 +16,7 @@ import {
16
16
  import { Theme } from 'termcast/src/theme'
17
17
  import { logger } from 'termcast/src/logger'
18
18
  import { useIsInFocus } from 'termcast/src/internal/focus-context'
19
+ import { useIsOffscreen } from 'termcast/src/internal/offscreen'
19
20
  import { CommonProps } from 'termcast/src/utils'
20
21
  import { createDescendants } from 'termcast/src/descendants'
21
22
  import { ScrollBox } from 'termcast/src/internal/scrollbox'
@@ -107,6 +108,7 @@ const Dropdown: DropdownType = (props) => {
107
108
  throttle,
108
109
  } = props
109
110
 
111
+ const isOffscreen = useIsOffscreen()
110
112
  const [selected, setSelected] = useState(0)
111
113
  const [searchText, setSearchTextState] = useState('')
112
114
  const [currentValue, setCurrentValue] = useState<string | undefined>(
@@ -122,7 +124,14 @@ const Dropdown: DropdownType = (props) => {
122
124
  const setSearchText = (text: string) => {
123
125
  inputRef.current?.setText(text)
124
126
  setSearchTextState(text)
125
- setSelected(0)
127
+ // TODO: use flushSync when available to force descendants to update visibility
128
+ const items = Object.values(descendantsContext.map.current)
129
+ .filter((item: any) => item.index !== -1 && !item.props?.hidden)
130
+ .sort((a: any, b: any) => a.index - b.index)
131
+
132
+ if (items.length > 0 && items[0]) {
133
+ setSelected(items[0].index)
134
+ }
126
135
  }
127
136
 
128
137
  const scrollToItem = (item: { props?: DropdownItemDescendant }) => {
@@ -132,19 +141,13 @@ const Dropdown: DropdownType = (props) => {
132
141
 
133
142
  const contentY = scrollBox.content?.y || 0
134
143
  const viewportHeight = scrollBox.viewport?.height || 10
135
- const currentScrollTop = scrollBox.scrollTop || 0
136
144
 
145
+ // Calculate item position relative to content
137
146
  const itemTop = elementRef.y - contentY
138
- const itemBottom = itemTop + elementRef.height
139
147
 
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
+ // Scroll so the top of the item is centered in the viewport
149
+ const targetScrollTop = itemTop - viewportHeight / 2
150
+ scrollBox.scrollTo(Math.max(0, targetScrollTop))
148
151
  }
149
152
 
150
153
  // Create context value for children
@@ -173,9 +176,16 @@ const Dropdown: DropdownType = (props) => {
173
176
  const handleSearchTextChange = (text: string) => {
174
177
  if (!inFocus) return
175
178
 
176
- // Update state for context and reset selection
179
+ // Update state for context
177
180
  setSearchTextState(text)
178
- setSelected(0)
181
+ // TODO: use flushSync when available to force descendants to update visibility
182
+ const items = Object.values(descendantsContext.map.current)
183
+ .filter((item: any) => item.index !== -1 && !item.props?.hidden)
184
+ .sort((a: any, b: any) => a.index - b.index)
185
+
186
+ if (items.length > 0 && items[0]) {
187
+ setSelected(items[0].index)
188
+ }
179
189
 
180
190
  if (onSearchTextChange) {
181
191
  if (throttle) {
@@ -244,18 +254,36 @@ const Dropdown: DropdownType = (props) => {
244
254
  if (evt.name === 'down') {
245
255
  move(1)
246
256
  }
257
+ // Tab and shift+tab for navigation
258
+ if (evt.name === 'tab' && !evt.shift) {
259
+ move(1)
260
+ }
261
+ if (evt.name === 'tab' && evt.shift) {
262
+ move(-1)
263
+ }
247
264
  if (evt.name === 'return') {
248
265
  const items = Object.values(descendantsContext.map.current)
249
266
  .filter((item: any) => item.index !== -1)
250
267
  .sort((a: any, b: any) => a.index - b.index)
251
268
 
252
- const currentItem = items[selected]
269
+ const currentItem = items.find((item) => item.index === selected)
253
270
  if (currentItem?.props) {
254
271
  selectItem((currentItem.props as DropdownItemDescendant).value)
255
272
  }
256
273
  }
257
274
  })
258
275
 
276
+ // When offscreen, just render children to collect descendants without UI
277
+ if (isOffscreen) {
278
+ return (
279
+ <DropdownDescendantsProvider value={descendantsContext}>
280
+ <DropdownContext.Provider value={contextValue}>
281
+ {children}
282
+ </DropdownContext.Provider>
283
+ </DropdownDescendantsProvider>
284
+ )
285
+ }
286
+
259
287
  return (
260
288
  <DropdownDescendantsProvider value={descendantsContext}>
261
289
  <DropdownContext.Provider value={contextValue}>
@@ -275,6 +303,7 @@ const Dropdown: DropdownType = (props) => {
275
303
  <textarea
276
304
  ref={inputRef}
277
305
  height={1}
306
+ wrapMode='none'
278
307
  keyBindings={[
279
308
  { name: 'return', action: 'submit' },
280
309
  { name: 'linefeed', action: 'submit' },
@@ -419,7 +448,11 @@ function ItemOption(props: {
419
448
  const DropdownItem: (props: DropdownItemProps) => any = (props) => {
420
449
  const context = useContext(DropdownContext)
421
450
  const elementRef = useRef<{ y: number; height: number } | null>(null)
451
+ const isOffscreen = useIsOffscreen()
422
452
  if (!context) return null
453
+
454
+ // Don't render UI when offscreen (used for collecting action descendants)
455
+ if (isOffscreen) return null
423
456
 
424
457
  const { searchText, filtering, currentSection, selectedIndex, currentValue } =
425
458
  context
@@ -9,6 +9,7 @@ import { LocalStorage } from 'termcast/src/apis/localstorage'
9
9
  import { useNavigation } from 'termcast/src/internal/navigation'
10
10
  import { logger } from 'termcast/src/logger'
11
11
  import { getStoreDirectory } from 'termcast/src/utils'
12
+ import { useStore } from 'termcast/src/state'
12
13
  import type { RaycastPackageJson } from 'termcast/src/package-json'
13
14
 
14
15
  interface ExtensionPreferencesProps {
@@ -46,17 +47,26 @@ export function ExtensionPreferences({
46
47
  queryKey: ['extension-preferences', extensionName, commandName],
47
48
  queryFn: async () => {
48
49
  try {
49
- const storeDir = getStoreDirectory()
50
- const extensionDir = path.join(storeDir, extensionName)
51
- const packageJsonPath = path.join(extensionDir, 'package.json')
50
+ // First check extensionPath from state (dev mode), then fall back to store directory
51
+ const { extensionPath, extensionPackageJson } = useStore.getState()
52
52
 
53
- if (!fs.existsSync(packageJsonPath)) {
54
- throw new Error(`Extension ${extensionName} not found`)
55
- }
53
+ let packageJson: RaycastPackageJson
54
+
55
+ if (extensionPath && extensionPackageJson?.name === extensionName) {
56
+ // Dev mode - use package.json from state or read from extensionPath
57
+ packageJson = extensionPackageJson
58
+ } else {
59
+ // Store extension - read from store directory
60
+ const storeDir = getStoreDirectory()
61
+ const extensionDir = path.join(storeDir, extensionName)
62
+ const packageJsonPath = path.join(extensionDir, 'package.json')
56
63
 
57
- const packageJson: RaycastPackageJson = JSON.parse(
58
- fs.readFileSync(packageJsonPath, 'utf-8'),
59
- )
64
+ if (!fs.existsSync(packageJsonPath)) {
65
+ throw new Error(`Extension ${extensionName} not found`)
66
+ }
67
+
68
+ packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'))
69
+ }
60
70
 
61
71
  let prefsToUse: PreferenceManifest[] = []
62
72
 
@@ -103,11 +113,29 @@ export function ExtensionPreferences({
103
113
 
104
114
  const handleSubmit = async (values: Record<string, any>) => {
105
115
  try {
116
+ // Transform file/directory values from arrays to strings
117
+ // Form.FilePicker returns string[] but Raycast preferences expect string for file/directory types
118
+ const transformedValues: Record<string, any> = {}
119
+ for (const pref of preferences) {
120
+ const value = values[pref.name]
121
+ if (
122
+ (pref.type === 'file' ||
123
+ pref.type === 'directory' ||
124
+ pref.type === 'appPicker') &&
125
+ Array.isArray(value)
126
+ ) {
127
+ // Extract first element from array, or empty string if empty
128
+ transformedValues[pref.name] = value[0] || ''
129
+ } else {
130
+ transformedValues[pref.name] = value
131
+ }
132
+ }
133
+
106
134
  // Save preferences to LocalStorage
107
135
  const preferencesKey = commandName
108
136
  ? `preferences.${extensionName}.${commandName}`
109
137
  : `preferences.${extensionName}`
110
- await LocalStorage.setItem(preferencesKey, JSON.stringify(values))
138
+ await LocalStorage.setItem(preferencesKey, JSON.stringify(transformedValues))
111
139
 
112
140
  await showToast({
113
141
  style: Toast.Style.Success,
@@ -118,7 +146,7 @@ export function ExtensionPreferences({
118
146
  })
119
147
 
120
148
  if (onSubmit) {
121
- onSubmit(values)
149
+ onSubmit(transformedValues)
122
150
  } else {
123
151
  pop()
124
152
  }
@@ -136,11 +164,11 @@ export function ExtensionPreferences({
136
164
  }
137
165
 
138
166
  if (preferences.length === 0) {
139
- // If no preferences but onSubmit provided, call it immediately
140
- if (onSubmit) {
141
- onSubmit({})
142
- return null
143
- }
167
+ // TODO this causes an infinite loop, because initially prefs are zero
168
+ // if (onSubmit) {
169
+ // onSubmit({})
170
+ // return null
171
+ // }
144
172
 
145
173
  return (
146
174
  <Form
@@ -9,6 +9,7 @@ import { Theme } from 'termcast/src/theme'
9
9
  import { WithLeftBorder } from './with-left-border'
10
10
  import { useFormNavigation } from './use-form-navigation'
11
11
  import { useIsInFocus } from 'termcast/src/internal/focus-context'
12
+ import { LoadingText } from 'termcast/src/components/loading-text'
12
13
 
13
14
  export interface CheckboxProps extends FormItemProps<boolean> {
14
15
  label: string
@@ -18,7 +19,8 @@ export type CheckboxRef = FormItemRef
18
19
 
19
20
  export const Checkbox = (props: CheckboxProps): any => {
20
21
  const { control, setValue, getValues } = useFormContext()
21
- const { focusedField, setFocusedField } = useFocusContext()
22
+ const focusContext = useFocusContext()
23
+ const { focusedField, setFocusedField } = focusContext
22
24
  const isFocused = focusedField === props.id
23
25
  const isInFocus = useIsInFocus()
24
26
 
@@ -57,9 +59,8 @@ export const Checkbox = (props: CheckboxProps): any => {
57
59
  render={({ field, fieldState, formState }) => {
58
60
  return (
59
61
  <box ref={elementRef} flexDirection='column'>
60
- <WithLeftBorder withDiamond isFocused={isFocused}>
61
- <text
62
- fg={isFocused ? Theme.primary : Theme.text}
62
+ <WithLeftBorder withDiamond isFocused={isFocused} isLoading={focusContext.isLoading}>
63
+ <box
63
64
  onMouseDown={() => {
64
65
  // Always focus the field when clicked
65
66
  if (!isFocused) {
@@ -69,8 +70,13 @@ export const Checkbox = (props: CheckboxProps): any => {
69
70
  handleToggle()
70
71
  }}
71
72
  >
72
- {props.title}
73
- </text>
73
+ <LoadingText
74
+ isLoading={isFocused && focusContext.isLoading}
75
+ color={isFocused ? Theme.primary : Theme.text}
76
+ >
77
+ {props.title || ''}
78
+ </LoadingText>
79
+ </box>
74
80
  </WithLeftBorder>
75
81
  <WithLeftBorder isFocused={isFocused}>
76
82
  <text
@@ -9,6 +9,7 @@ import { WithLeftBorder } from './with-left-border'
9
9
  import { DatePickerWidget } from 'termcast/src/internal/date-picker-widget'
10
10
  import { useIsInFocus } from 'termcast/src/internal/focus-context'
11
11
  import { useFormNavigationHelpers } from './use-form-navigation'
12
+ import { LoadingText } from 'termcast/src/components/loading-text'
12
13
 
13
14
  export enum DatePickerType {
14
15
  Date = 'date',
@@ -30,7 +31,8 @@ interface DatePickerComponentType {
30
31
 
31
32
  const DatePickerComponent = (props: DatePickerProps): any => {
32
33
  const { control } = useFormContext()
33
- const { focusedField, setFocusedField } = useFocusContext()
34
+ const focusContext = useFocusContext()
35
+ const { focusedField, setFocusedField } = focusContext
34
36
  const isFocused = focusedField === props.id
35
37
  const isInFocus = useIsInFocus()
36
38
 
@@ -65,15 +67,19 @@ const DatePickerComponent = (props: DatePickerProps): any => {
65
67
  render={({ field, fieldState, formState }) => {
66
68
  return (
67
69
  <box ref={elementRef} flexDirection='column'>
68
- <WithLeftBorder withDiamond isFocused={isFocused}>
69
- <text
70
- fg={isFocused ? Theme.primary : Theme.text}
70
+ <WithLeftBorder withDiamond isFocused={isFocused} isLoading={focusContext.isLoading}>
71
+ <box
71
72
  onMouseDown={() => {
72
73
  setFocusedField(props.id)
73
74
  }}
74
75
  >
75
- {props.title}
76
- </text>
76
+ <LoadingText
77
+ isLoading={isFocused && focusContext.isLoading}
78
+ color={isFocused ? Theme.primary : Theme.text}
79
+ >
80
+ {props.title || ''}
81
+ </LoadingText>
82
+ </box>
77
83
  </WithLeftBorder>
78
84
  <WithLeftBorder isFocused={isFocused}>
79
85
  <DatePickerWidget
@@ -4,6 +4,7 @@ import { Theme } from 'termcast/src/theme'
4
4
  import { WithLeftBorder } from './with-left-border'
5
5
  import { useFocusContext, useFormFieldDescendant } from './index'
6
6
  import { useFormNavigation } from './use-form-navigation'
7
+ import { LoadingText } from 'termcast/src/components/loading-text'
7
8
 
8
9
  export interface DescriptionProps {
9
10
  id?: string
@@ -44,10 +45,14 @@ export const Description = (props: DescriptionProps): any => {
44
45
  <WithLeftBorder
45
46
  customCharacter={{ focused: '■', unfocused: '▪︎' }}
46
47
  isFocused={isFocused}
48
+ isLoading={focusContext.isLoading}
47
49
  >
48
- <text fg={Theme.text} attributes={TextAttributes.BOLD}>
50
+ <LoadingText
51
+ isLoading={isFocused && focusContext.isLoading}
52
+ color={isFocused ? Theme.primary : Theme.text}
53
+ >
49
54
  {props.title}
50
- </text>
55
+ </LoadingText>
51
56
  </WithLeftBorder>
52
57
  )}
53
58
  <WithLeftBorder isFocused={isFocused}>