easy-forms-core 1.0.0

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/index.js ADDED
@@ -0,0 +1,2115 @@
1
+ // src/core/schema-parser.ts
2
+ var SchemaParser = class {
3
+ /**
4
+ * Parsea y valida un schema
5
+ */
6
+ parse(schema) {
7
+ if (!schema) {
8
+ throw new Error("Schema es requerido");
9
+ }
10
+ if (!schema.fields && !schema.steps) {
11
+ throw new Error("Schema debe tener fields o steps");
12
+ }
13
+ if (schema.steps) {
14
+ for (const step of schema.steps) {
15
+ if (!step.fields || step.fields.length === 0) {
16
+ throw new Error("Cada step debe tener al menos un field");
17
+ }
18
+ }
19
+ }
20
+ const normalizedFields = schema.fields ? this.normalizeFields(schema.fields) : [];
21
+ const normalizedSteps = schema.steps ? schema.steps.map((step) => ({
22
+ ...step,
23
+ fields: this.normalizeFields(step.fields)
24
+ })) : void 0;
25
+ return {
26
+ fields: normalizedFields,
27
+ steps: normalizedSteps,
28
+ isWizard: Boolean(schema.steps && schema.steps.length > 0)
29
+ };
30
+ }
31
+ /**
32
+ * Normaliza y valida campos
33
+ */
34
+ normalizeFields(fields) {
35
+ return fields.map((field, index) => {
36
+ if (!field.type) {
37
+ throw new Error(`Field en \xEDndice ${index} debe tener un type`);
38
+ }
39
+ if (!field.name) {
40
+ throw new Error(`Field en \xEDndice ${index} debe tener un name`);
41
+ }
42
+ this.validateFieldType(field, index);
43
+ return this.applyDefaults(field);
44
+ });
45
+ }
46
+ /**
47
+ * Valida el tipo de campo
48
+ */
49
+ validateFieldType(field, index) {
50
+ const validTypes = [
51
+ "text",
52
+ "email",
53
+ "number",
54
+ "password",
55
+ "textarea",
56
+ "select",
57
+ "checkbox",
58
+ "radio",
59
+ "switch",
60
+ "date",
61
+ "file",
62
+ "array",
63
+ "group",
64
+ "custom"
65
+ ];
66
+ if (!validTypes.includes(field.type)) {
67
+ throw new Error(
68
+ `Field en \xEDndice ${index} tiene un type inv\xE1lido: ${field.type}`
69
+ );
70
+ }
71
+ switch (field.type) {
72
+ case "select":
73
+ case "radio":
74
+ if (!("options" in field) || !field.options || field.options.length === 0) {
75
+ throw new Error(
76
+ `Field "${field.name}" de tipo ${field.type} debe tener options`
77
+ );
78
+ }
79
+ break;
80
+ case "array":
81
+ if (!("itemSchema" in field) || !field.itemSchema) {
82
+ throw new Error(
83
+ `Field "${field.name}" de tipo array debe tener itemSchema`
84
+ );
85
+ }
86
+ break;
87
+ case "group":
88
+ if (!("fields" in field) || !field.fields || field.fields.length === 0) {
89
+ throw new Error(
90
+ `Field "${field.name}" de tipo group debe tener fields`
91
+ );
92
+ }
93
+ break;
94
+ }
95
+ }
96
+ /**
97
+ * Aplica valores por defecto a un campo
98
+ */
99
+ applyDefaults(field) {
100
+ const defaults = {
101
+ disabled: false,
102
+ hidden: false
103
+ };
104
+ switch (field.type) {
105
+ case "checkbox":
106
+ case "switch":
107
+ if (!("checked" in field)) {
108
+ defaults.checked = false;
109
+ }
110
+ break;
111
+ case "select":
112
+ if (!("multiple" in field)) {
113
+ defaults.multiple = false;
114
+ }
115
+ break;
116
+ case "file":
117
+ if (!("multiple" in field)) {
118
+ defaults.multiple = false;
119
+ }
120
+ break;
121
+ }
122
+ return { ...defaults, ...field };
123
+ }
124
+ /**
125
+ * Obtiene todos los campos de un schema (incluyendo nested)
126
+ */
127
+ getAllFields(schema) {
128
+ const parsed = this.parse(schema);
129
+ const allFields = [];
130
+ const extractFields = (fields) => {
131
+ for (const field of fields) {
132
+ allFields.push(field);
133
+ if (field.type === "group" && "fields" in field) {
134
+ extractFields(field.fields);
135
+ }
136
+ if (field.type === "array" && "itemSchema" in field && field.itemSchema.fields) {
137
+ extractFields(field.itemSchema.fields);
138
+ }
139
+ }
140
+ };
141
+ if (parsed.fields) {
142
+ extractFields(parsed.fields);
143
+ }
144
+ if (parsed.steps) {
145
+ for (const step of parsed.steps) {
146
+ extractFields(step.fields);
147
+ }
148
+ }
149
+ return allFields;
150
+ }
151
+ };
152
+
153
+ // src/utils/styles.ts
154
+ var defaultColors = {
155
+ primary: "#007bff",
156
+ secondary: "#6c757d",
157
+ error: "#dc3545",
158
+ success: "#28a745",
159
+ text: "#212529",
160
+ border: "#ddd",
161
+ background: "#ffffff"
162
+ };
163
+ function getColors(colors) {
164
+ return { ...defaultColors, ...colors };
165
+ }
166
+ function getThemeStyles(theme, colors) {
167
+ const baseStyles = getBaseStyles(colors);
168
+ const themeStyles = getThemeSpecificStyles(theme, colors);
169
+ return baseStyles + themeStyles;
170
+ }
171
+ function getBaseStyles(colors) {
172
+ return `
173
+ :host {
174
+ display: block;
175
+ --easy-form-primary: ${colors.primary};
176
+ --easy-form-secondary: ${colors.secondary};
177
+ --easy-form-error: ${colors.error};
178
+ --easy-form-success: ${colors.success};
179
+ --easy-form-text: ${colors.text};
180
+ --easy-form-border: ${colors.border};
181
+ --easy-form-background: ${colors.background};
182
+ }
183
+ .easy-form-field {
184
+ margin-bottom: 1rem;
185
+ }
186
+ .easy-form-label {
187
+ display: block;
188
+ margin-bottom: 0.5rem;
189
+ font-weight: 500;
190
+ color: var(--easy-form-text);
191
+ }
192
+ .easy-form-required {
193
+ color: var(--easy-form-error);
194
+ }
195
+ .easy-form-input-error {
196
+ border-color: var(--easy-form-error) !important;
197
+ }
198
+ .easy-form-error {
199
+ color: var(--easy-form-error);
200
+ font-size: 0.875rem;
201
+ margin-top: 0.25rem;
202
+ }
203
+ .easy-form-description {
204
+ font-size: 0.875rem;
205
+ color: #666;
206
+ margin-top: 0.25rem;
207
+ }
208
+ .easy-form-submit {
209
+ padding: 0.5rem 1rem;
210
+ background: var(--easy-form-primary);
211
+ color: white;
212
+ border: none;
213
+ cursor: pointer;
214
+ font-size: 1rem;
215
+ transition: all 0.2s ease;
216
+ }
217
+ .easy-form-submit:hover {
218
+ opacity: 0.9;
219
+ }
220
+ .easy-form-submit:active {
221
+ transform: scale(0.98);
222
+ }
223
+ input:not([type="checkbox"]):not([type="radio"]), textarea, select {
224
+ width: 100%;
225
+ padding: 0.5rem;
226
+ font-size: 1rem;
227
+ color: var(--easy-form-text);
228
+ background: var(--easy-form-background);
229
+ transition: all 0.2s ease;
230
+ }
231
+ input[type="checkbox"],
232
+ input[type="radio"] {
233
+ width: 18px !important;
234
+ height: 18px !important;
235
+ min-width: 18px !important;
236
+ min-height: 18px !important;
237
+ max-width: 18px !important;
238
+ margin: 0;
239
+ padding: 0;
240
+ cursor: pointer;
241
+ accent-color: var(--easy-form-primary);
242
+ flex-shrink: 0;
243
+ }
244
+ input:focus, textarea:focus, select:focus {
245
+ outline: none;
246
+ }
247
+ .easy-form-group {
248
+ padding: 1rem;
249
+ margin-bottom: 1rem;
250
+ }
251
+ .easy-form-radio-group {
252
+ display: flex;
253
+ flex-direction: column;
254
+ gap: 0.75rem;
255
+ margin-top: 0.5rem;
256
+ }
257
+ .easy-form-radio-option {
258
+ display: flex;
259
+ align-items: center;
260
+ gap: 0.75rem;
261
+ padding: 0.5rem;
262
+ border-radius: 6px;
263
+ transition: background-color 0.2s ease;
264
+ }
265
+ .easy-form-radio-option:hover {
266
+ background-color: rgba(0, 0, 0, 0.03);
267
+ }
268
+ .easy-form-radio-option input[type="radio"] {
269
+ margin: 0;
270
+ flex-shrink: 0;
271
+ }
272
+ .easy-form-radio-label {
273
+ cursor: pointer;
274
+ user-select: none;
275
+ color: var(--easy-form-text);
276
+ font-weight: 400;
277
+ }
278
+ .easy-form-label-checkbox,
279
+ .easy-form-label-switch {
280
+ display: flex;
281
+ align-items: center;
282
+ gap: 0.75rem;
283
+ cursor: pointer;
284
+ user-select: none;
285
+ padding: 0.5rem;
286
+ border-radius: 6px;
287
+ transition: background-color 0.2s ease;
288
+ color: var(--easy-form-text);
289
+ }
290
+ .easy-form-label-checkbox input[type="checkbox"],
291
+ .easy-form-label-switch input[type="checkbox"] {
292
+ margin: 0;
293
+ flex-shrink: 0;
294
+ }
295
+ .easy-form-label-checkbox:hover,
296
+ .easy-form-label-switch:hover {
297
+ background-color: rgba(0, 0, 0, 0.03);
298
+ }
299
+ .easy-form-wizard-steps {
300
+ display: flex;
301
+ gap: 1rem;
302
+ margin-bottom: 2rem;
303
+ }
304
+ .easy-form-wizard-step {
305
+ padding: 0.5rem 1rem;
306
+ transition: all 0.2s ease;
307
+ }
308
+ .easy-form-wizard-step.active {
309
+ background: var(--easy-form-primary);
310
+ color: white;
311
+ }
312
+ .easy-form-wizard-step.completed {
313
+ background: var(--easy-form-success);
314
+ color: white;
315
+ }
316
+ .easy-form-wizard-nav {
317
+ display: flex;
318
+ gap: 1rem;
319
+ margin-top: 1rem;
320
+ }
321
+ .easy-form-array-item {
322
+ padding: 1rem;
323
+ margin-bottom: 1rem;
324
+ }
325
+ .easy-form-array-add,
326
+ .easy-form-array-remove {
327
+ padding: 0.25rem 0.5rem;
328
+ background: var(--easy-form-secondary);
329
+ color: white;
330
+ border: none;
331
+ cursor: pointer;
332
+ font-size: 0.875rem;
333
+ transition: all 0.2s ease;
334
+ }
335
+ .easy-form-array-remove {
336
+ background: var(--easy-form-error);
337
+ }
338
+ .easy-form-array-add:hover,
339
+ .easy-form-array-remove:hover {
340
+ opacity: 0.9;
341
+ }
342
+ `;
343
+ }
344
+ function getThemeSpecificStyles(theme, colors) {
345
+ switch (theme) {
346
+ case "plano":
347
+ return getPlanoStyles(colors);
348
+ case "tradicional":
349
+ return getTradicionalStyles(colors);
350
+ case "material":
351
+ return getMaterialStyles(colors);
352
+ case "rounded-shadow":
353
+ return getRoundedShadowStyles(colors);
354
+ case "lines":
355
+ return getLinesStyles(colors);
356
+ default:
357
+ return getPlanoStyles(colors);
358
+ }
359
+ }
360
+ function getPlanoStyles(_colors) {
361
+ return `
362
+ input:not([type="checkbox"]):not([type="radio"]), textarea, select {
363
+ border: none;
364
+ border-bottom: 2px solid var(--easy-form-border);
365
+ border-radius: 0;
366
+ padding: 0.75rem 0;
367
+ }
368
+ input:not([type="checkbox"]):not([type="radio"]):focus, textarea:focus, select:focus {
369
+ border-bottom-color: var(--easy-form-primary);
370
+ }
371
+ .easy-form-submit {
372
+ border-radius: 0;
373
+ font-weight: 600;
374
+ }
375
+ .easy-form-group {
376
+ border: none;
377
+ border-bottom: 1px solid var(--easy-form-border);
378
+ border-radius: 0;
379
+ }
380
+ .easy-form-wizard-step {
381
+ border: none;
382
+ border-bottom: 2px solid var(--easy-form-border);
383
+ border-radius: 0;
384
+ }
385
+ .easy-form-array-item {
386
+ border: none;
387
+ border-bottom: 1px solid var(--easy-form-border);
388
+ border-radius: 0;
389
+ }
390
+ `;
391
+ }
392
+ function getTradicionalStyles(_colors) {
393
+ return `
394
+ input:not([type="checkbox"]):not([type="radio"]), textarea, select {
395
+ border: 2px solid var(--easy-form-border);
396
+ border-radius: 4px;
397
+ padding: 0.625rem;
398
+ }
399
+ input:not([type="checkbox"]):not([type="radio"]):focus, textarea:focus, select:focus {
400
+ border-color: var(--easy-form-primary);
401
+ box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1);
402
+ }
403
+ .easy-form-submit {
404
+ border-radius: 4px;
405
+ font-weight: 500;
406
+ }
407
+ .easy-form-group {
408
+ border: 2px solid var(--easy-form-border);
409
+ border-radius: 4px;
410
+ background: #f8f9fa;
411
+ }
412
+ .easy-form-wizard-step {
413
+ border: 2px solid var(--easy-form-border);
414
+ border-radius: 4px;
415
+ background: #f8f9fa;
416
+ }
417
+ .easy-form-wizard-step.active {
418
+ border-color: var(--easy-form-primary);
419
+ }
420
+ .easy-form-array-item {
421
+ border: 2px solid var(--easy-form-border);
422
+ border-radius: 4px;
423
+ background: #f8f9fa;
424
+ }
425
+ `;
426
+ }
427
+ function getMaterialStyles(_colors) {
428
+ return `
429
+ .easy-form-label {
430
+ font-size: 0.875rem;
431
+ font-weight: 500;
432
+ margin-bottom: 0.25rem;
433
+ color: rgba(0, 0, 0, 0.6);
434
+ }
435
+ input:not([type="checkbox"]):not([type="radio"]), textarea, select {
436
+ border: none;
437
+ border-bottom: 1px solid rgba(0, 0, 0, 0.42);
438
+ border-radius: 4px 4px 0 0;
439
+ padding: 0.75rem 0.75rem 0.5rem 0.75rem;
440
+ background: transparent;
441
+ }
442
+ input:not([type="checkbox"]):not([type="radio"]):focus, textarea:focus, select:focus {
443
+ border-bottom-color: var(--easy-form-primary);
444
+ border-bottom-width: 2px;
445
+ padding-bottom: calc(0.5rem - 1px);
446
+ }
447
+ .easy-form-submit {
448
+ border-radius: 4px;
449
+ text-transform: uppercase;
450
+ font-weight: 500;
451
+ letter-spacing: 0.5px;
452
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
453
+ }
454
+ .easy-form-submit:hover {
455
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
456
+ }
457
+ .easy-form-group {
458
+ border: none;
459
+ border-radius: 4px;
460
+ background: #f5f5f5;
461
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
462
+ }
463
+ .easy-form-wizard-step {
464
+ border: none;
465
+ border-radius: 4px;
466
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
467
+ }
468
+ .easy-form-array-item {
469
+ border: none;
470
+ border-radius: 4px;
471
+ background: #f5f5f5;
472
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
473
+ }
474
+ `;
475
+ }
476
+ function getRoundedShadowStyles(_colors) {
477
+ return `
478
+ input:not([type="checkbox"]):not([type="radio"]), textarea, select {
479
+ border: 1px solid var(--easy-form-border);
480
+ border-radius: 12px;
481
+ padding: 0.75rem 1rem;
482
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
483
+ }
484
+ input:not([type="checkbox"]):not([type="radio"]):focus, textarea:focus, select:focus {
485
+ border-color: var(--easy-form-primary);
486
+ box-shadow: 0 4px 12px rgba(0, 123, 255, 0.15);
487
+ transform: translateY(-1px);
488
+ }
489
+ .easy-form-submit {
490
+ border-radius: 12px;
491
+ font-weight: 600;
492
+ box-shadow: 0 4px 12px rgba(0, 123, 255, 0.3);
493
+ }
494
+ .easy-form-submit:hover {
495
+ box-shadow: 0 6px 16px rgba(0, 123, 255, 0.4);
496
+ transform: translateY(-2px);
497
+ }
498
+ .easy-form-group {
499
+ border: 1px solid var(--easy-form-border);
500
+ border-radius: 16px;
501
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
502
+ background: var(--easy-form-background);
503
+ }
504
+ .easy-form-wizard-step {
505
+ border: 1px solid var(--easy-form-border);
506
+ border-radius: 12px;
507
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
508
+ }
509
+ .easy-form-wizard-step.active {
510
+ box-shadow: 0 4px 16px rgba(0, 123, 255, 0.3);
511
+ }
512
+ .easy-form-array-item {
513
+ border: 1px solid var(--easy-form-border);
514
+ border-radius: 12px;
515
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
516
+ background: var(--easy-form-background);
517
+ }
518
+ `;
519
+ }
520
+ function getLinesStyles(_colors) {
521
+ return `
522
+ .easy-form-field {
523
+ border-bottom: 1px solid var(--easy-form-border);
524
+ padding-bottom: 1rem;
525
+ margin-bottom: 1.5rem;
526
+ }
527
+ .easy-form-field:last-child {
528
+ border-bottom: none;
529
+ }
530
+ input:not([type="checkbox"]):not([type="radio"]), textarea, select {
531
+ border: none;
532
+ border-radius: 0;
533
+ padding: 0.5rem 0;
534
+ background: transparent;
535
+ }
536
+ input:not([type="checkbox"]):not([type="radio"]):focus, textarea:focus, select:focus {
537
+ border-bottom: 2px solid var(--easy-form-primary);
538
+ padding-bottom: calc(0.5rem - 1px);
539
+ }
540
+ .easy-form-submit {
541
+ border-radius: 0;
542
+ border-bottom: 3px solid var(--easy-form-primary);
543
+ background: transparent;
544
+ color: var(--easy-form-primary);
545
+ font-weight: 600;
546
+ padding: 0.75rem 0;
547
+ }
548
+ .easy-form-submit:hover {
549
+ background: rgba(0, 123, 255, 0.05);
550
+ }
551
+ .easy-form-group {
552
+ border: none;
553
+ border-bottom: 2px solid var(--easy-form-border);
554
+ border-radius: 0;
555
+ padding-bottom: 1rem;
556
+ }
557
+ .easy-form-wizard-step {
558
+ border: none;
559
+ border-bottom: 3px solid var(--easy-form-border);
560
+ border-radius: 0;
561
+ background: transparent;
562
+ }
563
+ .easy-form-wizard-step.active {
564
+ border-bottom-color: var(--easy-form-primary);
565
+ background: transparent;
566
+ color: var(--easy-form-primary);
567
+ }
568
+ .easy-form-wizard-step.completed {
569
+ border-bottom-color: var(--easy-form-success);
570
+ background: transparent;
571
+ color: var(--easy-form-success);
572
+ }
573
+ .easy-form-array-item {
574
+ border: none;
575
+ border-bottom: 1px solid var(--easy-form-border);
576
+ border-radius: 0;
577
+ }
578
+ `;
579
+ }
580
+
581
+ // src/utils/index.ts
582
+ function attributeValue(value) {
583
+ if (value === null || value === void 0) {
584
+ return "";
585
+ }
586
+ if (typeof value === "boolean") {
587
+ return value ? "true" : "false";
588
+ }
589
+ if (typeof value === "object") {
590
+ return JSON.stringify(value);
591
+ }
592
+ return String(value);
593
+ }
594
+ function parseAttributeValue(value) {
595
+ if (!value) {
596
+ return null;
597
+ }
598
+ try {
599
+ return JSON.parse(value);
600
+ } catch {
601
+ return value;
602
+ }
603
+ }
604
+ function generateId(prefix = "ef") {
605
+ return `${prefix}-${Math.random().toString(36).substr(2, 9)}`;
606
+ }
607
+ function getNestedValue(obj, path) {
608
+ return path.split(".").reduce((current, key) => current?.[key], obj);
609
+ }
610
+ function setNestedValue(obj, path, value) {
611
+ const keys = path.split(".");
612
+ const lastKey = keys.pop();
613
+ const target = keys.reduce((current, key) => {
614
+ if (!current[key] || typeof current[key] !== "object") {
615
+ current[key] = {};
616
+ }
617
+ return current[key];
618
+ }, obj);
619
+ target[lastKey] = value;
620
+ }
621
+ function isValidEmail(email) {
622
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
623
+ return emailRegex.test(email);
624
+ }
625
+ function sanitizeId(str) {
626
+ return str.replace(/[^a-zA-Z0-9-_]/g, "-");
627
+ }
628
+
629
+ // src/core/validation-engine.ts
630
+ var ValidationEngine = class {
631
+ /**
632
+ * Valida un campo con todas sus validaciones
633
+ */
634
+ async validateField(field, value) {
635
+ const errors = [];
636
+ if (!field.validations || field.validations.length === 0) {
637
+ return errors;
638
+ }
639
+ for (const validation of field.validations) {
640
+ const result = await this.validateValue(validation, value);
641
+ if (!result.isValid) {
642
+ errors.push(result.message || this.getDefaultMessage(validation));
643
+ }
644
+ }
645
+ return errors;
646
+ }
647
+ /**
648
+ * Valida un valor con una validación específica
649
+ */
650
+ async validateValue(validation, value) {
651
+ switch (validation.type) {
652
+ case "required":
653
+ return this.validateRequired(value);
654
+ case "email":
655
+ return this.validateEmail(value);
656
+ case "minLength":
657
+ return this.validateMinLength(value, validation.value);
658
+ case "maxLength":
659
+ return this.validateMaxLength(value, validation.value);
660
+ case "min":
661
+ return this.validateMin(value, validation.value);
662
+ case "max":
663
+ return this.validateMax(value, validation.value);
664
+ case "pattern":
665
+ return this.validatePattern(value, validation.value);
666
+ case "custom":
667
+ return await this.validateCustom(value, validation);
668
+ default:
669
+ return { isValid: true };
670
+ }
671
+ }
672
+ /**
673
+ * Valida campo requerido
674
+ */
675
+ validateRequired(value) {
676
+ const isValid = value !== null && value !== void 0 && value !== "" && !(Array.isArray(value) && value.length === 0);
677
+ return {
678
+ isValid,
679
+ message: isValid ? void 0 : "Este campo es requerido"
680
+ };
681
+ }
682
+ /**
683
+ * Valida email
684
+ */
685
+ validateEmail(value) {
686
+ if (!value) {
687
+ return { isValid: true };
688
+ }
689
+ const isValid = typeof value === "string" && isValidEmail(value);
690
+ return {
691
+ isValid,
692
+ message: isValid ? void 0 : "Debe ser un email v\xE1lido"
693
+ };
694
+ }
695
+ /**
696
+ * Valida longitud mínima
697
+ */
698
+ validateMinLength(value, minLength) {
699
+ if (!value) {
700
+ return { isValid: true };
701
+ }
702
+ const str = String(value);
703
+ const isValid = str.length >= minLength;
704
+ return {
705
+ isValid,
706
+ message: isValid ? void 0 : `Debe tener al menos ${minLength} caracteres`
707
+ };
708
+ }
709
+ /**
710
+ * Valida longitud máxima
711
+ */
712
+ validateMaxLength(value, maxLength) {
713
+ if (!value) {
714
+ return { isValid: true };
715
+ }
716
+ const str = String(value);
717
+ const isValid = str.length <= maxLength;
718
+ return {
719
+ isValid,
720
+ message: isValid ? void 0 : `Debe tener m\xE1ximo ${maxLength} caracteres`
721
+ };
722
+ }
723
+ /**
724
+ * Valida valor mínimo
725
+ */
726
+ validateMin(value, min) {
727
+ if (value === null || value === void 0 || value === "") {
728
+ return { isValid: true };
729
+ }
730
+ const num = Number(value);
731
+ const isValid = !isNaN(num) && num >= min;
732
+ return {
733
+ isValid,
734
+ message: isValid ? void 0 : `Debe ser mayor o igual a ${min}`
735
+ };
736
+ }
737
+ /**
738
+ * Valida valor máximo
739
+ */
740
+ validateMax(value, max) {
741
+ if (value === null || value === void 0 || value === "") {
742
+ return { isValid: true };
743
+ }
744
+ const num = Number(value);
745
+ const isValid = !isNaN(num) && num <= max;
746
+ return {
747
+ isValid,
748
+ message: isValid ? void 0 : `Debe ser menor o igual a ${max}`
749
+ };
750
+ }
751
+ /**
752
+ * Valida patrón regex
753
+ */
754
+ validatePattern(value, pattern) {
755
+ if (!value) {
756
+ return { isValid: true };
757
+ }
758
+ const regex = typeof pattern === "string" ? new RegExp(pattern) : pattern;
759
+ const isValid = regex.test(String(value));
760
+ return {
761
+ isValid,
762
+ message: isValid ? void 0 : "El formato no es v\xE1lido"
763
+ };
764
+ }
765
+ /**
766
+ * Valida con función personalizada
767
+ */
768
+ async validateCustom(value, validation) {
769
+ try {
770
+ const result = await validation.validator(value);
771
+ return {
772
+ isValid: Boolean(result),
773
+ message: result ? void 0 : validation.message || "Validaci\xF3n fallida"
774
+ };
775
+ } catch (error) {
776
+ return {
777
+ isValid: false,
778
+ message: validation.message || "Error en la validaci\xF3n"
779
+ };
780
+ }
781
+ }
782
+ /**
783
+ * Obtiene mensaje por defecto para una validación
784
+ */
785
+ getDefaultMessage(validation) {
786
+ switch (validation.type) {
787
+ case "required":
788
+ return "Este campo es requerido";
789
+ case "email":
790
+ return "Debe ser un email v\xE1lido";
791
+ case "minLength":
792
+ return `Debe tener al menos ${validation.value} caracteres`;
793
+ case "maxLength":
794
+ return `Debe tener m\xE1ximo ${validation.value} caracteres`;
795
+ case "min":
796
+ return `Debe ser mayor o igual a ${validation.value}`;
797
+ case "max":
798
+ return `Debe ser menor o igual a ${validation.value}`;
799
+ case "pattern":
800
+ return "El formato no es v\xE1lido";
801
+ case "custom":
802
+ return "Validaci\xF3n fallida";
803
+ default:
804
+ return "Campo inv\xE1lido";
805
+ }
806
+ }
807
+ /**
808
+ * Valida todos los campos de un formulario
809
+ */
810
+ async validateForm(fields, values) {
811
+ const errors = {};
812
+ for (const field of fields) {
813
+ const value = values[field.name];
814
+ const fieldErrors = await this.validateField(field, value);
815
+ if (fieldErrors.length > 0) {
816
+ errors[field.name] = fieldErrors;
817
+ }
818
+ }
819
+ return errors;
820
+ }
821
+ };
822
+
823
+ // src/core/state-manager.ts
824
+ var StateManager = class {
825
+ constructor() {
826
+ this.wizardState = null;
827
+ this.schema = null;
828
+ this.parser = new SchemaParser();
829
+ this.validator = new ValidationEngine();
830
+ this.state = this.createInitialState();
831
+ }
832
+ /**
833
+ * Crea el estado inicial
834
+ */
835
+ createInitialState() {
836
+ return {
837
+ values: {},
838
+ errors: {},
839
+ touched: {},
840
+ isValid: true,
841
+ isSubmitting: false
842
+ };
843
+ }
844
+ /**
845
+ * Inicializa el schema
846
+ */
847
+ initializeSchema(schema) {
848
+ this.schema = this.parser.parse(schema);
849
+ this.initializeValues();
850
+ this.initializeWizard();
851
+ }
852
+ /**
853
+ * Inicializa los valores por defecto
854
+ */
855
+ initializeValues() {
856
+ if (!this.schema) return;
857
+ const allFields = this.schema.isWizard ? this.schema.steps.flatMap((step) => step.fields) : this.schema.fields;
858
+ const existingValues = { ...this.state.values };
859
+ const values = {};
860
+ for (const field of allFields) {
861
+ const existingValue = getNestedValue(existingValues, field.name);
862
+ if (existingValue !== void 0 && existingValue !== null) {
863
+ values[field.name] = existingValue;
864
+ } else {
865
+ this.initializeFieldValue(field, values);
866
+ }
867
+ }
868
+ for (const key in existingValues) {
869
+ if (!(key in values)) {
870
+ values[key] = existingValues[key];
871
+ }
872
+ }
873
+ this.state.values = values;
874
+ }
875
+ /**
876
+ * Inicializa el valor de un campo
877
+ */
878
+ initializeFieldValue(field, values) {
879
+ if (field.defaultValue !== void 0) {
880
+ values[field.name] = field.defaultValue;
881
+ } else {
882
+ switch (field.type) {
883
+ case "checkbox":
884
+ case "switch":
885
+ values[field.name] = field.checked || false;
886
+ break;
887
+ case "select":
888
+ if ("multiple" in field && field.multiple) {
889
+ values[field.name] = [];
890
+ } else {
891
+ values[field.name] = null;
892
+ }
893
+ break;
894
+ case "array":
895
+ values[field.name] = [];
896
+ break;
897
+ case "group":
898
+ values[field.name] = {};
899
+ if ("fields" in field) {
900
+ for (const subField of field.fields) {
901
+ this.initializeFieldValue(subField, values[field.name]);
902
+ }
903
+ }
904
+ break;
905
+ default:
906
+ values[field.name] = null;
907
+ }
908
+ }
909
+ }
910
+ /**
911
+ * Inicializa el estado del wizard
912
+ */
913
+ initializeWizard() {
914
+ if (!this.schema || !this.schema.isWizard) {
915
+ this.wizardState = null;
916
+ return;
917
+ }
918
+ this.wizardState = {
919
+ currentStep: 0,
920
+ totalSteps: this.schema.steps.length,
921
+ completedSteps: []
922
+ };
923
+ }
924
+ /**
925
+ * Obtiene el estado actual
926
+ */
927
+ getState() {
928
+ return { ...this.state };
929
+ }
930
+ /**
931
+ * Obtiene el estado del wizard
932
+ */
933
+ getWizardState() {
934
+ return this.wizardState ? { ...this.wizardState } : null;
935
+ }
936
+ /**
937
+ * Obtiene un valor del formulario
938
+ */
939
+ getValue(fieldName) {
940
+ return getNestedValue(this.state.values, fieldName);
941
+ }
942
+ /**
943
+ * Establece un valor
944
+ */
945
+ async setValue(fieldName, value) {
946
+ setNestedValue(this.state.values, fieldName, value);
947
+ this.state.touched[fieldName] = true;
948
+ if (this.state.touched[fieldName] && this.schema) {
949
+ await this.validateField(fieldName);
950
+ }
951
+ this.updateValidity();
952
+ }
953
+ /**
954
+ * Establece un valor sin validar (útil para preservar valores durante re-renderizado)
955
+ */
956
+ setValueWithoutValidation(fieldName, value) {
957
+ setNestedValue(this.state.values, fieldName, value);
958
+ }
959
+ /**
960
+ * Valida un campo específico
961
+ */
962
+ async validateField(fieldName) {
963
+ if (!this.schema) return;
964
+ const allFields = this.schema.isWizard ? this.schema.steps.flatMap((step) => step.fields) : this.schema.fields;
965
+ const field = allFields.find((f) => f.name === fieldName);
966
+ if (!field) return;
967
+ const value = this.getValue(fieldName);
968
+ const errors = await this.validator.validateField(
969
+ field,
970
+ value
971
+ );
972
+ if (errors.length > 0) {
973
+ this.state.errors[fieldName] = errors;
974
+ } else {
975
+ delete this.state.errors[fieldName];
976
+ }
977
+ }
978
+ /**
979
+ * Valida todo el formulario
980
+ */
981
+ async validateForm() {
982
+ if (!this.schema) {
983
+ return {};
984
+ }
985
+ const allFields = this.schema.isWizard ? this.schema.steps.flatMap((step) => step.fields) : this.schema.fields;
986
+ const errors = await this.validator.validateForm(
987
+ allFields,
988
+ this.state.values
989
+ );
990
+ this.state.errors = errors;
991
+ this.updateValidity();
992
+ return errors;
993
+ }
994
+ /**
995
+ * Actualiza la validez del formulario
996
+ */
997
+ updateValidity() {
998
+ this.state.isValid = Object.keys(this.state.errors).length === 0;
999
+ }
1000
+ /**
1001
+ * Marca un campo como touched
1002
+ */
1003
+ setTouched(fieldName) {
1004
+ this.state.touched[fieldName] = true;
1005
+ }
1006
+ /**
1007
+ * Obtiene los errores de un campo
1008
+ */
1009
+ getErrors(fieldName) {
1010
+ return this.state.errors[fieldName] || [];
1011
+ }
1012
+ /**
1013
+ * Obtiene todos los errores
1014
+ */
1015
+ getAllErrors() {
1016
+ return { ...this.state.errors };
1017
+ }
1018
+ /**
1019
+ * Resetea el formulario
1020
+ */
1021
+ reset() {
1022
+ this.state = this.createInitialState();
1023
+ if (this.schema) {
1024
+ this.initializeValues();
1025
+ this.initializeWizard();
1026
+ }
1027
+ }
1028
+ /**
1029
+ * Avanza al siguiente step del wizard
1030
+ */
1031
+ nextStep() {
1032
+ if (!this.wizardState) return false;
1033
+ if (this.wizardState.currentStep < this.wizardState.totalSteps - 1) {
1034
+ this.wizardState.currentStep++;
1035
+ return true;
1036
+ }
1037
+ return false;
1038
+ }
1039
+ /**
1040
+ * Retrocede al step anterior del wizard
1041
+ */
1042
+ previousStep() {
1043
+ if (!this.wizardState) return false;
1044
+ if (this.wizardState.currentStep > 0) {
1045
+ this.wizardState.currentStep--;
1046
+ return true;
1047
+ }
1048
+ return false;
1049
+ }
1050
+ /**
1051
+ * Va a un step específico
1052
+ */
1053
+ goToStep(stepIndex) {
1054
+ if (!this.wizardState) return false;
1055
+ if (stepIndex >= 0 && stepIndex < this.wizardState.totalSteps) {
1056
+ this.wizardState.currentStep = stepIndex;
1057
+ return true;
1058
+ }
1059
+ return false;
1060
+ }
1061
+ /**
1062
+ * Marca un step como completado
1063
+ */
1064
+ completeStep(stepIndex) {
1065
+ if (!this.wizardState) return;
1066
+ if (!this.wizardState.completedSteps.includes(stepIndex)) {
1067
+ this.wizardState.completedSteps.push(stepIndex);
1068
+ }
1069
+ }
1070
+ /**
1071
+ * Establece el estado de submitting
1072
+ */
1073
+ setSubmitting(isSubmitting) {
1074
+ this.state.isSubmitting = isSubmitting;
1075
+ }
1076
+ /**
1077
+ * Obtiene los campos del step actual
1078
+ */
1079
+ getCurrentStepFields() {
1080
+ if (!this.schema || !this.schema.isWizard || !this.wizardState) {
1081
+ return this.schema?.fields || [];
1082
+ }
1083
+ return this.schema.steps[this.wizardState.currentStep].fields;
1084
+ }
1085
+ };
1086
+
1087
+ // src/components/inputs/base-input.ts
1088
+ var BaseInput = class {
1089
+ constructor(field, value, error, onChange, onBlur) {
1090
+ this.field = field;
1091
+ this.value = value;
1092
+ this.error = error;
1093
+ this.onChange = onChange;
1094
+ this.onBlur = onBlur;
1095
+ }
1096
+ /**
1097
+ * Crea un contenedor con label y error
1098
+ */
1099
+ createFieldContainer(input) {
1100
+ const container = document.createElement("div");
1101
+ container.className = "easy-form-field";
1102
+ if (this.field.label) {
1103
+ const label = document.createElement("label");
1104
+ label.className = "easy-form-label";
1105
+ label.setAttribute("for", this.getFieldId());
1106
+ label.textContent = this.field.label;
1107
+ if (this.field.validations?.some((v) => v.type === "required")) {
1108
+ const required = document.createElement("span");
1109
+ required.className = "easy-form-required";
1110
+ required.textContent = " *";
1111
+ label.appendChild(required);
1112
+ }
1113
+ container.appendChild(label);
1114
+ }
1115
+ container.appendChild(input);
1116
+ if (this.field.description) {
1117
+ const description = document.createElement("p");
1118
+ description.className = "easy-form-description";
1119
+ description.textContent = this.field.description;
1120
+ container.appendChild(description);
1121
+ }
1122
+ if (this.error) {
1123
+ const errorEl = document.createElement("p");
1124
+ errorEl.className = "easy-form-error";
1125
+ errorEl.textContent = this.error;
1126
+ container.appendChild(errorEl);
1127
+ }
1128
+ return container;
1129
+ }
1130
+ /**
1131
+ * Obtiene el ID del campo
1132
+ */
1133
+ getFieldId() {
1134
+ return `easy-form-${this.field.name}`;
1135
+ }
1136
+ /**
1137
+ * Aplica props comunes a un elemento
1138
+ */
1139
+ applyCommonProps(element) {
1140
+ element.id = this.getFieldId();
1141
+ element.setAttribute("name", this.field.name);
1142
+ if (this.field.disabled) {
1143
+ element.setAttribute("disabled", "true");
1144
+ }
1145
+ if (this.field.hidden) {
1146
+ element.style.display = "none";
1147
+ }
1148
+ if (this.error) {
1149
+ element.classList.add("easy-form-input-error");
1150
+ }
1151
+ if (this.field.props) {
1152
+ for (const [key, value] of Object.entries(this.field.props)) {
1153
+ if (key.startsWith("data-") || key.startsWith("aria-")) {
1154
+ element.setAttribute(key, String(value));
1155
+ }
1156
+ }
1157
+ }
1158
+ }
1159
+ };
1160
+
1161
+ // src/components/inputs/text-input.ts
1162
+ var TextInput = class extends BaseInput {
1163
+ render() {
1164
+ const input = document.createElement("input");
1165
+ input.type = this.field.type === "email" ? "email" : this.field.type === "password" ? "password" : "text";
1166
+ input.value = this.value ?? "";
1167
+ input.placeholder = this.field.placeholder || "";
1168
+ this.applyCommonProps(input);
1169
+ input.addEventListener("input", (e) => {
1170
+ const target = e.target;
1171
+ this.onChange(target.value);
1172
+ });
1173
+ input.addEventListener("blur", () => {
1174
+ this.onBlur();
1175
+ });
1176
+ return this.createFieldContainer(input);
1177
+ }
1178
+ };
1179
+
1180
+ // src/components/inputs/number-input.ts
1181
+ var NumberInput = class extends BaseInput {
1182
+ render() {
1183
+ const input = document.createElement("input");
1184
+ input.type = "number";
1185
+ input.value = this.value ?? "";
1186
+ input.placeholder = this.field.placeholder || "";
1187
+ const numberField = this.field;
1188
+ if (numberField.min !== void 0) {
1189
+ input.min = String(numberField.min);
1190
+ }
1191
+ if (numberField.max !== void 0) {
1192
+ input.max = String(numberField.max);
1193
+ }
1194
+ if (numberField.step !== void 0) {
1195
+ input.step = String(numberField.step);
1196
+ }
1197
+ this.applyCommonProps(input);
1198
+ input.addEventListener("input", (e) => {
1199
+ const target = e.target;
1200
+ const numValue = target.value === "" ? null : Number(target.value);
1201
+ this.onChange(numValue);
1202
+ });
1203
+ input.addEventListener("blur", () => {
1204
+ this.onBlur();
1205
+ });
1206
+ return this.createFieldContainer(input);
1207
+ }
1208
+ };
1209
+
1210
+ // src/components/inputs/textarea-input.ts
1211
+ var TextareaInput = class extends BaseInput {
1212
+ render() {
1213
+ const textarea = document.createElement("textarea");
1214
+ textarea.value = this.value ?? "";
1215
+ textarea.placeholder = this.field.placeholder || "";
1216
+ const textareaField = this.field;
1217
+ if (textareaField.rows) {
1218
+ textarea.rows = textareaField.rows;
1219
+ }
1220
+ if (textareaField.cols) {
1221
+ textarea.cols = textareaField.cols;
1222
+ }
1223
+ this.applyCommonProps(textarea);
1224
+ textarea.addEventListener("input", (e) => {
1225
+ const target = e.target;
1226
+ this.onChange(target.value);
1227
+ });
1228
+ textarea.addEventListener("blur", () => {
1229
+ this.onBlur();
1230
+ });
1231
+ return this.createFieldContainer(textarea);
1232
+ }
1233
+ };
1234
+
1235
+ // src/components/inputs/select-input.ts
1236
+ var SelectInput = class extends BaseInput {
1237
+ render() {
1238
+ const select = document.createElement("select");
1239
+ const selectField = this.field;
1240
+ if (selectField.multiple) {
1241
+ select.multiple = true;
1242
+ }
1243
+ for (const option of selectField.options) {
1244
+ const optionEl = document.createElement("option");
1245
+ if (typeof option === "string") {
1246
+ optionEl.value = option;
1247
+ optionEl.textContent = option;
1248
+ } else {
1249
+ optionEl.value = String(option.value);
1250
+ optionEl.textContent = option.label;
1251
+ }
1252
+ select.appendChild(optionEl);
1253
+ }
1254
+ if (selectField.multiple && Array.isArray(this.value)) {
1255
+ for (const option of select.options) {
1256
+ option.selected = this.value.includes(option.value);
1257
+ }
1258
+ } else {
1259
+ select.value = this.value ?? "";
1260
+ }
1261
+ this.applyCommonProps(select);
1262
+ select.addEventListener("change", (e) => {
1263
+ const target = e.target;
1264
+ if (selectField.multiple) {
1265
+ const selectedValues = Array.from(target.selectedOptions).map(
1266
+ (opt) => opt.value
1267
+ );
1268
+ this.onChange(selectedValues);
1269
+ } else {
1270
+ this.onChange(target.value || null);
1271
+ }
1272
+ });
1273
+ select.addEventListener("blur", () => {
1274
+ this.onBlur();
1275
+ });
1276
+ return this.createFieldContainer(select);
1277
+ }
1278
+ };
1279
+
1280
+ // src/components/inputs/checkbox-input.ts
1281
+ var CheckboxInput = class extends BaseInput {
1282
+ render() {
1283
+ const checkbox = document.createElement("input");
1284
+ checkbox.type = "checkbox";
1285
+ checkbox.checked = Boolean(this.value);
1286
+ this.applyCommonProps(checkbox);
1287
+ checkbox.addEventListener("change", (e) => {
1288
+ const target = e.target;
1289
+ this.onChange(target.checked);
1290
+ });
1291
+ checkbox.addEventListener("blur", () => {
1292
+ this.onBlur();
1293
+ });
1294
+ const container = document.createElement("div");
1295
+ container.className = "easy-form-field";
1296
+ const label = document.createElement("label");
1297
+ label.className = "easy-form-label-checkbox";
1298
+ label.setAttribute("for", this.getFieldId());
1299
+ label.appendChild(checkbox);
1300
+ if (this.field.label) {
1301
+ const labelText = document.createTextNode(this.field.label);
1302
+ label.appendChild(labelText);
1303
+ }
1304
+ container.appendChild(label);
1305
+ if (this.field.description) {
1306
+ const description = document.createElement("p");
1307
+ description.className = "easy-form-description";
1308
+ description.textContent = this.field.description;
1309
+ container.appendChild(description);
1310
+ }
1311
+ if (this.error) {
1312
+ const errorEl = document.createElement("p");
1313
+ errorEl.className = "easy-form-error";
1314
+ errorEl.textContent = this.error;
1315
+ container.appendChild(errorEl);
1316
+ }
1317
+ return container;
1318
+ }
1319
+ };
1320
+
1321
+ // src/components/inputs/radio-input.ts
1322
+ var RadioInput = class extends BaseInput {
1323
+ render() {
1324
+ const container = document.createElement("div");
1325
+ container.className = "easy-form-field";
1326
+ if (this.field.label) {
1327
+ const label = document.createElement("label");
1328
+ label.className = "easy-form-label";
1329
+ label.textContent = this.field.label;
1330
+ if (this.field.validations?.some((v) => v.type === "required")) {
1331
+ const required = document.createElement("span");
1332
+ required.className = "easy-form-required";
1333
+ required.textContent = " *";
1334
+ label.appendChild(required);
1335
+ }
1336
+ container.appendChild(label);
1337
+ }
1338
+ const radioGroup = document.createElement("div");
1339
+ radioGroup.className = "easy-form-radio-group";
1340
+ const radioField = this.field;
1341
+ for (const option of radioField.options) {
1342
+ const optionValue = typeof option === "string" ? option : option.value;
1343
+ const optionLabel = typeof option === "string" ? option : option.label;
1344
+ const radioContainer = document.createElement("div");
1345
+ radioContainer.className = "easy-form-radio-option";
1346
+ const radio = document.createElement("input");
1347
+ radio.type = "radio";
1348
+ radio.name = this.field.name;
1349
+ radio.id = `${this.getFieldId()}-${optionValue}`;
1350
+ radio.value = String(optionValue);
1351
+ radio.checked = String(this.value) === String(optionValue);
1352
+ if (this.field.disabled) {
1353
+ radio.disabled = true;
1354
+ }
1355
+ const label = document.createElement("label");
1356
+ label.setAttribute("for", radio.id);
1357
+ label.textContent = optionLabel;
1358
+ label.className = "easy-form-radio-label";
1359
+ radio.addEventListener("change", () => {
1360
+ this.onChange(optionValue);
1361
+ });
1362
+ radio.addEventListener("blur", () => {
1363
+ this.onBlur();
1364
+ });
1365
+ radioContainer.appendChild(radio);
1366
+ radioContainer.appendChild(label);
1367
+ radioGroup.appendChild(radioContainer);
1368
+ }
1369
+ container.appendChild(radioGroup);
1370
+ if (this.field.description) {
1371
+ const description = document.createElement("p");
1372
+ description.className = "easy-form-description";
1373
+ description.textContent = this.field.description;
1374
+ container.appendChild(description);
1375
+ }
1376
+ if (this.error) {
1377
+ const errorEl = document.createElement("p");
1378
+ errorEl.className = "easy-form-error";
1379
+ errorEl.textContent = this.error;
1380
+ container.appendChild(errorEl);
1381
+ }
1382
+ return container;
1383
+ }
1384
+ };
1385
+
1386
+ // src/components/inputs/switch-input.ts
1387
+ var SwitchInput = class extends BaseInput {
1388
+ render() {
1389
+ const switchEl = document.createElement("input");
1390
+ switchEl.type = "checkbox";
1391
+ switchEl.className = "easy-form-switch";
1392
+ switchEl.checked = Boolean(this.value);
1393
+ this.applyCommonProps(switchEl);
1394
+ switchEl.addEventListener("change", (e) => {
1395
+ const target = e.target;
1396
+ this.onChange(target.checked);
1397
+ });
1398
+ switchEl.addEventListener("blur", () => {
1399
+ this.onBlur();
1400
+ });
1401
+ const container = document.createElement("div");
1402
+ container.className = "easy-form-field";
1403
+ const label = document.createElement("label");
1404
+ label.className = "easy-form-label-switch";
1405
+ label.setAttribute("for", this.getFieldId());
1406
+ if (this.field.label) {
1407
+ const labelText = document.createTextNode(this.field.label);
1408
+ label.appendChild(labelText);
1409
+ }
1410
+ label.appendChild(switchEl);
1411
+ container.appendChild(label);
1412
+ if (this.field.description) {
1413
+ const description = document.createElement("p");
1414
+ description.className = "easy-form-description";
1415
+ description.textContent = this.field.description;
1416
+ container.appendChild(description);
1417
+ }
1418
+ if (this.error) {
1419
+ const errorEl = document.createElement("p");
1420
+ errorEl.className = "easy-form-error";
1421
+ errorEl.textContent = this.error;
1422
+ container.appendChild(errorEl);
1423
+ }
1424
+ return container;
1425
+ }
1426
+ };
1427
+
1428
+ // src/components/inputs/date-input.ts
1429
+ var DateInput = class extends BaseInput {
1430
+ render() {
1431
+ const input = document.createElement("input");
1432
+ input.type = "date";
1433
+ const dateField = this.field;
1434
+ if (dateField.min) {
1435
+ input.min = dateField.min;
1436
+ }
1437
+ if (dateField.max) {
1438
+ input.max = dateField.max;
1439
+ }
1440
+ if (this.value) {
1441
+ const date = this.value instanceof Date ? this.value.toISOString().split("T")[0] : String(this.value);
1442
+ input.value = date;
1443
+ }
1444
+ this.applyCommonProps(input);
1445
+ input.addEventListener("change", (e) => {
1446
+ const target = e.target;
1447
+ this.onChange(target.value || null);
1448
+ });
1449
+ input.addEventListener("blur", () => {
1450
+ this.onBlur();
1451
+ });
1452
+ return this.createFieldContainer(input);
1453
+ }
1454
+ };
1455
+
1456
+ // src/components/inputs/file-input.ts
1457
+ var FileInput = class extends BaseInput {
1458
+ render() {
1459
+ const input = document.createElement("input");
1460
+ input.type = "file";
1461
+ const fileField = this.field;
1462
+ if (fileField.accept) {
1463
+ input.accept = fileField.accept;
1464
+ }
1465
+ if (fileField.multiple) {
1466
+ input.multiple = true;
1467
+ }
1468
+ this.applyCommonProps(input);
1469
+ input.addEventListener("change", (e) => {
1470
+ const target = e.target;
1471
+ if (target.files) {
1472
+ if (fileField.multiple) {
1473
+ this.onChange(Array.from(target.files));
1474
+ } else {
1475
+ this.onChange(target.files[0] || null);
1476
+ }
1477
+ }
1478
+ });
1479
+ input.addEventListener("blur", () => {
1480
+ this.onBlur();
1481
+ });
1482
+ return this.createFieldContainer(input);
1483
+ }
1484
+ };
1485
+
1486
+ // src/components/inputs/index.ts
1487
+ function createInput(field, value, error, onChange, onBlur) {
1488
+ switch (field.type) {
1489
+ case "text":
1490
+ case "email":
1491
+ case "password":
1492
+ return new TextInput(field, value, error, onChange, onBlur).render();
1493
+ case "number":
1494
+ return new NumberInput(field, value, error, onChange, onBlur).render();
1495
+ case "textarea":
1496
+ return new TextareaInput(field, value, error, onChange, onBlur).render();
1497
+ case "select":
1498
+ return new SelectInput(field, value, error, onChange, onBlur).render();
1499
+ case "checkbox":
1500
+ return new CheckboxInput(field, value, error, onChange, onBlur).render();
1501
+ case "radio":
1502
+ return new RadioInput(field, value, error, onChange, onBlur).render();
1503
+ case "switch":
1504
+ return new SwitchInput(field, value, error, onChange, onBlur).render();
1505
+ case "date":
1506
+ return new DateInput(field, value, error, onChange, onBlur).render();
1507
+ case "file":
1508
+ return new FileInput(field, value, error, onChange, onBlur).render();
1509
+ default:
1510
+ const div = document.createElement("div");
1511
+ div.textContent = `Tipo de campo no soportado: ${field.type}`;
1512
+ return div;
1513
+ }
1514
+ }
1515
+ var customComponents = /* @__PURE__ */ new Map();
1516
+ function registerComponent(type, component) {
1517
+ customComponents.set(type, component);
1518
+ }
1519
+ function registerComponents(components) {
1520
+ for (const [type, component] of Object.entries(components)) {
1521
+ registerComponent(type, component);
1522
+ }
1523
+ }
1524
+ function getCustomComponent(type) {
1525
+ return customComponents.get(type);
1526
+ }
1527
+
1528
+ // src/components/easy-form.ts
1529
+ var BrowserHTMLElement = typeof HTMLElement !== "undefined" ? HTMLElement : class {
1530
+ };
1531
+ var EasyForm = class extends BrowserHTMLElement {
1532
+ constructor() {
1533
+ if (typeof HTMLElement === "undefined") {
1534
+ throw new Error("EasyForm can only be used in a browser environment");
1535
+ }
1536
+ super();
1537
+ this.customComponents = {};
1538
+ this.isRendering = false;
1539
+ this.stateManager = new StateManager();
1540
+ this.shadow = this.attachShadow({ mode: "open" });
1541
+ }
1542
+ static get observedAttributes() {
1543
+ return ["schema", "theme", "colors"];
1544
+ }
1545
+ /**
1546
+ * Obtiene el schema
1547
+ */
1548
+ get schema() {
1549
+ const schemaAttr = this.getAttribute("schema");
1550
+ if (!schemaAttr) return null;
1551
+ return parseAttributeValue(schemaAttr);
1552
+ }
1553
+ /**
1554
+ * Establece el schema
1555
+ */
1556
+ set schema(value) {
1557
+ if (value) {
1558
+ this.setAttribute("schema", attributeValue(value));
1559
+ } else {
1560
+ this.removeAttribute("schema");
1561
+ }
1562
+ }
1563
+ /**
1564
+ * Se llama cuando el componente se conecta al DOM
1565
+ */
1566
+ connectedCallback() {
1567
+ this.setupStyles();
1568
+ this.render();
1569
+ }
1570
+ /**
1571
+ * Se llama cuando un atributo cambia
1572
+ */
1573
+ attributeChangedCallback(name, oldValue, newValue) {
1574
+ if (name === "schema" && newValue !== oldValue) {
1575
+ this.handleSchemaChange();
1576
+ }
1577
+ if ((name === "theme" || name === "colors") && newValue !== oldValue) {
1578
+ this.setupStyles();
1579
+ }
1580
+ }
1581
+ /**
1582
+ * Maneja el cambio de schema
1583
+ */
1584
+ handleSchemaChange() {
1585
+ const schema = this.schema;
1586
+ if (schema) {
1587
+ this.stateManager.initializeSchema(schema);
1588
+ this.render();
1589
+ }
1590
+ }
1591
+ /**
1592
+ * Renderiza el formulario
1593
+ */
1594
+ async render() {
1595
+ if (this.isRendering) {
1596
+ return;
1597
+ }
1598
+ this.isRendering = true;
1599
+ try {
1600
+ const schema = this.schema;
1601
+ if (!schema) {
1602
+ const form = this.shadow.querySelector("form");
1603
+ if (form && form.parentNode === this.shadow) {
1604
+ form.remove();
1605
+ }
1606
+ return;
1607
+ }
1608
+ const preservedValues = this.preserveCurrentValues();
1609
+ if (preservedValues && Object.keys(preservedValues).length > 0) {
1610
+ for (const [key, value] of Object.entries(preservedValues)) {
1611
+ this.stateManager.setValueWithoutValidation(key, value);
1612
+ }
1613
+ }
1614
+ this.stateManager.initializeSchema(schema);
1615
+ const wizardState = this.stateManager.getWizardState();
1616
+ const newFormElement = document.createElement("form");
1617
+ newFormElement.addEventListener("submit", (e) => this.handleSubmit(e));
1618
+ if (wizardState) {
1619
+ this.renderWizard(newFormElement, wizardState);
1620
+ } else {
1621
+ this.renderFields(newFormElement, schema.fields || []);
1622
+ }
1623
+ const submitButton = document.createElement("button");
1624
+ submitButton.type = "submit";
1625
+ submitButton.textContent = "Enviar";
1626
+ submitButton.className = "easy-form-submit";
1627
+ newFormElement.appendChild(submitButton);
1628
+ const oldForm = this.shadow.querySelector("form");
1629
+ if (oldForm && oldForm.parentNode === this.shadow && oldForm !== newFormElement) {
1630
+ try {
1631
+ oldForm.remove();
1632
+ } catch (e) {
1633
+ console.warn("Error al eliminar formulario anterior:", e);
1634
+ }
1635
+ }
1636
+ this.shadow.appendChild(newFormElement);
1637
+ } finally {
1638
+ this.isRendering = false;
1639
+ }
1640
+ }
1641
+ /**
1642
+ * Preserva los valores actuales del DOM antes de re-renderizar
1643
+ * Retorna un objeto con los valores preservados
1644
+ */
1645
+ preserveCurrentValues() {
1646
+ const form = this.shadow.querySelector("form");
1647
+ const preservedValues = {};
1648
+ if (!form) return preservedValues;
1649
+ const inputs = form.querySelectorAll("input, textarea, select");
1650
+ for (const input of inputs) {
1651
+ const name = input.getAttribute("name");
1652
+ if (!name) continue;
1653
+ let value;
1654
+ if (input instanceof HTMLInputElement) {
1655
+ if (input.type === "checkbox") {
1656
+ value = input.checked;
1657
+ } else if (input.type === "radio") {
1658
+ if (input.checked) {
1659
+ value = input.value;
1660
+ } else {
1661
+ continue;
1662
+ }
1663
+ } else if (input.type === "number") {
1664
+ value = input.value === "" ? null : Number(input.value);
1665
+ } else {
1666
+ value = input.value;
1667
+ }
1668
+ } else if (input instanceof HTMLTextAreaElement) {
1669
+ value = input.value;
1670
+ } else if (input instanceof HTMLSelectElement) {
1671
+ if (input.multiple) {
1672
+ value = Array.from(input.selectedOptions).map((opt) => opt.value);
1673
+ } else {
1674
+ value = input.value || null;
1675
+ }
1676
+ }
1677
+ if (value !== void 0) {
1678
+ preservedValues[name] = value === "" ? null : value;
1679
+ }
1680
+ }
1681
+ return preservedValues;
1682
+ }
1683
+ /**
1684
+ * Renderiza campos normales
1685
+ */
1686
+ renderFields(container, fields) {
1687
+ for (const field of fields) {
1688
+ const fieldElement = this.renderField(field);
1689
+ if (fieldElement) {
1690
+ container.appendChild(fieldElement);
1691
+ }
1692
+ }
1693
+ }
1694
+ /**
1695
+ * Renderiza un campo
1696
+ */
1697
+ renderField(field) {
1698
+ if (field.type === "group") {
1699
+ return this.renderGroup(field);
1700
+ }
1701
+ if (field.type === "array") {
1702
+ return this.renderArray(field);
1703
+ }
1704
+ if (field.type === "custom") {
1705
+ return this.renderCustom(field);
1706
+ }
1707
+ const value = this.stateManager.getValue(field.name);
1708
+ const errors = this.stateManager.getErrors(field.name);
1709
+ const error = errors.length > 0 ? errors[0] : void 0;
1710
+ const customComponent = getCustomComponent(field.type);
1711
+ if (customComponent) {
1712
+ return customComponent({
1713
+ field,
1714
+ value,
1715
+ error,
1716
+ onChange: (val) => this.handleFieldChange(field.name, val),
1717
+ onBlur: () => this.handleFieldBlur(field.name)
1718
+ });
1719
+ }
1720
+ return createInput(
1721
+ field,
1722
+ value,
1723
+ error,
1724
+ (val) => this.handleFieldChange(field.name, val),
1725
+ () => this.handleFieldBlur(field.name)
1726
+ );
1727
+ }
1728
+ /**
1729
+ * Renderiza un grupo de campos
1730
+ */
1731
+ renderGroup(field) {
1732
+ const groupContainer = document.createElement("div");
1733
+ groupContainer.className = "easy-form-group";
1734
+ if (field.label) {
1735
+ const label = document.createElement("h3");
1736
+ label.className = "easy-form-group-label";
1737
+ label.textContent = field.label;
1738
+ groupContainer.appendChild(label);
1739
+ }
1740
+ if ("fields" in field && field.fields) {
1741
+ for (const subField of field.fields) {
1742
+ const fieldElement = this.renderField(subField);
1743
+ if (fieldElement) {
1744
+ groupContainer.appendChild(fieldElement);
1745
+ }
1746
+ }
1747
+ }
1748
+ return groupContainer;
1749
+ }
1750
+ /**
1751
+ * Renderiza un array dinámico
1752
+ */
1753
+ renderArray(field) {
1754
+ const arrayContainer = document.createElement("div");
1755
+ arrayContainer.className = "easy-form-array";
1756
+ if (field.label) {
1757
+ const label = document.createElement("label");
1758
+ label.className = "easy-form-label";
1759
+ label.textContent = field.label;
1760
+ arrayContainer.appendChild(label);
1761
+ }
1762
+ const values = this.stateManager.getValue(field.name) || [];
1763
+ const arrayField = field;
1764
+ const itemsContainer = document.createElement("div");
1765
+ itemsContainer.className = "easy-form-array-items";
1766
+ for (let i = 0; i < values.length; i++) {
1767
+ const itemContainer = document.createElement("div");
1768
+ itemContainer.className = "easy-form-array-item";
1769
+ if (arrayField.itemSchema?.fields) {
1770
+ for (const itemField of arrayField.itemSchema.fields) {
1771
+ const itemFieldWithName = {
1772
+ ...itemField,
1773
+ name: `${field.name}.${i}.${itemField.name}`
1774
+ };
1775
+ const fieldElement = this.renderField(itemFieldWithName);
1776
+ if (fieldElement) {
1777
+ itemContainer.appendChild(fieldElement);
1778
+ }
1779
+ }
1780
+ }
1781
+ const removeButton = document.createElement("button");
1782
+ removeButton.type = "button";
1783
+ removeButton.textContent = "Eliminar";
1784
+ removeButton.className = "easy-form-array-remove";
1785
+ removeButton.addEventListener("click", () => {
1786
+ const newValues = [...values];
1787
+ newValues.splice(i, 1);
1788
+ this.handleFieldChange(field.name, newValues);
1789
+ });
1790
+ itemContainer.appendChild(removeButton);
1791
+ itemsContainer.appendChild(itemContainer);
1792
+ }
1793
+ arrayContainer.appendChild(itemsContainer);
1794
+ const addButton = document.createElement("button");
1795
+ addButton.type = "button";
1796
+ addButton.textContent = "Agregar";
1797
+ addButton.className = "easy-form-array-add";
1798
+ addButton.addEventListener("click", () => {
1799
+ const newValues = [...values, {}];
1800
+ this.handleFieldChange(field.name, newValues);
1801
+ });
1802
+ arrayContainer.appendChild(addButton);
1803
+ return arrayContainer;
1804
+ }
1805
+ /**
1806
+ * Renderiza un campo custom
1807
+ */
1808
+ renderCustom(field) {
1809
+ const customComponent = getCustomComponent("custom");
1810
+ if (!customComponent) {
1811
+ const div = document.createElement("div");
1812
+ div.textContent = `Componente custom no registrado para: ${field.name}`;
1813
+ return div;
1814
+ }
1815
+ const value = this.stateManager.getValue(field.name);
1816
+ const errors = this.stateManager.getErrors(field.name);
1817
+ const error = errors.length > 0 ? errors[0] : void 0;
1818
+ return customComponent({
1819
+ field,
1820
+ value,
1821
+ error,
1822
+ onChange: (val) => this.handleFieldChange(field.name, val),
1823
+ onBlur: () => this.handleFieldBlur(field.name)
1824
+ });
1825
+ }
1826
+ /**
1827
+ * Renderiza wizard
1828
+ */
1829
+ renderWizard(container, wizardState) {
1830
+ const wizardContainer = document.createElement("div");
1831
+ wizardContainer.className = "easy-form-wizard";
1832
+ const stepsIndicator = document.createElement("div");
1833
+ stepsIndicator.className = "easy-form-wizard-steps";
1834
+ const schema = this.schema;
1835
+ if (schema?.steps) {
1836
+ for (let i = 0; i < schema.steps.length; i++) {
1837
+ const stepEl = document.createElement("div");
1838
+ stepEl.className = "easy-form-wizard-step";
1839
+ if (i === wizardState.currentStep) {
1840
+ stepEl.classList.add("active");
1841
+ }
1842
+ if (wizardState.completedSteps.includes(i)) {
1843
+ stepEl.classList.add("completed");
1844
+ }
1845
+ stepEl.textContent = schema.steps[i].title;
1846
+ stepsIndicator.appendChild(stepEl);
1847
+ }
1848
+ }
1849
+ wizardContainer.appendChild(stepsIndicator);
1850
+ const fieldsContainer = document.createElement("div");
1851
+ fieldsContainer.className = "easy-form-wizard-fields";
1852
+ const currentFields = this.stateManager.getCurrentStepFields();
1853
+ for (const field of currentFields) {
1854
+ const fieldElement = this.renderField(field);
1855
+ if (fieldElement) {
1856
+ fieldsContainer.appendChild(fieldElement);
1857
+ }
1858
+ }
1859
+ wizardContainer.appendChild(fieldsContainer);
1860
+ const navContainer = document.createElement("div");
1861
+ navContainer.className = "easy-form-wizard-nav";
1862
+ const prevButton = document.createElement("button");
1863
+ prevButton.type = "button";
1864
+ prevButton.textContent = "Anterior";
1865
+ prevButton.className = "easy-form-wizard-prev";
1866
+ prevButton.disabled = wizardState.currentStep === 0;
1867
+ prevButton.addEventListener("click", () => {
1868
+ if (this.stateManager.previousStep()) {
1869
+ this.render();
1870
+ this.emitStepChange();
1871
+ }
1872
+ });
1873
+ navContainer.appendChild(prevButton);
1874
+ const nextButton = document.createElement("button");
1875
+ nextButton.type = "button";
1876
+ nextButton.textContent = wizardState.currentStep === wizardState.totalSteps - 1 ? "Enviar" : "Siguiente";
1877
+ nextButton.className = "easy-form-wizard-next";
1878
+ nextButton.addEventListener("click", async () => {
1879
+ if (wizardState.currentStep === wizardState.totalSteps - 1) {
1880
+ await this.handleSubmit(new Event("submit"));
1881
+ } else {
1882
+ const currentFields2 = this.stateManager.getCurrentStepFields();
1883
+ const errors = await this.stateManager.validateForm();
1884
+ const hasErrors = currentFields2.some(
1885
+ (f) => errors[f.name] && errors[f.name].length > 0
1886
+ );
1887
+ if (!hasErrors) {
1888
+ this.stateManager.completeStep(wizardState.currentStep);
1889
+ if (this.stateManager.nextStep()) {
1890
+ this.render();
1891
+ this.emitStepChange();
1892
+ }
1893
+ } else {
1894
+ this.emitError(errors);
1895
+ }
1896
+ }
1897
+ });
1898
+ navContainer.appendChild(nextButton);
1899
+ wizardContainer.appendChild(navContainer);
1900
+ container.appendChild(wizardContainer);
1901
+ }
1902
+ /**
1903
+ * Maneja el cambio de un campo
1904
+ */
1905
+ async handleFieldChange(fieldName, value) {
1906
+ await this.stateManager.setValue(fieldName, value);
1907
+ const changeEvent = new CustomEvent("change", {
1908
+ detail: {
1909
+ field: fieldName,
1910
+ value,
1911
+ values: this.stateManager.getState().values
1912
+ },
1913
+ bubbles: true,
1914
+ composed: true
1915
+ });
1916
+ this.dispatchEvent(changeEvent);
1917
+ }
1918
+ /**
1919
+ * Maneja el blur de un campo
1920
+ */
1921
+ async handleFieldBlur(fieldName) {
1922
+ this.stateManager.setTouched(fieldName);
1923
+ await this.stateManager.validateField(fieldName);
1924
+ this.updateSingleField(fieldName);
1925
+ }
1926
+ /**
1927
+ * Actualiza solo un campo específico sin re-renderizar todo el formulario
1928
+ */
1929
+ updateSingleField(fieldName) {
1930
+ const schema = this.schema;
1931
+ if (!schema) return;
1932
+ const field = this.findFieldInSchema(schema, fieldName);
1933
+ if (!field) return;
1934
+ const errors = this.stateManager.getErrors(fieldName);
1935
+ const error = errors.length > 0 ? errors[0] : void 0;
1936
+ const fieldContainer = this.shadow.querySelector(`[name="${fieldName}"]`)?.closest(".easy-form-field");
1937
+ if (!fieldContainer) return;
1938
+ const errorElement = fieldContainer.querySelector(".easy-form-error");
1939
+ if (error) {
1940
+ if (!errorElement) {
1941
+ const errorEl = document.createElement("p");
1942
+ errorEl.className = "easy-form-error";
1943
+ errorEl.textContent = error;
1944
+ fieldContainer.appendChild(errorEl);
1945
+ } else {
1946
+ errorElement.textContent = error;
1947
+ }
1948
+ const input = fieldContainer.querySelector("input, textarea, select");
1949
+ input?.classList.add("easy-form-input-error");
1950
+ } else {
1951
+ errorElement?.remove();
1952
+ const input = fieldContainer.querySelector("input, textarea, select");
1953
+ input?.classList.remove("easy-form-input-error");
1954
+ }
1955
+ }
1956
+ /**
1957
+ * Busca un campo por nombre en el schema
1958
+ */
1959
+ findFieldInSchema(schema, name) {
1960
+ const fields = schema.fields || [];
1961
+ for (const field of fields) {
1962
+ if (field.name === name) {
1963
+ return field;
1964
+ }
1965
+ if (field.type === "group" && "fields" in field) {
1966
+ const found = this.findFieldInSchema({ fields: field.fields }, name);
1967
+ if (found) return found;
1968
+ }
1969
+ }
1970
+ return null;
1971
+ }
1972
+ /**
1973
+ * Maneja el submit del formulario
1974
+ */
1975
+ async handleSubmit(event) {
1976
+ event.preventDefault();
1977
+ const errors = await this.stateManager.validateForm();
1978
+ const state = this.stateManager.getState();
1979
+ if (Object.keys(errors).length > 0) {
1980
+ this.emitError(errors);
1981
+ this.render();
1982
+ return;
1983
+ }
1984
+ const submitEvent = new CustomEvent("submit", {
1985
+ detail: {
1986
+ values: state.values,
1987
+ isValid: true,
1988
+ errors: {}
1989
+ },
1990
+ bubbles: true,
1991
+ composed: true
1992
+ });
1993
+ this.dispatchEvent(submitEvent);
1994
+ }
1995
+ /**
1996
+ * Emite evento de error
1997
+ */
1998
+ emitError(errors) {
1999
+ const errorEvent = new CustomEvent("error", {
2000
+ detail: {
2001
+ errors
2002
+ },
2003
+ bubbles: true,
2004
+ composed: true
2005
+ });
2006
+ this.dispatchEvent(errorEvent);
2007
+ }
2008
+ /**
2009
+ * Emite evento de cambio de step
2010
+ */
2011
+ emitStepChange() {
2012
+ const wizardState = this.stateManager.getWizardState();
2013
+ if (!wizardState) return;
2014
+ const stepChangeEvent = new CustomEvent(
2015
+ "stepChange",
2016
+ {
2017
+ detail: {
2018
+ currentStep: wizardState.currentStep,
2019
+ previousStep: wizardState.currentStep > 0 ? wizardState.currentStep - 1 : wizardState.currentStep,
2020
+ totalSteps: wizardState.totalSteps
2021
+ },
2022
+ bubbles: true,
2023
+ composed: true
2024
+ }
2025
+ );
2026
+ this.dispatchEvent(stepChangeEvent);
2027
+ }
2028
+ /**
2029
+ * Registra componentes personalizados
2030
+ */
2031
+ registerComponents(components) {
2032
+ this.customComponents = { ...this.customComponents, ...components };
2033
+ registerComponents(components);
2034
+ }
2035
+ /**
2036
+ * Obtiene el tema del formulario
2037
+ */
2038
+ get theme() {
2039
+ const themeAttr = this.getAttribute("theme");
2040
+ if (themeAttr && ["plano", "tradicional", "material", "rounded-shadow", "lines"].includes(themeAttr)) {
2041
+ return themeAttr;
2042
+ }
2043
+ return "plano";
2044
+ }
2045
+ /**
2046
+ * Establece el tema del formulario
2047
+ */
2048
+ set theme(value) {
2049
+ if (value) {
2050
+ this.setAttribute("theme", value);
2051
+ } else {
2052
+ this.removeAttribute("theme");
2053
+ }
2054
+ }
2055
+ /**
2056
+ * Obtiene los colores personalizados
2057
+ */
2058
+ get colors() {
2059
+ const colorsAttr = this.getAttribute("colors");
2060
+ if (!colorsAttr) return null;
2061
+ return parseAttributeValue(colorsAttr);
2062
+ }
2063
+ /**
2064
+ * Establece los colores personalizados
2065
+ */
2066
+ set colors(value) {
2067
+ if (value) {
2068
+ this.setAttribute("colors", attributeValue(value));
2069
+ } else {
2070
+ this.removeAttribute("colors");
2071
+ }
2072
+ }
2073
+ /**
2074
+ * Configura estilos básicos
2075
+ */
2076
+ setupStyles() {
2077
+ const existingStyle = this.shadow.querySelector("style");
2078
+ if (existingStyle) {
2079
+ existingStyle.remove();
2080
+ }
2081
+ const theme = this.theme;
2082
+ const colors = getColors(this.colors || void 0);
2083
+ const styles = getThemeStyles(theme, colors);
2084
+ const style = document.createElement("style");
2085
+ style.textContent = styles;
2086
+ if (this.shadow.firstChild) {
2087
+ this.shadow.insertBefore(style, this.shadow.firstChild);
2088
+ } else {
2089
+ this.shadow.appendChild(style);
2090
+ }
2091
+ }
2092
+ };
2093
+ if (typeof window !== "undefined" && typeof customElements !== "undefined" && !customElements.get("easy-form")) {
2094
+ customElements.define("easy-form", EasyForm);
2095
+ }
2096
+ export {
2097
+ EasyForm,
2098
+ SchemaParser,
2099
+ StateManager,
2100
+ ValidationEngine,
2101
+ attributeValue,
2102
+ createInput,
2103
+ generateId,
2104
+ getColors,
2105
+ getCustomComponent,
2106
+ getNestedValue,
2107
+ getThemeStyles,
2108
+ isValidEmail,
2109
+ parseAttributeValue,
2110
+ registerComponent,
2111
+ registerComponents,
2112
+ sanitizeId,
2113
+ setNestedValue
2114
+ };
2115
+ //# sourceMappingURL=index.js.map