valtech-components 2.0.734 → 2.0.736

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.
@@ -50,7 +50,7 @@ import 'prismjs/components/prism-json';
50
50
  * Current version of valtech-components.
51
51
  * This is automatically updated during the publish process.
52
52
  */
53
- const VERSION = '2.0.734';
53
+ const VERSION = '2.0.737';
54
54
 
55
55
  /**
56
56
  * Servicio para gestionar presets de componentes.
@@ -24368,7 +24368,7 @@ class UsernameInputComponent {
24368
24368
  </ion-text>
24369
24369
  }
24370
24370
  </div>
24371
- `, isInline: true, styles: [".username-input-container{margin-bottom:1rem}.username-label{display:block;font-size:.875rem;font-weight:500;color:var(--ion-color-dark);margin-bottom:.5rem}.username-input-wrapper{display:flex;align-items:center;background:var(--ion-background-color, #fff);border:1px solid var(--ion-border-color, #e0e0e0);border-radius:8px;padding:0 .75rem;transition:border-color .2s,box-shadow .2s}.username-input-wrapper.focused{border-color:var(--ion-color-primary);box-shadow:0 0 0 2px var(--ion-color-primary-tint)}.username-input-wrapper.error{border-color:var(--ion-color-danger)}.username-prefix{font-size:1rem;font-weight:500;color:var(--ion-color-medium);-webkit-user-select:none;user-select:none}.username-field{flex:1;--padding-start: .25rem;--padding-end: 0;--background: transparent;--border-style: none;--border-width: 0;--border-color: transparent;--highlight-color-focused: transparent;--highlight-color-valid: transparent;--highlight-color-invalid: transparent;--box-shadow: none;font-size:1rem}.username-field::part(native){padding-left:.25rem;border:none;background:transparent;box-shadow:none}.availability-indicator{display:flex;align-items:center;justify-content:center;width:24px;height:24px;margin-left:.5rem}.checking-spinner{width:18px;height:18px;--color: var(--ion-color-medium)}.status-icon{font-size:1.25rem}.status-icon.available{color:var(--ion-color-success)}.status-icon.taken{color:var(--ion-color-danger)}.status-icon.invalid{color:var(--ion-color-warning)}.status-message,.error-message{display:block;margin-top:.25rem;padding-left:.25rem}:host-context(body.dark){.username-input-wrapper{background:var(--ion-color-step-50);border-color:var(--ion-color-step-150)}.username-label{color:var(--ion-color-light)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1$3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }] }); }
24371
+ `, isInline: true, styles: [".username-input-container{margin-bottom:1rem}.username-label{display:block;font-size:.875rem;font-weight:500;color:var(--ion-color-dark);margin-bottom:.5rem}.username-input-wrapper{display:flex;align-items:center;gap:.5rem;position:relative}.username-prefix{position:absolute;left:.75rem;top:50%;transform:translateY(-50%);font-size:1rem;font-weight:500;color:var(--ion-color-medium);-webkit-user-select:none;user-select:none;z-index:2;pointer-events:none}.username-field{flex:1}.username-field::part(native){padding-left:1.75rem}.availability-indicator{display:flex;align-items:center;justify-content:center;width:24px;height:24px;margin-left:.5rem}.checking-spinner{width:18px;height:18px;--color: var(--ion-color-medium)}.status-icon{font-size:1.25rem}.status-icon.available{color:var(--ion-color-success)}.status-icon.taken{color:var(--ion-color-danger)}.status-icon.invalid{color:var(--ion-color-warning)}.status-message,.error-message{display:block;margin-top:.25rem;padding-left:.25rem}:host-context(body.dark){.username-input-wrapper{background:var(--ion-color-step-50);border-color:var(--ion-color-step-150)}.username-label{color:var(--ion-color-light)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1$3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }] }); }
24372
24372
  }
24373
24373
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: UsernameInputComponent, decorators: [{
24374
24374
  type: Component,
@@ -24423,7 +24423,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
24423
24423
  </ion-text>
24424
24424
  }
24425
24425
  </div>
24426
- `, styles: [".username-input-container{margin-bottom:1rem}.username-label{display:block;font-size:.875rem;font-weight:500;color:var(--ion-color-dark);margin-bottom:.5rem}.username-input-wrapper{display:flex;align-items:center;background:var(--ion-background-color, #fff);border:1px solid var(--ion-border-color, #e0e0e0);border-radius:8px;padding:0 .75rem;transition:border-color .2s,box-shadow .2s}.username-input-wrapper.focused{border-color:var(--ion-color-primary);box-shadow:0 0 0 2px var(--ion-color-primary-tint)}.username-input-wrapper.error{border-color:var(--ion-color-danger)}.username-prefix{font-size:1rem;font-weight:500;color:var(--ion-color-medium);-webkit-user-select:none;user-select:none}.username-field{flex:1;--padding-start: .25rem;--padding-end: 0;--background: transparent;--border-style: none;--border-width: 0;--border-color: transparent;--highlight-color-focused: transparent;--highlight-color-valid: transparent;--highlight-color-invalid: transparent;--box-shadow: none;font-size:1rem}.username-field::part(native){padding-left:.25rem;border:none;background:transparent;box-shadow:none}.availability-indicator{display:flex;align-items:center;justify-content:center;width:24px;height:24px;margin-left:.5rem}.checking-spinner{width:18px;height:18px;--color: var(--ion-color-medium)}.status-icon{font-size:1.25rem}.status-icon.available{color:var(--ion-color-success)}.status-icon.taken{color:var(--ion-color-danger)}.status-icon.invalid{color:var(--ion-color-warning)}.status-message,.error-message{display:block;margin-top:.25rem;padding-left:.25rem}:host-context(body.dark){.username-input-wrapper{background:var(--ion-color-step-50);border-color:var(--ion-color-step-150)}.username-label{color:var(--ion-color-light)}}\n"] }]
24426
+ `, styles: [".username-input-container{margin-bottom:1rem}.username-label{display:block;font-size:.875rem;font-weight:500;color:var(--ion-color-dark);margin-bottom:.5rem}.username-input-wrapper{display:flex;align-items:center;gap:.5rem;position:relative}.username-prefix{position:absolute;left:.75rem;top:50%;transform:translateY(-50%);font-size:1rem;font-weight:500;color:var(--ion-color-medium);-webkit-user-select:none;user-select:none;z-index:2;pointer-events:none}.username-field{flex:1}.username-field::part(native){padding-left:1.75rem}.availability-indicator{display:flex;align-items:center;justify-content:center;width:24px;height:24px;margin-left:.5rem}.checking-spinner{width:18px;height:18px;--color: var(--ion-color-medium)}.status-icon{font-size:1.25rem}.status-icon.available{color:var(--ion-color-success)}.status-icon.taken{color:var(--ion-color-danger)}.status-icon.invalid{color:var(--ion-color-warning)}.status-message,.error-message{display:block;margin-top:.25rem;padding-left:.25rem}:host-context(body.dark){.username-input-wrapper{background:var(--ion-color-step-50);border-color:var(--ion-color-step-150)}.username-label{color:var(--ion-color-light)}}\n"] }]
24427
24427
  }], propDecorators: { props: [{
24428
24428
  type: Input
24429
24429
  }] } });
@@ -26027,6 +26027,12 @@ class FormComponent {
26027
26027
  this.types = InputType;
26028
26028
  this.subscriptions = [];
26029
26029
  this.actionsCache = [];
26030
+ // Memo de getFieldProp/getUsernameProp por referencia de field — evita
26031
+ // crear un nuevo objeto props por keystroke (cada CD cycle invocaría el
26032
+ // template binding, multiplicando re-renders en cascada por # fields).
26033
+ // WeakMap: si la referencia del field cambia, el cache se libera.
26034
+ this.fieldPropMemo = new WeakMap();
26035
+ this.usernamePropMemo = new WeakMap();
26030
26036
  }
26031
26037
  ngOnInit() {
26032
26038
  const formControls = {};
@@ -26136,16 +26142,24 @@ class FormComponent {
26136
26142
  return this.Form.get(field);
26137
26143
  }
26138
26144
  getFieldProp(field) {
26145
+ const cached = this.fieldPropMemo.get(field);
26146
+ if (cached)
26147
+ return cached;
26139
26148
  if (!field.token) {
26140
26149
  field.token = `input-${field.type}-${field.name}`;
26141
26150
  }
26151
+ let result;
26142
26152
  if (field.type === this.types.NUMBER_FROM_TO) {
26143
26153
  const fromControl = this.getControl(`${field.name}_from`);
26144
26154
  const toControl = this.getControl(`${field.name}_to`);
26145
- return { ...field, fromControl, toControl, control: undefined };
26155
+ result = { ...field, fromControl, toControl, control: undefined };
26146
26156
  }
26147
- const control = this.getControl(field.name);
26148
- return { ...field, control };
26157
+ else {
26158
+ const control = this.getControl(field.name);
26159
+ result = { ...field, control };
26160
+ }
26161
+ this.fieldPropMemo.set(field, result);
26162
+ return result;
26149
26163
  }
26150
26164
  /**
26151
26165
  * Adapter — convierte un `InputMetadata` (con type=HANDLE) a `UsernameInputMetadata`.
@@ -26154,8 +26168,11 @@ class FormComponent {
26154
26168
  * custom usando type=TEXT si necesita otra fuente de truth.
26155
26169
  */
26156
26170
  getUsernameProp(field) {
26171
+ const cached = this.usernamePropMemo.get(field);
26172
+ if (cached)
26173
+ return cached;
26157
26174
  const control = this.getControl(field.name);
26158
- return {
26175
+ const result = {
26159
26176
  control: control,
26160
26177
  label: field.label,
26161
26178
  placeholder: field.placeholder,
@@ -26164,6 +26181,8 @@ class FormComponent {
26164
26181
  errors: field.errors,
26165
26182
  state: field.state,
26166
26183
  };
26184
+ this.usernamePropMemo.set(field, result);
26185
+ return result;
26167
26186
  }
26168
26187
  get isAtEndOfForm() {
26169
26188
  return isAtEnd(this.elementRef);
@@ -26182,94 +26201,102 @@ class FormComponent {
26182
26201
  return this.actionsCache;
26183
26202
  }
26184
26203
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FormComponent, deps: [{ token: i1$3.FormBuilder }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
26185
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: FormComponent, isStandalone: true, selector: "val-form", inputs: { props: "props" }, outputs: { onSubmit: "onSubmit", onInvalid: "onInvalid", onSelectChange: "onSelectChange" }, usesOnChanges: true, ngImport: i0, template: `
26204
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: FormComponent, isStandalone: true, selector: "val-form", inputs: { props: "props" }, outputs: { onSubmit: "onSubmit", onInvalid: "onInvalid", onSelectChange: "onSelectChange" }, usesOnChanges: true, ngImport: i0, template: `
26186
26205
  <div class="container">
26187
26206
  <form [formGroup]="form">
26188
- <val-display
26189
- *ngIf="props.name"
26190
- [props]="{
26191
- content: props.name,
26192
- color: 'dark',
26193
- size: 'small',
26194
- }"
26195
- ></val-display>
26196
- <div class="section" *ngFor="let s of props.sections">
26197
- <val-title [props]="{ content: s.name, size: 'large', color: '', bold: false }"></val-title>
26198
- <div class="input" *ngFor="let f of s.fields">
26199
- <val-title
26200
- *ngIf="f.type !== types.PHONE"
26201
- [props]="{ content: f.label, size: 'small', color: 'dark', bold: false }"
26202
- ></val-title>
26203
- <span *ngIf="f.description" class="field-description">{{ f.description }}</span>
26204
- <ng-container *ngIf="f.type === types.TEXT">
26205
- <val-text-input [props]="getFieldProp(f)"></val-text-input>
26206
- </ng-container>
26207
- <ng-container *ngIf="f.type === types.CHECK">
26208
- <val-check-input></val-check-input>
26209
- </ng-container>
26210
- <ng-container *ngIf="f.type === types.COMMENT">
26211
- <val-comment-input [props]="getFieldProp(f)"></val-comment-input>
26212
- </ng-container>
26213
- <ng-container *ngIf="f.type === types.DATE">
26214
- <val-date-input [props]="getFieldProp(f)"></val-date-input>
26215
- </ng-container>
26216
- <ng-container *ngIf="f.type === types.EMAIL">
26217
- <val-email-input [props]="getFieldProp(f)"></val-email-input>
26218
- </ng-container>
26219
- <ng-container *ngIf="f.type === types.FILE">
26220
- <val-file-input [props]="getFieldProp(f)"></val-file-input>
26221
- </ng-container>
26222
- <ng-container *ngIf="f.type === types.HOUR">
26223
- <val-hour-input [props]="getFieldProp(f)"></val-hour-input>
26224
- </ng-container>
26225
- <ng-container *ngIf="f.type === types.NUMBER">
26226
- <val-number-input [props]="getFieldProp(f)"></val-number-input>
26227
- </ng-container>
26228
- <ng-container *ngIf="f.type === types.NUMBER_FROM_TO">
26229
- <val-number-from-to [props]="getFieldProp(f)"></val-number-from-to>
26230
- </ng-container>
26231
- <ng-container *ngIf="f.type === types.PASSWORD">
26232
- <val-password-input [props]="getFieldProp(f)"></val-password-input>
26233
- </ng-container>
26234
- <ng-container *ngIf="f.type === types.PIN_CODE">
26235
- <val-pin-input [props]="getFieldProp(f)"></val-pin-input>
26236
- </ng-container>
26237
- <ng-container *ngIf="f.type === types.RADIO">
26238
- <val-radio-input [props]="getFieldProp(f)"></val-radio-input>
26239
- </ng-container>
26240
- <ng-container *ngIf="f.type === types.SELECT">
26241
- <val-select-input [props]="getFieldProp(f)"></val-select-input>
26242
- </ng-container>
26243
- <ng-container *ngIf="f.type === types.SEARCH_SELECT">
26244
- <val-select-search [props]="getFieldProp(f)"></val-select-search>
26245
- </ng-container>
26246
- <ng-container *ngIf="f.type === types.MULTI_SELECT">
26247
- <val-multi-select-search [props]="getFieldProp(f)"></val-multi-select-search>
26248
- </ng-container>
26249
- <ng-container *ngIf="f.type === types.PHONE">
26250
- <val-phone-input [props]="getFieldProp(f)"></val-phone-input>
26251
- </ng-container>
26252
- <ng-container *ngIf="f.type === types.HANDLE">
26253
- <val-username-input [props]="getUsernameProp(f)"></val-username-input>
26254
- </ng-container>
26255
- <ng-container *ngIf="f.type === types.TOGGLE">
26256
- <val-toggle-input [props]="getFieldProp(f)"></val-toggle-input>
26257
- </ng-container>
26258
- <ng-container *ngIf="f.type === types.CHECKBOX_RADIO">
26259
- <val-checkbox-radio-input [props]="getFieldProp(f)"></val-checkbox-radio-input>
26260
- </ng-container>
26261
- <val-hint [props]="getFieldProp(f)"></val-hint>
26207
+ @if (props.name) {
26208
+ <val-display
26209
+ [props]="{
26210
+ content: props.name,
26211
+ color: 'dark',
26212
+ size: 'small',
26213
+ }"
26214
+ ></val-display>
26215
+ }
26216
+ @for (s of props.sections; track s.name) {
26217
+ <div class="section">
26218
+ <val-title [props]="{ content: s.name, size: 'large', color: '', bold: false }"></val-title>
26219
+ @for (f of s.fields; track f.name) {
26220
+ <div class="input">
26221
+ @if (f.type !== types.PHONE && f.type !== types.HANDLE) {
26222
+ <val-title [props]="{ content: f.label, size: 'small', color: 'dark', bold: false }"></val-title>
26223
+ }
26224
+ @if (f.description) {
26225
+ <span class="field-description">{{ f.description }}</span>
26226
+ }
26227
+ @switch (f.type) {
26228
+ @case (types.TEXT) {
26229
+ <val-text-input [props]="getFieldProp(f)"></val-text-input>
26230
+ }
26231
+ @case (types.CHECK) {
26232
+ <val-check-input></val-check-input>
26233
+ }
26234
+ @case (types.COMMENT) {
26235
+ <val-comment-input [props]="getFieldProp(f)"></val-comment-input>
26236
+ }
26237
+ @case (types.DATE) {
26238
+ <val-date-input [props]="getFieldProp(f)"></val-date-input>
26239
+ }
26240
+ @case (types.EMAIL) {
26241
+ <val-email-input [props]="getFieldProp(f)"></val-email-input>
26242
+ }
26243
+ @case (types.FILE) {
26244
+ <val-file-input [props]="getFieldProp(f)"></val-file-input>
26245
+ }
26246
+ @case (types.HOUR) {
26247
+ <val-hour-input [props]="getFieldProp(f)"></val-hour-input>
26248
+ }
26249
+ @case (types.NUMBER) {
26250
+ <val-number-input [props]="getFieldProp(f)"></val-number-input>
26251
+ }
26252
+ @case (types.NUMBER_FROM_TO) {
26253
+ <val-number-from-to [props]="getFieldProp(f)"></val-number-from-to>
26254
+ }
26255
+ @case (types.PASSWORD) {
26256
+ <val-password-input [props]="getFieldProp(f)"></val-password-input>
26257
+ }
26258
+ @case (types.PIN_CODE) {
26259
+ <val-pin-input [props]="getFieldProp(f)"></val-pin-input>
26260
+ }
26261
+ @case (types.RADIO) {
26262
+ <val-radio-input [props]="getFieldProp(f)"></val-radio-input>
26263
+ }
26264
+ @case (types.SELECT) {
26265
+ <val-select-input [props]="getFieldProp(f)"></val-select-input>
26266
+ }
26267
+ @case (types.SEARCH_SELECT) {
26268
+ <val-select-search [props]="getFieldProp(f)"></val-select-search>
26269
+ }
26270
+ @case (types.MULTI_SELECT) {
26271
+ <val-multi-select-search [props]="getFieldProp(f)"></val-multi-select-search>
26272
+ }
26273
+ @case (types.PHONE) {
26274
+ <val-phone-input [props]="getFieldProp(f)"></val-phone-input>
26275
+ }
26276
+ @case (types.HANDLE) {
26277
+ <val-username-input [props]="getUsernameProp(f)"></val-username-input>
26278
+ }
26279
+ @case (types.TOGGLE) {
26280
+ <val-toggle-input [props]="getFieldProp(f)"></val-toggle-input>
26281
+ }
26282
+ @case (types.CHECKBOX_RADIO) {
26283
+ <val-checkbox-radio-input [props]="getFieldProp(f)"></val-checkbox-radio-input>
26284
+ }
26285
+ }
26286
+ <val-hint [props]="getFieldProp(f)"></val-hint>
26287
+ </div>
26288
+ }
26289
+ <val-divider [props]="{ fill: 'solid', size: 'medium', color: 'medium' }"></val-divider>
26290
+ <ng-content></ng-content>
26262
26291
  </div>
26263
- <val-divider [props]="{ fill: 'solid', size: 'medium', color: 'medium' }"></val-divider>
26264
- <ng-content></ng-content>
26265
- </div>
26292
+ }
26266
26293
  <val-button-group
26267
26294
  [props]="{ buttons: actions, position: 'center', columned: false }"
26268
26295
  (onClick)="submitHandler($event)"
26269
26296
  ></val-button-group>
26270
26297
  </form>
26271
26298
  </div>
26272
- `, isInline: true, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}@media (prefers-color-scheme: dark){:root{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}.section{margin-top:1rem}.input{margin:.5rem 0}@media (min-width: 768px){.input{margin:.75rem 0}}.field-description{display:block;font-size:.75rem;color:var(--ion-color-medium);margin-bottom:.25rem;line-height:1.4}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: DisplayComponent, selector: "val-display", inputs: ["props"] }, { kind: "component", type: TitleComponent, selector: "val-title", inputs: ["props"] }, { kind: "component", type: TextInputComponent, selector: "val-text-input", inputs: ["preset", "props"] }, { kind: "component", type: CheckInputComponent, selector: "val-check-input", inputs: ["preset", "props"] }, { kind: "component", type: ButtonGroupComponent, selector: "val-button-group", inputs: ["props"], outputs: ["onClick"] }, { kind: "component", type: DividerComponent, selector: "val-divider", inputs: ["props"] }, { kind: "component", type: HintComponent, selector: "val-hint", inputs: ["props"] }, { kind: "component", type: CommentInputComponent, selector: "val-comment-input", inputs: ["props"] }, { kind: "component", type: DateInputComponent, selector: "val-date-input", inputs: ["preset", "props"] }, { kind: "component", type: FileInputComponent, selector: "val-file-input", inputs: ["props"] }, { kind: "component", type: HourInputComponent, selector: "val-hour-input", inputs: ["props"] }, { kind: "component", type: EmailInputComponent, selector: "val-email-input", inputs: ["preset", "props"] }, { kind: "component", type: NumberInputComponent, selector: "val-number-input", inputs: ["props"] }, { kind: "component", type: NumberFromToComponent, selector: "val-number-from-to", inputs: ["props"] }, { kind: "component", type: RadioInputComponent, selector: "val-radio-input", inputs: ["props"] }, { kind: "component", type: PasswordInputComponent, selector: "val-password-input", inputs: ["preset", "props"] }, { kind: "component", type: PinInputComponent, selector: "val-pin-input", inputs: ["props"] }, { kind: "component", type: SelectSearchComponent, selector: "val-select-search", inputs: ["label", "labelProperty", "valueProperty", "multiple", "placeholder", "props"] }, { kind: "component", type: MultiSelectSearchComponent, selector: "val-multi-select-search", inputs: ["label", "labelProperty", "valueProperty", "placeholder", "props"] }, { kind: "component", type: SearchSelectorComponent, selector: "val-select-input", inputs: ["preset", "props"] }, { kind: "component", type: PhoneInputComponent, selector: "val-phone-input", inputs: ["preset", "props"], outputs: ["phoneChange"] }, { kind: "component", type: ToggleInputComponent, selector: "val-toggle-input", inputs: ["preset", "props"] }, { kind: "component", type: CheckboxRadioInputComponent, selector: "val-checkbox-radio-input", inputs: ["props"] }, { kind: "component", type: UsernameInputComponent, selector: "val-username-input", inputs: ["props"] }] }); }
26299
+ `, isInline: true, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}@media (prefers-color-scheme: dark){:root{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}.section{margin-top:1rem}.input{margin:.5rem 0}@media (min-width: 768px){.input{margin:.75rem 0}}.field-description{display:block;font-size:.75rem;color:var(--ion-color-medium);margin-bottom:.25rem;line-height:1.4}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: DisplayComponent, selector: "val-display", inputs: ["props"] }, { kind: "component", type: TitleComponent, selector: "val-title", inputs: ["props"] }, { kind: "component", type: TextInputComponent, selector: "val-text-input", inputs: ["preset", "props"] }, { kind: "component", type: CheckInputComponent, selector: "val-check-input", inputs: ["preset", "props"] }, { kind: "component", type: ButtonGroupComponent, selector: "val-button-group", inputs: ["props"], outputs: ["onClick"] }, { kind: "component", type: DividerComponent, selector: "val-divider", inputs: ["props"] }, { kind: "component", type: HintComponent, selector: "val-hint", inputs: ["props"] }, { kind: "component", type: CommentInputComponent, selector: "val-comment-input", inputs: ["props"] }, { kind: "component", type: DateInputComponent, selector: "val-date-input", inputs: ["preset", "props"] }, { kind: "component", type: FileInputComponent, selector: "val-file-input", inputs: ["props"] }, { kind: "component", type: HourInputComponent, selector: "val-hour-input", inputs: ["props"] }, { kind: "component", type: EmailInputComponent, selector: "val-email-input", inputs: ["preset", "props"] }, { kind: "component", type: NumberInputComponent, selector: "val-number-input", inputs: ["props"] }, { kind: "component", type: NumberFromToComponent, selector: "val-number-from-to", inputs: ["props"] }, { kind: "component", type: RadioInputComponent, selector: "val-radio-input", inputs: ["props"] }, { kind: "component", type: PasswordInputComponent, selector: "val-password-input", inputs: ["preset", "props"] }, { kind: "component", type: PinInputComponent, selector: "val-pin-input", inputs: ["props"] }, { kind: "component", type: SelectSearchComponent, selector: "val-select-search", inputs: ["label", "labelProperty", "valueProperty", "multiple", "placeholder", "props"] }, { kind: "component", type: MultiSelectSearchComponent, selector: "val-multi-select-search", inputs: ["label", "labelProperty", "valueProperty", "placeholder", "props"] }, { kind: "component", type: SearchSelectorComponent, selector: "val-select-input", inputs: ["preset", "props"] }, { kind: "component", type: PhoneInputComponent, selector: "val-phone-input", inputs: ["preset", "props"], outputs: ["phoneChange"] }, { kind: "component", type: ToggleInputComponent, selector: "val-toggle-input", inputs: ["preset", "props"] }, { kind: "component", type: CheckboxRadioInputComponent, selector: "val-checkbox-radio-input", inputs: ["props"] }, { kind: "component", type: UsernameInputComponent, selector: "val-username-input", inputs: ["props"] }] }); }
26273
26300
  }
26274
26301
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FormComponent, decorators: [{
26275
26302
  type: Component,
@@ -26303,84 +26330,92 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
26303
26330
  ], template: `
26304
26331
  <div class="container">
26305
26332
  <form [formGroup]="form">
26306
- <val-display
26307
- *ngIf="props.name"
26308
- [props]="{
26309
- content: props.name,
26310
- color: 'dark',
26311
- size: 'small',
26312
- }"
26313
- ></val-display>
26314
- <div class="section" *ngFor="let s of props.sections">
26315
- <val-title [props]="{ content: s.name, size: 'large', color: '', bold: false }"></val-title>
26316
- <div class="input" *ngFor="let f of s.fields">
26317
- <val-title
26318
- *ngIf="f.type !== types.PHONE"
26319
- [props]="{ content: f.label, size: 'small', color: 'dark', bold: false }"
26320
- ></val-title>
26321
- <span *ngIf="f.description" class="field-description">{{ f.description }}</span>
26322
- <ng-container *ngIf="f.type === types.TEXT">
26323
- <val-text-input [props]="getFieldProp(f)"></val-text-input>
26324
- </ng-container>
26325
- <ng-container *ngIf="f.type === types.CHECK">
26326
- <val-check-input></val-check-input>
26327
- </ng-container>
26328
- <ng-container *ngIf="f.type === types.COMMENT">
26329
- <val-comment-input [props]="getFieldProp(f)"></val-comment-input>
26330
- </ng-container>
26331
- <ng-container *ngIf="f.type === types.DATE">
26332
- <val-date-input [props]="getFieldProp(f)"></val-date-input>
26333
- </ng-container>
26334
- <ng-container *ngIf="f.type === types.EMAIL">
26335
- <val-email-input [props]="getFieldProp(f)"></val-email-input>
26336
- </ng-container>
26337
- <ng-container *ngIf="f.type === types.FILE">
26338
- <val-file-input [props]="getFieldProp(f)"></val-file-input>
26339
- </ng-container>
26340
- <ng-container *ngIf="f.type === types.HOUR">
26341
- <val-hour-input [props]="getFieldProp(f)"></val-hour-input>
26342
- </ng-container>
26343
- <ng-container *ngIf="f.type === types.NUMBER">
26344
- <val-number-input [props]="getFieldProp(f)"></val-number-input>
26345
- </ng-container>
26346
- <ng-container *ngIf="f.type === types.NUMBER_FROM_TO">
26347
- <val-number-from-to [props]="getFieldProp(f)"></val-number-from-to>
26348
- </ng-container>
26349
- <ng-container *ngIf="f.type === types.PASSWORD">
26350
- <val-password-input [props]="getFieldProp(f)"></val-password-input>
26351
- </ng-container>
26352
- <ng-container *ngIf="f.type === types.PIN_CODE">
26353
- <val-pin-input [props]="getFieldProp(f)"></val-pin-input>
26354
- </ng-container>
26355
- <ng-container *ngIf="f.type === types.RADIO">
26356
- <val-radio-input [props]="getFieldProp(f)"></val-radio-input>
26357
- </ng-container>
26358
- <ng-container *ngIf="f.type === types.SELECT">
26359
- <val-select-input [props]="getFieldProp(f)"></val-select-input>
26360
- </ng-container>
26361
- <ng-container *ngIf="f.type === types.SEARCH_SELECT">
26362
- <val-select-search [props]="getFieldProp(f)"></val-select-search>
26363
- </ng-container>
26364
- <ng-container *ngIf="f.type === types.MULTI_SELECT">
26365
- <val-multi-select-search [props]="getFieldProp(f)"></val-multi-select-search>
26366
- </ng-container>
26367
- <ng-container *ngIf="f.type === types.PHONE">
26368
- <val-phone-input [props]="getFieldProp(f)"></val-phone-input>
26369
- </ng-container>
26370
- <ng-container *ngIf="f.type === types.HANDLE">
26371
- <val-username-input [props]="getUsernameProp(f)"></val-username-input>
26372
- </ng-container>
26373
- <ng-container *ngIf="f.type === types.TOGGLE">
26374
- <val-toggle-input [props]="getFieldProp(f)"></val-toggle-input>
26375
- </ng-container>
26376
- <ng-container *ngIf="f.type === types.CHECKBOX_RADIO">
26377
- <val-checkbox-radio-input [props]="getFieldProp(f)"></val-checkbox-radio-input>
26378
- </ng-container>
26379
- <val-hint [props]="getFieldProp(f)"></val-hint>
26333
+ @if (props.name) {
26334
+ <val-display
26335
+ [props]="{
26336
+ content: props.name,
26337
+ color: 'dark',
26338
+ size: 'small',
26339
+ }"
26340
+ ></val-display>
26341
+ }
26342
+ @for (s of props.sections; track s.name) {
26343
+ <div class="section">
26344
+ <val-title [props]="{ content: s.name, size: 'large', color: '', bold: false }"></val-title>
26345
+ @for (f of s.fields; track f.name) {
26346
+ <div class="input">
26347
+ @if (f.type !== types.PHONE && f.type !== types.HANDLE) {
26348
+ <val-title [props]="{ content: f.label, size: 'small', color: 'dark', bold: false }"></val-title>
26349
+ }
26350
+ @if (f.description) {
26351
+ <span class="field-description">{{ f.description }}</span>
26352
+ }
26353
+ @switch (f.type) {
26354
+ @case (types.TEXT) {
26355
+ <val-text-input [props]="getFieldProp(f)"></val-text-input>
26356
+ }
26357
+ @case (types.CHECK) {
26358
+ <val-check-input></val-check-input>
26359
+ }
26360
+ @case (types.COMMENT) {
26361
+ <val-comment-input [props]="getFieldProp(f)"></val-comment-input>
26362
+ }
26363
+ @case (types.DATE) {
26364
+ <val-date-input [props]="getFieldProp(f)"></val-date-input>
26365
+ }
26366
+ @case (types.EMAIL) {
26367
+ <val-email-input [props]="getFieldProp(f)"></val-email-input>
26368
+ }
26369
+ @case (types.FILE) {
26370
+ <val-file-input [props]="getFieldProp(f)"></val-file-input>
26371
+ }
26372
+ @case (types.HOUR) {
26373
+ <val-hour-input [props]="getFieldProp(f)"></val-hour-input>
26374
+ }
26375
+ @case (types.NUMBER) {
26376
+ <val-number-input [props]="getFieldProp(f)"></val-number-input>
26377
+ }
26378
+ @case (types.NUMBER_FROM_TO) {
26379
+ <val-number-from-to [props]="getFieldProp(f)"></val-number-from-to>
26380
+ }
26381
+ @case (types.PASSWORD) {
26382
+ <val-password-input [props]="getFieldProp(f)"></val-password-input>
26383
+ }
26384
+ @case (types.PIN_CODE) {
26385
+ <val-pin-input [props]="getFieldProp(f)"></val-pin-input>
26386
+ }
26387
+ @case (types.RADIO) {
26388
+ <val-radio-input [props]="getFieldProp(f)"></val-radio-input>
26389
+ }
26390
+ @case (types.SELECT) {
26391
+ <val-select-input [props]="getFieldProp(f)"></val-select-input>
26392
+ }
26393
+ @case (types.SEARCH_SELECT) {
26394
+ <val-select-search [props]="getFieldProp(f)"></val-select-search>
26395
+ }
26396
+ @case (types.MULTI_SELECT) {
26397
+ <val-multi-select-search [props]="getFieldProp(f)"></val-multi-select-search>
26398
+ }
26399
+ @case (types.PHONE) {
26400
+ <val-phone-input [props]="getFieldProp(f)"></val-phone-input>
26401
+ }
26402
+ @case (types.HANDLE) {
26403
+ <val-username-input [props]="getUsernameProp(f)"></val-username-input>
26404
+ }
26405
+ @case (types.TOGGLE) {
26406
+ <val-toggle-input [props]="getFieldProp(f)"></val-toggle-input>
26407
+ }
26408
+ @case (types.CHECKBOX_RADIO) {
26409
+ <val-checkbox-radio-input [props]="getFieldProp(f)"></val-checkbox-radio-input>
26410
+ }
26411
+ }
26412
+ <val-hint [props]="getFieldProp(f)"></val-hint>
26413
+ </div>
26414
+ }
26415
+ <val-divider [props]="{ fill: 'solid', size: 'medium', color: 'medium' }"></val-divider>
26416
+ <ng-content></ng-content>
26380
26417
  </div>
26381
- <val-divider [props]="{ fill: 'solid', size: 'medium', color: 'medium' }"></val-divider>
26382
- <ng-content></ng-content>
26383
- </div>
26418
+ }
26384
26419
  <val-button-group
26385
26420
  [props]="{ buttons: actions, position: 'center', columned: false }"
26386
26421
  (onClick)="submitHandler($event)"
@@ -35611,12 +35646,16 @@ class PreferencesService {
35611
35646
  }
35612
35647
  }, { allowSignalWrites: true });
35613
35648
  // Side-effect: aplicar theme local cuando llega snapshot real.
35649
+ // OJO: usar `toggleUserPreference()` y NO el setter `Theme =`. El setter
35650
+ // solo persiste localStorage + emite el BehaviorSubject; no aplica las
35651
+ // clases `body.dark`/`body.light` que el palette `dark.class.css` de
35652
+ // Ionic necesita para conmutar el tema visible.
35614
35653
  effect(() => {
35615
35654
  if (!this._synced())
35616
35655
  return;
35617
35656
  const t = this._theme();
35618
35657
  if (this.themeService) {
35619
- this.themeService.Theme = t;
35658
+ this.themeService.toggleUserPreference(t);
35620
35659
  }
35621
35660
  });
35622
35661
  // Side-effect: aplicar language local cuando llega snapshot real.