@reformer/core 1.1.0-beta.1 → 1.1.0-beta.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.
- package/llms.txt +209 -26
- package/package.json +1 -1
package/llms.txt
CHANGED
|
@@ -6,9 +6,16 @@
|
|
|
6
6
|
|
|
7
7
|
| What | Where |
|
|
8
8
|
| ------------------------------------------------------------------------------------------- | --------------------------- |
|
|
9
|
+
| `createForm`, `useFormControl`, `useFormControlValue` | `@reformer/core` |
|
|
9
10
|
| `ValidationSchemaFn`, `BehaviorSchemaFn`, `FieldPath`, `GroupNodeWithControls`, `FieldNode` | `@reformer/core` |
|
|
10
|
-
| `
|
|
11
|
-
| `
|
|
11
|
+
| `FormSchema`, `FieldConfig`, `ArrayNode` | `@reformer/core` |
|
|
12
|
+
| `required`, `min`, `max`, `minLength`, `maxLength`, `email` | `@reformer/core/validators` |
|
|
13
|
+
| `pattern`, `url`, `phone`, `number`, `date` | `@reformer/core/validators` |
|
|
14
|
+
| `validate`, `validateAsync`, `validateTree`, `applyWhen` | `@reformer/core/validators` |
|
|
15
|
+
| `notEmpty`, `validateItems` | `@reformer/core/validators` |
|
|
16
|
+
| `computeFrom`, `enableWhen`, `disableWhen`, `watchField`, `copyFrom` | `@reformer/core/behaviors` |
|
|
17
|
+
| `resetWhen`, `revalidateWhen`, `syncFields` | `@reformer/core/behaviors` |
|
|
18
|
+
| `transformValue`, `transformers` | `@reformer/core/behaviors` |
|
|
12
19
|
|
|
13
20
|
### Type Values
|
|
14
21
|
|
|
@@ -21,31 +28,68 @@
|
|
|
21
28
|
### Validators
|
|
22
29
|
|
|
23
30
|
```typescript
|
|
31
|
+
// Basic validators
|
|
24
32
|
required(path, options?: { message?: string })
|
|
25
33
|
min(path, value: number, options?: { message?: string })
|
|
26
34
|
max(path, value: number, options?: { message?: string })
|
|
27
35
|
minLength(path, length: number, options?: { message?: string })
|
|
28
36
|
maxLength(path, length: number, options?: { message?: string })
|
|
29
37
|
email(path, options?: { message?: string })
|
|
30
|
-
|
|
31
|
-
|
|
38
|
+
|
|
39
|
+
// Additional validators
|
|
40
|
+
pattern(path, regex: RegExp, options?: { message?: string })
|
|
41
|
+
url(path, options?: { message?: string })
|
|
42
|
+
phone(path, options?: { message?: string; format?: PhoneFormat })
|
|
43
|
+
number(path, options?: { message?: string })
|
|
44
|
+
date(path, options?: { message?: string; minAge?: number; maxAge?: number; noFuture?: boolean; noPast?: boolean })
|
|
45
|
+
|
|
46
|
+
// Custom validators
|
|
47
|
+
validate(path, validator: (value, ctx) => ValidationError | null)
|
|
48
|
+
validateAsync(path, validator: async (value, ctx) => ValidationError | null)
|
|
49
|
+
validateTree(validator: (ctx) => ValidationError | null, options?: { targetField?: string })
|
|
50
|
+
|
|
51
|
+
// Conditional validation
|
|
32
52
|
applyWhen(fieldPath, condition: (fieldValue) => boolean, validatorsFn: (path) => void)
|
|
53
|
+
|
|
54
|
+
// Array validators
|
|
55
|
+
notEmpty(path, options?: { message?: string })
|
|
56
|
+
validateItems(arrayPath, itemValidatorsFn: (itemPath) => void)
|
|
33
57
|
```
|
|
34
58
|
|
|
35
59
|
### Behaviors
|
|
36
60
|
|
|
37
61
|
```typescript
|
|
62
|
+
// Enable/disable fields conditionally
|
|
38
63
|
enableWhen(path, condition: (form) => boolean, options?: { resetOnDisable?: boolean })
|
|
39
64
|
disableWhen(path, condition: (form) => boolean)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
65
|
+
|
|
66
|
+
// Computed fields (same nesting level)
|
|
67
|
+
computeFrom(sourcePaths[], targetPath, compute: (values) => result, options?: { debounce?: number; condition?: (form) => boolean })
|
|
68
|
+
|
|
69
|
+
// Watch field changes
|
|
70
|
+
watchField(path, callback: (value, ctx: BehaviorContext) => void, options?: { immediate?: boolean; debounce?: number })
|
|
71
|
+
|
|
72
|
+
// Copy values between fields
|
|
73
|
+
copyFrom(sourcePath, targetPath, options?: { when?: (form) => boolean; fields?: string[]; transform?: (value) => value })
|
|
74
|
+
|
|
75
|
+
// Reset field when condition met
|
|
76
|
+
resetWhen(path, condition: (form) => boolean, options?: { toValue?: any })
|
|
77
|
+
|
|
78
|
+
// Re-validate when another field changes
|
|
79
|
+
revalidateWhen(triggerPath, targetPath)
|
|
80
|
+
|
|
81
|
+
// Sync multiple fields
|
|
82
|
+
syncFields(paths[], options?: { bidirectional?: boolean })
|
|
83
|
+
|
|
84
|
+
// Transform values
|
|
85
|
+
transformValue(path, transformer: (value) => value, options?: { on?: 'change' | 'blur' })
|
|
86
|
+
transformers.trim, transformers.toUpperCase, transformers.toLowerCase, transformers.toNumber
|
|
43
87
|
|
|
44
88
|
// BehaviorContext interface:
|
|
45
89
|
interface BehaviorContext<TForm> {
|
|
46
|
-
form: TForm
|
|
47
|
-
setFieldValue: (path, value) => void;
|
|
48
|
-
getFieldValue: (path) => unknown;
|
|
90
|
+
form: GroupNodeWithControls<TForm>; // Form proxy with typed field access
|
|
91
|
+
setFieldValue: (path: string, value: any) => void;
|
|
92
|
+
getFieldValue: (path: string) => unknown;
|
|
49
93
|
}
|
|
50
94
|
```
|
|
51
95
|
|
|
@@ -184,30 +228,119 @@ interface MyForm {
|
|
|
184
228
|
}
|
|
185
229
|
```
|
|
186
230
|
|
|
187
|
-
## 8.
|
|
231
|
+
## 8. FORMSCHEMA FORMAT (CRITICALLY IMPORTANT)
|
|
232
|
+
|
|
233
|
+
⚠️ **Every field MUST have `value` and `component` properties!**
|
|
234
|
+
|
|
235
|
+
### FieldConfig Interface
|
|
236
|
+
|
|
237
|
+
```typescript
|
|
238
|
+
interface FieldConfig<T> {
|
|
239
|
+
value: T | null; // Initial value (REQUIRED)
|
|
240
|
+
component: ComponentType; // React component (REQUIRED)
|
|
241
|
+
componentProps?: object; // Props passed to component
|
|
242
|
+
disabled?: boolean; // Disable field initially
|
|
243
|
+
validators?: ValidatorFn[]; // Sync validators
|
|
244
|
+
asyncValidators?: AsyncValidatorFn[]; // Async validators
|
|
245
|
+
updateOn?: 'change' | 'blur' | 'submit';
|
|
246
|
+
debounce?: number;
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Primitive Fields
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
import { Input, Select, Checkbox } from '@/components/ui';
|
|
254
|
+
|
|
255
|
+
const schema: FormSchema<MyForm> = {
|
|
256
|
+
// String field
|
|
257
|
+
name: {
|
|
258
|
+
value: '', // Initial value (REQUIRED)
|
|
259
|
+
component: Input, // React component (REQUIRED)
|
|
260
|
+
componentProps: {
|
|
261
|
+
label: 'Name',
|
|
262
|
+
placeholder: 'Enter name',
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
|
|
266
|
+
// Number field (optional)
|
|
267
|
+
age: {
|
|
268
|
+
value: undefined, // Use undefined, NOT null
|
|
269
|
+
component: Input,
|
|
270
|
+
componentProps: { type: 'number', label: 'Age' },
|
|
271
|
+
},
|
|
272
|
+
|
|
273
|
+
// Boolean field
|
|
274
|
+
agree: {
|
|
275
|
+
value: false,
|
|
276
|
+
component: Checkbox,
|
|
277
|
+
componentProps: { label: 'I agree to terms' },
|
|
278
|
+
},
|
|
279
|
+
|
|
280
|
+
// Enum/Select field
|
|
281
|
+
status: {
|
|
282
|
+
value: 'active',
|
|
283
|
+
component: Select,
|
|
284
|
+
componentProps: {
|
|
285
|
+
label: 'Status',
|
|
286
|
+
options: [
|
|
287
|
+
{ value: 'active', label: 'Active' },
|
|
288
|
+
{ value: 'inactive', label: 'Inactive' },
|
|
289
|
+
],
|
|
290
|
+
},
|
|
291
|
+
},
|
|
292
|
+
};
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### Nested Objects
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
const schema: FormSchema<MyForm> = {
|
|
299
|
+
address: {
|
|
300
|
+
street: { value: '', component: Input, componentProps: { label: 'Street' } },
|
|
301
|
+
city: { value: '', component: Input, componentProps: { label: 'City' } },
|
|
302
|
+
zip: { value: '', component: Input, componentProps: { label: 'ZIP' } },
|
|
303
|
+
},
|
|
304
|
+
};
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Arrays (Tuple Format)
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
const itemSchema = {
|
|
311
|
+
id: { value: '', component: Input, componentProps: { label: 'ID' } },
|
|
312
|
+
name: { value: '', component: Input, componentProps: { label: 'Name' } },
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
const schema: FormSchema<MyForm> = {
|
|
316
|
+
items: [itemSchema], // Array with ONE template item
|
|
317
|
+
};
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### ❌ WRONG - This will NOT compile
|
|
321
|
+
|
|
322
|
+
```typescript
|
|
323
|
+
// Missing value and component - TypeScript will error!
|
|
324
|
+
const schema = {
|
|
325
|
+
name: '', // ❌ Wrong
|
|
326
|
+
email: '', // ❌ Wrong
|
|
327
|
+
};
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### createForm API
|
|
188
331
|
|
|
189
332
|
```typescript
|
|
190
333
|
// Full config with behavior and validation
|
|
191
334
|
const form = createForm<MyForm>({
|
|
192
|
-
form: formSchema, // Required: form schema
|
|
335
|
+
form: formSchema, // Required: form schema with FieldConfig
|
|
193
336
|
behavior: behaviorSchema, // Optional: behavior rules
|
|
194
337
|
validation: validationSchema, // Optional: validation rules
|
|
195
338
|
});
|
|
196
339
|
|
|
197
|
-
//
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
//
|
|
201
|
-
const formSchema: FormSchema<MyForm> = {
|
|
202
|
-
name: '',
|
|
203
|
-
email: '',
|
|
204
|
-
address: {
|
|
205
|
-
street: '',
|
|
206
|
-
city: '',
|
|
207
|
-
},
|
|
208
|
-
// Arrays use tuple format
|
|
209
|
-
items: [{ id: '', name: '' }] as [{ id: string; name: string }],
|
|
210
|
-
};
|
|
340
|
+
// Access form controls
|
|
341
|
+
form.name.setValue('John');
|
|
342
|
+
form.address.city.value.value; // Get current value
|
|
343
|
+
form.items.push({ id: '1', name: 'Item' }); // Array operations
|
|
211
344
|
```
|
|
212
345
|
|
|
213
346
|
## 9. ARRAY SCHEMA FORMAT
|
|
@@ -421,3 +554,53 @@ export const creditApplicationValidation: ValidationSchemaFn<Form> = (path) => {
|
|
|
421
554
|
| Simple | Single file: `ContactForm.tsx` |
|
|
422
555
|
| Medium | Separate files: `type.ts`, `schema.ts`, `validators.ts`, `Form.tsx` |
|
|
423
556
|
| Complex | Full colocation with `steps/` and `sub-forms/` |
|
|
557
|
+
|
|
558
|
+
## 15. NON-EXISTENT API (DO NOT USE)
|
|
559
|
+
|
|
560
|
+
⚠️ **The following APIs do NOT exist in @reformer/core:**
|
|
561
|
+
|
|
562
|
+
| ❌ Wrong | ✅ Correct | Notes |
|
|
563
|
+
|----------|-----------|-------|
|
|
564
|
+
| `useForm` | `createForm` | There is no useForm hook |
|
|
565
|
+
| `FieldSchema` | `FieldConfig<T>` | Type for individual field config |
|
|
566
|
+
| `when()` | `applyWhen()` | Conditional validation function |
|
|
567
|
+
| `FormFields` | `FieldNode<T>` | Type for field nodes |
|
|
568
|
+
|
|
569
|
+
### Common Import Errors
|
|
570
|
+
|
|
571
|
+
```typescript
|
|
572
|
+
// ❌ WRONG - These do NOT exist
|
|
573
|
+
import { useForm } from '@reformer/core'; // NO!
|
|
574
|
+
import { when } from '@reformer/core/validators'; // NO!
|
|
575
|
+
import type { FieldSchema } from '@reformer/core'; // NO!
|
|
576
|
+
import type { FormFields } from '@reformer/core'; // NO!
|
|
577
|
+
|
|
578
|
+
// ✅ CORRECT
|
|
579
|
+
import { createForm, useFormControl } from '@reformer/core';
|
|
580
|
+
import { applyWhen } from '@reformer/core/validators';
|
|
581
|
+
import type { FieldConfig, FieldNode } from '@reformer/core';
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
### FormSchema Common Mistakes
|
|
585
|
+
|
|
586
|
+
```typescript
|
|
587
|
+
// ❌ WRONG - Simple values don't work
|
|
588
|
+
const schema = {
|
|
589
|
+
name: '', // Missing { value, component }
|
|
590
|
+
email: '', // Missing { value, component }
|
|
591
|
+
};
|
|
592
|
+
|
|
593
|
+
// ✅ CORRECT - Every field needs value and component
|
|
594
|
+
const schema: FormSchema<MyForm> = {
|
|
595
|
+
name: {
|
|
596
|
+
value: '',
|
|
597
|
+
component: Input,
|
|
598
|
+
componentProps: { label: 'Name' },
|
|
599
|
+
},
|
|
600
|
+
email: {
|
|
601
|
+
value: '',
|
|
602
|
+
component: Input,
|
|
603
|
+
componentProps: { label: 'Email', type: 'email' },
|
|
604
|
+
},
|
|
605
|
+
};
|
|
606
|
+
```
|