create-tsrouter-app 0.6.1 → 0.6.2

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.
@@ -0,0 +1,203 @@
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
65
+ name="fullName"
66
+ children={(field) => <field.TextField label="Full Name" />}
67
+ />
68
+
69
+ <form.AppField
70
+ name="email"
71
+ validators={{
72
+ onBlur: ({ value }) => {
73
+ if (!value || value.trim().length === 0) {
74
+ return 'Email is required'
75
+ }
76
+ if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(value)) {
77
+ return 'Invalid email address'
78
+ }
79
+ return undefined
80
+ },
81
+ }}
82
+ children={(field) => <field.TextField label="Email" />}
83
+ />
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
+ children={(field) => <field.TextField label="Street Address" />}
96
+ />
97
+
98
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
99
+ <form.AppField
100
+ name="address.city"
101
+ validators={{
102
+ onBlur: ({ value }) => {
103
+ if (!value || value.trim().length === 0) {
104
+ return 'City is required'
105
+ }
106
+ return undefined
107
+ },
108
+ }}
109
+ children={(field) => <field.TextField label="City" />}
110
+ />
111
+ <form.AppField
112
+ name="address.state"
113
+ validators={{
114
+ onBlur: ({ value }) => {
115
+ if (!value || value.trim().length === 0) {
116
+ return 'State is required'
117
+ }
118
+ return undefined
119
+ },
120
+ }}
121
+ children={(field) => <field.TextField label="State" />}
122
+ />
123
+ <form.AppField
124
+ name="address.zipCode"
125
+ validators={{
126
+ onBlur: ({ value }) => {
127
+ if (!value || value.trim().length === 0) {
128
+ return 'Zip code is required'
129
+ }
130
+ if (!/^\d{5}(-\d{4})?$/.test(value)) {
131
+ return 'Invalid zip code format'
132
+ }
133
+ return undefined
134
+ },
135
+ }}
136
+ children={(field) => <field.TextField label="Zip Code" />}
137
+ />
138
+ </div>
139
+
140
+ <form.AppField
141
+ name="address.country"
142
+ validators={{
143
+ onBlur: ({ value }) => {
144
+ if (!value || value.trim().length === 0) {
145
+ return 'Country is required'
146
+ }
147
+ return undefined
148
+ },
149
+ }}
150
+ children={(field) => (
151
+ <field.Select label="Country">
152
+ <option value="">Select a country</option>
153
+ <option value="US">United States</option>
154
+ <option value="CA">Canada</option>
155
+ <option value="UK">United Kingdom</option>
156
+ <option value="AU">Australia</option>
157
+ <option value="DE">Germany</option>
158
+ <option value="FR">France</option>
159
+ <option value="JP">Japan</option>
160
+ </field.Select>
161
+ )}
162
+ />
163
+
164
+ <form.AppField
165
+ name="phone"
166
+ validators={{
167
+ onBlur: ({ value }) => {
168
+ if (!value || value.trim().length === 0) {
169
+ return 'Phone number is required'
170
+ }
171
+ if (
172
+ !/^(\+\d{1,3})?\s?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}$/.test(
173
+ value,
174
+ )
175
+ ) {
176
+ return 'Invalid phone number format'
177
+ }
178
+ return undefined
179
+ },
180
+ }}
181
+ children={(field) => (
182
+ <field.TextField label="Phone" placeholder="123-456-7890" />
183
+ )}
184
+ />
185
+
186
+ <div className="flex justify-end">
187
+ <form.AppForm>
188
+ <form.SubscribeButton label="Submit" />
189
+ </form.AppForm>
190
+ </div>
191
+ </form>
192
+ </div>
193
+ </div>
194
+ )
195
+ }
196
+
197
+ <% if (codeRouter) { %>
198
+ export default (parentRoute: RootRoute) => createRoute({
199
+ path: '/demo/form',
200
+ component: Addres,
201
+ getParentRoute: () => parentRoute,
202
+ })
203
+ <% } %>
@@ -0,0 +1,79 @@
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
53
+ name="title"
54
+ children={(field) => <field.TextField label="Title" />}
55
+ />
56
+
57
+ <form.AppField
58
+ name="description"
59
+ children={(field) => <field.TextArea label="Description" />}
60
+ />
61
+
62
+ <div className="flex justify-end">
63
+ <form.AppForm>
64
+ <form.SubscribeButton label="Submit" />
65
+ </form.AppForm>
66
+ </div>
67
+ </form>
68
+ </div>
69
+ </div>
70
+ )
71
+ }
72
+
73
+ <% if (codeRouter) { %>
74
+ export default (parentRoute: RootRoute) => createRoute({
75
+ path: '/demo/form',
76
+ component: SimpleForm,
77
+ getParentRoute: () => parentRoute,
78
+ })
79
+ <% } %>
@@ -6,8 +6,12 @@
6
6
  "link": "https://tanstack.com/form/latest",
7
7
  "routes": [
8
8
  {
9
- "url": "/demo/form",
10
- "name": "Form"
9
+ "url": "/demo/form/simple",
10
+ "name": "Simple Form"
11
+ },
12
+ {
13
+ "url": "/demo/form/address",
14
+ "name": "Address Form"
11
15
  }
12
16
  ]
13
17
  }
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "dependencies": {
3
- "@tanstack/react-form": "^0.42.0"
3
+ "@tanstack/react-form": "^1.0.0",
4
+ "zod": "^3.24.2"
4
5
  }
5
6
  }
@@ -47,7 +47,7 @@ This project uses [Biome](https://biomejs.dev/) for linting and formatting. The
47
47
  <% } %>
48
48
 
49
49
  ## Routing
50
- <% if (fileRouter) { %>This project uses [TanStack Router](https://tanstack.com/router). The initial setup is a file based router. Which means that the routes are managed as fiels in `src/routes`.<% } else { %>This project uses [TanStack Router](https://tanstack.com/router). The initial setup is a code based router. Which means that the routes are defined in code (in the `./src/main.<%= jsx %>` file). If you like you can also use a file based routing setup by following the [File Based Routing](https://tanstack.com/router/latest/docs/framework/react/guide/file-based-routing) guide.<% } %>
50
+ <% if (fileRouter) { %>This project uses [TanStack Router](https://tanstack.com/router). The initial setup is a file based router. Which means that the routes are managed as files in `src/routes`.<% } else { %>This project uses [TanStack Router](https://tanstack.com/router). The initial setup is a code based router. Which means that the routes are defined in code (in the `./src/main.<%= jsx %>` file). If you like you can also use a file based routing setup by following the [File Based Routing](https://tanstack.com/router/latest/docs/framework/react/guide/file-based-routing) guide.<% } %>
51
51
 
52
52
  ### Adding A Route
53
53
  <% if (fileRouter) { %>
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "TanStack Chat",
3
- "description": "A chat example that uses TanStack Start and TanStack Store. Features chat with Antrhopic Sonnet, chat history and custom prompts.",
3
+ "description": "A chat example that uses TanStack Start and TanStack Store. Features chat with Anthropic Sonnet, chat history and custom prompts.",
4
4
  "phase": "example",
5
5
  "templates": ["file-router"],
6
6
  "link": "",