@coherent.js/forms 1.0.0-beta.2 → 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 +304 -0
- package/dist/index.js +1 -1
- package/package.json +4 -3
package/README.md
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
# @coherent.js/forms
|
|
2
|
+
|
|
3
|
+
Comprehensive forms handling and validation utilities for Coherent.js applications.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @coherent.js/forms
|
|
9
|
+
# or
|
|
10
|
+
pnpm add @coherent.js/forms
|
|
11
|
+
# or
|
|
12
|
+
yarn add @coherent.js/forms
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Overview
|
|
16
|
+
|
|
17
|
+
The `@coherent.js/forms` package provides powerful form handling capabilities including:
|
|
18
|
+
|
|
19
|
+
- Form state management
|
|
20
|
+
- Validation with built-in validators
|
|
21
|
+
- Error handling and display
|
|
22
|
+
- Form serialization and submission
|
|
23
|
+
- Integration with Coherent.js components
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
```javascript
|
|
28
|
+
import { createForm } from '@coherent.js/forms';
|
|
29
|
+
import { validators } from '@coherent.js/state';
|
|
30
|
+
|
|
31
|
+
const contactForm = createForm({
|
|
32
|
+
fields: {
|
|
33
|
+
email: {
|
|
34
|
+
value: '',
|
|
35
|
+
validators: [validators.email('Please enter a valid email')]
|
|
36
|
+
},
|
|
37
|
+
message: {
|
|
38
|
+
value: '',
|
|
39
|
+
validators: [validators.minLength(10, 'Message must be at least 10 characters')]
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
function ContactForm() {
|
|
45
|
+
const handleSubmit = async (event) => {
|
|
46
|
+
event.preventDefault();
|
|
47
|
+
|
|
48
|
+
if (contactForm.validate()) {
|
|
49
|
+
// Form is valid, submit data
|
|
50
|
+
await submitFormData(contactForm.values);
|
|
51
|
+
contactForm.reset();
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
form: {
|
|
57
|
+
onsubmit: handleSubmit,
|
|
58
|
+
children: [
|
|
59
|
+
{
|
|
60
|
+
input: {
|
|
61
|
+
type: 'email',
|
|
62
|
+
value: contactForm.fields.email.value,
|
|
63
|
+
oninput: (e) => contactForm.setField('email', e.target.value),
|
|
64
|
+
className: contactForm.fields.email.error ? 'error' : ''
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
span: {
|
|
69
|
+
text: contactForm.fields.email.error || '',
|
|
70
|
+
className: 'error-message'
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
textarea: {
|
|
75
|
+
value: contactForm.fields.message.value,
|
|
76
|
+
oninput: (e) => contactForm.setField('message', e.target.value),
|
|
77
|
+
className: contactForm.fields.message.error ? 'error' : ''
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
span: {
|
|
82
|
+
text: contactForm.fields.message.error || '',
|
|
83
|
+
className: 'error-message'
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
button: {
|
|
88
|
+
type: 'submit',
|
|
89
|
+
text: 'Send Message',
|
|
90
|
+
disabled: contactForm.isSubmitting
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Features
|
|
100
|
+
|
|
101
|
+
### Form State Management
|
|
102
|
+
|
|
103
|
+
Automatically manage form state including values, errors, and submission status:
|
|
104
|
+
|
|
105
|
+
```javascript
|
|
106
|
+
const form = createForm({
|
|
107
|
+
fields: {
|
|
108
|
+
username: { value: '' },
|
|
109
|
+
password: { value: '' }
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// Access form values
|
|
114
|
+
console.log(form.values); // { username: '', password: '' }
|
|
115
|
+
|
|
116
|
+
// Update field values
|
|
117
|
+
form.setField('username', 'john_doe');
|
|
118
|
+
|
|
119
|
+
// Check form validity
|
|
120
|
+
console.log(form.isValid); // true/false
|
|
121
|
+
|
|
122
|
+
// Check submission status
|
|
123
|
+
console.log(form.isSubmitting); // true/false
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Validation
|
|
127
|
+
|
|
128
|
+
Built-in validators with custom validation support:
|
|
129
|
+
|
|
130
|
+
```javascript
|
|
131
|
+
import { validators } from '@coherent.js/state';
|
|
132
|
+
|
|
133
|
+
const form = createForm({
|
|
134
|
+
fields: {
|
|
135
|
+
email: {
|
|
136
|
+
value: '',
|
|
137
|
+
validators: [
|
|
138
|
+
validators.required('Email is required'),
|
|
139
|
+
validators.email('Please enter a valid email')
|
|
140
|
+
]
|
|
141
|
+
},
|
|
142
|
+
age: {
|
|
143
|
+
value: '',
|
|
144
|
+
validators: [
|
|
145
|
+
validators.required('Age is required'),
|
|
146
|
+
validators.min(18, 'Must be at least 18 years old')
|
|
147
|
+
]
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// Custom validator
|
|
153
|
+
const customValidator = (value) => {
|
|
154
|
+
if (value && value.length < 5) {
|
|
155
|
+
return 'Value must be at least 5 characters';
|
|
156
|
+
}
|
|
157
|
+
return null; // null means valid
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
const formWithCustomValidation = createForm({
|
|
161
|
+
fields: {
|
|
162
|
+
customField: {
|
|
163
|
+
value: '',
|
|
164
|
+
validators: [customValidator]
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Async Validation
|
|
171
|
+
|
|
172
|
+
Support for asynchronous validation (e.g., checking if username is available):
|
|
173
|
+
|
|
174
|
+
```javascript
|
|
175
|
+
const asyncValidator = async (value) => {
|
|
176
|
+
if (!value) return null;
|
|
177
|
+
|
|
178
|
+
const response = await fetch(`/api/check-username/${value}`);
|
|
179
|
+
const exists = await response.json();
|
|
180
|
+
|
|
181
|
+
return exists ? 'Username is already taken' : null;
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
const signupForm = createForm({
|
|
185
|
+
fields: {
|
|
186
|
+
username: {
|
|
187
|
+
value: '',
|
|
188
|
+
validators: [asyncValidator]
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## API Reference
|
|
195
|
+
|
|
196
|
+
### createForm(options)
|
|
197
|
+
|
|
198
|
+
Create a new form instance.
|
|
199
|
+
|
|
200
|
+
**Parameters:**
|
|
201
|
+
- `options.fields` - Object defining form fields and their initial state
|
|
202
|
+
- `options.onSubmit` - Optional function to handle form submission
|
|
203
|
+
|
|
204
|
+
**Returns:** Form instance with methods and properties
|
|
205
|
+
|
|
206
|
+
### Form Instance Properties
|
|
207
|
+
|
|
208
|
+
- `values` - Current form values
|
|
209
|
+
- `fields` - Field state objects with value, error, touched, etc.
|
|
210
|
+
- `isValid` - Boolean indicating if form is valid
|
|
211
|
+
- `isSubmitting` - Boolean indicating if form is being submitted
|
|
212
|
+
- `errors` - Object containing field errors
|
|
213
|
+
|
|
214
|
+
### Form Instance Methods
|
|
215
|
+
|
|
216
|
+
- `setField(name, value)` - Update a field's value
|
|
217
|
+
- `validate()` - Validate all fields, returns boolean
|
|
218
|
+
- `reset()` - Reset form to initial state
|
|
219
|
+
- `submit()` - Trigger form submission
|
|
220
|
+
|
|
221
|
+
## Integration with @coherent.js/state
|
|
222
|
+
|
|
223
|
+
The forms package integrates seamlessly with the reactive state system:
|
|
224
|
+
|
|
225
|
+
```javascript
|
|
226
|
+
import { createForm } from '@coherent.js/forms';
|
|
227
|
+
import { observable } from '@coherent.js/state';
|
|
228
|
+
|
|
229
|
+
// Create reactive form
|
|
230
|
+
const form = createForm({
|
|
231
|
+
fields: {
|
|
232
|
+
search: { value: '' }
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
// Create observable for search results
|
|
237
|
+
const searchResults = observable([]);
|
|
238
|
+
|
|
239
|
+
// Update search results when form changes
|
|
240
|
+
form.fields.search.watch((newValue) => {
|
|
241
|
+
if (newValue.length > 2) {
|
|
242
|
+
performSearch(newValue).then(results => {
|
|
243
|
+
searchResults.value = results;
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## Examples
|
|
250
|
+
|
|
251
|
+
### Login Form
|
|
252
|
+
|
|
253
|
+
```javascript
|
|
254
|
+
import { createForm } from '@coherent.js/forms';
|
|
255
|
+
import { validators } from '@coherent.js/state';
|
|
256
|
+
|
|
257
|
+
const loginForm = createForm({
|
|
258
|
+
fields: {
|
|
259
|
+
email: {
|
|
260
|
+
value: '',
|
|
261
|
+
validators: [
|
|
262
|
+
validators.required('Email is required'),
|
|
263
|
+
validators.email('Please enter a valid email')
|
|
264
|
+
]
|
|
265
|
+
},
|
|
266
|
+
password: {
|
|
267
|
+
value: '',
|
|
268
|
+
validators: [
|
|
269
|
+
validators.required('Password is required'),
|
|
270
|
+
validators.minLength(8, 'Password must be at least 8 characters')
|
|
271
|
+
]
|
|
272
|
+
}
|
|
273
|
+
},
|
|
274
|
+
async onSubmit(values) {
|
|
275
|
+
try {
|
|
276
|
+
const response = await fetch('/api/login', {
|
|
277
|
+
method: 'POST',
|
|
278
|
+
headers: { 'Content-Type': 'application/json' },
|
|
279
|
+
body: JSON.stringify(values)
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
if (response.ok) {
|
|
283
|
+
// Handle successful login
|
|
284
|
+
window.location.href = '/dashboard';
|
|
285
|
+
} else {
|
|
286
|
+
// Handle login error
|
|
287
|
+
throw new Error('Invalid credentials');
|
|
288
|
+
}
|
|
289
|
+
} catch (error) {
|
|
290
|
+
loginForm.setError('login', error.message);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
## Related Packages
|
|
297
|
+
|
|
298
|
+
- [@coherent.js/state](../state/README.md) - Reactive state management
|
|
299
|
+
- [@coherent.js/core](../core/README.md) - Core framework
|
|
300
|
+
- [@coherent.js/client](../client/README.md) - Client-side utilities
|
|
301
|
+
|
|
302
|
+
## License
|
|
303
|
+
|
|
304
|
+
MIT
|
package/dist/index.js
CHANGED
|
@@ -1664,7 +1664,7 @@ var enhancedForm = createForm();
|
|
|
1664
1664
|
|
|
1665
1665
|
// src/advanced-validation.js
|
|
1666
1666
|
import { ReactiveState, observable, computed } from "@coherent.js/state/src/reactive-state.js";
|
|
1667
|
-
import { globalErrorHandler } from "@coherent.js/core/src/utils/
|
|
1667
|
+
import { globalErrorHandler } from "@coherent.js/core/src/utils/error-handler.js";
|
|
1668
1668
|
var validationRules = {
|
|
1669
1669
|
required: (value, params = true) => {
|
|
1670
1670
|
if (!params) return true;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coherent.js/forms",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.5",
|
|
4
4
|
"description": "SSR + Hydration form system for Coherent.js applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
"author": "Coherent.js Team",
|
|
23
23
|
"license": "MIT",
|
|
24
24
|
"peerDependencies": {
|
|
25
|
-
"@coherent.js/core": "1.0.0-beta.
|
|
26
|
-
"@coherent.js/state": "1.0.0-beta.
|
|
25
|
+
"@coherent.js/core": "1.0.0-beta.5",
|
|
26
|
+
"@coherent.js/state": "1.0.0-beta.5"
|
|
27
27
|
},
|
|
28
28
|
"repository": {
|
|
29
29
|
"type": "git",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"README.md",
|
|
39
39
|
"types/"
|
|
40
40
|
],
|
|
41
|
+
"sideEffects": false,
|
|
41
42
|
"scripts": {
|
|
42
43
|
"build": "node build.mjs",
|
|
43
44
|
"clean": "rm -rf dist"
|