@explita/formly 0.1.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 +261 -0
- package/README.old.md +141 -0
- package/dist/components/field-error.d.ts +2 -0
- package/dist/components/field-error.js +14 -0
- package/dist/components/field.d.ts +4 -0
- package/dist/components/field.js +120 -0
- package/dist/components/form-spy.d.ts +16 -0
- package/dist/components/form-spy.js +66 -0
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.js +20 -0
- package/dist/components/label.d.ts +2 -0
- package/dist/components/label.js +46 -0
- package/dist/hooks/use-field.d.ts +21 -0
- package/dist/hooks/use-field.js +66 -0
- package/dist/hooks/use-form-by-id.d.ts +6 -0
- package/dist/hooks/use-form-by-id.js +25 -0
- package/dist/hooks/use-form-context.d.ts +5 -0
- package/dist/hooks/use-form-context.js +17 -0
- package/dist/hooks/use-form.d.ts +43 -0
- package/dist/hooks/use-form.js +961 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +25 -0
- package/dist/lib/array-helpers.d.ts +6 -0
- package/dist/lib/array-helpers.js +281 -0
- package/dist/lib/css.d.ts +1 -0
- package/dist/lib/css.js +45 -0
- package/dist/lib/debounce.d.ts +13 -0
- package/dist/lib/debounce.js +28 -0
- package/dist/lib/deep-path.d.ts +4 -0
- package/dist/lib/deep-path.js +60 -0
- package/dist/lib/drafts-helpter.d.ts +31 -0
- package/dist/lib/drafts-helpter.js +67 -0
- package/dist/lib/form-registry.d.ts +9 -0
- package/dist/lib/form-registry.js +24 -0
- package/dist/lib/group-helpers.d.ts +9 -0
- package/dist/lib/group-helpers.js +29 -0
- package/dist/lib/pub-sub.d.ts +13 -0
- package/dist/lib/pub-sub.js +38 -0
- package/dist/lib/utils.d.ts +17 -0
- package/dist/lib/utils.js +190 -0
- package/dist/lib/validation.d.ts +22 -0
- package/dist/lib/validation.js +46 -0
- package/dist/lib/zod-helpers.d.ts +5 -0
- package/dist/lib/zod-helpers.js +63 -0
- package/dist/providers/form.d.ts +51 -0
- package/dist/providers/form.js +63 -0
- package/dist/types/array.d.ts +197 -0
- package/dist/types/array.js +2 -0
- package/dist/types/field.d.ts +61 -0
- package/dist/types/field.js +2 -0
- package/dist/types/group.d.ts +16 -0
- package/dist/types/group.js +2 -0
- package/dist/types/path.d.ts +8 -0
- package/dist/types/path.js +2 -0
- package/dist/types/pub-sub.d.ts +2 -0
- package/dist/types/pub-sub.js +2 -0
- package/dist/types/utils.d.ts +310 -0
- package/dist/types/utils.js +2 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.js +14 -0
- package/package.json +53 -0
package/README.md
ADDED
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
# @explita/formly
|
|
2
|
+
|
|
3
|
+
A lightweight, type-safe form toolkit for React built with developer ergonomics in mind. Provides a flexible form management solution with built-in validation, array manipulation, and nested form support.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🚀 **Type-safe** with TypeScript support
|
|
8
|
+
- 🧩 **Composable** form components and hooks
|
|
9
|
+
- 🔄 **Form State Management** with minimal re-renders
|
|
10
|
+
- ✅ **Built-in Validation** with Zod integration
|
|
11
|
+
- 📋 **Array & Nested Fields** support
|
|
12
|
+
- 🔍 **Form Context** for easy access to form state
|
|
13
|
+
- 🎯 **Field-level** and **Form-level** validation
|
|
14
|
+
- ⚡ **Optimized Performance** with smart re-rendering
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @explita/formly
|
|
20
|
+
# or
|
|
21
|
+
yarn add @explita/formly
|
|
22
|
+
# or
|
|
23
|
+
pnpm add @explita/formly
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
import { Form, Field, useForm, useField } from "@explita/formly";
|
|
30
|
+
import { z } from "zod";
|
|
31
|
+
|
|
32
|
+
// Define your form schema with Zod
|
|
33
|
+
const userSchema = z.object({
|
|
34
|
+
name: z.string().min(1, "Name is required"),
|
|
35
|
+
email: z.string().email("Invalid email"),
|
|
36
|
+
contacts: z
|
|
37
|
+
.array(
|
|
38
|
+
z.object({
|
|
39
|
+
phone: z.string().min(1, "Phone is required"),
|
|
40
|
+
type: z.enum(["home", "work", "mobile"]),
|
|
41
|
+
})
|
|
42
|
+
)
|
|
43
|
+
.min(1, "At least one contact is required"),
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
function UserForm() {
|
|
47
|
+
const form = useForm({
|
|
48
|
+
defaultValues: {
|
|
49
|
+
name: "",
|
|
50
|
+
email: "",
|
|
51
|
+
contacts: [{ phone: "", type: "mobile" }],
|
|
52
|
+
},
|
|
53
|
+
// Optional: Uncomment to enable Zod validation
|
|
54
|
+
// schema: userSchema,
|
|
55
|
+
onSubmit: (data) => {
|
|
56
|
+
console.log("Form submitted:", data);
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const contacts = form.array("contacts");
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<Form use={form}>
|
|
64
|
+
<Field name="name" label="Full Name" />
|
|
65
|
+
<Field name="email" type="email" label="Email" />
|
|
66
|
+
|
|
67
|
+
{/* Dynamic array fields */}
|
|
68
|
+
{contacts.value.map((contact, index) => (
|
|
69
|
+
<div key={index}>
|
|
70
|
+
<Field
|
|
71
|
+
name={`contacts.${index}.phone`}
|
|
72
|
+
label={`Phone ${index + 1}`}
|
|
73
|
+
/>
|
|
74
|
+
<Field name={`contacts.${index}.type`} as="select" label="Type">
|
|
75
|
+
<option value="home">Home</option>
|
|
76
|
+
<option value="work">Work</option>
|
|
77
|
+
<option value="mobile">Mobile</option>
|
|
78
|
+
</Field>
|
|
79
|
+
<button type="button" onClick={() => contacts.remove(index)}>
|
|
80
|
+
Remove
|
|
81
|
+
</button>
|
|
82
|
+
</div>
|
|
83
|
+
))}
|
|
84
|
+
|
|
85
|
+
<button
|
|
86
|
+
type="button"
|
|
87
|
+
onClick={() => contacts.push({ phone: "", type: "mobile" })}
|
|
88
|
+
>
|
|
89
|
+
Add Contact
|
|
90
|
+
</button>
|
|
91
|
+
|
|
92
|
+
<button type="submit">Submit</button>
|
|
93
|
+
</Form>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Core Concepts
|
|
99
|
+
|
|
100
|
+
### `useForm` Hook
|
|
101
|
+
|
|
102
|
+
The `useForm` hook is the heart of Formly. It manages the form state and provides methods to interact with the form.
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
const form = useForm({
|
|
106
|
+
defaultValues: {
|
|
107
|
+
/* ... */
|
|
108
|
+
},
|
|
109
|
+
// Optional: Zod schema for validation
|
|
110
|
+
schema: userSchema,
|
|
111
|
+
// Optional: Custom validation function
|
|
112
|
+
check: (values) => {
|
|
113
|
+
const errors = {};
|
|
114
|
+
if (!values.name) errors.name = "Name is required";
|
|
115
|
+
return errors;
|
|
116
|
+
},
|
|
117
|
+
// Form submission handler
|
|
118
|
+
onSubmit: async (values, ctx) => {
|
|
119
|
+
console.log("Form values:", values);
|
|
120
|
+
},
|
|
121
|
+
// Persist form state
|
|
122
|
+
persistKey: "myFormState",
|
|
123
|
+
});
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### `Field` Component
|
|
127
|
+
|
|
128
|
+
Render form inputs with automatic state management and validation.
|
|
129
|
+
|
|
130
|
+
```tsx
|
|
131
|
+
<Field
|
|
132
|
+
name="email"
|
|
133
|
+
label="Email Address"
|
|
134
|
+
placeholder="Enter your email"
|
|
135
|
+
required
|
|
136
|
+
render={(props, ctx) => <input {...props} type="email" />}
|
|
137
|
+
/>
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### `useField` Hook
|
|
141
|
+
|
|
142
|
+
Access and modify a specific field's state and helpers.
|
|
143
|
+
|
|
144
|
+
```tsx
|
|
145
|
+
function EmailField() {
|
|
146
|
+
const { value, setValue, error, touched } = useField("email");
|
|
147
|
+
|
|
148
|
+
return (
|
|
149
|
+
<div>
|
|
150
|
+
<input
|
|
151
|
+
type="email"
|
|
152
|
+
value={value || ""}
|
|
153
|
+
onChange={(e) => setValue(e.target.value)}
|
|
154
|
+
className={touched && error ? "error" : ""}
|
|
155
|
+
/>
|
|
156
|
+
{touched && error && <div className="error-message">{error}</div>}
|
|
157
|
+
</div>
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Array Fields
|
|
163
|
+
|
|
164
|
+
Easily manage dynamic arrays of fields.
|
|
165
|
+
|
|
166
|
+
```tsx
|
|
167
|
+
const todos = form.array("todos");
|
|
168
|
+
|
|
169
|
+
// Add item
|
|
170
|
+
todos.push({ text: "", completed: false });
|
|
171
|
+
|
|
172
|
+
// Update item
|
|
173
|
+
todos.update(0, { text: "Updated todo", completed: true });
|
|
174
|
+
|
|
175
|
+
// Remove item
|
|
176
|
+
todos.remove(0);
|
|
177
|
+
|
|
178
|
+
// Move item
|
|
179
|
+
todos.move(0, 1);
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Advanced Usage
|
|
183
|
+
|
|
184
|
+
### Conditional Fields
|
|
185
|
+
|
|
186
|
+
```tsx
|
|
187
|
+
const showAddress = form.watch("hasAddress");
|
|
188
|
+
|
|
189
|
+
return (
|
|
190
|
+
<>
|
|
191
|
+
<Field name="hasAddress" type="checkbox" label="Add address?" />
|
|
192
|
+
|
|
193
|
+
{showAddress && (
|
|
194
|
+
<div className="address-fields">
|
|
195
|
+
<Field name="address.street" label="Street" />
|
|
196
|
+
<Field name="address.city" label="City" />
|
|
197
|
+
<Field name="address.zip" label="ZIP Code" />
|
|
198
|
+
</div>
|
|
199
|
+
)}
|
|
200
|
+
</>
|
|
201
|
+
);
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## API Reference
|
|
205
|
+
|
|
206
|
+
### `useForm` Options
|
|
207
|
+
|
|
208
|
+
| Option | Type | Description |
|
|
209
|
+
| ------------------ | ----------------------- | ----------------------------------------- |
|
|
210
|
+
| `defaultValues` | `object` | Initial form values |
|
|
211
|
+
| `schema` | `z.ZodSchema` | Zod schema for validation |
|
|
212
|
+
| `check` | `(values) => object` | Custom validation function |
|
|
213
|
+
| `onSubmit` | `(values, ctx) => void` | Form submission handler |
|
|
214
|
+
| `persistKey` | `string` | Key to persist form state in localStorage |
|
|
215
|
+
| `autoFocusOnError` | `boolean` | Auto-focus first invalid field |
|
|
216
|
+
|
|
217
|
+
### Form Methods
|
|
218
|
+
|
|
219
|
+
| Method | Description |
|
|
220
|
+
| ---------------------------- | ---------------------------------------- |
|
|
221
|
+
| `submit()` | Submit the form programmatically |
|
|
222
|
+
| `reset(values?)` | Reset form to initial or provided values |
|
|
223
|
+
| `setValues(values)` | Set multiple field values |
|
|
224
|
+
| `setFieldValue(path, value)` | Set a single field value |
|
|
225
|
+
| `setErrors(errors)` | Set form errors |
|
|
226
|
+
| `setFieldError(path, error)` | Set error for a specific field |
|
|
227
|
+
| `validate()` | Trigger validation |
|
|
228
|
+
| `watch(path?)` | Watch form or specific field values |
|
|
229
|
+
| `array(path)` | Get array field helpers |
|
|
230
|
+
| `group(path)` | Get nested form group helpers |
|
|
231
|
+
|
|
232
|
+
## TypeScript Support
|
|
233
|
+
|
|
234
|
+
Formly is built with TypeScript and provides excellent type safety:
|
|
235
|
+
|
|
236
|
+
```ts
|
|
237
|
+
interface UserForm {
|
|
238
|
+
name: string;
|
|
239
|
+
email: string;
|
|
240
|
+
contacts: {
|
|
241
|
+
phone: string;
|
|
242
|
+
type: "home" | "work" | "mobile";
|
|
243
|
+
}[];
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const form = useForm<UserForm>({
|
|
247
|
+
defaultValues: {
|
|
248
|
+
name: "",
|
|
249
|
+
email: "",
|
|
250
|
+
contacts: [],
|
|
251
|
+
},
|
|
252
|
+
});
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## License
|
|
256
|
+
|
|
257
|
+
MIT © [Explita](https://github.com/explita)
|
|
258
|
+
|
|
259
|
+
## Contributing
|
|
260
|
+
|
|
261
|
+
Contributions are welcome! Please open an issue or submit a pull request.
|
package/README.old.md
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
⚠️ Using register() is convenient for quick input wiring, but for large forms where performance matters, prefer useField or Field to avoid unnecessary re-renders.
|
|
2
|
+
|
|
3
|
+
For performance and clarity, here’s the usual pattern I’d recommend:
|
|
4
|
+
|
|
5
|
+
<form.Field /> (from form instance) or standalone <Field />
|
|
6
|
+
|
|
7
|
+
Best for most use cases.
|
|
8
|
+
|
|
9
|
+
Handles binding, errors, and local reactivity automatically.
|
|
10
|
+
|
|
11
|
+
Encapsulates the field logic, so the parent form doesn’t rerender on every change.
|
|
12
|
+
|
|
13
|
+
Easy to drop into JSX and add labels, wrappers, or custom styling.
|
|
14
|
+
|
|
15
|
+
useField() inside a separate component
|
|
16
|
+
|
|
17
|
+
Great when you want full programmatic control over the field.
|
|
18
|
+
|
|
19
|
+
Can wrap a custom input or a complex component.
|
|
20
|
+
|
|
21
|
+
Keeps reactivity local to the component.
|
|
22
|
+
|
|
23
|
+
Allows you to do more advanced things like computed values, conditional logic, or side effects specific to that field.
|
|
24
|
+
|
|
25
|
+
✅ Rule of thumb:
|
|
26
|
+
|
|
27
|
+
If you just need a simple form input, use <Field /> — minimal boilerplate, good defaults.
|
|
28
|
+
|
|
29
|
+
If you need custom behavior or a completely custom component, wrap it with a component using useField().
|
|
30
|
+
|
|
31
|
+
This way, the form itself stays light and doesn’t rerender unnecessarily, while each field manages its own state efficiently.
|
|
32
|
+
|
|
33
|
+
# @explita/formly
|
|
34
|
+
|
|
35
|
+
A powerful and extensible React form hook for building scalable forms with Zod validation, persistence, and full control.
|
|
36
|
+
|
|
37
|
+
## ✨ Features
|
|
38
|
+
|
|
39
|
+
- ✅ Built-in Zod schema validation
|
|
40
|
+
- ✅ Controlled and uncontrolled modes
|
|
41
|
+
- ✅ Persistent form state via `localStorage`
|
|
42
|
+
- ✅ Field-level error handling and parsing
|
|
43
|
+
- ✅ Debounced input validation
|
|
44
|
+
- ✅ Works seamlessly with any UI library (e.g. shadcn/ui)
|
|
45
|
+
|
|
46
|
+
## 📦 Installation
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm install @explita/formly
|
|
50
|
+
# or
|
|
51
|
+
yarn add @explita/formly
|
|
52
|
+
# or
|
|
53
|
+
pnpm add @explita/formly
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## 🧪 Usage
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
import { z } from "zod";
|
|
60
|
+
import { useForm, Form, Field } from "@explita/formly";
|
|
61
|
+
import { Input } from "@/components/ui/input";
|
|
62
|
+
|
|
63
|
+
const schema = z.object({
|
|
64
|
+
email: z.email({ error: "Invalid email" }),
|
|
65
|
+
password: z
|
|
66
|
+
.string()
|
|
67
|
+
.min(6, { error: "Password must be at least 6 characters" }),
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
export default function LoginForm() {
|
|
71
|
+
const form = useForm({
|
|
72
|
+
schema,
|
|
73
|
+
defaultValues: { email: "", password: "" },
|
|
74
|
+
onSubmit: async (values) => {
|
|
75
|
+
console.log("Submitted", values);
|
|
76
|
+
// call server action here or perform an HTTP request
|
|
77
|
+
// const response = await login(values)
|
|
78
|
+
// return response
|
|
79
|
+
return values;
|
|
80
|
+
},
|
|
81
|
+
onSuccess: (result, ctx) => {
|
|
82
|
+
console.log("Success", result);
|
|
83
|
+
// result is the result of onSubmit
|
|
84
|
+
// ctx.reset(); - reset the form, you don't need this if resetOnSuccess is true
|
|
85
|
+
},
|
|
86
|
+
onError: (error, ctx) => {
|
|
87
|
+
console.log("Error", error, ctx);
|
|
88
|
+
// error - the error object (usually from schema or server)
|
|
89
|
+
// ctx.setErrors({ email: "Email is required" }); - useful for server errors
|
|
90
|
+
},
|
|
91
|
+
persistKey: "login-form", // Optional – saves input across reloads
|
|
92
|
+
errorParser: (msg) => msg, // Optional – customize error messages
|
|
93
|
+
mode: "controlled", // Optional – "controlled" is the default
|
|
94
|
+
resetOnSuccess: true, // Optional – clears the form on success
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
//Field meta is an object that contains the value, error, and hasError properties
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<Form use={form}>
|
|
101
|
+
<Field name="email" label="Email" isRequired>
|
|
102
|
+
{(props, meta) => <Input {...props} />}
|
|
103
|
+
</Field>
|
|
104
|
+
|
|
105
|
+
<Field name="password" label="Password" isRequired>
|
|
106
|
+
{(props, meta) => <Input type="password" {...props} />}
|
|
107
|
+
</Field>
|
|
108
|
+
|
|
109
|
+
<button type="submit" disabled={form.isSubmitting}>
|
|
110
|
+
Submit
|
|
111
|
+
</button>
|
|
112
|
+
</Form>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## 🧩 API Overview
|
|
118
|
+
|
|
119
|
+
### `useForm(options)`
|
|
120
|
+
|
|
121
|
+
| Option | Type | Description |
|
|
122
|
+
| ---------------- | ------------------------------------- | ------------------------------------------- |
|
|
123
|
+
| `schema` | `ZodObject` | Optional Zod schema for validation |
|
|
124
|
+
| `defaultValues` | `Partial<T>` | Initial form values |
|
|
125
|
+
| `onSubmit` | `(values, formData) => Promise<void>` | Async submission handler |
|
|
126
|
+
| `onSuccess` | `(result) => void` | Called on successful submission |
|
|
127
|
+
| `onError` | `(error, ctx) => void` | Called on error, with access to `setErrors` |
|
|
128
|
+
| `persistKey` | `string` | Key to store form values under |
|
|
129
|
+
| `errorParser` | `(msg: string) => string` | Optional formatter for error messages |
|
|
130
|
+
| `mode` | `controlled`\|`uncontrolled` | Default to controlled |
|
|
131
|
+
| `resetOnSuccess` | `boolean` | Clear the form on successful submission |
|
|
132
|
+
|
|
133
|
+
### `useFormContext()`
|
|
134
|
+
|
|
135
|
+
Can be used in any component nested inside the `Form` component to access the form context.
|
|
136
|
+
|
|
137
|
+
##
|
|
138
|
+
|
|
139
|
+
### 📄 License
|
|
140
|
+
|
|
141
|
+
MIT — Made with ❤️ by [Explita](https://explita.ng)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.FieldError = FieldError;
|
|
7
|
+
const react_1 = __importDefault(require("react"));
|
|
8
|
+
const __1 = require("../");
|
|
9
|
+
function FieldError() {
|
|
10
|
+
const { message } = (0, __1.useFieldContext)();
|
|
11
|
+
if (!message)
|
|
12
|
+
return null;
|
|
13
|
+
return (react_1.default.createElement("p", { "data-error": "true", style: { color: "red", fontSize: "0.75rem" } }, message));
|
|
14
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { JSX } from "react";
|
|
2
|
+
import { FieldContextType, FieldProps } from "../types/utils";
|
|
3
|
+
export declare function useFieldContext(): FieldContextType;
|
|
4
|
+
export declare function Field<T>({ name, id, label, as, required, hideError, className, children, render, ...rest }: FieldProps<T>): JSX.Element;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.useFieldContext = useFieldContext;
|
|
37
|
+
exports.Field = Field;
|
|
38
|
+
const react_1 = __importStar(require("react"));
|
|
39
|
+
const __1 = require("../");
|
|
40
|
+
const FieldContext = (0, react_1.createContext)(null);
|
|
41
|
+
function useFieldContext() {
|
|
42
|
+
const fieldContext = (0, react_1.use)(FieldContext);
|
|
43
|
+
if (!fieldContext) {
|
|
44
|
+
return {
|
|
45
|
+
name: "",
|
|
46
|
+
label: "",
|
|
47
|
+
id: "",
|
|
48
|
+
message: "",
|
|
49
|
+
required: false,
|
|
50
|
+
hasError: false,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
return fieldContext;
|
|
54
|
+
}
|
|
55
|
+
function Field({ name, id, label, as, required, hideError = false, className, children, render, ...rest }) {
|
|
56
|
+
//@ts-ignore
|
|
57
|
+
const field = (0, __1.useField)(name, { ...rest });
|
|
58
|
+
// Pick whichever function/render prop is provided
|
|
59
|
+
const renderFn = children || render;
|
|
60
|
+
if (!renderFn)
|
|
61
|
+
return react_1.default.createElement(react_1.default.Fragment, null);
|
|
62
|
+
const bind = {
|
|
63
|
+
...field.bind(),
|
|
64
|
+
id: id !== null && id !== void 0 ? id : field.refId,
|
|
65
|
+
};
|
|
66
|
+
const value = field.value;
|
|
67
|
+
const error = field.error;
|
|
68
|
+
const hasFieldError = error && (error === null || error === void 0 ? void 0 : error.length) > 0 ? true : false;
|
|
69
|
+
const hasError = !hideError && hasFieldError;
|
|
70
|
+
const setValue = field.setValue;
|
|
71
|
+
const isBoolean = as === "checkbox";
|
|
72
|
+
const fieldContextValue = {
|
|
73
|
+
name: name === null || name === void 0 ? void 0 : name.toString(),
|
|
74
|
+
label,
|
|
75
|
+
id: bind.id,
|
|
76
|
+
message: error,
|
|
77
|
+
required,
|
|
78
|
+
hasError,
|
|
79
|
+
};
|
|
80
|
+
const meta = {
|
|
81
|
+
internalRef: field.refId,
|
|
82
|
+
name,
|
|
83
|
+
value,
|
|
84
|
+
error,
|
|
85
|
+
hasError: hasFieldError !== null && hasFieldError !== void 0 ? hasFieldError : false,
|
|
86
|
+
onChange: field.setValue,
|
|
87
|
+
};
|
|
88
|
+
if (isBoolean) {
|
|
89
|
+
return (react_1.default.createElement(FieldContext, { value: fieldContextValue }, renderFn({
|
|
90
|
+
...bind,
|
|
91
|
+
//@ts-ignore
|
|
92
|
+
checked: !!value,
|
|
93
|
+
onCheckedChange: (val) => {
|
|
94
|
+
setValue(val);
|
|
95
|
+
},
|
|
96
|
+
}, meta)));
|
|
97
|
+
}
|
|
98
|
+
if (as === "select" || as === "date") {
|
|
99
|
+
return (react_1.default.createElement(FieldContext, { value: fieldContextValue },
|
|
100
|
+
react_1.default.createElement("div", { "data-slot": "field", style: { display: "flex", flexDirection: "column", gap: "0.25rem" }, className: className },
|
|
101
|
+
react_1.default.createElement(__1.Label, null),
|
|
102
|
+
renderFn({
|
|
103
|
+
...bind,
|
|
104
|
+
//@ts-ignore
|
|
105
|
+
onValueChange: (val) => {
|
|
106
|
+
setValue(val);
|
|
107
|
+
},
|
|
108
|
+
"data-input-error": hasError,
|
|
109
|
+
}, meta),
|
|
110
|
+
hasError && react_1.default.createElement(__1.FieldError, null))));
|
|
111
|
+
}
|
|
112
|
+
return (react_1.default.createElement(FieldContext, { value: fieldContextValue },
|
|
113
|
+
react_1.default.createElement("div", { "data-slot": "field", style: { display: "flex", flexDirection: "column", gap: "0.25rem" }, className: className },
|
|
114
|
+
react_1.default.createElement(__1.Label, null),
|
|
115
|
+
renderFn({
|
|
116
|
+
...bind,
|
|
117
|
+
"data-input-error": hasError,
|
|
118
|
+
}, meta),
|
|
119
|
+
hasError && react_1.default.createElement(__1.FieldError, null))));
|
|
120
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { JSX, ReactNode } from "react";
|
|
2
|
+
import { FormContextValue } from "../providers/form";
|
|
3
|
+
import { Path, PathValue } from "../types/path";
|
|
4
|
+
export declare function FormSpy<DefaultValues extends Record<string, any>, P extends Path<DefaultValues>>({ form, watch, render, }: {
|
|
5
|
+
form: FormContextValue<undefined, DefaultValues>;
|
|
6
|
+
render: (selected: PathValue<DefaultValues, P>) => ReactNode;
|
|
7
|
+
watch: P;
|
|
8
|
+
}): JSX.Element;
|
|
9
|
+
export declare function FormSpy<DefaultValues extends Record<string, any>, P extends Path<DefaultValues>>({ form, render, }: {
|
|
10
|
+
form: FormContextValue<undefined, DefaultValues>;
|
|
11
|
+
render: (selected: DefaultValues) => ReactNode;
|
|
12
|
+
}): JSX.Element;
|
|
13
|
+
export declare function FormSpyDebug<DefaultValues extends Record<string, any>>({ form, watch, }: {
|
|
14
|
+
form: FormContextValue<undefined, DefaultValues>;
|
|
15
|
+
watch?: Path<DefaultValues>;
|
|
16
|
+
}): JSX.Element;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.FormSpy = FormSpy;
|
|
37
|
+
exports.FormSpyDebug = FormSpyDebug;
|
|
38
|
+
const react_1 = __importStar(require("react"));
|
|
39
|
+
function FormSpy({ form, watch, render, }) {
|
|
40
|
+
const [selected, setSelected] = (0, react_1.useState)(() => watch ? form.field(watch).get() : form.values);
|
|
41
|
+
const prevRef = (0, react_1.useRef)(selected);
|
|
42
|
+
(0, react_1.useEffect)(() => {
|
|
43
|
+
const unsubscribe = form.subscribe((values) => {
|
|
44
|
+
const next = watch ? form.field(watch).get() : values;
|
|
45
|
+
if (JSON.stringify(prevRef.current) !== JSON.stringify(next)) {
|
|
46
|
+
prevRef.current = next;
|
|
47
|
+
setSelected(next);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
return unsubscribe;
|
|
51
|
+
}, [form, watch]);
|
|
52
|
+
return react_1.default.createElement(react_1.default.Fragment, null, render(selected));
|
|
53
|
+
}
|
|
54
|
+
function FormSpyDebug({ form, watch, }) {
|
|
55
|
+
return (react_1.default.createElement(FormSpy, { form: form,
|
|
56
|
+
//@ts-ignore
|
|
57
|
+
watch: watch, render: (v) => (react_1.default.createElement("pre", { style: {
|
|
58
|
+
whiteSpace: "pre-wrap", // allow wrapping
|
|
59
|
+
wordBreak: "break-word", // break long words
|
|
60
|
+
overflowWrap: "break-word", // extra safety
|
|
61
|
+
background: "#f5f5f5",
|
|
62
|
+
padding: "10px",
|
|
63
|
+
borderRadius: "4px",
|
|
64
|
+
width: "100%",
|
|
65
|
+
} }, JSON.stringify(v, null, 2))) }));
|
|
66
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./field"), exports);
|
|
18
|
+
__exportStar(require("./field-error"), exports);
|
|
19
|
+
__exportStar(require("./form-spy"), exports);
|
|
20
|
+
__exportStar(require("./label"), exports);
|