easy-forms-core 1.1.5 → 1.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -0
- package/dist/easy-form.d.ts +44 -0
- package/dist/easy-form.js +175 -20
- package/dist/easy-form.js.map +1 -1
- package/dist/index.d.ts +45 -1
- package/dist/index.js +175 -20
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -108,6 +108,68 @@ form.schema = {
|
|
|
108
108
|
}
|
|
109
109
|
```
|
|
110
110
|
|
|
111
|
+
### Slots con inserción por fila (row)
|
|
112
|
+
|
|
113
|
+
Puedes insertar contenido HTML personalizado en posiciones concretas del formulario usando **hijos directos** del componente con el atributo `row`. El índice es 0-based (cada campo o fila del schema cuenta como una posición). Usa `row="-1"` para insertar al final, antes del botón de envío.
|
|
114
|
+
|
|
115
|
+
| Valor | Comportamiento |
|
|
116
|
+
|--------|-----------------|
|
|
117
|
+
| `row="0"` | Antes del primer campo |
|
|
118
|
+
| `row="1"` | Entre el primer y el segundo campo |
|
|
119
|
+
| `row="-1"` | Al final del formulario (antes del submit) |
|
|
120
|
+
| Sin `row` o valor inválido | Se trata como `-1` (al final) |
|
|
121
|
+
|
|
122
|
+
**HTML Vanilla**
|
|
123
|
+
|
|
124
|
+
```html
|
|
125
|
+
<easy-form id="form">
|
|
126
|
+
<div row="0">Mensaje al inicio</div>
|
|
127
|
+
<div row="2">Mensaje después del segundo campo</div>
|
|
128
|
+
<div row="-1">Mensaje al final</div>
|
|
129
|
+
</easy-form>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
```javascript
|
|
133
|
+
import 'easy-forms-core'
|
|
134
|
+
|
|
135
|
+
const form = document.querySelector('#form')
|
|
136
|
+
form.schema = {
|
|
137
|
+
fields: [
|
|
138
|
+
{ type: 'text', name: 'name', label: 'Nombre' },
|
|
139
|
+
{ type: 'email', name: 'email', label: 'Email' },
|
|
140
|
+
{ type: 'textarea', name: 'message', label: 'Mensaje' }
|
|
141
|
+
]
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
**React**
|
|
146
|
+
|
|
147
|
+
```tsx
|
|
148
|
+
import 'easy-forms-core'
|
|
149
|
+
|
|
150
|
+
function MyForm() {
|
|
151
|
+
return (
|
|
152
|
+
<easy-form schema={{ fields: [...] }}>
|
|
153
|
+
<div row="0">Contenido al inicio</div>
|
|
154
|
+
<div row="-1">Contenido al final</div>
|
|
155
|
+
</easy-form>
|
|
156
|
+
)
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
**Vue**
|
|
161
|
+
|
|
162
|
+
```vue
|
|
163
|
+
<template>
|
|
164
|
+
<easy-form :schema="schema">
|
|
165
|
+
<div row="0">Contenido al inicio</div>
|
|
166
|
+
<div row="-1">Contenido al final</div>
|
|
167
|
+
</easy-form>
|
|
168
|
+
</template>
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Los slots son solo visuales: los inputs dentro de un slot **no** forman parte del estado ni del envío del formulario. En formularios por pasos (wizard), el índice `row` es relativo al paso actual.
|
|
172
|
+
|
|
111
173
|
### React
|
|
112
174
|
|
|
113
175
|
```tsx
|
|
@@ -407,6 +469,7 @@ Puedes sobrescribir cualquier estilo usando las clases CSS del componente. Todas
|
|
|
407
469
|
- Formularios anidados
|
|
408
470
|
- Arrays dinámicos
|
|
409
471
|
- **Rows (filas horizontales)** - Agrupa campos en filas
|
|
472
|
+
- **Slots (row)** - Inserta contenido HTML en posiciones concretas del formulario
|
|
410
473
|
- **Datos iniciales** - Carga valores iniciales desde datos externos
|
|
411
474
|
- Componentes visuales personalizables
|
|
412
475
|
- Eventos de submit, change y error
|
package/dist/easy-form.d.ts
CHANGED
|
@@ -307,6 +307,19 @@ interface FormColors {
|
|
|
307
307
|
* Template names available
|
|
308
308
|
*/
|
|
309
309
|
type TemplateName = 'login' | 'register' | 'otp' | 'contact' | 'password-reset' | 'password-change' | 'profile' | 'checkout' | 'feedback' | 'subscription' | 'booking' | 'review';
|
|
310
|
+
/**
|
|
311
|
+
* Configuración del botón de submit
|
|
312
|
+
*/
|
|
313
|
+
interface SubmitButtonConfig {
|
|
314
|
+
/** Si false, no se muestra el botón (submit programático) */
|
|
315
|
+
visible?: boolean;
|
|
316
|
+
/** Texto del botón (default: "Enviar") */
|
|
317
|
+
text?: string;
|
|
318
|
+
/** Ancho del botón: "auto", "100%", "200px", etc. (default: "auto") */
|
|
319
|
+
width?: string;
|
|
320
|
+
/** Alineación: "left" | "center" | "right" (default: "left") */
|
|
321
|
+
align?: 'left' | 'center' | 'right';
|
|
322
|
+
}
|
|
310
323
|
/**
|
|
311
324
|
* Schema del formulario
|
|
312
325
|
*/
|
|
@@ -314,6 +327,8 @@ interface FormSchema {
|
|
|
314
327
|
fields?: Field[];
|
|
315
328
|
steps?: Step[];
|
|
316
329
|
initialData?: Record<string, any>;
|
|
330
|
+
/** Configuración del botón de submit (también puede definirse vía atributo submit-button) */
|
|
331
|
+
submitButton?: SubmitButtonConfig;
|
|
317
332
|
}
|
|
318
333
|
/**
|
|
319
334
|
* Componente personalizado para inyección
|
|
@@ -346,6 +361,11 @@ declare class EasyForm extends BrowserHTMLElement {
|
|
|
346
361
|
private isRendering;
|
|
347
362
|
private attemptsLock;
|
|
348
363
|
private lockCountdownInterval;
|
|
364
|
+
/**
|
|
365
|
+
* Plantillas de slots basados en atributo `row` en el light DOM.
|
|
366
|
+
* Se inicializan una sola vez y se clonan en cada render.
|
|
367
|
+
*/
|
|
368
|
+
private slotTemplates;
|
|
349
369
|
static get observedAttributes(): string[];
|
|
350
370
|
constructor();
|
|
351
371
|
/**
|
|
@@ -387,6 +407,15 @@ declare class EasyForm extends BrowserHTMLElement {
|
|
|
387
407
|
*/
|
|
388
408
|
get attemptsStorageKey(): string | null;
|
|
389
409
|
set attemptsStorageKey(value: string | null);
|
|
410
|
+
/**
|
|
411
|
+
* Configuración del botón de submit (desde atributo o schema)
|
|
412
|
+
*/
|
|
413
|
+
get submitButton(): SubmitButtonConfig | null;
|
|
414
|
+
set submitButton(value: SubmitButtonConfig | null);
|
|
415
|
+
/**
|
|
416
|
+
* Obtiene la configuración efectiva del botón submit (atributo > schema > defaults)
|
|
417
|
+
*/
|
|
418
|
+
private getSubmitButtonConfig;
|
|
390
419
|
/**
|
|
391
420
|
* Se llama cuando el componente se conecta al DOM
|
|
392
421
|
*/
|
|
@@ -425,6 +454,16 @@ declare class EasyForm extends BrowserHTMLElement {
|
|
|
425
454
|
* Retorna un objeto con los valores preservados
|
|
426
455
|
*/
|
|
427
456
|
private preserveCurrentValues;
|
|
457
|
+
/**
|
|
458
|
+
* Inicializa las plantillas de slots a partir del light DOM.
|
|
459
|
+
* 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).
|
|
460
|
+
*/
|
|
461
|
+
private initializeSlotTemplates;
|
|
462
|
+
/**
|
|
463
|
+
* Obtiene clones de slots agrupados por índice de fila efectivo.
|
|
464
|
+
* Cualquier valor inválido o fuera de rango se normaliza a -1 (final del formulario).
|
|
465
|
+
*/
|
|
466
|
+
private getSlotClonesByRow;
|
|
428
467
|
/**
|
|
429
468
|
* Renderiza campos normales
|
|
430
469
|
*/
|
|
@@ -515,6 +554,11 @@ declare class EasyForm extends BrowserHTMLElement {
|
|
|
515
554
|
* Retorna los milisegundos restantes del bloqueo, o 0 si no está bloqueado.
|
|
516
555
|
*/
|
|
517
556
|
getRemainingBlockTimeMs(): number;
|
|
557
|
+
/**
|
|
558
|
+
* Dispara el submit del formulario programáticamente.
|
|
559
|
+
* Útil cuando el botón submit está oculto (visible: false).
|
|
560
|
+
*/
|
|
561
|
+
requestSubmit(): void;
|
|
518
562
|
/**
|
|
519
563
|
* Limpia todos los valores del formulario
|
|
520
564
|
*/
|
package/dist/easy-form.js
CHANGED
|
@@ -265,6 +265,13 @@ function getBaseStyles(colors) {
|
|
|
265
265
|
.easy-form-submit:active {
|
|
266
266
|
transform: scale(0.98);
|
|
267
267
|
}
|
|
268
|
+
.easy-form-submit-wrapper {
|
|
269
|
+
margin-top: 1rem;
|
|
270
|
+
margin-bottom: 0.5rem;
|
|
271
|
+
}
|
|
272
|
+
.easy-form-submit-wrapper .easy-form-submit {
|
|
273
|
+
min-width: 100px;
|
|
274
|
+
}
|
|
268
275
|
input:not([type="checkbox"]):not([type="radio"]), textarea, select {
|
|
269
276
|
width: 100%;
|
|
270
277
|
padding: 0.5rem;
|
|
@@ -4756,6 +4763,11 @@ var EasyForm = class extends BrowserHTMLElement {
|
|
|
4756
4763
|
this.isRendering = false;
|
|
4757
4764
|
this.attemptsLock = null;
|
|
4758
4765
|
this.lockCountdownInterval = null;
|
|
4766
|
+
/**
|
|
4767
|
+
* Plantillas de slots basados en atributo `row` en el light DOM.
|
|
4768
|
+
* Se inicializan una sola vez y se clonan en cada render.
|
|
4769
|
+
*/
|
|
4770
|
+
this.slotTemplates = null;
|
|
4759
4771
|
this.dependencyRenderTimeout = null;
|
|
4760
4772
|
this.stateManager = new StateManager();
|
|
4761
4773
|
this.shadow = this.attachShadow({ mode: "open" });
|
|
@@ -4772,7 +4784,8 @@ var EasyForm = class extends BrowserHTMLElement {
|
|
|
4772
4784
|
"disabled",
|
|
4773
4785
|
"max-attempts",
|
|
4774
4786
|
"block-duration-minutes",
|
|
4775
|
-
"attempts-storage-key"
|
|
4787
|
+
"attempts-storage-key",
|
|
4788
|
+
"submit-button"
|
|
4776
4789
|
];
|
|
4777
4790
|
}
|
|
4778
4791
|
/**
|
|
@@ -4892,6 +4905,41 @@ var EasyForm = class extends BrowserHTMLElement {
|
|
|
4892
4905
|
this.removeAttribute("attempts-storage-key");
|
|
4893
4906
|
}
|
|
4894
4907
|
}
|
|
4908
|
+
/**
|
|
4909
|
+
* Configuración del botón de submit (desde atributo o schema)
|
|
4910
|
+
*/
|
|
4911
|
+
get submitButton() {
|
|
4912
|
+
const attr = this.getAttribute("submit-button");
|
|
4913
|
+
if (attr) {
|
|
4914
|
+
try {
|
|
4915
|
+
return parseAttributeValue(attr);
|
|
4916
|
+
} catch {
|
|
4917
|
+
return null;
|
|
4918
|
+
}
|
|
4919
|
+
}
|
|
4920
|
+
return null;
|
|
4921
|
+
}
|
|
4922
|
+
set submitButton(value) {
|
|
4923
|
+
if (value && typeof value === "object") {
|
|
4924
|
+
this.setAttribute("submit-button", attributeValue(value));
|
|
4925
|
+
} else {
|
|
4926
|
+
this.removeAttribute("submit-button");
|
|
4927
|
+
}
|
|
4928
|
+
}
|
|
4929
|
+
/**
|
|
4930
|
+
* Obtiene la configuración efectiva del botón submit (atributo > schema > defaults)
|
|
4931
|
+
*/
|
|
4932
|
+
getSubmitButtonConfig(schema) {
|
|
4933
|
+
const fromAttr = this.submitButton;
|
|
4934
|
+
const fromSchema = schema?.submitButton;
|
|
4935
|
+
const merged = { ...fromSchema, ...fromAttr };
|
|
4936
|
+
return {
|
|
4937
|
+
visible: merged.visible ?? true,
|
|
4938
|
+
text: merged.text ?? "Enviar",
|
|
4939
|
+
width: merged.width ?? "auto",
|
|
4940
|
+
align: merged.align ?? "left"
|
|
4941
|
+
};
|
|
4942
|
+
}
|
|
4895
4943
|
/**
|
|
4896
4944
|
* Se llama cuando el componente se conecta al DOM
|
|
4897
4945
|
*/
|
|
@@ -4947,6 +4995,9 @@ var EasyForm = class extends BrowserHTMLElement {
|
|
|
4947
4995
|
this.setupAttemptsLock();
|
|
4948
4996
|
this.updateLockOverlay();
|
|
4949
4997
|
}
|
|
4998
|
+
if (name === "submit-button" && newValue !== oldValue) {
|
|
4999
|
+
this.render();
|
|
5000
|
+
}
|
|
4950
5001
|
}
|
|
4951
5002
|
/**
|
|
4952
5003
|
* Configura el AttemptsLock según los atributos actuales
|
|
@@ -5060,17 +5111,25 @@ var EasyForm = class extends BrowserHTMLElement {
|
|
|
5060
5111
|
newFormElement.classList.add("easy-form-disabled");
|
|
5061
5112
|
}
|
|
5062
5113
|
if (finalWizardState) {
|
|
5063
|
-
this.renderWizard(newFormElement);
|
|
5114
|
+
this.renderWizard(newFormElement, schema);
|
|
5064
5115
|
} else {
|
|
5065
5116
|
this.renderFields(newFormElement, schema.fields || []);
|
|
5066
|
-
const
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
submitButton
|
|
5117
|
+
const submitConfig = this.getSubmitButtonConfig(schema);
|
|
5118
|
+
if (submitConfig.visible) {
|
|
5119
|
+
const submitWrapper = document.createElement("div");
|
|
5120
|
+
submitWrapper.className = "easy-form-submit-wrapper";
|
|
5121
|
+
submitWrapper.style.textAlign = submitConfig.align;
|
|
5122
|
+
const submitButton = document.createElement("button");
|
|
5123
|
+
submitButton.type = "submit";
|
|
5124
|
+
submitButton.textContent = submitConfig.text;
|
|
5125
|
+
submitButton.className = "easy-form-submit";
|
|
5126
|
+
submitButton.style.width = submitConfig.width;
|
|
5127
|
+
if (this.disabled || this.loading) {
|
|
5128
|
+
submitButton.disabled = true;
|
|
5129
|
+
}
|
|
5130
|
+
submitWrapper.appendChild(submitButton);
|
|
5131
|
+
newFormElement.appendChild(submitWrapper);
|
|
5072
5132
|
}
|
|
5073
|
-
newFormElement.appendChild(submitButton);
|
|
5074
5133
|
}
|
|
5075
5134
|
const oldForm = this.shadow.querySelector("form");
|
|
5076
5135
|
if (oldForm && oldForm.parentNode === this.shadow && oldForm !== newFormElement) {
|
|
@@ -5153,6 +5212,16 @@ var EasyForm = class extends BrowserHTMLElement {
|
|
|
5153
5212
|
* Retorna un objeto con los valores preservados
|
|
5154
5213
|
*/
|
|
5155
5214
|
preserveCurrentValues() {
|
|
5215
|
+
let currentSchema = null;
|
|
5216
|
+
const templateName = this.template;
|
|
5217
|
+
if (templateName) {
|
|
5218
|
+
currentSchema = this.getSchemaFromTemplate(templateName);
|
|
5219
|
+
} else {
|
|
5220
|
+
currentSchema = this.schema;
|
|
5221
|
+
}
|
|
5222
|
+
if (!currentSchema) {
|
|
5223
|
+
return {};
|
|
5224
|
+
}
|
|
5156
5225
|
const form = this.shadow.querySelector("form");
|
|
5157
5226
|
const preservedValues = {};
|
|
5158
5227
|
if (!form) return preservedValues;
|
|
@@ -5160,6 +5229,8 @@ var EasyForm = class extends BrowserHTMLElement {
|
|
|
5160
5229
|
for (const input of inputs) {
|
|
5161
5230
|
const name = input.getAttribute("name");
|
|
5162
5231
|
if (!name) continue;
|
|
5232
|
+
const belongsToSchema = this.findFieldInSchema(currentSchema, name) !== null;
|
|
5233
|
+
if (!belongsToSchema) continue;
|
|
5163
5234
|
let value;
|
|
5164
5235
|
if (input instanceof HTMLInputElement) {
|
|
5165
5236
|
if (input.type === "checkbox") {
|
|
@@ -5190,16 +5261,93 @@ var EasyForm = class extends BrowserHTMLElement {
|
|
|
5190
5261
|
}
|
|
5191
5262
|
return preservedValues;
|
|
5192
5263
|
}
|
|
5264
|
+
/**
|
|
5265
|
+
* Inicializa las plantillas de slots a partir del light DOM.
|
|
5266
|
+
* 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).
|
|
5267
|
+
*/
|
|
5268
|
+
initializeSlotTemplates() {
|
|
5269
|
+
if (this.slotTemplates !== null) return;
|
|
5270
|
+
const elements = [];
|
|
5271
|
+
for (const child of Array.from(this.children)) {
|
|
5272
|
+
if (child instanceof HTMLElement) {
|
|
5273
|
+
elements.push(child);
|
|
5274
|
+
}
|
|
5275
|
+
}
|
|
5276
|
+
if (elements.length === 0) {
|
|
5277
|
+
this.slotTemplates = [];
|
|
5278
|
+
return;
|
|
5279
|
+
}
|
|
5280
|
+
this.slotTemplates = elements.map((el) => {
|
|
5281
|
+
const raw = el.hasAttribute("row") ? el.getAttribute("row") : null;
|
|
5282
|
+
const parsed = raw != null && raw !== "" ? Number(raw) : NaN;
|
|
5283
|
+
const row = Number.isFinite(parsed) ? parsed : null;
|
|
5284
|
+
return {
|
|
5285
|
+
template: el.cloneNode(true),
|
|
5286
|
+
row
|
|
5287
|
+
};
|
|
5288
|
+
});
|
|
5289
|
+
}
|
|
5290
|
+
/**
|
|
5291
|
+
* Obtiene clones de slots agrupados por índice de fila efectivo.
|
|
5292
|
+
* Cualquier valor inválido o fuera de rango se normaliza a -1 (final del formulario).
|
|
5293
|
+
*/
|
|
5294
|
+
getSlotClonesByRow(totalRows) {
|
|
5295
|
+
this.initializeSlotTemplates();
|
|
5296
|
+
const result = /* @__PURE__ */ new Map();
|
|
5297
|
+
if (!this.slotTemplates || this.slotTemplates.length === 0) {
|
|
5298
|
+
return result;
|
|
5299
|
+
}
|
|
5300
|
+
for (const { template, row } of this.slotTemplates) {
|
|
5301
|
+
let effectiveRow = typeof row === "number" ? row : -1;
|
|
5302
|
+
if (!Number.isFinite(effectiveRow)) {
|
|
5303
|
+
effectiveRow = -1;
|
|
5304
|
+
}
|
|
5305
|
+
if (effectiveRow < 0 || effectiveRow >= totalRows) {
|
|
5306
|
+
effectiveRow = -1;
|
|
5307
|
+
}
|
|
5308
|
+
const clone = template.cloneNode(true);
|
|
5309
|
+
const existing = result.get(effectiveRow) ?? [];
|
|
5310
|
+
existing.push(clone);
|
|
5311
|
+
result.set(effectiveRow, existing);
|
|
5312
|
+
}
|
|
5313
|
+
return result;
|
|
5314
|
+
}
|
|
5193
5315
|
/**
|
|
5194
5316
|
* Renderiza campos normales
|
|
5195
5317
|
*/
|
|
5196
5318
|
renderFields(container, fields) {
|
|
5197
|
-
|
|
5319
|
+
if (fields.length === 0) {
|
|
5320
|
+
const slotClones = this.getSlotClonesByRow(0);
|
|
5321
|
+
const endSlots2 = slotClones.get(-1);
|
|
5322
|
+
if (endSlots2 && endSlots2.length > 0) {
|
|
5323
|
+
for (const slotElement of endSlots2) {
|
|
5324
|
+
container.appendChild(slotElement);
|
|
5325
|
+
}
|
|
5326
|
+
}
|
|
5327
|
+
return;
|
|
5328
|
+
}
|
|
5329
|
+
const totalRows = fields.length;
|
|
5330
|
+
const slotClonesByRow = this.getSlotClonesByRow(totalRows);
|
|
5331
|
+
for (let rowIndex = 0; rowIndex < fields.length; rowIndex++) {
|
|
5332
|
+
const slotsForRow = slotClonesByRow.get(rowIndex);
|
|
5333
|
+
if (slotsForRow && slotsForRow.length > 0) {
|
|
5334
|
+
for (const slotElement of slotsForRow) {
|
|
5335
|
+
container.appendChild(slotElement);
|
|
5336
|
+
}
|
|
5337
|
+
slotClonesByRow.delete(rowIndex);
|
|
5338
|
+
}
|
|
5339
|
+
const field = fields[rowIndex];
|
|
5198
5340
|
const fieldElement = this.renderField(field);
|
|
5199
5341
|
if (fieldElement) {
|
|
5200
5342
|
container.appendChild(fieldElement);
|
|
5201
5343
|
}
|
|
5202
5344
|
}
|
|
5345
|
+
const endSlots = slotClonesByRow.get(-1);
|
|
5346
|
+
if (endSlots && endSlots.length > 0) {
|
|
5347
|
+
for (const slotElement of endSlots) {
|
|
5348
|
+
container.appendChild(slotElement);
|
|
5349
|
+
}
|
|
5350
|
+
}
|
|
5203
5351
|
}
|
|
5204
5352
|
/**
|
|
5205
5353
|
* Renderiza un campo
|
|
@@ -5432,14 +5580,13 @@ var EasyForm = class extends BrowserHTMLElement {
|
|
|
5432
5580
|
/**
|
|
5433
5581
|
* Renderiza wizard
|
|
5434
5582
|
*/
|
|
5435
|
-
renderWizard(container) {
|
|
5583
|
+
renderWizard(container, schema) {
|
|
5436
5584
|
const wizardState = this.stateManager.getWizardState();
|
|
5437
5585
|
if (!wizardState) return;
|
|
5438
5586
|
const wizardContainer = document.createElement("div");
|
|
5439
5587
|
wizardContainer.className = "easy-form-wizard";
|
|
5440
5588
|
const stepsIndicator = document.createElement("div");
|
|
5441
5589
|
stepsIndicator.className = "easy-form-wizard-steps";
|
|
5442
|
-
const schema = this.schema;
|
|
5443
5590
|
if (schema?.steps) {
|
|
5444
5591
|
for (let i = 0; i < schema.steps.length; i++) {
|
|
5445
5592
|
const stepEl = document.createElement("div");
|
|
@@ -5458,12 +5605,7 @@ var EasyForm = class extends BrowserHTMLElement {
|
|
|
5458
5605
|
const fieldsContainer = document.createElement("div");
|
|
5459
5606
|
fieldsContainer.className = "easy-form-wizard-fields";
|
|
5460
5607
|
const currentFields = this.stateManager.getCurrentStepFields();
|
|
5461
|
-
|
|
5462
|
-
const fieldElement = this.renderField(field);
|
|
5463
|
-
if (fieldElement) {
|
|
5464
|
-
fieldsContainer.appendChild(fieldElement);
|
|
5465
|
-
}
|
|
5466
|
-
}
|
|
5608
|
+
this.renderFields(fieldsContainer, currentFields);
|
|
5467
5609
|
wizardContainer.appendChild(fieldsContainer);
|
|
5468
5610
|
const navContainer = document.createElement("div");
|
|
5469
5611
|
navContainer.className = "easy-form-wizard-nav";
|
|
@@ -5524,11 +5666,13 @@ var EasyForm = class extends BrowserHTMLElement {
|
|
|
5524
5666
|
}
|
|
5525
5667
|
navContainer.appendChild(nextButton);
|
|
5526
5668
|
}
|
|
5527
|
-
|
|
5669
|
+
const submitConfig = this.getSubmitButtonConfig(schema);
|
|
5670
|
+
if (wizardState.currentStep === wizardState.totalSteps - 1 && submitConfig.visible) {
|
|
5528
5671
|
const submitButton = document.createElement("button");
|
|
5529
5672
|
submitButton.type = "button";
|
|
5530
|
-
submitButton.textContent =
|
|
5673
|
+
submitButton.textContent = submitConfig.text;
|
|
5531
5674
|
submitButton.className = "easy-form-wizard-next";
|
|
5675
|
+
submitButton.style.width = submitConfig.width;
|
|
5532
5676
|
if (this.disabled || this.loading) {
|
|
5533
5677
|
submitButton.disabled = true;
|
|
5534
5678
|
} else {
|
|
@@ -5783,6 +5927,17 @@ var EasyForm = class extends BrowserHTMLElement {
|
|
|
5783
5927
|
getRemainingBlockTimeMs() {
|
|
5784
5928
|
return this.attemptsLock?.getRemainingBlockTimeMs() ?? 0;
|
|
5785
5929
|
}
|
|
5930
|
+
/**
|
|
5931
|
+
* Dispara el submit del formulario programáticamente.
|
|
5932
|
+
* Útil cuando el botón submit está oculto (visible: false).
|
|
5933
|
+
*/
|
|
5934
|
+
requestSubmit() {
|
|
5935
|
+
const form = this.shadow.querySelector("form");
|
|
5936
|
+
if (form && typeof form.requestSubmit === "function") {
|
|
5937
|
+
;
|
|
5938
|
+
form.requestSubmit();
|
|
5939
|
+
}
|
|
5940
|
+
}
|
|
5786
5941
|
/**
|
|
5787
5942
|
* Limpia todos los valores del formulario
|
|
5788
5943
|
*/
|