@coherent.js/forms 1.0.0-beta.5 → 1.0.0-beta.7
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/dist/advanced-validation.js +523 -0
- package/dist/advanced-validation.js.map +7 -0
- package/dist/form-builder.js +492 -0
- package/dist/form-builder.js.map +7 -0
- package/dist/form-hydration.js +565 -0
- package/dist/form-hydration.js.map +7 -0
- package/dist/forms.js +432 -0
- package/dist/forms.js.map +7 -0
- package/dist/index.js.map +7 -0
- package/dist/validation.js +186 -0
- package/dist/validation.js.map +7 -0
- package/dist/validators.js +365 -0
- package/dist/validators.js.map +7 -0
- package/package.json +14 -4
- package/types/index.d.ts +361 -38
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
// src/form-builder.js
|
|
2
|
+
var FormBuilder = class {
|
|
3
|
+
constructor(options = {}) {
|
|
4
|
+
this.options = {
|
|
5
|
+
validateOnChange: true,
|
|
6
|
+
validateOnBlur: true,
|
|
7
|
+
name: options.name || "form",
|
|
8
|
+
...options
|
|
9
|
+
};
|
|
10
|
+
this.fields = /* @__PURE__ */ new Map();
|
|
11
|
+
this.groups = /* @__PURE__ */ new Map();
|
|
12
|
+
this.values = {};
|
|
13
|
+
this.errors = {};
|
|
14
|
+
this.touched = {};
|
|
15
|
+
this.initialValues = {};
|
|
16
|
+
this.submitHandler = null;
|
|
17
|
+
this.errorHandler = null;
|
|
18
|
+
this._isSubmitting = false;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Add a field to the form (alias for field)
|
|
22
|
+
*/
|
|
23
|
+
addField(name, config = {}) {
|
|
24
|
+
return this.field(name, config);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Add a field to the form
|
|
28
|
+
*/
|
|
29
|
+
field(name, config = {}) {
|
|
30
|
+
const fieldConfig = {
|
|
31
|
+
name,
|
|
32
|
+
type: config.type || "text",
|
|
33
|
+
label: config.label || name,
|
|
34
|
+
placeholder: config.placeholder || "",
|
|
35
|
+
defaultValue: config.defaultValue || "",
|
|
36
|
+
validators: config.validators || [],
|
|
37
|
+
required: config.required || false,
|
|
38
|
+
visible: config.visible !== false,
|
|
39
|
+
showWhen: config.showWhen,
|
|
40
|
+
...config
|
|
41
|
+
};
|
|
42
|
+
this.fields.set(name, fieldConfig);
|
|
43
|
+
if (config.defaultValue !== void 0) {
|
|
44
|
+
this.values[name] = config.defaultValue;
|
|
45
|
+
this.initialValues[name] = config.defaultValue;
|
|
46
|
+
}
|
|
47
|
+
return this;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Remove a field from the form
|
|
51
|
+
*/
|
|
52
|
+
removeField(name) {
|
|
53
|
+
this.fields.delete(name);
|
|
54
|
+
delete this.values[name];
|
|
55
|
+
delete this.errors[name];
|
|
56
|
+
delete this.touched[name];
|
|
57
|
+
return this;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Update field configuration
|
|
61
|
+
*/
|
|
62
|
+
updateField(name, config) {
|
|
63
|
+
const field = this.fields.get(name);
|
|
64
|
+
if (field) {
|
|
65
|
+
this.fields.set(name, { ...field, ...config });
|
|
66
|
+
}
|
|
67
|
+
return this;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Get all fields as array
|
|
71
|
+
*/
|
|
72
|
+
getFields() {
|
|
73
|
+
return Array.from(this.fields.values());
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Add a field group
|
|
77
|
+
*/
|
|
78
|
+
addGroup(name, config = {}) {
|
|
79
|
+
this.groups.set(name, {
|
|
80
|
+
name,
|
|
81
|
+
label: config.label || name,
|
|
82
|
+
fields: config.fields || [],
|
|
83
|
+
...config
|
|
84
|
+
});
|
|
85
|
+
if (config.fields) {
|
|
86
|
+
config.fields.forEach((fieldConfig) => {
|
|
87
|
+
this.addField(fieldConfig.name, fieldConfig);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
return this;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Get field configuration
|
|
94
|
+
*/
|
|
95
|
+
getField(name) {
|
|
96
|
+
return this.fields.get(name);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Set field value
|
|
100
|
+
*/
|
|
101
|
+
setValue(name, value) {
|
|
102
|
+
this.values[name] = value;
|
|
103
|
+
this.touched[name] = true;
|
|
104
|
+
const field = this.fields.get(name);
|
|
105
|
+
if (field && (field.validateOnChange || this.options.validateOnChange)) {
|
|
106
|
+
this.validateField(name);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Set multiple values
|
|
111
|
+
*/
|
|
112
|
+
setValues(values) {
|
|
113
|
+
Object.assign(this.values, values);
|
|
114
|
+
return this;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Get field value
|
|
118
|
+
*/
|
|
119
|
+
getValue(name) {
|
|
120
|
+
return this.values[name];
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Get all values
|
|
124
|
+
*/
|
|
125
|
+
getValues() {
|
|
126
|
+
return { ...this.values };
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Get field error
|
|
130
|
+
*/
|
|
131
|
+
getFieldError(name) {
|
|
132
|
+
return this.errors[name];
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Check if form has errors
|
|
136
|
+
*/
|
|
137
|
+
hasErrors() {
|
|
138
|
+
return Object.keys(this.errors).length > 0;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Clear all errors
|
|
142
|
+
*/
|
|
143
|
+
clearErrors() {
|
|
144
|
+
this.errors = {};
|
|
145
|
+
return this;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Check if form is dirty (values changed from initial)
|
|
149
|
+
*/
|
|
150
|
+
isDirty() {
|
|
151
|
+
return Object.keys(this.values).some((key) => {
|
|
152
|
+
return this.values[key] !== this.initialValues[key];
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Check if form is valid
|
|
157
|
+
*/
|
|
158
|
+
isValid() {
|
|
159
|
+
const result = this.validate();
|
|
160
|
+
return Object.keys(result).length === 0;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Validate a field
|
|
164
|
+
*/
|
|
165
|
+
validateField(name) {
|
|
166
|
+
const field = this.fields.get(name);
|
|
167
|
+
if (!field) return null;
|
|
168
|
+
const showCondition = field.showWhen || field.showIf;
|
|
169
|
+
if (showCondition && !showCondition(this.values)) {
|
|
170
|
+
delete this.errors[name];
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
const value = this.values[name];
|
|
174
|
+
if (field.required && (value === void 0 || value === null || value === "")) {
|
|
175
|
+
const error = "This field is required";
|
|
176
|
+
this.errors[name] = error;
|
|
177
|
+
return error;
|
|
178
|
+
}
|
|
179
|
+
if (!value && !field.required) {
|
|
180
|
+
delete this.errors[name];
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
if (value) {
|
|
184
|
+
if (field.type === "email") {
|
|
185
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
186
|
+
if (!emailRegex.test(value)) {
|
|
187
|
+
const error = "Please enter a valid email address";
|
|
188
|
+
this.errors[name] = error;
|
|
189
|
+
return error;
|
|
190
|
+
}
|
|
191
|
+
} else if (field.type === "url") {
|
|
192
|
+
try {
|
|
193
|
+
new URL(value);
|
|
194
|
+
} catch {
|
|
195
|
+
const error = "Please enter a valid URL";
|
|
196
|
+
this.errors[name] = error;
|
|
197
|
+
return error;
|
|
198
|
+
}
|
|
199
|
+
} else if (field.type === "number") {
|
|
200
|
+
if (isNaN(Number(value))) {
|
|
201
|
+
const error = "Please enter a valid number";
|
|
202
|
+
this.errors[name] = error;
|
|
203
|
+
return error;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
if (field.validate) {
|
|
208
|
+
const error = field.validate(value, this.values);
|
|
209
|
+
if (error) {
|
|
210
|
+
this.errors[name] = error;
|
|
211
|
+
return error;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
for (const validator of field.validators || []) {
|
|
215
|
+
const error = validator(value, this.values);
|
|
216
|
+
if (error) {
|
|
217
|
+
this.errors[name] = error;
|
|
218
|
+
return error;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
delete this.errors[name];
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Validate all fields
|
|
226
|
+
*/
|
|
227
|
+
validate() {
|
|
228
|
+
const errors = {};
|
|
229
|
+
for (const [name, field] of this.fields) {
|
|
230
|
+
const showCondition = field.showWhen || field.showIf;
|
|
231
|
+
if (showCondition && !showCondition(this.values)) {
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
const error = this.validateField(name);
|
|
235
|
+
if (error) {
|
|
236
|
+
errors[name] = error;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
this.errors = errors;
|
|
240
|
+
return errors;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Set submit handler
|
|
244
|
+
*/
|
|
245
|
+
onSubmit(handler) {
|
|
246
|
+
this.submitHandler = handler;
|
|
247
|
+
return this;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Set error handler
|
|
251
|
+
*/
|
|
252
|
+
onError(handler) {
|
|
253
|
+
this.errorHandler = handler;
|
|
254
|
+
return this;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Submit the form
|
|
258
|
+
*/
|
|
259
|
+
async submit() {
|
|
260
|
+
const errors = this.validate();
|
|
261
|
+
if (Object.keys(errors).length > 0) {
|
|
262
|
+
return { success: false, errors };
|
|
263
|
+
}
|
|
264
|
+
if (!this.submitHandler) {
|
|
265
|
+
return { success: true, data: this.values };
|
|
266
|
+
}
|
|
267
|
+
this._isSubmitting = true;
|
|
268
|
+
try {
|
|
269
|
+
const result = await this.submitHandler(this.values);
|
|
270
|
+
this._isSubmitting = false;
|
|
271
|
+
return { success: true, data: result };
|
|
272
|
+
} catch (error) {
|
|
273
|
+
this._isSubmitting = false;
|
|
274
|
+
if (this.errorHandler) {
|
|
275
|
+
this.errorHandler(error);
|
|
276
|
+
}
|
|
277
|
+
return { success: false, error };
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Serialize form data
|
|
282
|
+
*/
|
|
283
|
+
serialize() {
|
|
284
|
+
return { ...this.values };
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Convert form to HTML string
|
|
288
|
+
*/
|
|
289
|
+
toHTML() {
|
|
290
|
+
const fields = this.getFields();
|
|
291
|
+
let html = `<form name="${this.options.name}">`;
|
|
292
|
+
fields.forEach((field) => {
|
|
293
|
+
html += `<div class="form-field">`;
|
|
294
|
+
html += `<label for="${field.name}">${field.label}</label>`;
|
|
295
|
+
html += `<input type="${field.type}" name="${field.name}" id="${field.name}">`;
|
|
296
|
+
html += `</div>`;
|
|
297
|
+
});
|
|
298
|
+
html += `</form>`;
|
|
299
|
+
return html;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Mark field as touched
|
|
303
|
+
*/
|
|
304
|
+
touch(name) {
|
|
305
|
+
this.touched[name] = true;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Build input component with validation metadata for hydration
|
|
309
|
+
*/
|
|
310
|
+
buildInput(name) {
|
|
311
|
+
const field = this.fields.get(name);
|
|
312
|
+
if (!field) return null;
|
|
313
|
+
const value = this.values[name] || "";
|
|
314
|
+
const error = this.errors[name];
|
|
315
|
+
const isTouched = this.touched[name];
|
|
316
|
+
const validatorNames = field.validators.map((v) => {
|
|
317
|
+
if (typeof v === "function") return v.name || "custom";
|
|
318
|
+
if (typeof v === "string") return v;
|
|
319
|
+
return null;
|
|
320
|
+
}).filter(Boolean).join(",");
|
|
321
|
+
const inputProps = {
|
|
322
|
+
type: field.type,
|
|
323
|
+
name: field.name,
|
|
324
|
+
id: field.name,
|
|
325
|
+
value,
|
|
326
|
+
placeholder: field.placeholder,
|
|
327
|
+
"aria-invalid": error ? "true" : "false",
|
|
328
|
+
"aria-describedby": error ? `${name}-error` : void 0,
|
|
329
|
+
className: error && isTouched ? "error" : ""
|
|
330
|
+
};
|
|
331
|
+
if (field.required) {
|
|
332
|
+
inputProps.required = true;
|
|
333
|
+
inputProps["data-required"] = "true";
|
|
334
|
+
}
|
|
335
|
+
if (validatorNames) {
|
|
336
|
+
inputProps["data-validators"] = validatorNames;
|
|
337
|
+
}
|
|
338
|
+
return {
|
|
339
|
+
input: inputProps
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Build label component
|
|
344
|
+
*/
|
|
345
|
+
buildLabel(name) {
|
|
346
|
+
const field = this.fields.get(name);
|
|
347
|
+
if (!field) return null;
|
|
348
|
+
return {
|
|
349
|
+
label: {
|
|
350
|
+
for: field.name,
|
|
351
|
+
text: field.label
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Build error component
|
|
357
|
+
*/
|
|
358
|
+
buildError(name) {
|
|
359
|
+
const error = this.errors[name];
|
|
360
|
+
const isTouched = this.touched[name];
|
|
361
|
+
if (!error || !isTouched) return null;
|
|
362
|
+
return {
|
|
363
|
+
div: {
|
|
364
|
+
id: `${name}-error`,
|
|
365
|
+
className: "error-message",
|
|
366
|
+
role: "alert",
|
|
367
|
+
text: error
|
|
368
|
+
}
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Build complete field component
|
|
373
|
+
*/
|
|
374
|
+
buildField(name) {
|
|
375
|
+
const field = this.fields.get(name);
|
|
376
|
+
if (!field) return null;
|
|
377
|
+
const children = [
|
|
378
|
+
this.buildLabel(name),
|
|
379
|
+
this.buildInput(name)
|
|
380
|
+
];
|
|
381
|
+
const error = this.buildError(name);
|
|
382
|
+
if (error) {
|
|
383
|
+
children.push(error);
|
|
384
|
+
}
|
|
385
|
+
return {
|
|
386
|
+
div: {
|
|
387
|
+
className: "form-field",
|
|
388
|
+
"data-field": name,
|
|
389
|
+
children
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Build entire form
|
|
395
|
+
*/
|
|
396
|
+
buildForm(options = {}) {
|
|
397
|
+
const fields = [];
|
|
398
|
+
for (const [name] of this.fields) {
|
|
399
|
+
fields.push(this.buildField(name));
|
|
400
|
+
}
|
|
401
|
+
if (options.submitButton !== false) {
|
|
402
|
+
fields.push({
|
|
403
|
+
button: {
|
|
404
|
+
type: "submit",
|
|
405
|
+
text: options.submitText || "Submit",
|
|
406
|
+
className: "submit-button"
|
|
407
|
+
}
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
return {
|
|
411
|
+
form: {
|
|
412
|
+
onsubmit: "handleSubmit(event)",
|
|
413
|
+
novalidate: true,
|
|
414
|
+
children: fields
|
|
415
|
+
}
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Check if form is currently submitting
|
|
420
|
+
*/
|
|
421
|
+
isSubmitting() {
|
|
422
|
+
return this._isSubmitting;
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Get a field group
|
|
426
|
+
*/
|
|
427
|
+
getGroup(name) {
|
|
428
|
+
return this.groups.get(name);
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Check if a field is visible
|
|
432
|
+
*/
|
|
433
|
+
isFieldVisible(name) {
|
|
434
|
+
const field = this.fields.get(name);
|
|
435
|
+
if (!field) return false;
|
|
436
|
+
const showCondition = field.showWhen || field.showIf;
|
|
437
|
+
if (showCondition) {
|
|
438
|
+
return showCondition(this.values);
|
|
439
|
+
}
|
|
440
|
+
return field.visible !== false;
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Reset form
|
|
444
|
+
*/
|
|
445
|
+
reset() {
|
|
446
|
+
this.values = {};
|
|
447
|
+
for (const [name, field] of this.fields) {
|
|
448
|
+
if (field.defaultValue !== void 0) {
|
|
449
|
+
this.values[name] = field.defaultValue;
|
|
450
|
+
} else {
|
|
451
|
+
this.values[name] = "";
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
this.errors = {};
|
|
455
|
+
this.touched = {};
|
|
456
|
+
this._isSubmitting = false;
|
|
457
|
+
return this;
|
|
458
|
+
}
|
|
459
|
+
};
|
|
460
|
+
function createFormBuilder(options = {}) {
|
|
461
|
+
return new FormBuilder(options);
|
|
462
|
+
}
|
|
463
|
+
function createForm(options = {}) {
|
|
464
|
+
const form = new FormBuilder(options);
|
|
465
|
+
if (options.fields) {
|
|
466
|
+
options.fields.forEach((fieldConfig) => {
|
|
467
|
+
form.addField(fieldConfig.name, fieldConfig);
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
return form;
|
|
471
|
+
}
|
|
472
|
+
function buildForm(fields, options = {}) {
|
|
473
|
+
const builder = new FormBuilder(options);
|
|
474
|
+
for (const [name, config] of Object.entries(fields)) {
|
|
475
|
+
builder.field(name, config);
|
|
476
|
+
}
|
|
477
|
+
return builder;
|
|
478
|
+
}
|
|
479
|
+
var form_builder_default = {
|
|
480
|
+
FormBuilder,
|
|
481
|
+
createFormBuilder,
|
|
482
|
+
createForm,
|
|
483
|
+
buildForm
|
|
484
|
+
};
|
|
485
|
+
export {
|
|
486
|
+
FormBuilder,
|
|
487
|
+
buildForm,
|
|
488
|
+
createForm,
|
|
489
|
+
createFormBuilder,
|
|
490
|
+
form_builder_default as default
|
|
491
|
+
};
|
|
492
|
+
//# sourceMappingURL=form-builder.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/form-builder.js"],
|
|
4
|
+
"sourcesContent": ["/**\n * Coherent.js Form Builder\n * \n * Utilities for building forms with Coherent.js\n * \n * @module forms/form-builder\n */\n\n/**\n * Form Builder\n * Helps create form components with validation\n */\nexport class FormBuilder {\n constructor(options = {}) {\n this.options = {\n validateOnChange: true,\n validateOnBlur: true,\n name: options.name || 'form',\n ...options\n };\n \n this.fields = new Map();\n this.groups = new Map();\n this.values = {};\n this.errors = {};\n this.touched = {};\n this.initialValues = {};\n this.submitHandler = null;\n this.errorHandler = null;\n this._isSubmitting = false;\n }\n\n /**\n * Add a field to the form (alias for field)\n */\n addField(name, config = {}) {\n return this.field(name, config);\n }\n\n /**\n * Add a field to the form\n */\n field(name, config = {}) {\n const fieldConfig = {\n name,\n type: config.type || 'text',\n label: config.label || name,\n placeholder: config.placeholder || '',\n defaultValue: config.defaultValue || '',\n validators: config.validators || [],\n required: config.required || false,\n visible: config.visible !== false,\n showWhen: config.showWhen,\n ...config\n };\n \n this.fields.set(name, fieldConfig);\n\n // Set default value\n if (config.defaultValue !== undefined) {\n this.values[name] = config.defaultValue;\n this.initialValues[name] = config.defaultValue;\n }\n\n return this;\n }\n\n /**\n * Remove a field from the form\n */\n removeField(name) {\n this.fields.delete(name);\n delete this.values[name];\n delete this.errors[name];\n delete this.touched[name];\n return this;\n }\n\n /**\n * Update field configuration\n */\n updateField(name, config) {\n const field = this.fields.get(name);\n if (field) {\n this.fields.set(name, { ...field, ...config });\n }\n return this;\n }\n\n /**\n * Get all fields as array\n */\n getFields() {\n return Array.from(this.fields.values());\n }\n\n /**\n * Add a field group\n */\n addGroup(name, config = {}) {\n this.groups.set(name, {\n name,\n label: config.label || name,\n fields: config.fields || [],\n ...config\n });\n\n // Add fields in the group\n if (config.fields) {\n config.fields.forEach(fieldConfig => {\n this.addField(fieldConfig.name, fieldConfig);\n });\n }\n\n return this;\n }\n\n /**\n * Get field configuration\n */\n getField(name) {\n return this.fields.get(name);\n }\n\n /**\n * Set field value\n */\n setValue(name, value) {\n this.values[name] = value;\n this.touched[name] = true;\n\n const field = this.fields.get(name);\n if (field && (field.validateOnChange || this.options.validateOnChange)) {\n this.validateField(name);\n }\n }\n\n /**\n * Set multiple values\n */\n setValues(values) {\n Object.assign(this.values, values);\n return this;\n }\n\n /**\n * Get field value\n */\n getValue(name) {\n return this.values[name];\n }\n\n /**\n * Get all values\n */\n getValues() {\n return { ...this.values };\n }\n\n /**\n * Get field error\n */\n getFieldError(name) {\n return this.errors[name];\n }\n\n /**\n * Check if form has errors\n */\n hasErrors() {\n return Object.keys(this.errors).length > 0;\n }\n\n /**\n * Clear all errors\n */\n clearErrors() {\n this.errors = {};\n return this;\n }\n\n /**\n * Check if form is dirty (values changed from initial)\n */\n isDirty() {\n return Object.keys(this.values).some(key => {\n return this.values[key] !== this.initialValues[key];\n });\n }\n\n /**\n * Check if form is valid\n */\n isValid() {\n const result = this.validate();\n return Object.keys(result).length === 0;\n }\n\n /**\n * Validate a field\n */\n validateField(name) {\n const field = this.fields.get(name);\n if (!field) return null;\n\n // Skip validation for hidden fields (support both showWhen and showIf)\n const showCondition = field.showWhen || field.showIf;\n if (showCondition && !showCondition(this.values)) {\n delete this.errors[name];\n return null;\n }\n\n const value = this.values[name];\n \n // Check required\n if (field.required && (value === undefined || value === null || value === '')) {\n const error = 'This field is required';\n this.errors[name] = error;\n return error;\n }\n\n // Skip further validation if empty and not required\n if (!value && !field.required) {\n delete this.errors[name];\n return null;\n }\n\n // Type-based validation\n if (value) {\n if (field.type === 'email') {\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n if (!emailRegex.test(value)) {\n const error = 'Please enter a valid email address';\n this.errors[name] = error;\n return error;\n }\n } else if (field.type === 'url') {\n try {\n new URL(value);\n } catch {\n const error = 'Please enter a valid URL';\n this.errors[name] = error;\n return error;\n }\n } else if (field.type === 'number') {\n if (isNaN(Number(value))) {\n const error = 'Please enter a valid number';\n this.errors[name] = error;\n return error;\n }\n }\n }\n\n // Check custom validate function\n if (field.validate) {\n const error = field.validate(value, this.values);\n if (error) {\n this.errors[name] = error;\n return error;\n }\n }\n\n // Run validators\n for (const validator of field.validators || []) {\n const error = validator(value, this.values);\n if (error) {\n this.errors[name] = error;\n return error;\n }\n }\n\n delete this.errors[name];\n return null;\n }\n\n /**\n * Validate all fields\n */\n validate() {\n const errors = {};\n\n for (const [name, field] of this.fields) {\n // Skip hidden fields (support both showWhen and showIf)\n const showCondition = field.showWhen || field.showIf;\n if (showCondition && !showCondition(this.values)) {\n continue;\n }\n\n const error = this.validateField(name);\n if (error) {\n errors[name] = error;\n }\n }\n\n this.errors = errors;\n return errors;\n }\n\n /**\n * Set submit handler\n */\n onSubmit(handler) {\n this.submitHandler = handler;\n return this;\n }\n\n /**\n * Set error handler\n */\n onError(handler) {\n this.errorHandler = handler;\n return this;\n }\n\n /**\n * Submit the form\n */\n async submit() {\n const errors = this.validate();\n \n if (Object.keys(errors).length > 0) {\n return { success: false, errors };\n }\n\n if (!this.submitHandler) {\n return { success: true, data: this.values };\n }\n\n this._isSubmitting = true;\n\n try {\n const result = await this.submitHandler(this.values);\n this._isSubmitting = false;\n return { success: true, data: result };\n } catch (error) {\n this._isSubmitting = false;\n if (this.errorHandler) {\n this.errorHandler(error);\n }\n return { success: false, error };\n }\n }\n\n /**\n * Serialize form data\n */\n serialize() {\n return { ...this.values };\n }\n\n /**\n * Convert form to HTML string\n */\n toHTML() {\n const fields = this.getFields();\n let html = `<form name=\"${this.options.name}\">`;\n \n fields.forEach(field => {\n html += `<div class=\"form-field\">`;\n html += `<label for=\"${field.name}\">${field.label}</label>`;\n html += `<input type=\"${field.type}\" name=\"${field.name}\" id=\"${field.name}\">`;\n html += `</div>`;\n });\n \n html += `</form>`;\n return html;\n }\n\n /**\n * Mark field as touched\n */\n touch(name) {\n this.touched[name] = true;\n }\n\n /**\n * Build input component with validation metadata for hydration\n */\n buildInput(name) {\n const field = this.fields.get(name);\n if (!field) return null;\n\n const value = this.values[name] || '';\n const error = this.errors[name];\n const isTouched = this.touched[name];\n\n // Build validator names string for data-validators attribute\n const validatorNames = field.validators\n .map(v => {\n if (typeof v === 'function') return v.name || 'custom';\n if (typeof v === 'string') return v;\n return null;\n })\n .filter(Boolean)\n .join(',');\n\n const inputProps = {\n type: field.type,\n name: field.name,\n id: field.name,\n value: value,\n placeholder: field.placeholder,\n 'aria-invalid': error ? 'true' : 'false',\n 'aria-describedby': error ? `${name}-error` : undefined,\n className: error && isTouched ? 'error' : ''\n };\n\n // Add validation metadata for client-side hydration\n if (field.required) {\n inputProps.required = true;\n inputProps['data-required'] = 'true';\n }\n\n if (validatorNames) {\n inputProps['data-validators'] = validatorNames;\n }\n\n // Note: Event handlers are attached during hydration, not inline\n // This enables progressive enhancement and CSP compliance\n\n return {\n input: inputProps\n };\n }\n\n /**\n * Build label component\n */\n buildLabel(name) {\n const field = this.fields.get(name);\n if (!field) return null;\n\n return {\n label: {\n for: field.name,\n text: field.label\n }\n };\n }\n\n /**\n * Build error component\n */\n buildError(name) {\n const error = this.errors[name];\n const isTouched = this.touched[name];\n\n if (!error || !isTouched) return null;\n\n return {\n div: {\n id: `${name}-error`,\n className: 'error-message',\n role: 'alert',\n text: error\n }\n };\n }\n\n /**\n * Build complete field component\n */\n buildField(name) {\n const field = this.fields.get(name);\n if (!field) return null;\n\n const children = [\n this.buildLabel(name),\n this.buildInput(name)\n ];\n\n const error = this.buildError(name);\n if (error) {\n children.push(error);\n }\n\n return {\n div: {\n className: 'form-field',\n 'data-field': name,\n children\n }\n };\n }\n\n /**\n * Build entire form\n */\n buildForm(options = {}) {\n const fields = [];\n\n for (const [name] of this.fields) {\n fields.push(this.buildField(name));\n }\n\n if (options.submitButton !== false) {\n fields.push({\n button: {\n type: 'submit',\n text: options.submitText || 'Submit',\n className: 'submit-button'\n }\n });\n }\n\n return {\n form: {\n onsubmit: 'handleSubmit(event)',\n novalidate: true,\n children: fields\n }\n };\n }\n\n /**\n * Check if form is currently submitting\n */\n isSubmitting() {\n return this._isSubmitting;\n }\n\n /**\n * Get a field group\n */\n getGroup(name) {\n return this.groups.get(name);\n }\n\n /**\n * Check if a field is visible\n */\n isFieldVisible(name) {\n const field = this.fields.get(name);\n if (!field) return false;\n \n // Support both showWhen and showIf\n const showCondition = field.showWhen || field.showIf;\n if (showCondition) {\n return showCondition(this.values);\n }\n \n return field.visible !== false;\n }\n\n /**\n * Reset form\n */\n reset() {\n // Reset to initial values or empty strings\n this.values = {};\n for (const [name, field] of this.fields) {\n if (field.defaultValue !== undefined) {\n this.values[name] = field.defaultValue;\n } else {\n this.values[name] = '';\n }\n }\n this.errors = {};\n this.touched = {};\n this._isSubmitting = false;\n return this;\n }\n}\n\n/**\n * Create a form builder\n */\nexport function createFormBuilder(options = {}) {\n return new FormBuilder(options);\n}\n\n/**\n * Create a form with UI builder capabilities (for SSR rendering)\n * Alias for createFormBuilder - Use createFormBuilder() instead\n * @deprecated Use createFormBuilder() to avoid conflicts with advanced form system\n */\nexport function createForm(options = {}) {\n const form = new FormBuilder(options);\n\n // Add fields if provided\n if (options.fields) {\n options.fields.forEach(fieldConfig => {\n form.addField(fieldConfig.name, fieldConfig);\n });\n }\n\n return form;\n}\n\n/**\n * Quick form builder helper\n */\nexport function buildForm(fields, options = {}) {\n const builder = new FormBuilder(options);\n\n for (const [name, config] of Object.entries(fields)) {\n builder.field(name, config);\n }\n\n return builder;\n}\n\nexport default {\n FormBuilder,\n createFormBuilder,\n createForm,\n buildForm\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|