@beignet/react-hook-form 0.0.24 → 0.0.26
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/CHANGELOG.md +8 -0
- package/README.md +8 -0
- package/package.json +4 -2
- package/skills/forms/SKILL.md +143 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @beignet/react-hook-form
|
|
2
2
|
|
|
3
|
+
## 0.0.26
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 104302c: Refresh package-shipped TanStack Intent skills and add package skills for Drizzle database providers, Better Auth, React Hook Form, and React uploads.
|
|
8
|
+
|
|
9
|
+
## 0.0.25
|
|
10
|
+
|
|
3
11
|
## 0.0.24
|
|
4
12
|
|
|
5
13
|
## 0.0.23
|
package/README.md
CHANGED
|
@@ -18,6 +18,14 @@ npm install @beignet/react-hook-form @beignet/core react-hook-form @hookform/res
|
|
|
18
18
|
|
|
19
19
|
This package requires TypeScript 5.0 or higher for proper type inference.
|
|
20
20
|
|
|
21
|
+
## Agent skills
|
|
22
|
+
|
|
23
|
+
This package ships a TanStack Intent skill for coding agents:
|
|
24
|
+
`@beignet/react-hook-form#forms`. Load it when adding contract-backed forms,
|
|
25
|
+
React Hook Form setup, Standard Schema resolver behavior, `rootFormError`,
|
|
26
|
+
React Query mutations, transforming body schemas, feature component
|
|
27
|
+
boundaries, or field/server error mapping in a Beignet app.
|
|
28
|
+
|
|
21
29
|
## Usage
|
|
22
30
|
|
|
23
31
|
### Basic form
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@beignet/react-hook-form",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.26",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "React Hook Form integration for Beignet with Standard Schema support",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"!src/**/*.test.ts",
|
|
18
18
|
"!src/**/*.test.tsx",
|
|
19
19
|
"!src/**/*.test-d.ts",
|
|
20
|
+
"skills",
|
|
20
21
|
"README.md",
|
|
21
22
|
"CHANGELOG.md"
|
|
22
23
|
],
|
|
@@ -34,7 +35,8 @@
|
|
|
34
35
|
"api",
|
|
35
36
|
"typescript",
|
|
36
37
|
"react-hook-form",
|
|
37
|
-
"standard-schema"
|
|
38
|
+
"standard-schema",
|
|
39
|
+
"tanstack-intent"
|
|
38
40
|
],
|
|
39
41
|
"license": "MIT",
|
|
40
42
|
"repository": {
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: forms
|
|
3
|
+
description: "Build Beignet React Hook Form integration with @beignet/react-hook-form: createReactHookForm, contract body schemas, formOptions, useForm, Standard Schema resolver behavior, rootFormError, React Query mutations, transforming schemas, feature component boundaries, field/server error mapping, and client/server import fixes. Use when adding or debugging forms in a Beignet React app."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Beignet React Hook Form
|
|
7
|
+
|
|
8
|
+
Use this skill when working in a Beignet React app that depends on
|
|
9
|
+
`@beignet/react-hook-form`. Read the nearest feature component, feature
|
|
10
|
+
schemas/contracts, root `client/` helpers, and existing form patterns before
|
|
11
|
+
adding a new form.
|
|
12
|
+
|
|
13
|
+
## Setup
|
|
14
|
+
|
|
15
|
+
Create the adapter once in root `client/` or reuse the app's existing helper.
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { createReactHookForm } from "@beignet/react-hook-form";
|
|
19
|
+
|
|
20
|
+
export const rhf = createReactHookForm();
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Feature forms should import contracts, schemas, feature client helpers, React
|
|
24
|
+
Hook Form, React Query, and UI components only. They must not import use cases,
|
|
25
|
+
routes, providers, infra adapters, `server/`, or `app-context.ts`.
|
|
26
|
+
|
|
27
|
+
## Contract Requirements
|
|
28
|
+
|
|
29
|
+
React Hook Form binds to the contract body schema. If a contract has no
|
|
30
|
+
`.body(...)`, `rhf(contract)` throws because there are no form fields or body
|
|
31
|
+
validation to infer.
|
|
32
|
+
|
|
33
|
+
Keep shared form DTOs in `features/<feature>/schemas.ts`, then reuse them from
|
|
34
|
+
contracts, use cases, tests, and components.
|
|
35
|
+
|
|
36
|
+
## Form Pattern
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
"use client";
|
|
40
|
+
|
|
41
|
+
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
|
42
|
+
import { rootFormError } from "@beignet/react-hook-form";
|
|
43
|
+
import { rhf } from "@/client/forms";
|
|
44
|
+
import { createTodo } from "@/features/todos/contracts";
|
|
45
|
+
import {
|
|
46
|
+
createTodoMutationOptions,
|
|
47
|
+
invalidateTodos,
|
|
48
|
+
} from "@/features/todos/client/queries";
|
|
49
|
+
|
|
50
|
+
const createTodoForm = rhf(createTodo);
|
|
51
|
+
|
|
52
|
+
export function CreateTodoForm() {
|
|
53
|
+
const queryClient = useQueryClient();
|
|
54
|
+
const form = createTodoForm.useForm({
|
|
55
|
+
defaultValues: { title: "" },
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const mutation = useMutation({
|
|
59
|
+
...createTodoMutationOptions(),
|
|
60
|
+
onSuccess: () => {
|
|
61
|
+
form.reset();
|
|
62
|
+
invalidateTodos(queryClient);
|
|
63
|
+
},
|
|
64
|
+
onError: (error) => {
|
|
65
|
+
form.setError(
|
|
66
|
+
"root",
|
|
67
|
+
rootFormError(error, "Could not create the todo."),
|
|
68
|
+
);
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<form
|
|
74
|
+
onSubmit={form.handleSubmit((values) => {
|
|
75
|
+
form.clearErrors("root");
|
|
76
|
+
mutation.mutate({ body: values });
|
|
77
|
+
})}
|
|
78
|
+
>
|
|
79
|
+
{/* fields */}
|
|
80
|
+
</form>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Use `formOptions(...)` when a component or wrapper wants options without
|
|
86
|
+
calling the hook directly.
|
|
87
|
+
|
|
88
|
+
## Input And Output Types
|
|
89
|
+
|
|
90
|
+
React Hook Form field state uses the schema input type. `handleSubmit` receives
|
|
91
|
+
the schema output type after validation, coercion, defaults, and transforms.
|
|
92
|
+
|
|
93
|
+
For plain, defaulted, or coerced schemas, submitting `values` as the contract
|
|
94
|
+
body usually works. If a schema transform changes a field's type so the parsed
|
|
95
|
+
output no longer matches the contract body input, send raw field values from
|
|
96
|
+
`form.getValues()` after validation instead of `values`.
|
|
97
|
+
|
|
98
|
+
## Error Mapping
|
|
99
|
+
|
|
100
|
+
Use `rootFormError(error, fallback, overrides?)` for mutation or endpoint
|
|
101
|
+
failures when the server error belongs at the form level.
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
form.setError(
|
|
105
|
+
"root",
|
|
106
|
+
rootFormError(error, "Could not update profile.", {
|
|
107
|
+
HANDLE_UNAVAILABLE: "That handle is already taken.",
|
|
108
|
+
}),
|
|
109
|
+
);
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Map a server error to a field only when the server response identifies a
|
|
113
|
+
specific field and the field exists in the body schema. Keep route-owned error
|
|
114
|
+
codes declared on the contract with `.errors(...)`.
|
|
115
|
+
|
|
116
|
+
## Gotchas
|
|
117
|
+
|
|
118
|
+
- `rhf(contract)` only understands the request body. Path params, query
|
|
119
|
+
params, headers, tenant IDs, and auth-derived values belong in mutation
|
|
120
|
+
variables or app context, not form fields.
|
|
121
|
+
- Contracts without `.body(...)` are not form contracts.
|
|
122
|
+
- `handleSubmit` returns parsed schema output. For transforms that change field
|
|
123
|
+
types, submit `form.getValues()` after validation when the contract client
|
|
124
|
+
expects body input.
|
|
125
|
+
- Keep the root form helper in `client/forms.ts` unless the app already uses a
|
|
126
|
+
different local convention.
|
|
127
|
+
- Do not import use cases or server modules to reuse validation. Move shared
|
|
128
|
+
validation to `features/<feature>/schemas.ts`.
|
|
129
|
+
|
|
130
|
+
## Validation
|
|
131
|
+
|
|
132
|
+
Leave the generated Standard Schema resolver enabled by default. Use
|
|
133
|
+
`resolverEnabled: false` only for deliberate partial or multi-step flows, and
|
|
134
|
+
keep final validation in use cases.
|
|
135
|
+
|
|
136
|
+
After form changes, run from the app root:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
beignet lint
|
|
140
|
+
beignet doctor --strict
|
|
141
|
+
bun run typecheck
|
|
142
|
+
bun run test
|
|
143
|
+
```
|