termcast 1.3.30 → 1.3.32

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 (294) hide show
  1. package/dist/apis/cache.d.ts.map +1 -1
  2. package/dist/apis/cache.js +4 -39
  3. package/dist/apis/cache.js.map +1 -1
  4. package/dist/apis/hud.d.ts.map +1 -1
  5. package/dist/apis/hud.js +13 -31
  6. package/dist/apis/hud.js.map +1 -1
  7. package/dist/apis/localstorage.d.ts.map +1 -1
  8. package/dist/apis/localstorage.js +3 -27
  9. package/dist/apis/localstorage.js.map +1 -1
  10. package/dist/apis/toast.d.ts +16 -43
  11. package/dist/apis/toast.d.ts.map +1 -1
  12. package/dist/apis/toast.js +78 -177
  13. package/dist/apis/toast.js.map +1 -1
  14. package/dist/build.d.ts +3 -1
  15. package/dist/build.d.ts.map +1 -1
  16. package/dist/build.js +52 -2
  17. package/dist/build.js.map +1 -1
  18. package/dist/cli.d.ts +1 -0
  19. package/dist/cli.d.ts.map +1 -1
  20. package/dist/cli.js +206 -25
  21. package/dist/cli.js.map +1 -1
  22. package/dist/colors.d.ts.map +1 -1
  23. package/dist/colors.js +1 -0
  24. package/dist/colors.js.map +1 -1
  25. package/dist/compile.d.ts +0 -1
  26. package/dist/compile.d.ts.map +1 -1
  27. package/dist/compile.js +18 -23
  28. package/dist/compile.js.map +1 -1
  29. package/dist/components/actions.d.ts.map +1 -1
  30. package/dist/components/actions.js +30 -15
  31. package/dist/components/actions.js.map +1 -1
  32. package/dist/components/animation-tick.d.ts +12 -0
  33. package/dist/components/animation-tick.d.ts.map +1 -0
  34. package/dist/components/animation-tick.js +63 -0
  35. package/dist/components/animation-tick.js.map +1 -0
  36. package/dist/components/detail.d.ts.map +1 -1
  37. package/dist/components/detail.js +10 -13
  38. package/dist/components/detail.js.map +1 -1
  39. package/dist/components/dropdown.d.ts +1 -0
  40. package/dist/components/dropdown.d.ts.map +1 -1
  41. package/dist/components/dropdown.js +27 -26
  42. package/dist/components/dropdown.js.map +1 -1
  43. package/dist/components/extension-preferences.d.ts.map +1 -1
  44. package/dist/components/extension-preferences.js +15 -10
  45. package/dist/components/extension-preferences.js.map +1 -1
  46. package/dist/components/footer.d.ts +13 -0
  47. package/dist/components/footer.d.ts.map +1 -0
  48. package/dist/components/footer.js +106 -0
  49. package/dist/components/footer.js.map +1 -0
  50. package/dist/components/form/file-autocomplete.d.ts +19 -4
  51. package/dist/components/form/file-autocomplete.d.ts.map +1 -1
  52. package/dist/components/form/file-autocomplete.js +56 -55
  53. package/dist/components/form/file-autocomplete.js.map +1 -1
  54. package/dist/components/form/file-picker.d.ts.map +1 -1
  55. package/dist/components/form/file-picker.js +26 -15
  56. package/dist/components/form/file-picker.js.map +1 -1
  57. package/dist/components/form/index.d.ts.map +1 -1
  58. package/dist/components/form/index.js +17 -15
  59. package/dist/components/form/index.js.map +1 -1
  60. package/dist/components/form/with-left-border.d.ts.map +1 -1
  61. package/dist/components/form/with-left-border.js +4 -12
  62. package/dist/components/form/with-left-border.js.map +1 -1
  63. package/dist/components/list.d.ts.map +1 -1
  64. package/dist/components/list.js +126 -86
  65. package/dist/components/list.js.map +1 -1
  66. package/dist/components/loading-bar.d.ts.map +1 -1
  67. package/dist/components/loading-bar.js +5 -22
  68. package/dist/components/loading-bar.js.map +1 -1
  69. package/dist/components/loading-text.d.ts.map +1 -1
  70. package/dist/components/loading-text.js +3 -22
  71. package/dist/components/loading-text.js.map +1 -1
  72. package/dist/components/theme-picker.d.ts +2 -0
  73. package/dist/components/theme-picker.d.ts.map +1 -0
  74. package/dist/components/theme-picker.js +37 -0
  75. package/dist/components/theme-picker.js.map +1 -0
  76. package/dist/descendants.d.ts +6 -0
  77. package/dist/descendants.d.ts.map +1 -1
  78. package/dist/descendants.js +74 -8
  79. package/dist/descendants.js.map +1 -1
  80. package/dist/examples/internal/descendants-rerender.d.ts +14 -0
  81. package/dist/examples/internal/descendants-rerender.d.ts.map +1 -0
  82. package/dist/examples/internal/descendants-rerender.js +145 -0
  83. package/dist/examples/internal/descendants-rerender.js.map +1 -0
  84. package/dist/examples/internal/simple-dialog.js +4 -1
  85. package/dist/examples/internal/simple-dialog.js.map +1 -1
  86. package/dist/examples/internal/simple-scrollbox.js +1 -1
  87. package/dist/examples/internal/simple-scrollbox.js.map +1 -1
  88. package/dist/examples/list-with-dropdown.js +1 -1
  89. package/dist/examples/list-with-dropdown.js.map +1 -1
  90. package/dist/examples/miscellaneous.js +1 -1
  91. package/dist/examples/miscellaneous.js.map +1 -1
  92. package/dist/examples/toast-action.d.ts +2 -0
  93. package/dist/examples/toast-action.d.ts.map +1 -0
  94. package/dist/examples/toast-action.js +76 -0
  95. package/dist/examples/toast-action.js.map +1 -0
  96. package/dist/examples/toast-variations.js +38 -36
  97. package/dist/examples/toast-variations.js.map +1 -1
  98. package/dist/extensions/dev.d.ts +1 -1
  99. package/dist/extensions/dev.d.ts.map +1 -1
  100. package/dist/extensions/dev.js +62 -30
  101. package/dist/extensions/dev.js.map +1 -1
  102. package/dist/extensions/home.d.ts.map +1 -1
  103. package/dist/extensions/home.js +4 -3
  104. package/dist/extensions/home.js.map +1 -1
  105. package/dist/extensions/react-refresh-init.d.ts +5 -0
  106. package/dist/extensions/react-refresh-init.d.ts.map +1 -0
  107. package/dist/extensions/react-refresh-init.js +52 -0
  108. package/dist/extensions/react-refresh-init.js.map +1 -0
  109. package/dist/internal/date-picker-widget.js +1 -1
  110. package/dist/internal/date-picker-widget.js.map +1 -1
  111. package/dist/internal/dialog.d.ts +8 -3
  112. package/dist/internal/dialog.d.ts.map +1 -1
  113. package/dist/internal/dialog.js +37 -53
  114. package/dist/internal/dialog.js.map +1 -1
  115. package/dist/internal/navigation.d.ts +1 -0
  116. package/dist/internal/navigation.d.ts.map +1 -1
  117. package/dist/internal/navigation.js +25 -1
  118. package/dist/internal/navigation.js.map +1 -1
  119. package/dist/internal/providers.d.ts.map +1 -1
  120. package/dist/internal/providers.js +9 -197
  121. package/dist/internal/providers.js.map +1 -1
  122. package/dist/internal/scrollbox.d.ts.map +1 -1
  123. package/dist/internal/scrollbox.js +1 -0
  124. package/dist/internal/scrollbox.js.map +1 -1
  125. package/dist/release.d.ts +1 -0
  126. package/dist/release.d.ts.map +1 -1
  127. package/dist/release.js +16 -9
  128. package/dist/release.js.map +1 -1
  129. package/dist/state.d.ts +27 -1
  130. package/dist/state.d.ts.map +1 -1
  131. package/dist/state.js +6 -0
  132. package/dist/state.js.map +1 -1
  133. package/dist/theme.d.ts +6 -19
  134. package/dist/theme.d.ts.map +1 -1
  135. package/dist/theme.js +76 -45
  136. package/dist/theme.js.map +1 -1
  137. package/dist/themes/aura.json +69 -0
  138. package/dist/themes/ayu.json +80 -0
  139. package/dist/themes/catppuccin-frappe.json +233 -0
  140. package/dist/themes/catppuccin-macchiato.json +233 -0
  141. package/dist/themes/catppuccin.json +112 -0
  142. package/dist/themes/cobalt2.json +228 -0
  143. package/dist/themes/cursor.json +249 -0
  144. package/dist/themes/dracula.json +219 -0
  145. package/dist/themes/everforest.json +241 -0
  146. package/dist/themes/flexoki.json +237 -0
  147. package/dist/themes/github-light.json +56 -0
  148. package/dist/themes/github.json +241 -0
  149. package/dist/themes/gruvbox.json +95 -0
  150. package/dist/themes/kanagawa.json +77 -0
  151. package/dist/themes/lucent-orng.json +227 -0
  152. package/dist/themes/material.json +235 -0
  153. package/dist/themes/matrix.json +77 -0
  154. package/dist/themes/mercury.json +245 -0
  155. package/dist/themes/monokai.json +221 -0
  156. package/dist/themes/nightowl.json +221 -0
  157. package/dist/themes/nord.json +223 -0
  158. package/dist/themes/one-dark.json +84 -0
  159. package/dist/themes/opencode-light.json +62 -0
  160. package/dist/themes/opencode.json +245 -0
  161. package/dist/themes/orng.json +245 -0
  162. package/dist/themes/palenight.json +222 -0
  163. package/dist/themes/rosepine.json +234 -0
  164. package/dist/themes/solarized.json +223 -0
  165. package/dist/themes/synthwave84.json +226 -0
  166. package/dist/themes/termcast.json +226 -0
  167. package/dist/themes/tokyonight.json +243 -0
  168. package/dist/themes/vercel.json +255 -0
  169. package/dist/themes/vesper.json +218 -0
  170. package/dist/themes/zenburn.json +223 -0
  171. package/dist/themes.d.ts +57 -0
  172. package/dist/themes.d.ts.map +1 -0
  173. package/dist/themes.js +181 -0
  174. package/dist/themes.js.map +1 -0
  175. package/dist/utils/run-command.d.ts +2 -1
  176. package/dist/utils/run-command.d.ts.map +1 -1
  177. package/dist/utils/run-command.js +20 -10
  178. package/dist/utils/run-command.js.map +1 -1
  179. package/dist/utils.d.ts +2 -1
  180. package/dist/utils.d.ts.map +1 -1
  181. package/dist/utils.js +90 -17
  182. package/dist/utils.js.map +1 -1
  183. package/dist/watcher.d.ts +3 -0
  184. package/dist/watcher.d.ts.map +1 -0
  185. package/dist/watcher.js +16 -0
  186. package/dist/watcher.js.map +1 -0
  187. package/package.json +16 -10
  188. package/src/apis/cache.tsx +5 -44
  189. package/src/apis/hud.tsx +17 -62
  190. package/src/apis/localstorage.tsx +3 -32
  191. package/src/apis/toast.tsx +91 -275
  192. package/src/build.test.tsx +10 -0
  193. package/src/build.tsx +61 -1
  194. package/src/cli.tsx +365 -103
  195. package/src/colors.tsx +1 -0
  196. package/src/compile.tsx +21 -29
  197. package/src/compile.vitest.tsx +300 -0
  198. package/src/components/actions.tsx +64 -45
  199. package/src/components/animation-tick.tsx +85 -0
  200. package/src/components/detail.tsx +31 -35
  201. package/src/components/dropdown.tsx +32 -21
  202. package/src/components/extension-preferences.tsx +14 -10
  203. package/src/components/footer.tsx +241 -0
  204. package/src/components/form/file-autocomplete.tsx +80 -60
  205. package/src/components/form/file-picker.tsx +37 -25
  206. package/src/components/form/index.tsx +45 -41
  207. package/src/components/form/with-left-border.tsx +4 -14
  208. package/src/components/list.tsx +181 -121
  209. package/src/components/loading-bar.tsx +5 -25
  210. package/src/components/loading-text.tsx +4 -23
  211. package/src/components/theme-picker.tsx +57 -0
  212. package/src/descendants.tsx +98 -9
  213. package/src/examples/actions-dialog-layout.vitest.tsx +112 -0
  214. package/src/examples/file-autocomplete.vitest.tsx +131 -122
  215. package/src/examples/form-basic.vitest.tsx +463 -644
  216. package/src/examples/form-dropdown.vitest.tsx +553 -571
  217. package/src/examples/form-scroll.vitest.tsx +112 -102
  218. package/src/examples/form-tagpicker.vitest.tsx +364 -338
  219. package/src/examples/internal/descendants-rerender.tsx +273 -0
  220. package/src/examples/internal/descendants-rerender.vitest.tsx +194 -0
  221. package/src/examples/internal/simple-dialog.tsx +4 -4
  222. package/src/examples/internal/simple-scrollbox.tsx +2 -2
  223. package/src/examples/internal/simple-scrollbox.vitest.tsx +43 -31
  224. package/src/examples/list-detail-metadata.vitest.tsx +34 -30
  225. package/src/examples/list-dropdown-default.vitest.tsx +84 -72
  226. package/src/examples/list-empty-view.vitest.tsx +93 -0
  227. package/src/examples/list-fetch-data.vitest.tsx +36 -30
  228. package/src/examples/list-scrollbox.vitest.tsx +59 -39
  229. package/src/examples/list-with-detail.vitest.tsx +339 -314
  230. package/src/examples/list-with-dropdown.tsx +1 -0
  231. package/src/examples/list-with-dropdown.vitest.tsx +176 -150
  232. package/src/examples/list-with-sections.vitest.tsx +289 -270
  233. package/src/examples/list-with-toast.vitest.tsx +44 -44
  234. package/src/examples/miscellaneous.tsx +10 -0
  235. package/src/examples/simple-file-picker.vitest.tsx +90 -86
  236. package/src/examples/simple-grid.vitest.tsx +275 -249
  237. package/src/examples/simple-navigation.vitest.tsx +192 -168
  238. package/src/examples/store.vitest.tsx +6 -4
  239. package/src/examples/swift-extension.vitest.tsx +31 -19
  240. package/src/examples/synonyms.vitest.tsx +93 -83
  241. package/src/examples/toast-action.tsx +160 -0
  242. package/src/examples/toast-action.vitest.tsx +404 -0
  243. package/src/examples/toast-variations.tsx +58 -57
  244. package/src/examples/toast-variations.vitest.tsx +186 -166
  245. package/src/extensions/dev.tsx +74 -33
  246. package/src/extensions/dev.vitest.tsx +162 -69
  247. package/src/extensions/home.tsx +5 -6
  248. package/src/extensions/react-refresh-init.tsx +59 -0
  249. package/src/internal/date-picker-widget.tsx +1 -1
  250. package/src/internal/dialog.tsx +59 -83
  251. package/src/internal/navigation.tsx +37 -4
  252. package/src/internal/providers.tsx +27 -315
  253. package/src/internal/scrollbox.tsx +1 -0
  254. package/src/release.tsx +16 -10
  255. package/src/state.tsx +36 -3
  256. package/src/theme.tsx +82 -51
  257. package/src/themes/aura.json +69 -0
  258. package/src/themes/ayu.json +80 -0
  259. package/src/themes/catppuccin-frappe.json +233 -0
  260. package/src/themes/catppuccin-macchiato.json +233 -0
  261. package/src/themes/catppuccin.json +112 -0
  262. package/src/themes/cobalt2.json +228 -0
  263. package/src/themes/cursor.json +249 -0
  264. package/src/themes/dracula.json +219 -0
  265. package/src/themes/everforest.json +241 -0
  266. package/src/themes/flexoki.json +237 -0
  267. package/src/themes/github-light.json +56 -0
  268. package/src/themes/github.json +241 -0
  269. package/src/themes/gruvbox.json +95 -0
  270. package/src/themes/kanagawa.json +77 -0
  271. package/src/themes/lucent-orng.json +227 -0
  272. package/src/themes/material.json +235 -0
  273. package/src/themes/matrix.json +77 -0
  274. package/src/themes/mercury.json +252 -0
  275. package/src/themes/monokai.json +221 -0
  276. package/src/themes/nightowl.json +221 -0
  277. package/src/themes/nord.json +223 -0
  278. package/src/themes/one-dark.json +84 -0
  279. package/src/themes/opencode-light.json +62 -0
  280. package/src/themes/opencode.json +245 -0
  281. package/src/themes/orng.json +245 -0
  282. package/src/themes/palenight.json +222 -0
  283. package/src/themes/rosepine.json +234 -0
  284. package/src/themes/solarized.json +223 -0
  285. package/src/themes/synthwave84.json +226 -0
  286. package/src/themes/termcast.json +227 -0
  287. package/src/themes/tokyonight.json +243 -0
  288. package/src/themes/vercel.json +255 -0
  289. package/src/themes/vesper.json +218 -0
  290. package/src/themes/zenburn.json +223 -0
  291. package/src/themes.ts +291 -0
  292. package/src/utils/run-command.tsx +23 -12
  293. package/src/utils.tsx +115 -18
  294. package/src/watcher.tsx +19 -0
@@ -1,13 +1,20 @@
1
- import { test, expect, beforeEach, afterEach } from 'vitest'
1
+ import { test, expect, beforeEach, afterEach, describe } from 'vitest'
2
2
  import { launchTerminal, Session } from 'tuistory/src'
3
3
  import { execSync } from 'node:child_process'
4
4
  import fs from 'node:fs'
5
5
  import path from 'node:path'
6
+ import os from 'node:os'
7
+
8
+ // Skip all tests on non-macOS platforms (Swift is only available on macOS)
9
+ const isLinux = os.platform() === 'linux'
6
10
 
7
11
  const fixtureDir = path.resolve(__dirname, '../../fixtures/swift-extension')
8
12
 
9
13
  // Find binary - check debug first, then release
10
- function findSwiftBinary(): string {
14
+ function findSwiftBinary(): string | null {
15
+ if (isLinux) {
16
+ return null
17
+ }
11
18
  const debugPath = path.join(fixtureDir, 'swift/.build/debug/SwiftAPI')
12
19
  const releasePath = path.join(fixtureDir, 'swift/.build/release/SwiftAPI')
13
20
  if (fs.existsSync(debugPath)) {
@@ -21,7 +28,7 @@ function findSwiftBinary(): string {
21
28
 
22
29
  const swiftBinary = findSwiftBinary()
23
30
 
24
- test('swift binary returns items correctly', () => {
31
+ test.skipIf(isLinux)('swift binary returns items correctly', () => {
25
32
  const stdout = execSync(`${swiftBinary} getItems`, { encoding: 'utf-8' })
26
33
  expect(JSON.parse(stdout)).toMatchInlineSnapshot(`
27
34
  [
@@ -44,7 +51,7 @@ test('swift binary returns items correctly', () => {
44
51
  `)
45
52
  })
46
53
 
47
- test('swift binary greet function works', () => {
54
+ test.skipIf(isLinux)('swift binary greet function works', () => {
48
55
  const stdout = execSync(`${swiftBinary} greet '"World"'`, { encoding: 'utf-8' })
49
56
  expect(JSON.parse(stdout)).toMatchInlineSnapshot(`"Hello, World! Greetings from Swift."`)
50
57
  })
@@ -52,6 +59,7 @@ test('swift binary greet function works', () => {
52
59
  let session: Session
53
60
 
54
61
  beforeEach(async () => {
62
+ if (isLinux) return
55
63
  session = await launchTerminal({
56
64
  command: 'bun',
57
65
  args: ['src/cli.tsx', 'dev', fixtureDir],
@@ -65,7 +73,7 @@ afterEach(() => {
65
73
  session?.close()
66
74
  })
67
75
 
68
- test('swift extension dev mode shows command list', async () => {
76
+ test.skipIf(isLinux)('swift extension dev mode shows command list', async () => {
69
77
  // Wait for command list to appear
70
78
  const commandList = await session.text({
71
79
  waitFor: (text) => /Swift List/i.test(text),
@@ -76,13 +84,14 @@ test('swift extension dev mode shows command list', async () => {
76
84
  "
77
85
 
78
86
 
79
- Swift Test Extension ───────────────────────────────────────────
87
+ Swift Test Extension ───────────────────────────────────────────
88
+
89
+ > Search commands...
80
90
 
81
- Search commands...
91
+ Commands
92
+ ›List Items Displays a simple list with some items view
93
+ Swift List Displays a list of items returned by a Swift f view
82
94
 
83
- Commands
84
- ›List Items Displays a simple list with some items view
85
- Swift List Displays a list of items returned by a Swift fu view
86
95
 
87
96
 
88
97
 
@@ -95,12 +104,13 @@ test('swift extension dev mode shows command list', async () => {
95
104
 
96
105
 
97
106
 
107
+ ↵ run command ↑↓ navigate ^k actions
98
108
 
99
- ↵ run command ↑↓ navigate ^k actions"
109
+ "
100
110
  `)
101
111
  }, 60000)
102
112
 
103
- test('swift extension runs Swift List command and shows items', async () => {
113
+ test.skipIf(isLinux)('swift extension runs Swift List command and shows items', async () => {
104
114
  // Wait for command list to appear
105
115
  await session.text({
106
116
  waitFor: (text) => /Swift List/i.test(text),
@@ -123,16 +133,18 @@ test('swift extension runs Swift List command and shows items', async () => {
123
133
  "
124
134
 
125
135
 
126
- Swift Items ────────────────────────────────────────────────────
136
+ Swift Items ────────────────────────────────────────────────────
137
+
138
+ > Search...
127
139
 
128
- Search...
140
+ Items from Swift
141
+ ›Swift Item One Generated by Swift
142
+ Swift Item Two From native code
143
+ Swift Item Three Fast and safe
129
144
 
130
- Items from Swift
131
- ›Swift Item One Generated by Swift
132
- Swift Item Two From native code
133
- Swift Item Three Fast and safe
134
145
 
135
146
 
147
+ ↑↓ navigate ^k actions
136
148
 
137
149
 
138
150
 
@@ -143,6 +155,6 @@ test('swift extension runs Swift List command and shows items', async () => {
143
155
 
144
156
 
145
157
 
146
- ↑↓ navigate ^k actions"
158
+ "
147
159
  `)
148
160
  }, 60000)
@@ -1,13 +1,20 @@
1
1
  import { test, expect, beforeEach, afterEach, beforeAll } from 'vitest'
2
2
  import { launchTerminal, Session } from 'tuistory/src'
3
- import { execSync } from 'node:child_process'
3
+ import { spawnSync } from 'node:child_process'
4
4
  import path from 'node:path'
5
5
 
6
6
  const extensionDir = path.resolve(__dirname, '../../extensions/synonyms')
7
7
 
8
8
  // Install dependencies before running tests
9
9
  beforeAll(() => {
10
- execSync('bun install', { cwd: extensionDir, stdio: 'inherit' })
10
+ // Use spawnSync without shell to avoid /bin/sh issues on CI
11
+ const result = spawnSync('bun', ['install'], {
12
+ cwd: extensionDir,
13
+ stdio: 'inherit',
14
+ })
15
+ if (result.status !== 0) {
16
+ throw new Error(`bun install failed with exit code ${result.status}`)
17
+ }
11
18
  }, 60000)
12
19
 
13
20
  let session: Session
@@ -42,33 +49,34 @@ test('synonyms extension shows preferences form on first launch', async () => {
42
49
  "
43
50
 
44
51
 
45
- ◇ LLM Provider ▀
46
- │ Select...
47
-
48
- ○ Raycast AI
49
- ○ OpenAI
50
- │ ○ OpenAI Compatible
51
- │ ○ Anthropic
52
- │ ○ Fireworks.ai
53
-
54
- Select the LLM provider you want to use
55
-
56
- OpenAI API Key
57
-
58
- API Key for OpenAI
59
-
60
- OpenAI Model
61
- gpt-4.1-mini
62
-
63
- Model name for OpenAI
64
-
65
- OpenAI Compatible URL
66
-
67
-
68
- │ Base URL for OpenAI compatible provider
69
-
70
-
71
- ctrl ↵ submit tab navigate ^k actions"
52
+
53
+
54
+ ◇ LLM Provider ▀
55
+ Select...
56
+
57
+ │ ○ Raycast AI
58
+ │ ○ OpenAI
59
+ │ ○ OpenAI Compatible
60
+ ○ Anthropic
61
+ Fireworks.ai
62
+
63
+ Select the LLM provider you want to use
64
+
65
+ OpenAI API Key
66
+
67
+ API Key for OpenAI
68
+
69
+ ◇ OpenAI Model
70
+ gpt-4.1-mini
71
+
72
+ Model name for OpenAI
73
+
74
+ ◇ OpenAI Compatible URL
75
+
76
+
77
+ ctrl ↵ submit tab navigate ^k actions powered by termcast
78
+
79
+ "
72
80
  `)
73
81
  }, 60000)
74
82
 
@@ -91,33 +99,34 @@ test('synonyms extension preferences form can be navigated', async () => {
91
99
  "
92
100
 
93
101
 
94
- ◇ LLM Provider ▀
95
- │ Select...
96
-
97
- ○ Raycast AI
98
- ○ OpenAI
99
- │ ○ OpenAI Compatible
100
- │ ○ Anthropic
101
- │ ○ Fireworks.ai
102
-
103
- Select the LLM provider you want to use
104
-
105
- OpenAI API Key
106
-
107
- API Key for OpenAI
108
-
109
- OpenAI Model
110
- gpt-4.1-mini
111
-
112
- Model name for OpenAI
113
-
114
- OpenAI Compatible URL
115
-
116
-
117
- │ Base URL for OpenAI compatible provider
118
-
119
-
120
- ctrl ↵ submit tab navigate ^k actions"
102
+
103
+
104
+ ◇ LLM Provider ▀
105
+ Select...
106
+
107
+ │ ○ Raycast AI
108
+ │ ○ OpenAI
109
+ │ ○ OpenAI Compatible
110
+ ○ Anthropic
111
+ Fireworks.ai
112
+
113
+ Select the LLM provider you want to use
114
+
115
+ OpenAI API Key
116
+
117
+ API Key for OpenAI
118
+
119
+ ◇ OpenAI Model
120
+ gpt-4.1-mini
121
+
122
+ Model name for OpenAI
123
+
124
+ ◇ OpenAI Compatible URL
125
+
126
+
127
+ ctrl ↵ submit tab navigate ^k actions powered by termcast
128
+
129
+ "
121
130
  `)
122
131
 
123
132
  // Press tab to move to next field
@@ -128,32 +137,33 @@ test('synonyms extension preferences form can be navigated', async () => {
128
137
  "
129
138
 
130
139
 
131
- ◆ LLM Provider ▀
132
- │ Select...
133
-
134
- │› ○ Raycast AI
135
- ○ OpenAI
136
- OpenAI Compatible
137
- │ ○ Anthropic
138
- │ ○ Fireworks.ai
139
-
140
- Select the LLM provider you want to use
141
-
142
- OpenAI API Key
143
-
144
- API Key for OpenAI
145
-
146
- OpenAI Model
147
- gpt-4.1-mini
148
-
149
- Model name for OpenAI
150
-
151
- OpenAI Compatible URL
152
-
153
-
154
- │ Base URL for OpenAI compatible provider
155
-
156
-
157
- ctrl ↵ submit tab navigate ^k actions"
140
+
141
+
142
+ ◆ LLM Provider ▀
143
+ │ Select...
144
+
145
+ │› Raycast AI
146
+ │ ○ OpenAI
147
+ │ ○ OpenAI Compatible
148
+ ○ Anthropic
149
+ Fireworks.ai
150
+
151
+ Select the LLM provider you want to use
152
+
153
+ OpenAI API Key
154
+
155
+ API Key for OpenAI
156
+
157
+ ◇ OpenAI Model
158
+ gpt-4.1-mini
159
+
160
+ Model name for OpenAI
161
+
162
+ ◇ OpenAI Compatible URL
163
+
164
+
165
+ ctrl ↵ submit tab navigate ^k actions powered by termcast
166
+
167
+ "
158
168
  `)
159
169
  }, 60000)
@@ -0,0 +1,160 @@
1
+ import React from 'react'
2
+ import {
3
+ List,
4
+ renderWithProviders,
5
+ showToast,
6
+ Toast,
7
+ Form,
8
+ ActionPanel,
9
+ Action,
10
+ } from 'termcast'
11
+ import { useNavigation } from 'termcast/src/internal/navigation'
12
+
13
+ function DetailView({ name }: { name: string }): any {
14
+ return (
15
+ <List navigationTitle="Form Submitted">
16
+ <List.Item id="success" title={`Welcome, ${name}!`} subtitle="Form submission successful" />
17
+ </List>
18
+ )
19
+ }
20
+
21
+ function FormWithToast(): any {
22
+ const { push } = useNavigation()
23
+
24
+ const handleSubmit = async (values: { name: string }) => {
25
+ await showToast({
26
+ style: Toast.Style.Success,
27
+ title: 'Form Submitted',
28
+ message: `Hello, ${values.name}!`,
29
+ primaryAction: {
30
+ title: 'View Details',
31
+ onAction: async () => {
32
+ push(<DetailView name={values.name} />)
33
+ },
34
+ },
35
+ })
36
+ }
37
+
38
+ return (
39
+ <Form
40
+ navigationTitle="Form with Toast"
41
+ actions={
42
+ <ActionPanel>
43
+ <Action.SubmitForm title="Submit" onSubmit={handleSubmit} />
44
+ </ActionPanel>
45
+ }
46
+ >
47
+ <Form.TextField id="name" title="Name" placeholder="Enter your name" />
48
+ </Form>
49
+ )
50
+ }
51
+
52
+ function FormWithDelayedToastAction(): any {
53
+ const handleSubmit = async (values: { name: string }) => {
54
+ // Simulates tuitube pattern: show toast first, then set primaryAction later
55
+ const toast = await showToast({
56
+ style: Toast.Style.Animated,
57
+ title: 'Processing',
58
+ message: 'Please wait...',
59
+ })
60
+
61
+ // Simulate async operation completing
62
+ await new Promise((r) => setTimeout(r, 500))
63
+
64
+ // Set primaryAction AFTER toast is shown (like tuitube does in on("close") callback)
65
+ toast.style = Toast.Style.Success
66
+ toast.title = 'Done'
67
+ toast.message = `Hello, ${values.name}!`
68
+ toast.primaryAction = {
69
+ title: 'Open',
70
+ onAction: async () => {
71
+ await showToast({
72
+ style: Toast.Style.Success,
73
+ title: 'Opened!',
74
+ message: 'Action triggered successfully',
75
+ })
76
+ },
77
+ }
78
+ }
79
+
80
+ return (
81
+ <Form
82
+ navigationTitle="Delayed Toast Action"
83
+ actions={
84
+ <ActionPanel>
85
+ <Action.SubmitForm title="Submit" onSubmit={handleSubmit} />
86
+ </ActionPanel>
87
+ }
88
+ >
89
+ <Form.TextField id="name" title="Name" placeholder="Enter your name" />
90
+ </Form>
91
+ )
92
+ }
93
+
94
+ function ToastActionExample(): any {
95
+ const { push } = useNavigation()
96
+
97
+ return (
98
+ <List navigationTitle="Toast Action Test">
99
+ <List.Item
100
+ id="show-toast"
101
+ title="Show Toast with Action"
102
+ actions={
103
+ <ActionPanel>
104
+ <Action
105
+ title="Show Toast"
106
+ onAction={async () => {
107
+ await showToast({
108
+ style: Toast.Style.Success,
109
+ title: 'File Deleted',
110
+ message: 'document.pdf was moved to trash',
111
+ primaryAction: {
112
+ title: 'Undo',
113
+ onAction: async () => {
114
+ await showToast({
115
+ style: Toast.Style.Success,
116
+ title: 'Undone',
117
+ message: 'File restored',
118
+ })
119
+ },
120
+ },
121
+ })
122
+ }}
123
+ />
124
+ </ActionPanel>
125
+ }
126
+ />
127
+ <List.Item
128
+ id="form-toast"
129
+ title="Form with Toast"
130
+ actions={
131
+ <ActionPanel>
132
+ <Action
133
+ title="Open Form"
134
+ onAction={() => {
135
+ push(<FormWithToast />)
136
+ }}
137
+ />
138
+ </ActionPanel>
139
+ }
140
+ />
141
+ <List.Item
142
+ id="delayed-toast"
143
+ title="Form with Delayed Toast Action"
144
+ actions={
145
+ <ActionPanel>
146
+ <Action
147
+ title="Open Form"
148
+ onAction={() => {
149
+ push(<FormWithDelayedToastAction />)
150
+ }}
151
+ />
152
+ </ActionPanel>
153
+ }
154
+ />
155
+ <List.Item id="other" title="Other Item" />
156
+ </List>
157
+ )
158
+ }
159
+
160
+ await renderWithProviders(<ToastActionExample />)