@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.
@@ -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
+ }