easy-forms-core 1.2.9 → 1.2.10

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/schema-parser.ts","../src/utils/styles.ts","../src/utils/masks.ts","../src/utils/injection-validation.ts","../src/utils/attempts-lock.ts","../src/utils/index.ts","../src/core/validation-engine.ts","../src/core/condition-engine.ts","../src/core/state-manager.ts","../src/components/inputs/base-input.ts","../src/utils/mask-helpers.ts","../src/core/mask-engine.ts","../src/components/inputs/text-input.ts","../src/components/inputs/number-input.ts","../src/components/inputs/textarea-input.ts","../src/components/inputs/select-input.ts","../src/components/inputs/checkbox-input.ts","../src/components/inputs/radio-input.ts","../src/components/inputs/switch-input.ts","../src/components/inputs/date-input.ts","../src/components/inputs/file-input.ts","../src/components/inputs/quantity-input.ts","../src/components/inputs/accordion-select-input.ts","../src/components/inputs/image-grid-select-input.ts","../src/components/inputs/otp-input.ts","../src/components/inputs/password-input.ts","../src/components/inputs/file-drop-input.ts","../src/components/inputs/map-input.ts","../src/components/inputs/rating-input.ts","../src/components/inputs/slider-input.ts","../src/components/inputs/color-input.ts","../src/components/inputs/index.ts","../src/templates/index.ts","../src/components/easy-form.ts"],"sourcesContent":["import type { FormSchema, Field, Step, SlotContent } from '../types'\n\n/**\n * Parser del schema JSON\n */\nexport class SchemaParser {\n /**\n * Parsea y valida un schema\n */\n parse(schema: FormSchema): ParsedSchema {\n if (!schema) {\n throw new Error('Schema es requerido')\n }\n\n // Validar que tenga fields o steps\n if (!schema.fields && !schema.steps) {\n throw new Error('Schema debe tener fields o steps')\n }\n\n // Si tiene steps, validar que todos los steps tengan fields\n if (schema.steps) {\n for (const step of schema.steps) {\n if (!step.fields || step.fields.length === 0) {\n throw new Error('Cada step debe tener al menos un field')\n }\n }\n }\n\n // Normalizar campos\n const normalizedFields = schema.fields\n ? this.normalizeFields(schema.fields)\n : []\n\n const normalizedSteps = schema.steps\n ? schema.steps.map((step) => ({\n ...step,\n fields: this.normalizeFields(step.fields),\n }))\n : undefined\n\n return {\n fields: normalizedFields,\n steps: normalizedSteps,\n isWizard: Boolean(schema.steps && schema.steps.length > 0),\n }\n }\n\n /**\n * Normaliza y valida campos\n */\n private normalizeFields(fields: Field[]): Field[] {\n return fields.map((field, index) => {\n // Validar que tenga type y name\n if (!field.type) {\n throw new Error(`Field en índice ${index} debe tener un type`)\n }\n if (!field.name) {\n throw new Error(`Field en índice ${index} debe tener un name`)\n }\n\n // Validar tipos específicos\n this.validateFieldType(field, index)\n\n // Aplicar valores por defecto\n return this.applyDefaults(field)\n })\n }\n\n /**\n * Valida el tipo de campo\n */\n private validateFieldType(field: Field, index: number): void {\n const validTypes = [\n 'text',\n 'email',\n 'number',\n 'password',\n 'textarea',\n 'select',\n 'checkbox',\n 'radio',\n 'switch',\n 'date',\n 'file',\n 'file-drop',\n 'map',\n 'rating',\n 'slider',\n 'colorpicker',\n 'array',\n 'group',\n 'row',\n 'custom',\n 'quantity',\n 'accordion-select',\n 'image-grid-select',\n 'otp',\n ]\n\n if (!validTypes.includes(field.type)) {\n throw new Error(\n `Field en índice ${index} tiene un type inválido: ${field.type}`\n )\n }\n\n // Validaciones específicas por tipo\n switch (field.type) {\n case 'select':\n case 'radio':\n case 'accordion-select':\n case 'image-grid-select':\n if (!('options' in field) || !field.options || field.options.length === 0) {\n throw new Error(\n `Field \"${field.name}\" de tipo ${field.type} debe tener options`\n )\n }\n break\n case 'array':\n if (!('itemSchema' in field) || !field.itemSchema) {\n throw new Error(\n `Field \"${field.name}\" de tipo array debe tener itemSchema`\n )\n }\n if ('minItems' in field) {\n const min = (field as any).minItems\n if (min < 0) {\n throw new Error(\n `Field \"${field.name}\" de tipo array: minItems debe ser >= 0`\n )\n }\n if ('maxItems' in field) {\n const max = (field as any).maxItems\n if (min > max) {\n throw new Error(\n `Field \"${field.name}\" de tipo array: minItems (${min}) no puede ser mayor que maxItems (${max})`\n )\n }\n }\n }\n break\n case 'group':\n if (!('fields' in field) || !field.fields || field.fields.length === 0) {\n throw new Error(\n `Field \"${field.name}\" de tipo group debe tener fields`\n )\n }\n break\n case 'row':\n if (!('fields' in field) || !field.fields || field.fields.length === 0) {\n throw new Error(\n `Field \"${field.name}\" de tipo row debe tener fields`\n )\n }\n break\n case 'colorpicker':\n if ('defaultValue' in field && field.defaultValue != null) {\n const hex = /^#[0-9A-Fa-f]{6}$/\n if (!hex.test(String(field.defaultValue))) {\n throw new Error(\n `Field \"${field.name}\" de tipo colorpicker debe tener defaultValue en formato hex (#RRGGBB)`\n )\n }\n }\n break\n }\n\n // Validar leadingIcon y trailingIcon si existen\n if ('leadingIcon' in field && field.leadingIcon) {\n this.validateSlotContent(field.leadingIcon, field.name, 'leadingIcon')\n }\n if ('trailingIcon' in field && field.trailingIcon) {\n this.validateSlotContent(field.trailingIcon, field.name, 'trailingIcon')\n }\n }\n\n /**\n * Valida que SlotContent tenga las propiedades requeridas según type\n */\n private validateSlotContent(\n slot: SlotContent,\n fieldName: string,\n slotName: string\n ): void {\n if (!slot.type || !['image', 'html'].includes(slot.type)) {\n throw new Error(\n `Field \"${fieldName}\" ${slotName} debe tener type 'image' o 'html'`\n )\n }\n if (slot.type === 'image') {\n if (!slot.src || typeof slot.src !== 'string') {\n throw new Error(\n `Field \"${fieldName}\" ${slotName} con type 'image' debe tener src`\n )\n }\n }\n if (slot.type === 'html') {\n if (!slot.html || typeof slot.html !== 'string') {\n throw new Error(\n `Field \"${fieldName}\" ${slotName} con type 'html' debe tener html`\n )\n }\n }\n }\n\n /**\n * Aplica valores por defecto a un campo\n */\n private applyDefaults(field: Field): Field {\n const defaults: any = {\n disabled: false,\n hidden: false,\n }\n\n // Aplicar defaults específicos por tipo\n switch (field.type) {\n case 'checkbox':\n case 'switch':\n if (!('checked' in field)) {\n defaults.checked = false\n }\n break\n case 'select':\n case 'accordion-select':\n case 'image-grid-select':\n if (!('multiple' in field)) {\n defaults.multiple = false\n }\n if (field.type === 'image-grid-select') {\n if (!('columns' in field)) {\n defaults.columns = 3\n }\n if (!('imageSize' in field)) {\n defaults.imageSize = 'medium'\n }\n }\n break\n case 'file':\n if (!('multiple' in field)) {\n defaults.multiple = false\n }\n break\n case 'quantity':\n if (!('min' in field)) {\n defaults.min = 0\n }\n if (!('step' in field)) {\n defaults.step = 1\n }\n break\n case 'otp':\n if (!('length' in field)) {\n defaults.length = 6\n }\n if (!('numeric' in field)) {\n defaults.numeric = true\n }\n break\n case 'slider':\n if (!('min' in field)) {\n defaults.min = 0\n }\n if (!('max' in field)) {\n defaults.max = 100\n }\n if (!('step' in field)) {\n defaults.step = 1\n }\n break\n case 'rating':\n if (!('max' in field)) {\n defaults.max = 5\n }\n break\n case 'colorpicker':\n if (!('defaultValue' in field) || field.defaultValue == null) {\n defaults.defaultValue = '#000000'\n }\n break\n }\n\n return { ...defaults, ...field } as Field\n }\n\n /**\n * Obtiene todos los campos de un schema (incluyendo nested)\n */\n getAllFields(schema: FormSchema): Field[] {\n const parsed = this.parse(schema)\n const allFields: Field[] = []\n\n const extractFields = (fields: Field[]) => {\n for (const field of fields) {\n allFields.push(field)\n if (field.type === 'group' && 'fields' in field) {\n extractFields(field.fields)\n }\n if (field.type === 'row' && 'fields' in field) {\n extractFields(field.fields)\n }\n if (field.type === 'array' && 'itemSchema' in field && field.itemSchema.fields) {\n extractFields(field.itemSchema.fields)\n }\n }\n }\n\n if (parsed.fields) {\n extractFields(parsed.fields)\n }\n\n if (parsed.steps) {\n for (const step of parsed.steps) {\n extractFields(step.fields)\n }\n }\n\n return allFields\n }\n}\n\n/**\n * Schema parseado\n */\nexport interface ParsedSchema {\n fields: Field[]\n steps?: Step[]\n isWizard: boolean\n}\n","import type { FormTheme, FormColors } from '../types'\n\n/**\n * Convierte hex a componentes RGB para usar en rgba()\n */\nfunction hexToRgb(hex: string): string {\n const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex)\n if (!result) {\n const short = /^#?([a-f\\d])([a-f\\d])([a-f\\d])$/i.exec(hex)\n if (!short) return '0, 123, 255'\n return [\n parseInt(short[1] + short[1], 16),\n parseInt(short[2] + short[2], 16),\n parseInt(short[3] + short[3], 16),\n ].join(', ')\n }\n return [\n parseInt(result[1], 16),\n parseInt(result[2], 16),\n parseInt(result[3], 16),\n ].join(', ')\n}\n\n/**\n * Colores por defecto\n */\nconst defaultColors: Required<FormColors> = {\n primary: '#007bff',\n secondary: '#6c757d',\n error: '#dc3545',\n success: '#28a745',\n text: '#212529',\n labelColor: '#212529',\n border: '#ddd',\n background: '#ffffff',\n groupBackground: 'var(--easy-form-group-background)',\n groupTitle: '#212529',\n groupBorder: '#ddd',\n}\n\n/**\n * Obtiene los colores con valores por defecto\n */\nexport function getColors(colors?: FormColors): Required<FormColors> {\n return { ...defaultColors, ...colors }\n}\n\n/**\n * Genera estilos CSS para un tema específico\n */\nexport function getThemeStyles(theme: FormTheme, colors: Required<FormColors>): string {\n const baseStyles = getBaseStyles(colors)\n const themeStyles = getThemeSpecificStyles(theme, colors)\n return baseStyles + themeStyles\n}\n\n/**\n * Estilos base comunes a todos los temas\n */\nfunction getBaseStyles(colors: Required<FormColors>): string {\n return `\n :host {\n display: block;\n --easy-form-primary: ${colors.primary};\n --easy-form-primary-rgb: ${hexToRgb(colors.primary)};\n --easy-form-secondary: ${colors.secondary};\n --easy-form-error: ${colors.error};\n --easy-form-success: ${colors.success};\n --easy-form-text: ${colors.text};\n --easy-form-label-color: ${colors.labelColor};\n --easy-form-border: ${colors.border};\n --easy-form-background: ${colors.background};\n --easy-form-group-background: ${colors.groupBackground};\n --easy-form-group-title: ${colors.groupTitle};\n --easy-form-group-border: ${colors.groupBorder};\n --easy-form-on-primary: #ffffff;\n --easy-form-hover-overlay: rgba(0, 0, 0, 0.03);\n }\n .easy-form-field {\n margin-bottom: 1rem;\n }\n .easy-form-label {\n display: block;\n margin-bottom: 0.5rem;\n font-weight: 500;\n color: var(--easy-form-label-color);\n }\n .easy-form-label-down .easy-form-label {\n margin-bottom: 0;\n margin-top: 0.5rem;\n }\n .easy-form-field-inner-horizontal {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 0.75rem;\n }\n .easy-form-field-inner-horizontal .easy-form-label {\n display: inline-block;\n margin-bottom: 0;\n margin-top: 0;\n flex-shrink: 0;\n white-space: nowrap;\n }\n .easy-form-field-inner-horizontal > *:not(.easy-form-label) {\n flex: 1;\n min-width: 0;\n }\n .easy-form-direction-vertical {\n display: block;\n }\n .easy-form-direction-horizontal {\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n gap: 1rem;\n }\n .easy-form-direction-horizontal > * {\n flex: 1 1 auto;\n }\n .easy-form-completed-indicator {\n margin-bottom: 1rem;\n }\n .easy-form-completed-track {\n height: 6px;\n background: var(--easy-form-border);\n border-radius: 3px;\n overflow: hidden;\n }\n .easy-form-completed-fill {\n height: 100%;\n background: var(--easy-form-primary);\n border-radius: 3px;\n transition: width 0.2s ease;\n }\n .easy-form-slider-wrapper {\n display: flex;\n align-items: center;\n gap: 1rem;\n }\n .easy-form-slider-value {\n min-width: 2rem;\n font-weight: 500;\n }\n .easy-form-input-wrapper {\n display: flex;\n align-items: center;\n flex-wrap: nowrap;\n width: 100%;\n border: 1px solid var(--easy-form-border);\n border-radius: 4px;\n background: var(--easy-form-background);\n padding: 0 0.75rem;\n box-sizing: border-box;\n }\n .easy-form-input-wrapper:focus-within {\n border-color: var(--easy-form-primary);\n box-shadow: 0 0 0 3px rgba(var(--easy-form-primary-rgb), 0.1);\n }\n .easy-form-input-wrapper .easy-form-input-core {\n flex: 1;\n min-width: 0;\n }\n .easy-form-input-wrapper .easy-form-input-core input:not([type=\"checkbox\"]):not([type=\"radio\"]):not([type=\"color\"]),\n .easy-form-input-wrapper .easy-form-input-core textarea,\n .easy-form-input-wrapper .easy-form-input-core select {\n width: 100%;\n border: none !important;\n background: transparent !important;\n box-shadow: none !important;\n padding: 0.5rem 0 !important;\n }\n .easy-form-input-wrapper .easy-form-input-core input:focus,\n .easy-form-input-wrapper .easy-form-input-core textarea:focus,\n .easy-form-input-wrapper .easy-form-input-core select:focus {\n outline: none;\n }\n .easy-form-input-slot {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 0;\n min-width: 1.5rem;\n }\n .easy-form-input-slot-content {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n .easy-form-input-slot-content img {\n width: 20px;\n height: 20px;\n min-width: 20px;\n min-height: 20px;\n object-fit: contain;\n display: block;\n }\n .easy-form-input-slot-leading {\n padding-right: 0.5rem;\n }\n .easy-form-input-slot-trailing {\n padding-left: 0.5rem;\n }\n .easy-form-color-wrapper {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n }\n .easy-form-color-wrapper input[type=\"color\"] {\n width: 2.2rem;\n height: 2.2rem;\n min-width: 2.2rem;\n min-height: 2.2rem;\n padding: 0 !important;\n margin: 0;\n cursor: pointer;\n border: 1px solid var(--easy-form-border);\n border-radius: 2px;\n background: transparent;\n flex-shrink: 0;\n }\n .easy-form-color-wrapper input[type=\"color\"]::-webkit-color-swatch-wrapper {\n padding: 0;\n }\n .easy-form-color-wrapper input[type=\"color\"]::-webkit-color-swatch {\n border: none;\n border-radius: 1px;\n }\n .easy-form-color-wrapper input[type=\"color\"]::-moz-color-swatch {\n border: none;\n border-radius: 1px;\n }\n .easy-form-color-text {\n flex: 1;\n min-width: 0;\n color: var(--easy-form-text);\n background: var(--easy-form-background);\n border: 1px solid var(--easy-form-border);\n border-radius: 4px;\n padding: 0.5rem 0.75rem;\n font-family: ui-monospace, 'Cascadia Code', 'Fira Code', 'Courier New', monospace;\n font-size: 0.875rem;\n }\n .easy-form-rating {\n display: inline-flex;\n gap: 0.25rem;\n }\n .easy-form-rating-stars {\n display: flex;\n gap: 0.25rem;\n }\n .easy-form-rating-star {\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n color: var(--easy-form-border);\n }\n .easy-form-rating-star svg {\n display: block;\n }\n .easy-form-rating-star-filled {\n color: var(--easy-form-primary);\n }\n .easy-form-rating-star:hover,\n .easy-form-rating-star:focus {\n color: var(--easy-form-primary);\n }\n .easy-form-file-drop {\n border: 2px dashed var(--easy-form-border);\n border-radius: 8px;\n padding: 2rem;\n text-align: center;\n cursor: pointer;\n transition: border-color 0.2s, background 0.2s;\n }\n .easy-form-file-drop:hover,\n .easy-form-file-drop-over {\n border-color: var(--easy-form-primary);\n background: rgba(var(--easy-form-primary-rgb), 0.05);\n }\n .easy-form-file-drop-list {\n margin-top: 0.75rem;\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n }\n .easy-form-file-drop-item {\n font-size: 0.875rem;\n color: var(--easy-form-text);\n padding: 0.25rem 0;\n border-bottom: 1px solid var(--easy-form-border);\n }\n .easy-form-map-inputs {\n display: flex;\n gap: 1rem;\n margin-bottom: 0.5rem;\n }\n .easy-form-map-inputs input {\n flex: 1;\n }\n .easy-form-map-placeholder,\n .easy-form-map-container {\n min-height: 300px;\n height: 300px;\n border-radius: 4px;\n position: relative;\n overflow: hidden;\n width: 100%;\n display: block;\n box-sizing: border-box;\n }\n .easy-form-map-container {\n background: var(--easy-form-group-background);\n }\n .easy-form-map-container .leaflet-container {\n height: 100% !important;\n width: 100% !important;\n position: relative !important;\n }\n .easy-form-map-container .leaflet-tile-container {\n position: absolute;\n left: 0;\n top: 0;\n }\n .easy-form-required {\n color: var(--easy-form-error);\n }\n .easy-form-input-error {\n border-color: var(--easy-form-error) !important;\n }\n .easy-form-error {\n color: var(--easy-form-error);\n font-size: 0.875rem;\n margin-top: 0.25rem;\n }\n .easy-form-description {\n font-size: 0.875rem;\n color: var(--easy-form-secondary);\n margin-top: 0.25rem;\n }\n .easy-form-submit {\n padding: 0.5rem 1rem;\n background: var(--easy-form-primary);\n color: var(--easy-form-on-primary);\n border: none;\n cursor: pointer;\n font-size: 1rem;\n transition: all 0.2s ease;\n }\n .easy-form-submit:hover {\n opacity: 0.9;\n }\n .easy-form-submit:active {\n transform: scale(0.98);\n }\n .easy-form-submit-wrapper {\n margin-top: 1rem;\n margin-bottom: 0.5rem;\n }\n .easy-form-submit-wrapper .easy-form-submit {\n min-width: 100px;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):not([type=\"color\"]), textarea, select {\n width: 100%;\n padding: 0.5rem;\n font-size: 1rem;\n color: var(--easy-form-text);\n transition: all 0.2s ease;\n box-sizing: border-box;\n }\n input[type=\"checkbox\"],\n input[type=\"radio\"] {\n width: 18px !important;\n height: 18px !important;\n min-width: 18px !important;\n min-height: 18px !important;\n max-width: 18px !important;\n margin: 0;\n padding: 0;\n cursor: pointer;\n accent-color: var(--easy-form-primary);\n flex-shrink: 0;\n }\n input:focus, textarea:focus, select:focus {\n outline: none;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):not([type=\"color\"])::placeholder,\n textarea::placeholder {\n color: color-mix(in srgb, var(--easy-form-text) 55%, transparent);\n opacity: 1;\n }\n .easy-form-group {\n padding: 1rem;\n margin-bottom: 1rem;\n background: var(--easy-form-group-background);\n border: 1px solid var(--easy-form-group-border);\n border-radius: 4px;\n }\n .easy-form-group-label {\n color: var(--easy-form-group-title);\n font-weight: 600;\n font-size: 1rem;\n margin-bottom: 0.75rem;\n margin-top: 0;\n }\n .easy-form-group-collapsible {\n border: 1px solid var(--easy-form-group-border);\n border-radius: 4px;\n overflow: hidden;\n }\n .easy-form-group-collapsible .easy-form-group-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.75rem 1rem;\n cursor: pointer;\n background: var(--easy-form-group-background);\n color: var(--easy-form-group-title);\n font-weight: 600;\n font-size: 1rem;\n user-select: none;\n transition: background-color 0.2s ease;\n width: 100%;\n border: none;\n }\n .easy-form-group-collapsible .easy-form-group-header:hover {\n background: var(--easy-form-hover-overlay);\n }\n .easy-form-group-collapsible .easy-form-group-header:focus {\n outline: none;\n box-shadow: inset 0 0 0 2px var(--easy-form-primary);\n }\n .easy-form-group-collapsible .easy-form-group-chevron {\n flex-shrink: 0;\n margin-left: 0.5rem;\n transition: transform 0.2s ease;\n color: var(--easy-form-secondary);\n }\n .easy-form-group-collapsible.easy-form-group-collapsed .easy-form-group-chevron {\n transform: rotate(-90deg); /* ▼ → ▶ cuando colapsado */\n }\n .easy-form-group-collapsible .easy-form-group-content {\n overflow: hidden;\n transition: max-height 0.3s ease;\n padding: 0 1rem 1rem 1rem;\n }\n .easy-form-group-collapsible.easy-form-group-collapsed .easy-form-group-content {\n max-height: 0 !important;\n padding-top: 0;\n padding-bottom: 0;\n }\n .easy-form-row {\n display: flex;\n flex-wrap: wrap;\n gap: 1rem;\n margin-bottom: 1rem;\n align-items: stretch;\n }\n .easy-form-row > div {\n flex: 1;\n min-width: 0;\n }\n @media (max-width: 768px) {\n .easy-form-row {\n flex-direction: column;\n }\n .easy-form-row > div {\n flex: none;\n width: 100%;\n }\n }\n .easy-form-radio-group {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n margin-top: 0.5rem;\n }\n .easy-form-radio-option {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.5rem;\n border-radius: 6px;\n transition: background-color 0.2s ease;\n }\n .easy-form-radio-option:hover {\n background-color: var(--easy-form-hover-overlay);\n }\n .easy-form-radio-option input[type=\"radio\"] {\n margin: 0;\n flex-shrink: 0;\n }\n .easy-form-radio-label {\n cursor: pointer;\n user-select: none;\n color: var(--easy-form-label-color);\n font-weight: 400;\n }\n .easy-form-label-checkbox,\n .easy-form-label-switch {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n cursor: pointer;\n user-select: none;\n padding: 0.5rem;\n border-radius: 6px;\n transition: background-color 0.2s ease;\n color: var(--easy-form-label-color);\n }\n .easy-form-label-checkbox input[type=\"checkbox\"],\n .easy-form-label-switch input[type=\"checkbox\"] {\n margin: 0;\n flex-shrink: 0;\n }\n .easy-form-label-checkbox:hover,\n .easy-form-label-switch:hover {\n background-color: var(--easy-form-hover-overlay);\n }\n .easy-form-wizard-steps {\n display: flex;\n gap: 1rem;\n margin-bottom: 2rem;\n }\n .easy-form-wizard-step {\n padding: 0.5rem 1rem;\n transition: all 0.2s ease;\n }\n .easy-form-wizard-step.active {\n background: var(--easy-form-primary);\n color: var(--easy-form-on-primary);\n }\n .easy-form-wizard-step.completed {\n background: var(--easy-form-success);\n color: var(--easy-form-on-primary);\n }\n .easy-form-wizard-nav {\n display: flex;\n gap: 1rem;\n margin-top: 2rem;\n justify-content: flex-end;\n align-items: center;\n }\n .easy-form-wizard-prev,\n .easy-form-wizard-next {\n padding: 0.75rem 1.5rem;\n background: var(--easy-form-primary);\n color: var(--easy-form-on-primary);\n border: none;\n border-radius: 4px;\n font-size: 1rem;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n font-family: inherit;\n min-width: 120px;\n }\n .easy-form-wizard-prev:hover:not(:disabled),\n .easy-form-wizard-next:hover:not(:disabled) {\n opacity: 0.9;\n transform: translateY(-1px);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n }\n .easy-form-wizard-prev:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n .easy-form-wizard-prev {\n background: var(--easy-form-secondary);\n order: 1;\n }\n .easy-form-wizard-next {\n background: var(--easy-form-primary);\n order: 2;\n }\n .easy-form-array-item {\n padding: 1rem;\n margin-bottom: 1rem;\n }\n .easy-form-array-add,\n .easy-form-array-remove {\n padding: 0.25rem 0.5rem;\n background: var(--easy-form-secondary);\n color: var(--easy-form-on-primary);\n border: none;\n cursor: pointer;\n font-size: 0.875rem;\n transition: all 0.2s ease;\n }\n .easy-form-array-remove {\n background: var(--easy-form-error);\n }\n .easy-form-array-add:hover,\n .easy-form-array-remove:hover {\n opacity: 0.9;\n }\n /* Quantity Input */\n .easy-form-quantity-container {\n display: flex;\n flex-direction: column;\n }\n .easy-form-quantity-wrapper {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n }\n .easy-form-quantity-btn {\n width: 2.5rem;\n height: 2.5rem;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--easy-form-primary);\n color: var(--easy-form-on-primary);\n border: none;\n border-radius: 4px;\n font-size: 1.25rem;\n font-weight: bold;\n cursor: pointer;\n transition: all 0.2s ease;\n user-select: none;\n }\n .easy-form-quantity-btn:hover:not(.disabled) {\n opacity: 0.9;\n transform: scale(1.05);\n }\n .easy-form-quantity-btn.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n .easy-form-quantity-input {\n flex: 1;\n text-align: center;\n max-width: 100px;\n }\n /* Accordion Select */\n .easy-form-accordion-select-container {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n }\n .easy-form-accordion-item {\n border: 1px solid var(--easy-form-border);\n border-radius: 4px;\n overflow: hidden;\n transition: all 0.2s ease;\n }\n .easy-form-accordion-item.selected {\n border-color: var(--easy-form-primary);\n box-shadow: 0 0 0 2px rgba(var(--easy-form-primary-rgb), 0.1);\n }\n .easy-form-accordion-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.75rem 1rem;\n cursor: pointer;\n background: var(--easy-form-background);\n transition: background 0.2s ease;\n }\n .easy-form-accordion-header:hover {\n background: color-mix(in srgb, var(--easy-form-border) 95%, transparent);\n }\n .easy-form-accordion-header-content {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n flex: 1;\n }\n .easy-form-accordion-indicator {\n width: 20px;\n height: 20px;\n border: 2px solid var(--easy-form-border);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: all 0.2s ease;\n }\n .easy-form-accordion-indicator.radio {\n border-radius: 50%;\n }\n .easy-form-accordion-indicator.checkbox {\n border-radius: 4px;\n }\n .easy-form-accordion-indicator.checked {\n background: var(--easy-form-primary);\n border-color: var(--easy-form-primary);\n color: var(--easy-form-on-primary);\n }\n .easy-form-accordion-indicator.checked.radio::after {\n content: '';\n width: 8px;\n height: 8px;\n background: var(--easy-form-on-primary);\n border-radius: 50%;\n }\n .easy-form-accordion-indicator.checked.checkbox::after {\n content: '✓';\n font-size: 12px;\n color: var(--easy-form-on-primary);\n }\n .easy-form-accordion-label {\n font-weight: 500;\n color: var(--easy-form-text);\n }\n .easy-form-accordion-arrow {\n transition: transform 0.2s ease;\n color: var(--easy-form-secondary);\n }\n .easy-form-accordion-content {\n max-height: 0;\n overflow: hidden;\n transition: max-height 0.3s ease;\n padding: 0 1rem;\n }\n .easy-form-accordion-item.open .easy-form-accordion-content {\n padding: 1rem;\n }\n .easy-form-accordion-description {\n color: var(--easy-form-secondary);\n font-size: 0.875rem;\n margin: 0;\n }\n /* Image Grid Select */\n .easy-form-image-grid-container {\n display: grid;\n gap: 1rem;\n }\n .easy-form-image-grid-item {\n position: relative;\n border: 2px solid var(--easy-form-border);\n border-radius: 8px;\n overflow: hidden;\n cursor: pointer;\n transition: all 0.2s ease;\n background: var(--easy-form-background);\n }\n .easy-form-image-grid-item:hover {\n border-color: var(--easy-form-primary);\n transform: translateY(-2px);\n box-shadow: 0 4px 8px color-mix(in srgb, var(--easy-form-border) 30%, transparent);\n }\n .easy-form-image-grid-item.selected {\n border-color: var(--easy-form-primary);\n box-shadow: 0 0 0 3px rgba(var(--easy-form-primary-rgb), 0.2);\n }\n .easy-form-image-grid-image-container {\n position: relative;\n width: 100%;\n aspect-ratio: 1;\n overflow: hidden;\n background: var(--easy-form-group-background);\n }\n .easy-form-image-grid-image {\n width: 100%;\n height: 100%;\n object-fit: cover;\n }\n .easy-form-image-grid-placeholder {\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--easy-form-secondary);\n color: var(--easy-form-on-primary);\n font-size: 2rem;\n font-weight: bold;\n }\n .easy-form-image-grid-indicator {\n position: absolute;\n top: 0.5rem;\n right: 0.5rem;\n width: 24px;\n height: 24px;\n border: 2px solid var(--easy-form-on-primary);\n background: var(--easy-form-primary);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--easy-form-on-primary);\n font-size: 12px;\n opacity: 0;\n transition: opacity 0.2s ease;\n }\n .easy-form-image-grid-item.selected .easy-form-image-grid-indicator {\n opacity: 1;\n }\n .easy-form-image-grid-indicator.checkbox {\n border-radius: 4px;\n }\n .easy-form-image-grid-label {\n padding: 0.75rem;\n text-align: center;\n font-weight: 500;\n color: var(--easy-form-text);\n }\n .easy-form-image-grid-description {\n padding: 0 0.75rem 0.75rem;\n font-size: 0.875rem;\n color: var(--easy-form-secondary);\n text-align: center;\n }\n .easy-form-image-grid-small {\n grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));\n }\n .easy-form-image-grid-medium {\n grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));\n }\n .easy-form-image-grid-large {\n grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));\n }\n /* OTP Input */\n .easy-form-otp-container {\n display: flex;\n gap: 0.5rem;\n justify-content: center;\n align-items: center;\n }\n .easy-form-otp-input {\n width: 3rem;\n height: 3rem;\n text-align: center;\n font-size: 1.5rem;\n font-weight: bold;\n border: 2px solid var(--easy-form-border);\n border-radius: 4px;\n transition: all 0.2s ease;\n }\n .easy-form-otp-input:focus {\n border-color: var(--easy-form-primary);\n outline: none;\n box-shadow: 0 0 0 3px rgba(var(--easy-form-primary-rgb), 0.1);\n }\n .easy-form-otp-input:invalid {\n border-color: var(--easy-form-error);\n }\n /* Password inner (input + toggle) */\n .easy-form-password-inner {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n }\n .easy-form-password-inner .easy-form-password-input {\n flex: 1;\n min-width: 0;\n }\n .easy-form-password-toggle {\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0.35rem;\n background: transparent;\n border: 1px solid var(--easy-form-border);\n border-radius: 4px;\n cursor: pointer;\n color: var(--easy-form-text);\n }\n .easy-form-password-toggle:hover {\n border-color: var(--easy-form-primary);\n color: var(--easy-form-primary);\n }\n .easy-form-password-toggle:focus {\n outline: none;\n box-shadow: 0 0 0 2px var(--easy-form-primary);\n }\n /* Password carácter separado */\n .easy-form-password-separated {\n display: flex;\n flex-wrap: nowrap;\n gap: 0.5rem;\n align-items: center;\n }\n .easy-form-password-separated-input {\n width: 2.5rem;\n height: 2.5rem;\n text-align: center;\n font-size: 1.25rem;\n border: 2px solid var(--easy-form-border);\n border-radius: 4px;\n transition: border-color 0.2s ease;\n }\n .easy-form-password-separated-input:focus {\n border-color: var(--easy-form-primary);\n outline: none;\n }\n .easy-form-password-separated-toggle {\n flex-shrink: 0;\n }\n .easy-form-password-separated-toggle .easy-form-password-toggle {\n padding: 0.35rem;\n }\n /* Loading Overlay (sobre el formulario) */\n .easy-form-loading-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(255, 255, 255, 0.8);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n backdrop-filter: blur(2px);\n border-radius: inherit;\n }\n .easy-form-loading-spinner {\n width: 40px;\n height: 40px;\n border: 4px solid rgba(0, 0, 0, 0.1);\n border-top-color: var(--easy-form-primary);\n border-radius: 50%;\n animation: easy-form-spin 0.8s linear infinite;\n }\n @keyframes easy-form-spin {\n to {\n transform: rotate(360deg);\n }\n }\n /* Lock Overlay (bloqueo por intentos) */\n .easy-form-lock-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(255, 255, 255, 0.9);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1001;\n backdrop-filter: blur(4px);\n border-radius: inherit;\n text-align: center;\n padding: 1.5rem;\n }\n .easy-form-lock-message {\n font-size: 1rem;\n color: var(--easy-form-text);\n max-width: 280px;\n }\n /* Disabled State */\n .easy-form-disabled,\n .easy-form-disabled *,\n .easy-form-slot-disabled,\n .easy-form-slot-disabled * {\n pointer-events: none;\n opacity: 0.6;\n }\n .easy-form-disabled input,\n .easy-form-disabled textarea,\n .easy-form-disabled select,\n .easy-form-disabled button,\n .easy-form-slot-disabled input,\n .easy-form-slot-disabled textarea,\n .easy-form-slot-disabled select,\n .easy-form-slot-disabled button {\n cursor: not-allowed;\n }\n .easy-form-input-disabled {\n opacity: 0.6;\n cursor: not-allowed !important;\n }\n form {\n position: relative;\n }\n `\n}\n\n/**\n * Estilos específicos por tema\n */\nfunction getThemeSpecificStyles(theme: FormTheme, colors: Required<FormColors>): string {\n switch (theme) {\n case 'plano':\n return getPlanoStyles(colors)\n case 'tradicional':\n return getTradicionalStyles(colors)\n case 'material':\n return getMaterialStyles(colors)\n case 'rounded-shadow':\n return getRoundedShadowStyles(colors)\n case 'lines':\n return getLinesStyles(colors)\n case 'shadcn':\n return getShadcnStyles(colors)\n case 'chakra':\n return getChakraStyles(colors)\n case 'mantine':\n return getMantineStyles(colors)\n case 'glass':\n return getGlassStyles(colors)\n case 'bordered':\n return getBorderedStyles(colors)\n case 'minimal':\n return getMinimalStyles(colors)\n case 'efc':\n return getEfcStyles(colors)\n default:\n return getPlanoStyles(colors)\n }\n}\n\n/**\n * Estilo Plano - Minimalista sin bordes ni sombras\n */\nfunction getPlanoStyles(_colors: Required<FormColors>): string {\n return `\n .easy-form-label {\n color: var(--easy-form-label-color);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]), textarea, select {\n border: none;\n border-bottom: 2px solid var(--easy-form-border);\n border-radius: 0;\n padding: 0.75rem 0;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):focus, textarea:focus, select:focus {\n border-bottom-color: var(--easy-form-primary);\n }\n .easy-form-submit {\n border-radius: 0;\n font-weight: 600;\n }\n .easy-form-group {\n border: none;\n border-bottom: 1px solid var(--easy-form-group-border);\n border-radius: 0;\n background: transparent;\n }\n .easy-form-wizard-step {\n border: none;\n border-bottom: 2px solid var(--easy-form-border);\n border-radius: 0;\n }\n .easy-form-array-item {\n border: none;\n border-bottom: 1px solid var(--easy-form-group-border);\n border-radius: 0;\n }\n `\n}\n\n/**\n * Estilo Tradicional - Bordes clásicos y estructura tradicional\n */\nfunction getTradicionalStyles(_colors: Required<FormColors>): string {\n return `\n .easy-form-label {\n color: var(--easy-form-label-color);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]), textarea, select {\n border: 2px solid var(--easy-form-border);\n border-radius: 4px;\n padding: 0.625rem;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):focus, textarea:focus, select:focus {\n border-color: var(--easy-form-primary);\n box-shadow: 0 0 0 3px rgba(var(--easy-form-primary-rgb), 0.1);\n }\n .easy-form-submit {\n border-radius: 4px;\n font-weight: 500;\n }\n .easy-form-group {\n border: 2px solid var(--easy-form-group-border);\n border-radius: 4px;\n background: var(--easy-form-group-background);\n }\n .easy-form-wizard-step {\n border: 2px solid var(--easy-form-border);\n border-radius: 4px;\n background: var(--easy-form-group-background);\n }\n .easy-form-wizard-step.active {\n border-color: var(--easy-form-primary);\n }\n .easy-form-array-item {\n border: 2px solid var(--easy-form-group-border);\n border-radius: 4px;\n background: var(--easy-form-group-background);\n }\n `\n}\n\n/**\n * Estilo Material - Inspirado en Material Design\n */\nfunction getMaterialStyles(_colors: Required<FormColors>): string {\n return `\n .easy-form-label {\n font-size: 0.875rem;\n font-weight: 500;\n margin-bottom: 0.25rem;\n color: var(--easy-form-label-color);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]), textarea, select {\n border: none;\n border-bottom: 1px solid color-mix(in srgb, var(--easy-form-text) 42%, transparent);\n border-radius: 4px 4px 0 0;\n padding: 0.75rem 0.75rem 0.5rem 0.75rem;\n background: transparent;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):focus, textarea:focus, select:focus {\n border-bottom-color: var(--easy-form-primary);\n border-bottom-width: 2px;\n padding-bottom: calc(0.5rem - 1px);\n }\n .easy-form-submit {\n border-radius: 4px;\n text-transform: uppercase;\n font-weight: 500;\n letter-spacing: 0.5px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\n }\n .easy-form-submit:hover {\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);\n }\n .easy-form-group {\n border: none;\n border-radius: 4px;\n background: var(--easy-form-group-background);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);\n }\n .easy-form-wizard-step {\n border: none;\n border-radius: 4px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);\n }\n .easy-form-array-item {\n border: none;\n border-radius: 4px;\n background: var(--easy-form-group-background);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);\n }\n .easy-form-array-add,\n .easy-form-quantity-btn {\n border-radius: 4px;\n text-transform: uppercase;\n font-weight: 500;\n letter-spacing: 0.5px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\n }\n .easy-form-array-add:hover,\n .easy-form-quantity-btn:hover:not(.disabled) {\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);\n }\n .easy-form-array-remove {\n border-radius: 4px;\n text-transform: uppercase;\n font-weight: 500;\n letter-spacing: 0.5px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\n }\n .easy-form-array-remove:hover {\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);\n }\n .easy-form-wizard-prev,\n .easy-form-wizard-next {\n border-radius: 4px;\n text-transform: uppercase;\n font-weight: 500;\n letter-spacing: 0.5px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\n }\n .easy-form-wizard-prev:hover:not(:disabled),\n .easy-form-wizard-next:hover {\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);\n }\n .easy-form-error,\n .easy-form-description {\n background: transparent;\n border: none;\n }\n `\n}\n\n/**\n * Estilo Rounded Shadow - Bordes redondeados con sombras\n */\nfunction getRoundedShadowStyles(_colors: Required<FormColors>): string {\n return `\n .easy-form-label {\n color: var(--easy-form-label-color);\n }\n .easy-form-input-wrapper {\n border-radius: 12px;\n padding: 0 1rem;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);\n }\n .easy-form-input-wrapper:focus-within {\n box-shadow: 0 4px 12px rgba(var(--easy-form-primary-rgb), 0.15);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]), textarea, select {\n border: 1px solid var(--easy-form-border);\n border-radius: 12px;\n padding: 0.75rem 1rem;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):focus, textarea:focus, select:focus {\n border-color: var(--easy-form-primary);\n box-shadow: 0 4px 12px rgba(var(--easy-form-primary-rgb), 0.15);\n transform: translateY(-1px);\n }\n .easy-form-submit {\n border-radius: 12px;\n font-weight: 600;\n box-shadow: 0 4px 12px rgba(var(--easy-form-primary-rgb), 0.3);\n }\n .easy-form-submit:hover {\n box-shadow: 0 6px 16px rgba(var(--easy-form-primary-rgb), 0.4);\n transform: translateY(-2px);\n }\n .easy-form-group {\n border: 1px solid var(--easy-form-group-border);\n border-radius: 16px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\n background: var(--easy-form-group-background);\n }\n .easy-form-wizard-step {\n border: 1px solid var(--easy-form-border);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n }\n .easy-form-wizard-step.active {\n box-shadow: 0 4px 16px rgba(var(--easy-form-primary-rgb), 0.3);\n }\n .easy-form-array-item {\n border: 1px solid var(--easy-form-group-border);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n background: var(--easy-form-group-background);\n }\n `\n}\n\n/**\n * Estilo Lines - Solo líneas como separadores\n */\nfunction getLinesStyles(_colors: Required<FormColors>): string {\n return `\n .easy-form-field {\n border-bottom: 1px solid var(--easy-form-border);\n padding-bottom: 1rem;\n margin-bottom: 1.5rem;\n }\n .easy-form-field:last-child {\n border-bottom: none;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]), textarea, select {\n border: none;\n border-radius: 0;\n padding: 0.5rem 0;\n background: transparent;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):focus, textarea:focus, select:focus {\n border-bottom: 2px solid var(--easy-form-primary);\n padding-bottom: calc(0.5rem - 1px);\n }\n .easy-form-submit {\n border-radius: 0;\n border-bottom: 3px solid var(--easy-form-primary);\n background: transparent;\n color: var(--easy-form-primary);\n font-weight: 600;\n padding: 0.75rem 0;\n }\n .easy-form-submit:hover {\n background: rgba(var(--easy-form-primary-rgb), 0.05);\n }\n .easy-form-group {\n border: none;\n border-bottom: 2px solid var(--easy-form-group-border);\n border-radius: 0;\n padding-bottom: 1rem;\n background: transparent;\n }\n .easy-form-wizard-step {\n border: none;\n border-bottom: 3px solid var(--easy-form-border);\n border-radius: 0;\n background: transparent;\n }\n .easy-form-wizard-step.active {\n border-bottom-color: var(--easy-form-primary);\n background: transparent;\n color: var(--easy-form-primary);\n }\n .easy-form-wizard-step.completed {\n border-bottom-color: var(--easy-form-success);\n background: transparent;\n color: var(--easy-form-success);\n }\n .easy-form-array-item {\n border: none;\n border-bottom: 1px solid var(--easy-form-group-border);\n border-radius: 0;\n }\n .easy-form-array-add,\n .easy-form-quantity-btn {\n border-radius: 0;\n border: none;\n border-bottom: 3px solid var(--easy-form-primary);\n background: transparent;\n color: var(--easy-form-primary);\n font-weight: 600;\n padding: 0.5rem 0.75rem;\n }\n .easy-form-array-add:hover,\n .easy-form-quantity-btn:hover:not(.disabled) {\n background: rgba(var(--easy-form-primary-rgb), 0.05);\n }\n .easy-form-array-remove {\n border-radius: 0;\n border: none;\n border-bottom: 3px solid var(--easy-form-error);\n background: transparent;\n color: var(--easy-form-error);\n font-weight: 600;\n padding: 0.5rem 0.75rem;\n }\n .easy-form-array-remove:hover {\n background: rgba(var(--easy-form-primary-rgb), 0.05);\n }\n .easy-form-wizard-prev {\n border-radius: 0;\n border: none;\n border-bottom: 3px solid var(--easy-form-secondary);\n background: transparent;\n color: var(--easy-form-secondary);\n font-weight: 600;\n padding: 0.5rem 0.75rem;\n }\n .easy-form-wizard-next {\n border-radius: 0;\n border: none;\n border-bottom: 3px solid var(--easy-form-primary);\n background: transparent;\n color: var(--easy-form-primary);\n font-weight: 600;\n padding: 0.5rem 0.75rem;\n }\n .easy-form-wizard-prev:hover:not(:disabled),\n .easy-form-wizard-next:hover {\n background: rgba(var(--easy-form-primary-rgb), 0.05);\n }\n .easy-form-error,\n .easy-form-description {\n background: none;\n border: none;\n padding: 0;\n }\n `\n}\n\n/**\n * Estilo Shadcn - Moderno con gradientes sutiles y sombras pronunciadas\n */\nfunction getShadcnStyles(_colors: Required<FormColors>): string {\n return `\n .easy-form-label {\n color: var(--easy-form-label-color);\n font-size: 0.875rem;\n font-weight: 600;\n margin-bottom: 0.75rem;\n letter-spacing: -0.01em;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]), textarea, select {\n border: 1.5px solid var(--easy-form-border);\n border-radius: 8px;\n padding: 0.75rem 1rem;\n background: linear-gradient(to bottom, var(--easy-form-background), var(--easy-form-group-background));\n color: var(--easy-form-text);\n font-size: 0.875rem;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05), inset 0 1px 1px rgba(255, 255, 255, 0.8);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):hover, textarea:hover, select:hover {\n border-color: color-mix(in srgb, var(--easy-form-border) 80%, black);\n background: linear-gradient(to bottom, var(--easy-form-background), var(--easy-form-group-background));\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08), inset 0 1px 1px rgba(255, 255, 255, 0.9);\n transform: translateY(-1px);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):focus, textarea:focus, select:focus {\n outline: none;\n border-color: var(--easy-form-primary);\n background: var(--easy-form-background);\n box-shadow: 0 0 0 4px rgba(var(--easy-form-primary-rgb), 0.12), 0 4px 12px rgba(var(--easy-form-primary-rgb), 0.15);\n transform: translateY(-2px);\n }\n .easy-form-submit {\n border-radius: 8px;\n font-weight: 600;\n background: linear-gradient(135deg, var(--easy-form-primary) 0%, color-mix(in srgb, var(--easy-form-primary) 75%, black) 100%);\n box-shadow: 0 4px 12px rgba(var(--easy-form-primary-rgb), 0.3), 0 2px 4px rgba(0, 0, 0, 0.1);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n letter-spacing: 0.01em;\n }\n .easy-form-submit:hover {\n box-shadow: 0 6px 20px rgba(var(--easy-form-primary-rgb), 0.4), 0 4px 8px rgba(0, 0, 0, 0.15);\n transform: translateY(-2px);\n background: linear-gradient(135deg, color-mix(in srgb, var(--easy-form-primary) 75%, black) 0%, var(--easy-form-primary) 100%);\n }\n .easy-form-submit:active {\n transform: translateY(0);\n box-shadow: 0 2px 8px rgba(var(--easy-form-primary-rgb), 0.3);\n }\n .easy-form-group {\n border: 1.5px solid var(--easy-form-group-border);\n border-radius: 12px;\n background: var(--easy-form-group-background);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\n padding: 1.5rem;\n }\n .easy-form-wizard-step {\n border: 1.5px solid var(--easy-form-border);\n border-radius: 8px;\n background: linear-gradient(to bottom, var(--easy-form-background), var(--easy-form-group-background));\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-wizard-step:hover {\n border-color: color-mix(in srgb, var(--easy-form-border) 80%, black);\n transform: translateY(-2px);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n }\n .easy-form-wizard-step.active {\n border-color: var(--easy-form-primary);\n background: linear-gradient(135deg, var(--easy-form-primary) 0%, color-mix(in srgb, var(--easy-form-primary) 75%, black) 100%);\n color: white;\n box-shadow: 0 6px 20px rgba(var(--easy-form-primary-rgb), 0.4);\n transform: translateY(-2px);\n }\n .easy-form-array-item {\n border: 1.5px solid var(--easy-form-border);\n border-radius: 8px;\n background: var(--easy-form-group-background);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n }\n .easy-form-array-add,\n .easy-form-quantity-btn {\n border-radius: 8px;\n font-weight: 600;\n background: linear-gradient(135deg, var(--easy-form-primary) 0%, color-mix(in srgb, var(--easy-form-primary) 75%, black) 100%);\n border: 1.5px solid color-mix(in srgb, var(--easy-form-primary) 85%, black);\n box-shadow: 0 4px 12px rgba(var(--easy-form-primary-rgb), 0.3), 0 2px 4px rgba(0, 0, 0, 0.1);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-array-add:hover,\n .easy-form-quantity-btn:hover:not(.disabled) {\n box-shadow: 0 6px 20px rgba(var(--easy-form-primary-rgb), 0.4), 0 4px 8px rgba(0, 0, 0, 0.15);\n transform: translateY(-2px);\n background: linear-gradient(135deg, color-mix(in srgb, var(--easy-form-primary) 75%, black) 0%, var(--easy-form-primary) 100%);\n }\n .easy-form-array-remove {\n border-radius: 8px;\n font-weight: 600;\n background: linear-gradient(135deg, var(--easy-form-error) 0%, color-mix(in srgb, var(--easy-form-error) 75%, black) 100%);\n border: 1.5px solid color-mix(in srgb, var(--easy-form-error) 85%, black);\n box-shadow: 0 4px 12px rgba(var(--easy-form-primary-rgb), 0.2), 0 2px 4px rgba(0, 0, 0, 0.1);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-array-remove:hover {\n box-shadow: 0 6px 20px rgba(var(--easy-form-primary-rgb), 0.3), 0 4px 8px rgba(0, 0, 0, 0.15);\n transform: translateY(-2px);\n }\n .easy-form-wizard-prev {\n border-radius: 8px;\n font-weight: 600;\n background: linear-gradient(to bottom, var(--easy-form-background), var(--easy-form-group-background));\n border: 1.5px solid var(--easy-form-border);\n color: var(--easy-form-text);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-wizard-next {\n border-radius: 8px;\n font-weight: 600;\n background: linear-gradient(135deg, var(--easy-form-primary) 0%, color-mix(in srgb, var(--easy-form-primary) 75%, black) 100%);\n border: 1.5px solid color-mix(in srgb, var(--easy-form-primary) 85%, black);\n box-shadow: 0 4px 12px rgba(var(--easy-form-primary-rgb), 0.3), 0 2px 4px rgba(0, 0, 0, 0.1);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-wizard-prev:hover:not(:disabled) {\n border-color: color-mix(in srgb, var(--easy-form-border) 80%, black);\n transform: translateY(-2px);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n }\n .easy-form-wizard-next:hover {\n box-shadow: 0 6px 20px rgba(var(--easy-form-primary-rgb), 0.4), 0 4px 8px rgba(0, 0, 0, 0.15);\n transform: translateY(-2px);\n background: linear-gradient(135deg, color-mix(in srgb, var(--easy-form-primary) 75%, black) 0%, var(--easy-form-primary) 100%);\n }\n `\n}\n\n/**\n * Estilo Chakra - Vibrante con colores puros y efectos de hover pronunciados\n */\nfunction getChakraStyles(_colors: Required<FormColors>): string {\n return `\n .easy-form-label {\n color: var(--easy-form-label-color);\n font-size: 0.875rem;\n font-weight: 600;\n margin-bottom: 0.5rem;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n font-size: 0.75rem;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]), textarea, select {\n border: 2px solid var(--easy-form-border);\n border-radius: 6px;\n padding: 0.625rem 0.875rem;\n background: var(--easy-form-background);\n color: var(--easy-form-text);\n font-size: 0.875rem;\n transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);\n font-weight: 500;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):hover, textarea:hover, select:hover {\n border-color: var(--easy-form-primary);\n background: var(--easy-form-group-background);\n box-shadow: 0 0 0 3px rgba(var(--easy-form-primary-rgb), 0.1);\n transform: scale(1.02);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):focus, textarea:focus, select:focus {\n outline: none;\n border-color: var(--easy-form-primary);\n border-width: 2px;\n background: var(--easy-form-background);\n box-shadow: 0 0 0 3px rgba(var(--easy-form-primary-rgb), 0.2), 0 4px 12px rgba(var(--easy-form-primary-rgb), 0.15);\n transform: scale(1.02);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):disabled, textarea:disabled, select:disabled {\n background: var(--easy-form-group-background);\n border-color: var(--easy-form-border);\n cursor: not-allowed;\n opacity: 0.6;\n }\n .easy-form-submit {\n border-radius: 6px;\n font-weight: 600;\n background: var(--easy-form-primary);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n font-size: 0.875rem;\n transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: 0 4px 6px rgba(var(--easy-form-primary-rgb), 0.25);\n }\n .easy-form-submit:hover {\n background: color-mix(in srgb, var(--easy-form-primary) 75%, black);\n box-shadow: 0 6px 12px rgba(var(--easy-form-primary-rgb), 0.35);\n transform: translateY(-2px) scale(1.02);\n }\n .easy-form-submit:active {\n transform: translateY(0) scale(0.98);\n }\n .easy-form-submit:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n transform: none;\n }\n .easy-form-group {\n border: 2px solid var(--easy-form-group-border);\n border-radius: 8px;\n background: var(--easy-form-group-background);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n }\n .easy-form-wizard-step {\n border: 2px solid var(--easy-form-border);\n border-radius: 6px;\n background: var(--easy-form-background);\n transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-wizard-step:hover {\n border-color: var(--easy-form-primary);\n transform: scale(1.05);\n }\n .easy-form-wizard-step.active {\n border-color: var(--easy-form-primary);\n background: var(--easy-form-primary);\n color: white;\n box-shadow: 0 4px 12px rgba(var(--easy-form-primary-rgb), 0.3);\n transform: scale(1.05);\n }\n .easy-form-array-item {\n border: 2px solid var(--easy-form-border);\n border-radius: 6px;\n background: var(--easy-form-background);\n transition: all 0.25s ease;\n }\n .easy-form-array-item:hover {\n border-color: var(--easy-form-group-border);\n box-shadow: 0 2px 8px rgba(var(--easy-form-primary-rgb), 0.15);\n }\n `\n}\n\n/**\n * Estilo Mantine - Ultra redondeado con elevación y efectos 3D\n */\nfunction getMantineStyles(_colors: Required<FormColors>): string {\n return `\n .easy-form-label {\n color: var(--easy-form-label-color);\n font-size: 0.875rem;\n font-weight: 600;\n margin-bottom: 0.625rem;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]), textarea, select {\n border: 1px solid var(--easy-form-border);\n border-radius: 12px;\n padding: 0.875rem 1.25rem;\n background: var(--easy-form-background);\n color: var(--easy-form-text);\n font-size: 0.875rem;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04), inset 0 1px 0 rgba(255, 255, 255, 0.8);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):hover, textarea:hover, select:hover {\n border-color: color-mix(in srgb, var(--easy-form-border) 70%, black);\n background: linear-gradient(to bottom, var(--easy-form-background), var(--easy-form-group-background));\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.08), inset 0 1px 0 rgba(255, 255, 255, 0.9);\n transform: translateY(-2px);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):focus, textarea:focus, select:focus {\n outline: none;\n border-color: var(--easy-form-primary);\n background: var(--easy-form-background);\n box-shadow: 0 0 0 3px rgba(var(--easy-form-primary-rgb), 0.15), 0 6px 16px rgba(var(--easy-form-primary-rgb), 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.9);\n transform: translateY(-3px);\n }\n .easy-form-submit {\n border-radius: 12px;\n font-weight: 600;\n background: linear-gradient(135deg, var(--easy-form-primary) 0%, color-mix(in srgb, var(--easy-form-primary) 75%, black) 100%);\n box-shadow: 0 4px 12px rgba(var(--easy-form-primary-rgb), 0.3), 0 2px 4px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.2);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-submit:hover {\n box-shadow: 0 8px 20px rgba(var(--easy-form-primary-rgb), 0.4), 0 4px 8px rgba(0, 0, 0, 0.15), inset 0 1px 0 rgba(255, 255, 255, 0.3);\n transform: translateY(-3px) scale(1.02);\n }\n .easy-form-submit:active {\n transform: translateY(-1px) scale(0.98);\n box-shadow: 0 2px 8px rgba(var(--easy-form-primary-rgb), 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.2);\n }\n .easy-form-group {\n border: 1px solid var(--easy-form-group-border);\n border-radius: 16px;\n background: var(--easy-form-group-background);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08), inset 0 1px 0 rgba(255, 255, 255, 0.8);\n padding: 1.5rem;\n }\n .easy-form-wizard-step {\n border: 1px solid var(--easy-form-border);\n border-radius: 12px;\n background: var(--easy-form-background);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04);\n }\n .easy-form-wizard-step:hover {\n background: linear-gradient(to bottom, var(--easy-form-background), var(--easy-form-group-background));\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n transform: translateY(-2px);\n }\n .easy-form-wizard-step.active {\n border-color: var(--easy-form-primary);\n background: linear-gradient(135deg, var(--easy-form-primary) 0%, color-mix(in srgb, var(--easy-form-primary) 75%, black) 100%);\n color: white;\n box-shadow: 0 6px 20px rgba(var(--easy-form-primary-rgb), 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.2);\n transform: translateY(-3px) scale(1.05);\n }\n .easy-form-array-item {\n border: 1px solid var(--easy-form-group-border);\n border-radius: 12px;\n background: var(--easy-form-group-background);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06), inset 0 1px 0 rgba(255, 255, 255, 0.8);\n }\n `\n}\n\n/**\n * Estilo Glass - Glassmorphism extremo con blur pronunciado y efectos neón\n */\nfunction getGlassStyles(_colors: Required<FormColors>): string {\n return `\n .easy-form-label {\n color: var(--easy-form-label-color);\n font-size: 0.875rem;\n font-weight: 600;\n margin-bottom: 0.75rem;\n text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]), textarea, select {\n border: 2px solid rgba(255, 255, 255, 0.4);\n border-radius: 16px;\n padding: 0.875rem 1.25rem;\n background: rgba(255, 255, 255, 0.15);\n backdrop-filter: blur(20px) saturate(180%);\n -webkit-backdrop-filter: blur(20px) saturate(180%);\n font-size: 0.875rem;\n color: var(--easy-form-text);\n transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.3), 0 0 0 1px rgba(255, 255, 255, 0.1);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"])::placeholder, textarea::placeholder, select::placeholder {\n color: rgba(255, 255, 255, 0.6);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):hover, textarea:hover, select:hover {\n border-color: rgba(255, 255, 255, 0.6);\n background: rgba(255, 255, 255, 0.25);\n box-shadow: 0 12px 24px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 0 20px rgba(255, 255, 255, 0.1);\n transform: translateY(-2px);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):focus, textarea:focus, select:focus {\n outline: none;\n border-color: rgba(255, 255, 255, 0.8);\n background: rgba(255, 255, 255, 0.3);\n box-shadow: 0 0 0 4px rgba(var(--easy-form-primary-rgb), 0.3), 0 16px 32px rgba(var(--easy-form-primary-rgb), 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.5), 0 0 30px rgba(var(--easy-form-primary-rgb), 0.2);\n transform: translateY(-3px) scale(1.02);\n }\n .easy-form-submit {\n border-radius: 16px;\n font-weight: 600;\n background: rgba(255, 255, 255, 0.2);\n backdrop-filter: blur(20px) saturate(180%);\n -webkit-backdrop-filter: blur(20px) saturate(180%);\n border: 2px solid rgba(255, 255, 255, 0.4);\n color: var(--easy-form-text);\n box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3), 0 0 20px rgba(255, 255, 255, 0.1);\n transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-submit:hover {\n background: rgba(255, 255, 255, 0.3);\n border-color: rgba(255, 255, 255, 0.6);\n box-shadow: 0 12px 32px rgba(var(--easy-form-primary-rgb), 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.5), 0 0 40px rgba(var(--easy-form-primary-rgb), 0.3);\n transform: translateY(-3px) scale(1.05);\n }\n .easy-form-submit:active {\n transform: translateY(-1px) scale(0.98);\n }\n .easy-form-group {\n border: 2px solid var(--easy-form-group-border);\n border-radius: 20px;\n background: var(--easy-form-group-background);\n backdrop-filter: blur(20px) saturate(180%);\n -webkit-backdrop-filter: blur(20px) saturate(180%);\n box-shadow: 0 16px 32px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3);\n padding: 2rem;\n }\n .easy-form-wizard-step {\n border: 2px solid rgba(255, 255, 255, 0.4);\n border-radius: 16px;\n background: rgba(255, 255, 255, 0.15);\n backdrop-filter: blur(20px) saturate(180%);\n -webkit-backdrop-filter: blur(20px) saturate(180%);\n transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n color: var(--easy-form-text);\n }\n .easy-form-wizard-step:hover {\n background: rgba(255, 255, 255, 0.25);\n box-shadow: 0 12px 24px rgba(0, 0, 0, 0.3), 0 0 20px rgba(255, 255, 255, 0.1);\n transform: translateY(-2px);\n }\n .easy-form-wizard-step.active {\n border-color: rgba(255, 255, 255, 0.8);\n background: rgba(var(--easy-form-primary-rgb), 0.3);\n backdrop-filter: blur(20px) saturate(180%);\n -webkit-backdrop-filter: blur(20px) saturate(180%);\n box-shadow: 0 0 0 3px rgba(var(--easy-form-primary-rgb), 0.4), 0 16px 32px rgba(var(--easy-form-primary-rgb), 0.3), 0 0 40px rgba(var(--easy-form-primary-rgb), 0.2);\n transform: translateY(-3px) scale(1.05);\n }\n .easy-form-array-item {\n border: 2px solid rgba(255, 255, 255, 0.4);\n border-radius: 16px;\n background: rgba(255, 255, 255, 0.15);\n backdrop-filter: blur(20px) saturate(180%);\n -webkit-backdrop-filter: blur(20px) saturate(180%);\n box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.3);\n }\n .easy-form-array-add,\n .easy-form-quantity-btn {\n border-radius: 16px;\n font-weight: 600;\n background: rgba(255, 255, 255, 0.2);\n backdrop-filter: blur(20px) saturate(180%);\n -webkit-backdrop-filter: blur(20px) saturate(180%);\n border: 2px solid rgba(255, 255, 255, 0.4);\n color: var(--easy-form-text);\n box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3), 0 0 20px rgba(255, 255, 255, 0.1);\n transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-array-add:hover,\n .easy-form-quantity-btn:hover:not(.disabled) {\n background: rgba(255, 255, 255, 0.3);\n border-color: rgba(255, 255, 255, 0.6);\n box-shadow: 0 12px 32px rgba(var(--easy-form-primary-rgb), 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.5), 0 0 40px rgba(var(--easy-form-primary-rgb), 0.3);\n transform: translateY(-3px) scale(1.05);\n }\n .easy-form-array-remove {\n border-radius: 16px;\n font-weight: 600;\n background: rgba(255, 255, 255, 0.2);\n backdrop-filter: blur(20px) saturate(180%);\n -webkit-backdrop-filter: blur(20px) saturate(180%);\n border: 2px solid rgba(255, 255, 255, 0.4);\n color: var(--easy-form-error);\n box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3);\n transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-array-remove:hover {\n background: rgba(255, 255, 255, 0.3);\n border-color: rgba(255, 255, 255, 0.6);\n box-shadow: 0 12px 24px rgba(0, 0, 0, 0.3), 0 0 20px rgba(255, 255, 255, 0.1);\n transform: translateY(-2px);\n }\n .easy-form-wizard-prev,\n .easy-form-wizard-next {\n border-radius: 16px;\n font-weight: 600;\n background: rgba(255, 255, 255, 0.2);\n backdrop-filter: blur(20px) saturate(180%);\n -webkit-backdrop-filter: blur(20px) saturate(180%);\n border: 2px solid rgba(255, 255, 255, 0.4);\n color: var(--easy-form-text);\n box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3), 0 0 20px rgba(255, 255, 255, 0.1);\n transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-wizard-prev:hover:not(:disabled),\n .easy-form-wizard-next:hover {\n background: rgba(255, 255, 255, 0.3);\n border-color: rgba(255, 255, 255, 0.6);\n box-shadow: 0 12px 32px rgba(var(--easy-form-primary-rgb), 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.5), 0 0 40px rgba(var(--easy-form-primary-rgb), 0.3);\n transform: translateY(-3px) scale(1.05);\n }\n .easy-form-wizard-next {\n background: rgba(var(--easy-form-primary-rgb), 0.25);\n }\n .easy-form-wizard-next:hover {\n background: rgba(var(--easy-form-primary-rgb), 0.35);\n }\n `\n}\n\n/**\n * Estilo Bordered - Bordes ultra gruesos con efectos 3D y sombras pronunciadas\n */\nfunction getBorderedStyles(_colors: Required<FormColors>): string {\n return `\n .easy-form-label {\n color: var(--easy-form-label-color);\n font-size: 0.875rem;\n font-weight: 700;\n margin-bottom: 0.75rem;\n text-transform: uppercase;\n letter-spacing: 0.1em;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]), textarea, select {\n border: 3px solid var(--easy-form-text);\n border-radius: 0;\n padding: 0.875rem 1.25rem;\n background: var(--easy-form-background);\n color: var(--easy-form-text);\n font-size: 0.875rem;\n font-weight: 600;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.1), inset 0 2px 4px rgba(0, 0, 0, 0.05);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):hover, textarea:hover, select:hover {\n border-color: var(--easy-form-primary);\n box-shadow: 6px 6px 0 rgba(var(--easy-form-primary-rgb), 0.2), inset 0 2px 4px rgba(0, 0, 0, 0.05);\n transform: translate(-2px, -2px);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):focus, textarea:focus, select:focus {\n outline: none;\n border-color: var(--easy-form-primary);\n border-width: 4px;\n box-shadow: 8px 8px 0 rgba(var(--easy-form-primary-rgb), 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.05), 0 0 0 4px rgba(var(--easy-form-primary-rgb), 0.1);\n transform: translate(-4px, -4px);\n }\n .easy-form-submit {\n border-radius: 0;\n font-weight: 700;\n border: 4px solid var(--easy-form-text);\n background: var(--easy-form-primary);\n color: var(--easy-form-on-primary);\n text-transform: uppercase;\n letter-spacing: 0.1em;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: 6px 6px 0 rgba(0, 0, 0, 0.2);\n }\n .easy-form-submit:hover {\n background: color-mix(in srgb, var(--easy-form-primary) 75%, black);\n box-shadow: 8px 8px 0 rgba(0, 0, 0, 0.3);\n transform: translate(-2px, -2px);\n }\n .easy-form-submit:active {\n transform: translate(0, 0);\n box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.2);\n }\n .easy-form-group {\n border: 4px solid var(--easy-form-group-border);\n border-radius: 0;\n background: var(--easy-form-group-background);\n box-shadow: 8px 8px 0 rgba(0, 0, 0, 0.1);\n padding: 2rem;\n }\n .easy-form-wizard-step {\n border: 3px solid var(--easy-form-text);\n border-radius: 0;\n background: var(--easy-form-background);\n font-weight: 600;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.1);\n }\n .easy-form-wizard-step:hover {\n box-shadow: 6px 6px 0 rgba(0, 0, 0, 0.15);\n transform: translate(-2px, -2px);\n }\n .easy-form-wizard-step.active {\n border-color: var(--easy-form-primary);\n border-width: 4px;\n background: var(--easy-form-primary);\n color: white;\n box-shadow: 8px 8px 0 rgba(var(--easy-form-primary-rgb), 0.3);\n transform: translate(-4px, -4px);\n }\n .easy-form-array-item {\n border: 3px solid var(--easy-form-group-border);\n border-radius: 0;\n background: var(--easy-form-group-background);\n box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.1);\n }\n `\n}\n\n/**\n * Estilo Minimal - Ultra minimalista con líneas animadas y efectos sutiles\n */\nfunction getMinimalStyles(_colors: Required<FormColors>): string {\n return `\n .easy-form-label {\n color: var(--easy-form-label-color);\n font-size: 0.75rem;\n font-weight: 500;\n margin-bottom: 0.5rem;\n text-transform: uppercase;\n letter-spacing: 0.15em;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]), textarea, select {\n border: none;\n border-bottom: 1px solid var(--easy-form-border);\n border-radius: 0;\n padding: 0.625rem 0;\n background: transparent;\n color: var(--easy-form-text);\n font-size: 0.9375rem;\n font-weight: 300;\n transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n position: relative;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"])::after, textarea::after, select::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 0;\n width: 0;\n height: 2px;\n background: var(--easy-form-primary);\n transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):hover, textarea:hover, select:hover {\n border-bottom-color: color-mix(in srgb, var(--easy-form-border) 75%, black);\n padding-left: 0.5rem;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):focus, textarea:focus, select:focus {\n outline: none;\n border-bottom-color: var(--easy-form-primary);\n border-bottom-width: 2px;\n padding-bottom: calc(0.625rem - 1px);\n padding-left: 0;\n background: linear-gradient(to bottom, transparent 98%, rgba(var(--easy-form-primary-rgb), 0.05) 100%);\n }\n .easy-form-submit {\n border-radius: 0;\n font-weight: 300;\n border: none;\n border-bottom: 2px solid var(--easy-form-primary);\n background: transparent;\n color: var(--easy-form-primary);\n padding: 0.75rem 0;\n transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n text-transform: uppercase;\n letter-spacing: 0.2em;\n font-size: 0.75rem;\n position: relative;\n overflow: hidden;\n }\n .easy-form-submit::before {\n content: '';\n position: absolute;\n bottom: 0;\n left: -100%;\n width: 100%;\n height: 2px;\n background: var(--easy-form-primary);\n transition: left 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-submit:hover {\n background: linear-gradient(to bottom, rgba(var(--easy-form-primary-rgb), 0.03), transparent);\n padding-left: 1rem;\n }\n .easy-form-submit:hover::before {\n left: 0;\n }\n .easy-form-group {\n border: none;\n border-bottom: 1px solid var(--easy-form-group-border);\n border-radius: 0;\n background: transparent;\n padding-bottom: 2rem;\n margin-bottom: 2rem;\n }\n .easy-form-wizard-step {\n border: none;\n border-bottom: 2px solid var(--easy-form-border);\n border-radius: 0;\n background: transparent;\n font-weight: 300;\n text-transform: uppercase;\n letter-spacing: 0.15em;\n font-size: 0.75rem;\n transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n position: relative;\n }\n .easy-form-wizard-step::after {\n content: '';\n position: absolute;\n bottom: -2px;\n left: 0;\n width: 0;\n height: 2px;\n background: var(--easy-form-primary);\n transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-wizard-step:hover {\n color: var(--easy-form-primary);\n padding-left: 0.5rem;\n }\n .easy-form-wizard-step:hover::after {\n width: 100%;\n }\n .easy-form-wizard-step.active {\n border-bottom-color: var(--easy-form-primary);\n color: var(--easy-form-primary);\n font-weight: 500;\n }\n .easy-form-wizard-step.active::after {\n width: 100%;\n }\n .easy-form-array-item {\n border: none;\n border-bottom: 1px solid var(--easy-form-group-border);\n border-radius: 0;\n background: transparent;\n padding-bottom: 1.5rem;\n margin-bottom: 1.5rem;\n }\n .easy-form-array-add,\n .easy-form-quantity-btn {\n border-radius: 0;\n font-weight: 300;\n border: none;\n border-bottom: 2px solid var(--easy-form-primary);\n background: transparent;\n color: var(--easy-form-primary);\n padding: 0.5rem 0.75rem;\n text-transform: uppercase;\n letter-spacing: 0.15em;\n font-size: 0.75rem;\n transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-array-add:hover,\n .easy-form-quantity-btn:hover:not(.disabled) {\n background: linear-gradient(to bottom, rgba(var(--easy-form-primary-rgb), 0.03), transparent);\n padding-left: 1rem;\n }\n .easy-form-array-remove {\n border-radius: 0;\n font-weight: 300;\n border: none;\n border-bottom: 2px solid var(--easy-form-error);\n background: transparent;\n color: var(--easy-form-error);\n padding: 0.5rem 0.75rem;\n text-transform: uppercase;\n letter-spacing: 0.15em;\n font-size: 0.75rem;\n transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-array-remove:hover {\n background: linear-gradient(to bottom, rgba(var(--easy-form-primary-rgb), 0.03), transparent);\n padding-left: 1rem;\n }\n .easy-form-wizard-prev {\n border-radius: 0;\n font-weight: 300;\n border: none;\n border-bottom: 2px solid var(--easy-form-secondary);\n background: transparent;\n color: var(--easy-form-secondary);\n padding: 0.5rem 0.75rem;\n text-transform: uppercase;\n letter-spacing: 0.15em;\n font-size: 0.75rem;\n transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-wizard-next {\n border-radius: 0;\n font-weight: 300;\n border: none;\n border-bottom: 2px solid var(--easy-form-primary);\n background: transparent;\n color: var(--easy-form-primary);\n padding: 0.5rem 0.75rem;\n text-transform: uppercase;\n letter-spacing: 0.15em;\n font-size: 0.75rem;\n transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-wizard-prev:hover:not(:disabled),\n .easy-form-wizard-next:hover {\n background: linear-gradient(to bottom, rgba(var(--easy-form-primary-rgb), 0.03), transparent);\n padding-left: 1rem;\n }\n .easy-form-error,\n .easy-form-description {\n background: none;\n border: none;\n padding: 0;\n }\n `\n}\n\n/**\n * Estilo EFC - EasyFormsCore Documentation Style\n * Glassmorphism con acentos del primary color\n */\nfunction getEfcStyles(_colors: Required<FormColors>): string {\n return `\n .easy-form-label {\n color: var(--easy-form-label-color);\n font-size: 0.875rem;\n font-weight: 600;\n margin-bottom: 0.75rem;\n letter-spacing: 0.025em;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]), textarea, select {\n border: 1px solid rgba(var(--easy-form-primary-rgb), 0.2);\n border-radius: 12px;\n padding: 0.875rem 1rem;\n background: rgba(var(--easy-form-primary-rgb), 0.05);\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n font-size: 0.9rem;\n color: var(--easy-form-text);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"])::placeholder, textarea::placeholder, select::placeholder {\n color: var(--easy-form-label-color);\n opacity: 0.5;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):hover, textarea:hover, select:hover {\n border-color: rgba(var(--easy-form-primary-rgb), 0.4);\n background: rgba(var(--easy-form-primary-rgb), 0.08);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):focus, textarea:focus, select:focus {\n outline: none;\n border-color: rgba(var(--easy-form-primary-rgb), 0.5);\n background: rgba(var(--easy-form-primary-rgb), 0.1);\n box-shadow: 0 0 0 3px rgba(var(--easy-form-primary-rgb), 0.15);\n }\n .easy-form-submit {\n border-radius: 12px;\n font-weight: 600;\n background: linear-gradient(135deg, var(--easy-form-primary) 0%, var(--easy-form-primary) 100%);\n border: none;\n color: white;\n padding: 0.875rem 1.5rem;\n box-shadow: 0 4px 14px rgba(var(--easy-form-primary-rgb), 0.35);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n cursor: pointer;\n }\n .easy-form-submit:hover {\n transform: translateY(-2px);\n box-shadow: 0 6px 20px rgba(var(--easy-form-primary-rgb), 0.45);\n }\n .easy-form-submit:active {\n transform: translateY(0);\n box-shadow: 0 2px 8px rgba(var(--easy-form-primary-rgb), 0.3);\n }\n .easy-form-group {\n border: 1px solid rgba(var(--easy-form-primary-rgb), 0.2);\n border-radius: 16px;\n background: rgba(var(--easy-form-primary-rgb), 0.03);\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n padding: 1.5rem;\n transition: all 0.3s ease;\n }\n .easy-form-group:hover {\n border-color: rgba(var(--easy-form-primary-rgb), 0.3);\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);\n }\n .easy-form-group-label {\n color: var(--easy-form-group-title);\n font-weight: 700;\n font-size: 1.1rem;\n }\n .easy-form-wizard-step {\n border: 1px solid rgba(var(--easy-form-primary-rgb), 0.2);\n border-radius: 10px;\n background: rgba(var(--easy-form-primary-rgb), 0.05);\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n color: var(--easy-form-text);\n padding: 0.75rem 1.25rem;\n }\n .easy-form-wizard-step:hover {\n background: rgba(var(--easy-form-primary-rgb), 0.1);\n border-color: rgba(var(--easy-form-primary-rgb), 0.4);\n transform: translateY(-2px);\n }\n .easy-form-wizard-step.active {\n border-color: var(--easy-form-primary);\n background: linear-gradient(135deg, rgba(var(--easy-form-primary-rgb), 0.2) 0%, rgba(var(--easy-form-primary-rgb), 0.1) 100%);\n box-shadow: 0 0 8px rgba(var(--easy-form-primary-rgb), 0.3);\n font-weight: 600;\n }\n .easy-form-array-item {\n border: 1px solid rgba(var(--easy-form-primary-rgb), 0.15);\n border-radius: 12px;\n background: rgba(var(--easy-form-primary-rgb), 0.03);\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n padding: 1rem;\n transition: all 0.3s ease;\n }\n .easy-form-array-item:hover {\n border-color: rgba(var(--easy-form-primary-rgb), 0.25);\n }\n .easy-form-array-add,\n .easy-form-quantity-btn {\n border-radius: 10px;\n font-weight: 600;\n border: 1px solid rgba(var(--easy-form-primary-rgb), 0.2);\n background: rgba(var(--easy-form-primary-rgb), 0.1);\n color: var(--easy-form-primary);\n padding: 0.5rem 1rem;\n font-size: 0.85rem;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n cursor: pointer;\n }\n .easy-form-array-add:hover,\n .easy-form-quantity-btn:hover:not(.disabled) {\n background: rgba(var(--easy-form-primary-rgb), 0.2);\n border-color: rgba(var(--easy-form-primary-rgb), 0.4);\n transform: translateY(-1px);\n }\n .easy-form-array-remove {\n border-radius: 10px;\n font-weight: 600;\n border: 1px solid rgba(var(--easy-form-error-rgb), 0.2);\n background: rgba(var(--easy-form-error-rgb), 0.1);\n color: var(--easy-form-error);\n padding: 0.5rem 1rem;\n font-size: 0.85rem;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n cursor: pointer;\n }\n .easy-form-array-remove:hover {\n background: rgba(var(--easy-form-error-rgb), 0.2);\n border-color: rgba(var(--easy-form-error-rgb), 0.4);\n transform: translateY(-1px);\n }\n .easy-form-wizard-prev {\n border-radius: 10px;\n font-weight: 600;\n border: 1px solid rgba(var(--easy-form-primary-rgb), 0.2);\n background: rgba(var(--easy-form-primary-rgb), 0.05);\n color: var(--easy-form-primary);\n padding: 0.75rem 1.25rem;\n font-size: 0.9rem;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n cursor: pointer;\n }\n .easy-form-wizard-next {\n border-radius: 10px;\n font-weight: 600;\n background: linear-gradient(135deg, var(--easy-form-primary) 0%, var(--easy-form-primary) 100%);\n border: none;\n color: white;\n padding: 0.75rem 1.25rem;\n font-size: 0.9rem;\n box-shadow: 0 4px 14px rgba(var(--easy-form-primary-rgb), 0.35);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n cursor: pointer;\n }\n .easy-form-wizard-prev:hover:not(:disabled) {\n background: rgba(var(--easy-form-primary-rgb), 0.1);\n border-color: rgba(var(--easy-form-primary-rgb), 0.4);\n }\n .easy-form-wizard-next:hover {\n transform: translateY(-2px);\n box-shadow: 0 6px 20px rgba(var(--easy-form-primary-rgb), 0.45);\n }\n .easy-form-error {\n background: rgba(var(--easy-form-error-rgb), 0.1);\n border: 1px solid rgba(var(--easy-form-error-rgb), 0.2);\n border-radius: 8px;\n padding: 0.5rem 0.75rem;\n color: var(--easy-form-error);\n font-size: 0.85rem;\n }\n .easy-form-description {\n color: var(--easy-form-label-color);\n opacity: 0.7;\n font-size: 0.85rem;\n }\n .easy-form-checkbox-wrapper,\n .easy-form-radio-wrapper {\n gap: 0.75rem;\n }\n input[type=\"checkbox\"],\n input[type=\"radio\"] {\n accent-color: var(--easy-form-primary);\n width: 1.1rem;\n height: 1.1rem;\n }\n select {\n appearance: none;\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236366f1' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 1rem center;\n padding-right: 2.5rem;\n }\n `\n}\n","import type { PredefinedMask, CustomMask } from '../types'\n\n/**\n * Máscaras predefinidas\n */\nexport const PREDEFINED_MASKS: Record<PredefinedMask, CustomMask> = {\n 'phone': {\n pattern: '(999) 999-9999',\n placeholder: '_',\n },\n 'phone-us': {\n pattern: '(999) 999-9999',\n placeholder: '_',\n },\n 'phone-international': {\n pattern: '+99 999 999 9999',\n placeholder: '_',\n },\n 'date': {\n pattern: '99/99/9999',\n placeholder: '_',\n },\n 'date-us': {\n pattern: '99/99/9999',\n placeholder: '_',\n },\n 'date-eu': {\n pattern: '99-99-9999',\n placeholder: '_',\n },\n 'credit-card': {\n pattern: '9999 9999 9999 9999',\n placeholder: '_',\n },\n 'ssn': {\n pattern: '999-99-9999',\n placeholder: '_',\n },\n 'zip-code': {\n pattern: '99999',\n placeholder: '_',\n },\n 'currency': {\n pattern: '$999,999.99',\n placeholder: '_',\n transform: (value: string) => {\n // Remover caracteres no numéricos excepto punto decimal\n const cleaned = value.replace(/[^\\d.]/g, '')\n const num = parseFloat(cleaned) || 0\n return num.toFixed(2)\n },\n },\n 'percentage': {\n pattern: '999%',\n placeholder: '_',\n transform: (value: string) => {\n const cleaned = value.replace(/[^\\d]/g, '')\n return cleaned\n },\n },\n 'time': {\n pattern: '99:99',\n placeholder: '_',\n },\n 'datetime': {\n pattern: '99/99/9999 99:99',\n placeholder: '_',\n },\n}\n\n/**\n * Obtiene una máscara predefinida\n */\nexport function getPredefinedMask(type: PredefinedMask): CustomMask {\n return PREDEFINED_MASKS[type]\n}\n","/**\n * Validación contra patrones de inyección (SQL, XSS, command injection, etc.)\n */\n\n/** Mensaje de error por defecto para validación de inyección */\nexport const INJECTION_VALIDATION_MESSAGE =\n 'El valor contiene caracteres o patrones no permitidos'\n\n/** Patrones de inyección (regex, case-insensitive) */\nconst INJECTION_PATTERNS: RegExp[] = [\n // SQL Injection\n /\\b(union|select|insert|update|delete|drop|exec|execute|declare)\\s+(all\\s+)?(select|from|into|table)/i,\n /\\b(or|and)\\s+['\"]?\\d+['\"]?\\s*=\\s*['\"]?\\d+/i,\n /;\\s*(drop|delete|truncate|alter)\\s+/i,\n /--\\s*$/, // SQL comment\n /\\/\\*[\\s\\S]*\\*\\//, // Block comment\n /'\\s*or\\s+'1'\\s*=\\s*'1/i,\n /\"\\s*or\\s+\"1\"\\s*=\\s*\"1/i,\n /\\bexec\\s*\\(/i,\n /\\bxp_\\w+/i, // SQL Server extended procedures\n\n // XSS / Scripting\n /<script\\b[\\s\\S]*?>[\\s\\S]*?<\\/script>/i,\n /<script\\b/i,\n /javascript\\s*:/i,\n /vbscript\\s*:/i,\n /on\\w+\\s*=\\s*[\"'][^\"']*[\"']/i, // onclick=, onerror=, onload=, etc.\n /on\\w+\\s*=\\s*[^\\s>]+/i,\n /<iframe\\b/i,\n /<object\\b/i,\n /<embed\\b/i,\n /\\beval\\s*\\(/i,\n /document\\.(cookie|write|location)/i,\n /window\\.(location|open|eval)/i,\n\n // Command injection (shell)\n /[;&|]\\s*(ls|cat|rm|wget|curl|nc|bash|sh|python|perl)\\s/i,\n /\\$\\s*\\([^)]+\\)/, // $(...)\n /`[^`]+`/, // Backtick command substitution\n /\\|\\s*\\w+/, // Pipe to command (with word after)\n\n // NoSQL / Template injection\n /\\$\\s*where\\b/i,\n /\\$\\s*gt\\b|\\$\\s*ne\\b|\\$\\s*regex\\b/i,\n /\\{\\{[^}]*\\}\\}/, // Template literals\n /\\$\\{[^}]*\\}/, // JS template literals\n]\n\n/**\n * Verifica si un valor string contiene patrones de inyección\n */\nexport function containsInjection(value: string): boolean {\n if (typeof value !== 'string' || value.length === 0) {\n return false\n }\n const normalized = value.trim()\n if (normalized.length === 0) return false\n\n for (const pattern of INJECTION_PATTERNS) {\n if (pattern.test(value)) {\n return true\n }\n }\n return false\n}\n\n/**\n * Valida recursivamente un valor (string, array de strings, objetos con strings)\n * Retorna true si NO contiene inyección (válido), false si contiene (inválido)\n */\nexport function isSafeFromInjection(value: unknown): boolean {\n if (value === null || value === undefined) {\n return true\n }\n if (typeof value === 'string') {\n return !containsInjection(value)\n }\n if (Array.isArray(value)) {\n return value.every((item) => isSafeFromInjection(item))\n }\n if (typeof value === 'object') {\n return Object.values(value as Record<string, unknown>).every((v) =>\n isSafeFromInjection(v)\n )\n }\n // number, boolean, etc. - no aplica validación\n return true\n}\n","/**\n * Utilidad para bloquear formularios después de N intentos fallidos\n */\n\nexport interface AttemptsLockOptions {\n maxAttempts: number\n blockDurationMinutes?: number\n storageKey?: string\n onLocked?: (remainingMs: number) => void\n onUnlocked?: () => void\n}\n\ninterface StoredLockState {\n attempts: number\n lockedUntil?: number\n}\n\nexport class AttemptsLock {\n private maxAttempts: number\n private blockDurationMs: number\n private storageKey?: string\n private attempts: number = 0\n private lockedUntil: number | null = null\n private onLocked?: (remainingMs: number) => void\n private onUnlocked?: () => void\n private unlockCheckInterval: ReturnType<typeof setInterval> | null = null\n\n constructor(options: AttemptsLockOptions) {\n this.maxAttempts = Math.max(1, options.maxAttempts)\n this.blockDurationMs =\n (options.blockDurationMinutes ?? 5) * 60 * 1000\n this.storageKey = options.storageKey\n this.onLocked = options.onLocked\n this.onUnlocked = options.onUnlocked\n\n if (this.storageKey && typeof sessionStorage !== 'undefined') {\n this.loadFromStorage()\n }\n }\n\n private loadFromStorage(): void {\n if (!this.storageKey || typeof sessionStorage === 'undefined') return\n try {\n const stored = sessionStorage.getItem(this.storageKey)\n if (stored) {\n const data: StoredLockState = JSON.parse(stored)\n this.attempts = data.attempts ?? 0\n this.lockedUntil = data.lockedUntil ?? null\n this.checkExpiration()\n }\n } catch {\n // Ignorar errores de parsing\n }\n }\n\n private saveToStorage(): void {\n if (!this.storageKey || typeof sessionStorage === 'undefined') return\n try {\n const data: StoredLockState = {\n attempts: this.attempts,\n lockedUntil: this.lockedUntil ?? undefined,\n }\n sessionStorage.setItem(this.storageKey, JSON.stringify(data))\n } catch {\n // Ignorar errores\n }\n }\n\n private checkExpiration(): boolean {\n if (this.lockedUntil === null) return false\n if (Date.now() >= this.lockedUntil) {\n this.reset()\n this.onUnlocked?.()\n return true\n }\n return false\n }\n\n private startUnlockCheck(): void {\n if (this.unlockCheckInterval) return\n this.unlockCheckInterval = setInterval(() => {\n if (this.checkExpiration()) {\n this.stopUnlockCheck()\n }\n }, 1000)\n }\n\n private stopUnlockCheck(): void {\n if (this.unlockCheckInterval) {\n clearInterval(this.unlockCheckInterval)\n this.unlockCheckInterval = null\n }\n }\n\n /**\n * Incrementa el contador de intentos. Si alcanza maxAttempts, bloquea.\n */\n incrementAttempts(): void {\n this.attempts++\n if (this.attempts >= this.maxAttempts) {\n this.lockedUntil = Date.now() + this.blockDurationMs\n this.saveToStorage()\n this.onLocked?.(this.blockDurationMs)\n this.startUnlockCheck()\n } else {\n this.saveToStorage()\n }\n }\n\n /**\n * Retorna true si el lock está activo (aún dentro del período de bloqueo)\n */\n isLocked(): boolean {\n if (this.checkExpiration()) return false\n return this.lockedUntil !== null && Date.now() < this.lockedUntil\n }\n\n /**\n * Retorna los milisegundos restantes del bloqueo, o 0 si no está bloqueado\n */\n getRemainingBlockTimeMs(): number {\n if (this.checkExpiration()) return 0\n if (this.lockedUntil === null) return 0\n return Math.max(0, this.lockedUntil - Date.now())\n }\n\n /**\n * Resetea el contador de intentos y el bloqueo\n */\n reset(): void {\n this.attempts = 0\n this.lockedUntil = null\n this.stopUnlockCheck()\n this.saveToStorage()\n }\n\n /**\n * Retorna el número actual de intentos\n */\n getAttempts(): number {\n return this.attempts\n }\n}\n","/**\n * Utilidades generales\n */\n\n/**\n * Convierte un valor a string para atributos HTML\n */\nexport function attributeValue(value: any): string {\n if (value === null || value === undefined) {\n return ''\n }\n if (typeof value === 'boolean') {\n return value ? 'true' : 'false'\n }\n if (typeof value === 'object') {\n return JSON.stringify(value)\n }\n return String(value)\n}\n\n/**\n * Parsea un valor desde un atributo HTML\n */\nexport function parseAttributeValue(value: string | null): any {\n if (!value) {\n return null\n }\n try {\n return JSON.parse(value)\n } catch {\n return value\n }\n}\n\n/**\n * Genera un ID único\n */\nexport function generateId(prefix = 'ef'): string {\n return `${prefix}-${Math.random().toString(36).substr(2, 9)}`\n}\n\n/**\n * Obtiene el valor anidado de un objeto usando notación de punto\n */\nexport function getNestedValue(obj: Record<string, any>, path: string): any {\n return path.split('.').reduce((current, key) => current?.[key], obj)\n}\n\n/**\n * Establece un valor anidado en un objeto usando notación de punto\n */\nexport function setNestedValue(\n obj: Record<string, any>,\n path: string,\n value: any\n): void {\n const keys = path.split('.')\n const lastKey = keys.pop()!\n const target = keys.reduce((current, key) => {\n if (!current[key] || typeof current[key] !== 'object') {\n current[key] = {}\n }\n return current[key]\n }, obj)\n target[lastKey] = value\n}\n\n/**\n * Valida si un email es válido\n */\nexport function isValidEmail(email: string): boolean {\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n return emailRegex.test(email)\n}\n\n/**\n * Sanitiza un string para usar como ID de HTML\n */\nexport function sanitizeId(str: string): string {\n return str.replace(/[^a-zA-Z0-9-_]/g, '-')\n}\n\n// Exportar funciones de estilos\nexport { getThemeStyles, getColors } from './styles'\n\n// Exportar máscaras\nexport { PREDEFINED_MASKS, getPredefinedMask } from './masks'\n\n// Exportar validación anti-inyección\nexport {\n containsInjection,\n isSafeFromInjection,\n INJECTION_VALIDATION_MESSAGE,\n} from './injection-validation'\n\n// Exportar AttemptsLock\nexport { AttemptsLock } from './attempts-lock'\nexport type { AttemptsLockOptions } from './attempts-lock'\n","import type {\n Validation,\n Field,\n MinLengthValidation,\n MaxLengthValidation,\n MinValidation,\n MaxValidation,\n CustomValidation,\n NoInjectionValidation,\n} from '../types'\nimport { isValidEmail } from '../utils'\nimport { isSafeFromInjection, INJECTION_VALIDATION_MESSAGE } from '../utils/injection-validation'\n\n/**\n * Resultado de una validación\n */\nexport interface ValidationResult {\n isValid: boolean\n message?: string\n}\n\n/**\n * Motor de validaciones\n */\nexport class ValidationEngine {\n /**\n * Valida un campo con todas sus validaciones\n */\n async validateField(\n field: Field,\n value: any\n ): Promise<string[]> {\n return this.validateFieldWithValidations(field, value, field.validations || [])\n }\n\n /**\n * Valida un campo con validaciones específicas\n */\n async validateFieldWithValidations(\n _field: Field,\n value: any,\n validations: Validation[]\n ): Promise<string[]> {\n const errors: string[] = []\n\n if (!validations || validations.length === 0) {\n return errors\n }\n\n for (const validation of validations) {\n const result = await this.validateValue(validation, value)\n if (!result.isValid) {\n errors.push(result.message || this.getDefaultMessage(validation))\n }\n }\n\n return errors\n }\n\n /**\n * Valida un valor con una validación específica\n */\n private async validateValue(\n validation: Validation,\n value: any\n ): Promise<ValidationResult> {\n switch (validation.type) {\n case 'required':\n return this.validateRequired(value)\n case 'email':\n return this.validateEmail(value)\n case 'minLength':\n return this.validateMinLength(value, validation.value)\n case 'maxLength':\n return this.validateMaxLength(value, validation.value)\n case 'min':\n return this.validateMin(value, validation.value)\n case 'max':\n return this.validateMax(value, validation.value)\n case 'pattern':\n return this.validatePattern(value, validation.value)\n case 'custom':\n return await this.validateCustom(value, validation)\n case 'noInjection':\n return this.validateNoInjection(value, validation)\n default:\n return { isValid: true }\n }\n }\n\n /**\n * Valida campo requerido\n */\n private validateRequired(value: any): ValidationResult {\n const isValid =\n value !== null &&\n value !== undefined &&\n value !== '' &&\n !(Array.isArray(value) && value.length === 0)\n return {\n isValid,\n message: isValid ? undefined : 'Este campo es requerido',\n }\n }\n\n /**\n * Valida email\n */\n private validateEmail(value: any): ValidationResult {\n if (!value) {\n return { isValid: true } // Si está vacío, required debe manejarlo\n }\n const isValid = typeof value === 'string' && isValidEmail(value)\n return {\n isValid,\n message: isValid ? undefined : 'Debe ser un email válido',\n }\n }\n\n /**\n * Valida longitud mínima\n */\n private validateMinLength(\n value: any,\n minLength: number\n ): ValidationResult {\n if (!value) {\n return { isValid: true }\n }\n const str = String(value)\n const isValid = str.length >= minLength\n return {\n isValid,\n message: isValid\n ? undefined\n : `Debe tener al menos ${minLength} caracteres`,\n }\n }\n\n /**\n * Valida longitud máxima\n */\n private validateMaxLength(\n value: any,\n maxLength: number\n ): ValidationResult {\n if (!value) {\n return { isValid: true }\n }\n const str = String(value)\n const isValid = str.length <= maxLength\n return {\n isValid,\n message: isValid\n ? undefined\n : `Debe tener máximo ${maxLength} caracteres`,\n }\n }\n\n /**\n * Valida valor mínimo\n */\n private validateMin(value: any, min: number): ValidationResult {\n if (value === null || value === undefined || value === '') {\n return { isValid: true }\n }\n const num = Number(value)\n const isValid = !isNaN(num) && num >= min\n return {\n isValid,\n message: isValid ? undefined : `Debe ser mayor o igual a ${min}`,\n }\n }\n\n /**\n * Valida valor máximo\n */\n private validateMax(value: any, max: number): ValidationResult {\n if (value === null || value === undefined || value === '') {\n return { isValid: true }\n }\n const num = Number(value)\n const isValid = !isNaN(num) && num <= max\n return {\n isValid,\n message: isValid ? undefined : `Debe ser menor o igual a ${max}`,\n }\n }\n\n /**\n * Valida patrón regex\n */\n private validatePattern(value: any, pattern: string | RegExp): ValidationResult {\n if (!value) {\n return { isValid: true }\n }\n \n // Convertir pattern a RegExp si es necesario\n let regex: RegExp\n if (pattern instanceof RegExp) {\n regex = pattern\n } else if (typeof pattern === 'string') {\n try {\n regex = new RegExp(pattern)\n } catch (e) {\n // Si el patrón no es válido, considerar como válido para no bloquear\n console.warn('Invalid regex pattern:', pattern)\n return { isValid: true }\n }\n } else {\n // Si pattern no es string ni RegExp, intentar convertirlo\n console.warn('Pattern validation expects string or RegExp, got:', typeof pattern, pattern)\n return { isValid: true }\n }\n \n const isValid = regex.test(String(value))\n return {\n isValid,\n message: isValid ? undefined : 'El formato no es válido',\n }\n }\n\n /**\n * Valida que el valor no contenga patrones de inyección (SQL, XSS, etc.)\n */\n private validateNoInjection(\n value: any,\n validation: NoInjectionValidation\n ): ValidationResult {\n if (value === null || value === undefined || value === '') {\n return { isValid: true }\n }\n const isValid = isSafeFromInjection(value)\n return {\n isValid,\n message: isValid ? undefined : validation.message || INJECTION_VALIDATION_MESSAGE,\n }\n }\n\n /**\n * Valida con función personalizada\n */\n private async validateCustom(\n value: any,\n validation: CustomValidation\n ): Promise<ValidationResult> {\n try {\n const result = await validation.validator(value)\n return {\n isValid: Boolean(result),\n message: result ? undefined : validation.message || 'Validación fallida',\n }\n } catch (error) {\n return {\n isValid: false,\n message: validation.message || 'Error en la validación',\n }\n }\n }\n\n /**\n * Obtiene mensaje por defecto para una validación\n */\n private getDefaultMessage(validation: Validation): string {\n switch (validation.type) {\n case 'required':\n return 'Este campo es requerido'\n case 'email':\n return 'Debe ser un email válido'\n case 'minLength':\n return `Debe tener al menos ${(validation as MinLengthValidation).value} caracteres`\n case 'maxLength':\n return `Debe tener máximo ${(validation as MaxLengthValidation).value} caracteres`\n case 'min':\n return `Debe ser mayor o igual a ${(validation as MinValidation).value}`\n case 'max':\n return `Debe ser menor o igual a ${(validation as MaxValidation).value}`\n case 'pattern':\n return 'El formato no es válido'\n case 'custom':\n return 'Validación fallida'\n case 'noInjection':\n return INJECTION_VALIDATION_MESSAGE\n default:\n return 'Campo inválido'\n }\n }\n\n /**\n * Evalúa si un campo debe ser validado basándose en sus dependencias\n * Un campo no debe validarse si está oculto por una condición\n */\n private shouldValidateField(field: Field, values: Record<string, any>): boolean {\n // Skip if explicitly hidden or disabled\n if (field.hidden || field.disabled) {\n return false\n }\n\n // Check dependencies to see if field should be visible\n if (field.dependencies) {\n // Check if field should be shown based on dependencies.show\n const showDep = (field.dependencies as any).show\n if (showDep) {\n const isVisible = this.evaluateCondition(showDep, values)\n if (!isVisible) {\n return false\n }\n }\n \n // Also check other dependency actions (hide, enable, disable)\n for (const [action, dep] of Object.entries(field.dependencies)) {\n if (action === 'show') continue // Already handled above\n \n if (!dep || !dep.field) continue\n \n // Get the value of the dependency field\n const depValue = values[dep.field]\n \n let isConditionMet = false\n \n switch (dep.operator) {\n case 'equals':\n isConditionMet = depValue === dep.value\n break\n case 'notEquals':\n isConditionMet = depValue !== dep.value\n break\n case 'contains':\n isConditionMet = String(depValue).includes(String(dep.value))\n break\n case 'notContains':\n isConditionMet = !String(depValue).includes(String(dep.value))\n break\n case 'greaterThan':\n isConditionMet = Number(depValue) > Number(dep.value)\n break\n case 'lessThan':\n isConditionMet = Number(depValue) < Number(dep.value)\n break\n case 'greaterThanOrEqual':\n isConditionMet = Number(depValue) >= Number(dep.value)\n break\n case 'lessThanOrEqual':\n isConditionMet = Number(depValue) <= Number(dep.value)\n break\n case 'in':\n isConditionMet = Array.isArray(dep.value) ? dep.value.includes(depValue) : false\n break\n case 'notIn':\n isConditionMet = Array.isArray(dep.value) ? !dep.value.includes(depValue) : true\n break\n case 'isEmpty':\n isConditionMet = !depValue || depValue === '' || (Array.isArray(depValue) && depValue.length === 0)\n break\n case 'isNotEmpty':\n isConditionMet = depValue && depValue !== '' && !(Array.isArray(depValue) && depValue.length === 0)\n break\n default:\n isConditionMet = true\n }\n \n // If action is 'hide' or 'disable', field should be visible when condition is NOT met\n if (action === 'hide' || action === 'disable') {\n isConditionMet = !isConditionMet\n }\n \n // If the condition for visibility is not met, skip validation\n if (!isConditionMet) {\n return false\n }\n }\n }\n \n return true\n }\n\n /**\n * Evalúa una condición simple\n */\n private evaluateCondition(dep: { field: string; operator: string; value?: any }, values: Record<string, any>): boolean {\n if (!dep || !dep.field) return true\n \n const depValue = values[dep.field]\n \n switch (dep.operator) {\n case 'equals':\n return depValue === dep.value\n case 'notEquals':\n return depValue !== dep.value\n case 'contains':\n return String(depValue).includes(String(dep.value))\n case 'notContains':\n return !String(depValue).includes(String(dep.value))\n case 'greaterThan':\n return Number(depValue) > Number(dep.value)\n case 'lessThan':\n return Number(depValue) < Number(dep.value)\n case 'greaterThanOrEqual':\n return Number(depValue) >= Number(dep.value)\n case 'lessThanOrEqual':\n return Number(depValue) <= Number(dep.value)\n case 'in':\n return Array.isArray(dep.value) ? dep.value.includes(depValue) : false\n case 'notIn':\n return Array.isArray(dep.value) ? !dep.value.includes(depValue) : true\n case 'isEmpty':\n return !depValue || depValue === '' || (Array.isArray(depValue) && depValue.length === 0)\n case 'isNotEmpty':\n return depValue && depValue !== '' && !(Array.isArray(depValue) && depValue.length === 0)\n default:\n return true\n }\n }\n \n /**\n * Valida todos los campos de un formulario\n */\n async validateForm(\n fields: Field[],\n values: Record<string, any>\n ): Promise<Record<string, string[]>> {\n const errors: Record<string, string[]> = {}\n\n for (const field of fields) {\n // Skip validation if field should not be validated based on dependencies\n if (!this.shouldValidateField(field, values)) {\n continue\n }\n \n const value = values[field.name]\n const fieldErrors = await this.validateField(field, value)\n if (fieldErrors.length > 0) {\n errors[field.name] = fieldErrors\n }\n }\n\n return errors\n }\n}\n","import type {\n FieldCondition,\n FieldDependencies,\n ConditionOperator,\n} from '../types'\n\n/**\n * Motor de evaluación de condiciones\n */\nexport class ConditionEngine {\n /**\n * Evalúa una condición individual\n */\n evaluateCondition(\n condition: FieldCondition,\n formValues: Record<string, any>\n ): boolean {\n const fieldValue = this.getFieldValue(condition.field, formValues)\n return this.compareValues(fieldValue, condition.operator, condition.value)\n }\n\n /**\n * Evalúa múltiples condiciones (AND por defecto, soportar OR)\n */\n evaluateConditions(\n conditions: FieldCondition | FieldCondition[],\n formValues: Record<string, any>,\n logic: 'and' | 'or' = 'and'\n ): boolean {\n const conditionsArray = Array.isArray(conditions) ? conditions : [conditions]\n\n if (conditionsArray.length === 0) {\n return true\n }\n\n if (logic === 'and') {\n return conditionsArray.every((condition) =>\n this.evaluateCondition(condition, formValues)\n )\n } else {\n return conditionsArray.some((condition) =>\n this.evaluateCondition(condition, formValues)\n )\n }\n }\n\n /**\n * Evalúa dependencias de un campo\n */\n evaluateDependencies(\n dependencies: FieldDependencies,\n formValues: Record<string, any>\n ): {\n visible: boolean\n enabled: boolean\n required: boolean\n } {\n let visible = true\n let enabled = true\n let required = false\n\n // Evaluar show/hide\n if (dependencies.show) {\n visible = this.evaluateConditions(dependencies.show, formValues)\n }\n if (dependencies.hide) {\n const shouldHide = this.evaluateConditions(dependencies.hide, formValues)\n visible = visible && !shouldHide\n }\n\n // Evaluar enable/disable\n if (dependencies.enable) {\n enabled = this.evaluateConditions(dependencies.enable, formValues)\n }\n if (dependencies.disable) {\n const shouldDisable = this.evaluateConditions(\n dependencies.disable,\n formValues\n )\n enabled = enabled && !shouldDisable\n }\n\n // Evaluar required/optional\n if (dependencies.required) {\n required = this.evaluateConditions(dependencies.required, formValues)\n }\n if (dependencies.optional) {\n const shouldBeOptional = this.evaluateConditions(\n dependencies.optional,\n formValues\n )\n required = required && !shouldBeOptional\n }\n\n return { visible, enabled, required }\n }\n\n /**\n * Obtiene el valor de un campo (soporta nested paths)\n */\n private getFieldValue(\n fieldName: string,\n formValues: Record<string, any>\n ): any {\n const parts = fieldName.split('.')\n let value = formValues\n\n for (const part of parts) {\n if (value === null || value === undefined) {\n return null\n }\n value = value[part]\n }\n\n return value\n }\n\n /**\n * Compara valores según el operador\n */\n private compareValues(\n fieldValue: any,\n operator: ConditionOperator,\n compareValue: any\n ): boolean {\n switch (operator) {\n case 'equals':\n return this.deepEqual(fieldValue, compareValue)\n\n case 'notEquals':\n return !this.deepEqual(fieldValue, compareValue)\n\n case 'contains':\n if (Array.isArray(fieldValue)) {\n return fieldValue.includes(compareValue)\n }\n if (typeof fieldValue === 'string') {\n return fieldValue.includes(String(compareValue))\n }\n return false\n\n case 'notContains':\n return !this.compareValues(fieldValue, 'contains', compareValue)\n\n case 'greaterThan':\n return this.toNumber(fieldValue) > this.toNumber(compareValue)\n\n case 'lessThan':\n return this.toNumber(fieldValue) < this.toNumber(compareValue)\n\n case 'greaterThanOrEqual':\n return this.toNumber(fieldValue) >= this.toNumber(compareValue)\n\n case 'lessThanOrEqual':\n return this.toNumber(fieldValue) <= this.toNumber(compareValue)\n\n case 'in':\n if (Array.isArray(compareValue)) {\n return compareValue.includes(fieldValue)\n }\n return false\n\n case 'notIn':\n return !this.compareValues(fieldValue, 'in', compareValue)\n\n case 'isEmpty':\n return (\n fieldValue === null ||\n fieldValue === undefined ||\n fieldValue === '' ||\n (Array.isArray(fieldValue) && fieldValue.length === 0)\n )\n\n case 'isNotEmpty':\n return !this.compareValues(fieldValue, 'isEmpty', compareValue)\n\n case 'regex':\n try {\n const regex =\n typeof compareValue === 'string'\n ? new RegExp(compareValue)\n : compareValue\n return regex.test(String(fieldValue || ''))\n } catch {\n return false\n }\n\n default:\n return false\n }\n }\n\n /**\n * Comparación profunda de valores\n */\n private deepEqual(a: any, b: any): boolean {\n if (a === b) {\n return true\n }\n\n if (a === null || b === null || a === undefined || b === undefined) {\n return a === b\n }\n\n if (typeof a !== typeof b) {\n return false\n }\n\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) {\n return false\n }\n return a.every((val, index) => this.deepEqual(val, b[index]))\n }\n\n if (typeof a === 'object') {\n const keysA = Object.keys(a)\n const keysB = Object.keys(b)\n\n if (keysA.length !== keysB.length) {\n return false\n }\n\n return keysA.every((key) => this.deepEqual(a[key], b[key]))\n }\n\n return false\n }\n\n /**\n * Convierte un valor a número\n */\n private toNumber(value: any): number {\n if (typeof value === 'number') {\n return value\n }\n if (typeof value === 'string') {\n const parsed = parseFloat(value)\n return isNaN(parsed) ? 0 : parsed\n }\n return 0\n }\n}\n","import type {\n FormState,\n WizardState,\n Field,\n FormSchema,\n} from '../types'\nimport { SchemaParser, type ParsedSchema } from './schema-parser'\nimport { ValidationEngine } from './validation-engine'\nimport { ConditionEngine } from './condition-engine'\nimport { getNestedValue, setNestedValue } from '../utils'\n\n/**\n * Gestor de estado del formulario\n */\nexport class StateManager {\n private state: FormState\n private wizardState: WizardState | null = null\n private schema: ParsedSchema | null = null\n private parser: SchemaParser\n private validator: ValidationEngine\n private conditionEngine: ConditionEngine\n private dependencyCache: Map<string, { visible: boolean; enabled: boolean; required: boolean }> = new Map()\n private fieldDependencies: Map<string, Set<string>> = new Map() // campo observado -> campos dependientes\n\n constructor() {\n this.parser = new SchemaParser()\n this.validator = new ValidationEngine()\n this.conditionEngine = new ConditionEngine()\n this.state = this.createInitialState()\n }\n\n /**\n * Crea el estado inicial\n */\n private createInitialState(): FormState {\n return {\n values: {},\n errors: {},\n touched: {},\n isValid: true,\n isSubmitting: false,\n }\n }\n\n /**\n * Inicializa el schema\n */\n initializeSchema(schema: FormSchema, initialData?: Record<string, any>): void {\n this.schema = this.parser.parse(schema)\n this.initializeValues(initialData)\n this.initializeWizard()\n this.buildDependencyMap()\n }\n\n /**\n * Extrae todos los campos recursivamente (incluyendo groups, rows).\n * Los campos de array.itemSchema NO se incluyen como top-level: viven dentro de cada ítem.\n */\n private extractAllFields(fields: Field[]): Field[] {\n const allFields: Field[] = []\n \n for (const field of fields) {\n allFields.push(field)\n \n if (field.type === 'group' && 'fields' in field) {\n allFields.push(...this.extractAllFields(field.fields))\n }\n if (field.type === 'row' && 'fields' in field) {\n allFields.push(...this.extractAllFields(field.fields))\n }\n // Array: no extraer itemSchema.fields como top-level; se inicializan dentro de cada ítem\n }\n \n return allFields\n }\n\n /**\n * Devuelve los nombres de campos que solo existen dentro de itemSchema de arrays\n * y NO como campos top-level. Estos NO deben aparecer como claves en la raíz de values.\n */\n private getArrayItemOnlyFieldNames(fields: Field[]): Set<string> {\n const topLevelNames = new Set(fields.map((f) => f.name))\n const arrayItemNames = new Set<string>()\n for (const field of fields) {\n if (field.type === 'array' && 'itemSchema' in field && field.itemSchema?.fields) {\n for (const sub of field.itemSchema.fields) {\n if (!topLevelNames.has(sub.name)) {\n arrayItemNames.add(sub.name)\n }\n }\n }\n }\n return arrayItemNames\n }\n\n /**\n * Encuentra el path completo de un campo dentro de grupos\n */\n private findFieldPath(fieldName: string, fields: Field[], parentPath: string = ''): string | null {\n for (const field of fields) {\n const currentPath = parentPath ? `${parentPath}.${field.name}` : field.name\n \n if (field.name === fieldName) {\n return currentPath\n }\n \n if (field.type === 'group' && 'fields' in field) {\n const found = this.findFieldPath(fieldName, field.fields, currentPath)\n if (found) return found\n }\n if (field.type === 'row' && 'fields' in field) {\n const found = this.findFieldPath(fieldName, field.fields, currentPath)\n if (found) return found\n }\n }\n \n return null\n }\n\n /**\n * Construye el mapa de dependencias para optimizar re-evaluaciones\n */\n private buildDependencyMap(): void {\n this.fieldDependencies.clear()\n this.dependencyCache.clear()\n\n if (!this.schema) return\n\n const topLevelFields = this.schema.isWizard\n ? this.schema.steps!.flatMap((step) => step.fields)\n : this.schema.fields || []\n\n const allFields = this.extractAllFields(topLevelFields)\n\n for (const field of allFields) {\n if (!field.dependencies) continue\n\n // Extraer todos los campos observados\n const observedFields = this.extractObservedFields(field.dependencies)\n \n for (const observedField of observedFields) {\n if (!this.fieldDependencies.has(observedField)) {\n this.fieldDependencies.set(observedField, new Set())\n }\n this.fieldDependencies.get(observedField)!.add(field.name)\n }\n }\n }\n\n /**\n * Extrae los nombres de campos observados de las dependencias\n */\n private extractObservedFields(dependencies: any): Set<string> {\n const fields = new Set<string>()\n\n const extractFromCondition = (condition: any) => {\n if (condition && condition.field) {\n fields.add(condition.field)\n }\n }\n\n const extractFromConditions = (conditions: any) => {\n if (Array.isArray(conditions)) {\n conditions.forEach(extractFromCondition)\n } else if (conditions) {\n extractFromCondition(conditions)\n }\n }\n\n if (dependencies.show) extractFromConditions(dependencies.show)\n if (dependencies.hide) extractFromConditions(dependencies.hide)\n if (dependencies.enable) extractFromConditions(dependencies.enable)\n if (dependencies.disable) extractFromConditions(dependencies.disable)\n if (dependencies.required) extractFromConditions(dependencies.required)\n if (dependencies.optional) extractFromConditions(dependencies.optional)\n\n return fields\n }\n\n /**\n * Inicializa los valores por defecto\n */\n private initializeValues(initialData?: Record<string, any>): void {\n if (!this.schema) return\n\n const topLevelFields = this.schema.isWizard\n ? this.schema.steps!.flatMap((step) => step.fields)\n : this.schema.fields || []\n\n const allFields = this.extractAllFields(topLevelFields)\n\n // Preservar valores existentes\n const existingValues = { ...this.state.values }\n const values: Record<string, any> = {}\n\n // Primero, cargar valores desde initialData si está disponible\n if (initialData) {\n for (const key in initialData) {\n const value = initialData[key]\n if (value !== undefined && value !== null) {\n setNestedValue(values, key, value)\n }\n }\n }\n\n // Luego, inicializar campos desde defaultValue o valores por defecto\n for (const field of allFields) {\n // Verificar si ya hay un valor desde initialData\n const existingValue = getNestedValue(values, field.name)\n \n // Si el campo ya tiene un valor desde initialData o existingValues, preservarlo\n if (existingValue !== undefined && existingValue !== null) {\n // Ya está inicializado desde initialData\n continue\n }\n \n // Verificar si hay un valor previo en existingValues\n const prevValue = getNestedValue(existingValues, field.name)\n if (prevValue !== undefined && prevValue !== null) {\n setNestedValue(values, field.name, prevValue)\n } else {\n // Solo inicializar si no existe valor previo\n this.initializeFieldValue(field, values)\n }\n }\n\n // Preservar valores de campos que no están en el schema actual (por si acaso)\n // Excluir nombres que son solo de itemSchema de arrays (street, city, etc.) — no deben estar en raíz\n const arrayItemOnlyNames = this.getArrayItemOnlyFieldNames(topLevelFields)\n for (const key in existingValues) {\n if (arrayItemOnlyNames.has(key)) continue\n if (!(key in values)) {\n values[key] = existingValues[key]\n }\n }\n\n // Rellenar arrays con initialData cuando length < minItems\n for (const field of topLevelFields) {\n if (field.type === 'array' && 'minItems' in field && 'itemSchema' in field) {\n const arrayField = field as { minItems?: number; itemSchema?: { fields?: Field[] } }\n const minItems = arrayField.minItems ?? 0\n if (minItems >= 1 && arrayField.itemSchema?.fields?.length) {\n const arr = getNestedValue(values, field.name)\n if (Array.isArray(arr) && arr.length < minItems) {\n const padded = [...arr]\n for (let i = arr.length; i < minItems; i++) {\n const item: Record<string, any> = {}\n for (const subField of arrayField.itemSchema!.fields!) {\n this.initializeFieldValue(subField, item)\n }\n padded.push(item)\n }\n setNestedValue(values, field.name, padded)\n }\n }\n }\n }\n\n // Eliminar claves que solo pertenecen a itemSchema de arrays (nunca deben estar en raíz)\n for (const name of arrayItemOnlyNames) {\n if (name in values) {\n delete values[name]\n }\n }\n\n this.state.values = values\n }\n\n /**\n * Inicializa el valor de un campo\n */\n private initializeFieldValue(\n field: Field,\n values: Record<string, any>\n ): void {\n if (field.defaultValue !== undefined) {\n values[field.name] = field.defaultValue\n } else {\n switch (field.type) {\n case 'checkbox':\n case 'switch':\n values[field.name] = field.checked || false\n break\n case 'select':\n if ('multiple' in field && field.multiple) {\n values[field.name] = []\n } else {\n values[field.name] = null\n }\n break\n case 'array': {\n const arrayField = field as { itemSchema?: { fields?: Field[] }; minItems?: number }\n const minItems = arrayField.minItems ?? 0\n const itemFields = arrayField.itemSchema?.fields\n if (minItems >= 1 && itemFields?.length) {\n const arr: Record<string, any>[] = []\n for (let i = 0; i < minItems; i++) {\n const item: Record<string, any> = {}\n for (const subField of itemFields) {\n this.initializeFieldValue(subField, item)\n }\n arr.push(item)\n }\n values[field.name] = arr\n } else {\n values[field.name] = []\n }\n break\n }\n case 'group':\n values[field.name] = {}\n if ('fields' in field) {\n for (const subField of field.fields) {\n this.initializeFieldValue(subField, values[field.name] as Record<string, any>)\n }\n }\n break\n case 'colorpicker':\n values[field.name] =\n (field as { defaultValue?: string }).defaultValue ?? '#000000'\n break\n default:\n values[field.name] = null\n }\n }\n }\n\n /**\n * Inicializa el estado del wizard\n */\n private initializeWizard(): void {\n if (!this.schema || !this.schema.isWizard) {\n this.wizardState = null\n return\n }\n\n this.wizardState = {\n currentStep: 0,\n totalSteps: this.schema.steps!.length,\n completedSteps: [],\n }\n }\n\n /**\n * Obtiene el estado actual\n */\n getState(): FormState {\n return { ...this.state }\n }\n\n /**\n * Obtiene el estado del wizard\n */\n getWizardState(): WizardState | null {\n return this.wizardState ? { ...this.wizardState } : null\n }\n\n /**\n * Obtiene un valor del formulario\n */\n getValue(fieldName: string): any {\n return getNestedValue(this.state.values, fieldName)\n }\n\n /**\n * Crea un ítem nuevo con valores por defecto para un campo array\n */\n createDefaultArrayItem(arrayField: Field): Record<string, any> {\n const itemSchema = (arrayField as { itemSchema?: { fields?: Field[] } }).itemSchema\n const itemFields = itemSchema?.fields\n if (!itemFields?.length) return {}\n const item: Record<string, any> = {}\n for (const subField of itemFields) {\n this.initializeFieldValue(subField, item)\n }\n return item\n }\n\n /**\n * Establece un valor\n */\n async setValue(fieldName: string, value: any): Promise<void> {\n setNestedValue(this.state.values, fieldName, value)\n this.state.touched[fieldName] = true\n\n // Invalidar cache de dependencias para campos que dependen de este\n this.invalidateDependencyCache(fieldName)\n\n // Validar el campo si está touched\n if (this.state.touched[fieldName] && this.schema) {\n await this.validateField(fieldName)\n }\n\n // Validar campos dependientes que ahora pueden tener diferentes validaciones\n const dependentFields = this.fieldDependencies.get(fieldName)\n if (dependentFields) {\n for (const dependentField of dependentFields) {\n await this.validateField(dependentField)\n }\n }\n\n this.updateValidity()\n }\n\n /**\n * Invalida el cache de dependencias para campos dependientes\n */\n private invalidateDependencyCache(fieldName: string): void {\n const dependentFields = this.fieldDependencies.get(fieldName)\n if (dependentFields) {\n for (const dependentField of dependentFields) {\n this.dependencyCache.delete(dependentField)\n }\n }\n }\n\n /**\n * Establece un valor sin validar (útil para preservar valores durante re-renderizado)\n */\n setValueWithoutValidation(fieldName: string, value: any): void {\n setNestedValue(this.state.values, fieldName, value)\n // Invalidar cache de dependencias para campos que dependen de este\n this.invalidateDependencyCache(fieldName)\n // No marcar como touched ni validar\n }\n\n /**\n * Valida un campo específico\n */\n async validateField(fieldName: string): Promise<void> {\n if (!this.schema) return\n\n const topLevelFields = this.schema.isWizard\n ? this.schema.steps!.flatMap((step) => step.fields)\n : this.schema.fields || []\n\n const allFields = this.extractAllFields(topLevelFields)\n const field = allFields.find((f) => f.name === fieldName)\n if (!field) return\n\n // Si el campo no es visible, no validar\n if (!this.getFieldVisibility(fieldName)) {\n delete this.state.errors[fieldName]\n return\n }\n\n const value = this.getValue(fieldName)\n \n // Obtener validaciones activas (incluyendo condicionales)\n const activeValidations = this.getActiveValidations(field)\n \n const errors = await this.validator.validateFieldWithValidations(\n field,\n value,\n activeValidations\n )\n\n if (errors.length > 0) {\n this.state.errors[fieldName] = errors\n } else {\n delete this.state.errors[fieldName]\n }\n }\n\n /**\n * Obtiene las validaciones activas para un campo (incluyendo condicionales)\n */\n private getActiveValidations(field: Field): any[] {\n let validations = [...(field.validations || [])]\n\n // Agregar validación anti-inyección automática para campos de texto\n const textFieldTypes = ['text', 'email', 'password', 'textarea']\n const skipInjection = field.skipInjectionValidation ?? (field.props as any)?.skipInjectionValidation\n if (\n textFieldTypes.includes(field.type) &&\n !skipInjection &&\n !validations.some((v) => v.type === 'noInjection')\n ) {\n validations = [{ type: 'noInjection' }, ...validations]\n }\n\n // Verificar si el campo es requerido dinámicamente a través de dependencias\n const isRequired = this.getFieldRequired(field.name)\n const hasRequiredValidation = validations.some(v => v.type === 'required')\n \n if (isRequired && !hasRequiredValidation) {\n // Agregar validación required si no existe\n validations = [{ type: 'required' }, ...validations]\n } else if (!isRequired && hasRequiredValidation) {\n // Remover validación required si el campo no es requerido dinámicamente\n validations = validations.filter(v => v.type !== 'required')\n }\n\n // Agregar validaciones condicionales si se cumplen las condiciones\n if (field.conditionalValidations) {\n for (const conditional of field.conditionalValidations) {\n const conditionMet = this.conditionEngine.evaluateConditions(\n conditional.condition,\n this.state.values\n )\n if (conditionMet) {\n validations = [...validations, ...conditional.validations]\n }\n }\n }\n\n return validations\n }\n\n /**\n * Valida todo el formulario\n */\n async validateForm(): Promise<Record<string, string[]>> {\n if (!this.schema) {\n return {}\n }\n\n const topLevelFields = this.schema.isWizard\n ? this.schema.steps!.flatMap((step) => step.fields)\n : this.schema.fields || []\n\n const allFields = this.extractAllFields(topLevelFields)\n const errors = await this.validator.validateForm(\n allFields,\n this.state.values\n )\n\n this.state.errors = errors\n this.updateValidity()\n\n return errors\n }\n\n /**\n * Actualiza la validez del formulario\n */\n private updateValidity(): void {\n this.state.isValid = Object.keys(this.state.errors).length === 0\n }\n\n /**\n * Marca un campo como touched\n */\n setTouched(fieldName: string): void {\n this.state.touched[fieldName] = true\n }\n\n /**\n * Obtiene los errores de un campo\n */\n getErrors(fieldName: string): string[] {\n return this.state.errors[fieldName] || []\n }\n\n /**\n * Obtiene todos los errores\n */\n getAllErrors(): Record<string, string[]> {\n return { ...this.state.errors }\n }\n\n /**\n * Resetea el formulario\n */\n reset(): void {\n this.state = this.createInitialState()\n if (this.schema) {\n this.initializeValues()\n this.initializeWizard()\n }\n }\n\n /**\n * Avanza al siguiente step del wizard\n */\n nextStep(): boolean {\n if (!this.wizardState) return false\n if (this.wizardState.currentStep < this.wizardState.totalSteps - 1) {\n this.wizardState.currentStep++\n return true\n }\n return false\n }\n\n /**\n * Retrocede al step anterior del wizard\n */\n previousStep(): boolean {\n if (!this.wizardState) return false\n if (this.wizardState.currentStep > 0) {\n this.wizardState.currentStep--\n return true\n }\n return false\n }\n\n /**\n * Va a un step específico\n */\n goToStep(stepIndex: number): boolean {\n if (!this.wizardState) return false\n if (stepIndex >= 0 && stepIndex < this.wizardState.totalSteps) {\n this.wizardState.currentStep = stepIndex\n return true\n }\n return false\n }\n\n /**\n * Marca un step como completado\n */\n completeStep(stepIndex: number): void {\n if (!this.wizardState) return\n if (!this.wizardState.completedSteps.includes(stepIndex)) {\n this.wizardState.completedSteps.push(stepIndex)\n }\n }\n\n /**\n * Establece el estado de submitting\n */\n setSubmitting(isSubmitting: boolean): void {\n this.state.isSubmitting = isSubmitting\n }\n\n /**\n * Obtiene los campos del step actual\n */\n getCurrentStepFields(): Field[] {\n if (!this.schema || !this.schema.isWizard || !this.wizardState) {\n return this.schema?.fields || []\n }\n return this.schema.steps![this.wizardState.currentStep].fields\n }\n\n /**\n * Obtiene la visibilidad de un campo basándose en dependencias\n */\n getFieldVisibility(fieldName: string): boolean {\n // Verificar cache primero\n const cached = this.dependencyCache.get(fieldName)\n if (cached !== undefined) {\n return cached.visible\n }\n\n if (!this.schema) return true\n\n const topLevelFields = this.schema.isWizard\n ? this.schema.steps!.flatMap((step) => step.fields)\n : this.schema.fields || []\n\n const allFields = this.extractAllFields(topLevelFields)\n\n // Buscar el campo por nombre completo primero\n let field = allFields.find((f) => {\n const fullPath = this.findFieldPath(f.name, topLevelFields)\n return fullPath === fieldName || f.name === fieldName\n })\n \n // Si no se encuentra, buscar por nombre relativo\n if (!field) {\n field = allFields.find((f) => f.name === fieldName)\n }\n \n if (!field || !field.dependencies) {\n return !field?.hidden\n }\n\n // Si el campo está dentro de un grupo, las dependencias son relativas al grupo\n // Encontrar el path completo del campo\n const fieldFullPath = this.findFieldPath(field.name, topLevelFields) || field.name\n const groupPath = fieldFullPath.includes('.') ? fieldFullPath.split('.').slice(0, -1).join('.') : ''\n \n // Crear un contexto de valores que resuelva dependencias relativas dentro del grupo\n // Si el campo está en un grupo, las dependencias relativas (como 'profile.type') \n // deben resolverse en el contexto del grupo (user.profile.type)\n let valuesContext: Record<string, any> = { ...this.state.values }\n if (groupPath && field.dependencies) {\n // Obtener valores del grupo\n const groupValues = getNestedValue(this.state.values, groupPath)\n if (groupValues && typeof groupValues === 'object') {\n // Crear un contexto que mapee nombres relativos a valores del grupo\n // Por ejemplo, si groupPath es 'user' y groupValues es { profile: { type: 'premium' } }\n // entonces 'profile.type' debería resolverse a 'premium'\n const createRelativeContext = (obj: any, prefix: string = ''): Record<string, any> => {\n const result: Record<string, any> = {}\n for (const [key, value] of Object.entries(obj)) {\n const relativeKey = prefix ? `${prefix}.${key}` : key\n if (value && typeof value === 'object' && !Array.isArray(value) && value !== null) {\n Object.assign(result, createRelativeContext(value, relativeKey))\n } else {\n result[relativeKey] = value\n }\n }\n return result\n }\n const relativeContext = createRelativeContext(groupValues)\n // Combinar contexto relativo con valores globales\n valuesContext = { ...this.state.values, ...relativeContext }\n }\n }\n\n const result = this.conditionEngine.evaluateDependencies(\n field.dependencies,\n valuesContext\n )\n\n // Cachear resultado\n this.dependencyCache.set(fieldName, result)\n\n return result.visible && !field.hidden\n }\n\n /**\n * Obtiene si un campo está habilitado basándose en dependencias\n */\n getFieldEnabled(fieldName: string): boolean {\n // Verificar cache primero\n const cached = this.dependencyCache.get(fieldName)\n if (cached !== undefined) {\n return cached.enabled\n }\n\n if (!this.schema) return true\n\n const topLevelFields = this.schema.isWizard\n ? this.schema.steps!.flatMap((step) => step.fields)\n : this.schema.fields || []\n\n const allFields = this.extractAllFields(topLevelFields)\n const field = allFields.find((f) => f.name === fieldName)\n if (!field) return true\n\n if (field.disabled) return false\n\n if (!field.dependencies) {\n return true\n }\n\n const result = this.conditionEngine.evaluateDependencies(\n field.dependencies,\n this.state.values\n )\n\n // Cachear resultado\n this.dependencyCache.set(fieldName, result)\n\n return result.enabled\n }\n\n /**\n * Obtiene si un campo es requerido basándose en dependencias\n */\n getFieldRequired(fieldName: string): boolean {\n // Verificar cache primero\n const cached = this.dependencyCache.get(fieldName)\n if (cached !== undefined) {\n return cached.required\n }\n\n if (!this.schema) return false\n\n const topLevelFields = this.schema.isWizard\n ? this.schema.steps!.flatMap((step) => step.fields)\n : this.schema.fields || []\n\n const allFields = this.extractAllFields(topLevelFields)\n\n const field = allFields.find((f) => f.name === fieldName)\n if (!field) return false\n\n // Verificar si tiene validación required estándar\n const hasRequired = field.validations?.some((v) => v.type === 'required') || false\n\n if (!field.dependencies) {\n return hasRequired\n }\n\n const result = this.conditionEngine.evaluateDependencies(\n field.dependencies,\n this.state.values\n )\n\n // Cachear resultado\n this.dependencyCache.set(fieldName, result)\n\n return result.required || hasRequired\n }\n\n /**\n * Obtiene los campos que dependen de un campo específico\n */\n getDependentFields(fieldName: string): string[] {\n return Array.from(this.fieldDependencies.get(fieldName) || [])\n }\n}\n","import type { Field, SlotContent } from '../../types'\n\n/**\n * Clase base para inputs\n */\nexport abstract class BaseInput {\n protected field: Field\n protected value: any\n protected error?: string\n protected onChange: (value: any) => void\n protected onBlur: () => void\n\n constructor(\n field: Field,\n value: any,\n error: string | undefined,\n onChange: (value: any) => void,\n onBlur: () => void\n ) {\n this.field = field\n this.value = value\n this.error = error\n this.onChange = onChange\n this.onBlur = onBlur\n }\n\n /**\n * Renderiza el input\n */\n abstract render(): HTMLElement\n\n /**\n * Crea wrapper con slots leading/trailing si el campo tiene leadingIcon o trailingIcon.\n * Si no hay slots, devuelve el input sin wrapper (retrocompatibilidad).\n */\n protected createInputWithSlots(rawInput: HTMLElement): HTMLElement {\n const leading = this.field.leadingIcon\n const trailing = this.field.trailingIcon\n if (!leading && !trailing) {\n return rawInput\n }\n\n const wrapper = document.createElement('div')\n wrapper.className = 'easy-form-input-wrapper'\n\n if (leading && this.isSlotContentValid(leading)) {\n const slotEl = this.renderSlotContent(leading)\n slotEl.className = 'easy-form-input-slot easy-form-input-slot-leading'\n wrapper.appendChild(slotEl)\n }\n\n const inputWrap = document.createElement('div')\n inputWrap.className = 'easy-form-input-core'\n inputWrap.appendChild(rawInput)\n wrapper.appendChild(inputWrap)\n\n if (trailing && this.isSlotContentValid(trailing)) {\n const slotEl = this.renderSlotContent(trailing)\n slotEl.className = 'easy-form-input-slot easy-form-input-slot-trailing'\n wrapper.appendChild(slotEl)\n }\n\n return wrapper\n }\n\n private isSlotContentValid(slot: SlotContent): boolean {\n if (!slot.type) return false\n if (slot.type === 'image') return Boolean(slot.src)\n if (slot.type === 'html') return Boolean(slot.html)\n return false\n }\n\n private renderSlotContent(slot: SlotContent): HTMLElement {\n const container = document.createElement('span')\n container.className = 'easy-form-input-slot-content'\n if (slot.type === 'image' && slot.src) {\n const img = document.createElement('img')\n img.src = slot.src\n img.alt = slot.alt ?? ''\n img.setAttribute('aria-hidden', 'true')\n container.appendChild(img)\n } else if (slot.type === 'html' && slot.html) {\n container.innerHTML = slot.html\n }\n return container\n }\n\n /**\n * Crea un contenedor con label y error\n */\n protected createFieldContainer(input: HTMLElement): HTMLElement {\n const container = document.createElement('div')\n \n // Si el input es un contenedor con clases específicas de componentes, preservarlas\n const inputClasses = Array.from(input.classList)\n const componentContainerClasses = inputClasses.filter(\n (cls) => cls.startsWith('easy-form-') && \n cls !== 'easy-form-field' &&\n (cls.includes('-container') || cls.includes('-wrapper'))\n )\n \n const labelPosition = (this.field as { labelPosition?: 'up' | 'down' | 'left' | 'right' | 'none' }).labelPosition ?? 'up'\n\n const inputToAppend = this.createInputWithSlots(input)\n\n if (componentContainerClasses.length > 0) {\n container.className = `easy-form-field easy-form-label-${labelPosition} ${componentContainerClasses.join(' ')}`\n } else {\n container.className = `easy-form-field easy-form-label-${labelPosition}`\n }\n\n // Aplicar aria-label si labelPosition es 'none' y hay label\n if (labelPosition === 'none' && this.field.label) {\n const el = inputToAppend.querySelector('input, textarea, select') || inputToAppend\n if (el instanceof HTMLElement) {\n el.setAttribute('aria-label', this.field.label)\n }\n }\n\n const createLabel = (): HTMLLabelElement | null => {\n if (!this.field.label || labelPosition === 'none') return null\n const label = document.createElement('label')\n label.className = 'easy-form-label'\n label.setAttribute('for', this.getFieldId())\n label.textContent = this.field.label\n if (this.field.validations?.some((v) => v.type === 'required')) {\n const required = document.createElement('span')\n required.className = 'easy-form-required'\n required.textContent = ' *'\n label.appendChild(required)\n }\n return label\n }\n\n const label = createLabel()\n\n // Orden según labelPosition\n if (labelPosition === 'up') {\n if (label) container.appendChild(label)\n container.appendChild(inputToAppend)\n } else if (labelPosition === 'down') {\n container.appendChild(inputToAppend)\n if (label) container.appendChild(label)\n } else if (labelPosition === 'left') {\n const inner = document.createElement('div')\n inner.className = 'easy-form-field-inner easy-form-field-inner-horizontal'\n if (label) inner.appendChild(label)\n inner.appendChild(inputToAppend)\n container.appendChild(inner)\n } else if (labelPosition === 'right') {\n const inner = document.createElement('div')\n inner.className = 'easy-form-field-inner easy-form-field-inner-horizontal'\n inner.appendChild(inputToAppend)\n if (label) inner.appendChild(label)\n container.appendChild(inner)\n } else {\n container.appendChild(inputToAppend)\n }\n\n // Description\n if (this.field.description) {\n const description = document.createElement('p')\n description.className = 'easy-form-description'\n description.textContent = this.field.description\n container.appendChild(description)\n }\n\n // Error\n if (this.error) {\n const errorEl = document.createElement('p')\n errorEl.className = 'easy-form-error'\n errorEl.textContent = this.error\n container.appendChild(errorEl)\n }\n\n return container\n }\n\n /**\n * Obtiene el ID del campo\n */\n protected getFieldId(): string {\n return `easy-form-${this.field.name}`\n }\n\n /**\n * Aplica props comunes a un elemento\n */\n protected applyCommonProps(element: HTMLElement): void {\n element.id = this.getFieldId()\n element.setAttribute('name', this.field.name)\n\n if (this.field.disabled) {\n element.setAttribute('disabled', 'true')\n element.classList.add('easy-form-input-disabled')\n }\n\n if (this.field.hidden) {\n element.style.display = 'none'\n element.classList.add('easy-form-field-hidden')\n }\n\n if (this.error) {\n element.classList.add('easy-form-input-error')\n }\n\n if (this.field.props) {\n for (const [key, value] of Object.entries(this.field.props)) {\n if (key.startsWith('data-') || key.startsWith('aria-')) {\n element.setAttribute(key, String(value))\n }\n }\n }\n }\n}\n","/**\n * Token de máscara\n */\nexport interface MaskToken {\n type: 'digit' | 'letter' | 'any' | 'literal'\n char: string\n editable: boolean\n}\n\n/**\n * Parsea un patrón de máscara en tokens\n */\nexport function parseMaskPattern(pattern: string): MaskToken[] {\n const tokens: MaskToken[] = []\n\n for (let i = 0; i < pattern.length; i++) {\n const char = pattern[i]\n\n switch (char) {\n case '9':\n tokens.push({ type: 'digit', char: '9', editable: true })\n break\n case 'a':\n case 'A':\n tokens.push({ type: 'letter', char: char, editable: true })\n break\n case '*':\n tokens.push({ type: 'any', char: '*', editable: true })\n break\n default:\n tokens.push({ type: 'literal', char: char, editable: false })\n break\n }\n }\n\n return tokens\n}\n\n/**\n * Formatea un valor según los tokens de máscara\n */\nexport function formatValue(value: string, tokens: MaskToken[]): string {\n let result = ''\n let valueIndex = 0\n\n for (const token of tokens) {\n if (!token.editable) {\n result += token.char\n continue\n }\n\n if (valueIndex >= value.length) {\n break\n }\n\n const char = value[valueIndex]\n\n // Validar según el tipo de token\n if (token.type === 'digit' && !/\\d/.test(char)) {\n continue // Saltar caracteres no numéricos\n } else if (token.type === 'letter' && !/[a-zA-Z]/.test(char)) {\n continue // Saltar caracteres no alfabéticos\n } else if (token.type === 'any') {\n // Aceptar cualquier carácter\n } else if (token.type !== 'any' && token.type !== 'digit' && token.type !== 'letter') {\n continue\n }\n\n result += char\n valueIndex++\n }\n\n return result\n}\n\n/**\n * Remueve el formato de un valor (obtiene solo los caracteres editables)\n */\nexport function unformatValue(value: string, tokens: MaskToken[]): string {\n if (!value) return ''\n\n let result = ''\n let tokenIndex = 0\n\n for (let i = 0; i < value.length && tokenIndex < tokens.length; i++) {\n const char = value[i]\n const token = tokens[tokenIndex]\n\n if (token.editable) {\n // Verificar si el carácter coincide con el tipo de token\n if (token.type === 'digit' && /\\d/.test(char)) {\n result += char\n tokenIndex++\n } else if (token.type === 'letter' && /[a-zA-Z]/.test(char)) {\n result += char\n tokenIndex++\n } else if (token.type === 'any') {\n result += char\n tokenIndex++\n } else {\n // Carácter no válido para este token, avanzar al siguiente token editable\n tokenIndex++\n i-- // Revisar el mismo carácter con el siguiente token\n }\n } else {\n // Token literal, verificar si coincide\n if (char === token.char) {\n tokenIndex++\n } else {\n // El carácter no coincide con el literal esperado, puede ser un carácter editable extra\n // Intentar extraerlo si es válido\n if (tokenIndex < tokens.length - 1) {\n const nextToken = tokens[tokenIndex + 1]\n if (nextToken && nextToken.editable) {\n if (nextToken.type === 'digit' && /\\d/.test(char)) {\n result += char\n tokenIndex += 2\n } else if (nextToken.type === 'letter' && /[a-zA-Z]/.test(char)) {\n result += char\n tokenIndex += 2\n } else if (nextToken.type === 'any') {\n result += char\n tokenIndex += 2\n } else {\n tokenIndex++\n }\n } else {\n tokenIndex++\n }\n } else {\n break\n }\n }\n }\n }\n\n return result\n}\n\n/**\n * Obtiene la siguiente posición editable\n */\nexport function getNextEditablePosition(\n position: number,\n tokens: MaskToken[],\n direction: 'forward' | 'backward' = 'forward'\n): number {\n if (direction === 'forward') {\n for (let i = position + 1; i < tokens.length; i++) {\n if (tokens[i].editable) {\n return i\n }\n }\n return tokens.length\n } else {\n for (let i = position - 1; i >= 0; i--) {\n if (tokens[i].editable) {\n return i\n }\n }\n return 0\n }\n}\n\n/**\n * Obtiene el placeholder completo para una máscara\n */\nexport function getMaskPlaceholder(tokens: MaskToken[], placeholder: string = '_'): string {\n return tokens\n .map((token) => (token.editable ? placeholder : token.char))\n .join('')\n}\n\n/**\n * Calcula la posición del cursor después de aplicar máscara\n */\nexport function calculateCursorPosition(\n oldValue: string,\n newValue: string,\n oldCursorPosition: number,\n tokens: MaskToken[]\n): number {\n // Contar caracteres editables antes de la posición anterior\n let editableBeforeOld = 0\n for (let i = 0; i < Math.min(oldCursorPosition, oldValue.length); i++) {\n const tokenIndex = i\n if (tokenIndex < tokens.length && tokens[tokenIndex].editable) {\n editableBeforeOld++\n }\n }\n\n // Encontrar la posición correspondiente en el nuevo valor\n let editableCount = 0\n for (let i = 0; i < newValue.length && i < tokens.length; i++) {\n if (tokens[i].editable) {\n editableCount++\n if (editableCount > editableBeforeOld) {\n return i + 1\n }\n }\n }\n\n // Si no encontramos, buscar la siguiente posición editable\n return getNextEditablePosition(\n Math.min(oldCursorPosition, newValue.length - 1),\n tokens,\n 'forward'\n )\n}\n","import type { MaskConfig, CustomMask } from '../types'\nimport { getPredefinedMask } from '../utils/masks'\nimport {\n parseMaskPattern,\n formatValue,\n unformatValue,\n getNextEditablePosition,\n getMaskPlaceholder,\n calculateCursorPosition,\n type MaskToken,\n} from '../utils/mask-helpers'\n\n/**\n * Motor de máscaras\n */\nexport class MaskEngine {\n private tokenCache: Map<string, MaskToken[]> = new Map()\n\n /**\n * Obtiene la configuración de máscara personalizada\n */\n private getCustomMask(mask: MaskConfig): CustomMask | null {\n if (mask.custom) {\n return mask.custom\n }\n if (mask.type) {\n return getPredefinedMask(mask.type)\n }\n return null\n }\n\n /**\n * Obtiene los tokens parseados de una máscara (con cache)\n */\n private getTokens(mask: MaskConfig): MaskToken[] | null {\n const customMask = this.getCustomMask(mask)\n if (!customMask) {\n return null\n }\n\n const cacheKey = customMask.pattern\n if (this.tokenCache.has(cacheKey)) {\n return this.tokenCache.get(cacheKey)!\n }\n\n const tokens = parseMaskPattern(customMask.pattern)\n this.tokenCache.set(cacheKey, tokens)\n return tokens\n }\n\n /**\n * Aplica máscara a un valor\n */\n applyMask(value: string, mask: MaskConfig): string {\n const tokens = this.getTokens(mask)\n if (!tokens) {\n return value\n }\n\n const customMask = this.getCustomMask(mask)!\n // Extraer solo caracteres editables del valor\n const editableTokens = tokens.filter(t => t.editable)\n const acceptedTypes = new Set(editableTokens.map(t => t.type))\n let unformatted = ''\n for (const char of value) {\n if (acceptedTypes.has('any')) {\n unformatted += char\n } else if (acceptedTypes.has('digit') && /\\d/.test(char)) {\n unformatted += char\n } else if (acceptedTypes.has('letter') && /[a-zA-Z]/.test(char)) {\n unformatted += char\n }\n }\n let formatted = formatValue(unformatted, tokens)\n\n // Aplicar transformación si existe\n if (customMask.transform) {\n formatted = customMask.transform(formatted)\n // Re-formatear después de la transformación\n formatted = formatValue(formatted, tokens)\n }\n\n return formatted\n }\n\n /**\n * Remueve máscara de un valor (obtiene valor raw)\n */\n removeMask(value: string, mask: MaskConfig): string {\n const tokens = this.getTokens(mask)\n if (!tokens) {\n return value\n }\n\n return unformatValue(value, tokens)\n }\n\n /**\n * Obtiene el placeholder para una máscara\n */\n getMaskPlaceholder(mask: MaskConfig): string {\n const tokens = this.getTokens(mask)\n if (!tokens) {\n return ''\n }\n\n const customMask = this.getCustomMask(mask)!\n return getMaskPlaceholder(tokens, customMask.placeholder || '_')\n }\n\n /**\n * Valida si un carácter puede ser insertado en una posición\n */\n canInsertChar(char: string, position: number, mask: MaskConfig): boolean {\n const tokens = this.getTokens(mask)\n if (!tokens || position >= tokens.length) {\n return false\n }\n\n const token = tokens[position]\n if (!token.editable) {\n return false\n }\n\n switch (token.type) {\n case 'digit':\n return /\\d/.test(char)\n case 'letter':\n return /[a-zA-Z]/.test(char)\n case 'any':\n return true\n default:\n return false\n }\n }\n\n /**\n * Procesa entrada del usuario aplicando máscara en tiempo real\n */\n processInput(\n input: string,\n previousValue: string,\n mask: MaskConfig,\n cursorPosition: number\n ): { value: string; cursorPosition: number } {\n const tokens = this.getTokens(mask)\n if (!tokens) {\n return { value: input, cursorPosition: input.length }\n }\n\n // Obtener el valor sin formato del input actual\n const unformattedInput = unformatValue(input, tokens)\n\n // Aplicar máscara al nuevo valor\n let formatted = formatValue(unformattedInput, tokens)\n\n // Aplicar transformación si existe\n const customMask = this.getCustomMask(mask)!\n if (customMask.transform) {\n formatted = customMask.transform(formatted)\n formatted = formatValue(formatted, tokens)\n }\n\n // Calcular nueva posición del cursor\n const newCursorPosition = calculateCursorPosition(\n previousValue,\n formatted,\n cursorPosition,\n tokens\n )\n\n return {\n value: formatted,\n cursorPosition: Math.min(newCursorPosition, formatted.length),\n }\n }\n\n /**\n * Procesa entrada con manejo de backspace/delete\n */\n processKeyInput(\n key: string,\n currentValue: string,\n cursorPosition: number,\n mask: MaskConfig,\n isBackspace: boolean = false\n ): { value: string; cursorPosition: number } {\n const tokens = this.getTokens(mask)\n if (!tokens) {\n return { value: currentValue, cursorPosition: cursorPosition }\n }\n\n if (isBackspace) {\n // Manejar backspace\n if (cursorPosition === 0) {\n return { value: currentValue, cursorPosition: 0 }\n }\n\n // Encontrar la posición editable anterior\n const prevEditable = getNextEditablePosition(cursorPosition - 1, tokens, 'backward')\n \n // Remover el carácter en esa posición\n const before = currentValue.substring(0, prevEditable)\n const after = currentValue.substring(cursorPosition)\n const newValue = before + after\n\n // Re-aplicar máscara\n const unformatted = this.removeMask(newValue, mask)\n const formatted = this.applyMask(unformatted, mask)\n\n // Calcular nueva posición\n const newPos = Math.max(0, prevEditable - 1)\n const nextEditable = getNextEditablePosition(newPos, tokens, 'forward')\n\n return {\n value: formatted,\n cursorPosition: nextEditable,\n }\n }\n\n // Manejar entrada normal\n if (key.length === 1 && this.canInsertChar(key, cursorPosition, mask)) {\n // Insertar carácter en la posición actual\n const before = currentValue.substring(0, cursorPosition)\n const after = currentValue.substring(cursorPosition)\n const newValue = before + key + after\n\n return this.processInput(newValue, currentValue, mask, cursorPosition)\n }\n\n return { value: currentValue, cursorPosition: cursorPosition }\n }\n}\n","import { BaseInput } from './base-input'\nimport type { Field } from '../../types'\nimport { MaskEngine } from '../../core/mask-engine'\n\nexport class TextInput extends BaseInput {\n private maskEngine: MaskEngine | null = null\n private previousValue: string = ''\n\n constructor(\n field: Field,\n value: any,\n error: string | undefined,\n onChange: (value: any) => void,\n onBlur: () => void\n ) {\n super(field, value, error, onChange, onBlur)\n \n if (field.mask) {\n this.maskEngine = new MaskEngine()\n }\n }\n\n render(): HTMLElement {\n const input = document.createElement('input')\n input.type = this.field.type === 'email' ? 'email' : this.field.type === 'password' ? 'password' : 'text'\n \n // Aplicar máscara si existe\n let displayValue = this.value ?? ''\n if (this.maskEngine && this.field.mask) {\n if (displayValue) {\n displayValue = this.maskEngine.applyMask(String(displayValue), this.field.mask)\n }\n this.previousValue = displayValue\n }\n \n input.value = displayValue\n\n this.applyCommonProps(input)\n\n // Aplicar placeholder del field si está definido (después de applyCommonProps)\n if (this.field.placeholder) {\n input.placeholder = this.field.placeholder\n } else if (this.maskEngine && this.field.mask) {\n // Aplicar placeholder de máscara si no hay placeholder del field\n const maskPlaceholder = this.maskEngine.getMaskPlaceholder(this.field.mask)\n if (maskPlaceholder) {\n input.placeholder = maskPlaceholder\n }\n }\n\n // Manejar eventos de entrada con máscara\n if (this.maskEngine && this.field.mask) {\n input.addEventListener('input', (e) => {\n const target = e.target as HTMLInputElement\n const cursorPosition = target.selectionStart || 0\n const inputValue = target.value\n\n const result = this.maskEngine!.processInput(\n inputValue,\n this.previousValue,\n this.field.mask!,\n cursorPosition\n )\n\n // Actualizar valor y cursor\n target.value = result.value\n this.previousValue = result.value\n\n // Restaurar posición del cursor\n setTimeout(() => {\n target.setSelectionRange(result.cursorPosition, result.cursorPosition)\n }, 0)\n\n // Emitir valor según configuración (con o sin formato)\n const valueToEmit = this.field.mask!.keepFormat\n ? result.value\n : this.maskEngine!.removeMask(result.value, this.field.mask!)\n\n this.onChange(valueToEmit)\n })\n\n input.addEventListener('keydown', (e) => {\n const target = e.target as HTMLInputElement\n const cursorPosition = target.selectionStart || 0\n\n if (e.key === 'Backspace' || e.key === 'Delete') {\n e.preventDefault()\n \n const isBackspace = e.key === 'Backspace'\n const result = this.maskEngine!.processKeyInput(\n '',\n target.value,\n cursorPosition,\n this.field.mask!,\n isBackspace\n )\n\n target.value = result.value\n this.previousValue = result.value\n\n setTimeout(() => {\n target.setSelectionRange(result.cursorPosition, result.cursorPosition)\n }, 0)\n\n const valueToEmit = this.field.mask!.keepFormat\n ? result.value\n : this.maskEngine!.removeMask(result.value, this.field.mask!)\n\n this.onChange(valueToEmit)\n }\n })\n\n input.addEventListener('paste', (e) => {\n e.preventDefault()\n const pastedText = (e.clipboardData || (window as any).clipboardData).getData('text')\n \n if (pastedText) {\n const target = e.target as HTMLInputElement\n const cursorPosition = target.selectionStart || 0\n \n // Insertar texto pegado\n const before = target.value.substring(0, cursorPosition)\n const after = target.value.substring(cursorPosition)\n const newValue = before + pastedText + after\n\n const result = this.maskEngine!.processInput(\n newValue,\n this.previousValue,\n this.field.mask!,\n cursorPosition\n )\n\n target.value = result.value\n this.previousValue = result.value\n\n setTimeout(() => {\n target.setSelectionRange(result.cursorPosition, result.cursorPosition)\n }, 0)\n\n const valueToEmit = this.field.mask!.keepFormat\n ? result.value\n : this.maskEngine!.removeMask(result.value, this.field.mask!)\n\n this.onChange(valueToEmit)\n }\n })\n } else {\n // Sin máscara, comportamiento normal\n input.addEventListener('input', (e) => {\n const target = e.target as HTMLInputElement\n this.onChange(target.value)\n })\n }\n\n input.addEventListener('blur', () => {\n this.onBlur()\n })\n\n return this.createFieldContainer(input)\n }\n}\n","import { BaseInput } from './base-input'\nimport type { NumberField } from '../../types'\nimport { MaskEngine } from '../../core/mask-engine'\n\nexport class NumberInput extends BaseInput {\n private maskEngine: MaskEngine | null = null\n private previousValue: string = ''\n\n constructor(\n field: NumberField,\n value: any,\n error: string | undefined,\n onChange: (value: any) => void,\n onBlur: () => void\n ) {\n super(field, value, error, onChange, onBlur)\n \n if (field.mask) {\n this.maskEngine = new MaskEngine()\n }\n }\n\n render(): HTMLElement {\n const input = document.createElement('input')\n \n // Si tiene máscara, usar tipo text para mejor control\n if (this.maskEngine && this.field.mask) {\n input.type = 'text'\n \n // Aplicar máscara al valor inicial\n let displayValue = this.value ?? ''\n if (displayValue !== null && displayValue !== '') {\n if (this.field.mask.type === 'currency') {\n displayValue = this.maskEngine.applyMask(String(displayValue), this.field.mask)\n } else if (this.field.mask.type === 'percentage') {\n displayValue = this.maskEngine.applyMask(String(displayValue), this.field.mask)\n }\n }\n this.previousValue = displayValue\n input.value = displayValue\n } else {\n input.type = 'number'\n input.value = this.value ?? ''\n }\n\n const numberField = this.field as NumberField\n if (!this.maskEngine && input.type === 'number') {\n if (numberField.min !== undefined) {\n input.min = String(numberField.min)\n }\n if (numberField.max !== undefined) {\n input.max = String(numberField.max)\n }\n if (numberField.step !== undefined) {\n input.step = String(numberField.step)\n }\n }\n\n this.applyCommonProps(input)\n\n // Aplicar placeholder del field si está definido\n if (this.field.placeholder) {\n input.placeholder = this.field.placeholder\n } else if (this.maskEngine && this.field.mask) {\n // Aplicar placeholder de máscara si no hay placeholder del field\n const maskPlaceholder = this.maskEngine.getMaskPlaceholder(this.field.mask)\n if (maskPlaceholder) {\n input.placeholder = maskPlaceholder\n }\n }\n\n // Manejar eventos con máscara\n if (this.maskEngine && this.field.mask) {\n input.addEventListener('input', (e) => {\n const target = e.target as HTMLInputElement\n const cursorPosition = target.selectionStart || 0\n const inputValue = target.value\n\n const result = this.maskEngine!.processInput(\n inputValue,\n this.previousValue,\n this.field.mask!,\n cursorPosition\n )\n\n target.value = result.value\n this.previousValue = result.value\n\n setTimeout(() => {\n target.setSelectionRange(result.cursorPosition, result.cursorPosition)\n }, 0)\n\n // Convertir a número según el tipo de máscara\n let numValue: number | null = null\n if (this.field.mask!.type === 'currency') {\n const unformatted = this.maskEngine!.removeMask(result.value, this.field.mask!)\n numValue = unformatted ? parseFloat(unformatted.replace(/[^\\d.]/g, '')) : null\n } else if (this.field.mask!.type === 'percentage') {\n const unformatted = this.maskEngine!.removeMask(result.value, this.field.mask!)\n numValue = unformatted ? parseFloat(unformatted) : null\n }\n\n this.onChange(numValue)\n })\n\n input.addEventListener('keydown', (e) => {\n const target = e.target as HTMLInputElement\n const cursorPosition = target.selectionStart || 0\n\n if (e.key === 'Backspace' || e.key === 'Delete') {\n e.preventDefault()\n \n const isBackspace = e.key === 'Backspace'\n const result = this.maskEngine!.processKeyInput(\n '',\n target.value,\n cursorPosition,\n this.field.mask!,\n isBackspace\n )\n\n target.value = result.value\n this.previousValue = result.value\n\n setTimeout(() => {\n target.setSelectionRange(result.cursorPosition, result.cursorPosition)\n }, 0)\n\n let numValue: number | null = null\n if (this.field.mask!.type === 'currency') {\n const unformatted = this.maskEngine!.removeMask(result.value, this.field.mask!)\n numValue = unformatted ? parseFloat(unformatted.replace(/[^\\d.]/g, '')) : null\n } else if (this.field.mask!.type === 'percentage') {\n const unformatted = this.maskEngine!.removeMask(result.value, this.field.mask!)\n numValue = unformatted ? parseFloat(unformatted) : null\n }\n\n this.onChange(numValue)\n }\n })\n\n input.addEventListener('paste', (e) => {\n e.preventDefault()\n const pastedText = (e.clipboardData || (window as any).clipboardData).getData('text')\n \n if (pastedText) {\n const target = e.target as HTMLInputElement\n const cursorPosition = target.selectionStart || 0\n \n const before = target.value.substring(0, cursorPosition)\n const after = target.value.substring(cursorPosition)\n const newValue = before + pastedText + after\n\n const result = this.maskEngine!.processInput(\n newValue,\n this.previousValue,\n this.field.mask!,\n cursorPosition\n )\n\n target.value = result.value\n this.previousValue = result.value\n\n setTimeout(() => {\n target.setSelectionRange(result.cursorPosition, result.cursorPosition)\n }, 0)\n\n let numValue: number | null = null\n if (this.field.mask!.type === 'currency') {\n const unformatted = this.maskEngine!.removeMask(result.value, this.field.mask!)\n numValue = unformatted ? parseFloat(unformatted.replace(/[^\\d.]/g, '')) : null\n } else if (this.field.mask!.type === 'percentage') {\n const unformatted = this.maskEngine!.removeMask(result.value, this.field.mask!)\n numValue = unformatted ? parseFloat(unformatted) : null\n }\n\n this.onChange(numValue)\n }\n })\n } else {\n // Sin máscara, comportamiento normal\n input.addEventListener('input', (e) => {\n const target = e.target as HTMLInputElement\n const numValue = target.value === '' ? null : Number(target.value)\n this.onChange(numValue)\n })\n }\n\n input.addEventListener('blur', () => {\n this.onBlur()\n })\n\n return this.createFieldContainer(input)\n }\n}\n","import { BaseInput } from './base-input'\nimport type { TextareaField } from '../../types'\n\nexport class TextareaInput extends BaseInput {\n render(): HTMLElement {\n const textarea = document.createElement('textarea')\n textarea.value = this.value ?? ''\n textarea.placeholder = this.field.placeholder || ''\n\n const textareaField = this.field as TextareaField\n if (textareaField.rows) {\n textarea.rows = textareaField.rows\n }\n if (textareaField.cols) {\n textarea.cols = textareaField.cols\n }\n\n this.applyCommonProps(textarea)\n\n textarea.addEventListener('input', (e) => {\n const target = e.target as HTMLTextAreaElement\n this.onChange(target.value)\n })\n\n textarea.addEventListener('blur', () => {\n this.onBlur()\n })\n\n return this.createFieldContainer(textarea)\n }\n}\n","import { BaseInput } from './base-input'\nimport type { SelectField } from '../../types'\n\nexport class SelectInput extends BaseInput {\n render(): HTMLElement {\n const select = document.createElement('select')\n const selectField = this.field as SelectField\n\n if (selectField.multiple) {\n select.multiple = true\n }\n\n // Opción placeholder cuando no hay selección (solo para select simple)\n if (!selectField.multiple) {\n const placeholderOption = document.createElement('option')\n placeholderOption.value = ''\n placeholderOption.textContent = selectField.placeholder || 'Selecciona una opción'\n placeholderOption.setAttribute('data-placeholder', '')\n placeholderOption.disabled = true\n select.appendChild(placeholderOption)\n }\n\n // Crear opciones\n for (const option of selectField.options) {\n const optionEl = document.createElement('option')\n if (typeof option === 'string') {\n optionEl.value = option\n optionEl.textContent = option\n } else {\n optionEl.value = String(option.value)\n optionEl.textContent = option.label\n }\n select.appendChild(optionEl)\n }\n\n // Establecer valor\n if (selectField.multiple && Array.isArray(this.value)) {\n for (const option of select.options) {\n option.selected = this.value.includes(option.value)\n }\n } else {\n select.value = this.value ?? ''\n }\n\n this.applyCommonProps(select)\n\n const updatePlaceholderClass = () => {\n const isEmpty = !select.value\n if (isEmpty) {\n select.classList.add('easy-form-select-placeholder')\n } else {\n select.classList.remove('easy-form-select-placeholder')\n }\n }\n updatePlaceholderClass()\n\n select.addEventListener('change', (e) => {\n const target = e.target as HTMLSelectElement\n updatePlaceholderClass()\n if (selectField.multiple) {\n const selectedValues = Array.from(target.selectedOptions).map(\n (opt) => opt.value\n )\n this.onChange(selectedValues)\n } else {\n this.onChange(target.value || null)\n }\n })\n\n select.addEventListener('blur', () => {\n this.onBlur()\n })\n\n return this.createFieldContainer(select)\n }\n}\n","import { BaseInput } from './base-input'\n\nexport class CheckboxInput extends BaseInput {\n render(): HTMLElement {\n const checkbox = document.createElement('input')\n checkbox.type = 'checkbox'\n checkbox.checked = Boolean(this.value)\n\n this.applyCommonProps(checkbox)\n\n checkbox.addEventListener('change', (e) => {\n const target = e.target as HTMLInputElement\n this.onChange(target.checked)\n })\n\n checkbox.addEventListener('blur', () => {\n this.onBlur()\n })\n\n const container = document.createElement('div')\n container.className = 'easy-form-field'\n\n // Label (checkbox primero, luego label)\n const label = document.createElement('label')\n label.className = 'easy-form-label-checkbox'\n label.setAttribute('for', this.getFieldId())\n label.appendChild(checkbox)\n if (this.field.label) {\n const labelText = document.createTextNode(this.field.label)\n label.appendChild(labelText)\n }\n container.appendChild(label)\n\n // Description\n if (this.field.description) {\n const description = document.createElement('p')\n description.className = 'easy-form-description'\n description.textContent = this.field.description\n container.appendChild(description)\n }\n\n // Error\n if (this.error) {\n const errorEl = document.createElement('p')\n errorEl.className = 'easy-form-error'\n errorEl.textContent = this.error\n container.appendChild(errorEl)\n }\n\n return container\n }\n}\n","import { BaseInput } from './base-input'\nimport type { RadioField } from '../../types'\n\nexport class RadioInput extends BaseInput {\n render(): HTMLElement {\n const container = document.createElement('div')\n container.className = 'easy-form-field'\n\n // Label\n if (this.field.label) {\n const label = document.createElement('label')\n label.className = 'easy-form-label'\n label.textContent = this.field.label\n if (this.field.validations?.some((v) => v.type === 'required')) {\n const required = document.createElement('span')\n required.className = 'easy-form-required'\n required.textContent = ' *'\n label.appendChild(required)\n }\n container.appendChild(label)\n }\n\n // Radio buttons\n const radioGroup = document.createElement('div')\n radioGroup.className = 'easy-form-radio-group'\n\n const radioField = this.field as RadioField\n for (const option of radioField.options) {\n const optionValue = typeof option === 'string' ? option : option.value\n const optionLabel = typeof option === 'string' ? option : option.label\n\n const radioContainer = document.createElement('div')\n radioContainer.className = 'easy-form-radio-option'\n\n const radio = document.createElement('input')\n radio.type = 'radio'\n radio.name = this.field.name\n radio.id = `${this.getFieldId()}-${optionValue}`\n radio.value = String(optionValue)\n radio.checked = String(this.value) === String(optionValue)\n\n if (this.field.disabled) {\n radio.disabled = true\n }\n\n const label = document.createElement('label')\n label.setAttribute('for', radio.id)\n label.textContent = optionLabel\n label.className = 'easy-form-radio-label'\n\n radio.addEventListener('change', () => {\n this.onChange(optionValue)\n })\n\n radio.addEventListener('blur', () => {\n this.onBlur()\n })\n\n radioContainer.appendChild(radio)\n radioContainer.appendChild(label)\n radioGroup.appendChild(radioContainer)\n }\n\n container.appendChild(radioGroup)\n\n // Description\n if (this.field.description) {\n const description = document.createElement('p')\n description.className = 'easy-form-description'\n description.textContent = this.field.description\n container.appendChild(description)\n }\n\n // Error\n if (this.error) {\n const errorEl = document.createElement('p')\n errorEl.className = 'easy-form-error'\n errorEl.textContent = this.error\n container.appendChild(errorEl)\n }\n\n return container\n }\n}\n","import { BaseInput } from './base-input'\n\nexport class SwitchInput extends BaseInput {\n render(): HTMLElement {\n const switchEl = document.createElement('input')\n switchEl.type = 'checkbox'\n switchEl.className = 'easy-form-switch'\n switchEl.checked = Boolean(this.value)\n\n this.applyCommonProps(switchEl)\n\n switchEl.addEventListener('change', (e) => {\n const target = e.target as HTMLInputElement\n this.onChange(target.checked)\n })\n\n switchEl.addEventListener('blur', () => {\n this.onBlur()\n })\n\n const container = document.createElement('div')\n container.className = 'easy-form-field'\n\n // Label con switch\n const label = document.createElement('label')\n label.className = 'easy-form-label-switch'\n label.setAttribute('for', this.getFieldId())\n if (this.field.label) {\n const labelText = document.createTextNode(this.field.label)\n label.appendChild(labelText)\n }\n label.appendChild(switchEl)\n container.appendChild(label)\n\n // Description\n if (this.field.description) {\n const description = document.createElement('p')\n description.className = 'easy-form-description'\n description.textContent = this.field.description\n container.appendChild(description)\n }\n\n // Error\n if (this.error) {\n const errorEl = document.createElement('p')\n errorEl.className = 'easy-form-error'\n errorEl.textContent = this.error\n container.appendChild(errorEl)\n }\n\n return container\n }\n}\n","import { BaseInput } from './base-input'\nimport type { DateField } from '../../types'\n\nexport class DateInput extends BaseInput {\n render(): HTMLElement {\n const input = document.createElement('input')\n input.type = 'date'\n \n const dateField = this.field as DateField\n if (dateField.min) {\n input.min = dateField.min\n }\n if (dateField.max) {\n input.max = dateField.max\n }\n\n if (this.value) {\n const date = this.value instanceof Date \n ? this.value.toISOString().split('T')[0]\n : String(this.value)\n input.value = date\n }\n\n this.applyCommonProps(input)\n\n input.addEventListener('change', (e) => {\n const target = e.target as HTMLInputElement\n this.onChange(target.value || null)\n })\n\n input.addEventListener('blur', () => {\n this.onBlur()\n })\n\n return this.createFieldContainer(input)\n }\n}\n","import { BaseInput } from './base-input'\nimport type { FileField } from '../../types'\n\nexport class FileInput extends BaseInput {\n render(): HTMLElement {\n const input = document.createElement('input')\n input.type = 'file'\n \n const fileField = this.field as FileField\n if (fileField.accept) {\n input.accept = fileField.accept\n }\n if (fileField.multiple) {\n input.multiple = true\n }\n\n this.applyCommonProps(input)\n\n input.addEventListener('change', (e) => {\n const target = e.target as HTMLInputElement\n if (target.files) {\n if (fileField.multiple) {\n this.onChange(Array.from(target.files))\n } else {\n this.onChange(target.files[0] || null)\n }\n }\n })\n\n input.addEventListener('blur', () => {\n this.onBlur()\n })\n\n return this.createFieldContainer(input)\n }\n}\n","import { BaseInput } from './base-input'\nimport type { QuantityField } from '../../types'\n\nexport class QuantityInput extends BaseInput {\n render(): HTMLElement {\n const container = document.createElement('div')\n container.className = 'easy-form-quantity-container'\n\n const quantityField = this.field as QuantityField\n const min = quantityField.min ?? 0\n const max = quantityField.max ?? undefined\n const step = quantityField.step ?? 1\n const currentValue = this.value ?? min\n\n // Contenedor del input con botones\n const inputWrapper = document.createElement('div')\n inputWrapper.className = 'easy-form-quantity-wrapper'\n\n // Botón de decremento\n const decrementBtn = document.createElement('button')\n decrementBtn.type = 'button'\n decrementBtn.className = 'easy-form-quantity-btn easy-form-quantity-decrement'\n decrementBtn.textContent = '−'\n decrementBtn.setAttribute('aria-label', 'Decrementar')\n \n if (currentValue <= min) {\n decrementBtn.disabled = true\n decrementBtn.classList.add('disabled')\n }\n\n // Input numérico\n const input = document.createElement('input')\n input.type = 'number'\n input.value = String(currentValue)\n input.min = String(min)\n if (max !== undefined) {\n input.max = String(max)\n }\n input.step = String(step)\n input.className = 'easy-form-quantity-input'\n this.applyCommonProps(input)\n\n // Botón de incremento\n const incrementBtn = document.createElement('button')\n incrementBtn.type = 'button'\n incrementBtn.className = 'easy-form-quantity-btn easy-form-quantity-increment'\n incrementBtn.textContent = '+'\n incrementBtn.setAttribute('aria-label', 'Incrementar')\n \n if (max !== undefined && currentValue >= max) {\n incrementBtn.disabled = true\n incrementBtn.classList.add('disabled')\n }\n\n // Event listeners para botones\n decrementBtn.addEventListener('click', () => {\n const newValue = Math.max(min, Number(input.value) - step)\n input.value = String(newValue)\n this.onChange(newValue)\n updateButtons()\n })\n\n incrementBtn.addEventListener('click', () => {\n const newValue = max !== undefined \n ? Math.min(max, Number(input.value) + step)\n : Number(input.value) + step\n input.value = String(newValue)\n this.onChange(newValue)\n updateButtons()\n })\n\n // Event listener para input directo\n input.addEventListener('input', (e) => {\n const target = e.target as HTMLInputElement\n let numValue = Number(target.value)\n \n if (isNaN(numValue)) {\n numValue = min\n }\n \n if (numValue < min) {\n numValue = min\n }\n \n if (max !== undefined && numValue > max) {\n numValue = max\n }\n \n target.value = String(numValue)\n this.onChange(numValue)\n updateButtons()\n })\n\n input.addEventListener('blur', () => {\n this.onBlur()\n })\n\n // Función para actualizar estado de botones\n const updateButtons = () => {\n const value = Number(input.value)\n decrementBtn.disabled = value <= min\n decrementBtn.classList.toggle('disabled', value <= min)\n \n if (max !== undefined) {\n incrementBtn.disabled = value >= max\n incrementBtn.classList.toggle('disabled', value >= max)\n } else {\n incrementBtn.disabled = false\n incrementBtn.classList.remove('disabled')\n }\n }\n\n // Agregar elementos al wrapper\n inputWrapper.appendChild(decrementBtn)\n inputWrapper.appendChild(input)\n inputWrapper.appendChild(incrementBtn)\n\n container.appendChild(inputWrapper)\n\n return this.createFieldContainer(container)\n }\n}\n","import { BaseInput } from './base-input'\nimport type { AccordionSelectField } from '../../types'\n\nexport class AccordionSelectInput extends BaseInput {\n private openAccordion: string | null = null\n\n render(): HTMLElement {\n const container = document.createElement('div')\n container.className = 'easy-form-accordion-select-container'\n\n const accordionField = this.field as AccordionSelectField\n const selectedValue = this.value ?? null\n\n // Crear acordeón\n accordionField.options.forEach((option, index) => {\n const optionValue = typeof option === 'string' ? option : option.value\n const optionLabel = typeof option === 'string' ? option : option.label\n const optionDescription = typeof option === 'object' && 'description' in option && option.description\n ? option.description\n : undefined\n\n const accordionItem = document.createElement('div')\n accordionItem.className = 'easy-form-accordion-item'\n accordionItem.setAttribute('data-value', String(optionValue))\n\n if (selectedValue === optionValue || (Array.isArray(selectedValue) && selectedValue.includes(optionValue))) {\n accordionItem.classList.add('selected')\n if (!accordionField.multiple) {\n this.openAccordion = String(optionValue)\n }\n }\n\n // Header del acordeón\n const header = document.createElement('div')\n header.className = 'easy-form-accordion-header'\n header.setAttribute('role', 'button')\n header.setAttribute('tabindex', '0')\n header.setAttribute('aria-expanded', 'false')\n\n const headerContent = document.createElement('div')\n headerContent.className = 'easy-form-accordion-header-content'\n\n // Radio/Checkbox visual\n const indicator = document.createElement('div')\n indicator.className = 'easy-form-accordion-indicator'\n if (accordionField.multiple) {\n indicator.classList.add('checkbox')\n if (Array.isArray(selectedValue) && selectedValue.includes(optionValue)) {\n indicator.classList.add('checked')\n }\n } else {\n indicator.classList.add('radio')\n if (selectedValue === optionValue) {\n indicator.classList.add('checked')\n }\n }\n\n const label = document.createElement('span')\n label.className = 'easy-form-accordion-label'\n label.textContent = optionLabel\n\n const arrow = document.createElement('span')\n arrow.className = 'easy-form-accordion-arrow'\n arrow.textContent = '▼'\n\n headerContent.appendChild(indicator)\n headerContent.appendChild(label)\n header.appendChild(headerContent)\n header.appendChild(arrow)\n\n // Contenido del acordeón\n const content = document.createElement('div')\n content.className = 'easy-form-accordion-content'\n \n if (optionDescription) {\n const description = document.createElement('p')\n description.className = 'easy-form-accordion-description'\n description.textContent = optionDescription\n content.appendChild(description)\n }\n\n // Si hay campos anidados o contenido adicional\n if (typeof option === 'object' && 'content' in option && option.content) {\n const customContent = document.createElement('div')\n customContent.className = 'easy-form-accordion-custom-content'\n if (typeof option.content === 'string') {\n customContent.innerHTML = option.content\n } else if (option.content instanceof HTMLElement) {\n customContent.appendChild(option.content)\n }\n content.appendChild(customContent)\n }\n\n accordionItem.appendChild(header)\n accordionItem.appendChild(content)\n\n // Toggle acordeón\n const toggleAccordion = () => {\n const isOpen = accordionItem.classList.contains('open')\n \n if (!accordionField.multiple) {\n // Cerrar otros acordeones\n container.querySelectorAll('.easy-form-accordion-item').forEach((item) => {\n if (item !== accordionItem) {\n item.classList.remove('open')\n const otherHeader = item.querySelector('.easy-form-accordion-header')\n const otherContent = item.querySelector('.easy-form-accordion-content')\n const otherArrow = item.querySelector('.easy-form-accordion-arrow')\n if (otherHeader) otherHeader.setAttribute('aria-expanded', 'false')\n if (otherContent) otherContent.style.maxHeight = null\n if (otherArrow) otherArrow.style.transform = 'rotate(0deg)'\n }\n })\n }\n\n if (isOpen) {\n accordionItem.classList.remove('open')\n header.setAttribute('aria-expanded', 'false')\n content.style.maxHeight = null\n arrow.style.transform = 'rotate(0deg)'\n this.openAccordion = null\n } else {\n accordionItem.classList.add('open')\n header.setAttribute('aria-expanded', 'true')\n content.style.maxHeight = content.scrollHeight + 'px'\n arrow.style.transform = 'rotate(180deg)'\n this.openAccordion = String(optionValue)\n }\n }\n\n // Seleccionar opción\n const selectOption = () => {\n if (accordionField.multiple) {\n const currentValues = Array.isArray(selectedValue) ? [...selectedValue] : []\n const index = currentValues.indexOf(optionValue)\n \n if (index > -1) {\n currentValues.splice(index, 1)\n accordionItem.classList.remove('selected')\n indicator.classList.remove('checked')\n } else {\n currentValues.push(optionValue)\n accordionItem.classList.add('selected')\n indicator.classList.add('checked')\n }\n \n this.onChange(currentValues.length > 0 ? currentValues : null)\n } else {\n // Deseleccionar otros\n container.querySelectorAll('.easy-form-accordion-item').forEach((item) => {\n item.classList.remove('selected')\n const itemIndicator = item.querySelector('.easy-form-accordion-indicator')\n if (itemIndicator) itemIndicator.classList.remove('checked')\n })\n \n accordionItem.classList.add('selected')\n indicator.classList.add('checked')\n this.onChange(optionValue)\n }\n }\n\n header.addEventListener('click', (e) => {\n e.stopPropagation()\n selectOption()\n toggleAccordion()\n })\n\n header.addEventListener('keydown', (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n selectOption()\n toggleAccordion()\n }\n })\n\n // Abrir acordeón si está seleccionado inicialmente\n if (selectedValue === optionValue || (Array.isArray(selectedValue) && selectedValue.includes(optionValue))) {\n if (!accordionField.multiple || accordionField.autoExpand) {\n setTimeout(() => {\n accordionItem.classList.add('open')\n header.setAttribute('aria-expanded', 'true')\n content.style.maxHeight = content.scrollHeight + 'px'\n arrow.style.transform = 'rotate(180deg)'\n }, 0)\n }\n }\n\n container.appendChild(accordionItem)\n })\n\n return this.createFieldContainer(container)\n }\n}\n","import { BaseInput } from './base-input'\nimport type { ImageGridSelectField } from '../../types'\n\nexport class ImageGridSelectInput extends BaseInput {\n render(): HTMLElement {\n const container = document.createElement('div')\n container.className = 'easy-form-image-grid-container'\n\n const imageGridField = this.field as ImageGridSelectField\n const selectedValue = this.value ?? null\n const columns = imageGridField.columns ?? 3\n const imageSize = imageGridField.imageSize ?? 'medium'\n\n // Establecer grid columns\n container.style.gridTemplateColumns = `repeat(${columns}, 1fr)`\n container.style.gap = imageGridField.gap ?? '1rem'\n\n // Crear items de imagen\n imageGridField.options.forEach((option) => {\n const optionValue = typeof option === 'string' ? option : option.value\n const optionLabel = typeof option === 'string' ? option : option.label\n const optionImage = typeof option === 'object' && 'image' in option && option.image\n ? option.image\n : undefined\n const optionDescription = typeof option === 'object' && 'description' in option && option.description\n ? option.description\n : undefined\n\n const gridItem = document.createElement('div')\n gridItem.className = `easy-form-image-grid-item easy-form-image-grid-${imageSize}`\n gridItem.setAttribute('data-value', String(optionValue))\n gridItem.setAttribute('role', 'button')\n gridItem.setAttribute('tabindex', '0')\n gridItem.setAttribute('aria-label', optionLabel)\n\n if (selectedValue === optionValue || (Array.isArray(selectedValue) && selectedValue.includes(optionValue))) {\n gridItem.classList.add('selected')\n }\n\n // Contenedor de imagen\n const imageContainer = document.createElement('div')\n imageContainer.className = 'easy-form-image-grid-image-container'\n\n if (optionImage) {\n const img = document.createElement('img')\n img.src = optionImage\n img.alt = optionLabel\n img.className = 'easy-form-image-grid-image'\n imageContainer.appendChild(img)\n } else {\n // Placeholder si no hay imagen\n const placeholder = document.createElement('div')\n placeholder.className = 'easy-form-image-grid-placeholder'\n placeholder.textContent = optionLabel.charAt(0).toUpperCase()\n imageContainer.appendChild(placeholder)\n }\n\n // Indicador de selección\n const indicator = document.createElement('div')\n indicator.className = 'easy-form-image-grid-indicator'\n if (imageGridField.multiple) {\n indicator.classList.add('checkbox')\n if (Array.isArray(selectedValue) && selectedValue.includes(optionValue)) {\n indicator.classList.add('checked')\n indicator.innerHTML = '✓'\n }\n } else {\n indicator.classList.add('radio')\n if (selectedValue === optionValue) {\n indicator.classList.add('checked')\n indicator.innerHTML = '●'\n }\n }\n imageContainer.appendChild(indicator)\n\n // Label\n const label = document.createElement('div')\n label.className = 'easy-form-image-grid-label'\n label.textContent = optionLabel\n\n // Description (opcional)\n if (optionDescription) {\n const description = document.createElement('div')\n description.className = 'easy-form-image-grid-description'\n description.textContent = optionDescription\n gridItem.appendChild(description)\n }\n\n gridItem.appendChild(imageContainer)\n gridItem.appendChild(label)\n\n // Seleccionar opción\n const selectOption = () => {\n if (imageGridField.multiple) {\n const currentValues = Array.isArray(selectedValue) ? [...selectedValue] : []\n const index = currentValues.indexOf(optionValue)\n \n if (index > -1) {\n currentValues.splice(index, 1)\n gridItem.classList.remove('selected')\n indicator.classList.remove('checked')\n indicator.innerHTML = ''\n } else {\n currentValues.push(optionValue)\n gridItem.classList.add('selected')\n indicator.classList.add('checked')\n indicator.innerHTML = '✓'\n }\n \n this.onChange(currentValues.length > 0 ? currentValues : null)\n } else {\n // Deseleccionar otros\n container.querySelectorAll('.easy-form-image-grid-item').forEach((item) => {\n item.classList.remove('selected')\n const itemIndicator = item.querySelector('.easy-form-image-grid-indicator')\n if (itemIndicator) {\n itemIndicator.classList.remove('checked')\n itemIndicator.innerHTML = ''\n }\n })\n \n gridItem.classList.add('selected')\n indicator.classList.add('checked')\n indicator.innerHTML = '●'\n this.onChange(optionValue)\n }\n }\n\n gridItem.addEventListener('click', selectOption)\n gridItem.addEventListener('keydown', (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n selectOption()\n }\n })\n\n gridItem.addEventListener('blur', () => {\n this.onBlur()\n })\n\n container.appendChild(gridItem)\n })\n\n return this.createFieldContainer(container)\n }\n}\n","import { BaseInput } from './base-input'\nimport type { OTPField } from '../../types'\n\nexport class OTPInput extends BaseInput {\n private inputs: HTMLInputElement[] = []\n\n render(): HTMLElement {\n const container = document.createElement('div')\n container.className = 'easy-form-otp-container'\n\n const otpField = this.field as OTPField\n const length = otpField.length ?? 6\n const value = this.value ?? ''\n const valueString = String(value).padStart(length, '').slice(0, length)\n\n // Crear inputs individuales\n for (let i = 0; i < length; i++) {\n const input = document.createElement('input')\n input.type = 'text'\n input.inputMode = 'numeric'\n input.maxLength = 1\n input.className = 'easy-form-otp-input'\n input.setAttribute('aria-label', `Código dígito ${i + 1}`)\n \n if (valueString[i]) {\n input.value = valueString[i]\n }\n\n this.applyCommonProps(input)\n input.id = `${this.getFieldId()}-${i}`\n\n // Capturar el índice actual para usar en los callbacks\n const currentIndex = i\n\n // Event listeners\n input.addEventListener('input', (e) => {\n const target = e.target as HTMLInputElement\n const inputValue = target.value.replace(/[^0-9]/g, '')\n target.value = inputValue\n\n // Mover al siguiente input si hay valor\n if (inputValue && currentIndex < length - 1) {\n this.inputs[currentIndex + 1].focus()\n }\n\n this.updateOTPValue()\n })\n\n input.addEventListener('keydown', (e) => {\n const target = e.target as HTMLInputElement\n\n // Backspace: borrar y mover al anterior\n if (e.key === 'Backspace' && !target.value && currentIndex > 0) {\n this.inputs[currentIndex - 1].focus()\n this.inputs[currentIndex - 1].value = ''\n this.updateOTPValue()\n }\n\n // Arrow keys: navegar entre inputs\n if (e.key === 'ArrowLeft' && currentIndex > 0) {\n e.preventDefault()\n this.inputs[currentIndex - 1].focus()\n }\n if (e.key === 'ArrowRight' && currentIndex < length - 1) {\n e.preventDefault()\n this.inputs[currentIndex + 1].focus()\n }\n })\n\n input.addEventListener('paste', (e) => {\n e.preventDefault()\n const pastedData = (e.clipboardData || (window as any).clipboardData).getData('text')\n const digits = pastedData.replace(/[^0-9]/g, '').slice(0, length)\n\n // Llenar inputs con los dígitos pegados\n for (let j = 0; j < digits.length && (currentIndex + j) < length; j++) {\n this.inputs[currentIndex + j].value = digits[j]\n }\n\n // Mover foco al último input llenado o al siguiente vacío\n const nextEmptyIndex = Math.min(currentIndex + digits.length, length - 1)\n this.inputs[nextEmptyIndex].focus()\n this.updateOTPValue()\n })\n\n input.addEventListener('focus', (e) => {\n const target = e.target as HTMLInputElement\n target.select()\n })\n\n input.addEventListener('blur', () => {\n this.onBlur()\n })\n\n this.inputs.push(input)\n container.appendChild(input)\n }\n\n return this.createFieldContainer(container)\n }\n\n private updateOTPValue(): void {\n const otpValue = this.inputs.map(input => input.value).join('')\n const otpField = this.field as OTPField\n \n // Si está vacío, enviar null, de lo contrario el string completo\n const finalValue = otpValue.length === this.inputs.length ? otpValue : null\n \n // Si el campo tiene formato numérico, convertir a número\n if (otpField.numeric && finalValue) {\n this.onChange(Number(finalValue))\n } else {\n this.onChange(finalValue)\n }\n }\n}\n","import { BaseInput } from './base-input'\nimport type { PasswordField } from '../../types'\n\nconst DEFAULT_SEPARATED_LENGTH = 6\n\nfunction eyeSvg(visible: boolean): string {\n if (visible) {\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24\"/><line x1=\"1\" y1=\"1\" x2=\"23\" y2=\"23\"/></svg>`\n }\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/></svg>`\n}\n\nexport class PasswordInput extends BaseInput {\n private inputs: HTMLInputElement[] = []\n private visible = false\n\n get passwordField(): PasswordField {\n return this.field as PasswordField\n }\n\n render(): HTMLElement {\n const pf = this.passwordField\n const useSeparated = !!pf.characterSeparated\n const length = useSeparated\n ? typeof pf.characterSeparated === 'number'\n ? pf.characterSeparated\n : DEFAULT_SEPARATED_LENGTH\n : 0\n\n if (useSeparated) {\n return this.createFieldContainer(this.renderSeparated(length))\n }\n return this.createFieldContainer(this.renderSingle())\n }\n\n private renderSingle(): HTMLElement {\n const pf = this.passwordField\n const showToggle = !!pf.showToggle\n\n const input = document.createElement('input')\n input.type = 'password'\n input.value = this.value ?? ''\n input.id = this.getFieldId()\n this.applyCommonProps(input)\n if (this.field.placeholder) input.placeholder = this.field.placeholder\n\n input.addEventListener('input', (e) => {\n this.onChange((e.target as HTMLInputElement).value)\n })\n input.addEventListener('blur', () => this.onBlur())\n\n if (!showToggle) {\n return input\n }\n\n const wrapper = document.createElement('div')\n wrapper.className = 'easy-form-password-inner'\n input.classList.add('easy-form-password-input')\n wrapper.appendChild(input)\n\n const btn = document.createElement('button')\n btn.type = 'button'\n btn.className = 'easy-form-password-toggle'\n btn.setAttribute('aria-label', 'Mostrar contraseña')\n btn.innerHTML = eyeSvg(false)\n btn.addEventListener('click', () => {\n this.visible = !this.visible\n input.type = this.visible ? 'text' : 'password'\n btn.setAttribute('aria-label', this.visible ? 'Ocultar contraseña' : 'Mostrar contraseña')\n btn.innerHTML = eyeSvg(this.visible)\n })\n wrapper.appendChild(btn)\n return wrapper\n }\n\n private renderSeparated(length: number): HTMLElement {\n const pf = this.passwordField\n const showToggle = !!pf.showToggle\n const value = this.value ?? ''\n const valueString = String(value).slice(0, length)\n\n const container = document.createElement('div')\n container.className = 'easy-form-password-separated'\n\n for (let i = 0; i < length; i++) {\n const input = document.createElement('input')\n input.type = 'password'\n input.maxLength = 1\n input.className = 'easy-form-password-separated-input'\n input.setAttribute('aria-label', `Carácter ${i + 1} de ${length}`)\n if (valueString[i]) input.value = valueString[i]\n this.applyCommonProps(input)\n input.id = i === 0 ? this.getFieldId() : `${this.getFieldId()}-${i}`\n if (i > 0) input.removeAttribute('name') // solo el primero conserva name para que el form encuentre el campo\n const currentIndex = i\n\n input.addEventListener('input', (e) => {\n const target = e.target as HTMLInputElement\n const val = target.value\n if (val && currentIndex < length - 1) {\n this.inputs[currentIndex + 1].focus()\n }\n this.updateSeparatedValue()\n })\n\n input.addEventListener('keydown', (e) => {\n if (e.key === 'Backspace' && !(e.target as HTMLInputElement).value && currentIndex > 0) {\n this.inputs[currentIndex - 1].focus()\n this.inputs[currentIndex - 1].value = ''\n this.updateSeparatedValue()\n }\n if (e.key === 'ArrowLeft' && currentIndex > 0) {\n e.preventDefault()\n this.inputs[currentIndex - 1].focus()\n }\n if (e.key === 'ArrowRight' && currentIndex < length - 1) {\n e.preventDefault()\n this.inputs[currentIndex + 1].focus()\n }\n })\n\n input.addEventListener('paste', (e) => {\n e.preventDefault()\n const text = (e.clipboardData || (window as any).clipboardData)?.getData('text') || ''\n const chars = text.slice(0, length - currentIndex).split('')\n for (let j = 0; j < chars.length && currentIndex + j < length; j++) {\n this.inputs[currentIndex + j].value = chars[j]\n }\n const nextIdx = Math.min(currentIndex + chars.length, length - 1)\n this.inputs[nextIdx].focus()\n this.updateSeparatedValue()\n })\n\n input.addEventListener('focus', (e) => (e.target as HTMLInputElement).select())\n input.addEventListener('blur', () => this.onBlur())\n\n this.inputs.push(input)\n container.appendChild(input)\n }\n\n if (showToggle) {\n const toggleWrap = document.createElement('div')\n toggleWrap.className = 'easy-form-password-separated-toggle'\n const btn = document.createElement('button')\n btn.type = 'button'\n btn.className = 'easy-form-password-toggle'\n btn.setAttribute('aria-label', 'Mostrar contraseña')\n btn.innerHTML = eyeSvg(false)\n btn.addEventListener('click', () => {\n this.visible = !this.visible\n const type = this.visible ? 'text' : 'password'\n this.inputs.forEach((inp) => { inp.type = type })\n btn.setAttribute('aria-label', this.visible ? 'Ocultar contraseña' : 'Mostrar contraseña')\n btn.innerHTML = eyeSvg(this.visible)\n })\n toggleWrap.appendChild(btn)\n container.appendChild(toggleWrap)\n }\n\n return container\n }\n\n private updateSeparatedValue(): void {\n const value = this.inputs.map((inp) => inp.value).join('')\n this.onChange(value || null)\n }\n}\n","import { BaseInput } from './base-input'\nimport type { FileDropField } from '../../types'\n\nexport class FileDropInput extends BaseInput {\n render(): HTMLElement {\n const fileDropField = this.field as FileDropField\n const accept = fileDropField.accept ?? ''\n const multiple = fileDropField.multiple ?? false\n\n const dropZone = document.createElement('div')\n dropZone.className = 'easy-form-file-drop'\n dropZone.setAttribute('tabindex', '0')\n\n const hiddenInput = document.createElement('input')\n hiddenInput.type = 'file'\n hiddenInput.className = 'easy-form-file-drop-input'\n hiddenInput.style.display = 'none'\n if (accept) hiddenInput.accept = accept\n if (multiple) hiddenInput.multiple = true\n\n const label = document.createElement('span')\n label.className = 'easy-form-file-drop-label'\n label.textContent = 'Arrastra archivos aquí o haz clic para seleccionar'\n dropZone.appendChild(label)\n dropZone.appendChild(hiddenInput)\n\n const fileList = document.createElement('div')\n fileList.className = 'easy-form-file-drop-list'\n\n const renderFileList = (files: File | File[] | null) => {\n const names = !files\n ? []\n : Array.isArray(files)\n ? files.map((f) => f.name)\n : [files.name]\n fileList.innerHTML = ''\n if (names.length === 0) {\n fileList.style.display = 'none'\n return\n }\n fileList.style.display = 'block'\n names.forEach((name) => {\n const item = document.createElement('div')\n item.className = 'easy-form-file-drop-item'\n item.textContent = name\n fileList.appendChild(item)\n })\n }\n renderFileList(this.value as File | File[] | null)\n\n const handleFiles = (files: FileList | null) => {\n if (!files || files.length === 0) return\n const arr = multiple ? Array.from(files) : files[0]\n this.onChange(arr)\n this.onBlur()\n renderFileList(arr)\n }\n\n dropZone.addEventListener('click', () => {\n hiddenInput.click()\n })\n\n hiddenInput.addEventListener('change', (e) => {\n const target = e.target as HTMLInputElement\n handleFiles(target.files)\n target.value = ''\n })\n\n dropZone.addEventListener('dragover', (e) => {\n e.preventDefault()\n e.stopPropagation()\n dropZone.classList.add('easy-form-file-drop-over')\n })\n\n dropZone.addEventListener('dragleave', (e) => {\n e.preventDefault()\n e.stopPropagation()\n dropZone.classList.remove('easy-form-file-drop-over')\n })\n\n dropZone.addEventListener('drop', (e) => {\n e.preventDefault()\n e.stopPropagation()\n dropZone.classList.remove('easy-form-file-drop-over')\n handleFiles(e.dataTransfer?.files ?? null)\n })\n\n dropZone.appendChild(fileList)\n return this.createFieldContainer(dropZone)\n }\n}\n","import { BaseInput } from './base-input'\nimport type { MapField } from '../../types'\n\nconst LEAFLET_CSS = 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.css'\n\nexport class MapInput extends BaseInput {\n private mapInstance: L.Map | null = null\n private markerInstance: L.Marker | null = null\n\n render(): HTMLElement {\n const mapField = this.field as MapField\n const center = mapField.center ?? { lat: 0, lng: 0 }\n const zoom = mapField.zoom ?? 13\n const value = this.value as { lat?: number; lng?: number } | string | null | undefined\n const lat = typeof value === 'object' && value?.lat != null ? value.lat : center.lat\n const lng = typeof value === 'object' && value?.lng != null ? value.lng : center.lng\n\n const container = document.createElement('div')\n container.className = 'easy-form-map'\n\n const inputsWrapper = document.createElement('div')\n inputsWrapper.className = 'easy-form-map-inputs'\n\n const latInput = document.createElement('input')\n latInput.type = 'number'\n latInput.step = 'any'\n latInput.placeholder = 'Latitud'\n latInput.value = String(lat)\n latInput.className = 'easy-form-map-lat'\n\n const lngInput = document.createElement('input')\n lngInput.type = 'number'\n lngInput.step = 'any'\n lngInput.placeholder = 'Longitud'\n lngInput.value = String(lng)\n lngInput.className = 'easy-form-map-lng'\n\n const updateFromInputs = () => {\n const latVal = parseFloat(latInput.value)\n const lngVal = parseFloat(lngInput.value)\n if (!isNaN(latVal) && !isNaN(lngVal)) {\n this.onChange({ lat: latVal, lng: lngVal })\n this.syncMarkerPosition(latVal, lngVal)\n }\n this.onBlur()\n }\n\n latInput.addEventListener('change', updateFromInputs)\n lngInput.addEventListener('change', updateFromInputs)\n\n inputsWrapper.appendChild(latInput)\n inputsWrapper.appendChild(lngInput)\n container.appendChild(inputsWrapper)\n\n const mapContainer = document.createElement('div')\n mapContainer.className = 'easy-form-map-container'\n container.appendChild(mapContainer)\n\n // Inyectar CSS de Leaflet DENTRO del contenedor para que quede en el Shadow DOM\n // (document.head no aplica estilos al Shadow DOM de easy-form)\n const linkId = 'easy-form-leaflet-css'\n let cssLoaded = false\n const link = document.createElement('link')\n link.id = linkId\n link.rel = 'stylesheet'\n link.href = LEAFLET_CSS\n link.onload = () => { cssLoaded = true }\n container.insertBefore(link, container.firstChild)\n\n const initMap = async () => {\n if (typeof window === 'undefined') return\n \n // Asegurar que el contenedor tenga dimensiones antes de inicializar\n mapContainer.style.height = '300px'\n mapContainer.style.width = '100%'\n mapContainer.style.position = 'relative'\n mapContainer.style.overflow = 'hidden'\n mapContainer.style.display = 'block'\n\n // Esperar a que el CSS se cargue y el contenedor esté en el DOM con dimensiones\n await new Promise((resolve) => {\n const checkReady = () => {\n if (cssLoaded && mapContainer.offsetWidth > 0 && mapContainer.offsetHeight > 0) {\n resolve(undefined)\n } else {\n requestAnimationFrame(checkReady)\n }\n }\n checkReady()\n })\n \n // Esperar un poco más para asegurar que el layout esté completamente calculado\n await new Promise((resolve) => setTimeout(resolve, 50))\n\n let L: typeof import('leaflet')\n try {\n L = await import('leaflet')\n } catch {\n mapContainer.innerHTML = `\n <div style=\"padding:2rem;text-align:center;color:#666;font-size:0.875rem;background:#f9f9f9;border-radius:4px;\">\n <strong>Campo map requiere Leaflet</strong><br><br>\n Instala e importa Leaflet para usar el mapa interactivo:<br>\n <code>npm install leaflet</code><br><br>\n En tu app: <code>import 'leaflet'</code> y <code>import 'leaflet/dist/leaflet.css'</code><br>\n <a href=\"https://easyforms.dev/docs/tipos-campos#map\" target=\"_blank\" rel=\"noopener\" style=\"color:var(--easy-form-primary,#007bff);\">Ver documentación</a>\n </div>\n `\n return\n }\n\n // Fix icon paths when bundled (Leaflet default icons break with bundlers)\n delete (L.Icon.Default.prototype as { _getIconUrl?: unknown })._getIconUrl\n L.Icon.Default.mergeOptions({\n iconRetinaUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon-2x.png',\n iconUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon.png',\n shadowUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-shadow.png',\n })\n\n this.mapInstance = L.map(mapContainer, {\n preferCanvas: false,\n zoomControl: true\n }).setView([lat, lng], zoom)\n\n const tileLayer = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {\n attribution: '&copy; <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a>',\n maxZoom: 19\n }).addTo(this.mapInstance)\n\n // Invalidar tamaño inmediatamente después de crear el mapa\n this.mapInstance.invalidateSize()\n \n // Invalidar tamaño después de que los tiles se hayan cargado\n tileLayer.on('load', () => {\n if (this.mapInstance) {\n this.mapInstance.invalidateSize()\n }\n })\n \n // Invalidar tamaño con múltiples intentos para asegurar que todo esté renderizado\n const invalidateSize = () => {\n if (this.mapInstance) {\n this.mapInstance.invalidateSize()\n }\n }\n setTimeout(invalidateSize, 100)\n setTimeout(invalidateSize, 300)\n setTimeout(invalidateSize, 500)\n \n // Invalidar tamaño cuando el contenedor sea visible (por si estaba oculto inicialmente)\n const observer = new IntersectionObserver((entries) => {\n entries.forEach((entry) => {\n if (entry.isIntersecting && this.mapInstance) {\n setTimeout(() => {\n this.mapInstance?.invalidateSize()\n }, 100)\n }\n })\n })\n observer.observe(mapContainer)\n\n this.markerInstance = L.marker([lat, lng], { draggable: true })\n .addTo(this.mapInstance)\n .on('dragend', () => {\n const pos = this.markerInstance!.getLatLng()\n latInput.value = String(Number(pos.lat.toFixed(6)))\n lngInput.value = String(Number(pos.lng.toFixed(6)))\n this.onChange({ lat: pos.lat, lng: pos.lng })\n this.onBlur()\n })\n\n this.mapInstance.on('click', (e: L.LeafletMouseEvent) => {\n const { lat: newLat, lng: newLng } = e.latlng\n this.markerInstance!.setLatLng([newLat, newLng])\n latInput.value = String(Number(newLat.toFixed(6)))\n lngInput.value = String(Number(newLng.toFixed(6)))\n this.onChange({ lat: newLat, lng: newLng })\n this.onBlur()\n })\n }\n\n initMap()\n\n return this.createFieldContainer(container)\n }\n\n private syncMarkerPosition(newLat: number, newLng: number): void {\n if (this.mapInstance && this.markerInstance) {\n this.markerInstance.setLatLng([newLat, newLng])\n this.mapInstance.setView([newLat, newLng])\n // Invalidar tamaño por si el contenedor cambió\n setTimeout(() => {\n this.mapInstance?.invalidateSize()\n }, 50)\n }\n }\n}\n","import { BaseInput } from './base-input'\nimport type { RatingField } from '../../types'\n\nconst STAR_SVG = (filled: boolean) =>\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"${filled ? 'currentColor' : 'none'}\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" role=\"img\" aria-hidden=\"true\"><polygon points=\"12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2\"/></svg>`\n\nexport class RatingInput extends BaseInput {\n render(): HTMLElement {\n const ratingField = this.field as RatingField\n const max = ratingField.max ?? 5\n const half = ratingField.half ?? false\n const currentValue = this.value != null ? Number(this.value) : 0\n\n const container = document.createElement('div')\n container.className = 'easy-form-rating'\n container.setAttribute('role', 'slider')\n container.setAttribute('aria-valuemin', '0')\n container.setAttribute('aria-valuemax', String(max))\n container.setAttribute('aria-valuenow', String(currentValue))\n container.setAttribute('aria-label', this.field.label || 'Rating')\n container.setAttribute('tabindex', '0')\n\n const starsContainer = document.createElement('div')\n starsContainer.className = 'easy-form-rating-stars'\n\n for (let i = 1; i <= max; i++) {\n const starWrapper = document.createElement('button')\n starWrapper.type = 'button'\n const filled = currentValue >= i || (half && currentValue >= i - 0.5)\n starWrapper.className = filled\n ? 'easy-form-rating-star easy-form-rating-star-filled'\n : 'easy-form-rating-star'\n starWrapper.innerHTML = STAR_SVG(filled)\n starWrapper.setAttribute('aria-label', `${i} de ${max}`)\n starWrapper.addEventListener('click', (e) => {\n e.preventDefault()\n const rect = (e.target as HTMLElement).closest('button')?.getBoundingClientRect()\n let val = i\n if (half && rect) {\n const mid = rect.left + rect.width / 2\n val = (e as MouseEvent).clientX < mid ? i - 0.5 : i\n }\n this.onChange(val)\n this.onBlur()\n this.rerenderStars(container, max, val, half)\n container.setAttribute('aria-valuenow', String(val))\n })\n starsContainer.appendChild(starWrapper)\n }\n\n container.appendChild(starsContainer)\n\n container.addEventListener('keydown', (e) => {\n const cur = Number(container.getAttribute('aria-valuenow')) || 0\n let newVal = cur\n if (e.key === 'ArrowRight' || e.key === 'ArrowUp') {\n e.preventDefault()\n newVal = Math.min(max, half ? cur + 0.5 : cur + 1)\n this.onChange(newVal)\n } else if (e.key === 'ArrowLeft' || e.key === 'ArrowDown') {\n e.preventDefault()\n newVal = Math.max(0, half ? cur - 0.5 : cur - 1)\n this.onChange(newVal)\n }\n if (newVal !== cur) {\n this.rerenderStars(container, max, newVal, half)\n container.setAttribute('aria-valuenow', String(newVal))\n }\n })\n\n return this.createFieldContainer(container)\n }\n\n private rerenderStars(\n container: HTMLElement,\n max: number,\n value: number,\n half: boolean\n ): void {\n const stars = container.querySelectorAll('.easy-form-rating-star')\n stars.forEach((star, i) => {\n const idx = i + 1\n const filled = value >= idx || (half && value >= idx - 0.5)\n star.className = filled\n ? 'easy-form-rating-star easy-form-rating-star-filled'\n : 'easy-form-rating-star'\n star.innerHTML = STAR_SVG(filled)\n })\n }\n}\n","import { BaseInput } from './base-input'\nimport type { SliderField } from '../../types'\n\nexport class SliderInput extends BaseInput {\n render(): HTMLElement {\n const sliderField = this.field as SliderField\n const min = sliderField.min ?? 0\n const max = sliderField.max ?? 100\n const step = sliderField.step ?? 1\n const showValue = sliderField.showValue ?? false\n\n const input = document.createElement('input')\n input.type = 'range'\n input.min = String(min)\n input.max = String(max)\n input.step = String(step)\n input.value = this.value != null ? String(this.value) : String(min)\n\n input.setAttribute('aria-valuemin', String(min))\n input.setAttribute('aria-valuemax', String(max))\n input.setAttribute('aria-valuenow', input.value)\n\n this.applyCommonProps(input)\n\n input.addEventListener('input', (e) => {\n const target = e.target as HTMLInputElement\n const val = step >= 1 ? parseInt(target.value, 10) : parseFloat(target.value)\n this.onChange(isNaN(val) ? min : val)\n if (valueSpan) {\n valueSpan.textContent = target.value\n }\n input.setAttribute('aria-valuenow', target.value)\n })\n\n input.addEventListener('change', () => {\n this.onBlur()\n })\n\n let valueSpan: HTMLSpanElement | null = null\n if (showValue) {\n valueSpan = document.createElement('span')\n valueSpan.className = 'easy-form-slider-value'\n valueSpan.textContent = input.value\n const wrapper = document.createElement('div')\n wrapper.className = 'easy-form-slider-wrapper'\n wrapper.appendChild(input)\n wrapper.appendChild(valueSpan)\n return this.createFieldContainer(wrapper)\n }\n\n return this.createFieldContainer(input)\n }\n}\n","import { BaseInput } from './base-input'\nimport type { ColorpickerField } from '../../types'\n\nconst HEX_REGEX = /^#?([0-9A-Fa-f]{6})$/\n\nfunction toHex(value: string): string {\n const m = value.match(HEX_REGEX)\n if (m) return `#${m[1].toLowerCase()}`\n if (/^[0-9A-Fa-f]{6}$/.test(value)) return `#${value.toLowerCase()}`\n return '#000000'\n}\n\nexport class ColorInput extends BaseInput {\n render(): HTMLElement {\n const colorField = this.field as ColorpickerField\n const defaultValue = colorField.defaultValue ?? '#000000'\n const currentValue =\n this.value != null && typeof this.value === 'string'\n ? toHex(this.value)\n : defaultValue\n\n const wrapper = document.createElement('div')\n wrapper.className = 'easy-form-color-wrapper'\n\n const colorPicker = document.createElement('input')\n colorPicker.type = 'color'\n colorPicker.value = currentValue\n colorPicker.setAttribute('value', currentValue)\n colorPicker.setAttribute('aria-label', this.field.label || 'Color')\n colorPicker.id = `${this.getFieldId()}-picker`\n if (this.field.disabled) colorPicker.setAttribute('disabled', 'true')\n\n const textInput = document.createElement('input')\n textInput.type = 'text'\n textInput.value = currentValue\n textInput.setAttribute('aria-label', `${this.field.label || 'Color'} (hex)`)\n textInput.placeholder = '#000000'\n textInput.className = 'easy-form-color-text'\n this.applyCommonProps(textInput)\n\n const syncFromPicker = () => {\n const value = colorPicker.value || '#000000'\n const hex = toHex(value)\n textInput.value = hex\n this.onChange(hex)\n }\n\n const syncFromText = () => {\n const raw = textInput.value.trim()\n const value = raw.startsWith('#') ? raw : `#${raw}`\n if (/^#[0-9A-Fa-f]{6}$/.test(value)) {\n const hex = toHex(value)\n colorPicker.value = hex\n this.onChange(hex)\n }\n }\n\n colorPicker.addEventListener('input', syncFromPicker)\n colorPicker.addEventListener('change', () => {\n syncFromPicker()\n this.onBlur()\n })\n textInput.addEventListener('input', syncFromText)\n textInput.addEventListener('blur', () => {\n syncFromText()\n this.onBlur()\n })\n\n wrapper.appendChild(colorPicker)\n wrapper.appendChild(textInput)\n return this.createFieldContainer(wrapper)\n }\n}\n","import { TextInput } from './text-input'\nimport { NumberInput } from './number-input'\nimport { TextareaInput } from './textarea-input'\nimport { SelectInput } from './select-input'\nimport { CheckboxInput } from './checkbox-input'\nimport { RadioInput } from './radio-input'\nimport { SwitchInput } from './switch-input'\nimport { DateInput } from './date-input'\nimport { FileInput } from './file-input'\nimport { QuantityInput } from './quantity-input'\nimport { AccordionSelectInput } from './accordion-select-input'\nimport { ImageGridSelectInput } from './image-grid-select-input'\nimport { OTPInput } from './otp-input'\nimport { PasswordInput } from './password-input'\nimport { FileDropInput } from './file-drop-input'\nimport { MapInput } from './map-input'\nimport { RatingInput } from './rating-input'\nimport { SliderInput } from './slider-input'\nimport { ColorInput } from './color-input'\nimport type { Field, CustomComponent } from '../../types'\n\n/**\n * Factory para crear inputs\n */\nexport function createInput(\n field: Field,\n value: any,\n error: string | undefined,\n onChange: (value: any) => void,\n onBlur: () => void\n): HTMLElement {\n switch (field.type) {\n case 'text':\n case 'email':\n return new TextInput(field, value, error, onChange, onBlur).render()\n case 'password':\n return new PasswordInput(field, value, error, onChange, onBlur).render()\n case 'number':\n return new NumberInput(field, value, error, onChange, onBlur).render()\n case 'textarea':\n return new TextareaInput(field, value, error, onChange, onBlur).render()\n case 'select':\n return new SelectInput(field, value, error, onChange, onBlur).render()\n case 'checkbox':\n return new CheckboxInput(field, value, error, onChange, onBlur).render()\n case 'radio':\n return new RadioInput(field, value, error, onChange, onBlur).render()\n case 'switch':\n return new SwitchInput(field, value, error, onChange, onBlur).render()\n case 'date':\n return new DateInput(field, value, error, onChange, onBlur).render()\n case 'file':\n return new FileInput(field, value, error, onChange, onBlur).render()\n case 'file-drop':\n return new FileDropInput(field, value, error, onChange, onBlur).render()\n case 'map':\n return new MapInput(field, value, error, onChange, onBlur).render()\n case 'rating':\n return new RatingInput(field, value, error, onChange, onBlur).render()\n case 'slider':\n return new SliderInput(field, value, error, onChange, onBlur).render()\n case 'colorpicker':\n return new ColorInput(field, value, error, onChange, onBlur).render()\n case 'quantity':\n return new QuantityInput(field, value, error, onChange, onBlur).render()\n case 'accordion-select':\n return new AccordionSelectInput(field, value, error, onChange, onBlur).render()\n case 'image-grid-select':\n return new ImageGridSelectInput(field, value, error, onChange, onBlur).render()\n case 'otp':\n return new OTPInput(field, value, error, onChange, onBlur).render()\n default:\n const div = document.createElement('div')\n div.textContent = `Tipo de campo no soportado: ${field.type}`\n return div\n }\n}\n\n/**\n * Registro de componentes personalizados\n */\nlet customComponents: Map<string, CustomComponent> = new Map()\n\n/**\n * Registra un componente personalizado\n */\nexport function registerComponent(\n type: string,\n component: CustomComponent\n): void {\n customComponents.set(type, component)\n}\n\n/**\n * Registra múltiples componentes\n */\nexport function registerComponents(\n components: Record<string, CustomComponent>\n): void {\n for (const [type, component] of Object.entries(components)) {\n registerComponent(type, component)\n }\n}\n\n/**\n * Obtiene un componente personalizado\n */\nexport function getCustomComponent(type: string): CustomComponent | undefined {\n return customComponents.get(type)\n}\n","import type { FormSchema, Field, TemplateName } from '../types'\n\n/**\n * Login form template\n */\nconst loginTemplate: FormSchema = {\n fields: [\n {\n type: 'email',\n name: 'email',\n label: 'Email',\n placeholder: 'Enter your email',\n validations: [\n { type: 'required', message: 'Email is required' },\n { type: 'email', message: 'Please enter a valid email' },\n ],\n },\n {\n type: 'password',\n name: 'password',\n label: 'Password',\n placeholder: 'Enter your password',\n validations: [\n { type: 'required', message: 'Password is required' },\n { type: 'minLength', value: 6, message: 'Password must be at least 6 characters' },\n ],\n },\n {\n type: 'checkbox',\n name: 'rememberMe',\n label: 'Remember me',\n defaultValue: false,\n },\n ],\n}\n\n/**\n * Registration form template\n */\nconst registerTemplate: FormSchema = {\n fields: [\n {\n type: 'text',\n name: 'name',\n label: 'Full Name',\n placeholder: 'Enter your full name',\n validations: [\n { type: 'required', message: 'Name is required' },\n { type: 'minLength', value: 2, message: 'Name must be at least 2 characters' },\n ],\n },\n {\n type: 'email',\n name: 'email',\n label: 'Email',\n placeholder: 'Enter your email',\n validations: [\n { type: 'required', message: 'Email is required' },\n { type: 'email', message: 'Please enter a valid email' },\n ],\n },\n {\n type: 'password',\n name: 'password',\n label: 'Password',\n placeholder: 'Create a password',\n validations: [\n { type: 'required', message: 'Password is required' },\n { type: 'minLength', value: 8, message: 'Password must be at least 8 characters' },\n ],\n },\n {\n type: 'password',\n name: 'confirmPassword',\n label: 'Confirm Password',\n placeholder: 'Confirm your password',\n validations: [\n { type: 'required', message: 'Please confirm your password' },\n {\n type: 'custom',\n validator: (value) => {\n // Note: For password matching validation, you may need to implement\n // a custom validation that accesses the form's state manager\n // or use a form-level validation on submit\n return typeof value === 'string' && value.length >= 8\n },\n message: 'Password must be at least 8 characters',\n },\n ],\n },\n ],\n}\n\n/**\n * OTP verification template\n */\nconst otpTemplate: FormSchema = {\n fields: [\n {\n type: 'otp',\n name: 'code',\n label: 'Verification Code',\n validations: [\n { type: 'required', message: 'Verification code is required' },\n ],\n },\n ],\n}\n\n/**\n * Contact form template\n */\nconst contactTemplate: FormSchema = {\n fields: [\n {\n type: 'text',\n name: 'name',\n label: 'Name',\n placeholder: 'Enter your name',\n validations: [\n { type: 'required', message: 'Name is required' },\n ],\n },\n {\n type: 'email',\n name: 'email',\n label: 'Email',\n placeholder: 'Enter your email',\n validations: [\n { type: 'required', message: 'Email is required' },\n { type: 'email', message: 'Please enter a valid email' },\n ],\n },\n {\n type: 'text',\n name: 'subject',\n label: 'Subject',\n placeholder: 'Enter the subject',\n validations: [\n { type: 'required', message: 'Subject is required' },\n ],\n },\n {\n type: 'textarea',\n name: 'message',\n label: 'Message',\n placeholder: 'Enter your message',\n rows: 5,\n validations: [\n { type: 'required', message: 'Message is required' },\n { type: 'minLength', value: 10, message: 'Message must be at least 10 characters' },\n ],\n },\n ],\n}\n\n/**\n * Password reset request template\n */\nconst passwordResetTemplate: FormSchema = {\n fields: [\n {\n type: 'email',\n name: 'email',\n label: 'Email',\n placeholder: 'Enter your email address',\n validations: [\n { type: 'required', message: 'Email is required' },\n { type: 'email', message: 'Please enter a valid email' },\n ],\n },\n ],\n}\n\n/**\n * Password change template\n */\nconst passwordChangeTemplate: FormSchema = {\n fields: [\n {\n type: 'password',\n name: 'currentPassword',\n label: 'Current Password',\n placeholder: 'Enter your current password',\n validations: [\n { type: 'required', message: 'Current password is required' },\n ],\n },\n {\n type: 'password',\n name: 'newPassword',\n label: 'New Password',\n placeholder: 'Enter your new password',\n validations: [\n { type: 'required', message: 'New password is required' },\n { type: 'minLength', value: 8, message: 'Password must be at least 8 characters' },\n ],\n },\n {\n type: 'password',\n name: 'confirmPassword',\n label: 'Confirm New Password',\n placeholder: 'Confirm your new password',\n validations: [\n { type: 'required', message: 'Please confirm your new password' },\n {\n type: 'custom',\n validator: (value) => {\n // Note: For password matching validation, you may need to implement\n // a custom validation that accesses the form's state manager\n // or use a form-level validation on submit\n return typeof value === 'string' && value.length >= 8\n },\n message: 'Password must be at least 8 characters',\n },\n ],\n },\n ],\n}\n\n/**\n * User profile edit template\n */\nconst profileTemplate: FormSchema = {\n fields: [\n {\n type: 'text',\n name: 'name',\n label: 'Full Name',\n placeholder: 'Enter your full name',\n validations: [\n { type: 'required', message: 'Name is required' },\n ],\n },\n {\n type: 'email',\n name: 'email',\n label: 'Email',\n placeholder: 'Enter your email',\n validations: [\n { type: 'required', message: 'Email is required' },\n { type: 'email', message: 'Please enter a valid email' },\n ],\n },\n {\n type: 'text',\n name: 'phone',\n label: 'Phone',\n placeholder: 'Enter your phone number',\n mask: {\n type: 'phone',\n },\n },\n {\n type: 'textarea',\n name: 'bio',\n label: 'Bio',\n placeholder: 'Tell us about yourself',\n rows: 4,\n },\n {\n type: 'file',\n name: 'avatar',\n label: 'Profile Picture',\n accept: 'image/*',\n },\n ],\n}\n\n/**\n * Checkout form template\n */\nconst checkoutTemplate: FormSchema = {\n fields: [\n {\n type: 'group',\n name: 'billingAddress',\n label: 'Billing Address',\n fields: [\n {\n type: 'text',\n name: 'street',\n label: 'Street Address',\n placeholder: 'Enter street address',\n validations: [\n { type: 'required', message: 'Street address is required' },\n ],\n },\n {\n type: 'row',\n name: 'cityState',\n fields: [\n {\n type: 'text',\n name: 'city',\n label: 'City',\n placeholder: 'City',\n validations: [\n { type: 'required', message: 'City is required' },\n ],\n },\n {\n type: 'text',\n name: 'state',\n label: 'State',\n placeholder: 'State',\n validations: [\n { type: 'required', message: 'State is required' },\n ],\n },\n ],\n },\n {\n type: 'text',\n name: 'zipCode',\n label: 'ZIP Code',\n placeholder: 'ZIP Code',\n validations: [\n { type: 'required', message: 'ZIP code is required' },\n ],\n },\n ],\n },\n {\n type: 'select',\n name: 'paymentMethod',\n label: 'Payment Method',\n options: [\n { label: 'Credit Card', value: 'credit-card' },\n { label: 'Debit Card', value: 'debit-card' },\n { label: 'PayPal', value: 'paypal' },\n { label: 'Bank Transfer', value: 'bank-transfer' },\n ],\n validations: [\n { type: 'required', message: 'Payment method is required' },\n ],\n },\n {\n type: 'select',\n name: 'shipping',\n label: 'Shipping Method',\n options: [\n { label: 'Standard (5-7 days)', value: 'standard' },\n { label: 'Express (2-3 days)', value: 'express' },\n { label: 'Overnight', value: 'overnight' },\n ],\n validations: [\n { type: 'required', message: 'Shipping method is required' },\n ],\n },\n ],\n}\n\n/**\n * Feedback form template\n */\nconst feedbackTemplate: FormSchema = {\n fields: [\n {\n type: 'select',\n name: 'rating',\n label: 'Rating',\n options: [\n { label: '1 - Poor', value: 1 },\n { label: '2 - Fair', value: 2 },\n { label: '3 - Good', value: 3 },\n { label: '4 - Very Good', value: 4 },\n { label: '5 - Excellent', value: 5 },\n ],\n validations: [\n { type: 'required', message: 'Rating is required' },\n ],\n },\n {\n type: 'textarea',\n name: 'comment',\n label: 'Comment',\n placeholder: 'Share your feedback',\n rows: 5,\n validations: [\n { type: 'required', message: 'Comment is required' },\n ],\n },\n {\n type: 'email',\n name: 'email',\n label: 'Email (optional)',\n placeholder: 'Enter your email if you want a response',\n },\n ],\n}\n\n/**\n * Newsletter subscription template\n */\nconst subscriptionTemplate: FormSchema = {\n fields: [\n {\n type: 'email',\n name: 'email',\n label: 'Email',\n placeholder: 'Enter your email',\n validations: [\n { type: 'required', message: 'Email is required' },\n { type: 'email', message: 'Please enter a valid email' },\n ],\n },\n {\n type: 'checkbox',\n name: 'weeklyNewsletter',\n label: 'Weekly Newsletter',\n defaultValue: true,\n },\n {\n type: 'checkbox',\n name: 'productUpdates',\n label: 'Product Updates',\n defaultValue: false,\n },\n {\n type: 'checkbox',\n name: 'promotions',\n label: 'Promotions and Special Offers',\n defaultValue: false,\n },\n ],\n}\n\n/**\n * Booking/reservation template\n */\nconst bookingTemplate: FormSchema = {\n fields: [\n {\n type: 'date',\n name: 'date',\n label: 'Date',\n validations: [\n { type: 'required', message: 'Date is required' },\n ],\n },\n {\n type: 'text',\n name: 'time',\n label: 'Time',\n placeholder: 'HH:MM',\n mask: {\n type: 'time',\n },\n validations: [\n { type: 'required', message: 'Time is required' },\n ],\n },\n {\n type: 'number',\n name: 'guests',\n label: 'Number of Guests',\n placeholder: 'Enter number of guests',\n min: 1,\n max: 20,\n validations: [\n { type: 'required', message: 'Number of guests is required' },\n { type: 'min', value: 1, message: 'At least 1 guest is required' },\n ],\n },\n {\n type: 'textarea',\n name: 'specialRequests',\n label: 'Special Requests',\n placeholder: 'Any special requests or dietary restrictions?',\n rows: 4,\n },\n ],\n}\n\n/**\n * Review/rating form template\n */\nconst reviewTemplate: FormSchema = {\n fields: [\n {\n type: 'select',\n name: 'rating',\n label: 'Rating',\n options: [\n { label: '1 Star', value: 1 },\n { label: '2 Stars', value: 2 },\n { label: '3 Stars', value: 3 },\n { label: '4 Stars', value: 4 },\n { label: '5 Stars', value: 5 },\n ],\n validations: [\n { type: 'required', message: 'Rating is required' },\n ],\n },\n {\n type: 'text',\n name: 'title',\n label: 'Review Title',\n placeholder: 'Give your review a title',\n validations: [\n { type: 'required', message: 'Review title is required' },\n { type: 'minLength', value: 5, message: 'Title must be at least 5 characters' },\n ],\n },\n {\n type: 'textarea',\n name: 'comment',\n label: 'Your Review',\n placeholder: 'Share your experience',\n rows: 6,\n validations: [\n { type: 'required', message: 'Review comment is required' },\n { type: 'minLength', value: 20, message: 'Review must be at least 20 characters' },\n ],\n },\n ],\n}\n\n/**\n * Registry of all available templates\n */\nexport const templates: Record<TemplateName, FormSchema> = {\n login: loginTemplate,\n register: registerTemplate,\n otp: otpTemplate,\n contact: contactTemplate,\n 'password-reset': passwordResetTemplate,\n 'password-change': passwordChangeTemplate,\n profile: profileTemplate,\n checkout: checkoutTemplate,\n feedback: feedbackTemplate,\n subscription: subscriptionTemplate,\n booking: bookingTemplate,\n review: reviewTemplate,\n}\n\n/**\n * Get a template by name\n * @param templateName - Name of the template to retrieve\n * @returns The template schema or null if not found\n */\nexport function getTemplate(templateName: string): FormSchema | null {\n if (templateName in templates) {\n return templates[templateName as TemplateName]\n }\n return null\n}\n\n/**\n * Get list of all available template names\n * @returns Array of template names\n */\nexport function getAvailableTemplates(): TemplateName[] {\n return Object.keys(templates) as TemplateName[]\n}\n\n/**\n * Extend a template with additional fields\n * @param templateName - Name of the template to extend\n * @param additionalFields - Additional fields to add to the template\n * @returns Extended schema with template fields + additional fields\n */\nexport function extendTemplate(\n templateName: string,\n additionalFields: Field[]\n): FormSchema {\n const baseTemplate = getTemplate(templateName)\n if (!baseTemplate) {\n throw new Error(`Template \"${templateName}\" not found`)\n }\n\n const existingFields = baseTemplate.fields || []\n const existingSteps = baseTemplate.steps\n\n // If template has steps, extend the last step\n if (existingSteps && existingSteps.length > 0) {\n const lastStep = existingSteps[existingSteps.length - 1]\n return {\n ...baseTemplate,\n steps: [\n ...existingSteps.slice(0, -1),\n {\n ...lastStep,\n fields: [...lastStep.fields, ...additionalFields],\n },\n ],\n }\n }\n\n // Otherwise, extend fields array\n return {\n ...baseTemplate,\n fields: [...existingFields, ...additionalFields],\n }\n}\n","import { StateManager } from '../core/state-manager'\nimport { AttemptsLock } from '../utils/attempts-lock'\nimport { createInput, getCustomComponent, registerComponents } from './inputs'\nimport type {\n FormSchema,\n Field,\n ComponentRegistry,\n SubmitEventDetail,\n ChangeEventDetail,\n ErrorEventDetail,\n StepChangeEventDetail,\n FormTheme,\n FormColors,\n TemplateName,\n SubmitButtonConfig,\n} from '../types'\nimport { attributeValue, parseAttributeValue } from '../utils'\nimport { getThemeStyles, getColors } from '../utils/styles'\nimport { getTemplate, extendTemplate } from '../templates'\n\n// Verificar si estamos en un entorno del navegador\nconst BrowserHTMLElement = typeof HTMLElement !== 'undefined' ? HTMLElement : class {} as typeof HTMLElement\n\n/**\n * Web Component principal EasyForm\n */\nexport class EasyForm extends BrowserHTMLElement {\n private stateManager: StateManager\n protected shadow: ShadowRoot\n private customComponents: ComponentRegistry = {}\n private isRendering: boolean = false\n private attemptsLock: AttemptsLock | null = null\n private lockCountdownInterval: ReturnType<typeof setInterval> | null = null\n /**\n * Plantillas de slots basados en atributo `row` en el light DOM.\n * Se inicializan una sola vez y se clonan en cada render.\n */\n private slotTemplates: { template: HTMLElement; row: number | null }[] | null = null\n private skipPreserveValuesOnNextRender = false\n\n static get observedAttributes() {\n return [\n 'schema',\n 'template',\n 'template-extend',\n 'theme',\n 'colors',\n 'initialData',\n 'loading',\n 'disabled',\n 'max-attempts',\n 'block-duration-minutes',\n 'attempts-storage-key',\n 'submit-button',\n 'label-position',\n 'show-completed-indicator',\n 'form-direction',\n ]\n }\n\n constructor() {\n if (typeof HTMLElement === 'undefined') {\n throw new Error('EasyForm can only be used in a browser environment')\n }\n super()\n this.stateManager = new StateManager()\n this.shadow = this.attachShadow({ mode: 'open' })\n // Los estilos se aplicarán en connectedCallback cuando los atributos estén disponibles\n }\n\n /**\n * Obtiene el schema\n */\n get schema(): FormSchema | null {\n const schemaAttr = this.getAttribute('schema')\n if (!schemaAttr) return null\n \n // Validar mutua exclusividad con template\n if (this.getAttribute('template')) {\n console.warn('EasyForm: Cannot use both \"schema\" and \"template\" attributes. \"template\" will be ignored.')\n return parseAttributeValue(schemaAttr)\n }\n \n return parseAttributeValue(schemaAttr)\n }\n\n /**\n * Establece el schema\n */\n set schema(value: FormSchema | null) {\n // Si se establece schema, remover template\n if (value && this.getAttribute('template')) {\n console.warn('EasyForm: Setting \"schema\" will remove \"template\" attribute.')\n this.removeAttribute('template')\n this.removeAttribute('template-extend')\n }\n \n if (value) {\n this.setAttribute('schema', attributeValue(value))\n } else {\n this.removeAttribute('schema')\n }\n }\n\n /**\n * Obtiene el template\n */\n get template(): TemplateName | null {\n const templateAttr = this.getAttribute('template')\n if (!templateAttr) return null\n \n // Validar mutua exclusividad con schema\n if (this.getAttribute('schema')) {\n console.warn('EasyForm: Cannot use both \"template\" and \"schema\" attributes. \"schema\" will be ignored.')\n return templateAttr as TemplateName\n }\n \n return templateAttr as TemplateName\n }\n\n /**\n * Establece el template\n */\n set template(value: TemplateName | null) {\n // Si se establece template, remover schema\n if (value && this.getAttribute('schema')) {\n console.warn('EasyForm: Setting \"template\" will remove \"schema\" attribute.')\n this.removeAttribute('schema')\n }\n \n if (value) {\n this.setAttribute('template', value)\n } else {\n this.removeAttribute('template')\n this.removeAttribute('template-extend')\n }\n }\n\n /**\n * Obtiene los campos adicionales para extender el template\n */\n get templateExtend(): Field[] | null {\n const extendAttr = this.getAttribute('template-extend')\n if (!extendAttr) return null\n return parseAttributeValue(extendAttr)\n }\n\n /**\n * Establece los campos adicionales para extender el template\n */\n set templateExtend(value: Field[] | null) {\n if (value) {\n this.setAttribute('template-extend', attributeValue(value))\n } else {\n this.removeAttribute('template-extend')\n }\n }\n\n /**\n * Máximo de intentos antes de bloquear (para AttemptsLock)\n */\n get maxAttempts(): number | null {\n const attr = this.getAttribute('max-attempts')\n if (!attr) return null\n const n = parseInt(attr, 10)\n return isNaN(n) ? null : n\n }\n\n set maxAttempts(value: number | null) {\n if (value != null && value >= 1) {\n this.setAttribute('max-attempts', String(value))\n } else {\n this.removeAttribute('max-attempts')\n }\n }\n\n /**\n * Duración del bloqueo en minutos (default: 5)\n */\n get blockDurationMinutes(): number | null {\n const attr = this.getAttribute('block-duration-minutes')\n if (!attr) return null\n const n = parseInt(attr, 10)\n return isNaN(n) ? null : n\n }\n\n set blockDurationMinutes(value: number | null) {\n if (value != null && value >= 1) {\n this.setAttribute('block-duration-minutes', String(value))\n } else {\n this.removeAttribute('block-duration-minutes')\n }\n }\n\n /**\n * Clave para persistir intentos en sessionStorage\n */\n get attemptsStorageKey(): string | null {\n return this.getAttribute('attempts-storage-key')\n }\n\n set attemptsStorageKey(value: string | null) {\n if (value) {\n this.setAttribute('attempts-storage-key', value)\n } else {\n this.removeAttribute('attempts-storage-key')\n }\n }\n\n /**\n * Configuración del botón de submit (desde atributo o schema)\n */\n get submitButton(): SubmitButtonConfig | null {\n const attr = this.getAttribute('submit-button')\n if (attr) {\n try {\n return parseAttributeValue(attr) as SubmitButtonConfig\n } catch {\n return null\n }\n }\n return null\n }\n\n set submitButton(value: SubmitButtonConfig | null) {\n if (value && typeof value === 'object') {\n this.setAttribute('submit-button', attributeValue(value))\n } else {\n this.removeAttribute('submit-button')\n }\n }\n\n /**\n * Obtiene la configuración efectiva del botón submit (atributo > schema > defaults)\n */\n private getSubmitButtonConfig(schema: FormSchema | null): Required<SubmitButtonConfig> {\n const fromAttr = this.submitButton\n const fromSchema = schema?.submitButton\n const merged = { ...fromSchema, ...fromAttr } as SubmitButtonConfig\n return {\n visible: merged.visible ?? true,\n text: merged.text ?? 'Enviar',\n width: merged.width ?? 'auto',\n align: merged.align ?? 'left',\n }\n }\n\n /**\n * Se llama cuando el componente se conecta al DOM\n */\n connectedCallback() {\n this.setupAttemptsLock()\n // Asegurar que los estilos estén aplicados con los atributos actuales\n this.setupStyles()\n this.render()\n }\n\n /**\n * Se llama cuando un atributo cambia\n */\n attributeChangedCallback(name: string, oldValue: string, newValue: string) {\n // Validar mutua exclusividad\n if (name === 'schema' && newValue !== oldValue) {\n if (this.getAttribute('template')) {\n console.warn('EasyForm: \"schema\" and \"template\" cannot be used together. Removing \"template\".')\n this.removeAttribute('template')\n this.removeAttribute('template-extend')\n }\n this.handleSchemaChange()\n }\n if (name === 'template' && newValue !== oldValue) {\n if (this.getAttribute('schema')) {\n console.warn('EasyForm: \"template\" and \"schema\" cannot be used together. Removing \"schema\".')\n this.removeAttribute('schema')\n }\n this.handleSchemaChange()\n }\n if (name === 'template-extend' && newValue !== oldValue) {\n this.handleSchemaChange()\n }\n if (name === 'initialData' && newValue !== oldValue) {\n this.handleSchemaChange()\n }\n if ((name === 'theme' || name === 'colors') && newValue !== oldValue) {\n this.setupStyles()\n }\n if (name === 'loading' && newValue !== oldValue) {\n // Actualizar solo el overlay de loading sin re-renderizar todo\n const form = this.shadow.querySelector('form')\n this.updateLoadingOverlay(form || undefined)\n // También necesitamos actualizar el estado disabled de los campos\n if (form) {\n const inputs = form.querySelectorAll('input, textarea, select, button')\n inputs.forEach((input) => {\n if (input instanceof HTMLElement && 'disabled' in input) {\n (input as any).disabled = this.loading\n }\n })\n }\n }\n if (name === 'disabled' && newValue !== oldValue) {\n this.render()\n }\n if ((name === 'label-position' || name === 'form-direction' || name === 'show-completed-indicator') && newValue !== oldValue) {\n this.render()\n }\n if (\n (name === 'max-attempts' ||\n name === 'block-duration-minutes' ||\n name === 'attempts-storage-key') &&\n newValue !== oldValue\n ) {\n this.setupAttemptsLock()\n this.updateLockOverlay()\n }\n if (name === 'submit-button' && newValue !== oldValue) {\n this.render()\n }\n }\n\n /**\n * Configura el AttemptsLock según los atributos actuales\n */\n private setupAttemptsLock(): void {\n const maxAttempts = this.maxAttempts\n if (maxAttempts == null || maxAttempts < 1) {\n this.attemptsLock = null\n return\n }\n this.attemptsLock = new AttemptsLock({\n maxAttempts,\n blockDurationMinutes: this.blockDurationMinutes ?? 5,\n storageKey: this.attemptsStorageKey ?? undefined,\n onLocked: () => {\n this.updateLockOverlay()\n },\n onUnlocked: () => {\n this.stopLockCountdown()\n this.updateLockOverlay()\n this.render()\n },\n })\n }\n\n /**\n * Maneja el cambio de schema\n */\n private handleSchemaChange() {\n let schema: FormSchema | null = null\n \n // Priorizar template sobre schema\n const templateName = this.template\n if (templateName) {\n schema = this.getSchemaFromTemplate(templateName)\n } else {\n schema = this.schema\n }\n \n if (schema) {\n const initialData = this.initialData\n this.stateManager.initializeSchema(schema, initialData || undefined)\n this.render()\n }\n }\n\n /**\n * Obtiene el schema desde un template\n */\n private getSchemaFromTemplate(templateName: TemplateName): FormSchema | null {\n const baseTemplate = getTemplate(templateName)\n if (!baseTemplate) {\n console.error(`EasyForm: Template \"${templateName}\" not found`)\n return null\n }\n\n // Si hay campos adicionales, extender el template\n const additionalFields = this.templateExtend\n if (additionalFields && additionalFields.length > 0) {\n return extendTemplate(templateName, additionalFields)\n }\n\n return baseTemplate\n }\n\n /**\n * Renderiza el formulario\n */\n private async render() {\n // Evitar renderizados simultáneos\n if (this.isRendering) {\n return\n }\n \n this.isRendering = true\n \n try {\n // Obtener schema desde template o atributo schema\n let schema: FormSchema | null = null\n const templateName = this.template\n if (templateName) {\n schema = this.getSchemaFromTemplate(templateName)\n } else {\n schema = this.schema\n }\n \n if (!schema) {\n // Eliminar solo el formulario, mantener los estilos\n const form = this.shadow.querySelector('form')\n if (form && form.parentNode === this.shadow) {\n form.remove()\n }\n return\n }\n\n // Preservar valores actuales del DOM antes de re-renderizar (omitir si viene de add/remove en array)\n const isArrayRefresh = this.skipPreserveValuesOnNextRender\n const preservedValues = isArrayRefresh ? {} : this.preserveCurrentValues()\n this.skipPreserveValuesOnNextRender = false\n\n // Preservar el estado del wizard ANTES de reinicializar (pero después de cualquier cambio)\n const previousWizardState = this.stateManager.getWizardState()\n\n // Guardar los valores preservados en el estado sin validar\n // Esto evita disparar validaciones de todos los campos\n if (preservedValues && Object.keys(preservedValues).length > 0) {\n for (const [key, value] of Object.entries(preservedValues)) {\n this.stateManager.setValueWithoutValidation(key, value)\n }\n }\n\n const initialData = this.initialData\n \n // Verificar si el schema ha cambiado comparando si es wizard o no\n const wasWizard = previousWizardState !== null\n const isWizard = schema.steps && schema.steps.length > 0\n \n // Solo reinicializar el schema si es necesario (si cambió de wizard a normal o viceversa)\n // O si el número de steps cambió, o si no hay estado previo.\n // No re-inicializar cuando es refresh por add/remove en array (preservar estado actual).\n const shouldReinitialize = !isArrayRefresh && (\n !previousWizardState || !wasWizard || !isWizard || \n (previousWizardState && schema.steps && previousWizardState.totalSteps !== schema.steps.length)\n )\n \n if (shouldReinitialize) {\n this.stateManager.initializeSchema(schema, initialData || undefined)\n \n // Si había un wizard state previo y el schema sigue siendo wizard, restaurarlo\n if (wasWizard && isWizard && previousWizardState) {\n const wizardState = this.stateManager.getWizardState()\n if (wizardState && previousWizardState.totalSteps === wizardState.totalSteps) {\n // Restaurar el paso actual primero\n if (previousWizardState.currentStep >= 0 && previousWizardState.currentStep < wizardState.totalSteps) {\n this.stateManager.goToStep(previousWizardState.currentStep)\n }\n // Restaurar pasos completados\n for (const completedStep of previousWizardState.completedSteps) {\n if (completedStep >= 0 && completedStep < wizardState.totalSteps) {\n this.stateManager.completeStep(completedStep)\n }\n }\n }\n }\n }\n // Si no se reinicializa, el estado del wizard ya está actualizado (por nextStep/previousStep)\n // y los valores ya fueron preservados arriba\n \n // Obtener el estado actualizado\n const finalWizardState = this.stateManager.getWizardState()\n\n // Crear formulario\n const newFormElement = document.createElement('form')\n newFormElement.addEventListener('submit', (e) => this.handleSubmit(e))\n \n // Aplicar disabled al formulario si está disabled o loading\n if (this.disabled || this.loading) {\n newFormElement.classList.add('easy-form-disabled')\n }\n\n // Dirección del layout (vertical | horizontal)\n const directionAttr = this.getAttribute('form-direction') as 'vertical' | 'horizontal' | null\n const direction = schema.direction ?? (directionAttr === 'vertical' || directionAttr === 'horizontal' ? directionAttr : 'vertical')\n newFormElement.classList.add(`easy-form-direction-${direction}`)\n\n // Indicador de progreso (campos obligatorios completados)\n const showCompletedAttr = this.getAttribute('show-completed-indicator')\n const completedIndicator = schema.completedIndicator ?? (showCompletedAttr !== null && showCompletedAttr !== 'false')\n const completedPosition = typeof completedIndicator === 'object' && completedIndicator?.position ? completedIndicator.position : 'top'\n\n // Renderizar campos o steps\n if (finalWizardState) {\n this.renderWizard(newFormElement, schema)\n // No agregar botón submit normal para wizard, ya tiene sus propios botones\n } else {\n this.renderFields(newFormElement, schema.fields || [])\n\n // Botón submit solo para formularios normales (no wizard)\n const submitConfig = this.getSubmitButtonConfig(schema)\n if (submitConfig.visible) {\n const submitWrapper = document.createElement('div')\n submitWrapper.className = 'easy-form-submit-wrapper'\n submitWrapper.style.textAlign = submitConfig.align\n\n const submitButton = document.createElement('button')\n submitButton.type = 'submit'\n submitButton.textContent = submitConfig.text\n submitButton.className = 'easy-form-submit'\n submitButton.style.width = submitConfig.width\n if (this.disabled || this.loading) {\n submitButton.disabled = true\n }\n submitWrapper.appendChild(submitButton)\n newFormElement.appendChild(submitWrapper)\n }\n }\n\n // Indicador de progreso (antes o después del formulario)\n let formWrapper: HTMLElement | null = null\n if (completedIndicator) {\n const { completed, total } = this.getCompletedRequiredProgress(schema)\n const progressBar = document.createElement('div')\n progressBar.className = 'easy-form-completed-indicator'\n progressBar.setAttribute('role', 'progressbar')\n progressBar.setAttribute('aria-valuenow', String(completed))\n progressBar.setAttribute('aria-valuemin', '0')\n progressBar.setAttribute('aria-valuemax', String(total))\n progressBar.setAttribute('aria-label', `Campos obligatorios completados: ${completed} de ${total}`)\n const track = document.createElement('div')\n track.className = 'easy-form-completed-track'\n const fill = document.createElement('div')\n fill.className = 'easy-form-completed-fill'\n fill.style.width = total > 0 ? `${(completed / total) * 100}%` : '0%'\n track.appendChild(fill)\n progressBar.appendChild(track)\n formWrapper = document.createElement('div')\n formWrapper.className = 'easy-form-wrapper'\n if (completedPosition === 'top') {\n formWrapper.appendChild(progressBar)\n formWrapper.appendChild(newFormElement)\n } else {\n formWrapper.appendChild(newFormElement)\n formWrapper.appendChild(progressBar)\n }\n }\n\n // Eliminar solo el formulario anterior si existe y está en el DOM, mantener los estilos\n const oldForm = this.shadow.querySelector('form')\n if (oldForm && oldForm.parentNode === this.shadow && oldForm !== newFormElement) {\n try {\n oldForm.remove()\n } catch (e) {\n // Ignorar errores si el elemento ya fue eliminado\n console.warn('Error al eliminar formulario anterior:', e)\n }\n }\n const oldWrapper = this.shadow.querySelector('.easy-form-wrapper')\n if (oldWrapper) oldWrapper.remove()\n\n // Agregar el nuevo formulario (o wrapper con indicador)\n this.shadow.appendChild(formWrapper || newFormElement)\n \n // Agregar overlay de loading sobre el formulario si está activo\n if (this.loading) {\n this.updateLoadingOverlay(newFormElement)\n }\n // Agregar overlay de bloqueo si está activo\n this.updateLockOverlay(newFormElement)\n } finally {\n this.isRendering = false\n }\n }\n\n /**\n * Actualiza el overlay de bloqueo por intentos\n */\n private updateLockOverlay(formElement?: HTMLElement): void {\n const existingOverlay = this.shadow.querySelector('.easy-form-lock-overlay')\n if (existingOverlay) {\n existingOverlay.remove()\n }\n this.stopLockCountdown()\n\n if (!this.attemptsLock?.isLocked()) return\n\n const form = formElement || this.shadow.querySelector('form')\n if (!form) return\n\n const overlay = document.createElement('div')\n overlay.className = 'easy-form-lock-overlay'\n\n const message = document.createElement('div')\n message.className = 'easy-form-lock-message'\n message.setAttribute('role', 'alert')\n\n const updateCountdown = (): void => {\n const remainingMs = this.attemptsLock!.getRemainingBlockTimeMs()\n if (remainingMs <= 0) {\n this.stopLockCountdown()\n return\n }\n const minutes = Math.floor(remainingMs / 60000)\n const seconds = Math.floor((remainingMs % 60000) / 1000)\n const timeStr =\n minutes > 0\n ? `${minutes} min ${seconds} s`\n : `${seconds} segundos`\n message.textContent = `Demasiados intentos. Intenta de nuevo en ${timeStr}.`\n }\n\n updateCountdown()\n overlay.appendChild(message)\n form.appendChild(overlay)\n\n this.lockCountdownInterval = setInterval(updateCountdown, 1000)\n }\n\n private stopLockCountdown(): void {\n if (this.lockCountdownInterval) {\n clearInterval(this.lockCountdownInterval)\n this.lockCountdownInterval = null\n }\n }\n\n /**\n * Actualiza el overlay de loading sobre el formulario\n */\n private updateLoadingOverlay(formElement?: HTMLElement) {\n // Eliminar overlay anterior si existe\n const existingOverlay = this.shadow.querySelector('.easy-form-loading-overlay')\n if (existingOverlay) {\n existingOverlay.remove()\n }\n\n // Si loading está activo, agregar overlay sobre el formulario\n if (this.loading) {\n const form = formElement || this.shadow.querySelector('form')\n if (form) {\n const overlay = document.createElement('div')\n overlay.className = 'easy-form-loading-overlay'\n \n const spinner = document.createElement('div')\n spinner.className = 'easy-form-loading-spinner'\n overlay.appendChild(spinner)\n \n // Agregar el overlay como hijo del formulario\n form.appendChild(overlay)\n }\n }\n }\n\n /**\n * Preserva los valores actuales del DOM antes de re-renderizar\n * Retorna un objeto con los valores preservados\n */\n private preserveCurrentValues(): Record<string, any> {\n // Necesitamos el schema actual para poder filtrar inputs que no pertenecen al formulario\n // y asegurar que valores dentro de slots u otros elementos no definidos en el schema\n // no se mezclen con el estado interno del formulario.\n let currentSchema: FormSchema | null = null\n const templateName = this.template\n if (templateName) {\n currentSchema = this.getSchemaFromTemplate(templateName)\n } else {\n currentSchema = this.schema\n }\n\n if (!currentSchema) {\n return {}\n }\n\n const form = this.shadow.querySelector('form')\n const preservedValues: Record<string, any> = {}\n \n if (!form) return preservedValues\n\n // Obtener todos los inputs, textareas y selects del formulario\n const inputs = form.querySelectorAll('input, textarea, select')\n \n for (const input of inputs) {\n const name = input.getAttribute('name')\n if (!name) continue\n\n // Ignorar inputs que no están definidos en el schema (por ejemplo, dentro de slots)\n const belongsToSchema = this.findFieldInSchema(currentSchema, name) !== null\n if (!belongsToSchema) continue\n\n let value: any\n \n if (input instanceof HTMLInputElement) {\n if (input.type === 'checkbox') {\n value = input.checked\n } else if (input.type === 'radio') {\n if (input.checked) {\n value = input.value\n } else {\n continue // Solo guardar el radio seleccionado\n }\n } else if (input.type === 'number') {\n value = input.value === '' ? null : Number(input.value)\n } else {\n value = input.value\n }\n } else if (input instanceof HTMLTextAreaElement) {\n value = input.value\n } else if (input instanceof HTMLSelectElement) {\n if (input.multiple) {\n value = Array.from(input.selectedOptions).map(opt => opt.value)\n } else {\n value = input.value || null\n }\n }\n\n // Guardar el valor (incluso strings vacíos para preservar el estado)\n if (value !== undefined) {\n preservedValues[name] = value === '' ? null : value\n }\n }\n \n return preservedValues\n }\n\n /**\n * Inicializa las plantillas de slots a partir del light DOM.\n * Cualquier hijo directo que sea HTMLElement se considera slot; si tiene atributo `row` se usa para la posición, si no se inserta al final (-1).\n */\n private initializeSlotTemplates(): void {\n if (this.slotTemplates !== null) return\n\n const elements: HTMLElement[] = []\n for (const child of Array.from(this.children)) {\n if (child instanceof HTMLElement) {\n elements.push(child)\n }\n }\n\n if (elements.length === 0) {\n this.slotTemplates = []\n return\n }\n\n this.slotTemplates = elements.map((el) => {\n const raw = el.hasAttribute('row') ? el.getAttribute('row') : null\n const parsed = raw != null && raw !== '' ? Number(raw) : NaN\n const row = Number.isFinite(parsed) ? parsed : null\n return {\n template: el.cloneNode(true) as HTMLElement,\n row,\n }\n })\n }\n\n /**\n * Obtiene clones de slots agrupados por índice de fila efectivo.\n * Cualquier valor inválido o fuera de rango se normaliza a -1 (final del formulario).\n */\n private getSlotClonesByRow(totalRows: number): Map<number, HTMLElement[]> {\n this.initializeSlotTemplates()\n\n const result = new Map<number, HTMLElement[]>()\n\n if (!this.slotTemplates || this.slotTemplates.length === 0) {\n return result\n }\n\n for (const { template, row } of this.slotTemplates) {\n let effectiveRow: number = typeof row === 'number' ? row : -1\n\n if (!Number.isFinite(effectiveRow)) {\n effectiveRow = -1\n }\n\n // Normalizar índices fuera de rango al final\n if (effectiveRow < 0 || effectiveRow >= totalRows) {\n effectiveRow = -1\n }\n\n const clone = template.cloneNode(true) as HTMLElement\n const existing = result.get(effectiveRow) ?? []\n existing.push(clone)\n result.set(effectiveRow, existing)\n }\n\n return result\n }\n\n /**\n * Aplica estado disabled/loading a un clone de slot: deshabilita elementos\n * interactivos y añade clase para estilos. Respeta el estado del formulario.\n */\n private applySlotDisabledState(slotElement: HTMLElement): void {\n if (!this.disabled && !this.loading) return\n slotElement.classList.add('easy-form-slot-disabled')\n const interactives = slotElement.querySelectorAll<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement | HTMLButtonElement>(\n 'input, textarea, select, button'\n )\n interactives.forEach((el) => {\n if ('disabled' in el) el.disabled = true\n })\n }\n\n /**\n * Renderiza campos normales\n */\n private renderFields(container: HTMLElement, fields: Field[]) {\n // Si no hay campos, aún debemos soportar posibles slots al final\n if (fields.length === 0) {\n const slotClones = this.getSlotClonesByRow(0)\n const endSlots = slotClones.get(-1)\n if (endSlots && endSlots.length > 0) {\n for (const slotElement of endSlots) {\n this.applySlotDisabledState(slotElement)\n container.appendChild(slotElement)\n }\n }\n return\n }\n\n const totalRows = fields.length\n const slotClonesByRow = this.getSlotClonesByRow(totalRows)\n\n for (let rowIndex = 0; rowIndex < fields.length; rowIndex++) {\n // Insertar primero los slots asociados a este índice de fila\n const slotsForRow = slotClonesByRow.get(rowIndex)\n if (slotsForRow && slotsForRow.length > 0) {\n for (const slotElement of slotsForRow) {\n this.applySlotDisabledState(slotElement)\n container.appendChild(slotElement)\n }\n slotClonesByRow.delete(rowIndex)\n }\n\n const field = fields[rowIndex]\n const fieldElement = this.renderField(field)\n if (fieldElement) {\n container.appendChild(fieldElement)\n }\n }\n\n // Insertar cualquier slot restante (índice efectivo -1) al final del formulario\n const endSlots = slotClonesByRow.get(-1)\n if (endSlots && endSlots.length > 0) {\n for (const slotElement of endSlots) {\n this.applySlotDisabledState(slotElement)\n container.appendChild(slotElement)\n }\n }\n }\n\n /**\n * Renderiza un campo\n */\n private renderField(field: Field): HTMLElement | null {\n // Verificar visibilidad basada en dependencias\n const isVisible = this.stateManager.getFieldVisibility(field.name)\n const isEnabled = this.stateManager.getFieldEnabled(field.name)\n\n // Campos especiales\n if (field.type === 'group') {\n const groupElement = this.renderGroup(field)\n if (!isVisible) {\n groupElement.style.display = 'none'\n groupElement.classList.add('easy-form-field-hidden')\n }\n if (!isEnabled) {\n groupElement.classList.add('easy-form-field-disabled')\n }\n return groupElement\n }\n if (field.type === 'row') {\n const rowElement = this.renderRow(field)\n if (!isVisible) {\n rowElement.style.display = 'none'\n rowElement.classList.add('easy-form-field-hidden')\n }\n if (!isEnabled) {\n rowElement.classList.add('easy-form-field-disabled')\n }\n return rowElement\n }\n if (field.type === 'array') {\n const arrayElement = this.renderArray(field)\n if (!isVisible) {\n arrayElement.style.display = 'none'\n arrayElement.classList.add('easy-form-field-hidden')\n }\n if (!isEnabled) {\n arrayElement.classList.add('easy-form-field-disabled')\n }\n return arrayElement\n }\n if (field.type === 'custom') {\n const customElement = this.renderCustom(field)\n if (customElement) {\n if (!isVisible) {\n customElement.style.display = 'none'\n customElement.classList.add('easy-form-field-hidden')\n }\n if (!isEnabled) {\n customElement.classList.add('easy-form-field-disabled')\n }\n }\n return customElement\n }\n\n // Campos normales\n const value = this.stateManager.getValue(field.name)\n const errors = this.stateManager.getErrors(field.name)\n const error = errors.length > 0 ? errors[0] : undefined\n\n // Aplicar disabled basado en dependencias, disabled general o loading\n const isFormDisabled = this.disabled || this.loading\n const labelPositionAttr = this.getAttribute('label-position') as\n | 'up'\n | 'down'\n | 'left'\n | 'right'\n | 'none'\n | null\n const validLabelPositions = ['up', 'down', 'left', 'right', 'none']\n const effectiveLabelPosition =\n field.labelPosition ??\n (labelPositionAttr && validLabelPositions.includes(labelPositionAttr)\n ? labelPositionAttr\n : 'up')\n const fieldWithDependencies = {\n ...field,\n disabled: isFormDisabled || !isEnabled || field.disabled,\n labelPosition: effectiveLabelPosition,\n }\n\n const customComponent = getCustomComponent(field.type)\n if (customComponent) {\n const element = customComponent({\n field: fieldWithDependencies,\n value,\n error,\n onChange: (val) => this.handleFieldChange(field.name, val),\n onBlur: () => this.handleFieldBlur(field.name),\n })\n if (element && !isVisible) {\n element.style.display = 'none'\n element.classList.add('easy-form-field-hidden')\n }\n return element\n }\n\n const inputElement = createInput(\n fieldWithDependencies,\n value,\n error,\n (val) => this.handleFieldChange(field.name, val),\n () => this.handleFieldBlur(field.name)\n )\n\n // Agregar atributo para identificar el campo\n const fieldContainer = inputElement.querySelector('.easy-form-field') || inputElement\n if (fieldContainer instanceof HTMLElement) {\n fieldContainer.setAttribute('data-field-name', field.name)\n }\n\n // Aplicar clases para visibilidad\n if (!isVisible) {\n inputElement.style.display = 'none'\n inputElement.classList.add('easy-form-field-hidden')\n }\n\n return inputElement\n }\n\n /**\n * Renderiza un grupo de campos\n */\n private renderGroup(field: Field): HTMLElement {\n const groupField = field as {\n direction?: 'vertical' | 'horizontal'\n collapsible?: boolean\n defaultOpen?: boolean\n }\n const dir = groupField.direction ?? 'vertical'\n const collapsible = groupField.collapsible === true\n const defaultOpen = groupField.defaultOpen !== false\n\n const groupContainer = document.createElement('div')\n groupContainer.className = `easy-form-group easy-form-direction-${dir}`\n if (field.name) {\n groupContainer.setAttribute('data-field-name', field.name)\n }\n\n if (collapsible) {\n groupContainer.classList.add('easy-form-group-collapsible')\n if (!defaultOpen) {\n groupContainer.classList.add('easy-form-group-collapsed')\n }\n\n const header = document.createElement('button')\n header.type = 'button'\n header.className = 'easy-form-group-header'\n header.setAttribute('aria-expanded', String(defaultOpen))\n const groupContentId = `easy-form-group-${(field.name || 'group').replace(/[^a-z0-9]/gi, '-')}-content`\n header.setAttribute('aria-controls', groupContentId)\n\n const labelSpan = document.createElement('span')\n labelSpan.textContent = field.label || 'Grupo'\n\n const chevron = document.createElement('span')\n chevron.className = 'easy-form-group-chevron'\n chevron.setAttribute('aria-hidden', 'true')\n chevron.textContent = '▼'\n\n header.appendChild(labelSpan)\n header.appendChild(chevron)\n groupContainer.appendChild(header)\n\n const content = document.createElement('div')\n content.id = groupContentId\n content.className = 'easy-form-group-content'\n\n if ('fields' in field && field.fields) {\n for (const subField of field.fields) {\n const fullName = subField.name.startsWith(field.name + '.')\n ? subField.name\n : `${field.name}.${subField.name}`\n const subFieldWithPath = { ...subField, name: fullName }\n const fieldElement = this.renderField(subFieldWithPath)\n if (fieldElement) {\n content.appendChild(fieldElement)\n }\n }\n }\n\n groupContainer.appendChild(content)\n\n const setContentHeight = (open: boolean) => {\n if (open) {\n content.style.maxHeight = content.scrollHeight + 'px'\n } else {\n content.style.maxHeight = '0'\n }\n }\n\n if (defaultOpen) {\n requestAnimationFrame(() => setContentHeight(true))\n } else {\n content.style.maxHeight = '0'\n }\n\n header.addEventListener('click', () => {\n const isCollapsed = groupContainer.classList.contains('easy-form-group-collapsed')\n if (isCollapsed) {\n groupContainer.classList.remove('easy-form-group-collapsed')\n header.setAttribute('aria-expanded', 'true')\n setContentHeight(true)\n } else {\n content.style.maxHeight = content.scrollHeight + 'px'\n requestAnimationFrame(() => {\n groupContainer.classList.add('easy-form-group-collapsed')\n header.setAttribute('aria-expanded', 'false')\n setContentHeight(false)\n })\n }\n })\n } else {\n if (field.label) {\n const label = document.createElement('h3')\n label.className = 'easy-form-group-label'\n label.textContent = field.label\n groupContainer.appendChild(label)\n }\n\n if ('fields' in field && field.fields) {\n for (const subField of field.fields) {\n const fullName = subField.name.startsWith(field.name + '.')\n ? subField.name\n : `${field.name}.${subField.name}`\n const subFieldWithPath = { ...subField, name: fullName }\n const fieldElement = this.renderField(subFieldWithPath)\n if (fieldElement) {\n groupContainer.appendChild(fieldElement)\n }\n }\n }\n }\n\n return groupContainer\n }\n\n /**\n * Renderiza una fila de campos\n */\n private renderRow(field: Field): HTMLElement {\n const rowContainer = document.createElement('div')\n rowContainer.className = 'easy-form-row'\n\n const rowField = field as any\n\n // Aplicar estilos flexbox\n rowContainer.style.display = 'flex'\n rowContainer.style.flexWrap = 'wrap'\n rowContainer.style.alignItems = rowField.align || 'stretch'\n\n // Aplicar gap\n if (rowField.gap !== undefined) {\n const gapValue = typeof rowField.gap === 'number' ? `${rowField.gap}px` : rowField.gap\n rowContainer.style.gap = gapValue\n } else {\n rowContainer.style.gap = '1rem'\n }\n\n // Renderizar campos dentro de la fila\n if ('fields' in field && field.fields) {\n for (const subField of field.fields) {\n const fieldElement = this.renderField(subField)\n if (fieldElement) {\n // Hacer que cada campo en la fila tenga flex: 1 para distribuirse equitativamente\n const fieldWrapper = document.createElement('div')\n fieldWrapper.style.flex = '1'\n fieldWrapper.style.minWidth = '0' // Permite que los campos se reduzcan\n fieldWrapper.appendChild(fieldElement)\n rowContainer.appendChild(fieldWrapper)\n }\n }\n }\n\n return rowContainer\n }\n\n /**\n * Renderiza un array dinámico\n */\n private renderArray(field: Field): HTMLElement {\n const arrayContainer = document.createElement('div')\n arrayContainer.className = 'easy-form-array'\n arrayContainer.setAttribute('data-field-name', field.name)\n\n if (field.label) {\n const label = document.createElement('label')\n label.className = 'easy-form-label'\n label.textContent = field.label\n arrayContainer.appendChild(label)\n }\n\n const values = this.stateManager.getValue(field.name) || []\n const arrayField = field as { itemSchema?: { fields?: Field[] }; minItems?: number; maxItems?: number }\n const minItems = arrayField.minItems ?? 0\n const maxItems = arrayField.maxItems ?? Infinity\n\n // Renderizar items existentes\n const itemsContainer = document.createElement('div')\n itemsContainer.className = 'easy-form-array-items'\n\n for (let i = 0; i < values.length; i++) {\n const itemContainer = document.createElement('div')\n itemContainer.className = 'easy-form-array-item'\n\n if (arrayField.itemSchema?.fields) {\n for (const itemField of arrayField.itemSchema.fields) {\n const itemFieldWithName = {\n ...itemField,\n name: `${field.name}.${i}.${itemField.name}`,\n }\n const fieldElement = this.renderField(itemFieldWithName)\n if (fieldElement) {\n itemContainer.appendChild(fieldElement)\n }\n }\n }\n\n // Botón eliminar\n const removeButton = document.createElement('button')\n removeButton.type = 'button'\n removeButton.textContent = 'Eliminar'\n removeButton.className = 'easy-form-array-remove'\n const atMinItems = values.length <= minItems\n if (this.disabled || this.loading || atMinItems) {\n removeButton.disabled = true\n } else {\n removeButton.addEventListener('click', () => {\n const newValues = [...values]\n newValues.splice(i, 1)\n this.handleFieldChange(field.name, newValues)\n })\n }\n itemContainer.appendChild(removeButton)\n\n itemsContainer.appendChild(itemContainer)\n }\n\n arrayContainer.appendChild(itemsContainer)\n\n // Botón agregar\n const addButton = document.createElement('button')\n addButton.type = 'button'\n addButton.textContent = 'Agregar'\n addButton.className = 'easy-form-array-add'\n const atMaxItems = values.length >= maxItems\n if (this.disabled || this.loading || atMaxItems) {\n addButton.disabled = true\n } else {\n addButton.addEventListener('click', () => {\n const newItem = this.stateManager.createDefaultArrayItem(field)\n const newValues = [...values, newItem]\n this.handleFieldChange(field.name, newValues)\n })\n }\n arrayContainer.appendChild(addButton)\n\n return arrayContainer\n }\n\n /**\n * Renderiza un campo custom\n */\n private renderCustom(field: Field): HTMLElement | null {\n const customComponent = getCustomComponent('custom')\n if (!customComponent) {\n const div = document.createElement('div')\n div.textContent = `Componente custom no registrado para: ${field.name}`\n return div\n }\n\n const value = this.stateManager.getValue(field.name)\n const errors = this.stateManager.getErrors(field.name)\n const error = errors.length > 0 ? errors[0] : undefined\n\n return customComponent({\n field,\n value,\n error,\n onChange: (val) => this.handleFieldChange(field.name, val),\n onBlur: () => this.handleFieldBlur(field.name),\n })\n }\n\n /**\n * Obtiene el progreso de campos obligatorios completados\n */\n private getCompletedRequiredProgress(schema: FormSchema): { completed: number; total: number } {\n const extractFields = (fields: Field[]): Field[] => {\n const result: Field[] = []\n for (const f of fields) {\n if (f.type === 'array' && 'itemSchema' in f && f.itemSchema?.fields) {\n const items = this.stateManager.getValue(f.name) as any[]\n const count = Array.isArray(items) ? items.length : 0\n for (let i = 0; i < count; i++) {\n for (const sf of f.itemSchema.fields) {\n result.push({ ...sf, name: `${f.name}.${i}.${sf.name}` } as Field)\n }\n }\n } else if ((f.type === 'group' || f.type === 'row') && 'fields' in f && f.fields) {\n result.push(...extractFields(f.fields))\n } else {\n result.push(f)\n }\n }\n return result\n }\n\n const fields = schema.steps\n ? (this.stateManager.getCurrentStepFields() || [])\n : schema.fields || []\n const allFields = extractFields(fields)\n const requiredFields = allFields.filter(\n (f) => f.validations?.some((v) => v.type === 'required')\n )\n const visibleRequired = requiredFields.filter((f) =>\n this.stateManager.getFieldVisibility(f.name)\n )\n const total = visibleRequired.length\n const completed = visibleRequired.filter((f) => {\n const errors = this.stateManager.getErrors(f.name)\n if (errors.length > 0) return false\n const val = this.stateManager.getValue(f.name)\n if (val === null || val === undefined) return false\n if (typeof val === 'string' && val.trim() === '') return false\n if (Array.isArray(val) && val.length === 0 && f.type === 'array') return false\n return true\n }).length\n return { completed, total }\n }\n\n /**\n * Renderiza wizard\n */\n private renderWizard(container: HTMLElement, schema: FormSchema) {\n // Obtener el estado actualizado del wizard\n const wizardState = this.stateManager.getWizardState()\n if (!wizardState) return\n\n const wizardContainer = document.createElement('div')\n wizardContainer.className = 'easy-form-wizard'\n\n // Indicador de steps\n const stepsIndicator = document.createElement('div')\n stepsIndicator.className = 'easy-form-wizard-steps'\n if (schema?.steps) {\n for (let i = 0; i < schema.steps.length; i++) {\n const stepEl = document.createElement('div')\n stepEl.className = 'easy-form-wizard-step'\n if (i === wizardState.currentStep) {\n stepEl.classList.add('active')\n }\n if (wizardState.completedSteps.includes(i)) {\n stepEl.classList.add('completed')\n }\n stepEl.textContent = schema.steps[i].title\n stepsIndicator.appendChild(stepEl)\n }\n }\n wizardContainer.appendChild(stepsIndicator)\n\n // Campos del step actual (con soporte de slots por row, scoped al step actual)\n const fieldsContainer = document.createElement('div')\n fieldsContainer.className = 'easy-form-wizard-fields'\n const currentFields = this.stateManager.getCurrentStepFields()\n this.renderFields(fieldsContainer, currentFields)\n wizardContainer.appendChild(fieldsContainer)\n\n // Botones de navegación\n const navContainer = document.createElement('div')\n navContainer.className = 'easy-form-wizard-nav'\n\n // Botón Anterior (solo si no es el primer paso)\n if (wizardState.currentStep > 0) {\n const prevButton = document.createElement('button')\n prevButton.type = 'button'\n prevButton.textContent = 'Anterior'\n prevButton.className = 'easy-form-wizard-prev'\n if (this.disabled || this.loading) {\n prevButton.disabled = true\n } else {\n prevButton.addEventListener('click', () => {\n const currentState = this.stateManager.getWizardState()\n if (currentState && this.stateManager.previousStep()) {\n this.render()\n this.emitStepChange()\n }\n })\n }\n navContainer.appendChild(prevButton)\n }\n\n // Botón Siguiente (solo si NO es el último paso)\n if (wizardState.currentStep < wizardState.totalSteps - 1) {\n const nextButton = document.createElement('button')\n nextButton.type = 'button'\n nextButton.textContent = 'Siguiente'\n nextButton.className = 'easy-form-wizard-next'\n if (this.disabled || this.loading) {\n nextButton.disabled = true\n } else {\n nextButton.addEventListener('click', async () => {\n // Obtener el estado actual del wizard\n const currentState = this.stateManager.getWizardState()\n if (!currentState) return\n\n // Validar solo los campos del step actual antes de avanzar\n const currentFields = this.stateManager.getCurrentStepFields()\n \n // Validar cada campo del paso actual\n for (const field of currentFields) {\n // Solo validar campos visibles\n if (this.stateManager.getFieldVisibility(field.name)) {\n await this.stateManager.validateField(field.name)\n }\n }\n \n // Obtener errores después de validar\n const allErrors = this.stateManager.getAllErrors()\n const stepErrors: Record<string, string[]> = {}\n \n // Filtrar solo errores de campos del paso actual\n for (const field of currentFields) {\n if (allErrors[field.name] && allErrors[field.name].length > 0) {\n stepErrors[field.name] = allErrors[field.name]\n }\n }\n\n const hasErrors = Object.keys(stepErrors).length > 0\n\n if (!hasErrors) {\n // Marcar el paso actual como completado\n this.stateManager.completeStep(currentState.currentStep)\n \n // Avanzar al siguiente paso\n const moved = this.stateManager.nextStep()\n if (moved) {\n // Renderizar después de actualizar el estado\n // El render preservará el estado actualizado (con el nuevo paso)\n this.render()\n this.emitStepChange()\n }\n } else {\n this.emitError(stepErrors)\n }\n })\n }\n navContainer.appendChild(nextButton)\n }\n\n // Botón Enviar (solo en el último paso)\n const submitConfig = this.getSubmitButtonConfig(schema)\n if (\n wizardState.currentStep === wizardState.totalSteps - 1 &&\n submitConfig.visible\n ) {\n const submitButton = document.createElement('button')\n submitButton.type = 'button'\n submitButton.textContent = submitConfig.text\n submitButton.className = 'easy-form-wizard-next'\n submitButton.style.width = submitConfig.width\n if (this.disabled || this.loading) {\n submitButton.disabled = true\n } else {\n submitButton.addEventListener('click', async () => {\n // Validar todos los campos del último paso antes de enviar\n const currentFields = this.stateManager.getCurrentStepFields()\n \n // Validar cada campo del paso actual\n for (const field of currentFields) {\n // Solo validar campos visibles\n if (this.stateManager.getFieldVisibility(field.name)) {\n await this.stateManager.validateField(field.name)\n }\n }\n \n // Obtener errores después de validar\n const allErrors = this.stateManager.getAllErrors()\n const stepErrors: Record<string, string[]> = {}\n \n // Filtrar solo errores de campos del paso actual\n for (const field of currentFields) {\n if (allErrors[field.name] && allErrors[field.name].length > 0) {\n stepErrors[field.name] = allErrors[field.name]\n }\n }\n\n const hasErrors = Object.keys(stepErrors).length > 0\n\n if (!hasErrors) {\n await this.handleSubmit(new Event('submit') as SubmitEvent)\n } else {\n this.emitError(stepErrors)\n }\n })\n }\n navContainer.appendChild(submitButton)\n }\n\n wizardContainer.appendChild(navContainer)\n container.appendChild(wizardContainer)\n }\n\n /**\n * Maneja el cambio de un campo\n */\n private async handleFieldChange(fieldName: string, value: any) {\n await this.stateManager.setValue(fieldName, value)\n \n // Si es un array, re-renderizar para reflejar add/remove\n const schema = this.schema\n if (schema) {\n const field = this.findFieldInSchema(schema, fieldName)\n if (field?.type === 'array') {\n const replaced = this.rerenderArrayField(field)\n // Si no se encontró el contenedor, hacer render completo (ej. array dentro de row/group)\n if (!replaced) {\n this.skipPreserveValuesOnNextRender = true\n requestAnimationFrame(() => this.render())\n }\n }\n }\n \n // Obtener campos dependientes que necesitan re-renderizarse\n const dependentFields = this.stateManager.getDependentFields(fieldName)\n \n // Re-renderizar campos dependientes si hay cambios en dependencias\n if (dependentFields.length > 0) {\n // Usar un pequeño delay para agrupar múltiples cambios\n if (this.dependencyRenderTimeout) {\n clearTimeout(this.dependencyRenderTimeout)\n }\n \n this.dependencyRenderTimeout = setTimeout(() => {\n this.renderDependentFields(dependentFields)\n this.emitDependencyChange(fieldName, dependentFields)\n }, 10)\n }\n\n // Emitir evento change\n const changeEvent = new CustomEvent<ChangeEventDetail>('change', {\n detail: {\n field: fieldName,\n value,\n values: this.stateManager.getState().values,\n },\n bubbles: true,\n composed: true,\n })\n this.dispatchEvent(changeEvent)\n }\n\n private dependencyRenderTimeout: ReturnType<typeof setTimeout> | null = null\n\n /**\n * Re-renderiza un campo array cuando se añaden o eliminan ítems.\n * Retorna true si se reemplazó, false si no se encontró el contenedor.\n */\n private rerenderArrayField(field: Field): boolean {\n const arrayContainer = this.shadow.querySelector(\n `[data-field-name=\"${field.name}\"].easy-form-array`\n )\n if (!arrayContainer?.parentNode) return false\n\n const newArrayElement = this.renderArray(field)\n arrayContainer.parentNode.replaceChild(newArrayElement, arrayContainer)\n return true\n }\n\n /**\n * Re-renderiza campos dependientes\n */\n private renderDependentFields(fieldNames: string[]): void {\n const form = this.shadow.querySelector('form')\n if (!form) return\n\n const schema = this.schema\n if (!schema) return\n\n for (const fieldName of fieldNames) {\n const fieldContainer =\n form.querySelector(`.easy-form-field[name=\"${fieldName}\"], [data-field-name=\"${fieldName}\"]`)?.closest('.easy-form-field') ??\n form.querySelector(`[data-field-name=\"${fieldName}\"]`)\n\n if (fieldContainer) {\n const field = this.findFieldInSchema(schema, fieldName)\n if (!field) continue\n\n // Re-renderizar el campo\n const newFieldElement = this.renderField(field)\n if (newFieldElement && fieldContainer.parentNode) {\n fieldContainer.parentNode.replaceChild(newFieldElement, fieldContainer)\n }\n }\n }\n }\n\n /**\n * Emite evento de cambio de dependencia\n */\n private emitDependencyChange(\n changedField: string,\n affectedFields: string[]\n ): void {\n const dependencyEvent = new CustomEvent('dependencyChange', {\n detail: {\n changedField,\n affectedFields,\n },\n bubbles: true,\n composed: true,\n })\n this.dispatchEvent(dependencyEvent)\n }\n\n /**\n * Maneja el blur de un campo\n */\n private async handleFieldBlur(fieldName: string) {\n this.stateManager.setTouched(fieldName)\n // Validar solo el campo que perdió el foco\n await this.stateManager.validateField(fieldName)\n // Actualizar solo el campo específico sin re-renderizar todo el formulario\n this.updateSingleField(fieldName)\n }\n\n /**\n * Actualiza solo un campo específico sin re-renderizar todo el formulario\n */\n private updateSingleField(fieldName: string) {\n const schema = this.schema\n if (!schema) return\n\n const field = this.findFieldInSchema(schema, fieldName)\n if (!field) return\n\n const errors = this.stateManager.getErrors(fieldName)\n const error = errors.length > 0 ? errors[0] : undefined\n\n // Buscar el contenedor del campo en el DOM\n const fieldContainer = this.shadow.querySelector(`[name=\"${fieldName}\"]`)?.closest('.easy-form-field')\n if (!fieldContainer) return\n\n // Actualizar el error\n const errorElement = fieldContainer.querySelector('.easy-form-error')\n if (error) {\n if (!errorElement) {\n const errorEl = document.createElement('p')\n errorEl.className = 'easy-form-error'\n errorEl.textContent = error\n fieldContainer.appendChild(errorEl)\n } else {\n errorElement.textContent = error\n }\n // Agregar clase de error al input\n const input = fieldContainer.querySelector('input, textarea, select') as HTMLElement\n input?.classList.add('easy-form-input-error')\n } else {\n errorElement?.remove()\n const input = fieldContainer.querySelector('input, textarea, select') as HTMLElement\n input?.classList.remove('easy-form-input-error')\n }\n }\n\n /**\n * Busca un campo por nombre en el schema (soporta rutas como 'group.subfield')\n */\n private findFieldInSchema(schema: FormSchema, name: string): Field | null {\n const fields = schema.fields || []\n const dot = name.indexOf('.')\n if (dot > 0) {\n const parentName = name.slice(0, dot)\n const childName = name.slice(dot + 1)\n const parent = fields.find((f) => f.name === parentName)\n if (!parent) return null\n if ((parent.type === 'group' || parent.type === 'row') && 'fields' in parent && parent.fields) {\n const found = this.findFieldInSchema({ fields: parent.fields }, childName)\n return found ? { ...found, name } : null\n }\n return null\n }\n for (const field of fields) {\n if (field.name === name) {\n return field\n }\n if (field.type === 'group' && 'fields' in field) {\n const found = this.findFieldInSchema({ fields: field.fields }, name)\n if (found) return found\n }\n if (field.type === 'row' && 'fields' in field) {\n const found = this.findFieldInSchema({ fields: field.fields }, name)\n if (found) return found\n }\n }\n return null\n }\n\n /**\n * Maneja el submit del formulario\n */\n private async handleSubmit(event: Event) {\n event.preventDefault()\n\n if (this.attemptsLock?.isLocked()) {\n return\n }\n\n const errors = await this.stateManager.validateForm()\n const state = this.stateManager.getState()\n\n if (Object.keys(errors).length > 0) {\n this.emitError(errors)\n this.render()\n return\n }\n\n // Emitir evento submit\n const submitEvent = new CustomEvent<SubmitEventDetail>('submit', {\n detail: {\n values: state.values,\n isValid: true,\n errors: {},\n },\n bubbles: true,\n composed: true,\n })\n this.dispatchEvent(submitEvent)\n }\n\n /**\n * Emite evento de error\n */\n private emitError(errors: Record<string, string[]>) {\n const errorEvent = new CustomEvent<ErrorEventDetail>('error', {\n detail: {\n errors,\n },\n bubbles: true,\n composed: true,\n })\n this.dispatchEvent(errorEvent)\n }\n\n /**\n * Emite evento de cambio de step\n */\n private emitStepChange() {\n const wizardState = this.stateManager.getWizardState()\n if (!wizardState) return\n\n const stepChangeEvent = new CustomEvent<StepChangeEventDetail>(\n 'stepChange',\n {\n detail: {\n currentStep: wizardState.currentStep,\n previousStep:\n wizardState.currentStep > 0\n ? wizardState.currentStep - 1\n : wizardState.currentStep,\n totalSteps: wizardState.totalSteps,\n },\n bubbles: true,\n composed: true,\n }\n )\n this.dispatchEvent(stepChangeEvent)\n }\n\n /**\n * Registra componentes personalizados\n */\n public registerComponents(components: ComponentRegistry): void {\n this.customComponents = { ...this.customComponents, ...components }\n registerComponents(components)\n }\n\n /**\n * Resetea el formulario a sus valores iniciales\n */\n public reset(): void {\n this.stateManager.reset()\n this.render()\n }\n\n /**\n * Incrementa el contador de intentos (para bloqueo por intentos fallidos).\n * El consumidor debe llamar esto cuando la API/login falle.\n */\n public incrementAttempts(): void {\n this.attemptsLock?.incrementAttempts()\n if (this.attemptsLock?.isLocked()) {\n this.updateLockOverlay()\n }\n }\n\n /**\n * Resetea el contador de intentos y desbloquea el formulario.\n */\n public resetAttempts(): void {\n this.attemptsLock?.reset()\n this.stopLockCountdown()\n this.updateLockOverlay()\n this.render()\n }\n\n /**\n * Retorna true si el formulario está bloqueado por intentos.\n */\n public isLocked(): boolean {\n return this.attemptsLock?.isLocked() ?? false\n }\n\n /**\n * Retorna los milisegundos restantes del bloqueo, o 0 si no está bloqueado.\n */\n public getRemainingBlockTimeMs(): number {\n return this.attemptsLock?.getRemainingBlockTimeMs() ?? 0\n }\n\n /**\n * Dispara el submit del formulario programáticamente.\n * Útil cuando el botón submit está oculto (visible: false).\n */\n public requestSubmit(): void {\n const form = this.shadow.querySelector('form')\n if (form && typeof (form as HTMLFormElement).requestSubmit === 'function') {\n ;(form as HTMLFormElement).requestSubmit()\n }\n }\n\n /**\n * Limpia todos los valores del formulario\n */\n public clear(): void {\n const schema = this.schema\n const templateName = this.template\n let currentSchema: FormSchema | null = null\n \n if (templateName) {\n currentSchema = this.getSchemaFromTemplate(templateName)\n } else {\n currentSchema = schema\n }\n \n if (currentSchema) {\n this.stateManager.initializeSchema(currentSchema, {})\n this.render()\n }\n }\n\n /**\n * Obtiene todos los valores del formulario\n */\n public getValues(): Record<string, any> {\n return this.stateManager.getState().values\n }\n\n /**\n * Obtiene el valor de un campo específico\n */\n public getValue(fieldName: string): any {\n return this.stateManager.getValue(fieldName)\n }\n\n /**\n * Establece el valor de un campo específico\n */\n public async setValue(fieldName: string, value: any): Promise<void> {\n await this.stateManager.setValue(fieldName, value)\n this.render()\n }\n\n /**\n * Establece múltiples valores a la vez\n */\n public async setValues(values: Record<string, any>): Promise<void> {\n for (const [fieldName, value] of Object.entries(values)) {\n await this.stateManager.setValue(fieldName, value)\n }\n this.render()\n }\n\n /**\n * Valida el formulario completo\n */\n public async validate(): Promise<Record<string, string[]>> {\n const errors = await this.stateManager.validateForm()\n this.render()\n if (Object.keys(errors).length > 0) {\n this.emitError(errors)\n }\n return errors\n }\n\n /**\n * Valida un campo específico\n */\n public async validateField(fieldName: string): Promise<string[]> {\n await this.stateManager.validateField(fieldName)\n this.updateSingleField(fieldName)\n return this.stateManager.getErrors(fieldName)\n }\n\n /**\n * Obtiene todos los errores del formulario\n */\n public getErrors(): Record<string, string[]> {\n return this.stateManager.getAllErrors()\n }\n\n /**\n * Obtiene los errores de un campo específico\n */\n public getFieldErrors(fieldName: string): string[] {\n return this.stateManager.getErrors(fieldName)\n }\n\n /**\n * Verifica si el formulario es válido\n */\n public isValid(): boolean {\n return this.stateManager.getState().isValid\n }\n\n /**\n * Obtiene el tema del formulario\n */\n get theme(): FormTheme {\n const themeAttr = this.getAttribute('theme')\n const validThemes: FormTheme[] = [\n 'plano',\n 'tradicional',\n 'material',\n 'rounded-shadow',\n 'lines',\n 'shadcn',\n 'chakra',\n 'mantine',\n 'glass',\n 'bordered',\n 'minimal',\n 'efc'\n ]\n if (themeAttr && validThemes.includes(themeAttr as FormTheme)) {\n return themeAttr as FormTheme\n }\n return 'plano' // Tema por defecto\n }\n\n /**\n * Establece el tema del formulario\n */\n set theme(value: FormTheme) {\n if (value) {\n this.setAttribute('theme', value)\n } else {\n this.removeAttribute('theme')\n }\n }\n\n /**\n * Obtiene los colores personalizados\n */\n get colors(): FormColors | null {\n const colorsAttr = this.getAttribute('colors')\n if (!colorsAttr) return null\n return parseAttributeValue(colorsAttr)\n }\n\n /**\n * Establece los colores personalizados\n */\n set colors(value: FormColors | null) {\n if (value) {\n this.setAttribute('colors', attributeValue(value))\n } else {\n this.removeAttribute('colors')\n }\n }\n\n /**\n * Obtiene los datos iniciales\n */\n get initialData(): Record<string, any> | null {\n const initialDataAttr = this.getAttribute('initialData')\n if (!initialDataAttr) return null\n return parseAttributeValue(initialDataAttr)\n }\n\n /**\n * Establece los datos iniciales\n */\n set initialData(value: Record<string, any> | null) {\n if (value) {\n this.setAttribute('initialData', attributeValue(value))\n } else {\n this.removeAttribute('initialData')\n }\n }\n\n /**\n * Obtiene el estado de loading\n */\n get loading(): boolean {\n return this.hasAttribute('loading')\n }\n\n /**\n * Establece el estado de loading\n */\n set loading(value: boolean) {\n if (value) {\n this.setAttribute('loading', '')\n } else {\n this.removeAttribute('loading')\n }\n }\n\n /**\n * Obtiene el estado de disabled\n */\n get disabled(): boolean {\n return this.hasAttribute('disabled')\n }\n\n /**\n * Establece el estado de disabled\n */\n set disabled(value: boolean) {\n if (value) {\n this.setAttribute('disabled', '')\n } else {\n this.removeAttribute('disabled')\n }\n }\n\n /**\n * Configura estilos básicos\n */\n private setupStyles() {\n // Eliminar estilos anteriores si existen\n const existingStyle = this.shadow.querySelector('style')\n if (existingStyle) {\n existingStyle.remove()\n }\n\n const theme = this.theme\n const colors = getColors(this.colors || undefined)\n const styles = getThemeStyles(theme, colors)\n\n const style = document.createElement('style')\n style.textContent = styles\n \n // Insertar estilos ANTES de cualquier otro contenido para asegurar que se apliquen\n if (this.shadow.firstChild) {\n this.shadow.insertBefore(style, this.shadow.firstChild)\n } else {\n this.shadow.appendChild(style)\n }\n }\n}\n\n// Registrar el Web Component solo en el navegador\nif (typeof window !== 'undefined' && typeof customElements !== 'undefined' && !customElements.get('easy-form')) {\n customElements.define('easy-form', EasyForm)\n}\n"],"mappings":"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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA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,EAAuC,CAC/D,MAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GA0MT,CAMA,SAASD,GAAaC,EAAuC,CAC3D,MAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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","names":["SchemaParser","schema","step","normalizedFields","normalizedSteps","fields","field","index","min","max","slot","fieldName","slotName","defaults","parsed","allFields","extractFields","hexToRgb","hex","result","short","defaultColors","getColors","colors","getThemeStyles","theme","baseStyles","getBaseStyles","themeStyles","getThemeSpecificStyles","getPlanoStyles","getTradicionalStyles","getMaterialStyles","getRoundedShadowStyles","getLinesStyles","getShadcnStyles","getChakraStyles","getMantineStyles","getGlassStyles","getBorderedStyles","getMinimalStyles","getEfcStyles","_colors","PREDEFINED_MASKS","value","cleaned","getPredefinedMask","type","INJECTION_VALIDATION_MESSAGE","INJECTION_PATTERNS","containsInjection","value","pattern","isSafeFromInjection","item","v","AttemptsLock","options","stored","data","attributeValue","value","parseAttributeValue","getNestedValue","obj","path","current","key","setNestedValue","value","keys","lastKey","target","isValidEmail","email","ValidationEngine","field","value","_field","validations","errors","validation","result","isValid","isValidEmail","minLength","maxLength","min","num","max","pattern","regex","isSafeFromInjection","INJECTION_VALIDATION_MESSAGE","values","showDep","action","dep","depValue","isConditionMet","fields","fieldErrors","ConditionEngine","condition","formValues","fieldValue","conditions","logic","conditionsArray","dependencies","visible","enabled","required","shouldHide","shouldDisable","shouldBeOptional","fieldName","parts","value","part","operator","compareValue","a","b","val","index","keysA","keysB","key","parsed","StateManager","SchemaParser","ValidationEngine","ConditionEngine","schema","initialData","fields","allFields","field","topLevelNames","f","arrayItemNames","sub","fieldName","parentPath","currentPath","found","topLevelFields","step","observedFields","observedField","dependencies","extractFromCondition","condition","extractFromConditions","conditions","existingValues","values","key","value","setNestedValue","existingValue","getNestedValue","prevValue","arrayItemOnlyNames","arrayField","minItems","arr","padded","i","item","subField","name","itemFields","dependentFields","dependentField","activeValidations","errors","validations","textFieldTypes","skipInjection","v","isRequired","hasRequiredValidation","conditional","stepIndex","isSubmitting","cached","fieldFullPath","groupPath","valuesContext","groupValues","createRelativeContext","obj","prefix","result","relativeKey","relativeContext","hasRequired","BaseInput","field","value","error","onChange","onBlur","rawInput","leading","trailing","wrapper","slotEl","inputWrap","slot","container","img","input","componentContainerClasses","cls","labelPosition","inputToAppend","el","label","v","required","inner","description","errorEl","element","key","parseMaskPattern","pattern","tokens","i","char","formatValue","value","result","valueIndex","token","unformatValue","tokenIndex","nextToken","getNextEditablePosition","position","direction","getMaskPlaceholder","placeholder","calculateCursorPosition","oldValue","newValue","oldCursorPosition","editableBeforeOld","editableCount","MaskEngine","mask","getPredefinedMask","customMask","cacheKey","tokens","parseMaskPattern","value","editableTokens","t","acceptedTypes","unformatted","char","formatted","formatValue","unformatValue","getMaskPlaceholder","position","token","input","previousValue","cursorPosition","unformattedInput","newCursorPosition","calculateCursorPosition","key","currentValue","isBackspace","prevEditable","getNextEditablePosition","before","after","newValue","newPos","nextEditable","TextInput","BaseInput","field","value","error","onChange","onBlur","MaskEngine","input","displayValue","maskPlaceholder","e","target","cursorPosition","inputValue","result","valueToEmit","isBackspace","pastedText","before","after","newValue","NumberInput","BaseInput","field","value","error","onChange","onBlur","MaskEngine","input","displayValue","numberField","maskPlaceholder","e","target","cursorPosition","inputValue","result","numValue","unformatted","isBackspace","pastedText","before","after","newValue","TextareaInput","BaseInput","textarea","textareaField","e","target","SelectInput","BaseInput","select","selectField","placeholderOption","option","optionEl","updatePlaceholderClass","e","target","selectedValues","opt","CheckboxInput","BaseInput","checkbox","e","target","container","label","labelText","description","errorEl","RadioInput","BaseInput","container","label","v","required","radioGroup","radioField","option","optionValue","optionLabel","radioContainer","radio","description","errorEl","SwitchInput","BaseInput","switchEl","e","target","container","label","labelText","description","errorEl","DateInput","BaseInput","input","dateField","date","e","target","FileInput","BaseInput","input","fileField","e","target","QuantityInput","BaseInput","container","quantityField","min","max","step","currentValue","inputWrapper","decrementBtn","input","incrementBtn","newValue","updateButtons","e","target","numValue","value","AccordionSelectInput","BaseInput","container","accordionField","selectedValue","option","index","optionValue","optionLabel","optionDescription","accordionItem","header","headerContent","indicator","label","arrow","content","description","customContent","toggleAccordion","isOpen","item","otherHeader","otherContent","otherArrow","selectOption","currentValues","itemIndicator","e","ImageGridSelectInput","BaseInput","container","imageGridField","selectedValue","columns","imageSize","option","optionValue","optionLabel","optionImage","optionDescription","gridItem","imageContainer","img","placeholder","indicator","label","description","selectOption","currentValues","index","item","itemIndicator","e","OTPInput","BaseInput","container","length","value","valueString","input","currentIndex","e","target","inputValue","digits","j","nextEmptyIndex","otpValue","otpField","finalValue","DEFAULT_SEPARATED_LENGTH","eyeSvg","visible","PasswordInput","BaseInput","pf","useSeparated","length","showToggle","input","e","wrapper","btn","value","valueString","container","i","currentIndex","chars","j","nextIdx","toggleWrap","type","inp","FileDropInput","BaseInput","fileDropField","accept","multiple","dropZone","hiddenInput","label","fileList","renderFileList","files","names","f","name","item","handleFiles","arr","e","target","LEAFLET_CSS","MapInput","BaseInput","mapField","center","zoom","value","lat","lng","container","inputsWrapper","latInput","lngInput","updateFromInputs","latVal","lngVal","mapContainer","linkId","cssLoaded","link","resolve","checkReady","L","tileLayer","invalidateSize","entries","entry","pos","e","newLat","newLng","STAR_SVG","filled","RatingInput","BaseInput","ratingField","max","half","currentValue","container","starsContainer","starWrapper","e","rect","val","mid","cur","newVal","value","star","idx","SliderInput","BaseInput","sliderField","min","max","step","showValue","input","e","target","val","valueSpan","wrapper","HEX_REGEX","toHex","value","m","ColorInput","BaseInput","defaultValue","currentValue","wrapper","colorPicker","textInput","syncFromPicker","hex","syncFromText","raw","createInput","field","value","error","onChange","onBlur","TextInput","PasswordInput","NumberInput","TextareaInput","SelectInput","CheckboxInput","RadioInput","SwitchInput","DateInput","FileInput","FileDropInput","MapInput","RatingInput","SliderInput","ColorInput","QuantityInput","AccordionSelectInput","ImageGridSelectInput","OTPInput","div","customComponents","registerComponent","type","component","registerComponents","components","getCustomComponent","loginTemplate","registerTemplate","value","otpTemplate","contactTemplate","passwordResetTemplate","passwordChangeTemplate","profileTemplate","checkoutTemplate","feedbackTemplate","subscriptionTemplate","bookingTemplate","reviewTemplate","templates","getTemplate","templateName","extendTemplate","templateName","additionalFields","baseTemplate","getTemplate","existingFields","existingSteps","lastStep","BrowserHTMLElement","EasyForm","StateManager","schemaAttr","parseAttributeValue","value","attributeValue","templateAttr","extendAttr","attr","n","schema","fromAttr","merged","name","oldValue","newValue","form","input","maxAttempts","AttemptsLock","templateName","initialData","baseTemplate","getTemplate","additionalFields","extendTemplate","isArrayRefresh","preservedValues","previousWizardState","key","wasWizard","isWizard","wizardState","completedStep","finalWizardState","newFormElement","e","directionAttr","direction","showCompletedAttr","completedIndicator","completedPosition","submitConfig","submitWrapper","submitButton","formWrapper","completed","total","progressBar","track","fill","oldForm","oldWrapper","formElement","existingOverlay","overlay","message","updateCountdown","remainingMs","minutes","seconds","timeStr","spinner","currentSchema","inputs","opt","elements","child","el","raw","parsed","row","totalRows","result","template","effectiveRow","clone","existing","slotElement","container","fields","endSlots","slotClonesByRow","rowIndex","slotsForRow","field","fieldElement","isVisible","isEnabled","groupElement","rowElement","arrayElement","customElement","errors","error","isFormDisabled","labelPositionAttr","validLabelPositions","effectiveLabelPosition","fieldWithDependencies","customComponent","getCustomComponent","element","val","inputElement","createInput","fieldContainer","groupField","dir","collapsible","defaultOpen","groupContainer","header","groupContentId","labelSpan","chevron","content","subField","fullName","subFieldWithPath","setContentHeight","open","label","rowContainer","rowField","gapValue","fieldWrapper","arrayContainer","values","arrayField","minItems","maxItems","itemsContainer","i","itemContainer","itemField","itemFieldWithName","removeButton","atMinItems","newValues","addButton","atMaxItems","newItem","div","extractFields","f","items","count","sf","visibleRequired","v","wizardContainer","stepsIndicator","stepEl","fieldsContainer","currentFields","navContainer","prevButton","nextButton","currentState","allErrors","stepErrors","fieldName","dependentFields","changeEvent","newArrayElement","fieldNames","newFieldElement","changedField","affectedFields","dependencyEvent","errorElement","errorEl","dot","parentName","childName","parent","found","event","state","submitEvent","errorEvent","stepChangeEvent","components","registerComponents","themeAttr","colorsAttr","initialDataAttr","existingStyle","theme","colors","getColors","styles","getThemeStyles","style"]}
1
+ {"version":3,"sources":["../src/core/schema-parser.ts","../src/utils/styles.ts","../src/utils/masks.ts","../src/utils/injection-validation.ts","../src/utils/attempts-lock.ts","../src/utils/index.ts","../src/core/validation-engine.ts","../src/core/condition-engine.ts","../src/core/state-manager.ts","../src/components/inputs/base-input.ts","../src/utils/mask-helpers.ts","../src/core/mask-engine.ts","../src/components/inputs/text-input.ts","../src/components/inputs/number-input.ts","../src/components/inputs/textarea-input.ts","../src/components/inputs/select-input.ts","../src/components/inputs/checkbox-input.ts","../src/components/inputs/radio-input.ts","../src/components/inputs/switch-input.ts","../src/components/inputs/date-input.ts","../src/components/inputs/file-input.ts","../src/components/inputs/quantity-input.ts","../src/components/inputs/accordion-select-input.ts","../src/components/inputs/image-grid-select-input.ts","../src/components/inputs/otp-input.ts","../src/components/inputs/password-input.ts","../src/components/inputs/file-drop-input.ts","../src/components/inputs/map-input.ts","../src/components/inputs/rating-input.ts","../src/components/inputs/slider-input.ts","../src/components/inputs/color-input.ts","../src/components/inputs/index.ts","../src/templates/index.ts","../src/components/easy-form.ts"],"sourcesContent":["import type { FormSchema, Field, Step, SlotContent } from '../types'\n\n/**\n * Parser del schema JSON\n */\nexport class SchemaParser {\n /**\n * Parsea y valida un schema\n */\n parse(schema: FormSchema): ParsedSchema {\n if (!schema) {\n throw new Error('Schema es requerido')\n }\n\n // Validar que tenga fields o steps\n if (!schema.fields && !schema.steps) {\n throw new Error('Schema debe tener fields o steps')\n }\n\n // Si tiene steps, validar que todos los steps tengan fields\n if (schema.steps) {\n for (const step of schema.steps) {\n if (!step.fields || step.fields.length === 0) {\n throw new Error('Cada step debe tener al menos un field')\n }\n }\n }\n\n // Normalizar campos\n const normalizedFields = schema.fields\n ? this.normalizeFields(schema.fields)\n : []\n\n const normalizedSteps = schema.steps\n ? schema.steps.map((step) => ({\n ...step,\n fields: this.normalizeFields(step.fields),\n }))\n : undefined\n\n return {\n fields: normalizedFields,\n steps: normalizedSteps,\n isWizard: Boolean(schema.steps && schema.steps.length > 0),\n }\n }\n\n /**\n * Normaliza y valida campos\n */\n private normalizeFields(fields: Field[]): Field[] {\n return fields.map((field, index) => {\n // Validar que tenga type y name\n if (!field.type) {\n throw new Error(`Field en índice ${index} debe tener un type`)\n }\n if (!field.name) {\n throw new Error(`Field en índice ${index} debe tener un name`)\n }\n\n // Validar tipos específicos\n this.validateFieldType(field, index)\n\n // Aplicar valores por defecto\n return this.applyDefaults(field)\n })\n }\n\n /**\n * Valida el tipo de campo\n */\n private validateFieldType(field: Field, index: number): void {\n const validTypes = [\n 'text',\n 'email',\n 'number',\n 'password',\n 'textarea',\n 'select',\n 'checkbox',\n 'radio',\n 'switch',\n 'date',\n 'file',\n 'file-drop',\n 'map',\n 'rating',\n 'slider',\n 'colorpicker',\n 'array',\n 'group',\n 'row',\n 'custom',\n 'quantity',\n 'accordion-select',\n 'image-grid-select',\n 'otp',\n ]\n\n if (!validTypes.includes(field.type)) {\n throw new Error(\n `Field en índice ${index} tiene un type inválido: ${field.type}`\n )\n }\n\n // Validaciones específicas por tipo\n switch (field.type) {\n case 'select':\n case 'radio':\n case 'accordion-select':\n case 'image-grid-select':\n if (!('options' in field) || !field.options || field.options.length === 0) {\n throw new Error(\n `Field \"${field.name}\" de tipo ${field.type} debe tener options`\n )\n }\n break\n case 'array':\n if (!('itemSchema' in field) || !field.itemSchema) {\n throw new Error(\n `Field \"${field.name}\" de tipo array debe tener itemSchema`\n )\n }\n if ('minItems' in field) {\n const min = (field as any).minItems\n if (min < 0) {\n throw new Error(\n `Field \"${field.name}\" de tipo array: minItems debe ser >= 0`\n )\n }\n if ('maxItems' in field) {\n const max = (field as any).maxItems\n if (min > max) {\n throw new Error(\n `Field \"${field.name}\" de tipo array: minItems (${min}) no puede ser mayor que maxItems (${max})`\n )\n }\n }\n }\n break\n case 'group':\n if (!('fields' in field) || !field.fields || field.fields.length === 0) {\n throw new Error(\n `Field \"${field.name}\" de tipo group debe tener fields`\n )\n }\n break\n case 'row':\n if (!('fields' in field) || !field.fields || field.fields.length === 0) {\n throw new Error(\n `Field \"${field.name}\" de tipo row debe tener fields`\n )\n }\n break\n case 'colorpicker':\n if ('defaultValue' in field && field.defaultValue != null) {\n const hex = /^#[0-9A-Fa-f]{6}$/\n if (!hex.test(String(field.defaultValue))) {\n throw new Error(\n `Field \"${field.name}\" de tipo colorpicker debe tener defaultValue en formato hex (#RRGGBB)`\n )\n }\n }\n break\n }\n\n // Validar leadingIcon y trailingIcon si existen\n if ('leadingIcon' in field && field.leadingIcon) {\n this.validateSlotContent(field.leadingIcon, field.name, 'leadingIcon')\n }\n if ('trailingIcon' in field && field.trailingIcon) {\n this.validateSlotContent(field.trailingIcon, field.name, 'trailingIcon')\n }\n }\n\n /**\n * Valida que SlotContent tenga las propiedades requeridas según type\n */\n private validateSlotContent(\n slot: SlotContent,\n fieldName: string,\n slotName: string\n ): void {\n if (!slot.type || !['image', 'html'].includes(slot.type)) {\n throw new Error(\n `Field \"${fieldName}\" ${slotName} debe tener type 'image' o 'html'`\n )\n }\n if (slot.type === 'image') {\n if (!slot.src || typeof slot.src !== 'string') {\n throw new Error(\n `Field \"${fieldName}\" ${slotName} con type 'image' debe tener src`\n )\n }\n }\n if (slot.type === 'html') {\n if (!slot.html || typeof slot.html !== 'string') {\n throw new Error(\n `Field \"${fieldName}\" ${slotName} con type 'html' debe tener html`\n )\n }\n }\n }\n\n /**\n * Aplica valores por defecto a un campo\n */\n private applyDefaults(field: Field): Field {\n const defaults: any = {\n disabled: false,\n hidden: false,\n }\n\n // Aplicar defaults específicos por tipo\n switch (field.type) {\n case 'checkbox':\n case 'switch':\n if (!('checked' in field)) {\n defaults.checked = false\n }\n break\n case 'select':\n case 'accordion-select':\n case 'image-grid-select':\n if (!('multiple' in field)) {\n defaults.multiple = false\n }\n if (field.type === 'image-grid-select') {\n if (!('columns' in field)) {\n defaults.columns = 3\n }\n if (!('imageSize' in field)) {\n defaults.imageSize = 'medium'\n }\n }\n break\n case 'file':\n if (!('multiple' in field)) {\n defaults.multiple = false\n }\n break\n case 'quantity':\n if (!('min' in field)) {\n defaults.min = 0\n }\n if (!('step' in field)) {\n defaults.step = 1\n }\n break\n case 'otp':\n if (!('length' in field)) {\n defaults.length = 6\n }\n if (!('numeric' in field)) {\n defaults.numeric = true\n }\n break\n case 'slider':\n if (!('min' in field)) {\n defaults.min = 0\n }\n if (!('max' in field)) {\n defaults.max = 100\n }\n if (!('step' in field)) {\n defaults.step = 1\n }\n break\n case 'rating':\n if (!('max' in field)) {\n defaults.max = 5\n }\n break\n case 'colorpicker':\n if (!('defaultValue' in field) || field.defaultValue == null) {\n defaults.defaultValue = '#000000'\n }\n break\n }\n\n return { ...defaults, ...field } as Field\n }\n\n /**\n * Obtiene todos los campos de un schema (incluyendo nested)\n */\n getAllFields(schema: FormSchema): Field[] {\n const parsed = this.parse(schema)\n const allFields: Field[] = []\n\n const extractFields = (fields: Field[]) => {\n for (const field of fields) {\n allFields.push(field)\n if (field.type === 'group' && 'fields' in field) {\n extractFields(field.fields)\n }\n if (field.type === 'row' && 'fields' in field) {\n extractFields(field.fields)\n }\n if (field.type === 'array' && 'itemSchema' in field && field.itemSchema.fields) {\n extractFields(field.itemSchema.fields)\n }\n }\n }\n\n if (parsed.fields) {\n extractFields(parsed.fields)\n }\n\n if (parsed.steps) {\n for (const step of parsed.steps) {\n extractFields(step.fields)\n }\n }\n\n return allFields\n }\n}\n\n/**\n * Schema parseado\n */\nexport interface ParsedSchema {\n fields: Field[]\n steps?: Step[]\n isWizard: boolean\n}\n","import type { FormTheme, FormColors } from '../types'\n\n/**\n * Convierte hex a componentes RGB para usar en rgba()\n */\nfunction hexToRgb(hex: string): string {\n const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex)\n if (!result) {\n const short = /^#?([a-f\\d])([a-f\\d])([a-f\\d])$/i.exec(hex)\n if (!short) return '0, 123, 255'\n return [\n parseInt(short[1] + short[1], 16),\n parseInt(short[2] + short[2], 16),\n parseInt(short[3] + short[3], 16),\n ].join(', ')\n }\n return [\n parseInt(result[1], 16),\n parseInt(result[2], 16),\n parseInt(result[3], 16),\n ].join(', ')\n}\n\n/**\n * Colores por defecto\n */\nconst defaultColors: Required<FormColors> = {\n primary: '#007bff',\n secondary: '#6c757d',\n error: '#dc3545',\n success: '#28a745',\n text: '#212529',\n labelColor: '#212529',\n border: '#ddd',\n background: '#ffffff',\n groupBackground: 'var(--easy-form-group-background)',\n groupTitle: '#212529',\n groupBorder: '#ddd',\n}\n\n/**\n * Obtiene los colores con valores por defecto\n */\nexport function getColors(colors?: FormColors): Required<FormColors> {\n return { ...defaultColors, ...colors }\n}\n\n/**\n * Genera estilos CSS para un tema específico\n */\nexport function getThemeStyles(theme: FormTheme, colors: Required<FormColors>): string {\n const baseStyles = getBaseStyles(colors)\n const themeStyles = getThemeSpecificStyles(theme, colors)\n return baseStyles + themeStyles\n}\n\n/**\n * Estilos base comunes a todos los temas\n */\nfunction getBaseStyles(colors: Required<FormColors>): string {\n return `\n :host {\n display: block;\n --easy-form-primary: ${colors.primary};\n --easy-form-primary-rgb: ${hexToRgb(colors.primary)};\n --easy-form-secondary: ${colors.secondary};\n --easy-form-error: ${colors.error};\n --easy-form-success: ${colors.success};\n --easy-form-text: ${colors.text};\n --easy-form-label-color: ${colors.labelColor};\n --easy-form-border: ${colors.border};\n --easy-form-background: ${colors.background};\n --easy-form-group-background: ${colors.groupBackground};\n --easy-form-group-title: ${colors.groupTitle};\n --easy-form-group-border: ${colors.groupBorder};\n --easy-form-on-primary: #ffffff;\n --easy-form-hover-overlay: rgba(0, 0, 0, 0.03);\n }\n .easy-form-field {\n margin-bottom: 1rem;\n }\n .easy-form-label {\n display: block;\n margin-bottom: 0.5rem;\n font-weight: 500;\n color: var(--easy-form-label-color);\n }\n .easy-form-label-down .easy-form-label {\n margin-bottom: 0;\n margin-top: 0.5rem;\n }\n .easy-form-field-inner-horizontal {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 0.75rem;\n }\n .easy-form-field-inner-horizontal .easy-form-label {\n display: inline-block;\n margin-bottom: 0;\n margin-top: 0;\n flex-shrink: 0;\n white-space: nowrap;\n }\n .easy-form-field-inner-horizontal > *:not(.easy-form-label) {\n flex: 1;\n min-width: 0;\n }\n .easy-form-direction-vertical {\n display: block;\n }\n .easy-form-direction-horizontal {\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n gap: 1rem;\n }\n .easy-form-direction-horizontal > * {\n flex: 1 1 auto;\n }\n .easy-form-completed-indicator {\n margin-bottom: 1rem;\n }\n .easy-form-completed-track {\n height: 6px;\n background: var(--easy-form-border);\n border-radius: 3px;\n overflow: hidden;\n }\n .easy-form-completed-fill {\n height: 100%;\n background: var(--easy-form-primary);\n border-radius: 3px;\n transition: width 0.2s ease;\n }\n .easy-form-slider-wrapper {\n display: flex;\n align-items: center;\n gap: 1rem;\n }\n .easy-form-slider-value {\n min-width: 2rem;\n font-weight: 500;\n }\n .easy-form-input-wrapper {\n display: flex;\n align-items: center;\n flex-wrap: nowrap;\n width: 100%;\n border: 1px solid var(--easy-form-border);\n border-radius: 4px;\n background: var(--easy-form-background);\n padding: 0 0.75rem;\n box-sizing: border-box;\n }\n .easy-form-input-wrapper:focus-within {\n border-color: var(--easy-form-primary);\n box-shadow: 0 0 0 3px rgba(var(--easy-form-primary-rgb), 0.1);\n }\n .easy-form-input-wrapper .easy-form-input-core {\n flex: 1;\n min-width: 0;\n }\n .easy-form-input-wrapper .easy-form-input-core input:not([type=\"checkbox\"]):not([type=\"radio\"]):not([type=\"color\"]),\n .easy-form-input-wrapper .easy-form-input-core textarea,\n .easy-form-input-wrapper .easy-form-input-core select {\n width: 100%;\n border: none !important;\n background: transparent !important;\n box-shadow: none !important;\n padding: 0.5rem 0 !important;\n }\n .easy-form-input-wrapper .easy-form-input-core input:focus,\n .easy-form-input-wrapper .easy-form-input-core textarea:focus,\n .easy-form-input-wrapper .easy-form-input-core select:focus {\n outline: none;\n }\n .easy-form-input-slot {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 0;\n min-width: 1.5rem;\n }\n .easy-form-input-slot-content {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n .easy-form-input-slot-content img {\n width: 20px;\n height: 20px;\n min-width: 20px;\n min-height: 20px;\n object-fit: contain;\n display: block;\n }\n .easy-form-input-slot-leading {\n padding-right: 0.5rem;\n }\n .easy-form-input-slot-trailing {\n padding-left: 0.5rem;\n }\n .easy-form-color-wrapper {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n }\n .easy-form-color-wrapper input[type=\"color\"] {\n width: 2.2rem;\n height: 2.2rem;\n min-width: 2.2rem;\n min-height: 2.2rem;\n padding: 0 !important;\n margin: 0;\n cursor: pointer;\n border: 1px solid var(--easy-form-border);\n border-radius: 2px;\n background: transparent;\n flex-shrink: 0;\n }\n .easy-form-color-wrapper input[type=\"color\"]::-webkit-color-swatch-wrapper {\n padding: 0;\n }\n .easy-form-color-wrapper input[type=\"color\"]::-webkit-color-swatch {\n border: none;\n border-radius: 1px;\n }\n .easy-form-color-wrapper input[type=\"color\"]::-moz-color-swatch {\n border: none;\n border-radius: 1px;\n }\n .easy-form-color-text {\n flex: 1;\n min-width: 0;\n color: var(--easy-form-text);\n background: var(--easy-form-background);\n border: 1px solid var(--easy-form-border);\n border-radius: 4px;\n padding: 0.5rem 0.75rem;\n font-family: ui-monospace, 'Cascadia Code', 'Fira Code', 'Courier New', monospace;\n font-size: 0.875rem;\n }\n .easy-form-rating {\n display: inline-flex;\n gap: 0.25rem;\n }\n .easy-form-rating-stars {\n display: flex;\n gap: 0.25rem;\n }\n .easy-form-rating-star {\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n color: var(--easy-form-border);\n }\n .easy-form-rating-star svg {\n display: block;\n }\n .easy-form-rating-star-filled {\n color: var(--easy-form-primary);\n }\n .easy-form-rating-star:hover,\n .easy-form-rating-star:focus {\n color: var(--easy-form-primary);\n }\n .easy-form-file-drop {\n border: 2px dashed var(--easy-form-border);\n border-radius: 8px;\n padding: 2rem;\n text-align: center;\n cursor: pointer;\n transition: border-color 0.2s, background 0.2s;\n }\n .easy-form-file-drop:hover,\n .easy-form-file-drop-over {\n border-color: var(--easy-form-primary);\n background: rgba(var(--easy-form-primary-rgb), 0.05);\n }\n .easy-form-file-drop-list {\n margin-top: 0.75rem;\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n }\n .easy-form-file-drop-item {\n font-size: 0.875rem;\n color: var(--easy-form-text);\n padding: 0.25rem 0;\n border-bottom: 1px solid var(--easy-form-border);\n }\n .easy-form-map-inputs {\n display: flex;\n gap: 1rem;\n margin-bottom: 0.5rem;\n }\n .easy-form-map-inputs input {\n flex: 1;\n }\n .easy-form-map-placeholder,\n .easy-form-map-container {\n min-height: 300px;\n height: 300px;\n border-radius: 4px;\n position: relative;\n overflow: hidden;\n width: 100%;\n display: block;\n box-sizing: border-box;\n }\n .easy-form-map-container {\n background: var(--easy-form-group-background);\n }\n .easy-form-map-container .leaflet-container {\n height: 100% !important;\n width: 100% !important;\n position: relative !important;\n }\n .easy-form-map-container .leaflet-tile-container {\n position: absolute;\n left: 0;\n top: 0;\n }\n .easy-form-required {\n color: var(--easy-form-error);\n }\n .easy-form-input-error {\n border-color: var(--easy-form-error) !important;\n }\n .easy-form-error {\n color: var(--easy-form-error);\n font-size: 0.875rem;\n margin-top: 0.25rem;\n }\n .easy-form-description {\n font-size: 0.875rem;\n color: var(--easy-form-secondary);\n margin-top: 0.25rem;\n }\n .easy-form-submit {\n padding: 0.5rem 1rem;\n background: var(--easy-form-primary);\n color: var(--easy-form-on-primary);\n border: none;\n cursor: pointer;\n font-size: 1rem;\n transition: all 0.2s ease;\n }\n .easy-form-submit:hover {\n opacity: 0.9;\n }\n .easy-form-submit:active {\n transform: scale(0.98);\n }\n .easy-form-submit-wrapper {\n margin-top: 1rem;\n margin-bottom: 0.5rem;\n }\n .easy-form-submit-wrapper .easy-form-submit {\n min-width: 100px;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):not([type=\"color\"]), textarea, select {\n width: 100%;\n padding: 0.5rem;\n font-size: 1rem;\n color: var(--easy-form-text);\n transition: all 0.2s ease;\n box-sizing: border-box;\n }\n input[type=\"checkbox\"],\n input[type=\"radio\"] {\n width: 18px !important;\n height: 18px !important;\n min-width: 18px !important;\n min-height: 18px !important;\n max-width: 18px !important;\n margin: 0;\n padding: 0;\n cursor: pointer;\n accent-color: var(--easy-form-primary);\n flex-shrink: 0;\n }\n input:focus, textarea:focus, select:focus {\n outline: none;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):not([type=\"color\"])::placeholder,\n textarea::placeholder {\n color: color-mix(in srgb, var(--easy-form-text) 55%, transparent);\n opacity: 1;\n }\n .easy-form-group {\n padding: 1rem;\n margin-bottom: 1rem;\n background: var(--easy-form-group-background);\n border: 1px solid var(--easy-form-group-border);\n border-radius: 4px;\n }\n .easy-form-group-label {\n color: var(--easy-form-group-title);\n font-weight: 600;\n font-size: 1rem;\n margin-bottom: 0.75rem;\n margin-top: 0;\n }\n .easy-form-group-collapsible {\n border: 1px solid var(--easy-form-group-border);\n border-radius: 4px;\n overflow: hidden;\n }\n .easy-form-group-collapsible .easy-form-group-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.75rem 1rem;\n cursor: pointer;\n background: var(--easy-form-group-background);\n color: var(--easy-form-group-title);\n font-weight: 600;\n font-size: 1rem;\n user-select: none;\n transition: background-color 0.2s ease;\n width: 100%;\n border: none;\n }\n .easy-form-group-collapsible .easy-form-group-header:hover {\n background: var(--easy-form-hover-overlay);\n }\n .easy-form-group-collapsible .easy-form-group-header:focus {\n outline: none;\n box-shadow: inset 0 0 0 2px var(--easy-form-primary);\n }\n .easy-form-group-collapsible .easy-form-group-chevron {\n flex-shrink: 0;\n margin-left: 0.5rem;\n transition: transform 0.2s ease;\n color: var(--easy-form-secondary);\n }\n .easy-form-group-collapsible.easy-form-group-collapsed .easy-form-group-chevron {\n transform: rotate(-90deg); /* ▼ → ▶ cuando colapsado */\n }\n .easy-form-group-collapsible .easy-form-group-content {\n overflow: hidden;\n transition: max-height 0.3s ease;\n padding: 0 1rem 1rem 1rem;\n }\n .easy-form-group-collapsible.easy-form-group-collapsed .easy-form-group-content {\n max-height: 0 !important;\n padding-top: 0;\n padding-bottom: 0;\n }\n .easy-form-row {\n display: flex;\n flex-wrap: wrap;\n gap: 1rem;\n margin-bottom: 1rem;\n align-items: stretch;\n }\n .easy-form-row > div {\n flex: 1;\n min-width: 0;\n }\n @media (max-width: 768px) {\n .easy-form-row {\n flex-direction: column;\n }\n .easy-form-row > div {\n flex: none;\n width: 100%;\n }\n }\n .easy-form-radio-group {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n margin-top: 0.5rem;\n }\n .easy-form-radio-option {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.5rem;\n border-radius: 6px;\n transition: background-color 0.2s ease;\n }\n .easy-form-radio-option:hover {\n background-color: var(--easy-form-hover-overlay);\n }\n .easy-form-radio-option input[type=\"radio\"] {\n margin: 0;\n flex-shrink: 0;\n }\n .easy-form-radio-label {\n cursor: pointer;\n user-select: none;\n color: var(--easy-form-label-color);\n font-weight: 400;\n }\n .easy-form-label-checkbox,\n .easy-form-label-switch {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n cursor: pointer;\n user-select: none;\n padding: 0.5rem;\n border-radius: 6px;\n transition: background-color 0.2s ease;\n color: var(--easy-form-label-color);\n }\n .easy-form-label-checkbox input[type=\"checkbox\"],\n .easy-form-label-switch input[type=\"checkbox\"] {\n margin: 0;\n flex-shrink: 0;\n }\n .easy-form-label-checkbox:hover,\n .easy-form-label-switch:hover {\n background-color: var(--easy-form-hover-overlay);\n }\n .easy-form-wizard-steps {\n display: flex;\n gap: 1rem;\n margin-bottom: 2rem;\n }\n .easy-form-wizard-step {\n padding: 0.5rem 1rem;\n transition: all 0.2s ease;\n }\n .easy-form-wizard-step.active {\n background: var(--easy-form-primary);\n color: var(--easy-form-on-primary);\n }\n .easy-form-wizard-step.completed {\n background: var(--easy-form-success);\n color: var(--easy-form-on-primary);\n }\n .easy-form-wizard-nav {\n display: flex;\n gap: 1rem;\n margin-top: 2rem;\n justify-content: flex-end;\n align-items: center;\n }\n .easy-form-wizard-prev,\n .easy-form-wizard-next {\n padding: 0.75rem 1.5rem;\n background: var(--easy-form-primary);\n color: var(--easy-form-on-primary);\n border: none;\n border-radius: 4px;\n font-size: 1rem;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n font-family: inherit;\n min-width: 120px;\n }\n .easy-form-wizard-prev:hover:not(:disabled),\n .easy-form-wizard-next:hover:not(:disabled) {\n opacity: 0.9;\n transform: translateY(-1px);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n }\n .easy-form-wizard-prev:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n .easy-form-wizard-prev {\n background: var(--easy-form-secondary);\n order: 1;\n }\n .easy-form-wizard-next {\n background: var(--easy-form-primary);\n order: 2;\n }\n .easy-form-array-item {\n padding: 1rem;\n margin-bottom: 1rem;\n }\n .easy-form-array-add,\n .easy-form-array-remove {\n padding: 0.25rem 0.5rem;\n background: var(--easy-form-secondary);\n color: var(--easy-form-on-primary);\n border: none;\n cursor: pointer;\n font-size: 0.875rem;\n transition: all 0.2s ease;\n }\n .easy-form-array-remove {\n background: var(--easy-form-error);\n }\n .easy-form-array-add:hover,\n .easy-form-array-remove:hover {\n opacity: 0.9;\n }\n /* Quantity Input */\n .easy-form-quantity-container {\n display: flex;\n flex-direction: column;\n }\n .easy-form-quantity-wrapper {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n }\n .easy-form-quantity-btn {\n width: 2.5rem;\n height: 2.5rem;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--easy-form-primary);\n color: var(--easy-form-on-primary);\n border: none;\n border-radius: 4px;\n font-size: 1.25rem;\n font-weight: bold;\n cursor: pointer;\n transition: all 0.2s ease;\n user-select: none;\n }\n .easy-form-quantity-btn:hover:not(.disabled) {\n opacity: 0.9;\n transform: scale(1.05);\n }\n .easy-form-quantity-btn.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n .easy-form-quantity-input {\n flex: 1;\n text-align: center;\n max-width: 100px;\n }\n /* Accordion Select */\n .easy-form-accordion-select-container {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n }\n .easy-form-accordion-item {\n border: 1px solid var(--easy-form-border);\n border-radius: 4px;\n overflow: hidden;\n transition: all 0.2s ease;\n }\n .easy-form-accordion-item.selected {\n border-color: var(--easy-form-primary);\n box-shadow: 0 0 0 2px rgba(var(--easy-form-primary-rgb), 0.1);\n }\n .easy-form-accordion-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.75rem 1rem;\n cursor: pointer;\n background: var(--easy-form-background);\n transition: background 0.2s ease;\n }\n .easy-form-accordion-header:hover {\n background: color-mix(in srgb, var(--easy-form-border) 95%, transparent);\n }\n .easy-form-accordion-header-content {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n flex: 1;\n }\n .easy-form-accordion-indicator {\n width: 20px;\n height: 20px;\n border: 2px solid var(--easy-form-border);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: all 0.2s ease;\n }\n .easy-form-accordion-indicator.radio {\n border-radius: 50%;\n }\n .easy-form-accordion-indicator.checkbox {\n border-radius: 4px;\n }\n .easy-form-accordion-indicator.checked {\n background: var(--easy-form-primary);\n border-color: var(--easy-form-primary);\n color: var(--easy-form-on-primary);\n }\n .easy-form-accordion-indicator.checked.radio::after {\n content: '';\n width: 8px;\n height: 8px;\n background: var(--easy-form-on-primary);\n border-radius: 50%;\n }\n .easy-form-accordion-indicator.checked.checkbox::after {\n content: '✓';\n font-size: 12px;\n color: var(--easy-form-on-primary);\n }\n .easy-form-accordion-label {\n font-weight: 500;\n color: var(--easy-form-text);\n }\n .easy-form-accordion-arrow {\n transition: transform 0.2s ease;\n color: var(--easy-form-secondary);\n }\n .easy-form-accordion-content {\n max-height: 0;\n overflow: hidden;\n transition: max-height 0.3s ease;\n padding: 0 1rem;\n }\n .easy-form-accordion-item.open .easy-form-accordion-content {\n padding: 1rem;\n }\n .easy-form-accordion-description {\n color: var(--easy-form-secondary);\n font-size: 0.875rem;\n margin: 0;\n }\n /* Image Grid Select */\n .easy-form-image-grid-container {\n display: grid;\n gap: 1rem;\n }\n .easy-form-image-grid-item {\n position: relative;\n border: 2px solid var(--easy-form-border);\n border-radius: 8px;\n overflow: hidden;\n cursor: pointer;\n transition: all 0.2s ease;\n background: var(--easy-form-background);\n }\n .easy-form-image-grid-item:hover {\n border-color: var(--easy-form-primary);\n transform: translateY(-2px);\n box-shadow: 0 4px 8px color-mix(in srgb, var(--easy-form-border) 30%, transparent);\n }\n .easy-form-image-grid-item.selected {\n border-color: var(--easy-form-primary);\n box-shadow: 0 0 0 3px rgba(var(--easy-form-primary-rgb), 0.2);\n }\n .easy-form-image-grid-image-container {\n position: relative;\n width: 100%;\n aspect-ratio: 1;\n overflow: hidden;\n background: var(--easy-form-group-background);\n }\n .easy-form-image-grid-image {\n width: 100%;\n height: 100%;\n object-fit: cover;\n }\n .easy-form-image-grid-placeholder {\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--easy-form-secondary);\n color: var(--easy-form-on-primary);\n font-size: 2rem;\n font-weight: bold;\n }\n .easy-form-image-grid-indicator {\n position: absolute;\n top: 0.5rem;\n right: 0.5rem;\n width: 24px;\n height: 24px;\n border: 2px solid var(--easy-form-on-primary);\n background: var(--easy-form-primary);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--easy-form-on-primary);\n font-size: 12px;\n opacity: 0;\n transition: opacity 0.2s ease;\n }\n .easy-form-image-grid-item.selected .easy-form-image-grid-indicator {\n opacity: 1;\n }\n .easy-form-image-grid-indicator.checkbox {\n border-radius: 4px;\n }\n .easy-form-image-grid-label {\n padding: 0.75rem;\n text-align: center;\n font-weight: 500;\n color: var(--easy-form-text);\n }\n .easy-form-image-grid-description {\n padding: 0 0.75rem 0.75rem;\n font-size: 0.875rem;\n color: var(--easy-form-secondary);\n text-align: center;\n }\n .easy-form-image-grid-small {\n grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));\n }\n .easy-form-image-grid-medium {\n grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));\n }\n .easy-form-image-grid-large {\n grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));\n }\n /* OTP Input */\n .easy-form-otp-container {\n display: flex;\n gap: 0.5rem;\n justify-content: center;\n align-items: center;\n }\n .easy-form-otp-input {\n width: 3rem;\n height: 3rem;\n text-align: center;\n font-size: 1.5rem;\n font-weight: bold;\n border: 2px solid var(--easy-form-border);\n border-radius: 4px;\n transition: all 0.2s ease;\n }\n .easy-form-otp-input:focus {\n border-color: var(--easy-form-primary);\n outline: none;\n box-shadow: 0 0 0 3px rgba(var(--easy-form-primary-rgb), 0.1);\n }\n .easy-form-otp-input:invalid {\n border-color: var(--easy-form-error);\n }\n /* Password inner (input + toggle) */\n .easy-form-password-inner {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n }\n .easy-form-password-inner .easy-form-password-input {\n flex: 1;\n min-width: 0;\n }\n .easy-form-password-toggle {\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0.35rem;\n background: transparent;\n border: 1px solid var(--easy-form-border);\n border-radius: 4px;\n cursor: pointer;\n color: var(--easy-form-text);\n }\n .easy-form-password-toggle:hover {\n border-color: var(--easy-form-primary);\n color: var(--easy-form-primary);\n }\n .easy-form-password-toggle:focus {\n outline: none;\n box-shadow: 0 0 0 2px var(--easy-form-primary);\n }\n /* Password carácter separado */\n .easy-form-password-separated {\n display: flex;\n flex-wrap: nowrap;\n gap: 0.5rem;\n align-items: center;\n }\n .easy-form-password-separated-input {\n width: 2.5rem;\n height: 2.5rem;\n text-align: center;\n font-size: 1.25rem;\n border: 2px solid var(--easy-form-border);\n border-radius: 4px;\n transition: border-color 0.2s ease;\n }\n .easy-form-password-separated-input:focus {\n border-color: var(--easy-form-primary);\n outline: none;\n }\n .easy-form-password-separated-toggle {\n flex-shrink: 0;\n }\n .easy-form-password-separated-toggle .easy-form-password-toggle {\n padding: 0.35rem;\n }\n /* Loading Overlay (sobre el formulario) */\n .easy-form-loading-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(255, 255, 255, 0.8);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n backdrop-filter: blur(2px);\n border-radius: inherit;\n }\n .easy-form-loading-spinner {\n width: 40px;\n height: 40px;\n border: 4px solid rgba(0, 0, 0, 0.1);\n border-top-color: var(--easy-form-primary);\n border-radius: 50%;\n animation: easy-form-spin 0.8s linear infinite;\n }\n @keyframes easy-form-spin {\n to {\n transform: rotate(360deg);\n }\n }\n /* Lock Overlay (bloqueo por intentos) */\n .easy-form-lock-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(255, 255, 255, 0.9);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1001;\n backdrop-filter: blur(4px);\n border-radius: inherit;\n text-align: center;\n padding: 1.5rem;\n }\n .easy-form-lock-message {\n font-size: 1rem;\n color: var(--easy-form-text);\n max-width: 280px;\n }\n /* Disabled State */\n .easy-form-disabled,\n .easy-form-disabled *,\n .easy-form-slot-disabled,\n .easy-form-slot-disabled * {\n pointer-events: none;\n opacity: 0.6;\n }\n .easy-form-disabled input,\n .easy-form-disabled textarea,\n .easy-form-disabled select,\n .easy-form-disabled button,\n .easy-form-slot-disabled input,\n .easy-form-slot-disabled textarea,\n .easy-form-slot-disabled select,\n .easy-form-slot-disabled button {\n cursor: not-allowed;\n }\n .easy-form-input-disabled {\n opacity: 0.6;\n cursor: not-allowed !important;\n }\n form {\n position: relative;\n }\n `\n}\n\n/**\n * Estilos específicos por tema\n */\nfunction getThemeSpecificStyles(theme: FormTheme, colors: Required<FormColors>): string {\n switch (theme) {\n case 'plano':\n return getPlanoStyles(colors)\n case 'tradicional':\n return getTradicionalStyles(colors)\n case 'material':\n return getMaterialStyles(colors)\n case 'rounded-shadow':\n return getRoundedShadowStyles(colors)\n case 'lines':\n return getLinesStyles(colors)\n case 'shadcn':\n return getShadcnStyles(colors)\n case 'chakra':\n return getChakraStyles(colors)\n case 'mantine':\n return getMantineStyles(colors)\n case 'glass':\n return getGlassStyles(colors)\n case 'bordered':\n return getBorderedStyles(colors)\n case 'minimal':\n return getMinimalStyles(colors)\n case 'efc':\n return getEfcStyles(colors)\n default:\n return getPlanoStyles(colors)\n }\n}\n\n/**\n * Estilo Plano - Minimalista sin bordes ni sombras\n */\nfunction getPlanoStyles(_colors: Required<FormColors>): string {\n return `\n .easy-form-label {\n color: var(--easy-form-label-color);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]), textarea, select {\n border: none;\n border-bottom: 2px solid var(--easy-form-border);\n border-radius: 0;\n padding: 0.75rem 0;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):focus, textarea:focus, select:focus {\n border-bottom-color: var(--easy-form-primary);\n }\n .easy-form-submit {\n border-radius: 0;\n font-weight: 600;\n }\n .easy-form-group {\n border: none;\n border-bottom: 1px solid var(--easy-form-group-border);\n border-radius: 0;\n background: transparent;\n }\n .easy-form-wizard-step {\n border: none;\n border-bottom: 2px solid var(--easy-form-border);\n border-radius: 0;\n }\n .easy-form-array-item {\n border: none;\n border-bottom: 1px solid var(--easy-form-group-border);\n border-radius: 0;\n }\n `\n}\n\n/**\n * Estilo Tradicional - Bordes clásicos y estructura tradicional\n */\nfunction getTradicionalStyles(_colors: Required<FormColors>): string {\n return `\n .easy-form-label {\n color: var(--easy-form-label-color);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]), textarea, select {\n border: 2px solid var(--easy-form-border);\n border-radius: 4px;\n padding: 0.625rem;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):focus, textarea:focus, select:focus {\n border-color: var(--easy-form-primary);\n box-shadow: 0 0 0 3px rgba(var(--easy-form-primary-rgb), 0.1);\n }\n .easy-form-submit {\n border-radius: 4px;\n font-weight: 500;\n }\n .easy-form-group {\n border: 2px solid var(--easy-form-group-border);\n border-radius: 4px;\n background: var(--easy-form-group-background);\n }\n .easy-form-wizard-step {\n border: 2px solid var(--easy-form-border);\n border-radius: 4px;\n background: var(--easy-form-group-background);\n }\n .easy-form-wizard-step.active {\n border-color: var(--easy-form-primary);\n }\n .easy-form-array-item {\n border: 2px solid var(--easy-form-group-border);\n border-radius: 4px;\n background: var(--easy-form-group-background);\n }\n `\n}\n\n/**\n * Estilo Material - Inspirado en Material Design\n */\nfunction getMaterialStyles(_colors: Required<FormColors>): string {\n return `\n .easy-form-label {\n font-size: 0.875rem;\n font-weight: 500;\n margin-bottom: 0.25rem;\n color: var(--easy-form-label-color);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]), textarea, select {\n border: none;\n border-bottom: 1px solid color-mix(in srgb, var(--easy-form-text) 42%, transparent);\n border-radius: 4px 4px 0 0;\n padding: 0.75rem 0.75rem 0.5rem 0.75rem;\n background: transparent;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):focus, textarea:focus, select:focus {\n border-bottom-color: var(--easy-form-primary);\n border-bottom-width: 2px;\n padding-bottom: calc(0.5rem - 1px);\n }\n .easy-form-submit {\n border-radius: 4px;\n text-transform: uppercase;\n font-weight: 500;\n letter-spacing: 0.5px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\n }\n .easy-form-submit:hover {\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);\n }\n .easy-form-group {\n border: none;\n border-radius: 4px;\n background: var(--easy-form-group-background);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);\n }\n .easy-form-wizard-step {\n border: none;\n border-radius: 4px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);\n }\n .easy-form-array-item {\n border: none;\n border-radius: 4px;\n background: var(--easy-form-group-background);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);\n }\n .easy-form-array-add,\n .easy-form-quantity-btn {\n border-radius: 4px;\n text-transform: uppercase;\n font-weight: 500;\n letter-spacing: 0.5px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\n }\n .easy-form-array-add:hover,\n .easy-form-quantity-btn:hover:not(.disabled) {\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);\n }\n .easy-form-array-remove {\n border-radius: 4px;\n text-transform: uppercase;\n font-weight: 500;\n letter-spacing: 0.5px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\n }\n .easy-form-array-remove:hover {\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);\n }\n .easy-form-wizard-prev,\n .easy-form-wizard-next {\n border-radius: 4px;\n text-transform: uppercase;\n font-weight: 500;\n letter-spacing: 0.5px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\n }\n .easy-form-wizard-prev:hover:not(:disabled),\n .easy-form-wizard-next:hover {\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);\n }\n .easy-form-error,\n .easy-form-description {\n background: transparent;\n border: none;\n }\n `\n}\n\n/**\n * Estilo Rounded Shadow - Bordes redondeados con sombras\n */\nfunction getRoundedShadowStyles(_colors: Required<FormColors>): string {\n return `\n .easy-form-label {\n color: var(--easy-form-label-color);\n }\n .easy-form-input-wrapper {\n border-radius: 12px;\n padding: 0 1rem;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);\n }\n .easy-form-input-wrapper:focus-within {\n box-shadow: 0 4px 12px rgba(var(--easy-form-primary-rgb), 0.15);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]), textarea, select {\n border: 1px solid var(--easy-form-border);\n border-radius: 12px;\n padding: 0.75rem 1rem;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):focus, textarea:focus, select:focus {\n border-color: var(--easy-form-primary);\n box-shadow: 0 4px 12px rgba(var(--easy-form-primary-rgb), 0.15);\n transform: translateY(-1px);\n }\n .easy-form-submit {\n border-radius: 12px;\n font-weight: 600;\n box-shadow: 0 4px 12px rgba(var(--easy-form-primary-rgb), 0.3);\n }\n .easy-form-submit:hover {\n box-shadow: 0 6px 16px rgba(var(--easy-form-primary-rgb), 0.4);\n transform: translateY(-2px);\n }\n .easy-form-group {\n border: 1px solid var(--easy-form-group-border);\n border-radius: 16px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\n background: var(--easy-form-group-background);\n }\n .easy-form-wizard-step {\n border: 1px solid var(--easy-form-border);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n }\n .easy-form-wizard-step.active {\n box-shadow: 0 4px 16px rgba(var(--easy-form-primary-rgb), 0.3);\n }\n .easy-form-array-item {\n border: 1px solid var(--easy-form-group-border);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n background: var(--easy-form-group-background);\n }\n `\n}\n\n/**\n * Estilo Lines - Solo líneas como separadores\n */\nfunction getLinesStyles(_colors: Required<FormColors>): string {\n return `\n .easy-form-field {\n border-bottom: 1px solid var(--easy-form-border);\n padding-bottom: 1rem;\n margin-bottom: 1.5rem;\n }\n .easy-form-field:last-child {\n border-bottom: none;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]), textarea, select {\n border: none;\n border-radius: 0;\n padding: 0.5rem 0;\n background: transparent;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):focus, textarea:focus, select:focus {\n border-bottom: 2px solid var(--easy-form-primary);\n padding-bottom: calc(0.5rem - 1px);\n }\n .easy-form-submit {\n border-radius: 0;\n border-bottom: 3px solid var(--easy-form-primary);\n background: transparent;\n color: var(--easy-form-primary);\n font-weight: 600;\n padding: 0.75rem 0;\n }\n .easy-form-submit:hover {\n background: rgba(var(--easy-form-primary-rgb), 0.05);\n }\n .easy-form-group {\n border: none;\n border-bottom: 2px solid var(--easy-form-group-border);\n border-radius: 0;\n padding-bottom: 1rem;\n background: transparent;\n }\n .easy-form-wizard-step {\n border: none;\n border-bottom: 3px solid var(--easy-form-border);\n border-radius: 0;\n background: transparent;\n }\n .easy-form-wizard-step.active {\n border-bottom-color: var(--easy-form-primary);\n background: transparent;\n color: var(--easy-form-primary);\n }\n .easy-form-wizard-step.completed {\n border-bottom-color: var(--easy-form-success);\n background: transparent;\n color: var(--easy-form-success);\n }\n .easy-form-array-item {\n border: none;\n border-bottom: 1px solid var(--easy-form-group-border);\n border-radius: 0;\n }\n .easy-form-array-add,\n .easy-form-quantity-btn {\n border-radius: 0;\n border: none;\n border-bottom: 3px solid var(--easy-form-primary);\n background: transparent;\n color: var(--easy-form-primary);\n font-weight: 600;\n padding: 0.5rem 0.75rem;\n }\n .easy-form-array-add:hover,\n .easy-form-quantity-btn:hover:not(.disabled) {\n background: rgba(var(--easy-form-primary-rgb), 0.05);\n }\n .easy-form-array-remove {\n border-radius: 0;\n border: none;\n border-bottom: 3px solid var(--easy-form-error);\n background: transparent;\n color: var(--easy-form-error);\n font-weight: 600;\n padding: 0.5rem 0.75rem;\n }\n .easy-form-array-remove:hover {\n background: rgba(var(--easy-form-primary-rgb), 0.05);\n }\n .easy-form-wizard-prev {\n border-radius: 0;\n border: none;\n border-bottom: 3px solid var(--easy-form-secondary);\n background: transparent;\n color: var(--easy-form-secondary);\n font-weight: 600;\n padding: 0.5rem 0.75rem;\n }\n .easy-form-wizard-next {\n border-radius: 0;\n border: none;\n border-bottom: 3px solid var(--easy-form-primary);\n background: transparent;\n color: var(--easy-form-primary);\n font-weight: 600;\n padding: 0.5rem 0.75rem;\n }\n .easy-form-wizard-prev:hover:not(:disabled),\n .easy-form-wizard-next:hover {\n background: rgba(var(--easy-form-primary-rgb), 0.05);\n }\n .easy-form-error,\n .easy-form-description {\n background: none;\n border: none;\n padding: 0;\n }\n `\n}\n\n/**\n * Estilo Shadcn - Moderno con gradientes sutiles y sombras pronunciadas\n */\nfunction getShadcnStyles(_colors: Required<FormColors>): string {\n return `\n .easy-form-label {\n color: var(--easy-form-label-color);\n font-size: 0.875rem;\n font-weight: 600;\n margin-bottom: 0.75rem;\n letter-spacing: -0.01em;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]), textarea, select {\n border: 1.5px solid var(--easy-form-border);\n border-radius: 8px;\n padding: 0.75rem 1rem;\n background: linear-gradient(to bottom, var(--easy-form-background), var(--easy-form-group-background));\n color: var(--easy-form-text);\n font-size: 0.875rem;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05), inset 0 1px 1px rgba(255, 255, 255, 0.8);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):hover, textarea:hover, select:hover {\n border-color: color-mix(in srgb, var(--easy-form-border) 80%, black);\n background: linear-gradient(to bottom, var(--easy-form-background), var(--easy-form-group-background));\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08), inset 0 1px 1px rgba(255, 255, 255, 0.9);\n transform: translateY(-1px);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):focus, textarea:focus, select:focus {\n outline: none;\n border-color: var(--easy-form-primary);\n background: var(--easy-form-background);\n box-shadow: 0 0 0 4px rgba(var(--easy-form-primary-rgb), 0.12), 0 4px 12px rgba(var(--easy-form-primary-rgb), 0.15);\n transform: translateY(-2px);\n }\n .easy-form-submit {\n border-radius: 8px;\n font-weight: 600;\n background: linear-gradient(135deg, var(--easy-form-primary) 0%, color-mix(in srgb, var(--easy-form-primary) 75%, black) 100%);\n box-shadow: 0 4px 12px rgba(var(--easy-form-primary-rgb), 0.3), 0 2px 4px rgba(0, 0, 0, 0.1);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n letter-spacing: 0.01em;\n }\n .easy-form-submit:hover {\n box-shadow: 0 6px 20px rgba(var(--easy-form-primary-rgb), 0.4), 0 4px 8px rgba(0, 0, 0, 0.15);\n transform: translateY(-2px);\n background: linear-gradient(135deg, color-mix(in srgb, var(--easy-form-primary) 75%, black) 0%, var(--easy-form-primary) 100%);\n }\n .easy-form-submit:active {\n transform: translateY(0);\n box-shadow: 0 2px 8px rgba(var(--easy-form-primary-rgb), 0.3);\n }\n .easy-form-group {\n border: 1.5px solid var(--easy-form-group-border);\n border-radius: 12px;\n background: var(--easy-form-group-background);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\n padding: 1.5rem;\n }\n .easy-form-wizard-step {\n border: 1.5px solid var(--easy-form-border);\n border-radius: 8px;\n background: linear-gradient(to bottom, var(--easy-form-background), var(--easy-form-group-background));\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-wizard-step:hover {\n border-color: color-mix(in srgb, var(--easy-form-border) 80%, black);\n transform: translateY(-2px);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n }\n .easy-form-wizard-step.active {\n border-color: var(--easy-form-primary);\n background: linear-gradient(135deg, var(--easy-form-primary) 0%, color-mix(in srgb, var(--easy-form-primary) 75%, black) 100%);\n color: white;\n box-shadow: 0 6px 20px rgba(var(--easy-form-primary-rgb), 0.4);\n transform: translateY(-2px);\n }\n .easy-form-array-item {\n border: 1.5px solid var(--easy-form-border);\n border-radius: 8px;\n background: var(--easy-form-group-background);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n }\n .easy-form-array-add,\n .easy-form-quantity-btn {\n border-radius: 8px;\n font-weight: 600;\n background: linear-gradient(135deg, var(--easy-form-primary) 0%, color-mix(in srgb, var(--easy-form-primary) 75%, black) 100%);\n border: 1.5px solid color-mix(in srgb, var(--easy-form-primary) 85%, black);\n box-shadow: 0 4px 12px rgba(var(--easy-form-primary-rgb), 0.3), 0 2px 4px rgba(0, 0, 0, 0.1);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-array-add:hover,\n .easy-form-quantity-btn:hover:not(.disabled) {\n box-shadow: 0 6px 20px rgba(var(--easy-form-primary-rgb), 0.4), 0 4px 8px rgba(0, 0, 0, 0.15);\n transform: translateY(-2px);\n background: linear-gradient(135deg, color-mix(in srgb, var(--easy-form-primary) 75%, black) 0%, var(--easy-form-primary) 100%);\n }\n .easy-form-array-remove {\n border-radius: 8px;\n font-weight: 600;\n background: linear-gradient(135deg, var(--easy-form-error) 0%, color-mix(in srgb, var(--easy-form-error) 75%, black) 100%);\n border: 1.5px solid color-mix(in srgb, var(--easy-form-error) 85%, black);\n box-shadow: 0 4px 12px rgba(var(--easy-form-primary-rgb), 0.2), 0 2px 4px rgba(0, 0, 0, 0.1);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-array-remove:hover {\n box-shadow: 0 6px 20px rgba(var(--easy-form-primary-rgb), 0.3), 0 4px 8px rgba(0, 0, 0, 0.15);\n transform: translateY(-2px);\n }\n .easy-form-wizard-prev {\n border-radius: 8px;\n font-weight: 600;\n background: linear-gradient(to bottom, var(--easy-form-background), var(--easy-form-group-background));\n border: 1.5px solid var(--easy-form-border);\n color: var(--easy-form-text);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-wizard-next {\n border-radius: 8px;\n font-weight: 600;\n background: linear-gradient(135deg, var(--easy-form-primary) 0%, color-mix(in srgb, var(--easy-form-primary) 75%, black) 100%);\n border: 1.5px solid color-mix(in srgb, var(--easy-form-primary) 85%, black);\n box-shadow: 0 4px 12px rgba(var(--easy-form-primary-rgb), 0.3), 0 2px 4px rgba(0, 0, 0, 0.1);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-wizard-prev:hover:not(:disabled) {\n border-color: color-mix(in srgb, var(--easy-form-border) 80%, black);\n transform: translateY(-2px);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n }\n .easy-form-wizard-next:hover {\n box-shadow: 0 6px 20px rgba(var(--easy-form-primary-rgb), 0.4), 0 4px 8px rgba(0, 0, 0, 0.15);\n transform: translateY(-2px);\n background: linear-gradient(135deg, color-mix(in srgb, var(--easy-form-primary) 75%, black) 0%, var(--easy-form-primary) 100%);\n }\n `\n}\n\n/**\n * Estilo Chakra - Vibrante con colores puros y efectos de hover pronunciados\n */\nfunction getChakraStyles(_colors: Required<FormColors>): string {\n return `\n .easy-form-label {\n color: var(--easy-form-label-color);\n font-size: 0.875rem;\n font-weight: 600;\n margin-bottom: 0.5rem;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n font-size: 0.75rem;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]), textarea, select {\n border: 2px solid var(--easy-form-border);\n border-radius: 6px;\n padding: 0.625rem 0.875rem;\n background: var(--easy-form-background);\n color: var(--easy-form-text);\n font-size: 0.875rem;\n transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);\n font-weight: 500;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):hover, textarea:hover, select:hover {\n border-color: var(--easy-form-primary);\n background: var(--easy-form-group-background);\n box-shadow: 0 0 0 3px rgba(var(--easy-form-primary-rgb), 0.1);\n transform: scale(1.02);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):focus, textarea:focus, select:focus {\n outline: none;\n border-color: var(--easy-form-primary);\n border-width: 2px;\n background: var(--easy-form-background);\n box-shadow: 0 0 0 3px rgba(var(--easy-form-primary-rgb), 0.2), 0 4px 12px rgba(var(--easy-form-primary-rgb), 0.15);\n transform: scale(1.02);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):disabled, textarea:disabled, select:disabled {\n background: var(--easy-form-group-background);\n border-color: var(--easy-form-border);\n cursor: not-allowed;\n opacity: 0.6;\n }\n .easy-form-submit {\n border-radius: 6px;\n font-weight: 600;\n background: var(--easy-form-primary);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n font-size: 0.875rem;\n transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: 0 4px 6px rgba(var(--easy-form-primary-rgb), 0.25);\n }\n .easy-form-submit:hover {\n background: color-mix(in srgb, var(--easy-form-primary) 75%, black);\n box-shadow: 0 6px 12px rgba(var(--easy-form-primary-rgb), 0.35);\n transform: translateY(-2px) scale(1.02);\n }\n .easy-form-submit:active {\n transform: translateY(0) scale(0.98);\n }\n .easy-form-submit:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n transform: none;\n }\n .easy-form-group {\n border: 2px solid var(--easy-form-group-border);\n border-radius: 8px;\n background: var(--easy-form-group-background);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n }\n .easy-form-wizard-step {\n border: 2px solid var(--easy-form-border);\n border-radius: 6px;\n background: var(--easy-form-background);\n transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-wizard-step:hover {\n border-color: var(--easy-form-primary);\n transform: scale(1.05);\n }\n .easy-form-wizard-step.active {\n border-color: var(--easy-form-primary);\n background: var(--easy-form-primary);\n color: white;\n box-shadow: 0 4px 12px rgba(var(--easy-form-primary-rgb), 0.3);\n transform: scale(1.05);\n }\n .easy-form-array-item {\n border: 2px solid var(--easy-form-border);\n border-radius: 6px;\n background: var(--easy-form-background);\n transition: all 0.25s ease;\n }\n .easy-form-array-item:hover {\n border-color: var(--easy-form-group-border);\n box-shadow: 0 2px 8px rgba(var(--easy-form-primary-rgb), 0.15);\n }\n `\n}\n\n/**\n * Estilo Mantine - Ultra redondeado con elevación y efectos 3D\n */\nfunction getMantineStyles(_colors: Required<FormColors>): string {\n return `\n .easy-form-label {\n color: var(--easy-form-label-color);\n font-size: 0.875rem;\n font-weight: 600;\n margin-bottom: 0.625rem;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]), textarea, select {\n border: 1px solid var(--easy-form-border);\n border-radius: 12px;\n padding: 0.875rem 1.25rem;\n background: var(--easy-form-background);\n color: var(--easy-form-text);\n font-size: 0.875rem;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04), inset 0 1px 0 rgba(255, 255, 255, 0.8);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):hover, textarea:hover, select:hover {\n border-color: color-mix(in srgb, var(--easy-form-border) 70%, black);\n background: linear-gradient(to bottom, var(--easy-form-background), var(--easy-form-group-background));\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.08), inset 0 1px 0 rgba(255, 255, 255, 0.9);\n transform: translateY(-2px);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):focus, textarea:focus, select:focus {\n outline: none;\n border-color: var(--easy-form-primary);\n background: var(--easy-form-background);\n box-shadow: 0 0 0 3px rgba(var(--easy-form-primary-rgb), 0.15), 0 6px 16px rgba(var(--easy-form-primary-rgb), 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.9);\n transform: translateY(-3px);\n }\n .easy-form-submit {\n border-radius: 12px;\n font-weight: 600;\n background: linear-gradient(135deg, var(--easy-form-primary) 0%, color-mix(in srgb, var(--easy-form-primary) 75%, black) 100%);\n box-shadow: 0 4px 12px rgba(var(--easy-form-primary-rgb), 0.3), 0 2px 4px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.2);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-submit:hover {\n box-shadow: 0 8px 20px rgba(var(--easy-form-primary-rgb), 0.4), 0 4px 8px rgba(0, 0, 0, 0.15), inset 0 1px 0 rgba(255, 255, 255, 0.3);\n transform: translateY(-3px) scale(1.02);\n }\n .easy-form-submit:active {\n transform: translateY(-1px) scale(0.98);\n box-shadow: 0 2px 8px rgba(var(--easy-form-primary-rgb), 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.2);\n }\n .easy-form-group {\n border: 1px solid var(--easy-form-group-border);\n border-radius: 16px;\n background: var(--easy-form-group-background);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08), inset 0 1px 0 rgba(255, 255, 255, 0.8);\n padding: 1.5rem;\n }\n .easy-form-wizard-step {\n border: 1px solid var(--easy-form-border);\n border-radius: 12px;\n background: var(--easy-form-background);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04);\n }\n .easy-form-wizard-step:hover {\n background: linear-gradient(to bottom, var(--easy-form-background), var(--easy-form-group-background));\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n transform: translateY(-2px);\n }\n .easy-form-wizard-step.active {\n border-color: var(--easy-form-primary);\n background: linear-gradient(135deg, var(--easy-form-primary) 0%, color-mix(in srgb, var(--easy-form-primary) 75%, black) 100%);\n color: white;\n box-shadow: 0 6px 20px rgba(var(--easy-form-primary-rgb), 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.2);\n transform: translateY(-3px) scale(1.05);\n }\n .easy-form-array-item {\n border: 1px solid var(--easy-form-group-border);\n border-radius: 12px;\n background: var(--easy-form-group-background);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06), inset 0 1px 0 rgba(255, 255, 255, 0.8);\n }\n `\n}\n\n/**\n * Estilo Glass - Glassmorphism extremo con blur pronunciado y efectos neón\n */\nfunction getGlassStyles(_colors: Required<FormColors>): string {\n return `\n .easy-form-label {\n color: var(--easy-form-label-color);\n font-size: 0.875rem;\n font-weight: 600;\n margin-bottom: 0.75rem;\n text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]), textarea, select {\n border: 2px solid rgba(255, 255, 255, 0.4);\n border-radius: 16px;\n padding: 0.875rem 1.25rem;\n background: rgba(255, 255, 255, 0.15);\n backdrop-filter: blur(20px) saturate(180%);\n -webkit-backdrop-filter: blur(20px) saturate(180%);\n font-size: 0.875rem;\n color: var(--easy-form-text);\n transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.3), 0 0 0 1px rgba(255, 255, 255, 0.1);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"])::placeholder, textarea::placeholder, select::placeholder {\n color: rgba(255, 255, 255, 0.6);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):hover, textarea:hover, select:hover {\n border-color: rgba(255, 255, 255, 0.6);\n background: rgba(255, 255, 255, 0.25);\n box-shadow: 0 12px 24px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 0 20px rgba(255, 255, 255, 0.1);\n transform: translateY(-2px);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):focus, textarea:focus, select:focus {\n outline: none;\n border-color: rgba(255, 255, 255, 0.8);\n background: rgba(255, 255, 255, 0.3);\n box-shadow: 0 0 0 4px rgba(var(--easy-form-primary-rgb), 0.3), 0 16px 32px rgba(var(--easy-form-primary-rgb), 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.5), 0 0 30px rgba(var(--easy-form-primary-rgb), 0.2);\n transform: translateY(-3px) scale(1.02);\n }\n .easy-form-submit {\n border-radius: 16px;\n font-weight: 600;\n background: rgba(255, 255, 255, 0.2);\n backdrop-filter: blur(20px) saturate(180%);\n -webkit-backdrop-filter: blur(20px) saturate(180%);\n border: 2px solid rgba(255, 255, 255, 0.4);\n color: var(--easy-form-text);\n box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3), 0 0 20px rgba(255, 255, 255, 0.1);\n transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-submit:hover {\n background: rgba(255, 255, 255, 0.3);\n border-color: rgba(255, 255, 255, 0.6);\n box-shadow: 0 12px 32px rgba(var(--easy-form-primary-rgb), 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.5), 0 0 40px rgba(var(--easy-form-primary-rgb), 0.3);\n transform: translateY(-3px) scale(1.05);\n }\n .easy-form-submit:active {\n transform: translateY(-1px) scale(0.98);\n }\n .easy-form-group {\n border: 2px solid var(--easy-form-group-border);\n border-radius: 20px;\n background: var(--easy-form-group-background);\n backdrop-filter: blur(20px) saturate(180%);\n -webkit-backdrop-filter: blur(20px) saturate(180%);\n box-shadow: 0 16px 32px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3);\n padding: 2rem;\n }\n .easy-form-wizard-step {\n border: 2px solid rgba(255, 255, 255, 0.4);\n border-radius: 16px;\n background: rgba(255, 255, 255, 0.15);\n backdrop-filter: blur(20px) saturate(180%);\n -webkit-backdrop-filter: blur(20px) saturate(180%);\n transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n color: var(--easy-form-text);\n }\n .easy-form-wizard-step:hover {\n background: rgba(255, 255, 255, 0.25);\n box-shadow: 0 12px 24px rgba(0, 0, 0, 0.3), 0 0 20px rgba(255, 255, 255, 0.1);\n transform: translateY(-2px);\n }\n .easy-form-wizard-step.active {\n border-color: rgba(255, 255, 255, 0.8);\n background: rgba(var(--easy-form-primary-rgb), 0.3);\n backdrop-filter: blur(20px) saturate(180%);\n -webkit-backdrop-filter: blur(20px) saturate(180%);\n box-shadow: 0 0 0 3px rgba(var(--easy-form-primary-rgb), 0.4), 0 16px 32px rgba(var(--easy-form-primary-rgb), 0.3), 0 0 40px rgba(var(--easy-form-primary-rgb), 0.2);\n transform: translateY(-3px) scale(1.05);\n }\n .easy-form-array-item {\n border: 2px solid rgba(255, 255, 255, 0.4);\n border-radius: 16px;\n background: rgba(255, 255, 255, 0.15);\n backdrop-filter: blur(20px) saturate(180%);\n -webkit-backdrop-filter: blur(20px) saturate(180%);\n box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.3);\n }\n .easy-form-array-add,\n .easy-form-quantity-btn {\n border-radius: 16px;\n font-weight: 600;\n background: rgba(255, 255, 255, 0.2);\n backdrop-filter: blur(20px) saturate(180%);\n -webkit-backdrop-filter: blur(20px) saturate(180%);\n border: 2px solid rgba(255, 255, 255, 0.4);\n color: var(--easy-form-text);\n box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3), 0 0 20px rgba(255, 255, 255, 0.1);\n transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-array-add:hover,\n .easy-form-quantity-btn:hover:not(.disabled) {\n background: rgba(255, 255, 255, 0.3);\n border-color: rgba(255, 255, 255, 0.6);\n box-shadow: 0 12px 32px rgba(var(--easy-form-primary-rgb), 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.5), 0 0 40px rgba(var(--easy-form-primary-rgb), 0.3);\n transform: translateY(-3px) scale(1.05);\n }\n .easy-form-array-remove {\n border-radius: 16px;\n font-weight: 600;\n background: rgba(255, 255, 255, 0.2);\n backdrop-filter: blur(20px) saturate(180%);\n -webkit-backdrop-filter: blur(20px) saturate(180%);\n border: 2px solid rgba(255, 255, 255, 0.4);\n color: var(--easy-form-error);\n box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3);\n transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-array-remove:hover {\n background: rgba(255, 255, 255, 0.3);\n border-color: rgba(255, 255, 255, 0.6);\n box-shadow: 0 12px 24px rgba(0, 0, 0, 0.3), 0 0 20px rgba(255, 255, 255, 0.1);\n transform: translateY(-2px);\n }\n .easy-form-wizard-prev,\n .easy-form-wizard-next {\n border-radius: 16px;\n font-weight: 600;\n background: rgba(255, 255, 255, 0.2);\n backdrop-filter: blur(20px) saturate(180%);\n -webkit-backdrop-filter: blur(20px) saturate(180%);\n border: 2px solid rgba(255, 255, 255, 0.4);\n color: var(--easy-form-text);\n box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3), 0 0 20px rgba(255, 255, 255, 0.1);\n transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-wizard-prev:hover:not(:disabled),\n .easy-form-wizard-next:hover {\n background: rgba(255, 255, 255, 0.3);\n border-color: rgba(255, 255, 255, 0.6);\n box-shadow: 0 12px 32px rgba(var(--easy-form-primary-rgb), 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.5), 0 0 40px rgba(var(--easy-form-primary-rgb), 0.3);\n transform: translateY(-3px) scale(1.05);\n }\n .easy-form-wizard-next {\n background: rgba(var(--easy-form-primary-rgb), 0.25);\n }\n .easy-form-wizard-next:hover {\n background: rgba(var(--easy-form-primary-rgb), 0.35);\n }\n `\n}\n\n/**\n * Estilo Bordered - Bordes ultra gruesos con efectos 3D y sombras pronunciadas\n */\nfunction getBorderedStyles(_colors: Required<FormColors>): string {\n return `\n .easy-form-label {\n color: var(--easy-form-label-color);\n font-size: 0.875rem;\n font-weight: 700;\n margin-bottom: 0.75rem;\n text-transform: uppercase;\n letter-spacing: 0.1em;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]), textarea, select {\n border: 3px solid var(--easy-form-text);\n border-radius: 0;\n padding: 0.875rem 1.25rem;\n background: var(--easy-form-background);\n color: var(--easy-form-text);\n font-size: 0.875rem;\n font-weight: 600;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.1), inset 0 2px 4px rgba(0, 0, 0, 0.05);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):hover, textarea:hover, select:hover {\n border-color: var(--easy-form-primary);\n box-shadow: 6px 6px 0 rgba(var(--easy-form-primary-rgb), 0.2), inset 0 2px 4px rgba(0, 0, 0, 0.05);\n transform: translate(-2px, -2px);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):focus, textarea:focus, select:focus {\n outline: none;\n border-color: var(--easy-form-primary);\n border-width: 4px;\n box-shadow: 8px 8px 0 rgba(var(--easy-form-primary-rgb), 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.05), 0 0 0 4px rgba(var(--easy-form-primary-rgb), 0.1);\n transform: translate(-4px, -4px);\n }\n .easy-form-submit {\n border-radius: 0;\n font-weight: 700;\n border: 4px solid var(--easy-form-text);\n background: var(--easy-form-primary);\n color: var(--easy-form-on-primary);\n text-transform: uppercase;\n letter-spacing: 0.1em;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: 6px 6px 0 rgba(0, 0, 0, 0.2);\n }\n .easy-form-submit:hover {\n background: color-mix(in srgb, var(--easy-form-primary) 75%, black);\n box-shadow: 8px 8px 0 rgba(0, 0, 0, 0.3);\n transform: translate(-2px, -2px);\n }\n .easy-form-submit:active {\n transform: translate(0, 0);\n box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.2);\n }\n .easy-form-group {\n border: 4px solid var(--easy-form-group-border);\n border-radius: 0;\n background: var(--easy-form-group-background);\n box-shadow: 8px 8px 0 rgba(0, 0, 0, 0.1);\n padding: 2rem;\n }\n .easy-form-wizard-step {\n border: 3px solid var(--easy-form-text);\n border-radius: 0;\n background: var(--easy-form-background);\n font-weight: 600;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.1);\n }\n .easy-form-wizard-step:hover {\n box-shadow: 6px 6px 0 rgba(0, 0, 0, 0.15);\n transform: translate(-2px, -2px);\n }\n .easy-form-wizard-step.active {\n border-color: var(--easy-form-primary);\n border-width: 4px;\n background: var(--easy-form-primary);\n color: white;\n box-shadow: 8px 8px 0 rgba(var(--easy-form-primary-rgb), 0.3);\n transform: translate(-4px, -4px);\n }\n .easy-form-array-item {\n border: 3px solid var(--easy-form-group-border);\n border-radius: 0;\n background: var(--easy-form-group-background);\n box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.1);\n }\n `\n}\n\n/**\n * Estilo Minimal - Ultra minimalista con líneas animadas y efectos sutiles\n */\nfunction getMinimalStyles(_colors: Required<FormColors>): string {\n return `\n .easy-form-label {\n color: var(--easy-form-label-color);\n font-size: 0.75rem;\n font-weight: 500;\n margin-bottom: 0.5rem;\n text-transform: uppercase;\n letter-spacing: 0.15em;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]), textarea, select {\n border: none;\n border-bottom: 1px solid var(--easy-form-border);\n border-radius: 0;\n padding: 0.625rem 0;\n background: transparent;\n color: var(--easy-form-text);\n font-size: 0.9375rem;\n font-weight: 300;\n transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n position: relative;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"])::after, textarea::after, select::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 0;\n width: 0;\n height: 2px;\n background: var(--easy-form-primary);\n transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):hover, textarea:hover, select:hover {\n border-bottom-color: color-mix(in srgb, var(--easy-form-border) 75%, black);\n padding-left: 0.5rem;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):focus, textarea:focus, select:focus {\n outline: none;\n border-bottom-color: var(--easy-form-primary);\n border-bottom-width: 2px;\n padding-bottom: calc(0.625rem - 1px);\n padding-left: 0;\n background: linear-gradient(to bottom, transparent 98%, rgba(var(--easy-form-primary-rgb), 0.05) 100%);\n }\n .easy-form-submit {\n border-radius: 0;\n font-weight: 300;\n border: none;\n border-bottom: 2px solid var(--easy-form-primary);\n background: transparent;\n color: var(--easy-form-primary);\n padding: 0.75rem 0;\n transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n text-transform: uppercase;\n letter-spacing: 0.2em;\n font-size: 0.75rem;\n position: relative;\n overflow: hidden;\n }\n .easy-form-submit::before {\n content: '';\n position: absolute;\n bottom: 0;\n left: -100%;\n width: 100%;\n height: 2px;\n background: var(--easy-form-primary);\n transition: left 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-submit:hover {\n background: linear-gradient(to bottom, rgba(var(--easy-form-primary-rgb), 0.03), transparent);\n padding-left: 1rem;\n }\n .easy-form-submit:hover::before {\n left: 0;\n }\n .easy-form-group {\n border: none;\n border-bottom: 1px solid var(--easy-form-group-border);\n border-radius: 0;\n background: transparent;\n padding-bottom: 2rem;\n margin-bottom: 2rem;\n }\n .easy-form-wizard-step {\n border: none;\n border-bottom: 2px solid var(--easy-form-border);\n border-radius: 0;\n background: transparent;\n font-weight: 300;\n text-transform: uppercase;\n letter-spacing: 0.15em;\n font-size: 0.75rem;\n transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n position: relative;\n }\n .easy-form-wizard-step::after {\n content: '';\n position: absolute;\n bottom: -2px;\n left: 0;\n width: 0;\n height: 2px;\n background: var(--easy-form-primary);\n transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-wizard-step:hover {\n color: var(--easy-form-primary);\n padding-left: 0.5rem;\n }\n .easy-form-wizard-step:hover::after {\n width: 100%;\n }\n .easy-form-wizard-step.active {\n border-bottom-color: var(--easy-form-primary);\n color: var(--easy-form-primary);\n font-weight: 500;\n }\n .easy-form-wizard-step.active::after {\n width: 100%;\n }\n .easy-form-array-item {\n border: none;\n border-bottom: 1px solid var(--easy-form-group-border);\n border-radius: 0;\n background: transparent;\n padding-bottom: 1.5rem;\n margin-bottom: 1.5rem;\n }\n .easy-form-array-add,\n .easy-form-quantity-btn {\n border-radius: 0;\n font-weight: 300;\n border: none;\n border-bottom: 2px solid var(--easy-form-primary);\n background: transparent;\n color: var(--easy-form-primary);\n padding: 0.5rem 0.75rem;\n text-transform: uppercase;\n letter-spacing: 0.15em;\n font-size: 0.75rem;\n transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-array-add:hover,\n .easy-form-quantity-btn:hover:not(.disabled) {\n background: linear-gradient(to bottom, rgba(var(--easy-form-primary-rgb), 0.03), transparent);\n padding-left: 1rem;\n }\n .easy-form-array-remove {\n border-radius: 0;\n font-weight: 300;\n border: none;\n border-bottom: 2px solid var(--easy-form-error);\n background: transparent;\n color: var(--easy-form-error);\n padding: 0.5rem 0.75rem;\n text-transform: uppercase;\n letter-spacing: 0.15em;\n font-size: 0.75rem;\n transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-array-remove:hover {\n background: linear-gradient(to bottom, rgba(var(--easy-form-primary-rgb), 0.03), transparent);\n padding-left: 1rem;\n }\n .easy-form-wizard-prev {\n border-radius: 0;\n font-weight: 300;\n border: none;\n border-bottom: 2px solid var(--easy-form-secondary);\n background: transparent;\n color: var(--easy-form-secondary);\n padding: 0.5rem 0.75rem;\n text-transform: uppercase;\n letter-spacing: 0.15em;\n font-size: 0.75rem;\n transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-wizard-next {\n border-radius: 0;\n font-weight: 300;\n border: none;\n border-bottom: 2px solid var(--easy-form-primary);\n background: transparent;\n color: var(--easy-form-primary);\n padding: 0.5rem 0.75rem;\n text-transform: uppercase;\n letter-spacing: 0.15em;\n font-size: 0.75rem;\n transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n }\n .easy-form-wizard-prev:hover:not(:disabled),\n .easy-form-wizard-next:hover {\n background: linear-gradient(to bottom, rgba(var(--easy-form-primary-rgb), 0.03), transparent);\n padding-left: 1rem;\n }\n .easy-form-error,\n .easy-form-description {\n background: none;\n border: none;\n padding: 0;\n }\n `\n}\n\n/**\n * Estilo EFC - EasyFormsCore Documentation Style\n * Glassmorphism con acentos del primary color\n */\nfunction getEfcStyles(_colors: Required<FormColors>): string {\n return `\n .easy-form-label {\n color: var(--easy-form-label-color);\n font-size: 0.875rem;\n font-weight: 600;\n margin-bottom: 0.75rem;\n letter-spacing: 0.025em;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]), textarea, select {\n border: 1px solid rgba(var(--easy-form-primary-rgb), 0.2);\n border-radius: 12px;\n padding: 0.875rem 1rem;\n background: rgba(var(--easy-form-primary-rgb), 0.05);\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n font-size: 0.9rem;\n color: var(--easy-form-text);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"])::placeholder, textarea::placeholder, select::placeholder {\n color: var(--easy-form-label-color);\n opacity: 0.5;\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):hover, textarea:hover, select:hover {\n border-color: rgba(var(--easy-form-primary-rgb), 0.4);\n background: rgba(var(--easy-form-primary-rgb), 0.08);\n }\n input:not([type=\"checkbox\"]):not([type=\"radio\"]):focus, textarea:focus, select:focus {\n outline: none;\n border-color: rgba(var(--easy-form-primary-rgb), 0.5);\n background: rgba(var(--easy-form-primary-rgb), 0.1);\n box-shadow: 0 0 0 3px rgba(var(--easy-form-primary-rgb), 0.15);\n }\n .easy-form-submit {\n border-radius: 12px;\n font-weight: 600;\n background: linear-gradient(135deg, var(--easy-form-primary) 0%, var(--easy-form-primary) 100%);\n border: none;\n color: white;\n padding: 0.875rem 1.5rem;\n box-shadow: 0 4px 14px rgba(var(--easy-form-primary-rgb), 0.35);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n cursor: pointer;\n }\n .easy-form-submit:hover {\n transform: translateY(-2px);\n box-shadow: 0 6px 20px rgba(var(--easy-form-primary-rgb), 0.45);\n }\n .easy-form-submit:active {\n transform: translateY(0);\n box-shadow: 0 2px 8px rgba(var(--easy-form-primary-rgb), 0.3);\n }\n .easy-form-group {\n border: 1px solid rgba(var(--easy-form-primary-rgb), 0.2);\n border-radius: 16px;\n background: rgba(var(--easy-form-primary-rgb), 0.03);\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n padding: 1.5rem;\n transition: all 0.3s ease;\n }\n .easy-form-group:hover {\n border-color: rgba(var(--easy-form-primary-rgb), 0.3);\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);\n }\n .easy-form-group-label {\n color: var(--easy-form-group-title);\n font-weight: 700;\n font-size: 1.1rem;\n }\n .easy-form-wizard-step {\n border: 1px solid rgba(var(--easy-form-primary-rgb), 0.2);\n border-radius: 10px;\n background: rgba(var(--easy-form-primary-rgb), 0.05);\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n color: var(--easy-form-text);\n padding: 0.75rem 1.25rem;\n }\n .easy-form-wizard-step:hover {\n background: rgba(var(--easy-form-primary-rgb), 0.1);\n border-color: rgba(var(--easy-form-primary-rgb), 0.4);\n transform: translateY(-2px);\n }\n .easy-form-wizard-step.active {\n border-color: var(--easy-form-primary);\n background: linear-gradient(135deg, rgba(var(--easy-form-primary-rgb), 0.2) 0%, rgba(var(--easy-form-primary-rgb), 0.1) 100%);\n box-shadow: 0 0 8px rgba(var(--easy-form-primary-rgb), 0.3);\n font-weight: 600;\n }\n .easy-form-array-item {\n border: 1px solid rgba(var(--easy-form-primary-rgb), 0.15);\n border-radius: 12px;\n background: rgba(var(--easy-form-primary-rgb), 0.03);\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n padding: 1rem;\n transition: all 0.3s ease;\n }\n .easy-form-array-item:hover {\n border-color: rgba(var(--easy-form-primary-rgb), 0.25);\n }\n .easy-form-array-add,\n .easy-form-quantity-btn {\n border-radius: 10px;\n font-weight: 600;\n border: 1px solid rgba(var(--easy-form-primary-rgb), 0.2);\n background: rgba(var(--easy-form-primary-rgb), 0.1);\n color: var(--easy-form-primary);\n padding: 0.5rem 1rem;\n font-size: 0.85rem;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n cursor: pointer;\n }\n .easy-form-array-add:hover,\n .easy-form-quantity-btn:hover:not(.disabled) {\n background: rgba(var(--easy-form-primary-rgb), 0.2);\n border-color: rgba(var(--easy-form-primary-rgb), 0.4);\n transform: translateY(-1px);\n }\n .easy-form-array-remove {\n border-radius: 10px;\n font-weight: 600;\n border: 1px solid rgba(var(--easy-form-error-rgb), 0.2);\n background: rgba(var(--easy-form-error-rgb), 0.1);\n color: var(--easy-form-error);\n padding: 0.5rem 1rem;\n font-size: 0.85rem;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n cursor: pointer;\n }\n .easy-form-array-remove:hover {\n background: rgba(var(--easy-form-error-rgb), 0.2);\n border-color: rgba(var(--easy-form-error-rgb), 0.4);\n transform: translateY(-1px);\n }\n .easy-form-wizard-prev {\n border-radius: 10px;\n font-weight: 600;\n border: 1px solid rgba(var(--easy-form-primary-rgb), 0.2);\n background: rgba(var(--easy-form-primary-rgb), 0.05);\n color: var(--easy-form-primary);\n padding: 0.75rem 1.25rem;\n font-size: 0.9rem;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n cursor: pointer;\n }\n .easy-form-wizard-next {\n border-radius: 10px;\n font-weight: 600;\n background: linear-gradient(135deg, var(--easy-form-primary) 0%, var(--easy-form-primary) 100%);\n border: none;\n color: white;\n padding: 0.75rem 1.25rem;\n font-size: 0.9rem;\n box-shadow: 0 4px 14px rgba(var(--easy-form-primary-rgb), 0.35);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n cursor: pointer;\n }\n .easy-form-wizard-prev:hover:not(:disabled) {\n background: rgba(var(--easy-form-primary-rgb), 0.1);\n border-color: rgba(var(--easy-form-primary-rgb), 0.4);\n }\n .easy-form-wizard-next:hover {\n transform: translateY(-2px);\n box-shadow: 0 6px 20px rgba(var(--easy-form-primary-rgb), 0.45);\n }\n .easy-form-error {\n background: rgba(var(--easy-form-error-rgb), 0.1);\n border: 1px solid rgba(var(--easy-form-error-rgb), 0.2);\n border-radius: 8px;\n padding: 0.5rem 0.75rem;\n color: var(--easy-form-error);\n font-size: 0.85rem;\n }\n .easy-form-description {\n color: var(--easy-form-label-color);\n opacity: 0.7;\n font-size: 0.85rem;\n }\n .easy-form-checkbox-wrapper,\n .easy-form-radio-wrapper {\n gap: 0.75rem;\n }\n input[type=\"checkbox\"],\n input[type=\"radio\"] {\n accent-color: var(--easy-form-primary);\n width: 1.1rem;\n height: 1.1rem;\n }\n select {\n appearance: none;\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236366f1' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 1rem center;\n padding-right: 2.5rem;\n }\n `\n}\n","import type { PredefinedMask, CustomMask } from '../types'\n\n/**\n * Máscaras predefinidas\n */\nexport const PREDEFINED_MASKS: Record<PredefinedMask, CustomMask> = {\n 'phone': {\n pattern: '(999) 999-9999',\n placeholder: '_',\n },\n 'phone-us': {\n pattern: '(999) 999-9999',\n placeholder: '_',\n },\n 'phone-international': {\n pattern: '+99 999 999 9999',\n placeholder: '_',\n },\n 'date': {\n pattern: '99/99/9999',\n placeholder: '_',\n },\n 'date-us': {\n pattern: '99/99/9999',\n placeholder: '_',\n },\n 'date-eu': {\n pattern: '99-99-9999',\n placeholder: '_',\n },\n 'credit-card': {\n pattern: '9999 9999 9999 9999',\n placeholder: '_',\n },\n 'ssn': {\n pattern: '999-99-9999',\n placeholder: '_',\n },\n 'zip-code': {\n pattern: '99999',\n placeholder: '_',\n },\n 'currency': {\n pattern: '$999,999.99',\n placeholder: '_',\n transform: (value: string) => {\n // Remover caracteres no numéricos excepto punto decimal\n const cleaned = value.replace(/[^\\d.]/g, '')\n const num = parseFloat(cleaned) || 0\n return num.toFixed(2)\n },\n },\n 'percentage': {\n pattern: '999%',\n placeholder: '_',\n transform: (value: string) => {\n const cleaned = value.replace(/[^\\d]/g, '')\n return cleaned\n },\n },\n 'time': {\n pattern: '99:99',\n placeholder: '_',\n },\n 'datetime': {\n pattern: '99/99/9999 99:99',\n placeholder: '_',\n },\n}\n\n/**\n * Obtiene una máscara predefinida\n */\nexport function getPredefinedMask(type: PredefinedMask): CustomMask {\n return PREDEFINED_MASKS[type]\n}\n","/**\n * Validación contra patrones de inyección (SQL, XSS, command injection, etc.)\n */\n\n/** Mensaje de error por defecto para validación de inyección */\nexport const INJECTION_VALIDATION_MESSAGE =\n 'El valor contiene caracteres o patrones no permitidos'\n\n/** Patrones de inyección (regex, case-insensitive) */\nconst INJECTION_PATTERNS: RegExp[] = [\n // SQL Injection\n /\\b(union|select|insert|update|delete|drop|exec|execute|declare)\\s+(all\\s+)?(select|from|into|table)/i,\n /\\b(or|and)\\s+['\"]?\\d+['\"]?\\s*=\\s*['\"]?\\d+/i,\n /;\\s*(drop|delete|truncate|alter)\\s+/i,\n /--\\s*$/, // SQL comment\n /\\/\\*[\\s\\S]*\\*\\//, // Block comment\n /'\\s*or\\s+'1'\\s*=\\s*'1/i,\n /\"\\s*or\\s+\"1\"\\s*=\\s*\"1/i,\n /\\bexec\\s*\\(/i,\n /\\bxp_\\w+/i, // SQL Server extended procedures\n\n // XSS / Scripting\n /<script\\b[\\s\\S]*?>[\\s\\S]*?<\\/script>/i,\n /<script\\b/i,\n /javascript\\s*:/i,\n /vbscript\\s*:/i,\n /on\\w+\\s*=\\s*[\"'][^\"']*[\"']/i, // onclick=, onerror=, onload=, etc.\n /on\\w+\\s*=\\s*[^\\s>]+/i,\n /<iframe\\b/i,\n /<object\\b/i,\n /<embed\\b/i,\n /\\beval\\s*\\(/i,\n /document\\.(cookie|write|location)/i,\n /window\\.(location|open|eval)/i,\n\n // Command injection (shell)\n /[;&|]\\s*(ls|cat|rm|wget|curl|nc|bash|sh|python|perl)\\s/i,\n /\\$\\s*\\([^)]+\\)/, // $(...)\n /`[^`]+`/, // Backtick command substitution\n /\\|\\s*\\w+/, // Pipe to command (with word after)\n\n // NoSQL / Template injection\n /\\$\\s*where\\b/i,\n /\\$\\s*gt\\b|\\$\\s*ne\\b|\\$\\s*regex\\b/i,\n /\\{\\{[^}]*\\}\\}/, // Template literals\n /\\$\\{[^}]*\\}/, // JS template literals\n]\n\n/**\n * Verifica si un valor string contiene patrones de inyección\n */\nexport function containsInjection(value: string): boolean {\n if (typeof value !== 'string' || value.length === 0) {\n return false\n }\n const normalized = value.trim()\n if (normalized.length === 0) return false\n\n for (const pattern of INJECTION_PATTERNS) {\n if (pattern.test(value)) {\n return true\n }\n }\n return false\n}\n\n/**\n * Valida recursivamente un valor (string, array de strings, objetos con strings)\n * Retorna true si NO contiene inyección (válido), false si contiene (inválido)\n */\nexport function isSafeFromInjection(value: unknown): boolean {\n if (value === null || value === undefined) {\n return true\n }\n if (typeof value === 'string') {\n return !containsInjection(value)\n }\n if (Array.isArray(value)) {\n return value.every((item) => isSafeFromInjection(item))\n }\n if (typeof value === 'object') {\n return Object.values(value as Record<string, unknown>).every((v) =>\n isSafeFromInjection(v)\n )\n }\n // number, boolean, etc. - no aplica validación\n return true\n}\n","/**\n * Utilidad para bloquear formularios después de N intentos fallidos\n */\n\nexport interface AttemptsLockOptions {\n maxAttempts: number\n blockDurationMinutes?: number\n storageKey?: string\n onLocked?: (remainingMs: number) => void\n onUnlocked?: () => void\n}\n\ninterface StoredLockState {\n attempts: number\n lockedUntil?: number\n}\n\nexport class AttemptsLock {\n private maxAttempts: number\n private blockDurationMs: number\n private storageKey?: string\n private attempts: number = 0\n private lockedUntil: number | null = null\n private onLocked?: (remainingMs: number) => void\n private onUnlocked?: () => void\n private unlockCheckInterval: ReturnType<typeof setInterval> | null = null\n\n constructor(options: AttemptsLockOptions) {\n this.maxAttempts = Math.max(1, options.maxAttempts)\n this.blockDurationMs =\n (options.blockDurationMinutes ?? 5) * 60 * 1000\n this.storageKey = options.storageKey\n this.onLocked = options.onLocked\n this.onUnlocked = options.onUnlocked\n\n if (this.storageKey && typeof sessionStorage !== 'undefined') {\n this.loadFromStorage()\n }\n }\n\n private loadFromStorage(): void {\n if (!this.storageKey || typeof sessionStorage === 'undefined') return\n try {\n const stored = sessionStorage.getItem(this.storageKey)\n if (stored) {\n const data: StoredLockState = JSON.parse(stored)\n this.attempts = data.attempts ?? 0\n this.lockedUntil = data.lockedUntil ?? null\n this.checkExpiration()\n }\n } catch {\n // Ignorar errores de parsing\n }\n }\n\n private saveToStorage(): void {\n if (!this.storageKey || typeof sessionStorage === 'undefined') return\n try {\n const data: StoredLockState = {\n attempts: this.attempts,\n lockedUntil: this.lockedUntil ?? undefined,\n }\n sessionStorage.setItem(this.storageKey, JSON.stringify(data))\n } catch {\n // Ignorar errores\n }\n }\n\n private checkExpiration(): boolean {\n if (this.lockedUntil === null) return false\n if (Date.now() >= this.lockedUntil) {\n this.reset()\n this.onUnlocked?.()\n return true\n }\n return false\n }\n\n private startUnlockCheck(): void {\n if (this.unlockCheckInterval) return\n this.unlockCheckInterval = setInterval(() => {\n if (this.checkExpiration()) {\n this.stopUnlockCheck()\n }\n }, 1000)\n }\n\n private stopUnlockCheck(): void {\n if (this.unlockCheckInterval) {\n clearInterval(this.unlockCheckInterval)\n this.unlockCheckInterval = null\n }\n }\n\n /**\n * Incrementa el contador de intentos. Si alcanza maxAttempts, bloquea.\n */\n incrementAttempts(): void {\n this.attempts++\n if (this.attempts >= this.maxAttempts) {\n this.lockedUntil = Date.now() + this.blockDurationMs\n this.saveToStorage()\n this.onLocked?.(this.blockDurationMs)\n this.startUnlockCheck()\n } else {\n this.saveToStorage()\n }\n }\n\n /**\n * Retorna true si el lock está activo (aún dentro del período de bloqueo)\n */\n isLocked(): boolean {\n if (this.checkExpiration()) return false\n return this.lockedUntil !== null && Date.now() < this.lockedUntil\n }\n\n /**\n * Retorna los milisegundos restantes del bloqueo, o 0 si no está bloqueado\n */\n getRemainingBlockTimeMs(): number {\n if (this.checkExpiration()) return 0\n if (this.lockedUntil === null) return 0\n return Math.max(0, this.lockedUntil - Date.now())\n }\n\n /**\n * Resetea el contador de intentos y el bloqueo\n */\n reset(): void {\n this.attempts = 0\n this.lockedUntil = null\n this.stopUnlockCheck()\n this.saveToStorage()\n }\n\n /**\n * Retorna el número actual de intentos\n */\n getAttempts(): number {\n return this.attempts\n }\n}\n","/**\n * Utilidades generales\n */\n\n/**\n * Convierte un valor a string para atributos HTML\n */\nexport function attributeValue(value: any): string {\n if (value === null || value === undefined) {\n return ''\n }\n if (typeof value === 'boolean') {\n return value ? 'true' : 'false'\n }\n if (typeof value === 'object') {\n return JSON.stringify(value)\n }\n return String(value)\n}\n\n/**\n * Parsea un valor desde un atributo HTML\n */\nexport function parseAttributeValue(value: string | null): any {\n if (!value) {\n return null\n }\n try {\n return JSON.parse(value)\n } catch {\n return value\n }\n}\n\n/**\n * Genera un ID único\n */\nexport function generateId(prefix = 'ef'): string {\n return `${prefix}-${Math.random().toString(36).substr(2, 9)}`\n}\n\n/**\n * Obtiene el valor anidado de un objeto usando notación de punto\n */\nexport function getNestedValue(obj: Record<string, any>, path: string): any {\n return path.split('.').reduce((current, key) => current?.[key], obj)\n}\n\n/**\n * Establece un valor anidado en un objeto usando notación de punto\n */\nexport function setNestedValue(\n obj: Record<string, any>,\n path: string,\n value: any\n): void {\n const keys = path.split('.')\n const lastKey = keys.pop()!\n const target = keys.reduce((current, key) => {\n if (!current[key] || typeof current[key] !== 'object') {\n current[key] = {}\n }\n return current[key]\n }, obj)\n target[lastKey] = value\n}\n\n/**\n * Valida si un email es válido\n */\nexport function isValidEmail(email: string): boolean {\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n return emailRegex.test(email)\n}\n\n/**\n * Sanitiza un string para usar como ID de HTML\n */\nexport function sanitizeId(str: string): string {\n return str.replace(/[^a-zA-Z0-9-_]/g, '-')\n}\n\n// Exportar funciones de estilos\nexport { getThemeStyles, getColors } from './styles'\n\n// Exportar máscaras\nexport { PREDEFINED_MASKS, getPredefinedMask } from './masks'\n\n// Exportar validación anti-inyección\nexport {\n containsInjection,\n isSafeFromInjection,\n INJECTION_VALIDATION_MESSAGE,\n} from './injection-validation'\n\n// Exportar AttemptsLock\nexport { AttemptsLock } from './attempts-lock'\nexport type { AttemptsLockOptions } from './attempts-lock'\n","import type {\n Validation,\n Field,\n MinLengthValidation,\n MaxLengthValidation,\n MinValidation,\n MaxValidation,\n CustomValidation,\n NoInjectionValidation,\n} from '../types'\nimport { isValidEmail } from '../utils'\nimport { isSafeFromInjection, INJECTION_VALIDATION_MESSAGE } from '../utils/injection-validation'\n\n/**\n * Resultado de una validación\n */\nexport interface ValidationResult {\n isValid: boolean\n message?: string\n}\n\n/**\n * Motor de validaciones\n */\nexport class ValidationEngine {\n /**\n * Valida un campo con todas sus validaciones\n */\n async validateField(\n field: Field,\n value: any\n ): Promise<string[]> {\n return this.validateFieldWithValidations(field, value, field.validations || [])\n }\n\n /**\n * Valida un campo con validaciones específicas\n */\n async validateFieldWithValidations(\n _field: Field,\n value: any,\n validations: Validation[]\n ): Promise<string[]> {\n const errors: string[] = []\n\n if (!validations || validations.length === 0) {\n return errors\n }\n\n for (const validation of validations) {\n const result = await this.validateValue(validation, value)\n if (!result.isValid) {\n errors.push(result.message || this.getDefaultMessage(validation))\n }\n }\n\n return errors\n }\n\n /**\n * Valida un valor con una validación específica\n */\n private async validateValue(\n validation: Validation,\n value: any\n ): Promise<ValidationResult> {\n switch (validation.type) {\n case 'required':\n return this.validateRequired(value)\n case 'email':\n return this.validateEmail(value)\n case 'minLength':\n return this.validateMinLength(value, validation.value)\n case 'maxLength':\n return this.validateMaxLength(value, validation.value)\n case 'min':\n return this.validateMin(value, validation.value)\n case 'max':\n return this.validateMax(value, validation.value)\n case 'pattern':\n return this.validatePattern(value, validation.value)\n case 'custom':\n return await this.validateCustom(value, validation)\n case 'noInjection':\n return this.validateNoInjection(value, validation)\n default:\n return { isValid: true }\n }\n }\n\n /**\n * Valida campo requerido\n */\n private validateRequired(value: any): ValidationResult {\n const isValid =\n value !== null &&\n value !== undefined &&\n value !== '' &&\n !(Array.isArray(value) && value.length === 0)\n return {\n isValid,\n message: isValid ? undefined : 'Este campo es requerido',\n }\n }\n\n /**\n * Valida email\n */\n private validateEmail(value: any): ValidationResult {\n if (!value) {\n return { isValid: true } // Si está vacío, required debe manejarlo\n }\n const isValid = typeof value === 'string' && isValidEmail(value)\n return {\n isValid,\n message: isValid ? undefined : 'Debe ser un email válido',\n }\n }\n\n /**\n * Valida longitud mínima\n */\n private validateMinLength(\n value: any,\n minLength: number\n ): ValidationResult {\n if (!value) {\n return { isValid: true }\n }\n const str = String(value)\n const isValid = str.length >= minLength\n return {\n isValid,\n message: isValid\n ? undefined\n : `Debe tener al menos ${minLength} caracteres`,\n }\n }\n\n /**\n * Valida longitud máxima\n */\n private validateMaxLength(\n value: any,\n maxLength: number\n ): ValidationResult {\n if (!value) {\n return { isValid: true }\n }\n const str = String(value)\n const isValid = str.length <= maxLength\n return {\n isValid,\n message: isValid\n ? undefined\n : `Debe tener máximo ${maxLength} caracteres`,\n }\n }\n\n /**\n * Valida valor mínimo\n */\n private validateMin(value: any, min: number): ValidationResult {\n if (value === null || value === undefined || value === '') {\n return { isValid: true }\n }\n const num = Number(value)\n const isValid = !isNaN(num) && num >= min\n return {\n isValid,\n message: isValid ? undefined : `Debe ser mayor o igual a ${min}`,\n }\n }\n\n /**\n * Valida valor máximo\n */\n private validateMax(value: any, max: number): ValidationResult {\n if (value === null || value === undefined || value === '') {\n return { isValid: true }\n }\n const num = Number(value)\n const isValid = !isNaN(num) && num <= max\n return {\n isValid,\n message: isValid ? undefined : `Debe ser menor o igual a ${max}`,\n }\n }\n\n /**\n * Valida patrón regex\n */\n private validatePattern(value: any, pattern: string | RegExp): ValidationResult {\n if (!value) {\n return { isValid: true }\n }\n \n // Convertir pattern a RegExp si es necesario\n let regex: RegExp\n if (pattern instanceof RegExp) {\n regex = pattern\n } else if (typeof pattern === 'string') {\n try {\n regex = new RegExp(pattern)\n } catch (e) {\n // Si el patrón no es válido, considerar como válido para no bloquear\n console.warn('Invalid regex pattern:', pattern)\n return { isValid: true }\n }\n } else {\n // Si pattern no es string ni RegExp, intentar convertirlo\n console.warn('Pattern validation expects string or RegExp, got:', typeof pattern, pattern)\n return { isValid: true }\n }\n \n const isValid = regex.test(String(value))\n return {\n isValid,\n message: isValid ? undefined : 'El formato no es válido',\n }\n }\n\n /**\n * Valida que el valor no contenga patrones de inyección (SQL, XSS, etc.)\n */\n private validateNoInjection(\n value: any,\n validation: NoInjectionValidation\n ): ValidationResult {\n if (value === null || value === undefined || value === '') {\n return { isValid: true }\n }\n const isValid = isSafeFromInjection(value)\n return {\n isValid,\n message: isValid ? undefined : validation.message || INJECTION_VALIDATION_MESSAGE,\n }\n }\n\n /**\n * Valida con función personalizada\n */\n private async validateCustom(\n value: any,\n validation: CustomValidation\n ): Promise<ValidationResult> {\n try {\n const result = await validation.validator(value)\n return {\n isValid: Boolean(result),\n message: result ? undefined : validation.message || 'Validación fallida',\n }\n } catch (error) {\n return {\n isValid: false,\n message: validation.message || 'Error en la validación',\n }\n }\n }\n\n /**\n * Obtiene mensaje por defecto para una validación\n */\n private getDefaultMessage(validation: Validation): string {\n switch (validation.type) {\n case 'required':\n return 'Este campo es requerido'\n case 'email':\n return 'Debe ser un email válido'\n case 'minLength':\n return `Debe tener al menos ${(validation as MinLengthValidation).value} caracteres`\n case 'maxLength':\n return `Debe tener máximo ${(validation as MaxLengthValidation).value} caracteres`\n case 'min':\n return `Debe ser mayor o igual a ${(validation as MinValidation).value}`\n case 'max':\n return `Debe ser menor o igual a ${(validation as MaxValidation).value}`\n case 'pattern':\n return 'El formato no es válido'\n case 'custom':\n return 'Validación fallida'\n case 'noInjection':\n return INJECTION_VALIDATION_MESSAGE\n default:\n return 'Campo inválido'\n }\n }\n\n /**\n * Evalúa si un campo debe ser validado basándose en sus dependencias\n * Un campo no debe validarse si está oculto por una condición\n */\n private shouldValidateField(field: Field, values: Record<string, any>): boolean {\n // Skip if explicitly hidden or disabled\n if (field.hidden || field.disabled) {\n return false\n }\n\n // Check dependencies to see if field should be visible\n if (field.dependencies) {\n // Check if field should be shown based on dependencies.show\n const showDep = (field.dependencies as any).show\n if (showDep) {\n const isVisible = this.evaluateCondition(showDep, values)\n if (!isVisible) {\n return false\n }\n }\n \n // Also check other dependency actions (hide, enable, disable)\n for (const [action, dep] of Object.entries(field.dependencies)) {\n if (action === 'show') continue // Already handled above\n \n if (!dep || !dep.field) continue\n \n // Get the value of the dependency field\n const depValue = values[dep.field]\n \n let isConditionMet = false\n \n switch (dep.operator) {\n case 'equals':\n isConditionMet = depValue === dep.value\n break\n case 'notEquals':\n isConditionMet = depValue !== dep.value\n break\n case 'contains':\n isConditionMet = String(depValue).includes(String(dep.value))\n break\n case 'notContains':\n isConditionMet = !String(depValue).includes(String(dep.value))\n break\n case 'greaterThan':\n isConditionMet = Number(depValue) > Number(dep.value)\n break\n case 'lessThan':\n isConditionMet = Number(depValue) < Number(dep.value)\n break\n case 'greaterThanOrEqual':\n isConditionMet = Number(depValue) >= Number(dep.value)\n break\n case 'lessThanOrEqual':\n isConditionMet = Number(depValue) <= Number(dep.value)\n break\n case 'in':\n isConditionMet = Array.isArray(dep.value) ? dep.value.includes(depValue) : false\n break\n case 'notIn':\n isConditionMet = Array.isArray(dep.value) ? !dep.value.includes(depValue) : true\n break\n case 'isEmpty':\n isConditionMet = !depValue || depValue === '' || (Array.isArray(depValue) && depValue.length === 0)\n break\n case 'isNotEmpty':\n isConditionMet = depValue && depValue !== '' && !(Array.isArray(depValue) && depValue.length === 0)\n break\n default:\n isConditionMet = true\n }\n \n // If action is 'hide' or 'disable', field should be visible when condition is NOT met\n if (action === 'hide' || action === 'disable') {\n isConditionMet = !isConditionMet\n }\n \n // If the condition for visibility is not met, skip validation\n if (!isConditionMet) {\n return false\n }\n }\n }\n \n return true\n }\n\n /**\n * Evalúa una condición simple\n */\n private evaluateCondition(dep: { field: string; operator: string; value?: any }, values: Record<string, any>): boolean {\n if (!dep || !dep.field) return true\n \n const depValue = values[dep.field]\n \n switch (dep.operator) {\n case 'equals':\n return depValue === dep.value\n case 'notEquals':\n return depValue !== dep.value\n case 'contains':\n return String(depValue).includes(String(dep.value))\n case 'notContains':\n return !String(depValue).includes(String(dep.value))\n case 'greaterThan':\n return Number(depValue) > Number(dep.value)\n case 'lessThan':\n return Number(depValue) < Number(dep.value)\n case 'greaterThanOrEqual':\n return Number(depValue) >= Number(dep.value)\n case 'lessThanOrEqual':\n return Number(depValue) <= Number(dep.value)\n case 'in':\n return Array.isArray(dep.value) ? dep.value.includes(depValue) : false\n case 'notIn':\n return Array.isArray(dep.value) ? !dep.value.includes(depValue) : true\n case 'isEmpty':\n return !depValue || depValue === '' || (Array.isArray(depValue) && depValue.length === 0)\n case 'isNotEmpty':\n return depValue && depValue !== '' && !(Array.isArray(depValue) && depValue.length === 0)\n default:\n return true\n }\n }\n \n /**\n * Valida todos los campos de un formulario\n */\n async validateForm(\n fields: Field[],\n values: Record<string, any>\n ): Promise<Record<string, string[]>> {\n const errors: Record<string, string[]> = {}\n\n for (const field of fields) {\n // Skip validation if field should not be validated based on dependencies\n if (!this.shouldValidateField(field, values)) {\n continue\n }\n \n const value = values[field.name]\n const fieldErrors = await this.validateField(field, value)\n if (fieldErrors.length > 0) {\n errors[field.name] = fieldErrors\n }\n }\n\n return errors\n }\n}\n","import type {\n FieldCondition,\n FieldDependencies,\n ConditionOperator,\n} from '../types'\n\n/**\n * Motor de evaluación de condiciones\n */\nexport class ConditionEngine {\n /**\n * Evalúa una condición individual\n */\n evaluateCondition(\n condition: FieldCondition,\n formValues: Record<string, any>\n ): boolean {\n const fieldValue = this.getFieldValue(condition.field, formValues)\n return this.compareValues(fieldValue, condition.operator, condition.value)\n }\n\n /**\n * Evalúa múltiples condiciones (AND por defecto, soportar OR)\n */\n evaluateConditions(\n conditions: FieldCondition | FieldCondition[],\n formValues: Record<string, any>,\n logic: 'and' | 'or' = 'and'\n ): boolean {\n const conditionsArray = Array.isArray(conditions) ? conditions : [conditions]\n\n if (conditionsArray.length === 0) {\n return true\n }\n\n if (logic === 'and') {\n return conditionsArray.every((condition) =>\n this.evaluateCondition(condition, formValues)\n )\n } else {\n return conditionsArray.some((condition) =>\n this.evaluateCondition(condition, formValues)\n )\n }\n }\n\n /**\n * Evalúa dependencias de un campo\n */\n evaluateDependencies(\n dependencies: FieldDependencies,\n formValues: Record<string, any>\n ): {\n visible: boolean\n enabled: boolean\n required: boolean\n } {\n let visible = true\n let enabled = true\n let required = false\n\n // Evaluar show/hide\n if (dependencies.show) {\n visible = this.evaluateConditions(dependencies.show, formValues)\n }\n if (dependencies.hide) {\n const shouldHide = this.evaluateConditions(dependencies.hide, formValues)\n visible = visible && !shouldHide\n }\n\n // Evaluar enable/disable\n if (dependencies.enable) {\n enabled = this.evaluateConditions(dependencies.enable, formValues)\n }\n if (dependencies.disable) {\n const shouldDisable = this.evaluateConditions(\n dependencies.disable,\n formValues\n )\n enabled = enabled && !shouldDisable\n }\n\n // Evaluar required/optional\n if (dependencies.required) {\n required = this.evaluateConditions(dependencies.required, formValues)\n }\n if (dependencies.optional) {\n const shouldBeOptional = this.evaluateConditions(\n dependencies.optional,\n formValues\n )\n required = required && !shouldBeOptional\n }\n\n return { visible, enabled, required }\n }\n\n /**\n * Obtiene el valor de un campo (soporta nested paths)\n */\n private getFieldValue(\n fieldName: string,\n formValues: Record<string, any>\n ): any {\n const parts = fieldName.split('.')\n let value = formValues\n\n for (const part of parts) {\n if (value === null || value === undefined) {\n return null\n }\n value = value[part]\n }\n\n return value\n }\n\n /**\n * Compara valores según el operador\n */\n private compareValues(\n fieldValue: any,\n operator: ConditionOperator,\n compareValue: any\n ): boolean {\n switch (operator) {\n case 'equals':\n return this.deepEqual(fieldValue, compareValue)\n\n case 'notEquals':\n return !this.deepEqual(fieldValue, compareValue)\n\n case 'contains':\n if (Array.isArray(fieldValue)) {\n return fieldValue.includes(compareValue)\n }\n if (typeof fieldValue === 'string') {\n return fieldValue.includes(String(compareValue))\n }\n return false\n\n case 'notContains':\n return !this.compareValues(fieldValue, 'contains', compareValue)\n\n case 'greaterThan':\n return this.toNumber(fieldValue) > this.toNumber(compareValue)\n\n case 'lessThan':\n return this.toNumber(fieldValue) < this.toNumber(compareValue)\n\n case 'greaterThanOrEqual':\n return this.toNumber(fieldValue) >= this.toNumber(compareValue)\n\n case 'lessThanOrEqual':\n return this.toNumber(fieldValue) <= this.toNumber(compareValue)\n\n case 'in':\n if (Array.isArray(compareValue)) {\n return compareValue.includes(fieldValue)\n }\n return false\n\n case 'notIn':\n return !this.compareValues(fieldValue, 'in', compareValue)\n\n case 'isEmpty':\n return (\n fieldValue === null ||\n fieldValue === undefined ||\n fieldValue === '' ||\n (Array.isArray(fieldValue) && fieldValue.length === 0)\n )\n\n case 'isNotEmpty':\n return !this.compareValues(fieldValue, 'isEmpty', compareValue)\n\n case 'regex':\n try {\n const regex =\n typeof compareValue === 'string'\n ? new RegExp(compareValue)\n : compareValue\n return regex.test(String(fieldValue || ''))\n } catch {\n return false\n }\n\n default:\n return false\n }\n }\n\n /**\n * Comparación profunda de valores\n */\n private deepEqual(a: any, b: any): boolean {\n if (a === b) {\n return true\n }\n\n if (a === null || b === null || a === undefined || b === undefined) {\n return a === b\n }\n\n if (typeof a !== typeof b) {\n return false\n }\n\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) {\n return false\n }\n return a.every((val, index) => this.deepEqual(val, b[index]))\n }\n\n if (typeof a === 'object') {\n const keysA = Object.keys(a)\n const keysB = Object.keys(b)\n\n if (keysA.length !== keysB.length) {\n return false\n }\n\n return keysA.every((key) => this.deepEqual(a[key], b[key]))\n }\n\n return false\n }\n\n /**\n * Convierte un valor a número\n */\n private toNumber(value: any): number {\n if (typeof value === 'number') {\n return value\n }\n if (typeof value === 'string') {\n const parsed = parseFloat(value)\n return isNaN(parsed) ? 0 : parsed\n }\n return 0\n }\n}\n","import type {\n FormState,\n WizardState,\n Field,\n FormSchema,\n} from '../types'\nimport { SchemaParser, type ParsedSchema } from './schema-parser'\nimport { ValidationEngine } from './validation-engine'\nimport { ConditionEngine } from './condition-engine'\nimport { getNestedValue, setNestedValue } from '../utils'\n\n/**\n * Gestor de estado del formulario\n */\nexport class StateManager {\n private state: FormState\n private wizardState: WizardState | null = null\n private schema: ParsedSchema | null = null\n private parser: SchemaParser\n private validator: ValidationEngine\n private conditionEngine: ConditionEngine\n private dependencyCache: Map<string, { visible: boolean; enabled: boolean; required: boolean }> = new Map()\n private fieldDependencies: Map<string, Set<string>> = new Map() // campo observado -> campos dependientes\n\n constructor() {\n this.parser = new SchemaParser()\n this.validator = new ValidationEngine()\n this.conditionEngine = new ConditionEngine()\n this.state = this.createInitialState()\n }\n\n /**\n * Crea el estado inicial\n */\n private createInitialState(): FormState {\n return {\n values: {},\n errors: {},\n touched: {},\n isValid: true,\n isSubmitting: false,\n }\n }\n\n /**\n * Inicializa el schema\n */\n initializeSchema(schema: FormSchema, initialData?: Record<string, any>): void {\n this.schema = this.parser.parse(schema)\n this.initializeValues(initialData)\n this.initializeWizard()\n this.buildDependencyMap()\n }\n\n /**\n * Extrae todos los campos recursivamente (incluyendo groups, rows).\n * Los campos de array.itemSchema NO se incluyen como top-level: viven dentro de cada ítem.\n */\n private extractAllFields(fields: Field[]): Field[] {\n const allFields: Field[] = []\n \n for (const field of fields) {\n allFields.push(field)\n \n if (field.type === 'group' && 'fields' in field) {\n allFields.push(...this.extractAllFields(field.fields))\n }\n if (field.type === 'row' && 'fields' in field) {\n allFields.push(...this.extractAllFields(field.fields))\n }\n // Array: no extraer itemSchema.fields como top-level; se inicializan dentro de cada ítem\n }\n \n return allFields\n }\n\n /**\n * Devuelve los nombres de campos que solo existen dentro de itemSchema de arrays\n * y NO como campos top-level. Estos NO deben aparecer como claves en la raíz de values.\n */\n private getArrayItemOnlyFieldNames(fields: Field[]): Set<string> {\n const topLevelNames = new Set(fields.map((f) => f.name))\n const arrayItemNames = new Set<string>()\n for (const field of fields) {\n if (field.type === 'array' && 'itemSchema' in field && field.itemSchema?.fields) {\n for (const sub of field.itemSchema.fields) {\n if (!topLevelNames.has(sub.name)) {\n arrayItemNames.add(sub.name)\n }\n }\n }\n }\n return arrayItemNames\n }\n\n /**\n * Encuentra el path completo de un campo dentro de grupos\n */\n private findFieldPath(fieldName: string, fields: Field[], parentPath: string = ''): string | null {\n for (const field of fields) {\n const currentPath = parentPath ? `${parentPath}.${field.name}` : field.name\n \n if (field.name === fieldName) {\n return currentPath\n }\n \n if (field.type === 'group' && 'fields' in field) {\n const found = this.findFieldPath(fieldName, field.fields, currentPath)\n if (found) return found\n }\n if (field.type === 'row' && 'fields' in field) {\n const found = this.findFieldPath(fieldName, field.fields, currentPath)\n if (found) return found\n }\n }\n \n return null\n }\n\n /**\n * Construye el mapa de dependencias para optimizar re-evaluaciones\n */\n private buildDependencyMap(): void {\n this.fieldDependencies.clear()\n this.dependencyCache.clear()\n\n if (!this.schema) return\n\n const topLevelFields = this.schema.isWizard\n ? this.schema.steps!.flatMap((step) => step.fields)\n : this.schema.fields || []\n\n const allFields = this.extractAllFields(topLevelFields)\n\n for (const field of allFields) {\n if (!field.dependencies) continue\n\n // Extraer todos los campos observados\n const observedFields = this.extractObservedFields(field.dependencies)\n \n for (const observedField of observedFields) {\n if (!this.fieldDependencies.has(observedField)) {\n this.fieldDependencies.set(observedField, new Set())\n }\n this.fieldDependencies.get(observedField)!.add(field.name)\n }\n }\n }\n\n /**\n * Extrae los nombres de campos observados de las dependencias\n */\n private extractObservedFields(dependencies: any): Set<string> {\n const fields = new Set<string>()\n\n const extractFromCondition = (condition: any) => {\n if (condition && condition.field) {\n fields.add(condition.field)\n }\n }\n\n const extractFromConditions = (conditions: any) => {\n if (Array.isArray(conditions)) {\n conditions.forEach(extractFromCondition)\n } else if (conditions) {\n extractFromCondition(conditions)\n }\n }\n\n if (dependencies.show) extractFromConditions(dependencies.show)\n if (dependencies.hide) extractFromConditions(dependencies.hide)\n if (dependencies.enable) extractFromConditions(dependencies.enable)\n if (dependencies.disable) extractFromConditions(dependencies.disable)\n if (dependencies.required) extractFromConditions(dependencies.required)\n if (dependencies.optional) extractFromConditions(dependencies.optional)\n\n return fields\n }\n\n /**\n * Inicializa los valores por defecto\n */\n private initializeValues(initialData?: Record<string, any>): void {\n if (!this.schema) return\n\n const topLevelFields = this.schema.isWizard\n ? this.schema.steps!.flatMap((step) => step.fields)\n : this.schema.fields || []\n\n const allFields = this.extractAllFields(topLevelFields)\n\n // Preservar valores existentes\n const existingValues = { ...this.state.values }\n const values: Record<string, any> = {}\n\n // Primero, cargar valores desde initialData si está disponible\n if (initialData) {\n for (const key in initialData) {\n const value = initialData[key]\n if (value !== undefined && value !== null) {\n setNestedValue(values, key, value)\n }\n }\n }\n\n // Luego, inicializar campos desde defaultValue o valores por defecto\n for (const field of allFields) {\n // Verificar si ya hay un valor desde initialData\n const existingValue = getNestedValue(values, field.name)\n \n // Si el campo ya tiene un valor desde initialData o existingValues, preservarlo\n if (existingValue !== undefined && existingValue !== null) {\n // Ya está inicializado desde initialData\n continue\n }\n \n // Verificar si hay un valor previo en existingValues\n const prevValue = getNestedValue(existingValues, field.name)\n if (prevValue !== undefined && prevValue !== null) {\n setNestedValue(values, field.name, prevValue)\n } else {\n // Solo inicializar si no existe valor previo\n this.initializeFieldValue(field, values)\n }\n }\n\n // Preservar valores de campos que no están en el schema actual (por si acaso)\n // Excluir nombres que son solo de itemSchema de arrays (street, city, etc.) — no deben estar en raíz\n const arrayItemOnlyNames = this.getArrayItemOnlyFieldNames(topLevelFields)\n for (const key in existingValues) {\n if (arrayItemOnlyNames.has(key)) continue\n if (!(key in values)) {\n values[key] = existingValues[key]\n }\n }\n\n // Rellenar arrays con initialData cuando length < minItems\n for (const field of topLevelFields) {\n if (field.type === 'array' && 'minItems' in field && 'itemSchema' in field) {\n const arrayField = field as { minItems?: number; itemSchema?: { fields?: Field[] } }\n const minItems = arrayField.minItems ?? 0\n if (minItems >= 1 && arrayField.itemSchema?.fields?.length) {\n const arr = getNestedValue(values, field.name)\n if (Array.isArray(arr) && arr.length < minItems) {\n const padded = [...arr]\n for (let i = arr.length; i < minItems; i++) {\n const item: Record<string, any> = {}\n for (const subField of arrayField.itemSchema!.fields!) {\n this.initializeFieldValue(subField, item)\n }\n padded.push(item)\n }\n setNestedValue(values, field.name, padded)\n }\n }\n }\n }\n\n // Eliminar claves que solo pertenecen a itemSchema de arrays (nunca deben estar en raíz)\n for (const name of arrayItemOnlyNames) {\n if (name in values) {\n delete values[name]\n }\n }\n\n this.state.values = values\n }\n\n /**\n * Inicializa el valor de un campo\n */\n private initializeFieldValue(\n field: Field,\n values: Record<string, any>\n ): void {\n if (field.defaultValue !== undefined) {\n values[field.name] = field.defaultValue\n } else {\n switch (field.type) {\n case 'checkbox':\n case 'switch':\n values[field.name] = field.checked || false\n break\n case 'select':\n if ('multiple' in field && field.multiple) {\n values[field.name] = []\n } else {\n values[field.name] = null\n }\n break\n case 'array': {\n const arrayField = field as { itemSchema?: { fields?: Field[] }; minItems?: number }\n const minItems = arrayField.minItems ?? 0\n const itemFields = arrayField.itemSchema?.fields\n if (minItems >= 1 && itemFields?.length) {\n const arr: Record<string, any>[] = []\n for (let i = 0; i < minItems; i++) {\n const item: Record<string, any> = {}\n for (const subField of itemFields) {\n this.initializeFieldValue(subField, item)\n }\n arr.push(item)\n }\n values[field.name] = arr\n } else {\n values[field.name] = []\n }\n break\n }\n case 'group':\n values[field.name] = {}\n if ('fields' in field) {\n for (const subField of field.fields) {\n this.initializeFieldValue(subField, values[field.name] as Record<string, any>)\n }\n }\n break\n case 'colorpicker':\n values[field.name] =\n (field as { defaultValue?: string }).defaultValue ?? '#000000'\n break\n default:\n values[field.name] = null\n }\n }\n }\n\n /**\n * Inicializa el estado del wizard\n */\n private initializeWizard(): void {\n if (!this.schema || !this.schema.isWizard) {\n this.wizardState = null\n return\n }\n\n this.wizardState = {\n currentStep: 0,\n totalSteps: this.schema.steps!.length,\n completedSteps: [],\n }\n }\n\n /**\n * Obtiene el estado actual\n */\n getState(): FormState {\n return { ...this.state }\n }\n\n /**\n * Obtiene el estado del wizard\n */\n getWizardState(): WizardState | null {\n return this.wizardState ? { ...this.wizardState } : null\n }\n\n /**\n * Obtiene un valor del formulario\n */\n getValue(fieldName: string): any {\n return getNestedValue(this.state.values, fieldName)\n }\n\n /**\n * Crea un ítem nuevo con valores por defecto para un campo array\n */\n createDefaultArrayItem(arrayField: Field): Record<string, any> {\n const itemSchema = (arrayField as { itemSchema?: { fields?: Field[] } }).itemSchema\n const itemFields = itemSchema?.fields\n if (!itemFields?.length) return {}\n const item: Record<string, any> = {}\n for (const subField of itemFields) {\n this.initializeFieldValue(subField, item)\n }\n return item\n }\n\n /**\n * Establece un valor\n */\n async setValue(fieldName: string, value: any): Promise<void> {\n setNestedValue(this.state.values, fieldName, value)\n this.state.touched[fieldName] = true\n\n // Invalidar cache de dependencias para campos que dependen de este\n this.invalidateDependencyCache(fieldName)\n\n // Validar el campo si está touched\n if (this.state.touched[fieldName] && this.schema) {\n await this.validateField(fieldName)\n }\n\n // Validar campos dependientes que ahora pueden tener diferentes validaciones\n const dependentFields = this.fieldDependencies.get(fieldName)\n if (dependentFields) {\n for (const dependentField of dependentFields) {\n await this.validateField(dependentField)\n }\n }\n\n this.updateValidity()\n }\n\n /**\n * Invalida el cache de dependencias para campos dependientes\n */\n private invalidateDependencyCache(fieldName: string): void {\n const dependentFields = this.fieldDependencies.get(fieldName)\n if (dependentFields) {\n for (const dependentField of dependentFields) {\n this.dependencyCache.delete(dependentField)\n }\n }\n }\n\n /**\n * Establece un valor sin validar (útil para preservar valores durante re-renderizado)\n */\n setValueWithoutValidation(fieldName: string, value: any): void {\n setNestedValue(this.state.values, fieldName, value)\n // Invalidar cache de dependencias para campos que dependen de este\n this.invalidateDependencyCache(fieldName)\n // No marcar como touched ni validar\n }\n\n /**\n * Valida un campo específico\n */\n async validateField(fieldName: string): Promise<void> {\n if (!this.schema) return\n\n const topLevelFields = this.schema.isWizard\n ? this.schema.steps!.flatMap((step) => step.fields)\n : this.schema.fields || []\n\n const allFields = this.extractAllFields(topLevelFields)\n const field = allFields.find((f) => f.name === fieldName)\n if (!field) return\n\n // Si el campo no es visible, no validar\n if (!this.getFieldVisibility(fieldName)) {\n delete this.state.errors[fieldName]\n return\n }\n\n const value = this.getValue(fieldName)\n \n // Obtener validaciones activas (incluyendo condicionales)\n const activeValidations = this.getActiveValidations(field)\n \n const errors = await this.validator.validateFieldWithValidations(\n field,\n value,\n activeValidations\n )\n\n if (errors.length > 0) {\n this.state.errors[fieldName] = errors\n } else {\n delete this.state.errors[fieldName]\n }\n }\n\n /**\n * Obtiene las validaciones activas para un campo (incluyendo condicionales)\n */\n private getActiveValidations(field: Field): any[] {\n let validations = [...(field.validations || [])]\n\n // Agregar validación anti-inyección automática para campos de texto\n const textFieldTypes = ['text', 'email', 'password', 'textarea']\n const skipInjection = field.skipInjectionValidation ?? (field.props as any)?.skipInjectionValidation\n if (\n textFieldTypes.includes(field.type) &&\n !skipInjection &&\n !validations.some((v) => v.type === 'noInjection')\n ) {\n validations = [{ type: 'noInjection' }, ...validations]\n }\n\n // Verificar si el campo es requerido dinámicamente a través de dependencias\n const isRequired = this.getFieldRequired(field.name)\n const hasRequiredValidation = validations.some(v => v.type === 'required')\n \n if (isRequired && !hasRequiredValidation) {\n // Agregar validación required si no existe\n validations = [{ type: 'required' }, ...validations]\n } else if (!isRequired && hasRequiredValidation) {\n // Remover validación required si el campo no es requerido dinámicamente\n validations = validations.filter(v => v.type !== 'required')\n }\n\n // Agregar validaciones condicionales si se cumplen las condiciones\n if (field.conditionalValidations) {\n for (const conditional of field.conditionalValidations) {\n const conditionMet = this.conditionEngine.evaluateConditions(\n conditional.condition,\n this.state.values\n )\n if (conditionMet) {\n validations = [...validations, ...conditional.validations]\n }\n }\n }\n\n return validations\n }\n\n /**\n * Valida todo el formulario\n */\n async validateForm(): Promise<Record<string, string[]>> {\n if (!this.schema) {\n return {}\n }\n\n const topLevelFields = this.schema.isWizard\n ? this.schema.steps!.flatMap((step) => step.fields)\n : this.schema.fields || []\n\n const allFields = this.extractAllFields(topLevelFields)\n const errors = await this.validator.validateForm(\n allFields,\n this.state.values\n )\n\n this.state.errors = errors\n this.updateValidity()\n\n return errors\n }\n\n /**\n * Actualiza la validez del formulario\n */\n private updateValidity(): void {\n this.state.isValid = Object.keys(this.state.errors).length === 0\n }\n\n /**\n * Marca un campo como touched\n */\n setTouched(fieldName: string): void {\n this.state.touched[fieldName] = true\n }\n\n /**\n * Obtiene los errores de un campo\n */\n getErrors(fieldName: string): string[] {\n return this.state.errors[fieldName] || []\n }\n\n /**\n * Obtiene todos los errores\n */\n getAllErrors(): Record<string, string[]> {\n return { ...this.state.errors }\n }\n\n /**\n * Resetea el formulario\n */\n reset(): void {\n this.state = this.createInitialState()\n if (this.schema) {\n this.initializeValues()\n this.initializeWizard()\n }\n }\n\n /**\n * Avanza al siguiente step del wizard\n */\n nextStep(): boolean {\n if (!this.wizardState) return false\n if (this.wizardState.currentStep < this.wizardState.totalSteps - 1) {\n this.wizardState.currentStep++\n return true\n }\n return false\n }\n\n /**\n * Retrocede al step anterior del wizard\n */\n previousStep(): boolean {\n if (!this.wizardState) return false\n if (this.wizardState.currentStep > 0) {\n this.wizardState.currentStep--\n return true\n }\n return false\n }\n\n /**\n * Va a un step específico\n */\n goToStep(stepIndex: number): boolean {\n if (!this.wizardState) return false\n if (stepIndex >= 0 && stepIndex < this.wizardState.totalSteps) {\n this.wizardState.currentStep = stepIndex\n return true\n }\n return false\n }\n\n /**\n * Marca un step como completado\n */\n completeStep(stepIndex: number): void {\n if (!this.wizardState) return\n if (!this.wizardState.completedSteps.includes(stepIndex)) {\n this.wizardState.completedSteps.push(stepIndex)\n }\n }\n\n /**\n * Establece el estado de submitting\n */\n setSubmitting(isSubmitting: boolean): void {\n this.state.isSubmitting = isSubmitting\n }\n\n /**\n * Obtiene los campos del step actual\n */\n getCurrentStepFields(): Field[] {\n if (!this.schema || !this.schema.isWizard || !this.wizardState) {\n return this.schema?.fields || []\n }\n return this.schema.steps![this.wizardState.currentStep].fields\n }\n\n /**\n * Obtiene la visibilidad de un campo basándose en dependencias\n */\n getFieldVisibility(fieldName: string): boolean {\n // Verificar cache primero\n const cached = this.dependencyCache.get(fieldName)\n if (cached !== undefined) {\n return cached.visible\n }\n\n if (!this.schema) return true\n\n const topLevelFields = this.schema.isWizard\n ? this.schema.steps!.flatMap((step) => step.fields)\n : this.schema.fields || []\n\n const allFields = this.extractAllFields(topLevelFields)\n\n // Buscar el campo por nombre completo primero\n let field = allFields.find((f) => {\n const fullPath = this.findFieldPath(f.name, topLevelFields)\n return fullPath === fieldName || f.name === fieldName\n })\n \n // Si no se encuentra, buscar por nombre relativo\n if (!field) {\n field = allFields.find((f) => f.name === fieldName)\n }\n \n if (!field || !field.dependencies) {\n return !field?.hidden\n }\n\n // Si el campo está dentro de un grupo, las dependencias son relativas al grupo\n // Encontrar el path completo del campo\n const fieldFullPath = this.findFieldPath(field.name, topLevelFields) || field.name\n const groupPath = fieldFullPath.includes('.') ? fieldFullPath.split('.').slice(0, -1).join('.') : ''\n \n // Crear un contexto de valores que resuelva dependencias relativas dentro del grupo\n // Si el campo está en un grupo, las dependencias relativas (como 'profile.type') \n // deben resolverse en el contexto del grupo (user.profile.type)\n let valuesContext: Record<string, any> = { ...this.state.values }\n if (groupPath && field.dependencies) {\n // Obtener valores del grupo\n const groupValues = getNestedValue(this.state.values, groupPath)\n if (groupValues && typeof groupValues === 'object') {\n // Crear un contexto que mapee nombres relativos a valores del grupo\n // Por ejemplo, si groupPath es 'user' y groupValues es { profile: { type: 'premium' } }\n // entonces 'profile.type' debería resolverse a 'premium'\n const createRelativeContext = (obj: any, prefix: string = ''): Record<string, any> => {\n const result: Record<string, any> = {}\n for (const [key, value] of Object.entries(obj)) {\n const relativeKey = prefix ? `${prefix}.${key}` : key\n if (value && typeof value === 'object' && !Array.isArray(value) && value !== null) {\n Object.assign(result, createRelativeContext(value, relativeKey))\n } else {\n result[relativeKey] = value\n }\n }\n return result\n }\n const relativeContext = createRelativeContext(groupValues)\n // Combinar contexto relativo con valores globales\n valuesContext = { ...this.state.values, ...relativeContext }\n }\n }\n\n const result = this.conditionEngine.evaluateDependencies(\n field.dependencies,\n valuesContext\n )\n\n // Cachear resultado\n this.dependencyCache.set(fieldName, result)\n\n return result.visible && !field.hidden\n }\n\n /**\n * Obtiene si un campo está habilitado basándose en dependencias\n */\n getFieldEnabled(fieldName: string): boolean {\n // Verificar cache primero\n const cached = this.dependencyCache.get(fieldName)\n if (cached !== undefined) {\n return cached.enabled\n }\n\n if (!this.schema) return true\n\n const topLevelFields = this.schema.isWizard\n ? this.schema.steps!.flatMap((step) => step.fields)\n : this.schema.fields || []\n\n const allFields = this.extractAllFields(topLevelFields)\n const field = allFields.find((f) => f.name === fieldName)\n if (!field) return true\n\n if (field.disabled) return false\n\n if (!field.dependencies) {\n return true\n }\n\n const result = this.conditionEngine.evaluateDependencies(\n field.dependencies,\n this.state.values\n )\n\n // Cachear resultado\n this.dependencyCache.set(fieldName, result)\n\n return result.enabled\n }\n\n /**\n * Obtiene si un campo es requerido basándose en dependencias\n */\n getFieldRequired(fieldName: string): boolean {\n // Verificar cache primero\n const cached = this.dependencyCache.get(fieldName)\n if (cached !== undefined) {\n return cached.required\n }\n\n if (!this.schema) return false\n\n const topLevelFields = this.schema.isWizard\n ? this.schema.steps!.flatMap((step) => step.fields)\n : this.schema.fields || []\n\n const allFields = this.extractAllFields(topLevelFields)\n\n const field = allFields.find((f) => f.name === fieldName)\n if (!field) return false\n\n // Verificar si tiene validación required estándar\n const hasRequired = field.validations?.some((v) => v.type === 'required') || false\n\n if (!field.dependencies) {\n return hasRequired\n }\n\n const result = this.conditionEngine.evaluateDependencies(\n field.dependencies,\n this.state.values\n )\n\n // Cachear resultado\n this.dependencyCache.set(fieldName, result)\n\n return result.required || hasRequired\n }\n\n /**\n * Obtiene los campos que dependen de un campo específico\n */\n getDependentFields(fieldName: string): string[] {\n return Array.from(this.fieldDependencies.get(fieldName) || [])\n }\n}\n","import type { Field, SlotContent } from '../../types'\n\n/**\n * Clase base para inputs\n */\nexport abstract class BaseInput {\n protected field: Field\n protected value: any\n protected error?: string\n protected onChange: (value: any) => void\n protected onBlur: () => void\n\n constructor(\n field: Field,\n value: any,\n error: string | undefined,\n onChange: (value: any) => void,\n onBlur: () => void\n ) {\n this.field = field\n this.value = value\n this.error = error\n this.onChange = onChange\n this.onBlur = onBlur\n }\n\n /**\n * Renderiza el input\n */\n abstract render(): HTMLElement\n\n /**\n * Crea wrapper con slots leading/trailing si el campo tiene leadingIcon o trailingIcon.\n * Si no hay slots, devuelve el input sin wrapper (retrocompatibilidad).\n */\n protected createInputWithSlots(rawInput: HTMLElement): HTMLElement {\n const leading = this.field.leadingIcon\n const trailing = this.field.trailingIcon\n if (!leading && !trailing) {\n return rawInput\n }\n\n const wrapper = document.createElement('div')\n wrapper.className = 'easy-form-input-wrapper'\n\n if (leading && this.isSlotContentValid(leading)) {\n const slotEl = this.renderSlotContent(leading)\n slotEl.className = 'easy-form-input-slot easy-form-input-slot-leading'\n wrapper.appendChild(slotEl)\n }\n\n const inputWrap = document.createElement('div')\n inputWrap.className = 'easy-form-input-core'\n inputWrap.appendChild(rawInput)\n wrapper.appendChild(inputWrap)\n\n if (trailing && this.isSlotContentValid(trailing)) {\n const slotEl = this.renderSlotContent(trailing)\n slotEl.className = 'easy-form-input-slot easy-form-input-slot-trailing'\n wrapper.appendChild(slotEl)\n }\n\n return wrapper\n }\n\n private isSlotContentValid(slot: SlotContent): boolean {\n if (!slot.type) return false\n if (slot.type === 'image') return Boolean(slot.src)\n if (slot.type === 'html') return Boolean(slot.html)\n return false\n }\n\n private renderSlotContent(slot: SlotContent): HTMLElement {\n const container = document.createElement('span')\n container.className = 'easy-form-input-slot-content'\n if (slot.type === 'image' && slot.src) {\n const img = document.createElement('img')\n img.src = slot.src\n img.alt = slot.alt ?? ''\n img.setAttribute('aria-hidden', 'true')\n container.appendChild(img)\n } else if (slot.type === 'html' && slot.html) {\n container.innerHTML = slot.html\n }\n return container\n }\n\n /**\n * Crea un contenedor con label y error\n */\n protected createFieldContainer(input: HTMLElement): HTMLElement {\n const container = document.createElement('div')\n \n // Si el input es un contenedor con clases específicas de componentes, preservarlas\n const inputClasses = Array.from(input.classList)\n const componentContainerClasses = inputClasses.filter(\n (cls) => cls.startsWith('easy-form-') && \n cls !== 'easy-form-field' &&\n (cls.includes('-container') || cls.includes('-wrapper'))\n )\n \n const labelPosition = (this.field as { labelPosition?: 'up' | 'down' | 'left' | 'right' | 'none' }).labelPosition ?? 'up'\n\n const inputToAppend = this.createInputWithSlots(input)\n\n if (componentContainerClasses.length > 0) {\n container.className = `easy-form-field easy-form-label-${labelPosition} ${componentContainerClasses.join(' ')}`\n } else {\n container.className = `easy-form-field easy-form-label-${labelPosition}`\n }\n\n // Aplicar aria-label si labelPosition es 'none' y hay label\n if (labelPosition === 'none' && this.field.label) {\n const el = inputToAppend.querySelector('input, textarea, select') || inputToAppend\n if (el instanceof HTMLElement) {\n el.setAttribute('aria-label', this.field.label)\n }\n }\n\n const createLabel = (): HTMLLabelElement | null => {\n if (!this.field.label || labelPosition === 'none') return null\n const label = document.createElement('label')\n label.className = 'easy-form-label'\n label.setAttribute('for', this.getFieldId())\n label.textContent = this.field.label\n if (this.field.validations?.some((v) => v.type === 'required')) {\n const required = document.createElement('span')\n required.className = 'easy-form-required'\n required.textContent = ' *'\n label.appendChild(required)\n }\n return label\n }\n\n const label = createLabel()\n\n // Orden según labelPosition\n if (labelPosition === 'up') {\n if (label) container.appendChild(label)\n container.appendChild(inputToAppend)\n } else if (labelPosition === 'down') {\n container.appendChild(inputToAppend)\n if (label) container.appendChild(label)\n } else if (labelPosition === 'left') {\n const inner = document.createElement('div')\n inner.className = 'easy-form-field-inner easy-form-field-inner-horizontal'\n if (label) inner.appendChild(label)\n inner.appendChild(inputToAppend)\n container.appendChild(inner)\n } else if (labelPosition === 'right') {\n const inner = document.createElement('div')\n inner.className = 'easy-form-field-inner easy-form-field-inner-horizontal'\n inner.appendChild(inputToAppend)\n if (label) inner.appendChild(label)\n container.appendChild(inner)\n } else {\n container.appendChild(inputToAppend)\n }\n\n // Description\n if (this.field.description) {\n const description = document.createElement('p')\n description.className = 'easy-form-description'\n description.textContent = this.field.description\n container.appendChild(description)\n }\n\n // Error\n if (this.error) {\n const errorEl = document.createElement('p')\n errorEl.className = 'easy-form-error'\n errorEl.textContent = this.error\n container.appendChild(errorEl)\n }\n\n return container\n }\n\n /**\n * Obtiene el ID del campo\n */\n protected getFieldId(): string {\n return `easy-form-${this.field.name}`\n }\n\n /**\n * Aplica props comunes a un elemento\n */\n protected applyCommonProps(element: HTMLElement): void {\n element.id = this.getFieldId()\n element.setAttribute('name', this.field.name)\n\n if (this.field.disabled) {\n element.setAttribute('disabled', 'true')\n element.classList.add('easy-form-input-disabled')\n }\n\n if (this.field.hidden) {\n element.style.display = 'none'\n element.classList.add('easy-form-field-hidden')\n }\n\n if (this.error) {\n element.classList.add('easy-form-input-error')\n }\n\n if (this.field.props) {\n for (const [key, value] of Object.entries(this.field.props)) {\n if (key.startsWith('data-') || key.startsWith('aria-')) {\n element.setAttribute(key, String(value))\n }\n }\n }\n }\n}\n","/**\n * Token de máscara\n */\nexport interface MaskToken {\n type: 'digit' | 'letter' | 'any' | 'literal'\n char: string\n editable: boolean\n}\n\n/**\n * Parsea un patrón de máscara en tokens\n */\nexport function parseMaskPattern(pattern: string): MaskToken[] {\n const tokens: MaskToken[] = []\n\n for (let i = 0; i < pattern.length; i++) {\n const char = pattern[i]\n\n switch (char) {\n case '9':\n tokens.push({ type: 'digit', char: '9', editable: true })\n break\n case 'a':\n case 'A':\n tokens.push({ type: 'letter', char: char, editable: true })\n break\n case '*':\n tokens.push({ type: 'any', char: '*', editable: true })\n break\n default:\n tokens.push({ type: 'literal', char: char, editable: false })\n break\n }\n }\n\n return tokens\n}\n\n/**\n * Formatea un valor según los tokens de máscara\n */\nexport function formatValue(value: string, tokens: MaskToken[]): string {\n let result = ''\n let valueIndex = 0\n\n for (const token of tokens) {\n if (!token.editable) {\n result += token.char\n continue\n }\n\n if (valueIndex >= value.length) {\n break\n }\n\n const char = value[valueIndex]\n\n // Validar según el tipo de token\n if (token.type === 'digit' && !/\\d/.test(char)) {\n continue // Saltar caracteres no numéricos\n } else if (token.type === 'letter' && !/[a-zA-Z]/.test(char)) {\n continue // Saltar caracteres no alfabéticos\n } else if (token.type === 'any') {\n // Aceptar cualquier carácter\n } else if (token.type !== 'any' && token.type !== 'digit' && token.type !== 'letter') {\n continue\n }\n\n result += char\n valueIndex++\n }\n\n return result\n}\n\n/**\n * Remueve el formato de un valor (obtiene solo los caracteres editables)\n */\nexport function unformatValue(value: string, tokens: MaskToken[]): string {\n if (!value) return ''\n\n let result = ''\n let tokenIndex = 0\n\n for (let i = 0; i < value.length && tokenIndex < tokens.length; i++) {\n const char = value[i]\n const token = tokens[tokenIndex]\n\n if (token.editable) {\n // Verificar si el carácter coincide con el tipo de token\n if (token.type === 'digit' && /\\d/.test(char)) {\n result += char\n tokenIndex++\n } else if (token.type === 'letter' && /[a-zA-Z]/.test(char)) {\n result += char\n tokenIndex++\n } else if (token.type === 'any') {\n result += char\n tokenIndex++\n } else {\n // Carácter no válido para este token, avanzar al siguiente token editable\n tokenIndex++\n i-- // Revisar el mismo carácter con el siguiente token\n }\n } else {\n // Token literal, verificar si coincide\n if (char === token.char) {\n tokenIndex++\n } else {\n // El carácter no coincide con el literal esperado, puede ser un carácter editable extra\n // Intentar extraerlo si es válido\n if (tokenIndex < tokens.length - 1) {\n const nextToken = tokens[tokenIndex + 1]\n if (nextToken && nextToken.editable) {\n if (nextToken.type === 'digit' && /\\d/.test(char)) {\n result += char\n tokenIndex += 2\n } else if (nextToken.type === 'letter' && /[a-zA-Z]/.test(char)) {\n result += char\n tokenIndex += 2\n } else if (nextToken.type === 'any') {\n result += char\n tokenIndex += 2\n } else {\n tokenIndex++\n }\n } else {\n tokenIndex++\n }\n } else {\n break\n }\n }\n }\n }\n\n return result\n}\n\n/**\n * Obtiene la siguiente posición editable\n */\nexport function getNextEditablePosition(\n position: number,\n tokens: MaskToken[],\n direction: 'forward' | 'backward' = 'forward'\n): number {\n if (direction === 'forward') {\n for (let i = position + 1; i < tokens.length; i++) {\n if (tokens[i].editable) {\n return i\n }\n }\n return tokens.length\n } else {\n for (let i = position - 1; i >= 0; i--) {\n if (tokens[i].editable) {\n return i\n }\n }\n return 0\n }\n}\n\n/**\n * Obtiene el placeholder completo para una máscara\n */\nexport function getMaskPlaceholder(tokens: MaskToken[], placeholder: string = '_'): string {\n return tokens\n .map((token) => (token.editable ? placeholder : token.char))\n .join('')\n}\n\n/**\n * Calcula la posición del cursor después de aplicar máscara\n */\nexport function calculateCursorPosition(\n oldValue: string,\n newValue: string,\n oldCursorPosition: number,\n tokens: MaskToken[]\n): number {\n // Contar caracteres editables antes de la posición anterior\n let editableBeforeOld = 0\n for (let i = 0; i < Math.min(oldCursorPosition, oldValue.length); i++) {\n const tokenIndex = i\n if (tokenIndex < tokens.length && tokens[tokenIndex].editable) {\n editableBeforeOld++\n }\n }\n\n // Encontrar la posición correspondiente en el nuevo valor\n let editableCount = 0\n for (let i = 0; i < newValue.length && i < tokens.length; i++) {\n if (tokens[i].editable) {\n editableCount++\n if (editableCount > editableBeforeOld) {\n return i + 1\n }\n }\n }\n\n // Si no encontramos, buscar la siguiente posición editable\n return getNextEditablePosition(\n Math.min(oldCursorPosition, newValue.length - 1),\n tokens,\n 'forward'\n )\n}\n","import type { MaskConfig, CustomMask } from '../types'\nimport { getPredefinedMask } from '../utils/masks'\nimport {\n parseMaskPattern,\n formatValue,\n unformatValue,\n getNextEditablePosition,\n getMaskPlaceholder,\n calculateCursorPosition,\n type MaskToken,\n} from '../utils/mask-helpers'\n\n/**\n * Motor de máscaras\n */\nexport class MaskEngine {\n private tokenCache: Map<string, MaskToken[]> = new Map()\n\n /**\n * Obtiene la configuración de máscara personalizada\n */\n private getCustomMask(mask: MaskConfig): CustomMask | null {\n if (mask.custom) {\n return mask.custom\n }\n if (mask.type) {\n return getPredefinedMask(mask.type)\n }\n return null\n }\n\n /**\n * Obtiene los tokens parseados de una máscara (con cache)\n */\n private getTokens(mask: MaskConfig): MaskToken[] | null {\n const customMask = this.getCustomMask(mask)\n if (!customMask) {\n return null\n }\n\n const cacheKey = customMask.pattern\n if (this.tokenCache.has(cacheKey)) {\n return this.tokenCache.get(cacheKey)!\n }\n\n const tokens = parseMaskPattern(customMask.pattern)\n this.tokenCache.set(cacheKey, tokens)\n return tokens\n }\n\n /**\n * Aplica máscara a un valor\n */\n applyMask(value: string, mask: MaskConfig): string {\n const tokens = this.getTokens(mask)\n if (!tokens) {\n return value\n }\n\n const customMask = this.getCustomMask(mask)!\n // Extraer solo caracteres editables del valor\n const editableTokens = tokens.filter(t => t.editable)\n const acceptedTypes = new Set(editableTokens.map(t => t.type))\n let unformatted = ''\n for (const char of value) {\n if (acceptedTypes.has('any')) {\n unformatted += char\n } else if (acceptedTypes.has('digit') && /\\d/.test(char)) {\n unformatted += char\n } else if (acceptedTypes.has('letter') && /[a-zA-Z]/.test(char)) {\n unformatted += char\n }\n }\n let formatted = formatValue(unformatted, tokens)\n\n // Aplicar transformación si existe\n if (customMask.transform) {\n formatted = customMask.transform(formatted)\n // Re-formatear después de la transformación\n formatted = formatValue(formatted, tokens)\n }\n\n return formatted\n }\n\n /**\n * Remueve máscara de un valor (obtiene valor raw)\n */\n removeMask(value: string, mask: MaskConfig): string {\n const tokens = this.getTokens(mask)\n if (!tokens) {\n return value\n }\n\n return unformatValue(value, tokens)\n }\n\n /**\n * Obtiene el placeholder para una máscara\n */\n getMaskPlaceholder(mask: MaskConfig): string {\n const tokens = this.getTokens(mask)\n if (!tokens) {\n return ''\n }\n\n const customMask = this.getCustomMask(mask)!\n return getMaskPlaceholder(tokens, customMask.placeholder || '_')\n }\n\n /**\n * Valida si un carácter puede ser insertado en una posición\n */\n canInsertChar(char: string, position: number, mask: MaskConfig): boolean {\n const tokens = this.getTokens(mask)\n if (!tokens || position >= tokens.length) {\n return false\n }\n\n const token = tokens[position]\n if (!token.editable) {\n return false\n }\n\n switch (token.type) {\n case 'digit':\n return /\\d/.test(char)\n case 'letter':\n return /[a-zA-Z]/.test(char)\n case 'any':\n return true\n default:\n return false\n }\n }\n\n /**\n * Procesa entrada del usuario aplicando máscara en tiempo real\n */\n processInput(\n input: string,\n previousValue: string,\n mask: MaskConfig,\n cursorPosition: number\n ): { value: string; cursorPosition: number } {\n const tokens = this.getTokens(mask)\n if (!tokens) {\n return { value: input, cursorPosition: input.length }\n }\n\n // Obtener el valor sin formato del input actual\n const unformattedInput = unformatValue(input, tokens)\n\n // Aplicar máscara al nuevo valor\n let formatted = formatValue(unformattedInput, tokens)\n\n // Aplicar transformación si existe\n const customMask = this.getCustomMask(mask)!\n if (customMask.transform) {\n formatted = customMask.transform(formatted)\n formatted = formatValue(formatted, tokens)\n }\n\n // Calcular nueva posición del cursor\n const newCursorPosition = calculateCursorPosition(\n previousValue,\n formatted,\n cursorPosition,\n tokens\n )\n\n return {\n value: formatted,\n cursorPosition: Math.min(newCursorPosition, formatted.length),\n }\n }\n\n /**\n * Procesa entrada con manejo de backspace/delete\n */\n processKeyInput(\n key: string,\n currentValue: string,\n cursorPosition: number,\n mask: MaskConfig,\n isBackspace: boolean = false\n ): { value: string; cursorPosition: number } {\n const tokens = this.getTokens(mask)\n if (!tokens) {\n return { value: currentValue, cursorPosition: cursorPosition }\n }\n\n if (isBackspace) {\n // Manejar backspace\n if (cursorPosition === 0) {\n return { value: currentValue, cursorPosition: 0 }\n }\n\n // Encontrar la posición editable anterior\n const prevEditable = getNextEditablePosition(cursorPosition - 1, tokens, 'backward')\n \n // Remover el carácter en esa posición\n const before = currentValue.substring(0, prevEditable)\n const after = currentValue.substring(cursorPosition)\n const newValue = before + after\n\n // Re-aplicar máscara\n const unformatted = this.removeMask(newValue, mask)\n const formatted = this.applyMask(unformatted, mask)\n\n // Calcular nueva posición\n const newPos = Math.max(0, prevEditable - 1)\n const nextEditable = getNextEditablePosition(newPos, tokens, 'forward')\n\n return {\n value: formatted,\n cursorPosition: nextEditable,\n }\n }\n\n // Manejar entrada normal\n if (key.length === 1 && this.canInsertChar(key, cursorPosition, mask)) {\n // Insertar carácter en la posición actual\n const before = currentValue.substring(0, cursorPosition)\n const after = currentValue.substring(cursorPosition)\n const newValue = before + key + after\n\n return this.processInput(newValue, currentValue, mask, cursorPosition)\n }\n\n return { value: currentValue, cursorPosition: cursorPosition }\n }\n}\n","import { BaseInput } from './base-input'\nimport type { Field } from '../../types'\nimport { MaskEngine } from '../../core/mask-engine'\n\nexport class TextInput extends BaseInput {\n private maskEngine: MaskEngine | null = null\n private previousValue: string = ''\n\n constructor(\n field: Field,\n value: any,\n error: string | undefined,\n onChange: (value: any) => void,\n onBlur: () => void\n ) {\n super(field, value, error, onChange, onBlur)\n \n if (field.mask) {\n this.maskEngine = new MaskEngine()\n }\n }\n\n render(): HTMLElement {\n const input = document.createElement('input')\n input.type = this.field.type === 'email' ? 'email' : this.field.type === 'password' ? 'password' : 'text'\n \n // Aplicar máscara si existe\n let displayValue = this.value ?? ''\n if (this.maskEngine && this.field.mask) {\n if (displayValue) {\n displayValue = this.maskEngine.applyMask(String(displayValue), this.field.mask)\n }\n this.previousValue = displayValue\n }\n \n input.value = displayValue\n\n this.applyCommonProps(input)\n\n // Aplicar placeholder del field si está definido (después de applyCommonProps)\n if (this.field.placeholder) {\n input.placeholder = this.field.placeholder\n } else if (this.maskEngine && this.field.mask) {\n // Aplicar placeholder de máscara si no hay placeholder del field\n const maskPlaceholder = this.maskEngine.getMaskPlaceholder(this.field.mask)\n if (maskPlaceholder) {\n input.placeholder = maskPlaceholder\n }\n }\n\n // Manejar eventos de entrada con máscara\n if (this.maskEngine && this.field.mask) {\n input.addEventListener('input', (e) => {\n const target = e.target as HTMLInputElement\n const cursorPosition = target.selectionStart || 0\n const inputValue = target.value\n\n const result = this.maskEngine!.processInput(\n inputValue,\n this.previousValue,\n this.field.mask!,\n cursorPosition\n )\n\n // Actualizar valor y cursor\n target.value = result.value\n this.previousValue = result.value\n\n // Restaurar posición del cursor\n setTimeout(() => {\n target.setSelectionRange(result.cursorPosition, result.cursorPosition)\n }, 0)\n\n // Emitir valor según configuración (con o sin formato)\n const valueToEmit = this.field.mask!.keepFormat\n ? result.value\n : this.maskEngine!.removeMask(result.value, this.field.mask!)\n\n this.onChange(valueToEmit)\n })\n\n input.addEventListener('keydown', (e) => {\n const target = e.target as HTMLInputElement\n const cursorPosition = target.selectionStart || 0\n\n if (e.key === 'Backspace' || e.key === 'Delete') {\n e.preventDefault()\n \n const isBackspace = e.key === 'Backspace'\n const result = this.maskEngine!.processKeyInput(\n '',\n target.value,\n cursorPosition,\n this.field.mask!,\n isBackspace\n )\n\n target.value = result.value\n this.previousValue = result.value\n\n setTimeout(() => {\n target.setSelectionRange(result.cursorPosition, result.cursorPosition)\n }, 0)\n\n const valueToEmit = this.field.mask!.keepFormat\n ? result.value\n : this.maskEngine!.removeMask(result.value, this.field.mask!)\n\n this.onChange(valueToEmit)\n }\n })\n\n input.addEventListener('paste', (e) => {\n e.preventDefault()\n const pastedText = (e.clipboardData || (window as any).clipboardData).getData('text')\n \n if (pastedText) {\n const target = e.target as HTMLInputElement\n const cursorPosition = target.selectionStart || 0\n \n // Insertar texto pegado\n const before = target.value.substring(0, cursorPosition)\n const after = target.value.substring(cursorPosition)\n const newValue = before + pastedText + after\n\n const result = this.maskEngine!.processInput(\n newValue,\n this.previousValue,\n this.field.mask!,\n cursorPosition\n )\n\n target.value = result.value\n this.previousValue = result.value\n\n setTimeout(() => {\n target.setSelectionRange(result.cursorPosition, result.cursorPosition)\n }, 0)\n\n const valueToEmit = this.field.mask!.keepFormat\n ? result.value\n : this.maskEngine!.removeMask(result.value, this.field.mask!)\n\n this.onChange(valueToEmit)\n }\n })\n } else {\n // Sin máscara, comportamiento normal\n input.addEventListener('input', (e) => {\n const target = e.target as HTMLInputElement\n this.onChange(target.value)\n })\n }\n\n input.addEventListener('blur', () => {\n this.onBlur()\n })\n\n return this.createFieldContainer(input)\n }\n}\n","import { BaseInput } from './base-input'\nimport type { NumberField } from '../../types'\nimport { MaskEngine } from '../../core/mask-engine'\n\nexport class NumberInput extends BaseInput {\n private maskEngine: MaskEngine | null = null\n private previousValue: string = ''\n\n constructor(\n field: NumberField,\n value: any,\n error: string | undefined,\n onChange: (value: any) => void,\n onBlur: () => void\n ) {\n super(field, value, error, onChange, onBlur)\n \n if (field.mask) {\n this.maskEngine = new MaskEngine()\n }\n }\n\n render(): HTMLElement {\n const input = document.createElement('input')\n \n // Si tiene máscara, usar tipo text para mejor control\n if (this.maskEngine && this.field.mask) {\n input.type = 'text'\n \n // Aplicar máscara al valor inicial\n let displayValue = this.value ?? ''\n if (displayValue !== null && displayValue !== '') {\n if (this.field.mask.type === 'currency') {\n displayValue = this.maskEngine.applyMask(String(displayValue), this.field.mask)\n } else if (this.field.mask.type === 'percentage') {\n displayValue = this.maskEngine.applyMask(String(displayValue), this.field.mask)\n }\n }\n this.previousValue = displayValue\n input.value = displayValue\n } else {\n input.type = 'number'\n input.value = this.value ?? ''\n }\n\n const numberField = this.field as NumberField\n if (!this.maskEngine && input.type === 'number') {\n if (numberField.min !== undefined) {\n input.min = String(numberField.min)\n }\n if (numberField.max !== undefined) {\n input.max = String(numberField.max)\n }\n if (numberField.step !== undefined) {\n input.step = String(numberField.step)\n }\n }\n\n this.applyCommonProps(input)\n\n // Aplicar placeholder del field si está definido\n if (this.field.placeholder) {\n input.placeholder = this.field.placeholder\n } else if (this.maskEngine && this.field.mask) {\n // Aplicar placeholder de máscara si no hay placeholder del field\n const maskPlaceholder = this.maskEngine.getMaskPlaceholder(this.field.mask)\n if (maskPlaceholder) {\n input.placeholder = maskPlaceholder\n }\n }\n\n // Manejar eventos con máscara\n if (this.maskEngine && this.field.mask) {\n input.addEventListener('input', (e) => {\n const target = e.target as HTMLInputElement\n const cursorPosition = target.selectionStart || 0\n const inputValue = target.value\n\n const result = this.maskEngine!.processInput(\n inputValue,\n this.previousValue,\n this.field.mask!,\n cursorPosition\n )\n\n target.value = result.value\n this.previousValue = result.value\n\n setTimeout(() => {\n target.setSelectionRange(result.cursorPosition, result.cursorPosition)\n }, 0)\n\n // Convertir a número según el tipo de máscara\n let numValue: number | null = null\n if (this.field.mask!.type === 'currency') {\n const unformatted = this.maskEngine!.removeMask(result.value, this.field.mask!)\n numValue = unformatted ? parseFloat(unformatted.replace(/[^\\d.]/g, '')) : null\n } else if (this.field.mask!.type === 'percentage') {\n const unformatted = this.maskEngine!.removeMask(result.value, this.field.mask!)\n numValue = unformatted ? parseFloat(unformatted) : null\n }\n\n this.onChange(numValue)\n })\n\n input.addEventListener('keydown', (e) => {\n const target = e.target as HTMLInputElement\n const cursorPosition = target.selectionStart || 0\n\n if (e.key === 'Backspace' || e.key === 'Delete') {\n e.preventDefault()\n \n const isBackspace = e.key === 'Backspace'\n const result = this.maskEngine!.processKeyInput(\n '',\n target.value,\n cursorPosition,\n this.field.mask!,\n isBackspace\n )\n\n target.value = result.value\n this.previousValue = result.value\n\n setTimeout(() => {\n target.setSelectionRange(result.cursorPosition, result.cursorPosition)\n }, 0)\n\n let numValue: number | null = null\n if (this.field.mask!.type === 'currency') {\n const unformatted = this.maskEngine!.removeMask(result.value, this.field.mask!)\n numValue = unformatted ? parseFloat(unformatted.replace(/[^\\d.]/g, '')) : null\n } else if (this.field.mask!.type === 'percentage') {\n const unformatted = this.maskEngine!.removeMask(result.value, this.field.mask!)\n numValue = unformatted ? parseFloat(unformatted) : null\n }\n\n this.onChange(numValue)\n }\n })\n\n input.addEventListener('paste', (e) => {\n e.preventDefault()\n const pastedText = (e.clipboardData || (window as any).clipboardData).getData('text')\n \n if (pastedText) {\n const target = e.target as HTMLInputElement\n const cursorPosition = target.selectionStart || 0\n \n const before = target.value.substring(0, cursorPosition)\n const after = target.value.substring(cursorPosition)\n const newValue = before + pastedText + after\n\n const result = this.maskEngine!.processInput(\n newValue,\n this.previousValue,\n this.field.mask!,\n cursorPosition\n )\n\n target.value = result.value\n this.previousValue = result.value\n\n setTimeout(() => {\n target.setSelectionRange(result.cursorPosition, result.cursorPosition)\n }, 0)\n\n let numValue: number | null = null\n if (this.field.mask!.type === 'currency') {\n const unformatted = this.maskEngine!.removeMask(result.value, this.field.mask!)\n numValue = unformatted ? parseFloat(unformatted.replace(/[^\\d.]/g, '')) : null\n } else if (this.field.mask!.type === 'percentage') {\n const unformatted = this.maskEngine!.removeMask(result.value, this.field.mask!)\n numValue = unformatted ? parseFloat(unformatted) : null\n }\n\n this.onChange(numValue)\n }\n })\n } else {\n // Sin máscara, comportamiento normal\n input.addEventListener('input', (e) => {\n const target = e.target as HTMLInputElement\n const numValue = target.value === '' ? null : Number(target.value)\n this.onChange(numValue)\n })\n }\n\n input.addEventListener('blur', () => {\n this.onBlur()\n })\n\n return this.createFieldContainer(input)\n }\n}\n","import { BaseInput } from './base-input'\nimport type { TextareaField } from '../../types'\n\nexport class TextareaInput extends BaseInput {\n render(): HTMLElement {\n const textarea = document.createElement('textarea')\n textarea.value = this.value ?? ''\n textarea.placeholder = this.field.placeholder || ''\n\n const textareaField = this.field as TextareaField\n if (textareaField.rows) {\n textarea.rows = textareaField.rows\n }\n if (textareaField.cols) {\n textarea.cols = textareaField.cols\n }\n\n this.applyCommonProps(textarea)\n\n textarea.addEventListener('input', (e) => {\n const target = e.target as HTMLTextAreaElement\n this.onChange(target.value)\n })\n\n textarea.addEventListener('blur', () => {\n this.onBlur()\n })\n\n return this.createFieldContainer(textarea)\n }\n}\n","import { BaseInput } from './base-input'\nimport type { SelectField } from '../../types'\n\nexport class SelectInput extends BaseInput {\n render(): HTMLElement {\n const select = document.createElement('select')\n const selectField = this.field as SelectField\n\n if (selectField.multiple) {\n select.multiple = true\n }\n\n // Opción placeholder cuando no hay selección (solo para select simple)\n if (!selectField.multiple) {\n const placeholderOption = document.createElement('option')\n placeholderOption.value = ''\n placeholderOption.textContent = selectField.placeholder || 'Selecciona una opción'\n placeholderOption.setAttribute('data-placeholder', '')\n placeholderOption.disabled = true\n select.appendChild(placeholderOption)\n }\n\n // Crear opciones\n for (const option of selectField.options) {\n const optionEl = document.createElement('option')\n if (typeof option === 'string') {\n optionEl.value = option\n optionEl.textContent = option\n } else {\n optionEl.value = String(option.value)\n optionEl.textContent = option.label\n }\n select.appendChild(optionEl)\n }\n\n // Establecer valor\n if (selectField.multiple && Array.isArray(this.value)) {\n for (const option of select.options) {\n option.selected = this.value.includes(option.value)\n }\n } else {\n select.value = this.value ?? ''\n }\n\n this.applyCommonProps(select)\n\n const updatePlaceholderClass = () => {\n const isEmpty = !select.value\n if (isEmpty) {\n select.classList.add('easy-form-select-placeholder')\n } else {\n select.classList.remove('easy-form-select-placeholder')\n }\n }\n updatePlaceholderClass()\n\n select.addEventListener('change', (e) => {\n const target = e.target as HTMLSelectElement\n updatePlaceholderClass()\n if (selectField.multiple) {\n const selectedValues = Array.from(target.selectedOptions).map(\n (opt) => opt.value\n )\n this.onChange(selectedValues)\n } else {\n this.onChange(target.value || null)\n }\n })\n\n select.addEventListener('blur', () => {\n this.onBlur()\n })\n\n return this.createFieldContainer(select)\n }\n}\n","import { BaseInput } from './base-input'\n\nexport class CheckboxInput extends BaseInput {\n render(): HTMLElement {\n const checkbox = document.createElement('input')\n checkbox.type = 'checkbox'\n checkbox.checked = Boolean(this.value)\n\n this.applyCommonProps(checkbox)\n\n checkbox.addEventListener('change', (e) => {\n const target = e.target as HTMLInputElement\n this.onChange(target.checked)\n })\n\n checkbox.addEventListener('blur', () => {\n this.onBlur()\n })\n\n const container = document.createElement('div')\n container.className = 'easy-form-field'\n\n // Label (checkbox primero, luego label)\n const label = document.createElement('label')\n label.className = 'easy-form-label-checkbox'\n label.setAttribute('for', this.getFieldId())\n label.appendChild(checkbox)\n if (this.field.label) {\n const labelText = document.createTextNode(this.field.label)\n label.appendChild(labelText)\n }\n container.appendChild(label)\n\n // Description\n if (this.field.description) {\n const description = document.createElement('p')\n description.className = 'easy-form-description'\n description.textContent = this.field.description\n container.appendChild(description)\n }\n\n // Error\n if (this.error) {\n const errorEl = document.createElement('p')\n errorEl.className = 'easy-form-error'\n errorEl.textContent = this.error\n container.appendChild(errorEl)\n }\n\n return container\n }\n}\n","import { BaseInput } from './base-input'\nimport type { RadioField } from '../../types'\n\nexport class RadioInput extends BaseInput {\n render(): HTMLElement {\n const container = document.createElement('div')\n container.className = 'easy-form-field'\n\n // Label\n if (this.field.label) {\n const label = document.createElement('label')\n label.className = 'easy-form-label'\n label.textContent = this.field.label\n if (this.field.validations?.some((v) => v.type === 'required')) {\n const required = document.createElement('span')\n required.className = 'easy-form-required'\n required.textContent = ' *'\n label.appendChild(required)\n }\n container.appendChild(label)\n }\n\n // Radio buttons\n const radioGroup = document.createElement('div')\n radioGroup.className = 'easy-form-radio-group'\n\n const radioField = this.field as RadioField\n for (const option of radioField.options) {\n const optionValue = typeof option === 'string' ? option : option.value\n const optionLabel = typeof option === 'string' ? option : option.label\n\n const radioContainer = document.createElement('div')\n radioContainer.className = 'easy-form-radio-option'\n\n const radio = document.createElement('input')\n radio.type = 'radio'\n radio.name = this.field.name\n radio.id = `${this.getFieldId()}-${optionValue}`\n radio.value = String(optionValue)\n radio.checked = String(this.value) === String(optionValue)\n\n if (this.field.disabled) {\n radio.disabled = true\n }\n\n const label = document.createElement('label')\n label.setAttribute('for', radio.id)\n label.textContent = optionLabel\n label.className = 'easy-form-radio-label'\n\n radio.addEventListener('change', () => {\n this.onChange(optionValue)\n })\n\n radio.addEventListener('blur', () => {\n this.onBlur()\n })\n\n radioContainer.appendChild(radio)\n radioContainer.appendChild(label)\n radioGroup.appendChild(radioContainer)\n }\n\n container.appendChild(radioGroup)\n\n // Description\n if (this.field.description) {\n const description = document.createElement('p')\n description.className = 'easy-form-description'\n description.textContent = this.field.description\n container.appendChild(description)\n }\n\n // Error\n if (this.error) {\n const errorEl = document.createElement('p')\n errorEl.className = 'easy-form-error'\n errorEl.textContent = this.error\n container.appendChild(errorEl)\n }\n\n return container\n }\n}\n","import { BaseInput } from './base-input'\n\nexport class SwitchInput extends BaseInput {\n render(): HTMLElement {\n const switchEl = document.createElement('input')\n switchEl.type = 'checkbox'\n switchEl.className = 'easy-form-switch'\n switchEl.checked = Boolean(this.value)\n\n this.applyCommonProps(switchEl)\n\n switchEl.addEventListener('change', (e) => {\n const target = e.target as HTMLInputElement\n this.onChange(target.checked)\n })\n\n switchEl.addEventListener('blur', () => {\n this.onBlur()\n })\n\n const container = document.createElement('div')\n container.className = 'easy-form-field'\n\n // Label con switch\n const label = document.createElement('label')\n label.className = 'easy-form-label-switch'\n label.setAttribute('for', this.getFieldId())\n if (this.field.label) {\n const labelText = document.createTextNode(this.field.label)\n label.appendChild(labelText)\n }\n label.appendChild(switchEl)\n container.appendChild(label)\n\n // Description\n if (this.field.description) {\n const description = document.createElement('p')\n description.className = 'easy-form-description'\n description.textContent = this.field.description\n container.appendChild(description)\n }\n\n // Error\n if (this.error) {\n const errorEl = document.createElement('p')\n errorEl.className = 'easy-form-error'\n errorEl.textContent = this.error\n container.appendChild(errorEl)\n }\n\n return container\n }\n}\n","import { BaseInput } from './base-input'\nimport type { DateField } from '../../types'\n\nexport class DateInput extends BaseInput {\n render(): HTMLElement {\n const input = document.createElement('input')\n input.type = 'date'\n \n const dateField = this.field as DateField\n if (dateField.min) {\n input.min = dateField.min\n }\n if (dateField.max) {\n input.max = dateField.max\n }\n\n if (this.value) {\n const date = this.value instanceof Date \n ? this.value.toISOString().split('T')[0]\n : String(this.value)\n input.value = date\n }\n\n this.applyCommonProps(input)\n\n input.addEventListener('change', (e) => {\n const target = e.target as HTMLInputElement\n this.onChange(target.value || null)\n })\n\n input.addEventListener('blur', () => {\n this.onBlur()\n })\n\n return this.createFieldContainer(input)\n }\n}\n","import { BaseInput } from './base-input'\nimport type { FileField } from '../../types'\n\nexport class FileInput extends BaseInput {\n render(): HTMLElement {\n const input = document.createElement('input')\n input.type = 'file'\n \n const fileField = this.field as FileField\n if (fileField.accept) {\n input.accept = fileField.accept\n }\n if (fileField.multiple) {\n input.multiple = true\n }\n\n this.applyCommonProps(input)\n\n input.addEventListener('change', (e) => {\n const target = e.target as HTMLInputElement\n if (target.files) {\n if (fileField.multiple) {\n this.onChange(Array.from(target.files))\n } else {\n this.onChange(target.files[0] || null)\n }\n }\n })\n\n input.addEventListener('blur', () => {\n this.onBlur()\n })\n\n return this.createFieldContainer(input)\n }\n}\n","import { BaseInput } from './base-input'\nimport type { QuantityField } from '../../types'\n\nexport class QuantityInput extends BaseInput {\n render(): HTMLElement {\n const container = document.createElement('div')\n container.className = 'easy-form-quantity-container'\n\n const quantityField = this.field as QuantityField\n const min = quantityField.min ?? 0\n const max = quantityField.max ?? undefined\n const step = quantityField.step ?? 1\n const currentValue = this.value ?? min\n\n // Contenedor del input con botones\n const inputWrapper = document.createElement('div')\n inputWrapper.className = 'easy-form-quantity-wrapper'\n\n // Botón de decremento\n const decrementBtn = document.createElement('button')\n decrementBtn.type = 'button'\n decrementBtn.className = 'easy-form-quantity-btn easy-form-quantity-decrement'\n decrementBtn.textContent = '−'\n decrementBtn.setAttribute('aria-label', 'Decrementar')\n \n if (currentValue <= min) {\n decrementBtn.disabled = true\n decrementBtn.classList.add('disabled')\n }\n\n // Input numérico\n const input = document.createElement('input')\n input.type = 'number'\n input.value = String(currentValue)\n input.min = String(min)\n if (max !== undefined) {\n input.max = String(max)\n }\n input.step = String(step)\n input.className = 'easy-form-quantity-input'\n this.applyCommonProps(input)\n\n // Botón de incremento\n const incrementBtn = document.createElement('button')\n incrementBtn.type = 'button'\n incrementBtn.className = 'easy-form-quantity-btn easy-form-quantity-increment'\n incrementBtn.textContent = '+'\n incrementBtn.setAttribute('aria-label', 'Incrementar')\n \n if (max !== undefined && currentValue >= max) {\n incrementBtn.disabled = true\n incrementBtn.classList.add('disabled')\n }\n\n // Event listeners para botones\n decrementBtn.addEventListener('click', () => {\n const newValue = Math.max(min, Number(input.value) - step)\n input.value = String(newValue)\n this.onChange(newValue)\n updateButtons()\n })\n\n incrementBtn.addEventListener('click', () => {\n const newValue = max !== undefined \n ? Math.min(max, Number(input.value) + step)\n : Number(input.value) + step\n input.value = String(newValue)\n this.onChange(newValue)\n updateButtons()\n })\n\n // Event listener para input directo\n input.addEventListener('input', (e) => {\n const target = e.target as HTMLInputElement\n let numValue = Number(target.value)\n \n if (isNaN(numValue)) {\n numValue = min\n }\n \n if (numValue < min) {\n numValue = min\n }\n \n if (max !== undefined && numValue > max) {\n numValue = max\n }\n \n target.value = String(numValue)\n this.onChange(numValue)\n updateButtons()\n })\n\n input.addEventListener('blur', () => {\n this.onBlur()\n })\n\n // Función para actualizar estado de botones\n const updateButtons = () => {\n const value = Number(input.value)\n decrementBtn.disabled = value <= min\n decrementBtn.classList.toggle('disabled', value <= min)\n \n if (max !== undefined) {\n incrementBtn.disabled = value >= max\n incrementBtn.classList.toggle('disabled', value >= max)\n } else {\n incrementBtn.disabled = false\n incrementBtn.classList.remove('disabled')\n }\n }\n\n // Agregar elementos al wrapper\n inputWrapper.appendChild(decrementBtn)\n inputWrapper.appendChild(input)\n inputWrapper.appendChild(incrementBtn)\n\n container.appendChild(inputWrapper)\n\n return this.createFieldContainer(container)\n }\n}\n","import { BaseInput } from './base-input'\nimport type { AccordionSelectField } from '../../types'\n\nexport class AccordionSelectInput extends BaseInput {\n private openAccordion: string | null = null\n\n render(): HTMLElement {\n const container = document.createElement('div')\n container.className = 'easy-form-accordion-select-container'\n\n const accordionField = this.field as AccordionSelectField\n const selectedValue = this.value ?? null\n\n // Crear acordeón\n accordionField.options.forEach((option, index) => {\n const optionValue = typeof option === 'string' ? option : option.value\n const optionLabel = typeof option === 'string' ? option : option.label\n const optionDescription = typeof option === 'object' && 'description' in option && option.description\n ? option.description\n : undefined\n\n const accordionItem = document.createElement('div')\n accordionItem.className = 'easy-form-accordion-item'\n accordionItem.setAttribute('data-value', String(optionValue))\n\n if (selectedValue === optionValue || (Array.isArray(selectedValue) && selectedValue.includes(optionValue))) {\n accordionItem.classList.add('selected')\n if (!accordionField.multiple) {\n this.openAccordion = String(optionValue)\n }\n }\n\n // Header del acordeón\n const header = document.createElement('div')\n header.className = 'easy-form-accordion-header'\n header.setAttribute('role', 'button')\n header.setAttribute('tabindex', '0')\n header.setAttribute('aria-expanded', 'false')\n\n const headerContent = document.createElement('div')\n headerContent.className = 'easy-form-accordion-header-content'\n\n // Radio/Checkbox visual\n const indicator = document.createElement('div')\n indicator.className = 'easy-form-accordion-indicator'\n if (accordionField.multiple) {\n indicator.classList.add('checkbox')\n if (Array.isArray(selectedValue) && selectedValue.includes(optionValue)) {\n indicator.classList.add('checked')\n }\n } else {\n indicator.classList.add('radio')\n if (selectedValue === optionValue) {\n indicator.classList.add('checked')\n }\n }\n\n const label = document.createElement('span')\n label.className = 'easy-form-accordion-label'\n label.textContent = optionLabel\n\n const arrow = document.createElement('span')\n arrow.className = 'easy-form-accordion-arrow'\n arrow.textContent = '▼'\n\n headerContent.appendChild(indicator)\n headerContent.appendChild(label)\n header.appendChild(headerContent)\n header.appendChild(arrow)\n\n // Contenido del acordeón\n const content = document.createElement('div')\n content.className = 'easy-form-accordion-content'\n \n if (optionDescription) {\n const description = document.createElement('p')\n description.className = 'easy-form-accordion-description'\n description.textContent = optionDescription\n content.appendChild(description)\n }\n\n // Si hay campos anidados o contenido adicional\n if (typeof option === 'object' && 'content' in option && option.content) {\n const customContent = document.createElement('div')\n customContent.className = 'easy-form-accordion-custom-content'\n if (typeof option.content === 'string') {\n customContent.innerHTML = option.content\n } else if (option.content instanceof HTMLElement) {\n customContent.appendChild(option.content)\n }\n content.appendChild(customContent)\n }\n\n accordionItem.appendChild(header)\n accordionItem.appendChild(content)\n\n // Toggle acordeón\n const toggleAccordion = () => {\n const isOpen = accordionItem.classList.contains('open')\n \n if (!accordionField.multiple) {\n // Cerrar otros acordeones\n container.querySelectorAll('.easy-form-accordion-item').forEach((item) => {\n if (item !== accordionItem) {\n item.classList.remove('open')\n const otherHeader = item.querySelector('.easy-form-accordion-header')\n const otherContent = item.querySelector('.easy-form-accordion-content')\n const otherArrow = item.querySelector('.easy-form-accordion-arrow')\n if (otherHeader) otherHeader.setAttribute('aria-expanded', 'false')\n if (otherContent) otherContent.style.maxHeight = null\n if (otherArrow) otherArrow.style.transform = 'rotate(0deg)'\n }\n })\n }\n\n if (isOpen) {\n accordionItem.classList.remove('open')\n header.setAttribute('aria-expanded', 'false')\n content.style.maxHeight = null\n arrow.style.transform = 'rotate(0deg)'\n this.openAccordion = null\n } else {\n accordionItem.classList.add('open')\n header.setAttribute('aria-expanded', 'true')\n content.style.maxHeight = content.scrollHeight + 'px'\n arrow.style.transform = 'rotate(180deg)'\n this.openAccordion = String(optionValue)\n }\n }\n\n // Seleccionar opción\n const selectOption = () => {\n if (accordionField.multiple) {\n const currentValues = Array.isArray(selectedValue) ? [...selectedValue] : []\n const index = currentValues.indexOf(optionValue)\n \n if (index > -1) {\n currentValues.splice(index, 1)\n accordionItem.classList.remove('selected')\n indicator.classList.remove('checked')\n } else {\n currentValues.push(optionValue)\n accordionItem.classList.add('selected')\n indicator.classList.add('checked')\n }\n \n this.onChange(currentValues.length > 0 ? currentValues : null)\n } else {\n // Deseleccionar otros\n container.querySelectorAll('.easy-form-accordion-item').forEach((item) => {\n item.classList.remove('selected')\n const itemIndicator = item.querySelector('.easy-form-accordion-indicator')\n if (itemIndicator) itemIndicator.classList.remove('checked')\n })\n \n accordionItem.classList.add('selected')\n indicator.classList.add('checked')\n this.onChange(optionValue)\n }\n }\n\n header.addEventListener('click', (e) => {\n e.stopPropagation()\n selectOption()\n toggleAccordion()\n })\n\n header.addEventListener('keydown', (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n selectOption()\n toggleAccordion()\n }\n })\n\n // Abrir acordeón si está seleccionado inicialmente\n if (selectedValue === optionValue || (Array.isArray(selectedValue) && selectedValue.includes(optionValue))) {\n if (!accordionField.multiple || accordionField.autoExpand) {\n setTimeout(() => {\n accordionItem.classList.add('open')\n header.setAttribute('aria-expanded', 'true')\n content.style.maxHeight = content.scrollHeight + 'px'\n arrow.style.transform = 'rotate(180deg)'\n }, 0)\n }\n }\n\n container.appendChild(accordionItem)\n })\n\n return this.createFieldContainer(container)\n }\n}\n","import { BaseInput } from './base-input'\nimport type { ImageGridSelectField } from '../../types'\n\nexport class ImageGridSelectInput extends BaseInput {\n render(): HTMLElement {\n const container = document.createElement('div')\n container.className = 'easy-form-image-grid-container'\n\n const imageGridField = this.field as ImageGridSelectField\n const selectedValue = this.value ?? null\n const columns = imageGridField.columns ?? 3\n const imageSize = imageGridField.imageSize ?? 'medium'\n\n // Establecer grid columns\n container.style.gridTemplateColumns = `repeat(${columns}, 1fr)`\n container.style.gap = imageGridField.gap ?? '1rem'\n\n // Crear items de imagen\n imageGridField.options.forEach((option) => {\n const optionValue = typeof option === 'string' ? option : option.value\n const optionLabel = typeof option === 'string' ? option : option.label\n const optionImage = typeof option === 'object' && 'image' in option && option.image\n ? option.image\n : undefined\n const optionDescription = typeof option === 'object' && 'description' in option && option.description\n ? option.description\n : undefined\n\n const gridItem = document.createElement('div')\n gridItem.className = `easy-form-image-grid-item easy-form-image-grid-${imageSize}`\n gridItem.setAttribute('data-value', String(optionValue))\n gridItem.setAttribute('role', 'button')\n gridItem.setAttribute('tabindex', '0')\n gridItem.setAttribute('aria-label', optionLabel)\n\n if (selectedValue === optionValue || (Array.isArray(selectedValue) && selectedValue.includes(optionValue))) {\n gridItem.classList.add('selected')\n }\n\n // Contenedor de imagen\n const imageContainer = document.createElement('div')\n imageContainer.className = 'easy-form-image-grid-image-container'\n\n if (optionImage) {\n const img = document.createElement('img')\n img.src = optionImage\n img.alt = optionLabel\n img.className = 'easy-form-image-grid-image'\n imageContainer.appendChild(img)\n } else {\n // Placeholder si no hay imagen\n const placeholder = document.createElement('div')\n placeholder.className = 'easy-form-image-grid-placeholder'\n placeholder.textContent = optionLabel.charAt(0).toUpperCase()\n imageContainer.appendChild(placeholder)\n }\n\n // Indicador de selección\n const indicator = document.createElement('div')\n indicator.className = 'easy-form-image-grid-indicator'\n if (imageGridField.multiple) {\n indicator.classList.add('checkbox')\n if (Array.isArray(selectedValue) && selectedValue.includes(optionValue)) {\n indicator.classList.add('checked')\n indicator.innerHTML = '✓'\n }\n } else {\n indicator.classList.add('radio')\n if (selectedValue === optionValue) {\n indicator.classList.add('checked')\n indicator.innerHTML = '●'\n }\n }\n imageContainer.appendChild(indicator)\n\n // Label\n const label = document.createElement('div')\n label.className = 'easy-form-image-grid-label'\n label.textContent = optionLabel\n\n // Description (opcional)\n if (optionDescription) {\n const description = document.createElement('div')\n description.className = 'easy-form-image-grid-description'\n description.textContent = optionDescription\n gridItem.appendChild(description)\n }\n\n gridItem.appendChild(imageContainer)\n gridItem.appendChild(label)\n\n // Seleccionar opción\n const selectOption = () => {\n if (imageGridField.multiple) {\n const currentValues = Array.isArray(selectedValue) ? [...selectedValue] : []\n const index = currentValues.indexOf(optionValue)\n \n if (index > -1) {\n currentValues.splice(index, 1)\n gridItem.classList.remove('selected')\n indicator.classList.remove('checked')\n indicator.innerHTML = ''\n } else {\n currentValues.push(optionValue)\n gridItem.classList.add('selected')\n indicator.classList.add('checked')\n indicator.innerHTML = '✓'\n }\n \n this.onChange(currentValues.length > 0 ? currentValues : null)\n } else {\n // Deseleccionar otros\n container.querySelectorAll('.easy-form-image-grid-item').forEach((item) => {\n item.classList.remove('selected')\n const itemIndicator = item.querySelector('.easy-form-image-grid-indicator')\n if (itemIndicator) {\n itemIndicator.classList.remove('checked')\n itemIndicator.innerHTML = ''\n }\n })\n \n gridItem.classList.add('selected')\n indicator.classList.add('checked')\n indicator.innerHTML = '●'\n this.onChange(optionValue)\n }\n }\n\n gridItem.addEventListener('click', selectOption)\n gridItem.addEventListener('keydown', (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n selectOption()\n }\n })\n\n gridItem.addEventListener('blur', () => {\n this.onBlur()\n })\n\n container.appendChild(gridItem)\n })\n\n return this.createFieldContainer(container)\n }\n}\n","import { BaseInput } from './base-input'\nimport type { OTPField } from '../../types'\n\nexport class OTPInput extends BaseInput {\n private inputs: HTMLInputElement[] = []\n\n render(): HTMLElement {\n const container = document.createElement('div')\n container.className = 'easy-form-otp-container'\n\n const otpField = this.field as OTPField\n const length = otpField.length ?? 6\n const value = this.value ?? ''\n const valueString = String(value).padStart(length, '').slice(0, length)\n\n // Crear inputs individuales\n for (let i = 0; i < length; i++) {\n const input = document.createElement('input')\n input.type = 'text'\n input.inputMode = 'numeric'\n input.maxLength = 1\n input.className = 'easy-form-otp-input'\n input.setAttribute('aria-label', `Código dígito ${i + 1}`)\n \n if (valueString[i]) {\n input.value = valueString[i]\n }\n\n this.applyCommonProps(input)\n input.id = `${this.getFieldId()}-${i}`\n\n // Capturar el índice actual para usar en los callbacks\n const currentIndex = i\n\n // Event listeners\n input.addEventListener('input', (e) => {\n const target = e.target as HTMLInputElement\n const inputValue = target.value.replace(/[^0-9]/g, '')\n target.value = inputValue\n\n // Mover al siguiente input si hay valor\n if (inputValue && currentIndex < length - 1) {\n this.inputs[currentIndex + 1].focus()\n }\n\n this.updateOTPValue()\n })\n\n input.addEventListener('keydown', (e) => {\n const target = e.target as HTMLInputElement\n\n // Backspace: borrar y mover al anterior\n if (e.key === 'Backspace' && !target.value && currentIndex > 0) {\n this.inputs[currentIndex - 1].focus()\n this.inputs[currentIndex - 1].value = ''\n this.updateOTPValue()\n }\n\n // Arrow keys: navegar entre inputs\n if (e.key === 'ArrowLeft' && currentIndex > 0) {\n e.preventDefault()\n this.inputs[currentIndex - 1].focus()\n }\n if (e.key === 'ArrowRight' && currentIndex < length - 1) {\n e.preventDefault()\n this.inputs[currentIndex + 1].focus()\n }\n })\n\n input.addEventListener('paste', (e) => {\n e.preventDefault()\n const pastedData = (e.clipboardData || (window as any).clipboardData).getData('text')\n const digits = pastedData.replace(/[^0-9]/g, '').slice(0, length)\n\n // Llenar inputs con los dígitos pegados\n for (let j = 0; j < digits.length && (currentIndex + j) < length; j++) {\n this.inputs[currentIndex + j].value = digits[j]\n }\n\n // Mover foco al último input llenado o al siguiente vacío\n const nextEmptyIndex = Math.min(currentIndex + digits.length, length - 1)\n this.inputs[nextEmptyIndex].focus()\n this.updateOTPValue()\n })\n\n input.addEventListener('focus', (e) => {\n const target = e.target as HTMLInputElement\n target.select()\n })\n\n input.addEventListener('blur', () => {\n this.onBlur()\n })\n\n this.inputs.push(input)\n container.appendChild(input)\n }\n\n return this.createFieldContainer(container)\n }\n\n private updateOTPValue(): void {\n const otpValue = this.inputs.map(input => input.value).join('')\n const otpField = this.field as OTPField\n \n // Si está vacío, enviar null, de lo contrario el string completo\n const finalValue = otpValue.length === this.inputs.length ? otpValue : null\n \n // Si el campo tiene formato numérico, convertir a número\n if (otpField.numeric && finalValue) {\n this.onChange(Number(finalValue))\n } else {\n this.onChange(finalValue)\n }\n }\n}\n","import { BaseInput } from './base-input'\nimport type { PasswordField } from '../../types'\n\nconst DEFAULT_SEPARATED_LENGTH = 6\n\nfunction eyeSvg(visible: boolean): string {\n if (visible) {\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24\"/><line x1=\"1\" y1=\"1\" x2=\"23\" y2=\"23\"/></svg>`\n }\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/></svg>`\n}\n\nexport class PasswordInput extends BaseInput {\n private inputs: HTMLInputElement[] = []\n private visible = false\n\n get passwordField(): PasswordField {\n return this.field as PasswordField\n }\n\n render(): HTMLElement {\n const pf = this.passwordField\n const useSeparated = !!pf.characterSeparated\n const length = useSeparated\n ? typeof pf.characterSeparated === 'number'\n ? pf.characterSeparated\n : DEFAULT_SEPARATED_LENGTH\n : 0\n\n if (useSeparated) {\n return this.createFieldContainer(this.renderSeparated(length))\n }\n return this.createFieldContainer(this.renderSingle())\n }\n\n private renderSingle(): HTMLElement {\n const pf = this.passwordField\n const showToggle = !!pf.showToggle\n\n const input = document.createElement('input')\n input.type = 'password'\n input.value = this.value ?? ''\n input.id = this.getFieldId()\n this.applyCommonProps(input)\n if (this.field.placeholder) input.placeholder = this.field.placeholder\n\n input.addEventListener('input', (e) => {\n this.onChange((e.target as HTMLInputElement).value)\n })\n input.addEventListener('blur', () => this.onBlur())\n\n if (!showToggle) {\n return input\n }\n\n const wrapper = document.createElement('div')\n wrapper.className = 'easy-form-password-inner'\n input.classList.add('easy-form-password-input')\n wrapper.appendChild(input)\n\n const btn = document.createElement('button')\n btn.type = 'button'\n btn.className = 'easy-form-password-toggle'\n btn.setAttribute('aria-label', 'Mostrar contraseña')\n btn.innerHTML = eyeSvg(false)\n btn.addEventListener('click', () => {\n this.visible = !this.visible\n input.type = this.visible ? 'text' : 'password'\n btn.setAttribute('aria-label', this.visible ? 'Ocultar contraseña' : 'Mostrar contraseña')\n btn.innerHTML = eyeSvg(this.visible)\n })\n wrapper.appendChild(btn)\n return wrapper\n }\n\n private renderSeparated(length: number): HTMLElement {\n const pf = this.passwordField\n const showToggle = !!pf.showToggle\n const value = this.value ?? ''\n const valueString = String(value).slice(0, length)\n\n const container = document.createElement('div')\n container.className = 'easy-form-password-separated'\n\n for (let i = 0; i < length; i++) {\n const input = document.createElement('input')\n input.type = 'password'\n input.maxLength = 1\n input.className = 'easy-form-password-separated-input'\n input.setAttribute('aria-label', `Carácter ${i + 1} de ${length}`)\n if (valueString[i]) input.value = valueString[i]\n this.applyCommonProps(input)\n input.id = i === 0 ? this.getFieldId() : `${this.getFieldId()}-${i}`\n if (i > 0) input.removeAttribute('name') // solo el primero conserva name para que el form encuentre el campo\n const currentIndex = i\n\n input.addEventListener('input', (e) => {\n const target = e.target as HTMLInputElement\n const val = target.value\n if (val && currentIndex < length - 1) {\n this.inputs[currentIndex + 1].focus()\n }\n this.updateSeparatedValue()\n })\n\n input.addEventListener('keydown', (e) => {\n if (e.key === 'Backspace' && !(e.target as HTMLInputElement).value && currentIndex > 0) {\n this.inputs[currentIndex - 1].focus()\n this.inputs[currentIndex - 1].value = ''\n this.updateSeparatedValue()\n }\n if (e.key === 'ArrowLeft' && currentIndex > 0) {\n e.preventDefault()\n this.inputs[currentIndex - 1].focus()\n }\n if (e.key === 'ArrowRight' && currentIndex < length - 1) {\n e.preventDefault()\n this.inputs[currentIndex + 1].focus()\n }\n })\n\n input.addEventListener('paste', (e) => {\n e.preventDefault()\n const text = (e.clipboardData || (window as any).clipboardData)?.getData('text') || ''\n const chars = text.slice(0, length - currentIndex).split('')\n for (let j = 0; j < chars.length && currentIndex + j < length; j++) {\n this.inputs[currentIndex + j].value = chars[j]\n }\n const nextIdx = Math.min(currentIndex + chars.length, length - 1)\n this.inputs[nextIdx].focus()\n this.updateSeparatedValue()\n })\n\n input.addEventListener('focus', (e) => (e.target as HTMLInputElement).select())\n input.addEventListener('blur', () => this.onBlur())\n\n this.inputs.push(input)\n container.appendChild(input)\n }\n\n if (showToggle) {\n const toggleWrap = document.createElement('div')\n toggleWrap.className = 'easy-form-password-separated-toggle'\n const btn = document.createElement('button')\n btn.type = 'button'\n btn.className = 'easy-form-password-toggle'\n btn.setAttribute('aria-label', 'Mostrar contraseña')\n btn.innerHTML = eyeSvg(false)\n btn.addEventListener('click', () => {\n this.visible = !this.visible\n const type = this.visible ? 'text' : 'password'\n this.inputs.forEach((inp) => { inp.type = type })\n btn.setAttribute('aria-label', this.visible ? 'Ocultar contraseña' : 'Mostrar contraseña')\n btn.innerHTML = eyeSvg(this.visible)\n })\n toggleWrap.appendChild(btn)\n container.appendChild(toggleWrap)\n }\n\n return container\n }\n\n private updateSeparatedValue(): void {\n const value = this.inputs.map((inp) => inp.value).join('')\n this.onChange(value || null)\n }\n}\n","import { BaseInput } from './base-input'\nimport type { FileDropField } from '../../types'\n\nexport class FileDropInput extends BaseInput {\n render(): HTMLElement {\n const fileDropField = this.field as FileDropField\n const accept = fileDropField.accept ?? ''\n const multiple = fileDropField.multiple ?? false\n\n const dropZone = document.createElement('div')\n dropZone.className = 'easy-form-file-drop'\n dropZone.setAttribute('tabindex', '0')\n\n const hiddenInput = document.createElement('input')\n hiddenInput.type = 'file'\n hiddenInput.className = 'easy-form-file-drop-input'\n hiddenInput.style.display = 'none'\n if (accept) hiddenInput.accept = accept\n if (multiple) hiddenInput.multiple = true\n\n const label = document.createElement('span')\n label.className = 'easy-form-file-drop-label'\n label.textContent = 'Arrastra archivos aquí o haz clic para seleccionar'\n dropZone.appendChild(label)\n dropZone.appendChild(hiddenInput)\n\n const fileList = document.createElement('div')\n fileList.className = 'easy-form-file-drop-list'\n\n const renderFileList = (files: File | File[] | null) => {\n const names = !files\n ? []\n : Array.isArray(files)\n ? files.map((f) => f.name)\n : [files.name]\n fileList.innerHTML = ''\n if (names.length === 0) {\n fileList.style.display = 'none'\n return\n }\n fileList.style.display = 'block'\n names.forEach((name) => {\n const item = document.createElement('div')\n item.className = 'easy-form-file-drop-item'\n item.textContent = name\n fileList.appendChild(item)\n })\n }\n renderFileList(this.value as File | File[] | null)\n\n const handleFiles = (files: FileList | null) => {\n if (!files || files.length === 0) return\n const arr = multiple ? Array.from(files) : files[0]\n this.onChange(arr)\n this.onBlur()\n renderFileList(arr)\n }\n\n dropZone.addEventListener('click', () => {\n hiddenInput.click()\n })\n\n hiddenInput.addEventListener('change', (e) => {\n const target = e.target as HTMLInputElement\n handleFiles(target.files)\n target.value = ''\n })\n\n dropZone.addEventListener('dragover', (e) => {\n e.preventDefault()\n e.stopPropagation()\n dropZone.classList.add('easy-form-file-drop-over')\n })\n\n dropZone.addEventListener('dragleave', (e) => {\n e.preventDefault()\n e.stopPropagation()\n dropZone.classList.remove('easy-form-file-drop-over')\n })\n\n dropZone.addEventListener('drop', (e) => {\n e.preventDefault()\n e.stopPropagation()\n dropZone.classList.remove('easy-form-file-drop-over')\n handleFiles(e.dataTransfer?.files ?? null)\n })\n\n dropZone.appendChild(fileList)\n return this.createFieldContainer(dropZone)\n }\n}\n","import { BaseInput } from './base-input'\nimport type { MapField } from '../../types'\n\nconst LEAFLET_CSS = 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.css'\n\nexport class MapInput extends BaseInput {\n private mapInstance: L.Map | null = null\n private markerInstance: L.Marker | null = null\n\n render(): HTMLElement {\n const mapField = this.field as MapField\n const center = mapField.center ?? { lat: 0, lng: 0 }\n const zoom = mapField.zoom ?? 13\n const value = this.value as { lat?: number; lng?: number } | string | null | undefined\n const lat = typeof value === 'object' && value?.lat != null ? value.lat : center.lat\n const lng = typeof value === 'object' && value?.lng != null ? value.lng : center.lng\n\n const container = document.createElement('div')\n container.className = 'easy-form-map'\n\n const inputsWrapper = document.createElement('div')\n inputsWrapper.className = 'easy-form-map-inputs'\n\n const latInput = document.createElement('input')\n latInput.type = 'number'\n latInput.step = 'any'\n latInput.placeholder = 'Latitud'\n latInput.value = String(lat)\n latInput.className = 'easy-form-map-lat'\n\n const lngInput = document.createElement('input')\n lngInput.type = 'number'\n lngInput.step = 'any'\n lngInput.placeholder = 'Longitud'\n lngInput.value = String(lng)\n lngInput.className = 'easy-form-map-lng'\n\n const updateFromInputs = () => {\n const latVal = parseFloat(latInput.value)\n const lngVal = parseFloat(lngInput.value)\n if (!isNaN(latVal) && !isNaN(lngVal)) {\n this.onChange({ lat: latVal, lng: lngVal })\n this.syncMarkerPosition(latVal, lngVal)\n }\n this.onBlur()\n }\n\n latInput.addEventListener('change', updateFromInputs)\n lngInput.addEventListener('change', updateFromInputs)\n\n inputsWrapper.appendChild(latInput)\n inputsWrapper.appendChild(lngInput)\n container.appendChild(inputsWrapper)\n\n const mapContainer = document.createElement('div')\n mapContainer.className = 'easy-form-map-container'\n container.appendChild(mapContainer)\n\n // Inyectar CSS de Leaflet DENTRO del contenedor para que quede en el Shadow DOM\n // (document.head no aplica estilos al Shadow DOM de easy-form)\n const linkId = 'easy-form-leaflet-css'\n let cssLoaded = false\n const link = document.createElement('link')\n link.id = linkId\n link.rel = 'stylesheet'\n link.href = LEAFLET_CSS\n link.onload = () => { cssLoaded = true }\n container.insertBefore(link, container.firstChild)\n\n const initMap = async () => {\n if (typeof window === 'undefined') return\n \n // Asegurar que el contenedor tenga dimensiones antes de inicializar\n mapContainer.style.height = '300px'\n mapContainer.style.width = '100%'\n mapContainer.style.position = 'relative'\n mapContainer.style.overflow = 'hidden'\n mapContainer.style.display = 'block'\n\n // Esperar a que el CSS se cargue y el contenedor esté en el DOM con dimensiones\n await new Promise((resolve) => {\n const checkReady = () => {\n if (cssLoaded && mapContainer.offsetWidth > 0 && mapContainer.offsetHeight > 0) {\n resolve(undefined)\n } else {\n requestAnimationFrame(checkReady)\n }\n }\n checkReady()\n })\n \n // Esperar un poco más para asegurar que el layout esté completamente calculado\n await new Promise((resolve) => setTimeout(resolve, 50))\n\n let L: typeof import('leaflet')\n try {\n L = await import('leaflet')\n } catch {\n mapContainer.innerHTML = `\n <div style=\"padding:2rem;text-align:center;color:#666;font-size:0.875rem;background:#f9f9f9;border-radius:4px;\">\n <strong>Campo map requiere Leaflet</strong><br><br>\n Instala e importa Leaflet para usar el mapa interactivo:<br>\n <code>npm install leaflet</code><br><br>\n En tu app: <code>import 'leaflet'</code> y <code>import 'leaflet/dist/leaflet.css'</code><br>\n <a href=\"https://easyforms.dev/docs/tipos-campos#map\" target=\"_blank\" rel=\"noopener\" style=\"color:var(--easy-form-primary,#007bff);\">Ver documentación</a>\n </div>\n `\n return\n }\n\n // Fix icon paths when bundled (Leaflet default icons break with bundlers)\n delete (L.Icon.Default.prototype as { _getIconUrl?: unknown })._getIconUrl\n L.Icon.Default.mergeOptions({\n iconRetinaUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon-2x.png',\n iconUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon.png',\n shadowUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-shadow.png',\n })\n\n this.mapInstance = L.map(mapContainer, {\n preferCanvas: false,\n zoomControl: true\n }).setView([lat, lng], zoom)\n\n const tileLayer = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {\n attribution: '&copy; <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a>',\n maxZoom: 19\n }).addTo(this.mapInstance)\n\n // Invalidar tamaño inmediatamente después de crear el mapa\n this.mapInstance.invalidateSize()\n \n // Invalidar tamaño después de que los tiles se hayan cargado\n tileLayer.on('load', () => {\n if (this.mapInstance) {\n this.mapInstance.invalidateSize()\n }\n })\n \n // Invalidar tamaño con múltiples intentos para asegurar que todo esté renderizado\n const invalidateSize = () => {\n if (this.mapInstance) {\n this.mapInstance.invalidateSize()\n }\n }\n setTimeout(invalidateSize, 100)\n setTimeout(invalidateSize, 300)\n setTimeout(invalidateSize, 500)\n \n // Invalidar tamaño cuando el contenedor sea visible (por si estaba oculto inicialmente)\n const observer = new IntersectionObserver((entries) => {\n entries.forEach((entry) => {\n if (entry.isIntersecting && this.mapInstance) {\n setTimeout(() => {\n this.mapInstance?.invalidateSize()\n }, 100)\n }\n })\n })\n observer.observe(mapContainer)\n\n this.markerInstance = L.marker([lat, lng], { draggable: true })\n .addTo(this.mapInstance)\n .on('dragend', () => {\n const pos = this.markerInstance!.getLatLng()\n latInput.value = String(Number(pos.lat.toFixed(6)))\n lngInput.value = String(Number(pos.lng.toFixed(6)))\n this.onChange({ lat: pos.lat, lng: pos.lng })\n this.onBlur()\n })\n\n this.mapInstance.on('click', (e: L.LeafletMouseEvent) => {\n const { lat: newLat, lng: newLng } = e.latlng\n this.markerInstance!.setLatLng([newLat, newLng])\n latInput.value = String(Number(newLat.toFixed(6)))\n lngInput.value = String(Number(newLng.toFixed(6)))\n this.onChange({ lat: newLat, lng: newLng })\n this.onBlur()\n })\n }\n\n initMap()\n\n return this.createFieldContainer(container)\n }\n\n private syncMarkerPosition(newLat: number, newLng: number): void {\n if (this.mapInstance && this.markerInstance) {\n this.markerInstance.setLatLng([newLat, newLng])\n this.mapInstance.setView([newLat, newLng])\n // Invalidar tamaño por si el contenedor cambió\n setTimeout(() => {\n this.mapInstance?.invalidateSize()\n }, 50)\n }\n }\n}\n","import { BaseInput } from './base-input'\nimport type { RatingField } from '../../types'\n\nconst STAR_SVG = (filled: boolean) =>\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"${filled ? 'currentColor' : 'none'}\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" role=\"img\" aria-hidden=\"true\"><polygon points=\"12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2\"/></svg>`\n\nexport class RatingInput extends BaseInput {\n render(): HTMLElement {\n const ratingField = this.field as RatingField\n const max = ratingField.max ?? 5\n const half = ratingField.half ?? false\n const currentValue = this.value != null ? Number(this.value) : 0\n\n const container = document.createElement('div')\n container.className = 'easy-form-rating'\n container.setAttribute('role', 'slider')\n container.setAttribute('aria-valuemin', '0')\n container.setAttribute('aria-valuemax', String(max))\n container.setAttribute('aria-valuenow', String(currentValue))\n container.setAttribute('aria-label', this.field.label || 'Rating')\n container.setAttribute('tabindex', '0')\n\n const starsContainer = document.createElement('div')\n starsContainer.className = 'easy-form-rating-stars'\n\n for (let i = 1; i <= max; i++) {\n const starWrapper = document.createElement('button')\n starWrapper.type = 'button'\n const filled = currentValue >= i || (half && currentValue >= i - 0.5)\n starWrapper.className = filled\n ? 'easy-form-rating-star easy-form-rating-star-filled'\n : 'easy-form-rating-star'\n starWrapper.innerHTML = STAR_SVG(filled)\n starWrapper.setAttribute('aria-label', `${i} de ${max}`)\n starWrapper.addEventListener('click', (e) => {\n e.preventDefault()\n const rect = (e.target as HTMLElement).closest('button')?.getBoundingClientRect()\n let val = i\n if (half && rect) {\n const mid = rect.left + rect.width / 2\n val = (e as MouseEvent).clientX < mid ? i - 0.5 : i\n }\n this.onChange(val)\n this.onBlur()\n this.rerenderStars(container, max, val, half)\n container.setAttribute('aria-valuenow', String(val))\n })\n starsContainer.appendChild(starWrapper)\n }\n\n container.appendChild(starsContainer)\n\n container.addEventListener('keydown', (e) => {\n const cur = Number(container.getAttribute('aria-valuenow')) || 0\n let newVal = cur\n if (e.key === 'ArrowRight' || e.key === 'ArrowUp') {\n e.preventDefault()\n newVal = Math.min(max, half ? cur + 0.5 : cur + 1)\n this.onChange(newVal)\n } else if (e.key === 'ArrowLeft' || e.key === 'ArrowDown') {\n e.preventDefault()\n newVal = Math.max(0, half ? cur - 0.5 : cur - 1)\n this.onChange(newVal)\n }\n if (newVal !== cur) {\n this.rerenderStars(container, max, newVal, half)\n container.setAttribute('aria-valuenow', String(newVal))\n }\n })\n\n return this.createFieldContainer(container)\n }\n\n private rerenderStars(\n container: HTMLElement,\n max: number,\n value: number,\n half: boolean\n ): void {\n const stars = container.querySelectorAll('.easy-form-rating-star')\n stars.forEach((star, i) => {\n const idx = i + 1\n const filled = value >= idx || (half && value >= idx - 0.5)\n star.className = filled\n ? 'easy-form-rating-star easy-form-rating-star-filled'\n : 'easy-form-rating-star'\n star.innerHTML = STAR_SVG(filled)\n })\n }\n}\n","import { BaseInput } from './base-input'\nimport type { SliderField } from '../../types'\n\nexport class SliderInput extends BaseInput {\n render(): HTMLElement {\n const sliderField = this.field as SliderField\n const min = sliderField.min ?? 0\n const max = sliderField.max ?? 100\n const step = sliderField.step ?? 1\n const showValue = sliderField.showValue ?? false\n\n const input = document.createElement('input')\n input.type = 'range'\n input.min = String(min)\n input.max = String(max)\n input.step = String(step)\n input.value = this.value != null ? String(this.value) : String(min)\n\n input.setAttribute('aria-valuemin', String(min))\n input.setAttribute('aria-valuemax', String(max))\n input.setAttribute('aria-valuenow', input.value)\n\n this.applyCommonProps(input)\n\n input.addEventListener('input', (e) => {\n const target = e.target as HTMLInputElement\n const val = step >= 1 ? parseInt(target.value, 10) : parseFloat(target.value)\n this.onChange(isNaN(val) ? min : val)\n if (valueSpan) {\n valueSpan.textContent = target.value\n }\n input.setAttribute('aria-valuenow', target.value)\n })\n\n input.addEventListener('change', () => {\n this.onBlur()\n })\n\n let valueSpan: HTMLSpanElement | null = null\n if (showValue) {\n valueSpan = document.createElement('span')\n valueSpan.className = 'easy-form-slider-value'\n valueSpan.textContent = input.value\n const wrapper = document.createElement('div')\n wrapper.className = 'easy-form-slider-wrapper'\n wrapper.appendChild(input)\n wrapper.appendChild(valueSpan)\n return this.createFieldContainer(wrapper)\n }\n\n return this.createFieldContainer(input)\n }\n}\n","import { BaseInput } from './base-input'\nimport type { ColorpickerField } from '../../types'\n\nconst HEX_REGEX = /^#?([0-9A-Fa-f]{6})$/\n\nfunction toHex(value: string): string {\n const m = value.match(HEX_REGEX)\n if (m) return `#${m[1].toLowerCase()}`\n if (/^[0-9A-Fa-f]{6}$/.test(value)) return `#${value.toLowerCase()}`\n return '#000000'\n}\n\nexport class ColorInput extends BaseInput {\n render(): HTMLElement {\n const colorField = this.field as ColorpickerField\n const defaultValue = colorField.defaultValue ?? '#000000'\n const currentValue =\n this.value != null && typeof this.value === 'string'\n ? toHex(this.value)\n : defaultValue\n\n const wrapper = document.createElement('div')\n wrapper.className = 'easy-form-color-wrapper'\n\n const colorPicker = document.createElement('input')\n colorPicker.type = 'color'\n colorPicker.value = currentValue\n colorPicker.setAttribute('value', currentValue)\n colorPicker.setAttribute('aria-label', this.field.label || 'Color')\n colorPicker.id = `${this.getFieldId()}-picker`\n if (this.field.disabled) colorPicker.setAttribute('disabled', 'true')\n\n const textInput = document.createElement('input')\n textInput.type = 'text'\n textInput.value = currentValue\n textInput.setAttribute('aria-label', `${this.field.label || 'Color'} (hex)`)\n textInput.placeholder = '#000000'\n textInput.className = 'easy-form-color-text'\n this.applyCommonProps(textInput)\n\n const syncFromPicker = () => {\n const value = colorPicker.value || '#000000'\n const hex = toHex(value)\n textInput.value = hex\n this.onChange(hex)\n }\n\n const syncFromText = () => {\n const raw = textInput.value.trim()\n const value = raw.startsWith('#') ? raw : `#${raw}`\n if (/^#[0-9A-Fa-f]{6}$/.test(value)) {\n const hex = toHex(value)\n colorPicker.value = hex\n this.onChange(hex)\n }\n }\n\n colorPicker.addEventListener('input', syncFromPicker)\n colorPicker.addEventListener('change', () => {\n syncFromPicker()\n this.onBlur()\n })\n textInput.addEventListener('input', syncFromText)\n textInput.addEventListener('blur', () => {\n syncFromText()\n this.onBlur()\n })\n\n wrapper.appendChild(colorPicker)\n wrapper.appendChild(textInput)\n return this.createFieldContainer(wrapper)\n }\n}\n","import { TextInput } from './text-input'\nimport { NumberInput } from './number-input'\nimport { TextareaInput } from './textarea-input'\nimport { SelectInput } from './select-input'\nimport { CheckboxInput } from './checkbox-input'\nimport { RadioInput } from './radio-input'\nimport { SwitchInput } from './switch-input'\nimport { DateInput } from './date-input'\nimport { FileInput } from './file-input'\nimport { QuantityInput } from './quantity-input'\nimport { AccordionSelectInput } from './accordion-select-input'\nimport { ImageGridSelectInput } from './image-grid-select-input'\nimport { OTPInput } from './otp-input'\nimport { PasswordInput } from './password-input'\nimport { FileDropInput } from './file-drop-input'\nimport { MapInput } from './map-input'\nimport { RatingInput } from './rating-input'\nimport { SliderInput } from './slider-input'\nimport { ColorInput } from './color-input'\nimport type { Field, CustomComponent } from '../../types'\n\n/**\n * Factory para crear inputs\n */\nexport function createInput(\n field: Field,\n value: any,\n error: string | undefined,\n onChange: (value: any) => void,\n onBlur: () => void\n): HTMLElement {\n switch (field.type) {\n case 'text':\n case 'email':\n return new TextInput(field, value, error, onChange, onBlur).render()\n case 'password':\n return new PasswordInput(field, value, error, onChange, onBlur).render()\n case 'number':\n return new NumberInput(field, value, error, onChange, onBlur).render()\n case 'textarea':\n return new TextareaInput(field, value, error, onChange, onBlur).render()\n case 'select':\n return new SelectInput(field, value, error, onChange, onBlur).render()\n case 'checkbox':\n return new CheckboxInput(field, value, error, onChange, onBlur).render()\n case 'radio':\n return new RadioInput(field, value, error, onChange, onBlur).render()\n case 'switch':\n return new SwitchInput(field, value, error, onChange, onBlur).render()\n case 'date':\n return new DateInput(field, value, error, onChange, onBlur).render()\n case 'file':\n return new FileInput(field, value, error, onChange, onBlur).render()\n case 'file-drop':\n return new FileDropInput(field, value, error, onChange, onBlur).render()\n case 'map':\n return new MapInput(field, value, error, onChange, onBlur).render()\n case 'rating':\n return new RatingInput(field, value, error, onChange, onBlur).render()\n case 'slider':\n return new SliderInput(field, value, error, onChange, onBlur).render()\n case 'colorpicker':\n return new ColorInput(field, value, error, onChange, onBlur).render()\n case 'quantity':\n return new QuantityInput(field, value, error, onChange, onBlur).render()\n case 'accordion-select':\n return new AccordionSelectInput(field, value, error, onChange, onBlur).render()\n case 'image-grid-select':\n return new ImageGridSelectInput(field, value, error, onChange, onBlur).render()\n case 'otp':\n return new OTPInput(field, value, error, onChange, onBlur).render()\n default:\n const div = document.createElement('div')\n div.textContent = `Tipo de campo no soportado: ${field.type}`\n return div\n }\n}\n\n/**\n * Registro de componentes personalizados\n */\nlet customComponents: Map<string, CustomComponent> = new Map()\n\n/**\n * Registra un componente personalizado\n */\nexport function registerComponent(\n type: string,\n component: CustomComponent\n): void {\n customComponents.set(type, component)\n}\n\n/**\n * Registra múltiples componentes\n */\nexport function registerComponents(\n components: Record<string, CustomComponent>\n): void {\n for (const [type, component] of Object.entries(components)) {\n registerComponent(type, component)\n }\n}\n\n/**\n * Obtiene un componente personalizado\n */\nexport function getCustomComponent(type: string): CustomComponent | undefined {\n return customComponents.get(type)\n}\n","import type { FormSchema, Field, TemplateName } from '../types'\n\n/**\n * Login form template\n */\nconst loginTemplate: FormSchema = {\n fields: [\n {\n type: 'email',\n name: 'email',\n label: 'Email',\n placeholder: 'Enter your email',\n validations: [\n { type: 'required', message: 'Email is required' },\n { type: 'email', message: 'Please enter a valid email' },\n ],\n },\n {\n type: 'password',\n name: 'password',\n label: 'Password',\n placeholder: 'Enter your password',\n validations: [\n { type: 'required', message: 'Password is required' },\n { type: 'minLength', value: 6, message: 'Password must be at least 6 characters' },\n ],\n },\n {\n type: 'checkbox',\n name: 'rememberMe',\n label: 'Remember me',\n defaultValue: false,\n },\n ],\n}\n\n/**\n * Registration form template\n */\nconst registerTemplate: FormSchema = {\n fields: [\n {\n type: 'text',\n name: 'name',\n label: 'Full Name',\n placeholder: 'Enter your full name',\n validations: [\n { type: 'required', message: 'Name is required' },\n { type: 'minLength', value: 2, message: 'Name must be at least 2 characters' },\n ],\n },\n {\n type: 'email',\n name: 'email',\n label: 'Email',\n placeholder: 'Enter your email',\n validations: [\n { type: 'required', message: 'Email is required' },\n { type: 'email', message: 'Please enter a valid email' },\n ],\n },\n {\n type: 'password',\n name: 'password',\n label: 'Password',\n placeholder: 'Create a password',\n validations: [\n { type: 'required', message: 'Password is required' },\n { type: 'minLength', value: 8, message: 'Password must be at least 8 characters' },\n ],\n },\n {\n type: 'password',\n name: 'confirmPassword',\n label: 'Confirm Password',\n placeholder: 'Confirm your password',\n validations: [\n { type: 'required', message: 'Please confirm your password' },\n {\n type: 'custom',\n validator: (value) => {\n // Note: For password matching validation, you may need to implement\n // a custom validation that accesses the form's state manager\n // or use a form-level validation on submit\n return typeof value === 'string' && value.length >= 8\n },\n message: 'Password must be at least 8 characters',\n },\n ],\n },\n ],\n}\n\n/**\n * OTP verification template\n */\nconst otpTemplate: FormSchema = {\n fields: [\n {\n type: 'otp',\n name: 'code',\n label: 'Verification Code',\n validations: [\n { type: 'required', message: 'Verification code is required' },\n ],\n },\n ],\n}\n\n/**\n * Contact form template\n */\nconst contactTemplate: FormSchema = {\n fields: [\n {\n type: 'text',\n name: 'name',\n label: 'Name',\n placeholder: 'Enter your name',\n validations: [\n { type: 'required', message: 'Name is required' },\n ],\n },\n {\n type: 'email',\n name: 'email',\n label: 'Email',\n placeholder: 'Enter your email',\n validations: [\n { type: 'required', message: 'Email is required' },\n { type: 'email', message: 'Please enter a valid email' },\n ],\n },\n {\n type: 'text',\n name: 'subject',\n label: 'Subject',\n placeholder: 'Enter the subject',\n validations: [\n { type: 'required', message: 'Subject is required' },\n ],\n },\n {\n type: 'textarea',\n name: 'message',\n label: 'Message',\n placeholder: 'Enter your message',\n rows: 5,\n validations: [\n { type: 'required', message: 'Message is required' },\n { type: 'minLength', value: 10, message: 'Message must be at least 10 characters' },\n ],\n },\n ],\n}\n\n/**\n * Password reset request template\n */\nconst passwordResetTemplate: FormSchema = {\n fields: [\n {\n type: 'email',\n name: 'email',\n label: 'Email',\n placeholder: 'Enter your email address',\n validations: [\n { type: 'required', message: 'Email is required' },\n { type: 'email', message: 'Please enter a valid email' },\n ],\n },\n ],\n}\n\n/**\n * Password change template\n */\nconst passwordChangeTemplate: FormSchema = {\n fields: [\n {\n type: 'password',\n name: 'currentPassword',\n label: 'Current Password',\n placeholder: 'Enter your current password',\n validations: [\n { type: 'required', message: 'Current password is required' },\n ],\n },\n {\n type: 'password',\n name: 'newPassword',\n label: 'New Password',\n placeholder: 'Enter your new password',\n validations: [\n { type: 'required', message: 'New password is required' },\n { type: 'minLength', value: 8, message: 'Password must be at least 8 characters' },\n ],\n },\n {\n type: 'password',\n name: 'confirmPassword',\n label: 'Confirm New Password',\n placeholder: 'Confirm your new password',\n validations: [\n { type: 'required', message: 'Please confirm your new password' },\n {\n type: 'custom',\n validator: (value) => {\n // Note: For password matching validation, you may need to implement\n // a custom validation that accesses the form's state manager\n // or use a form-level validation on submit\n return typeof value === 'string' && value.length >= 8\n },\n message: 'Password must be at least 8 characters',\n },\n ],\n },\n ],\n}\n\n/**\n * User profile edit template\n */\nconst profileTemplate: FormSchema = {\n fields: [\n {\n type: 'text',\n name: 'name',\n label: 'Full Name',\n placeholder: 'Enter your full name',\n validations: [\n { type: 'required', message: 'Name is required' },\n ],\n },\n {\n type: 'email',\n name: 'email',\n label: 'Email',\n placeholder: 'Enter your email',\n validations: [\n { type: 'required', message: 'Email is required' },\n { type: 'email', message: 'Please enter a valid email' },\n ],\n },\n {\n type: 'text',\n name: 'phone',\n label: 'Phone',\n placeholder: 'Enter your phone number',\n mask: {\n type: 'phone',\n },\n },\n {\n type: 'textarea',\n name: 'bio',\n label: 'Bio',\n placeholder: 'Tell us about yourself',\n rows: 4,\n },\n {\n type: 'file',\n name: 'avatar',\n label: 'Profile Picture',\n accept: 'image/*',\n },\n ],\n}\n\n/**\n * Checkout form template\n */\nconst checkoutTemplate: FormSchema = {\n fields: [\n {\n type: 'group',\n name: 'billingAddress',\n label: 'Billing Address',\n fields: [\n {\n type: 'text',\n name: 'street',\n label: 'Street Address',\n placeholder: 'Enter street address',\n validations: [\n { type: 'required', message: 'Street address is required' },\n ],\n },\n {\n type: 'row',\n name: 'cityState',\n fields: [\n {\n type: 'text',\n name: 'city',\n label: 'City',\n placeholder: 'City',\n validations: [\n { type: 'required', message: 'City is required' },\n ],\n },\n {\n type: 'text',\n name: 'state',\n label: 'State',\n placeholder: 'State',\n validations: [\n { type: 'required', message: 'State is required' },\n ],\n },\n ],\n },\n {\n type: 'text',\n name: 'zipCode',\n label: 'ZIP Code',\n placeholder: 'ZIP Code',\n validations: [\n { type: 'required', message: 'ZIP code is required' },\n ],\n },\n ],\n },\n {\n type: 'select',\n name: 'paymentMethod',\n label: 'Payment Method',\n options: [\n { label: 'Credit Card', value: 'credit-card' },\n { label: 'Debit Card', value: 'debit-card' },\n { label: 'PayPal', value: 'paypal' },\n { label: 'Bank Transfer', value: 'bank-transfer' },\n ],\n validations: [\n { type: 'required', message: 'Payment method is required' },\n ],\n },\n {\n type: 'select',\n name: 'shipping',\n label: 'Shipping Method',\n options: [\n { label: 'Standard (5-7 days)', value: 'standard' },\n { label: 'Express (2-3 days)', value: 'express' },\n { label: 'Overnight', value: 'overnight' },\n ],\n validations: [\n { type: 'required', message: 'Shipping method is required' },\n ],\n },\n ],\n}\n\n/**\n * Feedback form template\n */\nconst feedbackTemplate: FormSchema = {\n fields: [\n {\n type: 'select',\n name: 'rating',\n label: 'Rating',\n options: [\n { label: '1 - Poor', value: 1 },\n { label: '2 - Fair', value: 2 },\n { label: '3 - Good', value: 3 },\n { label: '4 - Very Good', value: 4 },\n { label: '5 - Excellent', value: 5 },\n ],\n validations: [\n { type: 'required', message: 'Rating is required' },\n ],\n },\n {\n type: 'textarea',\n name: 'comment',\n label: 'Comment',\n placeholder: 'Share your feedback',\n rows: 5,\n validations: [\n { type: 'required', message: 'Comment is required' },\n ],\n },\n {\n type: 'email',\n name: 'email',\n label: 'Email (optional)',\n placeholder: 'Enter your email if you want a response',\n },\n ],\n}\n\n/**\n * Newsletter subscription template\n */\nconst subscriptionTemplate: FormSchema = {\n fields: [\n {\n type: 'email',\n name: 'email',\n label: 'Email',\n placeholder: 'Enter your email',\n validations: [\n { type: 'required', message: 'Email is required' },\n { type: 'email', message: 'Please enter a valid email' },\n ],\n },\n {\n type: 'checkbox',\n name: 'weeklyNewsletter',\n label: 'Weekly Newsletter',\n defaultValue: true,\n },\n {\n type: 'checkbox',\n name: 'productUpdates',\n label: 'Product Updates',\n defaultValue: false,\n },\n {\n type: 'checkbox',\n name: 'promotions',\n label: 'Promotions and Special Offers',\n defaultValue: false,\n },\n ],\n}\n\n/**\n * Booking/reservation template\n */\nconst bookingTemplate: FormSchema = {\n fields: [\n {\n type: 'date',\n name: 'date',\n label: 'Date',\n validations: [\n { type: 'required', message: 'Date is required' },\n ],\n },\n {\n type: 'text',\n name: 'time',\n label: 'Time',\n placeholder: 'HH:MM',\n mask: {\n type: 'time',\n },\n validations: [\n { type: 'required', message: 'Time is required' },\n ],\n },\n {\n type: 'number',\n name: 'guests',\n label: 'Number of Guests',\n placeholder: 'Enter number of guests',\n min: 1,\n max: 20,\n validations: [\n { type: 'required', message: 'Number of guests is required' },\n { type: 'min', value: 1, message: 'At least 1 guest is required' },\n ],\n },\n {\n type: 'textarea',\n name: 'specialRequests',\n label: 'Special Requests',\n placeholder: 'Any special requests or dietary restrictions?',\n rows: 4,\n },\n ],\n}\n\n/**\n * Review/rating form template\n */\nconst reviewTemplate: FormSchema = {\n fields: [\n {\n type: 'select',\n name: 'rating',\n label: 'Rating',\n options: [\n { label: '1 Star', value: 1 },\n { label: '2 Stars', value: 2 },\n { label: '3 Stars', value: 3 },\n { label: '4 Stars', value: 4 },\n { label: '5 Stars', value: 5 },\n ],\n validations: [\n { type: 'required', message: 'Rating is required' },\n ],\n },\n {\n type: 'text',\n name: 'title',\n label: 'Review Title',\n placeholder: 'Give your review a title',\n validations: [\n { type: 'required', message: 'Review title is required' },\n { type: 'minLength', value: 5, message: 'Title must be at least 5 characters' },\n ],\n },\n {\n type: 'textarea',\n name: 'comment',\n label: 'Your Review',\n placeholder: 'Share your experience',\n rows: 6,\n validations: [\n { type: 'required', message: 'Review comment is required' },\n { type: 'minLength', value: 20, message: 'Review must be at least 20 characters' },\n ],\n },\n ],\n}\n\n/**\n * Registry of all available templates\n */\nexport const templates: Record<TemplateName, FormSchema> = {\n login: loginTemplate,\n register: registerTemplate,\n otp: otpTemplate,\n contact: contactTemplate,\n 'password-reset': passwordResetTemplate,\n 'password-change': passwordChangeTemplate,\n profile: profileTemplate,\n checkout: checkoutTemplate,\n feedback: feedbackTemplate,\n subscription: subscriptionTemplate,\n booking: bookingTemplate,\n review: reviewTemplate,\n}\n\n/**\n * Get a template by name\n * @param templateName - Name of the template to retrieve\n * @returns The template schema or null if not found\n */\nexport function getTemplate(templateName: string): FormSchema | null {\n if (templateName in templates) {\n return templates[templateName as TemplateName]\n }\n return null\n}\n\n/**\n * Get list of all available template names\n * @returns Array of template names\n */\nexport function getAvailableTemplates(): TemplateName[] {\n return Object.keys(templates) as TemplateName[]\n}\n\n/**\n * Extend a template with additional fields\n * @param templateName - Name of the template to extend\n * @param additionalFields - Additional fields to add to the template\n * @returns Extended schema with template fields + additional fields\n */\nexport function extendTemplate(\n templateName: string,\n additionalFields: Field[]\n): FormSchema {\n const baseTemplate = getTemplate(templateName)\n if (!baseTemplate) {\n throw new Error(`Template \"${templateName}\" not found`)\n }\n\n const existingFields = baseTemplate.fields || []\n const existingSteps = baseTemplate.steps\n\n // If template has steps, extend the last step\n if (existingSteps && existingSteps.length > 0) {\n const lastStep = existingSteps[existingSteps.length - 1]\n return {\n ...baseTemplate,\n steps: [\n ...existingSteps.slice(0, -1),\n {\n ...lastStep,\n fields: [...lastStep.fields, ...additionalFields],\n },\n ],\n }\n }\n\n // Otherwise, extend fields array\n return {\n ...baseTemplate,\n fields: [...existingFields, ...additionalFields],\n }\n}\n","import { StateManager } from '../core/state-manager'\nimport { AttemptsLock } from '../utils/attempts-lock'\nimport { createInput, getCustomComponent, registerComponents } from './inputs'\nimport type {\n FormSchema,\n Field,\n ComponentRegistry,\n SubmitEventDetail,\n ChangeEventDetail,\n ErrorEventDetail,\n StepChangeEventDetail,\n FormTheme,\n FormColors,\n TemplateName,\n SubmitButtonConfig,\n} from '../types'\nimport { attributeValue, parseAttributeValue } from '../utils'\nimport { getThemeStyles, getColors } from '../utils/styles'\nimport { getTemplate, extendTemplate } from '../templates'\n\n// Verificar si estamos en un entorno del navegador\nconst BrowserHTMLElement = typeof HTMLElement !== 'undefined' ? HTMLElement : class {} as typeof HTMLElement\n\n/**\n * Web Component principal EasyForm\n */\nexport class EasyForm extends BrowserHTMLElement {\n private stateManager: StateManager\n protected shadow: ShadowRoot\n private customComponents: ComponentRegistry = {}\n private isRendering: boolean = false\n private attemptsLock: AttemptsLock | null = null\n private lockCountdownInterval: ReturnType<typeof setInterval> | null = null\n /**\n * Plantillas de slots basados en atributo `row` en el light DOM.\n * Se inicializan una sola vez y se clonan en cada render.\n */\n private slotTemplates: { template: HTMLElement; row: number | null }[] | null = null\n private skipPreserveValuesOnNextRender = false\n\n static get observedAttributes() {\n return [\n 'schema',\n 'template',\n 'template-extend',\n 'theme',\n 'colors',\n 'initialData',\n 'loading',\n 'disabled',\n 'max-attempts',\n 'block-duration-minutes',\n 'attempts-storage-key',\n 'submit-button',\n 'label-position',\n 'show-completed-indicator',\n 'form-direction',\n ]\n }\n\n constructor() {\n if (typeof HTMLElement === 'undefined') {\n throw new Error('EasyForm can only be used in a browser environment')\n }\n super()\n this.stateManager = new StateManager()\n this.shadow = this.attachShadow({ mode: 'open' })\n // Los estilos se aplicarán en connectedCallback cuando los atributos estén disponibles\n }\n\n /**\n * Obtiene el schema\n */\n get schema(): FormSchema | null {\n const schemaAttr = this.getAttribute('schema')\n if (!schemaAttr) return null\n \n // Validar mutua exclusividad con template\n if (this.getAttribute('template')) {\n console.warn('EasyForm: Cannot use both \"schema\" and \"template\" attributes. \"template\" will be ignored.')\n return parseAttributeValue(schemaAttr)\n }\n \n return parseAttributeValue(schemaAttr)\n }\n\n /**\n * Establece el schema\n */\n set schema(value: FormSchema | null) {\n // Si se establece schema, remover template\n if (value && this.getAttribute('template')) {\n console.warn('EasyForm: Setting \"schema\" will remove \"template\" attribute.')\n this.removeAttribute('template')\n this.removeAttribute('template-extend')\n }\n \n if (value) {\n this.setAttribute('schema', attributeValue(value))\n } else {\n this.removeAttribute('schema')\n }\n }\n\n /**\n * Obtiene el template\n */\n get template(): TemplateName | null {\n const templateAttr = this.getAttribute('template')\n if (!templateAttr) return null\n \n // Validar mutua exclusividad con schema\n if (this.getAttribute('schema')) {\n console.warn('EasyForm: Cannot use both \"template\" and \"schema\" attributes. \"schema\" will be ignored.')\n return templateAttr as TemplateName\n }\n \n return templateAttr as TemplateName\n }\n\n /**\n * Establece el template\n */\n set template(value: TemplateName | null) {\n // Si se establece template, remover schema\n if (value && this.getAttribute('schema')) {\n console.warn('EasyForm: Setting \"template\" will remove \"schema\" attribute.')\n this.removeAttribute('schema')\n }\n \n if (value) {\n this.setAttribute('template', value)\n } else {\n this.removeAttribute('template')\n this.removeAttribute('template-extend')\n }\n }\n\n /**\n * Obtiene los campos adicionales para extender el template\n */\n get templateExtend(): Field[] | null {\n const extendAttr = this.getAttribute('template-extend')\n if (!extendAttr) return null\n return parseAttributeValue(extendAttr)\n }\n\n /**\n * Establece los campos adicionales para extender el template\n */\n set templateExtend(value: Field[] | null) {\n if (value) {\n this.setAttribute('template-extend', attributeValue(value))\n } else {\n this.removeAttribute('template-extend')\n }\n }\n\n /**\n * Máximo de intentos antes de bloquear (para AttemptsLock)\n */\n get maxAttempts(): number | null {\n const attr = this.getAttribute('max-attempts')\n if (!attr) return null\n const n = parseInt(attr, 10)\n return isNaN(n) ? null : n\n }\n\n set maxAttempts(value: number | null) {\n if (value != null && value >= 1) {\n this.setAttribute('max-attempts', String(value))\n } else {\n this.removeAttribute('max-attempts')\n }\n }\n\n /**\n * Duración del bloqueo en minutos (default: 5)\n */\n get blockDurationMinutes(): number | null {\n const attr = this.getAttribute('block-duration-minutes')\n if (!attr) return null\n const n = parseInt(attr, 10)\n return isNaN(n) ? null : n\n }\n\n set blockDurationMinutes(value: number | null) {\n if (value != null && value >= 1) {\n this.setAttribute('block-duration-minutes', String(value))\n } else {\n this.removeAttribute('block-duration-minutes')\n }\n }\n\n /**\n * Clave para persistir intentos en sessionStorage\n */\n get attemptsStorageKey(): string | null {\n return this.getAttribute('attempts-storage-key')\n }\n\n set attemptsStorageKey(value: string | null) {\n if (value) {\n this.setAttribute('attempts-storage-key', value)\n } else {\n this.removeAttribute('attempts-storage-key')\n }\n }\n\n /**\n * Configuración del botón de submit (desde atributo o schema)\n */\n get submitButton(): SubmitButtonConfig | null {\n const attr = this.getAttribute('submit-button')\n if (attr) {\n try {\n return parseAttributeValue(attr) as SubmitButtonConfig\n } catch {\n return null\n }\n }\n return null\n }\n\n set submitButton(value: SubmitButtonConfig | null) {\n if (value && typeof value === 'object') {\n this.setAttribute('submit-button', attributeValue(value))\n } else {\n this.removeAttribute('submit-button')\n }\n }\n\n /**\n * Obtiene la configuración efectiva del botón submit (atributo > schema > defaults)\n */\n private getSubmitButtonConfig(schema: FormSchema | null): Required<SubmitButtonConfig> {\n const fromAttr = this.submitButton\n const fromSchema = schema?.submitButton\n const merged = { ...fromSchema, ...fromAttr } as SubmitButtonConfig\n return {\n visible: merged.visible ?? true,\n text: merged.text ?? 'Enviar',\n width: merged.width ?? 'auto',\n align: merged.align ?? 'left',\n }\n }\n\n /**\n * Se llama cuando el componente se conecta al DOM\n */\n connectedCallback() {\n this.setupAttemptsLock()\n // Asegurar que los estilos estén aplicados con los atributos actuales\n this.setupStyles()\n this.render()\n }\n\n /**\n * Se llama cuando un atributo cambia\n */\n attributeChangedCallback(name: string, oldValue: string, newValue: string) {\n // Validar mutua exclusividad\n if (name === 'schema' && newValue !== oldValue) {\n if (this.getAttribute('template')) {\n console.warn('EasyForm: \"schema\" and \"template\" cannot be used together. Removing \"template\".')\n this.removeAttribute('template')\n this.removeAttribute('template-extend')\n }\n this.handleSchemaChange()\n }\n if (name === 'template' && newValue !== oldValue) {\n if (this.getAttribute('schema')) {\n console.warn('EasyForm: \"template\" and \"schema\" cannot be used together. Removing \"schema\".')\n this.removeAttribute('schema')\n }\n this.handleSchemaChange()\n }\n if (name === 'template-extend' && newValue !== oldValue) {\n this.handleSchemaChange()\n }\n if (name === 'initialData' && newValue !== oldValue) {\n this.handleSchemaChange()\n }\n if ((name === 'theme' || name === 'colors') && newValue !== oldValue) {\n this.setupStyles()\n }\n if (name === 'loading' && newValue !== oldValue) {\n // Actualizar solo el overlay de loading sin re-renderizar todo\n const form = this.shadow.querySelector('form')\n this.updateLoadingOverlay(form || undefined)\n // También necesitamos actualizar el estado disabled de los campos\n if (form) {\n const inputs = form.querySelectorAll('input, textarea, select, button')\n inputs.forEach((input) => {\n if (input instanceof HTMLElement && 'disabled' in input) {\n (input as any).disabled = this.loading\n }\n })\n }\n }\n if (name === 'disabled' && newValue !== oldValue) {\n this.render()\n }\n if ((name === 'label-position' || name === 'form-direction' || name === 'show-completed-indicator') && newValue !== oldValue) {\n this.render()\n }\n if (\n (name === 'max-attempts' ||\n name === 'block-duration-minutes' ||\n name === 'attempts-storage-key') &&\n newValue !== oldValue\n ) {\n this.setupAttemptsLock()\n this.updateLockOverlay()\n }\n if (name === 'submit-button' && newValue !== oldValue) {\n this.render()\n }\n }\n\n /**\n * Configura el AttemptsLock según los atributos actuales\n */\n private setupAttemptsLock(): void {\n const maxAttempts = this.maxAttempts\n if (maxAttempts == null || maxAttempts < 1) {\n this.attemptsLock = null\n return\n }\n this.attemptsLock = new AttemptsLock({\n maxAttempts,\n blockDurationMinutes: this.blockDurationMinutes ?? 5,\n storageKey: this.attemptsStorageKey ?? undefined,\n onLocked: () => {\n this.updateLockOverlay()\n },\n onUnlocked: () => {\n this.stopLockCountdown()\n this.updateLockOverlay()\n this.render()\n },\n })\n }\n\n /**\n * Maneja el cambio de schema\n */\n private handleSchemaChange() {\n let schema: FormSchema | null = null\n \n // Priorizar template sobre schema\n const templateName = this.template\n if (templateName) {\n schema = this.getSchemaFromTemplate(templateName)\n } else {\n schema = this.schema\n }\n \n if (schema) {\n const initialData = this.initialData\n this.stateManager.initializeSchema(schema, initialData || undefined)\n this.render()\n }\n }\n\n /**\n * Obtiene el schema desde un template\n */\n private getSchemaFromTemplate(templateName: TemplateName): FormSchema | null {\n const baseTemplate = getTemplate(templateName)\n if (!baseTemplate) {\n console.error(`EasyForm: Template \"${templateName}\" not found`)\n return null\n }\n\n // Si hay campos adicionales, extender el template\n const additionalFields = this.templateExtend\n if (additionalFields && additionalFields.length > 0) {\n return extendTemplate(templateName, additionalFields)\n }\n\n return baseTemplate\n }\n\n /**\n * Renderiza el formulario\n */\n private async render() {\n // Evitar renderizados simultáneos\n if (this.isRendering) {\n return\n }\n \n this.isRendering = true\n \n try {\n // Obtener schema desde template o atributo schema\n let schema: FormSchema | null = null\n const templateName = this.template\n if (templateName) {\n schema = this.getSchemaFromTemplate(templateName)\n } else {\n schema = this.schema\n }\n \n if (!schema) {\n // Eliminar solo el formulario, mantener los estilos\n const form = this.shadow.querySelector('form')\n if (form && form.parentNode === this.shadow) {\n form.remove()\n }\n return\n }\n\n // Preservar valores actuales del DOM antes de re-renderizar (omitir si viene de add/remove en array)\n const isArrayRefresh = this.skipPreserveValuesOnNextRender\n const preservedValues = isArrayRefresh ? {} : this.preserveCurrentValues()\n this.skipPreserveValuesOnNextRender = false\n\n // Preservar el estado del wizard ANTES de reinicializar (pero después de cualquier cambio)\n const previousWizardState = this.stateManager.getWizardState()\n\n // Guardar los valores preservados en el estado sin validar\n // Esto evita disparar validaciones de todos los campos\n if (preservedValues && Object.keys(preservedValues).length > 0) {\n for (const [key, value] of Object.entries(preservedValues)) {\n this.stateManager.setValueWithoutValidation(key, value)\n }\n }\n\n const initialData = this.initialData\n \n // Verificar si el schema ha cambiado comparando si es wizard o no\n const wasWizard = previousWizardState !== null\n const isWizard = schema.steps && schema.steps.length > 0\n \n // Solo reinicializar el schema si es necesario (si cambió de wizard a normal o viceversa)\n // O si el número de steps cambió, o si no hay estado previo.\n // No re-inicializar cuando es refresh por add/remove en array (preservar estado actual).\n const shouldReinitialize = !isArrayRefresh && (\n !previousWizardState || !wasWizard || !isWizard || \n (previousWizardState && schema.steps && previousWizardState.totalSteps !== schema.steps.length)\n )\n \n if (shouldReinitialize) {\n this.stateManager.initializeSchema(schema, initialData || undefined)\n \n // Si había un wizard state previo y el schema sigue siendo wizard, restaurarlo\n if (wasWizard && isWizard && previousWizardState) {\n const wizardState = this.stateManager.getWizardState()\n if (wizardState && previousWizardState.totalSteps === wizardState.totalSteps) {\n // Restaurar el paso actual primero\n if (previousWizardState.currentStep >= 0 && previousWizardState.currentStep < wizardState.totalSteps) {\n this.stateManager.goToStep(previousWizardState.currentStep)\n }\n // Restaurar pasos completados\n for (const completedStep of previousWizardState.completedSteps) {\n if (completedStep >= 0 && completedStep < wizardState.totalSteps) {\n this.stateManager.completeStep(completedStep)\n }\n }\n }\n }\n }\n // Si no se reinicializa, el estado del wizard ya está actualizado (por nextStep/previousStep)\n // y los valores ya fueron preservados arriba\n \n // Obtener el estado actualizado\n const finalWizardState = this.stateManager.getWizardState()\n\n // Crear formulario\n const newFormElement = document.createElement('form')\n newFormElement.addEventListener('submit', (e) => this.handleSubmit(e))\n \n // Aplicar disabled al formulario si está disabled o loading\n if (this.disabled || this.loading) {\n newFormElement.classList.add('easy-form-disabled')\n }\n\n // Dirección del layout (vertical | horizontal)\n const directionAttr = this.getAttribute('form-direction') as 'vertical' | 'horizontal' | null\n const direction = schema.direction ?? (directionAttr === 'vertical' || directionAttr === 'horizontal' ? directionAttr : 'vertical')\n newFormElement.classList.add(`easy-form-direction-${direction}`)\n\n // Indicador de progreso (campos obligatorios completados)\n const showCompletedAttr = this.getAttribute('show-completed-indicator')\n const completedIndicator = schema.completedIndicator ?? (showCompletedAttr !== null && showCompletedAttr !== 'false')\n const completedPosition = typeof completedIndicator === 'object' && completedIndicator?.position ? completedIndicator.position : 'top'\n\n // Renderizar campos o steps\n if (finalWizardState) {\n this.renderWizard(newFormElement, schema)\n // No agregar botón submit normal para wizard, ya tiene sus propios botones\n } else {\n this.renderFields(newFormElement, schema.fields || [])\n\n // Botón submit solo para formularios normales (no wizard)\n const submitConfig = this.getSubmitButtonConfig(schema)\n if (submitConfig.visible) {\n const submitWrapper = document.createElement('div')\n submitWrapper.className = 'easy-form-submit-wrapper'\n submitWrapper.style.textAlign = submitConfig.align\n\n const submitButton = document.createElement('button')\n submitButton.type = 'submit'\n submitButton.textContent = submitConfig.text\n submitButton.className = 'easy-form-submit'\n submitButton.style.width = submitConfig.width\n if (this.disabled || this.loading) {\n submitButton.disabled = true\n }\n submitWrapper.appendChild(submitButton)\n newFormElement.appendChild(submitWrapper)\n }\n }\n\n // Indicador de progreso (antes o después del formulario)\n let formWrapper: HTMLElement | null = null\n if (completedIndicator) {\n const { completed, total } = this.getCompletedRequiredProgress(schema)\n const progressBar = document.createElement('div')\n progressBar.className = 'easy-form-completed-indicator'\n progressBar.setAttribute('role', 'progressbar')\n progressBar.setAttribute('aria-valuenow', String(completed))\n progressBar.setAttribute('aria-valuemin', '0')\n progressBar.setAttribute('aria-valuemax', String(total))\n progressBar.setAttribute('aria-label', `Campos obligatorios completados: ${completed} de ${total}`)\n const track = document.createElement('div')\n track.className = 'easy-form-completed-track'\n const fill = document.createElement('div')\n fill.className = 'easy-form-completed-fill'\n fill.style.width = total > 0 ? `${(completed / total) * 100}%` : '0%'\n track.appendChild(fill)\n progressBar.appendChild(track)\n formWrapper = document.createElement('div')\n formWrapper.className = 'easy-form-wrapper'\n if (completedPosition === 'top') {\n formWrapper.appendChild(progressBar)\n formWrapper.appendChild(newFormElement)\n } else {\n formWrapper.appendChild(newFormElement)\n formWrapper.appendChild(progressBar)\n }\n }\n\n // Eliminar solo el formulario anterior si existe y está en el DOM, mantener los estilos\n const oldForm = this.shadow.querySelector('form')\n if (oldForm && oldForm.parentNode === this.shadow && oldForm !== newFormElement) {\n try {\n oldForm.remove()\n } catch (e) {\n // Ignorar errores si el elemento ya fue eliminado\n console.warn('Error al eliminar formulario anterior:', e)\n }\n }\n const oldWrapper = this.shadow.querySelector('.easy-form-wrapper')\n if (oldWrapper) oldWrapper.remove()\n\n // Agregar el nuevo formulario (o wrapper con indicador)\n this.shadow.appendChild(formWrapper || newFormElement)\n \n // Agregar overlay de loading sobre el formulario si está activo\n if (this.loading) {\n this.updateLoadingOverlay(newFormElement)\n }\n // Agregar overlay de bloqueo si está activo\n this.updateLockOverlay(newFormElement)\n } finally {\n this.isRendering = false\n }\n }\n\n /**\n * Actualiza el overlay de bloqueo por intentos\n */\n private updateLockOverlay(formElement?: HTMLElement): void {\n const existingOverlay = this.shadow.querySelector('.easy-form-lock-overlay')\n if (existingOverlay) {\n existingOverlay.remove()\n }\n this.stopLockCountdown()\n\n if (!this.attemptsLock?.isLocked()) return\n\n const form = formElement || this.shadow.querySelector('form')\n if (!form) return\n\n const overlay = document.createElement('div')\n overlay.className = 'easy-form-lock-overlay'\n\n const message = document.createElement('div')\n message.className = 'easy-form-lock-message'\n message.setAttribute('role', 'alert')\n\n const updateCountdown = (): void => {\n const remainingMs = this.attemptsLock!.getRemainingBlockTimeMs()\n if (remainingMs <= 0) {\n this.stopLockCountdown()\n return\n }\n const minutes = Math.floor(remainingMs / 60000)\n const seconds = Math.floor((remainingMs % 60000) / 1000)\n const timeStr =\n minutes > 0\n ? `${minutes} min ${seconds} s`\n : `${seconds} segundos`\n message.textContent = `Demasiados intentos. Intenta de nuevo en ${timeStr}.`\n }\n\n updateCountdown()\n overlay.appendChild(message)\n form.appendChild(overlay)\n\n this.lockCountdownInterval = setInterval(updateCountdown, 1000)\n }\n\n private stopLockCountdown(): void {\n if (this.lockCountdownInterval) {\n clearInterval(this.lockCountdownInterval)\n this.lockCountdownInterval = null\n }\n }\n\n /**\n * Actualiza el overlay de loading sobre el formulario\n */\n private updateLoadingOverlay(formElement?: HTMLElement) {\n // Eliminar overlay anterior si existe\n const existingOverlay = this.shadow.querySelector('.easy-form-loading-overlay')\n if (existingOverlay) {\n existingOverlay.remove()\n }\n\n // Si loading está activo, agregar overlay sobre el formulario\n if (this.loading) {\n const form = formElement || this.shadow.querySelector('form')\n if (form) {\n const overlay = document.createElement('div')\n overlay.className = 'easy-form-loading-overlay'\n \n const spinner = document.createElement('div')\n spinner.className = 'easy-form-loading-spinner'\n overlay.appendChild(spinner)\n \n // Agregar el overlay como hijo del formulario\n form.appendChild(overlay)\n }\n }\n }\n\n /**\n * Preserva los valores actuales del DOM antes de re-renderizar\n * Retorna un objeto con los valores preservados\n */\n private preserveCurrentValues(): Record<string, any> {\n // Necesitamos el schema actual para poder filtrar inputs que no pertenecen al formulario\n // y asegurar que valores dentro de slots u otros elementos no definidos en el schema\n // no se mezclen con el estado interno del formulario.\n let currentSchema: FormSchema | null = null\n const templateName = this.template\n if (templateName) {\n currentSchema = this.getSchemaFromTemplate(templateName)\n } else {\n currentSchema = this.schema\n }\n\n if (!currentSchema) {\n return {}\n }\n\n const form = this.shadow.querySelector('form')\n const preservedValues: Record<string, any> = {}\n \n if (!form) return preservedValues\n\n // Obtener todos los inputs, textareas y selects del formulario\n const inputs = form.querySelectorAll('input, textarea, select')\n \n for (const input of inputs) {\n const name = input.getAttribute('name')\n if (!name) continue\n\n // Ignorar inputs que no están definidos en el schema (por ejemplo, dentro de slots)\n const belongsToSchema = this.findFieldInSchema(currentSchema, name) !== null\n if (!belongsToSchema) continue\n\n let value: any\n \n if (input instanceof HTMLInputElement) {\n if (input.type === 'checkbox') {\n value = input.checked\n } else if (input.type === 'radio') {\n if (input.checked) {\n value = input.value\n } else {\n continue // Solo guardar el radio seleccionado\n }\n } else if (input.type === 'number') {\n value = input.value === '' ? null : Number(input.value)\n } else {\n value = input.value\n }\n } else if (input instanceof HTMLTextAreaElement) {\n value = input.value\n } else if (input instanceof HTMLSelectElement) {\n if (input.multiple) {\n value = Array.from(input.selectedOptions).map(opt => opt.value)\n } else {\n value = input.value || null\n }\n }\n\n // Guardar el valor (incluso strings vacíos para preservar el estado)\n if (value !== undefined) {\n preservedValues[name] = value === '' ? null : value\n }\n }\n \n return preservedValues\n }\n\n /**\n * Inicializa las plantillas de slots a partir del light DOM.\n * Cualquier hijo directo que sea HTMLElement se considera slot; si tiene atributo `row` se usa para la posición, si no se inserta al final (-1).\n */\n private initializeSlotTemplates(): void {\n if (this.slotTemplates !== null) return\n\n const elements: HTMLElement[] = []\n for (const child of Array.from(this.children)) {\n if (child instanceof HTMLElement) {\n elements.push(child)\n }\n }\n\n if (elements.length === 0) {\n this.slotTemplates = []\n return\n }\n\n this.slotTemplates = elements.map((el) => {\n const raw = el.hasAttribute('row') ? el.getAttribute('row') : null\n const parsed = raw != null && raw !== '' ? Number(raw) : NaN\n const row = Number.isFinite(parsed) ? parsed : null\n return {\n template: el.cloneNode(true) as HTMLElement,\n row,\n }\n })\n }\n\n /**\n * Obtiene clones de slots agrupados por índice de fila efectivo.\n * Cualquier valor inválido o fuera de rango se normaliza a -1 (final del formulario).\n */\n private getSlotClonesByRow(totalRows: number): Map<number, HTMLElement[]> {\n this.initializeSlotTemplates()\n\n const result = new Map<number, HTMLElement[]>()\n\n if (!this.slotTemplates || this.slotTemplates.length === 0) {\n return result\n }\n\n for (const { template, row } of this.slotTemplates) {\n let effectiveRow: number = typeof row === 'number' ? row : -1\n\n if (!Number.isFinite(effectiveRow)) {\n effectiveRow = -1\n }\n\n // Normalizar índices fuera de rango al final\n if (effectiveRow < 0 || effectiveRow >= totalRows) {\n effectiveRow = -1\n }\n\n const clone = template.cloneNode(true) as HTMLElement\n const existing = result.get(effectiveRow) ?? []\n existing.push(clone)\n result.set(effectiveRow, existing)\n }\n\n return result\n }\n\n /**\n * Aplica estado disabled/loading a un clone de slot: deshabilita elementos\n * interactivos y añade clase para estilos. Respeta el estado del formulario.\n */\n private applySlotDisabledState(slotElement: HTMLElement): void {\n if (!this.disabled && !this.loading) return\n slotElement.classList.add('easy-form-slot-disabled')\n const interactives = slotElement.querySelectorAll<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement | HTMLButtonElement>(\n 'input, textarea, select, button'\n )\n interactives.forEach((el) => {\n if ('disabled' in el) el.disabled = true\n })\n }\n\n /**\n * Renderiza campos normales\n */\n private renderFields(container: HTMLElement, fields: Field[]) {\n // Si no hay campos, aún debemos soportar posibles slots al final\n if (fields.length === 0) {\n const slotClones = this.getSlotClonesByRow(0)\n const endSlots = slotClones.get(-1)\n if (endSlots && endSlots.length > 0) {\n for (const slotElement of endSlots) {\n this.applySlotDisabledState(slotElement)\n container.appendChild(slotElement)\n }\n }\n return\n }\n\n const totalRows = fields.length\n const slotClonesByRow = this.getSlotClonesByRow(totalRows)\n\n for (let rowIndex = 0; rowIndex < fields.length; rowIndex++) {\n // Insertar primero los slots asociados a este índice de fila\n const slotsForRow = slotClonesByRow.get(rowIndex)\n if (slotsForRow && slotsForRow.length > 0) {\n for (const slotElement of slotsForRow) {\n this.applySlotDisabledState(slotElement)\n container.appendChild(slotElement)\n }\n slotClonesByRow.delete(rowIndex)\n }\n\n const field = fields[rowIndex]\n const fieldElement = this.renderField(field)\n if (fieldElement) {\n container.appendChild(fieldElement)\n }\n }\n\n // Insertar cualquier slot restante (índice efectivo -1) al final del formulario\n const endSlots = slotClonesByRow.get(-1)\n if (endSlots && endSlots.length > 0) {\n for (const slotElement of endSlots) {\n this.applySlotDisabledState(slotElement)\n container.appendChild(slotElement)\n }\n }\n }\n\n /**\n * Renderiza un campo\n */\n private renderField(field: Field): HTMLElement | null {\n // Verificar visibilidad basada en dependencias\n const isVisible = this.stateManager.getFieldVisibility(field.name)\n const isEnabled = this.stateManager.getFieldEnabled(field.name)\n\n // Campos especiales\n if (field.type === 'group') {\n const groupElement = this.renderGroup(field)\n if (!isVisible) {\n groupElement.style.display = 'none'\n groupElement.classList.add('easy-form-field-hidden')\n }\n if (!isEnabled) {\n groupElement.classList.add('easy-form-field-disabled')\n }\n return groupElement\n }\n if (field.type === 'row') {\n const rowElement = this.renderRow(field)\n if (!isVisible) {\n rowElement.style.display = 'none'\n rowElement.classList.add('easy-form-field-hidden')\n }\n if (!isEnabled) {\n rowElement.classList.add('easy-form-field-disabled')\n }\n return rowElement\n }\n if (field.type === 'array') {\n const arrayElement = this.renderArray(field)\n if (!isVisible) {\n arrayElement.style.display = 'none'\n arrayElement.classList.add('easy-form-field-hidden')\n }\n if (!isEnabled) {\n arrayElement.classList.add('easy-form-field-disabled')\n }\n return arrayElement\n }\n if (field.type === 'custom') {\n const customElement = this.renderCustom(field)\n if (customElement) {\n if (!isVisible) {\n customElement.style.display = 'none'\n customElement.classList.add('easy-form-field-hidden')\n }\n if (!isEnabled) {\n customElement.classList.add('easy-form-field-disabled')\n }\n }\n return customElement\n }\n\n // Campos normales\n const value = this.stateManager.getValue(field.name)\n const errors = this.stateManager.getErrors(field.name)\n const error = errors.length > 0 ? errors[0] : undefined\n\n // Aplicar disabled basado en dependencias, disabled general o loading\n const isFormDisabled = this.disabled || this.loading\n const labelPositionAttr = this.getAttribute('label-position') as\n | 'up'\n | 'down'\n | 'left'\n | 'right'\n | 'none'\n | null\n const validLabelPositions = ['up', 'down', 'left', 'right', 'none']\n const effectiveLabelPosition =\n field.labelPosition ??\n (labelPositionAttr && validLabelPositions.includes(labelPositionAttr)\n ? labelPositionAttr\n : 'up')\n const fieldWithDependencies = {\n ...field,\n disabled: isFormDisabled || !isEnabled || field.disabled,\n labelPosition: effectiveLabelPosition,\n }\n\n const customComponent = getCustomComponent(field.type)\n if (customComponent) {\n const element = customComponent({\n field: fieldWithDependencies,\n value,\n error,\n onChange: (val) => this.handleFieldChange(field.name, val),\n onBlur: () => this.handleFieldBlur(field.name),\n })\n if (element && !isVisible) {\n element.style.display = 'none'\n element.classList.add('easy-form-field-hidden')\n }\n return element\n }\n\n const inputElement = createInput(\n fieldWithDependencies,\n value,\n error,\n (val) => this.handleFieldChange(field.name, val),\n () => this.handleFieldBlur(field.name)\n )\n\n // Agregar atributo para identificar el campo\n const fieldContainer = inputElement.querySelector('.easy-form-field') || inputElement\n if (fieldContainer instanceof HTMLElement) {\n fieldContainer.setAttribute('data-field-name', field.name)\n }\n\n // Aplicar clases para visibilidad\n if (!isVisible) {\n inputElement.style.display = 'none'\n inputElement.classList.add('easy-form-field-hidden')\n }\n\n return inputElement\n }\n\n /**\n * Renderiza un grupo de campos\n */\n private renderGroup(field: Field): HTMLElement {\n const groupField = field as {\n direction?: 'vertical' | 'horizontal'\n collapsible?: boolean\n defaultOpen?: boolean\n }\n const dir = groupField.direction ?? 'vertical'\n const collapsible = groupField.collapsible === true\n const defaultOpen = groupField.defaultOpen !== false\n\n const groupContainer = document.createElement('div')\n groupContainer.className = `easy-form-group easy-form-direction-${dir}`\n if (field.name) {\n groupContainer.setAttribute('data-field-name', field.name)\n }\n\n if (collapsible) {\n groupContainer.classList.add('easy-form-group-collapsible')\n if (!defaultOpen) {\n groupContainer.classList.add('easy-form-group-collapsed')\n }\n\n const header = document.createElement('button')\n header.type = 'button'\n header.className = 'easy-form-group-header'\n header.setAttribute('aria-expanded', String(defaultOpen))\n const groupContentId = `easy-form-group-${(field.name || 'group').replace(/[^a-z0-9]/gi, '-')}-content`\n header.setAttribute('aria-controls', groupContentId)\n\n const labelSpan = document.createElement('span')\n labelSpan.textContent = field.label || 'Grupo'\n\n const chevron = document.createElement('span')\n chevron.className = 'easy-form-group-chevron'\n chevron.setAttribute('aria-hidden', 'true')\n chevron.textContent = '▼'\n\n header.appendChild(labelSpan)\n header.appendChild(chevron)\n groupContainer.appendChild(header)\n\n const content = document.createElement('div')\n content.id = groupContentId\n content.className = 'easy-form-group-content'\n\n if ('fields' in field && field.fields) {\n for (const subField of field.fields) {\n const fullName = subField.name.startsWith(field.name + '.')\n ? subField.name\n : `${field.name}.${subField.name}`\n const subFieldWithPath = { ...subField, name: fullName }\n const fieldElement = this.renderField(subFieldWithPath)\n if (fieldElement) {\n content.appendChild(fieldElement)\n }\n }\n }\n\n groupContainer.appendChild(content)\n\n const setContentHeight = (open: boolean) => {\n if (open) {\n content.style.maxHeight = content.scrollHeight + 'px'\n } else {\n content.style.maxHeight = '0'\n }\n }\n\n if (defaultOpen) {\n requestAnimationFrame(() => setContentHeight(true))\n } else {\n content.style.maxHeight = '0'\n }\n\n header.addEventListener('click', () => {\n const isCollapsed = groupContainer.classList.contains('easy-form-group-collapsed')\n if (isCollapsed) {\n groupContainer.classList.remove('easy-form-group-collapsed')\n header.setAttribute('aria-expanded', 'true')\n setContentHeight(true)\n } else {\n content.style.maxHeight = content.scrollHeight + 'px'\n requestAnimationFrame(() => {\n groupContainer.classList.add('easy-form-group-collapsed')\n header.setAttribute('aria-expanded', 'false')\n setContentHeight(false)\n })\n }\n })\n } else {\n if (field.label) {\n const label = document.createElement('h3')\n label.className = 'easy-form-group-label'\n label.textContent = field.label\n groupContainer.appendChild(label)\n }\n\n if ('fields' in field && field.fields) {\n for (const subField of field.fields) {\n const fullName = subField.name.startsWith(field.name + '.')\n ? subField.name\n : `${field.name}.${subField.name}`\n const subFieldWithPath = { ...subField, name: fullName }\n const fieldElement = this.renderField(subFieldWithPath)\n if (fieldElement) {\n groupContainer.appendChild(fieldElement)\n }\n }\n }\n }\n\n return groupContainer\n }\n\n /**\n * Renderiza una fila de campos\n */\n private renderRow(field: Field): HTMLElement {\n const rowContainer = document.createElement('div')\n rowContainer.className = 'easy-form-row'\n\n const rowField = field as any\n\n // Aplicar estilos flexbox\n rowContainer.style.display = 'flex'\n rowContainer.style.flexWrap = 'wrap'\n rowContainer.style.alignItems = rowField.align || 'stretch'\n\n // Aplicar gap\n if (rowField.gap !== undefined) {\n const gapValue = typeof rowField.gap === 'number' ? `${rowField.gap}px` : rowField.gap\n rowContainer.style.gap = gapValue\n } else {\n rowContainer.style.gap = '1rem'\n }\n\n // Renderizar campos dentro de la fila\n if ('fields' in field && field.fields) {\n for (const subField of field.fields) {\n const fieldElement = this.renderField(subField)\n if (fieldElement) {\n // Hacer que cada campo en la fila tenga flex: 1 para distribuirse equitativamente\n const fieldWrapper = document.createElement('div')\n fieldWrapper.style.flex = '1'\n fieldWrapper.style.minWidth = '0' // Permite que los campos se reduzcan\n fieldWrapper.appendChild(fieldElement)\n rowContainer.appendChild(fieldWrapper)\n }\n }\n }\n\n return rowContainer\n }\n\n /**\n * Renderiza un array dinámico\n */\n private renderArray(field: Field): HTMLElement {\n const arrayContainer = document.createElement('div')\n arrayContainer.className = 'easy-form-array'\n arrayContainer.setAttribute('data-field-name', field.name)\n\n if (field.label) {\n const label = document.createElement('label')\n label.className = 'easy-form-label'\n label.textContent = field.label\n arrayContainer.appendChild(label)\n }\n\n const values = this.stateManager.getValue(field.name) || []\n const arrayField = field as { itemSchema?: { fields?: Field[] }; minItems?: number; maxItems?: number }\n const minItems = arrayField.minItems ?? 0\n const maxItems = arrayField.maxItems ?? Infinity\n\n // Renderizar items existentes\n const itemsContainer = document.createElement('div')\n itemsContainer.className = 'easy-form-array-items'\n\n for (let i = 0; i < values.length; i++) {\n const itemContainer = document.createElement('div')\n itemContainer.className = 'easy-form-array-item'\n\n if (arrayField.itemSchema?.fields) {\n for (const itemField of arrayField.itemSchema.fields) {\n const itemFieldWithName = {\n ...itemField,\n name: `${field.name}.${i}.${itemField.name}`,\n }\n const fieldElement = this.renderField(itemFieldWithName)\n if (fieldElement) {\n itemContainer.appendChild(fieldElement)\n }\n }\n }\n\n // Botón eliminar\n const removeButton = document.createElement('button')\n removeButton.type = 'button'\n removeButton.textContent = 'Eliminar'\n removeButton.className = 'easy-form-array-remove'\n const atMinItems = values.length <= minItems\n if (this.disabled || this.loading || atMinItems) {\n removeButton.disabled = true\n } else {\n removeButton.addEventListener('click', () => {\n const newValues = [...values]\n newValues.splice(i, 1)\n this.handleFieldChange(field.name, newValues)\n })\n }\n itemContainer.appendChild(removeButton)\n\n itemsContainer.appendChild(itemContainer)\n }\n\n arrayContainer.appendChild(itemsContainer)\n\n // Botón agregar\n const addButton = document.createElement('button')\n addButton.type = 'button'\n addButton.textContent = 'Agregar'\n addButton.className = 'easy-form-array-add'\n const atMaxItems = values.length >= maxItems\n if (this.disabled || this.loading || atMaxItems) {\n addButton.disabled = true\n } else {\n addButton.addEventListener('click', () => {\n const newItem = this.stateManager.createDefaultArrayItem(field)\n const newValues = [...values, newItem]\n this.handleFieldChange(field.name, newValues)\n })\n }\n arrayContainer.appendChild(addButton)\n\n return arrayContainer\n }\n\n /**\n * Renderiza un campo custom\n */\n private renderCustom(field: Field): HTMLElement | null {\n const customComponent = getCustomComponent('custom')\n if (!customComponent) {\n const div = document.createElement('div')\n div.textContent = `Componente custom no registrado para: ${field.name}`\n return div\n }\n\n const value = this.stateManager.getValue(field.name)\n const errors = this.stateManager.getErrors(field.name)\n const error = errors.length > 0 ? errors[0] : undefined\n\n return customComponent({\n field,\n value,\n error,\n onChange: (val) => this.handleFieldChange(field.name, val),\n onBlur: () => this.handleFieldBlur(field.name),\n })\n }\n\n /**\n * Obtiene el progreso de campos obligatorios completados\n */\n private getCompletedRequiredProgress(schema: FormSchema): { completed: number; total: number } {\n const extractFields = (fields: Field[]): Field[] => {\n const result: Field[] = []\n for (const f of fields) {\n if (f.type === 'array' && 'itemSchema' in f && f.itemSchema?.fields) {\n const items = this.stateManager.getValue(f.name) as any[]\n const count = Array.isArray(items) ? items.length : 0\n for (let i = 0; i < count; i++) {\n for (const sf of f.itemSchema.fields) {\n result.push({ ...sf, name: `${f.name}.${i}.${sf.name}` } as Field)\n }\n }\n } else if ((f.type === 'group' || f.type === 'row') && 'fields' in f && f.fields) {\n result.push(...extractFields(f.fields))\n } else {\n result.push(f)\n }\n }\n return result\n }\n\n const fields = schema.steps\n ? (this.stateManager.getCurrentStepFields() || [])\n : schema.fields || []\n const allFields = extractFields(fields)\n const requiredFields = allFields.filter(\n (f) => f.validations?.some((v) => v.type === 'required')\n )\n const visibleRequired = requiredFields.filter((f) =>\n this.stateManager.getFieldVisibility(f.name)\n )\n const total = visibleRequired.length\n const completed = visibleRequired.filter((f) => {\n const errors = this.stateManager.getErrors(f.name)\n if (errors.length > 0) return false\n const val = this.stateManager.getValue(f.name)\n if (val === null || val === undefined) return false\n if (typeof val === 'string' && val.trim() === '') return false\n if (Array.isArray(val) && val.length === 0 && f.type === 'array') return false\n return true\n }).length\n return { completed, total }\n }\n\n /**\n * Renderiza wizard\n */\n private renderWizard(container: HTMLElement, schema: FormSchema) {\n // Obtener el estado actualizado del wizard\n const wizardState = this.stateManager.getWizardState()\n if (!wizardState) return\n\n const wizardContainer = document.createElement('div')\n wizardContainer.className = 'easy-form-wizard'\n\n // Indicador de steps\n const stepsIndicator = document.createElement('div')\n stepsIndicator.className = 'easy-form-wizard-steps'\n if (schema?.steps) {\n for (let i = 0; i < schema.steps.length; i++) {\n const stepEl = document.createElement('div')\n stepEl.className = 'easy-form-wizard-step'\n if (i === wizardState.currentStep) {\n stepEl.classList.add('active')\n }\n if (wizardState.completedSteps.includes(i)) {\n stepEl.classList.add('completed')\n }\n stepEl.textContent = schema.steps[i].title\n stepsIndicator.appendChild(stepEl)\n }\n }\n wizardContainer.appendChild(stepsIndicator)\n\n // Campos del step actual (con soporte de slots por row, scoped al step actual)\n const fieldsContainer = document.createElement('div')\n fieldsContainer.className = 'easy-form-wizard-fields'\n const currentFields = this.stateManager.getCurrentStepFields()\n this.renderFields(fieldsContainer, currentFields)\n wizardContainer.appendChild(fieldsContainer)\n\n // Botones de navegación\n const navContainer = document.createElement('div')\n navContainer.className = 'easy-form-wizard-nav'\n\n // Botón Anterior (solo si no es el primer paso)\n if (wizardState.currentStep > 0) {\n const prevButton = document.createElement('button')\n prevButton.type = 'button'\n prevButton.textContent = 'Anterior'\n prevButton.className = 'easy-form-wizard-prev'\n if (this.disabled || this.loading) {\n prevButton.disabled = true\n } else {\n prevButton.addEventListener('click', () => {\n const currentState = this.stateManager.getWizardState()\n if (currentState && this.stateManager.previousStep()) {\n this.render()\n this.emitStepChange()\n }\n })\n }\n navContainer.appendChild(prevButton)\n }\n\n // Botón Siguiente (solo si NO es el último paso)\n if (wizardState.currentStep < wizardState.totalSteps - 1) {\n const nextButton = document.createElement('button')\n nextButton.type = 'button'\n nextButton.textContent = 'Siguiente'\n nextButton.className = 'easy-form-wizard-next'\n if (this.disabled || this.loading) {\n nextButton.disabled = true\n } else {\n nextButton.addEventListener('click', async () => {\n // Obtener el estado actual del wizard\n const currentState = this.stateManager.getWizardState()\n if (!currentState) return\n\n // Validar solo los campos del step actual antes de avanzar\n const currentFields = this.stateManager.getCurrentStepFields()\n \n // Validar cada campo del paso actual\n for (const field of currentFields) {\n // Solo validar campos visibles\n if (this.stateManager.getFieldVisibility(field.name)) {\n await this.stateManager.validateField(field.name)\n }\n }\n \n // Obtener errores después de validar\n const allErrors = this.stateManager.getAllErrors()\n const stepErrors: Record<string, string[]> = {}\n \n // Filtrar solo errores de campos del paso actual\n for (const field of currentFields) {\n if (allErrors[field.name] && allErrors[field.name].length > 0) {\n stepErrors[field.name] = allErrors[field.name]\n }\n }\n\n const hasErrors = Object.keys(stepErrors).length > 0\n\n if (!hasErrors) {\n // Marcar el paso actual como completado\n this.stateManager.completeStep(currentState.currentStep)\n \n // Avanzar al siguiente paso\n const moved = this.stateManager.nextStep()\n if (moved) {\n // Renderizar después de actualizar el estado\n // El render preservará el estado actualizado (con el nuevo paso)\n this.render()\n this.emitStepChange()\n }\n } else {\n this.emitError(stepErrors)\n }\n })\n }\n navContainer.appendChild(nextButton)\n }\n\n // Botón Enviar (solo en el último paso)\n const submitConfig = this.getSubmitButtonConfig(schema)\n if (\n wizardState.currentStep === wizardState.totalSteps - 1 &&\n submitConfig.visible\n ) {\n const submitButton = document.createElement('button')\n submitButton.type = 'button'\n submitButton.textContent = submitConfig.text\n submitButton.className = 'easy-form-wizard-next'\n submitButton.style.width = submitConfig.width\n if (this.disabled || this.loading) {\n submitButton.disabled = true\n } else {\n submitButton.addEventListener('click', async () => {\n // Validar todos los campos del último paso antes de enviar\n const currentFields = this.stateManager.getCurrentStepFields()\n \n // Validar cada campo del paso actual\n for (const field of currentFields) {\n // Solo validar campos visibles\n if (this.stateManager.getFieldVisibility(field.name)) {\n await this.stateManager.validateField(field.name)\n }\n }\n \n // Obtener errores después de validar\n const allErrors = this.stateManager.getAllErrors()\n const stepErrors: Record<string, string[]> = {}\n \n // Filtrar solo errores de campos del paso actual\n for (const field of currentFields) {\n if (allErrors[field.name] && allErrors[field.name].length > 0) {\n stepErrors[field.name] = allErrors[field.name]\n }\n }\n\n const hasErrors = Object.keys(stepErrors).length > 0\n\n if (!hasErrors) {\n await this.handleSubmit(new Event('submit') as SubmitEvent)\n } else {\n this.emitError(stepErrors)\n }\n })\n }\n navContainer.appendChild(submitButton)\n }\n\n wizardContainer.appendChild(navContainer)\n container.appendChild(wizardContainer)\n }\n\n /**\n * Maneja el cambio de un campo\n */\n private async handleFieldChange(fieldName: string, value: any) {\n await this.stateManager.setValue(fieldName, value)\n \n // Si es un array, re-renderizar para reflejar add/remove\n const schema = this.schema\n if (schema) {\n const field = this.findFieldInSchema(schema, fieldName)\n if (field?.type === 'array') {\n const replaced = this.rerenderArrayField(field)\n // Si no se encontró el contenedor, hacer render completo (ej. array dentro de row/group)\n if (!replaced) {\n this.skipPreserveValuesOnNextRender = true\n requestAnimationFrame(() => this.render())\n }\n }\n }\n \n // Obtener campos dependientes que necesitan re-renderizarse\n const dependentFields = this.stateManager.getDependentFields(fieldName)\n \n // Re-renderizar campos dependientes si hay cambios en dependencias\n if (dependentFields.length > 0) {\n // Usar un pequeño delay para agrupar múltiples cambios\n if (this.dependencyRenderTimeout) {\n clearTimeout(this.dependencyRenderTimeout)\n }\n \n this.dependencyRenderTimeout = setTimeout(() => {\n this.renderDependentFields(dependentFields)\n this.emitDependencyChange(fieldName, dependentFields)\n }, 10)\n }\n\n // Emitir evento change\n const changeEvent = new CustomEvent<ChangeEventDetail>('change', {\n detail: {\n field: fieldName,\n value,\n values: this.stateManager.getState().values,\n },\n bubbles: true,\n composed: true,\n })\n this.dispatchEvent(changeEvent)\n }\n\n private dependencyRenderTimeout: ReturnType<typeof setTimeout> | null = null\n\n /**\n * Re-renderiza un campo array cuando se añaden o eliminan ítems.\n * Retorna true si se reemplazó, false si no se encontró el contenedor.\n */\n private rerenderArrayField(field: Field): boolean {\n const arrayContainer = this.shadow.querySelector(\n `[data-field-name=\"${field.name}\"].easy-form-array`\n )\n if (!arrayContainer?.parentNode) return false\n\n const newArrayElement = this.renderArray(field)\n arrayContainer.parentNode.replaceChild(newArrayElement, arrayContainer)\n return true\n }\n\n /**\n * Re-renderiza campos dependientes\n */\n private renderDependentFields(fieldNames: string[]): void {\n const form = this.shadow.querySelector('form')\n if (!form) return\n\n const schema = this.schema\n if (!schema) return\n\n for (const fieldName of fieldNames) {\n const fieldContainer =\n form.querySelector(`.easy-form-field[name=\"${fieldName}\"], [data-field-name=\"${fieldName}\"]`)?.closest('.easy-form-field') ??\n form.querySelector(`[data-field-name=\"${fieldName}\"]`)\n\n if (fieldContainer) {\n const field = this.findFieldInSchema(schema, fieldName)\n if (!field) continue\n\n // Re-renderizar el campo\n const newFieldElement = this.renderField(field)\n if (newFieldElement && fieldContainer.parentNode) {\n fieldContainer.parentNode.replaceChild(newFieldElement, fieldContainer)\n }\n }\n }\n }\n\n /**\n * Emite evento de cambio de dependencia\n */\n private emitDependencyChange(\n changedField: string,\n affectedFields: string[]\n ): void {\n const dependencyEvent = new CustomEvent('dependencyChange', {\n detail: {\n changedField,\n affectedFields,\n },\n bubbles: true,\n composed: true,\n })\n this.dispatchEvent(dependencyEvent)\n }\n\n /**\n * Maneja el blur de un campo\n */\n private async handleFieldBlur(fieldName: string) {\n this.stateManager.setTouched(fieldName)\n // Validar solo el campo que perdió el foco\n await this.stateManager.validateField(fieldName)\n // Actualizar solo el campo específico sin re-renderizar todo el formulario\n this.updateSingleField(fieldName)\n }\n\n /**\n * Actualiza solo un campo específico sin re-renderizar todo el formulario\n */\n private updateSingleField(fieldName: string) {\n const schema = this.schema\n if (!schema) return\n\n const field = this.findFieldInSchema(schema, fieldName)\n if (!field) return\n\n const errors = this.stateManager.getErrors(fieldName)\n const error = errors.length > 0 ? errors[0] : undefined\n\n // Buscar el contenedor del campo en el DOM\n const fieldContainer = this.shadow.querySelector(`[name=\"${fieldName}\"]`)?.closest('.easy-form-field')\n if (!fieldContainer) return\n\n // Actualizar el error\n const errorElement = fieldContainer.querySelector('.easy-form-error')\n if (error) {\n if (!errorElement) {\n const errorEl = document.createElement('p')\n errorEl.className = 'easy-form-error'\n errorEl.textContent = error\n fieldContainer.appendChild(errorEl)\n } else {\n errorElement.textContent = error\n }\n // Agregar clase de error al input\n const input = fieldContainer.querySelector('input, textarea, select') as HTMLElement\n input?.classList.add('easy-form-input-error')\n } else {\n errorElement?.remove()\n const input = fieldContainer.querySelector('input, textarea, select') as HTMLElement\n input?.classList.remove('easy-form-input-error')\n }\n }\n\n /**\n * Busca un campo por nombre en el schema (soporta rutas como 'group.subfield')\n */\n private findFieldInSchema(schema: FormSchema, name: string): Field | null {\n const fields = schema.fields || []\n const dot = name.indexOf('.')\n if (dot > 0) {\n const parentName = name.slice(0, dot)\n const childName = name.slice(dot + 1)\n const parent = fields.find((f) => f.name === parentName)\n if (!parent) return null\n if ((parent.type === 'group' || parent.type === 'row') && 'fields' in parent && parent.fields) {\n const found = this.findFieldInSchema({ fields: parent.fields }, childName)\n return found ? { ...found, name } : null\n }\n return null\n }\n for (const field of fields) {\n if (field.name === name) {\n return field\n }\n if (field.type === 'group' && 'fields' in field) {\n const found = this.findFieldInSchema({ fields: field.fields }, name)\n if (found) return found\n }\n if (field.type === 'row' && 'fields' in field) {\n const found = this.findFieldInSchema({ fields: field.fields }, name)\n if (found) return found\n }\n }\n return null\n }\n\n /**\n * Maneja el submit del formulario\n */\n private async handleSubmit(event: Event) {\n event.preventDefault()\n\n if (this.attemptsLock?.isLocked()) {\n return\n }\n\n const errors = await this.stateManager.validateForm()\n const state = this.stateManager.getState()\n\n if (Object.keys(errors).length > 0) {\n this.emitError(errors)\n // Don't call render() here as it resets the form\n // The error event handler can handle showing errors\n return\n }\n\n // Emitir evento submit\n const submitEvent = new CustomEvent<SubmitEventDetail>('submit', {\n detail: {\n values: state.values,\n isValid: true,\n errors: {},\n },\n bubbles: true,\n composed: true,\n })\n this.dispatchEvent(submitEvent)\n }\n\n /**\n * Emite evento de error\n */\n private emitError(errors: Record<string, string[]>) {\n const errorEvent = new CustomEvent<ErrorEventDetail>('error', {\n detail: {\n errors,\n },\n bubbles: true,\n composed: true,\n })\n this.dispatchEvent(errorEvent)\n }\n\n /**\n * Emite evento de cambio de step\n */\n private emitStepChange() {\n const wizardState = this.stateManager.getWizardState()\n if (!wizardState) return\n\n const stepChangeEvent = new CustomEvent<StepChangeEventDetail>(\n 'stepChange',\n {\n detail: {\n currentStep: wizardState.currentStep,\n previousStep:\n wizardState.currentStep > 0\n ? wizardState.currentStep - 1\n : wizardState.currentStep,\n totalSteps: wizardState.totalSteps,\n },\n bubbles: true,\n composed: true,\n }\n )\n this.dispatchEvent(stepChangeEvent)\n }\n\n /**\n * Registra componentes personalizados\n */\n public registerComponents(components: ComponentRegistry): void {\n this.customComponents = { ...this.customComponents, ...components }\n registerComponents(components)\n }\n\n /**\n * Resetea el formulario a sus valores iniciales\n */\n public reset(): void {\n this.stateManager.reset()\n this.render()\n }\n\n /**\n * Incrementa el contador de intentos (para bloqueo por intentos fallidos).\n * El consumidor debe llamar esto cuando la API/login falle.\n */\n public incrementAttempts(): void {\n this.attemptsLock?.incrementAttempts()\n if (this.attemptsLock?.isLocked()) {\n this.updateLockOverlay()\n }\n }\n\n /**\n * Resetea el contador de intentos y desbloquea el formulario.\n */\n public resetAttempts(): void {\n this.attemptsLock?.reset()\n this.stopLockCountdown()\n this.updateLockOverlay()\n this.render()\n }\n\n /**\n * Retorna true si el formulario está bloqueado por intentos.\n */\n public isLocked(): boolean {\n return this.attemptsLock?.isLocked() ?? false\n }\n\n /**\n * Retorna los milisegundos restantes del bloqueo, o 0 si no está bloqueado.\n */\n public getRemainingBlockTimeMs(): number {\n return this.attemptsLock?.getRemainingBlockTimeMs() ?? 0\n }\n\n /**\n * Dispara el submit del formulario programáticamente.\n * Útil cuando el botón submit está oculto (visible: false).\n */\n public requestSubmit(): void {\n const form = this.shadow.querySelector('form')\n if (form && typeof (form as HTMLFormElement).requestSubmit === 'function') {\n ;(form as HTMLFormElement).requestSubmit()\n }\n }\n\n /**\n * Limpia todos los valores del formulario\n */\n public clear(): void {\n const schema = this.schema\n const templateName = this.template\n let currentSchema: FormSchema | null = null\n \n if (templateName) {\n currentSchema = this.getSchemaFromTemplate(templateName)\n } else {\n currentSchema = schema\n }\n \n if (currentSchema) {\n this.stateManager.initializeSchema(currentSchema, {})\n this.render()\n }\n }\n\n /**\n * Obtiene todos los valores del formulario\n */\n public getValues(): Record<string, any> {\n return this.stateManager.getState().values\n }\n\n /**\n * Obtiene el valor de un campo específico\n */\n public getValue(fieldName: string): any {\n return this.stateManager.getValue(fieldName)\n }\n\n /**\n * Establece el valor de un campo específico\n */\n public async setValue(fieldName: string, value: any): Promise<void> {\n await this.stateManager.setValue(fieldName, value)\n this.render()\n }\n\n /**\n * Establece múltiples valores a la vez\n */\n public async setValues(values: Record<string, any>): Promise<void> {\n for (const [fieldName, value] of Object.entries(values)) {\n await this.stateManager.setValue(fieldName, value)\n }\n this.render()\n }\n\n /**\n * Valida el formulario completo\n */\n public async validate(): Promise<Record<string, string[]>> {\n const errors = await this.stateManager.validateForm()\n // Don't call render() as it resets the form values\n if (Object.keys(errors).length > 0) {\n this.emitError(errors)\n }\n return errors\n }\n\n /**\n * Valida un campo específico\n */\n public async validateField(fieldName: string): Promise<string[]> {\n await this.stateManager.validateField(fieldName)\n this.updateSingleField(fieldName)\n return this.stateManager.getErrors(fieldName)\n }\n\n /**\n * Obtiene todos los errores del formulario\n */\n public getErrors(): Record<string, string[]> {\n return this.stateManager.getAllErrors()\n }\n\n /**\n * Obtiene los errores de un campo específico\n */\n public getFieldErrors(fieldName: string): string[] {\n return this.stateManager.getErrors(fieldName)\n }\n\n /**\n * Verifica si el formulario es válido\n */\n public isValid(): boolean {\n return this.stateManager.getState().isValid\n }\n\n /**\n * Obtiene el tema del formulario\n */\n get theme(): FormTheme {\n const themeAttr = this.getAttribute('theme')\n const validThemes: FormTheme[] = [\n 'plano',\n 'tradicional',\n 'material',\n 'rounded-shadow',\n 'lines',\n 'shadcn',\n 'chakra',\n 'mantine',\n 'glass',\n 'bordered',\n 'minimal',\n 'efc'\n ]\n if (themeAttr && validThemes.includes(themeAttr as FormTheme)) {\n return themeAttr as FormTheme\n }\n return 'plano' // Tema por defecto\n }\n\n /**\n * Establece el tema del formulario\n */\n set theme(value: FormTheme) {\n if (value) {\n this.setAttribute('theme', value)\n } else {\n this.removeAttribute('theme')\n }\n }\n\n /**\n * Obtiene los colores personalizados\n */\n get colors(): FormColors | null {\n const colorsAttr = this.getAttribute('colors')\n if (!colorsAttr) return null\n return parseAttributeValue(colorsAttr)\n }\n\n /**\n * Establece los colores personalizados\n */\n set colors(value: FormColors | null) {\n if (value) {\n this.setAttribute('colors', attributeValue(value))\n } else {\n this.removeAttribute('colors')\n }\n }\n\n /**\n * Obtiene los datos iniciales\n */\n get initialData(): Record<string, any> | null {\n const initialDataAttr = this.getAttribute('initialData')\n if (!initialDataAttr) return null\n return parseAttributeValue(initialDataAttr)\n }\n\n /**\n * Establece los datos iniciales\n */\n set initialData(value: Record<string, any> | null) {\n if (value) {\n this.setAttribute('initialData', attributeValue(value))\n } else {\n this.removeAttribute('initialData')\n }\n }\n\n /**\n * Obtiene el estado de loading\n */\n get loading(): boolean {\n return this.hasAttribute('loading')\n }\n\n /**\n * Establece el estado de loading\n */\n set loading(value: boolean) {\n if (value) {\n this.setAttribute('loading', '')\n } else {\n this.removeAttribute('loading')\n }\n }\n\n /**\n * Obtiene el estado de disabled\n */\n get disabled(): boolean {\n return this.hasAttribute('disabled')\n }\n\n /**\n * Establece el estado de disabled\n */\n set disabled(value: boolean) {\n if (value) {\n this.setAttribute('disabled', '')\n } else {\n this.removeAttribute('disabled')\n }\n }\n\n /**\n * Configura estilos básicos\n */\n private setupStyles() {\n // Eliminar estilos anteriores si existen\n const existingStyle = this.shadow.querySelector('style')\n if (existingStyle) {\n existingStyle.remove()\n }\n\n const theme = this.theme\n const colors = getColors(this.colors || undefined)\n const styles = getThemeStyles(theme, colors)\n\n const style = document.createElement('style')\n style.textContent = styles\n \n // Insertar estilos ANTES de cualquier otro contenido para asegurar que se apliquen\n if (this.shadow.firstChild) {\n this.shadow.insertBefore(style, this.shadow.firstChild)\n } else {\n this.shadow.appendChild(style)\n }\n }\n}\n\n// Registrar el Web Component solo en el navegador\nif (typeof window !== 'undefined' && typeof customElements !== 'undefined' && !customElements.get('easy-form')) {\n customElements.define('easy-form', EasyForm)\n}\n"],"mappings":"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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAm4BpD,CAKA,SAASM,GAAuBJ,EAAkBF,EAAsC,CACtF,OAAQE,EAAO,CACb,IAAK,QACH,OAAOK,GAAeP,CAAM,EAC9B,IAAK,cACH,OAAOQ,GAAqBR,CAAM,EACpC,IAAK,WACH,OAAOS,GAAkBT,CAAM,EACjC,IAAK,iBACH,OAAOU,GAAuBV,CAAM,EACtC,IAAK,QACH,OAAOW,GAAeX,CAAM,EAC9B,IAAK,SACH,OAAOY,GAAgBZ,CAAM,EAC/B,IAAK,SACH,OAAOa,GAAgBb,CAAM,EAC/B,IAAK,UACH,OAAOc,GAAiBd,CAAM,EAChC,IAAK,QACH,OAAOe,GAAef,CAAM,EAC9B,IAAK,WACH,OAAOgB,GAAkBhB,CAAM,EACjC,IAAK,UACH,OAAOiB,GAAiBjB,CAAM,EAChC,IAAK,MACH,OAAOkB,GAAalB,CAAM,EAC5B,QACE,OAAOO,GAAeP,CAAM,CAChC,CACF,CAKA,SAASO,GAAeY,EAAuC,CAC7D,MAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAkCT,CAKA,SAASX,GAAqBW,EAAuC,CACnE,MAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAoCT,CAKA,SAASV,GAAkBU,EAAuC,CAChE,MAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAsFT,CAKA,SAAST,GAAuBS,EAAuC,CACrE,MAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAqDT,CAKA,SAASR,GAAeQ,EAAuC,CAC7D,MAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAiHT,CAKA,SAASP,GAAgBO,EAAuC,CAC9D,MAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAsIT,CAKA,SAASN,GAAgBM,EAAuC,CAC9D,MAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAiGT,CAKA,SAASL,GAAiBK,EAAuC,CAC/D,MAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GA8ET,CAKA,SAASJ,GAAeI,EAAuC,CAC7D,MAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GA6JT,CAKA,SAASH,GAAkBG,EAAuC,CAChE,MAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAsFT,CAKA,SAASF,GAAiBE,EAAuC,CAC/D,MAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GA0MT,CAMA,SAASD,GAAaC,EAAuC,CAC3D,MAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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","names":["SchemaParser","schema","step","normalizedFields","normalizedSteps","fields","field","index","min","max","slot","fieldName","slotName","defaults","parsed","allFields","extractFields","hexToRgb","hex","result","short","defaultColors","getColors","colors","getThemeStyles","theme","baseStyles","getBaseStyles","themeStyles","getThemeSpecificStyles","getPlanoStyles","getTradicionalStyles","getMaterialStyles","getRoundedShadowStyles","getLinesStyles","getShadcnStyles","getChakraStyles","getMantineStyles","getGlassStyles","getBorderedStyles","getMinimalStyles","getEfcStyles","_colors","PREDEFINED_MASKS","value","cleaned","getPredefinedMask","type","INJECTION_VALIDATION_MESSAGE","INJECTION_PATTERNS","containsInjection","value","pattern","isSafeFromInjection","item","v","AttemptsLock","options","stored","data","attributeValue","value","parseAttributeValue","getNestedValue","obj","path","current","key","setNestedValue","value","keys","lastKey","target","isValidEmail","email","ValidationEngine","field","value","_field","validations","errors","validation","result","isValid","isValidEmail","minLength","maxLength","min","num","max","pattern","regex","isSafeFromInjection","INJECTION_VALIDATION_MESSAGE","values","showDep","action","dep","depValue","isConditionMet","fields","fieldErrors","ConditionEngine","condition","formValues","fieldValue","conditions","logic","conditionsArray","dependencies","visible","enabled","required","shouldHide","shouldDisable","shouldBeOptional","fieldName","parts","value","part","operator","compareValue","a","b","val","index","keysA","keysB","key","parsed","StateManager","SchemaParser","ValidationEngine","ConditionEngine","schema","initialData","fields","allFields","field","topLevelNames","f","arrayItemNames","sub","fieldName","parentPath","currentPath","found","topLevelFields","step","observedFields","observedField","dependencies","extractFromCondition","condition","extractFromConditions","conditions","existingValues","values","key","value","setNestedValue","existingValue","getNestedValue","prevValue","arrayItemOnlyNames","arrayField","minItems","arr","padded","i","item","subField","name","itemFields","dependentFields","dependentField","activeValidations","errors","validations","textFieldTypes","skipInjection","v","isRequired","hasRequiredValidation","conditional","stepIndex","isSubmitting","cached","fieldFullPath","groupPath","valuesContext","groupValues","createRelativeContext","obj","prefix","result","relativeKey","relativeContext","hasRequired","BaseInput","field","value","error","onChange","onBlur","rawInput","leading","trailing","wrapper","slotEl","inputWrap","slot","container","img","input","componentContainerClasses","cls","labelPosition","inputToAppend","el","label","v","required","inner","description","errorEl","element","key","parseMaskPattern","pattern","tokens","i","char","formatValue","value","result","valueIndex","token","unformatValue","tokenIndex","nextToken","getNextEditablePosition","position","direction","getMaskPlaceholder","placeholder","calculateCursorPosition","oldValue","newValue","oldCursorPosition","editableBeforeOld","editableCount","MaskEngine","mask","getPredefinedMask","customMask","cacheKey","tokens","parseMaskPattern","value","editableTokens","t","acceptedTypes","unformatted","char","formatted","formatValue","unformatValue","getMaskPlaceholder","position","token","input","previousValue","cursorPosition","unformattedInput","newCursorPosition","calculateCursorPosition","key","currentValue","isBackspace","prevEditable","getNextEditablePosition","before","after","newValue","newPos","nextEditable","TextInput","BaseInput","field","value","error","onChange","onBlur","MaskEngine","input","displayValue","maskPlaceholder","e","target","cursorPosition","inputValue","result","valueToEmit","isBackspace","pastedText","before","after","newValue","NumberInput","BaseInput","field","value","error","onChange","onBlur","MaskEngine","input","displayValue","numberField","maskPlaceholder","e","target","cursorPosition","inputValue","result","numValue","unformatted","isBackspace","pastedText","before","after","newValue","TextareaInput","BaseInput","textarea","textareaField","e","target","SelectInput","BaseInput","select","selectField","placeholderOption","option","optionEl","updatePlaceholderClass","e","target","selectedValues","opt","CheckboxInput","BaseInput","checkbox","e","target","container","label","labelText","description","errorEl","RadioInput","BaseInput","container","label","v","required","radioGroup","radioField","option","optionValue","optionLabel","radioContainer","radio","description","errorEl","SwitchInput","BaseInput","switchEl","e","target","container","label","labelText","description","errorEl","DateInput","BaseInput","input","dateField","date","e","target","FileInput","BaseInput","input","fileField","e","target","QuantityInput","BaseInput","container","quantityField","min","max","step","currentValue","inputWrapper","decrementBtn","input","incrementBtn","newValue","updateButtons","e","target","numValue","value","AccordionSelectInput","BaseInput","container","accordionField","selectedValue","option","index","optionValue","optionLabel","optionDescription","accordionItem","header","headerContent","indicator","label","arrow","content","description","customContent","toggleAccordion","isOpen","item","otherHeader","otherContent","otherArrow","selectOption","currentValues","itemIndicator","e","ImageGridSelectInput","BaseInput","container","imageGridField","selectedValue","columns","imageSize","option","optionValue","optionLabel","optionImage","optionDescription","gridItem","imageContainer","img","placeholder","indicator","label","description","selectOption","currentValues","index","item","itemIndicator","e","OTPInput","BaseInput","container","length","value","valueString","input","currentIndex","e","target","inputValue","digits","j","nextEmptyIndex","otpValue","otpField","finalValue","DEFAULT_SEPARATED_LENGTH","eyeSvg","visible","PasswordInput","BaseInput","pf","useSeparated","length","showToggle","input","e","wrapper","btn","value","valueString","container","i","currentIndex","chars","j","nextIdx","toggleWrap","type","inp","FileDropInput","BaseInput","fileDropField","accept","multiple","dropZone","hiddenInput","label","fileList","renderFileList","files","names","f","name","item","handleFiles","arr","e","target","LEAFLET_CSS","MapInput","BaseInput","mapField","center","zoom","value","lat","lng","container","inputsWrapper","latInput","lngInput","updateFromInputs","latVal","lngVal","mapContainer","linkId","cssLoaded","link","resolve","checkReady","L","tileLayer","invalidateSize","entries","entry","pos","e","newLat","newLng","STAR_SVG","filled","RatingInput","BaseInput","ratingField","max","half","currentValue","container","starsContainer","starWrapper","e","rect","val","mid","cur","newVal","value","star","idx","SliderInput","BaseInput","sliderField","min","max","step","showValue","input","e","target","val","valueSpan","wrapper","HEX_REGEX","toHex","value","m","ColorInput","BaseInput","defaultValue","currentValue","wrapper","colorPicker","textInput","syncFromPicker","hex","syncFromText","raw","createInput","field","value","error","onChange","onBlur","TextInput","PasswordInput","NumberInput","TextareaInput","SelectInput","CheckboxInput","RadioInput","SwitchInput","DateInput","FileInput","FileDropInput","MapInput","RatingInput","SliderInput","ColorInput","QuantityInput","AccordionSelectInput","ImageGridSelectInput","OTPInput","div","customComponents","registerComponent","type","component","registerComponents","components","getCustomComponent","loginTemplate","registerTemplate","value","otpTemplate","contactTemplate","passwordResetTemplate","passwordChangeTemplate","profileTemplate","checkoutTemplate","feedbackTemplate","subscriptionTemplate","bookingTemplate","reviewTemplate","templates","getTemplate","templateName","extendTemplate","templateName","additionalFields","baseTemplate","getTemplate","existingFields","existingSteps","lastStep","BrowserHTMLElement","EasyForm","StateManager","schemaAttr","parseAttributeValue","value","attributeValue","templateAttr","extendAttr","attr","n","schema","fromAttr","merged","name","oldValue","newValue","form","input","maxAttempts","AttemptsLock","templateName","initialData","baseTemplate","getTemplate","additionalFields","extendTemplate","isArrayRefresh","preservedValues","previousWizardState","key","wasWizard","isWizard","wizardState","completedStep","finalWizardState","newFormElement","e","directionAttr","direction","showCompletedAttr","completedIndicator","completedPosition","submitConfig","submitWrapper","submitButton","formWrapper","completed","total","progressBar","track","fill","oldForm","oldWrapper","formElement","existingOverlay","overlay","message","updateCountdown","remainingMs","minutes","seconds","timeStr","spinner","currentSchema","inputs","opt","elements","child","el","raw","parsed","row","totalRows","result","template","effectiveRow","clone","existing","slotElement","container","fields","endSlots","slotClonesByRow","rowIndex","slotsForRow","field","fieldElement","isVisible","isEnabled","groupElement","rowElement","arrayElement","customElement","errors","error","isFormDisabled","labelPositionAttr","validLabelPositions","effectiveLabelPosition","fieldWithDependencies","customComponent","getCustomComponent","element","val","inputElement","createInput","fieldContainer","groupField","dir","collapsible","defaultOpen","groupContainer","header","groupContentId","labelSpan","chevron","content","subField","fullName","subFieldWithPath","setContentHeight","open","label","rowContainer","rowField","gapValue","fieldWrapper","arrayContainer","values","arrayField","minItems","maxItems","itemsContainer","i","itemContainer","itemField","itemFieldWithName","removeButton","atMinItems","newValues","addButton","atMaxItems","newItem","div","extractFields","f","items","count","sf","visibleRequired","v","wizardContainer","stepsIndicator","stepEl","fieldsContainer","currentFields","navContainer","prevButton","nextButton","currentState","allErrors","stepErrors","fieldName","dependentFields","changeEvent","newArrayElement","fieldNames","newFieldElement","changedField","affectedFields","dependencyEvent","errorElement","errorEl","dot","parentName","childName","parent","found","event","state","submitEvent","errorEvent","stepChangeEvent","components","registerComponents","themeAttr","colorsAttr","initialDataAttr","existingStyle","theme","colors","getColors","styles","getThemeStyles","style"]}