@solcre-org/core-ui 2.12.12 → 2.12.14

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.
@@ -450,10 +450,9 @@ class CheckboxFieldComponent extends BaseFieldComponent {
450
450
  this.formControl().setValue(option.value);
451
451
  }
452
452
  else if (currentValue === option.value) {
453
- if (this.isRequired()) {
454
- return;
453
+ if (!this.isRequired()) {
454
+ this.formControl().setValue(null);
455
455
  }
456
- this.formControl().setValue(null);
457
456
  }
458
457
  }
459
458
  }
@@ -467,17 +466,15 @@ class CheckboxFieldComponent extends BaseFieldComponent {
467
466
  }
468
467
  }
469
468
  cannotDeselect(option) {
469
+ if (!this.allowMultiple()) {
470
+ return false;
471
+ }
470
472
  if (!this.isRequired() || !this.isOptionSelected(option)) {
471
473
  return false;
472
474
  }
473
475
  const currentValue = this.formControl().value;
474
- if (this.allowMultiple()) {
475
- const selectedCount = Array.isArray(currentValue) ? currentValue.length : 0;
476
- return selectedCount <= 1;
477
- }
478
- else {
479
- return true;
480
- }
476
+ const selectedCount = Array.isArray(currentValue) ? currentValue.length : 0;
477
+ return selectedCount <= 1;
481
478
  }
482
479
  onValueChange(newValue) {
483
480
  super.onValueChange(newValue);
@@ -493,11 +490,11 @@ class CheckboxFieldComponent extends BaseFieldComponent {
493
490
  }
494
491
  }
495
492
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: CheckboxFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
496
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: CheckboxFieldComponent, isStandalone: true, selector: "core-checkbox-field", usesInheritance: true, hostDirectives: [{ directive: CoreHostDirective }], ngImport: i0, template: "<!-- Clase para layout inline cuando hay m\u00FAltiples opciones -->\n<div class=\"c-entry-toggle-holder\" [class.hasSeparatedOptions]=\"hasSeparatedOptions()\" [class.multiple-inline]=\"hasMultipleOptions()\">\n\n <span class=\"c-entry-text\"\n *ngIf=\"field().label\">\n {{ field().label | translate }}\n @if (hasRequiredValidators()) {\n <span class=\"c-required\">*</span>\n }\n </span>\n \n @if (hasMultipleOptions()) {\n @for (option of options(); track option.value) {\n\n <!-- ! Solcre: Este .c-entry-toggle deber\u00EDa ser un componente en s\u00ED mismo. -->\n <!-- ! Solcre: El cannot-deselect no est\u00E1 over-engineered. Deber\u00EDa ser un Radio. -->\n <label class=\"c-entry-toggle\"\n [class.is-invalid]=\"hasError()\"\n [class.is-disabled]=\"isDisabled()\"\n [class.cannot-deselect]=\"cannotDeselect(option)\">\n\n <!-- onBlurInput() maneja validaciones y marca el campo como touched para mostrar errores -->\n @if (cannotDeselect(option)) {\n <!-- Usar radio cuando no se puede deseleccionar -->\n <input\n type=\"radio\"\n [attr.id]=\"field().key.toString() + '_' + option.value\"\n [attr.name]=\"field().key.toString()\"\n [checked]=\"isOptionSelected(option)\"\n (change)=\"handleOptionChange(option, $event)\"\n (blur)=\"onBlurInput()\"\n />\n } @else {\n <!-- Usar checkbox normal cuando se puede deseleccionar -->\n <input\n type=\"checkbox\"\n [attr.id]=\"field().key.toString() + '_' + option.value\"\n [attr.name]=\"allowMultiple() ? field().key.toString() + '[]' : field().key.toString()\"\n [checked]=\"isOptionSelected(option)\"\n (change)=\"handleOptionChange(option, $event)\"\n (blur)=\"onBlurInput()\"\n />\n }\n <span class=\"c-entry-toggle__toggle\"></span>\n\n <span class=\"c-entry-toggle__text\">\n {{ option.label | translate }}\n @if(option.externalLink) {\n <!-- Link externo funcional implementado -->\n <a class=\"icon-external-link-thin\" [href]=\"option.externalLink\" target=\"_blank\"></a>\n }\n </span>\n @if(option.detail) {\n <!-- Texto de detalle funcional implementado -->\n <span class=\"c-form-checkbox__detail\">{{ option.detail }}</span>\n }\n </label>\n\n }\n } @else {\n <!-- ! Solcre: Este .c-entry-toggle deber\u00EDa ser un componente en s\u00ED mismo. -->\n <!-- ! Solcre: El cannot-deselect no est\u00E1 over-engineered. Deber\u00EDa ser un Radio. -->\n <label class=\"c-entry-toggle\"\n [class.is-invalid]=\"hasError()\"\n [class.is-disabled]=\"isDisabled()\"\n [class.cannot-deselect]=\"isRequired() && !!formControl().value\">\n\n <!-- onBlurInput() maneja validaciones y marca el campo como touched para mostrar errores -->\n @if (isRequired() && !!formControl().value) {\n <!-- Usar radio cuando es requerido y tiene valor (cannot-deselect) -->\n <input\n type=\"radio\"\n [attr.id]=\"field().key.toString()\"\n [attr.name]=\"field().key.toString()\"\n [checked]=\"!!formControl().value\"\n (change)=\"onRadioChange($event)\"\n (blur)=\"onBlurInput()\"\n />\n } @else {\n <!-- Usar checkbox normal cuando se puede deseleccionar -->\n <input\n type=\"checkbox\"\n [attr.id]=\"field().key.toString()\"\n [attr.name]=\"field().key.toString()\"\n [formControl]=\"formControl()\"\n (blur)=\"onBlurInput()\"\n />\n }\n <span class=\"c-entry-toggle__toggle\"></span>\n <span class=\"c-entry-toggle__text\">\n {{ field().label | translate }}\n @if(externalLink()) {\n <!-- Link externo funcional implementado -->\n <a class=\"icon-external-link-thin\" [href]=\"externalLink()\" target=\"_blank\"></a>\n }\n </span>\n @if(detail()) {\n <!-- Texto de detalle funcional implementado -->\n <span class=\"c-form-checkbox__detail\">{{ detail() }}</span>\n }\n </label>\n }\n\n <core-field-errors [errors]=\"errors()\" />\n</div> \n ", styles: [".cannot-deselect{pointer-events:none;cursor:not-allowed}.c-entry-text+.c-entry-toggle-holder.hasSeparatedOptions{margin-top:calc(var(--_entry-group-gap) * .8)}.c-entry-toggle-holder.hasSeparatedOptions{display:grid;grid-template-columns:1fr 1fr;gap:calc(var(--_entry-group-gap) * .8)}.c-entry-toggle-holder.hasSeparatedOptions .c-entry-text{grid-column:span 2;margin-top:1em}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i3$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "component", type: FieldErrorsComponent, selector: "core-field-errors", inputs: ["errors"] }] });
493
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: CheckboxFieldComponent, isStandalone: true, selector: "core-checkbox-field", usesInheritance: true, hostDirectives: [{ directive: CoreHostDirective }], ngImport: i0, template: "<!-- Clase para layout inline cuando hay m\u00FAltiples opciones -->\n<div class=\"c-entry-toggle-holder\" [class.hasSeparatedOptions]=\"hasSeparatedOptions()\" [class.multiple-inline]=\"hasMultipleOptions()\">\n\n <span class=\"c-entry-text\"\n *ngIf=\"field().label\">\n {{ field().label | translate }}\n @if (hasRequiredValidators()) {\n <span class=\"c-required\">*</span>\n }\n </span>\n \n @if (hasMultipleOptions()) {\n @for (option of options(); track option.value) {\n\n <!-- ! Solcre: Este .c-entry-toggle deber\u00EDa ser un componente en s\u00ED mismo. -->\n <!-- ! Solcre: El cannot-deselect no est\u00E1 over-engineered. Deber\u00EDa ser un Radio. -->\n <label class=\"c-entry-toggle\"\n [class.is-invalid]=\"hasError()\"\n [class.is-disabled]=\"isDisabled()\"\n [class.cannot-deselect]=\"cannotDeselect(option)\">\n\n <!-- onBlurInput() maneja validaciones y marca el campo como touched para mostrar errores -->\n @if (!allowMultiple() && isRequired()) {\n <!-- Cuando allowMultiple: false y required: true, usar radio buttons para todas las opciones -->\n <input\n type=\"radio\"\n [attr.id]=\"field().key.toString() + '_' + option.value\"\n [attr.name]=\"field().key.toString()\"\n [checked]=\"isOptionSelected(option)\"\n (change)=\"handleOptionChange(option, $event)\"\n (blur)=\"onBlurInput()\"\n />\n } @else if (cannotDeselect(option)) {\n <!-- Usar radio cuando no se puede deseleccionar (modo m\u00FAltiple con una sola opci\u00F3n) -->\n <input\n type=\"radio\"\n [attr.id]=\"field().key.toString() + '_' + option.value\"\n [attr.name]=\"field().key.toString()\"\n [checked]=\"isOptionSelected(option)\"\n (change)=\"handleOptionChange(option, $event)\"\n (blur)=\"onBlurInput()\"\n />\n } @else {\n <!-- Usar checkbox normal cuando se puede deseleccionar -->\n <input\n type=\"checkbox\"\n [attr.id]=\"field().key.toString() + '_' + option.value\"\n [attr.name]=\"allowMultiple() ? field().key.toString() + '[]' : field().key.toString()\"\n [checked]=\"isOptionSelected(option)\"\n (change)=\"handleOptionChange(option, $event)\"\n (blur)=\"onBlurInput()\"\n />\n }\n <span class=\"c-entry-toggle__toggle\"></span>\n\n <span class=\"c-entry-toggle__text\">\n {{ option.label | translate }}\n @if(option.externalLink) {\n <!-- Link externo funcional implementado -->\n <a class=\"icon-external-link-thin\" [href]=\"option.externalLink\" target=\"_blank\"></a>\n }\n </span>\n @if(option.detail) {\n <!-- Texto de detalle funcional implementado -->\n <span class=\"c-form-checkbox__detail\">{{ option.detail }}</span>\n }\n </label>\n\n }\n } @else {\n <!-- ! Solcre: Este .c-entry-toggle deber\u00EDa ser un componente en s\u00ED mismo. -->\n <!-- ! Solcre: El cannot-deselect no est\u00E1 over-engineered. Deber\u00EDa ser un Radio. -->\n <label class=\"c-entry-toggle\"\n [class.is-invalid]=\"hasError()\"\n [class.is-disabled]=\"isDisabled()\"\n [class.cannot-deselect]=\"isRequired() && !!formControl().value\">\n\n <!-- onBlurInput() maneja validaciones y marca el campo como touched para mostrar errores -->\n @if (isRequired() && !!formControl().value) {\n <!-- Usar radio cuando es requerido y tiene valor (cannot-deselect) -->\n <input\n type=\"radio\"\n [attr.id]=\"field().key.toString()\"\n [attr.name]=\"field().key.toString()\"\n [checked]=\"!!formControl().value\"\n (change)=\"onRadioChange($event)\"\n (blur)=\"onBlurInput()\"\n />\n } @else {\n <!-- Usar checkbox normal cuando se puede deseleccionar -->\n <input\n type=\"checkbox\"\n [attr.id]=\"field().key.toString()\"\n [attr.name]=\"field().key.toString()\"\n [formControl]=\"formControl()\"\n (blur)=\"onBlurInput()\"\n />\n }\n <span class=\"c-entry-toggle__toggle\"></span>\n <span class=\"c-entry-toggle__text\">\n {{ field().label | translate }}\n @if(externalLink()) {\n <!-- Link externo funcional implementado -->\n <a class=\"icon-external-link-thin\" [href]=\"externalLink()\" target=\"_blank\"></a>\n }\n </span>\n @if(detail()) {\n <!-- Texto de detalle funcional implementado -->\n <span class=\"c-form-checkbox__detail\">{{ detail() }}</span>\n }\n </label>\n }\n\n <core-field-errors [errors]=\"errors()\" />\n</div> \n ", styles: [".cannot-deselect{pointer-events:none;cursor:not-allowed}.c-entry-text+.c-entry-toggle-holder.hasSeparatedOptions{margin-top:calc(var(--_entry-group-gap) * .8)}.c-entry-toggle-holder.hasSeparatedOptions{display:grid;grid-template-columns:1fr 1fr;gap:calc(var(--_entry-group-gap) * .8)}.c-entry-toggle-holder.hasSeparatedOptions .c-entry-text{grid-column:span 2;margin-top:1em}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i3$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "component", type: FieldErrorsComponent, selector: "core-field-errors", inputs: ["errors"] }] });
497
494
  }
498
495
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: CheckboxFieldComponent, decorators: [{
499
496
  type: Component,
500
- args: [{ selector: 'core-checkbox-field', standalone: true, imports: [CommonModule, FormsModule, ReactiveFormsModule, TranslateModule, FieldErrorsComponent], hostDirectives: [CoreHostDirective], template: "<!-- Clase para layout inline cuando hay m\u00FAltiples opciones -->\n<div class=\"c-entry-toggle-holder\" [class.hasSeparatedOptions]=\"hasSeparatedOptions()\" [class.multiple-inline]=\"hasMultipleOptions()\">\n\n <span class=\"c-entry-text\"\n *ngIf=\"field().label\">\n {{ field().label | translate }}\n @if (hasRequiredValidators()) {\n <span class=\"c-required\">*</span>\n }\n </span>\n \n @if (hasMultipleOptions()) {\n @for (option of options(); track option.value) {\n\n <!-- ! Solcre: Este .c-entry-toggle deber\u00EDa ser un componente en s\u00ED mismo. -->\n <!-- ! Solcre: El cannot-deselect no est\u00E1 over-engineered. Deber\u00EDa ser un Radio. -->\n <label class=\"c-entry-toggle\"\n [class.is-invalid]=\"hasError()\"\n [class.is-disabled]=\"isDisabled()\"\n [class.cannot-deselect]=\"cannotDeselect(option)\">\n\n <!-- onBlurInput() maneja validaciones y marca el campo como touched para mostrar errores -->\n @if (cannotDeselect(option)) {\n <!-- Usar radio cuando no se puede deseleccionar -->\n <input\n type=\"radio\"\n [attr.id]=\"field().key.toString() + '_' + option.value\"\n [attr.name]=\"field().key.toString()\"\n [checked]=\"isOptionSelected(option)\"\n (change)=\"handleOptionChange(option, $event)\"\n (blur)=\"onBlurInput()\"\n />\n } @else {\n <!-- Usar checkbox normal cuando se puede deseleccionar -->\n <input\n type=\"checkbox\"\n [attr.id]=\"field().key.toString() + '_' + option.value\"\n [attr.name]=\"allowMultiple() ? field().key.toString() + '[]' : field().key.toString()\"\n [checked]=\"isOptionSelected(option)\"\n (change)=\"handleOptionChange(option, $event)\"\n (blur)=\"onBlurInput()\"\n />\n }\n <span class=\"c-entry-toggle__toggle\"></span>\n\n <span class=\"c-entry-toggle__text\">\n {{ option.label | translate }}\n @if(option.externalLink) {\n <!-- Link externo funcional implementado -->\n <a class=\"icon-external-link-thin\" [href]=\"option.externalLink\" target=\"_blank\"></a>\n }\n </span>\n @if(option.detail) {\n <!-- Texto de detalle funcional implementado -->\n <span class=\"c-form-checkbox__detail\">{{ option.detail }}</span>\n }\n </label>\n\n }\n } @else {\n <!-- ! Solcre: Este .c-entry-toggle deber\u00EDa ser un componente en s\u00ED mismo. -->\n <!-- ! Solcre: El cannot-deselect no est\u00E1 over-engineered. Deber\u00EDa ser un Radio. -->\n <label class=\"c-entry-toggle\"\n [class.is-invalid]=\"hasError()\"\n [class.is-disabled]=\"isDisabled()\"\n [class.cannot-deselect]=\"isRequired() && !!formControl().value\">\n\n <!-- onBlurInput() maneja validaciones y marca el campo como touched para mostrar errores -->\n @if (isRequired() && !!formControl().value) {\n <!-- Usar radio cuando es requerido y tiene valor (cannot-deselect) -->\n <input\n type=\"radio\"\n [attr.id]=\"field().key.toString()\"\n [attr.name]=\"field().key.toString()\"\n [checked]=\"!!formControl().value\"\n (change)=\"onRadioChange($event)\"\n (blur)=\"onBlurInput()\"\n />\n } @else {\n <!-- Usar checkbox normal cuando se puede deseleccionar -->\n <input\n type=\"checkbox\"\n [attr.id]=\"field().key.toString()\"\n [attr.name]=\"field().key.toString()\"\n [formControl]=\"formControl()\"\n (blur)=\"onBlurInput()\"\n />\n }\n <span class=\"c-entry-toggle__toggle\"></span>\n <span class=\"c-entry-toggle__text\">\n {{ field().label | translate }}\n @if(externalLink()) {\n <!-- Link externo funcional implementado -->\n <a class=\"icon-external-link-thin\" [href]=\"externalLink()\" target=\"_blank\"></a>\n }\n </span>\n @if(detail()) {\n <!-- Texto de detalle funcional implementado -->\n <span class=\"c-form-checkbox__detail\">{{ detail() }}</span>\n }\n </label>\n }\n\n <core-field-errors [errors]=\"errors()\" />\n</div> \n ", styles: [".cannot-deselect{pointer-events:none;cursor:not-allowed}.c-entry-text+.c-entry-toggle-holder.hasSeparatedOptions{margin-top:calc(var(--_entry-group-gap) * .8)}.c-entry-toggle-holder.hasSeparatedOptions{display:grid;grid-template-columns:1fr 1fr;gap:calc(var(--_entry-group-gap) * .8)}.c-entry-toggle-holder.hasSeparatedOptions .c-entry-text{grid-column:span 2;margin-top:1em}\n"] }]
497
+ args: [{ selector: 'core-checkbox-field', standalone: true, imports: [CommonModule, FormsModule, ReactiveFormsModule, TranslateModule, FieldErrorsComponent], hostDirectives: [CoreHostDirective], template: "<!-- Clase para layout inline cuando hay m\u00FAltiples opciones -->\n<div class=\"c-entry-toggle-holder\" [class.hasSeparatedOptions]=\"hasSeparatedOptions()\" [class.multiple-inline]=\"hasMultipleOptions()\">\n\n <span class=\"c-entry-text\"\n *ngIf=\"field().label\">\n {{ field().label | translate }}\n @if (hasRequiredValidators()) {\n <span class=\"c-required\">*</span>\n }\n </span>\n \n @if (hasMultipleOptions()) {\n @for (option of options(); track option.value) {\n\n <!-- ! Solcre: Este .c-entry-toggle deber\u00EDa ser un componente en s\u00ED mismo. -->\n <!-- ! Solcre: El cannot-deselect no est\u00E1 over-engineered. Deber\u00EDa ser un Radio. -->\n <label class=\"c-entry-toggle\"\n [class.is-invalid]=\"hasError()\"\n [class.is-disabled]=\"isDisabled()\"\n [class.cannot-deselect]=\"cannotDeselect(option)\">\n\n <!-- onBlurInput() maneja validaciones y marca el campo como touched para mostrar errores -->\n @if (!allowMultiple() && isRequired()) {\n <!-- Cuando allowMultiple: false y required: true, usar radio buttons para todas las opciones -->\n <input\n type=\"radio\"\n [attr.id]=\"field().key.toString() + '_' + option.value\"\n [attr.name]=\"field().key.toString()\"\n [checked]=\"isOptionSelected(option)\"\n (change)=\"handleOptionChange(option, $event)\"\n (blur)=\"onBlurInput()\"\n />\n } @else if (cannotDeselect(option)) {\n <!-- Usar radio cuando no se puede deseleccionar (modo m\u00FAltiple con una sola opci\u00F3n) -->\n <input\n type=\"radio\"\n [attr.id]=\"field().key.toString() + '_' + option.value\"\n [attr.name]=\"field().key.toString()\"\n [checked]=\"isOptionSelected(option)\"\n (change)=\"handleOptionChange(option, $event)\"\n (blur)=\"onBlurInput()\"\n />\n } @else {\n <!-- Usar checkbox normal cuando se puede deseleccionar -->\n <input\n type=\"checkbox\"\n [attr.id]=\"field().key.toString() + '_' + option.value\"\n [attr.name]=\"allowMultiple() ? field().key.toString() + '[]' : field().key.toString()\"\n [checked]=\"isOptionSelected(option)\"\n (change)=\"handleOptionChange(option, $event)\"\n (blur)=\"onBlurInput()\"\n />\n }\n <span class=\"c-entry-toggle__toggle\"></span>\n\n <span class=\"c-entry-toggle__text\">\n {{ option.label | translate }}\n @if(option.externalLink) {\n <!-- Link externo funcional implementado -->\n <a class=\"icon-external-link-thin\" [href]=\"option.externalLink\" target=\"_blank\"></a>\n }\n </span>\n @if(option.detail) {\n <!-- Texto de detalle funcional implementado -->\n <span class=\"c-form-checkbox__detail\">{{ option.detail }}</span>\n }\n </label>\n\n }\n } @else {\n <!-- ! Solcre: Este .c-entry-toggle deber\u00EDa ser un componente en s\u00ED mismo. -->\n <!-- ! Solcre: El cannot-deselect no est\u00E1 over-engineered. Deber\u00EDa ser un Radio. -->\n <label class=\"c-entry-toggle\"\n [class.is-invalid]=\"hasError()\"\n [class.is-disabled]=\"isDisabled()\"\n [class.cannot-deselect]=\"isRequired() && !!formControl().value\">\n\n <!-- onBlurInput() maneja validaciones y marca el campo como touched para mostrar errores -->\n @if (isRequired() && !!formControl().value) {\n <!-- Usar radio cuando es requerido y tiene valor (cannot-deselect) -->\n <input\n type=\"radio\"\n [attr.id]=\"field().key.toString()\"\n [attr.name]=\"field().key.toString()\"\n [checked]=\"!!formControl().value\"\n (change)=\"onRadioChange($event)\"\n (blur)=\"onBlurInput()\"\n />\n } @else {\n <!-- Usar checkbox normal cuando se puede deseleccionar -->\n <input\n type=\"checkbox\"\n [attr.id]=\"field().key.toString()\"\n [attr.name]=\"field().key.toString()\"\n [formControl]=\"formControl()\"\n (blur)=\"onBlurInput()\"\n />\n }\n <span class=\"c-entry-toggle__toggle\"></span>\n <span class=\"c-entry-toggle__text\">\n {{ field().label | translate }}\n @if(externalLink()) {\n <!-- Link externo funcional implementado -->\n <a class=\"icon-external-link-thin\" [href]=\"externalLink()\" target=\"_blank\"></a>\n }\n </span>\n @if(detail()) {\n <!-- Texto de detalle funcional implementado -->\n <span class=\"c-form-checkbox__detail\">{{ detail() }}</span>\n }\n </label>\n }\n\n <core-field-errors [errors]=\"errors()\" />\n</div> \n ", styles: [".cannot-deselect{pointer-events:none;cursor:not-allowed}.c-entry-text+.c-entry-toggle-holder.hasSeparatedOptions{margin-top:calc(var(--_entry-group-gap) * .8)}.c-entry-toggle-holder.hasSeparatedOptions{display:grid;grid-template-columns:1fr 1fr;gap:calc(var(--_entry-group-gap) * .8)}.c-entry-toggle-holder.hasSeparatedOptions .c-entry-text{grid-column:span 2;margin-top:1em}\n"] }]
501
498
  }], ctorParameters: () => [] });
502
499
 
503
500
  class DateFieldComponent extends BaseFieldComponent {
@@ -958,6 +955,352 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
958
955
  }]
959
956
  }] });
960
957
 
958
+ var SkeletonType;
959
+ (function (SkeletonType) {
960
+ SkeletonType["INPUT"] = "input";
961
+ SkeletonType["TEXTAREA"] = "textarea";
962
+ SkeletonType["BUTTON"] = "button";
963
+ SkeletonType["CHECKBOX"] = "checkbox";
964
+ SkeletonType["IMAGE"] = "image";
965
+ SkeletonType["TEXT"] = "text";
966
+ SkeletonType["CARD"] = "card";
967
+ SkeletonType["LIST"] = "list";
968
+ SkeletonType["AVATAR"] = "avatar";
969
+ })(SkeletonType || (SkeletonType = {}));
970
+
971
+ var SkeletonSize;
972
+ (function (SkeletonSize) {
973
+ SkeletonSize["SMALL"] = "small";
974
+ SkeletonSize["MEDIUM"] = "medium";
975
+ SkeletonSize["LARGE"] = "large";
976
+ SkeletonSize["EXTRA_LARGE"] = "extra-large";
977
+ })(SkeletonSize || (SkeletonSize = {}));
978
+
979
+ var SkeletonAnimation;
980
+ (function (SkeletonAnimation) {
981
+ SkeletonAnimation["PULSE"] = "pulse";
982
+ SkeletonAnimation["WAVE"] = "wave";
983
+ SkeletonAnimation["SHIMMER"] = "shimmer";
984
+ SkeletonAnimation["NONE"] = "none";
985
+ })(SkeletonAnimation || (SkeletonAnimation = {}));
986
+
987
+ class GenericSkeletonComponent {
988
+ config = input();
989
+ items = input();
990
+ type = input();
991
+ size = input();
992
+ width = input();
993
+ height = input();
994
+ animated = input(true);
995
+ animation = input(SkeletonAnimation.PULSE);
996
+ lines = input(1);
997
+ customClass = input('');
998
+ ariaLabel = input('Loading content');
999
+ SkeletonType = SkeletonType;
1000
+ SkeletonSize = SkeletonSize;
1001
+ SkeletonAnimation = SkeletonAnimation;
1002
+ skeletonItems = computed(() => {
1003
+ const config = this.config();
1004
+ const items = this.items();
1005
+ const type = this.type();
1006
+ if (config?.items) {
1007
+ return config.items;
1008
+ }
1009
+ if (items) {
1010
+ return items;
1011
+ }
1012
+ if (type) {
1013
+ return [{
1014
+ type,
1015
+ size: this.size(),
1016
+ width: this.width(),
1017
+ height: this.height(),
1018
+ animated: this.animated(),
1019
+ animation: this.animation(),
1020
+ lines: this.lines(),
1021
+ customClass: this.customClass(),
1022
+ ariaLabel: this.ariaLabel()
1023
+ }];
1024
+ }
1025
+ return [{
1026
+ type: SkeletonType.TEXT,
1027
+ size: this.size() || SkeletonSize.MEDIUM,
1028
+ animated: this.animated(),
1029
+ animation: this.animation(),
1030
+ lines: this.lines(),
1031
+ customClass: this.customClass(),
1032
+ ariaLabel: this.ariaLabel()
1033
+ }];
1034
+ });
1035
+ containerClasses = computed(() => {
1036
+ const config = this.config();
1037
+ const baseClasses = ['c-skeleton'];
1038
+ if (config?.containerClass) {
1039
+ baseClasses.push(config.containerClass);
1040
+ }
1041
+ if (config?.animated !== false && this.animated()) {
1042
+ const animation = config?.animation || this.animation();
1043
+ baseClasses.push(`c-skeleton--${animation}`);
1044
+ }
1045
+ return baseClasses.join(' ');
1046
+ });
1047
+ getItemClasses(item) {
1048
+ const classes = [];
1049
+ switch (item.type) {
1050
+ case SkeletonType.INPUT:
1051
+ classes.push('c-skeleton__input');
1052
+ break;
1053
+ case SkeletonType.TEXTAREA:
1054
+ classes.push('c-skeleton__textarea');
1055
+ break;
1056
+ case SkeletonType.BUTTON:
1057
+ classes.push('c-skeleton__btn');
1058
+ break;
1059
+ case SkeletonType.CHECKBOX:
1060
+ classes.push('c-skeleton__check', 'c-skeleton-check');
1061
+ break;
1062
+ case SkeletonType.IMAGE:
1063
+ classes.push('c-skeleton-image');
1064
+ break;
1065
+ case SkeletonType.TEXT:
1066
+ classes.push('c-skeleton__text');
1067
+ break;
1068
+ case SkeletonType.CARD:
1069
+ classes.push('c-skeleton__card');
1070
+ break;
1071
+ case SkeletonType.LIST:
1072
+ classes.push('c-skeleton__list');
1073
+ break;
1074
+ case SkeletonType.AVATAR:
1075
+ classes.push('c-skeleton__avatar');
1076
+ break;
1077
+ }
1078
+ if (item.size) {
1079
+ classes.push(`c-skeleton--${item.size}`);
1080
+ }
1081
+ if (item.animated !== false) {
1082
+ const animation = item.animation || this.animation();
1083
+ classes.push(`c-skeleton--${animation}`);
1084
+ }
1085
+ if (item.customClass) {
1086
+ classes.push(item.customClass);
1087
+ }
1088
+ return classes.join(' ');
1089
+ }
1090
+ getItemStyles(item) {
1091
+ const styles = {};
1092
+ if (item.width) {
1093
+ styles['width'] = item.width;
1094
+ }
1095
+ if (item.height) {
1096
+ styles['height'] = item.height;
1097
+ }
1098
+ const config = this.config();
1099
+ if (config?.spacing) {
1100
+ styles['margin-bottom'] = config.spacing;
1101
+ }
1102
+ return styles;
1103
+ }
1104
+ getTextLines(item) {
1105
+ const lines = item.lines || this.lines() || 1;
1106
+ return Array.from({ length: lines }, (_, i) => i);
1107
+ }
1108
+ getListItems(item) {
1109
+ const items = item.listConfig?.items || 3;
1110
+ return Array.from({ length: items }, (_, i) => i);
1111
+ }
1112
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: GenericSkeletonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1113
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.0.6", type: GenericSkeletonComponent, isStandalone: true, selector: "core-generic-skeleton", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, animated: { classPropertyName: "animated", publicName: "animated", isSignal: true, isRequired: false, transformFunction: null }, animation: { classPropertyName: "animation", publicName: "animation", isSignal: true, isRequired: false, transformFunction: null }, lines: { classPropertyName: "lines", publicName: "lines", isSignal: true, isRequired: false, transformFunction: null }, customClass: { classPropertyName: "customClass", publicName: "customClass", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div [class]=\"containerClasses()\" [attr.aria-label]=\"ariaLabel()\">\n <ng-container *ngFor=\"let item of skeletonItems()\">\n \n <!-- Skeleton Input -->\n <div *ngIf=\"item.type === SkeletonType.INPUT\"\n [class]=\"getItemClasses(item)\"\n [ngStyle]=\"getItemStyles(item)\"\n [attr.aria-label]=\"item.ariaLabel || 'Loading input field'\">\n </div>\n \n <!-- Skeleton Textarea -->\n <div *ngIf=\"item.type === SkeletonType.TEXTAREA\"\n [class]=\"getItemClasses(item)\"\n [ngStyle]=\"getItemStyles(item)\"\n [attr.aria-label]=\"item.ariaLabel || 'Loading textarea field'\">\n </div>\n \n <!-- Skeleton Button -->\n <div *ngIf=\"item.type === SkeletonType.BUTTON\"\n [class]=\"getItemClasses(item)\"\n [ngStyle]=\"getItemStyles(item)\"\n [attr.aria-label]=\"item.ariaLabel || 'Loading button'\">\n </div>\n \n <!-- Skeleton Checkbox -->\n <div *ngIf=\"item.type === SkeletonType.CHECKBOX\"\n [class]=\"getItemClasses(item)\"\n [ngStyle]=\"getItemStyles(item)\"\n [attr.aria-label]=\"item.ariaLabel || 'Loading checkbox'\">\n <div class=\"c-skeleton-check__check\"></div>\n <div *ngIf=\"item.checkboxConfig?.showText !== false\" \n class=\"c-skeleton-check__text\"\n [style.width]=\"item.checkboxConfig?.textWidth || 'auto'\">\n </div>\n </div>\n \n <!-- Skeleton Image -->\n <div *ngIf=\"item.type === SkeletonType.IMAGE\"\n [class]=\"getItemClasses(item)\"\n [ngStyle]=\"getItemStyles(item)\"\n [attr.aria-label]=\"item.ariaLabel || 'Loading image'\">\n </div>\n \n <!-- Skeleton Text -->\n <div *ngIf=\"item.type === SkeletonType.TEXT\"\n [ngStyle]=\"getItemStyles(item)\"\n [attr.aria-label]=\"item.ariaLabel || 'Loading text'\">\n <div *ngFor=\"let line of getTextLines(item)\"\n [class]=\"getItemClasses(item)\"\n [style.width]=\"line === getTextLines(item).length - 1 ? '75%' : '100%'\">\n </div>\n </div>\n \n <!-- Skeleton Avatar -->\n <div *ngIf=\"item.type === SkeletonType.AVATAR\"\n [class]=\"getItemClasses(item)\"\n [ngStyle]=\"getItemStyles(item)\"\n [attr.aria-label]=\"item.ariaLabel || 'Loading avatar'\">\n </div>\n \n <!-- Skeleton Card -->\n <div *ngIf=\"item.type === SkeletonType.CARD\"\n [class]=\"getItemClasses(item)\"\n [ngStyle]=\"getItemStyles(item)\"\n [attr.aria-label]=\"item.ariaLabel || 'Loading card'\">\n <div class=\"c-skeleton__card-header\"></div>\n <div class=\"c-skeleton__card-body\">\n <div class=\"c-skeleton__text\"></div>\n <div class=\"c-skeleton__text\" style=\"width: 80%;\"></div>\n <div class=\"c-skeleton__text\" style=\"width: 60%;\"></div>\n </div>\n </div>\n \n <!-- Skeleton List -->\n <div *ngIf=\"item.type === SkeletonType.LIST\"\n [class]=\"getItemClasses(item)\"\n [ngStyle]=\"getItemStyles(item)\"\n [attr.aria-label]=\"item.ariaLabel || 'Loading list'\">\n <div *ngFor=\"let listItem of getListItems(item)\" class=\"c-skeleton__list-item\">\n <div *ngIf=\"item.listConfig?.showAvatar\" class=\"c-skeleton__avatar c-skeleton__avatar--small\"></div>\n <div class=\"c-skeleton__list-content\">\n <div class=\"c-skeleton__text\"></div>\n <div *ngIf=\"item.listConfig?.showSecondaryText\" \n class=\"c-skeleton__text c-skeleton__text--secondary\" \n style=\"width: 70%;\"></div>\n </div>\n </div>\n </div>\n \n </ng-container>\n</div>", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
1114
+ }
1115
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: GenericSkeletonComponent, decorators: [{
1116
+ type: Component,
1117
+ args: [{ selector: 'core-generic-skeleton', standalone: true, imports: [CommonModule], template: "<div [class]=\"containerClasses()\" [attr.aria-label]=\"ariaLabel()\">\n <ng-container *ngFor=\"let item of skeletonItems()\">\n \n <!-- Skeleton Input -->\n <div *ngIf=\"item.type === SkeletonType.INPUT\"\n [class]=\"getItemClasses(item)\"\n [ngStyle]=\"getItemStyles(item)\"\n [attr.aria-label]=\"item.ariaLabel || 'Loading input field'\">\n </div>\n \n <!-- Skeleton Textarea -->\n <div *ngIf=\"item.type === SkeletonType.TEXTAREA\"\n [class]=\"getItemClasses(item)\"\n [ngStyle]=\"getItemStyles(item)\"\n [attr.aria-label]=\"item.ariaLabel || 'Loading textarea field'\">\n </div>\n \n <!-- Skeleton Button -->\n <div *ngIf=\"item.type === SkeletonType.BUTTON\"\n [class]=\"getItemClasses(item)\"\n [ngStyle]=\"getItemStyles(item)\"\n [attr.aria-label]=\"item.ariaLabel || 'Loading button'\">\n </div>\n \n <!-- Skeleton Checkbox -->\n <div *ngIf=\"item.type === SkeletonType.CHECKBOX\"\n [class]=\"getItemClasses(item)\"\n [ngStyle]=\"getItemStyles(item)\"\n [attr.aria-label]=\"item.ariaLabel || 'Loading checkbox'\">\n <div class=\"c-skeleton-check__check\"></div>\n <div *ngIf=\"item.checkboxConfig?.showText !== false\" \n class=\"c-skeleton-check__text\"\n [style.width]=\"item.checkboxConfig?.textWidth || 'auto'\">\n </div>\n </div>\n \n <!-- Skeleton Image -->\n <div *ngIf=\"item.type === SkeletonType.IMAGE\"\n [class]=\"getItemClasses(item)\"\n [ngStyle]=\"getItemStyles(item)\"\n [attr.aria-label]=\"item.ariaLabel || 'Loading image'\">\n </div>\n \n <!-- Skeleton Text -->\n <div *ngIf=\"item.type === SkeletonType.TEXT\"\n [ngStyle]=\"getItemStyles(item)\"\n [attr.aria-label]=\"item.ariaLabel || 'Loading text'\">\n <div *ngFor=\"let line of getTextLines(item)\"\n [class]=\"getItemClasses(item)\"\n [style.width]=\"line === getTextLines(item).length - 1 ? '75%' : '100%'\">\n </div>\n </div>\n \n <!-- Skeleton Avatar -->\n <div *ngIf=\"item.type === SkeletonType.AVATAR\"\n [class]=\"getItemClasses(item)\"\n [ngStyle]=\"getItemStyles(item)\"\n [attr.aria-label]=\"item.ariaLabel || 'Loading avatar'\">\n </div>\n \n <!-- Skeleton Card -->\n <div *ngIf=\"item.type === SkeletonType.CARD\"\n [class]=\"getItemClasses(item)\"\n [ngStyle]=\"getItemStyles(item)\"\n [attr.aria-label]=\"item.ariaLabel || 'Loading card'\">\n <div class=\"c-skeleton__card-header\"></div>\n <div class=\"c-skeleton__card-body\">\n <div class=\"c-skeleton__text\"></div>\n <div class=\"c-skeleton__text\" style=\"width: 80%;\"></div>\n <div class=\"c-skeleton__text\" style=\"width: 60%;\"></div>\n </div>\n </div>\n \n <!-- Skeleton List -->\n <div *ngIf=\"item.type === SkeletonType.LIST\"\n [class]=\"getItemClasses(item)\"\n [ngStyle]=\"getItemStyles(item)\"\n [attr.aria-label]=\"item.ariaLabel || 'Loading list'\">\n <div *ngFor=\"let listItem of getListItems(item)\" class=\"c-skeleton__list-item\">\n <div *ngIf=\"item.listConfig?.showAvatar\" class=\"c-skeleton__avatar c-skeleton__avatar--small\"></div>\n <div class=\"c-skeleton__list-content\">\n <div class=\"c-skeleton__text\"></div>\n <div *ngIf=\"item.listConfig?.showSecondaryText\" \n class=\"c-skeleton__text c-skeleton__text--secondary\" \n style=\"width: 70%;\"></div>\n </div>\n </div>\n </div>\n \n </ng-container>\n</div>" }]
1118
+ }] });
1119
+
1120
+ class SkeletonService {
1121
+ presetConfigs = {
1122
+ form: {
1123
+ items: [
1124
+ { type: SkeletonType.INPUT },
1125
+ { type: SkeletonType.INPUT },
1126
+ { type: SkeletonType.TEXTAREA },
1127
+ { type: SkeletonType.CHECKBOX, checkboxConfig: { showText: true } },
1128
+ { type: SkeletonType.BUTTON, width: '120px' }
1129
+ ],
1130
+ animated: true,
1131
+ animation: SkeletonAnimation.PULSE
1132
+ },
1133
+ userCard: {
1134
+ items: [
1135
+ { type: SkeletonType.AVATAR, size: SkeletonSize.LARGE },
1136
+ { type: SkeletonType.TEXT, lines: 2 },
1137
+ { type: SkeletonType.TEXT, width: '60%' }
1138
+ ],
1139
+ animated: true,
1140
+ animation: SkeletonAnimation.SHIMMER
1141
+ },
1142
+ articleList: {
1143
+ items: [
1144
+ {
1145
+ type: SkeletonType.LIST,
1146
+ listConfig: {
1147
+ items: 5,
1148
+ showAvatar: true,
1149
+ showSecondaryText: true
1150
+ }
1151
+ }
1152
+ ],
1153
+ animated: true,
1154
+ animation: SkeletonAnimation.WAVE
1155
+ },
1156
+ imageGallery: {
1157
+ items: [
1158
+ { type: SkeletonType.IMAGE, height: '200px' },
1159
+ { type: SkeletonType.IMAGE, height: '200px' },
1160
+ { type: SkeletonType.IMAGE, height: '200px' }
1161
+ ],
1162
+ containerClass: 'skeleton-gallery',
1163
+ animated: true,
1164
+ animation: SkeletonAnimation.PULSE
1165
+ },
1166
+ dataTable: {
1167
+ items: [
1168
+ { type: SkeletonType.TEXT, height: '40px', width: '100%' },
1169
+ { type: SkeletonType.TEXT, height: '35px', width: '100%' },
1170
+ { type: SkeletonType.TEXT, height: '35px', width: '100%' },
1171
+ { type: SkeletonType.TEXT, height: '35px', width: '100%' },
1172
+ { type: SkeletonType.TEXT, height: '35px', width: '100%' }
1173
+ ],
1174
+ animated: true,
1175
+ animation: SkeletonAnimation.SHIMMER
1176
+ },
1177
+ dashboard: {
1178
+ items: [
1179
+ { type: SkeletonType.CARD, height: '150px' },
1180
+ { type: SkeletonType.CARD, height: '150px' },
1181
+ { type: SkeletonType.CARD, height: '300px' }
1182
+ ],
1183
+ animated: true,
1184
+ animation: SkeletonAnimation.PULSE
1185
+ }
1186
+ };
1187
+ getPresetConfig(preset) {
1188
+ return { ...this.presetConfigs[preset] };
1189
+ }
1190
+ createFormSkeleton(fields = 3, includeButton = true) {
1191
+ const items = [];
1192
+ for (let i = 0; i < fields; i++) {
1193
+ items.push({ type: SkeletonType.INPUT });
1194
+ }
1195
+ if (includeButton) {
1196
+ items.push({ type: SkeletonType.BUTTON, width: '120px' });
1197
+ }
1198
+ return {
1199
+ items,
1200
+ animated: true,
1201
+ animation: SkeletonAnimation.PULSE
1202
+ };
1203
+ }
1204
+ createListSkeleton(itemCount = 5, showAvatar = false, showSecondaryText = false) {
1205
+ return {
1206
+ items: [{
1207
+ type: SkeletonType.LIST,
1208
+ listConfig: {
1209
+ items: itemCount,
1210
+ showAvatar,
1211
+ showSecondaryText
1212
+ }
1213
+ }],
1214
+ animated: true,
1215
+ animation: SkeletonAnimation.WAVE
1216
+ };
1217
+ }
1218
+ createTextSkeleton(lines = 3, width) {
1219
+ return {
1220
+ items: [{
1221
+ type: SkeletonType.TEXT,
1222
+ lines,
1223
+ width
1224
+ }],
1225
+ animated: true,
1226
+ animation: SkeletonAnimation.PULSE
1227
+ };
1228
+ }
1229
+ createImageSkeleton(width, height) {
1230
+ return {
1231
+ items: [{
1232
+ type: SkeletonType.IMAGE,
1233
+ width: width || '100%',
1234
+ height: height || '200px'
1235
+ }],
1236
+ animated: true,
1237
+ animation: SkeletonAnimation.SHIMMER
1238
+ };
1239
+ }
1240
+ createCardSkeleton(includeAvatar = false, textLines = 3) {
1241
+ const items = [];
1242
+ if (includeAvatar) {
1243
+ items.push({ type: SkeletonType.AVATAR });
1244
+ }
1245
+ items.push({
1246
+ type: SkeletonType.TEXT,
1247
+ lines: textLines
1248
+ });
1249
+ return {
1250
+ items,
1251
+ animated: true,
1252
+ animation: SkeletonAnimation.PULSE
1253
+ };
1254
+ }
1255
+ combineConfigs(...configs) {
1256
+ const combinedItems = [];
1257
+ let finalAnimation = SkeletonAnimation.PULSE;
1258
+ let finalAnimated = true;
1259
+ let finalContainerClass = '';
1260
+ configs.forEach(config => {
1261
+ combinedItems.push(...config.items);
1262
+ if (config.animation) {
1263
+ finalAnimation = config.animation;
1264
+ }
1265
+ if (config.animated !== undefined) {
1266
+ finalAnimated = config.animated;
1267
+ }
1268
+ if (config.containerClass) {
1269
+ finalContainerClass += ` ${config.containerClass}`;
1270
+ }
1271
+ });
1272
+ return {
1273
+ items: combinedItems,
1274
+ animated: finalAnimated,
1275
+ animation: finalAnimation,
1276
+ containerClass: finalContainerClass.trim() || undefined
1277
+ };
1278
+ }
1279
+ createCustomSkeleton(type, options = {}) {
1280
+ return {
1281
+ items: [{
1282
+ type,
1283
+ animated: true,
1284
+ animation: SkeletonAnimation.PULSE,
1285
+ ...options
1286
+ }],
1287
+ animated: true,
1288
+ animation: options.animation || SkeletonAnimation.PULSE
1289
+ };
1290
+ }
1291
+ getAvailablePresets() {
1292
+ return Object.keys(this.presetConfigs);
1293
+ }
1294
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: SkeletonService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1295
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: SkeletonService, providedIn: 'root' });
1296
+ }
1297
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: SkeletonService, decorators: [{
1298
+ type: Injectable,
1299
+ args: [{
1300
+ providedIn: 'root'
1301
+ }]
1302
+ }] });
1303
+
961
1304
  class ImagePreviewComponent {
962
1305
  imageModalService = inject(ImageModalService);
963
1306
  src = input.required();
@@ -970,19 +1313,39 @@ class ImagePreviewComponent {
970
1313
  cursor = input('pointer');
971
1314
  loading = input('lazy');
972
1315
  isRelative = input(false);
1316
+ showSkeleton = input(true);
1317
+ skeletonAnimation = input(SkeletonAnimation.SHIMMER);
1318
+ isImageLoading = signal(true);
1319
+ hasImageError = signal(false);
1320
+ SkeletonType = SkeletonType;
1321
+ onImageLoad() {
1322
+ this.isImageLoading.set(false);
1323
+ this.hasImageError.set(false);
1324
+ }
1325
+ onImageError() {
1326
+ this.isImageLoading.set(false);
1327
+ this.hasImageError.set(true);
1328
+ }
973
1329
  onImageClick() {
974
- this.imageModalService.openImageModal({
975
- src: this.src(),
976
- alt: this.alt(),
977
- title: this.title()
978
- });
1330
+ if (!this.isImageLoading() && !this.hasImageError()) {
1331
+ this.imageModalService.openImageModal({
1332
+ src: this.src(),
1333
+ alt: this.alt(),
1334
+ title: this.title()
1335
+ });
1336
+ }
1337
+ }
1338
+ onSkeletonClick() {
1339
+ if (!this.isImageLoading()) {
1340
+ this.onImageClick();
1341
+ }
979
1342
  }
980
1343
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: ImagePreviewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
981
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.0.6", type: ImagePreviewComponent, isStandalone: true, selector: "core-image-preview", inputs: { src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: true, transformFunction: null }, alt: { classPropertyName: "alt", publicName: "alt", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, objectFit: { classPropertyName: "objectFit", publicName: "objectFit", isSignal: true, isRequired: false, transformFunction: null }, borderRadius: { classPropertyName: "borderRadius", publicName: "borderRadius", isSignal: true, isRequired: false, transformFunction: null }, cursor: { classPropertyName: "cursor", publicName: "cursor", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, isRelative: { classPropertyName: "isRelative", publicName: "isRelative", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"c-img-preview\" \n (click)=\"onImageClick()\">\n <img \n [src]=\"src()\" \n [alt]=\"alt()\"\n [title]=\"title()\"\n [loading]=\"loading()\"\n [style.object-fit]=\"objectFit()\"\n [style.border-radius]=\"borderRadius()\"\n [style.cursor]=\"cursor()\">\n</div>", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
1344
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: ImagePreviewComponent, isStandalone: true, selector: "core-image-preview", inputs: { src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: true, transformFunction: null }, alt: { classPropertyName: "alt", publicName: "alt", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, objectFit: { classPropertyName: "objectFit", publicName: "objectFit", isSignal: true, isRequired: false, transformFunction: null }, borderRadius: { classPropertyName: "borderRadius", publicName: "borderRadius", isSignal: true, isRequired: false, transformFunction: null }, cursor: { classPropertyName: "cursor", publicName: "cursor", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, isRelative: { classPropertyName: "isRelative", publicName: "isRelative", isSignal: true, isRequired: false, transformFunction: null }, showSkeleton: { classPropertyName: "showSkeleton", publicName: "showSkeleton", isSignal: true, isRequired: false, transformFunction: null }, skeletonAnimation: { classPropertyName: "skeletonAnimation", publicName: "skeletonAnimation", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"c-img-preview\" \n [class.c-img-preview--loading]=\"isImageLoading() && showSkeleton()\"\n [class.c-img-preview--error]=\"hasImageError()\"\n [style.width]=\"width()\"\n [style.height]=\"height()\"\n [style.border-radius]=\"borderRadius()\"\n [style.position]=\"isRelative() ? 'relative' : 'static'\">\n \n @if (isImageLoading() && showSkeleton()) {\n <div class=\"c-img-preview__skeleton\"\n (click)=\"onSkeletonClick()\">\n <core-generic-skeleton \n [type]=\"SkeletonType.IMAGE\"\n [width]=\"width() || '100%'\"\n [height]=\"height() || '200px'\"\n [animation]=\"skeletonAnimation()\"\n [ariaLabel]=\"'Loading image: ' + (alt() || 'Image')\">\n </core-generic-skeleton>\n </div>\n }\n \n @if (!hasImageError()) {\n <img \n [src]=\"src()\" \n [alt]=\"alt()\"\n [title]=\"title()\"\n [loading]=\"loading()\"\n [style.object-fit]=\"objectFit()\"\n [style.border-radius]=\"borderRadius()\"\n [style.cursor]=\"cursor()\"\n [style.display]=\"isImageLoading() && showSkeleton() ? 'none' : 'block'\"\n (load)=\"onImageLoad()\"\n (error)=\"onImageError()\"\n (click)=\"onImageClick()\">\n }\n \n @if (hasImageError()) {\n <div class=\"c-img-preview__error\"\n [style.width]=\"width() || '100%'\"\n [style.height]=\"height() || '200px'\"\n [style.border-radius]=\"borderRadius()\">\n <div class=\"c-img-preview__error-content\">\n <span class=\"c-img-preview__error-icon\">\uD83D\uDCF7</span>\n <span class=\"c-img-preview__error-text\">Error al cargar imagen</span>\n </div>\n </div>\n }\n \n</div>", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: GenericSkeletonComponent, selector: "core-generic-skeleton", inputs: ["config", "items", "type", "size", "width", "height", "animated", "animation", "lines", "customClass", "ariaLabel"] }] });
982
1345
  }
983
1346
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: ImagePreviewComponent, decorators: [{
984
1347
  type: Component,
985
- args: [{ selector: 'core-image-preview', standalone: true, imports: [CommonModule], template: "<div class=\"c-img-preview\" \n (click)=\"onImageClick()\">\n <img \n [src]=\"src()\" \n [alt]=\"alt()\"\n [title]=\"title()\"\n [loading]=\"loading()\"\n [style.object-fit]=\"objectFit()\"\n [style.border-radius]=\"borderRadius()\"\n [style.cursor]=\"cursor()\">\n</div>" }]
1348
+ args: [{ selector: 'core-image-preview', standalone: true, imports: [CommonModule, GenericSkeletonComponent], template: "<div class=\"c-img-preview\" \n [class.c-img-preview--loading]=\"isImageLoading() && showSkeleton()\"\n [class.c-img-preview--error]=\"hasImageError()\"\n [style.width]=\"width()\"\n [style.height]=\"height()\"\n [style.border-radius]=\"borderRadius()\"\n [style.position]=\"isRelative() ? 'relative' : 'static'\">\n \n @if (isImageLoading() && showSkeleton()) {\n <div class=\"c-img-preview__skeleton\"\n (click)=\"onSkeletonClick()\">\n <core-generic-skeleton \n [type]=\"SkeletonType.IMAGE\"\n [width]=\"width() || '100%'\"\n [height]=\"height() || '200px'\"\n [animation]=\"skeletonAnimation()\"\n [ariaLabel]=\"'Loading image: ' + (alt() || 'Image')\">\n </core-generic-skeleton>\n </div>\n }\n \n @if (!hasImageError()) {\n <img \n [src]=\"src()\" \n [alt]=\"alt()\"\n [title]=\"title()\"\n [loading]=\"loading()\"\n [style.object-fit]=\"objectFit()\"\n [style.border-radius]=\"borderRadius()\"\n [style.cursor]=\"cursor()\"\n [style.display]=\"isImageLoading() && showSkeleton() ? 'none' : 'block'\"\n (load)=\"onImageLoad()\"\n (error)=\"onImageError()\"\n (click)=\"onImageClick()\">\n }\n \n @if (hasImageError()) {\n <div class=\"c-img-preview__error\"\n [style.width]=\"width() || '100%'\"\n [style.height]=\"height() || '200px'\"\n [style.border-radius]=\"borderRadius()\">\n <div class=\"c-img-preview__error-content\">\n <span class=\"c-img-preview__error-icon\">\uD83D\uDCF7</span>\n <span class=\"c-img-preview__error-text\">Error al cargar imagen</span>\n </div>\n </div>\n }\n \n</div>" }]
986
1349
  }] });
987
1350
 
988
1351
  class FileFieldComponent extends BaseFieldComponent {
@@ -1470,7 +1833,7 @@ class FileFieldComponent extends BaseFieldComponent {
1470
1833
  this.onBlur();
1471
1834
  }
1472
1835
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: FileFieldComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1473
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: FileFieldComponent, isStandalone: true, selector: "core-file-field", usesInheritance: true, hostDirectives: [{ directive: CoreHostDirective }], ngImport: i0, template: "<label class=\"c-entry-item\" [class.c-entry-item--inline]=\"field().inline\">\n @if (field().label) {\n <span class=\"c-entry-text\">\n {{ field().label | translate }}\n @if (hasRequiredValidators()) {\n <span class=\"c-required\">*</span>\n }\n </span>\n }\n <div class=\"c-entry-file\" [class.has-error]=\"hasError()\">\n @if(fieldConfig().multiple || isEditMode() || allFiles().length === 0) {\n <label class=\"c-entry-file__label\">\n <span class=\"icon-upload c-entry-file__icon\"></span>\n <input\n type=\"file\"\n class=\"c-entry-file__input\"\n (change)=\"onFileSelected($event)\"\n [accept]=\"fieldConfig().accept\"\n [multiple]=\"fieldConfig().multiple\"\n (blur)=\"onBlurInput()\"\n [readonly]=\"isReadonly()\"\n >\n {{ fieldConfig().placeholder ?? fieldConfig().label | translate }}\n @if(fieldConfig().acceptString) {\n <br>\n <span class=\"c-entry-file__filename\" id=\"file-name\">{{ fieldConfig().acceptString }}</span>\n }\n </label>\n }\n\n @if (allFiles().length > 0) {\n <div class=\"c-attachments\">\n <p class=\"c-entry-text\">{{ 'files.attachedFiles' | translate }}</p>\n \n <ul class=\"c-attachments__list\">\n @for (file of allFiles(); track $index; let i = $index) {\n <li class=\"c-attachments__item\">\n <div class=\"c-bulleted-text\">\n @if(!isServerFile(file)) {\n <time>{{ getCurrentDate() }}</time>\n <span>{{ getCurrentUser() }}</span>\n }\n </div>\n \n <div class=\"c-attachments__holder\">\n @if(!isServerFile(file) && file.type.startsWith('image/') && fieldConfig().showPreview !== false) {\n <div class=\"c-attachments__content\">\n <div class=\"c-attachments__pic\">\n @if(isPreviewFile(file) && getOriginalUrl(file)) {\n <core-image-preview\n [src]=\"getOriginalUrl(file)!\"\n [alt]=\"file.name\"\n ></core-image-preview>\n } @else if(getPreviewUrl(file)) {\n <core-image-preview\n [src]=\"getPreviewUrl(file)!\"\n [alt]=\"file.name\"\n ></core-image-preview>\n }\n </div>\n <div class=\"c-attachments__text\">\n <span class=\"c-attachments__name-file\">{{ file.name }}</span>\n <span class=\"c-attachments__file-size\">({{ formatFileSize(file.size) }})</span>\n </div>\n </div>\n } @else {\n <a class=\"c-attachments__content\">\n @if(isServerFile(file)) {\n <span class=\"icon-file\"></span>\n {{ file.filename }}\n } @else {\n <span [class]=\"getFileIcon(file)\"></span>\n <div class=\"c-attachments__text\">\n <span class=\"c-attachments__name-file\">{{ file.name }}</span>\n <span class=\"c-attachments__file-size\">({{ formatFileSize(file.size) }})</span>\n </div>\n }\n </a>\n }\n\n <div class=\"c-attachments__actions u-flex u-flex--wrap\">\n <button \n type=\"button\" \n class=\"c-link context:error\" \n (click)=\"removeFile(i)\"\n [title]=\"'files.remove' | translate\"\n >\n <span class=\"icon-delete\"></span>\n {{ 'files.remove' | translate }}\n </button>\n\n @if(fieldConfig().customActions) {\n @for(action of fieldConfig().customActions; track action.id) {\n <button \n type=\"button\"\n class=\"c-link c-link--underlined\" \n (click)=\"action.action(file)\"\n [title]=\"action.label | translate\"\n >\n {{ action.label | translate }}\n <span [ngClass]=\"action.icon | coreIconCompat\"></span>\n </button>\n }\n }\n </div>\n </div>\n </li>\n }\n </ul>\n </div>\n }\n </div>\n <core-field-errors [errors]=\"errors()\" />\n @if(displayErrorMessage()) {\n <span class=\"c-entry-error\">{{ displayErrorMessage()!.key | translate:displayErrorMessage()!.params }}</span>\n }\n</label>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: FieldErrorsComponent, selector: "core-field-errors", inputs: ["errors"] }, { kind: "pipe", type: IconCompatPipe, name: "coreIconCompat" }, { kind: "component", type: ImagePreviewComponent, selector: "core-image-preview", inputs: ["src", "alt", "title", "width", "height", "objectFit", "borderRadius", "cursor", "loading", "isRelative"] }] });
1836
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: FileFieldComponent, isStandalone: true, selector: "core-file-field", usesInheritance: true, hostDirectives: [{ directive: CoreHostDirective }], ngImport: i0, template: "<label class=\"c-entry-item\" [class.c-entry-item--inline]=\"field().inline\">\n @if (field().label) {\n <span class=\"c-entry-text\">\n {{ field().label | translate }}\n @if (hasRequiredValidators()) {\n <span class=\"c-required\">*</span>\n }\n </span>\n }\n <div class=\"c-entry-file\" [class.has-error]=\"hasError()\">\n @if(fieldConfig().multiple || isEditMode() || allFiles().length === 0) {\n <label class=\"c-entry-file__label\">\n <span class=\"icon-upload c-entry-file__icon\"></span>\n <input\n type=\"file\"\n class=\"c-entry-file__input\"\n (change)=\"onFileSelected($event)\"\n [accept]=\"fieldConfig().accept\"\n [multiple]=\"fieldConfig().multiple\"\n (blur)=\"onBlurInput()\"\n [readonly]=\"isReadonly()\"\n >\n {{ fieldConfig().placeholder ?? fieldConfig().label | translate }}\n @if(fieldConfig().acceptString) {\n <br>\n <span class=\"c-entry-file__filename\" id=\"file-name\">{{ fieldConfig().acceptString }}</span>\n }\n </label>\n }\n\n @if (allFiles().length > 0) {\n <div class=\"c-attachments\">\n <p class=\"c-entry-text\">{{ 'files.attachedFiles' | translate }}</p>\n \n <ul class=\"c-attachments__list\">\n @for (file of allFiles(); track $index; let i = $index) {\n <li class=\"c-attachments__item\">\n <div class=\"c-bulleted-text\">\n @if(!isServerFile(file)) {\n <time>{{ getCurrentDate() }}</time>\n <span>{{ getCurrentUser() }}</span>\n }\n </div>\n \n <div class=\"c-attachments__holder\">\n @if(!isServerFile(file) && file.type.startsWith('image/') && fieldConfig().showPreview !== false) {\n <div class=\"c-attachments__content\">\n <div class=\"c-attachments__pic\">\n @if(isPreviewFile(file) && getOriginalUrl(file)) {\n <core-image-preview\n [src]=\"getOriginalUrl(file)!\"\n [alt]=\"file.name\"\n ></core-image-preview>\n } @else if(getPreviewUrl(file)) {\n <core-image-preview\n [src]=\"getPreviewUrl(file)!\"\n [alt]=\"file.name\"\n ></core-image-preview>\n }\n </div>\n <div class=\"c-attachments__text\">\n <span class=\"c-attachments__name-file\">{{ file.name }}</span>\n <span class=\"c-attachments__file-size\">({{ formatFileSize(file.size) }})</span>\n </div>\n </div>\n } @else {\n <a class=\"c-attachments__content\">\n @if(isServerFile(file)) {\n <span class=\"icon-file\"></span>\n {{ file.filename }}\n } @else {\n <span [class]=\"getFileIcon(file)\"></span>\n <div class=\"c-attachments__text\">\n <span class=\"c-attachments__name-file\">{{ file.name }}</span>\n <span class=\"c-attachments__file-size\">({{ formatFileSize(file.size) }})</span>\n </div>\n }\n </a>\n }\n\n <div class=\"c-attachments__actions u-flex u-flex--wrap\">\n <button \n type=\"button\" \n class=\"c-link context:error\" \n (click)=\"removeFile(i)\"\n [title]=\"'files.remove' | translate\"\n >\n <span class=\"icon-delete\"></span>\n {{ 'files.remove' | translate }}\n </button>\n\n @if(fieldConfig().customActions) {\n @for(action of fieldConfig().customActions; track action.id) {\n <button \n type=\"button\"\n class=\"c-link c-link--underlined\" \n (click)=\"action.action(file)\"\n [title]=\"action.label | translate\"\n >\n {{ action.label | translate }}\n <span [ngClass]=\"action.icon | coreIconCompat\"></span>\n </button>\n }\n }\n </div>\n </div>\n </li>\n }\n </ul>\n </div>\n }\n </div>\n <core-field-errors [errors]=\"errors()\" />\n @if(displayErrorMessage()) {\n <span class=\"c-entry-error\">{{ displayErrorMessage()!.key | translate:displayErrorMessage()!.params }}</span>\n }\n</label>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: FieldErrorsComponent, selector: "core-field-errors", inputs: ["errors"] }, { kind: "pipe", type: IconCompatPipe, name: "coreIconCompat" }, { kind: "component", type: ImagePreviewComponent, selector: "core-image-preview", inputs: ["src", "alt", "title", "width", "height", "objectFit", "borderRadius", "cursor", "loading", "isRelative", "showSkeleton", "skeletonAnimation"] }] });
1474
1837
  }
1475
1838
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: FileFieldComponent, decorators: [{
1476
1839
  type: Component,
@@ -11622,11 +11985,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
11622
11985
  // Este archivo es generado automáticamente por scripts/update-version.js
11623
11986
  // No edites manualmente este archivo
11624
11987
  const VERSION = {
11625
- full: '2.12.12',
11988
+ full: '2.12.14',
11626
11989
  major: 2,
11627
11990
  minor: 12,
11628
- patch: 12,
11629
- timestamp: '2025-09-08T12:06:21.236Z',
11991
+ patch: 14,
11992
+ timestamp: '2025-09-08T19:40:24.625Z',
11630
11993
  buildDate: '8/9/2025'
11631
11994
  };
11632
11995
 
@@ -13204,7 +13567,7 @@ class CarouselComponent {
13204
13567
  };
13205
13568
  }
13206
13569
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: CarouselComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
13207
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: CarouselComponent, isStandalone: true, selector: "core-carousel", inputs: { images: { classPropertyName: "images", publicName: "images", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "window:resize": "onResize()", "keydown": "onKeyDown($event)" } }, viewQueries: [{ propertyName: "carouselHolder", first: true, predicate: ["carouselHolder"], descendants: true, isSignal: true }, { propertyName: "carouselViewport", first: true, predicate: ["carouselViewport"], descendants: true, isSignal: true }], ngImport: i0, template: "<div \n [ngClass]=\"carouselClasses()\"\n [attr.aria-label]=\"ariaLabel()\"\n tabindex=\"0\"\n #carouselViewport\n [class.is-multiple]=\"perView() > 1\">\n \n <div class=\"c-img-carousel__viewport\">\n <div class=\"c-img-carousel__holder js-img-carousel-holder\" #carouselHolder>\n <div \n *ngFor=\"let image of images(); let i = index\"\n class=\"c-img-carousel__slide js-img-carousel-slide\">\n <div class=\"c-img-carousel__slide-inner\">\n <core-image-preview\n [src]=\"image.url\"\n [alt]=\"image.alt || 'Image ' + (i + 1)\"\n [title]=\"image.title || image.alt || 'Image ' + (i + 1)\">\n </core-image-preview>\n </div>\n </div>\n </div>\n \n @if (!config().arrowsOutside) {\n <button \n *ngIf=\"showArrows()\"\n class=\"c-img-carousel__btn c-img-carousel__btn--prev icon-arrow-left\"\n type=\"button\"\n (click)=\"goToPrevSlide()\"\n [attr.aria-label]=\"'Anterior'\"\n data-control=\"prevBtn\">\n </button>\n \n <button \n *ngIf=\"showArrows()\"\n class=\"c-img-carousel__btn c-img-carousel__btn--next icon-arrow-right\"\n type=\"button\"\n (click)=\"goToNextSlide()\"\n [attr.aria-label]=\"'Siguiente'\"\n data-control=\"nextBtn\">\n </button>\n }\n \n <div \n *ngIf=\"showDots()\"\n class=\"c-img-carousel__dots js-img-carousel-nav\"\n aria-label=\"Navegaci\u00F3n\">\n <button\n *ngFor=\"let page of dots(); let i = index\"\n class=\"c-img-carousel__dot js-img-carousel-dot\"\n type=\"button\"\n (click)=\"goToPage(i)\"\n [class.c-img-carousel__dot--active]=\"currentPage() === i\"\n [attr.aria-label]=\"'Ir a p\u00E1gina ' + (i + 1)\"\n [attr.aria-current]=\"currentPage() === i ? 'true' : 'false'\">\n </button>\n </div>\n </div>\n @if(config().arrowsOutside) {\n <button \n *ngIf=\"showArrows()\"\n class=\"c-img-carousel__btn c-img-carousel__btn--prev icon-arrow-left\"\n type=\"button\"\n (click)=\"goToPrevSlide()\"\n [attr.aria-label]=\"'Anterior'\"\n data-control=\"prevBtn\">\n </button>\n \n <button \n *ngIf=\"showArrows()\"\n class=\"c-img-carousel__btn c-img-carousel__btn--next icon-arrow-right\"\n type=\"button\"\n (click)=\"goToNextSlide()\"\n [attr.aria-label]=\"'Siguiente'\"\n data-control=\"nextBtn\">\n </button>\n }\n</div>", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: ImagePreviewComponent, selector: "core-image-preview", inputs: ["src", "alt", "title", "width", "height", "objectFit", "borderRadius", "cursor", "loading", "isRelative"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
13570
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: CarouselComponent, isStandalone: true, selector: "core-carousel", inputs: { images: { classPropertyName: "images", publicName: "images", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "window:resize": "onResize()", "keydown": "onKeyDown($event)" } }, viewQueries: [{ propertyName: "carouselHolder", first: true, predicate: ["carouselHolder"], descendants: true, isSignal: true }, { propertyName: "carouselViewport", first: true, predicate: ["carouselViewport"], descendants: true, isSignal: true }], ngImport: i0, template: "<div \n [ngClass]=\"carouselClasses()\"\n [attr.aria-label]=\"ariaLabel()\"\n tabindex=\"0\"\n #carouselViewport\n [class.is-multiple]=\"perView() > 1\">\n \n <div class=\"c-img-carousel__viewport\">\n <div class=\"c-img-carousel__holder js-img-carousel-holder\" #carouselHolder>\n <div \n *ngFor=\"let image of images(); let i = index\"\n class=\"c-img-carousel__slide js-img-carousel-slide\">\n <div class=\"c-img-carousel__slide-inner\">\n <core-image-preview\n [src]=\"image.url\"\n [alt]=\"image.alt || 'Image ' + (i + 1)\"\n [title]=\"image.title || image.alt || 'Image ' + (i + 1)\">\n </core-image-preview>\n </div>\n </div>\n </div>\n \n @if (!config().arrowsOutside) {\n <button \n *ngIf=\"showArrows()\"\n class=\"c-img-carousel__btn c-img-carousel__btn--prev icon-arrow-left\"\n type=\"button\"\n (click)=\"goToPrevSlide()\"\n [attr.aria-label]=\"'Anterior'\"\n data-control=\"prevBtn\">\n </button>\n \n <button \n *ngIf=\"showArrows()\"\n class=\"c-img-carousel__btn c-img-carousel__btn--next icon-arrow-right\"\n type=\"button\"\n (click)=\"goToNextSlide()\"\n [attr.aria-label]=\"'Siguiente'\"\n data-control=\"nextBtn\">\n </button>\n }\n \n <div \n *ngIf=\"showDots()\"\n class=\"c-img-carousel__dots js-img-carousel-nav\"\n aria-label=\"Navegaci\u00F3n\">\n <button\n *ngFor=\"let page of dots(); let i = index\"\n class=\"c-img-carousel__dot js-img-carousel-dot\"\n type=\"button\"\n (click)=\"goToPage(i)\"\n [class.c-img-carousel__dot--active]=\"currentPage() === i\"\n [attr.aria-label]=\"'Ir a p\u00E1gina ' + (i + 1)\"\n [attr.aria-current]=\"currentPage() === i ? 'true' : 'false'\">\n </button>\n </div>\n </div>\n @if(config().arrowsOutside) {\n <button \n *ngIf=\"showArrows()\"\n class=\"c-img-carousel__btn c-img-carousel__btn--prev icon-arrow-left\"\n type=\"button\"\n (click)=\"goToPrevSlide()\"\n [attr.aria-label]=\"'Anterior'\"\n data-control=\"prevBtn\">\n </button>\n \n <button \n *ngIf=\"showArrows()\"\n class=\"c-img-carousel__btn c-img-carousel__btn--next icon-arrow-right\"\n type=\"button\"\n (click)=\"goToNextSlide()\"\n [attr.aria-label]=\"'Siguiente'\"\n data-control=\"nextBtn\">\n </button>\n }\n</div>", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: ImagePreviewComponent, selector: "core-image-preview", inputs: ["src", "alt", "title", "width", "height", "objectFit", "borderRadius", "cursor", "loading", "isRelative", "showSkeleton", "skeletonAnimation"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
13208
13571
  }
13209
13572
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: CarouselComponent, decorators: [{
13210
13573
  type: Component,
@@ -13544,5 +13907,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
13544
13907
  * Generated bundle index. Do not edit.
13545
13908
  */
13546
13909
 
13547
- export { ActiveFiltersComponent, AlertComponent, AlertContainerComponent, AlertService, AlertType, ApiConfigurationProvider, BaseFieldComponent, ButtonContext, ButtonSize, ButtonType, CacheBustingInterceptor, CardComponent, CarouselComponent, CheckboxFieldComponent, ConfigurationModel, ConfirmationDialogComponent, ConfirmationDialogService, CoreHostDirective, CoreUiHttpLoaderFactory, CoreUiTranslateLoader, CoreUiTranslateService, DataListComponent, DataListItemComponent, DateFieldComponent, DateUtility, DatetimeFieldComponent, DialogActions, DocumentAction, DocumentDisplayMode, DropdownComponent, DropdownDirection, DropdownService, DynamicFieldDirective, DynamicFieldsHelper, FieldErrorsComponent, FieldType, FileFieldComponent, FileModel, FileTemplateModel, FileTemplateType, FileType, FileTypeModel, FileUploadService, FilterModalComponent, FilterService, FilterType, GenericButtonComponent, GenericDocumentationComponent, GenericModalComponent, GenericPaginationComponent, GenericRatingComponent, GenericSidebarComponent, GenericStepsComponent, GenericTableComponent, GenericTabsComponent, GenericTimelineComponent, GlobalApiConfigService, HeaderComponent, HeaderConfigurationService, HeaderElementType, HeaderService, HttpLoaderFactory, ImageModalComponent, ImageModalService, ImagePreviewComponent, LayoutAuth, LayoutBreakpoint, LayoutComponent, LayoutService, LayoutStateService, LayoutType, LoaderComponent, LoaderService, MainNavComponent, MainNavService, ModalMode, ModelApiService, MultiEntryFieldComponent, MultiEntryOutputFormat, NumberFieldComponent, NumberFieldConfigType, NumberFieldType, NumberRange, PERMISSION_ACTIONS_PROVIDER, PERMISSION_PROVIDER, PERMISSION_RESOURCES_PROVIDER, PaginationService, PasswordFieldComponent, PermissionEnumsService, PermissionModel, PermissionService, PermissionWrapperService, PermissionsActions, PermissionsInterceptor, PermissionsResources, ProgressBarComponent, ProgressBarSize, RatingService, RatingSize, RatingType, ResetPasswordModel, RoleModel, SelectFieldComponent, ServerSelectFieldComponent, ServerSelectService, SidebarCustomModalComponent, SidebarCustomModalService, SidebarHeight, SidebarMobileModalService, SidebarMobileType, SidebarPosition, SidebarService, SidebarState, SidebarTemplateRegistryService, SidebarVisibility, SidebarWidth, SmartFieldComponent, SortDirection, SortMode, StepSize, StepStatus, StepType, StepsService, SwitchFieldComponent, TableAction, TableActionService, TableDataService, TableSortService, TextAreaFieldComponent, TextFieldComponent, TimeFieldComponent, TimeInterval, TimelineService, TimelineStatus, TimelineType, TranslationMergeService, UsersModel, VERSION, equalToValidator, isSameDate, provideCoreUiTranslateLoader, providePermissionActions, providePermissionEnums, providePermissionResources, providePermissionService, providePermissionServiceFactory, provideTranslateLoader };
13910
+ export { ActiveFiltersComponent, AlertComponent, AlertContainerComponent, AlertService, AlertType, ApiConfigurationProvider, BaseFieldComponent, ButtonContext, ButtonSize, ButtonType, CacheBustingInterceptor, CardComponent, CarouselComponent, CheckboxFieldComponent, ConfigurationModel, ConfirmationDialogComponent, ConfirmationDialogService, CoreHostDirective, CoreUiHttpLoaderFactory, CoreUiTranslateLoader, CoreUiTranslateService, DataListComponent, DataListItemComponent, DateFieldComponent, DateUtility, DatetimeFieldComponent, DialogActions, DocumentAction, DocumentDisplayMode, DropdownComponent, DropdownDirection, DropdownService, DynamicFieldDirective, DynamicFieldsHelper, FieldErrorsComponent, FieldType, FileFieldComponent, FileModel, FileTemplateModel, FileTemplateType, FileType, FileTypeModel, FileUploadService, FilterModalComponent, FilterService, FilterType, GenericButtonComponent, GenericDocumentationComponent, GenericModalComponent, GenericPaginationComponent, GenericRatingComponent, GenericSidebarComponent, GenericSkeletonComponent, GenericStepsComponent, GenericTableComponent, GenericTabsComponent, GenericTimelineComponent, GlobalApiConfigService, HeaderComponent, HeaderConfigurationService, HeaderElementType, HeaderService, HttpLoaderFactory, ImageModalComponent, ImageModalService, ImagePreviewComponent, LayoutAuth, LayoutBreakpoint, LayoutComponent, LayoutService, LayoutStateService, LayoutType, LoaderComponent, LoaderService, MainNavComponent, MainNavService, ModalMode, ModelApiService, MultiEntryFieldComponent, MultiEntryOutputFormat, NumberFieldComponent, NumberFieldConfigType, NumberFieldType, NumberRange, PERMISSION_ACTIONS_PROVIDER, PERMISSION_PROVIDER, PERMISSION_RESOURCES_PROVIDER, PaginationService, PasswordFieldComponent, PermissionEnumsService, PermissionModel, PermissionService, PermissionWrapperService, PermissionsActions, PermissionsInterceptor, PermissionsResources, ProgressBarComponent, ProgressBarSize, RatingService, RatingSize, RatingType, ResetPasswordModel, RoleModel, SelectFieldComponent, ServerSelectFieldComponent, ServerSelectService, SidebarCustomModalComponent, SidebarCustomModalService, SidebarHeight, SidebarMobileModalService, SidebarMobileType, SidebarPosition, SidebarService, SidebarState, SidebarTemplateRegistryService, SidebarVisibility, SidebarWidth, SkeletonAnimation, SkeletonService, SkeletonSize, SkeletonType, SmartFieldComponent, SortDirection, SortMode, StepSize, StepStatus, StepType, StepsService, SwitchFieldComponent, TableAction, TableActionService, TableDataService, TableSortService, TextAreaFieldComponent, TextFieldComponent, TimeFieldComponent, TimeInterval, TimelineService, TimelineStatus, TimelineType, TranslationMergeService, UsersModel, VERSION, equalToValidator, isSameDate, provideCoreUiTranslateLoader, providePermissionActions, providePermissionEnums, providePermissionResources, providePermissionService, providePermissionServiceFactory, provideTranslateLoader };
13548
13911
  //# sourceMappingURL=solcre-org-core-ui.mjs.map