@reformer/core 1.0.0-beta.4 → 1.0.0-beta.5
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 +101 -20
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,14 +3,13 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/@reformer/core)
|
|
4
4
|
[](https://www.npmjs.com/package/@reformer/core)
|
|
5
5
|
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](https://stackblitz.com/~/github.com/AlexandrBukhtatyy/ReFormer/tree/main/projects/react-playground?file=projects/react-playground/src/App.tsx)
|
|
6
7
|
|
|
7
8
|
Reactive form state management library for React with signals-based architecture.
|
|
8
9
|
|
|
9
|
-
##
|
|
10
|
+
## Documentation
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
npm install @reformer/core
|
|
13
|
-
```
|
|
12
|
+
Full documentation is available at [https://alexandrbukhtatyy.github.io/ReFormer/](https://alexandrbukhtatyy.github.io/ReFormer/)
|
|
14
13
|
|
|
15
14
|
## Features
|
|
16
15
|
|
|
@@ -20,33 +19,115 @@ npm install @reformer/core
|
|
|
20
19
|
- TypeScript support
|
|
21
20
|
- Tree-shakeable exports
|
|
22
21
|
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install @reformer/core
|
|
26
|
+
```
|
|
27
|
+
|
|
23
28
|
## Quick Start
|
|
24
29
|
|
|
25
30
|
```tsx
|
|
26
|
-
import {
|
|
31
|
+
import { useMemo } from 'react';
|
|
32
|
+
import {
|
|
33
|
+
createForm,
|
|
34
|
+
useFormControl,
|
|
35
|
+
required,
|
|
36
|
+
email,
|
|
37
|
+
validate,
|
|
38
|
+
watchField,
|
|
39
|
+
FieldNode,
|
|
40
|
+
} from '@reformer/core';
|
|
27
41
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
42
|
+
// 1. Define form interface
|
|
43
|
+
interface RegistrationForm {
|
|
44
|
+
username: string;
|
|
45
|
+
email: string;
|
|
46
|
+
password: string;
|
|
47
|
+
confirmPassword: string;
|
|
48
|
+
}
|
|
34
49
|
|
|
35
|
-
|
|
36
|
-
|
|
50
|
+
// 2. Simple FormField component
|
|
51
|
+
function FormField({ label, control }: { label: string; control: FieldNode<string> }) {
|
|
52
|
+
const { value, errors } = useFormControl(control);
|
|
37
53
|
|
|
38
54
|
return (
|
|
39
|
-
<
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
55
|
+
<div>
|
|
56
|
+
<label>{label}</label>
|
|
57
|
+
<input
|
|
58
|
+
value={value}
|
|
59
|
+
onChange={(e) => control.setValue(e.target.value)}
|
|
60
|
+
onBlur={() => control.markAsTouched()}
|
|
61
|
+
/>
|
|
62
|
+
{errors.length > 0 && <span className="error">{errors[0].message}</span>}
|
|
63
|
+
</div>
|
|
43
64
|
);
|
|
44
65
|
}
|
|
45
|
-
```
|
|
46
66
|
|
|
47
|
-
|
|
67
|
+
// 3. Registration form component
|
|
68
|
+
function RegistrationFormExample() {
|
|
69
|
+
const form = useMemo(
|
|
70
|
+
() =>
|
|
71
|
+
createForm<RegistrationForm>({
|
|
72
|
+
// Form schema
|
|
73
|
+
form: {
|
|
74
|
+
username: { value: '' },
|
|
75
|
+
email: { value: '' },
|
|
76
|
+
password: { value: '' },
|
|
77
|
+
confirmPassword: { value: '' },
|
|
78
|
+
},
|
|
48
79
|
|
|
49
|
-
|
|
80
|
+
// Validation schema
|
|
81
|
+
validation: (path) => {
|
|
82
|
+
required(path.username);
|
|
83
|
+
required(path.email);
|
|
84
|
+
email(path.email);
|
|
85
|
+
required(path.password);
|
|
86
|
+
required(path.confirmPassword);
|
|
87
|
+
|
|
88
|
+
// Cross-field validation: passwords must match
|
|
89
|
+
validate(path.confirmPassword, (value, ctx) => {
|
|
90
|
+
const password = ctx.form.password.value.value;
|
|
91
|
+
if (value && password && value !== password) {
|
|
92
|
+
return { code: 'mismatch', message: 'Passwords do not match' };
|
|
93
|
+
}
|
|
94
|
+
return null;
|
|
95
|
+
});
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
// Behavior schema
|
|
99
|
+
behavior: (path) => {
|
|
100
|
+
// Clear confirmPassword when password changes (if not empty)
|
|
101
|
+
watchField(path.password, (_, ctx) => {
|
|
102
|
+
const confirmValue = ctx.form.confirmPassword.value.value;
|
|
103
|
+
if (confirmValue) {
|
|
104
|
+
ctx.form.confirmPassword.setValue('', { emitEvent: false });
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
},
|
|
108
|
+
}),
|
|
109
|
+
[]
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
const handleSubmit = async (e: React.FormEvent) => {
|
|
113
|
+
e.preventDefault();
|
|
114
|
+
await form.validate();
|
|
115
|
+
if (form.valid.value) {
|
|
116
|
+
console.log('Form data:', form.value.value);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
return (
|
|
121
|
+
<form onSubmit={handleSubmit}>
|
|
122
|
+
<FormField label="Username" control={form.username} />
|
|
123
|
+
<FormField label="Email" control={form.email} />
|
|
124
|
+
<FormField label="Password" control={form.password} />
|
|
125
|
+
<FormField label="Confirm Password" control={form.confirmPassword} />
|
|
126
|
+
<button type="submit">Register</button>
|
|
127
|
+
</form>
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
```
|
|
50
131
|
|
|
51
132
|
## License
|
|
52
133
|
|