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.
@@ -0,0 +1,2093 @@
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 getNestedValue(obj, path) {
605
+ return path.split(".").reduce((current, key) => current?.[key], obj);
606
+ }
607
+ function setNestedValue(obj, path, value) {
608
+ const keys = path.split(".");
609
+ const lastKey = keys.pop();
610
+ const target = keys.reduce((current, key) => {
611
+ if (!current[key] || typeof current[key] !== "object") {
612
+ current[key] = {};
613
+ }
614
+ return current[key];
615
+ }, obj);
616
+ target[lastKey] = value;
617
+ }
618
+ function isValidEmail(email) {
619
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
620
+ return emailRegex.test(email);
621
+ }
622
+
623
+ // src/core/validation-engine.ts
624
+ var ValidationEngine = class {
625
+ /**
626
+ * Valida un campo con todas sus validaciones
627
+ */
628
+ async validateField(field, value) {
629
+ const errors = [];
630
+ if (!field.validations || field.validations.length === 0) {
631
+ return errors;
632
+ }
633
+ for (const validation of field.validations) {
634
+ const result = await this.validateValue(validation, value);
635
+ if (!result.isValid) {
636
+ errors.push(result.message || this.getDefaultMessage(validation));
637
+ }
638
+ }
639
+ return errors;
640
+ }
641
+ /**
642
+ * Valida un valor con una validación específica
643
+ */
644
+ async validateValue(validation, value) {
645
+ switch (validation.type) {
646
+ case "required":
647
+ return this.validateRequired(value);
648
+ case "email":
649
+ return this.validateEmail(value);
650
+ case "minLength":
651
+ return this.validateMinLength(value, validation.value);
652
+ case "maxLength":
653
+ return this.validateMaxLength(value, validation.value);
654
+ case "min":
655
+ return this.validateMin(value, validation.value);
656
+ case "max":
657
+ return this.validateMax(value, validation.value);
658
+ case "pattern":
659
+ return this.validatePattern(value, validation.value);
660
+ case "custom":
661
+ return await this.validateCustom(value, validation);
662
+ default:
663
+ return { isValid: true };
664
+ }
665
+ }
666
+ /**
667
+ * Valida campo requerido
668
+ */
669
+ validateRequired(value) {
670
+ const isValid = value !== null && value !== void 0 && value !== "" && !(Array.isArray(value) && value.length === 0);
671
+ return {
672
+ isValid,
673
+ message: isValid ? void 0 : "Este campo es requerido"
674
+ };
675
+ }
676
+ /**
677
+ * Valida email
678
+ */
679
+ validateEmail(value) {
680
+ if (!value) {
681
+ return { isValid: true };
682
+ }
683
+ const isValid = typeof value === "string" && isValidEmail(value);
684
+ return {
685
+ isValid,
686
+ message: isValid ? void 0 : "Debe ser un email v\xE1lido"
687
+ };
688
+ }
689
+ /**
690
+ * Valida longitud mínima
691
+ */
692
+ validateMinLength(value, minLength) {
693
+ if (!value) {
694
+ return { isValid: true };
695
+ }
696
+ const str = String(value);
697
+ const isValid = str.length >= minLength;
698
+ return {
699
+ isValid,
700
+ message: isValid ? void 0 : `Debe tener al menos ${minLength} caracteres`
701
+ };
702
+ }
703
+ /**
704
+ * Valida longitud máxima
705
+ */
706
+ validateMaxLength(value, maxLength) {
707
+ if (!value) {
708
+ return { isValid: true };
709
+ }
710
+ const str = String(value);
711
+ const isValid = str.length <= maxLength;
712
+ return {
713
+ isValid,
714
+ message: isValid ? void 0 : `Debe tener m\xE1ximo ${maxLength} caracteres`
715
+ };
716
+ }
717
+ /**
718
+ * Valida valor mínimo
719
+ */
720
+ validateMin(value, min) {
721
+ if (value === null || value === void 0 || value === "") {
722
+ return { isValid: true };
723
+ }
724
+ const num = Number(value);
725
+ const isValid = !isNaN(num) && num >= min;
726
+ return {
727
+ isValid,
728
+ message: isValid ? void 0 : `Debe ser mayor o igual a ${min}`
729
+ };
730
+ }
731
+ /**
732
+ * Valida valor máximo
733
+ */
734
+ validateMax(value, max) {
735
+ if (value === null || value === void 0 || value === "") {
736
+ return { isValid: true };
737
+ }
738
+ const num = Number(value);
739
+ const isValid = !isNaN(num) && num <= max;
740
+ return {
741
+ isValid,
742
+ message: isValid ? void 0 : `Debe ser menor o igual a ${max}`
743
+ };
744
+ }
745
+ /**
746
+ * Valida patrón regex
747
+ */
748
+ validatePattern(value, pattern) {
749
+ if (!value) {
750
+ return { isValid: true };
751
+ }
752
+ const regex = typeof pattern === "string" ? new RegExp(pattern) : pattern;
753
+ const isValid = regex.test(String(value));
754
+ return {
755
+ isValid,
756
+ message: isValid ? void 0 : "El formato no es v\xE1lido"
757
+ };
758
+ }
759
+ /**
760
+ * Valida con función personalizada
761
+ */
762
+ async validateCustom(value, validation) {
763
+ try {
764
+ const result = await validation.validator(value);
765
+ return {
766
+ isValid: Boolean(result),
767
+ message: result ? void 0 : validation.message || "Validaci\xF3n fallida"
768
+ };
769
+ } catch (error) {
770
+ return {
771
+ isValid: false,
772
+ message: validation.message || "Error en la validaci\xF3n"
773
+ };
774
+ }
775
+ }
776
+ /**
777
+ * Obtiene mensaje por defecto para una validación
778
+ */
779
+ getDefaultMessage(validation) {
780
+ switch (validation.type) {
781
+ case "required":
782
+ return "Este campo es requerido";
783
+ case "email":
784
+ return "Debe ser un email v\xE1lido";
785
+ case "minLength":
786
+ return `Debe tener al menos ${validation.value} caracteres`;
787
+ case "maxLength":
788
+ return `Debe tener m\xE1ximo ${validation.value} caracteres`;
789
+ case "min":
790
+ return `Debe ser mayor o igual a ${validation.value}`;
791
+ case "max":
792
+ return `Debe ser menor o igual a ${validation.value}`;
793
+ case "pattern":
794
+ return "El formato no es v\xE1lido";
795
+ case "custom":
796
+ return "Validaci\xF3n fallida";
797
+ default:
798
+ return "Campo inv\xE1lido";
799
+ }
800
+ }
801
+ /**
802
+ * Valida todos los campos de un formulario
803
+ */
804
+ async validateForm(fields, values) {
805
+ const errors = {};
806
+ for (const field of fields) {
807
+ const value = values[field.name];
808
+ const fieldErrors = await this.validateField(field, value);
809
+ if (fieldErrors.length > 0) {
810
+ errors[field.name] = fieldErrors;
811
+ }
812
+ }
813
+ return errors;
814
+ }
815
+ };
816
+
817
+ // src/core/state-manager.ts
818
+ var StateManager = class {
819
+ constructor() {
820
+ this.wizardState = null;
821
+ this.schema = null;
822
+ this.parser = new SchemaParser();
823
+ this.validator = new ValidationEngine();
824
+ this.state = this.createInitialState();
825
+ }
826
+ /**
827
+ * Crea el estado inicial
828
+ */
829
+ createInitialState() {
830
+ return {
831
+ values: {},
832
+ errors: {},
833
+ touched: {},
834
+ isValid: true,
835
+ isSubmitting: false
836
+ };
837
+ }
838
+ /**
839
+ * Inicializa el schema
840
+ */
841
+ initializeSchema(schema) {
842
+ this.schema = this.parser.parse(schema);
843
+ this.initializeValues();
844
+ this.initializeWizard();
845
+ }
846
+ /**
847
+ * Inicializa los valores por defecto
848
+ */
849
+ initializeValues() {
850
+ if (!this.schema) return;
851
+ const allFields = this.schema.isWizard ? this.schema.steps.flatMap((step) => step.fields) : this.schema.fields;
852
+ const existingValues = { ...this.state.values };
853
+ const values = {};
854
+ for (const field of allFields) {
855
+ const existingValue = getNestedValue(existingValues, field.name);
856
+ if (existingValue !== void 0 && existingValue !== null) {
857
+ values[field.name] = existingValue;
858
+ } else {
859
+ this.initializeFieldValue(field, values);
860
+ }
861
+ }
862
+ for (const key in existingValues) {
863
+ if (!(key in values)) {
864
+ values[key] = existingValues[key];
865
+ }
866
+ }
867
+ this.state.values = values;
868
+ }
869
+ /**
870
+ * Inicializa el valor de un campo
871
+ */
872
+ initializeFieldValue(field, values) {
873
+ if (field.defaultValue !== void 0) {
874
+ values[field.name] = field.defaultValue;
875
+ } else {
876
+ switch (field.type) {
877
+ case "checkbox":
878
+ case "switch":
879
+ values[field.name] = field.checked || false;
880
+ break;
881
+ case "select":
882
+ if ("multiple" in field && field.multiple) {
883
+ values[field.name] = [];
884
+ } else {
885
+ values[field.name] = null;
886
+ }
887
+ break;
888
+ case "array":
889
+ values[field.name] = [];
890
+ break;
891
+ case "group":
892
+ values[field.name] = {};
893
+ if ("fields" in field) {
894
+ for (const subField of field.fields) {
895
+ this.initializeFieldValue(subField, values[field.name]);
896
+ }
897
+ }
898
+ break;
899
+ default:
900
+ values[field.name] = null;
901
+ }
902
+ }
903
+ }
904
+ /**
905
+ * Inicializa el estado del wizard
906
+ */
907
+ initializeWizard() {
908
+ if (!this.schema || !this.schema.isWizard) {
909
+ this.wizardState = null;
910
+ return;
911
+ }
912
+ this.wizardState = {
913
+ currentStep: 0,
914
+ totalSteps: this.schema.steps.length,
915
+ completedSteps: []
916
+ };
917
+ }
918
+ /**
919
+ * Obtiene el estado actual
920
+ */
921
+ getState() {
922
+ return { ...this.state };
923
+ }
924
+ /**
925
+ * Obtiene el estado del wizard
926
+ */
927
+ getWizardState() {
928
+ return this.wizardState ? { ...this.wizardState } : null;
929
+ }
930
+ /**
931
+ * Obtiene un valor del formulario
932
+ */
933
+ getValue(fieldName) {
934
+ return getNestedValue(this.state.values, fieldName);
935
+ }
936
+ /**
937
+ * Establece un valor
938
+ */
939
+ async setValue(fieldName, value) {
940
+ setNestedValue(this.state.values, fieldName, value);
941
+ this.state.touched[fieldName] = true;
942
+ if (this.state.touched[fieldName] && this.schema) {
943
+ await this.validateField(fieldName);
944
+ }
945
+ this.updateValidity();
946
+ }
947
+ /**
948
+ * Establece un valor sin validar (útil para preservar valores durante re-renderizado)
949
+ */
950
+ setValueWithoutValidation(fieldName, value) {
951
+ setNestedValue(this.state.values, fieldName, value);
952
+ }
953
+ /**
954
+ * Valida un campo específico
955
+ */
956
+ async validateField(fieldName) {
957
+ if (!this.schema) return;
958
+ const allFields = this.schema.isWizard ? this.schema.steps.flatMap((step) => step.fields) : this.schema.fields;
959
+ const field = allFields.find((f) => f.name === fieldName);
960
+ if (!field) return;
961
+ const value = this.getValue(fieldName);
962
+ const errors = await this.validator.validateField(
963
+ field,
964
+ value
965
+ );
966
+ if (errors.length > 0) {
967
+ this.state.errors[fieldName] = errors;
968
+ } else {
969
+ delete this.state.errors[fieldName];
970
+ }
971
+ }
972
+ /**
973
+ * Valida todo el formulario
974
+ */
975
+ async validateForm() {
976
+ if (!this.schema) {
977
+ return {};
978
+ }
979
+ const allFields = this.schema.isWizard ? this.schema.steps.flatMap((step) => step.fields) : this.schema.fields;
980
+ const errors = await this.validator.validateForm(
981
+ allFields,
982
+ this.state.values
983
+ );
984
+ this.state.errors = errors;
985
+ this.updateValidity();
986
+ return errors;
987
+ }
988
+ /**
989
+ * Actualiza la validez del formulario
990
+ */
991
+ updateValidity() {
992
+ this.state.isValid = Object.keys(this.state.errors).length === 0;
993
+ }
994
+ /**
995
+ * Marca un campo como touched
996
+ */
997
+ setTouched(fieldName) {
998
+ this.state.touched[fieldName] = true;
999
+ }
1000
+ /**
1001
+ * Obtiene los errores de un campo
1002
+ */
1003
+ getErrors(fieldName) {
1004
+ return this.state.errors[fieldName] || [];
1005
+ }
1006
+ /**
1007
+ * Obtiene todos los errores
1008
+ */
1009
+ getAllErrors() {
1010
+ return { ...this.state.errors };
1011
+ }
1012
+ /**
1013
+ * Resetea el formulario
1014
+ */
1015
+ reset() {
1016
+ this.state = this.createInitialState();
1017
+ if (this.schema) {
1018
+ this.initializeValues();
1019
+ this.initializeWizard();
1020
+ }
1021
+ }
1022
+ /**
1023
+ * Avanza al siguiente step del wizard
1024
+ */
1025
+ nextStep() {
1026
+ if (!this.wizardState) return false;
1027
+ if (this.wizardState.currentStep < this.wizardState.totalSteps - 1) {
1028
+ this.wizardState.currentStep++;
1029
+ return true;
1030
+ }
1031
+ return false;
1032
+ }
1033
+ /**
1034
+ * Retrocede al step anterior del wizard
1035
+ */
1036
+ previousStep() {
1037
+ if (!this.wizardState) return false;
1038
+ if (this.wizardState.currentStep > 0) {
1039
+ this.wizardState.currentStep--;
1040
+ return true;
1041
+ }
1042
+ return false;
1043
+ }
1044
+ /**
1045
+ * Va a un step específico
1046
+ */
1047
+ goToStep(stepIndex) {
1048
+ if (!this.wizardState) return false;
1049
+ if (stepIndex >= 0 && stepIndex < this.wizardState.totalSteps) {
1050
+ this.wizardState.currentStep = stepIndex;
1051
+ return true;
1052
+ }
1053
+ return false;
1054
+ }
1055
+ /**
1056
+ * Marca un step como completado
1057
+ */
1058
+ completeStep(stepIndex) {
1059
+ if (!this.wizardState) return;
1060
+ if (!this.wizardState.completedSteps.includes(stepIndex)) {
1061
+ this.wizardState.completedSteps.push(stepIndex);
1062
+ }
1063
+ }
1064
+ /**
1065
+ * Establece el estado de submitting
1066
+ */
1067
+ setSubmitting(isSubmitting) {
1068
+ this.state.isSubmitting = isSubmitting;
1069
+ }
1070
+ /**
1071
+ * Obtiene los campos del step actual
1072
+ */
1073
+ getCurrentStepFields() {
1074
+ if (!this.schema || !this.schema.isWizard || !this.wizardState) {
1075
+ return this.schema?.fields || [];
1076
+ }
1077
+ return this.schema.steps[this.wizardState.currentStep].fields;
1078
+ }
1079
+ };
1080
+
1081
+ // src/components/inputs/base-input.ts
1082
+ var BaseInput = class {
1083
+ constructor(field, value, error, onChange, onBlur) {
1084
+ this.field = field;
1085
+ this.value = value;
1086
+ this.error = error;
1087
+ this.onChange = onChange;
1088
+ this.onBlur = onBlur;
1089
+ }
1090
+ /**
1091
+ * Crea un contenedor con label y error
1092
+ */
1093
+ createFieldContainer(input) {
1094
+ const container = document.createElement("div");
1095
+ container.className = "easy-form-field";
1096
+ if (this.field.label) {
1097
+ const label = document.createElement("label");
1098
+ label.className = "easy-form-label";
1099
+ label.setAttribute("for", this.getFieldId());
1100
+ label.textContent = this.field.label;
1101
+ if (this.field.validations?.some((v) => v.type === "required")) {
1102
+ const required = document.createElement("span");
1103
+ required.className = "easy-form-required";
1104
+ required.textContent = " *";
1105
+ label.appendChild(required);
1106
+ }
1107
+ container.appendChild(label);
1108
+ }
1109
+ container.appendChild(input);
1110
+ if (this.field.description) {
1111
+ const description = document.createElement("p");
1112
+ description.className = "easy-form-description";
1113
+ description.textContent = this.field.description;
1114
+ container.appendChild(description);
1115
+ }
1116
+ if (this.error) {
1117
+ const errorEl = document.createElement("p");
1118
+ errorEl.className = "easy-form-error";
1119
+ errorEl.textContent = this.error;
1120
+ container.appendChild(errorEl);
1121
+ }
1122
+ return container;
1123
+ }
1124
+ /**
1125
+ * Obtiene el ID del campo
1126
+ */
1127
+ getFieldId() {
1128
+ return `easy-form-${this.field.name}`;
1129
+ }
1130
+ /**
1131
+ * Aplica props comunes a un elemento
1132
+ */
1133
+ applyCommonProps(element) {
1134
+ element.id = this.getFieldId();
1135
+ element.setAttribute("name", this.field.name);
1136
+ if (this.field.disabled) {
1137
+ element.setAttribute("disabled", "true");
1138
+ }
1139
+ if (this.field.hidden) {
1140
+ element.style.display = "none";
1141
+ }
1142
+ if (this.error) {
1143
+ element.classList.add("easy-form-input-error");
1144
+ }
1145
+ if (this.field.props) {
1146
+ for (const [key, value] of Object.entries(this.field.props)) {
1147
+ if (key.startsWith("data-") || key.startsWith("aria-")) {
1148
+ element.setAttribute(key, String(value));
1149
+ }
1150
+ }
1151
+ }
1152
+ }
1153
+ };
1154
+
1155
+ // src/components/inputs/text-input.ts
1156
+ var TextInput = class extends BaseInput {
1157
+ render() {
1158
+ const input = document.createElement("input");
1159
+ input.type = this.field.type === "email" ? "email" : this.field.type === "password" ? "password" : "text";
1160
+ input.value = this.value ?? "";
1161
+ input.placeholder = this.field.placeholder || "";
1162
+ this.applyCommonProps(input);
1163
+ input.addEventListener("input", (e) => {
1164
+ const target = e.target;
1165
+ this.onChange(target.value);
1166
+ });
1167
+ input.addEventListener("blur", () => {
1168
+ this.onBlur();
1169
+ });
1170
+ return this.createFieldContainer(input);
1171
+ }
1172
+ };
1173
+
1174
+ // src/components/inputs/number-input.ts
1175
+ var NumberInput = class extends BaseInput {
1176
+ render() {
1177
+ const input = document.createElement("input");
1178
+ input.type = "number";
1179
+ input.value = this.value ?? "";
1180
+ input.placeholder = this.field.placeholder || "";
1181
+ const numberField = this.field;
1182
+ if (numberField.min !== void 0) {
1183
+ input.min = String(numberField.min);
1184
+ }
1185
+ if (numberField.max !== void 0) {
1186
+ input.max = String(numberField.max);
1187
+ }
1188
+ if (numberField.step !== void 0) {
1189
+ input.step = String(numberField.step);
1190
+ }
1191
+ this.applyCommonProps(input);
1192
+ input.addEventListener("input", (e) => {
1193
+ const target = e.target;
1194
+ const numValue = target.value === "" ? null : Number(target.value);
1195
+ this.onChange(numValue);
1196
+ });
1197
+ input.addEventListener("blur", () => {
1198
+ this.onBlur();
1199
+ });
1200
+ return this.createFieldContainer(input);
1201
+ }
1202
+ };
1203
+
1204
+ // src/components/inputs/textarea-input.ts
1205
+ var TextareaInput = class extends BaseInput {
1206
+ render() {
1207
+ const textarea = document.createElement("textarea");
1208
+ textarea.value = this.value ?? "";
1209
+ textarea.placeholder = this.field.placeholder || "";
1210
+ const textareaField = this.field;
1211
+ if (textareaField.rows) {
1212
+ textarea.rows = textareaField.rows;
1213
+ }
1214
+ if (textareaField.cols) {
1215
+ textarea.cols = textareaField.cols;
1216
+ }
1217
+ this.applyCommonProps(textarea);
1218
+ textarea.addEventListener("input", (e) => {
1219
+ const target = e.target;
1220
+ this.onChange(target.value);
1221
+ });
1222
+ textarea.addEventListener("blur", () => {
1223
+ this.onBlur();
1224
+ });
1225
+ return this.createFieldContainer(textarea);
1226
+ }
1227
+ };
1228
+
1229
+ // src/components/inputs/select-input.ts
1230
+ var SelectInput = class extends BaseInput {
1231
+ render() {
1232
+ const select = document.createElement("select");
1233
+ const selectField = this.field;
1234
+ if (selectField.multiple) {
1235
+ select.multiple = true;
1236
+ }
1237
+ for (const option of selectField.options) {
1238
+ const optionEl = document.createElement("option");
1239
+ if (typeof option === "string") {
1240
+ optionEl.value = option;
1241
+ optionEl.textContent = option;
1242
+ } else {
1243
+ optionEl.value = String(option.value);
1244
+ optionEl.textContent = option.label;
1245
+ }
1246
+ select.appendChild(optionEl);
1247
+ }
1248
+ if (selectField.multiple && Array.isArray(this.value)) {
1249
+ for (const option of select.options) {
1250
+ option.selected = this.value.includes(option.value);
1251
+ }
1252
+ } else {
1253
+ select.value = this.value ?? "";
1254
+ }
1255
+ this.applyCommonProps(select);
1256
+ select.addEventListener("change", (e) => {
1257
+ const target = e.target;
1258
+ if (selectField.multiple) {
1259
+ const selectedValues = Array.from(target.selectedOptions).map(
1260
+ (opt) => opt.value
1261
+ );
1262
+ this.onChange(selectedValues);
1263
+ } else {
1264
+ this.onChange(target.value || null);
1265
+ }
1266
+ });
1267
+ select.addEventListener("blur", () => {
1268
+ this.onBlur();
1269
+ });
1270
+ return this.createFieldContainer(select);
1271
+ }
1272
+ };
1273
+
1274
+ // src/components/inputs/checkbox-input.ts
1275
+ var CheckboxInput = class extends BaseInput {
1276
+ render() {
1277
+ const checkbox = document.createElement("input");
1278
+ checkbox.type = "checkbox";
1279
+ checkbox.checked = Boolean(this.value);
1280
+ this.applyCommonProps(checkbox);
1281
+ checkbox.addEventListener("change", (e) => {
1282
+ const target = e.target;
1283
+ this.onChange(target.checked);
1284
+ });
1285
+ checkbox.addEventListener("blur", () => {
1286
+ this.onBlur();
1287
+ });
1288
+ const container = document.createElement("div");
1289
+ container.className = "easy-form-field";
1290
+ const label = document.createElement("label");
1291
+ label.className = "easy-form-label-checkbox";
1292
+ label.setAttribute("for", this.getFieldId());
1293
+ label.appendChild(checkbox);
1294
+ if (this.field.label) {
1295
+ const labelText = document.createTextNode(this.field.label);
1296
+ label.appendChild(labelText);
1297
+ }
1298
+ container.appendChild(label);
1299
+ if (this.field.description) {
1300
+ const description = document.createElement("p");
1301
+ description.className = "easy-form-description";
1302
+ description.textContent = this.field.description;
1303
+ container.appendChild(description);
1304
+ }
1305
+ if (this.error) {
1306
+ const errorEl = document.createElement("p");
1307
+ errorEl.className = "easy-form-error";
1308
+ errorEl.textContent = this.error;
1309
+ container.appendChild(errorEl);
1310
+ }
1311
+ return container;
1312
+ }
1313
+ };
1314
+
1315
+ // src/components/inputs/radio-input.ts
1316
+ var RadioInput = class extends BaseInput {
1317
+ render() {
1318
+ const container = document.createElement("div");
1319
+ container.className = "easy-form-field";
1320
+ if (this.field.label) {
1321
+ const label = document.createElement("label");
1322
+ label.className = "easy-form-label";
1323
+ label.textContent = this.field.label;
1324
+ if (this.field.validations?.some((v) => v.type === "required")) {
1325
+ const required = document.createElement("span");
1326
+ required.className = "easy-form-required";
1327
+ required.textContent = " *";
1328
+ label.appendChild(required);
1329
+ }
1330
+ container.appendChild(label);
1331
+ }
1332
+ const radioGroup = document.createElement("div");
1333
+ radioGroup.className = "easy-form-radio-group";
1334
+ const radioField = this.field;
1335
+ for (const option of radioField.options) {
1336
+ const optionValue = typeof option === "string" ? option : option.value;
1337
+ const optionLabel = typeof option === "string" ? option : option.label;
1338
+ const radioContainer = document.createElement("div");
1339
+ radioContainer.className = "easy-form-radio-option";
1340
+ const radio = document.createElement("input");
1341
+ radio.type = "radio";
1342
+ radio.name = this.field.name;
1343
+ radio.id = `${this.getFieldId()}-${optionValue}`;
1344
+ radio.value = String(optionValue);
1345
+ radio.checked = String(this.value) === String(optionValue);
1346
+ if (this.field.disabled) {
1347
+ radio.disabled = true;
1348
+ }
1349
+ const label = document.createElement("label");
1350
+ label.setAttribute("for", radio.id);
1351
+ label.textContent = optionLabel;
1352
+ label.className = "easy-form-radio-label";
1353
+ radio.addEventListener("change", () => {
1354
+ this.onChange(optionValue);
1355
+ });
1356
+ radio.addEventListener("blur", () => {
1357
+ this.onBlur();
1358
+ });
1359
+ radioContainer.appendChild(radio);
1360
+ radioContainer.appendChild(label);
1361
+ radioGroup.appendChild(radioContainer);
1362
+ }
1363
+ container.appendChild(radioGroup);
1364
+ if (this.field.description) {
1365
+ const description = document.createElement("p");
1366
+ description.className = "easy-form-description";
1367
+ description.textContent = this.field.description;
1368
+ container.appendChild(description);
1369
+ }
1370
+ if (this.error) {
1371
+ const errorEl = document.createElement("p");
1372
+ errorEl.className = "easy-form-error";
1373
+ errorEl.textContent = this.error;
1374
+ container.appendChild(errorEl);
1375
+ }
1376
+ return container;
1377
+ }
1378
+ };
1379
+
1380
+ // src/components/inputs/switch-input.ts
1381
+ var SwitchInput = class extends BaseInput {
1382
+ render() {
1383
+ const switchEl = document.createElement("input");
1384
+ switchEl.type = "checkbox";
1385
+ switchEl.className = "easy-form-switch";
1386
+ switchEl.checked = Boolean(this.value);
1387
+ this.applyCommonProps(switchEl);
1388
+ switchEl.addEventListener("change", (e) => {
1389
+ const target = e.target;
1390
+ this.onChange(target.checked);
1391
+ });
1392
+ switchEl.addEventListener("blur", () => {
1393
+ this.onBlur();
1394
+ });
1395
+ const container = document.createElement("div");
1396
+ container.className = "easy-form-field";
1397
+ const label = document.createElement("label");
1398
+ label.className = "easy-form-label-switch";
1399
+ label.setAttribute("for", this.getFieldId());
1400
+ if (this.field.label) {
1401
+ const labelText = document.createTextNode(this.field.label);
1402
+ label.appendChild(labelText);
1403
+ }
1404
+ label.appendChild(switchEl);
1405
+ container.appendChild(label);
1406
+ if (this.field.description) {
1407
+ const description = document.createElement("p");
1408
+ description.className = "easy-form-description";
1409
+ description.textContent = this.field.description;
1410
+ container.appendChild(description);
1411
+ }
1412
+ if (this.error) {
1413
+ const errorEl = document.createElement("p");
1414
+ errorEl.className = "easy-form-error";
1415
+ errorEl.textContent = this.error;
1416
+ container.appendChild(errorEl);
1417
+ }
1418
+ return container;
1419
+ }
1420
+ };
1421
+
1422
+ // src/components/inputs/date-input.ts
1423
+ var DateInput = class extends BaseInput {
1424
+ render() {
1425
+ const input = document.createElement("input");
1426
+ input.type = "date";
1427
+ const dateField = this.field;
1428
+ if (dateField.min) {
1429
+ input.min = dateField.min;
1430
+ }
1431
+ if (dateField.max) {
1432
+ input.max = dateField.max;
1433
+ }
1434
+ if (this.value) {
1435
+ const date = this.value instanceof Date ? this.value.toISOString().split("T")[0] : String(this.value);
1436
+ input.value = date;
1437
+ }
1438
+ this.applyCommonProps(input);
1439
+ input.addEventListener("change", (e) => {
1440
+ const target = e.target;
1441
+ this.onChange(target.value || null);
1442
+ });
1443
+ input.addEventListener("blur", () => {
1444
+ this.onBlur();
1445
+ });
1446
+ return this.createFieldContainer(input);
1447
+ }
1448
+ };
1449
+
1450
+ // src/components/inputs/file-input.ts
1451
+ var FileInput = class extends BaseInput {
1452
+ render() {
1453
+ const input = document.createElement("input");
1454
+ input.type = "file";
1455
+ const fileField = this.field;
1456
+ if (fileField.accept) {
1457
+ input.accept = fileField.accept;
1458
+ }
1459
+ if (fileField.multiple) {
1460
+ input.multiple = true;
1461
+ }
1462
+ this.applyCommonProps(input);
1463
+ input.addEventListener("change", (e) => {
1464
+ const target = e.target;
1465
+ if (target.files) {
1466
+ if (fileField.multiple) {
1467
+ this.onChange(Array.from(target.files));
1468
+ } else {
1469
+ this.onChange(target.files[0] || null);
1470
+ }
1471
+ }
1472
+ });
1473
+ input.addEventListener("blur", () => {
1474
+ this.onBlur();
1475
+ });
1476
+ return this.createFieldContainer(input);
1477
+ }
1478
+ };
1479
+
1480
+ // src/components/inputs/index.ts
1481
+ function createInput(field, value, error, onChange, onBlur) {
1482
+ switch (field.type) {
1483
+ case "text":
1484
+ case "email":
1485
+ case "password":
1486
+ return new TextInput(field, value, error, onChange, onBlur).render();
1487
+ case "number":
1488
+ return new NumberInput(field, value, error, onChange, onBlur).render();
1489
+ case "textarea":
1490
+ return new TextareaInput(field, value, error, onChange, onBlur).render();
1491
+ case "select":
1492
+ return new SelectInput(field, value, error, onChange, onBlur).render();
1493
+ case "checkbox":
1494
+ return new CheckboxInput(field, value, error, onChange, onBlur).render();
1495
+ case "radio":
1496
+ return new RadioInput(field, value, error, onChange, onBlur).render();
1497
+ case "switch":
1498
+ return new SwitchInput(field, value, error, onChange, onBlur).render();
1499
+ case "date":
1500
+ return new DateInput(field, value, error, onChange, onBlur).render();
1501
+ case "file":
1502
+ return new FileInput(field, value, error, onChange, onBlur).render();
1503
+ default:
1504
+ const div = document.createElement("div");
1505
+ div.textContent = `Tipo de campo no soportado: ${field.type}`;
1506
+ return div;
1507
+ }
1508
+ }
1509
+ var customComponents = /* @__PURE__ */ new Map();
1510
+ function registerComponent(type, component) {
1511
+ customComponents.set(type, component);
1512
+ }
1513
+ function registerComponents(components) {
1514
+ for (const [type, component] of Object.entries(components)) {
1515
+ registerComponent(type, component);
1516
+ }
1517
+ }
1518
+ function getCustomComponent(type) {
1519
+ return customComponents.get(type);
1520
+ }
1521
+
1522
+ // src/components/easy-form.ts
1523
+ var BrowserHTMLElement = typeof HTMLElement !== "undefined" ? HTMLElement : class {
1524
+ };
1525
+ var EasyForm = class extends BrowserHTMLElement {
1526
+ constructor() {
1527
+ if (typeof HTMLElement === "undefined") {
1528
+ throw new Error("EasyForm can only be used in a browser environment");
1529
+ }
1530
+ super();
1531
+ this.customComponents = {};
1532
+ this.isRendering = false;
1533
+ this.stateManager = new StateManager();
1534
+ this.shadow = this.attachShadow({ mode: "open" });
1535
+ }
1536
+ static get observedAttributes() {
1537
+ return ["schema", "theme", "colors"];
1538
+ }
1539
+ /**
1540
+ * Obtiene el schema
1541
+ */
1542
+ get schema() {
1543
+ const schemaAttr = this.getAttribute("schema");
1544
+ if (!schemaAttr) return null;
1545
+ return parseAttributeValue(schemaAttr);
1546
+ }
1547
+ /**
1548
+ * Establece el schema
1549
+ */
1550
+ set schema(value) {
1551
+ if (value) {
1552
+ this.setAttribute("schema", attributeValue(value));
1553
+ } else {
1554
+ this.removeAttribute("schema");
1555
+ }
1556
+ }
1557
+ /**
1558
+ * Se llama cuando el componente se conecta al DOM
1559
+ */
1560
+ connectedCallback() {
1561
+ this.setupStyles();
1562
+ this.render();
1563
+ }
1564
+ /**
1565
+ * Se llama cuando un atributo cambia
1566
+ */
1567
+ attributeChangedCallback(name, oldValue, newValue) {
1568
+ if (name === "schema" && newValue !== oldValue) {
1569
+ this.handleSchemaChange();
1570
+ }
1571
+ if ((name === "theme" || name === "colors") && newValue !== oldValue) {
1572
+ this.setupStyles();
1573
+ }
1574
+ }
1575
+ /**
1576
+ * Maneja el cambio de schema
1577
+ */
1578
+ handleSchemaChange() {
1579
+ const schema = this.schema;
1580
+ if (schema) {
1581
+ this.stateManager.initializeSchema(schema);
1582
+ this.render();
1583
+ }
1584
+ }
1585
+ /**
1586
+ * Renderiza el formulario
1587
+ */
1588
+ async render() {
1589
+ if (this.isRendering) {
1590
+ return;
1591
+ }
1592
+ this.isRendering = true;
1593
+ try {
1594
+ const schema = this.schema;
1595
+ if (!schema) {
1596
+ const form = this.shadow.querySelector("form");
1597
+ if (form && form.parentNode === this.shadow) {
1598
+ form.remove();
1599
+ }
1600
+ return;
1601
+ }
1602
+ const preservedValues = this.preserveCurrentValues();
1603
+ if (preservedValues && Object.keys(preservedValues).length > 0) {
1604
+ for (const [key, value] of Object.entries(preservedValues)) {
1605
+ this.stateManager.setValueWithoutValidation(key, value);
1606
+ }
1607
+ }
1608
+ this.stateManager.initializeSchema(schema);
1609
+ const wizardState = this.stateManager.getWizardState();
1610
+ const newFormElement = document.createElement("form");
1611
+ newFormElement.addEventListener("submit", (e) => this.handleSubmit(e));
1612
+ if (wizardState) {
1613
+ this.renderWizard(newFormElement, wizardState);
1614
+ } else {
1615
+ this.renderFields(newFormElement, schema.fields || []);
1616
+ }
1617
+ const submitButton = document.createElement("button");
1618
+ submitButton.type = "submit";
1619
+ submitButton.textContent = "Enviar";
1620
+ submitButton.className = "easy-form-submit";
1621
+ newFormElement.appendChild(submitButton);
1622
+ const oldForm = this.shadow.querySelector("form");
1623
+ if (oldForm && oldForm.parentNode === this.shadow && oldForm !== newFormElement) {
1624
+ try {
1625
+ oldForm.remove();
1626
+ } catch (e) {
1627
+ console.warn("Error al eliminar formulario anterior:", e);
1628
+ }
1629
+ }
1630
+ this.shadow.appendChild(newFormElement);
1631
+ } finally {
1632
+ this.isRendering = false;
1633
+ }
1634
+ }
1635
+ /**
1636
+ * Preserva los valores actuales del DOM antes de re-renderizar
1637
+ * Retorna un objeto con los valores preservados
1638
+ */
1639
+ preserveCurrentValues() {
1640
+ const form = this.shadow.querySelector("form");
1641
+ const preservedValues = {};
1642
+ if (!form) return preservedValues;
1643
+ const inputs = form.querySelectorAll("input, textarea, select");
1644
+ for (const input of inputs) {
1645
+ const name = input.getAttribute("name");
1646
+ if (!name) continue;
1647
+ let value;
1648
+ if (input instanceof HTMLInputElement) {
1649
+ if (input.type === "checkbox") {
1650
+ value = input.checked;
1651
+ } else if (input.type === "radio") {
1652
+ if (input.checked) {
1653
+ value = input.value;
1654
+ } else {
1655
+ continue;
1656
+ }
1657
+ } else if (input.type === "number") {
1658
+ value = input.value === "" ? null : Number(input.value);
1659
+ } else {
1660
+ value = input.value;
1661
+ }
1662
+ } else if (input instanceof HTMLTextAreaElement) {
1663
+ value = input.value;
1664
+ } else if (input instanceof HTMLSelectElement) {
1665
+ if (input.multiple) {
1666
+ value = Array.from(input.selectedOptions).map((opt) => opt.value);
1667
+ } else {
1668
+ value = input.value || null;
1669
+ }
1670
+ }
1671
+ if (value !== void 0) {
1672
+ preservedValues[name] = value === "" ? null : value;
1673
+ }
1674
+ }
1675
+ return preservedValues;
1676
+ }
1677
+ /**
1678
+ * Renderiza campos normales
1679
+ */
1680
+ renderFields(container, fields) {
1681
+ for (const field of fields) {
1682
+ const fieldElement = this.renderField(field);
1683
+ if (fieldElement) {
1684
+ container.appendChild(fieldElement);
1685
+ }
1686
+ }
1687
+ }
1688
+ /**
1689
+ * Renderiza un campo
1690
+ */
1691
+ renderField(field) {
1692
+ if (field.type === "group") {
1693
+ return this.renderGroup(field);
1694
+ }
1695
+ if (field.type === "array") {
1696
+ return this.renderArray(field);
1697
+ }
1698
+ if (field.type === "custom") {
1699
+ return this.renderCustom(field);
1700
+ }
1701
+ const value = this.stateManager.getValue(field.name);
1702
+ const errors = this.stateManager.getErrors(field.name);
1703
+ const error = errors.length > 0 ? errors[0] : void 0;
1704
+ const customComponent = getCustomComponent(field.type);
1705
+ if (customComponent) {
1706
+ return customComponent({
1707
+ field,
1708
+ value,
1709
+ error,
1710
+ onChange: (val) => this.handleFieldChange(field.name, val),
1711
+ onBlur: () => this.handleFieldBlur(field.name)
1712
+ });
1713
+ }
1714
+ return createInput(
1715
+ field,
1716
+ value,
1717
+ error,
1718
+ (val) => this.handleFieldChange(field.name, val),
1719
+ () => this.handleFieldBlur(field.name)
1720
+ );
1721
+ }
1722
+ /**
1723
+ * Renderiza un grupo de campos
1724
+ */
1725
+ renderGroup(field) {
1726
+ const groupContainer = document.createElement("div");
1727
+ groupContainer.className = "easy-form-group";
1728
+ if (field.label) {
1729
+ const label = document.createElement("h3");
1730
+ label.className = "easy-form-group-label";
1731
+ label.textContent = field.label;
1732
+ groupContainer.appendChild(label);
1733
+ }
1734
+ if ("fields" in field && field.fields) {
1735
+ for (const subField of field.fields) {
1736
+ const fieldElement = this.renderField(subField);
1737
+ if (fieldElement) {
1738
+ groupContainer.appendChild(fieldElement);
1739
+ }
1740
+ }
1741
+ }
1742
+ return groupContainer;
1743
+ }
1744
+ /**
1745
+ * Renderiza un array dinámico
1746
+ */
1747
+ renderArray(field) {
1748
+ const arrayContainer = document.createElement("div");
1749
+ arrayContainer.className = "easy-form-array";
1750
+ if (field.label) {
1751
+ const label = document.createElement("label");
1752
+ label.className = "easy-form-label";
1753
+ label.textContent = field.label;
1754
+ arrayContainer.appendChild(label);
1755
+ }
1756
+ const values = this.stateManager.getValue(field.name) || [];
1757
+ const arrayField = field;
1758
+ const itemsContainer = document.createElement("div");
1759
+ itemsContainer.className = "easy-form-array-items";
1760
+ for (let i = 0; i < values.length; i++) {
1761
+ const itemContainer = document.createElement("div");
1762
+ itemContainer.className = "easy-form-array-item";
1763
+ if (arrayField.itemSchema?.fields) {
1764
+ for (const itemField of arrayField.itemSchema.fields) {
1765
+ const itemFieldWithName = {
1766
+ ...itemField,
1767
+ name: `${field.name}.${i}.${itemField.name}`
1768
+ };
1769
+ const fieldElement = this.renderField(itemFieldWithName);
1770
+ if (fieldElement) {
1771
+ itemContainer.appendChild(fieldElement);
1772
+ }
1773
+ }
1774
+ }
1775
+ const removeButton = document.createElement("button");
1776
+ removeButton.type = "button";
1777
+ removeButton.textContent = "Eliminar";
1778
+ removeButton.className = "easy-form-array-remove";
1779
+ removeButton.addEventListener("click", () => {
1780
+ const newValues = [...values];
1781
+ newValues.splice(i, 1);
1782
+ this.handleFieldChange(field.name, newValues);
1783
+ });
1784
+ itemContainer.appendChild(removeButton);
1785
+ itemsContainer.appendChild(itemContainer);
1786
+ }
1787
+ arrayContainer.appendChild(itemsContainer);
1788
+ const addButton = document.createElement("button");
1789
+ addButton.type = "button";
1790
+ addButton.textContent = "Agregar";
1791
+ addButton.className = "easy-form-array-add";
1792
+ addButton.addEventListener("click", () => {
1793
+ const newValues = [...values, {}];
1794
+ this.handleFieldChange(field.name, newValues);
1795
+ });
1796
+ arrayContainer.appendChild(addButton);
1797
+ return arrayContainer;
1798
+ }
1799
+ /**
1800
+ * Renderiza un campo custom
1801
+ */
1802
+ renderCustom(field) {
1803
+ const customComponent = getCustomComponent("custom");
1804
+ if (!customComponent) {
1805
+ const div = document.createElement("div");
1806
+ div.textContent = `Componente custom no registrado para: ${field.name}`;
1807
+ return div;
1808
+ }
1809
+ const value = this.stateManager.getValue(field.name);
1810
+ const errors = this.stateManager.getErrors(field.name);
1811
+ const error = errors.length > 0 ? errors[0] : void 0;
1812
+ return customComponent({
1813
+ field,
1814
+ value,
1815
+ error,
1816
+ onChange: (val) => this.handleFieldChange(field.name, val),
1817
+ onBlur: () => this.handleFieldBlur(field.name)
1818
+ });
1819
+ }
1820
+ /**
1821
+ * Renderiza wizard
1822
+ */
1823
+ renderWizard(container, wizardState) {
1824
+ const wizardContainer = document.createElement("div");
1825
+ wizardContainer.className = "easy-form-wizard";
1826
+ const stepsIndicator = document.createElement("div");
1827
+ stepsIndicator.className = "easy-form-wizard-steps";
1828
+ const schema = this.schema;
1829
+ if (schema?.steps) {
1830
+ for (let i = 0; i < schema.steps.length; i++) {
1831
+ const stepEl = document.createElement("div");
1832
+ stepEl.className = "easy-form-wizard-step";
1833
+ if (i === wizardState.currentStep) {
1834
+ stepEl.classList.add("active");
1835
+ }
1836
+ if (wizardState.completedSteps.includes(i)) {
1837
+ stepEl.classList.add("completed");
1838
+ }
1839
+ stepEl.textContent = schema.steps[i].title;
1840
+ stepsIndicator.appendChild(stepEl);
1841
+ }
1842
+ }
1843
+ wizardContainer.appendChild(stepsIndicator);
1844
+ const fieldsContainer = document.createElement("div");
1845
+ fieldsContainer.className = "easy-form-wizard-fields";
1846
+ const currentFields = this.stateManager.getCurrentStepFields();
1847
+ for (const field of currentFields) {
1848
+ const fieldElement = this.renderField(field);
1849
+ if (fieldElement) {
1850
+ fieldsContainer.appendChild(fieldElement);
1851
+ }
1852
+ }
1853
+ wizardContainer.appendChild(fieldsContainer);
1854
+ const navContainer = document.createElement("div");
1855
+ navContainer.className = "easy-form-wizard-nav";
1856
+ const prevButton = document.createElement("button");
1857
+ prevButton.type = "button";
1858
+ prevButton.textContent = "Anterior";
1859
+ prevButton.className = "easy-form-wizard-prev";
1860
+ prevButton.disabled = wizardState.currentStep === 0;
1861
+ prevButton.addEventListener("click", () => {
1862
+ if (this.stateManager.previousStep()) {
1863
+ this.render();
1864
+ this.emitStepChange();
1865
+ }
1866
+ });
1867
+ navContainer.appendChild(prevButton);
1868
+ const nextButton = document.createElement("button");
1869
+ nextButton.type = "button";
1870
+ nextButton.textContent = wizardState.currentStep === wizardState.totalSteps - 1 ? "Enviar" : "Siguiente";
1871
+ nextButton.className = "easy-form-wizard-next";
1872
+ nextButton.addEventListener("click", async () => {
1873
+ if (wizardState.currentStep === wizardState.totalSteps - 1) {
1874
+ await this.handleSubmit(new Event("submit"));
1875
+ } else {
1876
+ const currentFields2 = this.stateManager.getCurrentStepFields();
1877
+ const errors = await this.stateManager.validateForm();
1878
+ const hasErrors = currentFields2.some(
1879
+ (f) => errors[f.name] && errors[f.name].length > 0
1880
+ );
1881
+ if (!hasErrors) {
1882
+ this.stateManager.completeStep(wizardState.currentStep);
1883
+ if (this.stateManager.nextStep()) {
1884
+ this.render();
1885
+ this.emitStepChange();
1886
+ }
1887
+ } else {
1888
+ this.emitError(errors);
1889
+ }
1890
+ }
1891
+ });
1892
+ navContainer.appendChild(nextButton);
1893
+ wizardContainer.appendChild(navContainer);
1894
+ container.appendChild(wizardContainer);
1895
+ }
1896
+ /**
1897
+ * Maneja el cambio de un campo
1898
+ */
1899
+ async handleFieldChange(fieldName, value) {
1900
+ await this.stateManager.setValue(fieldName, value);
1901
+ const changeEvent = new CustomEvent("change", {
1902
+ detail: {
1903
+ field: fieldName,
1904
+ value,
1905
+ values: this.stateManager.getState().values
1906
+ },
1907
+ bubbles: true,
1908
+ composed: true
1909
+ });
1910
+ this.dispatchEvent(changeEvent);
1911
+ }
1912
+ /**
1913
+ * Maneja el blur de un campo
1914
+ */
1915
+ async handleFieldBlur(fieldName) {
1916
+ this.stateManager.setTouched(fieldName);
1917
+ await this.stateManager.validateField(fieldName);
1918
+ this.updateSingleField(fieldName);
1919
+ }
1920
+ /**
1921
+ * Actualiza solo un campo específico sin re-renderizar todo el formulario
1922
+ */
1923
+ updateSingleField(fieldName) {
1924
+ const schema = this.schema;
1925
+ if (!schema) return;
1926
+ const field = this.findFieldInSchema(schema, fieldName);
1927
+ if (!field) return;
1928
+ const errors = this.stateManager.getErrors(fieldName);
1929
+ const error = errors.length > 0 ? errors[0] : void 0;
1930
+ const fieldContainer = this.shadow.querySelector(`[name="${fieldName}"]`)?.closest(".easy-form-field");
1931
+ if (!fieldContainer) return;
1932
+ const errorElement = fieldContainer.querySelector(".easy-form-error");
1933
+ if (error) {
1934
+ if (!errorElement) {
1935
+ const errorEl = document.createElement("p");
1936
+ errorEl.className = "easy-form-error";
1937
+ errorEl.textContent = error;
1938
+ fieldContainer.appendChild(errorEl);
1939
+ } else {
1940
+ errorElement.textContent = error;
1941
+ }
1942
+ const input = fieldContainer.querySelector("input, textarea, select");
1943
+ input?.classList.add("easy-form-input-error");
1944
+ } else {
1945
+ errorElement?.remove();
1946
+ const input = fieldContainer.querySelector("input, textarea, select");
1947
+ input?.classList.remove("easy-form-input-error");
1948
+ }
1949
+ }
1950
+ /**
1951
+ * Busca un campo por nombre en el schema
1952
+ */
1953
+ findFieldInSchema(schema, name) {
1954
+ const fields = schema.fields || [];
1955
+ for (const field of fields) {
1956
+ if (field.name === name) {
1957
+ return field;
1958
+ }
1959
+ if (field.type === "group" && "fields" in field) {
1960
+ const found = this.findFieldInSchema({ fields: field.fields }, name);
1961
+ if (found) return found;
1962
+ }
1963
+ }
1964
+ return null;
1965
+ }
1966
+ /**
1967
+ * Maneja el submit del formulario
1968
+ */
1969
+ async handleSubmit(event) {
1970
+ event.preventDefault();
1971
+ const errors = await this.stateManager.validateForm();
1972
+ const state = this.stateManager.getState();
1973
+ if (Object.keys(errors).length > 0) {
1974
+ this.emitError(errors);
1975
+ this.render();
1976
+ return;
1977
+ }
1978
+ const submitEvent = new CustomEvent("submit", {
1979
+ detail: {
1980
+ values: state.values,
1981
+ isValid: true,
1982
+ errors: {}
1983
+ },
1984
+ bubbles: true,
1985
+ composed: true
1986
+ });
1987
+ this.dispatchEvent(submitEvent);
1988
+ }
1989
+ /**
1990
+ * Emite evento de error
1991
+ */
1992
+ emitError(errors) {
1993
+ const errorEvent = new CustomEvent("error", {
1994
+ detail: {
1995
+ errors
1996
+ },
1997
+ bubbles: true,
1998
+ composed: true
1999
+ });
2000
+ this.dispatchEvent(errorEvent);
2001
+ }
2002
+ /**
2003
+ * Emite evento de cambio de step
2004
+ */
2005
+ emitStepChange() {
2006
+ const wizardState = this.stateManager.getWizardState();
2007
+ if (!wizardState) return;
2008
+ const stepChangeEvent = new CustomEvent(
2009
+ "stepChange",
2010
+ {
2011
+ detail: {
2012
+ currentStep: wizardState.currentStep,
2013
+ previousStep: wizardState.currentStep > 0 ? wizardState.currentStep - 1 : wizardState.currentStep,
2014
+ totalSteps: wizardState.totalSteps
2015
+ },
2016
+ bubbles: true,
2017
+ composed: true
2018
+ }
2019
+ );
2020
+ this.dispatchEvent(stepChangeEvent);
2021
+ }
2022
+ /**
2023
+ * Registra componentes personalizados
2024
+ */
2025
+ registerComponents(components) {
2026
+ this.customComponents = { ...this.customComponents, ...components };
2027
+ registerComponents(components);
2028
+ }
2029
+ /**
2030
+ * Obtiene el tema del formulario
2031
+ */
2032
+ get theme() {
2033
+ const themeAttr = this.getAttribute("theme");
2034
+ if (themeAttr && ["plano", "tradicional", "material", "rounded-shadow", "lines"].includes(themeAttr)) {
2035
+ return themeAttr;
2036
+ }
2037
+ return "plano";
2038
+ }
2039
+ /**
2040
+ * Establece el tema del formulario
2041
+ */
2042
+ set theme(value) {
2043
+ if (value) {
2044
+ this.setAttribute("theme", value);
2045
+ } else {
2046
+ this.removeAttribute("theme");
2047
+ }
2048
+ }
2049
+ /**
2050
+ * Obtiene los colores personalizados
2051
+ */
2052
+ get colors() {
2053
+ const colorsAttr = this.getAttribute("colors");
2054
+ if (!colorsAttr) return null;
2055
+ return parseAttributeValue(colorsAttr);
2056
+ }
2057
+ /**
2058
+ * Establece los colores personalizados
2059
+ */
2060
+ set colors(value) {
2061
+ if (value) {
2062
+ this.setAttribute("colors", attributeValue(value));
2063
+ } else {
2064
+ this.removeAttribute("colors");
2065
+ }
2066
+ }
2067
+ /**
2068
+ * Configura estilos básicos
2069
+ */
2070
+ setupStyles() {
2071
+ const existingStyle = this.shadow.querySelector("style");
2072
+ if (existingStyle) {
2073
+ existingStyle.remove();
2074
+ }
2075
+ const theme = this.theme;
2076
+ const colors = getColors(this.colors || void 0);
2077
+ const styles = getThemeStyles(theme, colors);
2078
+ const style = document.createElement("style");
2079
+ style.textContent = styles;
2080
+ if (this.shadow.firstChild) {
2081
+ this.shadow.insertBefore(style, this.shadow.firstChild);
2082
+ } else {
2083
+ this.shadow.appendChild(style);
2084
+ }
2085
+ }
2086
+ };
2087
+ if (typeof window !== "undefined" && typeof customElements !== "undefined" && !customElements.get("easy-form")) {
2088
+ customElements.define("easy-form", EasyForm);
2089
+ }
2090
+ export {
2091
+ EasyForm
2092
+ };
2093
+ //# sourceMappingURL=easy-form.js.map