termcast 1.3.21 → 1.3.25

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 (429) 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/apis/toast.d.ts +5 -0
  19. package/dist/apis/toast.d.ts.map +1 -1
  20. package/dist/apis/toast.js +7 -43
  21. package/dist/apis/toast.js.map +1 -1
  22. package/dist/build.d.ts.map +1 -1
  23. package/dist/build.js +3 -1
  24. package/dist/build.js.map +1 -1
  25. package/dist/cache.d.ts +32 -0
  26. package/dist/cache.d.ts.map +1 -0
  27. package/dist/cache.js +205 -0
  28. package/dist/cache.js.map +1 -0
  29. package/dist/cli.d.ts.map +1 -1
  30. package/dist/cli.js +87 -41
  31. package/dist/cli.js.map +1 -1
  32. package/dist/clipboard.d.ts +36 -0
  33. package/dist/clipboard.d.ts.map +1 -0
  34. package/dist/clipboard.js +154 -0
  35. package/dist/clipboard.js.map +1 -0
  36. package/dist/compile.d.ts +2 -1
  37. package/dist/compile.d.ts.map +1 -1
  38. package/dist/compile.js +31 -12
  39. package/dist/compile.js.map +1 -1
  40. package/dist/components/actions.d.ts.map +1 -1
  41. package/dist/components/actions.js +56 -30
  42. package/dist/components/actions.js.map +1 -1
  43. package/dist/components/detail.d.ts.map +1 -1
  44. package/dist/components/detail.js +4 -0
  45. package/dist/components/detail.js.map +1 -1
  46. package/dist/components/dropdown.d.ts.map +1 -1
  47. package/dist/components/dropdown.js +38 -15
  48. package/dist/components/dropdown.js.map +1 -1
  49. package/dist/components/extension-preferences.d.ts.map +1 -1
  50. package/dist/components/extension-preferences.js +40 -13
  51. package/dist/components/extension-preferences.js.map +1 -1
  52. package/dist/components/form/checkbox.d.ts.map +1 -1
  53. package/dist/components/form/checkbox.js +5 -3
  54. package/dist/components/form/checkbox.js.map +1 -1
  55. package/dist/components/form/date-picker.d.ts.map +1 -1
  56. package/dist/components/form/date-picker.js +5 -3
  57. package/dist/components/form/date-picker.js.map +1 -1
  58. package/dist/components/form/description.d.ts.map +1 -1
  59. package/dist/components/form/description.js +2 -2
  60. package/dist/components/form/description.js.map +1 -1
  61. package/dist/components/form/dropdown.d.ts.map +1 -1
  62. package/dist/components/form/dropdown.js +84 -80
  63. package/dist/components/form/dropdown.js.map +1 -1
  64. package/dist/components/form/file-autocomplete.d.ts +3 -6
  65. package/dist/components/form/file-autocomplete.d.ts.map +1 -1
  66. package/dist/components/form/file-autocomplete.js +61 -66
  67. package/dist/components/form/file-autocomplete.js.map +1 -1
  68. package/dist/components/form/file-picker.d.ts.map +1 -1
  69. package/dist/components/form/file-picker.js +33 -30
  70. package/dist/components/form/file-picker.js.map +1 -1
  71. package/dist/components/form/form-end.d.ts.map +1 -1
  72. package/dist/components/form/form-end.js +21 -1
  73. package/dist/components/form/form-end.js.map +1 -1
  74. package/dist/components/form/form-type-only.d.ts +174 -0
  75. package/dist/components/form/form-type-only.d.ts.map +1 -0
  76. package/dist/components/form/form-type-only.js +2 -0
  77. package/dist/components/form/form-type-only.js.map +1 -0
  78. package/dist/components/form/index.d.ts +3 -1
  79. package/dist/components/form/index.d.ts.map +1 -1
  80. package/dist/components/form/index.js +104 -30
  81. package/dist/components/form/index.js.map +1 -1
  82. package/dist/components/form/password-field.d.ts.map +1 -1
  83. package/dist/components/form/password-field.js +5 -3
  84. package/dist/components/form/password-field.js.map +1 -1
  85. package/dist/components/form/text-area.d.ts.map +1 -1
  86. package/dist/components/form/text-area.js +5 -3
  87. package/dist/components/form/text-area.js.map +1 -1
  88. package/dist/components/form/text-field.d.ts.map +1 -1
  89. package/dist/components/form/text-field.js +6 -4
  90. package/dist/components/form/text-field.js.map +1 -1
  91. package/dist/components/form/types.d.ts +5 -0
  92. package/dist/components/form/types.d.ts.map +1 -1
  93. package/dist/components/form/use-form-handling.d.ts +4 -0
  94. package/dist/components/form/use-form-handling.d.ts.map +1 -0
  95. package/dist/components/form/use-form-handling.js +37 -0
  96. package/dist/components/form/use-form-handling.js.map +1 -0
  97. package/dist/components/form/with-left-border.d.ts +2 -1
  98. package/dist/components/form/with-left-border.d.ts.map +1 -1
  99. package/dist/components/form/with-left-border.js +27 -3
  100. package/dist/components/form/with-left-border.js.map +1 -1
  101. package/dist/components/icon.d.ts +1 -0
  102. package/dist/components/icon.d.ts.map +1 -1
  103. package/dist/components/icon.js +24 -8
  104. package/dist/components/icon.js.map +1 -1
  105. package/dist/components/list.d.ts +2 -2
  106. package/dist/components/list.d.ts.map +1 -1
  107. package/dist/components/list.js +155 -70
  108. package/dist/components/list.js.map +1 -1
  109. package/dist/components/loading-bar.d.ts.map +1 -1
  110. package/dist/components/loading-bar.js +2 -2
  111. package/dist/components/loading-bar.js.map +1 -1
  112. package/dist/components/loading-text.d.ts +8 -0
  113. package/dist/components/loading-text.d.ts.map +1 -0
  114. package/dist/components/loading-text.js +58 -0
  115. package/dist/components/loading-text.js.map +1 -0
  116. package/dist/descendants.js +1 -1
  117. package/dist/descendants.js.map +1 -1
  118. package/dist/dev-ui.d.ts +7 -0
  119. package/dist/dev-ui.d.ts.map +1 -0
  120. package/dist/dev-ui.js +118 -0
  121. package/dist/dev-ui.js.map +1 -0
  122. package/dist/environment.d.ts +63 -0
  123. package/dist/environment.d.ts.map +1 -0
  124. package/dist/environment.js +189 -0
  125. package/dist/environment.js.map +1 -0
  126. package/dist/examples/datepicker.d.ts +2 -0
  127. package/dist/examples/datepicker.d.ts.map +1 -0
  128. package/dist/examples/datepicker.js +344 -0
  129. package/dist/examples/datepicker.js.map +1 -0
  130. package/dist/examples/file-autocomplete.vitest.d.ts +2 -0
  131. package/dist/examples/file-autocomplete.vitest.d.ts.map +1 -0
  132. package/dist/examples/file-autocomplete.vitest.js +223 -0
  133. package/dist/examples/file-autocomplete.vitest.js.map +1 -0
  134. package/dist/examples/form-basic-arrow-keys.vitest.d.ts +2 -0
  135. package/dist/examples/form-basic-arrow-keys.vitest.d.ts.map +1 -0
  136. package/dist/examples/form-basic-arrow-keys.vitest.js +46 -0
  137. package/dist/examples/form-basic-arrow-keys.vitest.js.map +1 -0
  138. package/dist/examples/form-basic.vitest.d.ts +2 -0
  139. package/dist/examples/form-basic.vitest.d.ts.map +1 -0
  140. package/dist/examples/form-basic.vitest.js +630 -0
  141. package/dist/examples/form-basic.vitest.js.map +1 -0
  142. package/dist/examples/form-dropdown-with-sections.d.ts +2 -0
  143. package/dist/examples/form-dropdown-with-sections.d.ts.map +1 -0
  144. package/dist/examples/form-dropdown-with-sections.js +13 -0
  145. package/dist/examples/form-dropdown-with-sections.js.map +1 -0
  146. package/dist/examples/form-dropdown-with-sections.vitest.d.ts +2 -0
  147. package/dist/examples/form-dropdown-with-sections.vitest.d.ts.map +1 -0
  148. package/dist/examples/form-dropdown-with-sections.vitest.js +75 -0
  149. package/dist/examples/form-dropdown-with-sections.vitest.js.map +1 -0
  150. package/dist/examples/form-dropdown.vitest.d.ts +2 -0
  151. package/dist/examples/form-dropdown.vitest.d.ts.map +1 -0
  152. package/dist/examples/form-dropdown.vitest.js +854 -0
  153. package/dist/examples/form-dropdown.vitest.js.map +1 -0
  154. package/dist/examples/form-multiselect-dropdown.d.ts +2 -0
  155. package/dist/examples/form-multiselect-dropdown.d.ts.map +1 -0
  156. package/dist/examples/form-multiselect-dropdown.js +13 -0
  157. package/dist/examples/form-multiselect-dropdown.js.map +1 -0
  158. package/dist/examples/form-scroll.d.ts.map +1 -1
  159. package/dist/examples/form-scroll.js +7 -1
  160. package/dist/examples/form-scroll.js.map +1 -1
  161. package/dist/examples/form-scroll.vitest.d.ts +2 -0
  162. package/dist/examples/form-scroll.vitest.d.ts.map +1 -0
  163. package/dist/examples/form-scroll.vitest.js +211 -0
  164. package/dist/examples/form-scroll.vitest.js.map +1 -0
  165. package/dist/examples/form-tagpicker.vitest.d.ts +2 -0
  166. package/dist/examples/form-tagpicker.vitest.d.ts.map +1 -0
  167. package/dist/examples/form-tagpicker.vitest.js +736 -0
  168. package/dist/examples/form-tagpicker.vitest.js.map +1 -0
  169. package/dist/examples/internal/descendants-filtering.js +1 -1
  170. package/dist/examples/internal/descendants-filtering.js.map +1 -1
  171. package/dist/examples/internal/descendants.js +1 -1
  172. package/dist/examples/internal/descendants.js.map +1 -1
  173. package/dist/examples/internal/nested-boxes.d.ts +2 -0
  174. package/dist/examples/internal/nested-boxes.d.ts.map +1 -0
  175. package/dist/examples/internal/nested-boxes.js +7 -0
  176. package/dist/examples/internal/nested-boxes.js.map +1 -0
  177. package/dist/examples/internal/rhf-custom-ref.js +2 -2
  178. package/dist/examples/internal/rhf-custom-ref.js.map +1 -1
  179. package/dist/examples/internal/scrollbox-demo.js +3 -22
  180. package/dist/examples/internal/scrollbox-demo.js.map +1 -1
  181. package/dist/examples/internal/scrollbox-descendants.d.ts +2 -0
  182. package/dist/examples/internal/scrollbox-descendants.d.ts.map +1 -0
  183. package/dist/examples/internal/scrollbox-descendants.js +83 -0
  184. package/dist/examples/internal/scrollbox-descendants.js.map +1 -0
  185. package/dist/examples/internal/scrollbox-with-descendants.js +4 -8
  186. package/dist/examples/internal/scrollbox-with-descendants.js.map +1 -1
  187. package/dist/examples/internal/simple-scrollbox.vitest.d.ts +2 -0
  188. package/dist/examples/internal/simple-scrollbox.vitest.d.ts.map +1 -0
  189. package/dist/examples/internal/simple-scrollbox.vitest.js +96 -0
  190. package/dist/examples/internal/simple-scrollbox.vitest.js.map +1 -0
  191. package/dist/examples/internal/unicode-square-repro.d.ts +2 -0
  192. package/dist/examples/internal/unicode-square-repro.d.ts.map +1 -0
  193. package/dist/examples/internal/unicode-square-repro.js +7 -0
  194. package/dist/examples/internal/unicode-square-repro.js.map +1 -0
  195. package/dist/examples/list-detail-metadata.d.ts +2 -0
  196. package/dist/examples/list-detail-metadata.d.ts.map +1 -0
  197. package/dist/examples/list-detail-metadata.js +8 -0
  198. package/dist/examples/list-detail-metadata.js.map +1 -0
  199. package/dist/examples/list-dropdown-default.vitest.d.ts +2 -0
  200. package/dist/examples/list-dropdown-default.vitest.d.ts.map +1 -0
  201. package/dist/examples/list-dropdown-default.vitest.js +234 -0
  202. package/dist/examples/list-dropdown-default.vitest.js.map +1 -0
  203. package/dist/examples/list-fetch-data.vitest.d.ts +2 -0
  204. package/dist/examples/list-fetch-data.vitest.d.ts.map +1 -0
  205. package/dist/examples/list-fetch-data.vitest.js +111 -0
  206. package/dist/examples/list-fetch-data.vitest.js.map +1 -0
  207. package/dist/examples/list-filter-navigation.d.ts +2 -0
  208. package/dist/examples/list-filter-navigation.d.ts.map +1 -0
  209. package/dist/examples/list-filter-navigation.js +8 -0
  210. package/dist/examples/list-filter-navigation.js.map +1 -0
  211. package/dist/examples/list-scrollbox.vitest.d.ts +2 -0
  212. package/dist/examples/list-scrollbox.vitest.d.ts.map +1 -0
  213. package/dist/examples/list-scrollbox.vitest.js +93 -0
  214. package/dist/examples/list-scrollbox.vitest.js.map +1 -0
  215. package/dist/examples/list-with-detail-long.d.ts +2 -0
  216. package/dist/examples/list-with-detail-long.d.ts.map +1 -0
  217. package/dist/examples/list-with-detail-long.js +53 -0
  218. package/dist/examples/list-with-detail-long.js.map +1 -0
  219. package/dist/examples/list-with-detail.vitest.d.ts +2 -0
  220. package/dist/examples/list-with-detail.vitest.d.ts.map +1 -0
  221. package/dist/examples/list-with-detail.vitest.js +434 -0
  222. package/dist/examples/list-with-detail.vitest.js.map +1 -0
  223. package/dist/examples/list-with-dropdown.vitest.d.ts +2 -0
  224. package/dist/examples/list-with-dropdown.vitest.d.ts.map +1 -0
  225. package/dist/examples/list-with-dropdown.vitest.js +337 -0
  226. package/dist/examples/list-with-dropdown.vitest.js.map +1 -0
  227. package/dist/examples/list-with-sections.js +5 -1
  228. package/dist/examples/list-with-sections.js.map +1 -1
  229. package/dist/examples/list-with-sections.vitest.d.ts +2 -0
  230. package/dist/examples/list-with-sections.vitest.d.ts.map +1 -0
  231. package/dist/examples/list-with-sections.vitest.js +601 -0
  232. package/dist/examples/list-with-sections.vitest.js.map +1 -0
  233. package/dist/examples/scrollbox-vertical-centering.d.ts +6 -0
  234. package/dist/examples/scrollbox-vertical-centering.d.ts.map +1 -0
  235. package/dist/examples/scrollbox-vertical-centering.js +17 -0
  236. package/dist/examples/scrollbox-vertical-centering.js.map +1 -0
  237. package/dist/examples/simple-file-picker.vitest.d.ts +2 -0
  238. package/dist/examples/simple-file-picker.vitest.d.ts.map +1 -0
  239. package/dist/examples/simple-file-picker.vitest.js +678 -0
  240. package/dist/examples/simple-file-picker.vitest.js.map +1 -0
  241. package/dist/examples/simple-grid.vitest.d.ts +2 -0
  242. package/dist/examples/simple-grid.vitest.d.ts.map +1 -0
  243. package/dist/examples/simple-grid.vitest.js +521 -0
  244. package/dist/examples/simple-grid.vitest.js.map +1 -0
  245. package/dist/examples/simple-navigation.js +10 -4
  246. package/dist/examples/simple-navigation.js.map +1 -1
  247. package/dist/examples/simple-navigation.vitest.d.ts +2 -0
  248. package/dist/examples/simple-navigation.vitest.d.ts.map +1 -0
  249. package/dist/examples/simple-navigation.vitest.js +718 -0
  250. package/dist/examples/simple-navigation.vitest.js.map +1 -0
  251. package/dist/examples/store.vitest.d.ts +2 -0
  252. package/dist/examples/store.vitest.d.ts.map +1 -0
  253. package/dist/examples/store.vitest.js +69 -0
  254. package/dist/examples/store.vitest.js.map +1 -0
  255. package/dist/examples/toast-variations.d.ts +2 -0
  256. package/dist/examples/toast-variations.d.ts.map +1 -0
  257. package/dist/examples/toast-variations.js +122 -0
  258. package/dist/examples/toast-variations.js.map +1 -0
  259. package/dist/extensions/dev.d.ts +4 -2
  260. package/dist/extensions/dev.d.ts.map +1 -1
  261. package/dist/extensions/dev.js +61 -10
  262. package/dist/extensions/dev.js.map +1 -1
  263. package/dist/extensions/dev.vitest.d.ts +2 -0
  264. package/dist/extensions/dev.vitest.d.ts.map +1 -0
  265. package/dist/extensions/dev.vitest.js +197 -0
  266. package/dist/extensions/dev.vitest.js.map +1 -0
  267. package/dist/extensions/home.d.ts.map +1 -1
  268. package/dist/extensions/home.js +3 -0
  269. package/dist/extensions/home.js.map +1 -1
  270. package/dist/home-command.d.ts +8 -0
  271. package/dist/home-command.d.ts.map +1 -0
  272. package/dist/home-command.js +181 -0
  273. package/dist/home-command.js.map +1 -0
  274. package/dist/hover-repro.d.ts +2 -0
  275. package/dist/hover-repro.d.ts.map +1 -0
  276. package/dist/hover-repro.js +20 -0
  277. package/dist/hover-repro.js.map +1 -0
  278. package/dist/index.d.ts +1 -0
  279. package/dist/index.d.ts.map +1 -1
  280. package/dist/index.js +2 -0
  281. package/dist/index.js.map +1 -1
  282. package/dist/internal/dialog.d.ts +1 -0
  283. package/dist/internal/dialog.d.ts.map +1 -1
  284. package/dist/internal/dialog.js +27 -18
  285. package/dist/internal/dialog.js.map +1 -1
  286. package/dist/internal/navigation.d.ts +9 -1
  287. package/dist/internal/navigation.d.ts.map +1 -1
  288. package/dist/internal/navigation.js +5 -5
  289. package/dist/internal/navigation.js.map +1 -1
  290. package/dist/internal/offscreen.d.ts +6 -0
  291. package/dist/internal/offscreen.d.ts.map +1 -0
  292. package/dist/internal/offscreen.js +10 -0
  293. package/dist/internal/offscreen.js.map +1 -0
  294. package/dist/internal/providers.d.ts.map +1 -1
  295. package/dist/internal/providers.js +2 -2
  296. package/dist/internal/providers.js.map +1 -1
  297. package/dist/internal/scrollbox.d.ts +1 -10
  298. package/dist/internal/scrollbox.d.ts.map +1 -1
  299. package/dist/internal/scrollbox.js +2 -1
  300. package/dist/internal/scrollbox.js.map +1 -1
  301. package/dist/localstorage.d.ts +13 -0
  302. package/dist/localstorage.d.ts.map +1 -0
  303. package/dist/localstorage.js +190 -0
  304. package/dist/localstorage.js.map +1 -0
  305. package/dist/oauth.d.ts +142 -0
  306. package/dist/oauth.d.ts.map +1 -0
  307. package/dist/oauth.js +551 -0
  308. package/dist/oauth.js.map +1 -0
  309. package/dist/preferences.d.ts +23 -0
  310. package/dist/preferences.d.ts.map +1 -0
  311. package/dist/preferences.js +105 -0
  312. package/dist/preferences.js.map +1 -0
  313. package/dist/release.d.ts +1 -1
  314. package/dist/release.d.ts.map +1 -1
  315. package/dist/release.js +29 -33
  316. package/dist/release.js.map +1 -1
  317. package/dist/state.d.ts +2 -0
  318. package/dist/state.d.ts.map +1 -1
  319. package/dist/state.js +3 -0
  320. package/dist/state.js.map +1 -1
  321. package/dist/store.d.ts +21 -0
  322. package/dist/store.d.ts.map +1 -0
  323. package/dist/store.js +84 -0
  324. package/dist/store.js.map +1 -0
  325. package/dist/swift-loader.d.ts +3 -0
  326. package/dist/swift-loader.d.ts.map +1 -0
  327. package/dist/swift-loader.js +193 -0
  328. package/dist/swift-loader.js.map +1 -0
  329. package/dist/swift-runtime.d.ts +2 -0
  330. package/dist/swift-runtime.d.ts.map +1 -0
  331. package/dist/swift-runtime.js +27 -0
  332. package/dist/swift-runtime.js.map +1 -0
  333. package/dist/toast.d.ts +44 -0
  334. package/dist/toast.d.ts.map +1 -0
  335. package/dist/toast.js +221 -0
  336. package/dist/toast.js.map +1 -0
  337. package/dist/utils/file-system.d.ts +9 -0
  338. package/dist/utils/file-system.d.ts.map +1 -1
  339. package/dist/utils/file-system.js +49 -0
  340. package/dist/utils/file-system.js.map +1 -1
  341. package/dist/utils/run-command.d.ts +26 -1
  342. package/dist/utils/run-command.d.ts.map +1 -1
  343. package/dist/utils/run-command.js +53 -4
  344. package/dist/utils/run-command.js.map +1 -1
  345. package/dist/window.d.ts +12 -0
  346. package/dist/window.d.ts.map +1 -0
  347. package/dist/window.js +48 -0
  348. package/dist/window.js.map +1 -0
  349. package/package.json +12 -12
  350. package/src/apis/browser-extension.tsx +29 -0
  351. package/src/apis/localstorage.test.ts +14 -6
  352. package/src/apis/localstorage.tsx +8 -5
  353. package/src/apis/oauth.tsx +5 -1
  354. package/src/apis/preferences.tsx +48 -22
  355. package/src/apis/toast.tsx +37 -62
  356. package/src/build.test.tsx +52 -0
  357. package/src/build.tsx +3 -1
  358. package/src/cli.tsx +99 -48
  359. package/src/compile.tsx +32 -11
  360. package/src/components/actions.tsx +94 -32
  361. package/src/components/detail.tsx +4 -0
  362. package/src/components/dropdown.tsx +47 -14
  363. package/src/components/extension-preferences.tsx +44 -16
  364. package/src/components/form/checkbox.tsx +12 -6
  365. package/src/components/form/date-picker.tsx +12 -6
  366. package/src/components/form/description.tsx +7 -2
  367. package/src/components/form/dropdown.tsx +131 -119
  368. package/src/components/form/file-autocomplete.tsx +90 -108
  369. package/src/components/form/file-picker.tsx +54 -43
  370. package/src/components/form/form-end.tsx +23 -2
  371. package/src/components/form/index.tsx +168 -41
  372. package/src/components/form/password-field.tsx +12 -6
  373. package/src/components/form/text-area.tsx +13 -6
  374. package/src/components/form/text-field.tsx +13 -6
  375. package/src/components/form/types.tsx +6 -0
  376. package/src/components/form/with-left-border.tsx +41 -8
  377. package/src/components/icon.tsx +27 -8
  378. package/src/components/list.tsx +243 -101
  379. package/src/components/loading-bar.tsx +3 -2
  380. package/src/components/loading-text.tsx +79 -0
  381. package/src/descendants.tsx +1 -0
  382. package/src/examples/file-autocomplete.vitest.tsx +130 -125
  383. package/src/examples/form-basic.vitest.tsx +376 -176
  384. package/src/examples/form-dropdown.vitest.tsx +126 -126
  385. package/src/examples/form-scroll.tsx +2 -0
  386. package/src/examples/form-scroll.vitest.tsx +58 -58
  387. package/src/examples/form-tagpicker.vitest.tsx +99 -99
  388. package/src/examples/internal/descendants-filtering.tsx +1 -0
  389. package/src/examples/internal/descendants.tsx +1 -0
  390. package/src/examples/internal/rhf-custom-ref.tsx +2 -0
  391. package/src/examples/internal/scrollbox-demo.tsx +3 -27
  392. package/src/examples/internal/scrollbox-with-descendants.tsx +4 -7
  393. package/src/examples/internal/simple-scrollbox.vitest.tsx +7 -5
  394. package/src/examples/list-detail-metadata.tsx +49 -0
  395. package/src/examples/list-detail-metadata.vitest.tsx +88 -0
  396. package/src/examples/list-dropdown-default.vitest.tsx +51 -51
  397. package/src/examples/list-fetch-data.vitest.tsx +4 -4
  398. package/src/examples/list-scrollbox.vitest.tsx +73 -14
  399. package/src/examples/list-with-detail-long.tsx +70 -0
  400. package/src/examples/list-with-detail.vitest.tsx +191 -85
  401. package/src/examples/list-with-dropdown.vitest.tsx +53 -53
  402. package/src/examples/list-with-sections.tsx +1 -0
  403. package/src/examples/list-with-sections.vitest.tsx +221 -97
  404. package/src/examples/list-with-toast.vitest.tsx +16 -16
  405. package/src/examples/simple-file-picker.vitest.tsx +63 -469
  406. package/src/examples/simple-grid.vitest.tsx +238 -233
  407. package/src/examples/simple-navigation.tsx +15 -7
  408. package/src/examples/simple-navigation.vitest.tsx +130 -219
  409. package/src/examples/store.vitest.tsx +1 -1
  410. package/src/examples/swift-extension.vitest.tsx +148 -0
  411. package/src/examples/synonyms.vitest.tsx +159 -0
  412. package/src/examples/toast-variations.tsx +150 -0
  413. package/src/examples/toast-variations.vitest.tsx +370 -0
  414. package/src/extensions/dev.tsx +74 -7
  415. package/src/extensions/dev.vitest.tsx +102 -34
  416. package/src/extensions/home.tsx +6 -0
  417. package/src/index.tsx +3 -0
  418. package/src/internal/dialog.tsx +43 -30
  419. package/src/internal/navigation.tsx +3 -1
  420. package/src/internal/offscreen.tsx +15 -0
  421. package/src/internal/providers.tsx +4 -2
  422. package/src/internal/scrollbox.tsx +4 -8
  423. package/src/keyboard.test.tsx +69 -0
  424. package/src/release.tsx +32 -38
  425. package/src/state.tsx +7 -0
  426. package/src/swift-loader.tsx +239 -0
  427. package/src/swift-runtime.tsx +36 -0
  428. package/src/utils/file-system.ts +61 -0
  429. package/src/utils/run-command.tsx +82 -6
@@ -38,11 +38,10 @@ test('dev command shows extension commands list', async () => {
38
38
  ›List Items Displays a simple list with some ite view ▀
39
39
  Search Items Search and filter through a list o view
40
40
  Google Oauth view
41
- usePromise Demo Shows how to use the usePromise view
42
-
41
+ usePromise Demo Shows how to use the usePromise view
43
42
 
44
43
 
45
- select ↑↓ navigate ^k actions"
44
+ run command ↑↓ navigate ^k actions"
46
45
  `)
47
46
  }, 30000)
48
47
 
@@ -68,15 +67,14 @@ test('selecting command with arguments shows arguments form', async () => {
68
67
 
69
68
  Search commands...
70
69
 
71
- Search Items Search and filter through a list o view ▲
72
- Google Oauth view
73
- usePromise Demo Shows how to use the usePromise view ▄
70
+ usePromise Demo Shows how to use the usePromise view ▲
74
71
  Show State Shows the current application state view
75
72
  ›With Arguments Demonstrates command arguments ( view
73
+ Quick Action Copies current timestamp to cli no-view ▄
76
74
 
77
75
 
78
76
 
79
- select ↑↓ navigate ^k actions"
77
+ run command ↑↓ navigate ^k actions"
80
78
  `)
81
79
 
82
80
  // Select the command to show arguments form (enter opens action panel, enter again runs)
@@ -93,19 +91,19 @@ test('selecting command with arguments shows arguments form', async () => {
93
91
  "
94
92
 
95
93
 
96
- With Arguments █
97
- │ Enter the arguments to run this command.
94
+ With Arguments █
95
+ │ Enter the arguments to run this command.
96
+
97
+ ◇ Search query
98
+ │ Search query
98
99
 
99
- ◆ Search query
100
- ┃ Search query
101
-
102
100
  ◇ Secret key
103
101
  │ Secret key
104
102
  ◇ Category
105
103
  │ Category
106
104
 
107
105
 
108
- alt ↵ submit ↑↓ navigate ^k actions"
106
+ ctrl ↵ submit tab navigate ^k actions"
109
107
  `)
110
108
  }, 30000)
111
109
 
@@ -137,19 +135,19 @@ test('can fill arguments and run command', async () => {
137
135
  "
138
136
 
139
137
 
140
- With Arguments █
141
- │ Enter the arguments to run this command.
138
+ With Arguments █
139
+ │ Enter the arguments to run this command.
140
+
141
+ ◇ Search query
142
+ │ Search query
142
143
 
143
- ◆ Search query
144
- ┃ my search term
145
-
146
144
  ◇ Secret key
147
145
  │ Secret key
148
146
  ◇ Category
149
147
  │ Category
150
148
 
151
149
 
152
- alt ↵ submit ↑↓ navigate ^k actions"
150
+ ctrl ↵ submit tab navigate ^k actions"
153
151
  `)
154
152
 
155
153
  // Submit the form with Alt+Enter (opens action panel), then Enter (selects submit)
@@ -171,15 +169,15 @@ test('can fill arguments and run command', async () => {
171
169
  Search...
172
170
 
173
171
  Received Arguments
174
- Search Query my search term
175
- Secret Key (empty)
176
- Category (empty)
172
+ ›▼ Search Query (empty)
173
+ Secret Key (empty)
174
+ Category (empty)
177
175
 
178
176
 
179
-
180
- sele┌────────────────────────────────────────┐
181
- ✓ Copied to Clipboard - my search term
182
- └────────────────────────────────────────┘"
177
+ ┌───────────────────────┐
178
+ ✓ Copied to Clipboard │
179
+ (empty)
180
+ └───────────────────────┘"
183
181
  `)
184
182
  }, 30000)
185
183
 
@@ -208,13 +206,83 @@ test('can run simple view command without arguments', async () => {
208
206
  Search...
209
207
 
210
208
  Items ▲
211
- First Item This is the first item
212
- Second Item This is the second item
213
- Third Item This is the third item
214
- Fourth Item This is the fourth item
215
-
216
-
217
-
218
- select ↑↓ navigate ^k actions"
209
+ ›▲ First Item This is the first item
210
+ Second Item This is the second item
211
+ Third Item This is the third item
212
+ Fourth Item This is the fourth item
213
+ ▲ Fifth Item This is the fifth item
214
+ ┌───────────────────────┐
215
+ │ ✓ Copied to Clipboard │
216
+ │ First Item │
217
+ └───────────────────────┘"
219
218
  `)
220
219
  }, 30000)
220
+
221
+ test('hot reload updates TUI when source file changes', async () => {
222
+ const hotReloadFixtureDir = path.resolve(__dirname, '../../fixtures/hot-reload-extension')
223
+ const sourceFilePath = path.join(hotReloadFixtureDir, 'src/detail-view.tsx')
224
+ const fs = await import('node:fs')
225
+
226
+ // Read original content to restore later
227
+ const originalContent = fs.readFileSync(sourceFilePath, 'utf-8')
228
+
229
+ // Start a new session for this test
230
+ const hotReloadSession = await launchTerminal({
231
+ command: 'bun',
232
+ args: ['src/cli.tsx', 'dev', hotReloadFixtureDir],
233
+ cols: 60,
234
+ rows: 16,
235
+ })
236
+
237
+ try {
238
+ // Wait for the extension to load
239
+ await hotReloadSession.text({
240
+ waitFor: (text) => /Hot Reload Test/i.test(text) && /Detail View/i.test(text),
241
+ timeout: 5000,
242
+ })
243
+ await hotReloadSession.waitIdle()
244
+
245
+ // Run the Detail View command
246
+ await hotReloadSession.press('enter')
247
+ await hotReloadSession.press('enter')
248
+ await hotReloadSession.waitIdle()
249
+
250
+ // Wait for the detail view to show
251
+ await hotReloadSession.text({
252
+ waitFor: (text) => /MARKER_VALUE/i.test(text),
253
+ timeout: 10000,
254
+ })
255
+
256
+ // Generate a random number
257
+ const randomNumber = Math.floor(Math.random() * 1000000)
258
+
259
+ // Update the source file with the random number
260
+ const newContent = originalContent.replace('MARKER_VALUE', `UPDATED_${randomNumber}`)
261
+ fs.writeFileSync(sourceFilePath, newContent)
262
+
263
+ // Wait for rebuild - navigation resets to commands list
264
+ await hotReloadSession.text({
265
+ waitFor: (text) => /Hot Reload Test/i.test(text) && /Detail View/i.test(text),
266
+ timeout: 5000,
267
+ })
268
+ await hotReloadSession.waitIdle()
269
+
270
+ // Run the command again to see updated content
271
+ await hotReloadSession.press('enter')
272
+ await hotReloadSession.press('enter')
273
+ await hotReloadSession.waitIdle()
274
+
275
+ // Wait for the updated content
276
+ await hotReloadSession.text({
277
+ waitFor: (text) => text.includes(`UPDATED_${randomNumber}`),
278
+ timeout: 10000,
279
+ })
280
+
281
+ const updatedSnapshot = await hotReloadSession.text()
282
+ expect(updatedSnapshot).toContain(`UPDATED_${randomNumber}`)
283
+ } finally {
284
+ // Restore original content
285
+ fs.writeFileSync(sourceFilePath, originalContent)
286
+ hotReloadSession?.close()
287
+ }
288
+ }, 60000)
@@ -1,4 +1,5 @@
1
1
  import fs from 'node:fs'
2
+ import path from 'node:path'
2
3
  import React from 'react'
3
4
  import { createRoot } from '@opentui/react'
4
5
  import { createCliRenderer } from '@opentui/core'
@@ -17,6 +18,7 @@ import '../globals'
17
18
  interface ExtensionCommand {
18
19
  extensionName: string
19
20
  extensionTitle: string
21
+ extensionDir?: string
20
22
  command: any
21
23
  bundledPath?: string
22
24
  Component?: () => any
@@ -52,6 +54,8 @@ function ExtensionsList({
52
54
  const handleCommandSelect = async (item: ExtensionCommand) => {
53
55
  clearCommandArguments()
54
56
 
57
+
58
+
55
59
  try {
56
60
  await runCommand({
57
61
  command: item.command,
@@ -208,12 +212,14 @@ export default function Home({
208
212
  const packageJson = JSON.parse(
209
213
  fs.readFileSync(extension.packageJsonPath, 'utf-8'),
210
214
  )
215
+ const extensionPath = path.dirname(extension.packageJsonPath)
211
216
 
212
217
  for (const command of extension.commands) {
213
218
  if (command.bundledPath) {
214
219
  allCommands.push({
215
220
  extensionName: extension.name,
216
221
  extensionTitle: packageJson.title || extension.name,
222
+ extensionDir: extensionPath,
217
223
  command,
218
224
  bundledPath: command.bundledPath,
219
225
  packageJson,
package/src/index.tsx CHANGED
@@ -124,6 +124,9 @@ export type {
124
124
  // AI
125
125
  export { AI } from 'termcast/src/apis/ai'
126
126
 
127
+ // Browser Extension
128
+ export { BrowserExtension } from 'termcast/src/apis/browser-extension'
129
+
127
130
  // OAuth
128
131
  export { OAuth } from 'termcast/src/apis/oauth'
129
132
 
@@ -1,5 +1,5 @@
1
1
  import { useKeyboard, useTerminalDimensions } from '@opentui/react'
2
- import React, { type ReactNode, useRef } from 'react'
2
+ import React, { type ReactNode, useRef, useContext } from 'react'
3
3
  import { Theme } from 'termcast/src/theme'
4
4
  import { InFocus, useIsInFocus } from 'termcast/src/internal/focus-context'
5
5
  import { CommonProps } from 'termcast/src/utils'
@@ -10,13 +10,14 @@ import {
10
10
  } from 'termcast/src/state'
11
11
  import { logger } from '../logger'
12
12
  import { ToastOverlay } from 'termcast/src/apis/toast'
13
+ import { NavigationContext } from 'termcast/src/internal/navigation'
13
14
 
14
15
  const Border = {
15
- topLeft: '',
16
- topRight: '',
16
+ topLeft: '',
17
+ topRight: '',
17
18
  bottomLeft: '',
18
19
  bottomRight: '',
19
- horizontal: '',
20
+ horizontal: '',
20
21
  vertical: '┃',
21
22
  topT: '+',
22
23
  bottomT: '+',
@@ -107,7 +108,7 @@ export function Dialog({
107
108
  onMouseDown={handleBackdropClick}
108
109
  >
109
110
  <box
110
- border={false}
111
+ border
111
112
  customBorderChars={Border}
112
113
  width={76}
113
114
  maxWidth={dimensions.width - 2}
@@ -145,31 +146,6 @@ export function DialogProvider(props: DialogProviderProps): any {
145
146
  return (
146
147
  <>
147
148
  <InFocus inFocus={!dialogStack?.length}>{props.children}</InFocus>
148
- {dialogStack.length > 0 && (
149
- <box position='absolute'>
150
- {dialogStack.map((item, index) => {
151
- const isLastItem = index === dialogStack.length - 1
152
- return (
153
- <InFocus key={'dialog' + String(index)} inFocus={isLastItem}>
154
- <Dialog
155
- position={item.position}
156
- onClickOutside={() => {
157
- if (!isLastItem) return
158
- const state = useStore.getState()
159
- if (state.dialogStack.length > 0) {
160
- useStore.setState({
161
- dialogStack: state.dialogStack.slice(0, -1),
162
- })
163
- }
164
- }}
165
- >
166
- {item.element}
167
- </Dialog>
168
- </InFocus>
169
- )
170
- })}
171
- </box>
172
- )}
173
149
  <InFocus inFocus={false}>
174
150
  <ToastOverlay />
175
151
  </InFocus>
@@ -177,6 +153,43 @@ export function DialogProvider(props: DialogProviderProps): any {
177
153
  )
178
154
  }
179
155
 
156
+ export function DialogOverlay(): any {
157
+ const dialogStack = useStore((state) => state.dialogStack)
158
+ const navContext = useContext(NavigationContext)
159
+
160
+ if (dialogStack.length === 0) {
161
+ return null
162
+ }
163
+
164
+ return (
165
+ <box position='absolute'>
166
+ {dialogStack.map((item, index) => {
167
+ const isLastItem = index === dialogStack.length - 1
168
+ return (
169
+ <InFocus key={'dialog' + String(index)} inFocus={isLastItem}>
170
+ <Dialog
171
+ position={item.position}
172
+ onClickOutside={() => {
173
+ if (!isLastItem) return
174
+ const state = useStore.getState()
175
+ if (state.dialogStack.length > 0) {
176
+ useStore.setState({
177
+ dialogStack: state.dialogStack.slice(0, -1),
178
+ })
179
+ }
180
+ }}
181
+ >
182
+ <NavigationContext.Provider value={navContext}>
183
+ {item.element}
184
+ </NavigationContext.Provider>
185
+ </Dialog>
186
+ </InFocus>
187
+ )
188
+ })}
189
+ </box>
190
+ )
191
+ }
192
+
180
193
  export function useDialog() {
181
194
  const dialogStack = useStore((state) => state.dialogStack)
182
195
 
@@ -26,12 +26,13 @@ interface NavigationContextType {
26
26
  isPending: boolean
27
27
  }
28
28
 
29
- const NavigationContext = createContext<NavigationContextType | undefined>(
29
+ export const NavigationContext = createContext<NavigationContextType | undefined>(
30
30
  undefined,
31
31
  )
32
32
 
33
33
  interface NavigationProviderProps extends CommonProps {
34
34
  children: ReactNode
35
+ overlay?: ReactNode
35
36
  }
36
37
 
37
38
  export function NavigationProvider(props: NavigationProviderProps): any {
@@ -139,6 +140,7 @@ export function NavigationProvider(props: NavigationProviderProps): any {
139
140
  {React.cloneElement(currentItem?.element as React.ReactElement, {
140
141
  key: stack.length,
141
142
  })}
143
+ {props.overlay}
142
144
  </NavigationContext.Provider>
143
145
  )
144
146
  }
@@ -0,0 +1,15 @@
1
+ import { createContext, useContext, ReactNode } from 'react'
2
+
3
+ const OffscreenContext = createContext(false)
4
+
5
+ export function useIsOffscreen(): boolean {
6
+ return useContext(OffscreenContext)
7
+ }
8
+
9
+ export function Offscreen({ children }: { children: ReactNode }): any {
10
+ return (
11
+ <OffscreenContext.Provider value={true}>
12
+ {children}
13
+ </OffscreenContext.Provider>
14
+ )
15
+ }
@@ -6,7 +6,7 @@ import React, {
6
6
  } from 'react'
7
7
  import { QueryClient } from '@tanstack/react-query'
8
8
  import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'
9
- import { DialogProvider } from 'termcast/src/internal/dialog'
9
+ import { DialogProvider, DialogOverlay } from 'termcast/src/internal/dialog'
10
10
  import { NavigationProvider } from 'termcast/src/internal/navigation'
11
11
  import { CommonProps } from 'termcast/src/utils'
12
12
  import { Cache } from 'termcast/src/apis/cache'
@@ -420,7 +420,9 @@ export function TermcastProvider(props: ProvidersProps): any {
420
420
  <DialogProvider>
421
421
  <box padding={2}>
422
422
  {/* NavigationProvider must be last to ensure parent providers remain in the tree when navigation changes */}
423
- <NavigationProvider>{props.children}</NavigationProvider>
423
+ <NavigationProvider overlay={<DialogOverlay />}>
424
+ {props.children}
425
+ </NavigationProvider>
424
426
  </box>
425
427
  </DialogProvider>
426
428
  </PersistQueryClientProvider>
@@ -1,14 +1,8 @@
1
1
  import React from 'react'
2
2
  import Theme from '../theme'
3
+ import { MacOSScrollAccel } from '@opentui/core'
4
+ import { ScrollBoxProps } from '@opentui/react'
3
5
 
4
- interface ScrollBoxProps {
5
- children?: React.ReactNode
6
- focused?: boolean
7
- flexGrow?: number
8
- flexShrink?: number
9
- style?: any
10
- ref?: React.Ref<any>
11
- }
12
6
 
13
7
  export function ScrollBox({
14
8
  children,
@@ -23,6 +17,7 @@ export function ScrollBox({
23
17
  <scrollbox
24
18
  ref={ref}
25
19
  focused={focused}
20
+ scrollAcceleration={new MacOSScrollAccel()}
26
21
  flexGrow={flexGrow}
27
22
  flexShrink={flexShrink}
28
23
  style={{
@@ -34,6 +29,7 @@ export function ScrollBox({
34
29
  flexGrow: 1,
35
30
  flexShrink: 1,
36
31
  paddingRight: 1,
32
+
37
33
  ...(style?.viewportOptions || {}),
38
34
  },
39
35
  contentOptions: {
@@ -0,0 +1,69 @@
1
+ import { describe, test, expect } from 'bun:test'
2
+ import { Keyboard } from 'termcast/src/keyboard'
3
+ import type {
4
+ KeyboardKeyEquivalent,
5
+ KeyboardKeyModifier,
6
+ KeyboardShortcut,
7
+ } from 'termcast/src/keyboard'
8
+
9
+ describe('Keyboard', () => {
10
+ test('Keyboard.Shortcut.Common has all expected shortcuts', () => {
11
+ const commonShortcuts = Object.keys(Keyboard.Shortcut.Common)
12
+ expect(commonShortcuts).toMatchInlineSnapshot(`
13
+ [
14
+ "Copy",
15
+ "CopyDeeplink",
16
+ "CopyName",
17
+ "CopyPath",
18
+ "Save",
19
+ "Duplicate",
20
+ "Edit",
21
+ "MoveDown",
22
+ "MoveUp",
23
+ "New",
24
+ "Open",
25
+ "OpenWith",
26
+ "Pin",
27
+ "Refresh",
28
+ "Remove",
29
+ "RemoveAll",
30
+ "ToggleQuickLook",
31
+ ]
32
+ `)
33
+ })
34
+
35
+ test('Keyboard.Shortcut.Common.Open has correct structure', () => {
36
+ expect(Keyboard.Shortcut.Common.Open).toMatchInlineSnapshot(`
37
+ {
38
+ "key": "o",
39
+ "modifiers": [
40
+ "cmd",
41
+ ],
42
+ }
43
+ `)
44
+ })
45
+
46
+ test('Keyboard.Shortcut.Common.Copy has correct structure', () => {
47
+ expect(Keyboard.Shortcut.Common.Copy).toMatchInlineSnapshot(`
48
+ {
49
+ "key": "c",
50
+ "modifiers": [
51
+ "cmd",
52
+ "shift",
53
+ ],
54
+ }
55
+ `)
56
+ })
57
+
58
+ test('Keyboard.Shortcut.Common.Remove uses ctrl modifier', () => {
59
+ expect(Keyboard.Shortcut.Common.Remove).toMatchInlineSnapshot(`
60
+ {
61
+ "key": "x",
62
+ "modifiers": [
63
+ "ctrl",
64
+ ],
65
+ }
66
+ `)
67
+ })
68
+
69
+ })
package/src/release.tsx CHANGED
@@ -19,7 +19,7 @@ export interface ReleaseOptions {
19
19
 
20
20
  export interface ReleaseResult {
21
21
  success: boolean
22
- version: string
22
+ tag: string
23
23
  uploadedFiles: string[]
24
24
  }
25
25
 
@@ -33,46 +33,38 @@ export async function releaseExtension({
33
33
  throw new Error(`Extension path does not exist: ${resolvedPath}`)
34
34
  }
35
35
 
36
- const packageJsonPath = path.join(resolvedPath, 'package.json')
37
- if (!fs.existsSync(packageJsonPath)) {
38
- throw new Error(`No package.json found at: ${packageJsonPath}`)
39
- }
40
-
41
- const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'))
42
- const name = packageJson.name
43
- const version = packageJson.version
44
-
45
- if (!name) {
46
- throw new Error('package.json must have a name field')
47
- }
48
- if (!version) {
49
- throw new Error('package.json must have a version field')
50
- }
51
-
52
- const tag = `${name}@${version}`
53
- console.log(`Preparing release ${tag}...`)
54
-
55
- // Check if release already exists
36
+ // Get repo name from git remote
37
+ let repoName: string
56
38
  try {
57
- const checkResult = execSync(`gh release view "${tag}" --json tagName`, {
39
+ const remoteUrl = execSync('git config --get remote.origin.url', {
58
40
  cwd: resolvedPath,
59
41
  encoding: 'utf-8',
60
- stdio: ['pipe', 'pipe', 'pipe'],
61
- })
62
- if (checkResult.includes(tag)) {
63
- throw new Error(`Release ${tag} already exists. Bump the version in package.json first.`)
42
+ }).trim()
43
+ // Handle both HTTPS and SSH URLs:
44
+ // https://github.com/user/repo.git -> repo
45
+ // git@github.com:user/repo.git -> repo
46
+ const match = remoteUrl.match(/\/([^/]+?)(?:\.git)?$/) || remoteUrl.match(/:([^/]+?)(?:\.git)?$/)
47
+ if (!match) {
48
+ throw new Error(`Could not parse repo name from remote URL: ${remoteUrl}`)
64
49
  }
50
+ repoName = match[1].replace(/\.git$/, '')
65
51
  } catch (error: any) {
66
- if (error.message?.includes('already exists')) {
67
- throw error
68
- }
69
- const stderr = error.stderr?.toString() || ''
70
- const isNotFound = stderr.includes('release not found') || stderr.includes('Not Found')
71
- if (!isNotFound) {
72
- throw new Error(`Failed to check release status: ${stderr || error.message}`)
73
- }
52
+ throw new Error(`Failed to get git remote: ${error.message}`)
74
53
  }
75
54
 
55
+ // Generate date-based tag with hour and minute
56
+ const now = new Date()
57
+ const dateTag = [
58
+ now.getFullYear(),
59
+ String(now.getMonth() + 1).padStart(2, '0'),
60
+ String(now.getDate()).padStart(2, '0'),
61
+ String(now.getHours()).padStart(2, '0'),
62
+ String(now.getMinutes()).padStart(2, '0'),
63
+ ].join('')
64
+
65
+ const tag = `${repoName}@${dateTag}`
66
+ console.log(`Preparing release ${tag}...`)
67
+
76
68
  // Install dependencies for all platforms
77
69
  console.log('Installing dependencies for all platforms...')
78
70
  execSync('bun install --os="*" --cpu="*"', {
@@ -92,13 +84,14 @@ export async function releaseExtension({
92
84
  if (!fs.existsSync(outputDir)) {
93
85
  fs.mkdirSync(outputDir, { recursive: true })
94
86
  }
87
+ fs.writeFileSync(path.join(outputDir, '.gitignore'), '*\n')
95
88
 
96
89
  // Compile for all targets in parallel
97
90
  console.log(`Compiling for ${targets.length} targets in parallel...`)
98
91
  const compileResults = await Promise.all(
99
92
  targets.map(async (target) => {
100
93
  const suffix = targetToFileSuffix(target)
101
- const binaryName = `${name}-${suffix}`
94
+ const binaryName = `${repoName}-${suffix}`
102
95
  const outfile = path.join(outputDir, binaryName)
103
96
 
104
97
  const result = await compileExtension({
@@ -106,12 +99,13 @@ export async function releaseExtension({
106
99
  outfile,
107
100
  minify: true,
108
101
  target,
102
+ version: tag,
109
103
  })
110
104
 
111
105
  console.log(` ✓ ${path.basename(result.outfile)}`)
112
106
 
113
107
  const archiveExt = getArchiveExtension(target)
114
- const archiveName = `${name}-${suffix}${archiveExt}`
108
+ const archiveName = `${repoName}-${suffix}${archiveExt}`
115
109
  const archivePath = path.join(outputDir, archiveName)
116
110
 
117
111
  if (archiveExt === '.tar.gz') {
@@ -130,7 +124,7 @@ export async function releaseExtension({
130
124
  // Create GitHub release
131
125
  console.log(`\nCreating GitHub release ${tag}...`)
132
126
  try {
133
- execSync(`gh release create "${tag}" --title "${tag}" --notes "Release ${version}"`, {
127
+ execSync(`gh release create "${tag}" --title "${tag}" --notes "Release ${tag}"`, {
134
128
  cwd: resolvedPath,
135
129
  stdio: 'inherit',
136
130
  })
@@ -158,7 +152,7 @@ export async function releaseExtension({
158
152
 
159
153
  return {
160
154
  success: true,
161
- version,
155
+ tag,
162
156
  uploadedFiles: compileResults,
163
157
  }
164
158
  }
package/src/state.tsx CHANGED
@@ -30,6 +30,10 @@ interface AppState {
30
30
  // OAuth state
31
31
  googleAccessToken?: string
32
32
  googleIdToken?: string
33
+ // Actions state - when true, auto-execute first action instead of showing sheet
34
+ shouldAutoExecuteFirstAction: boolean
35
+ // First action title for footer display (set by offscreen ActionPanel)
36
+ firstActionTitle: string
33
37
  }
34
38
 
35
39
  export const useStore = create<AppState>(() => ({
@@ -48,4 +52,7 @@ export const useStore = create<AppState>(() => ({
48
52
  // OAuth state
49
53
  googleAccessToken: undefined,
50
54
  googleIdToken: undefined,
55
+ // Actions state
56
+ shouldAutoExecuteFirstAction: false,
57
+ firstActionTitle: '',
51
58
  }))