@zod-utils/react-hook-form 0.1.0 → 0.2.0
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.
- package/README.md +100 -108
- package/dist/index.d.mts +210 -47
- package/dist/index.d.ts +210 -47
- package/dist/index.js +1 -281
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -278
- package/dist/index.mjs.map +1 -1
- package/package.json +13 -5
package/README.md
CHANGED
|
@@ -1,13 +1,48 @@
|
|
|
1
1
|
# @zod-utils/react-hook-form
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
[](https://www.npmjs.com/package/@zod-utils/react-hook-form)
|
|
5
4
|
[](https://www.npmjs.com/package/@zod-utils/react-hook-form)
|
|
6
5
|
[](https://opensource.org/licenses/MIT)
|
|
7
6
|
[](https://www.typescriptlang.org/)
|
|
8
7
|
[](https://github.com/thu-san/zod-utils/actions)
|
|
8
|
+
[](https://codecov.io/gh/thu-san/zod-utils)
|
|
9
|
+
|
|
9
10
|
React Hook Form integration and utilities for Zod schemas.
|
|
10
11
|
|
|
12
|
+
## 💡 Why Use This?
|
|
13
|
+
|
|
14
|
+
**The whole point:** Automatically transforms your Zod schema types so form inputs and default values accept `null | undefined` during editing, while the validated output remains exactly as your Zod schema defines.
|
|
15
|
+
|
|
16
|
+
No more type wrestling with React Hook Form - just pass your schema and it works.
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import { useZodForm } from "@zod-utils/react-hook-form";
|
|
20
|
+
import { z } from "zod";
|
|
21
|
+
|
|
22
|
+
// Your schema requires string - NOT optional
|
|
23
|
+
const schema = z.object({
|
|
24
|
+
username: z.string().min(3),
|
|
25
|
+
email: z.string().email(),
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const form = useZodForm({ schema });
|
|
29
|
+
|
|
30
|
+
// ✅ Works! defaultValues accepts null/undefined during editing
|
|
31
|
+
form.reset({ username: null, email: undefined });
|
|
32
|
+
|
|
33
|
+
// ✅ Works! setValue accepts null/undefined during editing
|
|
34
|
+
form.setValue("username", null);
|
|
35
|
+
form.setValue("email", undefined);
|
|
36
|
+
|
|
37
|
+
// ✅ Validated output type is exactly z.infer<typeof schema>
|
|
38
|
+
const onSubmit = form.handleSubmit((data) => {
|
|
39
|
+
// Type: { username: string; email: string }
|
|
40
|
+
// NOT { username: string | null | undefined; email: string | null | undefined }
|
|
41
|
+
console.log(data.username); // Type: string
|
|
42
|
+
console.log(data.email); // Type: string
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
11
46
|
## Installation
|
|
12
47
|
|
|
13
48
|
```bash
|
|
@@ -16,19 +51,18 @@ npm install @zod-utils/react-hook-form zod react react-hook-form @hookform/resol
|
|
|
16
51
|
|
|
17
52
|
## Features
|
|
18
53
|
|
|
19
|
-
- 🎣 **useZodForm** -
|
|
20
|
-
- 🌐 **Custom error messages** - Japanese error resolver (customizable)
|
|
54
|
+
- 🎣 **useZodForm** - Automatic type transformation for form inputs (nullable/undefined) while preserving Zod schema validation
|
|
21
55
|
- 📦 **All core utilities** - Re-exports everything from `@zod-utils/core`
|
|
22
56
|
- ⚛️ **React-optimized** - Built specifically for React applications
|
|
23
57
|
|
|
24
58
|
## Quick Start
|
|
25
59
|
|
|
26
60
|
```typescript
|
|
27
|
-
import { useZodForm, getSchemaDefaults } from
|
|
28
|
-
import { z } from
|
|
61
|
+
import { useZodForm, getSchemaDefaults } from "@zod-utils/react-hook-form";
|
|
62
|
+
import { z } from "zod";
|
|
29
63
|
|
|
30
64
|
const schema = z.object({
|
|
31
|
-
name: z.string().default(
|
|
65
|
+
name: z.string().default("John Doe"),
|
|
32
66
|
email: z.string().email(),
|
|
33
67
|
age: z.number().min(18),
|
|
34
68
|
});
|
|
@@ -45,9 +79,9 @@ function MyForm() {
|
|
|
45
79
|
|
|
46
80
|
return (
|
|
47
81
|
<form onSubmit={onSubmit}>
|
|
48
|
-
<input {...form.register(
|
|
49
|
-
<input {...form.register(
|
|
50
|
-
<input {...form.register(
|
|
82
|
+
<input {...form.register("name")} />
|
|
83
|
+
<input {...form.register("email")} type="email" />
|
|
84
|
+
<input {...form.register("age")} type="number" />
|
|
51
85
|
<button type="submit">Submit</button>
|
|
52
86
|
</form>
|
|
53
87
|
);
|
|
@@ -61,8 +95,8 @@ function MyForm() {
|
|
|
61
95
|
Type-safe wrapper around React Hook Form's `useForm` with automatic Zod schema integration.
|
|
62
96
|
|
|
63
97
|
```typescript
|
|
64
|
-
import { useZodForm } from
|
|
65
|
-
import { z } from
|
|
98
|
+
import { useZodForm } from "@zod-utils/react-hook-form";
|
|
99
|
+
import { z } from "zod";
|
|
66
100
|
|
|
67
101
|
const schema = z.object({
|
|
68
102
|
username: z.string().min(3),
|
|
@@ -70,86 +104,23 @@ const schema = z.object({
|
|
|
70
104
|
});
|
|
71
105
|
|
|
72
106
|
const form = useZodForm({
|
|
73
|
-
schema,
|
|
74
|
-
defaultValues: {
|
|
75
|
-
|
|
107
|
+
schema, // Zod schema (required)
|
|
108
|
+
defaultValues: {
|
|
109
|
+
/* ... */
|
|
110
|
+
}, // Optional default values
|
|
111
|
+
zodResolverOptions: {
|
|
112
|
+
/* ... */
|
|
113
|
+
}, // Optional zodResolver options
|
|
76
114
|
// ... all other useForm options
|
|
77
115
|
});
|
|
78
116
|
```
|
|
79
117
|
|
|
80
|
-
**
|
|
81
|
-
- Zod schema validation via `zodResolver`
|
|
82
|
-
- Proper TypeScript typing
|
|
83
|
-
- Form state management
|
|
84
|
-
|
|
85
|
-
---
|
|
86
|
-
|
|
87
|
-
### `customErrorResolver(config)`
|
|
88
|
-
|
|
89
|
-
Custom error message resolver with Japanese translations. Easily customizable for other languages.
|
|
90
|
-
|
|
91
|
-
```typescript
|
|
92
|
-
import { customErrorResolver, FieldNamespaceMapping } from '@zod-utils/react-hook-form';
|
|
93
|
-
import { z } from 'zod';
|
|
94
|
-
|
|
95
|
-
// Extend the field namespace mapping
|
|
96
|
-
const MyFieldNamespaceMapping = {
|
|
97
|
-
...FieldNamespaceMapping,
|
|
98
|
-
myForm: {
|
|
99
|
-
username: 'ユーザー名',
|
|
100
|
-
email: 'メールアドレス',
|
|
101
|
-
},
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
const errorMap = customErrorResolver({
|
|
105
|
-
fieldNamespace: 'myForm',
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
const schema = z.object({
|
|
109
|
-
username: z.string(),
|
|
110
|
-
email: z.string().email(),
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
// Use with Zod
|
|
114
|
-
schema.parse({ username: '', email: 'invalid' }, { errorMap });
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
**Supported error types:**
|
|
118
|
-
- `too_small` / `too_big` - With field-specific messages
|
|
119
|
-
- `invalid_type` - Type mismatch errors
|
|
120
|
-
- `invalid_format` - Email, URL, UUID, etc.
|
|
121
|
-
- `invalid_value` - Enum/literal errors
|
|
122
|
-
- And more...
|
|
123
|
-
|
|
124
|
-
---
|
|
125
|
-
|
|
126
|
-
### `FieldNamespaceMapping`
|
|
118
|
+
**What it does:**
|
|
127
119
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
department: {
|
|
133
|
-
groupName: '部署・店舗名',
|
|
134
|
-
},
|
|
135
|
-
// Add your own namespaces
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
export type FIELD_NAMESPACE = keyof typeof FieldNamespaceMapping;
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
**Extend it:**
|
|
142
|
-
```typescript
|
|
143
|
-
import { FieldNamespaceMapping } from '@zod-utils/react-hook-form';
|
|
144
|
-
|
|
145
|
-
const CustomMapping = {
|
|
146
|
-
...FieldNamespaceMapping,
|
|
147
|
-
userForm: {
|
|
148
|
-
firstName: '名',
|
|
149
|
-
lastName: '姓',
|
|
150
|
-
},
|
|
151
|
-
};
|
|
152
|
-
```
|
|
120
|
+
- **Input transformation**: Form field values can be `null` or `undefined` during editing
|
|
121
|
+
- **Output validation**: Validated data matches your Zod schema exactly
|
|
122
|
+
- **Type inference**: No manual type annotations needed - everything is inferred from the schema
|
|
123
|
+
- **Zod integration**: Automatically sets up `zodResolver` for validation
|
|
153
124
|
|
|
154
125
|
---
|
|
155
126
|
|
|
@@ -159,35 +130,53 @@ All utilities from `@zod-utils/core` are re-exported for convenience:
|
|
|
159
130
|
|
|
160
131
|
```typescript
|
|
161
132
|
import {
|
|
162
|
-
// Schema utilities
|
|
133
|
+
// Schema utilities (from @zod-utils/core)
|
|
163
134
|
getSchemaDefaults,
|
|
164
135
|
checkIfFieldIsRequired,
|
|
165
136
|
getPrimitiveType,
|
|
166
137
|
removeDefault,
|
|
167
138
|
extractDefault,
|
|
168
|
-
|
|
139
|
+
type Simplify,
|
|
169
140
|
|
|
170
|
-
// Type utilities
|
|
141
|
+
// Type utilities (react-hook-form specific)
|
|
171
142
|
type MakeOptionalAndNullable,
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
143
|
+
} from "@zod-utils/react-hook-form";
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
See [@zod-utils/core documentation](../core/README.md) for details on schema utilities.
|
|
147
|
+
|
|
148
|
+
### Type Utilities
|
|
149
|
+
|
|
150
|
+
#### `MakeOptionalAndNullable<T>`
|
|
151
|
+
|
|
152
|
+
Make all properties optional and nullable. Useful for React Hook Form input types where fields can be empty during editing.
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
import type { MakeOptionalAndNullable } from "@zod-utils/react-hook-form";
|
|
156
|
+
|
|
157
|
+
type User = {
|
|
158
|
+
name: string;
|
|
159
|
+
age: number;
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
type FormInput = MakeOptionalAndNullable<User>;
|
|
163
|
+
// { name?: string | null; age?: number | null; }
|
|
175
164
|
```
|
|
176
165
|
|
|
177
|
-
|
|
166
|
+
This type is used internally by `useZodForm` to allow form fields to be null/undefined during editing while maintaining proper validation types.
|
|
178
167
|
|
|
179
168
|
---
|
|
180
169
|
|
|
181
170
|
## Complete Example
|
|
182
171
|
|
|
183
172
|
```typescript
|
|
184
|
-
import { useZodForm, getSchemaDefaults } from
|
|
185
|
-
import { z } from
|
|
173
|
+
import { useZodForm, getSchemaDefaults } from "@zod-utils/react-hook-form";
|
|
174
|
+
import { z } from "zod";
|
|
186
175
|
|
|
187
176
|
const userSchema = z.object({
|
|
188
177
|
profile: z.object({
|
|
189
|
-
firstName: z.string().min(1,
|
|
190
|
-
lastName: z.string().min(1,
|
|
178
|
+
firstName: z.string().min(1, "First name is required"),
|
|
179
|
+
lastName: z.string().min(1, "Last name is required"),
|
|
191
180
|
age: z.number().min(18).max(120),
|
|
192
181
|
}),
|
|
193
182
|
contact: z.object({
|
|
@@ -195,7 +184,7 @@ const userSchema = z.object({
|
|
|
195
184
|
phone: z.string().optional(),
|
|
196
185
|
}),
|
|
197
186
|
preferences: z.object({
|
|
198
|
-
theme: z.enum([
|
|
187
|
+
theme: z.enum(["light", "dark"]).default("light"),
|
|
199
188
|
notifications: z.boolean().default(true),
|
|
200
189
|
}),
|
|
201
190
|
});
|
|
@@ -207,44 +196,47 @@ function UserForm() {
|
|
|
207
196
|
});
|
|
208
197
|
|
|
209
198
|
const onSubmit = form.handleSubmit((data) => {
|
|
210
|
-
console.log(
|
|
199
|
+
console.log("Valid data:", data);
|
|
211
200
|
});
|
|
212
201
|
|
|
213
202
|
return (
|
|
214
203
|
<form onSubmit={onSubmit}>
|
|
215
204
|
{/* Profile */}
|
|
216
|
-
<input {...form.register(
|
|
205
|
+
<input {...form.register("profile.firstName")} />
|
|
217
206
|
{form.formState.errors.profile?.firstName && (
|
|
218
207
|
<span>{form.formState.errors.profile.firstName.message}</span>
|
|
219
208
|
)}
|
|
220
209
|
|
|
221
|
-
<input {...form.register(
|
|
210
|
+
<input {...form.register("profile.lastName")} />
|
|
222
211
|
{form.formState.errors.profile?.lastName && (
|
|
223
212
|
<span>{form.formState.errors.profile.lastName.message}</span>
|
|
224
213
|
)}
|
|
225
214
|
|
|
226
|
-
<input
|
|
215
|
+
<input
|
|
216
|
+
{...form.register("profile.age", { valueAsNumber: true })}
|
|
217
|
+
type="number"
|
|
218
|
+
/>
|
|
227
219
|
{form.formState.errors.profile?.age && (
|
|
228
220
|
<span>{form.formState.errors.profile.age.message}</span>
|
|
229
221
|
)}
|
|
230
222
|
|
|
231
223
|
{/* Contact */}
|
|
232
|
-
<input {...form.register(
|
|
224
|
+
<input {...form.register("contact.email")} type="email" />
|
|
233
225
|
{form.formState.errors.contact?.email && (
|
|
234
226
|
<span>{form.formState.errors.contact.email.message}</span>
|
|
235
227
|
)}
|
|
236
228
|
|
|
237
|
-
<input {...form.register(
|
|
229
|
+
<input {...form.register("contact.phone")} type="tel" />
|
|
238
230
|
|
|
239
231
|
{/* Preferences - pre-filled with defaults */}
|
|
240
|
-
<select {...form.register(
|
|
232
|
+
<select {...form.register("preferences.theme")}>
|
|
241
233
|
<option value="light">Light</option>
|
|
242
234
|
<option value="dark">Dark</option>
|
|
243
235
|
</select>
|
|
244
236
|
|
|
245
237
|
<label>
|
|
246
238
|
<input
|
|
247
|
-
{...form.register(
|
|
239
|
+
{...form.register("preferences.notifications")}
|
|
248
240
|
type="checkbox"
|
|
249
241
|
/>
|
|
250
242
|
Enable notifications
|
|
@@ -269,10 +261,10 @@ const form = useZodForm({
|
|
|
269
261
|
});
|
|
270
262
|
|
|
271
263
|
// ✅ Fully typed
|
|
272
|
-
form.register(
|
|
264
|
+
form.register("profile.firstName");
|
|
273
265
|
|
|
274
266
|
// ❌ TypeScript error
|
|
275
|
-
form.register(
|
|
267
|
+
form.register("nonexistent.field");
|
|
276
268
|
```
|
|
277
269
|
|
|
278
270
|
---
|
package/dist/index.d.mts
CHANGED
|
@@ -1,66 +1,229 @@
|
|
|
1
|
+
export * from '@zod-utils/core';
|
|
1
2
|
import * as react_hook_form from 'react-hook-form';
|
|
2
3
|
import { FieldValues, DefaultValues, UseFormProps } from 'react-hook-form';
|
|
3
4
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Transforms all properties in a type to be optional and nullable.
|
|
9
|
+
*
|
|
10
|
+
* This type utility is the secret sauce behind `useZodForm`'s type transformation.
|
|
11
|
+
* It makes form inputs accept `null | undefined` during editing, while validated
|
|
12
|
+
* output remains exactly as the schema defines.
|
|
13
|
+
*
|
|
14
|
+
* **Why this matters:**
|
|
15
|
+
* - React Hook Form fields often contain `null` or `undefined` during user input
|
|
16
|
+
* - Zod schemas define strict output types without these nullable/optional wrappers
|
|
17
|
+
* - This type bridges the gap, eliminating "Type 'null' is not assignable to..." errors
|
|
18
|
+
*
|
|
19
|
+
* @template T - The object type to transform
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* Basic transformation
|
|
23
|
+
* ```typescript
|
|
24
|
+
* type User = {
|
|
25
|
+
* name: string;
|
|
26
|
+
* age: number;
|
|
27
|
+
* };
|
|
28
|
+
*
|
|
29
|
+
* type FormUser = MakeOptionalAndNullable<User>;
|
|
30
|
+
* // Result: {
|
|
31
|
+
* // name?: string | null;
|
|
32
|
+
* // age?: number | null;
|
|
33
|
+
* // }
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* Usage with useZodForm
|
|
38
|
+
* ```typescript
|
|
39
|
+
* const schema = z.object({
|
|
40
|
+
* title: z.string(),
|
|
41
|
+
* count: z.number(),
|
|
42
|
+
* });
|
|
43
|
+
*
|
|
44
|
+
* const form = useZodForm({ schema });
|
|
45
|
+
*
|
|
46
|
+
* // ✅ These work without type errors:
|
|
47
|
+
* form.setValue('title', null); // Accepts null during editing
|
|
48
|
+
* form.setValue('title', undefined); // Accepts undefined
|
|
49
|
+
* form.reset({ title: null, count: null }); // Reset with null values
|
|
50
|
+
*
|
|
51
|
+
* // But validated output is still:
|
|
52
|
+
* // { title: string, count: number }
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* Comparison with original type
|
|
57
|
+
* ```typescript
|
|
58
|
+
* type Schema = {
|
|
59
|
+
* email: string;
|
|
60
|
+
* isActive: boolean;
|
|
61
|
+
* };
|
|
62
|
+
*
|
|
63
|
+
* // Original: { email: string; isActive: boolean }
|
|
64
|
+
* // Transformed: { email?: string | null; isActive?: boolean | null }
|
|
65
|
+
*
|
|
66
|
+
* const original: Schema = { email: '', isActive: true }; // OK
|
|
67
|
+
* const original2: Schema = { email: null }; // ❌ Error
|
|
68
|
+
*
|
|
69
|
+
* const transformed: MakeOptionalAndNullable<Schema> = {}; // OK
|
|
70
|
+
* const transformed2: MakeOptionalAndNullable<Schema> = { email: null }; // OK
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
* @see {@link useZodForm} for how this type is used in practice
|
|
74
|
+
* @since 0.1.0
|
|
75
|
+
*/
|
|
76
|
+
type MakeOptionalAndNullable<T> = {
|
|
77
|
+
[K in keyof T]?: T[K] | null;
|
|
78
|
+
};
|
|
7
79
|
|
|
8
80
|
/**
|
|
9
|
-
* Type-safe
|
|
10
|
-
*
|
|
81
|
+
* Type-safe React Hook Form wrapper with automatic Zod v4 schema validation and type transformation.
|
|
82
|
+
*
|
|
83
|
+
* This hook eliminates the TypeScript friction between React Hook Form's nullable field values
|
|
84
|
+
* and Zod's strict output types. It uses a two-type schema pattern where:
|
|
85
|
+
* - **Input type** (`MakeOptionalAndNullable<T>`): Form fields accept `null | undefined` during editing
|
|
86
|
+
* - **Output type** (`T`): Validated data matches exact schema type (no `null | undefined`)
|
|
87
|
+
*
|
|
88
|
+
* **Key Benefits:**
|
|
89
|
+
* - ✅ No more "Type 'null' is not assignable to..." TypeScript errors
|
|
90
|
+
* - ✅ Use `form.setValue()` and `form.reset()` with `null` values freely
|
|
91
|
+
* - ✅ Validated output is still type-safe with exact Zod schema types
|
|
92
|
+
* - ✅ Automatic zodResolver setup - no manual configuration needed
|
|
93
|
+
*
|
|
94
|
+
* @template T - The Zod schema output type (extends FieldValues)
|
|
95
|
+
*
|
|
96
|
+
* @param options - Configuration object
|
|
97
|
+
* @param options.schema - Zod schema with two-type signature `z.ZodType<T, MakeOptionalAndNullable<T>>`
|
|
98
|
+
* @param options.defaultValues - Default form values (accepts nullable/undefined values)
|
|
99
|
+
* @param options.zodResolverOptions - Optional zodResolver configuration
|
|
100
|
+
* @param options....formOptions - All other react-hook-form useForm options
|
|
101
|
+
*
|
|
102
|
+
* @returns React Hook Form instance with type-safe methods
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* Basic usage with required fields
|
|
106
|
+
* ```typescript
|
|
107
|
+
* import { useZodForm } from '@zod-utils/react-hook-form';
|
|
108
|
+
* import { z } from 'zod';
|
|
109
|
+
*
|
|
110
|
+
* const schema = z.object({
|
|
111
|
+
* name: z.string().min(1), // Required field
|
|
112
|
+
* age: z.number().min(0),
|
|
113
|
+
* }) satisfies z.ZodType<{ name: string; age: number }, any>;
|
|
114
|
+
*
|
|
115
|
+
* function MyForm() {
|
|
116
|
+
* const form = useZodForm({ schema });
|
|
117
|
+
*
|
|
118
|
+
* // ✅ These work without type errors:
|
|
119
|
+
* form.setValue('name', null); // Accepts null during editing
|
|
120
|
+
* form.reset({ name: null, age: null }); // Reset with null
|
|
121
|
+
*
|
|
122
|
+
* const onSubmit = (data: { name: string; age: number }) => {
|
|
123
|
+
* // ✅ data is exact type - no null | undefined
|
|
124
|
+
* console.log(data.name.toUpperCase()); // Safe to use string methods
|
|
125
|
+
* };
|
|
126
|
+
*
|
|
127
|
+
* return <form onSubmit={form.handleSubmit(onSubmit)}>...</form>;
|
|
128
|
+
* }
|
|
129
|
+
* ```
|
|
11
130
|
*
|
|
12
131
|
* @example
|
|
13
|
-
*
|
|
132
|
+
* With default values
|
|
133
|
+
* ```typescript
|
|
14
134
|
* const schema = z.object({
|
|
15
|
-
*
|
|
16
|
-
*
|
|
135
|
+
* username: z.string(),
|
|
136
|
+
* email: z.string().email(),
|
|
137
|
+
* notifications: z.boolean().default(true),
|
|
138
|
+
* }) satisfies z.ZodType<{
|
|
139
|
+
* username: string;
|
|
140
|
+
* email: string;
|
|
141
|
+
* notifications: boolean;
|
|
142
|
+
* }, any>;
|
|
143
|
+
*
|
|
144
|
+
* const form = useZodForm({
|
|
145
|
+
* schema,
|
|
146
|
+
* defaultValues: {
|
|
147
|
+
* username: '',
|
|
148
|
+
* email: '',
|
|
149
|
+
* // notifications gets default from schema
|
|
150
|
+
* },
|
|
17
151
|
* });
|
|
152
|
+
* ```
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* With optional and nullable fields
|
|
156
|
+
* ```typescript
|
|
157
|
+
* const schema = z.object({
|
|
158
|
+
* title: z.string(),
|
|
159
|
+
* description: z.string().optional(), // Optional in output
|
|
160
|
+
* tags: z.array(z.string()).nullable(), // Nullable in output
|
|
161
|
+
* }) satisfies z.ZodType<{
|
|
162
|
+
* title: string;
|
|
163
|
+
* description?: string;
|
|
164
|
+
* tags: string[] | null;
|
|
165
|
+
* }, any>;
|
|
166
|
+
*
|
|
167
|
+
* const form = useZodForm({ schema });
|
|
18
168
|
*
|
|
169
|
+
* // All fields accept null/undefined during editing
|
|
170
|
+
* form.setValue('title', null);
|
|
171
|
+
* form.setValue('description', undefined);
|
|
172
|
+
* form.setValue('tags', null);
|
|
173
|
+
* ```
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* With zodResolver options
|
|
177
|
+
* ```typescript
|
|
19
178
|
* const form = useZodForm({
|
|
20
179
|
* schema,
|
|
21
|
-
*
|
|
180
|
+
* zodResolverOptions: {
|
|
181
|
+
* async: true, // Enable async validation
|
|
182
|
+
* errorMap: customErrorMap, // Custom error messages
|
|
183
|
+
* },
|
|
22
184
|
* });
|
|
23
185
|
* ```
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* Complete form example
|
|
189
|
+
* ```typescript
|
|
190
|
+
* const userSchema = z.object({
|
|
191
|
+
* name: z.string().min(1, 'Name is required'),
|
|
192
|
+
* email: z.string().email('Invalid email'),
|
|
193
|
+
* age: z.number().min(18, 'Must be 18+'),
|
|
194
|
+
* }) satisfies z.ZodType<{ name: string; email: string; age: number }, any>;
|
|
195
|
+
*
|
|
196
|
+
* function UserForm() {
|
|
197
|
+
* const form = useZodForm({
|
|
198
|
+
* schema: userSchema,
|
|
199
|
+
* defaultValues: { name: '', email: '', age: null },
|
|
200
|
+
* });
|
|
201
|
+
*
|
|
202
|
+
* const onSubmit = (data: { name: string; email: string; age: number }) => {
|
|
203
|
+
* // Type-safe: data has exact types, no null/undefined
|
|
204
|
+
* console.log(`${data.name} is ${data.age} years old`);
|
|
205
|
+
* };
|
|
206
|
+
*
|
|
207
|
+
* return (
|
|
208
|
+
* <form onSubmit={form.handleSubmit(onSubmit)}>
|
|
209
|
+
* <input {...form.register('name')} />
|
|
210
|
+
* <input {...form.register('email')} type="email" />
|
|
211
|
+
* <input {...form.register('age', { valueAsNumber: true })} type="number" />
|
|
212
|
+
* <button type="submit">Submit</button>
|
|
213
|
+
* </form>
|
|
214
|
+
* );
|
|
215
|
+
* }
|
|
216
|
+
* ```
|
|
217
|
+
*
|
|
218
|
+
* @see {@link MakeOptionalAndNullable} for the type transformation utility
|
|
219
|
+
* @see https://react-hook-form.com/docs/useform for React Hook Form documentation
|
|
220
|
+
* @see https://zod.dev for Zod schema documentation
|
|
221
|
+
* @since 0.1.0
|
|
24
222
|
*/
|
|
25
223
|
declare const useZodForm: <T extends FieldValues>({ schema, zodResolverOptions, ...formOptions }: {
|
|
26
|
-
schema:
|
|
224
|
+
schema: z.ZodType<T, MakeOptionalAndNullable<T>>;
|
|
27
225
|
defaultValues?: DefaultValues<MakeOptionalAndNullable<T>>;
|
|
28
226
|
zodResolverOptions?: Parameters<typeof zodResolver>[1];
|
|
29
|
-
} & Omit<UseFormProps<MakeOptionalAndNullable<T>, unknown, T>, "resolver" | "defaultValues">) => react_hook_form.UseFormReturn<
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Japanese error map for Zod validation errors
|
|
33
|
-
* @param fieldName - Optional custom field name to use in error messages
|
|
34
|
-
* @returns Zod error map function
|
|
35
|
-
*/
|
|
36
|
-
declare function createJapaneseErrorMap(fieldName?: string): (issue: Parameters<ZodErrorMap>[0]) => string;
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* English error map for Zod validation errors
|
|
40
|
-
* @param fieldName - Optional custom field name to use in error messages
|
|
41
|
-
* @returns Zod error map function
|
|
42
|
-
*/
|
|
43
|
-
declare function createEnglishErrorMap(fieldName?: string): (issue: Parameters<ZodErrorMap>[0]) => string;
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Field namespace mapping for custom error messages
|
|
47
|
-
* You can extend this mapping to customize field names in error messages
|
|
48
|
-
*/
|
|
49
|
-
declare const FieldNamespaceMapping: {
|
|
50
|
-
department: {
|
|
51
|
-
groupName: string;
|
|
52
|
-
};
|
|
53
|
-
};
|
|
54
|
-
type FIELD_NAMESPACE = keyof typeof FieldNamespaceMapping;
|
|
55
|
-
/**
|
|
56
|
-
* Custom error resolver with field namespace support (Japanese locale)
|
|
57
|
-
* @deprecated Use createJapaneseErrorMap or createEnglishErrorMap instead
|
|
58
|
-
* @param options - Configuration options
|
|
59
|
-
* @param options.fieldNamespace - Namespace for field name mappings
|
|
60
|
-
* @returns Error resolver function
|
|
61
|
-
*/
|
|
62
|
-
declare const customErrorResolver: ({ fieldNamespace, }: {
|
|
63
|
-
fieldNamespace: FIELD_NAMESPACE;
|
|
64
|
-
}) => (issue: Parameters<ZodErrorMap>[0]) => string;
|
|
227
|
+
} & Omit<UseFormProps<MakeOptionalAndNullable<T>, unknown, T>, "resolver" | "defaultValues">) => react_hook_form.UseFormReturn<MakeOptionalAndNullable<T>, unknown, T>;
|
|
65
228
|
|
|
66
|
-
export { type
|
|
229
|
+
export { type MakeOptionalAndNullable, useZodForm };
|