easy-forms-core 1.0.11 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/easy-form.js +235 -49
- package/dist/easy-form.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +235 -49
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
package/dist/easy-form.js
CHANGED
|
@@ -382,7 +382,41 @@ function getBaseStyles(colors) {
|
|
|
382
382
|
.easy-form-wizard-nav {
|
|
383
383
|
display: flex;
|
|
384
384
|
gap: 1rem;
|
|
385
|
-
margin-top:
|
|
385
|
+
margin-top: 2rem;
|
|
386
|
+
justify-content: flex-end;
|
|
387
|
+
align-items: center;
|
|
388
|
+
}
|
|
389
|
+
.easy-form-wizard-prev,
|
|
390
|
+
.easy-form-wizard-next {
|
|
391
|
+
padding: 0.75rem 1.5rem;
|
|
392
|
+
background: var(--easy-form-primary);
|
|
393
|
+
color: white;
|
|
394
|
+
border: none;
|
|
395
|
+
border-radius: 4px;
|
|
396
|
+
font-size: 1rem;
|
|
397
|
+
font-weight: 600;
|
|
398
|
+
cursor: pointer;
|
|
399
|
+
transition: all 0.2s ease;
|
|
400
|
+
font-family: inherit;
|
|
401
|
+
min-width: 120px;
|
|
402
|
+
}
|
|
403
|
+
.easy-form-wizard-prev:hover:not(:disabled),
|
|
404
|
+
.easy-form-wizard-next:hover:not(:disabled) {
|
|
405
|
+
opacity: 0.9;
|
|
406
|
+
transform: translateY(-1px);
|
|
407
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
408
|
+
}
|
|
409
|
+
.easy-form-wizard-prev:disabled {
|
|
410
|
+
opacity: 0.5;
|
|
411
|
+
cursor: not-allowed;
|
|
412
|
+
}
|
|
413
|
+
.easy-form-wizard-prev {
|
|
414
|
+
background: var(--easy-form-secondary);
|
|
415
|
+
order: 1;
|
|
416
|
+
}
|
|
417
|
+
.easy-form-wizard-next {
|
|
418
|
+
background: var(--easy-form-primary);
|
|
419
|
+
order: 2;
|
|
386
420
|
}
|
|
387
421
|
.easy-form-array-item {
|
|
388
422
|
padding: 1rem;
|
|
@@ -1731,7 +1765,20 @@ var ValidationEngine = class {
|
|
|
1731
1765
|
if (!value) {
|
|
1732
1766
|
return { isValid: true };
|
|
1733
1767
|
}
|
|
1734
|
-
|
|
1768
|
+
let regex;
|
|
1769
|
+
if (pattern instanceof RegExp) {
|
|
1770
|
+
regex = pattern;
|
|
1771
|
+
} else if (typeof pattern === "string") {
|
|
1772
|
+
try {
|
|
1773
|
+
regex = new RegExp(pattern);
|
|
1774
|
+
} catch (e) {
|
|
1775
|
+
console.warn("Invalid regex pattern:", pattern);
|
|
1776
|
+
return { isValid: true };
|
|
1777
|
+
}
|
|
1778
|
+
} else {
|
|
1779
|
+
console.warn("Pattern validation expects string or RegExp, got:", typeof pattern, pattern);
|
|
1780
|
+
return { isValid: true };
|
|
1781
|
+
}
|
|
1735
1782
|
const isValid = regex.test(String(value));
|
|
1736
1783
|
return {
|
|
1737
1784
|
isValid,
|
|
@@ -2019,6 +2066,26 @@ var StateManager = class {
|
|
|
2019
2066
|
}
|
|
2020
2067
|
return allFields;
|
|
2021
2068
|
}
|
|
2069
|
+
/**
|
|
2070
|
+
* Encuentra el path completo de un campo dentro de grupos
|
|
2071
|
+
*/
|
|
2072
|
+
findFieldPath(fieldName, fields, parentPath = "") {
|
|
2073
|
+
for (const field of fields) {
|
|
2074
|
+
const currentPath = parentPath ? `${parentPath}.${field.name}` : field.name;
|
|
2075
|
+
if (field.name === fieldName) {
|
|
2076
|
+
return currentPath;
|
|
2077
|
+
}
|
|
2078
|
+
if (field.type === "group" && "fields" in field) {
|
|
2079
|
+
const found = this.findFieldPath(fieldName, field.fields, currentPath);
|
|
2080
|
+
if (found) return found;
|
|
2081
|
+
}
|
|
2082
|
+
if (field.type === "row" && "fields" in field) {
|
|
2083
|
+
const found = this.findFieldPath(fieldName, field.fields, currentPath);
|
|
2084
|
+
if (found) return found;
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
return null;
|
|
2088
|
+
}
|
|
2022
2089
|
/**
|
|
2023
2090
|
* Construye el mapa de dependencias para optimizar re-evaluaciones
|
|
2024
2091
|
*/
|
|
@@ -2201,6 +2268,7 @@ var StateManager = class {
|
|
|
2201
2268
|
*/
|
|
2202
2269
|
setValueWithoutValidation(fieldName, value) {
|
|
2203
2270
|
setNestedValue(this.state.values, fieldName, value);
|
|
2271
|
+
this.invalidateDependencyCache(fieldName);
|
|
2204
2272
|
}
|
|
2205
2273
|
/**
|
|
2206
2274
|
* Valida un campo específico
|
|
@@ -2233,6 +2301,13 @@ var StateManager = class {
|
|
|
2233
2301
|
*/
|
|
2234
2302
|
getActiveValidations(field) {
|
|
2235
2303
|
let validations = [...field.validations || []];
|
|
2304
|
+
const isRequired = this.getFieldRequired(field.name);
|
|
2305
|
+
const hasRequiredValidation = validations.some((v) => v.type === "required");
|
|
2306
|
+
if (isRequired && !hasRequiredValidation) {
|
|
2307
|
+
validations = [{ type: "required" }, ...validations];
|
|
2308
|
+
} else if (!isRequired && hasRequiredValidation) {
|
|
2309
|
+
validations = validations.filter((v) => v.type !== "required");
|
|
2310
|
+
}
|
|
2236
2311
|
if (field.conditionalValidations) {
|
|
2237
2312
|
for (const conditional of field.conditionalValidations) {
|
|
2238
2313
|
const conditionMet = this.conditionEngine.evaluateConditions(
|
|
@@ -2365,13 +2440,41 @@ var StateManager = class {
|
|
|
2365
2440
|
if (!this.schema) return true;
|
|
2366
2441
|
const topLevelFields = this.schema.isWizard ? this.schema.steps.flatMap((step) => step.fields) : this.schema.fields || [];
|
|
2367
2442
|
const allFields = this.extractAllFields(topLevelFields);
|
|
2368
|
-
|
|
2443
|
+
let field = allFields.find((f) => {
|
|
2444
|
+
const fullPath = this.findFieldPath(f.name, topLevelFields);
|
|
2445
|
+
return fullPath === fieldName || f.name === fieldName;
|
|
2446
|
+
});
|
|
2447
|
+
if (!field) {
|
|
2448
|
+
field = allFields.find((f) => f.name === fieldName);
|
|
2449
|
+
}
|
|
2369
2450
|
if (!field || !field.dependencies) {
|
|
2370
2451
|
return !field?.hidden;
|
|
2371
2452
|
}
|
|
2453
|
+
const fieldFullPath = this.findFieldPath(field.name, topLevelFields) || field.name;
|
|
2454
|
+
const groupPath = fieldFullPath.includes(".") ? fieldFullPath.split(".").slice(0, -1).join(".") : "";
|
|
2455
|
+
let valuesContext = { ...this.state.values };
|
|
2456
|
+
if (groupPath && field.dependencies) {
|
|
2457
|
+
const groupValues = getNestedValue(this.state.values, groupPath);
|
|
2458
|
+
if (groupValues && typeof groupValues === "object") {
|
|
2459
|
+
const createRelativeContext = (obj, prefix = "") => {
|
|
2460
|
+
const result2 = {};
|
|
2461
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
2462
|
+
const relativeKey = prefix ? `${prefix}.${key}` : key;
|
|
2463
|
+
if (value && typeof value === "object" && !Array.isArray(value) && value !== null) {
|
|
2464
|
+
Object.assign(result2, createRelativeContext(value, relativeKey));
|
|
2465
|
+
} else {
|
|
2466
|
+
result2[relativeKey] = value;
|
|
2467
|
+
}
|
|
2468
|
+
}
|
|
2469
|
+
return result2;
|
|
2470
|
+
};
|
|
2471
|
+
const relativeContext = createRelativeContext(groupValues);
|
|
2472
|
+
valuesContext = { ...this.state.values, ...relativeContext };
|
|
2473
|
+
}
|
|
2474
|
+
}
|
|
2372
2475
|
const result = this.conditionEngine.evaluateDependencies(
|
|
2373
2476
|
field.dependencies,
|
|
2374
|
-
|
|
2477
|
+
valuesContext
|
|
2375
2478
|
);
|
|
2376
2479
|
this.dependencyCache.set(fieldName, result);
|
|
2377
2480
|
return result.visible && !field.hidden;
|
|
@@ -2446,7 +2549,15 @@ var BaseInput = class {
|
|
|
2446
2549
|
*/
|
|
2447
2550
|
createFieldContainer(input) {
|
|
2448
2551
|
const container = document.createElement("div");
|
|
2449
|
-
|
|
2552
|
+
const inputClasses = Array.from(input.classList);
|
|
2553
|
+
const componentContainerClasses = inputClasses.filter(
|
|
2554
|
+
(cls) => cls.startsWith("easy-form-") && cls !== "easy-form-field" && (cls.includes("-container") || cls.includes("-wrapper"))
|
|
2555
|
+
);
|
|
2556
|
+
if (componentContainerClasses.length > 0) {
|
|
2557
|
+
container.className = `easy-form-field ${componentContainerClasses.join(" ")}`;
|
|
2558
|
+
} else {
|
|
2559
|
+
container.className = "easy-form-field";
|
|
2560
|
+
}
|
|
2450
2561
|
if (this.field.label) {
|
|
2451
2562
|
const label = document.createElement("label");
|
|
2452
2563
|
label.className = "easy-form-label";
|
|
@@ -2693,7 +2804,18 @@ var MaskEngine = class {
|
|
|
2693
2804
|
return value;
|
|
2694
2805
|
}
|
|
2695
2806
|
const customMask = this.getCustomMask(mask);
|
|
2696
|
-
const
|
|
2807
|
+
const editableTokens = tokens.filter((t) => t.editable);
|
|
2808
|
+
const acceptedTypes = new Set(editableTokens.map((t) => t.type));
|
|
2809
|
+
let unformatted = "";
|
|
2810
|
+
for (const char of value) {
|
|
2811
|
+
if (acceptedTypes.has("any")) {
|
|
2812
|
+
unformatted += char;
|
|
2813
|
+
} else if (acceptedTypes.has("digit") && /\d/.test(char)) {
|
|
2814
|
+
unformatted += char;
|
|
2815
|
+
} else if (acceptedTypes.has("letter") && /[a-zA-Z]/.test(char)) {
|
|
2816
|
+
unformatted += char;
|
|
2817
|
+
}
|
|
2818
|
+
}
|
|
2697
2819
|
let formatted = formatValue(unformatted, tokens);
|
|
2698
2820
|
if (customMask.transform) {
|
|
2699
2821
|
formatted = customMask.transform(formatted);
|
|
@@ -2828,7 +2950,9 @@ var TextInput = class extends BaseInput {
|
|
|
2828
2950
|
}
|
|
2829
2951
|
input.value = displayValue;
|
|
2830
2952
|
this.applyCommonProps(input);
|
|
2831
|
-
if (this.
|
|
2953
|
+
if (this.field.placeholder) {
|
|
2954
|
+
input.placeholder = this.field.placeholder;
|
|
2955
|
+
} else if (this.maskEngine && this.field.mask) {
|
|
2832
2956
|
const maskPlaceholder = this.maskEngine.getMaskPlaceholder(this.field.mask);
|
|
2833
2957
|
if (maskPlaceholder) {
|
|
2834
2958
|
input.placeholder = maskPlaceholder;
|
|
@@ -2940,7 +3064,6 @@ var NumberInput = class extends BaseInput {
|
|
|
2940
3064
|
input.type = "number";
|
|
2941
3065
|
input.value = this.value ?? "";
|
|
2942
3066
|
}
|
|
2943
|
-
input.placeholder = this.field.placeholder || "";
|
|
2944
3067
|
const numberField = this.field;
|
|
2945
3068
|
if (!this.maskEngine && input.type === "number") {
|
|
2946
3069
|
if (numberField.min !== void 0) {
|
|
@@ -2954,7 +3077,9 @@ var NumberInput = class extends BaseInput {
|
|
|
2954
3077
|
}
|
|
2955
3078
|
}
|
|
2956
3079
|
this.applyCommonProps(input);
|
|
2957
|
-
if (this.
|
|
3080
|
+
if (this.field.placeholder) {
|
|
3081
|
+
input.placeholder = this.field.placeholder;
|
|
3082
|
+
} else if (this.maskEngine && this.field.mask) {
|
|
2958
3083
|
const maskPlaceholder = this.maskEngine.getMaskPlaceholder(this.field.mask);
|
|
2959
3084
|
if (maskPlaceholder) {
|
|
2960
3085
|
input.placeholder = maskPlaceholder;
|
|
@@ -4524,26 +4649,45 @@ var EasyForm = class extends BrowserHTMLElement {
|
|
|
4524
4649
|
return;
|
|
4525
4650
|
}
|
|
4526
4651
|
const preservedValues = this.preserveCurrentValues();
|
|
4652
|
+
const previousWizardState = this.stateManager.getWizardState();
|
|
4527
4653
|
if (preservedValues && Object.keys(preservedValues).length > 0) {
|
|
4528
4654
|
for (const [key, value] of Object.entries(preservedValues)) {
|
|
4529
4655
|
this.stateManager.setValueWithoutValidation(key, value);
|
|
4530
4656
|
}
|
|
4531
4657
|
}
|
|
4532
4658
|
const initialData = this.initialData;
|
|
4533
|
-
|
|
4534
|
-
const
|
|
4659
|
+
const wasWizard = previousWizardState !== null;
|
|
4660
|
+
const isWizard = schema.steps && schema.steps.length > 0;
|
|
4661
|
+
const shouldReinitialize = !previousWizardState || !wasWizard || !isWizard || previousWizardState && schema.steps && previousWizardState.totalSteps !== schema.steps.length;
|
|
4662
|
+
if (shouldReinitialize) {
|
|
4663
|
+
this.stateManager.initializeSchema(schema, initialData || void 0);
|
|
4664
|
+
if (wasWizard && isWizard && previousWizardState) {
|
|
4665
|
+
const wizardState = this.stateManager.getWizardState();
|
|
4666
|
+
if (wizardState && previousWizardState.totalSteps === wizardState.totalSteps) {
|
|
4667
|
+
if (previousWizardState.currentStep >= 0 && previousWizardState.currentStep < wizardState.totalSteps) {
|
|
4668
|
+
this.stateManager.goToStep(previousWizardState.currentStep);
|
|
4669
|
+
}
|
|
4670
|
+
for (const completedStep of previousWizardState.completedSteps) {
|
|
4671
|
+
if (completedStep >= 0 && completedStep < wizardState.totalSteps) {
|
|
4672
|
+
this.stateManager.completeStep(completedStep);
|
|
4673
|
+
}
|
|
4674
|
+
}
|
|
4675
|
+
}
|
|
4676
|
+
}
|
|
4677
|
+
}
|
|
4678
|
+
const finalWizardState = this.stateManager.getWizardState();
|
|
4535
4679
|
const newFormElement = document.createElement("form");
|
|
4536
4680
|
newFormElement.addEventListener("submit", (e) => this.handleSubmit(e));
|
|
4537
|
-
if (
|
|
4538
|
-
this.renderWizard(newFormElement
|
|
4681
|
+
if (finalWizardState) {
|
|
4682
|
+
this.renderWizard(newFormElement);
|
|
4539
4683
|
} else {
|
|
4540
4684
|
this.renderFields(newFormElement, schema.fields || []);
|
|
4685
|
+
const submitButton = document.createElement("button");
|
|
4686
|
+
submitButton.type = "submit";
|
|
4687
|
+
submitButton.textContent = "Enviar";
|
|
4688
|
+
submitButton.className = "easy-form-submit";
|
|
4689
|
+
newFormElement.appendChild(submitButton);
|
|
4541
4690
|
}
|
|
4542
|
-
const submitButton = document.createElement("button");
|
|
4543
|
-
submitButton.type = "submit";
|
|
4544
|
-
submitButton.textContent = "Enviar";
|
|
4545
|
-
submitButton.className = "easy-form-submit";
|
|
4546
|
-
newFormElement.appendChild(submitButton);
|
|
4547
4691
|
const oldForm = this.shadow.querySelector("form");
|
|
4548
4692
|
if (oldForm && oldForm.parentNode === this.shadow && oldForm !== newFormElement) {
|
|
4549
4693
|
try {
|
|
@@ -4832,7 +4976,9 @@ var EasyForm = class extends BrowserHTMLElement {
|
|
|
4832
4976
|
/**
|
|
4833
4977
|
* Renderiza wizard
|
|
4834
4978
|
*/
|
|
4835
|
-
renderWizard(container
|
|
4979
|
+
renderWizard(container) {
|
|
4980
|
+
const wizardState = this.stateManager.getWizardState();
|
|
4981
|
+
if (!wizardState) return;
|
|
4836
4982
|
const wizardContainer = document.createElement("div");
|
|
4837
4983
|
wizardContainer.className = "easy-form-wizard";
|
|
4838
4984
|
const stepsIndicator = document.createElement("div");
|
|
@@ -4865,43 +5011,83 @@ var EasyForm = class extends BrowserHTMLElement {
|
|
|
4865
5011
|
wizardContainer.appendChild(fieldsContainer);
|
|
4866
5012
|
const navContainer = document.createElement("div");
|
|
4867
5013
|
navContainer.className = "easy-form-wizard-nav";
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
this.
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
5014
|
+
if (wizardState.currentStep > 0) {
|
|
5015
|
+
const prevButton = document.createElement("button");
|
|
5016
|
+
prevButton.type = "button";
|
|
5017
|
+
prevButton.textContent = "Anterior";
|
|
5018
|
+
prevButton.className = "easy-form-wizard-prev";
|
|
5019
|
+
prevButton.addEventListener("click", () => {
|
|
5020
|
+
const currentState = this.stateManager.getWizardState();
|
|
5021
|
+
if (currentState && this.stateManager.previousStep()) {
|
|
5022
|
+
this.render();
|
|
5023
|
+
this.emitStepChange();
|
|
5024
|
+
}
|
|
5025
|
+
});
|
|
5026
|
+
navContainer.appendChild(prevButton);
|
|
5027
|
+
}
|
|
5028
|
+
if (wizardState.currentStep < wizardState.totalSteps - 1) {
|
|
5029
|
+
const nextButton = document.createElement("button");
|
|
5030
|
+
nextButton.type = "button";
|
|
5031
|
+
nextButton.textContent = "Siguiente";
|
|
5032
|
+
nextButton.className = "easy-form-wizard-next";
|
|
5033
|
+
nextButton.addEventListener("click", async () => {
|
|
5034
|
+
const currentState = this.stateManager.getWizardState();
|
|
5035
|
+
if (!currentState) return;
|
|
4888
5036
|
const currentFields2 = this.stateManager.getCurrentStepFields();
|
|
4889
|
-
const
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
|
|
5037
|
+
for (const field of currentFields2) {
|
|
5038
|
+
if (this.stateManager.getFieldVisibility(field.name)) {
|
|
5039
|
+
await this.stateManager.validateField(field.name);
|
|
5040
|
+
}
|
|
5041
|
+
}
|
|
5042
|
+
const allErrors = this.stateManager.getAllErrors();
|
|
5043
|
+
const stepErrors = {};
|
|
5044
|
+
for (const field of currentFields2) {
|
|
5045
|
+
if (allErrors[field.name] && allErrors[field.name].length > 0) {
|
|
5046
|
+
stepErrors[field.name] = allErrors[field.name];
|
|
5047
|
+
}
|
|
5048
|
+
}
|
|
5049
|
+
const hasErrors = Object.keys(stepErrors).length > 0;
|
|
4893
5050
|
if (!hasErrors) {
|
|
4894
|
-
this.stateManager.completeStep(
|
|
4895
|
-
|
|
5051
|
+
this.stateManager.completeStep(currentState.currentStep);
|
|
5052
|
+
const moved = this.stateManager.nextStep();
|
|
5053
|
+
if (moved) {
|
|
4896
5054
|
this.render();
|
|
4897
5055
|
this.emitStepChange();
|
|
4898
5056
|
}
|
|
4899
5057
|
} else {
|
|
4900
|
-
this.emitError(
|
|
5058
|
+
this.emitError(stepErrors);
|
|
4901
5059
|
}
|
|
4902
|
-
}
|
|
4903
|
-
|
|
4904
|
-
|
|
5060
|
+
});
|
|
5061
|
+
navContainer.appendChild(nextButton);
|
|
5062
|
+
}
|
|
5063
|
+
if (wizardState.currentStep === wizardState.totalSteps - 1) {
|
|
5064
|
+
const submitButton = document.createElement("button");
|
|
5065
|
+
submitButton.type = "button";
|
|
5066
|
+
submitButton.textContent = "Enviar";
|
|
5067
|
+
submitButton.className = "easy-form-wizard-next";
|
|
5068
|
+
submitButton.addEventListener("click", async () => {
|
|
5069
|
+
const currentFields2 = this.stateManager.getCurrentStepFields();
|
|
5070
|
+
for (const field of currentFields2) {
|
|
5071
|
+
if (this.stateManager.getFieldVisibility(field.name)) {
|
|
5072
|
+
await this.stateManager.validateField(field.name);
|
|
5073
|
+
}
|
|
5074
|
+
}
|
|
5075
|
+
const allErrors = this.stateManager.getAllErrors();
|
|
5076
|
+
const stepErrors = {};
|
|
5077
|
+
for (const field of currentFields2) {
|
|
5078
|
+
if (allErrors[field.name] && allErrors[field.name].length > 0) {
|
|
5079
|
+
stepErrors[field.name] = allErrors[field.name];
|
|
5080
|
+
}
|
|
5081
|
+
}
|
|
5082
|
+
const hasErrors = Object.keys(stepErrors).length > 0;
|
|
5083
|
+
if (!hasErrors) {
|
|
5084
|
+
await this.handleSubmit(new Event("submit"));
|
|
5085
|
+
} else {
|
|
5086
|
+
this.emitError(stepErrors);
|
|
5087
|
+
}
|
|
5088
|
+
});
|
|
5089
|
+
navContainer.appendChild(submitButton);
|
|
5090
|
+
}
|
|
4905
5091
|
wizardContainer.appendChild(navContainer);
|
|
4906
5092
|
container.appendChild(wizardContainer);
|
|
4907
5093
|
}
|