@tanstack/cta-engine 0.10.0-alpha.14 → 0.10.0-alpha.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (291) hide show
  1. package/dist/add-ons.js +8 -73
  2. package/dist/{add.js → add-to-app.js} +19 -19
  3. package/dist/config-file.js +6 -3
  4. package/dist/constants.js +0 -2
  5. package/dist/create-app.js +76 -460
  6. package/dist/environment.js +11 -26
  7. package/dist/file-helpers.js +59 -0
  8. package/dist/frameworks.js +78 -0
  9. package/dist/index.js +10 -1
  10. package/dist/integrations/git.js +4 -0
  11. package/dist/integrations/shadcn.js +27 -0
  12. package/dist/package-json.js +46 -0
  13. package/dist/package-manager.js +51 -6
  14. package/dist/template-file.js +108 -0
  15. package/dist/types/add-ons.d.ts +2 -6
  16. package/dist/types/add-to-app.d.ts +4 -0
  17. package/dist/types/config-file.d.ts +3 -2
  18. package/dist/types/constants.d.ts +0 -3
  19. package/dist/types/file-helpers.d.ts +5 -0
  20. package/dist/types/frameworks.d.ts +5 -0
  21. package/dist/types/index.d.ts +13 -1
  22. package/dist/types/integrations/git.d.ts +2 -0
  23. package/dist/types/integrations/shadcn.d.ts +2 -0
  24. package/dist/types/package-json.d.ts +2 -0
  25. package/dist/types/package-manager.d.ts +14 -1
  26. package/dist/types/template-file.d.ts +2 -0
  27. package/dist/types/types.d.ts +86 -64
  28. package/dist/types/utils.d.ts +5 -0
  29. package/dist/utils.js +9 -0
  30. package/package.json +3 -13
  31. package/src/add-ons.ts +11 -104
  32. package/src/{add.ts → add-to-app.ts} +29 -35
  33. package/src/config-file.ts +12 -6
  34. package/src/constants.ts +0 -5
  35. package/src/create-app.ts +126 -727
  36. package/src/environment.ts +12 -27
  37. package/src/file-helpers.ts +73 -0
  38. package/src/frameworks.ts +114 -0
  39. package/src/index.ts +42 -1
  40. package/src/integrations/git.ts +7 -0
  41. package/src/integrations/shadcn.ts +44 -0
  42. package/src/package-json.ts +62 -0
  43. package/src/package-manager.ts +80 -9
  44. package/src/template-file.ts +146 -0
  45. package/src/types.ts +101 -70
  46. package/src/utils.ts +17 -0
  47. package/tests/file-helper.test.ts +37 -0
  48. package/tests/package-manager.test.ts +154 -0
  49. package/dist/cli.js +0 -126
  50. package/dist/custom-add-on.js +0 -254
  51. package/dist/file-helper.js +0 -18
  52. package/dist/mcp.js +0 -229
  53. package/dist/options.js +0 -328
  54. package/dist/templates.js +0 -6
  55. package/dist/toolchain.js +0 -6
  56. package/dist/types/add.d.ts +0 -3
  57. package/dist/types/cli.d.ts +0 -6
  58. package/dist/types/custom-add-on.d.ts +0 -3
  59. package/dist/types/file-helper.d.ts +0 -2
  60. package/dist/types/mcp.d.ts +0 -7
  61. package/dist/types/options.d.ts +0 -6
  62. package/dist/types/templates.d.ts +0 -1
  63. package/dist/types/toolchain.d.ts +0 -3
  64. package/src/cli.ts +0 -189
  65. package/src/custom-add-on.ts +0 -325
  66. package/src/file-helper.ts +0 -20
  67. package/src/mcp.ts +0 -302
  68. package/src/options.ts +0 -399
  69. package/src/templates.ts +0 -7
  70. package/src/toolchain.ts +0 -7
  71. package/templates/react/add-on/clerk/README.md +0 -3
  72. package/templates/react/add-on/clerk/assets/_dot_env.local.append +0 -2
  73. package/templates/react/add-on/clerk/assets/src/integrations/clerk/header-user.tsx +0 -19
  74. package/templates/react/add-on/clerk/assets/src/integrations/clerk/provider.tsx +0 -18
  75. package/templates/react/add-on/clerk/assets/src/routes/demo.clerk.tsx +0 -20
  76. package/templates/react/add-on/clerk/info.json +0 -13
  77. package/templates/react/add-on/clerk/package.json +0 -5
  78. package/templates/react/add-on/convex/README.md +0 -4
  79. package/templates/react/add-on/convex/assets/_dot_cursorrules.append +0 -93
  80. package/templates/react/add-on/convex/assets/_dot_env.local.append +0 -3
  81. package/templates/react/add-on/convex/assets/convex/products.ts +0 -8
  82. package/templates/react/add-on/convex/assets/convex/schema.ts +0 -10
  83. package/templates/react/add-on/convex/assets/src/integrations/convex/provider.tsx +0 -20
  84. package/templates/react/add-on/convex/assets/src/routes/demo.convex.tsx +0 -33
  85. package/templates/react/add-on/convex/info.json +0 -13
  86. package/templates/react/add-on/convex/package.json +0 -6
  87. package/templates/react/add-on/form/assets/src/components/demo.FormComponents.tsx.ejs +0 -300
  88. package/templates/react/add-on/form/assets/src/hooks/demo.form-context.ts +0 -4
  89. package/templates/react/add-on/form/assets/src/hooks/demo.form.ts +0 -22
  90. package/templates/react/add-on/form/assets/src/routes/demo.form.address.tsx.ejs +0 -213
  91. package/templates/react/add-on/form/assets/src/routes/demo.form.simple.tsx.ejs +0 -77
  92. package/templates/react/add-on/form/info.json +0 -26
  93. package/templates/react/add-on/form/package.json +0 -6
  94. package/templates/react/add-on/module-federation/assets/module-federation.config.js.ejs +0 -31
  95. package/templates/react/add-on/module-federation/assets/src/demo-mf-component.tsx +0 -3
  96. package/templates/react/add-on/module-federation/assets/src/demo-mf-self-contained.tsx +0 -11
  97. package/templates/react/add-on/module-federation/info.json +0 -7
  98. package/templates/react/add-on/module-federation/package.json +0 -5
  99. package/templates/react/add-on/netlify/README.md +0 -11
  100. package/templates/react/add-on/netlify/info.json +0 -7
  101. package/templates/react/add-on/sentry/assets/_dot_cursorrules.append +0 -22
  102. package/templates/react/add-on/sentry/assets/_dot_env.local.append +0 -2
  103. package/templates/react/add-on/sentry/assets/src/app/global-middleware.ts +0 -25
  104. package/templates/react/add-on/sentry/assets/src/routes/demo.sentry.testing.tsx +0 -480
  105. package/templates/react/add-on/sentry/info.json +0 -14
  106. package/templates/react/add-on/sentry/package.json +0 -7
  107. package/templates/react/add-on/shadcn/README.md +0 -7
  108. package/templates/react/add-on/shadcn/assets/_dot_cursorrules.append +0 -7
  109. package/templates/react/add-on/shadcn/assets/components.json +0 -21
  110. package/templates/react/add-on/shadcn/assets/src/lib/utils.ts +0 -6
  111. package/templates/react/add-on/shadcn/assets/src/styles.css +0 -138
  112. package/templates/react/add-on/shadcn/info.json +0 -7
  113. package/templates/react/add-on/shadcn/package.json +0 -9
  114. package/templates/react/add-on/start/assets/_dot_gitignore.append +0 -2
  115. package/templates/react/add-on/start/assets/app.config.ts.ejs +0 -19
  116. package/templates/react/add-on/start/assets/src/api.ts +0 -6
  117. package/templates/react/add-on/start/assets/src/client.tsx +0 -8
  118. package/templates/react/add-on/start/assets/src/router.tsx.ejs +0 -77
  119. package/templates/react/add-on/start/assets/src/routes/api.demo-names.ts +0 -11
  120. package/templates/react/add-on/start/assets/src/routes/demo.start.api-request.tsx.ejs +0 -33
  121. package/templates/react/add-on/start/assets/src/routes/demo.start.server-funcs.tsx +0 -50
  122. package/templates/react/add-on/start/assets/src/ssr.tsx +0 -12
  123. package/templates/react/add-on/start/info.json +0 -18
  124. package/templates/react/add-on/start/package.json +0 -13
  125. package/templates/react/add-on/store/assets/src/lib/demo-store.ts +0 -13
  126. package/templates/react/add-on/store/assets/src/routes/demo.store.tsx.ejs +0 -75
  127. package/templates/react/add-on/store/info.json +0 -13
  128. package/templates/react/add-on/store/package.json +0 -6
  129. package/templates/react/add-on/tRPC/assets/src/integrations/trpc/init.ts +0 -9
  130. package/templates/react/add-on/tRPC/assets/src/integrations/trpc/react.ts +0 -4
  131. package/templates/react/add-on/tRPC/assets/src/integrations/trpc/router.ts +0 -18
  132. package/templates/react/add-on/tRPC/assets/src/routes/api.trpc.$.tsx +0 -16
  133. package/templates/react/add-on/tRPC/info.json +0 -9
  134. package/templates/react/add-on/tRPC/package.json +0 -9
  135. package/templates/react/add-on/table/assets/src/data/demo-table-data.ts +0 -50
  136. package/templates/react/add-on/table/assets/src/routes/demo.table.tsx.ejs +0 -373
  137. package/templates/react/add-on/table/info.json +0 -13
  138. package/templates/react/add-on/table/package.json +0 -7
  139. package/templates/react/add-on/tanstack-query/assets/src/integrations/tanstack-query/layout.tsx +0 -5
  140. package/templates/react/add-on/tanstack-query/assets/src/integrations/tanstack-query/root-provider.tsx.ejs +0 -70
  141. package/templates/react/add-on/tanstack-query/assets/src/routes/demo.tanstack-query.tsx.ejs +0 -53
  142. package/templates/react/add-on/tanstack-query/info.json +0 -13
  143. package/templates/react/add-on/tanstack-query/package.json +0 -6
  144. package/templates/react/base/README.md.ejs +0 -558
  145. package/templates/react/base/_dot_gitignore +0 -5
  146. package/templates/react/base/_dot_vscode/settings.biome.json +0 -38
  147. package/templates/react/base/_dot_vscode/settings.json +0 -11
  148. package/templates/react/base/index.html.ejs +0 -20
  149. package/templates/react/base/package.biome.json +0 -10
  150. package/templates/react/base/package.eslintprettier.json +0 -11
  151. package/templates/react/base/package.json +0 -29
  152. package/templates/react/base/package.ts.json +0 -7
  153. package/templates/react/base/package.tw.json +0 -6
  154. package/templates/react/base/public/favicon.ico +0 -0
  155. package/templates/react/base/public/logo192.png +0 -0
  156. package/templates/react/base/public/logo512.png +0 -0
  157. package/templates/react/base/public/manifest.json +0 -25
  158. package/templates/react/base/public/robots.txt +0 -3
  159. package/templates/react/base/src/App.css +0 -38
  160. package/templates/react/base/src/App.test.tsx.ejs +0 -10
  161. package/templates/react/base/src/App.tsx.ejs +0 -74
  162. package/templates/react/base/src/components/Header.tsx.ejs +0 -27
  163. package/templates/react/base/src/logo.svg +0 -44
  164. package/templates/react/base/src/reportWebVitals.ts.ejs +0 -28
  165. package/templates/react/base/src/styles.css.ejs +0 -15
  166. package/templates/react/base/toolchain/.prettierignore +0 -3
  167. package/templates/react/base/toolchain/biome.json +0 -31
  168. package/templates/react/base/toolchain/eslint.config.js +0 -5
  169. package/templates/react/base/toolchain/prettier.config.js +0 -10
  170. package/templates/react/base/tsconfig.json.ejs +0 -29
  171. package/templates/react/base/vite.config.js.ejs +0 -23
  172. package/templates/react/code-router/src/main.tsx.ejs +0 -92
  173. package/templates/react/example/tanchat/README.md +0 -37
  174. package/templates/react/example/tanchat/assets/_dot_env.local.append +0 -2
  175. package/templates/react/example/tanchat/assets/public/example-guitar-flowers.jpg +0 -0
  176. package/templates/react/example/tanchat/assets/public/example-guitar-motherboard.jpg +0 -0
  177. package/templates/react/example/tanchat/assets/public/example-guitar-racing.jpg +0 -0
  178. package/templates/react/example/tanchat/assets/public/example-guitar-steamer-trunk.jpg +0 -0
  179. package/templates/react/example/tanchat/assets/public/example-guitar-superhero.jpg +0 -0
  180. package/templates/react/example/tanchat/assets/public/example-guitar-traveling.jpg +0 -0
  181. package/templates/react/example/tanchat/assets/public/example-guitar-video-games.jpg +0 -0
  182. package/templates/react/example/tanchat/assets/src/components/example-AIAssistant.tsx +0 -173
  183. package/templates/react/example/tanchat/assets/src/components/example-GuitarRecommendation.tsx +0 -47
  184. package/templates/react/example/tanchat/assets/src/data/example-guitars.ts +0 -83
  185. package/templates/react/example/tanchat/assets/src/demo.index.css +0 -220
  186. package/templates/react/example/tanchat/assets/src/integrations/tanchat/header-user.tsx +0 -5
  187. package/templates/react/example/tanchat/assets/src/routes/example.chat.tsx +0 -159
  188. package/templates/react/example/tanchat/assets/src/routes/example.guitars/$guitarId.tsx +0 -50
  189. package/templates/react/example/tanchat/assets/src/routes/example.guitars/index.tsx +0 -54
  190. package/templates/react/example/tanchat/assets/src/store/example-assistant.ts +0 -3
  191. package/templates/react/example/tanchat/assets/src/utils/demo.ai.ts +0 -62
  192. package/templates/react/example/tanchat/assets/src/utils/demo.tools.ts +0 -47
  193. package/templates/react/example/tanchat/info.json +0 -19
  194. package/templates/react/example/tanchat/package.json +0 -15
  195. package/templates/react/file-router/package.fr.json +0 -5
  196. package/templates/react/file-router/src/main.tsx.ejs +0 -55
  197. package/templates/react/file-router/src/routes/__root.tsx.ejs +0 -82
  198. package/templates/solid/add-on/form/assets/src/routes/demo.form.tsx.ejs +0 -352
  199. package/templates/solid/add-on/form/info.json +0 -13
  200. package/templates/solid/add-on/form/package.json +0 -5
  201. package/templates/solid/add-on/module-federation/assets/module-federation.config.js.ejs +0 -27
  202. package/templates/solid/add-on/module-federation/assets/src/demo-mf-component.tsx +0 -3
  203. package/templates/solid/add-on/module-federation/assets/src/demo-mf-self-contained.tsx +0 -9
  204. package/templates/solid/add-on/module-federation/info.json +0 -7
  205. package/templates/solid/add-on/module-federation/package.json +0 -5
  206. package/templates/solid/add-on/sentry/assets/_dot_cursorrules.append +0 -22
  207. package/templates/solid/add-on/sentry/assets/_dot_env.local.append +0 -2
  208. package/templates/solid/add-on/sentry/assets/src/routes/demo.sentry.bad-event-handler.tsx +0 -20
  209. package/templates/solid/add-on/sentry/info.json +0 -13
  210. package/templates/solid/add-on/sentry/package.json +0 -5
  211. package/templates/solid/add-on/solid-ui/README.md +0 -9
  212. package/templates/solid/add-on/solid-ui/assets/src/lib/utils.ts +0 -6
  213. package/templates/solid/add-on/solid-ui/assets/src/styles.css +0 -138
  214. package/templates/solid/add-on/solid-ui/assets/ui.config.json +0 -13
  215. package/templates/solid/add-on/solid-ui/info.json +0 -11
  216. package/templates/solid/add-on/solid-ui/package.json +0 -9
  217. package/templates/solid/add-on/start/assets/app.config.ts +0 -16
  218. package/templates/solid/add-on/start/assets/src/api.ts +0 -6
  219. package/templates/solid/add-on/start/assets/src/client.tsx +0 -7
  220. package/templates/solid/add-on/start/assets/src/router.tsx.ejs +0 -24
  221. package/templates/solid/add-on/start/assets/src/routes/demo.start.server-funcs.tsx +0 -49
  222. package/templates/solid/add-on/start/assets/src/ssr.tsx +0 -12
  223. package/templates/solid/add-on/start/info.json +0 -14
  224. package/templates/solid/add-on/start/package.json +0 -12
  225. package/templates/solid/add-on/store/assets/src/lib/demo-store.ts +0 -13
  226. package/templates/solid/add-on/store/assets/src/routes/demo.store.tsx.ejs +0 -77
  227. package/templates/solid/add-on/store/info.json +0 -13
  228. package/templates/solid/add-on/store/package.json +0 -6
  229. package/templates/solid/add-on/tanstack-query/assets/src/integrations/tanstack-query/header-user.tsx +0 -5
  230. package/templates/solid/add-on/tanstack-query/assets/src/integrations/tanstack-query/provider.tsx +0 -15
  231. package/templates/solid/add-on/tanstack-query/assets/src/routes/demo.tanstack-query.tsx +0 -30
  232. package/templates/solid/add-on/tanstack-query/info.json +0 -13
  233. package/templates/solid/add-on/tanstack-query/package.json +0 -6
  234. package/templates/solid/base/README.md.ejs +0 -215
  235. package/templates/solid/base/_dot_cursorrules.append +0 -35
  236. package/templates/solid/base/_dot_gitignore +0 -5
  237. package/templates/solid/base/_dot_vscode/settings.biome.json +0 -38
  238. package/templates/solid/base/_dot_vscode/settings.json +0 -11
  239. package/templates/solid/base/index.html.ejs +0 -20
  240. package/templates/solid/base/package.biome.json +0 -10
  241. package/templates/solid/base/package.eslintprettier.json +0 -11
  242. package/templates/solid/base/package.json +0 -22
  243. package/templates/solid/base/package.ts.json +0 -5
  244. package/templates/solid/base/package.tw.json +0 -6
  245. package/templates/solid/base/public/favicon.ico +0 -0
  246. package/templates/solid/base/public/logo192.png +0 -0
  247. package/templates/solid/base/public/logo512.png +0 -0
  248. package/templates/solid/base/public/manifest.json +0 -25
  249. package/templates/solid/base/public/robots.txt +0 -3
  250. package/templates/solid/base/src/App.css +0 -0
  251. package/templates/solid/base/src/App.tsx.ejs +0 -47
  252. package/templates/solid/base/src/components/Header.tsx.ejs +0 -26
  253. package/templates/solid/base/src/logo.svg +0 -120
  254. package/templates/solid/base/src/styles.css.ejs +0 -15
  255. package/templates/solid/base/toolchain/.prettierignore +0 -3
  256. package/templates/solid/base/toolchain/biome.json +0 -31
  257. package/templates/solid/base/toolchain/eslint.config.js +0 -5
  258. package/templates/solid/base/toolchain/prettier.config.js +0 -10
  259. package/templates/solid/base/tsconfig.json.ejs +0 -31
  260. package/templates/solid/base/vite.config.js.ejs +0 -22
  261. package/templates/solid/code-router/src/main.tsx.ejs +0 -71
  262. package/templates/solid/example/tanchat/README.md +0 -52
  263. package/templates/solid/example/tanchat/assets/ai-streaming-server/README.md +0 -110
  264. package/templates/solid/example/tanchat/assets/ai-streaming-server/_dot_env.example +0 -1
  265. package/templates/solid/example/tanchat/assets/ai-streaming-server/package.json +0 -26
  266. package/templates/solid/example/tanchat/assets/ai-streaming-server/src/index.ts +0 -102
  267. package/templates/solid/example/tanchat/assets/ai-streaming-server/tsconfig.json +0 -15
  268. package/templates/solid/example/tanchat/assets/src/components/demo.SettingsDialog.tsx +0 -149
  269. package/templates/solid/example/tanchat/assets/src/demo.index.css +0 -227
  270. package/templates/solid/example/tanchat/assets/src/lib/demo-store.ts +0 -13
  271. package/templates/solid/example/tanchat/assets/src/routes/example.chat.tsx +0 -435
  272. package/templates/solid/example/tanchat/assets/src/store/demo.hooks.ts +0 -17
  273. package/templates/solid/example/tanchat/assets/src/store/demo.store.ts +0 -133
  274. package/templates/solid/example/tanchat/info.json +0 -14
  275. package/templates/solid/example/tanchat/package.json +0 -7
  276. package/templates/solid/file-router/package.fr.json +0 -5
  277. package/templates/solid/file-router/src/main.tsx.ejs +0 -47
  278. package/templates/solid/file-router/src/routes/__root.tsx.ejs +0 -41
  279. package/templates/solid/file-router/src/routes/index.tsx +0 -43
  280. package/tests/cra.test.ts +0 -293
  281. package/tests/snapshots/cra/cr-js-npm.json +0 -33
  282. package/tests/snapshots/cra/cr-ts-npm.json +0 -34
  283. package/tests/snapshots/cra/cr-ts-start-npm.json +0 -38
  284. package/tests/snapshots/cra/fr-ts-npm.json +0 -34
  285. package/tests/snapshots/cra/fr-ts-tw-npm.json +0 -33
  286. package/tests/snapshots/cra/solid-cr-js-npm.json +0 -31
  287. package/tests/snapshots/cra/solid-cr-ts-npm.json +0 -32
  288. package/tests/snapshots/cra/solid-cr-ts-start-npm.json +0 -36
  289. package/tests/snapshots/cra/solid-fr-ts-npm.json +0 -33
  290. package/tests/snapshots/cra/solid-fr-ts-tw-npm.json +0 -32
  291. package/tests/test-utilities.ts +0 -87
@@ -1,13 +0,0 @@
1
- {
2
- "name": "Convex",
3
- "description": "Add the Convex database to your application.",
4
- "link": "https://convex.dev",
5
- "phase": "add-on",
6
- "templates": ["file-router"],
7
- "routes": [
8
- {
9
- "url": "/demo/convex",
10
- "name": "Convex"
11
- }
12
- ]
13
- }
@@ -1,6 +0,0 @@
1
- {
2
- "dependencies": {
3
- "@convex-dev/react-query": "0.0.0-alpha.8",
4
- "convex": "^1.19.2"
5
- }
6
- }
@@ -1,300 +0,0 @@
1
- import { useStore } from '@tanstack/react-form'
2
-
3
- import { useFieldContext, useFormContext } from '../hooks/demo.form-context'
4
- <% if (addOnEnabled.shadcn) { %>
5
- import { Button } from '@/components/ui/button'
6
- import { Input } from '@/components/ui/input'
7
- import { Textarea as ShadcnTextarea } from '@/components/ui/textarea'
8
- import * as ShadcnSelect from '@/components/ui/select'
9
- import { Slider as ShadcnSlider } from '@/components/ui/slider'
10
- import { Switch as ShadcnSwitch } from '@/components/ui/switch'
11
- import { Label } from '@/components/ui/label'
12
-
13
- export function SubscribeButton({ label }: { label: string }) {
14
- const form = useFormContext()
15
- return (
16
- <form.Subscribe selector={(state) => state.isSubmitting}>
17
- {(isSubmitting) => (
18
- <Button type="submit" disabled={isSubmitting}>
19
- {label}
20
- </Button>
21
- )}
22
- </form.Subscribe>
23
- )
24
- }
25
-
26
- function ErrorMessages({
27
- errors,
28
- }: {
29
- errors: Array<string | { message: string }>
30
- }) {
31
- return (
32
- <>
33
- {errors.map((error) => (
34
- <div
35
- key={typeof error === 'string' ? error : error.message}
36
- className="text-red-500 mt-1 font-bold"
37
- >
38
- {typeof error === 'string' ? error : error.message}
39
- </div>
40
- ))}
41
- </>
42
- )
43
- }
44
-
45
- export function TextField({
46
- label,
47
- placeholder,
48
- }: {
49
- label: string
50
- placeholder?: string
51
- }) {
52
- const field = useFieldContext<string>()
53
- const errors = useStore(field.store, (state) => state.meta.errors)
54
-
55
- return (
56
- <div>
57
- <Label htmlFor={label} className="mb-2 text-xl font-bold">
58
- {label}
59
- </Label>
60
- <Input
61
- value={field.state.value}
62
- placeholder={placeholder}
63
- onBlur={field.handleBlur}
64
- onChange={(e) => field.handleChange(e.target.value)}
65
- />
66
- {field.state.meta.isTouched && <ErrorMessages errors={errors} />}
67
- </div>
68
- )
69
- }
70
-
71
- export function TextArea({
72
- label,
73
- rows = 3,
74
- }: {
75
- label: string
76
- rows?: number
77
- }) {
78
- const field = useFieldContext<string>()
79
- const errors = useStore(field.store, (state) => state.meta.errors)
80
-
81
- return (
82
- <div>
83
- <Label htmlFor={label} className="mb-2 text-xl font-bold">
84
- {label}
85
- </Label>
86
- <ShadcnTextarea
87
- id={label}
88
- value={field.state.value}
89
- onBlur={field.handleBlur}
90
- rows={rows}
91
- onChange={(e) => field.handleChange(e.target.value)}
92
- />
93
- {field.state.meta.isTouched && <ErrorMessages errors={errors} />}
94
- </div>
95
- )
96
- }
97
-
98
- export function Select({
99
- label,
100
- values,
101
- placeholder,
102
- }: {
103
- label: string
104
- values: Array<{ label: string; value: string }>
105
- placeholder?: string
106
- }) {
107
- const field = useFieldContext<string>()
108
- const errors = useStore(field.store, (state) => state.meta.errors)
109
-
110
- return (
111
- <div>
112
- <ShadcnSelect.Select
113
- name={field.name}
114
- value={field.state.value}
115
- onValueChange={(value) => field.handleChange(value)}
116
- >
117
- <ShadcnSelect.SelectTrigger className="w-full">
118
- <ShadcnSelect.SelectValue placeholder={placeholder} />
119
- </ShadcnSelect.SelectTrigger>
120
- <ShadcnSelect.SelectContent>
121
- <ShadcnSelect.SelectGroup>
122
- <ShadcnSelect.SelectLabel>{label}</ShadcnSelect.SelectLabel>
123
- {values.map((value) => (
124
- <ShadcnSelect.SelectItem key={value.value} value={value.value}>
125
- {value.label}
126
- </ShadcnSelect.SelectItem>
127
- ))}
128
- </ShadcnSelect.SelectGroup>
129
- </ShadcnSelect.SelectContent>
130
- </ShadcnSelect.Select>
131
- {field.state.meta.isTouched && <ErrorMessages errors={errors} />}
132
- </div>
133
- )
134
- }
135
-
136
- export function Slider({ label }: { label: string }) {
137
- const field = useFieldContext<number>()
138
- const errors = useStore(field.store, (state) => state.meta.errors)
139
-
140
- return (
141
- <div>
142
- <Label htmlFor={label} className="mb-2 text-xl font-bold">
143
- {label}
144
- </Label>
145
- <ShadcnSlider
146
- id={label}
147
- onBlur={field.handleBlur}
148
- value={[field.state.value]}
149
- onValueChange={(value) => field.handleChange(value[0])}
150
- />
151
- {field.state.meta.isTouched && <ErrorMessages errors={errors} />}
152
- </div>
153
- )
154
- }
155
-
156
- export function Switch({ label }: { label: string }) {
157
- const field = useFieldContext<boolean>()
158
- const errors = useStore(field.store, (state) => state.meta.errors)
159
-
160
- return (
161
- <div>
162
- <div className="flex items-center gap-2">
163
- <ShadcnSwitch
164
- id={label}
165
- onBlur={field.handleBlur}
166
- checked={field.state.value}
167
- onCheckedChange={(checked) => field.handleChange(checked)}
168
- />
169
- <Label htmlFor={label}>{label}</Label>
170
- </div>
171
- {field.state.meta.isTouched && <ErrorMessages errors={errors} />}
172
- </div>
173
- )
174
- }
175
-
176
- <% } else { %>
177
- export function SubscribeButton({ label }: { label: string }) {
178
- const form = useFormContext()
179
- return (
180
- <form.Subscribe selector={(state) => state.isSubmitting}>
181
- {(isSubmitting) => (
182
- <button
183
- type="submit"
184
- disabled={isSubmitting}
185
- className="px-6 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 transition-colors disabled:opacity-50"
186
- >
187
- {label}
188
- </button>
189
- )}
190
- </form.Subscribe>
191
- )
192
- }
193
-
194
- function ErrorMessages({
195
- errors,
196
- }: {
197
- errors: Array<string | { message: string }>
198
- }) {
199
- return (
200
- <>
201
- {errors.map((error) => (
202
- <div
203
- key={typeof error === 'string' ? error : error.message}
204
- className="text-red-500 mt-1 font-bold"
205
- >
206
- {typeof error === 'string' ? error : error.message}
207
- </div>
208
- ))}
209
- </>
210
- )
211
- }
212
-
213
- export function TextField({
214
- label,
215
- placeholder,
216
- }: {
217
- label: string
218
- placeholder?: string
219
- }) {
220
- const field = useFieldContext<string>()
221
- const errors = useStore(field.store, (state) => state.meta.errors)
222
-
223
- return (
224
- <div>
225
- <label htmlFor={label} className="block font-bold mb-1 text-xl">
226
- {label}
227
- <input
228
- value={field.state.value}
229
- placeholder={placeholder}
230
- onBlur={field.handleBlur}
231
- onChange={(e) => field.handleChange(e.target.value)}
232
- className="w-full px-4 py-2 rounded-md border border-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500"
233
- />
234
- </label>
235
- {field.state.meta.isTouched && <ErrorMessages errors={errors} />}
236
- </div>
237
- )
238
- }
239
-
240
- export function TextArea({
241
- label,
242
- rows = 3,
243
- }: {
244
- label: string
245
- rows?: number
246
- }) {
247
- const field = useFieldContext<string>()
248
- const errors = useStore(field.store, (state) => state.meta.errors)
249
-
250
- return (
251
- <div>
252
- <label htmlFor={label} className="block font-bold mb-1 text-xl">
253
- {label}
254
- <textarea
255
- value={field.state.value}
256
- onBlur={field.handleBlur}
257
- rows={rows}
258
- onChange={(e) => field.handleChange(e.target.value)}
259
- className="w-full px-4 py-2 rounded-md border border-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500"
260
- />
261
- </label>
262
- {field.state.meta.isTouched && <ErrorMessages errors={errors} />}
263
- </div>
264
- )
265
- }
266
-
267
- export function Select({
268
- label,
269
- values,
270
- }: {
271
- label: string
272
- values: Array<{ label: string; value: string }>
273
- placeholder?: string
274
- }) {
275
- const field = useFieldContext<string>()
276
- const errors = useStore(field.store, (state) => state.meta.errors)
277
-
278
- return (
279
- <div>
280
- <label htmlFor={label} className="block font-bold mb-1 text-xl">
281
- {label}
282
- </label>
283
- <select
284
- name={field.name}
285
- value={field.state.value}
286
- onBlur={field.handleBlur}
287
- onChange={(e) => field.handleChange(e.target.value)}
288
- className="w-full px-4 py-2 rounded-md border border-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500"
289
- >
290
- {values.map((value) => (
291
- <option key={value.value} value={value.value}>
292
- {value.label}
293
- </option>
294
- ))}
295
- </select>
296
- {field.state.meta.isTouched && <ErrorMessages errors={errors} />}
297
- </div>
298
- )
299
- }
300
- <% } %>
@@ -1,4 +0,0 @@
1
- import { createFormHookContexts } from '@tanstack/react-form'
2
-
3
- export const { fieldContext, useFieldContext, formContext, useFormContext } =
4
- createFormHookContexts()
@@ -1,22 +0,0 @@
1
- import { createFormHook } from '@tanstack/react-form'
2
-
3
- import {
4
- Select,
5
- SubscribeButton,
6
- TextArea,
7
- TextField,
8
- } from '../components/demo.FormComponents'
9
- import { fieldContext, formContext } from './demo.form-context'
10
-
11
- export const { useAppForm } = createFormHook({
12
- fieldComponents: {
13
- TextField,
14
- Select,
15
- TextArea,
16
- },
17
- formComponents: {
18
- SubscribeButton,
19
- },
20
- fieldContext,
21
- formContext,
22
- })
@@ -1,213 +0,0 @@
1
- import { <% if (fileRouter) { %>createFileRoute<% } else { %>createRoute<% } %> } from '@tanstack/react-router'
2
-
3
- import { useAppForm } from '../hooks/demo.form'
4
-
5
- <% if (codeRouter) { %>
6
- import type { RootRoute } from '@tanstack/react-router'
7
- <% } else { %>
8
- export const Route = createFileRoute('/demo/form')({
9
- component: AddressForm,
10
- })
11
- <% } %>
12
-
13
- function AddressForm() {
14
- const form = useAppForm({
15
- defaultValues: {
16
- fullName: '',
17
- email: '',
18
- address: {
19
- street: '',
20
- city: '',
21
- state: '',
22
- zipCode: '',
23
- country: '',
24
- },
25
- phone: '',
26
- },
27
- validators: {
28
- onBlur: ({ value }) => {
29
- const errors = {
30
- fields: {},
31
- } as {
32
- fields: Record<string, string>
33
- }
34
- if (value.fullName.trim().length === 0) {
35
- errors.fields.fullName = 'Full name is required'
36
- }
37
- return errors
38
- },
39
- },
40
- onSubmit: ({ value }) => {
41
- console.log(value)
42
- // Show success message
43
- alert('Form submitted successfully!')
44
- },
45
- })
46
-
47
- return (
48
- <div
49
- className="flex items-center justify-center min-h-screen bg-gradient-to-br from-purple-100 to-blue-100 p-4 text-white"
50
- style={{
51
- backgroundImage:
52
- 'radial-gradient(50% 50% at 5% 40%, #f4a460 0%, #8b4513 70%, #1a0f0a 100%)',
53
- }}
54
- >
55
- <div className="w-full max-w-2xl p-8 rounded-xl backdrop-blur-md bg-black/50 shadow-xl border-8 border-black/10">
56
- <form
57
- onSubmit={(e) => {
58
- e.preventDefault()
59
- e.stopPropagation()
60
- form.handleSubmit()
61
- }}
62
- className="space-y-6"
63
- >
64
- <form.AppField name="fullName">
65
- {(field) => <field.TextField label="Full Name" />}
66
- </form.AppField>
67
-
68
- <form.AppField
69
- name="email"
70
- validators={{
71
- onBlur: ({ value }) => {
72
- if (!value || value.trim().length === 0) {
73
- return 'Email is required'
74
- }
75
- if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(value)) {
76
- return 'Invalid email address'
77
- }
78
- return undefined
79
- },
80
- }}
81
- >
82
- {(field) => <field.TextField label="Email" />}
83
- </form.AppField>
84
-
85
- <form.AppField
86
- name="address.street"
87
- validators={{
88
- onBlur: ({ value }) => {
89
- if (!value || value.trim().length === 0) {
90
- return 'Street address is required'
91
- }
92
- return undefined
93
- },
94
- }}
95
- >
96
- {(field) => <field.TextField label="Street Address" />}
97
- </form.AppField>
98
-
99
- <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
100
- <form.AppField
101
- name="address.city"
102
- validators={{
103
- onBlur: ({ value }) => {
104
- if (!value || value.trim().length === 0) {
105
- return 'City is required'
106
- }
107
- return undefined
108
- },
109
- }}
110
- >
111
- {(field) => <field.TextField label="City" />}
112
- </form.AppField>
113
- <form.AppField
114
- name="address.state"
115
- validators={{
116
- onBlur: ({ value }) => {
117
- if (!value || value.trim().length === 0) {
118
- return 'State is required'
119
- }
120
- return undefined
121
- },
122
- }}
123
- >
124
- {(field) => <field.TextField label="State" />}
125
- </form.AppField>
126
- <form.AppField
127
- name="address.zipCode"
128
- validators={{
129
- onBlur: ({ value }) => {
130
- if (!value || value.trim().length === 0) {
131
- return 'Zip code is required'
132
- }
133
- if (!/^\d{5}(-\d{4})?$/.test(value)) {
134
- return 'Invalid zip code format'
135
- }
136
- return undefined
137
- },
138
- }}
139
- >
140
- {(field) => <field.TextField label="Zip Code" />}
141
- </form.AppField>
142
- </div>
143
-
144
- <form.AppField
145
- name="address.country"
146
- validators={{
147
- onBlur: ({ value }) => {
148
- if (!value || value.trim().length === 0) {
149
- return 'Country is required'
150
- }
151
- return undefined
152
- },
153
- }}
154
- >
155
- {(field) => (
156
- <field.Select
157
- label="Country"
158
- values={[
159
- { label: 'United States', value: 'US' },
160
- { label: 'Canada', value: 'CA' },
161
- { label: 'United Kingdom', value: 'UK' },
162
- { label: 'Australia', value: 'AU' },
163
- { label: 'Germany', value: 'DE' },
164
- { label: 'France', value: 'FR' },
165
- { label: 'Japan', value: 'JP' },
166
- ]}
167
- placeholder="Select a country"
168
- />
169
- )}
170
- </form.AppField>
171
-
172
- <form.AppField
173
- name="phone"
174
- validators={{
175
- onBlur: ({ value }) => {
176
- if (!value || value.trim().length === 0) {
177
- return 'Phone number is required'
178
- }
179
- if (
180
- !/^(\+\d{1,3})?\s?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}$/.test(
181
- value,
182
- )
183
- ) {
184
- return 'Invalid phone number format'
185
- }
186
- return undefined
187
- },
188
- }}
189
- >
190
- {(field) => (
191
- <field.TextField label="Phone" placeholder="123-456-7890" />
192
- )}
193
- </form.AppField>
194
-
195
- <div className="flex justify-end">
196
- <form.AppForm>
197
- <form.SubscribeButton label="Submit" />
198
- </form.AppForm>
199
- </div>
200
- </form>
201
- </div>
202
- </div>
203
- )
204
- }
205
-
206
-
207
- <% if (codeRouter) { %>
208
- export default (parentRoute: RootRoute) => createRoute({
209
- path: '/demo/form/address',
210
- component: AddressForm,
211
- getParentRoute: () => parentRoute,
212
- })
213
- <% } %>
@@ -1,77 +0,0 @@
1
- import { <% if (fileRouter) { %>createFileRoute<% } else { %>createRoute<% } %> } from '@tanstack/react-router'
2
- import { z } from 'zod'
3
-
4
- import { useAppForm } from '../hooks/demo.form'
5
-
6
- <% if (codeRouter) { %>
7
- import type { RootRoute } from '@tanstack/react-router'
8
- <% } else { %>
9
- export const Route = createFileRoute('/demo/form')({
10
- component: SimpleForm,
11
- })
12
- <% } %>
13
-
14
- const schema = z.object({
15
- title: z.string().min(1, 'Title is required'),
16
- description: z.string().min(1, 'Description is required'),
17
- })
18
-
19
- function SimpleForm() {
20
- const form = useAppForm({
21
- defaultValues: {
22
- title: '',
23
- description: '',
24
- },
25
- validators: {
26
- onBlur: schema,
27
- },
28
- onSubmit: ({ value }) => {
29
- console.log(value)
30
- // Show success message
31
- alert('Form submitted successfully!')
32
- },
33
- })
34
-
35
- return (
36
- <div
37
- className="flex items-center justify-center min-h-screen bg-gradient-to-br from-purple-100 to-blue-100 p-4 text-white"
38
- style={{
39
- backgroundImage:
40
- 'radial-gradient(50% 50% at 5% 40%, #add8e6 0%, #0000ff 70%, #00008b 100%)',
41
- }}
42
- >
43
- <div className="w-full max-w-2xl p-8 rounded-xl backdrop-blur-md bg-black/50 shadow-xl border-8 border-black/10">
44
- <form
45
- onSubmit={(e) => {
46
- e.preventDefault()
47
- e.stopPropagation()
48
- form.handleSubmit()
49
- }}
50
- className="space-y-6"
51
- >
52
- <form.AppField name="title">
53
- {(field) => <field.TextField label="Title" />}
54
- </form.AppField>
55
-
56
- <form.AppField name="description">
57
- {(field) => <field.TextArea label="Description" />}
58
- </form.AppField>
59
-
60
- <div className="flex justify-end">
61
- <form.AppForm>
62
- <form.SubscribeButton label="Submit" />
63
- </form.AppForm>
64
- </div>
65
- </form>
66
- </div>
67
- </div>
68
- )
69
- }
70
-
71
- <% if (codeRouter) { %>
72
- export default (parentRoute: RootRoute) => createRoute({
73
- path: '/demo/form/simple',
74
- component: SimpleForm,
75
- getParentRoute: () => parentRoute,
76
- })
77
- <% } %>
@@ -1,26 +0,0 @@
1
- {
2
- "name": "Form",
3
- "description": "TanStack Form",
4
- "phase": "add-on",
5
- "templates": ["file-router", "code-router"],
6
- "link": "https://tanstack.com/form/latest",
7
- "routes": [
8
- {
9
- "url": "/demo/form/simple",
10
- "name": "Simple Form"
11
- },
12
- {
13
- "url": "/demo/form/address",
14
- "name": "Address Form"
15
- }
16
- ],
17
- "shadcnComponents": [
18
- "button",
19
- "select",
20
- "input",
21
- "textarea",
22
- "slider",
23
- "switch",
24
- "label"
25
- ]
26
- }
@@ -1,6 +0,0 @@
1
- {
2
- "dependencies": {
3
- "@tanstack/react-form": "^1.0.0",
4
- "zod": "^3.24.2"
5
- }
6
- }