`FormField` with its react-hook-form wiring already done — the control's value/onChange/onBlur/ref, the label association, and the error message.

pnpm add @behivetech/forms.form-field-managed

You are viewing Form Field Managed v0.1.8, snapshotted 2026-11-09. The latest is v0.1.10. Go to the latest →

Examples of v0.1.8 are shown as code; only the latest version runs live. Open the live examples →

One managed form covering both integration shapes: a native control, where the field spreads straight on, and two Radix controls, where the caller maps the one prop that differs. Each field passes `control` rather than naming type parameters. That is the shape worth copying: it infers both parameters, so `field.value` is the type of that one field and needs no cast. Reading `control` from context instead works too, but then the field type has to be named — `<FormFieldManaged< DemoValues, "email">` — because supplying one type argument stops TypeScript inferring the other.

Managed Form
1interface DemoValues {
2 email: string;
3 role: string;
4 active: boolean;
5}
6
7const ROLES = [
8 { label: "Admin", value: "admin" },
9 { label: "Editor", value: "editor" },
10];
11
12const ManagedForm = () => {
13 const methods = useForm<DemoValues>({
14 defaultValues: { email: "", role: "", active: false },
15 });
16
17 return (
18 <Form methods={methods} onSubmit={(values) => console.log(values)}>
19 <FormFieldManaged
20 control={methods.control}
21 name="email"
22 label="Email"
23 hint="We only use this for sign-in"
24 required
25 rules={{ required: "Email is required" }}
26 >
27 {(field) => <TextField {...field} type="email" />}
28 </FormFieldManaged>
29
30 <FormFieldManaged
31 control={methods.control}
32 name="role"
33 label="Role"
34 rules={{ required: "Pick a role" }}
35 >
36 {(field) => (
37 <Select
38 id={field.id}
39 name={field.name}
40 options={ROLES}
41 value={field.value}
42 onValueChange={field.onChange}
43 placeholder="Pick one"
44 />
45 )}
46 </FormFieldManaged>
47
48 <FormFieldManaged control={methods.control} name="active" label="Active">
49 {(field) => (
50 <Toggle
51 id={field.id}
52 name={field.name}
53 checked={field.value}
54 onCheckedChange={field.onChange}
55 />
56 )}
57 </FormFieldManaged>
58
59 <Button type="submit" variant="primary" size="sm">
60 Save
61 </Button>
62 </Form>
63 );
64};
65
66render(<ManagedForm />);