ngx-eiffage-material 0.1.8 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,43 +1,43 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, Component, inject, ChangeDetectorRef, signal, viewChild, computed, afterRenderEffect, effect, untracked, forwardRef, Injectable, output, ChangeDetectionStrategy, ViewContainerRef, Directive, Pipe, InjectionToken, PLATFORM_ID, HostListener, DestroyRef, ViewEncapsulation, booleanAttribute } from '@angular/core';
2
+ import { Injectable, InjectionToken, makeEnvironmentProviders, isSignal, signal, inject, computed, input, booleanAttribute, numberAttribute, ChangeDetectionStrategy, Component, ChangeDetectorRef, viewChild, afterRenderEffect, effect, untracked, forwardRef, output, ViewContainerRef, Directive, Pipe, PLATFORM_ID, HostListener, DestroyRef, ViewEncapsulation } from '@angular/core';
3
3
  import * as i1 from '@angular/material/button';
4
4
  import { MatButtonModule } from '@angular/material/button';
5
- import * as i1$1 from '@angular/material/icon';
6
- import { MatIconModule } from '@angular/material/icon';
7
5
  import * as i2 from '@angular/material/progress-spinner';
8
6
  import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
7
+ import { Subject, fromEvent, startWith, map, catchError, of, merge, skip, debounceTime, distinctUntilChanged } from 'rxjs';
8
+ import { toSignal, takeUntilDestroyed, rxResource, toObservable } from '@angular/core/rxjs-interop';
9
9
  import * as i3 from '@angular/forms';
10
10
  import { FormControl, ReactiveFormsModule, NG_VALUE_ACCESSOR, NgControl, FormGroupDirective, NgForm, Validators, FormArray, FormGroup, FormBuilder, FormsModule } from '@angular/forms';
11
11
  import * as i11 from '@angular/common';
12
- import { CommonModule, DatePipe, isPlatformBrowser, LowerCasePipe } from '@angular/common';
13
- import * as i2$1 from '@angular/material/chips';
12
+ import { CommonModule, NgTemplateOutlet, DatePipe, isPlatformBrowser, LowerCasePipe } from '@angular/common';
13
+ import * as i2$2 from '@angular/material/chips';
14
14
  import { MatChipsModule } from '@angular/material/chips';
15
- import * as i2$2 from '@angular/material/form-field';
15
+ import * as i2$3 from '@angular/material/form-field';
16
16
  import { MatFormFieldModule } from '@angular/material/form-field';
17
+ import * as i2$1 from '@angular/material/icon';
18
+ import { MatIconModule } from '@angular/material/icon';
17
19
  import * as i6 from '@angular/material/progress-bar';
18
20
  import { MatProgressBarModule } from '@angular/material/progress-bar';
19
21
  import * as i7 from '@angular/material/tooltip';
20
22
  import { MatTooltipModule } from '@angular/material/tooltip';
21
23
  import * as i4 from '@angular/material/input';
22
24
  import { MatInputModule } from '@angular/material/input';
23
- import { takeUntilDestroyed, toSignal, rxResource, toObservable } from '@angular/core/rxjs-interop';
24
25
  import * as i3$1 from '@angular/material/select';
25
26
  import { MatSelectModule } from '@angular/material/select';
26
- import { Subject, fromEvent, startWith, map, takeUntil, catchError, of, merge, skip, debounceTime, distinctUntilChanged } from 'rxjs';
27
27
  import { MatDialogRef, MAT_DIALOG_DATA, MatDialogTitle, MatDialogContent, MatDialogActions, MatDialogClose, MatDialog } from '@angular/material/dialog';
28
- import * as i1$2 from '@angular/material/divider';
29
- import { MatDividerModule } from '@angular/material/divider';
30
28
  import * as i14 from '@angular/material/checkbox';
31
29
  import { MatCheckboxModule } from '@angular/material/checkbox';
32
30
  import * as i10 from '@angular/material/datepicker';
33
31
  import { DateRange, MatDatepickerModule } from '@angular/material/datepicker';
32
+ import * as i13 from '@angular/material/divider';
33
+ import { MatDividerModule } from '@angular/material/divider';
34
34
  import * as i12 from '@angular/material/menu';
35
35
  import { MatMenuModule } from '@angular/material/menu';
36
36
  import * as i3$3 from '@angular/material/paginator';
37
37
  import { MatPaginatorModule, MatPaginator } from '@angular/material/paginator';
38
- import * as i2$3 from '@angular/material/sort';
38
+ import * as i2$4 from '@angular/material/sort';
39
39
  import { MatSortModule } from '@angular/material/sort';
40
- import * as i1$3 from '@angular/material/table';
40
+ import * as i1$1 from '@angular/material/table';
41
41
  import { MatTableModule, MatTableDataSource } from '@angular/material/table';
42
42
  import { Overlay, OverlayContainer } from '@angular/cdk/overlay';
43
43
  import { TemplatePortal } from '@angular/cdk/portal';
@@ -56,234 +56,12 @@ import * as i4$2 from '@angular/material/core';
56
56
  import { MatRippleModule } from '@angular/material/core';
57
57
  import { MatBadgeModule } from '@angular/material/badge';
58
58
 
59
- class NgxLoadingButton {
60
- isLoading = input.required(...(ngDevMode ? [{ debugName: "isLoading" }] : [])); //Indica si el botón está cargando
61
- label = input.required(...(ngDevMode ? [{ debugName: "label" }] : [])); //Texto del botón
62
- matButton = input('filled', ...(ngDevMode ? [{ debugName: "matButton" }] : [])); //Tipo de botón
63
- type = input('button', ...(ngDevMode ? [{ debugName: "type" }] : [])); //Tipo de acción del botón
64
- disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : [])); //Indica si el botón está deshabilitado
65
- spinnerDiameter = input(24, ...(ngDevMode ? [{ debugName: "spinnerDiameter" }] : [])); //Diameter del spinner de carga
66
- spinnerStrokeWidth = input(3, ...(ngDevMode ? [{ debugName: "spinnerStrokeWidth" }] : [])); //StrokeWidth del spinner de carga
67
- //Por defecto es Primary
68
- color = input(undefined, ...(ngDevMode ? [{ debugName: "color" }] : [])); //Color del botón
69
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxLoadingButton, deps: [], target: i0.ɵɵFactoryTarget.Component });
70
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: NgxLoadingButton, isStandalone: true, selector: "ngx-loading-button", inputs: { isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, matButton: { classPropertyName: "matButton", publicName: "matButton", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, spinnerDiameter: { classPropertyName: "spinnerDiameter", publicName: "spinnerDiameter", isSignal: true, isRequired: false, transformFunction: null }, spinnerStrokeWidth: { classPropertyName: "spinnerStrokeWidth", publicName: "spinnerStrokeWidth", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<button\r\n class=\"loadingButton\"\r\n [matButton]=\"matButton()\"\r\n [type]=\"type()\"\r\n [disabled]=\"disabled() || isLoading()\"\r\n [class.isLoading]=\"isLoading()\"\r\n [class]=\"color() ?? ''\"\r\n>\r\n {{ label() }}\r\n</button>\r\n\r\n@if (isLoading()) {\r\n <mat-spinner\r\n class=\"spinnerLoadingButton\"\r\n [diameter]=\"spinnerDiameter()\"\r\n [strokeWidth]=\"spinnerStrokeWidth()\"\r\n />\r\n}\r\n", styles: [":host{display:inline-flex;position:relative}.loadingButton{width:100%}.spinnerLoadingButton{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.isLoading{--mat-button-filled-disabled-label-text-color: transparent;--mat-button-outlined-disabled-label-text-color: transparent;--mat-button-protected-disabled-label-text-color: transparent;--mat-button-text-disabled-label-text-color: transparent;--mat-button-tonal-disabled-label-text-color: transparent}.secondary{--mat-button-filled-container-color: var(--mat-sys-secondary);--mat-button-filled-label-text-color: var(--mat-sys-on-secondary);--mat-button-outlined-label-text-color: var(--mat-sys-secondary);--mat-button-outlined-state-layer-color: var(--mat-sys-secondary);--mat-button-outlined-ripple-color: var(--mat-sys-secondary-container);--mat-button-protected-label-text-color: var(--mat-sys-secondary);--mat-button-protected-state-layer-color: var(--mat-sys-secondary);--mat-button-protected-ripple-color: var(--mat-sys-secondary-container);--mat-button-text-label-text-color: var(--mat-sys-secondary);--mat-button-text-state-layer-color: var(--mat-sys-secondary);--mat-button-text-ripple-color: var(--mat-sys-secondary-container)}.secondarySpinner{--mat-progress-spinner-active-indicator-color: var(--mat-sys-secondary)}.tertiary{--mat-button-filled-container-color: var(--mat-sys-tertiary);--mat-button-filled-label-text-color: var(--mat-sys-on-tertiary);--mat-button-outlined-label-text-color: var(--mat-sys-tertiary);--mat-button-outlined-state-layer-color: var(--mat-sys-tertiary);--mat-button-outlined-ripple-color: var(--mat-sys-tertiary-container);--mat-button-protected-label-text-color: var(--mat-sys-tertiary);--mat-button-protected-state-layer-color: var(--mat-sys-tertiary);--mat-button-protected-ripple-color: var(--mat-sys-tertiary-container);--mat-button-text-label-text-color: var(--mat-sys-tertiary);--mat-button-text-state-layer-color: var(--mat-sys-tertiary);--mat-button-text-ripple-color: var(--mat-sys-tertiary-container)}.tertiarySpinner{--mat-progress-spinner-active-indicator-color: var(--mat-sys-tertiary)}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i2.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatIconModule }] });
71
- }
72
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxLoadingButton, decorators: [{
73
- type: Component,
74
- args: [{ selector: 'ngx-loading-button', imports: [
75
- MatButtonModule,
76
- MatProgressSpinnerModule,
77
- MatIconModule,
78
- ], template: "<button\r\n class=\"loadingButton\"\r\n [matButton]=\"matButton()\"\r\n [type]=\"type()\"\r\n [disabled]=\"disabled() || isLoading()\"\r\n [class.isLoading]=\"isLoading()\"\r\n [class]=\"color() ?? ''\"\r\n>\r\n {{ label() }}\r\n</button>\r\n\r\n@if (isLoading()) {\r\n <mat-spinner\r\n class=\"spinnerLoadingButton\"\r\n [diameter]=\"spinnerDiameter()\"\r\n [strokeWidth]=\"spinnerStrokeWidth()\"\r\n />\r\n}\r\n", styles: [":host{display:inline-flex;position:relative}.loadingButton{width:100%}.spinnerLoadingButton{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.isLoading{--mat-button-filled-disabled-label-text-color: transparent;--mat-button-outlined-disabled-label-text-color: transparent;--mat-button-protected-disabled-label-text-color: transparent;--mat-button-text-disabled-label-text-color: transparent;--mat-button-tonal-disabled-label-text-color: transparent}.secondary{--mat-button-filled-container-color: var(--mat-sys-secondary);--mat-button-filled-label-text-color: var(--mat-sys-on-secondary);--mat-button-outlined-label-text-color: var(--mat-sys-secondary);--mat-button-outlined-state-layer-color: var(--mat-sys-secondary);--mat-button-outlined-ripple-color: var(--mat-sys-secondary-container);--mat-button-protected-label-text-color: var(--mat-sys-secondary);--mat-button-protected-state-layer-color: var(--mat-sys-secondary);--mat-button-protected-ripple-color: var(--mat-sys-secondary-container);--mat-button-text-label-text-color: var(--mat-sys-secondary);--mat-button-text-state-layer-color: var(--mat-sys-secondary);--mat-button-text-ripple-color: var(--mat-sys-secondary-container)}.secondarySpinner{--mat-progress-spinner-active-indicator-color: var(--mat-sys-secondary)}.tertiary{--mat-button-filled-container-color: var(--mat-sys-tertiary);--mat-button-filled-label-text-color: var(--mat-sys-on-tertiary);--mat-button-outlined-label-text-color: var(--mat-sys-tertiary);--mat-button-outlined-state-layer-color: var(--mat-sys-tertiary);--mat-button-outlined-ripple-color: var(--mat-sys-tertiary-container);--mat-button-protected-label-text-color: var(--mat-sys-tertiary);--mat-button-protected-state-layer-color: var(--mat-sys-tertiary);--mat-button-protected-ripple-color: var(--mat-sys-tertiary-container);--mat-button-text-label-text-color: var(--mat-sys-tertiary);--mat-button-text-state-layer-color: var(--mat-sys-tertiary);--mat-button-text-ripple-color: var(--mat-sys-tertiary-container)}.tertiarySpinner{--mat-progress-spinner-active-indicator-color: var(--mat-sys-tertiary)}\n"] }]
79
- }], propDecorators: { isLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoading", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], matButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "matButton", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], spinnerDiameter: [{ type: i0.Input, args: [{ isSignal: true, alias: "spinnerDiameter", required: false }] }], spinnerStrokeWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "spinnerStrokeWidth", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }] } });
80
-
81
- class NgxInputFile {
82
- // dependencies injection
83
- _cdr = inject(ChangeDetectorRef);
84
- value = signal([], ...(ngDevMode ? [{ debugName: "value" }] : []));
85
- onChangeCb;
86
- onTouchCb;
87
- label = input('Seleccionar archivo', ...(ngDevMode ? [{ debugName: "label" }] : []));
88
- /**
89
- * FormControl externo. Es opcional: si el componente se usa con
90
- * `formControlName` / `[formControl]`, el enlace se hace por
91
- * ControlValueAccessor y no hace falta pasarlo.
92
- */
93
- control = input(...(ngDevMode ? [undefined, { debugName: "control" }] : []));
94
- disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
95
- placeholder = input('Haz click o arrastra archivos aquí', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
96
- class = input('', ...(ngDevMode ? [{ debugName: "class" }] : []));
97
- accept = input([], ...(ngDevMode ? [{ debugName: "accept" }] : []));
98
- multiple = input(false, ...(ngDevMode ? [{ debugName: "multiple" }] : []));
99
- hint = input('', ...(ngDevMode ? [{ debugName: "hint" }] : []));
100
- error = input('', ...(ngDevMode ? [{ debugName: "error" }] : []));
101
- isDropping = signal(false, ...(ngDevMode ? [{ debugName: "isDropping" }] : []));
102
- inputFileRef = viewChild('inputFileRef', ...(ngDevMode ? [{ debugName: "inputFileRef" }] : []));
103
- internalControl = new FormControl([]);
104
- /** Estado deshabilitado que llega desde setDisabledState() (reactive forms). */
105
- _cvaDisabled = signal(false, ...(ngDevMode ? [{ debugName: "_cvaDisabled" }] : []));
106
- /** Estado deshabilitado efectivo: input `disabled` o el del FormControl padre. */
107
- isDisabled = computed(() => this.disabled() || this._cvaDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : []));
108
- constructor() {
109
- afterRenderEffect(() => {
110
- const disabled = this.isDisabled();
111
- const control = this.control();
112
- if (disabled) {
113
- if (control?.enabled)
114
- control.disable({ emitEvent: false });
115
- if (this.internalControl.enabled)
116
- this.internalControl.disable({ emitEvent: false });
117
- }
118
- else {
119
- if (control?.disabled)
120
- control.enable({ emitEvent: false });
121
- if (this.internalControl.disabled)
122
- this.internalControl.enable({ emitEvent: false });
123
- }
124
- });
125
- }
126
- checkErrors() {
127
- const control = this.control();
128
- if (control?.invalid) {
129
- this.internalControl.setErrors(control.errors);
130
- }
131
- else {
132
- this.internalControl.setErrors(null);
133
- }
134
- this._cdr.markForCheck();
135
- }
136
- controlEffect = effect(() => {
137
- const value = this.value();
138
- // Usar untracked para evitar ciclos y emitEvent: false para no disparar eventos
139
- untracked(() => {
140
- this.control()?.setValue(value, { emitEvent: false });
141
- // Actualizar el control interno con strings (nombres de archivo)
142
- const fileNames = value.map(f => f.name);
143
- this.internalControl.setValue(fileNames, { emitEvent: false });
144
- this.checkErrors();
145
- this._cdr.markForCheck();
146
- });
147
- }, ...(ngDevMode ? [{ debugName: "controlEffect" }] : []));
148
- ngOnInit() {
149
- if (this.isDisabled()) {
150
- this.control()?.disable();
151
- this.internalControl.disable();
152
- }
153
- }
154
- onContainerClick() {
155
- if (!this.isDisabled()) {
156
- this.markAsTouched();
157
- this.checkErrors();
158
- this._cdr.markForCheck();
159
- this.onTouchCb?.();
160
- this.inputFileRef()?.nativeElement.click();
161
- }
162
- }
163
- onInputchange(event) {
164
- const target = event.target;
165
- const files = target.files;
166
- this.attachFiles(files);
167
- target.value = '';
168
- }
169
- onDragOver(event) {
170
- event.preventDefault();
171
- if (!this.isDisabled())
172
- this.isDropping.set(true);
173
- }
174
- onDragLeave(event) {
175
- event.preventDefault();
176
- this.isDropping.set(false);
177
- }
178
- onDrop(event) {
179
- event.preventDefault();
180
- this.isDropping.set(false);
181
- if (!this.isDisabled()) {
182
- this.onTouchCb?.();
183
- const files = event.dataTransfer?.files;
184
- this.attachFiles(files);
185
- }
186
- }
187
- attachFiles(files) {
188
- if (files && files.length > 0) {
189
- let newValue;
190
- if (this.multiple()) {
191
- const currentFiles = this.value();
192
- const newFiles = Array.from(files);
193
- newValue = [...currentFiles, ...newFiles];
194
- }
195
- else {
196
- newValue = [files[0]];
197
- }
198
- this.value.set(newValue);
199
- this.onChangeCb?.(newValue);
200
- this.markAsTouched();
201
- this.markAsDirty();
202
- }
203
- }
204
- writeValue(files) {
205
- this.value.set(files ?? []);
206
- }
207
- registerOnChange(fn) {
208
- this.onChangeCb = fn;
209
- }
210
- registerOnTouched(fn) {
211
- this.onTouchCb = fn;
212
- }
213
- setDisabledState(isDisabled) {
214
- this._cvaDisabled.set(isDisabled);
215
- }
216
- onDeleteFileClick(file) {
217
- const newValue = this.value().filter((item) => item !== file);
218
- this.value.set(newValue);
219
- this.onChangeCb?.(newValue);
220
- this.markAsTouched();
221
- this.markAsDirty();
222
- }
223
- getAccept() {
224
- return this.accept().join();
225
- }
226
- bytesToMegaBytes(bytes) {
227
- return (bytes / 1024 / 1024).toFixed(1);
228
- }
229
- markAsTouched() {
230
- this.control()?.markAsTouched();
231
- this.internalControl.markAsTouched();
232
- }
233
- markAsDirty() {
234
- this.control()?.markAsDirty();
235
- this.internalControl.markAsDirty();
236
- }
237
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxInputFile, deps: [], target: i0.ɵɵFactoryTarget.Component });
238
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: NgxInputFile, isStandalone: true, selector: "ngx-input-file", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, control: { classPropertyName: "control", publicName: "control", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
239
- {
240
- provide: NG_VALUE_ACCESSOR,
241
- useExisting: forwardRef(() => NgxInputFile),
242
- multi: true,
243
- },
244
- ], viewQueries: [{ propertyName: "inputFileRef", first: true, predicate: ["inputFileRef"], descendants: true, isSignal: true }], ngImport: i0, template: "<mat-form-field\r\n appearance=\"outline\"\r\n floatLabel=\"always\"\r\n (click)=\"onContainerClick()\"\r\n (dragover)=\"onDragOver($event)\"\r\n (dragleave)=\"onDragLeave($event)\"\r\n (drop)=\"onDrop($event)\"\r\n [class.dragover]=\"isDropping()\"\r\n>\r\n <mat-label>{{ label() }}</mat-label>\r\n <mat-chip-grid \r\n #chipGrid \r\n [formControl]=\"internalControl\"\r\n class=\"chips-grid\"\r\n >\r\n @for(file of value(); track file.name + $index) {\r\n <mat-chip-row\r\n (removed)=\"onDeleteFileClick(file)\"\r\n class=\"chip-item\"\r\n [title]=\"file.name\"\r\n >\r\n <div class=\"chip-content\">\r\n <span class=\"chip-label\">\r\n ({{ bytesToMegaBytes(file.size) }} MB) {{ file.name }}\r\n </span>\r\n </div>\r\n <button matChipRemove [attr.aria-label]=\"'Eliminar ' + file.name\">\r\n <mat-icon>cancel</mat-icon>\r\n </button>\r\n </mat-chip-row>\r\n }\r\n </mat-chip-grid>\r\n <input \r\n #inputFileRef\r\n type=\"file\"\r\n [accept]=\"getAccept()\" \r\n [multiple]=\"multiple()\" \r\n (change)=\"onInputchange($event)\"\r\n [matChipInputFor]=\"chipGrid\"\r\n style=\"display: none\"\r\n /> \r\n <mat-hint>{{ isDropping() ? 'Arrastrar archivos aqu\u00ED' : hint() }}</mat-hint>\r\n <mat-error>{{ error() }}</mat-error>\r\n</mat-form-field>", styles: [":host{display:block;width:100%}mat-form-field{width:100%;cursor:pointer;--mat-form-field-outlined-focus-outline-color: var(--mat-sys-outline);--mat-form-field-outlined-outline-color: var(--mat-sys-outline);--mat-form-field-outlined-hover-outline-color: var(--mat-sys-outline);--mat-form-field-outlined-focus-label-text-color: var(--mat-sys-on-surface)}.chips-grid{display:flex;flex-wrap:wrap;gap:8px;width:100%}.chip-item{max-width:100%!important;box-sizing:border-box!important}.chip-item ::ng-deep .mdc-evolution-chip__cell{display:flex!important;align-items:center!important}.chip-item ::ng-deep .mdc-evolution-chip__cell--primary{overflow:hidden!important;max-width:100%!important;display:flex!important;align-items:center!important}.chip-item ::ng-deep .mdc-evolution-chip__action--primary{overflow:hidden!important;max-width:100%!important;display:flex!important;align-items:center!important}.chip-item ::ng-deep .mdc-evolution-chip__text-label{overflow:hidden!important;max-width:100%!important;display:flex!important;align-items:center!important}.chip-item ::ng-deep .mdc-evolution-chip__cell--trailing{display:flex!important;align-items:center!important}.chip-content{overflow:hidden!important;max-width:100%!important;display:flex!important;align-items:center!important}.chip-label{display:block!important;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important;max-width:100%!important;line-height:1.5!important}[matChipRemove]{flex-shrink:0!important;display:flex!important;align-items:center!important;justify-content:center!important}[matChipRemove] mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}.dragover ::ng-deep .mat-mdc-text-field-wrapper{border-color:var(--mat-sys-primary);border-width:2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatProgressBarModule }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i2$1.MatChipGrid, selector: "mat-chip-grid", inputs: ["disabled", "placeholder", "required", "value", "errorStateMatcher"], outputs: ["change", "valueChange"] }, { kind: "directive", type: i2$1.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled", "readonly", "matChipInputDisabledInteractive"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { kind: "directive", type: i2$1.MatChipRemove, selector: "[matChipRemove]" }, { kind: "component", type: i2$1.MatChipRow, selector: "mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]", inputs: ["editable"], outputs: ["edited"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$2.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i2$2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatInputModule }] });
245
- }
246
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxInputFile, decorators: [{
247
- type: Component,
248
- args: [{ selector: 'ngx-input-file', imports: [
249
- CommonModule,
250
- MatButtonModule,
251
- MatIconModule,
252
- MatProgressBarModule,
253
- MatChipsModule,
254
- MatTooltipModule,
255
- MatFormFieldModule,
256
- ReactiveFormsModule,
257
- MatInputModule,
258
- ], providers: [
259
- {
260
- provide: NG_VALUE_ACCESSOR,
261
- useExisting: forwardRef(() => NgxInputFile),
262
- multi: true,
263
- },
264
- ], template: "<mat-form-field\r\n appearance=\"outline\"\r\n floatLabel=\"always\"\r\n (click)=\"onContainerClick()\"\r\n (dragover)=\"onDragOver($event)\"\r\n (dragleave)=\"onDragLeave($event)\"\r\n (drop)=\"onDrop($event)\"\r\n [class.dragover]=\"isDropping()\"\r\n>\r\n <mat-label>{{ label() }}</mat-label>\r\n <mat-chip-grid \r\n #chipGrid \r\n [formControl]=\"internalControl\"\r\n class=\"chips-grid\"\r\n >\r\n @for(file of value(); track file.name + $index) {\r\n <mat-chip-row\r\n (removed)=\"onDeleteFileClick(file)\"\r\n class=\"chip-item\"\r\n [title]=\"file.name\"\r\n >\r\n <div class=\"chip-content\">\r\n <span class=\"chip-label\">\r\n ({{ bytesToMegaBytes(file.size) }} MB) {{ file.name }}\r\n </span>\r\n </div>\r\n <button matChipRemove [attr.aria-label]=\"'Eliminar ' + file.name\">\r\n <mat-icon>cancel</mat-icon>\r\n </button>\r\n </mat-chip-row>\r\n }\r\n </mat-chip-grid>\r\n <input \r\n #inputFileRef\r\n type=\"file\"\r\n [accept]=\"getAccept()\" \r\n [multiple]=\"multiple()\" \r\n (change)=\"onInputchange($event)\"\r\n [matChipInputFor]=\"chipGrid\"\r\n style=\"display: none\"\r\n /> \r\n <mat-hint>{{ isDropping() ? 'Arrastrar archivos aqu\u00ED' : hint() }}</mat-hint>\r\n <mat-error>{{ error() }}</mat-error>\r\n</mat-form-field>", styles: [":host{display:block;width:100%}mat-form-field{width:100%;cursor:pointer;--mat-form-field-outlined-focus-outline-color: var(--mat-sys-outline);--mat-form-field-outlined-outline-color: var(--mat-sys-outline);--mat-form-field-outlined-hover-outline-color: var(--mat-sys-outline);--mat-form-field-outlined-focus-label-text-color: var(--mat-sys-on-surface)}.chips-grid{display:flex;flex-wrap:wrap;gap:8px;width:100%}.chip-item{max-width:100%!important;box-sizing:border-box!important}.chip-item ::ng-deep .mdc-evolution-chip__cell{display:flex!important;align-items:center!important}.chip-item ::ng-deep .mdc-evolution-chip__cell--primary{overflow:hidden!important;max-width:100%!important;display:flex!important;align-items:center!important}.chip-item ::ng-deep .mdc-evolution-chip__action--primary{overflow:hidden!important;max-width:100%!important;display:flex!important;align-items:center!important}.chip-item ::ng-deep .mdc-evolution-chip__text-label{overflow:hidden!important;max-width:100%!important;display:flex!important;align-items:center!important}.chip-item ::ng-deep .mdc-evolution-chip__cell--trailing{display:flex!important;align-items:center!important}.chip-content{overflow:hidden!important;max-width:100%!important;display:flex!important;align-items:center!important}.chip-label{display:block!important;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important;max-width:100%!important;line-height:1.5!important}[matChipRemove]{flex-shrink:0!important;display:flex!important;align-items:center!important;justify-content:center!important}[matChipRemove] mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}.dragover ::ng-deep .mat-mdc-text-field-wrapper{border-color:var(--mat-sys-primary);border-width:2px}\n"] }]
265
- }], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], control: [{ type: i0.Input, args: [{ isSignal: true, alias: "control", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], inputFileRef: [{ type: i0.ViewChild, args: ['inputFileRef', { isSignal: true }] }] } });
266
-
267
- const includeNoSensible = (cadena, query) => {
268
- const nomalizadoCadena = cadena
269
- .toLowerCase()
270
- .normalize('NFD')
271
- .replace(/[\u0300-\u036f]/g, '');
272
- const nomalizadoQuery = query
273
- .toLowerCase()
274
- .normalize('NFD')
275
- .replace(/[\u0300-\u036f]/g, '');
276
- return nomalizadoCadena.includes(nomalizadoQuery);
277
- };
278
- const base64ToUtf8 = (str) => {
279
- return decodeURIComponent(atob(str)
280
- .split('')
281
- .map(function (c) {
282
- return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
283
- })
284
- .join(''));
285
- };
286
-
59
+ /**
60
+ * @deprecated Usa `provideNgxEiffageTexts()`: solo hay que indicar los textos que cambian, se agrupan
61
+ * por componente y se actualizan solos al cambiar de idioma (signals). Mientras tanto, una subclase de
62
+ * NgxTablesIntl provista en la app se sigue respetando. Esta clase no recibirá textos nuevos y se
63
+ * eliminará en una versión mayor.
64
+ */
287
65
  class NgxTablesIntl {
288
66
  /**
289
67
  * Stream que emite cuando las etiquetas cambian.
@@ -510,73 +288,652 @@ class NgxTablesIntl {
510
288
  if (itemName) {
511
289
  return `Vas a eliminar '${itemName}'. ¿Estas seguro?`;
512
290
  }
513
- return this.deleteConfirmBody;
291
+ return this.deleteConfirmBody;
292
+ }
293
+ /**
294
+ * Función para obtener el mensaje de eliminación de filtro avanzado
295
+ * @param filterName Nombre del filtro
296
+ */
297
+ getDeleteAdvancedFilterMessage(filterName) {
298
+ return `Vas a eliminar la plantilla de filtro avanzado '${filterName}'. ¿Estas seguro?`;
299
+ }
300
+ /**
301
+ * Función para obtener el tooltip de editar filtro avanzado con nombre
302
+ * @param filterName Nombre del filtro
303
+ */
304
+ getEditAdvancedFilterTooltip(filterName) {
305
+ return `Editar '${filterName}'`;
306
+ }
307
+ /**
308
+ * Función para obtener el tooltip de eliminar filtro avanzado con nombre
309
+ * @param filterName Nombre del filtro
310
+ */
311
+ getDeleteAdvancedFilterTooltip(filterName) {
312
+ return `Eliminar '${filterName}'`;
313
+ }
314
+ /**
315
+ * Función para obtener el label de elementos seleccionados
316
+ * @param count Número de elementos seleccionados
317
+ */
318
+ getSelectedItemsLabel(count) {
319
+ return count === 1
320
+ ? `${count} elemento seleccionado`
321
+ : `${count} elementos seleccionados`;
322
+ }
323
+ /**
324
+ * Función para obtener el texto de quitar selección en selects
325
+ * @param optionName Nombre de la opción (opcional)
326
+ */
327
+ getRemoveOptionText(optionName) {
328
+ return `-- Quitar ${optionName} --`;
329
+ }
330
+ /**
331
+ * Mensaje anunciado por lectores de pantalla (aria-live) con el número de
332
+ * resultados tras filtrar en un select buscable.
333
+ * @param count Número de resultados visibles
334
+ */
335
+ getSearchResultsCountMessage(count) {
336
+ return count === 1 ? '1 resultado' : `${count} resultados`;
337
+ }
338
+ /**
339
+ * Footer del ngx-paginated-select en modo múltiple: elementos seleccionados
340
+ * sobre el total disponible.
341
+ */
342
+ getPaginatedSelectSelectedCountLabel(selected, total) {
343
+ return `${selected} de ${total} seleccionados`;
344
+ }
345
+ /**
346
+ * Footer del ngx-paginated-select en modo simple: número total de resultados.
347
+ */
348
+ getPaginatedSelectResultsCountLabel(total) {
349
+ return total === 1 ? '1 resultado' : `${total} resultados`;
350
+ }
351
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxTablesIntl, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
352
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxTablesIntl, providedIn: 'root' });
353
+ }
354
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxTablesIntl, decorators: [{
355
+ type: Injectable,
356
+ args: [{ providedIn: 'root' }]
357
+ }] });
358
+
359
+ const plural = (count, one, many) => (count === 1 ? one : many);
360
+ /** Valores por defecto (castellano). */
361
+ const NGX_EIFFAGE_DEFAULT_TEXTS = {
362
+ common: {
363
+ search: 'Buscar...',
364
+ clearSearch: 'Limpiar búsqueda',
365
+ noData: 'No se han encontrado resultados...',
366
+ loading: 'Cargando...',
367
+ cancel: 'Cancelar',
368
+ confirm: 'Confirmar',
369
+ close: 'Cerrar',
370
+ save: 'Guardar',
371
+ saveAndApply: 'Guardar y aplicar',
372
+ },
373
+ table: {
374
+ create: 'Nuevo',
375
+ edit: 'Editar',
376
+ delete: 'Eliminar',
377
+ confirmDelete: 'Eliminar',
378
+ deleteConfirmTitle: 'Eliminar',
379
+ deleteConfirmBody: 'Vas a eliminar el registro seleccionado. ¿Estas seguro?',
380
+ editColumns: 'Visualizar y ordenar columnas',
381
+ deselectAll: 'Desmarcar todos los registros',
382
+ selectionActions: 'Operaciones sobre los registros seleccionados',
383
+ export: 'Exportar datos',
384
+ exportExcel: 'Exportar a XLSX la página actual',
385
+ exportPdf: 'Exportar a PDF la página actual',
386
+ enterFullscreen: 'Pantalla completa',
387
+ exitFullscreen: 'Salir del modo de pantalla completa',
388
+ actions: 'Acciones',
389
+ dateRangeStart: 'Desde',
390
+ dateRangeEnd: 'Hasta',
391
+ totalPerPage: 'Total parcial (por página)',
392
+ totalGeneral: 'Total (todos los registros)',
393
+ },
394
+ columnsDialog: {
395
+ title: 'Ordenar y visualizar columnas de la tabla',
396
+ pin: 'Anclar columna',
397
+ unpin: 'Desanclar',
398
+ moveUp: 'Subir',
399
+ moveDown: 'Bajar',
400
+ hasFiltersApplied: '(hay filtros aplicados)',
401
+ hideColumnWithFiltersNote: 'Para ocultar una columna, primero debes quitar los filtros que tenga aplicados',
402
+ note: 'Nota:',
403
+ reset: 'Reestablecer orden y visualización',
404
+ },
405
+ advancedFilters: {
406
+ label: 'Filtros avanzados',
407
+ new: 'Nuevo filtro',
408
+ remove: 'Quitar filtros avanzados',
409
+ editTooltip: name => `Editar '${name}'`,
410
+ deleteTooltip: name => `Eliminar '${name}'`,
411
+ deleteTitle: 'Eliminar plantilla de filtro avanzado',
412
+ deleteMessage: name => `Vas a eliminar la plantilla de filtro avanzado '${name}'. ¿Estas seguro?`,
413
+ dialogTitle: 'Filtros avanzados para la tabla',
414
+ templateName: 'Nombre de la plantilla',
415
+ templateNameRequired: 'El nombre es obligatorio',
416
+ helpTitle: 'Uso de filtros avanzados',
417
+ groupHelp: 'Un conjunto de filtros que se evalúan juntos. Todos los filtros dentro de un grupo usan el mismo conector (“Y” u “O”). Cada rectángulo representa un grupo y dentro de ellos puede haber filtros u otros grupos',
418
+ ruleHelp: 'Una regla individual que compara un campo con un valor (por ejemplo: “Precio > 100”)',
419
+ group: 'Grupo:',
420
+ filter: 'Filtro:',
421
+ addFilter: 'Añadir filtro',
422
+ addGroup: 'Añadir grupo',
423
+ deleteGroup: 'Eliminar grupo',
424
+ deleteFilter: 'Eliminar filtro',
425
+ field: 'Campo',
426
+ condition: 'Condición',
427
+ value: 'Valor',
428
+ selectOption: 'Selecciona una opción',
429
+ required: 'Obligatorio',
430
+ and: 'Y',
431
+ or: 'O',
432
+ operators: {
433
+ equals: 'Igual a',
434
+ notEquals: 'Distinto de',
435
+ greaterThan: 'Mayor que',
436
+ greaterOrEquals: 'Mayor o igual que',
437
+ lessThan: 'Menor que',
438
+ lessOrEquals: 'Menor o igual que',
439
+ like: 'Contiene',
440
+ },
441
+ },
442
+ select: {
443
+ noResults: 'No se han encontrado resultados...',
444
+ showMore: 'Ver más',
445
+ removeOption: name => `-- Quitar ${name} --`,
446
+ resultsCount: count => plural(count, '1 resultado', `${count} resultados`),
447
+ },
448
+ paginatedSelect: {
449
+ confirm: 'Confirmar',
450
+ reset: 'Limpiar',
451
+ selectAll: 'Seleccionar todo',
452
+ loadingMore: 'Cargando más…',
453
+ endOfList: 'No hay más resultados',
454
+ noResultsHint: 'Prueba con otro término de búsqueda',
455
+ clearSearch: 'Limpiar búsqueda',
456
+ errorTitle: 'No se pudieron cargar los datos',
457
+ errorHint: 'Revisa tu conexión e inténtalo de nuevo',
458
+ retry: 'Reintentar',
459
+ selectedCount: (selected, total) => `${selected} de ${total} seleccionados`,
460
+ resultsCount: total => plural(total, '1 resultado', `${total} resultados`),
461
+ },
462
+ dialog: {
463
+ cancel: 'Cancelar',
464
+ confirm: 'Confirmar',
465
+ accept: 'Aceptar',
466
+ close: 'Cerrar',
467
+ },
468
+ fileInput: {
469
+ dropLabel: 'Arrastra archivos aquí',
470
+ browse: 'o haz clic para seleccionar',
471
+ remove: name => `Eliminar ${name}`,
472
+ removed: name => `Archivo ${name} eliminado`,
473
+ added: count => plural(count, '1 archivo añadido', `${count} archivos añadidos`),
474
+ maxFiles: max => `Máximo ${max} archivos permitidos`,
475
+ typeNotAllowed: type => `Tipo no permitido: ${type}`,
476
+ tooLarge: maxSize => `Excede el tamaño máximo (${maxSize})`,
477
+ },
478
+ inputFile: {
479
+ label: 'Seleccionar archivo',
480
+ dropping: 'Arrastrar archivos aquí',
481
+ remove: name => `Eliminar ${name}`,
482
+ },
483
+ skeleton: {
484
+ loading: 'Cargando…',
485
+ },
486
+ alert: {
487
+ dismiss: 'Cerrar aviso',
488
+ },
489
+ loadingButton: {
490
+ busy: 'Cargando…',
491
+ },
492
+ };
493
+ /** Textos que la app consumidora sustituye. Se provee con provideNgxEiffageTexts(). */
494
+ const NGX_EIFFAGE_TEXTS = new InjectionToken('NGX_EIFFAGE_TEXTS');
495
+ /**
496
+ * Cambia los textos de la librería. Solo hay que indicar los que difieren de los valores por defecto.
497
+ *
498
+ * ```ts
499
+ * // Textos fijos
500
+ * provideNgxEiffageTexts({ alert: { dismiss: 'Dismiss' } })
501
+ *
502
+ * // Según el idioma de la app: una función (se ejecuta en contexto de inyección) que devuelve un signal
503
+ * provideNgxEiffageTexts(() => {
504
+ * const language = inject(LanguageService);
505
+ * return computed(() => language.current() === 'en' ? EN_TEXTS : {});
506
+ * })
507
+ * ```
508
+ */
509
+ function provideNgxEiffageTexts(texts) {
510
+ return makeEnvironmentProviders([
511
+ {
512
+ provide: NGX_EIFFAGE_TEXTS,
513
+ useFactory: () => {
514
+ const source = typeof texts === 'function' && !isSignal(texts) ? texts() : texts;
515
+ return isSignal(source) ? source : signal(source);
516
+ },
517
+ },
518
+ ]);
519
+ }
520
+ /** Textos efectivos de la librería: valores por defecto + NgxTablesIntl (obsoleto) + provideNgxEiffageTexts. */
521
+ class NgxTexts {
522
+ _overrides = inject(NGX_EIFFAGE_TEXTS, { optional: true });
523
+ _legacyIntl = inject(NgxTablesIntl);
524
+ _legacyChanges = toSignal(this._legacyIntl.changes);
525
+ /** Todos los textos ya combinados. En plantilla: `texts().alert.dismiss`. */
526
+ texts = computed(() => {
527
+ this._legacyChanges();
528
+ const legacy = isCustomizedLegacyIntl(this._legacyIntl) ? textsFromLegacyIntl(this._legacyIntl) : {};
529
+ return deepMerge(deepMerge(NGX_EIFFAGE_DEFAULT_TEXTS, legacy), this._overrides?.() ?? {});
530
+ }, ...(ngDevMode ? [{ debugName: "texts" }] : []));
531
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxTexts, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
532
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxTexts, providedIn: 'root' });
533
+ }
534
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxTexts, decorators: [{
535
+ type: Injectable,
536
+ args: [{ providedIn: 'root' }]
537
+ }] });
538
+ // ── Compatibilidad con NgxTablesIntl ────────────────────────────────────────
539
+ /** Solo se leen los valores de NgxTablesIntl si el consumidor la ha sustituido (subclase o useValue). */
540
+ function isCustomizedLegacyIntl(intl) {
541
+ return Object.getPrototypeOf(intl) !== NgxTablesIntl.prototype;
542
+ }
543
+ /** Traduce una NgxTablesIntl personalizada al formato nuevo. */
544
+ function textsFromLegacyIntl(intl) {
545
+ return {
546
+ common: {
547
+ search: intl.searchPlaceholder,
548
+ clearSearch: intl.clearSearchTooltip,
549
+ noData: intl.noDataMessage,
550
+ loading: intl.loadingMessage,
551
+ cancel: intl.cancelButtonLabel,
552
+ confirm: intl.confirmButtonLabel,
553
+ close: intl.closeButtonLabel,
554
+ save: intl.saveButtonLabel,
555
+ saveAndApply: intl.saveAndApplyButtonLabel,
556
+ },
557
+ table: {
558
+ create: intl.createButtonLabel,
559
+ edit: intl.editTooltip,
560
+ delete: intl.deleteTooltip,
561
+ confirmDelete: intl.confirmDeleteLabel,
562
+ deleteConfirmTitle: intl.deleteConfirmTitle,
563
+ deleteConfirmBody: intl.deleteConfirmBody,
564
+ editColumns: intl.editColumnsTooltip,
565
+ deselectAll: intl.deselectAllLabel,
566
+ selectionActions: intl.selectionActionsTooltip,
567
+ export: intl.exportTooltip,
568
+ exportExcel: intl.exportToExcelLabel,
569
+ exportPdf: intl.exportToPdfLabel,
570
+ enterFullscreen: intl.enterFullscreenTooltip,
571
+ exitFullscreen: intl.exitFullscreenTooltip,
572
+ actions: intl.actionsLabel,
573
+ dateRangeStart: intl.dateRangeStartPlaceholder,
574
+ dateRangeEnd: intl.dateRangeEndPlaceholder,
575
+ totalPerPage: intl.totalPerPageLabel,
576
+ totalGeneral: intl.totalGeneralLabel,
577
+ },
578
+ columnsDialog: {
579
+ title: intl.configureColumnsTitle,
580
+ pin: intl.pinColumnTooltip,
581
+ unpin: intl.unpinColumnTooltip,
582
+ moveUp: intl.moveUpTooltip,
583
+ moveDown: intl.moveDownTooltip,
584
+ hasFiltersApplied: intl.hasFiltersAppliedText,
585
+ hideColumnWithFiltersNote: intl.hideColumnWithFiltersNote,
586
+ note: intl.noteLabel,
587
+ reset: intl.resetColumnsButtonLabel,
588
+ },
589
+ advancedFilters: {
590
+ label: intl.advancedFiltersLabel,
591
+ new: intl.newAdvancedFilterLabel,
592
+ remove: intl.removeAdvancedFilterTooltip,
593
+ editTooltip: name => intl.getEditAdvancedFilterTooltip(name),
594
+ deleteTooltip: name => intl.getDeleteAdvancedFilterTooltip(name),
595
+ deleteTitle: intl.deleteAdvancedFilterTitle,
596
+ deleteMessage: name => intl.getDeleteAdvancedFilterMessage(name),
597
+ dialogTitle: intl.advancedFiltersDialogTitle,
598
+ templateName: intl.templateNameLabel,
599
+ templateNameRequired: intl.templateNameRequiredError,
600
+ helpTitle: intl.advancedFiltersHelpTitle,
601
+ groupHelp: intl.advancedFiltersGroupHelp,
602
+ ruleHelp: intl.advancedFiltersRuleHelp,
603
+ group: intl.groupLabel,
604
+ filter: intl.filterLabel,
605
+ addFilter: intl.addFilterButtonLabel,
606
+ addGroup: intl.addGroupButtonLabel,
607
+ deleteGroup: intl.deleteGroupTooltip,
608
+ deleteFilter: intl.deleteFilterTooltip,
609
+ field: intl.fieldLabel,
610
+ condition: intl.conditionLabel,
611
+ value: intl.valueLabel,
612
+ selectOption: intl.selectOptionPlaceholder,
613
+ required: intl.requiredFieldError,
614
+ and: intl.connectorAnd,
615
+ or: intl.connectorOr,
616
+ operators: {
617
+ equals: intl.operatorEquals,
618
+ notEquals: intl.operatorNotEquals,
619
+ greaterThan: intl.operatorGreaterThan,
620
+ greaterOrEquals: intl.operatorGreaterOrEquals,
621
+ lessThan: intl.operatorLessThan,
622
+ lessOrEquals: intl.operatorLessOrEquals,
623
+ like: intl.operatorLike,
624
+ },
625
+ },
626
+ select: {
627
+ noResults: intl.noResultsMessage,
628
+ showMore: intl.showMoreLabel,
629
+ removeOption: name => intl.getRemoveOptionText(name),
630
+ resultsCount: count => intl.getSearchResultsCountMessage(count),
631
+ },
632
+ paginatedSelect: {
633
+ confirm: intl.paginatedSelectConfirmLabel,
634
+ reset: intl.paginatedSelectResetLabel,
635
+ selectAll: intl.paginatedSelectSelectAllLabel,
636
+ loadingMore: intl.paginatedSelectLoadingMoreLabel,
637
+ endOfList: intl.paginatedSelectEndOfListLabel,
638
+ noResultsHint: intl.paginatedSelectNoResultsHint,
639
+ clearSearch: intl.paginatedSelectClearSearchLabel,
640
+ errorTitle: intl.paginatedSelectErrorTitle,
641
+ errorHint: intl.paginatedSelectErrorHint,
642
+ retry: intl.paginatedSelectRetryLabel,
643
+ selectedCount: (selected, total) => intl.getPaginatedSelectSelectedCountLabel(selected, total),
644
+ resultsCount: total => intl.getPaginatedSelectResultsCountLabel(total),
645
+ },
646
+ };
647
+ }
648
+ // ── Utilidades ──────────────────────────────────────────────────────────────
649
+ function isPlainObject(value) {
650
+ return typeof value === 'object' && value !== null && !Array.isArray(value) && !isSignal(value);
651
+ }
652
+ /** Copia profunda de `base` con los valores de `overrides` encima; ignora los undefined. */
653
+ function deepMerge(base, overrides) {
654
+ const result = { ...base };
655
+ for (const [key, value] of Object.entries(overrides)) {
656
+ if (value === undefined)
657
+ continue;
658
+ const current = result[key];
659
+ result[key] = isPlainObject(current) && isPlainObject(value)
660
+ ? deepMerge(current, value)
661
+ : value;
662
+ }
663
+ return result;
664
+ }
665
+
666
+ /**
667
+ * Botón de Material que muestra un spinner mientras dura una acción y no deja volver a pulsarlo.
668
+ *
669
+ * El clic se escucha en el propio selector: `<ngx-loading-button (click)="save()" />`.
670
+ * Mientras `isLoading` es true el clic no llega (ni el submit del formulario, ni con Enter).
671
+ */
672
+ class NgxLoadingButton {
673
+ _texts = inject(NgxTexts).texts;
674
+ /** Muestra el spinner y bloquea el botón. */
675
+ isLoading = input(false, ...(ngDevMode ? [{ debugName: "isLoading", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
676
+ /** Texto del botón. Para iconos o contenido con formato, proyéctalo en su lugar. */
677
+ label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : []));
678
+ /**
679
+ * Texto que sustituye al contenido mientras carga, con un spinner pequeño delante
680
+ * (p. ej. «Guardando…»). Sin él, el spinner se superpone y el botón mantiene su ancho.
681
+ */
682
+ loadingText = input(...(ngDevMode ? [undefined, { debugName: "loadingText" }] : []));
683
+ /** Apariencia de Material: text, filled, elevated, outlined o tonal. */
684
+ matButton = input('filled', ...(ngDevMode ? [{ debugName: "matButton" }] : []));
685
+ /** Tipo nativo del botón. */
686
+ type = input('button', ...(ngDevMode ? [{ debugName: "type" }] : []));
687
+ /** Deshabilita el botón (independiente de isLoading). */
688
+ disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
689
+ /** Color. Sin valor, el primary del tema. */
690
+ color = input(...(ngDevMode ? [undefined, { debugName: "color" }] : []));
691
+ /** Diámetro en px del spinner superpuesto. */
692
+ spinnerDiameter = input(24, ...(ngDevMode ? [{ debugName: "spinnerDiameter", transform: numberAttribute }] : [{ transform: numberAttribute }]));
693
+ /** Grosor en px del trazo del spinner. */
694
+ spinnerStrokeWidth = input(3, ...(ngDevMode ? [{ debugName: "spinnerStrokeWidth", transform: numberAttribute }] : [{ transform: numberAttribute }]));
695
+ /** Lo que anuncia el lector de pantalla mientras carga. Por defecto, el texto `loadingButton.busy` de la librería. */
696
+ busyLabel = input(...(ngDevMode ? [undefined, { debugName: "busyLabel" }] : []));
697
+ /** El spinner va encima del contenido (que se oculta sin cambiar el ancho). */
698
+ overlaySpinner = computed(() => this.isLoading() && !this.loadingText(), ...(ngDevMode ? [{ debugName: "overlaySpinner" }] : []));
699
+ /** El spinner va en línea, delante de loadingText. */
700
+ inlineSpinner = computed(() => this.isLoading() && !!this.loadingText(), ...(ngDevMode ? [{ debugName: "inlineSpinner" }] : []));
701
+ resolvedBusyLabel = computed(() => {
702
+ return this.busyLabel() ?? this._texts().loadingButton.busy;
703
+ }, ...(ngDevMode ? [{ debugName: "resolvedBusyLabel" }] : []));
704
+ /**
705
+ * Mientras carga, anula el clic en el propio botón: preventDefault evita el submit del formulario
706
+ * (también el implícito al pulsar Enter en un campo) y stopImmediatePropagation evita que llegue
707
+ * al (click) que el consumidor escucha en <ngx-loading-button>.
708
+ */
709
+ blockWhileLoading(event) {
710
+ if (!this.isLoading())
711
+ return;
712
+ event.preventDefault();
713
+ event.stopImmediatePropagation();
714
+ }
715
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxLoadingButton, deps: [], target: i0.ɵɵFactoryTarget.Component });
716
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: NgxLoadingButton, isStandalone: true, selector: "ngx-loading-button", inputs: { isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, loadingText: { classPropertyName: "loadingText", publicName: "loadingText", isSignal: true, isRequired: false, transformFunction: null }, matButton: { classPropertyName: "matButton", publicName: "matButton", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, spinnerDiameter: { classPropertyName: "spinnerDiameter", publicName: "spinnerDiameter", isSignal: true, isRequired: false, transformFunction: null }, spinnerStrokeWidth: { classPropertyName: "spinnerStrokeWidth", publicName: "spinnerStrokeWidth", isSignal: true, isRequired: false, transformFunction: null }, busyLabel: { classPropertyName: "busyLabel", publicName: "busyLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.ngx-loading-button--secondary": "color() === \"secondary\"", "class.ngx-loading-button--tertiary": "color() === \"tertiary\"", "class.ngx-loading-button--error": "color() === \"error\"", "class.ngx-loading-button--loading": "isLoading() && !disabled()" } }, ngImport: i0, template: "<!--\r\n Mientras carga: disabledInteractive mantiene el foco en el bot\u00F3n (el lector de pantalla sigue en \u00E9l\r\n y oye aria-busy). Material NO bloquea el clic de un <button> en ese estado: lo hace blockWhileLoading.\r\n Con disabled, el bot\u00F3n se deshabilita del todo y el navegador ya no emite clics.\r\n-->\r\n<button\r\n class=\"loadingButton\"\r\n [matButton]=\"matButton()\"\r\n [type]=\"type()\"\r\n [disabled]=\"disabled() || isLoading()\"\r\n [disabledInteractive]=\"isLoading() && !disabled()\"\r\n [attr.aria-busy]=\"isLoading() || null\"\r\n (click)=\"blockWhileLoading($event)\"\r\n>\r\n <span class=\"loadingButton__content\" [class.loadingButton__content--hidden]=\"overlaySpinner()\" [class.loadingButton__content--gone]=\"inlineSpinner()\">\r\n {{ label() }}\r\n <ng-content />\r\n </span>\r\n\r\n @if (inlineSpinner()) {\r\n <span class=\"loadingButton__content\">\r\n <mat-spinner class=\"loadingButton__inlineSpinner\" diameter=\"18\" strokeWidth=\"2.5\" aria-hidden=\"true\" />\r\n {{ loadingText() }}\r\n </span>\r\n }\r\n\r\n @if (overlaySpinner()) {\r\n <mat-spinner\r\n class=\"loadingButton__overlaySpinner\"\r\n [diameter]=\"spinnerDiameter()\"\r\n [strokeWidth]=\"spinnerStrokeWidth()\"\r\n [attr.aria-label]=\"resolvedBusyLabel()\"\r\n />\r\n }\r\n</button>\r\n", styles: [":host{display:inline-flex;vertical-align:middle}.loadingButton{width:100%}.loadingButton__content{display:inline-flex;align-items:center;justify-content:center;gap:8px}.loadingButton__content--hidden{visibility:hidden}.loadingButton__content--gone{display:none}.loadingButton__content ::ng-deep .mat-icon{width:18px;height:18px;font-size:18px}.loadingButton__overlaySpinner,.loadingButton__inlineSpinner{--mat-progress-spinner-active-indicator-color: currentColor}.loadingButton__overlaySpinner{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);pointer-events:none}.loadingButton__inlineSpinner{flex:none}.loadingButton[aria-busy=true]{cursor:progress}:host(.ngx-loading-button--loading){--mat-button-filled-disabled-container-color: var(--mat-button-filled-container-color, var(--mat-sys-primary));--mat-button-filled-disabled-label-text-color: var(--mat-button-filled-label-text-color, var(--mat-sys-on-primary));--mat-button-tonal-disabled-container-color: var(--mat-button-tonal-container-color, var(--mat-sys-secondary-container));--mat-button-tonal-disabled-label-text-color: var(--mat-button-tonal-label-text-color, var(--mat-sys-on-secondary-container));--mat-button-protected-disabled-container-color: var(--mat-button-protected-container-color, var(--mat-sys-surface));--mat-button-protected-disabled-container-elevation-shadow: var(--mat-button-protected-container-elevation-shadow, var(--mat-sys-level1));--mat-button-protected-disabled-label-text-color: var(--mat-button-protected-label-text-color, var(--mat-sys-primary));--mat-button-outlined-disabled-outline-color: var(--mat-button-outlined-outline-color, var(--mat-sys-outline));--mat-button-outlined-disabled-label-text-color: var(--mat-button-outlined-label-text-color, var(--mat-sys-primary));--mat-button-text-disabled-label-text-color: var(--mat-button-text-label-text-color, var(--mat-sys-primary))}:host(.ngx-loading-button--secondary){--mat-button-filled-container-color: var(--mat-sys-secondary);--mat-button-filled-label-text-color: var(--mat-sys-on-secondary);--mat-button-filled-state-layer-color: var(--mat-sys-on-secondary);--mat-button-tonal-container-color: var(--mat-sys-secondary-container);--mat-button-tonal-label-text-color: var(--mat-sys-on-secondary-container);--mat-button-tonal-state-layer-color: var(--mat-sys-on-secondary-container);--mat-button-outlined-label-text-color: var(--mat-sys-secondary);--mat-button-outlined-state-layer-color: var(--mat-sys-secondary);--mat-button-outlined-ripple-color: var(--mat-sys-secondary-container);--mat-button-protected-label-text-color: var(--mat-sys-secondary);--mat-button-protected-state-layer-color: var(--mat-sys-secondary);--mat-button-protected-ripple-color: var(--mat-sys-secondary-container);--mat-button-text-label-text-color: var(--mat-sys-secondary);--mat-button-text-state-layer-color: var(--mat-sys-secondary);--mat-button-text-ripple-color: var(--mat-sys-secondary-container)}:host(.ngx-loading-button--tertiary){--mat-button-filled-container-color: var(--mat-sys-tertiary);--mat-button-filled-label-text-color: var(--mat-sys-on-tertiary);--mat-button-filled-state-layer-color: var(--mat-sys-on-tertiary);--mat-button-tonal-container-color: var(--mat-sys-tertiary-container);--mat-button-tonal-label-text-color: var(--mat-sys-on-tertiary-container);--mat-button-tonal-state-layer-color: var(--mat-sys-on-tertiary-container);--mat-button-outlined-label-text-color: var(--mat-sys-tertiary);--mat-button-outlined-state-layer-color: var(--mat-sys-tertiary);--mat-button-outlined-ripple-color: var(--mat-sys-tertiary-container);--mat-button-protected-label-text-color: var(--mat-sys-tertiary);--mat-button-protected-state-layer-color: var(--mat-sys-tertiary);--mat-button-protected-ripple-color: var(--mat-sys-tertiary-container);--mat-button-text-label-text-color: var(--mat-sys-tertiary);--mat-button-text-state-layer-color: var(--mat-sys-tertiary);--mat-button-text-ripple-color: var(--mat-sys-tertiary-container)}:host(.ngx-loading-button--error){--mat-button-filled-container-color: var(--mat-sys-error);--mat-button-filled-label-text-color: var(--mat-sys-on-error);--mat-button-filled-state-layer-color: var(--mat-sys-on-error);--mat-button-tonal-container-color: var(--mat-sys-error-container);--mat-button-tonal-label-text-color: var(--mat-sys-on-error-container);--mat-button-tonal-state-layer-color: var(--mat-sys-on-error-container);--mat-button-outlined-label-text-color: var(--mat-sys-error);--mat-button-outlined-state-layer-color: var(--mat-sys-error);--mat-button-outlined-ripple-color: var(--mat-sys-error-container);--mat-button-protected-label-text-color: var(--mat-sys-error);--mat-button-protected-state-layer-color: var(--mat-sys-error);--mat-button-protected-ripple-color: var(--mat-sys-error-container);--mat-button-text-label-text-color: var(--mat-sys-error);--mat-button-text-state-layer-color: var(--mat-sys-error);--mat-button-text-ripple-color: var(--mat-sys-error-container)}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i2.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
717
+ }
718
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxLoadingButton, decorators: [{
719
+ type: Component,
720
+ args: [{ selector: 'ngx-loading-button', imports: [MatButtonModule, MatProgressSpinnerModule], changeDetection: ChangeDetectionStrategy.OnPush, host: {
721
+ '[class.ngx-loading-button--secondary]': 'color() === "secondary"',
722
+ '[class.ngx-loading-button--tertiary]': 'color() === "tertiary"',
723
+ '[class.ngx-loading-button--error]': 'color() === "error"',
724
+ '[class.ngx-loading-button--loading]': 'isLoading() && !disabled()',
725
+ }, template: "<!--\r\n Mientras carga: disabledInteractive mantiene el foco en el bot\u00F3n (el lector de pantalla sigue en \u00E9l\r\n y oye aria-busy). Material NO bloquea el clic de un <button> en ese estado: lo hace blockWhileLoading.\r\n Con disabled, el bot\u00F3n se deshabilita del todo y el navegador ya no emite clics.\r\n-->\r\n<button\r\n class=\"loadingButton\"\r\n [matButton]=\"matButton()\"\r\n [type]=\"type()\"\r\n [disabled]=\"disabled() || isLoading()\"\r\n [disabledInteractive]=\"isLoading() && !disabled()\"\r\n [attr.aria-busy]=\"isLoading() || null\"\r\n (click)=\"blockWhileLoading($event)\"\r\n>\r\n <span class=\"loadingButton__content\" [class.loadingButton__content--hidden]=\"overlaySpinner()\" [class.loadingButton__content--gone]=\"inlineSpinner()\">\r\n {{ label() }}\r\n <ng-content />\r\n </span>\r\n\r\n @if (inlineSpinner()) {\r\n <span class=\"loadingButton__content\">\r\n <mat-spinner class=\"loadingButton__inlineSpinner\" diameter=\"18\" strokeWidth=\"2.5\" aria-hidden=\"true\" />\r\n {{ loadingText() }}\r\n </span>\r\n }\r\n\r\n @if (overlaySpinner()) {\r\n <mat-spinner\r\n class=\"loadingButton__overlaySpinner\"\r\n [diameter]=\"spinnerDiameter()\"\r\n [strokeWidth]=\"spinnerStrokeWidth()\"\r\n [attr.aria-label]=\"resolvedBusyLabel()\"\r\n />\r\n }\r\n</button>\r\n", styles: [":host{display:inline-flex;vertical-align:middle}.loadingButton{width:100%}.loadingButton__content{display:inline-flex;align-items:center;justify-content:center;gap:8px}.loadingButton__content--hidden{visibility:hidden}.loadingButton__content--gone{display:none}.loadingButton__content ::ng-deep .mat-icon{width:18px;height:18px;font-size:18px}.loadingButton__overlaySpinner,.loadingButton__inlineSpinner{--mat-progress-spinner-active-indicator-color: currentColor}.loadingButton__overlaySpinner{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);pointer-events:none}.loadingButton__inlineSpinner{flex:none}.loadingButton[aria-busy=true]{cursor:progress}:host(.ngx-loading-button--loading){--mat-button-filled-disabled-container-color: var(--mat-button-filled-container-color, var(--mat-sys-primary));--mat-button-filled-disabled-label-text-color: var(--mat-button-filled-label-text-color, var(--mat-sys-on-primary));--mat-button-tonal-disabled-container-color: var(--mat-button-tonal-container-color, var(--mat-sys-secondary-container));--mat-button-tonal-disabled-label-text-color: var(--mat-button-tonal-label-text-color, var(--mat-sys-on-secondary-container));--mat-button-protected-disabled-container-color: var(--mat-button-protected-container-color, var(--mat-sys-surface));--mat-button-protected-disabled-container-elevation-shadow: var(--mat-button-protected-container-elevation-shadow, var(--mat-sys-level1));--mat-button-protected-disabled-label-text-color: var(--mat-button-protected-label-text-color, var(--mat-sys-primary));--mat-button-outlined-disabled-outline-color: var(--mat-button-outlined-outline-color, var(--mat-sys-outline));--mat-button-outlined-disabled-label-text-color: var(--mat-button-outlined-label-text-color, var(--mat-sys-primary));--mat-button-text-disabled-label-text-color: var(--mat-button-text-label-text-color, var(--mat-sys-primary))}:host(.ngx-loading-button--secondary){--mat-button-filled-container-color: var(--mat-sys-secondary);--mat-button-filled-label-text-color: var(--mat-sys-on-secondary);--mat-button-filled-state-layer-color: var(--mat-sys-on-secondary);--mat-button-tonal-container-color: var(--mat-sys-secondary-container);--mat-button-tonal-label-text-color: var(--mat-sys-on-secondary-container);--mat-button-tonal-state-layer-color: var(--mat-sys-on-secondary-container);--mat-button-outlined-label-text-color: var(--mat-sys-secondary);--mat-button-outlined-state-layer-color: var(--mat-sys-secondary);--mat-button-outlined-ripple-color: var(--mat-sys-secondary-container);--mat-button-protected-label-text-color: var(--mat-sys-secondary);--mat-button-protected-state-layer-color: var(--mat-sys-secondary);--mat-button-protected-ripple-color: var(--mat-sys-secondary-container);--mat-button-text-label-text-color: var(--mat-sys-secondary);--mat-button-text-state-layer-color: var(--mat-sys-secondary);--mat-button-text-ripple-color: var(--mat-sys-secondary-container)}:host(.ngx-loading-button--tertiary){--mat-button-filled-container-color: var(--mat-sys-tertiary);--mat-button-filled-label-text-color: var(--mat-sys-on-tertiary);--mat-button-filled-state-layer-color: var(--mat-sys-on-tertiary);--mat-button-tonal-container-color: var(--mat-sys-tertiary-container);--mat-button-tonal-label-text-color: var(--mat-sys-on-tertiary-container);--mat-button-tonal-state-layer-color: var(--mat-sys-on-tertiary-container);--mat-button-outlined-label-text-color: var(--mat-sys-tertiary);--mat-button-outlined-state-layer-color: var(--mat-sys-tertiary);--mat-button-outlined-ripple-color: var(--mat-sys-tertiary-container);--mat-button-protected-label-text-color: var(--mat-sys-tertiary);--mat-button-protected-state-layer-color: var(--mat-sys-tertiary);--mat-button-protected-ripple-color: var(--mat-sys-tertiary-container);--mat-button-text-label-text-color: var(--mat-sys-tertiary);--mat-button-text-state-layer-color: var(--mat-sys-tertiary);--mat-button-text-ripple-color: var(--mat-sys-tertiary-container)}:host(.ngx-loading-button--error){--mat-button-filled-container-color: var(--mat-sys-error);--mat-button-filled-label-text-color: var(--mat-sys-on-error);--mat-button-filled-state-layer-color: var(--mat-sys-on-error);--mat-button-tonal-container-color: var(--mat-sys-error-container);--mat-button-tonal-label-text-color: var(--mat-sys-on-error-container);--mat-button-tonal-state-layer-color: var(--mat-sys-on-error-container);--mat-button-outlined-label-text-color: var(--mat-sys-error);--mat-button-outlined-state-layer-color: var(--mat-sys-error);--mat-button-outlined-ripple-color: var(--mat-sys-error-container);--mat-button-protected-label-text-color: var(--mat-sys-error);--mat-button-protected-state-layer-color: var(--mat-sys-error);--mat-button-protected-ripple-color: var(--mat-sys-error-container);--mat-button-text-label-text-color: var(--mat-sys-error);--mat-button-text-state-layer-color: var(--mat-sys-error);--mat-button-text-ripple-color: var(--mat-sys-error-container)}\n"] }]
726
+ }], propDecorators: { isLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoading", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], loadingText: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingText", required: false }] }], matButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "matButton", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], spinnerDiameter: [{ type: i0.Input, args: [{ isSignal: true, alias: "spinnerDiameter", required: false }] }], spinnerStrokeWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "spinnerStrokeWidth", required: false }] }], busyLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "busyLabel", required: false }] }] } });
727
+
728
+ class NgxInputFile {
729
+ // dependencies injection
730
+ _cdr = inject(ChangeDetectorRef);
731
+ value = signal([], ...(ngDevMode ? [{ debugName: "value" }] : []));
732
+ onChangeCb;
733
+ onTouchCb;
734
+ /** Etiqueta del campo. Por defecto, el texto `inputFile.label` de la librería. */
735
+ label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : []));
736
+ /**
737
+ * FormControl externo. Es opcional: si el componente se usa con
738
+ * `formControlName` / `[formControl]`, el enlace se hace por
739
+ * ControlValueAccessor y no hace falta pasarlo.
740
+ */
741
+ control = input(...(ngDevMode ? [undefined, { debugName: "control" }] : []));
742
+ disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
743
+ /** Sin uso: la plantilla nunca lo ha pintado (pendiente de revisar en ngx-input-file). */
744
+ placeholder = input(...(ngDevMode ? [undefined, { debugName: "placeholder" }] : []));
745
+ texts = inject(NgxTexts).texts;
746
+ resolvedLabel = computed(() => this.label() ?? this.texts().inputFile.label, ...(ngDevMode ? [{ debugName: "resolvedLabel" }] : []));
747
+ class = input('', ...(ngDevMode ? [{ debugName: "class" }] : []));
748
+ accept = input([], ...(ngDevMode ? [{ debugName: "accept" }] : []));
749
+ multiple = input(false, ...(ngDevMode ? [{ debugName: "multiple" }] : []));
750
+ hint = input('', ...(ngDevMode ? [{ debugName: "hint" }] : []));
751
+ error = input('', ...(ngDevMode ? [{ debugName: "error" }] : []));
752
+ isDropping = signal(false, ...(ngDevMode ? [{ debugName: "isDropping" }] : []));
753
+ inputFileRef = viewChild('inputFileRef', ...(ngDevMode ? [{ debugName: "inputFileRef" }] : []));
754
+ internalControl = new FormControl([]);
755
+ /** Estado deshabilitado que llega desde setDisabledState() (reactive forms). */
756
+ _cvaDisabled = signal(false, ...(ngDevMode ? [{ debugName: "_cvaDisabled" }] : []));
757
+ /** Estado deshabilitado efectivo: input `disabled` o el del FormControl padre. */
758
+ isDisabled = computed(() => this.disabled() || this._cvaDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : []));
759
+ constructor() {
760
+ afterRenderEffect(() => {
761
+ const disabled = this.isDisabled();
762
+ const control = this.control();
763
+ if (disabled) {
764
+ if (control?.enabled)
765
+ control.disable({ emitEvent: false });
766
+ if (this.internalControl.enabled)
767
+ this.internalControl.disable({ emitEvent: false });
768
+ }
769
+ else {
770
+ if (control?.disabled)
771
+ control.enable({ emitEvent: false });
772
+ if (this.internalControl.disabled)
773
+ this.internalControl.enable({ emitEvent: false });
774
+ }
775
+ });
776
+ }
777
+ checkErrors() {
778
+ const control = this.control();
779
+ if (control?.invalid) {
780
+ this.internalControl.setErrors(control.errors);
781
+ }
782
+ else {
783
+ this.internalControl.setErrors(null);
784
+ }
785
+ this._cdr.markForCheck();
786
+ }
787
+ controlEffect = effect(() => {
788
+ const value = this.value();
789
+ // Usar untracked para evitar ciclos y emitEvent: false para no disparar eventos
790
+ untracked(() => {
791
+ this.control()?.setValue(value, { emitEvent: false });
792
+ // Actualizar el control interno con strings (nombres de archivo)
793
+ const fileNames = value.map(f => f.name);
794
+ this.internalControl.setValue(fileNames, { emitEvent: false });
795
+ this.checkErrors();
796
+ this._cdr.markForCheck();
797
+ });
798
+ }, ...(ngDevMode ? [{ debugName: "controlEffect" }] : []));
799
+ ngOnInit() {
800
+ if (this.isDisabled()) {
801
+ this.control()?.disable();
802
+ this.internalControl.disable();
803
+ }
514
804
  }
515
- /**
516
- * Función para obtener el mensaje de eliminación de filtro avanzado
517
- * @param filterName Nombre del filtro
518
- */
519
- getDeleteAdvancedFilterMessage(filterName) {
520
- return `Vas a eliminar la plantilla de filtro avanzado '${filterName}'. ¿Estas seguro?`;
805
+ onContainerClick() {
806
+ if (!this.isDisabled()) {
807
+ this.markAsTouched();
808
+ this.checkErrors();
809
+ this._cdr.markForCheck();
810
+ this.onTouchCb?.();
811
+ this.inputFileRef()?.nativeElement.click();
812
+ }
521
813
  }
522
- /**
523
- * Función para obtener el tooltip de editar filtro avanzado con nombre
524
- * @param filterName Nombre del filtro
525
- */
526
- getEditAdvancedFilterTooltip(filterName) {
527
- return `Editar '${filterName}'`;
814
+ onInputchange(event) {
815
+ const target = event.target;
816
+ const files = target.files;
817
+ this.attachFiles(files);
818
+ target.value = '';
528
819
  }
529
- /**
530
- * Función para obtener el tooltip de eliminar filtro avanzado con nombre
531
- * @param filterName Nombre del filtro
532
- */
533
- getDeleteAdvancedFilterTooltip(filterName) {
534
- return `Eliminar '${filterName}'`;
820
+ onDragOver(event) {
821
+ event.preventDefault();
822
+ if (!this.isDisabled())
823
+ this.isDropping.set(true);
535
824
  }
536
- /**
537
- * Función para obtener el label de elementos seleccionados
538
- * @param count Número de elementos seleccionados
539
- */
540
- getSelectedItemsLabel(count) {
541
- return count === 1
542
- ? `${count} elemento seleccionado`
543
- : `${count} elementos seleccionados`;
825
+ onDragLeave(event) {
826
+ event.preventDefault();
827
+ this.isDropping.set(false);
544
828
  }
545
- /**
546
- * Función para obtener el texto de quitar selección en selects
547
- * @param optionName Nombre de la opción (opcional)
548
- */
549
- getRemoveOptionText(optionName) {
550
- return `-- Quitar ${optionName} --`;
829
+ onDrop(event) {
830
+ event.preventDefault();
831
+ this.isDropping.set(false);
832
+ if (!this.isDisabled()) {
833
+ this.onTouchCb?.();
834
+ const files = event.dataTransfer?.files;
835
+ this.attachFiles(files);
836
+ }
551
837
  }
552
- /**
553
- * Mensaje anunciado por lectores de pantalla (aria-live) con el número de
554
- * resultados tras filtrar en un select buscable.
555
- * @param count Número de resultados visibles
556
- */
557
- getSearchResultsCountMessage(count) {
558
- return count === 1 ? '1 resultado' : `${count} resultados`;
838
+ attachFiles(files) {
839
+ if (files && files.length > 0) {
840
+ let newValue;
841
+ if (this.multiple()) {
842
+ const currentFiles = this.value();
843
+ const newFiles = Array.from(files);
844
+ newValue = [...currentFiles, ...newFiles];
845
+ }
846
+ else {
847
+ newValue = [files[0]];
848
+ }
849
+ this.value.set(newValue);
850
+ this.onChangeCb?.(newValue);
851
+ this.markAsTouched();
852
+ this.markAsDirty();
853
+ }
559
854
  }
560
- /**
561
- * Footer del ngx-paginated-select en modo múltiple: elementos seleccionados
562
- * sobre el total disponible.
563
- */
564
- getPaginatedSelectSelectedCountLabel(selected, total) {
565
- return `${selected} de ${total} seleccionados`;
855
+ writeValue(files) {
856
+ this.value.set(files ?? []);
566
857
  }
567
- /**
568
- * Footer del ngx-paginated-select en modo simple: número total de resultados.
569
- */
570
- getPaginatedSelectResultsCountLabel(total) {
571
- return total === 1 ? '1 resultado' : `${total} resultados`;
858
+ registerOnChange(fn) {
859
+ this.onChangeCb = fn;
572
860
  }
573
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxTablesIntl, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
574
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxTablesIntl, providedIn: 'root' });
861
+ registerOnTouched(fn) {
862
+ this.onTouchCb = fn;
863
+ }
864
+ setDisabledState(isDisabled) {
865
+ this._cvaDisabled.set(isDisabled);
866
+ }
867
+ onDeleteFileClick(file) {
868
+ const newValue = this.value().filter((item) => item !== file);
869
+ this.value.set(newValue);
870
+ this.onChangeCb?.(newValue);
871
+ this.markAsTouched();
872
+ this.markAsDirty();
873
+ }
874
+ getAccept() {
875
+ return this.accept().join();
876
+ }
877
+ bytesToMegaBytes(bytes) {
878
+ return (bytes / 1024 / 1024).toFixed(1);
879
+ }
880
+ markAsTouched() {
881
+ this.control()?.markAsTouched();
882
+ this.internalControl.markAsTouched();
883
+ }
884
+ markAsDirty() {
885
+ this.control()?.markAsDirty();
886
+ this.internalControl.markAsDirty();
887
+ }
888
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxInputFile, deps: [], target: i0.ɵɵFactoryTarget.Component });
889
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: NgxInputFile, isStandalone: true, selector: "ngx-input-file", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, control: { classPropertyName: "control", publicName: "control", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
890
+ {
891
+ provide: NG_VALUE_ACCESSOR,
892
+ useExisting: forwardRef(() => NgxInputFile),
893
+ multi: true,
894
+ },
895
+ ], viewQueries: [{ propertyName: "inputFileRef", first: true, predicate: ["inputFileRef"], descendants: true, isSignal: true }], ngImport: i0, template: "<mat-form-field\r\n appearance=\"outline\"\r\n floatLabel=\"always\"\r\n (click)=\"onContainerClick()\"\r\n (dragover)=\"onDragOver($event)\"\r\n (dragleave)=\"onDragLeave($event)\"\r\n (drop)=\"onDrop($event)\"\r\n [class.dragover]=\"isDropping()\"\r\n>\r\n <mat-label>{{ resolvedLabel() }}</mat-label>\r\n <mat-chip-grid \r\n #chipGrid \r\n [formControl]=\"internalControl\"\r\n class=\"chips-grid\"\r\n >\r\n @for(file of value(); track file.name + $index) {\r\n <mat-chip-row\r\n (removed)=\"onDeleteFileClick(file)\"\r\n class=\"chip-item\"\r\n [title]=\"file.name\"\r\n >\r\n <div class=\"chip-content\">\r\n <span class=\"chip-label\">\r\n ({{ bytesToMegaBytes(file.size) }} MB) {{ file.name }}\r\n </span>\r\n </div>\r\n <button matChipRemove [attr.aria-label]=\"texts().inputFile.remove(file.name)\">\r\n <mat-icon>cancel</mat-icon>\r\n </button>\r\n </mat-chip-row>\r\n }\r\n </mat-chip-grid>\r\n <input \r\n #inputFileRef\r\n type=\"file\"\r\n [accept]=\"getAccept()\" \r\n [multiple]=\"multiple()\" \r\n (change)=\"onInputchange($event)\"\r\n [matChipInputFor]=\"chipGrid\"\r\n style=\"display: none\"\r\n /> \r\n <mat-hint>{{ isDropping() ? texts().inputFile.dropping : hint() }}</mat-hint>\r\n <mat-error>{{ error() }}</mat-error>\r\n</mat-form-field>", styles: [":host{display:block;width:100%}mat-form-field{width:100%;cursor:pointer;--mat-form-field-outlined-focus-outline-color: var(--mat-sys-outline);--mat-form-field-outlined-outline-color: var(--mat-sys-outline);--mat-form-field-outlined-hover-outline-color: var(--mat-sys-outline);--mat-form-field-outlined-focus-label-text-color: var(--mat-sys-on-surface)}.chips-grid{display:flex;flex-wrap:wrap;gap:8px;width:100%}.chip-item{max-width:100%!important;box-sizing:border-box!important}.chip-item ::ng-deep .mdc-evolution-chip__cell{display:flex!important;align-items:center!important}.chip-item ::ng-deep .mdc-evolution-chip__cell--primary{overflow:hidden!important;max-width:100%!important;display:flex!important;align-items:center!important}.chip-item ::ng-deep .mdc-evolution-chip__action--primary{overflow:hidden!important;max-width:100%!important;display:flex!important;align-items:center!important}.chip-item ::ng-deep .mdc-evolution-chip__text-label{overflow:hidden!important;max-width:100%!important;display:flex!important;align-items:center!important}.chip-item ::ng-deep .mdc-evolution-chip__cell--trailing{display:flex!important;align-items:center!important}.chip-content{overflow:hidden!important;max-width:100%!important;display:flex!important;align-items:center!important}.chip-label{display:block!important;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important;max-width:100%!important;line-height:1.5!important}[matChipRemove]{flex-shrink:0!important;display:flex!important;align-items:center!important;justify-content:center!important}[matChipRemove] mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}.dragover ::ng-deep .mat-mdc-text-field-wrapper{border-color:var(--mat-sys-primary);border-width:2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatProgressBarModule }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i2$2.MatChipGrid, selector: "mat-chip-grid", inputs: ["disabled", "placeholder", "required", "value", "errorStateMatcher"], outputs: ["change", "valueChange"] }, { kind: "directive", type: i2$2.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled", "readonly", "matChipInputDisabledInteractive"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { kind: "directive", type: i2$2.MatChipRemove, selector: "[matChipRemove]" }, { kind: "component", type: i2$2.MatChipRow, selector: "mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]", inputs: ["editable"], outputs: ["edited"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$3.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i2$3.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatInputModule }] });
575
896
  }
576
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxTablesIntl, decorators: [{
577
- type: Injectable,
578
- args: [{ providedIn: 'root' }]
579
- }] });
897
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxInputFile, decorators: [{
898
+ type: Component,
899
+ args: [{ selector: 'ngx-input-file', imports: [
900
+ CommonModule,
901
+ MatButtonModule,
902
+ MatIconModule,
903
+ MatProgressBarModule,
904
+ MatChipsModule,
905
+ MatTooltipModule,
906
+ MatFormFieldModule,
907
+ ReactiveFormsModule,
908
+ MatInputModule,
909
+ ], providers: [
910
+ {
911
+ provide: NG_VALUE_ACCESSOR,
912
+ useExisting: forwardRef(() => NgxInputFile),
913
+ multi: true,
914
+ },
915
+ ], template: "<mat-form-field\r\n appearance=\"outline\"\r\n floatLabel=\"always\"\r\n (click)=\"onContainerClick()\"\r\n (dragover)=\"onDragOver($event)\"\r\n (dragleave)=\"onDragLeave($event)\"\r\n (drop)=\"onDrop($event)\"\r\n [class.dragover]=\"isDropping()\"\r\n>\r\n <mat-label>{{ resolvedLabel() }}</mat-label>\r\n <mat-chip-grid \r\n #chipGrid \r\n [formControl]=\"internalControl\"\r\n class=\"chips-grid\"\r\n >\r\n @for(file of value(); track file.name + $index) {\r\n <mat-chip-row\r\n (removed)=\"onDeleteFileClick(file)\"\r\n class=\"chip-item\"\r\n [title]=\"file.name\"\r\n >\r\n <div class=\"chip-content\">\r\n <span class=\"chip-label\">\r\n ({{ bytesToMegaBytes(file.size) }} MB) {{ file.name }}\r\n </span>\r\n </div>\r\n <button matChipRemove [attr.aria-label]=\"texts().inputFile.remove(file.name)\">\r\n <mat-icon>cancel</mat-icon>\r\n </button>\r\n </mat-chip-row>\r\n }\r\n </mat-chip-grid>\r\n <input \r\n #inputFileRef\r\n type=\"file\"\r\n [accept]=\"getAccept()\" \r\n [multiple]=\"multiple()\" \r\n (change)=\"onInputchange($event)\"\r\n [matChipInputFor]=\"chipGrid\"\r\n style=\"display: none\"\r\n /> \r\n <mat-hint>{{ isDropping() ? texts().inputFile.dropping : hint() }}</mat-hint>\r\n <mat-error>{{ error() }}</mat-error>\r\n</mat-form-field>", styles: [":host{display:block;width:100%}mat-form-field{width:100%;cursor:pointer;--mat-form-field-outlined-focus-outline-color: var(--mat-sys-outline);--mat-form-field-outlined-outline-color: var(--mat-sys-outline);--mat-form-field-outlined-hover-outline-color: var(--mat-sys-outline);--mat-form-field-outlined-focus-label-text-color: var(--mat-sys-on-surface)}.chips-grid{display:flex;flex-wrap:wrap;gap:8px;width:100%}.chip-item{max-width:100%!important;box-sizing:border-box!important}.chip-item ::ng-deep .mdc-evolution-chip__cell{display:flex!important;align-items:center!important}.chip-item ::ng-deep .mdc-evolution-chip__cell--primary{overflow:hidden!important;max-width:100%!important;display:flex!important;align-items:center!important}.chip-item ::ng-deep .mdc-evolution-chip__action--primary{overflow:hidden!important;max-width:100%!important;display:flex!important;align-items:center!important}.chip-item ::ng-deep .mdc-evolution-chip__text-label{overflow:hidden!important;max-width:100%!important;display:flex!important;align-items:center!important}.chip-item ::ng-deep .mdc-evolution-chip__cell--trailing{display:flex!important;align-items:center!important}.chip-content{overflow:hidden!important;max-width:100%!important;display:flex!important;align-items:center!important}.chip-label{display:block!important;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important;max-width:100%!important;line-height:1.5!important}[matChipRemove]{flex-shrink:0!important;display:flex!important;align-items:center!important;justify-content:center!important}[matChipRemove] mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}.dragover ::ng-deep .mat-mdc-text-field-wrapper{border-color:var(--mat-sys-primary);border-width:2px}\n"] }]
916
+ }], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], control: [{ type: i0.Input, args: [{ isSignal: true, alias: "control", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], inputFileRef: [{ type: i0.ViewChild, args: ['inputFileRef', { isSignal: true }] }] } });
917
+
918
+ const includeNoSensible = (cadena, query) => {
919
+ const nomalizadoCadena = cadena
920
+ .toLowerCase()
921
+ .normalize('NFD')
922
+ .replace(/[\u0300-\u036f]/g, '');
923
+ const nomalizadoQuery = query
924
+ .toLowerCase()
925
+ .normalize('NFD')
926
+ .replace(/[\u0300-\u036f]/g, '');
927
+ return nomalizadoCadena.includes(nomalizadoQuery);
928
+ };
929
+ const base64ToUtf8 = (str) => {
930
+ return decodeURIComponent(atob(str)
931
+ .split('')
932
+ .map(function (c) {
933
+ return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
934
+ })
935
+ .join(''));
936
+ };
580
937
 
581
938
  /** Teclas que deben llegar al mat-select para navegar/seleccionar desde el buscador. */
582
939
  const NAVIGATION_KEYS = new Set([
@@ -590,7 +947,7 @@ const NAVIGATION_KEYS = new Set([
590
947
  ]);
591
948
  class NgxBasicSelect {
592
949
  // Servicio de internacionalización (placeholder del buscador, mensajes de estado…)
593
- intl = inject(NgxTablesIntl);
950
+ texts = inject(NgxTexts).texts;
594
951
  /**
595
952
  * Se auto-registra como ControlValueAccessor del control del formulario.
596
953
  * Se usa `self`/`optional` para poder leer el estado de validación (invalid/touched)
@@ -675,7 +1032,7 @@ class NgxBasicSelect {
675
1032
  if (!query)
676
1033
  return '';
677
1034
  const count = this.resolvedOptions().filter(o => o.visible).length;
678
- return this.intl.getSearchResultsCountMessage(count);
1035
+ return this.texts().select.resultsCount(count);
679
1036
  }, ...(ngDevMode ? [{ debugName: "searchAnnouncement" }] : []));
680
1037
  /**
681
1038
  * ErrorStateMatcher que refleja el estado del control del formulario.
@@ -785,7 +1142,7 @@ class NgxBasicSelect {
785
1142
  this._ngControl?.control?.markAsTouched();
786
1143
  }
787
1144
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxBasicSelect, deps: [], target: i0.ɵɵFactoryTarget.Component });
788
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: NgxBasicSelect, isStandalone: true, selector: "ngx-basic-select", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, basicSelectConfig: { classPropertyName: "basicSelectConfig", publicName: "basicSelectConfig", isSignal: true, isRequired: true, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, subscriptSizing: { classPropertyName: "subscriptSizing", publicName: "subscriptSizing", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange" }, viewQueries: [{ propertyName: "matSelect", first: true, predicate: ["matSelect"], descendants: true, isSignal: true }, { propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true, isSignal: true }], ngImport: i0, template: "\n<mat-form-field [appearance]=\"appearance()\" [className]=\"class()\" [subscriptSizing]=\"subscriptSizing()\">\n <mat-label>{{ label() }}</mat-label>\n <mat-select\n #matSelect\n [formControl]=\"innerControl\"\n [errorStateMatcher]=\"errorStateMatcher\"\n [required]=\"isRequired()\"\n [multiple]=\"multiple()\"\n [placeholder]=\"placeholder()\"\n (openedChange)=\"onOpenedChange($event)\"\n >\n @if(isLoading()) {\n <!--\n Opcion deshabilitada (no un div): mat-select no abre el panel si no\n tiene ninguna mat-option (_canOpen exige options.length > 0). Asi el\n panel abre tambien durante la carga y se ve el indicador.\n -->\n <mat-option disabled class=\"stateOption loadingOption\">\n <mat-spinner diameter=\"18\" />\n <span>{{ intl.loadingMessage }}</span>\n </mat-option>\n } @else {\n <div class=\"searchFilter\">\n <mat-icon class=\"searchIcon\">search</mat-icon>\n <input\n matInput\n #searchInput\n type=\"text\"\n [attr.aria-label]=\"intl.searchPlaceholder\"\n [placeholder]=\"intl.searchPlaceholder\"\n [value]=\"searchQuery()\"\n (input)=\"onSearchInput($any($event.target).value)\"\n (keydown)=\"onSearchKeydown($event)\"\n />\n <button type=\"button\" matIconButton [attr.aria-label]=\"intl.clearSearchTooltip\" (click)=\"clearSearch()\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n <!--\n Solo se renderizan las opciones que casan con el buscador (mas las\n seleccionadas). Las que no casan se quitan del DOM para que no se puedan\n enfocar con las flechas: con el panel abierto mat-select permite navegar\n a opciones deshabilitadas, asi que ocultarlas + disabled no bastaria.\n -->\n @for(option of displayedOptions(); track option.value) {\n <mat-option [value]=\"option.value\" [disabled]=\"option.disabled\">\n {{ option.label }}\n </mat-option>\n }\n @if(showNoOptionsMessage()) {\n <mat-option disabled class=\"stateOption noResults\">\n {{ hasData() ? intl.noResultsMessage : intl.noDataMessage }}\n </mat-option>\n }\n }\n </mat-select>\n @if(isLoading()) {\n <mat-icon matSuffix><mat-spinner diameter=\"20\" /></mat-icon>\n } @else if(clearable() && (multiple() ? value()?.length : value())) {\n <button\n matIconButton\n matSuffix\n [attr.aria-label]=\"intl.clearSearchTooltip\"\n (click)=\"onClearClick(); $event.stopPropagation()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n }\n <mat-error>{{ error() }}</mat-error>\n</mat-form-field>\n\n<!-- Anuncio para lectores de pantalla del numero de resultados al filtrar -->\n<div class=\"srOnly\" aria-live=\"polite\">{{ searchAnnouncement() }}</div>\n", styles: [":host{display:block;width:100%}mat-form-field{width:100%}mat-select{width:100%}.searchFilter{display:flex;align-items:center;position:sticky;top:-8px;height:48px;width:100%;background:var(--mat-sys-surface-container);z-index:10;border-bottom:1px solid var(--mat-sys-outline-variant)}.searchFilter input{height:48px;padding:0 48px;width:calc(100% - 96px);position:absolute;top:0;left:0}.searchFilter .searchIcon{position:absolute;top:0;left:0;height:48px;width:48px;display:flex;align-items:center;justify-content:center}.searchFilter button{position:absolute;right:5px}.stateOption{justify-content:center;text-align:center;color:var(--mat-sys-on-surface-variant);font:var(--mat-sys-body-medium);pointer-events:none;opacity:1}.loadingOption{display:flex;align-items:center;gap:8px}.srOnly{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i2$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i2$2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i3$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i3$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i2.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1145
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: NgxBasicSelect, isStandalone: true, selector: "ngx-basic-select", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, basicSelectConfig: { classPropertyName: "basicSelectConfig", publicName: "basicSelectConfig", isSignal: true, isRequired: true, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, subscriptSizing: { classPropertyName: "subscriptSizing", publicName: "subscriptSizing", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange" }, viewQueries: [{ propertyName: "matSelect", first: true, predicate: ["matSelect"], descendants: true, isSignal: true }, { propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true, isSignal: true }], ngImport: i0, template: "\r\n<mat-form-field [appearance]=\"appearance()\" [className]=\"class()\" [subscriptSizing]=\"subscriptSizing()\">\r\n <mat-label>{{ label() }}</mat-label>\r\n <mat-select\r\n #matSelect\r\n [formControl]=\"innerControl\"\r\n [errorStateMatcher]=\"errorStateMatcher\"\r\n [required]=\"isRequired()\"\r\n [multiple]=\"multiple()\"\r\n [placeholder]=\"placeholder()\"\r\n (openedChange)=\"onOpenedChange($event)\"\r\n >\r\n @if(isLoading()) {\r\n <!--\r\n Opcion deshabilitada (no un div): mat-select no abre el panel si no\r\n tiene ninguna mat-option (_canOpen exige options.length > 0). Asi el\r\n panel abre tambien durante la carga y se ve el indicador.\r\n -->\r\n <mat-option disabled class=\"stateOption loadingOption\">\r\n <mat-spinner diameter=\"18\" />\r\n <span>{{ texts().common.loading }}</span>\r\n </mat-option>\r\n } @else {\r\n <div class=\"searchFilter\">\r\n <mat-icon class=\"searchIcon\">search</mat-icon>\r\n <input\r\n matInput\r\n #searchInput\r\n type=\"text\"\r\n [attr.aria-label]=\"texts().common.search\"\r\n [placeholder]=\"texts().common.search\"\r\n [value]=\"searchQuery()\"\r\n (input)=\"onSearchInput($any($event.target).value)\"\r\n (keydown)=\"onSearchKeydown($event)\"\r\n />\r\n <button type=\"button\" matIconButton [attr.aria-label]=\"texts().common.clearSearch\" (click)=\"clearSearch()\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n <!--\r\n Solo se renderizan las opciones que casan con el buscador (mas las\r\n seleccionadas). Las que no casan se quitan del DOM para que no se puedan\r\n enfocar con las flechas: con el panel abierto mat-select permite navegar\r\n a opciones deshabilitadas, asi que ocultarlas + disabled no bastaria.\r\n -->\r\n @for(option of displayedOptions(); track option.value) {\r\n <mat-option [value]=\"option.value\" [disabled]=\"option.disabled\">\r\n {{ option.label }}\r\n </mat-option>\r\n }\r\n @if(showNoOptionsMessage()) {\r\n <mat-option disabled class=\"stateOption noResults\">\r\n {{ hasData() ? texts().select.noResults : texts().common.noData }}\r\n </mat-option>\r\n }\r\n }\r\n </mat-select>\r\n @if(isLoading()) {\r\n <mat-icon matSuffix><mat-spinner diameter=\"20\" /></mat-icon>\r\n } @else if(clearable() && (multiple() ? value()?.length : value())) {\r\n <button\r\n matIconButton\r\n matSuffix\r\n [attr.aria-label]=\"texts().common.clearSearch\"\r\n (click)=\"onClearClick(); $event.stopPropagation()\"\r\n >\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n }\r\n <mat-error>{{ error() }}</mat-error>\r\n</mat-form-field>\r\n\r\n<!-- Anuncio para lectores de pantalla del numero de resultados al filtrar -->\r\n<div class=\"srOnly\" aria-live=\"polite\">{{ searchAnnouncement() }}</div>\r\n", styles: [":host{display:block;width:100%}mat-form-field{width:100%}mat-select{width:100%}.searchFilter{display:flex;align-items:center;position:sticky;top:-8px;height:48px;width:100%;background:var(--mat-sys-surface-container);z-index:10;border-bottom:1px solid var(--mat-sys-outline-variant)}.searchFilter input{height:48px;padding:0 48px;width:calc(100% - 96px);position:absolute;top:0;left:0}.searchFilter .searchIcon{position:absolute;top:0;left:0;height:48px;width:48px;display:flex;align-items:center;justify-content:center}.searchFilter button{position:absolute;right:5px}.stateOption{justify-content:center;text-align:center;color:var(--mat-sys-on-surface-variant);font:var(--mat-sys-body-medium);pointer-events:none;opacity:1}.loadingOption{display:flex;align-items:center;gap:8px}.srOnly{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i2$3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$3.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i2$3.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i3$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i3$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i2.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
789
1146
  }
790
1147
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxBasicSelect, decorators: [{
791
1148
  type: Component,
@@ -797,7 +1154,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
797
1154
  MatFormFieldModule,
798
1155
  ReactiveFormsModule,
799
1156
  MatProgressSpinnerModule,
800
- ], template: "\n<mat-form-field [appearance]=\"appearance()\" [className]=\"class()\" [subscriptSizing]=\"subscriptSizing()\">\n <mat-label>{{ label() }}</mat-label>\n <mat-select\n #matSelect\n [formControl]=\"innerControl\"\n [errorStateMatcher]=\"errorStateMatcher\"\n [required]=\"isRequired()\"\n [multiple]=\"multiple()\"\n [placeholder]=\"placeholder()\"\n (openedChange)=\"onOpenedChange($event)\"\n >\n @if(isLoading()) {\n <!--\n Opcion deshabilitada (no un div): mat-select no abre el panel si no\n tiene ninguna mat-option (_canOpen exige options.length > 0). Asi el\n panel abre tambien durante la carga y se ve el indicador.\n -->\n <mat-option disabled class=\"stateOption loadingOption\">\n <mat-spinner diameter=\"18\" />\n <span>{{ intl.loadingMessage }}</span>\n </mat-option>\n } @else {\n <div class=\"searchFilter\">\n <mat-icon class=\"searchIcon\">search</mat-icon>\n <input\n matInput\n #searchInput\n type=\"text\"\n [attr.aria-label]=\"intl.searchPlaceholder\"\n [placeholder]=\"intl.searchPlaceholder\"\n [value]=\"searchQuery()\"\n (input)=\"onSearchInput($any($event.target).value)\"\n (keydown)=\"onSearchKeydown($event)\"\n />\n <button type=\"button\" matIconButton [attr.aria-label]=\"intl.clearSearchTooltip\" (click)=\"clearSearch()\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n <!--\n Solo se renderizan las opciones que casan con el buscador (mas las\n seleccionadas). Las que no casan se quitan del DOM para que no se puedan\n enfocar con las flechas: con el panel abierto mat-select permite navegar\n a opciones deshabilitadas, asi que ocultarlas + disabled no bastaria.\n -->\n @for(option of displayedOptions(); track option.value) {\n <mat-option [value]=\"option.value\" [disabled]=\"option.disabled\">\n {{ option.label }}\n </mat-option>\n }\n @if(showNoOptionsMessage()) {\n <mat-option disabled class=\"stateOption noResults\">\n {{ hasData() ? intl.noResultsMessage : intl.noDataMessage }}\n </mat-option>\n }\n }\n </mat-select>\n @if(isLoading()) {\n <mat-icon matSuffix><mat-spinner diameter=\"20\" /></mat-icon>\n } @else if(clearable() && (multiple() ? value()?.length : value())) {\n <button\n matIconButton\n matSuffix\n [attr.aria-label]=\"intl.clearSearchTooltip\"\n (click)=\"onClearClick(); $event.stopPropagation()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n }\n <mat-error>{{ error() }}</mat-error>\n</mat-form-field>\n\n<!-- Anuncio para lectores de pantalla del numero de resultados al filtrar -->\n<div class=\"srOnly\" aria-live=\"polite\">{{ searchAnnouncement() }}</div>\n", styles: [":host{display:block;width:100%}mat-form-field{width:100%}mat-select{width:100%}.searchFilter{display:flex;align-items:center;position:sticky;top:-8px;height:48px;width:100%;background:var(--mat-sys-surface-container);z-index:10;border-bottom:1px solid var(--mat-sys-outline-variant)}.searchFilter input{height:48px;padding:0 48px;width:calc(100% - 96px);position:absolute;top:0;left:0}.searchFilter .searchIcon{position:absolute;top:0;left:0;height:48px;width:48px;display:flex;align-items:center;justify-content:center}.searchFilter button{position:absolute;right:5px}.stateOption{justify-content:center;text-align:center;color:var(--mat-sys-on-surface-variant);font:var(--mat-sys-body-medium);pointer-events:none;opacity:1}.loadingOption{display:flex;align-items:center;gap:8px}.srOnly{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"] }]
1157
+ ], template: "\r\n<mat-form-field [appearance]=\"appearance()\" [className]=\"class()\" [subscriptSizing]=\"subscriptSizing()\">\r\n <mat-label>{{ label() }}</mat-label>\r\n <mat-select\r\n #matSelect\r\n [formControl]=\"innerControl\"\r\n [errorStateMatcher]=\"errorStateMatcher\"\r\n [required]=\"isRequired()\"\r\n [multiple]=\"multiple()\"\r\n [placeholder]=\"placeholder()\"\r\n (openedChange)=\"onOpenedChange($event)\"\r\n >\r\n @if(isLoading()) {\r\n <!--\r\n Opcion deshabilitada (no un div): mat-select no abre el panel si no\r\n tiene ninguna mat-option (_canOpen exige options.length > 0). Asi el\r\n panel abre tambien durante la carga y se ve el indicador.\r\n -->\r\n <mat-option disabled class=\"stateOption loadingOption\">\r\n <mat-spinner diameter=\"18\" />\r\n <span>{{ texts().common.loading }}</span>\r\n </mat-option>\r\n } @else {\r\n <div class=\"searchFilter\">\r\n <mat-icon class=\"searchIcon\">search</mat-icon>\r\n <input\r\n matInput\r\n #searchInput\r\n type=\"text\"\r\n [attr.aria-label]=\"texts().common.search\"\r\n [placeholder]=\"texts().common.search\"\r\n [value]=\"searchQuery()\"\r\n (input)=\"onSearchInput($any($event.target).value)\"\r\n (keydown)=\"onSearchKeydown($event)\"\r\n />\r\n <button type=\"button\" matIconButton [attr.aria-label]=\"texts().common.clearSearch\" (click)=\"clearSearch()\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n <!--\r\n Solo se renderizan las opciones que casan con el buscador (mas las\r\n seleccionadas). Las que no casan se quitan del DOM para que no se puedan\r\n enfocar con las flechas: con el panel abierto mat-select permite navegar\r\n a opciones deshabilitadas, asi que ocultarlas + disabled no bastaria.\r\n -->\r\n @for(option of displayedOptions(); track option.value) {\r\n <mat-option [value]=\"option.value\" [disabled]=\"option.disabled\">\r\n {{ option.label }}\r\n </mat-option>\r\n }\r\n @if(showNoOptionsMessage()) {\r\n <mat-option disabled class=\"stateOption noResults\">\r\n {{ hasData() ? texts().select.noResults : texts().common.noData }}\r\n </mat-option>\r\n }\r\n }\r\n </mat-select>\r\n @if(isLoading()) {\r\n <mat-icon matSuffix><mat-spinner diameter=\"20\" /></mat-icon>\r\n } @else if(clearable() && (multiple() ? value()?.length : value())) {\r\n <button\r\n matIconButton\r\n matSuffix\r\n [attr.aria-label]=\"texts().common.clearSearch\"\r\n (click)=\"onClearClick(); $event.stopPropagation()\"\r\n >\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n }\r\n <mat-error>{{ error() }}</mat-error>\r\n</mat-form-field>\r\n\r\n<!-- Anuncio para lectores de pantalla del numero de resultados al filtrar -->\r\n<div class=\"srOnly\" aria-live=\"polite\">{{ searchAnnouncement() }}</div>\r\n", styles: [":host{display:block;width:100%}mat-form-field{width:100%}mat-select{width:100%}.searchFilter{display:flex;align-items:center;position:sticky;top:-8px;height:48px;width:100%;background:var(--mat-sys-surface-container);z-index:10;border-bottom:1px solid var(--mat-sys-outline-variant)}.searchFilter input{height:48px;padding:0 48px;width:calc(100% - 96px);position:absolute;top:0;left:0}.searchFilter .searchIcon{position:absolute;top:0;left:0;height:48px;width:48px;display:flex;align-items:center;justify-content:center}.searchFilter button{position:absolute;right:5px}.stateOption{justify-content:center;text-align:center;color:var(--mat-sys-on-surface-variant);font:var(--mat-sys-body-medium);pointer-events:none;opacity:1}.loadingOption{display:flex;align-items:center;gap:8px}.srOnly{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"] }]
801
1158
  }], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], basicSelectConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "basicSelectConfig", required: true }] }], isLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoading", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], subscriptSizing: [{ type: i0.Input, args: [{ isSignal: true, alias: "subscriptSizing", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], matSelect: [{ type: i0.ViewChild, args: ['matSelect', { isSignal: true }] }], searchInput: [{ type: i0.ViewChild, args: ['searchInput', { isSignal: true }] }] } });
802
1159
 
803
1160
  var DialogBodyType;
@@ -807,6 +1164,14 @@ var DialogBodyType;
807
1164
  DialogBodyType["COMPONENT"] = "component";
808
1165
  DialogBodyType["TEMPLATE"] = "template";
809
1166
  })(DialogBodyType || (DialogBodyType = {}));
1167
+ /**
1168
+ * Lo que un componente o plantilla dentro de un diálogo de NgxDialogService puede controlar.
1169
+ *
1170
+ * - En un componente: `inject(NgxDialogContext)`.
1171
+ * - En una plantilla: viene en el contexto como `dialog` (`let-dialog="dialog"`).
1172
+ */
1173
+ class NgxDialogContext {
1174
+ }
810
1175
 
811
1176
  class DynamicHostDirective {
812
1177
  _vcr = inject(ViewContainerRef);
@@ -845,10 +1210,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
845
1210
  }]
846
1211
  }], ctorParameters: () => [], propDecorators: { component: [{ type: i0.Input, args: [{ isSignal: true, alias: "component", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }] } });
847
1212
 
1213
+ /**
1214
+ * Diálogo genérico que abre NgxDialogService. El contenido (texto, HTML, componente o plantilla)
1215
+ * puede usar NgxDialogContext para devolver un resultado o deshabilitar el botón de confirmar.
1216
+ */
848
1217
  class NgxDialog {
849
- //dependencies injection
850
1218
  _dialogRef = inject((MatDialogRef));
851
1219
  _data = inject(MAT_DIALOG_DATA);
1220
+ _texts = inject(NgxTexts).texts;
852
1221
  title = this._data.title;
853
1222
  icon = this._data.icon;
854
1223
  iconColor = this._data.iconColor;
@@ -856,17 +1225,35 @@ class NgxDialog {
856
1225
  body = this._data.body;
857
1226
  showCancel = this._data.showCancel ?? true;
858
1227
  showConfirm = this._data.showConfirm ?? true;
859
- cancelText = this._data.cancelText ?? 'Cancelar';
860
- confirmText = this._data.confirmText ?? 'Aceptar';
1228
+ destructive = this._data.destructive ?? false;
1229
+ /** La X no tiene sentido en un diálogo con disableClose (está pensado para no poder cerrarse sin decidir). */
1230
+ showClose = this._data.showClose ?? !this._dialogRef.disableClose;
1231
+ closeLabel = this._texts().dialog.close;
1232
+ cancelText = this._data.cancelText ?? this._texts().dialog.cancel;
1233
+ confirmText = this._data.confirmText ?? this._texts().dialog.accept;
1234
+ // ── NgxDialogContext ──────────────────────────────────────────────────────
1235
+ result = signal(undefined, ...(ngDevMode ? [{ debugName: "result" }] : []));
1236
+ confirmDisabled = signal(false, ...(ngDevMode ? [{ debugName: "confirmDisabled" }] : []));
1237
+ close(result) {
1238
+ this._dialogRef.close(result);
1239
+ }
1240
+ // ── Plantilla ─────────────────────────────────────────────────────────────
861
1241
  DialogBodyType = DialogBodyType;
1242
+ templateContext = {
1243
+ $implicit: this.body.data,
1244
+ dialog: this,
1245
+ };
862
1246
  onCancelClick() {
863
1247
  this._dialogRef.close(false);
864
1248
  }
865
1249
  onConfirmClick() {
866
- this._dialogRef.close(true);
1250
+ if (this.confirmDisabled())
1251
+ return;
1252
+ const result = this.result();
1253
+ this._dialogRef.close(result === undefined ? true : result);
867
1254
  }
868
1255
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxDialog, deps: [], target: i0.ɵɵFactoryTarget.Component });
869
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: NgxDialog, isStandalone: true, selector: "ngx-dialog", ngImport: i0, template: "<h2 mat-dialog-title class=\"title\">\r\n {{ title }}\r\n @if(icon) {\r\n <mat-icon \r\n [style.color]=\"iconColor\"\r\n class=\"icon\"\r\n >\r\n {{ icon }}\r\n </mat-icon>\r\n }\r\n</h2>\r\n<mat-dialog-content>\r\n @if(subtitle) {\r\n <p class=\"subtitle\">{{ subtitle }}</p>\r\n <mat-divider />\r\n }\r\n\r\n <div class=\"content\">\r\n @switch (body.type) {\r\n @case (DialogBodyType.TEXT) {\r\n <p>{{ body.content }}</p>\r\n }\r\n @case (DialogBodyType.HTML) {\r\n <div [innerHTML]=\"body.content\"></div>\r\n }\r\n @case (DialogBodyType.COMPONENT) {\r\n <ng-container \r\n ngxDynamicHost \r\n [component]=\"$any(body.content)\"\r\n [data]=\"body.data\"\r\n />\r\n }\r\n @case (DialogBodyType.TEMPLATE) {\r\n <ng-container \r\n [ngTemplateOutlet]=\"$any(body.content)\"\r\n [ngTemplateOutletContext]=\"{ $implicit: body.data }\"\r\n />\r\n }\r\n }\r\n </div>\r\n\r\n</mat-dialog-content>\r\n<mat-dialog-actions align=\"end\" class=\"matDialogActionsCustomGap\">\r\n @if(showCancel) {\r\n <button matButton=\"outlined\" (click)=\"onCancelClick()\">\r\n {{ cancelText }}\r\n </button>\r\n }\r\n @if(showConfirm) {\r\n <button matButton=\"filled\" (click)=\"onConfirmClick()\">\r\n {{ confirmText }}\r\n </button>\r\n }\r\n</mat-dialog-actions>\r\n", styles: [":host{display:block}h2{display:flex;align-items:center;font-weight:600;padding:8px 16px;gap:8px}mat-icon{min-width:28px;min-height:28px;font-size:28px}.subtitle{font-weight:400;font-size:14px;color:#0009;margin-top:-4px}.matDialogActionsCustomGap{gap:.25rem}\n"], dependencies: [{ kind: "directive", type: MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i1$2.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i11.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: DynamicHostDirective, selector: "[ngxDynamicHost]", inputs: ["component", "data"] }] });
1256
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: NgxDialog, isStandalone: true, selector: "ngx-dialog", providers: [{ provide: NgxDialogContext, useExisting: forwardRef(() => NgxDialog) }], ngImport: i0, template: "<!--\r\n Encabezado: el h2 (mat-dialog-title) da el nombre accesible al di\u00E1logo, as\u00ED que la X va fuera de \u00E9l,\r\n posicionada encima, para que no forme parte de ese nombre.\r\n-->\r\n<div class=\"ngx-dialog__header\" [class.ngx-dialog__header--closable]=\"showClose\">\r\n <h2 mat-dialog-title class=\"ngx-dialog__title\">\r\n @if (icon) {\r\n <mat-icon class=\"ngx-dialog__icon\" [style.color]=\"iconColor || null\" aria-hidden=\"true\">{{ icon }}</mat-icon>\r\n }\r\n <span class=\"ngx-dialog__heading\">\r\n <span class=\"ngx-dialog__title-text\">{{ title }}</span>\r\n @if (subtitle) {\r\n <span class=\"ngx-dialog__subtitle\">{{ subtitle }}</span>\r\n }\r\n </span>\r\n </h2>\r\n\r\n @if (showClose) {\r\n <button\r\n type=\"button\"\r\n matIconButton\r\n class=\"ngx-dialog__close\"\r\n [attr.aria-label]=\"closeLabel\"\r\n [matTooltip]=\"closeLabel\"\r\n (click)=\"close()\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n }\r\n</div>\r\n\r\n<mat-dialog-content>\r\n <div class=\"ngx-dialog__content\">\r\n @switch (body.type) {\r\n @case (DialogBodyType.TEXT) {\r\n <p class=\"ngx-dialog__text\">{{ body.content }}</p>\r\n }\r\n @case (DialogBodyType.HTML) {\r\n <div [innerHTML]=\"body.content\"></div>\r\n }\r\n @case (DialogBodyType.COMPONENT) {\r\n <ng-container\r\n ngxDynamicHost\r\n [component]=\"$any(body.content)\"\r\n [data]=\"body.data\"\r\n />\r\n }\r\n @case (DialogBodyType.TEMPLATE) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"$any(body.content)\"\r\n [ngTemplateOutletContext]=\"templateContext\"\r\n />\r\n }\r\n }\r\n </div>\r\n</mat-dialog-content>\r\n\r\n@if (showCancel || showConfirm) {\r\n <mat-dialog-actions align=\"end\" class=\"ngx-dialog__actions\">\r\n @if (showCancel) {\r\n <button type=\"button\" matButton=\"outlined\" (click)=\"onCancelClick()\">\r\n {{ cancelText }}\r\n </button>\r\n }\r\n @if (showConfirm) {\r\n <button\r\n type=\"button\"\r\n matButton=\"filled\"\r\n class=\"ngx-dialog__confirm\"\r\n [class.ngx-dialog__confirm--destructive]=\"destructive\"\r\n [disabled]=\"confirmDisabled()\"\r\n (click)=\"onConfirmClick()\">\r\n {{ confirmText }}\r\n </button>\r\n }\r\n </mat-dialog-actions>\r\n}\r\n", styles: [":host{display:block}.ngx-dialog__header{position:relative}.ngx-dialog__title.mat-mdc-dialog-title{display:flex;align-items:center;gap:12px;margin:0;padding:18px 24px 16px}.ngx-dialog__title.mat-mdc-dialog-title:before{display:none}.ngx-dialog__header--closable .ngx-dialog__title.mat-mdc-dialog-title{padding-right:64px}.ngx-dialog__icon{flex:none;width:28px;height:28px;font-size:28px}.ngx-dialog__heading{display:flex;flex-direction:column;gap:2px;min-width:0}.ngx-dialog__title-text{font:var(--mat-sys-title-large);color:var(--mat-sys-on-surface);overflow-wrap:anywhere}.ngx-dialog__subtitle{font:var(--mat-sys-body-medium);color:var(--mat-sys-on-surface-variant)}.ngx-dialog__close{position:absolute;top:50%;right:12px;transform:translateY(-50%);color:var(--mat-sys-on-surface-variant)}.ngx-dialog__content{padding-top:4px}.ngx-dialog__text{margin:0;white-space:pre-line}.ngx-dialog__actions{gap:8px}.ngx-dialog__confirm--destructive{--mat-button-filled-container-color: var(--mat-sys-error);--mat-button-filled-label-text-color: var(--mat-sys-on-error);--mat-button-filled-state-layer-color: var(--mat-sys-on-error)}\n"], dependencies: [{ kind: "directive", type: MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: DynamicHostDirective, selector: "[ngxDynamicHost]", inputs: ["component", "data"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
870
1257
  }
871
1258
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxDialog, decorators: [{
872
1259
  type: Component,
@@ -874,20 +1261,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
874
1261
  MatDialogTitle,
875
1262
  MatDialogContent,
876
1263
  MatDialogActions,
877
- MatDividerModule,
878
1264
  MatButtonModule,
879
1265
  MatIconModule,
880
- CommonModule,
881
- DynamicHostDirective
882
- ], template: "<h2 mat-dialog-title class=\"title\">\r\n {{ title }}\r\n @if(icon) {\r\n <mat-icon \r\n [style.color]=\"iconColor\"\r\n class=\"icon\"\r\n >\r\n {{ icon }}\r\n </mat-icon>\r\n }\r\n</h2>\r\n<mat-dialog-content>\r\n @if(subtitle) {\r\n <p class=\"subtitle\">{{ subtitle }}</p>\r\n <mat-divider />\r\n }\r\n\r\n <div class=\"content\">\r\n @switch (body.type) {\r\n @case (DialogBodyType.TEXT) {\r\n <p>{{ body.content }}</p>\r\n }\r\n @case (DialogBodyType.HTML) {\r\n <div [innerHTML]=\"body.content\"></div>\r\n }\r\n @case (DialogBodyType.COMPONENT) {\r\n <ng-container \r\n ngxDynamicHost \r\n [component]=\"$any(body.content)\"\r\n [data]=\"body.data\"\r\n />\r\n }\r\n @case (DialogBodyType.TEMPLATE) {\r\n <ng-container \r\n [ngTemplateOutlet]=\"$any(body.content)\"\r\n [ngTemplateOutletContext]=\"{ $implicit: body.data }\"\r\n />\r\n }\r\n }\r\n </div>\r\n\r\n</mat-dialog-content>\r\n<mat-dialog-actions align=\"end\" class=\"matDialogActionsCustomGap\">\r\n @if(showCancel) {\r\n <button matButton=\"outlined\" (click)=\"onCancelClick()\">\r\n {{ cancelText }}\r\n </button>\r\n }\r\n @if(showConfirm) {\r\n <button matButton=\"filled\" (click)=\"onConfirmClick()\">\r\n {{ confirmText }}\r\n </button>\r\n }\r\n</mat-dialog-actions>\r\n", styles: [":host{display:block}h2{display:flex;align-items:center;font-weight:600;padding:8px 16px;gap:8px}mat-icon{min-width:28px;min-height:28px;font-size:28px}.subtitle{font-weight:400;font-size:14px;color:#0009;margin-top:-4px}.matDialogActionsCustomGap{gap:.25rem}\n"] }]
1266
+ MatTooltipModule,
1267
+ NgTemplateOutlet,
1268
+ DynamicHostDirective,
1269
+ ], changeDetection: ChangeDetectionStrategy.OnPush, providers: [{ provide: NgxDialogContext, useExisting: forwardRef(() => NgxDialog) }], template: "<!--\r\n Encabezado: el h2 (mat-dialog-title) da el nombre accesible al di\u00E1logo, as\u00ED que la X va fuera de \u00E9l,\r\n posicionada encima, para que no forme parte de ese nombre.\r\n-->\r\n<div class=\"ngx-dialog__header\" [class.ngx-dialog__header--closable]=\"showClose\">\r\n <h2 mat-dialog-title class=\"ngx-dialog__title\">\r\n @if (icon) {\r\n <mat-icon class=\"ngx-dialog__icon\" [style.color]=\"iconColor || null\" aria-hidden=\"true\">{{ icon }}</mat-icon>\r\n }\r\n <span class=\"ngx-dialog__heading\">\r\n <span class=\"ngx-dialog__title-text\">{{ title }}</span>\r\n @if (subtitle) {\r\n <span class=\"ngx-dialog__subtitle\">{{ subtitle }}</span>\r\n }\r\n </span>\r\n </h2>\r\n\r\n @if (showClose) {\r\n <button\r\n type=\"button\"\r\n matIconButton\r\n class=\"ngx-dialog__close\"\r\n [attr.aria-label]=\"closeLabel\"\r\n [matTooltip]=\"closeLabel\"\r\n (click)=\"close()\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n }\r\n</div>\r\n\r\n<mat-dialog-content>\r\n <div class=\"ngx-dialog__content\">\r\n @switch (body.type) {\r\n @case (DialogBodyType.TEXT) {\r\n <p class=\"ngx-dialog__text\">{{ body.content }}</p>\r\n }\r\n @case (DialogBodyType.HTML) {\r\n <div [innerHTML]=\"body.content\"></div>\r\n }\r\n @case (DialogBodyType.COMPONENT) {\r\n <ng-container\r\n ngxDynamicHost\r\n [component]=\"$any(body.content)\"\r\n [data]=\"body.data\"\r\n />\r\n }\r\n @case (DialogBodyType.TEMPLATE) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"$any(body.content)\"\r\n [ngTemplateOutletContext]=\"templateContext\"\r\n />\r\n }\r\n }\r\n </div>\r\n</mat-dialog-content>\r\n\r\n@if (showCancel || showConfirm) {\r\n <mat-dialog-actions align=\"end\" class=\"ngx-dialog__actions\">\r\n @if (showCancel) {\r\n <button type=\"button\" matButton=\"outlined\" (click)=\"onCancelClick()\">\r\n {{ cancelText }}\r\n </button>\r\n }\r\n @if (showConfirm) {\r\n <button\r\n type=\"button\"\r\n matButton=\"filled\"\r\n class=\"ngx-dialog__confirm\"\r\n [class.ngx-dialog__confirm--destructive]=\"destructive\"\r\n [disabled]=\"confirmDisabled()\"\r\n (click)=\"onConfirmClick()\">\r\n {{ confirmText }}\r\n </button>\r\n }\r\n </mat-dialog-actions>\r\n}\r\n", styles: [":host{display:block}.ngx-dialog__header{position:relative}.ngx-dialog__title.mat-mdc-dialog-title{display:flex;align-items:center;gap:12px;margin:0;padding:18px 24px 16px}.ngx-dialog__title.mat-mdc-dialog-title:before{display:none}.ngx-dialog__header--closable .ngx-dialog__title.mat-mdc-dialog-title{padding-right:64px}.ngx-dialog__icon{flex:none;width:28px;height:28px;font-size:28px}.ngx-dialog__heading{display:flex;flex-direction:column;gap:2px;min-width:0}.ngx-dialog__title-text{font:var(--mat-sys-title-large);color:var(--mat-sys-on-surface);overflow-wrap:anywhere}.ngx-dialog__subtitle{font:var(--mat-sys-body-medium);color:var(--mat-sys-on-surface-variant)}.ngx-dialog__close{position:absolute;top:50%;right:12px;transform:translateY(-50%);color:var(--mat-sys-on-surface-variant)}.ngx-dialog__content{padding-top:4px}.ngx-dialog__text{margin:0;white-space:pre-line}.ngx-dialog__actions{gap:8px}.ngx-dialog__confirm--destructive{--mat-button-filled-container-color: var(--mat-sys-error);--mat-button-filled-label-text-color: var(--mat-sys-on-error);--mat-button-filled-state-layer-color: var(--mat-sys-on-error)}\n"] }]
883
1270
  }] });
884
1271
 
885
1272
  class NgxConfirmDialogComponent {
886
1273
  dialogRef = inject((MatDialogRef));
887
1274
  data = inject(MAT_DIALOG_DATA);
888
- intl = inject(NgxTablesIntl);
1275
+ texts = inject(NgxTexts).texts;
889
1276
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxConfirmDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
890
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: NgxConfirmDialogComponent, isStandalone: true, selector: "ngx-confirm-dialog", ngImport: i0, template: "<h2 mat-dialog-title>{{data.title}}</h2>\r\n<mat-dialog-content>\r\n @if(data.body) {\r\n <p>{{data.body}}</p>\r\n }\r\n \r\n @if (data.template) {\r\n <ng-container *ngTemplateOutlet=\"data.template; context: { $implicit: data.row }\"></ng-container>\r\n }\r\n</mat-dialog-content>\r\n<mat-dialog-actions>\r\n <button matButton [mat-dialog-close]=\"false\">{{ data.denyButtonLabel ?? intl.cancelButtonLabel }}</button>\r\n <button matButton [mat-dialog-close]=\"true\">{{ data.confirmButtonLabel ?? intl.confirmButtonLabel }}</button>\r\n</mat-dialog-actions>", styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i11.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
1277
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: NgxConfirmDialogComponent, isStandalone: true, selector: "ngx-confirm-dialog", ngImport: i0, template: "<h2 mat-dialog-title>{{data.title}}</h2>\r\n<mat-dialog-content>\r\n @if(data.body) {\r\n <p>{{data.body}}</p>\r\n }\r\n \r\n @if (data.template) {\r\n <ng-container *ngTemplateOutlet=\"data.template; context: { $implicit: data.row }\"></ng-container>\r\n }\r\n</mat-dialog-content>\r\n<mat-dialog-actions>\r\n <button matButton [mat-dialog-close]=\"false\">{{ data.denyButtonLabel ?? texts().common.cancel }}</button>\r\n <button matButton [mat-dialog-close]=\"true\">{{ data.confirmButtonLabel ?? texts().common.confirm }}</button>\r\n</mat-dialog-actions>", styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i11.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
891
1278
  }
892
1279
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxConfirmDialogComponent, decorators: [{
893
1280
  type: Component,
@@ -898,7 +1285,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
898
1285
  MatDialogActions,
899
1286
  MatDialogClose,
900
1287
  CommonModule
901
- ], template: "<h2 mat-dialog-title>{{data.title}}</h2>\r\n<mat-dialog-content>\r\n @if(data.body) {\r\n <p>{{data.body}}</p>\r\n }\r\n \r\n @if (data.template) {\r\n <ng-container *ngTemplateOutlet=\"data.template; context: { $implicit: data.row }\"></ng-container>\r\n }\r\n</mat-dialog-content>\r\n<mat-dialog-actions>\r\n <button matButton [mat-dialog-close]=\"false\">{{ data.denyButtonLabel ?? intl.cancelButtonLabel }}</button>\r\n <button matButton [mat-dialog-close]=\"true\">{{ data.confirmButtonLabel ?? intl.confirmButtonLabel }}</button>\r\n</mat-dialog-actions>", styles: [":host{display:block}\n"] }]
1288
+ ], template: "<h2 mat-dialog-title>{{data.title}}</h2>\r\n<mat-dialog-content>\r\n @if(data.body) {\r\n <p>{{data.body}}</p>\r\n }\r\n \r\n @if (data.template) {\r\n <ng-container *ngTemplateOutlet=\"data.template; context: { $implicit: data.row }\"></ng-container>\r\n }\r\n</mat-dialog-content>\r\n<mat-dialog-actions>\r\n <button matButton [mat-dialog-close]=\"false\">{{ data.denyButtonLabel ?? texts().common.cancel }}</button>\r\n <button matButton [mat-dialog-close]=\"true\">{{ data.confirmButtonLabel ?? texts().common.confirm }}</button>\r\n</mat-dialog-actions>", styles: [":host{display:block}\n"] }]
902
1289
  }] });
903
1290
 
904
1291
  class DynamicCellHostDirective {
@@ -1130,40 +1517,40 @@ class AdvancedFilterUtils {
1130
1517
  static isNonEmptyRule(rule) {
1131
1518
  return !!(rule.key && rule.operator && rule.value !== undefined && rule.value !== null && rule.value !== '');
1132
1519
  }
1133
- static groupsToReadableHtml(groups, columns, intl) {
1134
- return this.groupToHtml(groups[0], columns, intl);
1520
+ static groupsToReadableHtml(groups, columns, texts) {
1521
+ return this.groupToHtml(groups[0], columns, texts);
1135
1522
  //return groups.map(g => this.groupToString(g)).join(' OR ');
1136
1523
  }
1137
- static groupToHtml(group, columns, intl) {
1138
- const connectorLabel = group.connector === 'AND' ? intl.connectorAnd : intl.connectorOr;
1524
+ static groupToHtml(group, columns, texts) {
1525
+ const connectorLabel = group.connector === 'AND' ? texts.advancedFilters.and : texts.advancedFilters.or;
1139
1526
  const connector = ` <strong>${connectorLabel}</strong> `;
1140
1527
  const parts = group.filters.map(filter => {
1141
1528
  if (this.isFilterGroup(filter))
1142
- return `<strong>[ </strong>${this.groupToHtml(filter, columns, intl)}<strong> ]</strong>`;
1529
+ return `<strong>[ </strong>${this.groupToHtml(filter, columns, texts)}<strong> ]</strong>`;
1143
1530
  else
1144
- return this.ruleToHtml(filter, columns, intl);
1531
+ return this.ruleToHtml(filter, columns, texts);
1145
1532
  });
1146
1533
  return parts.join(connector);
1147
1534
  }
1148
- static ruleToHtml(rule, columns, intl) {
1535
+ static ruleToHtml(rule, columns, texts) {
1149
1536
  const column = columns.find(column => column.key == rule.key);
1150
1537
  if (!column)
1151
1538
  return "";
1152
1539
  const key = `<i>${column.label}</i>`;
1153
- const operator = rule.operator ? this.getOperatorLabel(rule.operator, intl).toLowerCase() : '';
1540
+ const operator = rule.operator ? this.getOperatorLabel(rule.operator, texts).toLowerCase() : '';
1154
1541
  //const operator = rule.operator ?? '';
1155
1542
  const value = this.valueToHtml(rule.value, column);
1156
1543
  return `${key} ${operator} "${value}"`;
1157
1544
  }
1158
- static getOperatorLabel(operator, intl) {
1545
+ static getOperatorLabel(operator, texts) {
1159
1546
  const operatorLabels = {
1160
- '=': intl.operatorEquals,
1161
- '<>': intl.operatorNotEquals,
1162
- '>': intl.operatorGreaterThan,
1163
- '>=': intl.operatorGreaterOrEquals,
1164
- '<': intl.operatorLessThan,
1165
- '<=': intl.operatorLessOrEquals,
1166
- 'LIKE': intl.operatorLike
1547
+ '=': texts.advancedFilters.operators.equals,
1548
+ '<>': texts.advancedFilters.operators.notEquals,
1549
+ '>': texts.advancedFilters.operators.greaterThan,
1550
+ '>=': texts.advancedFilters.operators.greaterOrEquals,
1551
+ '<': texts.advancedFilters.operators.lessThan,
1552
+ '<=': texts.advancedFilters.operators.lessOrEquals,
1553
+ 'LIKE': texts.advancedFilters.operators.like
1167
1554
  };
1168
1555
  return operatorLabels[operator];
1169
1556
  }
@@ -1454,7 +1841,7 @@ class ConfigureTableColumnsComponent {
1454
1841
  columnConfigService = inject(ColumnConfigService);
1455
1842
  dialogRef = inject((MatDialogRef));
1456
1843
  data = inject(MAT_DIALOG_DATA);
1457
- intl = inject(NgxTablesIntl);
1844
+ texts = inject(NgxTexts).texts;
1458
1845
  columns = signal(this.data.columns, ...(ngDevMode ? [{ debugName: "columns" }] : []));
1459
1846
  isConfirmDisabled = computed(() => {
1460
1847
  const allDisabled = this.columns().every(column => !column.show);
@@ -1547,7 +1934,7 @@ class ConfigureTableColumnsComponent {
1547
1934
  this.dialogRef.close();
1548
1935
  }
1549
1936
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfigureTableColumnsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1550
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: ConfigureTableColumnsComponent, isStandalone: true, selector: "lib-configure-table-columns", ngImport: i0, template: "<h2 mat-dialog-title>{{intl.configureColumnsTitle}} {{data.tableName| lowercase}}</h2>\r\n<mat-dialog-content>\r\n\r\n <div class=\"columnsList\" cdkDropList (cdkDropListDropped)=\"onDrop($event)\">\r\n @for (column of columns(); track $index; let first = $first; let last = $last;) {\r\n <div \r\n class=\"columnContainer\" \r\n cdkDrag \r\n [class.pinned]=\"$index == animationIndex()\"\r\n [style]=\"{ transition: `background-color ${animationTime}ms ease` }\">\r\n\r\n <div class=\"labelContainer\">\r\n <mat-icon>drag_indicator</mat-icon>\r\n <p class=\"label\">\r\n {{data.columnsLabels[column.key] ?? ''}}\r\n @if(hasFilterAndDisabled(column)) {\r\n <span> {{intl.hasFiltersAppliedText}}</span>\r\n }\r\n </p>\r\n </div>\r\n\r\n <div class=\"actions\">\r\n <button \r\n matIconButton\r\n [matTooltip]=\"column.isSticky ? intl.unpinColumnTooltip : intl.pinColumnTooltip\"\r\n (click)=\"onPinClick(column, $index)\">\r\n <mat-icon>{{column.isSticky ? 'keep_off' : 'keep'}}</mat-icon>\r\n </button>\r\n\r\n <button [matTooltip]=\"intl.moveUpTooltip\" matIconButton [disabled]=\"$first\" (click)=\"onUpClick($index)\"><mat-icon>keyboard_arrow_up</mat-icon></button>\r\n <button [matTooltip]=\"intl.moveDownTooltip\" matIconButton [disabled]=\"$last\" (click)=\"onDownClick($index)\"><mat-icon>keyboard_arrow_down</mat-icon></button>\r\n <mat-slide-toggle [checked]=\"column.show\" (toggleChange)=\"onToggleChange(column)\"></mat-slide-toggle>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n <p class=\"note\"><span>{{intl.noteLabel}}</span> {{intl.hideColumnWithFiltersNote}}</p>\r\n \r\n</mat-dialog-content>\r\n<mat-dialog-actions>\r\n <button matButton [mat-dialog-close]=\"undefined\">{{intl.closeButtonLabel}}</button>\r\n <button matButton (click)=\"onResetClick()\">{{intl.resetColumnsButtonLabel}}</button>\r\n <button matButton [disabled]=\"isConfirmDisabled()\" (click)=\"onConfirmClick()\">{{intl.confirmButtonLabel}}</button>\r\n</mat-dialog-actions>", styles: [".columnsList{display:flex;flex-direction:column;cursor:grab}.columnContainer{display:flex;flex-direction:row;align-items:center;justify-content:space-between;background-color:var(--mat-sys-surface);padding:4px 10px}p{margin:0}.label span{font:var(--mat-sys-label-small);color:var(--mat-sys-error);font-weight:400;font-style:italic}.labelContainer,.actions{display:flex;flex-direction:row;align-items:center;gap:10px}.note{margin-top:20px;font-style:italic;font:var(--mat-sys-body-small);font-weight:300;width:100%;text-align:center}.note span{font-weight:500}.cdk-drag-preview{border:none;box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.columnContainer:last-child{border:none}.columnsList.cdk-drop-list-dragging .columnContainer:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.columnContainer.pinned{background-color:#ffeb3b4d;border-radius:4px}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i3$2.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "pipe", type: LowerCasePipe, name: "lowercase" }] });
1937
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: ConfigureTableColumnsComponent, isStandalone: true, selector: "lib-configure-table-columns", ngImport: i0, template: "<h2 mat-dialog-title>{{texts().columnsDialog.title}} {{data.tableName| lowercase}}</h2>\r\n<mat-dialog-content>\r\n\r\n <div class=\"columnsList\" cdkDropList (cdkDropListDropped)=\"onDrop($event)\">\r\n @for (column of columns(); track $index; let first = $first; let last = $last;) {\r\n <div \r\n class=\"columnContainer\" \r\n cdkDrag \r\n [class.pinned]=\"$index == animationIndex()\"\r\n [style]=\"{ transition: `background-color ${animationTime}ms ease` }\">\r\n\r\n <div class=\"labelContainer\">\r\n <mat-icon>drag_indicator</mat-icon>\r\n <p class=\"label\">\r\n {{data.columnsLabels[column.key] ?? ''}}\r\n @if(hasFilterAndDisabled(column)) {\r\n <span> {{texts().columnsDialog.hasFiltersApplied}}</span>\r\n }\r\n </p>\r\n </div>\r\n\r\n <div class=\"actions\">\r\n <button \r\n matIconButton\r\n [matTooltip]=\"column.isSticky ? texts().columnsDialog.unpin : texts().columnsDialog.pin\"\r\n (click)=\"onPinClick(column, $index)\">\r\n <mat-icon>{{column.isSticky ? 'keep_off' : 'keep'}}</mat-icon>\r\n </button>\r\n\r\n <button [matTooltip]=\"texts().columnsDialog.moveUp\" matIconButton [disabled]=\"$first\" (click)=\"onUpClick($index)\"><mat-icon>keyboard_arrow_up</mat-icon></button>\r\n <button [matTooltip]=\"texts().columnsDialog.moveDown\" matIconButton [disabled]=\"$last\" (click)=\"onDownClick($index)\"><mat-icon>keyboard_arrow_down</mat-icon></button>\r\n <mat-slide-toggle [checked]=\"column.show\" (toggleChange)=\"onToggleChange(column)\"></mat-slide-toggle>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n <p class=\"note\"><span>{{texts().columnsDialog.note}}</span> {{texts().columnsDialog.hideColumnWithFiltersNote}}</p>\r\n \r\n</mat-dialog-content>\r\n<mat-dialog-actions>\r\n <button matButton [mat-dialog-close]=\"undefined\">{{texts().common.close}}</button>\r\n <button matButton (click)=\"onResetClick()\">{{texts().columnsDialog.reset}}</button>\r\n <button matButton [disabled]=\"isConfirmDisabled()\" (click)=\"onConfirmClick()\">{{texts().common.confirm}}</button>\r\n</mat-dialog-actions>", styles: [".columnsList{display:flex;flex-direction:column;cursor:grab}.columnContainer{display:flex;flex-direction:row;align-items:center;justify-content:space-between;background-color:var(--mat-sys-surface);padding:4px 10px}p{margin:0}.label span{font:var(--mat-sys-label-small);color:var(--mat-sys-error);font-weight:400;font-style:italic}.labelContainer,.actions{display:flex;flex-direction:row;align-items:center;gap:10px}.note{margin-top:20px;font-style:italic;font:var(--mat-sys-body-small);font-weight:300;width:100%;text-align:center}.note span{font-weight:500}.cdk-drag-preview{border:none;box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.columnContainer:last-child{border:none}.columnsList.cdk-drop-list-dragging .columnContainer:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.columnContainer.pinned{background-color:#ffeb3b4d;border-radius:4px}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i3$2.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "pipe", type: LowerCasePipe, name: "lowercase" }] });
1551
1938
  }
1552
1939
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfigureTableColumnsComponent, decorators: [{
1553
1940
  type: Component,
@@ -1563,14 +1950,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
1563
1950
  CdkDropList,
1564
1951
  CdkDrag,
1565
1952
  MatTooltipModule
1566
- ], template: "<h2 mat-dialog-title>{{intl.configureColumnsTitle}} {{data.tableName| lowercase}}</h2>\r\n<mat-dialog-content>\r\n\r\n <div class=\"columnsList\" cdkDropList (cdkDropListDropped)=\"onDrop($event)\">\r\n @for (column of columns(); track $index; let first = $first; let last = $last;) {\r\n <div \r\n class=\"columnContainer\" \r\n cdkDrag \r\n [class.pinned]=\"$index == animationIndex()\"\r\n [style]=\"{ transition: `background-color ${animationTime}ms ease` }\">\r\n\r\n <div class=\"labelContainer\">\r\n <mat-icon>drag_indicator</mat-icon>\r\n <p class=\"label\">\r\n {{data.columnsLabels[column.key] ?? ''}}\r\n @if(hasFilterAndDisabled(column)) {\r\n <span> {{intl.hasFiltersAppliedText}}</span>\r\n }\r\n </p>\r\n </div>\r\n\r\n <div class=\"actions\">\r\n <button \r\n matIconButton\r\n [matTooltip]=\"column.isSticky ? intl.unpinColumnTooltip : intl.pinColumnTooltip\"\r\n (click)=\"onPinClick(column, $index)\">\r\n <mat-icon>{{column.isSticky ? 'keep_off' : 'keep'}}</mat-icon>\r\n </button>\r\n\r\n <button [matTooltip]=\"intl.moveUpTooltip\" matIconButton [disabled]=\"$first\" (click)=\"onUpClick($index)\"><mat-icon>keyboard_arrow_up</mat-icon></button>\r\n <button [matTooltip]=\"intl.moveDownTooltip\" matIconButton [disabled]=\"$last\" (click)=\"onDownClick($index)\"><mat-icon>keyboard_arrow_down</mat-icon></button>\r\n <mat-slide-toggle [checked]=\"column.show\" (toggleChange)=\"onToggleChange(column)\"></mat-slide-toggle>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n <p class=\"note\"><span>{{intl.noteLabel}}</span> {{intl.hideColumnWithFiltersNote}}</p>\r\n \r\n</mat-dialog-content>\r\n<mat-dialog-actions>\r\n <button matButton [mat-dialog-close]=\"undefined\">{{intl.closeButtonLabel}}</button>\r\n <button matButton (click)=\"onResetClick()\">{{intl.resetColumnsButtonLabel}}</button>\r\n <button matButton [disabled]=\"isConfirmDisabled()\" (click)=\"onConfirmClick()\">{{intl.confirmButtonLabel}}</button>\r\n</mat-dialog-actions>", styles: [".columnsList{display:flex;flex-direction:column;cursor:grab}.columnContainer{display:flex;flex-direction:row;align-items:center;justify-content:space-between;background-color:var(--mat-sys-surface);padding:4px 10px}p{margin:0}.label span{font:var(--mat-sys-label-small);color:var(--mat-sys-error);font-weight:400;font-style:italic}.labelContainer,.actions{display:flex;flex-direction:row;align-items:center;gap:10px}.note{margin-top:20px;font-style:italic;font:var(--mat-sys-body-small);font-weight:300;width:100%;text-align:center}.note span{font-weight:500}.cdk-drag-preview{border:none;box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.columnContainer:last-child{border:none}.columnsList.cdk-drop-list-dragging .columnContainer:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.columnContainer.pinned{background-color:#ffeb3b4d;border-radius:4px}\n"] }]
1953
+ ], template: "<h2 mat-dialog-title>{{texts().columnsDialog.title}} {{data.tableName| lowercase}}</h2>\r\n<mat-dialog-content>\r\n\r\n <div class=\"columnsList\" cdkDropList (cdkDropListDropped)=\"onDrop($event)\">\r\n @for (column of columns(); track $index; let first = $first; let last = $last;) {\r\n <div \r\n class=\"columnContainer\" \r\n cdkDrag \r\n [class.pinned]=\"$index == animationIndex()\"\r\n [style]=\"{ transition: `background-color ${animationTime}ms ease` }\">\r\n\r\n <div class=\"labelContainer\">\r\n <mat-icon>drag_indicator</mat-icon>\r\n <p class=\"label\">\r\n {{data.columnsLabels[column.key] ?? ''}}\r\n @if(hasFilterAndDisabled(column)) {\r\n <span> {{texts().columnsDialog.hasFiltersApplied}}</span>\r\n }\r\n </p>\r\n </div>\r\n\r\n <div class=\"actions\">\r\n <button \r\n matIconButton\r\n [matTooltip]=\"column.isSticky ? texts().columnsDialog.unpin : texts().columnsDialog.pin\"\r\n (click)=\"onPinClick(column, $index)\">\r\n <mat-icon>{{column.isSticky ? 'keep_off' : 'keep'}}</mat-icon>\r\n </button>\r\n\r\n <button [matTooltip]=\"texts().columnsDialog.moveUp\" matIconButton [disabled]=\"$first\" (click)=\"onUpClick($index)\"><mat-icon>keyboard_arrow_up</mat-icon></button>\r\n <button [matTooltip]=\"texts().columnsDialog.moveDown\" matIconButton [disabled]=\"$last\" (click)=\"onDownClick($index)\"><mat-icon>keyboard_arrow_down</mat-icon></button>\r\n <mat-slide-toggle [checked]=\"column.show\" (toggleChange)=\"onToggleChange(column)\"></mat-slide-toggle>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n <p class=\"note\"><span>{{texts().columnsDialog.note}}</span> {{texts().columnsDialog.hideColumnWithFiltersNote}}</p>\r\n \r\n</mat-dialog-content>\r\n<mat-dialog-actions>\r\n <button matButton [mat-dialog-close]=\"undefined\">{{texts().common.close}}</button>\r\n <button matButton (click)=\"onResetClick()\">{{texts().columnsDialog.reset}}</button>\r\n <button matButton [disabled]=\"isConfirmDisabled()\" (click)=\"onConfirmClick()\">{{texts().common.confirm}}</button>\r\n</mat-dialog-actions>", styles: [".columnsList{display:flex;flex-direction:column;cursor:grab}.columnContainer{display:flex;flex-direction:row;align-items:center;justify-content:space-between;background-color:var(--mat-sys-surface);padding:4px 10px}p{margin:0}.label span{font:var(--mat-sys-label-small);color:var(--mat-sys-error);font-weight:400;font-style:italic}.labelContainer,.actions{display:flex;flex-direction:row;align-items:center;gap:10px}.note{margin-top:20px;font-style:italic;font:var(--mat-sys-body-small);font-weight:300;width:100%;text-align:center}.note span{font-weight:500}.cdk-drag-preview{border:none;box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.columnContainer:last-child{border:none}.columnsList.cdk-drop-list-dragging .columnContainer:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.columnContainer.pinned{background-color:#ffeb3b4d;border-radius:4px}\n"] }]
1567
1954
  }] });
1568
1955
 
1569
1956
  class PaginatedSearchableSelectComponent {
1570
1957
  // Inyectar el servicio de internacionalización.
1571
1958
  // inject() resuelve tambien los providers a nivel de componente/ruta, por lo que
1572
1959
  // el override sigue siendo posible.
1573
- intl = inject(NgxTablesIntl);
1960
+ texts = inject(NgxTexts).texts;
1574
1961
  control = input(...(ngDevMode ? [undefined, { debugName: "control" }] : []));
1575
1962
  endpoint = input.required(...(ngDevMode ? [{ debugName: "endpoint" }] : []));
1576
1963
  filters = input(signal({
@@ -1710,7 +2097,7 @@ class PaginatedSearchableSelectComponent {
1710
2097
  });
1711
2098
  }
1712
2099
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: PaginatedSearchableSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1713
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: PaginatedSearchableSelectComponent, isStandalone: true, selector: "ngx-paginated-searchable-select", inputs: { control: { classPropertyName: "control", publicName: "control", isSignal: true, isRequired: false, transformFunction: null }, endpoint: { classPropertyName: "endpoint", publicName: "endpoint", isSignal: true, isRequired: true, transformFunction: null }, filters: { classPropertyName: "filters", publicName: "filters", isSignal: true, isRequired: false, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: false, transformFunction: null }, compareWith: { classPropertyName: "compareWith", publicName: "compareWith", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, searchInputPlaceholder: { classPropertyName: "searchInputPlaceholder", publicName: "searchInputPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, selectLabel: { classPropertyName: "selectLabel", publicName: "selectLabel", isSignal: true, isRequired: false, transformFunction: null }, selectPlaceholder: { classPropertyName: "selectPlaceholder", publicName: "selectPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, clearableOptionLabel: { classPropertyName: "clearableOptionLabel", publicName: "clearableOptionLabel", isSignal: true, isRequired: false, transformFunction: null }, subscriptSizing: { classPropertyName: "subscriptSizing", publicName: "subscriptSizing", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { optionChange: "optionChange" }, viewQueries: [{ propertyName: "searcher", first: true, predicate: ["htmlSearcher"], descendants: true, isSignal: true }], ngImport: i0, template: "<mat-form-field [subscriptSizing]=\"subscriptSizing()\">\r\n @if (selectLabel()) {\r\n <mat-label>{{ selectLabel() }}</mat-label>\r\n }\r\n\r\n <mat-select\r\n [formControl]=\"innerControl()\"\r\n [multiple]=\"multiple()\"\r\n (openedChange)=\"openedChange($event)\" \r\n [placeholder]=\"selectPlaceholder()\"\r\n panelClass=\"searchableSelectPanelClass\"\r\n (selectionChange)=\"onOptionChange($event)\"\r\n [compareWith]=\"compareWith()\">\r\n\r\n <div class=\"searcherContainer\">\r\n <mat-icon class=\"searchIcon\">search</mat-icon>\r\n\r\n @if (htmlSearcher.value.length == 0) {\r\n <span>{{ searchInputPlaceholder() || intl.searchPlaceholder }}</span> \r\n }\r\n\r\n <input \r\n #htmlSearcher \r\n type=\"text\" \r\n matInput \r\n (keydown)=\"$event.stopPropagation()\"\r\n [value]=\"filters()().query ?? ''\" \r\n (input)=\"onQueryChange()\">\r\n\r\n @if (htmlSearcher.value.length > 0) {\r\n <button mat-icon-button (click)=\"cleanQuery()\"><mat-icon>close</mat-icon></button>\r\n }\r\n </div>\r\n\r\n <mat-progress-bar mode=\"indeterminate\" [style.visibility]=\"dataResource.isLoading() ? 'visible': 'hidden'\" />\r\n\r\n @if(clearable() && !multiple()) {\r\n <mat-option>{{ intl.getRemoveOptionText(getClearableOptionName()) }}</mat-option>\r\n }\r\n \r\n @for (option of options(); track $index) {\r\n <mat-option [value]=\"option\">\r\n {{ optionLabel()(option) }}\r\n </mat-option>\r\n }\r\n\r\n <!-- Es MUY importante que estos vayan los ultimos (al final de todas las opciones). -->\r\n @for (option of optionsSelectedForView(); track $index) {\r\n <mat-option [value]=\"option\" class=\"hideOption\">\r\n {{ optionLabel()(option) }}\r\n </mat-option>\r\n }\r\n\r\n <!-- Si es multiple, como no esta el option de resetear, si filtran y no hay opciones, y luego cierran el select el desplegable no se abre y queda inutilizado, por eso, ponemos esta opcion dummy, que siempre esta oculta, y no hace nada, pero ya hace que haya un item, y el desplegable se abra -->\r\n @if(multiple()) {\r\n <mat-option class=\"hideOption\" dummyOption></mat-option>\r\n }\r\n\r\n @if (total() == 0) {\r\n <p class=\"withoutResults\">{{ intl.noResultsMessage }}</p>\r\n }\r\n\r\n @if((filters()().pageNumber * filters()().pageSize) < total() && !dataResource.isLoading()) {\r\n <button matButton=\"text\" class=\"showMore\" (click)=\"onMoreClick()\">\r\n {{ intl.showMoreLabel }}\r\n </button>\r\n }\r\n </mat-select>\r\n\r\n <mat-error>{{ error() }}</mat-error>\r\n</mat-form-field>", styles: [":host{display:inline-flex}mat-form-field{width:100%}.searcherContainer{height:48px;position:sticky;top:0;left:0;right:0;background:var(--mat-sys-surface-container);z-index:10}mat-progress-bar{position:sticky;top:48px;z-index:10}.searcherContainer input{height:48px;padding:0 48px;width:calc(100% - 96px);position:absolute;top:0;left:0}.searchIcon{position:absolute;top:0;left:0;height:48px;width:48px;display:flex;align-items:center;justify-content:center;color:#888}.searcherContainer span{line-height:48px;position:absolute;left:48px;color:#888}.searcherContainer button{position:absolute;height:48px;width:48px;top:0;right:0;display:flex;align-items:center;justify-content:center}.hideOption{display:none}.withoutResults{color:#888;text-align:center;padding:0 16px;width:calc(100% - 32px)}.showMore{width:calc(100% - 32px);margin:4px 16px 0}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i3$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i3$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatProgressBarModule }, { kind: "component", type: i6.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }] });
2100
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: PaginatedSearchableSelectComponent, isStandalone: true, selector: "ngx-paginated-searchable-select", inputs: { control: { classPropertyName: "control", publicName: "control", isSignal: true, isRequired: false, transformFunction: null }, endpoint: { classPropertyName: "endpoint", publicName: "endpoint", isSignal: true, isRequired: true, transformFunction: null }, filters: { classPropertyName: "filters", publicName: "filters", isSignal: true, isRequired: false, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: false, transformFunction: null }, compareWith: { classPropertyName: "compareWith", publicName: "compareWith", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, searchInputPlaceholder: { classPropertyName: "searchInputPlaceholder", publicName: "searchInputPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, selectLabel: { classPropertyName: "selectLabel", publicName: "selectLabel", isSignal: true, isRequired: false, transformFunction: null }, selectPlaceholder: { classPropertyName: "selectPlaceholder", publicName: "selectPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, clearableOptionLabel: { classPropertyName: "clearableOptionLabel", publicName: "clearableOptionLabel", isSignal: true, isRequired: false, transformFunction: null }, subscriptSizing: { classPropertyName: "subscriptSizing", publicName: "subscriptSizing", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { optionChange: "optionChange" }, viewQueries: [{ propertyName: "searcher", first: true, predicate: ["htmlSearcher"], descendants: true, isSignal: true }], ngImport: i0, template: "<mat-form-field [subscriptSizing]=\"subscriptSizing()\">\r\n @if (selectLabel()) {\r\n <mat-label>{{ selectLabel() }}</mat-label>\r\n }\r\n\r\n <mat-select\r\n [formControl]=\"innerControl()\"\r\n [multiple]=\"multiple()\"\r\n (openedChange)=\"openedChange($event)\" \r\n [placeholder]=\"selectPlaceholder()\"\r\n panelClass=\"searchableSelectPanelClass\"\r\n (selectionChange)=\"onOptionChange($event)\"\r\n [compareWith]=\"compareWith()\">\r\n\r\n <div class=\"searcherContainer\">\r\n <mat-icon class=\"searchIcon\">search</mat-icon>\r\n\r\n @if (htmlSearcher.value.length == 0) {\r\n <span>{{ searchInputPlaceholder() || texts().common.search }}</span> \r\n }\r\n\r\n <input \r\n #htmlSearcher \r\n type=\"text\" \r\n matInput \r\n (keydown)=\"$event.stopPropagation()\"\r\n [value]=\"filters()().query ?? ''\" \r\n (input)=\"onQueryChange()\">\r\n\r\n @if (htmlSearcher.value.length > 0) {\r\n <button mat-icon-button (click)=\"cleanQuery()\"><mat-icon>close</mat-icon></button>\r\n }\r\n </div>\r\n\r\n <mat-progress-bar mode=\"indeterminate\" [style.visibility]=\"dataResource.isLoading() ? 'visible': 'hidden'\" />\r\n\r\n @if(clearable() && !multiple()) {\r\n <mat-option>{{ texts().select.removeOption(getClearableOptionName()) }}</mat-option>\r\n }\r\n \r\n @for (option of options(); track $index) {\r\n <mat-option [value]=\"option\">\r\n {{ optionLabel()(option) }}\r\n </mat-option>\r\n }\r\n\r\n <!-- Es MUY importante que estos vayan los ultimos (al final de todas las opciones). -->\r\n @for (option of optionsSelectedForView(); track $index) {\r\n <mat-option [value]=\"option\" class=\"hideOption\">\r\n {{ optionLabel()(option) }}\r\n </mat-option>\r\n }\r\n\r\n <!-- Si es multiple, como no esta el option de resetear, si filtran y no hay opciones, y luego cierran el select el desplegable no se abre y queda inutilizado, por eso, ponemos esta opcion dummy, que siempre esta oculta, y no hace nada, pero ya hace que haya un item, y el desplegable se abra -->\r\n @if(multiple()) {\r\n <mat-option class=\"hideOption\" dummyOption></mat-option>\r\n }\r\n\r\n @if (total() == 0) {\r\n <p class=\"withoutResults\">{{ texts().select.noResults }}</p>\r\n }\r\n\r\n @if((filters()().pageNumber * filters()().pageSize) < total() && !dataResource.isLoading()) {\r\n <button matButton=\"text\" class=\"showMore\" (click)=\"onMoreClick()\">\r\n {{ texts().select.showMore }}\r\n </button>\r\n }\r\n </mat-select>\r\n\r\n <mat-error>{{ error() }}</mat-error>\r\n</mat-form-field>", styles: [":host{display:inline-flex}mat-form-field{width:100%}.searcherContainer{height:48px;position:sticky;top:0;left:0;right:0;background:var(--mat-sys-surface-container);z-index:10}mat-progress-bar{position:sticky;top:48px;z-index:10}.searcherContainer input{height:48px;padding:0 48px;width:calc(100% - 96px);position:absolute;top:0;left:0}.searchIcon{position:absolute;top:0;left:0;height:48px;width:48px;display:flex;align-items:center;justify-content:center;color:#888}.searcherContainer span{line-height:48px;position:absolute;left:48px;color:#888}.searcherContainer button{position:absolute;height:48px;width:48px;top:0;right:0;display:flex;align-items:center;justify-content:center}.hideOption{display:none}.withoutResults{color:#888;text-align:center;padding:0 16px;width:calc(100% - 32px)}.showMore{width:calc(100% - 32px);margin:4px 16px 0}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$3.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i3$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i3$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatProgressBarModule }, { kind: "component", type: i6.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }] });
1714
2101
  }
1715
2102
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: PaginatedSearchableSelectComponent, decorators: [{
1716
2103
  type: Component,
@@ -1723,14 +2110,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
1723
2110
  MatButtonModule,
1724
2111
  CommonModule,
1725
2112
  MatProgressBarModule
1726
- ], template: "<mat-form-field [subscriptSizing]=\"subscriptSizing()\">\r\n @if (selectLabel()) {\r\n <mat-label>{{ selectLabel() }}</mat-label>\r\n }\r\n\r\n <mat-select\r\n [formControl]=\"innerControl()\"\r\n [multiple]=\"multiple()\"\r\n (openedChange)=\"openedChange($event)\" \r\n [placeholder]=\"selectPlaceholder()\"\r\n panelClass=\"searchableSelectPanelClass\"\r\n (selectionChange)=\"onOptionChange($event)\"\r\n [compareWith]=\"compareWith()\">\r\n\r\n <div class=\"searcherContainer\">\r\n <mat-icon class=\"searchIcon\">search</mat-icon>\r\n\r\n @if (htmlSearcher.value.length == 0) {\r\n <span>{{ searchInputPlaceholder() || intl.searchPlaceholder }}</span> \r\n }\r\n\r\n <input \r\n #htmlSearcher \r\n type=\"text\" \r\n matInput \r\n (keydown)=\"$event.stopPropagation()\"\r\n [value]=\"filters()().query ?? ''\" \r\n (input)=\"onQueryChange()\">\r\n\r\n @if (htmlSearcher.value.length > 0) {\r\n <button mat-icon-button (click)=\"cleanQuery()\"><mat-icon>close</mat-icon></button>\r\n }\r\n </div>\r\n\r\n <mat-progress-bar mode=\"indeterminate\" [style.visibility]=\"dataResource.isLoading() ? 'visible': 'hidden'\" />\r\n\r\n @if(clearable() && !multiple()) {\r\n <mat-option>{{ intl.getRemoveOptionText(getClearableOptionName()) }}</mat-option>\r\n }\r\n \r\n @for (option of options(); track $index) {\r\n <mat-option [value]=\"option\">\r\n {{ optionLabel()(option) }}\r\n </mat-option>\r\n }\r\n\r\n <!-- Es MUY importante que estos vayan los ultimos (al final de todas las opciones). -->\r\n @for (option of optionsSelectedForView(); track $index) {\r\n <mat-option [value]=\"option\" class=\"hideOption\">\r\n {{ optionLabel()(option) }}\r\n </mat-option>\r\n }\r\n\r\n <!-- Si es multiple, como no esta el option de resetear, si filtran y no hay opciones, y luego cierran el select el desplegable no se abre y queda inutilizado, por eso, ponemos esta opcion dummy, que siempre esta oculta, y no hace nada, pero ya hace que haya un item, y el desplegable se abra -->\r\n @if(multiple()) {\r\n <mat-option class=\"hideOption\" dummyOption></mat-option>\r\n }\r\n\r\n @if (total() == 0) {\r\n <p class=\"withoutResults\">{{ intl.noResultsMessage }}</p>\r\n }\r\n\r\n @if((filters()().pageNumber * filters()().pageSize) < total() && !dataResource.isLoading()) {\r\n <button matButton=\"text\" class=\"showMore\" (click)=\"onMoreClick()\">\r\n {{ intl.showMoreLabel }}\r\n </button>\r\n }\r\n </mat-select>\r\n\r\n <mat-error>{{ error() }}</mat-error>\r\n</mat-form-field>", styles: [":host{display:inline-flex}mat-form-field{width:100%}.searcherContainer{height:48px;position:sticky;top:0;left:0;right:0;background:var(--mat-sys-surface-container);z-index:10}mat-progress-bar{position:sticky;top:48px;z-index:10}.searcherContainer input{height:48px;padding:0 48px;width:calc(100% - 96px);position:absolute;top:0;left:0}.searchIcon{position:absolute;top:0;left:0;height:48px;width:48px;display:flex;align-items:center;justify-content:center;color:#888}.searcherContainer span{line-height:48px;position:absolute;left:48px;color:#888}.searcherContainer button{position:absolute;height:48px;width:48px;top:0;right:0;display:flex;align-items:center;justify-content:center}.hideOption{display:none}.withoutResults{color:#888;text-align:center;padding:0 16px;width:calc(100% - 32px)}.showMore{width:calc(100% - 32px);margin:4px 16px 0}\n"] }]
2113
+ ], template: "<mat-form-field [subscriptSizing]=\"subscriptSizing()\">\r\n @if (selectLabel()) {\r\n <mat-label>{{ selectLabel() }}</mat-label>\r\n }\r\n\r\n <mat-select\r\n [formControl]=\"innerControl()\"\r\n [multiple]=\"multiple()\"\r\n (openedChange)=\"openedChange($event)\" \r\n [placeholder]=\"selectPlaceholder()\"\r\n panelClass=\"searchableSelectPanelClass\"\r\n (selectionChange)=\"onOptionChange($event)\"\r\n [compareWith]=\"compareWith()\">\r\n\r\n <div class=\"searcherContainer\">\r\n <mat-icon class=\"searchIcon\">search</mat-icon>\r\n\r\n @if (htmlSearcher.value.length == 0) {\r\n <span>{{ searchInputPlaceholder() || texts().common.search }}</span> \r\n }\r\n\r\n <input \r\n #htmlSearcher \r\n type=\"text\" \r\n matInput \r\n (keydown)=\"$event.stopPropagation()\"\r\n [value]=\"filters()().query ?? ''\" \r\n (input)=\"onQueryChange()\">\r\n\r\n @if (htmlSearcher.value.length > 0) {\r\n <button mat-icon-button (click)=\"cleanQuery()\"><mat-icon>close</mat-icon></button>\r\n }\r\n </div>\r\n\r\n <mat-progress-bar mode=\"indeterminate\" [style.visibility]=\"dataResource.isLoading() ? 'visible': 'hidden'\" />\r\n\r\n @if(clearable() && !multiple()) {\r\n <mat-option>{{ texts().select.removeOption(getClearableOptionName()) }}</mat-option>\r\n }\r\n \r\n @for (option of options(); track $index) {\r\n <mat-option [value]=\"option\">\r\n {{ optionLabel()(option) }}\r\n </mat-option>\r\n }\r\n\r\n <!-- Es MUY importante que estos vayan los ultimos (al final de todas las opciones). -->\r\n @for (option of optionsSelectedForView(); track $index) {\r\n <mat-option [value]=\"option\" class=\"hideOption\">\r\n {{ optionLabel()(option) }}\r\n </mat-option>\r\n }\r\n\r\n <!-- Si es multiple, como no esta el option de resetear, si filtran y no hay opciones, y luego cierran el select el desplegable no se abre y queda inutilizado, por eso, ponemos esta opcion dummy, que siempre esta oculta, y no hace nada, pero ya hace que haya un item, y el desplegable se abra -->\r\n @if(multiple()) {\r\n <mat-option class=\"hideOption\" dummyOption></mat-option>\r\n }\r\n\r\n @if (total() == 0) {\r\n <p class=\"withoutResults\">{{ texts().select.noResults }}</p>\r\n }\r\n\r\n @if((filters()().pageNumber * filters()().pageSize) < total() && !dataResource.isLoading()) {\r\n <button matButton=\"text\" class=\"showMore\" (click)=\"onMoreClick()\">\r\n {{ texts().select.showMore }}\r\n </button>\r\n }\r\n </mat-select>\r\n\r\n <mat-error>{{ error() }}</mat-error>\r\n</mat-form-field>", styles: [":host{display:inline-flex}mat-form-field{width:100%}.searcherContainer{height:48px;position:sticky;top:0;left:0;right:0;background:var(--mat-sys-surface-container);z-index:10}mat-progress-bar{position:sticky;top:48px;z-index:10}.searcherContainer input{height:48px;padding:0 48px;width:calc(100% - 96px);position:absolute;top:0;left:0}.searchIcon{position:absolute;top:0;left:0;height:48px;width:48px;display:flex;align-items:center;justify-content:center;color:#888}.searcherContainer span{line-height:48px;position:absolute;left:48px;color:#888}.searcherContainer button{position:absolute;height:48px;width:48px;top:0;right:0;display:flex;align-items:center;justify-content:center}.hideOption{display:none}.withoutResults{color:#888;text-align:center;padding:0 16px;width:calc(100% - 32px)}.showMore{width:calc(100% - 32px);margin:4px 16px 0}\n"] }]
1727
2114
  }], propDecorators: { control: [{ type: i0.Input, args: [{ isSignal: true, alias: "control", required: false }] }], endpoint: [{ type: i0.Input, args: [{ isSignal: true, alias: "endpoint", required: true }] }], filters: [{ type: i0.Input, args: [{ isSignal: true, alias: "filters", required: false }] }], optionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionLabel", required: false }] }], compareWith: [{ type: i0.Input, args: [{ isSignal: true, alias: "compareWith", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], searchInputPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchInputPlaceholder", required: false }] }], selectLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectLabel", required: false }] }], selectPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectPlaceholder", required: false }] }], clearableOptionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearableOptionLabel", required: false }] }], subscriptSizing: [{ type: i0.Input, args: [{ isSignal: true, alias: "subscriptSizing", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], optionChange: [{ type: i0.Output, args: ["optionChange"] }], searcher: [{ type: i0.ViewChild, args: ['htmlSearcher', { isSignal: true }] }] } });
1728
2115
 
1729
2116
  class SearchableSelectComponent {
1730
2117
  // Inyectar el servicio de internacionalización.
1731
2118
  // inject() resuelve tambien los providers a nivel de componente/ruta, por lo que
1732
2119
  // el override sigue siendo posible.
1733
- intl = inject(NgxTablesIntl);
2120
+ texts = inject(NgxTexts).texts;
1734
2121
  control = input(...(ngDevMode ? [undefined, { debugName: "control" }] : []));
1735
2122
  options = input.required(...(ngDevMode ? [{ debugName: "options" }] : []));
1736
2123
  optionLabel = input((option) => {
@@ -1811,7 +2198,7 @@ class SearchableSelectComponent {
1811
2198
  return results.length;
1812
2199
  }
1813
2200
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SearchableSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1814
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: SearchableSelectComponent, isStandalone: true, selector: "ngx-searchable-select", inputs: { control: { classPropertyName: "control", publicName: "control", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: false, transformFunction: null }, optionValue: { classPropertyName: "optionValue", publicName: "optionValue", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, searchInputPlaceholder: { classPropertyName: "searchInputPlaceholder", publicName: "searchInputPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, selectLabel: { classPropertyName: "selectLabel", publicName: "selectLabel", isSignal: true, isRequired: false, transformFunction: null }, selectPlaceholder: { classPropertyName: "selectPlaceholder", publicName: "selectPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, clearableOptionLabel: { classPropertyName: "clearableOptionLabel", publicName: "clearableOptionLabel", isSignal: true, isRequired: false, transformFunction: null }, subscriptSizing: { classPropertyName: "subscriptSizing", publicName: "subscriptSizing", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { optionChange: "optionChange" }, viewQueries: [{ propertyName: "searcher", first: true, predicate: ["htmlSearcher"], descendants: true, isSignal: true }], ngImport: i0, template: "<mat-form-field [subscriptSizing]=\"subscriptSizing()\">\r\n @if (selectLabel()) {\r\n <mat-label>{{selectLabel()}}</mat-label>\r\n }\r\n\r\n <mat-select\r\n [formControl]=\"innerControl()\"\r\n [multiple]=\"multiple()\"\r\n (openedChange)=\"openedChange($event)\" \r\n [placeholder]=\"selectPlaceholder()\"\r\n panelClass=\"searchableSelectPanelClass\"\r\n (selectionChange)=\"onOptionChange($event)\">\r\n\r\n <div class=\"searcherContainer\">\r\n <mat-icon class=\"searchIcon\">search</mat-icon>\r\n\r\n @if (htmlSearcher.value.length == 0) {\r\n <span>{{ searchInputPlaceholder() || intl.searchPlaceholder }}</span> \r\n }\r\n\r\n <input \r\n #htmlSearcher \r\n type=\"text\" \r\n matInput \r\n (keydown)=\"$event.stopPropagation()\">\r\n\r\n @if (htmlSearcher.value.length > 0) {\r\n <button mat-icon-button (click)=\"cleanQuery()\"><mat-icon>close</mat-icon></button>\r\n }\r\n </div>\r\n\r\n @if(clearable() && !multiple()) {\r\n <mat-option>{{ intl.getRemoveOptionText(getClearableOptionName()) }}</mat-option>\r\n }\r\n \r\n @for (option of options(); track $index) {\r\n <mat-option \r\n [value]=\"optionValue()(option)\"\r\n [class.hideOption]=\"!showOption(option)\">\r\n {{optionLabel()(option)}}\r\n </mat-option>\r\n }\r\n\r\n @if (numberOfResults() == 0) {\r\n <p class=\"withoutResults\">{{ intl.noResultsMessage }}</p>\r\n }\r\n </mat-select>\r\n\r\n <mat-error>{{error()}}</mat-error>\r\n</mat-form-field>", styles: [":host{display:inline-flex}mat-form-field{width:100%}.searcherContainer{height:48px;position:sticky;top:0;left:0;right:0;background:var(--mat-sys-surface-container);z-index:10}.searcherContainer input{height:48px;padding:0 48px;width:calc(100% - 96px);position:absolute;top:0;left:0}.searchIcon{position:absolute;top:0;left:0;height:48px;width:48px;display:flex;align-items:center;justify-content:center;color:#888}.searcherContainer span{line-height:48px;position:absolute;left:48px;color:#888}.searcherContainer button{position:absolute;height:48px;width:48px;top:0;right:0;display:flex;align-items:center;justify-content:center}.hideOption{display:none}.withoutResults{color:#888;text-align:center;padding:0 16px;width:calc(100% - 32px)}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i3$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i3$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: CommonModule }] });
2201
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: SearchableSelectComponent, isStandalone: true, selector: "ngx-searchable-select", inputs: { control: { classPropertyName: "control", publicName: "control", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: false, transformFunction: null }, optionValue: { classPropertyName: "optionValue", publicName: "optionValue", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, searchInputPlaceholder: { classPropertyName: "searchInputPlaceholder", publicName: "searchInputPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, selectLabel: { classPropertyName: "selectLabel", publicName: "selectLabel", isSignal: true, isRequired: false, transformFunction: null }, selectPlaceholder: { classPropertyName: "selectPlaceholder", publicName: "selectPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, clearableOptionLabel: { classPropertyName: "clearableOptionLabel", publicName: "clearableOptionLabel", isSignal: true, isRequired: false, transformFunction: null }, subscriptSizing: { classPropertyName: "subscriptSizing", publicName: "subscriptSizing", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { optionChange: "optionChange" }, viewQueries: [{ propertyName: "searcher", first: true, predicate: ["htmlSearcher"], descendants: true, isSignal: true }], ngImport: i0, template: "<mat-form-field [subscriptSizing]=\"subscriptSizing()\">\r\n @if (selectLabel()) {\r\n <mat-label>{{selectLabel()}}</mat-label>\r\n }\r\n\r\n <mat-select\r\n [formControl]=\"innerControl()\"\r\n [multiple]=\"multiple()\"\r\n (openedChange)=\"openedChange($event)\" \r\n [placeholder]=\"selectPlaceholder()\"\r\n panelClass=\"searchableSelectPanelClass\"\r\n (selectionChange)=\"onOptionChange($event)\">\r\n\r\n <div class=\"searcherContainer\">\r\n <mat-icon class=\"searchIcon\">search</mat-icon>\r\n\r\n @if (htmlSearcher.value.length == 0) {\r\n <span>{{ searchInputPlaceholder() || texts().common.search }}</span> \r\n }\r\n\r\n <input \r\n #htmlSearcher \r\n type=\"text\" \r\n matInput \r\n (keydown)=\"$event.stopPropagation()\">\r\n\r\n @if (htmlSearcher.value.length > 0) {\r\n <button mat-icon-button (click)=\"cleanQuery()\"><mat-icon>close</mat-icon></button>\r\n }\r\n </div>\r\n\r\n @if(clearable() && !multiple()) {\r\n <mat-option>{{ texts().select.removeOption(getClearableOptionName()) }}</mat-option>\r\n }\r\n \r\n @for (option of options(); track $index) {\r\n <mat-option \r\n [value]=\"optionValue()(option)\"\r\n [class.hideOption]=\"!showOption(option)\">\r\n {{optionLabel()(option)}}\r\n </mat-option>\r\n }\r\n\r\n @if (numberOfResults() == 0) {\r\n <p class=\"withoutResults\">{{ texts().select.noResults }}</p>\r\n }\r\n </mat-select>\r\n\r\n <mat-error>{{error()}}</mat-error>\r\n</mat-form-field>", styles: [":host{display:inline-flex}mat-form-field{width:100%}.searcherContainer{height:48px;position:sticky;top:0;left:0;right:0;background:var(--mat-sys-surface-container);z-index:10}.searcherContainer input{height:48px;padding:0 48px;width:calc(100% - 96px);position:absolute;top:0;left:0}.searchIcon{position:absolute;top:0;left:0;height:48px;width:48px;display:flex;align-items:center;justify-content:center;color:#888}.searcherContainer span{line-height:48px;position:absolute;left:48px;color:#888}.searcherContainer button{position:absolute;height:48px;width:48px;top:0;right:0;display:flex;align-items:center;justify-content:center}.hideOption{display:none}.withoutResults{color:#888;text-align:center;padding:0 16px;width:calc(100% - 32px)}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$3.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i3$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i3$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: CommonModule }] });
1815
2202
  }
1816
2203
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SearchableSelectComponent, decorators: [{
1817
2204
  type: Component,
@@ -1823,24 +2210,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
1823
2210
  ReactiveFormsModule,
1824
2211
  MatButtonModule,
1825
2212
  CommonModule
1826
- ], template: "<mat-form-field [subscriptSizing]=\"subscriptSizing()\">\r\n @if (selectLabel()) {\r\n <mat-label>{{selectLabel()}}</mat-label>\r\n }\r\n\r\n <mat-select\r\n [formControl]=\"innerControl()\"\r\n [multiple]=\"multiple()\"\r\n (openedChange)=\"openedChange($event)\" \r\n [placeholder]=\"selectPlaceholder()\"\r\n panelClass=\"searchableSelectPanelClass\"\r\n (selectionChange)=\"onOptionChange($event)\">\r\n\r\n <div class=\"searcherContainer\">\r\n <mat-icon class=\"searchIcon\">search</mat-icon>\r\n\r\n @if (htmlSearcher.value.length == 0) {\r\n <span>{{ searchInputPlaceholder() || intl.searchPlaceholder }}</span> \r\n }\r\n\r\n <input \r\n #htmlSearcher \r\n type=\"text\" \r\n matInput \r\n (keydown)=\"$event.stopPropagation()\">\r\n\r\n @if (htmlSearcher.value.length > 0) {\r\n <button mat-icon-button (click)=\"cleanQuery()\"><mat-icon>close</mat-icon></button>\r\n }\r\n </div>\r\n\r\n @if(clearable() && !multiple()) {\r\n <mat-option>{{ intl.getRemoveOptionText(getClearableOptionName()) }}</mat-option>\r\n }\r\n \r\n @for (option of options(); track $index) {\r\n <mat-option \r\n [value]=\"optionValue()(option)\"\r\n [class.hideOption]=\"!showOption(option)\">\r\n {{optionLabel()(option)}}\r\n </mat-option>\r\n }\r\n\r\n @if (numberOfResults() == 0) {\r\n <p class=\"withoutResults\">{{ intl.noResultsMessage }}</p>\r\n }\r\n </mat-select>\r\n\r\n <mat-error>{{error()}}</mat-error>\r\n</mat-form-field>", styles: [":host{display:inline-flex}mat-form-field{width:100%}.searcherContainer{height:48px;position:sticky;top:0;left:0;right:0;background:var(--mat-sys-surface-container);z-index:10}.searcherContainer input{height:48px;padding:0 48px;width:calc(100% - 96px);position:absolute;top:0;left:0}.searchIcon{position:absolute;top:0;left:0;height:48px;width:48px;display:flex;align-items:center;justify-content:center;color:#888}.searcherContainer span{line-height:48px;position:absolute;left:48px;color:#888}.searcherContainer button{position:absolute;height:48px;width:48px;top:0;right:0;display:flex;align-items:center;justify-content:center}.hideOption{display:none}.withoutResults{color:#888;text-align:center;padding:0 16px;width:calc(100% - 32px)}\n"] }]
2213
+ ], template: "<mat-form-field [subscriptSizing]=\"subscriptSizing()\">\r\n @if (selectLabel()) {\r\n <mat-label>{{selectLabel()}}</mat-label>\r\n }\r\n\r\n <mat-select\r\n [formControl]=\"innerControl()\"\r\n [multiple]=\"multiple()\"\r\n (openedChange)=\"openedChange($event)\" \r\n [placeholder]=\"selectPlaceholder()\"\r\n panelClass=\"searchableSelectPanelClass\"\r\n (selectionChange)=\"onOptionChange($event)\">\r\n\r\n <div class=\"searcherContainer\">\r\n <mat-icon class=\"searchIcon\">search</mat-icon>\r\n\r\n @if (htmlSearcher.value.length == 0) {\r\n <span>{{ searchInputPlaceholder() || texts().common.search }}</span> \r\n }\r\n\r\n <input \r\n #htmlSearcher \r\n type=\"text\" \r\n matInput \r\n (keydown)=\"$event.stopPropagation()\">\r\n\r\n @if (htmlSearcher.value.length > 0) {\r\n <button mat-icon-button (click)=\"cleanQuery()\"><mat-icon>close</mat-icon></button>\r\n }\r\n </div>\r\n\r\n @if(clearable() && !multiple()) {\r\n <mat-option>{{ texts().select.removeOption(getClearableOptionName()) }}</mat-option>\r\n }\r\n \r\n @for (option of options(); track $index) {\r\n <mat-option \r\n [value]=\"optionValue()(option)\"\r\n [class.hideOption]=\"!showOption(option)\">\r\n {{optionLabel()(option)}}\r\n </mat-option>\r\n }\r\n\r\n @if (numberOfResults() == 0) {\r\n <p class=\"withoutResults\">{{ texts().select.noResults }}</p>\r\n }\r\n </mat-select>\r\n\r\n <mat-error>{{error()}}</mat-error>\r\n</mat-form-field>", styles: [":host{display:inline-flex}mat-form-field{width:100%}.searcherContainer{height:48px;position:sticky;top:0;left:0;right:0;background:var(--mat-sys-surface-container);z-index:10}.searcherContainer input{height:48px;padding:0 48px;width:calc(100% - 96px);position:absolute;top:0;left:0}.searchIcon{position:absolute;top:0;left:0;height:48px;width:48px;display:flex;align-items:center;justify-content:center;color:#888}.searcherContainer span{line-height:48px;position:absolute;left:48px;color:#888}.searcherContainer button{position:absolute;height:48px;width:48px;top:0;right:0;display:flex;align-items:center;justify-content:center}.hideOption{display:none}.withoutResults{color:#888;text-align:center;padding:0 16px;width:calc(100% - 32px)}\n"] }]
1827
2214
  }], propDecorators: { control: [{ type: i0.Input, args: [{ isSignal: true, alias: "control", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], optionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionLabel", required: false }] }], optionValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionValue", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], searchInputPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchInputPlaceholder", required: false }] }], selectLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectLabel", required: false }] }], selectPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectPlaceholder", required: false }] }], clearableOptionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearableOptionLabel", required: false }] }], subscriptSizing: [{ type: i0.Input, args: [{ isSignal: true, alias: "subscriptSizing", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], optionChange: [{ type: i0.Output, args: ["optionChange"] }], searcher: [{ type: i0.ViewChild, args: ['htmlSearcher', { isSignal: true }] }] } });
1828
2215
 
1829
2216
  class AdvancedFilterRuleComponent {
1830
2217
  rule = input.required(...(ngDevMode ? [{ debugName: "rule" }] : []));
1831
2218
  config = input.required(...(ngDevMode ? [{ debugName: "config" }] : []));
1832
2219
  deleteFilter = output();
1833
- intl = inject(NgxTablesIntl);
2220
+ texts = inject(NgxTexts).texts;
1834
2221
  columns = computed(() => this.config().columns.filter(column => column.filterType != undefined), ...(ngDevMode ? [{ debugName: "columns" }] : []));
1835
2222
  operatorByFilterType = OPERATOR_BY_FILTER_TYPE;
1836
2223
  filterOperatorLabel = computed(() => ({
1837
- '=': this.intl.operatorEquals,
1838
- '<>': this.intl.operatorNotEquals,
1839
- '>': this.intl.operatorGreaterThan,
1840
- '>=': this.intl.operatorGreaterOrEquals,
1841
- '<': this.intl.operatorLessThan,
1842
- '<=': this.intl.operatorLessOrEquals,
1843
- 'LIKE': this.intl.operatorLike
2224
+ '=': this.texts().advancedFilters.operators.equals,
2225
+ '<>': this.texts().advancedFilters.operators.notEquals,
2226
+ '>': this.texts().advancedFilters.operators.greaterThan,
2227
+ '>=': this.texts().advancedFilters.operators.greaterOrEquals,
2228
+ '<': this.texts().advancedFilters.operators.lessThan,
2229
+ '<=': this.texts().advancedFilters.operators.lessOrEquals,
2230
+ 'LIKE': this.texts().advancedFilters.operators.like
1844
2231
  }), ...(ngDevMode ? [{ debugName: "filterOperatorLabel" }] : []));
1845
2232
  defaultFiltersForPaginatedFilterOptions = signal({
1846
2233
  pageNumber: 1,
@@ -1881,7 +2268,7 @@ class AdvancedFilterRuleComponent {
1881
2268
  operatorOptionLabel = (filterOperator) => this.filterOperatorLabel()[filterOperator];
1882
2269
  operatorOptionValue = (filterOperator) => filterOperator;
1883
2270
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AdvancedFilterRuleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1884
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: AdvancedFilterRuleComponent, isStandalone: true, selector: "lib-advanced-filter-rule", inputs: { rule: { classPropertyName: "rule", publicName: "rule", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { deleteFilter: "deleteFilter" }, ngImport: i0, template: "<button \r\n matIconButton \r\n [matTooltip]=\"intl.deleteFilterTooltip\" \r\n (click)=\"deleteFilter.emit(getRuleId())\"\r\n class=\"deleteButton\"\r\n type=\"button\">\r\n <mat-icon>delete</mat-icon>\r\n</button>\r\n\r\n<ngx-searchable-select\r\n [control]=\"getKey()\"\r\n [options]=\"columns()\"\r\n [optionLabel]=\"keyOptionLabel\"\r\n [optionValue]=\"keyOptionValue\"\r\n (optionChange)=\"onKeyChange($event)\"\r\n [selectLabel]=\"intl.fieldLabel\"\r\n [selectPlaceholder]=\"intl.selectOptionPlaceholder\"\r\n [error]=\"intl.requiredFieldError\"\r\n/>\r\n\r\n<ngx-searchable-select\r\n [control]=\"getOperator()\"\r\n [options]=\"getOperatorsOption(getKey().value)\"\r\n [optionLabel]=\"operatorOptionLabel\"\r\n [optionValue]=\"operatorOptionValue\"\r\n [selectLabel]=\"intl.conditionLabel\"\r\n [selectPlaceholder]=\"intl.selectOptionPlaceholder\"\r\n [error]=\"intl.requiredFieldError\"\r\n/>\r\n\r\n@if (getFilterType(getKey().value) == 'text' || getFilterType(getKey().value) == 'number') {\r\n <mat-form-field>\r\n <mat-label>{{intl.valueLabel}}</mat-label>\r\n <input [formControl]=\"getValue()\" [type]=\"getFilterType(getKey().value) ?? 'text'\" matInput>\r\n <mat-error>{{intl.requiredFieldError}}</mat-error>\r\n </mat-form-field>\r\n}\r\n\r\n@if (getFilterType(getKey().value) == 'option' || getFilterType(getKey().value) == 'option-multiple') {\r\n @if(getColumnSelected(getKey().value)?.endpointForPaginatedFilterOptions) {\r\n <ngx-paginated-searchable-select \r\n [control]=\"getValue()\"\r\n [endpoint]=\"getColumnSelected(getKey().value)!.endpointForPaginatedFilterOptions!\"\r\n [filters]=\"getColumnSelected(getKey().value)!.filtersForEndpointPaginatedFilterOptions ?? defaultFiltersForPaginatedFilterOptions\"\r\n [selectLabel]=\"intl.valueLabel\"\r\n [selectPlaceholder]=\"intl.selectOptionPlaceholder\"\r\n [error]=\"intl.requiredFieldError\"\r\n />\r\n } @else {\r\n <ngx-searchable-select\r\n [control]=\"getValue()\"\r\n [options]=\"getColumnSelected(getKey().value)?.filterOptions ?? []\"\r\n [selectLabel]=\"intl.valueLabel\"\r\n [selectPlaceholder]=\"intl.selectOptionPlaceholder\"\r\n [error]=\"intl.requiredFieldError\"\r\n />\r\n }\r\n}\r\n\r\n@if(getFilterType(getKey().value) == 'date' || getFilterType(getKey().value) == 'date-range') {\r\n <mat-form-field>\r\n <mat-label>{{intl.valueLabel}}</mat-label>\r\n <input\r\n [formControl]=\"getValue()\"\r\n matInput \r\n [matDatepicker]=\"picker\">\r\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\r\n <mat-datepicker #picker></mat-datepicker>\r\n <mat-error>{{intl.requiredFieldError}}</mat-error>\r\n </mat-form-field>\r\n}\r\n\r\n\r\n", styles: [":host{display:flex;flex-direction:row;gap:10px;align-items:center;margin-top:14px}.deleteButton{margin-bottom:20px}mat-form-field,ngx-searchable-select,ngx-paginated-searchable-select{flex:1}@media (max-width: 900px){:host{flex-direction:column;align-items:normal}}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i2$2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i10.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i10.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i10.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: SearchableSelectComponent, selector: "ngx-searchable-select", inputs: ["control", "options", "optionLabel", "optionValue", "multiple", "searchInputPlaceholder", "selectLabel", "selectPlaceholder", "clearableOptionLabel", "subscriptSizing", "clearable", "error", "selected", "disabled"], outputs: ["optionChange"] }, { kind: "component", type: PaginatedSearchableSelectComponent, selector: "ngx-paginated-searchable-select", inputs: ["control", "endpoint", "filters", "optionLabel", "compareWith", "multiple", "searchInputPlaceholder", "selectLabel", "selectPlaceholder", "clearableOptionLabel", "subscriptSizing", "clearable", "error", "selected", "disabled"], outputs: ["optionChange"] }] });
2271
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: AdvancedFilterRuleComponent, isStandalone: true, selector: "lib-advanced-filter-rule", inputs: { rule: { classPropertyName: "rule", publicName: "rule", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { deleteFilter: "deleteFilter" }, ngImport: i0, template: "<button \r\n matIconButton \r\n [matTooltip]=\"texts().advancedFilters.deleteFilter\" \r\n (click)=\"deleteFilter.emit(getRuleId())\"\r\n class=\"deleteButton\"\r\n type=\"button\">\r\n <mat-icon>delete</mat-icon>\r\n</button>\r\n\r\n<ngx-searchable-select\r\n [control]=\"getKey()\"\r\n [options]=\"columns()\"\r\n [optionLabel]=\"keyOptionLabel\"\r\n [optionValue]=\"keyOptionValue\"\r\n (optionChange)=\"onKeyChange($event)\"\r\n [selectLabel]=\"texts().advancedFilters.field\"\r\n [selectPlaceholder]=\"texts().advancedFilters.selectOption\"\r\n [error]=\"texts().advancedFilters.required\"\r\n/>\r\n\r\n<ngx-searchable-select\r\n [control]=\"getOperator()\"\r\n [options]=\"getOperatorsOption(getKey().value)\"\r\n [optionLabel]=\"operatorOptionLabel\"\r\n [optionValue]=\"operatorOptionValue\"\r\n [selectLabel]=\"texts().advancedFilters.condition\"\r\n [selectPlaceholder]=\"texts().advancedFilters.selectOption\"\r\n [error]=\"texts().advancedFilters.required\"\r\n/>\r\n\r\n@if (getFilterType(getKey().value) == 'text' || getFilterType(getKey().value) == 'number') {\r\n <mat-form-field>\r\n <mat-label>{{texts().advancedFilters.value}}</mat-label>\r\n <input [formControl]=\"getValue()\" [type]=\"getFilterType(getKey().value) ?? 'text'\" matInput>\r\n <mat-error>{{texts().advancedFilters.required}}</mat-error>\r\n </mat-form-field>\r\n}\r\n\r\n@if (getFilterType(getKey().value) == 'option' || getFilterType(getKey().value) == 'option-multiple') {\r\n @if(getColumnSelected(getKey().value)?.endpointForPaginatedFilterOptions) {\r\n <ngx-paginated-searchable-select \r\n [control]=\"getValue()\"\r\n [endpoint]=\"getColumnSelected(getKey().value)!.endpointForPaginatedFilterOptions!\"\r\n [filters]=\"getColumnSelected(getKey().value)!.filtersForEndpointPaginatedFilterOptions ?? defaultFiltersForPaginatedFilterOptions\"\r\n [selectLabel]=\"texts().advancedFilters.value\"\r\n [selectPlaceholder]=\"texts().advancedFilters.selectOption\"\r\n [error]=\"texts().advancedFilters.required\"\r\n />\r\n } @else {\r\n <ngx-searchable-select\r\n [control]=\"getValue()\"\r\n [options]=\"getColumnSelected(getKey().value)?.filterOptions ?? []\"\r\n [selectLabel]=\"texts().advancedFilters.value\"\r\n [selectPlaceholder]=\"texts().advancedFilters.selectOption\"\r\n [error]=\"texts().advancedFilters.required\"\r\n />\r\n }\r\n}\r\n\r\n@if(getFilterType(getKey().value) == 'date' || getFilterType(getKey().value) == 'date-range') {\r\n <mat-form-field>\r\n <mat-label>{{texts().advancedFilters.value}}</mat-label>\r\n <input\r\n [formControl]=\"getValue()\"\r\n matInput \r\n [matDatepicker]=\"picker\">\r\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\r\n <mat-datepicker #picker></mat-datepicker>\r\n <mat-error>{{texts().advancedFilters.required}}</mat-error>\r\n </mat-form-field>\r\n}\r\n\r\n\r\n", styles: [":host{display:flex;flex-direction:row;gap:10px;align-items:center;margin-top:14px}.deleteButton{margin-bottom:20px}mat-form-field,ngx-searchable-select,ngx-paginated-searchable-select{flex:1}@media (max-width: 900px){:host{flex-direction:column;align-items:normal}}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$3.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i2$3.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i10.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i10.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i10.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: SearchableSelectComponent, selector: "ngx-searchable-select", inputs: ["control", "options", "optionLabel", "optionValue", "multiple", "searchInputPlaceholder", "selectLabel", "selectPlaceholder", "clearableOptionLabel", "subscriptSizing", "clearable", "error", "selected", "disabled"], outputs: ["optionChange"] }, { kind: "component", type: PaginatedSearchableSelectComponent, selector: "ngx-paginated-searchable-select", inputs: ["control", "endpoint", "filters", "optionLabel", "compareWith", "multiple", "searchInputPlaceholder", "selectLabel", "selectPlaceholder", "clearableOptionLabel", "subscriptSizing", "clearable", "error", "selected", "disabled"], outputs: ["optionChange"] }] });
1885
2272
  }
1886
2273
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AdvancedFilterRuleComponent, decorators: [{
1887
2274
  type: Component,
@@ -1896,7 +2283,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
1896
2283
  MatTooltipModule,
1897
2284
  SearchableSelectComponent,
1898
2285
  PaginatedSearchableSelectComponent
1899
- ], template: "<button \r\n matIconButton \r\n [matTooltip]=\"intl.deleteFilterTooltip\" \r\n (click)=\"deleteFilter.emit(getRuleId())\"\r\n class=\"deleteButton\"\r\n type=\"button\">\r\n <mat-icon>delete</mat-icon>\r\n</button>\r\n\r\n<ngx-searchable-select\r\n [control]=\"getKey()\"\r\n [options]=\"columns()\"\r\n [optionLabel]=\"keyOptionLabel\"\r\n [optionValue]=\"keyOptionValue\"\r\n (optionChange)=\"onKeyChange($event)\"\r\n [selectLabel]=\"intl.fieldLabel\"\r\n [selectPlaceholder]=\"intl.selectOptionPlaceholder\"\r\n [error]=\"intl.requiredFieldError\"\r\n/>\r\n\r\n<ngx-searchable-select\r\n [control]=\"getOperator()\"\r\n [options]=\"getOperatorsOption(getKey().value)\"\r\n [optionLabel]=\"operatorOptionLabel\"\r\n [optionValue]=\"operatorOptionValue\"\r\n [selectLabel]=\"intl.conditionLabel\"\r\n [selectPlaceholder]=\"intl.selectOptionPlaceholder\"\r\n [error]=\"intl.requiredFieldError\"\r\n/>\r\n\r\n@if (getFilterType(getKey().value) == 'text' || getFilterType(getKey().value) == 'number') {\r\n <mat-form-field>\r\n <mat-label>{{intl.valueLabel}}</mat-label>\r\n <input [formControl]=\"getValue()\" [type]=\"getFilterType(getKey().value) ?? 'text'\" matInput>\r\n <mat-error>{{intl.requiredFieldError}}</mat-error>\r\n </mat-form-field>\r\n}\r\n\r\n@if (getFilterType(getKey().value) == 'option' || getFilterType(getKey().value) == 'option-multiple') {\r\n @if(getColumnSelected(getKey().value)?.endpointForPaginatedFilterOptions) {\r\n <ngx-paginated-searchable-select \r\n [control]=\"getValue()\"\r\n [endpoint]=\"getColumnSelected(getKey().value)!.endpointForPaginatedFilterOptions!\"\r\n [filters]=\"getColumnSelected(getKey().value)!.filtersForEndpointPaginatedFilterOptions ?? defaultFiltersForPaginatedFilterOptions\"\r\n [selectLabel]=\"intl.valueLabel\"\r\n [selectPlaceholder]=\"intl.selectOptionPlaceholder\"\r\n [error]=\"intl.requiredFieldError\"\r\n />\r\n } @else {\r\n <ngx-searchable-select\r\n [control]=\"getValue()\"\r\n [options]=\"getColumnSelected(getKey().value)?.filterOptions ?? []\"\r\n [selectLabel]=\"intl.valueLabel\"\r\n [selectPlaceholder]=\"intl.selectOptionPlaceholder\"\r\n [error]=\"intl.requiredFieldError\"\r\n />\r\n }\r\n}\r\n\r\n@if(getFilterType(getKey().value) == 'date' || getFilterType(getKey().value) == 'date-range') {\r\n <mat-form-field>\r\n <mat-label>{{intl.valueLabel}}</mat-label>\r\n <input\r\n [formControl]=\"getValue()\"\r\n matInput \r\n [matDatepicker]=\"picker\">\r\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\r\n <mat-datepicker #picker></mat-datepicker>\r\n <mat-error>{{intl.requiredFieldError}}</mat-error>\r\n </mat-form-field>\r\n}\r\n\r\n\r\n", styles: [":host{display:flex;flex-direction:row;gap:10px;align-items:center;margin-top:14px}.deleteButton{margin-bottom:20px}mat-form-field,ngx-searchable-select,ngx-paginated-searchable-select{flex:1}@media (max-width: 900px){:host{flex-direction:column;align-items:normal}}\n"] }]
2286
+ ], template: "<button \r\n matIconButton \r\n [matTooltip]=\"texts().advancedFilters.deleteFilter\" \r\n (click)=\"deleteFilter.emit(getRuleId())\"\r\n class=\"deleteButton\"\r\n type=\"button\">\r\n <mat-icon>delete</mat-icon>\r\n</button>\r\n\r\n<ngx-searchable-select\r\n [control]=\"getKey()\"\r\n [options]=\"columns()\"\r\n [optionLabel]=\"keyOptionLabel\"\r\n [optionValue]=\"keyOptionValue\"\r\n (optionChange)=\"onKeyChange($event)\"\r\n [selectLabel]=\"texts().advancedFilters.field\"\r\n [selectPlaceholder]=\"texts().advancedFilters.selectOption\"\r\n [error]=\"texts().advancedFilters.required\"\r\n/>\r\n\r\n<ngx-searchable-select\r\n [control]=\"getOperator()\"\r\n [options]=\"getOperatorsOption(getKey().value)\"\r\n [optionLabel]=\"operatorOptionLabel\"\r\n [optionValue]=\"operatorOptionValue\"\r\n [selectLabel]=\"texts().advancedFilters.condition\"\r\n [selectPlaceholder]=\"texts().advancedFilters.selectOption\"\r\n [error]=\"texts().advancedFilters.required\"\r\n/>\r\n\r\n@if (getFilterType(getKey().value) == 'text' || getFilterType(getKey().value) == 'number') {\r\n <mat-form-field>\r\n <mat-label>{{texts().advancedFilters.value}}</mat-label>\r\n <input [formControl]=\"getValue()\" [type]=\"getFilterType(getKey().value) ?? 'text'\" matInput>\r\n <mat-error>{{texts().advancedFilters.required}}</mat-error>\r\n </mat-form-field>\r\n}\r\n\r\n@if (getFilterType(getKey().value) == 'option' || getFilterType(getKey().value) == 'option-multiple') {\r\n @if(getColumnSelected(getKey().value)?.endpointForPaginatedFilterOptions) {\r\n <ngx-paginated-searchable-select \r\n [control]=\"getValue()\"\r\n [endpoint]=\"getColumnSelected(getKey().value)!.endpointForPaginatedFilterOptions!\"\r\n [filters]=\"getColumnSelected(getKey().value)!.filtersForEndpointPaginatedFilterOptions ?? defaultFiltersForPaginatedFilterOptions\"\r\n [selectLabel]=\"texts().advancedFilters.value\"\r\n [selectPlaceholder]=\"texts().advancedFilters.selectOption\"\r\n [error]=\"texts().advancedFilters.required\"\r\n />\r\n } @else {\r\n <ngx-searchable-select\r\n [control]=\"getValue()\"\r\n [options]=\"getColumnSelected(getKey().value)?.filterOptions ?? []\"\r\n [selectLabel]=\"texts().advancedFilters.value\"\r\n [selectPlaceholder]=\"texts().advancedFilters.selectOption\"\r\n [error]=\"texts().advancedFilters.required\"\r\n />\r\n }\r\n}\r\n\r\n@if(getFilterType(getKey().value) == 'date' || getFilterType(getKey().value) == 'date-range') {\r\n <mat-form-field>\r\n <mat-label>{{texts().advancedFilters.value}}</mat-label>\r\n <input\r\n [formControl]=\"getValue()\"\r\n matInput \r\n [matDatepicker]=\"picker\">\r\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\r\n <mat-datepicker #picker></mat-datepicker>\r\n <mat-error>{{texts().advancedFilters.required}}</mat-error>\r\n </mat-form-field>\r\n}\r\n\r\n\r\n", styles: [":host{display:flex;flex-direction:row;gap:10px;align-items:center;margin-top:14px}.deleteButton{margin-bottom:20px}mat-form-field,ngx-searchable-select,ngx-paginated-searchable-select{flex:1}@media (max-width: 900px){:host{flex-direction:column;align-items:normal}}\n"] }]
1900
2287
  }], propDecorators: { rule: [{ type: i0.Input, args: [{ isSignal: true, alias: "rule", required: true }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], deleteFilter: [{ type: i0.Output, args: ["deleteFilter"] }] } });
1901
2288
 
1902
2289
  class AdvancedFilterGroupComponent {
@@ -1908,11 +2295,11 @@ class AdvancedFilterGroupComponent {
1908
2295
  deleteGroup = output();
1909
2296
  deleteFilter = output();
1910
2297
  datosPantallaService = inject(DatosPantallaService);
1911
- intl = inject(NgxTablesIntl);
2298
+ texts = inject(NgxTexts).texts;
1912
2299
  isDesktop = computed(() => this.datosPantallaService.pantalla()?.tipo == 'escritorio', ...(ngDevMode ? [{ debugName: "isDesktop" }] : []));
1913
2300
  optionsFilterConnector = computed(() => [
1914
- { value: 'AND', label: this.intl.connectorAnd },
1915
- { value: 'OR', label: this.intl.connectorOr }
2301
+ { value: 'AND', label: this.texts().advancedFilters.and },
2302
+ { value: 'OR', label: this.texts().advancedFilters.or }
1916
2303
  ], ...(ngDevMode ? [{ debugName: "optionsFilterConnector" }] : []));
1917
2304
  isFilterGroupForm(group) {
1918
2305
  return AdvancedFilterUtils.isFilterGroupForm(group);
@@ -1927,7 +2314,7 @@ class AdvancedFilterGroupComponent {
1927
2314
  return this.group().get('filters').controls;
1928
2315
  }
1929
2316
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AdvancedFilterGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1930
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: AdvancedFilterGroupComponent, isStandalone: true, selector: "lib-advanced-filter-group", inputs: { isRootNode: { classPropertyName: "isRootNode", publicName: "isRootNode", isSignal: true, isRequired: true, transformFunction: null }, group: { classPropertyName: "group", publicName: "group", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { addGroup: "addGroup", addFilter: "addFilter", deleteGroup: "deleteGroup", deleteFilter: "deleteFilter" }, ngImport: i0, template: "<div class=\"grupo\" [formGroup]=\"group()\">\r\n \r\n <mat-button-toggle-group [formControl]=\"getConnector()\">\r\n @for (option of optionsFilterConnector(); track option.value) {\r\n <mat-button-toggle [value]=\"option.value\">{{option.label}}</mat-button-toggle>\r\n }\r\n </mat-button-toggle-group>\r\n\r\n @if (isDesktop()) {\r\n <button \r\n matButton=\"outlined\" \r\n (click)=\"addFilter.emit(getGroupId())\"\r\n class=\"addFilterButton\"\r\n type=\"button\">\r\n <mat-icon>add</mat-icon>\r\n {{intl.addFilterButtonLabel}}\r\n </button>\r\n\r\n <button \r\n matButton=\"outlined\"\r\n (click)=\"addGroup.emit(getGroupId())\"\r\n class=\"addGroupButton\"\r\n type=\"button\">\r\n <mat-icon>data_array</mat-icon>\r\n {{intl.addGroupButtonLabel}}\r\n </button>\r\n } @else {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"intl.addFilterButtonLabel\" \r\n (click)=\"addFilter.emit(getGroupId())\"\r\n class=\"addFilterButton\"\r\n type=\"button\">\r\n <mat-icon>add</mat-icon>\r\n </button>\r\n\r\n <button \r\n matIconButton \r\n [matTooltip]=\"intl.addGroupButtonLabel\" \r\n (click)=\"addGroup.emit(getGroupId())\"\r\n class=\"addGroupButton\"\r\n type=\"button\">\r\n <mat-icon>data_array</mat-icon>\r\n </button>\r\n }\r\n \r\n\r\n @if(!isRootNode()) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"intl.deleteGroupTooltip\" \r\n (click)=\"deleteGroup.emit(getGroupId())\"\r\n class=\"deleteGroupButton\"\r\n type=\"button\">\r\n <mat-icon>delete</mat-icon>\r\n </button>\r\n }\r\n\r\n @for (group of getFilters(); track $index) {\r\n @if(isFilterGroupForm(group)) {\r\n <lib-advanced-filter-group \r\n [group]=\"group\"\r\n [config]=\"config()\"\r\n [isRootNode]=\"false\"\r\n (addGroup)=\"addGroup.emit($event)\"\r\n (addFilter)=\"addFilter.emit($event)\"\r\n (deleteGroup)=\"deleteGroup.emit($event)\"\r\n (deleteFilter)=\"deleteFilter.emit($event)\"\r\n />\r\n } @else {\r\n <lib-advanced-filter-rule \r\n [rule]=\"group\"\r\n [config]=\"config()\"\r\n (deleteFilter)=\"deleteFilter.emit($event)\"\r\n />\r\n }\r\n }\r\n\r\n</div>", styles: [":host{display:block}.grupo{border-radius:4px;border:1px solid var(--mat-sys-outline);padding:40px 34px 10px 20px;position:relative;min-height:60px;display:flex;flex-direction:column;margin-top:24px;gap:8px}mat-button-toggle-group{position:absolute;top:-20px;left:50%;transform:translate(-50%);background-color:var(--mat-sys-surface)}.addFilterButton{position:absolute;top:-20px;left:10px;background-color:var(--mat-sys-surface)}.addGroupButton{position:absolute;top:-20px;right:10px;background-color:var(--mat-sys-surface)}.deleteGroupButton{position:absolute;top:50%;right:-20px;transform:translateY(-50%);background-color:var(--mat-sys-surface)}\n"], dependencies: [{ kind: "component", type: AdvancedFilterGroupComponent, selector: "lib-advanced-filter-group", inputs: ["isRootNode", "group", "config"], outputs: ["addGroup", "addFilter", "deleteGroup", "deleteFilter"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatSelectModule }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: AdvancedFilterRuleComponent, selector: "lib-advanced-filter-rule", inputs: ["rule", "config"], outputs: ["deleteFilter"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "directive", type: i4$1.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i4$1.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
2317
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: AdvancedFilterGroupComponent, isStandalone: true, selector: "lib-advanced-filter-group", inputs: { isRootNode: { classPropertyName: "isRootNode", publicName: "isRootNode", isSignal: true, isRequired: true, transformFunction: null }, group: { classPropertyName: "group", publicName: "group", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { addGroup: "addGroup", addFilter: "addFilter", deleteGroup: "deleteGroup", deleteFilter: "deleteFilter" }, ngImport: i0, template: "<div class=\"grupo\" [formGroup]=\"group()\">\r\n \r\n <mat-button-toggle-group [formControl]=\"getConnector()\">\r\n @for (option of optionsFilterConnector(); track option.value) {\r\n <mat-button-toggle [value]=\"option.value\">{{option.label}}</mat-button-toggle>\r\n }\r\n </mat-button-toggle-group>\r\n\r\n @if (isDesktop()) {\r\n <button \r\n matButton=\"outlined\" \r\n (click)=\"addFilter.emit(getGroupId())\"\r\n class=\"addFilterButton\"\r\n type=\"button\">\r\n <mat-icon>add</mat-icon>\r\n {{texts().advancedFilters.addFilter}}\r\n </button>\r\n\r\n <button \r\n matButton=\"outlined\"\r\n (click)=\"addGroup.emit(getGroupId())\"\r\n class=\"addGroupButton\"\r\n type=\"button\">\r\n <mat-icon>data_array</mat-icon>\r\n {{texts().advancedFilters.addGroup}}\r\n </button>\r\n } @else {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"texts().advancedFilters.addFilter\" \r\n (click)=\"addFilter.emit(getGroupId())\"\r\n class=\"addFilterButton\"\r\n type=\"button\">\r\n <mat-icon>add</mat-icon>\r\n </button>\r\n\r\n <button \r\n matIconButton \r\n [matTooltip]=\"texts().advancedFilters.addGroup\" \r\n (click)=\"addGroup.emit(getGroupId())\"\r\n class=\"addGroupButton\"\r\n type=\"button\">\r\n <mat-icon>data_array</mat-icon>\r\n </button>\r\n }\r\n \r\n\r\n @if(!isRootNode()) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"texts().advancedFilters.deleteGroup\" \r\n (click)=\"deleteGroup.emit(getGroupId())\"\r\n class=\"deleteGroupButton\"\r\n type=\"button\">\r\n <mat-icon>delete</mat-icon>\r\n </button>\r\n }\r\n\r\n @for (group of getFilters(); track $index) {\r\n @if(isFilterGroupForm(group)) {\r\n <lib-advanced-filter-group \r\n [group]=\"group\"\r\n [config]=\"config()\"\r\n [isRootNode]=\"false\"\r\n (addGroup)=\"addGroup.emit($event)\"\r\n (addFilter)=\"addFilter.emit($event)\"\r\n (deleteGroup)=\"deleteGroup.emit($event)\"\r\n (deleteFilter)=\"deleteFilter.emit($event)\"\r\n />\r\n } @else {\r\n <lib-advanced-filter-rule \r\n [rule]=\"group\"\r\n [config]=\"config()\"\r\n (deleteFilter)=\"deleteFilter.emit($event)\"\r\n />\r\n }\r\n }\r\n\r\n</div>", styles: [":host{display:block}.grupo{border-radius:4px;border:1px solid var(--mat-sys-outline);padding:40px 34px 10px 20px;position:relative;min-height:60px;display:flex;flex-direction:column;margin-top:24px;gap:8px}mat-button-toggle-group{position:absolute;top:-20px;left:50%;transform:translate(-50%);background-color:var(--mat-sys-surface)}.addFilterButton{position:absolute;top:-20px;left:10px;background-color:var(--mat-sys-surface)}.addGroupButton{position:absolute;top:-20px;right:10px;background-color:var(--mat-sys-surface)}.deleteGroupButton{position:absolute;top:50%;right:-20px;transform:translateY(-50%);background-color:var(--mat-sys-surface)}\n"], dependencies: [{ kind: "component", type: AdvancedFilterGroupComponent, selector: "lib-advanced-filter-group", inputs: ["isRootNode", "group", "config"], outputs: ["addGroup", "addFilter", "deleteGroup", "deleteFilter"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatSelectModule }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: AdvancedFilterRuleComponent, selector: "lib-advanced-filter-rule", inputs: ["rule", "config"], outputs: ["deleteFilter"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "directive", type: i4$1.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i4$1.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
1931
2318
  }
1932
2319
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AdvancedFilterGroupComponent, decorators: [{
1933
2320
  type: Component,
@@ -1942,7 +2329,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
1942
2329
  AdvancedFilterRuleComponent,
1943
2330
  MatButtonToggleModule,
1944
2331
  MatTooltipModule
1945
- ], template: "<div class=\"grupo\" [formGroup]=\"group()\">\r\n \r\n <mat-button-toggle-group [formControl]=\"getConnector()\">\r\n @for (option of optionsFilterConnector(); track option.value) {\r\n <mat-button-toggle [value]=\"option.value\">{{option.label}}</mat-button-toggle>\r\n }\r\n </mat-button-toggle-group>\r\n\r\n @if (isDesktop()) {\r\n <button \r\n matButton=\"outlined\" \r\n (click)=\"addFilter.emit(getGroupId())\"\r\n class=\"addFilterButton\"\r\n type=\"button\">\r\n <mat-icon>add</mat-icon>\r\n {{intl.addFilterButtonLabel}}\r\n </button>\r\n\r\n <button \r\n matButton=\"outlined\"\r\n (click)=\"addGroup.emit(getGroupId())\"\r\n class=\"addGroupButton\"\r\n type=\"button\">\r\n <mat-icon>data_array</mat-icon>\r\n {{intl.addGroupButtonLabel}}\r\n </button>\r\n } @else {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"intl.addFilterButtonLabel\" \r\n (click)=\"addFilter.emit(getGroupId())\"\r\n class=\"addFilterButton\"\r\n type=\"button\">\r\n <mat-icon>add</mat-icon>\r\n </button>\r\n\r\n <button \r\n matIconButton \r\n [matTooltip]=\"intl.addGroupButtonLabel\" \r\n (click)=\"addGroup.emit(getGroupId())\"\r\n class=\"addGroupButton\"\r\n type=\"button\">\r\n <mat-icon>data_array</mat-icon>\r\n </button>\r\n }\r\n \r\n\r\n @if(!isRootNode()) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"intl.deleteGroupTooltip\" \r\n (click)=\"deleteGroup.emit(getGroupId())\"\r\n class=\"deleteGroupButton\"\r\n type=\"button\">\r\n <mat-icon>delete</mat-icon>\r\n </button>\r\n }\r\n\r\n @for (group of getFilters(); track $index) {\r\n @if(isFilterGroupForm(group)) {\r\n <lib-advanced-filter-group \r\n [group]=\"group\"\r\n [config]=\"config()\"\r\n [isRootNode]=\"false\"\r\n (addGroup)=\"addGroup.emit($event)\"\r\n (addFilter)=\"addFilter.emit($event)\"\r\n (deleteGroup)=\"deleteGroup.emit($event)\"\r\n (deleteFilter)=\"deleteFilter.emit($event)\"\r\n />\r\n } @else {\r\n <lib-advanced-filter-rule \r\n [rule]=\"group\"\r\n [config]=\"config()\"\r\n (deleteFilter)=\"deleteFilter.emit($event)\"\r\n />\r\n }\r\n }\r\n\r\n</div>", styles: [":host{display:block}.grupo{border-radius:4px;border:1px solid var(--mat-sys-outline);padding:40px 34px 10px 20px;position:relative;min-height:60px;display:flex;flex-direction:column;margin-top:24px;gap:8px}mat-button-toggle-group{position:absolute;top:-20px;left:50%;transform:translate(-50%);background-color:var(--mat-sys-surface)}.addFilterButton{position:absolute;top:-20px;left:10px;background-color:var(--mat-sys-surface)}.addGroupButton{position:absolute;top:-20px;right:10px;background-color:var(--mat-sys-surface)}.deleteGroupButton{position:absolute;top:50%;right:-20px;transform:translateY(-50%);background-color:var(--mat-sys-surface)}\n"] }]
2332
+ ], template: "<div class=\"grupo\" [formGroup]=\"group()\">\r\n \r\n <mat-button-toggle-group [formControl]=\"getConnector()\">\r\n @for (option of optionsFilterConnector(); track option.value) {\r\n <mat-button-toggle [value]=\"option.value\">{{option.label}}</mat-button-toggle>\r\n }\r\n </mat-button-toggle-group>\r\n\r\n @if (isDesktop()) {\r\n <button \r\n matButton=\"outlined\" \r\n (click)=\"addFilter.emit(getGroupId())\"\r\n class=\"addFilterButton\"\r\n type=\"button\">\r\n <mat-icon>add</mat-icon>\r\n {{texts().advancedFilters.addFilter}}\r\n </button>\r\n\r\n <button \r\n matButton=\"outlined\"\r\n (click)=\"addGroup.emit(getGroupId())\"\r\n class=\"addGroupButton\"\r\n type=\"button\">\r\n <mat-icon>data_array</mat-icon>\r\n {{texts().advancedFilters.addGroup}}\r\n </button>\r\n } @else {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"texts().advancedFilters.addFilter\" \r\n (click)=\"addFilter.emit(getGroupId())\"\r\n class=\"addFilterButton\"\r\n type=\"button\">\r\n <mat-icon>add</mat-icon>\r\n </button>\r\n\r\n <button \r\n matIconButton \r\n [matTooltip]=\"texts().advancedFilters.addGroup\" \r\n (click)=\"addGroup.emit(getGroupId())\"\r\n class=\"addGroupButton\"\r\n type=\"button\">\r\n <mat-icon>data_array</mat-icon>\r\n </button>\r\n }\r\n \r\n\r\n @if(!isRootNode()) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"texts().advancedFilters.deleteGroup\" \r\n (click)=\"deleteGroup.emit(getGroupId())\"\r\n class=\"deleteGroupButton\"\r\n type=\"button\">\r\n <mat-icon>delete</mat-icon>\r\n </button>\r\n }\r\n\r\n @for (group of getFilters(); track $index) {\r\n @if(isFilterGroupForm(group)) {\r\n <lib-advanced-filter-group \r\n [group]=\"group\"\r\n [config]=\"config()\"\r\n [isRootNode]=\"false\"\r\n (addGroup)=\"addGroup.emit($event)\"\r\n (addFilter)=\"addFilter.emit($event)\"\r\n (deleteGroup)=\"deleteGroup.emit($event)\"\r\n (deleteFilter)=\"deleteFilter.emit($event)\"\r\n />\r\n } @else {\r\n <lib-advanced-filter-rule \r\n [rule]=\"group\"\r\n [config]=\"config()\"\r\n (deleteFilter)=\"deleteFilter.emit($event)\"\r\n />\r\n }\r\n }\r\n\r\n</div>", styles: [":host{display:block}.grupo{border-radius:4px;border:1px solid var(--mat-sys-outline);padding:40px 34px 10px 20px;position:relative;min-height:60px;display:flex;flex-direction:column;margin-top:24px;gap:8px}mat-button-toggle-group{position:absolute;top:-20px;left:50%;transform:translate(-50%);background-color:var(--mat-sys-surface)}.addFilterButton{position:absolute;top:-20px;left:10px;background-color:var(--mat-sys-surface)}.addGroupButton{position:absolute;top:-20px;right:10px;background-color:var(--mat-sys-surface)}.deleteGroupButton{position:absolute;top:50%;right:-20px;transform:translateY(-50%);background-color:var(--mat-sys-surface)}\n"] }]
1946
2333
  }], propDecorators: { isRootNode: [{ type: i0.Input, args: [{ isSignal: true, alias: "isRootNode", required: true }] }], group: [{ type: i0.Input, args: [{ isSignal: true, alias: "group", required: true }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], addGroup: [{ type: i0.Output, args: ["addGroup"] }], addFilter: [{ type: i0.Output, args: ["addFilter"] }], deleteGroup: [{ type: i0.Output, args: ["deleteGroup"] }], deleteFilter: [{ type: i0.Output, args: ["deleteFilter"] }] } });
1947
2334
 
1948
2335
  class ConfigureAdvancedFilterComponent {
@@ -1950,7 +2337,7 @@ class ConfigureAdvancedFilterComponent {
1950
2337
  advancedFilterService = inject(AdvancedFilterService);
1951
2338
  dialogRef = inject((MatDialogRef));
1952
2339
  data = inject(MAT_DIALOG_DATA);
1953
- intl = inject(NgxTablesIntl);
2340
+ texts = inject(NgxTexts).texts;
1954
2341
  query = signal('', ...(ngDevMode ? [{ debugName: "query" }] : []));
1955
2342
  form = AdvancedFilterUtils.createAdvancedFilter(this.fb, this.data.advancedFilter);
1956
2343
  formChanges = toSignal(this.form.valueChanges);
@@ -1961,7 +2348,7 @@ class ConfigureAdvancedFilterComponent {
1961
2348
  return;
1962
2349
  }
1963
2350
  const advancedFilter = AdvancedFilterUtils.mapFormToAdvancedFilter(this.form);
1964
- const queryString = AdvancedFilterUtils.groupsToReadableHtml(advancedFilter.groups, this.data.config.columns, this.intl);
2351
+ const queryString = AdvancedFilterUtils.groupsToReadableHtml(advancedFilter.groups, this.data.config.columns, this.texts());
1965
2352
  this.query.set(queryString);
1966
2353
  }, ...(ngDevMode ? [{ debugName: "mapFormToAdvancedFilterEffect" }] : []));
1967
2354
  getRootGroup() {
@@ -2001,7 +2388,7 @@ class ConfigureAdvancedFilterComponent {
2001
2388
  }
2002
2389
  }
2003
2390
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfigureAdvancedFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2004
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: ConfigureAdvancedFilterComponent, isStandalone: true, selector: "lib-configure-advanced-filter", ngImport: i0, template: "<form [formGroup]=\"form\" (ngSubmit)=\"onSubmit('save_and_apply')\">\r\n\r\n <h2 mat-dialog-title>{{intl.advancedFiltersDialogTitle}} {{data.config.title() | lowercase}}</h2>\r\n <mat-dialog-content>\r\n\r\n <p class=\"advancedFilterResult\" [innerHTML]=\"query()\" [style.visibility]=\"query() ? 'visible': 'hidden'\"></p>\r\n\r\n <mat-form-field>\r\n <mat-label>{{intl.templateNameLabel}}</mat-label>\r\n <input matInput formControlName=\"name\" [maxlength]=\"16\">\r\n <mat-hint>{{form.get('name')?.value.length ?? 0}}/16</mat-hint>\r\n <mat-error>{{intl.templateNameRequiredError}}</mat-error>\r\n </mat-form-field>\r\n\r\n <lib-advanced-filter-group \r\n [group]=\"getRootGroup()\"\r\n [config]=\"data.config\"\r\n [isRootNode]=\"true\"\r\n (addGroup)=\"addGroup($event)\"\r\n (addFilter)=\"addFilter($event)\"\r\n (deleteGroup)=\"deleteGroup($event)\"\r\n (deleteFilter)=\"deleteFilter($event)\"\r\n />\r\n\r\n <div class=\"helperContainer\">\r\n <p class=\"helperTitle\"><strong>{{intl.advancedFiltersHelpTitle}}</strong></p>\r\n <p class=\"helper\">\r\n <strong>{{intl.groupLabel}} </strong>{{intl.advancedFiltersGroupHelp}}<br>\r\n <strong>{{intl.filterLabel}} </strong>{{intl.advancedFiltersRuleHelp}}\r\n </p>\r\n </div>\r\n \r\n </mat-dialog-content>\r\n <mat-dialog-actions>\r\n <button matButton [mat-dialog-close]=\"undefined\">{{intl.closeButtonLabel}}</button>\r\n <button matButton [disabled]=\"form.invalid\" type=\"button\" (click)=\"onSubmit('save')\">{{intl.saveButtonLabel}}</button>\r\n <button matButton [disabled]=\"form.invalid\" type=\"button\" (click)=\"onSubmit('save_and_apply')\">{{intl.saveAndApplyButtonLabel}}</button>\r\n </mat-dialog-actions>\r\n\r\n\r\n</form>", styles: [":host{display:block}mat-dialog-content{display:flex;flex-direction:column;gap:12px}.helperContainer{margin-top:30px}.helperTitle,.helper{font:var(--mat-sys-body-small);font-weight:300;margin:0}.helper{margin-top:4px;padding-left:20px}.advancedFilterResult{align-self:center;text-align:center;font:var(--mat-sys-body-large);padding:8px;border-radius:4px;background-color:var(--warning);color:var(--on-warning)}\n"], dependencies: [{ kind: "directive", type: MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$2.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i2$2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: AdvancedFilterGroupComponent, selector: "lib-advanced-filter-group", inputs: ["isRootNode", "group", "config"], outputs: ["addGroup", "addFilter", "deleteGroup", "deleteFilter"] }, { kind: "pipe", type: LowerCasePipe, name: "lowercase" }] });
2391
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: ConfigureAdvancedFilterComponent, isStandalone: true, selector: "lib-configure-advanced-filter", ngImport: i0, template: "<form [formGroup]=\"form\" (ngSubmit)=\"onSubmit('save_and_apply')\">\r\n\r\n <h2 mat-dialog-title>{{texts().advancedFilters.dialogTitle}} {{data.config.title() | lowercase}}</h2>\r\n <mat-dialog-content>\r\n\r\n <p class=\"advancedFilterResult\" [innerHTML]=\"query()\" [style.visibility]=\"query() ? 'visible': 'hidden'\"></p>\r\n\r\n <mat-form-field>\r\n <mat-label>{{texts().advancedFilters.templateName}}</mat-label>\r\n <input matInput formControlName=\"name\" [maxlength]=\"16\">\r\n <mat-hint>{{form.get('name')?.value.length ?? 0}}/16</mat-hint>\r\n <mat-error>{{texts().advancedFilters.templateNameRequired}}</mat-error>\r\n </mat-form-field>\r\n\r\n <lib-advanced-filter-group \r\n [group]=\"getRootGroup()\"\r\n [config]=\"data.config\"\r\n [isRootNode]=\"true\"\r\n (addGroup)=\"addGroup($event)\"\r\n (addFilter)=\"addFilter($event)\"\r\n (deleteGroup)=\"deleteGroup($event)\"\r\n (deleteFilter)=\"deleteFilter($event)\"\r\n />\r\n\r\n <div class=\"helperContainer\">\r\n <p class=\"helperTitle\"><strong>{{texts().advancedFilters.helpTitle}}</strong></p>\r\n <p class=\"helper\">\r\n <strong>{{texts().advancedFilters.group}} </strong>{{texts().advancedFilters.groupHelp}}<br>\r\n <strong>{{texts().advancedFilters.filter}} </strong>{{texts().advancedFilters.ruleHelp}}\r\n </p>\r\n </div>\r\n \r\n </mat-dialog-content>\r\n <mat-dialog-actions>\r\n <button matButton [mat-dialog-close]=\"undefined\">{{texts().common.close}}</button>\r\n <button matButton [disabled]=\"form.invalid\" type=\"button\" (click)=\"onSubmit('save')\">{{texts().common.save}}</button>\r\n <button matButton [disabled]=\"form.invalid\" type=\"button\" (click)=\"onSubmit('save_and_apply')\">{{texts().common.saveAndApply}}</button>\r\n </mat-dialog-actions>\r\n\r\n\r\n</form>", styles: [":host{display:block}mat-dialog-content{display:flex;flex-direction:column;gap:12px}.helperContainer{margin-top:30px}.helperTitle,.helper{font:var(--mat-sys-body-small);font-weight:300;margin:0}.helper{margin-top:4px;padding-left:20px}.advancedFilterResult{align-self:center;text-align:center;font:var(--mat-sys-body-large);padding:8px;border-radius:4px;background-color:var(--warning);color:var(--on-warning)}\n"], dependencies: [{ kind: "directive", type: MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$3.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i2$3.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: AdvancedFilterGroupComponent, selector: "lib-advanced-filter-group", inputs: ["isRootNode", "group", "config"], outputs: ["addGroup", "addFilter", "deleteGroup", "deleteFilter"] }, { kind: "pipe", type: LowerCasePipe, name: "lowercase" }] });
2005
2392
  }
2006
2393
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfigureAdvancedFilterComponent, decorators: [{
2007
2394
  type: Component,
@@ -2017,7 +2404,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
2017
2404
  MatFormFieldModule,
2018
2405
  MatInputModule,
2019
2406
  AdvancedFilterGroupComponent
2020
- ], template: "<form [formGroup]=\"form\" (ngSubmit)=\"onSubmit('save_and_apply')\">\r\n\r\n <h2 mat-dialog-title>{{intl.advancedFiltersDialogTitle}} {{data.config.title() | lowercase}}</h2>\r\n <mat-dialog-content>\r\n\r\n <p class=\"advancedFilterResult\" [innerHTML]=\"query()\" [style.visibility]=\"query() ? 'visible': 'hidden'\"></p>\r\n\r\n <mat-form-field>\r\n <mat-label>{{intl.templateNameLabel}}</mat-label>\r\n <input matInput formControlName=\"name\" [maxlength]=\"16\">\r\n <mat-hint>{{form.get('name')?.value.length ?? 0}}/16</mat-hint>\r\n <mat-error>{{intl.templateNameRequiredError}}</mat-error>\r\n </mat-form-field>\r\n\r\n <lib-advanced-filter-group \r\n [group]=\"getRootGroup()\"\r\n [config]=\"data.config\"\r\n [isRootNode]=\"true\"\r\n (addGroup)=\"addGroup($event)\"\r\n (addFilter)=\"addFilter($event)\"\r\n (deleteGroup)=\"deleteGroup($event)\"\r\n (deleteFilter)=\"deleteFilter($event)\"\r\n />\r\n\r\n <div class=\"helperContainer\">\r\n <p class=\"helperTitle\"><strong>{{intl.advancedFiltersHelpTitle}}</strong></p>\r\n <p class=\"helper\">\r\n <strong>{{intl.groupLabel}} </strong>{{intl.advancedFiltersGroupHelp}}<br>\r\n <strong>{{intl.filterLabel}} </strong>{{intl.advancedFiltersRuleHelp}}\r\n </p>\r\n </div>\r\n \r\n </mat-dialog-content>\r\n <mat-dialog-actions>\r\n <button matButton [mat-dialog-close]=\"undefined\">{{intl.closeButtonLabel}}</button>\r\n <button matButton [disabled]=\"form.invalid\" type=\"button\" (click)=\"onSubmit('save')\">{{intl.saveButtonLabel}}</button>\r\n <button matButton [disabled]=\"form.invalid\" type=\"button\" (click)=\"onSubmit('save_and_apply')\">{{intl.saveAndApplyButtonLabel}}</button>\r\n </mat-dialog-actions>\r\n\r\n\r\n</form>", styles: [":host{display:block}mat-dialog-content{display:flex;flex-direction:column;gap:12px}.helperContainer{margin-top:30px}.helperTitle,.helper{font:var(--mat-sys-body-small);font-weight:300;margin:0}.helper{margin-top:4px;padding-left:20px}.advancedFilterResult{align-self:center;text-align:center;font:var(--mat-sys-body-large);padding:8px;border-radius:4px;background-color:var(--warning);color:var(--on-warning)}\n"] }]
2407
+ ], template: "<form [formGroup]=\"form\" (ngSubmit)=\"onSubmit('save_and_apply')\">\r\n\r\n <h2 mat-dialog-title>{{texts().advancedFilters.dialogTitle}} {{data.config.title() | lowercase}}</h2>\r\n <mat-dialog-content>\r\n\r\n <p class=\"advancedFilterResult\" [innerHTML]=\"query()\" [style.visibility]=\"query() ? 'visible': 'hidden'\"></p>\r\n\r\n <mat-form-field>\r\n <mat-label>{{texts().advancedFilters.templateName}}</mat-label>\r\n <input matInput formControlName=\"name\" [maxlength]=\"16\">\r\n <mat-hint>{{form.get('name')?.value.length ?? 0}}/16</mat-hint>\r\n <mat-error>{{texts().advancedFilters.templateNameRequired}}</mat-error>\r\n </mat-form-field>\r\n\r\n <lib-advanced-filter-group \r\n [group]=\"getRootGroup()\"\r\n [config]=\"data.config\"\r\n [isRootNode]=\"true\"\r\n (addGroup)=\"addGroup($event)\"\r\n (addFilter)=\"addFilter($event)\"\r\n (deleteGroup)=\"deleteGroup($event)\"\r\n (deleteFilter)=\"deleteFilter($event)\"\r\n />\r\n\r\n <div class=\"helperContainer\">\r\n <p class=\"helperTitle\"><strong>{{texts().advancedFilters.helpTitle}}</strong></p>\r\n <p class=\"helper\">\r\n <strong>{{texts().advancedFilters.group}} </strong>{{texts().advancedFilters.groupHelp}}<br>\r\n <strong>{{texts().advancedFilters.filter}} </strong>{{texts().advancedFilters.ruleHelp}}\r\n </p>\r\n </div>\r\n \r\n </mat-dialog-content>\r\n <mat-dialog-actions>\r\n <button matButton [mat-dialog-close]=\"undefined\">{{texts().common.close}}</button>\r\n <button matButton [disabled]=\"form.invalid\" type=\"button\" (click)=\"onSubmit('save')\">{{texts().common.save}}</button>\r\n <button matButton [disabled]=\"form.invalid\" type=\"button\" (click)=\"onSubmit('save_and_apply')\">{{texts().common.saveAndApply}}</button>\r\n </mat-dialog-actions>\r\n\r\n\r\n</form>", styles: [":host{display:block}mat-dialog-content{display:flex;flex-direction:column;gap:12px}.helperContainer{margin-top:30px}.helperTitle,.helper{font:var(--mat-sys-body-small);font-weight:300;margin:0}.helper{margin-top:4px;padding-left:20px}.advancedFilterResult{align-self:center;text-align:center;font:var(--mat-sys-body-large);padding:8px;border-radius:4px;background-color:var(--warning);color:var(--on-warning)}\n"] }]
2021
2408
  }] });
2022
2409
 
2023
2410
  class NgxPaginatedTable {
@@ -2025,12 +2412,10 @@ class NgxPaginatedTable {
2025
2412
  advancedFilterService = inject(AdvancedFilterService);
2026
2413
  dialog = inject(MatDialog);
2027
2414
  datosPantallaService = inject(DatosPantallaService);
2028
- _changeDetectorRef = inject(ChangeDetectorRef);
2029
2415
  // Inyectar el servicio de internacionalización.
2030
2416
  // inject() resuelve tambien los providers a nivel de componente/ruta, por lo que
2031
2417
  // el override sigue siendo posible sin necesidad de instanciarlo a mano.
2032
- intl = inject(NgxTablesIntl);
2033
- _destroy$ = new Subject();
2418
+ texts = inject(NgxTexts).texts;
2034
2419
  isDesktop = computed(() => this.datosPantallaService.pantalla()?.tipo == 'escritorio', ...(ngDevMode ? [{ debugName: "isDesktop" }] : []));
2035
2420
  endpoint = input.required(...(ngDevMode ? [{ debugName: "endpoint" }] : []));
2036
2421
  filters = input(signal({
@@ -2155,14 +2540,6 @@ class NgxPaginatedTable {
2155
2540
  pageSize: 20,
2156
2541
  query: undefined
2157
2542
  }, ...(ngDevMode ? [{ debugName: "defaultFiltersForPaginatedFilterOptions" }] : []));
2158
- ngOnInit() {
2159
- // Suscribirse a los cambios de las etiquetas
2160
- this.intl.changes
2161
- .pipe(takeUntil(this._destroy$))
2162
- .subscribe(() => {
2163
- this._changeDetectorRef.markForCheck();
2164
- });
2165
- }
2166
2543
  onEscape() {
2167
2544
  if (this.overlayRef && this.isMyOverlayOnTop())
2168
2545
  this.exitFullscreen();
@@ -2176,8 +2553,6 @@ class NgxPaginatedTable {
2176
2553
  const timeout = this.timeoutsByKey[key];
2177
2554
  clearTimeout(timeout);
2178
2555
  });
2179
- this._destroy$.next();
2180
- this._destroy$.complete();
2181
2556
  }
2182
2557
  includeInColumnConfig(searchedColumn, allColumns) {
2183
2558
  return allColumns.some(column => searchedColumn.key == column.key);
@@ -2234,15 +2609,15 @@ class NgxPaginatedTable {
2234
2609
  }
2235
2610
  onDeleteClick(row, event) {
2236
2611
  event.stopPropagation();
2237
- const title = this.config()().deleteConfirm?.title?.(row) ?? this.intl.deleteConfirmTitle;
2238
- const body = this.config()().deleteConfirm?.body?.(row) ?? this.intl.deleteConfirmBody;
2612
+ const title = this.config()().deleteConfirm?.title?.(row) ?? this.texts().table.deleteConfirmTitle;
2613
+ const body = this.config()().deleteConfirm?.body?.(row) ?? this.texts().table.deleteConfirmBody;
2239
2614
  const template = this.config()().deleteConfirm?.templateRef?.();
2240
2615
  const data = {
2241
2616
  title: title,
2242
2617
  body: !template ? body : undefined,
2243
2618
  template: template,
2244
2619
  row: row,
2245
- confirmButtonLabel: this.intl.confirmDeleteLabel
2620
+ confirmButtonLabel: this.texts().table.confirmDelete
2246
2621
  };
2247
2622
  const dialogRef = this.dialog.open(NgxConfirmDialogComponent, { data: data });
2248
2623
  dialogRef.afterClosed().subscribe((confirm) => {
@@ -2387,9 +2762,9 @@ class NgxPaginatedTable {
2387
2762
  event.stopPropagation();
2388
2763
  advancedFiltersMenuTrigger.closeMenu();
2389
2764
  const data = {
2390
- title: this.intl.deleteAdvancedFilterTitle,
2391
- body: this.intl.getDeleteAdvancedFilterMessage(advancedFilter.name),
2392
- confirmButtonLabel: this.intl.confirmDeleteLabel
2765
+ title: this.texts().advancedFilters.deleteTitle,
2766
+ body: this.texts().advancedFilters.deleteMessage(advancedFilter.name),
2767
+ confirmButtonLabel: this.texts().table.confirmDelete
2393
2768
  };
2394
2769
  const dialogRef = this.dialog.open(NgxConfirmDialogComponent, { data: data });
2395
2770
  dialogRef.afterClosed().subscribe((confirm) => {
@@ -2412,7 +2787,7 @@ class NgxPaginatedTable {
2412
2787
  const advancedFilter = this.advancedFilterService.getAdvancedFilterById(tableId, advancedFilterId, false);
2413
2788
  if (!advancedFilter)
2414
2789
  return '';
2415
- return AdvancedFilterUtils.groupsToReadableHtml(advancedFilter.groups, this.config()().columns, this.intl);
2790
+ return AdvancedFilterUtils.groupsToReadableHtml(advancedFilter.groups, this.config()().columns, this.texts());
2416
2791
  }
2417
2792
  rowIsExpanded(row) {
2418
2793
  return this.expandedItem() == row;
@@ -2581,7 +2956,7 @@ class NgxPaginatedTable {
2581
2956
  return topOverlay === this.overlayRef.hostElement;
2582
2957
  }
2583
2958
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxPaginatedTable, deps: [], target: i0.ɵɵFactoryTarget.Component });
2584
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: NgxPaginatedTable, isStandalone: true, selector: "ngx-paginated-table", inputs: { endpoint: { classPropertyName: "endpoint", publicName: "endpoint", isSignal: true, isRequired: true, transformFunction: null }, filters: { classPropertyName: "filters", publicName: "filters", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { createClick: "createClick", updateClick: "updateClick", deleteClick: "deleteClick", rowActionClick: "rowActionClick", expandedItemChange: "expandedItemChange", selectionActionEvent: "selectionActionEvent" }, host: { listeners: { "document:keydown.escape": "onEscape()" }, classAttribute: "contenedorDefecto" }, viewQueries: [{ propertyName: "tableContentTemplate", first: true, predicate: ["tableContent"], descendants: true, isSignal: true }], ngImport: i0, template: "@if(!isFullScreen()) {\r\n <ng-container *ngTemplateOutlet=\"tableContentTemplate()\"></ng-container>\r\n}\r\n\r\n<ng-template #tableContent>\r\n <div class=\"tableContainer\" [class.inFullScreenMode]=\"isFullScreen()\">\r\n <div class=\"headerContainer\">\r\n <div class=\"titleAndButtonContainer\">\r\n <p class=\"title\">{{ config()().title() }}</p>\r\n <div class=\"buttonContainer\">\r\n @if(config()().create && (!config()().create?.show || config()().create?.show())) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"config()().create?.tooltip?.() ?? intl.createButtonLabel\" \r\n [disabled]=\"config()().create?.disabled?.()\" \r\n class=\"newButtonIcon\"\r\n (click)=\"onNewClick()\">\r\n <mat-icon>add_circle</mat-icon>\r\n </button>\r\n }\r\n\r\n @if(config()().hideColumnConfig?.() !== true) {\r\n <button matIconButton [matTooltip]=\"intl.editColumnsTooltip\" class=\"editColumnsButtonIcon\" (click)=\"onEditColumns()\">\r\n <mat-icon>table_edit</mat-icon>\r\n </button>\r\n }\r\n\r\n @if(config()().showAdvancedFilters) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"intl.advancedFiltersLabel\"\r\n [matMenuTriggerFor]=\"advancedFiltersMenu\" \r\n #advancedFiltersMenuTrigger=\"matMenuTrigger\">\r\n\r\n <mat-icon>filter_alt</mat-icon>\r\n </button>\r\n\r\n <mat-menu #advancedFiltersMenu=\"matMenu\" xPosition=\"before\" yPosition=\"below\">\r\n <button mat-menu-item (click)=\"onNewAdvancedFiltersClick()\">\r\n <mat-icon>filter_alt</mat-icon>\r\n <span>{{ intl.newAdvancedFilterLabel }}</span>\r\n </button>\r\n\r\n @for (advancedFilter of advancedFilters(); track $index; let first = $first) {\r\n @if (first) {\r\n <mat-divider />\r\n }\r\n\r\n <div mat-menu-item (click)=\"onApplyTemplateClick(advancedFilter)\">\r\n <div class=\"templateContainer\"> \r\n <span>{{advancedFilter.name | ngxOnlyUpperFirstCharacter}}</span>\r\n\r\n <div class=\"buttonTemplateContainer\">\r\n <button\r\n matIconButton \r\n [matTooltip]=\"intl.getEditAdvancedFilterTooltip(advancedFilter.name | ngxOnlyUpperFirstCharacter)\"\r\n (click)=\"onAdvancedFilterUpdate($event, advancedFilter, advancedFiltersMenuTrigger)\">\r\n <mat-icon>edit</mat-icon>\r\n </button>\r\n\r\n <button\r\n matIconButton \r\n [matTooltip]=\"intl.getDeleteAdvancedFilterTooltip(advancedFilter.name | ngxOnlyUpperFirstCharacter)\"\r\n (click)=\"onAdvancedFilterDelete($event, advancedFiltersMenuTrigger, advancedFilter)\">\r\n <mat-icon>delete</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </mat-menu>\r\n }\r\n\r\n @if(selection().length > 0) {\r\n @if(getRowSelectionAction().length > 0) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"intl.selectionActionsTooltip\"\r\n [matMenuTriggerFor]=\"selectedRecordsMenu\">\r\n <mat-icon>event_list</mat-icon>\r\n </button>\r\n\r\n <mat-menu #selectedRecordsMenu=\"matMenu\" xPosition=\"before\" yPosition=\"below\">\r\n <button mat-menu-item (click)=\"uncheckAllSelection()\">\r\n <mat-icon>deselect</mat-icon>\r\n <span>{{ intl.deselectAllLabel }}</span>\r\n </button>\r\n\r\n @for (action of getRowSelectionAction(); track $index) {\r\n <button mat-menu-item (click)=\"onRowSelectionActionClick(action.id)\">\r\n <mat-icon>{{action.icon}}</mat-icon>\r\n <span>{{action.label(selection(), selection().length)}}</span>\r\n </button>\r\n }\r\n </mat-menu>\r\n } @else {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"intl.deselectAllLabel\"\r\n (click)=\"uncheckAllSelection()\">\r\n <mat-icon>deselect</mat-icon>\r\n </button>\r\n }\r\n }\r\n @if(config()().hideExportData?.() !== true) {\r\n <button matIconButton [matTooltip]=\"intl.exportTooltip\" [matMenuTriggerFor]=\"exportMenu\">\r\n <mat-icon>download</mat-icon>\r\n </button>\r\n <mat-menu #exportMenu=\"matMenu\" xPosition=\"before\" yPosition=\"below\">\r\n <button mat-menu-item (click)=\"exportToCsvCurrentPage()\">\r\n <mat-icon>csv</mat-icon>\r\n <span>{{ intl.exportToExcelLabel }}</span>\r\n </button>\r\n\r\n <button mat-menu-item (click)=\"exportToPdfCurrentPage()\">\r\n <mat-icon>picture_as_pdf</mat-icon>\r\n <span>{{ intl.exportToPdfLabel }}</span>\r\n </button>\r\n </mat-menu>\r\n }\r\n @if(config()().hideFullScreen?.() !== true) {\r\n <button matIconButton [matTooltip]=\"isFullScreen() ? intl.exitFullscreenTooltip : intl.enterFullscreenTooltip\" (click)=\"onToggleFullScreen()\">\r\n <mat-icon>{{isFullScreen() ? 'fullscreen_exit': 'fullscreen'}}</mat-icon>\r\n </button>\r\n }\r\n\r\n <ng-content select=\"[icon-buttons]\"></ng-content>\r\n </div>\r\n </div>\r\n\r\n <div class=\"filterContainer\">\r\n <div class=\"moreFiltersContainer\">\r\n <ng-content select=\"[more-filters]\"></ng-content>\r\n </div>\r\n\r\n @if(config()().showQueryFilter) {\r\n <mat-form-field subscriptSizing=\"dynamic\">\r\n <mat-icon matPrefix>search</mat-icon>\r\n <input #queryElement matInput [placeholder]=\"config()().queryFilterPlaceholder ?? intl.searchPlaceholder\" [value]=\"filters()().query ?? ''\" (input)=\"onQueryChange(queryElement)\">\r\n <button matIconButton matSuffix (click)=\"onQueryReset(queryElement)\" [style.visibility]=\"queryElement.value ? 'visible': 'hidden'\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </mat-form-field>\r\n }\r\n </div>\r\n\r\n <ng-content select=\"[extra-header-content]\"></ng-content>\r\n </div>\r\n\r\n @if(filters()().advancedFilterId) {\r\n <div class=\"advancedFiltersApplied\" (click)=\"onSelectedAdvancedFilterUpdate($event)\">\r\n <p [innerHTML]=\"getAdvancedFilterLabel()\"></p>\r\n <button matIconButton [matTooltip]=\"intl.removeAdvancedFilterTooltip\" class=\"\" (click)=\"onQuitAdvancedFilter($event)\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n }\r\n\r\n <mat-progress-bar mode=\"indeterminate\" [style.visibility]=\"dataResource.isLoading() ? 'visible': 'hidden'\"/>\r\n\r\n <div class=\"tableOverflow\" [style.max-height]=\"config()().maxHeight && !isFullScreen() ? config()().maxHeight : null\">\r\n <table\r\n mat-table \r\n matSort\r\n [multiTemplateDataRows]=\"config()().expandableDetail\"\r\n [dataSource]=\"data()\" \r\n [matSortActive]=\"filters()().sortBy?.key ?? ''\" \r\n [matSortDirection]=\"filters()().sortBy?.direction ?? ''\"\r\n (matSortChange)=\"onSortChange($event)\">\r\n\r\n @if(config()().enableRowSelection) {\r\n @if(showFiltersRow()) {\r\n <ng-container [matColumnDef]=\"`${filterKeyPrefix}${nameOfRowSelectionColumn}`\" [sticky]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef class=\"celdaSelection\"></th>\r\n </ng-container>\r\n } \r\n\r\n <ng-container [matColumnDef]=\"nameOfRowSelectionColumn\" [sticky]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef>\r\n <mat-checkbox \r\n class=\"headerCheckbox\"\r\n (change)=\"$event ? toggleAllPageRowSelection() : null\"\r\n [checked]=\"selection().length > 0 && isAllPageRowSelected()\"\r\n [indeterminate]=\"selection().length > 0 && !isAllPageRowSelected()\">\r\n </mat-checkbox>\r\n </th>\r\n <td mat-cell *matCellDef=\"let row\" (click)=\"$event.stopPropagation()\" class=\"celdaSelection\">\r\n @if(!config()().showRowSelection || config()().showRowSelection?.(row)) {\r\n <mat-checkbox\r\n (change)=\"$event ? toggleRowSelection(row) : null\"\r\n [checked]=\"isRowSelected(row)\">\r\n </mat-checkbox>\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n\r\n @if(showTotalGeneralFooter()) {\r\n <ng-container [matColumnDef]=\"`${generalFooterKeyPrefix}${nameOfRowSelectionColumn}`\" [sticky]=\"isDesktop()\">\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @for (column of config()().columns; track $index) {\r\n <ng-container \r\n [matColumnDef]=\"getKeyAsString(column.key)\" \r\n [sticky]=\"stickyColumnKey() == column.key && isDesktop()\">\r\n\r\n <th mat-header-cell *matHeaderCellDef mat-sort-header [disabled]=\"!column.isSortable\" class=\"columnLabel\">\r\n <p class=\"headerTitle\">\r\n @if(stickyColumnKey() == column.key && isDesktop()) {\r\n <mat-icon>keep</mat-icon>\r\n }\r\n {{ column.label }}\r\n </p>\r\n </th>\r\n\r\n <td \r\n mat-cell \r\n *matCellDef=\"let row\" \r\n [class.columnSticky]=\"stickyColumnKey() == column.key && isDesktop()\"\r\n [style]=\"column.style\"\r\n class=\"celdaDatos\">\r\n\r\n @if(column.component) {\r\n <ng-container \r\n ngxDynamicCellHost\r\n [component]=\"column.component\"\r\n [row]=\"row\"\r\n [key]=\"column.key\" />\r\n } @else if(column.templateRef) {\r\n <ng-container \r\n *ngTemplateOutlet=\"column.templateRef(); \r\n context: { $implicit: row }\" />\r\n } @else if(column.valueGetter) {\r\n {{ column.valueGetter(row) }}\r\n } @else {\r\n {{ applyColumnPipes(row[column.key], column.pipes) ?? '-' }}\r\n }\r\n </td>\r\n \r\n <td \r\n mat-footer-cell \r\n *matFooterCellDef \r\n [class.columnSticky]=\"stickyColumnKey() == column.key && isDesktop()\"\r\n [style]=\"column.footerStyle\">\r\n\r\n @if(column.showTotalPerPage) {\r\n @if(column.pipes) {\r\n {{ applyColumnPipes(getTotalOfColum(column.key), column.pipes) }}\r\n } @else if(column.totalFooterFormatter) {\r\n {{ column.totalFooterFormatter(getTotalOfColum(column.key)) }}\r\n } @else {\r\n {{ getTotalOfColum(column.key) }}\r\n }\r\n }\r\n </td>\r\n </ng-container>\r\n }\r\n\r\n @if(showTotalGeneralFooter()) {\r\n @for (column of config()().columns; track $index) {\r\n <ng-container \r\n [matColumnDef]=\"`${generalFooterKeyPrefix}${getKeyAsString(column.key)}`\"\r\n [sticky]=\"stickyColumnKey() == column.key && isDesktop()\">\r\n\r\n <td mat-footer-cell *matFooterCellDef [style]=\"column.footerStyle\">\r\n @if(column.showTotalGeneral && column.getTotalGeneral) {\r\n @if(column.pipes) {\r\n {{ applyColumnPipes(column.getTotalGeneral(), column.pipes) }}\r\n } @else if(column.totalFooterFormatter) {\r\n {{ column.totalFooterFormatter(column.getTotalGeneral()) }}\r\n } @else {\r\n {{ column.getTotalGeneral() }}\r\n }\r\n }\r\n </td>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @if(showFiltersRow()) {\r\n @for (column of config()().columns; track $index) {\r\n <ng-container \r\n [matColumnDef]=\"`${filterKeyPrefix}${getKeyAsString(column.key)}`\" \r\n [sticky]=\"stickyColumnKey() == column.key && isDesktop()\">\r\n\r\n <th mat-header-cell *matHeaderCellDef>\r\n @if (column.filterType == 'text' || column.filterType == 'number') {\r\n <mat-form-field subscriptSizing=\"dynamic\" class=\"inputQueryColumn\">\r\n <input [type]=\"column.filterType\" matInput [placeholder]=\"column.label\" [value]=\"getValueOfColumnFilter(column.key) ?? ''\" (input)=\"onTextFilterColumnChange(column, $event)\">\r\n <mat-icon matSuffix>{{ column.filterType == 'text' ? 'search' : 'numbers'}}</mat-icon>\r\n </mat-form-field>\r\n }\r\n\r\n @if (column.filterType == 'option' || column.filterType == 'option-multiple') {\r\n @if(column.endpointForPaginatedFilterOptions) {\r\n <ngx-paginated-searchable-select\r\n class=\"selectColumn\"\r\n [selected]=\"getPaginatedSearchableSelectValueOfColumnFilter(column.key)\"\r\n [endpoint]=\"column.endpointForPaginatedFilterOptions\"\r\n [filters]=\"column.filtersForEndpointPaginatedFilterOptions ?? defaultFiltersForPaginatedFilterOptions\"\r\n [multiple]=\"column.filterType == 'option-multiple'\"\r\n subscriptSizing=\"dynamic\"\r\n [selectPlaceholder]=\"column.label\"\r\n (optionChange)=\"onPaginatedOptionFilterColumnChange(column, $event)\"\r\n clearableOptionLabel=\"filtro\"\r\n />\r\n } @else {\r\n <ngx-searchable-select\r\n class=\"selectColumn\"\r\n [selected]=\"getSearchableSelectValueOfColumnFilter(column.key)\"\r\n [options]=\"column.filterOptions ?? []\"\r\n [multiple]=\"column.filterType == 'option-multiple'\"\r\n subscriptSizing=\"dynamic\"\r\n [selectPlaceholder]=\"column.label\"\r\n (optionChange)=\"onOptionFilterColumnChange(column, $event)\"\r\n clearableOptionLabel=\"filtro\"\r\n />\r\n }\r\n }\r\n \r\n @if(column.filterType == 'date') {\r\n <mat-form-field subscriptSizing=\"dynamic\" class=\"dateColumn\">\r\n <input \r\n matInput \r\n [matDatepicker]=\"picker\" \r\n [placeholder]=\"column.label\"\r\n [value]=\"getValueOfColumnFilter(column.key)\"\r\n (dateChange)=\"onDateFilterChange(column, $event.value)\">\r\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\r\n <mat-datepicker #picker></mat-datepicker>\r\n </mat-form-field>\r\n }\r\n\r\n @if(column.filterType == 'date-range') {\r\n <mat-form-field subscriptSizing=\"dynamic\" class=\"dateColumn\">\r\n <mat-date-range-input [rangePicker]=\"picker\" #dateRangeInput>\r\n <input \r\n matStartDate \r\n [placeholder]=\"intl.dateRangeStartPlaceholder\"\r\n [value]=\"getDateRangeValueOfColumnFilter(column.key, 'start')\"\r\n (dateChange)=\"onDateRangeFilterChange(column, dateRangeInput.value)\">\r\n <input \r\n matEndDate \r\n [placeholder]=\"intl.dateRangeEndPlaceholder\"\r\n [value]=\"getDateRangeValueOfColumnFilter(column.key, 'end')\"\r\n (dateChange)=\"onDateRangeFilterChange(column, dateRangeInput.value)\">\r\n </mat-date-range-input>\r\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\r\n <mat-date-range-picker #picker></mat-date-range-picker>\r\n </mat-form-field>\r\n }\r\n </th>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @if(showActionsColumn()) {\r\n @if(showFiltersRow()) {\r\n <ng-container [matColumnDef]=\"`${filterKeyPrefix}${nameOfActionsColumn}`\" [stickyEnd]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef class=\"celdaAcciones\"></th>\r\n </ng-container>\r\n } \r\n\r\n <ng-container [matColumnDef]=\"nameOfActionsColumn\" [stickyEnd]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef>{{ intl.actionsLabel }}</th>\r\n <td mat-cell *matCellDef=\"let row\" (click)=\"$event.stopPropagation()\" class=\"celdaAcciones\">\r\n <div class=\"contenedorCeldaAcciones\">\r\n @if(config()().expandableDetail) {\r\n <button \r\n matIconButton\r\n (click)=\"expandableToggle(row)\">\r\n <mat-icon>{{ rowIsExpanded(row) ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}</mat-icon>\r\n </button>\r\n }\r\n\r\n @if(config()().update && !config()().clickOnRowForUpdate && (!config()().update?.show || config()().update?.show(row))) {\r\n <button \r\n matIconButton\r\n [matTooltip]=\"config()().update?.tooltip?.(row) ?? intl.editTooltip\" \r\n [disabled]=\"config()().update?.disabled?.(row)\" \r\n class=\"editButtonIcon\"\r\n (click)=\"onUpdateClick(row, $event)\">\r\n <mat-icon>edit_square</mat-icon>\r\n </button>\r\n }\r\n \r\n @if(config()().delete && (!config()().delete?.show || config()().delete?.show(row))) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"config()().delete?.tooltip?.(row) ?? intl.deleteTooltip\" \r\n [disabled]=\"config()().delete?.disabled?.(row)\" \r\n class=\"deleteButtonIcon\"\r\n (click)=\"onDeleteClick(row, $event)\">\r\n <mat-icon>delete</mat-icon>\r\n </button>\r\n }\r\n\r\n @for (rowAction of config()().rowActions; track $index) {\r\n @if(!rowAction.show || rowAction.show(row)) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"rowAction.tooltip(row)\" \r\n [disabled]=\"rowAction.disabled?.(row)\" \r\n [class]=\"rowAction.iconColor ? `rowActionIconColor${rowAction.iconColor}` : ''\"\r\n (click)=\"onRowActionClick(row, rowAction, $event)\">\r\n <mat-icon>{{rowAction.icon}}</mat-icon>\r\n </button>\r\n } \r\n }\r\n </div>\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n\r\n @if(showTotalGeneralFooter()) {\r\n <ng-container [matColumnDef]=\"`${generalFooterKeyPrefix}${nameOfActionsColumn}`\" [stickyEnd]=\"isDesktop()\">\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @if(config()().expandableDetail) {\r\n <ng-container [matColumnDef]=\"expandableColumnDef\">\r\n <td mat-cell *matCellDef=\"let row\" [attr.colspan]=\"keys().length\">\r\n <div \r\n class=\"detailWrapper\"\r\n [class.detailWrapperExpanded]=\"rowIsExpanded(row)\">\r\n <div class=\"columnDetail\">\r\n @if(config()().expandableDetailTemplateRef) {\r\n <ng-container \r\n *ngTemplateOutlet=\"config()().expandableDetailTemplateRef!(); \r\n context: { $implicit: row }\" />\r\n }\r\n </div>\r\n </div>\r\n </td>\r\n </ng-container>\r\n }\r\n \r\n <tr mat-header-row *matHeaderRowDef=\"keys(); sticky: true\" class=\"tableHeader\"></tr>\r\n \r\n @if(showFiltersRow()) {\r\n <tr mat-header-row *matHeaderRowDef=\"keysWithFilter(); sticky: true\" class=\"filtersByColumn\"></tr>\r\n }\r\n \r\n <tr mat-row *matRowDef=\"let row; columns: keys();\" \r\n (click)=\"onRowClick(row)\" \r\n [class.rowClickEnable]=\"isRowEnabled(row)\"\r\n [class.expandableRow]=\"config()().expandableDetail\">\r\n </tr>\r\n \r\n @if(config()().expandableDetail) {\r\n <tr mat-row *matRowDef=\"let row; columns: [expandableColumnDef]\" class=\"rowDetail\"></tr>\r\n }\r\n\r\n <tr mat-footer-row \r\n *matFooterRowDef=\"showTotalPerPageFooter() ? keys() : []\" \r\n class=\"totalPerPageFooter\"\r\n [class.hideFooter]=\"!showTotalPerPageFooter()\">\r\n </tr>\r\n\r\n <tr mat-footer-row \r\n *matFooterRowDef=\"showTotalGeneralFooter() ? keysWithGeneralFooter() : []\" \r\n class=\"totalFooter\"\r\n [class.hideFooter]=\"!showTotalGeneralFooter()\">\r\n </tr>\r\n\r\n <tr class=\"mat-row\" *matNoDataRow>\r\n <td class=\"noData\" [colSpan]=\"keys().length\">{{ dataResource.isLoading() ? intl.loadingMessage : intl.noDataMessage }}</td>\r\n </tr>\r\n </table>\r\n </div>\r\n\r\n <div class=\"paginatorContainer\">\r\n <div class=\"footerLegend\">\r\n @if(showTotalPerPageFooter()) {\r\n <div class=\"legendItem\">\r\n <div class=\"legendSquare\"></div>\r\n <p>{{ intl.totalPerPageLabel }}</p> \r\n </div>\r\n }\r\n\r\n @if(showTotalGeneralFooter()) {\r\n <div class=\"legendItem\">\r\n <div class=\"legendSquare totalGeneral\"></div>\r\n <p>{{ intl.totalGeneralLabel }}</p>\r\n </div>\r\n }\r\n </div>\r\n <mat-paginator [length]=\"total()\" [pageSize]=\"filters()().pageSize\" [pageIndex]=\"filters()().pageNumber - 1\" (page)=\"onPageChange($event)\"/>\r\n </div>\r\n\r\n <ng-content select=\"[end-container]\"></ng-content>\r\n </div>\r\n</ng-template>", styles: [".tableContainer{display:flex;flex-direction:column;padding:14px;gap:10px;--mat-table-background-color: transparent;--mat-table-header-headline-color: var(--mat-sys-on-primary)}.inFullScreenMode{height:calc(100vh - 28px);width:calc(100vw - 28px);max-width:calc(100% - 28px);background:var(--mat-sys-surface)}.title{font:var(--mat-sys-title-large);color:var(--mat-sys-on-surface);margin:0;position:relative}.headerContainer{display:flex;justify-content:space-between;gap:10px;flex-direction:column}.titleAndButtonContainer{display:flex;justify-content:space-between;align-items:center;gap:20px}.buttonContainer{display:flex;gap:10px;align-items:center}.filterContainer{display:flex;flex-direction:row;align-items:center;gap:20px;justify-content:space-between}.moreFiltersContainer{display:flex;gap:20px}.editButtonIcon{--mat-icon-button-icon-color: var(--warning)}.deleteButtonIcon{--mat-icon-button-icon-color: var(--mat-sys-error)}.rowActionIconColorYellow{--mat-icon-button-icon-color: rgb(211, 211, 7)}.rowActionIconColorOrange{--mat-icon-button-icon-color: orange}.rowActionIconColorPink{--mat-icon-button-icon-color: pink}.rowActionIconColorPurple{--mat-icon-button-icon-color: purple}.rowActionIconColorGreen{--mat-icon-button-icon-color: var(--success)}.rowActionIconColorBlue{--mat-icon-button-icon-color: var(--information)}.rowActionIconColorBrown{--mat-icon-button-icon-color: brown}.rowActionIconColorSky{--mat-icon-button-icon-color: rgb(0, 247, 255)}.noData{padding:24px}.tableOverflow{overflow:auto;border-radius:10px}.columnLabel{text-wrap:nowrap}.headerTitle{display:flex;align-items:center;gap:4px}.headerTitle mat-icon{font-size:12px;width:12px;height:12px}.tableHeader{background-color:var(--mat-sys-primary)!important}.filtersByColumn{background-color:var(--mat-sys-surface)!important}.filtersByColumn th{padding:0}.celdaDatos{background-color:var(--mat-sys-surface)!important;transition:background-color .1s}.celdaAcciones,.celdaSelection{cursor:default!important;background-color:var(--mat-sys-surface)!important;transition:background-color .1s}.columnSticky{background-color:var(--mat-sys-surface)!important;transition:background-color .1s}.contenedorCeldaAcciones{display:flex;align-items:center;cursor:default!important}.rowClickEnable{cursor:pointer;transition:background-color .1s}.rowClickEnable:hover,.rowClickEnable:hover>.celdaAcciones,.rowClickEnable:hover>.celdaSelection,.rowClickEnable:hover>.celdaDatos,.rowClickEnable:hover>.columnSticky{background-color:var(--mat-sys-surface-container)!important}.inputQueryColumn,.selectColumn,.dateColumn{--mat-form-field-outlined-focus-outline-color: transparent;--mat-form-field-outlined-outline-color: transparent;--mat-form-field-outlined-hover-outline-color: transparent}.templateContainer{display:flex;align-items:center;justify-content:space-between;gap:60px}.buttonTemplateContainer{display:flex;flex-wrap:nowrap}.advancedFiltersApplied{display:flex;flex-direction:row;justify-content:space-between;gap:20px;border-radius:10px;background-color:var(--warning);color:var(--on-warning);align-items:center;margin-top:10px;padding:5px 5px 5px 15px;cursor:pointer;transition:background-color .3s}.advancedFiltersApplied:hover:not(:has(button:hover)){background-color:color-mix(in srgb,var(--warning) 80%,transparent)}.advancedFiltersApplied p{margin:0}.rowDetail{height:0}.expandableRow td{border-bottom-width:0}.detailWrapper{overflow:hidden;display:grid;grid-template-rows:0fr;grid-template-columns:100%;transition:grid-template-rows 225ms cubic-bezier(.4,0,.2,1)}.detailWrapperExpanded{grid-template-rows:1fr}.columnDetail{display:flex;flex-direction:column;min-height:0}.totalPerPageFooter{font-weight:700}.totalFooter{font-weight:700;background-color:var(--mat-sys-surface-container-highest);color:var(--mat-sys-on-surface)}.hideFooter{display:none}.paginatorContainer{display:flex;flex-direction:row;justify-content:space-between;align-items:center;gap:20px;margin-top:10px}.footerLegend{display:flex;flex-direction:row;gap:30px}.footerLegend p{margin:0;font:var(--mat-sys-label-medium)}.legendItem{display:flex;flex-direction:row;align-items:center;gap:6px}.legendSquare{width:24px;height:14px;border-radius:4px;border:2px solid var(--mat-sys-on-surface)}.totalGeneral{background-color:var(--mat-sys-surface-container-highest)}.headerCheckbox{--mat-checkbox-selected-checkmark-color: var(--mat-sys-primary);--mat-checkbox-selected-focus-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-focus-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-selected-hover-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-hover-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-selected-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-pressed-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-pressed-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-focus-icon-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-focus-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-hover-icon-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-hover-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-icon-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-pressed-state-layer-color: var(--mat-sys-on-primary)}@media (max-width: 1200px){.filterContainer{flex-direction:column;align-items:normal}.moreFiltersContainer{flex-direction:column}}@media (max-width: 900px){.footerLegend{flex-direction:column;gap:6px}}@media (max-width: 700px){.paginatorContainer{flex-direction:column;align-items:flex-end}}@media (max-width: 600px){.titleAndButtonContainer{flex-direction:column;align-items:normal}}\n"], dependencies: [{ kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i1$3.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i1$3.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1$3.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i1$3.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1$3.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1$3.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i1$3.MatFooterCellDef, selector: "[matFooterCellDef]" }, { kind: "directive", type: i1$3.MatFooterRowDef, selector: "[matFooterRowDef]", inputs: ["matFooterRowDef", "matFooterRowDefSticky"] }, { kind: "directive", type: i1$3.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1$3.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: i1$3.MatFooterCell, selector: "mat-footer-cell, td[mat-footer-cell]" }, { kind: "component", type: i1$3.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i1$3.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i1$3.MatFooterRow, selector: "mat-footer-row, tr[mat-footer-row]", exportAs: ["matFooterRow"] }, { kind: "directive", type: i1$3.MatNoDataRow, selector: "ng-template[matNoDataRow]" }, { kind: "ngmodule", type: MatSortModule }, { kind: "directive", type: i2$3.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i2$3.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i3$3.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatProgressBarModule }, { kind: "component", type: i6.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$2.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i2$2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i10.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i10.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i10.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "component", type: i10.MatDateRangeInput, selector: "mat-date-range-input", inputs: ["rangePicker", "required", "dateFilter", "min", "max", "disabled", "separator", "comparisonStart", "comparisonEnd"], exportAs: ["matDateRangeInput"] }, { kind: "directive", type: i10.MatStartDate, selector: "input[matStartDate]", outputs: ["dateChange", "dateInput"] }, { kind: "directive", type: i10.MatEndDate, selector: "input[matEndDate]", outputs: ["dateChange", "dateInput"] }, { kind: "component", type: i10.MatDateRangePicker, selector: "mat-date-range-picker", exportAs: ["matDateRangePicker"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i11.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: DynamicCellHostDirective, selector: "[ngxDynamicCellHost]", inputs: ["component", "row", "key"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i12.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i12.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i12.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i1$2.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i14.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: PaginatedSearchableSelectComponent, selector: "ngx-paginated-searchable-select", inputs: ["control", "endpoint", "filters", "optionLabel", "compareWith", "multiple", "searchInputPlaceholder", "selectLabel", "selectPlaceholder", "clearableOptionLabel", "subscriptSizing", "clearable", "error", "selected", "disabled"], outputs: ["optionChange"] }, { kind: "component", type: SearchableSelectComponent, selector: "ngx-searchable-select", inputs: ["control", "options", "optionLabel", "optionValue", "multiple", "searchInputPlaceholder", "selectLabel", "selectPlaceholder", "clearableOptionLabel", "subscriptSizing", "clearable", "error", "selected", "disabled"], outputs: ["optionChange"] }, { kind: "pipe", type: OnlyUpperFirstCharacterPipe, name: "ngxOnlyUpperFirstCharacter" }] });
2959
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: NgxPaginatedTable, isStandalone: true, selector: "ngx-paginated-table", inputs: { endpoint: { classPropertyName: "endpoint", publicName: "endpoint", isSignal: true, isRequired: true, transformFunction: null }, filters: { classPropertyName: "filters", publicName: "filters", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { createClick: "createClick", updateClick: "updateClick", deleteClick: "deleteClick", rowActionClick: "rowActionClick", expandedItemChange: "expandedItemChange", selectionActionEvent: "selectionActionEvent" }, host: { listeners: { "document:keydown.escape": "onEscape()" }, classAttribute: "contenedorDefecto" }, viewQueries: [{ propertyName: "tableContentTemplate", first: true, predicate: ["tableContent"], descendants: true, isSignal: true }], ngImport: i0, template: "@if(!isFullScreen()) {\r\n <ng-container *ngTemplateOutlet=\"tableContentTemplate()\"></ng-container>\r\n}\r\n\r\n<ng-template #tableContent>\r\n <div class=\"tableContainer\" [class.inFullScreenMode]=\"isFullScreen()\">\r\n <div class=\"headerContainer\">\r\n <div class=\"titleAndButtonContainer\">\r\n <p class=\"title\">{{ config()().title() }}</p>\r\n <div class=\"buttonContainer\">\r\n @if(config()().create && (!config()().create?.show || config()().create?.show())) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"config()().create?.tooltip?.() ?? texts().table.create\" \r\n [disabled]=\"config()().create?.disabled?.()\" \r\n class=\"newButtonIcon\"\r\n (click)=\"onNewClick()\">\r\n <mat-icon>add_circle</mat-icon>\r\n </button>\r\n }\r\n\r\n @if(config()().hideColumnConfig?.() !== true) {\r\n <button matIconButton [matTooltip]=\"texts().table.editColumns\" class=\"editColumnsButtonIcon\" (click)=\"onEditColumns()\">\r\n <mat-icon>table_edit</mat-icon>\r\n </button>\r\n }\r\n\r\n @if(config()().showAdvancedFilters) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"texts().advancedFilters.label\"\r\n [matMenuTriggerFor]=\"advancedFiltersMenu\" \r\n #advancedFiltersMenuTrigger=\"matMenuTrigger\">\r\n\r\n <mat-icon>filter_alt</mat-icon>\r\n </button>\r\n\r\n <mat-menu #advancedFiltersMenu=\"matMenu\" xPosition=\"before\" yPosition=\"below\">\r\n <button mat-menu-item (click)=\"onNewAdvancedFiltersClick()\">\r\n <mat-icon>filter_alt</mat-icon>\r\n <span>{{ texts().advancedFilters.new }}</span>\r\n </button>\r\n\r\n @for (advancedFilter of advancedFilters(); track $index; let first = $first) {\r\n @if (first) {\r\n <mat-divider />\r\n }\r\n\r\n <div mat-menu-item (click)=\"onApplyTemplateClick(advancedFilter)\">\r\n <div class=\"templateContainer\"> \r\n <span>{{advancedFilter.name | ngxOnlyUpperFirstCharacter}}</span>\r\n\r\n <div class=\"buttonTemplateContainer\">\r\n <button\r\n matIconButton \r\n [matTooltip]=\"texts().advancedFilters.editTooltip(advancedFilter.name | ngxOnlyUpperFirstCharacter)\"\r\n (click)=\"onAdvancedFilterUpdate($event, advancedFilter, advancedFiltersMenuTrigger)\">\r\n <mat-icon>edit</mat-icon>\r\n </button>\r\n\r\n <button\r\n matIconButton \r\n [matTooltip]=\"texts().advancedFilters.deleteTooltip(advancedFilter.name | ngxOnlyUpperFirstCharacter)\"\r\n (click)=\"onAdvancedFilterDelete($event, advancedFiltersMenuTrigger, advancedFilter)\">\r\n <mat-icon>delete</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </mat-menu>\r\n }\r\n\r\n @if(selection().length > 0) {\r\n @if(getRowSelectionAction().length > 0) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"texts().table.selectionActions\"\r\n [matMenuTriggerFor]=\"selectedRecordsMenu\">\r\n <mat-icon>event_list</mat-icon>\r\n </button>\r\n\r\n <mat-menu #selectedRecordsMenu=\"matMenu\" xPosition=\"before\" yPosition=\"below\">\r\n <button mat-menu-item (click)=\"uncheckAllSelection()\">\r\n <mat-icon>deselect</mat-icon>\r\n <span>{{ texts().table.deselectAll }}</span>\r\n </button>\r\n\r\n @for (action of getRowSelectionAction(); track $index) {\r\n <button mat-menu-item (click)=\"onRowSelectionActionClick(action.id)\">\r\n <mat-icon>{{action.icon}}</mat-icon>\r\n <span>{{action.label(selection(), selection().length)}}</span>\r\n </button>\r\n }\r\n </mat-menu>\r\n } @else {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"texts().table.deselectAll\"\r\n (click)=\"uncheckAllSelection()\">\r\n <mat-icon>deselect</mat-icon>\r\n </button>\r\n }\r\n }\r\n @if(config()().hideExportData?.() !== true) {\r\n <button matIconButton [matTooltip]=\"texts().table.export\" [matMenuTriggerFor]=\"exportMenu\">\r\n <mat-icon>download</mat-icon>\r\n </button>\r\n <mat-menu #exportMenu=\"matMenu\" xPosition=\"before\" yPosition=\"below\">\r\n <button mat-menu-item (click)=\"exportToCsvCurrentPage()\">\r\n <mat-icon>csv</mat-icon>\r\n <span>{{ texts().table.exportExcel }}</span>\r\n </button>\r\n\r\n <button mat-menu-item (click)=\"exportToPdfCurrentPage()\">\r\n <mat-icon>picture_as_pdf</mat-icon>\r\n <span>{{ texts().table.exportPdf }}</span>\r\n </button>\r\n </mat-menu>\r\n }\r\n @if(config()().hideFullScreen?.() !== true) {\r\n <button matIconButton [matTooltip]=\"isFullScreen() ? texts().table.exitFullscreen : texts().table.enterFullscreen\" (click)=\"onToggleFullScreen()\">\r\n <mat-icon>{{isFullScreen() ? 'fullscreen_exit': 'fullscreen'}}</mat-icon>\r\n </button>\r\n }\r\n\r\n <ng-content select=\"[icon-buttons]\"></ng-content>\r\n </div>\r\n </div>\r\n\r\n <div class=\"filterContainer\">\r\n <div class=\"moreFiltersContainer\">\r\n <ng-content select=\"[more-filters]\"></ng-content>\r\n </div>\r\n\r\n @if(config()().showQueryFilter) {\r\n <mat-form-field subscriptSizing=\"dynamic\">\r\n <mat-icon matPrefix>search</mat-icon>\r\n <input #queryElement matInput [placeholder]=\"config()().queryFilterPlaceholder ?? texts().common.search\" [value]=\"filters()().query ?? ''\" (input)=\"onQueryChange(queryElement)\">\r\n <button matIconButton matSuffix (click)=\"onQueryReset(queryElement)\" [style.visibility]=\"queryElement.value ? 'visible': 'hidden'\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </mat-form-field>\r\n }\r\n </div>\r\n\r\n <ng-content select=\"[extra-header-content]\"></ng-content>\r\n </div>\r\n\r\n @if(filters()().advancedFilterId) {\r\n <div class=\"advancedFiltersApplied\" (click)=\"onSelectedAdvancedFilterUpdate($event)\">\r\n <p [innerHTML]=\"getAdvancedFilterLabel()\"></p>\r\n <button matIconButton [matTooltip]=\"texts().advancedFilters.remove\" class=\"\" (click)=\"onQuitAdvancedFilter($event)\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n }\r\n\r\n <mat-progress-bar mode=\"indeterminate\" [style.visibility]=\"dataResource.isLoading() ? 'visible': 'hidden'\"/>\r\n\r\n <div class=\"tableOverflow\" [style.max-height]=\"config()().maxHeight && !isFullScreen() ? config()().maxHeight : null\">\r\n <table\r\n mat-table \r\n matSort\r\n [multiTemplateDataRows]=\"config()().expandableDetail\"\r\n [dataSource]=\"data()\" \r\n [matSortActive]=\"filters()().sortBy?.key ?? ''\" \r\n [matSortDirection]=\"filters()().sortBy?.direction ?? ''\"\r\n (matSortChange)=\"onSortChange($event)\">\r\n\r\n @if(config()().enableRowSelection) {\r\n @if(showFiltersRow()) {\r\n <ng-container [matColumnDef]=\"`${filterKeyPrefix}${nameOfRowSelectionColumn}`\" [sticky]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef class=\"celdaSelection\"></th>\r\n </ng-container>\r\n } \r\n\r\n <ng-container [matColumnDef]=\"nameOfRowSelectionColumn\" [sticky]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef>\r\n <mat-checkbox \r\n class=\"headerCheckbox\"\r\n (change)=\"$event ? toggleAllPageRowSelection() : null\"\r\n [checked]=\"selection().length > 0 && isAllPageRowSelected()\"\r\n [indeterminate]=\"selection().length > 0 && !isAllPageRowSelected()\">\r\n </mat-checkbox>\r\n </th>\r\n <td mat-cell *matCellDef=\"let row\" (click)=\"$event.stopPropagation()\" class=\"celdaSelection\">\r\n @if(!config()().showRowSelection || config()().showRowSelection?.(row)) {\r\n <mat-checkbox\r\n (change)=\"$event ? toggleRowSelection(row) : null\"\r\n [checked]=\"isRowSelected(row)\">\r\n </mat-checkbox>\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n\r\n @if(showTotalGeneralFooter()) {\r\n <ng-container [matColumnDef]=\"`${generalFooterKeyPrefix}${nameOfRowSelectionColumn}`\" [sticky]=\"isDesktop()\">\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @for (column of config()().columns; track $index) {\r\n <ng-container \r\n [matColumnDef]=\"getKeyAsString(column.key)\" \r\n [sticky]=\"stickyColumnKey() == column.key && isDesktop()\">\r\n\r\n <th mat-header-cell *matHeaderCellDef mat-sort-header [disabled]=\"!column.isSortable\" class=\"columnLabel\">\r\n <p class=\"headerTitle\">\r\n @if(stickyColumnKey() == column.key && isDesktop()) {\r\n <mat-icon>keep</mat-icon>\r\n }\r\n {{ column.label }}\r\n </p>\r\n </th>\r\n\r\n <td \r\n mat-cell \r\n *matCellDef=\"let row\" \r\n [class.columnSticky]=\"stickyColumnKey() == column.key && isDesktop()\"\r\n [style]=\"column.style\"\r\n class=\"celdaDatos\">\r\n\r\n @if(column.component) {\r\n <ng-container \r\n ngxDynamicCellHost\r\n [component]=\"column.component\"\r\n [row]=\"row\"\r\n [key]=\"column.key\" />\r\n } @else if(column.templateRef) {\r\n <ng-container \r\n *ngTemplateOutlet=\"column.templateRef(); \r\n context: { $implicit: row }\" />\r\n } @else if(column.valueGetter) {\r\n {{ column.valueGetter(row) }}\r\n } @else {\r\n {{ applyColumnPipes(row[column.key], column.pipes) ?? '-' }}\r\n }\r\n </td>\r\n \r\n <td \r\n mat-footer-cell \r\n *matFooterCellDef \r\n [class.columnSticky]=\"stickyColumnKey() == column.key && isDesktop()\"\r\n [style]=\"column.footerStyle\">\r\n\r\n @if(column.showTotalPerPage) {\r\n @if(column.pipes) {\r\n {{ applyColumnPipes(getTotalOfColum(column.key), column.pipes) }}\r\n } @else if(column.totalFooterFormatter) {\r\n {{ column.totalFooterFormatter(getTotalOfColum(column.key)) }}\r\n } @else {\r\n {{ getTotalOfColum(column.key) }}\r\n }\r\n }\r\n </td>\r\n </ng-container>\r\n }\r\n\r\n @if(showTotalGeneralFooter()) {\r\n @for (column of config()().columns; track $index) {\r\n <ng-container \r\n [matColumnDef]=\"`${generalFooterKeyPrefix}${getKeyAsString(column.key)}`\"\r\n [sticky]=\"stickyColumnKey() == column.key && isDesktop()\">\r\n\r\n <td mat-footer-cell *matFooterCellDef [style]=\"column.footerStyle\">\r\n @if(column.showTotalGeneral && column.getTotalGeneral) {\r\n @if(column.pipes) {\r\n {{ applyColumnPipes(column.getTotalGeneral(), column.pipes) }}\r\n } @else if(column.totalFooterFormatter) {\r\n {{ column.totalFooterFormatter(column.getTotalGeneral()) }}\r\n } @else {\r\n {{ column.getTotalGeneral() }}\r\n }\r\n }\r\n </td>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @if(showFiltersRow()) {\r\n @for (column of config()().columns; track $index) {\r\n <ng-container \r\n [matColumnDef]=\"`${filterKeyPrefix}${getKeyAsString(column.key)}`\" \r\n [sticky]=\"stickyColumnKey() == column.key && isDesktop()\">\r\n\r\n <th mat-header-cell *matHeaderCellDef>\r\n @if (column.filterType == 'text' || column.filterType == 'number') {\r\n <mat-form-field subscriptSizing=\"dynamic\" class=\"inputQueryColumn\">\r\n <input [type]=\"column.filterType\" matInput [placeholder]=\"column.label\" [value]=\"getValueOfColumnFilter(column.key) ?? ''\" (input)=\"onTextFilterColumnChange(column, $event)\">\r\n <mat-icon matSuffix>{{ column.filterType == 'text' ? 'search' : 'numbers'}}</mat-icon>\r\n </mat-form-field>\r\n }\r\n\r\n @if (column.filterType == 'option' || column.filterType == 'option-multiple') {\r\n @if(column.endpointForPaginatedFilterOptions) {\r\n <ngx-paginated-searchable-select\r\n class=\"selectColumn\"\r\n [selected]=\"getPaginatedSearchableSelectValueOfColumnFilter(column.key)\"\r\n [endpoint]=\"column.endpointForPaginatedFilterOptions\"\r\n [filters]=\"column.filtersForEndpointPaginatedFilterOptions ?? defaultFiltersForPaginatedFilterOptions\"\r\n [multiple]=\"column.filterType == 'option-multiple'\"\r\n subscriptSizing=\"dynamic\"\r\n [selectPlaceholder]=\"column.label\"\r\n (optionChange)=\"onPaginatedOptionFilterColumnChange(column, $event)\"\r\n clearableOptionLabel=\"filtro\"\r\n />\r\n } @else {\r\n <ngx-searchable-select\r\n class=\"selectColumn\"\r\n [selected]=\"getSearchableSelectValueOfColumnFilter(column.key)\"\r\n [options]=\"column.filterOptions ?? []\"\r\n [multiple]=\"column.filterType == 'option-multiple'\"\r\n subscriptSizing=\"dynamic\"\r\n [selectPlaceholder]=\"column.label\"\r\n (optionChange)=\"onOptionFilterColumnChange(column, $event)\"\r\n clearableOptionLabel=\"filtro\"\r\n />\r\n }\r\n }\r\n \r\n @if(column.filterType == 'date') {\r\n <mat-form-field subscriptSizing=\"dynamic\" class=\"dateColumn\">\r\n <input \r\n matInput \r\n [matDatepicker]=\"picker\" \r\n [placeholder]=\"column.label\"\r\n [value]=\"getValueOfColumnFilter(column.key)\"\r\n (dateChange)=\"onDateFilterChange(column, $event.value)\">\r\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\r\n <mat-datepicker #picker></mat-datepicker>\r\n </mat-form-field>\r\n }\r\n\r\n @if(column.filterType == 'date-range') {\r\n <mat-form-field subscriptSizing=\"dynamic\" class=\"dateColumn\">\r\n <mat-date-range-input [rangePicker]=\"picker\" #dateRangeInput>\r\n <input \r\n matStartDate \r\n [placeholder]=\"texts().table.dateRangeStart\"\r\n [value]=\"getDateRangeValueOfColumnFilter(column.key, 'start')\"\r\n (dateChange)=\"onDateRangeFilterChange(column, dateRangeInput.value)\">\r\n <input \r\n matEndDate \r\n [placeholder]=\"texts().table.dateRangeEnd\"\r\n [value]=\"getDateRangeValueOfColumnFilter(column.key, 'end')\"\r\n (dateChange)=\"onDateRangeFilterChange(column, dateRangeInput.value)\">\r\n </mat-date-range-input>\r\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\r\n <mat-date-range-picker #picker></mat-date-range-picker>\r\n </mat-form-field>\r\n }\r\n </th>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @if(showActionsColumn()) {\r\n @if(showFiltersRow()) {\r\n <ng-container [matColumnDef]=\"`${filterKeyPrefix}${nameOfActionsColumn}`\" [stickyEnd]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef class=\"celdaAcciones\"></th>\r\n </ng-container>\r\n } \r\n\r\n <ng-container [matColumnDef]=\"nameOfActionsColumn\" [stickyEnd]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef>{{ texts().table.actions }}</th>\r\n <td mat-cell *matCellDef=\"let row\" (click)=\"$event.stopPropagation()\" class=\"celdaAcciones\">\r\n <div class=\"contenedorCeldaAcciones\">\r\n @if(config()().expandableDetail) {\r\n <button \r\n matIconButton\r\n (click)=\"expandableToggle(row)\">\r\n <mat-icon>{{ rowIsExpanded(row) ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}</mat-icon>\r\n </button>\r\n }\r\n\r\n @if(config()().update && !config()().clickOnRowForUpdate && (!config()().update?.show || config()().update?.show(row))) {\r\n <button \r\n matIconButton\r\n [matTooltip]=\"config()().update?.tooltip?.(row) ?? texts().table.edit\" \r\n [disabled]=\"config()().update?.disabled?.(row)\" \r\n class=\"editButtonIcon\"\r\n (click)=\"onUpdateClick(row, $event)\">\r\n <mat-icon>edit_square</mat-icon>\r\n </button>\r\n }\r\n \r\n @if(config()().delete && (!config()().delete?.show || config()().delete?.show(row))) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"config()().delete?.tooltip?.(row) ?? texts().table.delete\" \r\n [disabled]=\"config()().delete?.disabled?.(row)\" \r\n class=\"deleteButtonIcon\"\r\n (click)=\"onDeleteClick(row, $event)\">\r\n <mat-icon>delete</mat-icon>\r\n </button>\r\n }\r\n\r\n @for (rowAction of config()().rowActions; track $index) {\r\n @if(!rowAction.show || rowAction.show(row)) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"rowAction.tooltip(row)\" \r\n [disabled]=\"rowAction.disabled?.(row)\" \r\n [class]=\"rowAction.iconColor ? `rowActionIconColor${rowAction.iconColor}` : ''\"\r\n (click)=\"onRowActionClick(row, rowAction, $event)\">\r\n <mat-icon>{{rowAction.icon}}</mat-icon>\r\n </button>\r\n } \r\n }\r\n </div>\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n\r\n @if(showTotalGeneralFooter()) {\r\n <ng-container [matColumnDef]=\"`${generalFooterKeyPrefix}${nameOfActionsColumn}`\" [stickyEnd]=\"isDesktop()\">\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @if(config()().expandableDetail) {\r\n <ng-container [matColumnDef]=\"expandableColumnDef\">\r\n <td mat-cell *matCellDef=\"let row\" [attr.colspan]=\"keys().length\">\r\n <div \r\n class=\"detailWrapper\"\r\n [class.detailWrapperExpanded]=\"rowIsExpanded(row)\">\r\n <div class=\"columnDetail\">\r\n @if(config()().expandableDetailTemplateRef) {\r\n <ng-container \r\n *ngTemplateOutlet=\"config()().expandableDetailTemplateRef!(); \r\n context: { $implicit: row }\" />\r\n }\r\n </div>\r\n </div>\r\n </td>\r\n </ng-container>\r\n }\r\n \r\n <tr mat-header-row *matHeaderRowDef=\"keys(); sticky: true\" class=\"tableHeader\"></tr>\r\n \r\n @if(showFiltersRow()) {\r\n <tr mat-header-row *matHeaderRowDef=\"keysWithFilter(); sticky: true\" class=\"filtersByColumn\"></tr>\r\n }\r\n \r\n <tr mat-row *matRowDef=\"let row; columns: keys();\" \r\n (click)=\"onRowClick(row)\" \r\n [class.rowClickEnable]=\"isRowEnabled(row)\"\r\n [class.expandableRow]=\"config()().expandableDetail\">\r\n </tr>\r\n \r\n @if(config()().expandableDetail) {\r\n <tr mat-row *matRowDef=\"let row; columns: [expandableColumnDef]\" class=\"rowDetail\"></tr>\r\n }\r\n\r\n <tr mat-footer-row \r\n *matFooterRowDef=\"showTotalPerPageFooter() ? keys() : []\" \r\n class=\"totalPerPageFooter\"\r\n [class.hideFooter]=\"!showTotalPerPageFooter()\">\r\n </tr>\r\n\r\n <tr mat-footer-row \r\n *matFooterRowDef=\"showTotalGeneralFooter() ? keysWithGeneralFooter() : []\" \r\n class=\"totalFooter\"\r\n [class.hideFooter]=\"!showTotalGeneralFooter()\">\r\n </tr>\r\n\r\n <tr class=\"mat-row\" *matNoDataRow>\r\n <td class=\"noData\" [colSpan]=\"keys().length\">{{ dataResource.isLoading() ? texts().common.loading : texts().common.noData }}</td>\r\n </tr>\r\n </table>\r\n </div>\r\n\r\n <div class=\"paginatorContainer\">\r\n <div class=\"footerLegend\">\r\n @if(showTotalPerPageFooter()) {\r\n <div class=\"legendItem\">\r\n <div class=\"legendSquare\"></div>\r\n <p>{{ texts().table.totalPerPage }}</p> \r\n </div>\r\n }\r\n\r\n @if(showTotalGeneralFooter()) {\r\n <div class=\"legendItem\">\r\n <div class=\"legendSquare totalGeneral\"></div>\r\n <p>{{ texts().table.totalGeneral }}</p>\r\n </div>\r\n }\r\n </div>\r\n <mat-paginator [length]=\"total()\" [pageSize]=\"filters()().pageSize\" [pageIndex]=\"filters()().pageNumber - 1\" (page)=\"onPageChange($event)\"/>\r\n </div>\r\n\r\n <ng-content select=\"[end-container]\"></ng-content>\r\n </div>\r\n</ng-template>", styles: [".tableContainer{display:flex;flex-direction:column;padding:14px;gap:10px;--mat-table-background-color: transparent;--mat-table-header-headline-color: var(--mat-sys-on-primary)}.inFullScreenMode{height:calc(100vh - 28px);width:calc(100vw - 28px);max-width:calc(100% - 28px);background:var(--mat-sys-surface)}.title{font:var(--mat-sys-title-large);color:var(--mat-sys-on-surface);margin:0;position:relative}.headerContainer{display:flex;justify-content:space-between;gap:10px;flex-direction:column}.titleAndButtonContainer{display:flex;justify-content:space-between;align-items:center;gap:20px}.buttonContainer{display:flex;gap:10px;align-items:center}.filterContainer{display:flex;flex-direction:row;align-items:center;gap:20px;justify-content:space-between}.moreFiltersContainer{display:flex;gap:20px}.editButtonIcon{--mat-icon-button-icon-color: var(--warning)}.deleteButtonIcon{--mat-icon-button-icon-color: var(--mat-sys-error)}.rowActionIconColorYellow{--mat-icon-button-icon-color: rgb(211, 211, 7)}.rowActionIconColorOrange{--mat-icon-button-icon-color: orange}.rowActionIconColorPink{--mat-icon-button-icon-color: pink}.rowActionIconColorPurple{--mat-icon-button-icon-color: purple}.rowActionIconColorGreen{--mat-icon-button-icon-color: var(--success)}.rowActionIconColorBlue{--mat-icon-button-icon-color: var(--information)}.rowActionIconColorBrown{--mat-icon-button-icon-color: brown}.rowActionIconColorSky{--mat-icon-button-icon-color: rgb(0, 247, 255)}.noData{padding:24px}.tableOverflow{overflow:auto;border-radius:10px}.columnLabel{text-wrap:nowrap}.headerTitle{display:flex;align-items:center;gap:4px}.headerTitle mat-icon{font-size:12px;width:12px;height:12px}.tableHeader{background-color:var(--mat-sys-primary)!important}.filtersByColumn{background-color:var(--mat-sys-surface)!important}.filtersByColumn th{padding:0}.celdaDatos{background-color:var(--mat-sys-surface)!important;transition:background-color .1s}.celdaAcciones,.celdaSelection{cursor:default!important;background-color:var(--mat-sys-surface)!important;transition:background-color .1s}.columnSticky{background-color:var(--mat-sys-surface)!important;transition:background-color .1s}.contenedorCeldaAcciones{display:flex;align-items:center;cursor:default!important}.rowClickEnable{cursor:pointer;transition:background-color .1s}.rowClickEnable:hover,.rowClickEnable:hover>.celdaAcciones,.rowClickEnable:hover>.celdaSelection,.rowClickEnable:hover>.celdaDatos,.rowClickEnable:hover>.columnSticky{background-color:var(--mat-sys-surface-container)!important}.inputQueryColumn,.selectColumn,.dateColumn{--mat-form-field-outlined-focus-outline-color: transparent;--mat-form-field-outlined-outline-color: transparent;--mat-form-field-outlined-hover-outline-color: transparent}.templateContainer{display:flex;align-items:center;justify-content:space-between;gap:60px}.buttonTemplateContainer{display:flex;flex-wrap:nowrap}.advancedFiltersApplied{display:flex;flex-direction:row;justify-content:space-between;gap:20px;border-radius:10px;background-color:var(--warning);color:var(--on-warning);align-items:center;margin-top:10px;padding:5px 5px 5px 15px;cursor:pointer;transition:background-color .3s}.advancedFiltersApplied:hover:not(:has(button:hover)){background-color:color-mix(in srgb,var(--warning) 80%,transparent)}.advancedFiltersApplied p{margin:0}.rowDetail{height:0}.expandableRow td{border-bottom-width:0}.detailWrapper{overflow:hidden;display:grid;grid-template-rows:0fr;grid-template-columns:100%;transition:grid-template-rows 225ms cubic-bezier(.4,0,.2,1)}.detailWrapperExpanded{grid-template-rows:1fr}.columnDetail{display:flex;flex-direction:column;min-height:0}.totalPerPageFooter{font-weight:700}.totalFooter{font-weight:700;background-color:var(--mat-sys-surface-container-highest);color:var(--mat-sys-on-surface)}.hideFooter{display:none}.paginatorContainer{display:flex;flex-direction:row;justify-content:space-between;align-items:center;gap:20px;margin-top:10px}.footerLegend{display:flex;flex-direction:row;gap:30px}.footerLegend p{margin:0;font:var(--mat-sys-label-medium)}.legendItem{display:flex;flex-direction:row;align-items:center;gap:6px}.legendSquare{width:24px;height:14px;border-radius:4px;border:2px solid var(--mat-sys-on-surface)}.totalGeneral{background-color:var(--mat-sys-surface-container-highest)}.headerCheckbox{--mat-checkbox-selected-checkmark-color: var(--mat-sys-primary);--mat-checkbox-selected-focus-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-focus-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-selected-hover-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-hover-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-selected-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-pressed-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-pressed-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-focus-icon-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-focus-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-hover-icon-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-hover-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-icon-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-pressed-state-layer-color: var(--mat-sys-on-primary)}@media (max-width: 1200px){.filterContainer{flex-direction:column;align-items:normal}.moreFiltersContainer{flex-direction:column}}@media (max-width: 900px){.footerLegend{flex-direction:column;gap:6px}}@media (max-width: 700px){.paginatorContainer{flex-direction:column;align-items:flex-end}}@media (max-width: 600px){.titleAndButtonContainer{flex-direction:column;align-items:normal}}\n"], dependencies: [{ kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i1$1.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i1$1.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1$1.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i1$1.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1$1.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1$1.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i1$1.MatFooterCellDef, selector: "[matFooterCellDef]" }, { kind: "directive", type: i1$1.MatFooterRowDef, selector: "[matFooterRowDef]", inputs: ["matFooterRowDef", "matFooterRowDefSticky"] }, { kind: "directive", type: i1$1.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1$1.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: i1$1.MatFooterCell, selector: "mat-footer-cell, td[mat-footer-cell]" }, { kind: "component", type: i1$1.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i1$1.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i1$1.MatFooterRow, selector: "mat-footer-row, tr[mat-footer-row]", exportAs: ["matFooterRow"] }, { kind: "directive", type: i1$1.MatNoDataRow, selector: "ng-template[matNoDataRow]" }, { kind: "ngmodule", type: MatSortModule }, { kind: "directive", type: i2$4.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i2$4.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i3$3.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatProgressBarModule }, { kind: "component", type: i6.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$3.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i2$3.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i10.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i10.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i10.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "component", type: i10.MatDateRangeInput, selector: "mat-date-range-input", inputs: ["rangePicker", "required", "dateFilter", "min", "max", "disabled", "separator", "comparisonStart", "comparisonEnd"], exportAs: ["matDateRangeInput"] }, { kind: "directive", type: i10.MatStartDate, selector: "input[matStartDate]", outputs: ["dateChange", "dateInput"] }, { kind: "directive", type: i10.MatEndDate, selector: "input[matEndDate]", outputs: ["dateChange", "dateInput"] }, { kind: "component", type: i10.MatDateRangePicker, selector: "mat-date-range-picker", exportAs: ["matDateRangePicker"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i11.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: DynamicCellHostDirective, selector: "[ngxDynamicCellHost]", inputs: ["component", "row", "key"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i12.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i12.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i12.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i13.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i14.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: PaginatedSearchableSelectComponent, selector: "ngx-paginated-searchable-select", inputs: ["control", "endpoint", "filters", "optionLabel", "compareWith", "multiple", "searchInputPlaceholder", "selectLabel", "selectPlaceholder", "clearableOptionLabel", "subscriptSizing", "clearable", "error", "selected", "disabled"], outputs: ["optionChange"] }, { kind: "component", type: SearchableSelectComponent, selector: "ngx-searchable-select", inputs: ["control", "options", "optionLabel", "optionValue", "multiple", "searchInputPlaceholder", "selectLabel", "selectPlaceholder", "clearableOptionLabel", "subscriptSizing", "clearable", "error", "selected", "disabled"], outputs: ["optionChange"] }, { kind: "pipe", type: OnlyUpperFirstCharacterPipe, name: "ngxOnlyUpperFirstCharacter" }] });
2585
2960
  }
2586
2961
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxPaginatedTable, decorators: [{
2587
2962
  type: Component,
@@ -2605,7 +2980,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
2605
2980
  MatCheckboxModule,
2606
2981
  PaginatedSearchableSelectComponent,
2607
2982
  SearchableSelectComponent
2608
- ], host: { class: 'contenedorDefecto' }, template: "@if(!isFullScreen()) {\r\n <ng-container *ngTemplateOutlet=\"tableContentTemplate()\"></ng-container>\r\n}\r\n\r\n<ng-template #tableContent>\r\n <div class=\"tableContainer\" [class.inFullScreenMode]=\"isFullScreen()\">\r\n <div class=\"headerContainer\">\r\n <div class=\"titleAndButtonContainer\">\r\n <p class=\"title\">{{ config()().title() }}</p>\r\n <div class=\"buttonContainer\">\r\n @if(config()().create && (!config()().create?.show || config()().create?.show())) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"config()().create?.tooltip?.() ?? intl.createButtonLabel\" \r\n [disabled]=\"config()().create?.disabled?.()\" \r\n class=\"newButtonIcon\"\r\n (click)=\"onNewClick()\">\r\n <mat-icon>add_circle</mat-icon>\r\n </button>\r\n }\r\n\r\n @if(config()().hideColumnConfig?.() !== true) {\r\n <button matIconButton [matTooltip]=\"intl.editColumnsTooltip\" class=\"editColumnsButtonIcon\" (click)=\"onEditColumns()\">\r\n <mat-icon>table_edit</mat-icon>\r\n </button>\r\n }\r\n\r\n @if(config()().showAdvancedFilters) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"intl.advancedFiltersLabel\"\r\n [matMenuTriggerFor]=\"advancedFiltersMenu\" \r\n #advancedFiltersMenuTrigger=\"matMenuTrigger\">\r\n\r\n <mat-icon>filter_alt</mat-icon>\r\n </button>\r\n\r\n <mat-menu #advancedFiltersMenu=\"matMenu\" xPosition=\"before\" yPosition=\"below\">\r\n <button mat-menu-item (click)=\"onNewAdvancedFiltersClick()\">\r\n <mat-icon>filter_alt</mat-icon>\r\n <span>{{ intl.newAdvancedFilterLabel }}</span>\r\n </button>\r\n\r\n @for (advancedFilter of advancedFilters(); track $index; let first = $first) {\r\n @if (first) {\r\n <mat-divider />\r\n }\r\n\r\n <div mat-menu-item (click)=\"onApplyTemplateClick(advancedFilter)\">\r\n <div class=\"templateContainer\"> \r\n <span>{{advancedFilter.name | ngxOnlyUpperFirstCharacter}}</span>\r\n\r\n <div class=\"buttonTemplateContainer\">\r\n <button\r\n matIconButton \r\n [matTooltip]=\"intl.getEditAdvancedFilterTooltip(advancedFilter.name | ngxOnlyUpperFirstCharacter)\"\r\n (click)=\"onAdvancedFilterUpdate($event, advancedFilter, advancedFiltersMenuTrigger)\">\r\n <mat-icon>edit</mat-icon>\r\n </button>\r\n\r\n <button\r\n matIconButton \r\n [matTooltip]=\"intl.getDeleteAdvancedFilterTooltip(advancedFilter.name | ngxOnlyUpperFirstCharacter)\"\r\n (click)=\"onAdvancedFilterDelete($event, advancedFiltersMenuTrigger, advancedFilter)\">\r\n <mat-icon>delete</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </mat-menu>\r\n }\r\n\r\n @if(selection().length > 0) {\r\n @if(getRowSelectionAction().length > 0) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"intl.selectionActionsTooltip\"\r\n [matMenuTriggerFor]=\"selectedRecordsMenu\">\r\n <mat-icon>event_list</mat-icon>\r\n </button>\r\n\r\n <mat-menu #selectedRecordsMenu=\"matMenu\" xPosition=\"before\" yPosition=\"below\">\r\n <button mat-menu-item (click)=\"uncheckAllSelection()\">\r\n <mat-icon>deselect</mat-icon>\r\n <span>{{ intl.deselectAllLabel }}</span>\r\n </button>\r\n\r\n @for (action of getRowSelectionAction(); track $index) {\r\n <button mat-menu-item (click)=\"onRowSelectionActionClick(action.id)\">\r\n <mat-icon>{{action.icon}}</mat-icon>\r\n <span>{{action.label(selection(), selection().length)}}</span>\r\n </button>\r\n }\r\n </mat-menu>\r\n } @else {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"intl.deselectAllLabel\"\r\n (click)=\"uncheckAllSelection()\">\r\n <mat-icon>deselect</mat-icon>\r\n </button>\r\n }\r\n }\r\n @if(config()().hideExportData?.() !== true) {\r\n <button matIconButton [matTooltip]=\"intl.exportTooltip\" [matMenuTriggerFor]=\"exportMenu\">\r\n <mat-icon>download</mat-icon>\r\n </button>\r\n <mat-menu #exportMenu=\"matMenu\" xPosition=\"before\" yPosition=\"below\">\r\n <button mat-menu-item (click)=\"exportToCsvCurrentPage()\">\r\n <mat-icon>csv</mat-icon>\r\n <span>{{ intl.exportToExcelLabel }}</span>\r\n </button>\r\n\r\n <button mat-menu-item (click)=\"exportToPdfCurrentPage()\">\r\n <mat-icon>picture_as_pdf</mat-icon>\r\n <span>{{ intl.exportToPdfLabel }}</span>\r\n </button>\r\n </mat-menu>\r\n }\r\n @if(config()().hideFullScreen?.() !== true) {\r\n <button matIconButton [matTooltip]=\"isFullScreen() ? intl.exitFullscreenTooltip : intl.enterFullscreenTooltip\" (click)=\"onToggleFullScreen()\">\r\n <mat-icon>{{isFullScreen() ? 'fullscreen_exit': 'fullscreen'}}</mat-icon>\r\n </button>\r\n }\r\n\r\n <ng-content select=\"[icon-buttons]\"></ng-content>\r\n </div>\r\n </div>\r\n\r\n <div class=\"filterContainer\">\r\n <div class=\"moreFiltersContainer\">\r\n <ng-content select=\"[more-filters]\"></ng-content>\r\n </div>\r\n\r\n @if(config()().showQueryFilter) {\r\n <mat-form-field subscriptSizing=\"dynamic\">\r\n <mat-icon matPrefix>search</mat-icon>\r\n <input #queryElement matInput [placeholder]=\"config()().queryFilterPlaceholder ?? intl.searchPlaceholder\" [value]=\"filters()().query ?? ''\" (input)=\"onQueryChange(queryElement)\">\r\n <button matIconButton matSuffix (click)=\"onQueryReset(queryElement)\" [style.visibility]=\"queryElement.value ? 'visible': 'hidden'\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </mat-form-field>\r\n }\r\n </div>\r\n\r\n <ng-content select=\"[extra-header-content]\"></ng-content>\r\n </div>\r\n\r\n @if(filters()().advancedFilterId) {\r\n <div class=\"advancedFiltersApplied\" (click)=\"onSelectedAdvancedFilterUpdate($event)\">\r\n <p [innerHTML]=\"getAdvancedFilterLabel()\"></p>\r\n <button matIconButton [matTooltip]=\"intl.removeAdvancedFilterTooltip\" class=\"\" (click)=\"onQuitAdvancedFilter($event)\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n }\r\n\r\n <mat-progress-bar mode=\"indeterminate\" [style.visibility]=\"dataResource.isLoading() ? 'visible': 'hidden'\"/>\r\n\r\n <div class=\"tableOverflow\" [style.max-height]=\"config()().maxHeight && !isFullScreen() ? config()().maxHeight : null\">\r\n <table\r\n mat-table \r\n matSort\r\n [multiTemplateDataRows]=\"config()().expandableDetail\"\r\n [dataSource]=\"data()\" \r\n [matSortActive]=\"filters()().sortBy?.key ?? ''\" \r\n [matSortDirection]=\"filters()().sortBy?.direction ?? ''\"\r\n (matSortChange)=\"onSortChange($event)\">\r\n\r\n @if(config()().enableRowSelection) {\r\n @if(showFiltersRow()) {\r\n <ng-container [matColumnDef]=\"`${filterKeyPrefix}${nameOfRowSelectionColumn}`\" [sticky]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef class=\"celdaSelection\"></th>\r\n </ng-container>\r\n } \r\n\r\n <ng-container [matColumnDef]=\"nameOfRowSelectionColumn\" [sticky]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef>\r\n <mat-checkbox \r\n class=\"headerCheckbox\"\r\n (change)=\"$event ? toggleAllPageRowSelection() : null\"\r\n [checked]=\"selection().length > 0 && isAllPageRowSelected()\"\r\n [indeterminate]=\"selection().length > 0 && !isAllPageRowSelected()\">\r\n </mat-checkbox>\r\n </th>\r\n <td mat-cell *matCellDef=\"let row\" (click)=\"$event.stopPropagation()\" class=\"celdaSelection\">\r\n @if(!config()().showRowSelection || config()().showRowSelection?.(row)) {\r\n <mat-checkbox\r\n (change)=\"$event ? toggleRowSelection(row) : null\"\r\n [checked]=\"isRowSelected(row)\">\r\n </mat-checkbox>\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n\r\n @if(showTotalGeneralFooter()) {\r\n <ng-container [matColumnDef]=\"`${generalFooterKeyPrefix}${nameOfRowSelectionColumn}`\" [sticky]=\"isDesktop()\">\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @for (column of config()().columns; track $index) {\r\n <ng-container \r\n [matColumnDef]=\"getKeyAsString(column.key)\" \r\n [sticky]=\"stickyColumnKey() == column.key && isDesktop()\">\r\n\r\n <th mat-header-cell *matHeaderCellDef mat-sort-header [disabled]=\"!column.isSortable\" class=\"columnLabel\">\r\n <p class=\"headerTitle\">\r\n @if(stickyColumnKey() == column.key && isDesktop()) {\r\n <mat-icon>keep</mat-icon>\r\n }\r\n {{ column.label }}\r\n </p>\r\n </th>\r\n\r\n <td \r\n mat-cell \r\n *matCellDef=\"let row\" \r\n [class.columnSticky]=\"stickyColumnKey() == column.key && isDesktop()\"\r\n [style]=\"column.style\"\r\n class=\"celdaDatos\">\r\n\r\n @if(column.component) {\r\n <ng-container \r\n ngxDynamicCellHost\r\n [component]=\"column.component\"\r\n [row]=\"row\"\r\n [key]=\"column.key\" />\r\n } @else if(column.templateRef) {\r\n <ng-container \r\n *ngTemplateOutlet=\"column.templateRef(); \r\n context: { $implicit: row }\" />\r\n } @else if(column.valueGetter) {\r\n {{ column.valueGetter(row) }}\r\n } @else {\r\n {{ applyColumnPipes(row[column.key], column.pipes) ?? '-' }}\r\n }\r\n </td>\r\n \r\n <td \r\n mat-footer-cell \r\n *matFooterCellDef \r\n [class.columnSticky]=\"stickyColumnKey() == column.key && isDesktop()\"\r\n [style]=\"column.footerStyle\">\r\n\r\n @if(column.showTotalPerPage) {\r\n @if(column.pipes) {\r\n {{ applyColumnPipes(getTotalOfColum(column.key), column.pipes) }}\r\n } @else if(column.totalFooterFormatter) {\r\n {{ column.totalFooterFormatter(getTotalOfColum(column.key)) }}\r\n } @else {\r\n {{ getTotalOfColum(column.key) }}\r\n }\r\n }\r\n </td>\r\n </ng-container>\r\n }\r\n\r\n @if(showTotalGeneralFooter()) {\r\n @for (column of config()().columns; track $index) {\r\n <ng-container \r\n [matColumnDef]=\"`${generalFooterKeyPrefix}${getKeyAsString(column.key)}`\"\r\n [sticky]=\"stickyColumnKey() == column.key && isDesktop()\">\r\n\r\n <td mat-footer-cell *matFooterCellDef [style]=\"column.footerStyle\">\r\n @if(column.showTotalGeneral && column.getTotalGeneral) {\r\n @if(column.pipes) {\r\n {{ applyColumnPipes(column.getTotalGeneral(), column.pipes) }}\r\n } @else if(column.totalFooterFormatter) {\r\n {{ column.totalFooterFormatter(column.getTotalGeneral()) }}\r\n } @else {\r\n {{ column.getTotalGeneral() }}\r\n }\r\n }\r\n </td>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @if(showFiltersRow()) {\r\n @for (column of config()().columns; track $index) {\r\n <ng-container \r\n [matColumnDef]=\"`${filterKeyPrefix}${getKeyAsString(column.key)}`\" \r\n [sticky]=\"stickyColumnKey() == column.key && isDesktop()\">\r\n\r\n <th mat-header-cell *matHeaderCellDef>\r\n @if (column.filterType == 'text' || column.filterType == 'number') {\r\n <mat-form-field subscriptSizing=\"dynamic\" class=\"inputQueryColumn\">\r\n <input [type]=\"column.filterType\" matInput [placeholder]=\"column.label\" [value]=\"getValueOfColumnFilter(column.key) ?? ''\" (input)=\"onTextFilterColumnChange(column, $event)\">\r\n <mat-icon matSuffix>{{ column.filterType == 'text' ? 'search' : 'numbers'}}</mat-icon>\r\n </mat-form-field>\r\n }\r\n\r\n @if (column.filterType == 'option' || column.filterType == 'option-multiple') {\r\n @if(column.endpointForPaginatedFilterOptions) {\r\n <ngx-paginated-searchable-select\r\n class=\"selectColumn\"\r\n [selected]=\"getPaginatedSearchableSelectValueOfColumnFilter(column.key)\"\r\n [endpoint]=\"column.endpointForPaginatedFilterOptions\"\r\n [filters]=\"column.filtersForEndpointPaginatedFilterOptions ?? defaultFiltersForPaginatedFilterOptions\"\r\n [multiple]=\"column.filterType == 'option-multiple'\"\r\n subscriptSizing=\"dynamic\"\r\n [selectPlaceholder]=\"column.label\"\r\n (optionChange)=\"onPaginatedOptionFilterColumnChange(column, $event)\"\r\n clearableOptionLabel=\"filtro\"\r\n />\r\n } @else {\r\n <ngx-searchable-select\r\n class=\"selectColumn\"\r\n [selected]=\"getSearchableSelectValueOfColumnFilter(column.key)\"\r\n [options]=\"column.filterOptions ?? []\"\r\n [multiple]=\"column.filterType == 'option-multiple'\"\r\n subscriptSizing=\"dynamic\"\r\n [selectPlaceholder]=\"column.label\"\r\n (optionChange)=\"onOptionFilterColumnChange(column, $event)\"\r\n clearableOptionLabel=\"filtro\"\r\n />\r\n }\r\n }\r\n \r\n @if(column.filterType == 'date') {\r\n <mat-form-field subscriptSizing=\"dynamic\" class=\"dateColumn\">\r\n <input \r\n matInput \r\n [matDatepicker]=\"picker\" \r\n [placeholder]=\"column.label\"\r\n [value]=\"getValueOfColumnFilter(column.key)\"\r\n (dateChange)=\"onDateFilterChange(column, $event.value)\">\r\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\r\n <mat-datepicker #picker></mat-datepicker>\r\n </mat-form-field>\r\n }\r\n\r\n @if(column.filterType == 'date-range') {\r\n <mat-form-field subscriptSizing=\"dynamic\" class=\"dateColumn\">\r\n <mat-date-range-input [rangePicker]=\"picker\" #dateRangeInput>\r\n <input \r\n matStartDate \r\n [placeholder]=\"intl.dateRangeStartPlaceholder\"\r\n [value]=\"getDateRangeValueOfColumnFilter(column.key, 'start')\"\r\n (dateChange)=\"onDateRangeFilterChange(column, dateRangeInput.value)\">\r\n <input \r\n matEndDate \r\n [placeholder]=\"intl.dateRangeEndPlaceholder\"\r\n [value]=\"getDateRangeValueOfColumnFilter(column.key, 'end')\"\r\n (dateChange)=\"onDateRangeFilterChange(column, dateRangeInput.value)\">\r\n </mat-date-range-input>\r\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\r\n <mat-date-range-picker #picker></mat-date-range-picker>\r\n </mat-form-field>\r\n }\r\n </th>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @if(showActionsColumn()) {\r\n @if(showFiltersRow()) {\r\n <ng-container [matColumnDef]=\"`${filterKeyPrefix}${nameOfActionsColumn}`\" [stickyEnd]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef class=\"celdaAcciones\"></th>\r\n </ng-container>\r\n } \r\n\r\n <ng-container [matColumnDef]=\"nameOfActionsColumn\" [stickyEnd]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef>{{ intl.actionsLabel }}</th>\r\n <td mat-cell *matCellDef=\"let row\" (click)=\"$event.stopPropagation()\" class=\"celdaAcciones\">\r\n <div class=\"contenedorCeldaAcciones\">\r\n @if(config()().expandableDetail) {\r\n <button \r\n matIconButton\r\n (click)=\"expandableToggle(row)\">\r\n <mat-icon>{{ rowIsExpanded(row) ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}</mat-icon>\r\n </button>\r\n }\r\n\r\n @if(config()().update && !config()().clickOnRowForUpdate && (!config()().update?.show || config()().update?.show(row))) {\r\n <button \r\n matIconButton\r\n [matTooltip]=\"config()().update?.tooltip?.(row) ?? intl.editTooltip\" \r\n [disabled]=\"config()().update?.disabled?.(row)\" \r\n class=\"editButtonIcon\"\r\n (click)=\"onUpdateClick(row, $event)\">\r\n <mat-icon>edit_square</mat-icon>\r\n </button>\r\n }\r\n \r\n @if(config()().delete && (!config()().delete?.show || config()().delete?.show(row))) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"config()().delete?.tooltip?.(row) ?? intl.deleteTooltip\" \r\n [disabled]=\"config()().delete?.disabled?.(row)\" \r\n class=\"deleteButtonIcon\"\r\n (click)=\"onDeleteClick(row, $event)\">\r\n <mat-icon>delete</mat-icon>\r\n </button>\r\n }\r\n\r\n @for (rowAction of config()().rowActions; track $index) {\r\n @if(!rowAction.show || rowAction.show(row)) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"rowAction.tooltip(row)\" \r\n [disabled]=\"rowAction.disabled?.(row)\" \r\n [class]=\"rowAction.iconColor ? `rowActionIconColor${rowAction.iconColor}` : ''\"\r\n (click)=\"onRowActionClick(row, rowAction, $event)\">\r\n <mat-icon>{{rowAction.icon}}</mat-icon>\r\n </button>\r\n } \r\n }\r\n </div>\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n\r\n @if(showTotalGeneralFooter()) {\r\n <ng-container [matColumnDef]=\"`${generalFooterKeyPrefix}${nameOfActionsColumn}`\" [stickyEnd]=\"isDesktop()\">\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @if(config()().expandableDetail) {\r\n <ng-container [matColumnDef]=\"expandableColumnDef\">\r\n <td mat-cell *matCellDef=\"let row\" [attr.colspan]=\"keys().length\">\r\n <div \r\n class=\"detailWrapper\"\r\n [class.detailWrapperExpanded]=\"rowIsExpanded(row)\">\r\n <div class=\"columnDetail\">\r\n @if(config()().expandableDetailTemplateRef) {\r\n <ng-container \r\n *ngTemplateOutlet=\"config()().expandableDetailTemplateRef!(); \r\n context: { $implicit: row }\" />\r\n }\r\n </div>\r\n </div>\r\n </td>\r\n </ng-container>\r\n }\r\n \r\n <tr mat-header-row *matHeaderRowDef=\"keys(); sticky: true\" class=\"tableHeader\"></tr>\r\n \r\n @if(showFiltersRow()) {\r\n <tr mat-header-row *matHeaderRowDef=\"keysWithFilter(); sticky: true\" class=\"filtersByColumn\"></tr>\r\n }\r\n \r\n <tr mat-row *matRowDef=\"let row; columns: keys();\" \r\n (click)=\"onRowClick(row)\" \r\n [class.rowClickEnable]=\"isRowEnabled(row)\"\r\n [class.expandableRow]=\"config()().expandableDetail\">\r\n </tr>\r\n \r\n @if(config()().expandableDetail) {\r\n <tr mat-row *matRowDef=\"let row; columns: [expandableColumnDef]\" class=\"rowDetail\"></tr>\r\n }\r\n\r\n <tr mat-footer-row \r\n *matFooterRowDef=\"showTotalPerPageFooter() ? keys() : []\" \r\n class=\"totalPerPageFooter\"\r\n [class.hideFooter]=\"!showTotalPerPageFooter()\">\r\n </tr>\r\n\r\n <tr mat-footer-row \r\n *matFooterRowDef=\"showTotalGeneralFooter() ? keysWithGeneralFooter() : []\" \r\n class=\"totalFooter\"\r\n [class.hideFooter]=\"!showTotalGeneralFooter()\">\r\n </tr>\r\n\r\n <tr class=\"mat-row\" *matNoDataRow>\r\n <td class=\"noData\" [colSpan]=\"keys().length\">{{ dataResource.isLoading() ? intl.loadingMessage : intl.noDataMessage }}</td>\r\n </tr>\r\n </table>\r\n </div>\r\n\r\n <div class=\"paginatorContainer\">\r\n <div class=\"footerLegend\">\r\n @if(showTotalPerPageFooter()) {\r\n <div class=\"legendItem\">\r\n <div class=\"legendSquare\"></div>\r\n <p>{{ intl.totalPerPageLabel }}</p> \r\n </div>\r\n }\r\n\r\n @if(showTotalGeneralFooter()) {\r\n <div class=\"legendItem\">\r\n <div class=\"legendSquare totalGeneral\"></div>\r\n <p>{{ intl.totalGeneralLabel }}</p>\r\n </div>\r\n }\r\n </div>\r\n <mat-paginator [length]=\"total()\" [pageSize]=\"filters()().pageSize\" [pageIndex]=\"filters()().pageNumber - 1\" (page)=\"onPageChange($event)\"/>\r\n </div>\r\n\r\n <ng-content select=\"[end-container]\"></ng-content>\r\n </div>\r\n</ng-template>", styles: [".tableContainer{display:flex;flex-direction:column;padding:14px;gap:10px;--mat-table-background-color: transparent;--mat-table-header-headline-color: var(--mat-sys-on-primary)}.inFullScreenMode{height:calc(100vh - 28px);width:calc(100vw - 28px);max-width:calc(100% - 28px);background:var(--mat-sys-surface)}.title{font:var(--mat-sys-title-large);color:var(--mat-sys-on-surface);margin:0;position:relative}.headerContainer{display:flex;justify-content:space-between;gap:10px;flex-direction:column}.titleAndButtonContainer{display:flex;justify-content:space-between;align-items:center;gap:20px}.buttonContainer{display:flex;gap:10px;align-items:center}.filterContainer{display:flex;flex-direction:row;align-items:center;gap:20px;justify-content:space-between}.moreFiltersContainer{display:flex;gap:20px}.editButtonIcon{--mat-icon-button-icon-color: var(--warning)}.deleteButtonIcon{--mat-icon-button-icon-color: var(--mat-sys-error)}.rowActionIconColorYellow{--mat-icon-button-icon-color: rgb(211, 211, 7)}.rowActionIconColorOrange{--mat-icon-button-icon-color: orange}.rowActionIconColorPink{--mat-icon-button-icon-color: pink}.rowActionIconColorPurple{--mat-icon-button-icon-color: purple}.rowActionIconColorGreen{--mat-icon-button-icon-color: var(--success)}.rowActionIconColorBlue{--mat-icon-button-icon-color: var(--information)}.rowActionIconColorBrown{--mat-icon-button-icon-color: brown}.rowActionIconColorSky{--mat-icon-button-icon-color: rgb(0, 247, 255)}.noData{padding:24px}.tableOverflow{overflow:auto;border-radius:10px}.columnLabel{text-wrap:nowrap}.headerTitle{display:flex;align-items:center;gap:4px}.headerTitle mat-icon{font-size:12px;width:12px;height:12px}.tableHeader{background-color:var(--mat-sys-primary)!important}.filtersByColumn{background-color:var(--mat-sys-surface)!important}.filtersByColumn th{padding:0}.celdaDatos{background-color:var(--mat-sys-surface)!important;transition:background-color .1s}.celdaAcciones,.celdaSelection{cursor:default!important;background-color:var(--mat-sys-surface)!important;transition:background-color .1s}.columnSticky{background-color:var(--mat-sys-surface)!important;transition:background-color .1s}.contenedorCeldaAcciones{display:flex;align-items:center;cursor:default!important}.rowClickEnable{cursor:pointer;transition:background-color .1s}.rowClickEnable:hover,.rowClickEnable:hover>.celdaAcciones,.rowClickEnable:hover>.celdaSelection,.rowClickEnable:hover>.celdaDatos,.rowClickEnable:hover>.columnSticky{background-color:var(--mat-sys-surface-container)!important}.inputQueryColumn,.selectColumn,.dateColumn{--mat-form-field-outlined-focus-outline-color: transparent;--mat-form-field-outlined-outline-color: transparent;--mat-form-field-outlined-hover-outline-color: transparent}.templateContainer{display:flex;align-items:center;justify-content:space-between;gap:60px}.buttonTemplateContainer{display:flex;flex-wrap:nowrap}.advancedFiltersApplied{display:flex;flex-direction:row;justify-content:space-between;gap:20px;border-radius:10px;background-color:var(--warning);color:var(--on-warning);align-items:center;margin-top:10px;padding:5px 5px 5px 15px;cursor:pointer;transition:background-color .3s}.advancedFiltersApplied:hover:not(:has(button:hover)){background-color:color-mix(in srgb,var(--warning) 80%,transparent)}.advancedFiltersApplied p{margin:0}.rowDetail{height:0}.expandableRow td{border-bottom-width:0}.detailWrapper{overflow:hidden;display:grid;grid-template-rows:0fr;grid-template-columns:100%;transition:grid-template-rows 225ms cubic-bezier(.4,0,.2,1)}.detailWrapperExpanded{grid-template-rows:1fr}.columnDetail{display:flex;flex-direction:column;min-height:0}.totalPerPageFooter{font-weight:700}.totalFooter{font-weight:700;background-color:var(--mat-sys-surface-container-highest);color:var(--mat-sys-on-surface)}.hideFooter{display:none}.paginatorContainer{display:flex;flex-direction:row;justify-content:space-between;align-items:center;gap:20px;margin-top:10px}.footerLegend{display:flex;flex-direction:row;gap:30px}.footerLegend p{margin:0;font:var(--mat-sys-label-medium)}.legendItem{display:flex;flex-direction:row;align-items:center;gap:6px}.legendSquare{width:24px;height:14px;border-radius:4px;border:2px solid var(--mat-sys-on-surface)}.totalGeneral{background-color:var(--mat-sys-surface-container-highest)}.headerCheckbox{--mat-checkbox-selected-checkmark-color: var(--mat-sys-primary);--mat-checkbox-selected-focus-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-focus-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-selected-hover-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-hover-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-selected-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-pressed-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-pressed-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-focus-icon-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-focus-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-hover-icon-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-hover-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-icon-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-pressed-state-layer-color: var(--mat-sys-on-primary)}@media (max-width: 1200px){.filterContainer{flex-direction:column;align-items:normal}.moreFiltersContainer{flex-direction:column}}@media (max-width: 900px){.footerLegend{flex-direction:column;gap:6px}}@media (max-width: 700px){.paginatorContainer{flex-direction:column;align-items:flex-end}}@media (max-width: 600px){.titleAndButtonContainer{flex-direction:column;align-items:normal}}\n"] }]
2983
+ ], host: { class: 'contenedorDefecto' }, template: "@if(!isFullScreen()) {\r\n <ng-container *ngTemplateOutlet=\"tableContentTemplate()\"></ng-container>\r\n}\r\n\r\n<ng-template #tableContent>\r\n <div class=\"tableContainer\" [class.inFullScreenMode]=\"isFullScreen()\">\r\n <div class=\"headerContainer\">\r\n <div class=\"titleAndButtonContainer\">\r\n <p class=\"title\">{{ config()().title() }}</p>\r\n <div class=\"buttonContainer\">\r\n @if(config()().create && (!config()().create?.show || config()().create?.show())) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"config()().create?.tooltip?.() ?? texts().table.create\" \r\n [disabled]=\"config()().create?.disabled?.()\" \r\n class=\"newButtonIcon\"\r\n (click)=\"onNewClick()\">\r\n <mat-icon>add_circle</mat-icon>\r\n </button>\r\n }\r\n\r\n @if(config()().hideColumnConfig?.() !== true) {\r\n <button matIconButton [matTooltip]=\"texts().table.editColumns\" class=\"editColumnsButtonIcon\" (click)=\"onEditColumns()\">\r\n <mat-icon>table_edit</mat-icon>\r\n </button>\r\n }\r\n\r\n @if(config()().showAdvancedFilters) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"texts().advancedFilters.label\"\r\n [matMenuTriggerFor]=\"advancedFiltersMenu\" \r\n #advancedFiltersMenuTrigger=\"matMenuTrigger\">\r\n\r\n <mat-icon>filter_alt</mat-icon>\r\n </button>\r\n\r\n <mat-menu #advancedFiltersMenu=\"matMenu\" xPosition=\"before\" yPosition=\"below\">\r\n <button mat-menu-item (click)=\"onNewAdvancedFiltersClick()\">\r\n <mat-icon>filter_alt</mat-icon>\r\n <span>{{ texts().advancedFilters.new }}</span>\r\n </button>\r\n\r\n @for (advancedFilter of advancedFilters(); track $index; let first = $first) {\r\n @if (first) {\r\n <mat-divider />\r\n }\r\n\r\n <div mat-menu-item (click)=\"onApplyTemplateClick(advancedFilter)\">\r\n <div class=\"templateContainer\"> \r\n <span>{{advancedFilter.name | ngxOnlyUpperFirstCharacter}}</span>\r\n\r\n <div class=\"buttonTemplateContainer\">\r\n <button\r\n matIconButton \r\n [matTooltip]=\"texts().advancedFilters.editTooltip(advancedFilter.name | ngxOnlyUpperFirstCharacter)\"\r\n (click)=\"onAdvancedFilterUpdate($event, advancedFilter, advancedFiltersMenuTrigger)\">\r\n <mat-icon>edit</mat-icon>\r\n </button>\r\n\r\n <button\r\n matIconButton \r\n [matTooltip]=\"texts().advancedFilters.deleteTooltip(advancedFilter.name | ngxOnlyUpperFirstCharacter)\"\r\n (click)=\"onAdvancedFilterDelete($event, advancedFiltersMenuTrigger, advancedFilter)\">\r\n <mat-icon>delete</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </mat-menu>\r\n }\r\n\r\n @if(selection().length > 0) {\r\n @if(getRowSelectionAction().length > 0) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"texts().table.selectionActions\"\r\n [matMenuTriggerFor]=\"selectedRecordsMenu\">\r\n <mat-icon>event_list</mat-icon>\r\n </button>\r\n\r\n <mat-menu #selectedRecordsMenu=\"matMenu\" xPosition=\"before\" yPosition=\"below\">\r\n <button mat-menu-item (click)=\"uncheckAllSelection()\">\r\n <mat-icon>deselect</mat-icon>\r\n <span>{{ texts().table.deselectAll }}</span>\r\n </button>\r\n\r\n @for (action of getRowSelectionAction(); track $index) {\r\n <button mat-menu-item (click)=\"onRowSelectionActionClick(action.id)\">\r\n <mat-icon>{{action.icon}}</mat-icon>\r\n <span>{{action.label(selection(), selection().length)}}</span>\r\n </button>\r\n }\r\n </mat-menu>\r\n } @else {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"texts().table.deselectAll\"\r\n (click)=\"uncheckAllSelection()\">\r\n <mat-icon>deselect</mat-icon>\r\n </button>\r\n }\r\n }\r\n @if(config()().hideExportData?.() !== true) {\r\n <button matIconButton [matTooltip]=\"texts().table.export\" [matMenuTriggerFor]=\"exportMenu\">\r\n <mat-icon>download</mat-icon>\r\n </button>\r\n <mat-menu #exportMenu=\"matMenu\" xPosition=\"before\" yPosition=\"below\">\r\n <button mat-menu-item (click)=\"exportToCsvCurrentPage()\">\r\n <mat-icon>csv</mat-icon>\r\n <span>{{ texts().table.exportExcel }}</span>\r\n </button>\r\n\r\n <button mat-menu-item (click)=\"exportToPdfCurrentPage()\">\r\n <mat-icon>picture_as_pdf</mat-icon>\r\n <span>{{ texts().table.exportPdf }}</span>\r\n </button>\r\n </mat-menu>\r\n }\r\n @if(config()().hideFullScreen?.() !== true) {\r\n <button matIconButton [matTooltip]=\"isFullScreen() ? texts().table.exitFullscreen : texts().table.enterFullscreen\" (click)=\"onToggleFullScreen()\">\r\n <mat-icon>{{isFullScreen() ? 'fullscreen_exit': 'fullscreen'}}</mat-icon>\r\n </button>\r\n }\r\n\r\n <ng-content select=\"[icon-buttons]\"></ng-content>\r\n </div>\r\n </div>\r\n\r\n <div class=\"filterContainer\">\r\n <div class=\"moreFiltersContainer\">\r\n <ng-content select=\"[more-filters]\"></ng-content>\r\n </div>\r\n\r\n @if(config()().showQueryFilter) {\r\n <mat-form-field subscriptSizing=\"dynamic\">\r\n <mat-icon matPrefix>search</mat-icon>\r\n <input #queryElement matInput [placeholder]=\"config()().queryFilterPlaceholder ?? texts().common.search\" [value]=\"filters()().query ?? ''\" (input)=\"onQueryChange(queryElement)\">\r\n <button matIconButton matSuffix (click)=\"onQueryReset(queryElement)\" [style.visibility]=\"queryElement.value ? 'visible': 'hidden'\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </mat-form-field>\r\n }\r\n </div>\r\n\r\n <ng-content select=\"[extra-header-content]\"></ng-content>\r\n </div>\r\n\r\n @if(filters()().advancedFilterId) {\r\n <div class=\"advancedFiltersApplied\" (click)=\"onSelectedAdvancedFilterUpdate($event)\">\r\n <p [innerHTML]=\"getAdvancedFilterLabel()\"></p>\r\n <button matIconButton [matTooltip]=\"texts().advancedFilters.remove\" class=\"\" (click)=\"onQuitAdvancedFilter($event)\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n }\r\n\r\n <mat-progress-bar mode=\"indeterminate\" [style.visibility]=\"dataResource.isLoading() ? 'visible': 'hidden'\"/>\r\n\r\n <div class=\"tableOverflow\" [style.max-height]=\"config()().maxHeight && !isFullScreen() ? config()().maxHeight : null\">\r\n <table\r\n mat-table \r\n matSort\r\n [multiTemplateDataRows]=\"config()().expandableDetail\"\r\n [dataSource]=\"data()\" \r\n [matSortActive]=\"filters()().sortBy?.key ?? ''\" \r\n [matSortDirection]=\"filters()().sortBy?.direction ?? ''\"\r\n (matSortChange)=\"onSortChange($event)\">\r\n\r\n @if(config()().enableRowSelection) {\r\n @if(showFiltersRow()) {\r\n <ng-container [matColumnDef]=\"`${filterKeyPrefix}${nameOfRowSelectionColumn}`\" [sticky]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef class=\"celdaSelection\"></th>\r\n </ng-container>\r\n } \r\n\r\n <ng-container [matColumnDef]=\"nameOfRowSelectionColumn\" [sticky]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef>\r\n <mat-checkbox \r\n class=\"headerCheckbox\"\r\n (change)=\"$event ? toggleAllPageRowSelection() : null\"\r\n [checked]=\"selection().length > 0 && isAllPageRowSelected()\"\r\n [indeterminate]=\"selection().length > 0 && !isAllPageRowSelected()\">\r\n </mat-checkbox>\r\n </th>\r\n <td mat-cell *matCellDef=\"let row\" (click)=\"$event.stopPropagation()\" class=\"celdaSelection\">\r\n @if(!config()().showRowSelection || config()().showRowSelection?.(row)) {\r\n <mat-checkbox\r\n (change)=\"$event ? toggleRowSelection(row) : null\"\r\n [checked]=\"isRowSelected(row)\">\r\n </mat-checkbox>\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n\r\n @if(showTotalGeneralFooter()) {\r\n <ng-container [matColumnDef]=\"`${generalFooterKeyPrefix}${nameOfRowSelectionColumn}`\" [sticky]=\"isDesktop()\">\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @for (column of config()().columns; track $index) {\r\n <ng-container \r\n [matColumnDef]=\"getKeyAsString(column.key)\" \r\n [sticky]=\"stickyColumnKey() == column.key && isDesktop()\">\r\n\r\n <th mat-header-cell *matHeaderCellDef mat-sort-header [disabled]=\"!column.isSortable\" class=\"columnLabel\">\r\n <p class=\"headerTitle\">\r\n @if(stickyColumnKey() == column.key && isDesktop()) {\r\n <mat-icon>keep</mat-icon>\r\n }\r\n {{ column.label }}\r\n </p>\r\n </th>\r\n\r\n <td \r\n mat-cell \r\n *matCellDef=\"let row\" \r\n [class.columnSticky]=\"stickyColumnKey() == column.key && isDesktop()\"\r\n [style]=\"column.style\"\r\n class=\"celdaDatos\">\r\n\r\n @if(column.component) {\r\n <ng-container \r\n ngxDynamicCellHost\r\n [component]=\"column.component\"\r\n [row]=\"row\"\r\n [key]=\"column.key\" />\r\n } @else if(column.templateRef) {\r\n <ng-container \r\n *ngTemplateOutlet=\"column.templateRef(); \r\n context: { $implicit: row }\" />\r\n } @else if(column.valueGetter) {\r\n {{ column.valueGetter(row) }}\r\n } @else {\r\n {{ applyColumnPipes(row[column.key], column.pipes) ?? '-' }}\r\n }\r\n </td>\r\n \r\n <td \r\n mat-footer-cell \r\n *matFooterCellDef \r\n [class.columnSticky]=\"stickyColumnKey() == column.key && isDesktop()\"\r\n [style]=\"column.footerStyle\">\r\n\r\n @if(column.showTotalPerPage) {\r\n @if(column.pipes) {\r\n {{ applyColumnPipes(getTotalOfColum(column.key), column.pipes) }}\r\n } @else if(column.totalFooterFormatter) {\r\n {{ column.totalFooterFormatter(getTotalOfColum(column.key)) }}\r\n } @else {\r\n {{ getTotalOfColum(column.key) }}\r\n }\r\n }\r\n </td>\r\n </ng-container>\r\n }\r\n\r\n @if(showTotalGeneralFooter()) {\r\n @for (column of config()().columns; track $index) {\r\n <ng-container \r\n [matColumnDef]=\"`${generalFooterKeyPrefix}${getKeyAsString(column.key)}`\"\r\n [sticky]=\"stickyColumnKey() == column.key && isDesktop()\">\r\n\r\n <td mat-footer-cell *matFooterCellDef [style]=\"column.footerStyle\">\r\n @if(column.showTotalGeneral && column.getTotalGeneral) {\r\n @if(column.pipes) {\r\n {{ applyColumnPipes(column.getTotalGeneral(), column.pipes) }}\r\n } @else if(column.totalFooterFormatter) {\r\n {{ column.totalFooterFormatter(column.getTotalGeneral()) }}\r\n } @else {\r\n {{ column.getTotalGeneral() }}\r\n }\r\n }\r\n </td>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @if(showFiltersRow()) {\r\n @for (column of config()().columns; track $index) {\r\n <ng-container \r\n [matColumnDef]=\"`${filterKeyPrefix}${getKeyAsString(column.key)}`\" \r\n [sticky]=\"stickyColumnKey() == column.key && isDesktop()\">\r\n\r\n <th mat-header-cell *matHeaderCellDef>\r\n @if (column.filterType == 'text' || column.filterType == 'number') {\r\n <mat-form-field subscriptSizing=\"dynamic\" class=\"inputQueryColumn\">\r\n <input [type]=\"column.filterType\" matInput [placeholder]=\"column.label\" [value]=\"getValueOfColumnFilter(column.key) ?? ''\" (input)=\"onTextFilterColumnChange(column, $event)\">\r\n <mat-icon matSuffix>{{ column.filterType == 'text' ? 'search' : 'numbers'}}</mat-icon>\r\n </mat-form-field>\r\n }\r\n\r\n @if (column.filterType == 'option' || column.filterType == 'option-multiple') {\r\n @if(column.endpointForPaginatedFilterOptions) {\r\n <ngx-paginated-searchable-select\r\n class=\"selectColumn\"\r\n [selected]=\"getPaginatedSearchableSelectValueOfColumnFilter(column.key)\"\r\n [endpoint]=\"column.endpointForPaginatedFilterOptions\"\r\n [filters]=\"column.filtersForEndpointPaginatedFilterOptions ?? defaultFiltersForPaginatedFilterOptions\"\r\n [multiple]=\"column.filterType == 'option-multiple'\"\r\n subscriptSizing=\"dynamic\"\r\n [selectPlaceholder]=\"column.label\"\r\n (optionChange)=\"onPaginatedOptionFilterColumnChange(column, $event)\"\r\n clearableOptionLabel=\"filtro\"\r\n />\r\n } @else {\r\n <ngx-searchable-select\r\n class=\"selectColumn\"\r\n [selected]=\"getSearchableSelectValueOfColumnFilter(column.key)\"\r\n [options]=\"column.filterOptions ?? []\"\r\n [multiple]=\"column.filterType == 'option-multiple'\"\r\n subscriptSizing=\"dynamic\"\r\n [selectPlaceholder]=\"column.label\"\r\n (optionChange)=\"onOptionFilterColumnChange(column, $event)\"\r\n clearableOptionLabel=\"filtro\"\r\n />\r\n }\r\n }\r\n \r\n @if(column.filterType == 'date') {\r\n <mat-form-field subscriptSizing=\"dynamic\" class=\"dateColumn\">\r\n <input \r\n matInput \r\n [matDatepicker]=\"picker\" \r\n [placeholder]=\"column.label\"\r\n [value]=\"getValueOfColumnFilter(column.key)\"\r\n (dateChange)=\"onDateFilterChange(column, $event.value)\">\r\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\r\n <mat-datepicker #picker></mat-datepicker>\r\n </mat-form-field>\r\n }\r\n\r\n @if(column.filterType == 'date-range') {\r\n <mat-form-field subscriptSizing=\"dynamic\" class=\"dateColumn\">\r\n <mat-date-range-input [rangePicker]=\"picker\" #dateRangeInput>\r\n <input \r\n matStartDate \r\n [placeholder]=\"texts().table.dateRangeStart\"\r\n [value]=\"getDateRangeValueOfColumnFilter(column.key, 'start')\"\r\n (dateChange)=\"onDateRangeFilterChange(column, dateRangeInput.value)\">\r\n <input \r\n matEndDate \r\n [placeholder]=\"texts().table.dateRangeEnd\"\r\n [value]=\"getDateRangeValueOfColumnFilter(column.key, 'end')\"\r\n (dateChange)=\"onDateRangeFilterChange(column, dateRangeInput.value)\">\r\n </mat-date-range-input>\r\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\r\n <mat-date-range-picker #picker></mat-date-range-picker>\r\n </mat-form-field>\r\n }\r\n </th>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @if(showActionsColumn()) {\r\n @if(showFiltersRow()) {\r\n <ng-container [matColumnDef]=\"`${filterKeyPrefix}${nameOfActionsColumn}`\" [stickyEnd]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef class=\"celdaAcciones\"></th>\r\n </ng-container>\r\n } \r\n\r\n <ng-container [matColumnDef]=\"nameOfActionsColumn\" [stickyEnd]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef>{{ texts().table.actions }}</th>\r\n <td mat-cell *matCellDef=\"let row\" (click)=\"$event.stopPropagation()\" class=\"celdaAcciones\">\r\n <div class=\"contenedorCeldaAcciones\">\r\n @if(config()().expandableDetail) {\r\n <button \r\n matIconButton\r\n (click)=\"expandableToggle(row)\">\r\n <mat-icon>{{ rowIsExpanded(row) ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}</mat-icon>\r\n </button>\r\n }\r\n\r\n @if(config()().update && !config()().clickOnRowForUpdate && (!config()().update?.show || config()().update?.show(row))) {\r\n <button \r\n matIconButton\r\n [matTooltip]=\"config()().update?.tooltip?.(row) ?? texts().table.edit\" \r\n [disabled]=\"config()().update?.disabled?.(row)\" \r\n class=\"editButtonIcon\"\r\n (click)=\"onUpdateClick(row, $event)\">\r\n <mat-icon>edit_square</mat-icon>\r\n </button>\r\n }\r\n \r\n @if(config()().delete && (!config()().delete?.show || config()().delete?.show(row))) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"config()().delete?.tooltip?.(row) ?? texts().table.delete\" \r\n [disabled]=\"config()().delete?.disabled?.(row)\" \r\n class=\"deleteButtonIcon\"\r\n (click)=\"onDeleteClick(row, $event)\">\r\n <mat-icon>delete</mat-icon>\r\n </button>\r\n }\r\n\r\n @for (rowAction of config()().rowActions; track $index) {\r\n @if(!rowAction.show || rowAction.show(row)) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"rowAction.tooltip(row)\" \r\n [disabled]=\"rowAction.disabled?.(row)\" \r\n [class]=\"rowAction.iconColor ? `rowActionIconColor${rowAction.iconColor}` : ''\"\r\n (click)=\"onRowActionClick(row, rowAction, $event)\">\r\n <mat-icon>{{rowAction.icon}}</mat-icon>\r\n </button>\r\n } \r\n }\r\n </div>\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n\r\n @if(showTotalGeneralFooter()) {\r\n <ng-container [matColumnDef]=\"`${generalFooterKeyPrefix}${nameOfActionsColumn}`\" [stickyEnd]=\"isDesktop()\">\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @if(config()().expandableDetail) {\r\n <ng-container [matColumnDef]=\"expandableColumnDef\">\r\n <td mat-cell *matCellDef=\"let row\" [attr.colspan]=\"keys().length\">\r\n <div \r\n class=\"detailWrapper\"\r\n [class.detailWrapperExpanded]=\"rowIsExpanded(row)\">\r\n <div class=\"columnDetail\">\r\n @if(config()().expandableDetailTemplateRef) {\r\n <ng-container \r\n *ngTemplateOutlet=\"config()().expandableDetailTemplateRef!(); \r\n context: { $implicit: row }\" />\r\n }\r\n </div>\r\n </div>\r\n </td>\r\n </ng-container>\r\n }\r\n \r\n <tr mat-header-row *matHeaderRowDef=\"keys(); sticky: true\" class=\"tableHeader\"></tr>\r\n \r\n @if(showFiltersRow()) {\r\n <tr mat-header-row *matHeaderRowDef=\"keysWithFilter(); sticky: true\" class=\"filtersByColumn\"></tr>\r\n }\r\n \r\n <tr mat-row *matRowDef=\"let row; columns: keys();\" \r\n (click)=\"onRowClick(row)\" \r\n [class.rowClickEnable]=\"isRowEnabled(row)\"\r\n [class.expandableRow]=\"config()().expandableDetail\">\r\n </tr>\r\n \r\n @if(config()().expandableDetail) {\r\n <tr mat-row *matRowDef=\"let row; columns: [expandableColumnDef]\" class=\"rowDetail\"></tr>\r\n }\r\n\r\n <tr mat-footer-row \r\n *matFooterRowDef=\"showTotalPerPageFooter() ? keys() : []\" \r\n class=\"totalPerPageFooter\"\r\n [class.hideFooter]=\"!showTotalPerPageFooter()\">\r\n </tr>\r\n\r\n <tr mat-footer-row \r\n *matFooterRowDef=\"showTotalGeneralFooter() ? keysWithGeneralFooter() : []\" \r\n class=\"totalFooter\"\r\n [class.hideFooter]=\"!showTotalGeneralFooter()\">\r\n </tr>\r\n\r\n <tr class=\"mat-row\" *matNoDataRow>\r\n <td class=\"noData\" [colSpan]=\"keys().length\">{{ dataResource.isLoading() ? texts().common.loading : texts().common.noData }}</td>\r\n </tr>\r\n </table>\r\n </div>\r\n\r\n <div class=\"paginatorContainer\">\r\n <div class=\"footerLegend\">\r\n @if(showTotalPerPageFooter()) {\r\n <div class=\"legendItem\">\r\n <div class=\"legendSquare\"></div>\r\n <p>{{ texts().table.totalPerPage }}</p> \r\n </div>\r\n }\r\n\r\n @if(showTotalGeneralFooter()) {\r\n <div class=\"legendItem\">\r\n <div class=\"legendSquare totalGeneral\"></div>\r\n <p>{{ texts().table.totalGeneral }}</p>\r\n </div>\r\n }\r\n </div>\r\n <mat-paginator [length]=\"total()\" [pageSize]=\"filters()().pageSize\" [pageIndex]=\"filters()().pageNumber - 1\" (page)=\"onPageChange($event)\"/>\r\n </div>\r\n\r\n <ng-content select=\"[end-container]\"></ng-content>\r\n </div>\r\n</ng-template>", styles: [".tableContainer{display:flex;flex-direction:column;padding:14px;gap:10px;--mat-table-background-color: transparent;--mat-table-header-headline-color: var(--mat-sys-on-primary)}.inFullScreenMode{height:calc(100vh - 28px);width:calc(100vw - 28px);max-width:calc(100% - 28px);background:var(--mat-sys-surface)}.title{font:var(--mat-sys-title-large);color:var(--mat-sys-on-surface);margin:0;position:relative}.headerContainer{display:flex;justify-content:space-between;gap:10px;flex-direction:column}.titleAndButtonContainer{display:flex;justify-content:space-between;align-items:center;gap:20px}.buttonContainer{display:flex;gap:10px;align-items:center}.filterContainer{display:flex;flex-direction:row;align-items:center;gap:20px;justify-content:space-between}.moreFiltersContainer{display:flex;gap:20px}.editButtonIcon{--mat-icon-button-icon-color: var(--warning)}.deleteButtonIcon{--mat-icon-button-icon-color: var(--mat-sys-error)}.rowActionIconColorYellow{--mat-icon-button-icon-color: rgb(211, 211, 7)}.rowActionIconColorOrange{--mat-icon-button-icon-color: orange}.rowActionIconColorPink{--mat-icon-button-icon-color: pink}.rowActionIconColorPurple{--mat-icon-button-icon-color: purple}.rowActionIconColorGreen{--mat-icon-button-icon-color: var(--success)}.rowActionIconColorBlue{--mat-icon-button-icon-color: var(--information)}.rowActionIconColorBrown{--mat-icon-button-icon-color: brown}.rowActionIconColorSky{--mat-icon-button-icon-color: rgb(0, 247, 255)}.noData{padding:24px}.tableOverflow{overflow:auto;border-radius:10px}.columnLabel{text-wrap:nowrap}.headerTitle{display:flex;align-items:center;gap:4px}.headerTitle mat-icon{font-size:12px;width:12px;height:12px}.tableHeader{background-color:var(--mat-sys-primary)!important}.filtersByColumn{background-color:var(--mat-sys-surface)!important}.filtersByColumn th{padding:0}.celdaDatos{background-color:var(--mat-sys-surface)!important;transition:background-color .1s}.celdaAcciones,.celdaSelection{cursor:default!important;background-color:var(--mat-sys-surface)!important;transition:background-color .1s}.columnSticky{background-color:var(--mat-sys-surface)!important;transition:background-color .1s}.contenedorCeldaAcciones{display:flex;align-items:center;cursor:default!important}.rowClickEnable{cursor:pointer;transition:background-color .1s}.rowClickEnable:hover,.rowClickEnable:hover>.celdaAcciones,.rowClickEnable:hover>.celdaSelection,.rowClickEnable:hover>.celdaDatos,.rowClickEnable:hover>.columnSticky{background-color:var(--mat-sys-surface-container)!important}.inputQueryColumn,.selectColumn,.dateColumn{--mat-form-field-outlined-focus-outline-color: transparent;--mat-form-field-outlined-outline-color: transparent;--mat-form-field-outlined-hover-outline-color: transparent}.templateContainer{display:flex;align-items:center;justify-content:space-between;gap:60px}.buttonTemplateContainer{display:flex;flex-wrap:nowrap}.advancedFiltersApplied{display:flex;flex-direction:row;justify-content:space-between;gap:20px;border-radius:10px;background-color:var(--warning);color:var(--on-warning);align-items:center;margin-top:10px;padding:5px 5px 5px 15px;cursor:pointer;transition:background-color .3s}.advancedFiltersApplied:hover:not(:has(button:hover)){background-color:color-mix(in srgb,var(--warning) 80%,transparent)}.advancedFiltersApplied p{margin:0}.rowDetail{height:0}.expandableRow td{border-bottom-width:0}.detailWrapper{overflow:hidden;display:grid;grid-template-rows:0fr;grid-template-columns:100%;transition:grid-template-rows 225ms cubic-bezier(.4,0,.2,1)}.detailWrapperExpanded{grid-template-rows:1fr}.columnDetail{display:flex;flex-direction:column;min-height:0}.totalPerPageFooter{font-weight:700}.totalFooter{font-weight:700;background-color:var(--mat-sys-surface-container-highest);color:var(--mat-sys-on-surface)}.hideFooter{display:none}.paginatorContainer{display:flex;flex-direction:row;justify-content:space-between;align-items:center;gap:20px;margin-top:10px}.footerLegend{display:flex;flex-direction:row;gap:30px}.footerLegend p{margin:0;font:var(--mat-sys-label-medium)}.legendItem{display:flex;flex-direction:row;align-items:center;gap:6px}.legendSquare{width:24px;height:14px;border-radius:4px;border:2px solid var(--mat-sys-on-surface)}.totalGeneral{background-color:var(--mat-sys-surface-container-highest)}.headerCheckbox{--mat-checkbox-selected-checkmark-color: var(--mat-sys-primary);--mat-checkbox-selected-focus-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-focus-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-selected-hover-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-hover-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-selected-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-pressed-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-pressed-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-focus-icon-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-focus-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-hover-icon-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-hover-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-icon-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-pressed-state-layer-color: var(--mat-sys-on-primary)}@media (max-width: 1200px){.filterContainer{flex-direction:column;align-items:normal}.moreFiltersContainer{flex-direction:column}}@media (max-width: 900px){.footerLegend{flex-direction:column;gap:6px}}@media (max-width: 700px){.paginatorContainer{flex-direction:column;align-items:flex-end}}@media (max-width: 600px){.titleAndButtonContainer{flex-direction:column;align-items:normal}}\n"] }]
2609
2984
  }], propDecorators: { endpoint: [{ type: i0.Input, args: [{ isSignal: true, alias: "endpoint", required: true }] }], filters: [{ type: i0.Input, args: [{ isSignal: true, alias: "filters", required: false }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], createClick: [{ type: i0.Output, args: ["createClick"] }], updateClick: [{ type: i0.Output, args: ["updateClick"] }], deleteClick: [{ type: i0.Output, args: ["deleteClick"] }], rowActionClick: [{ type: i0.Output, args: ["rowActionClick"] }], expandedItemChange: [{ type: i0.Output, args: ["expandedItemChange"] }], selectionActionEvent: [{ type: i0.Output, args: ["selectionActionEvent"] }], tableContentTemplate: [{ type: i0.ViewChild, args: ['tableContent', { isSignal: true }] }], onEscape: [{
2610
2985
  type: HostListener,
2611
2986
  args: ['document:keydown.escape']
@@ -2616,7 +2991,7 @@ class NgxBasicTable {
2616
2991
  dialog = inject(MatDialog);
2617
2992
  datosPantallaService = inject(DatosPantallaService);
2618
2993
  // Inyectar el servicio de internacionalización
2619
- intl = inject(NgxTablesIntl);
2994
+ texts = inject(NgxTexts).texts;
2620
2995
  isDesktop = computed(() => this.datosPantallaService.pantalla()?.tipo == 'escritorio', ...(ngDevMode ? [{ debugName: "isDesktop" }] : []));
2621
2996
  filters = input(signal({
2622
2997
  query: undefined,
@@ -2916,15 +3291,15 @@ class NgxBasicTable {
2916
3291
  }
2917
3292
  onDeleteClick(row, event) {
2918
3293
  event.stopPropagation();
2919
- const title = this.config()().deleteConfirm?.title?.(row) ?? this.intl.deleteConfirmTitle;
2920
- const body = this.config()().deleteConfirm?.body?.(row) ?? this.intl.deleteConfirmBody;
3294
+ const title = this.config()().deleteConfirm?.title?.(row) ?? this.texts().table.deleteConfirmTitle;
3295
+ const body = this.config()().deleteConfirm?.body?.(row) ?? this.texts().table.deleteConfirmBody;
2921
3296
  const template = this.config()().deleteConfirm?.templateRef?.();
2922
3297
  const data = {
2923
3298
  title: title,
2924
3299
  body: !template ? body : undefined,
2925
3300
  template: template,
2926
3301
  row: row,
2927
- confirmButtonLabel: this.intl.confirmDeleteLabel
3302
+ confirmButtonLabel: this.texts().table.confirmDelete
2928
3303
  };
2929
3304
  const dialogRef = this.dialog.open(NgxConfirmDialogComponent, { data: data });
2930
3305
  dialogRef.afterClosed().subscribe((confirm) => {
@@ -3165,7 +3540,7 @@ class NgxBasicTable {
3165
3540
  });
3166
3541
  }
3167
3542
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxBasicTable, deps: [], target: i0.ɵɵFactoryTarget.Component });
3168
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: NgxBasicTable, isStandalone: true, selector: "ngx-basic-table", inputs: { filters: { classPropertyName: "filters", publicName: "filters", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, queryFilter: { classPropertyName: "queryFilter", publicName: "queryFilter", isSignal: true, isRequired: false, transformFunction: null }, moreFilters: { classPropertyName: "moreFilters", publicName: "moreFilters", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { createClick: "createClick", updateClick: "updateClick", deleteClick: "deleteClick", rowActionClick: "rowActionClick", expandedItemChange: "expandedItemChange", selectionActionEvent: "selectionActionEvent" }, host: { listeners: { "document:keydown.escape": "onEscape()" }, classAttribute: "contenedorDefecto" }, viewQueries: [{ propertyName: "tableContentTemplate", first: true, predicate: ["tableContent"], descendants: true, isSignal: true }, { propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true, isSignal: true }], ngImport: i0, template: "@if(!isFullScreen()) {\r\n <ng-container *ngTemplateOutlet=\"tableContentTemplate()\"></ng-container>\r\n}\r\n\r\n<ng-template #tableContent>\r\n <div class=\"tableContainer\" [class.inFullScreenMode]=\"isFullScreen()\">\r\n <div class=\"headerContainer\">\r\n <div class=\"titleAndButtonContainer\">\r\n <p class=\"title\">{{ config()().title() }}</p>\r\n <div class=\"buttonContainer\">\r\n @if(config()().create && (!config()().create?.show || config()().create?.show())) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"config()().create?.tooltip?.() ?? intl.createButtonLabel\" \r\n [disabled]=\"config()().create?.disabled?.()\" \r\n class=\"newButtonIcon\"\r\n (click)=\"onNewClick()\">\r\n <mat-icon>add_circle</mat-icon>\r\n </button>\r\n }\r\n\r\n @if(config()().hideColumnConfig?.() !== true) {\r\n <button matIconButton [matTooltip]=\"intl.editColumnsTooltip\" class=\"editColumnsButtonIcon\" (click)=\"onEditColumns()\">\r\n <mat-icon>table_edit</mat-icon>\r\n </button>\r\n }\r\n\r\n @if(selection().length > 0) {\r\n @if(getRowSelectionAction().length > 0) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"intl.selectionActionsTooltip\"\r\n [matMenuTriggerFor]=\"selectedRecordsMenu\">\r\n <mat-icon>event_list</mat-icon>\r\n </button>\r\n\r\n <mat-menu #selectedRecordsMenu=\"matMenu\" xPosition=\"before\" yPosition=\"below\">\r\n <button mat-menu-item (click)=\"uncheckAllSelection()\">\r\n <mat-icon>deselect</mat-icon>\r\n <span>{{ intl.deselectAllLabel }}</span>\r\n </button>\r\n\r\n @for (action of getRowSelectionAction(); track $index) {\r\n <button mat-menu-item (click)=\"onRowSelectionActionClick(action.id)\">\r\n <mat-icon>{{action.icon}}</mat-icon>\r\n <span>{{action.label(selection(), selection().length)}}</span>\r\n </button>\r\n }\r\n </mat-menu>\r\n } @else {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"intl.deselectAllLabel\"\r\n (click)=\"uncheckAllSelection()\">\r\n <mat-icon>deselect</mat-icon>\r\n </button>\r\n }\r\n }\r\n\r\n @if(config()().hideExportData?.() !== true) {\r\n <button matIconButton [matTooltip]=\"intl.exportTooltip\" [matMenuTriggerFor]=\"exportMenu\">\r\n <mat-icon>download</mat-icon>\r\n </button>\r\n <mat-menu #exportMenu=\"matMenu\" xPosition=\"before\" yPosition=\"below\">\r\n <button mat-menu-item (click)=\"exportToCsv()\">\r\n <mat-icon>csv</mat-icon>\r\n <span>{{ intl.exportToExcelLabel }}</span>\r\n </button>\r\n\r\n <button mat-menu-item (click)=\"exportToPdf()\">\r\n <mat-icon>picture_as_pdf</mat-icon>\r\n <span>{{ intl.exportToPdfLabel }}</span>\r\n </button>\r\n </mat-menu>\r\n }\r\n\r\n @if(config()().hideFullScreen?.() !== true) {\r\n <button matIconButton [matTooltip]=\"isFullScreen() ? intl.exitFullscreenTooltip : intl.enterFullscreenTooltip\" (click)=\"onToggleFullScreen()\">\r\n <mat-icon>{{isFullScreen() ? 'fullscreen_exit': 'fullscreen'}}</mat-icon>\r\n </button>\r\n }\r\n\r\n <ng-content select=\"[icon-buttons]\"></ng-content>\r\n </div>\r\n </div>\r\n\r\n <div class=\"filterContainer\">\r\n <div class=\"moreFiltersContainer\">\r\n <ng-content select=\"[more-filters]\"></ng-content>\r\n </div>\r\n\r\n @if(showQueryFilter()) {\r\n <mat-form-field subscriptSizing=\"dynamic\">\r\n <mat-icon matPrefix>search</mat-icon>\r\n <input #queryElement matInput [placeholder]=\"config()().queryFilterPlaceholder ?? intl.searchPlaceholder\" [value]=\"filters()().query ?? ''\" (input)=\"onQueryChange(queryElement)\">\r\n <button matIconButton matSuffix (click)=\"onQueryReset(queryElement)\" [style.visibility]=\"queryElement.value ? 'visible': 'hidden'\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </mat-form-field>\r\n }\r\n </div>\r\n\r\n <ng-content select=\"[extra-header-content]\"></ng-content>\r\n </div>\r\n\r\n <mat-progress-bar mode=\"indeterminate\" [style.visibility]=\"loading() ? 'visible': 'hidden'\"/>\r\n\r\n <div class=\"tableOverflow\" [style.max-height]=\"config()().maxHeight && !isFullScreen() ? config()().maxHeight : null\">\r\n <table\r\n mat-table \r\n matSort\r\n [multiTemplateDataRows]=\"config()().expandableDetail\"\r\n [dataSource]=\"dataSource()\" \r\n [matSortActive]=\"filters()().sortBy?.key ?? ''\" \r\n [matSortDirection]=\"filters()().sortBy?.direction ?? ''\"\r\n (matSortChange)=\"onSortChange($event)\">\r\n\r\n @if(config()().enableRowSelection) {\r\n @if(showFiltersRow()) {\r\n <ng-container [matColumnDef]=\"`${filterKeyPrefix}${nameOfRowSelectionColumn}`\" [sticky]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef class=\"celdaSelection\"></th>\r\n </ng-container>\r\n } \r\n\r\n <ng-container [matColumnDef]=\"nameOfRowSelectionColumn\" [sticky]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef>\r\n <mat-checkbox \r\n class=\"headerCheckbox\"\r\n (change)=\"$event ? toggleAllPageRowSelection() : null\"\r\n [checked]=\"selection().length > 0 && isAllPageRowSelected()\"\r\n [indeterminate]=\"selection().length > 0 && !isAllPageRowSelected()\">\r\n </mat-checkbox>\r\n </th>\r\n <td mat-cell *matCellDef=\"let row\" (click)=\"$event.stopPropagation()\" class=\"celdaSelection\">\r\n <mat-checkbox\r\n (change)=\"$event ? toggleRowSelection(row) : null\"\r\n [checked]=\"isRowSelected(row)\">\r\n </mat-checkbox>\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef class=\"celdaSelection\"></td>\r\n </ng-container>\r\n\r\n @if(showTotalGeneralFooter()) {\r\n <ng-container [matColumnDef]=\"`${generalFooterKeyPrefix}${nameOfRowSelectionColumn}`\" [sticky]=\"isDesktop()\">\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @for (column of config()().columns; track $index) {\r\n <ng-container \r\n [matColumnDef]=\"getKeyAsString(column.key)\" \r\n [sticky]=\"stickyColumnKey() == column.key && isDesktop()\">\r\n\r\n <th mat-header-cell *matHeaderCellDef mat-sort-header [disabled]=\"column.sortType === undefined\" class=\"columnLabel\">\r\n <p class=\"headerTitle\">\r\n @if(stickyColumnKey() == column.key && isDesktop()) {\r\n <mat-icon>keep</mat-icon>\r\n }\r\n {{ column.label }}\r\n </p>\r\n </th>\r\n\r\n <td \r\n mat-cell \r\n *matCellDef=\"let row\" \r\n [class.columnSticky]=\"stickyColumnKey() == column.key && isDesktop()\"\r\n [style]=\"column.style\"\r\n class=\"celdaDatos\">\r\n\r\n @if(column.component) {\r\n <ng-container \r\n ngxDynamicCellHost\r\n [component]=\"column.component\"\r\n [row]=\"row\"\r\n [key]=\"column.key\" />\r\n } @else if(column.templateRef) {\r\n <ng-container \r\n *ngTemplateOutlet=\"column.templateRef(); \r\n context: { $implicit: row }\" />\r\n } @else if(column.valueGetter) {\r\n {{ column.valueGetter(row) }}\r\n } @else {\r\n {{ applyColumnPipes(row[column.key], column.pipes) ?? '-' }}\r\n }\r\n </td>\r\n \r\n <td\r\n mat-footer-cell \r\n *matFooterCellDef\r\n [class.columnSticky]=\"stickyColumnKey() == column.key && isDesktop()\"\r\n [style]=\"column.footerStyle\">\r\n\r\n @if(column.showTotalPerPage) {\r\n @if(column.pipes) {\r\n {{ applyColumnPipes(getTotalPerPageOfColum(column.key), column.pipes) }}\r\n } @else if(column.totalFooterFormatter) {\r\n {{ column.totalFooterFormatter(getTotalPerPageOfColum(column.key)) }}\r\n } @else {\r\n {{ getTotalPerPageOfColum(column.key) }}\r\n }\r\n }\r\n </td>\r\n </ng-container>\r\n }\r\n\r\n @if(showTotalGeneralFooter()) {\r\n @for (column of config()().columns; track $index) {\r\n <ng-container \r\n [matColumnDef]=\"`${generalFooterKeyPrefix}${getKeyAsString(column.key)}`\"\r\n [sticky]=\"stickyColumnKey() == column.key && isDesktop()\">\r\n <td mat-footer-cell *matFooterCellDef [style]=\"column.footerStyle\">\r\n @if(column.showTotalGeneral) {\r\n @if(column.pipes) {\r\n {{ applyColumnPipes(getTotalOfColum(column.key), column.pipes) }}\r\n } @else if(column.totalFooterFormatter) {\r\n {{ column.totalFooterFormatter(getTotalOfColum(column.key)) }}\r\n } @else {\r\n {{ getTotalOfColum(column.key) }}\r\n }\r\n }\r\n </td>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @if(showFiltersRow()) {\r\n @for (column of config()().columns; track $index) {\r\n <ng-container \r\n [matColumnDef]=\"`${filterKeyPrefix}${getKeyAsString(column.key)}`\" \r\n [sticky]=\"stickyColumnKey() == column.key && isDesktop()\">\r\n\r\n <th mat-header-cell *matHeaderCellDef>\r\n @if (column.filterType == 'text' || column.filterType == 'number') {\r\n <mat-form-field subscriptSizing=\"dynamic\" class=\"inputQueryColumn\">\r\n <input [type]=\"column.filterType\" matInput [placeholder]=\"column.label\" [value]=\"getValueOfColumnFilter(column.key) ?? ''\" (input)=\"onTextFilterColumnChange(column, $event)\">\r\n <mat-icon matSuffix>{{ column.filterType == 'text' ? 'search' : 'numbers'}}</mat-icon>\r\n </mat-form-field>\r\n }\r\n\r\n @if (column.filterType == 'option' || column.filterType == 'option-multiple') {\r\n @if(column.endpointForPaginatedFilterOptions) {\r\n <ngx-paginated-searchable-select\r\n class=\"selectColumn\"\r\n [selected]=\"getPaginatedSearchableSelectValueOfColumnFilter(column.key)\"\r\n [endpoint]=\"column.endpointForPaginatedFilterOptions\"\r\n [filters]=\"column.filtersForEndpointPaginatedFilterOptions ?? defaultFiltersForPaginatedFilterOptions\"\r\n [multiple]=\"column.filterType == 'option-multiple'\"\r\n subscriptSizing=\"dynamic\"\r\n [selectPlaceholder]=\"column.label\"\r\n (optionChange)=\"onPaginatedOptionFilterColumnChange(column, $event)\"\r\n clearableOptionLabel=\"filtro\"\r\n />\r\n } @else {\r\n <ngx-searchable-select\r\n class=\"selectColumn\"\r\n [selected]=\"getSearchableSelectValueOfColumnFilter(column.key)\"\r\n [options]=\"column.filterOptions ?? []\"\r\n [multiple]=\"column.filterType == 'option-multiple'\"\r\n subscriptSizing=\"dynamic\"\r\n [selectPlaceholder]=\"column.label\"\r\n (optionChange)=\"onOptionFilterColumnChange(column, $event)\"\r\n clearableOptionLabel=\"filtro\"\r\n />\r\n } \r\n }\r\n \r\n @if(column.filterType == 'date') {\r\n <mat-form-field subscriptSizing=\"dynamic\" class=\"dateColumn\">\r\n <input \r\n matInput \r\n [matDatepicker]=\"picker\" \r\n [placeholder]=\"column.label\"\r\n [value]=\"getValueOfColumnFilter(column.key)\"\r\n (dateChange)=\"onDateFilterChange(column, $event.value)\">\r\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\r\n <mat-datepicker #picker></mat-datepicker>\r\n </mat-form-field>\r\n }\r\n\r\n @if(column.filterType == 'date-range') {\r\n <mat-form-field subscriptSizing=\"dynamic\" class=\"dateColumn\">\r\n <mat-date-range-input [rangePicker]=\"picker\" #dateRangeInput>\r\n <input \r\n matStartDate \r\n [placeholder]=\"intl.dateRangeStartPlaceholder\"\r\n [value]=\"getDateRangeValueOfColumnFilter(column.key, 'start')\"\r\n (dateChange)=\"onDateRangeFilterChange(column, dateRangeInput.value)\">\r\n <input \r\n matEndDate \r\n [placeholder]=\"intl.dateRangeEndPlaceholder\"\r\n [value]=\"getDateRangeValueOfColumnFilter(column.key, 'end')\"\r\n (dateChange)=\"onDateRangeFilterChange(column, dateRangeInput.value)\">\r\n </mat-date-range-input>\r\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\r\n <mat-date-range-picker #picker></mat-date-range-picker>\r\n </mat-form-field>\r\n }\r\n </th>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @if(showActionsColumn()) {\r\n @if(showFiltersRow()) {\r\n <ng-container [matColumnDef]=\"`${filterKeyPrefix}${nameOfActionsColumn}`\" [stickyEnd]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef class=\"celdaAcciones\"></th>\r\n </ng-container>\r\n } \r\n\r\n <ng-container [matColumnDef]=\"nameOfActionsColumn\" [stickyEnd]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef>{{ intl.actionsLabel }}</th>\r\n <td mat-cell *matCellDef=\"let row\" (click)=\"$event.stopPropagation()\" class=\"celdaAcciones\">\r\n <div class=\"contenedorCeldaAcciones\">\r\n @if(config()().expandableDetail) {\r\n <button \r\n matIconButton\r\n (click)=\"expandableToggle(row)\">\r\n <mat-icon>{{ rowIsExpanded(row) ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}</mat-icon>\r\n </button>\r\n }\r\n\r\n @for (rowAction of config()().rowActions; track $index) {\r\n @if(!rowAction.show || rowAction.show(row)) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"rowAction.tooltip(row)\" \r\n [disabled]=\"rowAction.disabled?.(row)\" \r\n [class]=\"rowAction.iconColor ? `rowActionIconColor${rowAction.iconColor}` : ''\"\r\n (click)=\"onRowActionClick(row, rowAction, $event)\">\r\n <mat-icon>{{rowAction.icon}}</mat-icon>\r\n </button>\r\n } \r\n }\r\n\r\n @if(config()().update && !config()().clickOnRowForUpdate && (!config()().update?.show || config()().update?.show(row))) {\r\n <button \r\n matIconButton\r\n [matTooltip]=\"config()().update?.tooltip?.(row) ?? intl.editTooltip\" \r\n [disabled]=\"config()().update?.disabled?.(row)\" \r\n class=\"editButtonIcon\"\r\n (click)=\"onUpdateClick(row, $event)\">\r\n <mat-icon>edit_square</mat-icon>\r\n </button>\r\n }\r\n \r\n @if(config()().delete && (!config()().delete?.show || config()().delete?.show(row))) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"config()().delete?.tooltip?.(row) ?? intl.deleteTooltip\" \r\n [disabled]=\"config()().delete?.disabled?.(row)\" \r\n class=\"deleteButtonIcon\"\r\n (click)=\"onDeleteClick(row, $event)\">\r\n <mat-icon>delete</mat-icon>\r\n </button>\r\n }\r\n </div>\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n\r\n @if(showTotalGeneralFooter()) {\r\n <ng-container [matColumnDef]=\"`${generalFooterKeyPrefix}${nameOfActionsColumn}`\" [stickyEnd]=\"isDesktop()\">\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @if(config()().expandableDetail) {\r\n <ng-container [matColumnDef]=\"expandableColumnDef\">\r\n <td mat-cell *matCellDef=\"let row\" [attr.colspan]=\"keys().length\">\r\n <div \r\n class=\"detailWrapper\"\r\n [class.detailWrapperExpanded]=\"rowIsExpanded(row)\">\r\n <div class=\"columnDetail\">\r\n @if(config()().expandableDetailTemplateRef) {\r\n <ng-container \r\n *ngTemplateOutlet=\"config()().expandableDetailTemplateRef!(); \r\n context: { $implicit: row }\" />\r\n }\r\n </div>\r\n </div>\r\n </td>\r\n </ng-container>\r\n }\r\n \r\n <tr mat-header-row *matHeaderRowDef=\"keys(); sticky: true\" class=\"tableHeader\"></tr>\r\n \r\n @if(showFiltersRow()) {\r\n <tr mat-header-row *matHeaderRowDef=\"keysWithFilter(); sticky: true\" class=\"filtersByColumn\"></tr>\r\n }\r\n \r\n <tr mat-row *matRowDef=\"let row; columns: keys();\" \r\n (click)=\"onRowClick(row)\" \r\n [class.rowClickEnable]=\"isRowEnabled(row)\"\r\n [class.expandableRow]=\"config()().expandableDetail\">\r\n </tr>\r\n \r\n @if(config()().expandableDetail) {\r\n <tr mat-row *matRowDef=\"let row; columns: [expandableColumnDef]\" class=\"rowDetail\"></tr>\r\n }\r\n\r\n <tr mat-footer-row \r\n *matFooterRowDef=\"showTotalPerPageFooter() ? keys() : []\" \r\n class=\"totalPerPageFooter\"\r\n [class.hideFooter]=\"!showTotalPerPageFooter()\">\r\n </tr>\r\n\r\n <tr mat-footer-row \r\n *matFooterRowDef=\"showTotalGeneralFooter() ? keysWithGeneralFooter() : []\" \r\n class=\"totalFooter\"\r\n [class.hideFooter]=\"!showTotalGeneralFooter()\">\r\n </tr>\r\n\r\n <tr class=\"mat-row\" *matNoDataRow>\r\n <td class=\"noData\" [colSpan]=\"keys().length\">{{ loading() ? intl.loadingMessage : intl.noDataMessage }}</td>\r\n </tr>\r\n </table>\r\n </div>\r\n\r\n <div class=\"paginatorContainer\">\r\n <div class=\"footerLegend\">\r\n @if(showTotalPerPageFooter()) {\r\n <div class=\"legendItem\">\r\n <div class=\"legendSquare\"></div>\r\n <p>{{ intl.totalPerPageLabel }}</p> \r\n </div>\r\n }\r\n\r\n @if(showTotalGeneralFooter()) {\r\n <div class=\"legendItem\">\r\n <div class=\"legendSquare totalGeneral\"></div>\r\n <p>{{ intl.totalGeneralLabel }}</p>\r\n </div>\r\n }\r\n </div>\r\n <mat-paginator />\r\n </div>\r\n\r\n <ng-content select=\"[end-container]\"></ng-content>\r\n </div>\r\n</ng-template>", styles: [".tableContainer{display:flex;flex-direction:column;padding:14px;gap:10px;--mat-table-background-color: transparent;--mat-table-header-headline-color: var(--mat-sys-on-primary)}.inFullScreenMode{height:calc(100vh - 28px);width:calc(100vw - 28px);max-width:calc(100% - 28px);background:var(--mat-sys-surface)}.title{font:var(--mat-sys-title-large);color:var(--mat-sys-on-surface);margin:0;position:relative}.headerContainer{display:flex;justify-content:space-between;gap:10px;flex-direction:column}.titleAndButtonContainer{display:flex;justify-content:space-between;align-items:center;gap:20px}.buttonContainer{display:flex;gap:10px;align-items:center}.filterContainer{display:flex;flex-direction:row;align-items:center;gap:20px;justify-content:space-between}.moreFiltersContainer{display:flex;gap:20px}.editButtonIcon{--mat-icon-button-icon-color: var(--warning)}.deleteButtonIcon{--mat-icon-button-icon-color: var(--mat-sys-error)}.rowActionIconColorYellow{--mat-icon-button-icon-color: rgb(211, 211, 7)}.rowActionIconColorOrange{--mat-icon-button-icon-color: orange}.rowActionIconColorPink{--mat-icon-button-icon-color: pink}.rowActionIconColorPurple{--mat-icon-button-icon-color: purple}.rowActionIconColorGreen{--mat-icon-button-icon-color: var(--success)}.rowActionIconColorBlue{--mat-icon-button-icon-color: var(--information)}.rowActionIconColorBrown{--mat-icon-button-icon-color: brown}.rowActionIconColorSky{--mat-icon-button-icon-color: rgb(0, 247, 255)}.noData{padding:24px}.tableOverflow{overflow:auto;border-radius:10px}.columnLabel{text-wrap:nowrap}.headerTitle{display:flex;align-items:center;gap:4px}.headerTitle mat-icon{font-size:12px;width:12px;height:12px}.tableHeader{background-color:var(--mat-sys-primary)!important}.filtersByColumn{background-color:var(--mat-sys-surface)!important}.filtersByColumn th{padding:0}.celdaDatos{background-color:var(--mat-sys-surface)!important;transition:background-color .1s}.celdaAcciones,.celdaSelection{cursor:default!important;background-color:var(--mat-sys-surface)!important;transition:background-color .1s}.columnSticky{background-color:var(--mat-sys-surface)!important;transition:background-color .1s}.contenedorCeldaAcciones{display:flex;align-items:center;cursor:default!important}.rowClickEnable{cursor:pointer;transition:background-color .1s}.rowClickEnable:hover,.rowClickEnable:hover>.celdaAcciones,.rowClickEnable:hover>.celdaSelection,.rowClickEnable:hover>.celdaDatos,.rowClickEnable:hover>.columnSticky{background-color:var(--mat-sys-surface-container)!important}.inputQueryColumn,.selectColumn,.dateColumn{--mat-form-field-outlined-focus-outline-color: transparent;--mat-form-field-outlined-outline-color: transparent;--mat-form-field-outlined-hover-outline-color: transparent}.advancedFiltersApplied{display:flex;flex-direction:row;justify-content:space-between;gap:20px;border-radius:10px;background-color:var(--warning);color:var(--on-warning);align-items:center;margin-top:10px;padding:5px 5px 5px 15px;cursor:pointer;transition:background-color .3s}.advancedFiltersApplied:hover:not(:has(button:hover)){background-color:color-mix(in srgb,var(--warning) 80%,transparent)}.advancedFiltersApplied p{margin:0}.rowDetail{height:0}.expandableRow td{border-bottom-width:0}.detailWrapper{overflow:hidden;display:grid;grid-template-rows:0fr;grid-template-columns:100%;transition:grid-template-rows 225ms cubic-bezier(.4,0,.2,1)}.detailWrapperExpanded{grid-template-rows:1fr}.columnDetail{display:flex;flex-direction:column;min-height:0}.totalPerPageFooter{font-weight:700}.totalFooter{font-weight:700;background-color:var(--mat-sys-surface-container-highest);color:var(--mat-sys-on-surface)}.hideFooter{display:none}.paginatorContainer{display:flex;flex-direction:row;justify-content:space-between;align-items:center;gap:20px;margin-top:10px}.footerLegend{display:flex;flex-direction:row;gap:30px}.footerLegend p{margin:0;font:var(--mat-sys-label-medium)}.legendItem{display:flex;flex-direction:row;align-items:center;gap:6px}.legendSquare{width:24px;height:14px;border-radius:4px;border:2px solid var(--mat-sys-on-surface)}.totalGeneral{background-color:var(--mat-sys-surface-container-highest)}.headerCheckbox{--mat-checkbox-selected-checkmark-color: var(--mat-sys-primary);--mat-checkbox-selected-focus-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-focus-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-selected-hover-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-hover-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-selected-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-pressed-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-pressed-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-focus-icon-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-focus-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-hover-icon-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-hover-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-icon-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-pressed-state-layer-color: var(--mat-sys-on-primary)}@media (max-width: 1200px){.filterContainer{flex-direction:column;align-items:normal}.moreFiltersContainer{flex-direction:column}}@media (max-width: 900px){.footerLegend{flex-direction:column;gap:6px}}@media (max-width: 700px){.paginatorContainer{flex-direction:column;align-items:flex-end}}@media (max-width: 600px){.titleAndButtonContainer{flex-direction:column;align-items:normal}}\n"], dependencies: [{ kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i1$3.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i1$3.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1$3.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i1$3.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1$3.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1$3.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i1$3.MatFooterCellDef, selector: "[matFooterCellDef]" }, { kind: "directive", type: i1$3.MatFooterRowDef, selector: "[matFooterRowDef]", inputs: ["matFooterRowDef", "matFooterRowDefSticky"] }, { kind: "directive", type: i1$3.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1$3.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: i1$3.MatFooterCell, selector: "mat-footer-cell, td[mat-footer-cell]" }, { kind: "component", type: i1$3.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i1$3.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i1$3.MatFooterRow, selector: "mat-footer-row, tr[mat-footer-row]", exportAs: ["matFooterRow"] }, { kind: "directive", type: i1$3.MatNoDataRow, selector: "ng-template[matNoDataRow]" }, { kind: "ngmodule", type: MatSortModule }, { kind: "directive", type: i2$3.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i2$3.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i3$3.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatProgressBarModule }, { kind: "component", type: i6.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$2.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i2$2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i10.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i10.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i10.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "component", type: i10.MatDateRangeInput, selector: "mat-date-range-input", inputs: ["rangePicker", "required", "dateFilter", "min", "max", "disabled", "separator", "comparisonStart", "comparisonEnd"], exportAs: ["matDateRangeInput"] }, { kind: "directive", type: i10.MatStartDate, selector: "input[matStartDate]", outputs: ["dateChange", "dateInput"] }, { kind: "directive", type: i10.MatEndDate, selector: "input[matEndDate]", outputs: ["dateChange", "dateInput"] }, { kind: "component", type: i10.MatDateRangePicker, selector: "mat-date-range-picker", exportAs: ["matDateRangePicker"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i11.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: DynamicCellHostDirective, selector: "[ngxDynamicCellHost]", inputs: ["component", "row", "key"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i12.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i12.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i12.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i14.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: SearchableSelectComponent, selector: "ngx-searchable-select", inputs: ["control", "options", "optionLabel", "optionValue", "multiple", "searchInputPlaceholder", "selectLabel", "selectPlaceholder", "clearableOptionLabel", "subscriptSizing", "clearable", "error", "selected", "disabled"], outputs: ["optionChange"] }, { kind: "component", type: PaginatedSearchableSelectComponent, selector: "ngx-paginated-searchable-select", inputs: ["control", "endpoint", "filters", "optionLabel", "compareWith", "multiple", "searchInputPlaceholder", "selectLabel", "selectPlaceholder", "clearableOptionLabel", "subscriptSizing", "clearable", "error", "selected", "disabled"], outputs: ["optionChange"] }] });
3543
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: NgxBasicTable, isStandalone: true, selector: "ngx-basic-table", inputs: { filters: { classPropertyName: "filters", publicName: "filters", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, queryFilter: { classPropertyName: "queryFilter", publicName: "queryFilter", isSignal: true, isRequired: false, transformFunction: null }, moreFilters: { classPropertyName: "moreFilters", publicName: "moreFilters", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { createClick: "createClick", updateClick: "updateClick", deleteClick: "deleteClick", rowActionClick: "rowActionClick", expandedItemChange: "expandedItemChange", selectionActionEvent: "selectionActionEvent" }, host: { listeners: { "document:keydown.escape": "onEscape()" }, classAttribute: "contenedorDefecto" }, viewQueries: [{ propertyName: "tableContentTemplate", first: true, predicate: ["tableContent"], descendants: true, isSignal: true }, { propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true, isSignal: true }], ngImport: i0, template: "@if(!isFullScreen()) {\r\n <ng-container *ngTemplateOutlet=\"tableContentTemplate()\"></ng-container>\r\n}\r\n\r\n<ng-template #tableContent>\r\n <div class=\"tableContainer\" [class.inFullScreenMode]=\"isFullScreen()\">\r\n <div class=\"headerContainer\">\r\n <div class=\"titleAndButtonContainer\">\r\n <p class=\"title\">{{ config()().title() }}</p>\r\n <div class=\"buttonContainer\">\r\n @if(config()().create && (!config()().create?.show || config()().create?.show())) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"config()().create?.tooltip?.() ?? texts().table.create\" \r\n [disabled]=\"config()().create?.disabled?.()\" \r\n class=\"newButtonIcon\"\r\n (click)=\"onNewClick()\">\r\n <mat-icon>add_circle</mat-icon>\r\n </button>\r\n }\r\n\r\n @if(config()().hideColumnConfig?.() !== true) {\r\n <button matIconButton [matTooltip]=\"texts().table.editColumns\" class=\"editColumnsButtonIcon\" (click)=\"onEditColumns()\">\r\n <mat-icon>table_edit</mat-icon>\r\n </button>\r\n }\r\n\r\n @if(selection().length > 0) {\r\n @if(getRowSelectionAction().length > 0) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"texts().table.selectionActions\"\r\n [matMenuTriggerFor]=\"selectedRecordsMenu\">\r\n <mat-icon>event_list</mat-icon>\r\n </button>\r\n\r\n <mat-menu #selectedRecordsMenu=\"matMenu\" xPosition=\"before\" yPosition=\"below\">\r\n <button mat-menu-item (click)=\"uncheckAllSelection()\">\r\n <mat-icon>deselect</mat-icon>\r\n <span>{{ texts().table.deselectAll }}</span>\r\n </button>\r\n\r\n @for (action of getRowSelectionAction(); track $index) {\r\n <button mat-menu-item (click)=\"onRowSelectionActionClick(action.id)\">\r\n <mat-icon>{{action.icon}}</mat-icon>\r\n <span>{{action.label(selection(), selection().length)}}</span>\r\n </button>\r\n }\r\n </mat-menu>\r\n } @else {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"texts().table.deselectAll\"\r\n (click)=\"uncheckAllSelection()\">\r\n <mat-icon>deselect</mat-icon>\r\n </button>\r\n }\r\n }\r\n\r\n @if(config()().hideExportData?.() !== true) {\r\n <button matIconButton [matTooltip]=\"texts().table.export\" [matMenuTriggerFor]=\"exportMenu\">\r\n <mat-icon>download</mat-icon>\r\n </button>\r\n <mat-menu #exportMenu=\"matMenu\" xPosition=\"before\" yPosition=\"below\">\r\n <button mat-menu-item (click)=\"exportToCsv()\">\r\n <mat-icon>csv</mat-icon>\r\n <span>{{ texts().table.exportExcel }}</span>\r\n </button>\r\n\r\n <button mat-menu-item (click)=\"exportToPdf()\">\r\n <mat-icon>picture_as_pdf</mat-icon>\r\n <span>{{ texts().table.exportPdf }}</span>\r\n </button>\r\n </mat-menu>\r\n }\r\n\r\n @if(config()().hideFullScreen?.() !== true) {\r\n <button matIconButton [matTooltip]=\"isFullScreen() ? texts().table.exitFullscreen : texts().table.enterFullscreen\" (click)=\"onToggleFullScreen()\">\r\n <mat-icon>{{isFullScreen() ? 'fullscreen_exit': 'fullscreen'}}</mat-icon>\r\n </button>\r\n }\r\n\r\n <ng-content select=\"[icon-buttons]\"></ng-content>\r\n </div>\r\n </div>\r\n\r\n <div class=\"filterContainer\">\r\n <div class=\"moreFiltersContainer\">\r\n <ng-content select=\"[more-filters]\"></ng-content>\r\n </div>\r\n\r\n @if(showQueryFilter()) {\r\n <mat-form-field subscriptSizing=\"dynamic\">\r\n <mat-icon matPrefix>search</mat-icon>\r\n <input #queryElement matInput [placeholder]=\"config()().queryFilterPlaceholder ?? texts().common.search\" [value]=\"filters()().query ?? ''\" (input)=\"onQueryChange(queryElement)\">\r\n <button matIconButton matSuffix (click)=\"onQueryReset(queryElement)\" [style.visibility]=\"queryElement.value ? 'visible': 'hidden'\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </mat-form-field>\r\n }\r\n </div>\r\n\r\n <ng-content select=\"[extra-header-content]\"></ng-content>\r\n </div>\r\n\r\n <mat-progress-bar mode=\"indeterminate\" [style.visibility]=\"loading() ? 'visible': 'hidden'\"/>\r\n\r\n <div class=\"tableOverflow\" [style.max-height]=\"config()().maxHeight && !isFullScreen() ? config()().maxHeight : null\">\r\n <table\r\n mat-table \r\n matSort\r\n [multiTemplateDataRows]=\"config()().expandableDetail\"\r\n [dataSource]=\"dataSource()\" \r\n [matSortActive]=\"filters()().sortBy?.key ?? ''\" \r\n [matSortDirection]=\"filters()().sortBy?.direction ?? ''\"\r\n (matSortChange)=\"onSortChange($event)\">\r\n\r\n @if(config()().enableRowSelection) {\r\n @if(showFiltersRow()) {\r\n <ng-container [matColumnDef]=\"`${filterKeyPrefix}${nameOfRowSelectionColumn}`\" [sticky]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef class=\"celdaSelection\"></th>\r\n </ng-container>\r\n } \r\n\r\n <ng-container [matColumnDef]=\"nameOfRowSelectionColumn\" [sticky]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef>\r\n <mat-checkbox \r\n class=\"headerCheckbox\"\r\n (change)=\"$event ? toggleAllPageRowSelection() : null\"\r\n [checked]=\"selection().length > 0 && isAllPageRowSelected()\"\r\n [indeterminate]=\"selection().length > 0 && !isAllPageRowSelected()\">\r\n </mat-checkbox>\r\n </th>\r\n <td mat-cell *matCellDef=\"let row\" (click)=\"$event.stopPropagation()\" class=\"celdaSelection\">\r\n <mat-checkbox\r\n (change)=\"$event ? toggleRowSelection(row) : null\"\r\n [checked]=\"isRowSelected(row)\">\r\n </mat-checkbox>\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef class=\"celdaSelection\"></td>\r\n </ng-container>\r\n\r\n @if(showTotalGeneralFooter()) {\r\n <ng-container [matColumnDef]=\"`${generalFooterKeyPrefix}${nameOfRowSelectionColumn}`\" [sticky]=\"isDesktop()\">\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @for (column of config()().columns; track $index) {\r\n <ng-container \r\n [matColumnDef]=\"getKeyAsString(column.key)\" \r\n [sticky]=\"stickyColumnKey() == column.key && isDesktop()\">\r\n\r\n <th mat-header-cell *matHeaderCellDef mat-sort-header [disabled]=\"column.sortType === undefined\" class=\"columnLabel\">\r\n <p class=\"headerTitle\">\r\n @if(stickyColumnKey() == column.key && isDesktop()) {\r\n <mat-icon>keep</mat-icon>\r\n }\r\n {{ column.label }}\r\n </p>\r\n </th>\r\n\r\n <td \r\n mat-cell \r\n *matCellDef=\"let row\" \r\n [class.columnSticky]=\"stickyColumnKey() == column.key && isDesktop()\"\r\n [style]=\"column.style\"\r\n class=\"celdaDatos\">\r\n\r\n @if(column.component) {\r\n <ng-container \r\n ngxDynamicCellHost\r\n [component]=\"column.component\"\r\n [row]=\"row\"\r\n [key]=\"column.key\" />\r\n } @else if(column.templateRef) {\r\n <ng-container \r\n *ngTemplateOutlet=\"column.templateRef(); \r\n context: { $implicit: row }\" />\r\n } @else if(column.valueGetter) {\r\n {{ column.valueGetter(row) }}\r\n } @else {\r\n {{ applyColumnPipes(row[column.key], column.pipes) ?? '-' }}\r\n }\r\n </td>\r\n \r\n <td\r\n mat-footer-cell \r\n *matFooterCellDef\r\n [class.columnSticky]=\"stickyColumnKey() == column.key && isDesktop()\"\r\n [style]=\"column.footerStyle\">\r\n\r\n @if(column.showTotalPerPage) {\r\n @if(column.pipes) {\r\n {{ applyColumnPipes(getTotalPerPageOfColum(column.key), column.pipes) }}\r\n } @else if(column.totalFooterFormatter) {\r\n {{ column.totalFooterFormatter(getTotalPerPageOfColum(column.key)) }}\r\n } @else {\r\n {{ getTotalPerPageOfColum(column.key) }}\r\n }\r\n }\r\n </td>\r\n </ng-container>\r\n }\r\n\r\n @if(showTotalGeneralFooter()) {\r\n @for (column of config()().columns; track $index) {\r\n <ng-container \r\n [matColumnDef]=\"`${generalFooterKeyPrefix}${getKeyAsString(column.key)}`\"\r\n [sticky]=\"stickyColumnKey() == column.key && isDesktop()\">\r\n <td mat-footer-cell *matFooterCellDef [style]=\"column.footerStyle\">\r\n @if(column.showTotalGeneral) {\r\n @if(column.pipes) {\r\n {{ applyColumnPipes(getTotalOfColum(column.key), column.pipes) }}\r\n } @else if(column.totalFooterFormatter) {\r\n {{ column.totalFooterFormatter(getTotalOfColum(column.key)) }}\r\n } @else {\r\n {{ getTotalOfColum(column.key) }}\r\n }\r\n }\r\n </td>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @if(showFiltersRow()) {\r\n @for (column of config()().columns; track $index) {\r\n <ng-container \r\n [matColumnDef]=\"`${filterKeyPrefix}${getKeyAsString(column.key)}`\" \r\n [sticky]=\"stickyColumnKey() == column.key && isDesktop()\">\r\n\r\n <th mat-header-cell *matHeaderCellDef>\r\n @if (column.filterType == 'text' || column.filterType == 'number') {\r\n <mat-form-field subscriptSizing=\"dynamic\" class=\"inputQueryColumn\">\r\n <input [type]=\"column.filterType\" matInput [placeholder]=\"column.label\" [value]=\"getValueOfColumnFilter(column.key) ?? ''\" (input)=\"onTextFilterColumnChange(column, $event)\">\r\n <mat-icon matSuffix>{{ column.filterType == 'text' ? 'search' : 'numbers'}}</mat-icon>\r\n </mat-form-field>\r\n }\r\n\r\n @if (column.filterType == 'option' || column.filterType == 'option-multiple') {\r\n @if(column.endpointForPaginatedFilterOptions) {\r\n <ngx-paginated-searchable-select\r\n class=\"selectColumn\"\r\n [selected]=\"getPaginatedSearchableSelectValueOfColumnFilter(column.key)\"\r\n [endpoint]=\"column.endpointForPaginatedFilterOptions\"\r\n [filters]=\"column.filtersForEndpointPaginatedFilterOptions ?? defaultFiltersForPaginatedFilterOptions\"\r\n [multiple]=\"column.filterType == 'option-multiple'\"\r\n subscriptSizing=\"dynamic\"\r\n [selectPlaceholder]=\"column.label\"\r\n (optionChange)=\"onPaginatedOptionFilterColumnChange(column, $event)\"\r\n clearableOptionLabel=\"filtro\"\r\n />\r\n } @else {\r\n <ngx-searchable-select\r\n class=\"selectColumn\"\r\n [selected]=\"getSearchableSelectValueOfColumnFilter(column.key)\"\r\n [options]=\"column.filterOptions ?? []\"\r\n [multiple]=\"column.filterType == 'option-multiple'\"\r\n subscriptSizing=\"dynamic\"\r\n [selectPlaceholder]=\"column.label\"\r\n (optionChange)=\"onOptionFilterColumnChange(column, $event)\"\r\n clearableOptionLabel=\"filtro\"\r\n />\r\n } \r\n }\r\n \r\n @if(column.filterType == 'date') {\r\n <mat-form-field subscriptSizing=\"dynamic\" class=\"dateColumn\">\r\n <input \r\n matInput \r\n [matDatepicker]=\"picker\" \r\n [placeholder]=\"column.label\"\r\n [value]=\"getValueOfColumnFilter(column.key)\"\r\n (dateChange)=\"onDateFilterChange(column, $event.value)\">\r\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\r\n <mat-datepicker #picker></mat-datepicker>\r\n </mat-form-field>\r\n }\r\n\r\n @if(column.filterType == 'date-range') {\r\n <mat-form-field subscriptSizing=\"dynamic\" class=\"dateColumn\">\r\n <mat-date-range-input [rangePicker]=\"picker\" #dateRangeInput>\r\n <input \r\n matStartDate \r\n [placeholder]=\"texts().table.dateRangeStart\"\r\n [value]=\"getDateRangeValueOfColumnFilter(column.key, 'start')\"\r\n (dateChange)=\"onDateRangeFilterChange(column, dateRangeInput.value)\">\r\n <input \r\n matEndDate \r\n [placeholder]=\"texts().table.dateRangeEnd\"\r\n [value]=\"getDateRangeValueOfColumnFilter(column.key, 'end')\"\r\n (dateChange)=\"onDateRangeFilterChange(column, dateRangeInput.value)\">\r\n </mat-date-range-input>\r\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\r\n <mat-date-range-picker #picker></mat-date-range-picker>\r\n </mat-form-field>\r\n }\r\n </th>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @if(showActionsColumn()) {\r\n @if(showFiltersRow()) {\r\n <ng-container [matColumnDef]=\"`${filterKeyPrefix}${nameOfActionsColumn}`\" [stickyEnd]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef class=\"celdaAcciones\"></th>\r\n </ng-container>\r\n } \r\n\r\n <ng-container [matColumnDef]=\"nameOfActionsColumn\" [stickyEnd]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef>{{ texts().table.actions }}</th>\r\n <td mat-cell *matCellDef=\"let row\" (click)=\"$event.stopPropagation()\" class=\"celdaAcciones\">\r\n <div class=\"contenedorCeldaAcciones\">\r\n @if(config()().expandableDetail) {\r\n <button \r\n matIconButton\r\n (click)=\"expandableToggle(row)\">\r\n <mat-icon>{{ rowIsExpanded(row) ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}</mat-icon>\r\n </button>\r\n }\r\n\r\n @for (rowAction of config()().rowActions; track $index) {\r\n @if(!rowAction.show || rowAction.show(row)) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"rowAction.tooltip(row)\" \r\n [disabled]=\"rowAction.disabled?.(row)\" \r\n [class]=\"rowAction.iconColor ? `rowActionIconColor${rowAction.iconColor}` : ''\"\r\n (click)=\"onRowActionClick(row, rowAction, $event)\">\r\n <mat-icon>{{rowAction.icon}}</mat-icon>\r\n </button>\r\n } \r\n }\r\n\r\n @if(config()().update && !config()().clickOnRowForUpdate && (!config()().update?.show || config()().update?.show(row))) {\r\n <button \r\n matIconButton\r\n [matTooltip]=\"config()().update?.tooltip?.(row) ?? texts().table.edit\" \r\n [disabled]=\"config()().update?.disabled?.(row)\" \r\n class=\"editButtonIcon\"\r\n (click)=\"onUpdateClick(row, $event)\">\r\n <mat-icon>edit_square</mat-icon>\r\n </button>\r\n }\r\n \r\n @if(config()().delete && (!config()().delete?.show || config()().delete?.show(row))) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"config()().delete?.tooltip?.(row) ?? texts().table.delete\" \r\n [disabled]=\"config()().delete?.disabled?.(row)\" \r\n class=\"deleteButtonIcon\"\r\n (click)=\"onDeleteClick(row, $event)\">\r\n <mat-icon>delete</mat-icon>\r\n </button>\r\n }\r\n </div>\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n\r\n @if(showTotalGeneralFooter()) {\r\n <ng-container [matColumnDef]=\"`${generalFooterKeyPrefix}${nameOfActionsColumn}`\" [stickyEnd]=\"isDesktop()\">\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @if(config()().expandableDetail) {\r\n <ng-container [matColumnDef]=\"expandableColumnDef\">\r\n <td mat-cell *matCellDef=\"let row\" [attr.colspan]=\"keys().length\">\r\n <div \r\n class=\"detailWrapper\"\r\n [class.detailWrapperExpanded]=\"rowIsExpanded(row)\">\r\n <div class=\"columnDetail\">\r\n @if(config()().expandableDetailTemplateRef) {\r\n <ng-container \r\n *ngTemplateOutlet=\"config()().expandableDetailTemplateRef!(); \r\n context: { $implicit: row }\" />\r\n }\r\n </div>\r\n </div>\r\n </td>\r\n </ng-container>\r\n }\r\n \r\n <tr mat-header-row *matHeaderRowDef=\"keys(); sticky: true\" class=\"tableHeader\"></tr>\r\n \r\n @if(showFiltersRow()) {\r\n <tr mat-header-row *matHeaderRowDef=\"keysWithFilter(); sticky: true\" class=\"filtersByColumn\"></tr>\r\n }\r\n \r\n <tr mat-row *matRowDef=\"let row; columns: keys();\" \r\n (click)=\"onRowClick(row)\" \r\n [class.rowClickEnable]=\"isRowEnabled(row)\"\r\n [class.expandableRow]=\"config()().expandableDetail\">\r\n </tr>\r\n \r\n @if(config()().expandableDetail) {\r\n <tr mat-row *matRowDef=\"let row; columns: [expandableColumnDef]\" class=\"rowDetail\"></tr>\r\n }\r\n\r\n <tr mat-footer-row \r\n *matFooterRowDef=\"showTotalPerPageFooter() ? keys() : []\" \r\n class=\"totalPerPageFooter\"\r\n [class.hideFooter]=\"!showTotalPerPageFooter()\">\r\n </tr>\r\n\r\n <tr mat-footer-row \r\n *matFooterRowDef=\"showTotalGeneralFooter() ? keysWithGeneralFooter() : []\" \r\n class=\"totalFooter\"\r\n [class.hideFooter]=\"!showTotalGeneralFooter()\">\r\n </tr>\r\n\r\n <tr class=\"mat-row\" *matNoDataRow>\r\n <td class=\"noData\" [colSpan]=\"keys().length\">{{ loading() ? texts().common.loading : texts().common.noData }}</td>\r\n </tr>\r\n </table>\r\n </div>\r\n\r\n <div class=\"paginatorContainer\">\r\n <div class=\"footerLegend\">\r\n @if(showTotalPerPageFooter()) {\r\n <div class=\"legendItem\">\r\n <div class=\"legendSquare\"></div>\r\n <p>{{ texts().table.totalPerPage }}</p> \r\n </div>\r\n }\r\n\r\n @if(showTotalGeneralFooter()) {\r\n <div class=\"legendItem\">\r\n <div class=\"legendSquare totalGeneral\"></div>\r\n <p>{{ texts().table.totalGeneral }}</p>\r\n </div>\r\n }\r\n </div>\r\n <mat-paginator />\r\n </div>\r\n\r\n <ng-content select=\"[end-container]\"></ng-content>\r\n </div>\r\n</ng-template>", styles: [".tableContainer{display:flex;flex-direction:column;padding:14px;gap:10px;--mat-table-background-color: transparent;--mat-table-header-headline-color: var(--mat-sys-on-primary)}.inFullScreenMode{height:calc(100vh - 28px);width:calc(100vw - 28px);max-width:calc(100% - 28px);background:var(--mat-sys-surface)}.title{font:var(--mat-sys-title-large);color:var(--mat-sys-on-surface);margin:0;position:relative}.headerContainer{display:flex;justify-content:space-between;gap:10px;flex-direction:column}.titleAndButtonContainer{display:flex;justify-content:space-between;align-items:center;gap:20px}.buttonContainer{display:flex;gap:10px;align-items:center}.filterContainer{display:flex;flex-direction:row;align-items:center;gap:20px;justify-content:space-between}.moreFiltersContainer{display:flex;gap:20px}.editButtonIcon{--mat-icon-button-icon-color: var(--warning)}.deleteButtonIcon{--mat-icon-button-icon-color: var(--mat-sys-error)}.rowActionIconColorYellow{--mat-icon-button-icon-color: rgb(211, 211, 7)}.rowActionIconColorOrange{--mat-icon-button-icon-color: orange}.rowActionIconColorPink{--mat-icon-button-icon-color: pink}.rowActionIconColorPurple{--mat-icon-button-icon-color: purple}.rowActionIconColorGreen{--mat-icon-button-icon-color: var(--success)}.rowActionIconColorBlue{--mat-icon-button-icon-color: var(--information)}.rowActionIconColorBrown{--mat-icon-button-icon-color: brown}.rowActionIconColorSky{--mat-icon-button-icon-color: rgb(0, 247, 255)}.noData{padding:24px}.tableOverflow{overflow:auto;border-radius:10px}.columnLabel{text-wrap:nowrap}.headerTitle{display:flex;align-items:center;gap:4px}.headerTitle mat-icon{font-size:12px;width:12px;height:12px}.tableHeader{background-color:var(--mat-sys-primary)!important}.filtersByColumn{background-color:var(--mat-sys-surface)!important}.filtersByColumn th{padding:0}.celdaDatos{background-color:var(--mat-sys-surface)!important;transition:background-color .1s}.celdaAcciones,.celdaSelection{cursor:default!important;background-color:var(--mat-sys-surface)!important;transition:background-color .1s}.columnSticky{background-color:var(--mat-sys-surface)!important;transition:background-color .1s}.contenedorCeldaAcciones{display:flex;align-items:center;cursor:default!important}.rowClickEnable{cursor:pointer;transition:background-color .1s}.rowClickEnable:hover,.rowClickEnable:hover>.celdaAcciones,.rowClickEnable:hover>.celdaSelection,.rowClickEnable:hover>.celdaDatos,.rowClickEnable:hover>.columnSticky{background-color:var(--mat-sys-surface-container)!important}.inputQueryColumn,.selectColumn,.dateColumn{--mat-form-field-outlined-focus-outline-color: transparent;--mat-form-field-outlined-outline-color: transparent;--mat-form-field-outlined-hover-outline-color: transparent}.advancedFiltersApplied{display:flex;flex-direction:row;justify-content:space-between;gap:20px;border-radius:10px;background-color:var(--warning);color:var(--on-warning);align-items:center;margin-top:10px;padding:5px 5px 5px 15px;cursor:pointer;transition:background-color .3s}.advancedFiltersApplied:hover:not(:has(button:hover)){background-color:color-mix(in srgb,var(--warning) 80%,transparent)}.advancedFiltersApplied p{margin:0}.rowDetail{height:0}.expandableRow td{border-bottom-width:0}.detailWrapper{overflow:hidden;display:grid;grid-template-rows:0fr;grid-template-columns:100%;transition:grid-template-rows 225ms cubic-bezier(.4,0,.2,1)}.detailWrapperExpanded{grid-template-rows:1fr}.columnDetail{display:flex;flex-direction:column;min-height:0}.totalPerPageFooter{font-weight:700}.totalFooter{font-weight:700;background-color:var(--mat-sys-surface-container-highest);color:var(--mat-sys-on-surface)}.hideFooter{display:none}.paginatorContainer{display:flex;flex-direction:row;justify-content:space-between;align-items:center;gap:20px;margin-top:10px}.footerLegend{display:flex;flex-direction:row;gap:30px}.footerLegend p{margin:0;font:var(--mat-sys-label-medium)}.legendItem{display:flex;flex-direction:row;align-items:center;gap:6px}.legendSquare{width:24px;height:14px;border-radius:4px;border:2px solid var(--mat-sys-on-surface)}.totalGeneral{background-color:var(--mat-sys-surface-container-highest)}.headerCheckbox{--mat-checkbox-selected-checkmark-color: var(--mat-sys-primary);--mat-checkbox-selected-focus-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-focus-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-selected-hover-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-hover-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-selected-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-pressed-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-pressed-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-focus-icon-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-focus-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-hover-icon-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-hover-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-icon-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-pressed-state-layer-color: var(--mat-sys-on-primary)}@media (max-width: 1200px){.filterContainer{flex-direction:column;align-items:normal}.moreFiltersContainer{flex-direction:column}}@media (max-width: 900px){.footerLegend{flex-direction:column;gap:6px}}@media (max-width: 700px){.paginatorContainer{flex-direction:column;align-items:flex-end}}@media (max-width: 600px){.titleAndButtonContainer{flex-direction:column;align-items:normal}}\n"], dependencies: [{ kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i1$1.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i1$1.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1$1.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i1$1.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1$1.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1$1.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i1$1.MatFooterCellDef, selector: "[matFooterCellDef]" }, { kind: "directive", type: i1$1.MatFooterRowDef, selector: "[matFooterRowDef]", inputs: ["matFooterRowDef", "matFooterRowDefSticky"] }, { kind: "directive", type: i1$1.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1$1.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: i1$1.MatFooterCell, selector: "mat-footer-cell, td[mat-footer-cell]" }, { kind: "component", type: i1$1.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i1$1.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i1$1.MatFooterRow, selector: "mat-footer-row, tr[mat-footer-row]", exportAs: ["matFooterRow"] }, { kind: "directive", type: i1$1.MatNoDataRow, selector: "ng-template[matNoDataRow]" }, { kind: "ngmodule", type: MatSortModule }, { kind: "directive", type: i2$4.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i2$4.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i3$3.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatProgressBarModule }, { kind: "component", type: i6.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$3.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i2$3.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i10.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i10.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i10.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "component", type: i10.MatDateRangeInput, selector: "mat-date-range-input", inputs: ["rangePicker", "required", "dateFilter", "min", "max", "disabled", "separator", "comparisonStart", "comparisonEnd"], exportAs: ["matDateRangeInput"] }, { kind: "directive", type: i10.MatStartDate, selector: "input[matStartDate]", outputs: ["dateChange", "dateInput"] }, { kind: "directive", type: i10.MatEndDate, selector: "input[matEndDate]", outputs: ["dateChange", "dateInput"] }, { kind: "component", type: i10.MatDateRangePicker, selector: "mat-date-range-picker", exportAs: ["matDateRangePicker"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i11.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: DynamicCellHostDirective, selector: "[ngxDynamicCellHost]", inputs: ["component", "row", "key"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i12.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i12.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i12.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i14.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: SearchableSelectComponent, selector: "ngx-searchable-select", inputs: ["control", "options", "optionLabel", "optionValue", "multiple", "searchInputPlaceholder", "selectLabel", "selectPlaceholder", "clearableOptionLabel", "subscriptSizing", "clearable", "error", "selected", "disabled"], outputs: ["optionChange"] }, { kind: "component", type: PaginatedSearchableSelectComponent, selector: "ngx-paginated-searchable-select", inputs: ["control", "endpoint", "filters", "optionLabel", "compareWith", "multiple", "searchInputPlaceholder", "selectLabel", "selectPlaceholder", "clearableOptionLabel", "subscriptSizing", "clearable", "error", "selected", "disabled"], outputs: ["optionChange"] }] });
3169
3544
  }
3170
3545
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxBasicTable, decorators: [{
3171
3546
  type: Component,
@@ -3188,41 +3563,79 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
3188
3563
  MatCheckboxModule,
3189
3564
  SearchableSelectComponent,
3190
3565
  PaginatedSearchableSelectComponent
3191
- ], host: { class: 'contenedorDefecto' }, template: "@if(!isFullScreen()) {\r\n <ng-container *ngTemplateOutlet=\"tableContentTemplate()\"></ng-container>\r\n}\r\n\r\n<ng-template #tableContent>\r\n <div class=\"tableContainer\" [class.inFullScreenMode]=\"isFullScreen()\">\r\n <div class=\"headerContainer\">\r\n <div class=\"titleAndButtonContainer\">\r\n <p class=\"title\">{{ config()().title() }}</p>\r\n <div class=\"buttonContainer\">\r\n @if(config()().create && (!config()().create?.show || config()().create?.show())) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"config()().create?.tooltip?.() ?? intl.createButtonLabel\" \r\n [disabled]=\"config()().create?.disabled?.()\" \r\n class=\"newButtonIcon\"\r\n (click)=\"onNewClick()\">\r\n <mat-icon>add_circle</mat-icon>\r\n </button>\r\n }\r\n\r\n @if(config()().hideColumnConfig?.() !== true) {\r\n <button matIconButton [matTooltip]=\"intl.editColumnsTooltip\" class=\"editColumnsButtonIcon\" (click)=\"onEditColumns()\">\r\n <mat-icon>table_edit</mat-icon>\r\n </button>\r\n }\r\n\r\n @if(selection().length > 0) {\r\n @if(getRowSelectionAction().length > 0) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"intl.selectionActionsTooltip\"\r\n [matMenuTriggerFor]=\"selectedRecordsMenu\">\r\n <mat-icon>event_list</mat-icon>\r\n </button>\r\n\r\n <mat-menu #selectedRecordsMenu=\"matMenu\" xPosition=\"before\" yPosition=\"below\">\r\n <button mat-menu-item (click)=\"uncheckAllSelection()\">\r\n <mat-icon>deselect</mat-icon>\r\n <span>{{ intl.deselectAllLabel }}</span>\r\n </button>\r\n\r\n @for (action of getRowSelectionAction(); track $index) {\r\n <button mat-menu-item (click)=\"onRowSelectionActionClick(action.id)\">\r\n <mat-icon>{{action.icon}}</mat-icon>\r\n <span>{{action.label(selection(), selection().length)}}</span>\r\n </button>\r\n }\r\n </mat-menu>\r\n } @else {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"intl.deselectAllLabel\"\r\n (click)=\"uncheckAllSelection()\">\r\n <mat-icon>deselect</mat-icon>\r\n </button>\r\n }\r\n }\r\n\r\n @if(config()().hideExportData?.() !== true) {\r\n <button matIconButton [matTooltip]=\"intl.exportTooltip\" [matMenuTriggerFor]=\"exportMenu\">\r\n <mat-icon>download</mat-icon>\r\n </button>\r\n <mat-menu #exportMenu=\"matMenu\" xPosition=\"before\" yPosition=\"below\">\r\n <button mat-menu-item (click)=\"exportToCsv()\">\r\n <mat-icon>csv</mat-icon>\r\n <span>{{ intl.exportToExcelLabel }}</span>\r\n </button>\r\n\r\n <button mat-menu-item (click)=\"exportToPdf()\">\r\n <mat-icon>picture_as_pdf</mat-icon>\r\n <span>{{ intl.exportToPdfLabel }}</span>\r\n </button>\r\n </mat-menu>\r\n }\r\n\r\n @if(config()().hideFullScreen?.() !== true) {\r\n <button matIconButton [matTooltip]=\"isFullScreen() ? intl.exitFullscreenTooltip : intl.enterFullscreenTooltip\" (click)=\"onToggleFullScreen()\">\r\n <mat-icon>{{isFullScreen() ? 'fullscreen_exit': 'fullscreen'}}</mat-icon>\r\n </button>\r\n }\r\n\r\n <ng-content select=\"[icon-buttons]\"></ng-content>\r\n </div>\r\n </div>\r\n\r\n <div class=\"filterContainer\">\r\n <div class=\"moreFiltersContainer\">\r\n <ng-content select=\"[more-filters]\"></ng-content>\r\n </div>\r\n\r\n @if(showQueryFilter()) {\r\n <mat-form-field subscriptSizing=\"dynamic\">\r\n <mat-icon matPrefix>search</mat-icon>\r\n <input #queryElement matInput [placeholder]=\"config()().queryFilterPlaceholder ?? intl.searchPlaceholder\" [value]=\"filters()().query ?? ''\" (input)=\"onQueryChange(queryElement)\">\r\n <button matIconButton matSuffix (click)=\"onQueryReset(queryElement)\" [style.visibility]=\"queryElement.value ? 'visible': 'hidden'\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </mat-form-field>\r\n }\r\n </div>\r\n\r\n <ng-content select=\"[extra-header-content]\"></ng-content>\r\n </div>\r\n\r\n <mat-progress-bar mode=\"indeterminate\" [style.visibility]=\"loading() ? 'visible': 'hidden'\"/>\r\n\r\n <div class=\"tableOverflow\" [style.max-height]=\"config()().maxHeight && !isFullScreen() ? config()().maxHeight : null\">\r\n <table\r\n mat-table \r\n matSort\r\n [multiTemplateDataRows]=\"config()().expandableDetail\"\r\n [dataSource]=\"dataSource()\" \r\n [matSortActive]=\"filters()().sortBy?.key ?? ''\" \r\n [matSortDirection]=\"filters()().sortBy?.direction ?? ''\"\r\n (matSortChange)=\"onSortChange($event)\">\r\n\r\n @if(config()().enableRowSelection) {\r\n @if(showFiltersRow()) {\r\n <ng-container [matColumnDef]=\"`${filterKeyPrefix}${nameOfRowSelectionColumn}`\" [sticky]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef class=\"celdaSelection\"></th>\r\n </ng-container>\r\n } \r\n\r\n <ng-container [matColumnDef]=\"nameOfRowSelectionColumn\" [sticky]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef>\r\n <mat-checkbox \r\n class=\"headerCheckbox\"\r\n (change)=\"$event ? toggleAllPageRowSelection() : null\"\r\n [checked]=\"selection().length > 0 && isAllPageRowSelected()\"\r\n [indeterminate]=\"selection().length > 0 && !isAllPageRowSelected()\">\r\n </mat-checkbox>\r\n </th>\r\n <td mat-cell *matCellDef=\"let row\" (click)=\"$event.stopPropagation()\" class=\"celdaSelection\">\r\n <mat-checkbox\r\n (change)=\"$event ? toggleRowSelection(row) : null\"\r\n [checked]=\"isRowSelected(row)\">\r\n </mat-checkbox>\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef class=\"celdaSelection\"></td>\r\n </ng-container>\r\n\r\n @if(showTotalGeneralFooter()) {\r\n <ng-container [matColumnDef]=\"`${generalFooterKeyPrefix}${nameOfRowSelectionColumn}`\" [sticky]=\"isDesktop()\">\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @for (column of config()().columns; track $index) {\r\n <ng-container \r\n [matColumnDef]=\"getKeyAsString(column.key)\" \r\n [sticky]=\"stickyColumnKey() == column.key && isDesktop()\">\r\n\r\n <th mat-header-cell *matHeaderCellDef mat-sort-header [disabled]=\"column.sortType === undefined\" class=\"columnLabel\">\r\n <p class=\"headerTitle\">\r\n @if(stickyColumnKey() == column.key && isDesktop()) {\r\n <mat-icon>keep</mat-icon>\r\n }\r\n {{ column.label }}\r\n </p>\r\n </th>\r\n\r\n <td \r\n mat-cell \r\n *matCellDef=\"let row\" \r\n [class.columnSticky]=\"stickyColumnKey() == column.key && isDesktop()\"\r\n [style]=\"column.style\"\r\n class=\"celdaDatos\">\r\n\r\n @if(column.component) {\r\n <ng-container \r\n ngxDynamicCellHost\r\n [component]=\"column.component\"\r\n [row]=\"row\"\r\n [key]=\"column.key\" />\r\n } @else if(column.templateRef) {\r\n <ng-container \r\n *ngTemplateOutlet=\"column.templateRef(); \r\n context: { $implicit: row }\" />\r\n } @else if(column.valueGetter) {\r\n {{ column.valueGetter(row) }}\r\n } @else {\r\n {{ applyColumnPipes(row[column.key], column.pipes) ?? '-' }}\r\n }\r\n </td>\r\n \r\n <td\r\n mat-footer-cell \r\n *matFooterCellDef\r\n [class.columnSticky]=\"stickyColumnKey() == column.key && isDesktop()\"\r\n [style]=\"column.footerStyle\">\r\n\r\n @if(column.showTotalPerPage) {\r\n @if(column.pipes) {\r\n {{ applyColumnPipes(getTotalPerPageOfColum(column.key), column.pipes) }}\r\n } @else if(column.totalFooterFormatter) {\r\n {{ column.totalFooterFormatter(getTotalPerPageOfColum(column.key)) }}\r\n } @else {\r\n {{ getTotalPerPageOfColum(column.key) }}\r\n }\r\n }\r\n </td>\r\n </ng-container>\r\n }\r\n\r\n @if(showTotalGeneralFooter()) {\r\n @for (column of config()().columns; track $index) {\r\n <ng-container \r\n [matColumnDef]=\"`${generalFooterKeyPrefix}${getKeyAsString(column.key)}`\"\r\n [sticky]=\"stickyColumnKey() == column.key && isDesktop()\">\r\n <td mat-footer-cell *matFooterCellDef [style]=\"column.footerStyle\">\r\n @if(column.showTotalGeneral) {\r\n @if(column.pipes) {\r\n {{ applyColumnPipes(getTotalOfColum(column.key), column.pipes) }}\r\n } @else if(column.totalFooterFormatter) {\r\n {{ column.totalFooterFormatter(getTotalOfColum(column.key)) }}\r\n } @else {\r\n {{ getTotalOfColum(column.key) }}\r\n }\r\n }\r\n </td>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @if(showFiltersRow()) {\r\n @for (column of config()().columns; track $index) {\r\n <ng-container \r\n [matColumnDef]=\"`${filterKeyPrefix}${getKeyAsString(column.key)}`\" \r\n [sticky]=\"stickyColumnKey() == column.key && isDesktop()\">\r\n\r\n <th mat-header-cell *matHeaderCellDef>\r\n @if (column.filterType == 'text' || column.filterType == 'number') {\r\n <mat-form-field subscriptSizing=\"dynamic\" class=\"inputQueryColumn\">\r\n <input [type]=\"column.filterType\" matInput [placeholder]=\"column.label\" [value]=\"getValueOfColumnFilter(column.key) ?? ''\" (input)=\"onTextFilterColumnChange(column, $event)\">\r\n <mat-icon matSuffix>{{ column.filterType == 'text' ? 'search' : 'numbers'}}</mat-icon>\r\n </mat-form-field>\r\n }\r\n\r\n @if (column.filterType == 'option' || column.filterType == 'option-multiple') {\r\n @if(column.endpointForPaginatedFilterOptions) {\r\n <ngx-paginated-searchable-select\r\n class=\"selectColumn\"\r\n [selected]=\"getPaginatedSearchableSelectValueOfColumnFilter(column.key)\"\r\n [endpoint]=\"column.endpointForPaginatedFilterOptions\"\r\n [filters]=\"column.filtersForEndpointPaginatedFilterOptions ?? defaultFiltersForPaginatedFilterOptions\"\r\n [multiple]=\"column.filterType == 'option-multiple'\"\r\n subscriptSizing=\"dynamic\"\r\n [selectPlaceholder]=\"column.label\"\r\n (optionChange)=\"onPaginatedOptionFilterColumnChange(column, $event)\"\r\n clearableOptionLabel=\"filtro\"\r\n />\r\n } @else {\r\n <ngx-searchable-select\r\n class=\"selectColumn\"\r\n [selected]=\"getSearchableSelectValueOfColumnFilter(column.key)\"\r\n [options]=\"column.filterOptions ?? []\"\r\n [multiple]=\"column.filterType == 'option-multiple'\"\r\n subscriptSizing=\"dynamic\"\r\n [selectPlaceholder]=\"column.label\"\r\n (optionChange)=\"onOptionFilterColumnChange(column, $event)\"\r\n clearableOptionLabel=\"filtro\"\r\n />\r\n } \r\n }\r\n \r\n @if(column.filterType == 'date') {\r\n <mat-form-field subscriptSizing=\"dynamic\" class=\"dateColumn\">\r\n <input \r\n matInput \r\n [matDatepicker]=\"picker\" \r\n [placeholder]=\"column.label\"\r\n [value]=\"getValueOfColumnFilter(column.key)\"\r\n (dateChange)=\"onDateFilterChange(column, $event.value)\">\r\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\r\n <mat-datepicker #picker></mat-datepicker>\r\n </mat-form-field>\r\n }\r\n\r\n @if(column.filterType == 'date-range') {\r\n <mat-form-field subscriptSizing=\"dynamic\" class=\"dateColumn\">\r\n <mat-date-range-input [rangePicker]=\"picker\" #dateRangeInput>\r\n <input \r\n matStartDate \r\n [placeholder]=\"intl.dateRangeStartPlaceholder\"\r\n [value]=\"getDateRangeValueOfColumnFilter(column.key, 'start')\"\r\n (dateChange)=\"onDateRangeFilterChange(column, dateRangeInput.value)\">\r\n <input \r\n matEndDate \r\n [placeholder]=\"intl.dateRangeEndPlaceholder\"\r\n [value]=\"getDateRangeValueOfColumnFilter(column.key, 'end')\"\r\n (dateChange)=\"onDateRangeFilterChange(column, dateRangeInput.value)\">\r\n </mat-date-range-input>\r\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\r\n <mat-date-range-picker #picker></mat-date-range-picker>\r\n </mat-form-field>\r\n }\r\n </th>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @if(showActionsColumn()) {\r\n @if(showFiltersRow()) {\r\n <ng-container [matColumnDef]=\"`${filterKeyPrefix}${nameOfActionsColumn}`\" [stickyEnd]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef class=\"celdaAcciones\"></th>\r\n </ng-container>\r\n } \r\n\r\n <ng-container [matColumnDef]=\"nameOfActionsColumn\" [stickyEnd]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef>{{ intl.actionsLabel }}</th>\r\n <td mat-cell *matCellDef=\"let row\" (click)=\"$event.stopPropagation()\" class=\"celdaAcciones\">\r\n <div class=\"contenedorCeldaAcciones\">\r\n @if(config()().expandableDetail) {\r\n <button \r\n matIconButton\r\n (click)=\"expandableToggle(row)\">\r\n <mat-icon>{{ rowIsExpanded(row) ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}</mat-icon>\r\n </button>\r\n }\r\n\r\n @for (rowAction of config()().rowActions; track $index) {\r\n @if(!rowAction.show || rowAction.show(row)) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"rowAction.tooltip(row)\" \r\n [disabled]=\"rowAction.disabled?.(row)\" \r\n [class]=\"rowAction.iconColor ? `rowActionIconColor${rowAction.iconColor}` : ''\"\r\n (click)=\"onRowActionClick(row, rowAction, $event)\">\r\n <mat-icon>{{rowAction.icon}}</mat-icon>\r\n </button>\r\n } \r\n }\r\n\r\n @if(config()().update && !config()().clickOnRowForUpdate && (!config()().update?.show || config()().update?.show(row))) {\r\n <button \r\n matIconButton\r\n [matTooltip]=\"config()().update?.tooltip?.(row) ?? intl.editTooltip\" \r\n [disabled]=\"config()().update?.disabled?.(row)\" \r\n class=\"editButtonIcon\"\r\n (click)=\"onUpdateClick(row, $event)\">\r\n <mat-icon>edit_square</mat-icon>\r\n </button>\r\n }\r\n \r\n @if(config()().delete && (!config()().delete?.show || config()().delete?.show(row))) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"config()().delete?.tooltip?.(row) ?? intl.deleteTooltip\" \r\n [disabled]=\"config()().delete?.disabled?.(row)\" \r\n class=\"deleteButtonIcon\"\r\n (click)=\"onDeleteClick(row, $event)\">\r\n <mat-icon>delete</mat-icon>\r\n </button>\r\n }\r\n </div>\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n\r\n @if(showTotalGeneralFooter()) {\r\n <ng-container [matColumnDef]=\"`${generalFooterKeyPrefix}${nameOfActionsColumn}`\" [stickyEnd]=\"isDesktop()\">\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @if(config()().expandableDetail) {\r\n <ng-container [matColumnDef]=\"expandableColumnDef\">\r\n <td mat-cell *matCellDef=\"let row\" [attr.colspan]=\"keys().length\">\r\n <div \r\n class=\"detailWrapper\"\r\n [class.detailWrapperExpanded]=\"rowIsExpanded(row)\">\r\n <div class=\"columnDetail\">\r\n @if(config()().expandableDetailTemplateRef) {\r\n <ng-container \r\n *ngTemplateOutlet=\"config()().expandableDetailTemplateRef!(); \r\n context: { $implicit: row }\" />\r\n }\r\n </div>\r\n </div>\r\n </td>\r\n </ng-container>\r\n }\r\n \r\n <tr mat-header-row *matHeaderRowDef=\"keys(); sticky: true\" class=\"tableHeader\"></tr>\r\n \r\n @if(showFiltersRow()) {\r\n <tr mat-header-row *matHeaderRowDef=\"keysWithFilter(); sticky: true\" class=\"filtersByColumn\"></tr>\r\n }\r\n \r\n <tr mat-row *matRowDef=\"let row; columns: keys();\" \r\n (click)=\"onRowClick(row)\" \r\n [class.rowClickEnable]=\"isRowEnabled(row)\"\r\n [class.expandableRow]=\"config()().expandableDetail\">\r\n </tr>\r\n \r\n @if(config()().expandableDetail) {\r\n <tr mat-row *matRowDef=\"let row; columns: [expandableColumnDef]\" class=\"rowDetail\"></tr>\r\n }\r\n\r\n <tr mat-footer-row \r\n *matFooterRowDef=\"showTotalPerPageFooter() ? keys() : []\" \r\n class=\"totalPerPageFooter\"\r\n [class.hideFooter]=\"!showTotalPerPageFooter()\">\r\n </tr>\r\n\r\n <tr mat-footer-row \r\n *matFooterRowDef=\"showTotalGeneralFooter() ? keysWithGeneralFooter() : []\" \r\n class=\"totalFooter\"\r\n [class.hideFooter]=\"!showTotalGeneralFooter()\">\r\n </tr>\r\n\r\n <tr class=\"mat-row\" *matNoDataRow>\r\n <td class=\"noData\" [colSpan]=\"keys().length\">{{ loading() ? intl.loadingMessage : intl.noDataMessage }}</td>\r\n </tr>\r\n </table>\r\n </div>\r\n\r\n <div class=\"paginatorContainer\">\r\n <div class=\"footerLegend\">\r\n @if(showTotalPerPageFooter()) {\r\n <div class=\"legendItem\">\r\n <div class=\"legendSquare\"></div>\r\n <p>{{ intl.totalPerPageLabel }}</p> \r\n </div>\r\n }\r\n\r\n @if(showTotalGeneralFooter()) {\r\n <div class=\"legendItem\">\r\n <div class=\"legendSquare totalGeneral\"></div>\r\n <p>{{ intl.totalGeneralLabel }}</p>\r\n </div>\r\n }\r\n </div>\r\n <mat-paginator />\r\n </div>\r\n\r\n <ng-content select=\"[end-container]\"></ng-content>\r\n </div>\r\n</ng-template>", styles: [".tableContainer{display:flex;flex-direction:column;padding:14px;gap:10px;--mat-table-background-color: transparent;--mat-table-header-headline-color: var(--mat-sys-on-primary)}.inFullScreenMode{height:calc(100vh - 28px);width:calc(100vw - 28px);max-width:calc(100% - 28px);background:var(--mat-sys-surface)}.title{font:var(--mat-sys-title-large);color:var(--mat-sys-on-surface);margin:0;position:relative}.headerContainer{display:flex;justify-content:space-between;gap:10px;flex-direction:column}.titleAndButtonContainer{display:flex;justify-content:space-between;align-items:center;gap:20px}.buttonContainer{display:flex;gap:10px;align-items:center}.filterContainer{display:flex;flex-direction:row;align-items:center;gap:20px;justify-content:space-between}.moreFiltersContainer{display:flex;gap:20px}.editButtonIcon{--mat-icon-button-icon-color: var(--warning)}.deleteButtonIcon{--mat-icon-button-icon-color: var(--mat-sys-error)}.rowActionIconColorYellow{--mat-icon-button-icon-color: rgb(211, 211, 7)}.rowActionIconColorOrange{--mat-icon-button-icon-color: orange}.rowActionIconColorPink{--mat-icon-button-icon-color: pink}.rowActionIconColorPurple{--mat-icon-button-icon-color: purple}.rowActionIconColorGreen{--mat-icon-button-icon-color: var(--success)}.rowActionIconColorBlue{--mat-icon-button-icon-color: var(--information)}.rowActionIconColorBrown{--mat-icon-button-icon-color: brown}.rowActionIconColorSky{--mat-icon-button-icon-color: rgb(0, 247, 255)}.noData{padding:24px}.tableOverflow{overflow:auto;border-radius:10px}.columnLabel{text-wrap:nowrap}.headerTitle{display:flex;align-items:center;gap:4px}.headerTitle mat-icon{font-size:12px;width:12px;height:12px}.tableHeader{background-color:var(--mat-sys-primary)!important}.filtersByColumn{background-color:var(--mat-sys-surface)!important}.filtersByColumn th{padding:0}.celdaDatos{background-color:var(--mat-sys-surface)!important;transition:background-color .1s}.celdaAcciones,.celdaSelection{cursor:default!important;background-color:var(--mat-sys-surface)!important;transition:background-color .1s}.columnSticky{background-color:var(--mat-sys-surface)!important;transition:background-color .1s}.contenedorCeldaAcciones{display:flex;align-items:center;cursor:default!important}.rowClickEnable{cursor:pointer;transition:background-color .1s}.rowClickEnable:hover,.rowClickEnable:hover>.celdaAcciones,.rowClickEnable:hover>.celdaSelection,.rowClickEnable:hover>.celdaDatos,.rowClickEnable:hover>.columnSticky{background-color:var(--mat-sys-surface-container)!important}.inputQueryColumn,.selectColumn,.dateColumn{--mat-form-field-outlined-focus-outline-color: transparent;--mat-form-field-outlined-outline-color: transparent;--mat-form-field-outlined-hover-outline-color: transparent}.advancedFiltersApplied{display:flex;flex-direction:row;justify-content:space-between;gap:20px;border-radius:10px;background-color:var(--warning);color:var(--on-warning);align-items:center;margin-top:10px;padding:5px 5px 5px 15px;cursor:pointer;transition:background-color .3s}.advancedFiltersApplied:hover:not(:has(button:hover)){background-color:color-mix(in srgb,var(--warning) 80%,transparent)}.advancedFiltersApplied p{margin:0}.rowDetail{height:0}.expandableRow td{border-bottom-width:0}.detailWrapper{overflow:hidden;display:grid;grid-template-rows:0fr;grid-template-columns:100%;transition:grid-template-rows 225ms cubic-bezier(.4,0,.2,1)}.detailWrapperExpanded{grid-template-rows:1fr}.columnDetail{display:flex;flex-direction:column;min-height:0}.totalPerPageFooter{font-weight:700}.totalFooter{font-weight:700;background-color:var(--mat-sys-surface-container-highest);color:var(--mat-sys-on-surface)}.hideFooter{display:none}.paginatorContainer{display:flex;flex-direction:row;justify-content:space-between;align-items:center;gap:20px;margin-top:10px}.footerLegend{display:flex;flex-direction:row;gap:30px}.footerLegend p{margin:0;font:var(--mat-sys-label-medium)}.legendItem{display:flex;flex-direction:row;align-items:center;gap:6px}.legendSquare{width:24px;height:14px;border-radius:4px;border:2px solid var(--mat-sys-on-surface)}.totalGeneral{background-color:var(--mat-sys-surface-container-highest)}.headerCheckbox{--mat-checkbox-selected-checkmark-color: var(--mat-sys-primary);--mat-checkbox-selected-focus-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-focus-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-selected-hover-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-hover-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-selected-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-pressed-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-pressed-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-focus-icon-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-focus-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-hover-icon-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-hover-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-icon-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-pressed-state-layer-color: var(--mat-sys-on-primary)}@media (max-width: 1200px){.filterContainer{flex-direction:column;align-items:normal}.moreFiltersContainer{flex-direction:column}}@media (max-width: 900px){.footerLegend{flex-direction:column;gap:6px}}@media (max-width: 700px){.paginatorContainer{flex-direction:column;align-items:flex-end}}@media (max-width: 600px){.titleAndButtonContainer{flex-direction:column;align-items:normal}}\n"] }]
3566
+ ], host: { class: 'contenedorDefecto' }, template: "@if(!isFullScreen()) {\r\n <ng-container *ngTemplateOutlet=\"tableContentTemplate()\"></ng-container>\r\n}\r\n\r\n<ng-template #tableContent>\r\n <div class=\"tableContainer\" [class.inFullScreenMode]=\"isFullScreen()\">\r\n <div class=\"headerContainer\">\r\n <div class=\"titleAndButtonContainer\">\r\n <p class=\"title\">{{ config()().title() }}</p>\r\n <div class=\"buttonContainer\">\r\n @if(config()().create && (!config()().create?.show || config()().create?.show())) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"config()().create?.tooltip?.() ?? texts().table.create\" \r\n [disabled]=\"config()().create?.disabled?.()\" \r\n class=\"newButtonIcon\"\r\n (click)=\"onNewClick()\">\r\n <mat-icon>add_circle</mat-icon>\r\n </button>\r\n }\r\n\r\n @if(config()().hideColumnConfig?.() !== true) {\r\n <button matIconButton [matTooltip]=\"texts().table.editColumns\" class=\"editColumnsButtonIcon\" (click)=\"onEditColumns()\">\r\n <mat-icon>table_edit</mat-icon>\r\n </button>\r\n }\r\n\r\n @if(selection().length > 0) {\r\n @if(getRowSelectionAction().length > 0) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"texts().table.selectionActions\"\r\n [matMenuTriggerFor]=\"selectedRecordsMenu\">\r\n <mat-icon>event_list</mat-icon>\r\n </button>\r\n\r\n <mat-menu #selectedRecordsMenu=\"matMenu\" xPosition=\"before\" yPosition=\"below\">\r\n <button mat-menu-item (click)=\"uncheckAllSelection()\">\r\n <mat-icon>deselect</mat-icon>\r\n <span>{{ texts().table.deselectAll }}</span>\r\n </button>\r\n\r\n @for (action of getRowSelectionAction(); track $index) {\r\n <button mat-menu-item (click)=\"onRowSelectionActionClick(action.id)\">\r\n <mat-icon>{{action.icon}}</mat-icon>\r\n <span>{{action.label(selection(), selection().length)}}</span>\r\n </button>\r\n }\r\n </mat-menu>\r\n } @else {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"texts().table.deselectAll\"\r\n (click)=\"uncheckAllSelection()\">\r\n <mat-icon>deselect</mat-icon>\r\n </button>\r\n }\r\n }\r\n\r\n @if(config()().hideExportData?.() !== true) {\r\n <button matIconButton [matTooltip]=\"texts().table.export\" [matMenuTriggerFor]=\"exportMenu\">\r\n <mat-icon>download</mat-icon>\r\n </button>\r\n <mat-menu #exportMenu=\"matMenu\" xPosition=\"before\" yPosition=\"below\">\r\n <button mat-menu-item (click)=\"exportToCsv()\">\r\n <mat-icon>csv</mat-icon>\r\n <span>{{ texts().table.exportExcel }}</span>\r\n </button>\r\n\r\n <button mat-menu-item (click)=\"exportToPdf()\">\r\n <mat-icon>picture_as_pdf</mat-icon>\r\n <span>{{ texts().table.exportPdf }}</span>\r\n </button>\r\n </mat-menu>\r\n }\r\n\r\n @if(config()().hideFullScreen?.() !== true) {\r\n <button matIconButton [matTooltip]=\"isFullScreen() ? texts().table.exitFullscreen : texts().table.enterFullscreen\" (click)=\"onToggleFullScreen()\">\r\n <mat-icon>{{isFullScreen() ? 'fullscreen_exit': 'fullscreen'}}</mat-icon>\r\n </button>\r\n }\r\n\r\n <ng-content select=\"[icon-buttons]\"></ng-content>\r\n </div>\r\n </div>\r\n\r\n <div class=\"filterContainer\">\r\n <div class=\"moreFiltersContainer\">\r\n <ng-content select=\"[more-filters]\"></ng-content>\r\n </div>\r\n\r\n @if(showQueryFilter()) {\r\n <mat-form-field subscriptSizing=\"dynamic\">\r\n <mat-icon matPrefix>search</mat-icon>\r\n <input #queryElement matInput [placeholder]=\"config()().queryFilterPlaceholder ?? texts().common.search\" [value]=\"filters()().query ?? ''\" (input)=\"onQueryChange(queryElement)\">\r\n <button matIconButton matSuffix (click)=\"onQueryReset(queryElement)\" [style.visibility]=\"queryElement.value ? 'visible': 'hidden'\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </mat-form-field>\r\n }\r\n </div>\r\n\r\n <ng-content select=\"[extra-header-content]\"></ng-content>\r\n </div>\r\n\r\n <mat-progress-bar mode=\"indeterminate\" [style.visibility]=\"loading() ? 'visible': 'hidden'\"/>\r\n\r\n <div class=\"tableOverflow\" [style.max-height]=\"config()().maxHeight && !isFullScreen() ? config()().maxHeight : null\">\r\n <table\r\n mat-table \r\n matSort\r\n [multiTemplateDataRows]=\"config()().expandableDetail\"\r\n [dataSource]=\"dataSource()\" \r\n [matSortActive]=\"filters()().sortBy?.key ?? ''\" \r\n [matSortDirection]=\"filters()().sortBy?.direction ?? ''\"\r\n (matSortChange)=\"onSortChange($event)\">\r\n\r\n @if(config()().enableRowSelection) {\r\n @if(showFiltersRow()) {\r\n <ng-container [matColumnDef]=\"`${filterKeyPrefix}${nameOfRowSelectionColumn}`\" [sticky]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef class=\"celdaSelection\"></th>\r\n </ng-container>\r\n } \r\n\r\n <ng-container [matColumnDef]=\"nameOfRowSelectionColumn\" [sticky]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef>\r\n <mat-checkbox \r\n class=\"headerCheckbox\"\r\n (change)=\"$event ? toggleAllPageRowSelection() : null\"\r\n [checked]=\"selection().length > 0 && isAllPageRowSelected()\"\r\n [indeterminate]=\"selection().length > 0 && !isAllPageRowSelected()\">\r\n </mat-checkbox>\r\n </th>\r\n <td mat-cell *matCellDef=\"let row\" (click)=\"$event.stopPropagation()\" class=\"celdaSelection\">\r\n <mat-checkbox\r\n (change)=\"$event ? toggleRowSelection(row) : null\"\r\n [checked]=\"isRowSelected(row)\">\r\n </mat-checkbox>\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef class=\"celdaSelection\"></td>\r\n </ng-container>\r\n\r\n @if(showTotalGeneralFooter()) {\r\n <ng-container [matColumnDef]=\"`${generalFooterKeyPrefix}${nameOfRowSelectionColumn}`\" [sticky]=\"isDesktop()\">\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @for (column of config()().columns; track $index) {\r\n <ng-container \r\n [matColumnDef]=\"getKeyAsString(column.key)\" \r\n [sticky]=\"stickyColumnKey() == column.key && isDesktop()\">\r\n\r\n <th mat-header-cell *matHeaderCellDef mat-sort-header [disabled]=\"column.sortType === undefined\" class=\"columnLabel\">\r\n <p class=\"headerTitle\">\r\n @if(stickyColumnKey() == column.key && isDesktop()) {\r\n <mat-icon>keep</mat-icon>\r\n }\r\n {{ column.label }}\r\n </p>\r\n </th>\r\n\r\n <td \r\n mat-cell \r\n *matCellDef=\"let row\" \r\n [class.columnSticky]=\"stickyColumnKey() == column.key && isDesktop()\"\r\n [style]=\"column.style\"\r\n class=\"celdaDatos\">\r\n\r\n @if(column.component) {\r\n <ng-container \r\n ngxDynamicCellHost\r\n [component]=\"column.component\"\r\n [row]=\"row\"\r\n [key]=\"column.key\" />\r\n } @else if(column.templateRef) {\r\n <ng-container \r\n *ngTemplateOutlet=\"column.templateRef(); \r\n context: { $implicit: row }\" />\r\n } @else if(column.valueGetter) {\r\n {{ column.valueGetter(row) }}\r\n } @else {\r\n {{ applyColumnPipes(row[column.key], column.pipes) ?? '-' }}\r\n }\r\n </td>\r\n \r\n <td\r\n mat-footer-cell \r\n *matFooterCellDef\r\n [class.columnSticky]=\"stickyColumnKey() == column.key && isDesktop()\"\r\n [style]=\"column.footerStyle\">\r\n\r\n @if(column.showTotalPerPage) {\r\n @if(column.pipes) {\r\n {{ applyColumnPipes(getTotalPerPageOfColum(column.key), column.pipes) }}\r\n } @else if(column.totalFooterFormatter) {\r\n {{ column.totalFooterFormatter(getTotalPerPageOfColum(column.key)) }}\r\n } @else {\r\n {{ getTotalPerPageOfColum(column.key) }}\r\n }\r\n }\r\n </td>\r\n </ng-container>\r\n }\r\n\r\n @if(showTotalGeneralFooter()) {\r\n @for (column of config()().columns; track $index) {\r\n <ng-container \r\n [matColumnDef]=\"`${generalFooterKeyPrefix}${getKeyAsString(column.key)}`\"\r\n [sticky]=\"stickyColumnKey() == column.key && isDesktop()\">\r\n <td mat-footer-cell *matFooterCellDef [style]=\"column.footerStyle\">\r\n @if(column.showTotalGeneral) {\r\n @if(column.pipes) {\r\n {{ applyColumnPipes(getTotalOfColum(column.key), column.pipes) }}\r\n } @else if(column.totalFooterFormatter) {\r\n {{ column.totalFooterFormatter(getTotalOfColum(column.key)) }}\r\n } @else {\r\n {{ getTotalOfColum(column.key) }}\r\n }\r\n }\r\n </td>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @if(showFiltersRow()) {\r\n @for (column of config()().columns; track $index) {\r\n <ng-container \r\n [matColumnDef]=\"`${filterKeyPrefix}${getKeyAsString(column.key)}`\" \r\n [sticky]=\"stickyColumnKey() == column.key && isDesktop()\">\r\n\r\n <th mat-header-cell *matHeaderCellDef>\r\n @if (column.filterType == 'text' || column.filterType == 'number') {\r\n <mat-form-field subscriptSizing=\"dynamic\" class=\"inputQueryColumn\">\r\n <input [type]=\"column.filterType\" matInput [placeholder]=\"column.label\" [value]=\"getValueOfColumnFilter(column.key) ?? ''\" (input)=\"onTextFilterColumnChange(column, $event)\">\r\n <mat-icon matSuffix>{{ column.filterType == 'text' ? 'search' : 'numbers'}}</mat-icon>\r\n </mat-form-field>\r\n }\r\n\r\n @if (column.filterType == 'option' || column.filterType == 'option-multiple') {\r\n @if(column.endpointForPaginatedFilterOptions) {\r\n <ngx-paginated-searchable-select\r\n class=\"selectColumn\"\r\n [selected]=\"getPaginatedSearchableSelectValueOfColumnFilter(column.key)\"\r\n [endpoint]=\"column.endpointForPaginatedFilterOptions\"\r\n [filters]=\"column.filtersForEndpointPaginatedFilterOptions ?? defaultFiltersForPaginatedFilterOptions\"\r\n [multiple]=\"column.filterType == 'option-multiple'\"\r\n subscriptSizing=\"dynamic\"\r\n [selectPlaceholder]=\"column.label\"\r\n (optionChange)=\"onPaginatedOptionFilterColumnChange(column, $event)\"\r\n clearableOptionLabel=\"filtro\"\r\n />\r\n } @else {\r\n <ngx-searchable-select\r\n class=\"selectColumn\"\r\n [selected]=\"getSearchableSelectValueOfColumnFilter(column.key)\"\r\n [options]=\"column.filterOptions ?? []\"\r\n [multiple]=\"column.filterType == 'option-multiple'\"\r\n subscriptSizing=\"dynamic\"\r\n [selectPlaceholder]=\"column.label\"\r\n (optionChange)=\"onOptionFilterColumnChange(column, $event)\"\r\n clearableOptionLabel=\"filtro\"\r\n />\r\n } \r\n }\r\n \r\n @if(column.filterType == 'date') {\r\n <mat-form-field subscriptSizing=\"dynamic\" class=\"dateColumn\">\r\n <input \r\n matInput \r\n [matDatepicker]=\"picker\" \r\n [placeholder]=\"column.label\"\r\n [value]=\"getValueOfColumnFilter(column.key)\"\r\n (dateChange)=\"onDateFilterChange(column, $event.value)\">\r\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\r\n <mat-datepicker #picker></mat-datepicker>\r\n </mat-form-field>\r\n }\r\n\r\n @if(column.filterType == 'date-range') {\r\n <mat-form-field subscriptSizing=\"dynamic\" class=\"dateColumn\">\r\n <mat-date-range-input [rangePicker]=\"picker\" #dateRangeInput>\r\n <input \r\n matStartDate \r\n [placeholder]=\"texts().table.dateRangeStart\"\r\n [value]=\"getDateRangeValueOfColumnFilter(column.key, 'start')\"\r\n (dateChange)=\"onDateRangeFilterChange(column, dateRangeInput.value)\">\r\n <input \r\n matEndDate \r\n [placeholder]=\"texts().table.dateRangeEnd\"\r\n [value]=\"getDateRangeValueOfColumnFilter(column.key, 'end')\"\r\n (dateChange)=\"onDateRangeFilterChange(column, dateRangeInput.value)\">\r\n </mat-date-range-input>\r\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\r\n <mat-date-range-picker #picker></mat-date-range-picker>\r\n </mat-form-field>\r\n }\r\n </th>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @if(showActionsColumn()) {\r\n @if(showFiltersRow()) {\r\n <ng-container [matColumnDef]=\"`${filterKeyPrefix}${nameOfActionsColumn}`\" [stickyEnd]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef class=\"celdaAcciones\"></th>\r\n </ng-container>\r\n } \r\n\r\n <ng-container [matColumnDef]=\"nameOfActionsColumn\" [stickyEnd]=\"isDesktop()\">\r\n <th mat-header-cell *matHeaderCellDef>{{ texts().table.actions }}</th>\r\n <td mat-cell *matCellDef=\"let row\" (click)=\"$event.stopPropagation()\" class=\"celdaAcciones\">\r\n <div class=\"contenedorCeldaAcciones\">\r\n @if(config()().expandableDetail) {\r\n <button \r\n matIconButton\r\n (click)=\"expandableToggle(row)\">\r\n <mat-icon>{{ rowIsExpanded(row) ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}</mat-icon>\r\n </button>\r\n }\r\n\r\n @for (rowAction of config()().rowActions; track $index) {\r\n @if(!rowAction.show || rowAction.show(row)) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"rowAction.tooltip(row)\" \r\n [disabled]=\"rowAction.disabled?.(row)\" \r\n [class]=\"rowAction.iconColor ? `rowActionIconColor${rowAction.iconColor}` : ''\"\r\n (click)=\"onRowActionClick(row, rowAction, $event)\">\r\n <mat-icon>{{rowAction.icon}}</mat-icon>\r\n </button>\r\n } \r\n }\r\n\r\n @if(config()().update && !config()().clickOnRowForUpdate && (!config()().update?.show || config()().update?.show(row))) {\r\n <button \r\n matIconButton\r\n [matTooltip]=\"config()().update?.tooltip?.(row) ?? texts().table.edit\" \r\n [disabled]=\"config()().update?.disabled?.(row)\" \r\n class=\"editButtonIcon\"\r\n (click)=\"onUpdateClick(row, $event)\">\r\n <mat-icon>edit_square</mat-icon>\r\n </button>\r\n }\r\n \r\n @if(config()().delete && (!config()().delete?.show || config()().delete?.show(row))) {\r\n <button \r\n matIconButton \r\n [matTooltip]=\"config()().delete?.tooltip?.(row) ?? texts().table.delete\" \r\n [disabled]=\"config()().delete?.disabled?.(row)\" \r\n class=\"deleteButtonIcon\"\r\n (click)=\"onDeleteClick(row, $event)\">\r\n <mat-icon>delete</mat-icon>\r\n </button>\r\n }\r\n </div>\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n\r\n @if(showTotalGeneralFooter()) {\r\n <ng-container [matColumnDef]=\"`${generalFooterKeyPrefix}${nameOfActionsColumn}`\" [stickyEnd]=\"isDesktop()\">\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n }\r\n }\r\n\r\n @if(config()().expandableDetail) {\r\n <ng-container [matColumnDef]=\"expandableColumnDef\">\r\n <td mat-cell *matCellDef=\"let row\" [attr.colspan]=\"keys().length\">\r\n <div \r\n class=\"detailWrapper\"\r\n [class.detailWrapperExpanded]=\"rowIsExpanded(row)\">\r\n <div class=\"columnDetail\">\r\n @if(config()().expandableDetailTemplateRef) {\r\n <ng-container \r\n *ngTemplateOutlet=\"config()().expandableDetailTemplateRef!(); \r\n context: { $implicit: row }\" />\r\n }\r\n </div>\r\n </div>\r\n </td>\r\n </ng-container>\r\n }\r\n \r\n <tr mat-header-row *matHeaderRowDef=\"keys(); sticky: true\" class=\"tableHeader\"></tr>\r\n \r\n @if(showFiltersRow()) {\r\n <tr mat-header-row *matHeaderRowDef=\"keysWithFilter(); sticky: true\" class=\"filtersByColumn\"></tr>\r\n }\r\n \r\n <tr mat-row *matRowDef=\"let row; columns: keys();\" \r\n (click)=\"onRowClick(row)\" \r\n [class.rowClickEnable]=\"isRowEnabled(row)\"\r\n [class.expandableRow]=\"config()().expandableDetail\">\r\n </tr>\r\n \r\n @if(config()().expandableDetail) {\r\n <tr mat-row *matRowDef=\"let row; columns: [expandableColumnDef]\" class=\"rowDetail\"></tr>\r\n }\r\n\r\n <tr mat-footer-row \r\n *matFooterRowDef=\"showTotalPerPageFooter() ? keys() : []\" \r\n class=\"totalPerPageFooter\"\r\n [class.hideFooter]=\"!showTotalPerPageFooter()\">\r\n </tr>\r\n\r\n <tr mat-footer-row \r\n *matFooterRowDef=\"showTotalGeneralFooter() ? keysWithGeneralFooter() : []\" \r\n class=\"totalFooter\"\r\n [class.hideFooter]=\"!showTotalGeneralFooter()\">\r\n </tr>\r\n\r\n <tr class=\"mat-row\" *matNoDataRow>\r\n <td class=\"noData\" [colSpan]=\"keys().length\">{{ loading() ? texts().common.loading : texts().common.noData }}</td>\r\n </tr>\r\n </table>\r\n </div>\r\n\r\n <div class=\"paginatorContainer\">\r\n <div class=\"footerLegend\">\r\n @if(showTotalPerPageFooter()) {\r\n <div class=\"legendItem\">\r\n <div class=\"legendSquare\"></div>\r\n <p>{{ texts().table.totalPerPage }}</p> \r\n </div>\r\n }\r\n\r\n @if(showTotalGeneralFooter()) {\r\n <div class=\"legendItem\">\r\n <div class=\"legendSquare totalGeneral\"></div>\r\n <p>{{ texts().table.totalGeneral }}</p>\r\n </div>\r\n }\r\n </div>\r\n <mat-paginator />\r\n </div>\r\n\r\n <ng-content select=\"[end-container]\"></ng-content>\r\n </div>\r\n</ng-template>", styles: [".tableContainer{display:flex;flex-direction:column;padding:14px;gap:10px;--mat-table-background-color: transparent;--mat-table-header-headline-color: var(--mat-sys-on-primary)}.inFullScreenMode{height:calc(100vh - 28px);width:calc(100vw - 28px);max-width:calc(100% - 28px);background:var(--mat-sys-surface)}.title{font:var(--mat-sys-title-large);color:var(--mat-sys-on-surface);margin:0;position:relative}.headerContainer{display:flex;justify-content:space-between;gap:10px;flex-direction:column}.titleAndButtonContainer{display:flex;justify-content:space-between;align-items:center;gap:20px}.buttonContainer{display:flex;gap:10px;align-items:center}.filterContainer{display:flex;flex-direction:row;align-items:center;gap:20px;justify-content:space-between}.moreFiltersContainer{display:flex;gap:20px}.editButtonIcon{--mat-icon-button-icon-color: var(--warning)}.deleteButtonIcon{--mat-icon-button-icon-color: var(--mat-sys-error)}.rowActionIconColorYellow{--mat-icon-button-icon-color: rgb(211, 211, 7)}.rowActionIconColorOrange{--mat-icon-button-icon-color: orange}.rowActionIconColorPink{--mat-icon-button-icon-color: pink}.rowActionIconColorPurple{--mat-icon-button-icon-color: purple}.rowActionIconColorGreen{--mat-icon-button-icon-color: var(--success)}.rowActionIconColorBlue{--mat-icon-button-icon-color: var(--information)}.rowActionIconColorBrown{--mat-icon-button-icon-color: brown}.rowActionIconColorSky{--mat-icon-button-icon-color: rgb(0, 247, 255)}.noData{padding:24px}.tableOverflow{overflow:auto;border-radius:10px}.columnLabel{text-wrap:nowrap}.headerTitle{display:flex;align-items:center;gap:4px}.headerTitle mat-icon{font-size:12px;width:12px;height:12px}.tableHeader{background-color:var(--mat-sys-primary)!important}.filtersByColumn{background-color:var(--mat-sys-surface)!important}.filtersByColumn th{padding:0}.celdaDatos{background-color:var(--mat-sys-surface)!important;transition:background-color .1s}.celdaAcciones,.celdaSelection{cursor:default!important;background-color:var(--mat-sys-surface)!important;transition:background-color .1s}.columnSticky{background-color:var(--mat-sys-surface)!important;transition:background-color .1s}.contenedorCeldaAcciones{display:flex;align-items:center;cursor:default!important}.rowClickEnable{cursor:pointer;transition:background-color .1s}.rowClickEnable:hover,.rowClickEnable:hover>.celdaAcciones,.rowClickEnable:hover>.celdaSelection,.rowClickEnable:hover>.celdaDatos,.rowClickEnable:hover>.columnSticky{background-color:var(--mat-sys-surface-container)!important}.inputQueryColumn,.selectColumn,.dateColumn{--mat-form-field-outlined-focus-outline-color: transparent;--mat-form-field-outlined-outline-color: transparent;--mat-form-field-outlined-hover-outline-color: transparent}.advancedFiltersApplied{display:flex;flex-direction:row;justify-content:space-between;gap:20px;border-radius:10px;background-color:var(--warning);color:var(--on-warning);align-items:center;margin-top:10px;padding:5px 5px 5px 15px;cursor:pointer;transition:background-color .3s}.advancedFiltersApplied:hover:not(:has(button:hover)){background-color:color-mix(in srgb,var(--warning) 80%,transparent)}.advancedFiltersApplied p{margin:0}.rowDetail{height:0}.expandableRow td{border-bottom-width:0}.detailWrapper{overflow:hidden;display:grid;grid-template-rows:0fr;grid-template-columns:100%;transition:grid-template-rows 225ms cubic-bezier(.4,0,.2,1)}.detailWrapperExpanded{grid-template-rows:1fr}.columnDetail{display:flex;flex-direction:column;min-height:0}.totalPerPageFooter{font-weight:700}.totalFooter{font-weight:700;background-color:var(--mat-sys-surface-container-highest);color:var(--mat-sys-on-surface)}.hideFooter{display:none}.paginatorContainer{display:flex;flex-direction:row;justify-content:space-between;align-items:center;gap:20px;margin-top:10px}.footerLegend{display:flex;flex-direction:row;gap:30px}.footerLegend p{margin:0;font:var(--mat-sys-label-medium)}.legendItem{display:flex;flex-direction:row;align-items:center;gap:6px}.legendSquare{width:24px;height:14px;border-radius:4px;border:2px solid var(--mat-sys-on-surface)}.totalGeneral{background-color:var(--mat-sys-surface-container-highest)}.headerCheckbox{--mat-checkbox-selected-checkmark-color: var(--mat-sys-primary);--mat-checkbox-selected-focus-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-focus-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-selected-hover-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-hover-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-selected-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-pressed-icon-color: var(--mat-sys-on-primary);--mat-checkbox-selected-pressed-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-focus-icon-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-focus-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-hover-icon-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-hover-state-layer-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-icon-color: var(--mat-sys-on-primary);--mat-checkbox-unselected-pressed-state-layer-color: var(--mat-sys-on-primary)}@media (max-width: 1200px){.filterContainer{flex-direction:column;align-items:normal}.moreFiltersContainer{flex-direction:column}}@media (max-width: 900px){.footerLegend{flex-direction:column;gap:6px}}@media (max-width: 700px){.paginatorContainer{flex-direction:column;align-items:flex-end}}@media (max-width: 600px){.titleAndButtonContainer{flex-direction:column;align-items:normal}}\n"] }]
3192
3567
  }], propDecorators: { filters: [{ type: i0.Input, args: [{ isSignal: true, alias: "filters", required: false }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: true }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], queryFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "queryFilter", required: false }] }], moreFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "moreFilters", required: false }] }], createClick: [{ type: i0.Output, args: ["createClick"] }], updateClick: [{ type: i0.Output, args: ["updateClick"] }], deleteClick: [{ type: i0.Output, args: ["deleteClick"] }], rowActionClick: [{ type: i0.Output, args: ["rowActionClick"] }], expandedItemChange: [{ type: i0.Output, args: ["expandedItemChange"] }], selectionActionEvent: [{ type: i0.Output, args: ["selectionActionEvent"] }], tableContentTemplate: [{ type: i0.ViewChild, args: ['tableContent', { isSignal: true }] }], paginator: [{ type: i0.ViewChild, args: [i0.forwardRef(() => MatPaginator), { isSignal: true }] }], onEscape: [{
3193
3568
  type: HostListener,
3194
3569
  args: ['document:keydown.escape']
3195
3570
  }] } });
3196
3571
 
3572
+ const DEFAULT_ICONS = {
3573
+ info: 'info',
3574
+ success: 'check_circle',
3575
+ warning: 'warning',
3576
+ error: 'error',
3577
+ };
3197
3578
  class NgxAlert {
3579
+ _texts = inject(NgxTexts).texts;
3580
+ /** Gravedad del mensaje: define color, icono por defecto y cómo se anuncia. */
3198
3581
  type = input('info', ...(ngDevMode ? [{ debugName: "type" }] : []));
3582
+ /** Título en negrita sobre el mensaje. */
3199
3583
  title = input(...(ngDevMode ? [undefined, { debugName: "title" }] : []));
3584
+ /** Mensaje en texto plano. Para contenido con formato o enlaces, proyéctalo como contenido. */
3200
3585
  message = input(...(ngDevMode ? [undefined, { debugName: "message" }] : []));
3201
- iconName = computed(() => {
3202
- switch (this.type()) {
3203
- case 'warning': return 'warning';
3204
- case 'error': return 'error';
3205
- case 'success': return 'check_circle';
3206
- case 'info':
3207
- default: return 'info';
3586
+ /** Estilo visual: standard (fondo + franja lateral), soft (solo fondo) u outlined (solo borde). */
3587
+ appearance = input('standard', ...(ngDevMode ? [{ debugName: "appearance" }] : []));
3588
+ /** Icono de Material Symbols. Por defecto, el del tipo (info, check_circle, warning, error). */
3589
+ icon = input(...(ngDevMode ? [undefined, { debugName: "icon" }] : []));
3590
+ /** Oculta el icono. */
3591
+ hideIcon = input(false, ...(ngDevMode ? [{ debugName: "hideIcon", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
3592
+ /** Muestra un botón para cerrar el aviso. Al pulsarlo se oculta y emite `dismissed`. */
3593
+ dismissible = input(false, ...(ngDevMode ? [{ debugName: "dismissible", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
3594
+ /** Etiqueta accesible del botón de cerrar. Por defecto, el texto `alert.dismiss` de la librería. */
3595
+ dismissLabel = input(...(ngDevMode ? [undefined, { debugName: "dismissLabel" }] : []));
3596
+ /**
3597
+ * Cómo lo anuncia el lector de pantalla. assertive interrumpe (role="alert"), polite espera
3598
+ * a que termine (role="status") y off no lo anuncia. Por defecto: assertive para error y
3599
+ * warning, polite para info y success.
3600
+ */
3601
+ politeness = input(...(ngDevMode ? [undefined, { debugName: "politeness" }] : []));
3602
+ /** Se emite cuando el usuario cierra el aviso con el botón de cerrar. */
3603
+ dismissed = output();
3604
+ isDismissed = signal(false, ...(ngDevMode ? [{ debugName: "isDismissed" }] : []));
3605
+ resolvedIcon = computed(() => this.icon() || DEFAULT_ICONS[this.type()] || DEFAULT_ICONS.info, ...(ngDevMode ? [{ debugName: "resolvedIcon" }] : []));
3606
+ resolvedDismissLabel = computed(() => {
3607
+ return this.dismissLabel() ?? this._texts().alert.dismiss;
3608
+ }, ...(ngDevMode ? [{ debugName: "resolvedDismissLabel" }] : []));
3609
+ resolvedRole = computed(() => {
3610
+ const politeness = this.politeness()
3611
+ ?? (this.type() === 'error' || this.type() === 'warning' ? 'assertive' : 'polite');
3612
+ switch (politeness) {
3613
+ case 'assertive': return 'alert';
3614
+ case 'polite': return 'status';
3615
+ default: return null;
3208
3616
  }
3209
- }, ...(ngDevMode ? [{ debugName: "iconName" }] : []));
3617
+ }, ...(ngDevMode ? [{ debugName: "resolvedRole" }] : []));
3618
+ dismiss() {
3619
+ this.isDismissed.set(true);
3620
+ this.dismissed.emit();
3621
+ }
3210
3622
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxAlert, deps: [], target: i0.ɵɵFactoryTarget.Component });
3211
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: NgxAlert, isStandalone: true, selector: "ngx-alert", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"alert\" [class]=\"type()\">\n <div class=\"icon-wrapper\">\n <mat-icon>{{ iconName() }}</mat-icon>\n </div>\n <div class=\"content\">\n @if (title()) {\n <div class=\"title\">{{ title() }}</div>\n }\n <div class=\"description\">\n @if (message()) {\n {{ message() }}\n } @else {\n <ng-content />\n }\n </div>\n </div>\n</div>\n", styles: [":host{display:block}.alert{display:flex;gap:16px;padding:16px;border-left-width:4px;border-left-style:solid;border-radius:4px;box-shadow:0 1px 2px #0000001a;margin-bottom:24px}.alert .icon-wrapper{display:flex;align-items:flex-start;padding-top:2px}.alert .content{display:flex;flex-direction:column;gap:4px;flex:1}.alert .content .title{font-weight:600;font-size:16px}.alert .content .description{margin:0;font-size:14px;line-height:1.5}.alert.warning{background-color:#fff8e1;border-left-color:#ffc107}.alert.warning .icon-wrapper mat-icon{color:#ffb300}.alert.warning .content .title{color:#4e342e}.alert.warning .content .description{color:#5d4037}.alert.error{background-color:#ffebee;border-left-color:#f44336}.alert.error .icon-wrapper mat-icon{color:#d32f2f}.alert.error .content .title{color:#b71c1c}.alert.error .content .description{color:#c62828}.alert.info{background-color:#e3f2fd;border-left-color:#2196f3}.alert.info .icon-wrapper mat-icon{color:#1976d2}.alert.info .content .title{color:#0d47a1}.alert.info .content .description{color:#1565c0}.alert.success{background-color:#e8f5e9;border-left-color:#4caf50}.alert.success .icon-wrapper mat-icon{color:#2e7d32}.alert.success .content .title{color:#1b5e20}.alert.success .content .description{color:#2e7d32}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
3623
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: NgxAlert, isStandalone: true, selector: "ngx-alert", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, hideIcon: { classPropertyName: "hideIcon", publicName: "hideIcon", isSignal: true, isRequired: false, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null }, dismissLabel: { classPropertyName: "dismissLabel", publicName: "dismissLabel", isSignal: true, isRequired: false, transformFunction: null }, politeness: { classPropertyName: "politeness", publicName: "politeness", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dismissed: "dismissed" }, host: { properties: { "attr.role": "isDismissed() ? null : resolvedRole()", "class.ngx-alert--dismissed": "isDismissed()" } }, ngImport: i0, template: "@if (!isDismissed()) {\n <div class=\"alert\" [class]=\"'alert alert--' + type() + ' alert--' + appearance()\">\n @if (!hideIcon()) {\n <mat-icon class=\"alert__icon\" aria-hidden=\"true\">{{ resolvedIcon() }}</mat-icon>\n }\n\n <div class=\"alert__content\">\n @if (title()) {\n <div class=\"alert__title\">{{ title() }}</div>\n }\n\n <div class=\"alert__description\">\n @if (message()) {\n <p class=\"alert__message\">{{ message() }}</p>\n }\n <ng-content />\n </div>\n\n <div class=\"alert__actions\">\n <ng-content select=\"[alertActions]\" />\n </div>\n </div>\n\n @if (dismissible()) {\n <button\n type=\"button\"\n class=\"alert__dismiss\"\n matIconButton\n [attr.aria-label]=\"resolvedDismissLabel()\"\n [matTooltip]=\"resolvedDismissLabel()\"\n (click)=\"dismiss()\">\n <mat-icon>close</mat-icon>\n </button>\n }\n </div>\n}\n", styles: [":host{display:block}:host(.ngx-alert--dismissed){display:none}.alert{--_accent: var(--ngx-alert-info-color, #1a73e8);--_container: color-mix(in srgb, var(--_accent) 12%, var(--mat-sys-surface));--_icon: color-mix(in srgb, var(--_accent) 85%, var(--mat-sys-on-surface));display:flex;align-items:flex-start;gap:12px;padding:14px 16px;border-radius:var(--ngx-alert-radius, 12px);color:var(--mat-sys-on-surface)}.alert--success{--_accent: var(--ngx-alert-success-color, #1e8e3e)}.alert--warning{--_accent: var(--ngx-alert-warning-color, #e37400)}.alert--error{--_accent: var(--ngx-alert-error-color, var(--mat-sys-error))}.alert--standard{background-color:var(--_container);box-shadow:inset 4px 0 0 var(--_accent);padding-left:20px}.alert--soft{background-color:var(--_container)}.alert--outlined{background-color:transparent;border:1px solid color-mix(in srgb,var(--_accent) 55%,var(--mat-sys-surface))}.alert__icon{flex:none;margin-top:1px;color:var(--_icon)}.alert__content{display:flex;flex:1;flex-direction:column;gap:4px;min-width:0}.alert__title{font:var(--mat-sys-title-small);color:var(--mat-sys-on-surface)}.alert__description{font:var(--mat-sys-body-medium);color:var(--mat-sys-on-surface-variant);overflow-wrap:anywhere}.alert__description ::ng-deep>:first-child{margin-top:0}.alert__description ::ng-deep>:last-child{margin-bottom:0}.alert__description ::ng-deep a{color:var(--_icon)}.alert__message{margin:0}.alert__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:8px}.alert__actions:empty{display:none}.alert__dismiss{flex:none;margin:-8px -8px -8px 0;color:var(--mat-sys-on-surface-variant)}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3212
3624
  }
3213
3625
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxAlert, decorators: [{
3214
3626
  type: Component,
3215
- args: [{ selector: 'ngx-alert', imports: [
3216
- MatIconModule
3217
- ], template: "<div class=\"alert\" [class]=\"type()\">\n <div class=\"icon-wrapper\">\n <mat-icon>{{ iconName() }}</mat-icon>\n </div>\n <div class=\"content\">\n @if (title()) {\n <div class=\"title\">{{ title() }}</div>\n }\n <div class=\"description\">\n @if (message()) {\n {{ message() }}\n } @else {\n <ng-content />\n }\n </div>\n </div>\n</div>\n", styles: [":host{display:block}.alert{display:flex;gap:16px;padding:16px;border-left-width:4px;border-left-style:solid;border-radius:4px;box-shadow:0 1px 2px #0000001a;margin-bottom:24px}.alert .icon-wrapper{display:flex;align-items:flex-start;padding-top:2px}.alert .content{display:flex;flex-direction:column;gap:4px;flex:1}.alert .content .title{font-weight:600;font-size:16px}.alert .content .description{margin:0;font-size:14px;line-height:1.5}.alert.warning{background-color:#fff8e1;border-left-color:#ffc107}.alert.warning .icon-wrapper mat-icon{color:#ffb300}.alert.warning .content .title{color:#4e342e}.alert.warning .content .description{color:#5d4037}.alert.error{background-color:#ffebee;border-left-color:#f44336}.alert.error .icon-wrapper mat-icon{color:#d32f2f}.alert.error .content .title{color:#b71c1c}.alert.error .content .description{color:#c62828}.alert.info{background-color:#e3f2fd;border-left-color:#2196f3}.alert.info .icon-wrapper mat-icon{color:#1976d2}.alert.info .content .title{color:#0d47a1}.alert.info .content .description{color:#1565c0}.alert.success{background-color:#e8f5e9;border-left-color:#4caf50}.alert.success .icon-wrapper mat-icon{color:#2e7d32}.alert.success .content .title{color:#1b5e20}.alert.success .content .description{color:#2e7d32}\n"] }]
3218
- }], propDecorators: { type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: false }] }] } });
3627
+ args: [{ selector: 'ngx-alert', imports: [MatIconModule, MatButtonModule, MatTooltipModule], changeDetection: ChangeDetectionStrategy.OnPush, host: {
3628
+ '[attr.role]': 'isDismissed() ? null : resolvedRole()',
3629
+ '[class.ngx-alert--dismissed]': 'isDismissed()',
3630
+ }, template: "@if (!isDismissed()) {\n <div class=\"alert\" [class]=\"'alert alert--' + type() + ' alert--' + appearance()\">\n @if (!hideIcon()) {\n <mat-icon class=\"alert__icon\" aria-hidden=\"true\">{{ resolvedIcon() }}</mat-icon>\n }\n\n <div class=\"alert__content\">\n @if (title()) {\n <div class=\"alert__title\">{{ title() }}</div>\n }\n\n <div class=\"alert__description\">\n @if (message()) {\n <p class=\"alert__message\">{{ message() }}</p>\n }\n <ng-content />\n </div>\n\n <div class=\"alert__actions\">\n <ng-content select=\"[alertActions]\" />\n </div>\n </div>\n\n @if (dismissible()) {\n <button\n type=\"button\"\n class=\"alert__dismiss\"\n matIconButton\n [attr.aria-label]=\"resolvedDismissLabel()\"\n [matTooltip]=\"resolvedDismissLabel()\"\n (click)=\"dismiss()\">\n <mat-icon>close</mat-icon>\n </button>\n }\n </div>\n}\n", styles: [":host{display:block}:host(.ngx-alert--dismissed){display:none}.alert{--_accent: var(--ngx-alert-info-color, #1a73e8);--_container: color-mix(in srgb, var(--_accent) 12%, var(--mat-sys-surface));--_icon: color-mix(in srgb, var(--_accent) 85%, var(--mat-sys-on-surface));display:flex;align-items:flex-start;gap:12px;padding:14px 16px;border-radius:var(--ngx-alert-radius, 12px);color:var(--mat-sys-on-surface)}.alert--success{--_accent: var(--ngx-alert-success-color, #1e8e3e)}.alert--warning{--_accent: var(--ngx-alert-warning-color, #e37400)}.alert--error{--_accent: var(--ngx-alert-error-color, var(--mat-sys-error))}.alert--standard{background-color:var(--_container);box-shadow:inset 4px 0 0 var(--_accent);padding-left:20px}.alert--soft{background-color:var(--_container)}.alert--outlined{background-color:transparent;border:1px solid color-mix(in srgb,var(--_accent) 55%,var(--mat-sys-surface))}.alert__icon{flex:none;margin-top:1px;color:var(--_icon)}.alert__content{display:flex;flex:1;flex-direction:column;gap:4px;min-width:0}.alert__title{font:var(--mat-sys-title-small);color:var(--mat-sys-on-surface)}.alert__description{font:var(--mat-sys-body-medium);color:var(--mat-sys-on-surface-variant);overflow-wrap:anywhere}.alert__description ::ng-deep>:first-child{margin-top:0}.alert__description ::ng-deep>:last-child{margin-bottom:0}.alert__description ::ng-deep a{color:var(--_icon)}.alert__message{margin:0}.alert__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:8px}.alert__actions:empty{display:none}.alert__dismiss{flex:none;margin:-8px -8px -8px 0;color:var(--mat-sys-on-surface-variant)}\n"] }]
3631
+ }], propDecorators: { type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], hideIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideIcon", required: false }] }], dismissible: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissible", required: false }] }], dismissLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissLabel", required: false }] }], politeness: [{ type: i0.Input, args: [{ isSignal: true, alias: "politeness", required: false }] }], dismissed: [{ type: i0.Output, args: ["dismissed"] }] } });
3219
3632
 
3220
3633
  class NgxPaginatedSelectBottomSheetComponent {
3221
3634
  // ─── Dependencies ──────────────────────────────────────────────────────────
3222
3635
  _ref = inject((MatBottomSheetRef));
3223
3636
  _destroy = inject(DestroyRef);
3224
3637
  data = inject(MAT_BOTTOM_SHEET_DATA);
3225
- intl = inject(NgxTablesIntl);
3638
+ texts = inject(NgxTexts).texts;
3226
3639
  // ─── State ─────────────────────────────────────────────────────────────────
3227
3640
  /** Raw input value — updates on every keystroke, does NOT trigger the resource */
3228
3641
  query = signal(this.data.filters().query, ...(ngDevMode ? [{ debugName: "query" }] : []));
@@ -3502,7 +3915,7 @@ class NgxPaginatedSelectBottomSheetComponent {
3502
3915
  this._ref.dismiss(undefined);
3503
3916
  }
3504
3917
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxPaginatedSelectBottomSheetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3505
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: NgxPaginatedSelectBottomSheetComponent, isStandalone: true, selector: "ngx-paginated-select-bottom-sheet", ngImport: i0, template: "<div class=\"ps-bs\">\n\n <!-- \u2500\u2500 Handle bar (mobile) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"ps-bs__handle\">\n <div class=\"ps-bs__handle-bar\"></div>\n </div>\n\n <!-- \u2500\u2500 Header (pinned: title + search only) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"ps-bs__header\" [class.ps-bs__header--scrolled]=\"headerScrolled()\">\n <div class=\"ps-bs__header-top\">\n <div class=\"ps-bs__title-area\">\n <span class=\"ps-bs__title\">{{ data.title }}</span>\n @if (data.multiple && selectedCount() > 0) {\n <span class=\"ps-bs__badge\">{{ selectedCount() }}</span>\n }\n </div>\n <button mat-icon-button class=\"ps-bs__close-btn\" [attr.aria-label]=\"intl.closeButtonLabel\" (click)=\"close()\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n\n <!-- Pill search -->\n @if (data.showSearch) {\n <div class=\"ps-bs__search\">\n <mat-icon class=\"ps-bs__search-icon\">search</mat-icon>\n <input\n class=\"ps-bs__search-input\"\n #searchInput\n type=\"text\"\n [value]=\"query() ?? ''\"\n [placeholder]=\"data.searchPlaceholder\"\n (input)=\"onQueryInput($event, bodyContainer)\"\n />\n @if (searchInput.value.length > 0) {\n <button\n class=\"ps-bs__search-clear\"\n type=\"button\"\n [attr.aria-label]=\"intl.clearSearchTooltip\"\n (click)=\"clearQuery(bodyContainer); $event.stopPropagation()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n }\n </div>\n }\n </div>\n\n <!-- \u2500\u2500 Body (\u00DANICA zona de scroll: filtros + chips + select-all + lista) \u2500\u2500\u2500\u2500 -->\n <div class=\"ps-bs__body\" #bodyContainer (scroll)=\"onScroll(bodyContainer)\">\n\n <!-- Extra filters projection -->\n @if (data.extraFiltersTemplate) {\n <div class=\"ps-bs__extra-filters\">\n <ng-container *ngTemplateOutlet=\"data.extraFiltersTemplate\" />\n </div>\n }\n\n <!-- Selected chips (custom lightweight chips) -->\n @if (data.multiple && selectedItems().length > 0) {\n <div class=\"ps-bs__selected-chips\">\n @for (item of selectedItems(); track item[data.config.valueKey]) {\n <div class=\"ps-bs__chip\">\n <span class=\"ps-bs__chip-label\">{{ getLabel(item) }}</span>\n <button class=\"ps-bs__chip-remove\" type=\"button\" [attr.aria-label]=\"intl.clearSearchTooltip\" (click)=\"removeSelectedChip(item)\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n }\n </div>\n }\n\n <!-- Select all (sticky top of the scroll area) -->\n @if (data.multiple && data.showSelectAll && options().length > 0) {\n <div class=\"ps-bs__select-all\" matRipple (click)=\"toggleSelectAll()\">\n <mat-checkbox\n [checked]=\"allSelected()\"\n [indeterminate]=\"someSelected()\"\n (click)=\"$event.preventDefault()\"\n />\n <span class=\"ps-bs__select-all-label\">{{ data.selectAllLabel }}</span>\n </div>\n }\n\n <!-- \u2500\u2500 Options list \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"ps-bs__list\">\n\n <!-- Skeleton loading (only for the first page) -->\n @if (isInitialLoading()) {\n @for (i of [1, 2, 3, 4, 5, 6]; track i) {\n <div class=\"ps-bs__skeleton\">\n <div class=\"ps-bs__skeleton-avatar\"></div>\n <div class=\"ps-bs__skeleton-content\">\n <div class=\"ps-bs__skeleton-line ps-bs__skeleton-line--title\"></div>\n <div class=\"ps-bs__skeleton-line ps-bs__skeleton-line--subtitle\"></div>\n </div>\n </div>\n }\n }\n\n <!-- Error state -->\n @if (hasError() && !isLoading() && options().length === 0) {\n <div class=\"ps-bs__state ps-bs__error\">\n <div class=\"ps-bs__state-icon-wrap ps-bs__error-icon-wrap\">\n <mat-icon>error_outline</mat-icon>\n </div>\n <div class=\"ps-bs__state-title\">{{ intl.paginatedSelectErrorTitle }}</div>\n <div class=\"ps-bs__state-hint\">{{ intl.paginatedSelectErrorHint }}</div>\n <button matButton=\"tonal\" (click)=\"retry()\">\n <mat-icon>refresh</mat-icon>\n {{ intl.paginatedSelectRetryLabel }}\n </button>\n </div>\n }\n\n <!-- Empty state -->\n @if (!hasError() && options().length === 0 && !isLoading()) {\n <div class=\"ps-bs__state ps-bs__empty\">\n <div class=\"ps-bs__state-icon-wrap\">\n <mat-icon>search_off</mat-icon>\n </div>\n <div class=\"ps-bs__state-title\">{{ data.noResultsMessage }}</div>\n @if (query()) {\n <div class=\"ps-bs__state-hint\">{{ intl.paginatedSelectNoResultsHint }}</div>\n <button matButton (click)=\"clearQuery(bodyContainer)\">\n {{ intl.paginatedSelectClearSearchLabel }}\n </button>\n }\n </div>\n }\n\n <!-- Option rows -->\n @for (item of options(); track item[data.config.valueKey]) {\n @let disabled = data.config.disabled ? data.config.disabled(item) : false;\n @let selected = isSelected(item);\n @let avatarImg = getAvatarImage(item);\n\n <div\n class=\"ps-bs__option\"\n [class.ps-bs__option--selected]=\"selected\"\n [class.ps-bs__option--disabled]=\"disabled\"\n matRipple\n [matRippleDisabled]=\"disabled\"\n (click)=\"toggleItem(item)\"\n role=\"option\"\n [attr.aria-selected]=\"selected\"\n [attr.aria-disabled]=\"disabled\"\n >\n <!-- Avatar (al seleccionar se voltea a un check, estilo Gmail) -->\n <div class=\"ps-bs__option-avatar\" [class.ps-bs__option-avatar--selected]=\"selected\">\n @if (selected) {\n <mat-icon class=\"ps-bs__option-avatar-check\">check</mat-icon>\n } @else if (avatarImg) {\n <img [src]=\"avatarImg\" [alt]=\"getLabel(item)\" (error)=\"onAvatarError(item)\" loading=\"lazy\" />\n } @else if (data.config.avatarText) {\n {{ getAvatarText(item) }}\n } @else if (data.config.avatarIcon) {\n <mat-icon>{{ data.config.avatarIcon }}</mat-icon>\n } @else {\n {{ getAvatarText(item) }}\n }\n </div>\n\n <!-- Content -->\n <div class=\"ps-bs__option-content\">\n @if (data.optionTemplate) {\n <ng-container *ngTemplateOutlet=\"data.optionTemplate; context: { $implicit: item }\" />\n } @else {\n <span class=\"ps-bs__option-label\">{{ getLabel(item) }}</span>\n @if (data.config.subtitle) {\n <span class=\"ps-bs__option-subtitle\">{{ data.config.subtitle(item) }}</span>\n }\n }\n </div>\n\n <!-- Check indicator -->\n @if (data.multiple) {\n <mat-checkbox [checked]=\"selected\" [disabled]=\"disabled\" (click)=\"$event.preventDefault()\" />\n } @else if (selected) {\n <mat-icon class=\"ps-bs__option-check\">check_circle</mat-icon>\n }\n </div>\n }\n\n <!-- Loading more (pagination) / end of list -->\n @if (isLoadingMore()) {\n <div class=\"ps-bs__loading-more\" aria-live=\"polite\">\n <span class=\"ps-bs__loading-more-dot\"></span>\n <span class=\"ps-bs__loading-more-dot\"></span>\n <span class=\"ps-bs__loading-more-dot\"></span>\n <span class=\"ps-bs__loading-more-text\">{{ intl.paginatedSelectLoadingMoreLabel }}</span>\n </div>\n } @else if (allLoaded() && options().length > 0) {\n <div class=\"ps-bs__list-end\">{{ intl.paginatedSelectEndOfListLabel }}</div>\n }\n </div>\n </div>\n\n <!-- \u2500\u2500 Footer (ALWAYS VISIBLE \u2014 never scrolls) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"ps-bs__footer\">\n <span class=\"ps-bs__footer-count\">\n @if (data.multiple) {\n {{ intl.getPaginatedSelectSelectedCountLabel(selectedCount(), total()) }}\n } @else {\n {{ intl.getPaginatedSelectResultsCountLabel(total()) }}\n }\n </span>\n\n @if (data.multiple) {\n <div class=\"ps-bs__footer-actions\">\n @if (selectedCount() > 0) {\n <button matButton (click)=\"reset()\">{{ data.resetLabel }}</button>\n }\n <button matButton=\"filled\" color=\"primary\" (click)=\"confirm()\">{{ data.confirmLabel }}</button>\n </div>\n }\n </div>\n</div>\n", styles: [".cdk-global-overlay-wrapper:has(.ngx-paginated-select-panel){align-items:center!important;justify-content:center!important}.ngx-paginated-select-backdrop{background:color-mix(in srgb,var(--mat-sys-scrim, #000) 40%,transparent);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.ngx-paginated-select-panel .mat-bottom-sheet-container{padding:0!important;overflow:hidden!important;display:flex!important;flex-direction:column!important;width:min(640px,100vw - 48px);min-width:0;max-width:640px;height:min(86vh,760px)!important;max-height:min(86vh,760px)!important;border-radius:28px;background:var(--mat-sys-surface-container-high);border:1px solid color-mix(in srgb,var(--mat-sys-outline-variant) 60%,transparent);box-shadow:0 1px 3px #0000001f,0 8px 24px #00000024,0 24px 48px #0000001a!important}ngx-paginated-select-bottom-sheet{display:flex;flex-direction:column;flex:1 1 0;min-height:0;overflow:hidden;width:100%}.ps-bs{display:flex;flex-direction:column;height:100%;overflow:hidden}.ps-bs__handle{display:none;justify-content:center;padding:12px 0 4px;flex:0 0 auto}.ps-bs__handle-bar{width:32px;height:4px;border-radius:9999px;background:var(--mat-sys-outline-variant)}.ps-bs__header{flex:0 0 auto;padding:20px 24px 14px;display:flex;flex-direction:column;gap:14px;position:relative;z-index:2;transition:box-shadow .2s cubic-bezier(.2,0,0,1)}.ps-bs__header--scrolled{box-shadow:0 1px 0 0 var(--mat-sys-outline-variant),0 6px 14px -10px #00000059}.ps-bs__header-top{display:flex;align-items:center;justify-content:space-between;gap:8px}.ps-bs__title-area{display:flex;align-items:center;gap:10px;flex:1;min-width:0}.ps-bs__title{font:var(--mat-sys-title-large);font-weight:600;color:var(--mat-sys-on-surface);letter-spacing:-.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ps-bs__badge{display:inline-flex;align-items:center;justify-content:center;min-width:22px;height:22px;padding:0 7px;border-radius:9999px;font:var(--mat-sys-label-medium);font-weight:700;font-variant-numeric:tabular-nums;background:var(--mat-sys-primary);color:var(--mat-sys-on-primary);flex-shrink:0;animation:ps-badge-pop .3s cubic-bezier(.34,1.56,.64,1)}@keyframes ps-badge-pop{0%{transform:scale(0)}to{transform:scale(1)}}.ps-bs__close-btn{flex:0 0 auto}.ps-bs__search{display:flex;align-items:center;gap:10px;height:48px;padding:0 6px 0 16px;background:var(--mat-sys-surface-container-highest);border-radius:9999px;border:1.5px solid transparent;transition:background .2s cubic-bezier(.2,0,0,1),border-color .2s cubic-bezier(.2,0,0,1),box-shadow .2s cubic-bezier(.2,0,0,1)}.ps-bs__search:hover{background:color-mix(in srgb,var(--mat-sys-on-surface) 4%,var(--mat-sys-surface-container-highest))}.ps-bs__search:focus-within{background:var(--mat-sys-surface);border-color:var(--mat-sys-primary);box-shadow:0 0 0 4px color-mix(in srgb,var(--mat-sys-primary) 12%,transparent)}.ps-bs__search-icon{color:var(--mat-sys-on-surface-variant);font-size:22px;width:22px;height:22px;flex-shrink:0;transition:color .2s cubic-bezier(.2,0,0,1)}.ps-bs__search:focus-within .ps-bs__search-icon{color:var(--mat-sys-primary)}.ps-bs__search-input{flex:1;border:none;outline:none;background:transparent;font:var(--mat-sys-body-large);font-family:inherit;color:var(--mat-sys-on-surface);min-width:0}.ps-bs__search-input::placeholder{color:var(--mat-sys-on-surface-variant)}.ps-bs__search-clear{display:flex;align-items:center;justify-content:center;width:34px;height:34px;border-radius:50%;border:none;background:transparent;cursor:pointer;color:var(--mat-sys-on-surface-variant);transition:background .15s cubic-bezier(.2,0,0,1);flex-shrink:0}.ps-bs__search-clear:hover{background:color-mix(in srgb,var(--mat-sys-on-surface) 10%,transparent)}.ps-bs__search-clear mat-icon{font-size:20px;width:20px;height:20px}.ps-bs__body{flex:1 1 auto;min-height:0;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;padding:6px 10px 8px;display:flex;flex-direction:column}.ps-bs__body>*{flex-shrink:0}.ps-bs__extra-filters{width:100%;padding:10px 6px 6px}.ps-bs__selected-chips{display:flex;flex-wrap:wrap;gap:8px;padding:4px 6px 6px}.ps-bs__chip{display:inline-flex;align-items:center;gap:2px;height:32px;padding:0 4px 0 12px;border-radius:9999px;background:var(--mat-sys-secondary-container);color:var(--mat-sys-on-secondary-container);font:var(--mat-sys-label-large);white-space:nowrap;max-width:200px;animation:ps-chip-in .2s cubic-bezier(.2,0,0,1)}.ps-bs__chip-label{overflow:hidden;text-overflow:ellipsis}.ps-bs__chip-remove{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:50%;border:none;background:transparent;cursor:pointer;color:inherit;opacity:.55;transition:opacity .15s,background .15s}.ps-bs__chip-remove:hover{opacity:1;background:color-mix(in srgb,var(--mat-sys-on-secondary-container) 12%,transparent)}.ps-bs__chip-remove mat-icon{font-size:16px;width:16px;height:16px}@keyframes ps-chip-in{0%{transform:scale(.85);opacity:0}to{transform:scale(1);opacity:1}}.ps-bs__select-all.ps-bs__select-all{position:sticky;top:-6px;z-index:3;display:flex;align-items:center;gap:12px;margin:0 -10px;padding:8px 24px;cursor:pointer;background:var(--mat-sys-surface-container-high);border-bottom:1px solid var(--mat-sys-outline-variant);transition:background .15s cubic-bezier(.2,0,0,1)}.ps-bs__select-all.ps-bs__select-all:hover{background:color-mix(in srgb,var(--mat-sys-on-surface) 5%,var(--mat-sys-surface-container-high))}.ps-bs__select-all.ps-bs__select-all-label{font:var(--mat-sys-label-large);color:var(--mat-sys-on-surface)}.ps-bs__list{flex:1 1 auto}.ps-bs__option{display:flex;align-items:center;gap:14px;padding:8px 12px;margin:2px 0;cursor:pointer;border-radius:16px;min-height:56px;transition:background .15s cubic-bezier(.2,0,0,1)}.ps-bs__option:hover:not(.ps-bs__option--disabled){background:color-mix(in srgb,var(--mat-sys-on-surface) 8%,transparent)}.ps-bs__option:active:not(.ps-bs__option--disabled){background:color-mix(in srgb,var(--mat-sys-on-surface) 12%,transparent)}.ps-bs__option--selected{background:color-mix(in srgb,var(--mat-sys-primary) 10%,transparent)}.ps-bs__option--selected:hover{background:color-mix(in srgb,var(--mat-sys-primary) 14%,transparent)}.ps-bs__option--disabled{opacity:.38;cursor:not-allowed}.ps-bs__option .mat-ripple-element{background:color-mix(in srgb,var(--mat-sys-primary) 12%,transparent)}.ps-bs__option .mat-mdc-checkbox{margin-left:auto;margin-right:-8px;flex-shrink:0}.ps-bs__option-avatar{width:40px;height:40px;min-width:40px;border-radius:50%;overflow:hidden;display:flex;align-items:center;justify-content:center;font:var(--mat-sys-label-large);font-weight:600;background:var(--mat-sys-primary-container);color:var(--mat-sys-on-primary-container);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--mat-sys-on-surface) 8%,transparent);transition:box-shadow .18s cubic-bezier(.2,0,0,1)}.ps-bs__option-avatar img{width:100%;height:100%;object-fit:cover;display:block}.ps-bs__option-avatar mat-icon{font-size:20px;width:20px;height:20px}.ps-bs__option-avatar--selected{background:var(--mat-sys-primary);color:var(--mat-sys-on-primary);box-shadow:none;animation:ps-avatar-flip .25s cubic-bezier(.05,.7,.1,1)}.ps-bs__option-avatar-check{color:var(--mat-sys-on-primary)}@keyframes ps-avatar-flip{0%{transform:scale(.6) rotate(-30deg);opacity:.4}to{transform:scale(1) rotate(0);opacity:1}}.ps-bs__option-content{flex:1;display:flex;flex-direction:column;gap:2px;min-width:0}.ps-bs__option-label{font:var(--mat-sys-body-large);color:var(--mat-sys-on-surface);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ps-bs__option--selected .ps-bs__option-label{font-weight:600}.ps-bs__option-subtitle{font:var(--mat-sys-body-small);color:var(--mat-sys-on-surface-variant);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ps-bs__option-check{color:var(--mat-sys-primary);font-size:22px;width:22px;height:22px;margin-left:auto;flex-shrink:0}.ps-bs__skeleton{display:flex;align-items:center;gap:14px;padding:8px 12px;margin:2px 0;min-height:56px;border-radius:16px;opacity:0;animation:ps-skeleton-in .4s ease forwards}.ps-bs__skeleton-avatar{width:40px;height:40px;min-width:40px;border-radius:50%;background:linear-gradient(90deg,var(--mat-sys-surface-container) 25%,var(--mat-sys-surface-container-highest) 37%,var(--mat-sys-surface-container) 63%);background-size:400% 100%;animation:ps-shimmer 1.4s ease-in-out infinite}.ps-bs__skeleton-content{flex:1;display:flex;flex-direction:column;gap:10px}.ps-bs__skeleton-line{height:12px;border-radius:6px;background:linear-gradient(90deg,var(--mat-sys-surface-container) 25%,var(--mat-sys-surface-container-highest) 37%,var(--mat-sys-surface-container) 63%);background-size:400% 100%;animation:ps-shimmer 1.4s ease-in-out infinite}.ps-bs__skeleton-line--title{width:60%}.ps-bs__skeleton-line--subtitle{width:38%;height:10px}.ps-bs__skeleton:nth-child(1){animation-delay:0ms}.ps-bs__skeleton:nth-child(2){animation-delay:60ms}.ps-bs__skeleton:nth-child(3){animation-delay:.12s}.ps-bs__skeleton:nth-child(4){animation-delay:.18s}.ps-bs__skeleton:nth-child(5){animation-delay:.24s}.ps-bs__skeleton:nth-child(6){animation-delay:.3s}@keyframes ps-skeleton-in{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@keyframes ps-shimmer{0%{background-position:100% 0}to{background-position:-100% 0}}.ps-bs__loading-more{display:flex;align-items:center;justify-content:center;gap:6px;padding:18px;color:var(--mat-sys-on-surface-variant);font:var(--mat-sys-body-small)}.ps-bs__loading-more-dot{width:6px;height:6px;border-radius:50%;background:var(--mat-sys-primary);animation:ps-bounce 1s ease-in-out infinite}.ps-bs__loading-more-dot:nth-child(2){animation-delay:.15s}.ps-bs__loading-more-dot:nth-child(3){animation-delay:.3s}.ps-bs__loading-more-text{margin-left:6px}@keyframes ps-bounce{0%,80%,to{transform:translateY(0);opacity:.4}40%{transform:translateY(-4px);opacity:1}}.ps-bs__list-end{text-align:center;padding:16px;font:var(--mat-sys-body-small);color:var(--mat-sys-on-surface-variant);opacity:.7}.ps-bs__state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:56px 32px;gap:12px;text-align:center;animation:ps-fade-in .2s ease}.ps-bs__state-icon-wrap{width:72px;height:72px;border-radius:50%;display:flex;align-items:center;justify-content:center;background:var(--mat-sys-surface-container-highest)}.ps-bs__state-icon-wrap mat-icon{font-size:32px;width:32px;height:32px;color:var(--mat-sys-on-surface-variant)}.ps-bs__state-title{font:var(--mat-sys-title-medium);color:var(--mat-sys-on-surface)}.ps-bs__state-hint{font:var(--mat-sys-body-medium);color:var(--mat-sys-on-surface-variant);max-width:280px}.ps-bs__state button{margin-top:4px}.ps-bs__error-icon-wrap{background:color-mix(in srgb,var(--mat-sys-error) 12%,transparent)}.ps-bs__error-icon-wrap mat-icon{color:var(--mat-sys-error)}@keyframes ps-fade-in{0%{opacity:0}to{opacity:1}}.ps-bs__footer{flex:0 0 auto;display:flex;align-items:center;justify-content:space-between;padding:16px 24px;gap:12px;z-index:2;background:var(--mat-sys-surface-container-high);border-top:1px solid var(--mat-sys-outline-variant)}.ps-bs__footer-count{font:var(--mat-sys-body-medium);color:var(--mat-sys-on-surface-variant);font-variant-numeric:tabular-nums;white-space:nowrap}.ps-bs__footer-actions{display:flex;gap:8px;align-items:center}.ps-bs__footer-actions button[matButton=filled]{min-width:96px;border-radius:9999px}@media (max-width: 600px){.cdk-global-overlay-wrapper:has(.ngx-paginated-select-panel){align-items:flex-end!important}.ngx-paginated-select-panel .mat-bottom-sheet-container{width:100vw;max-width:100vw;height:90vh!important;max-height:90vh!important;border-radius:24px 24px 0 0;border-bottom:none}.ps-bs__handle{display:flex}.ps-bs__header{padding:8px 16px 12px}.ps-bs__footer{padding:12px 16px}.ps-bs__body{padding:4px 8px 6px}.ps-bs__select-all{margin:0 -8px}}@media (prefers-reduced-motion: reduce){.ps-bs__badge,.ps-bs__chip,.ps-bs__skeleton,.ps-bs__option-avatar--selected,.ps-bs__state{animation:none}.ps-bs__skeleton-avatar,.ps-bs__skeleton-line{animation:none;background:var(--mat-sys-surface-container-highest)}.ps-bs__loading-more-dot{animation:none;opacity:.7}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i11.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatProgressBarModule }, { kind: "ngmodule", type: MatRippleModule }, { kind: "directive", type: i4$2.MatRipple, selector: "[mat-ripple], [matRipple]", inputs: ["matRippleColor", "matRippleUnbounded", "matRippleCentered", "matRippleRadius", "matRippleAnimation", "matRippleDisabled", "matRippleTrigger"], exportAs: ["matRipple"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i14.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "ngmodule", type: MatBadgeModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
3918
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: NgxPaginatedSelectBottomSheetComponent, isStandalone: true, selector: "ngx-paginated-select-bottom-sheet", ngImport: i0, template: "<div class=\"ps-bs\">\r\n\r\n <!-- \u2500\u2500 Handle bar (mobile) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"ps-bs__handle\">\r\n <div class=\"ps-bs__handle-bar\"></div>\r\n </div>\r\n\r\n <!-- \u2500\u2500 Header (pinned: title + search only) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"ps-bs__header\" [class.ps-bs__header--scrolled]=\"headerScrolled()\">\r\n <div class=\"ps-bs__header-top\">\r\n <div class=\"ps-bs__title-area\">\r\n <span class=\"ps-bs__title\">{{ data.title }}</span>\r\n @if (data.multiple && selectedCount() > 0) {\r\n <span class=\"ps-bs__badge\">{{ selectedCount() }}</span>\r\n }\r\n </div>\r\n <button mat-icon-button class=\"ps-bs__close-btn\" [attr.aria-label]=\"texts().common.close\" (click)=\"close()\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <!-- Pill search -->\r\n @if (data.showSearch) {\r\n <div class=\"ps-bs__search\">\r\n <mat-icon class=\"ps-bs__search-icon\">search</mat-icon>\r\n <input\r\n class=\"ps-bs__search-input\"\r\n #searchInput\r\n type=\"text\"\r\n [value]=\"query() ?? ''\"\r\n [placeholder]=\"data.searchPlaceholder\"\r\n (input)=\"onQueryInput($event, bodyContainer)\"\r\n />\r\n @if (searchInput.value.length > 0) {\r\n <button\r\n class=\"ps-bs__search-clear\"\r\n type=\"button\"\r\n [attr.aria-label]=\"texts().common.clearSearch\"\r\n (click)=\"clearQuery(bodyContainer); $event.stopPropagation()\"\r\n >\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- \u2500\u2500 Body (\u00DANICA zona de scroll: filtros + chips + select-all + lista) \u2500\u2500\u2500\u2500 -->\r\n <div class=\"ps-bs__body\" #bodyContainer (scroll)=\"onScroll(bodyContainer)\">\r\n\r\n <!-- Extra filters projection -->\r\n @if (data.extraFiltersTemplate) {\r\n <div class=\"ps-bs__extra-filters\">\r\n <ng-container *ngTemplateOutlet=\"data.extraFiltersTemplate\" />\r\n </div>\r\n }\r\n\r\n <!-- Selected chips (custom lightweight chips) -->\r\n @if (data.multiple && selectedItems().length > 0) {\r\n <div class=\"ps-bs__selected-chips\">\r\n @for (item of selectedItems(); track item[data.config.valueKey]) {\r\n <div class=\"ps-bs__chip\">\r\n <span class=\"ps-bs__chip-label\">{{ getLabel(item) }}</span>\r\n <button class=\"ps-bs__chip-remove\" type=\"button\" [attr.aria-label]=\"texts().common.clearSearch\" (click)=\"removeSelectedChip(item)\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Select all (sticky top of the scroll area) -->\r\n @if (data.multiple && data.showSelectAll && options().length > 0) {\r\n <div class=\"ps-bs__select-all\" matRipple (click)=\"toggleSelectAll()\">\r\n <mat-checkbox\r\n [checked]=\"allSelected()\"\r\n [indeterminate]=\"someSelected()\"\r\n (click)=\"$event.preventDefault()\"\r\n />\r\n <span class=\"ps-bs__select-all-label\">{{ data.selectAllLabel }}</span>\r\n </div>\r\n }\r\n\r\n <!-- \u2500\u2500 Options list \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"ps-bs__list\">\r\n\r\n <!-- Skeleton loading (only for the first page) -->\r\n @if (isInitialLoading()) {\r\n @for (i of [1, 2, 3, 4, 5, 6]; track i) {\r\n <div class=\"ps-bs__skeleton\">\r\n <div class=\"ps-bs__skeleton-avatar\"></div>\r\n <div class=\"ps-bs__skeleton-content\">\r\n <div class=\"ps-bs__skeleton-line ps-bs__skeleton-line--title\"></div>\r\n <div class=\"ps-bs__skeleton-line ps-bs__skeleton-line--subtitle\"></div>\r\n </div>\r\n </div>\r\n }\r\n }\r\n\r\n <!-- Error state -->\r\n @if (hasError() && !isLoading() && options().length === 0) {\r\n <div class=\"ps-bs__state ps-bs__error\">\r\n <div class=\"ps-bs__state-icon-wrap ps-bs__error-icon-wrap\">\r\n <mat-icon>error_outline</mat-icon>\r\n </div>\r\n <div class=\"ps-bs__state-title\">{{ texts().paginatedSelect.errorTitle }}</div>\r\n <div class=\"ps-bs__state-hint\">{{ texts().paginatedSelect.errorHint }}</div>\r\n <button matButton=\"tonal\" (click)=\"retry()\">\r\n <mat-icon>refresh</mat-icon>\r\n {{ texts().paginatedSelect.retry }}\r\n </button>\r\n </div>\r\n }\r\n\r\n <!-- Empty state -->\r\n @if (!hasError() && options().length === 0 && !isLoading()) {\r\n <div class=\"ps-bs__state ps-bs__empty\">\r\n <div class=\"ps-bs__state-icon-wrap\">\r\n <mat-icon>search_off</mat-icon>\r\n </div>\r\n <div class=\"ps-bs__state-title\">{{ data.noResultsMessage }}</div>\r\n @if (query()) {\r\n <div class=\"ps-bs__state-hint\">{{ texts().paginatedSelect.noResultsHint }}</div>\r\n <button matButton (click)=\"clearQuery(bodyContainer)\">\r\n {{ texts().paginatedSelect.clearSearch }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Option rows -->\r\n @for (item of options(); track item[data.config.valueKey]) {\r\n @let disabled = data.config.disabled ? data.config.disabled(item) : false;\r\n @let selected = isSelected(item);\r\n @let avatarImg = getAvatarImage(item);\r\n\r\n <div\r\n class=\"ps-bs__option\"\r\n [class.ps-bs__option--selected]=\"selected\"\r\n [class.ps-bs__option--disabled]=\"disabled\"\r\n matRipple\r\n [matRippleDisabled]=\"disabled\"\r\n (click)=\"toggleItem(item)\"\r\n role=\"option\"\r\n [attr.aria-selected]=\"selected\"\r\n [attr.aria-disabled]=\"disabled\"\r\n >\r\n <!-- Avatar (al seleccionar se voltea a un check, estilo Gmail) -->\r\n <div class=\"ps-bs__option-avatar\" [class.ps-bs__option-avatar--selected]=\"selected\">\r\n @if (selected) {\r\n <mat-icon class=\"ps-bs__option-avatar-check\">check</mat-icon>\r\n } @else if (avatarImg) {\r\n <img [src]=\"avatarImg\" [alt]=\"getLabel(item)\" (error)=\"onAvatarError(item)\" loading=\"lazy\" />\r\n } @else if (data.config.avatarText) {\r\n {{ getAvatarText(item) }}\r\n } @else if (data.config.avatarIcon) {\r\n <mat-icon>{{ data.config.avatarIcon }}</mat-icon>\r\n } @else {\r\n {{ getAvatarText(item) }}\r\n }\r\n </div>\r\n\r\n <!-- Content -->\r\n <div class=\"ps-bs__option-content\">\r\n @if (data.optionTemplate) {\r\n <ng-container *ngTemplateOutlet=\"data.optionTemplate; context: { $implicit: item }\" />\r\n } @else {\r\n <span class=\"ps-bs__option-label\">{{ getLabel(item) }}</span>\r\n @if (data.config.subtitle) {\r\n <span class=\"ps-bs__option-subtitle\">{{ data.config.subtitle(item) }}</span>\r\n }\r\n }\r\n </div>\r\n\r\n <!-- Check indicator -->\r\n @if (data.multiple) {\r\n <mat-checkbox [checked]=\"selected\" [disabled]=\"disabled\" (click)=\"$event.preventDefault()\" />\r\n } @else if (selected) {\r\n <mat-icon class=\"ps-bs__option-check\">check_circle</mat-icon>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Loading more (pagination) / end of list -->\r\n @if (isLoadingMore()) {\r\n <div class=\"ps-bs__loading-more\" aria-live=\"polite\">\r\n <span class=\"ps-bs__loading-more-dot\"></span>\r\n <span class=\"ps-bs__loading-more-dot\"></span>\r\n <span class=\"ps-bs__loading-more-dot\"></span>\r\n <span class=\"ps-bs__loading-more-text\">{{ texts().paginatedSelect.loadingMore }}</span>\r\n </div>\r\n } @else if (allLoaded() && options().length > 0) {\r\n <div class=\"ps-bs__list-end\">{{ texts().paginatedSelect.endOfList }}</div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- \u2500\u2500 Footer (ALWAYS VISIBLE \u2014 never scrolls) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"ps-bs__footer\">\r\n <span class=\"ps-bs__footer-count\">\r\n @if (data.multiple) {\r\n {{ texts().paginatedSelect.selectedCount(selectedCount(), total()) }}\r\n } @else {\r\n {{ texts().paginatedSelect.resultsCount(total()) }}\r\n }\r\n </span>\r\n\r\n @if (data.multiple) {\r\n <div class=\"ps-bs__footer-actions\">\r\n @if (selectedCount() > 0) {\r\n <button matButton (click)=\"reset()\">{{ data.resetLabel }}</button>\r\n }\r\n <button matButton=\"filled\" color=\"primary\" (click)=\"confirm()\">{{ data.confirmLabel }}</button>\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n", styles: [".cdk-global-overlay-wrapper:has(.ngx-paginated-select-panel){align-items:center!important;justify-content:center!important}.ngx-paginated-select-backdrop{background:color-mix(in srgb,var(--mat-sys-scrim, #000) 40%,transparent);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.ngx-paginated-select-panel .mat-bottom-sheet-container{padding:0!important;overflow:hidden!important;display:flex!important;flex-direction:column!important;width:min(640px,100vw - 48px);min-width:0;max-width:640px;height:min(86vh,760px)!important;max-height:min(86vh,760px)!important;border-radius:28px;background:var(--mat-sys-surface-container-high);border:1px solid color-mix(in srgb,var(--mat-sys-outline-variant) 60%,transparent);box-shadow:0 1px 3px #0000001f,0 8px 24px #00000024,0 24px 48px #0000001a!important}ngx-paginated-select-bottom-sheet{display:flex;flex-direction:column;flex:1 1 0;min-height:0;overflow:hidden;width:100%}.ps-bs{display:flex;flex-direction:column;height:100%;overflow:hidden}.ps-bs__handle{display:none;justify-content:center;padding:12px 0 4px;flex:0 0 auto}.ps-bs__handle-bar{width:32px;height:4px;border-radius:9999px;background:var(--mat-sys-outline-variant)}.ps-bs__header{flex:0 0 auto;padding:20px 24px 14px;display:flex;flex-direction:column;gap:14px;position:relative;z-index:2;transition:box-shadow .2s cubic-bezier(.2,0,0,1)}.ps-bs__header--scrolled{box-shadow:0 1px 0 0 var(--mat-sys-outline-variant),0 6px 14px -10px #00000059}.ps-bs__header-top{display:flex;align-items:center;justify-content:space-between;gap:8px}.ps-bs__title-area{display:flex;align-items:center;gap:10px;flex:1;min-width:0}.ps-bs__title{font:var(--mat-sys-title-large);font-weight:600;color:var(--mat-sys-on-surface);letter-spacing:-.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ps-bs__badge{display:inline-flex;align-items:center;justify-content:center;min-width:22px;height:22px;padding:0 7px;border-radius:9999px;font:var(--mat-sys-label-medium);font-weight:700;font-variant-numeric:tabular-nums;background:var(--mat-sys-primary);color:var(--mat-sys-on-primary);flex-shrink:0;animation:ps-badge-pop .3s cubic-bezier(.34,1.56,.64,1)}@keyframes ps-badge-pop{0%{transform:scale(0)}to{transform:scale(1)}}.ps-bs__close-btn{flex:0 0 auto}.ps-bs__search{display:flex;align-items:center;gap:10px;height:48px;padding:0 6px 0 16px;background:var(--mat-sys-surface-container-highest);border-radius:9999px;border:1.5px solid transparent;transition:background .2s cubic-bezier(.2,0,0,1),border-color .2s cubic-bezier(.2,0,0,1),box-shadow .2s cubic-bezier(.2,0,0,1)}.ps-bs__search:hover{background:color-mix(in srgb,var(--mat-sys-on-surface) 4%,var(--mat-sys-surface-container-highest))}.ps-bs__search:focus-within{background:var(--mat-sys-surface);border-color:var(--mat-sys-primary);box-shadow:0 0 0 4px color-mix(in srgb,var(--mat-sys-primary) 12%,transparent)}.ps-bs__search-icon{color:var(--mat-sys-on-surface-variant);font-size:22px;width:22px;height:22px;flex-shrink:0;transition:color .2s cubic-bezier(.2,0,0,1)}.ps-bs__search:focus-within .ps-bs__search-icon{color:var(--mat-sys-primary)}.ps-bs__search-input{flex:1;border:none;outline:none;background:transparent;font:var(--mat-sys-body-large);font-family:inherit;color:var(--mat-sys-on-surface);min-width:0}.ps-bs__search-input::placeholder{color:var(--mat-sys-on-surface-variant)}.ps-bs__search-clear{display:flex;align-items:center;justify-content:center;width:34px;height:34px;border-radius:50%;border:none;background:transparent;cursor:pointer;color:var(--mat-sys-on-surface-variant);transition:background .15s cubic-bezier(.2,0,0,1);flex-shrink:0}.ps-bs__search-clear:hover{background:color-mix(in srgb,var(--mat-sys-on-surface) 10%,transparent)}.ps-bs__search-clear mat-icon{font-size:20px;width:20px;height:20px}.ps-bs__body{flex:1 1 auto;min-height:0;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;padding:6px 10px 8px;display:flex;flex-direction:column}.ps-bs__body>*{flex-shrink:0}.ps-bs__extra-filters{width:100%;padding:10px 6px 6px}.ps-bs__selected-chips{display:flex;flex-wrap:wrap;gap:8px;padding:4px 6px 6px}.ps-bs__chip{display:inline-flex;align-items:center;gap:2px;height:32px;padding:0 4px 0 12px;border-radius:9999px;background:var(--mat-sys-secondary-container);color:var(--mat-sys-on-secondary-container);font:var(--mat-sys-label-large);white-space:nowrap;max-width:200px;animation:ps-chip-in .2s cubic-bezier(.2,0,0,1)}.ps-bs__chip-label{overflow:hidden;text-overflow:ellipsis}.ps-bs__chip-remove{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:50%;border:none;background:transparent;cursor:pointer;color:inherit;opacity:.55;transition:opacity .15s,background .15s}.ps-bs__chip-remove:hover{opacity:1;background:color-mix(in srgb,var(--mat-sys-on-secondary-container) 12%,transparent)}.ps-bs__chip-remove mat-icon{font-size:16px;width:16px;height:16px}@keyframes ps-chip-in{0%{transform:scale(.85);opacity:0}to{transform:scale(1);opacity:1}}.ps-bs__select-all.ps-bs__select-all{position:sticky;top:-6px;z-index:3;display:flex;align-items:center;gap:12px;margin:0 -10px;padding:8px 24px;cursor:pointer;background:var(--mat-sys-surface-container-high);border-bottom:1px solid var(--mat-sys-outline-variant);transition:background .15s cubic-bezier(.2,0,0,1)}.ps-bs__select-all.ps-bs__select-all:hover{background:color-mix(in srgb,var(--mat-sys-on-surface) 5%,var(--mat-sys-surface-container-high))}.ps-bs__select-all.ps-bs__select-all-label{font:var(--mat-sys-label-large);color:var(--mat-sys-on-surface)}.ps-bs__list{flex:1 1 auto}.ps-bs__option{display:flex;align-items:center;gap:14px;padding:8px 12px;margin:2px 0;cursor:pointer;border-radius:16px;min-height:56px;transition:background .15s cubic-bezier(.2,0,0,1)}.ps-bs__option:hover:not(.ps-bs__option--disabled){background:color-mix(in srgb,var(--mat-sys-on-surface) 8%,transparent)}.ps-bs__option:active:not(.ps-bs__option--disabled){background:color-mix(in srgb,var(--mat-sys-on-surface) 12%,transparent)}.ps-bs__option--selected{background:color-mix(in srgb,var(--mat-sys-primary) 10%,transparent)}.ps-bs__option--selected:hover{background:color-mix(in srgb,var(--mat-sys-primary) 14%,transparent)}.ps-bs__option--disabled{opacity:.38;cursor:not-allowed}.ps-bs__option .mat-ripple-element{background:color-mix(in srgb,var(--mat-sys-primary) 12%,transparent)}.ps-bs__option .mat-mdc-checkbox{margin-left:auto;margin-right:-8px;flex-shrink:0}.ps-bs__option-avatar{width:40px;height:40px;min-width:40px;border-radius:50%;overflow:hidden;display:flex;align-items:center;justify-content:center;font:var(--mat-sys-label-large);font-weight:600;background:var(--mat-sys-primary-container);color:var(--mat-sys-on-primary-container);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--mat-sys-on-surface) 8%,transparent);transition:box-shadow .18s cubic-bezier(.2,0,0,1)}.ps-bs__option-avatar img{width:100%;height:100%;object-fit:cover;display:block}.ps-bs__option-avatar mat-icon{font-size:20px;width:20px;height:20px}.ps-bs__option-avatar--selected{background:var(--mat-sys-primary);color:var(--mat-sys-on-primary);box-shadow:none;animation:ps-avatar-flip .25s cubic-bezier(.05,.7,.1,1)}.ps-bs__option-avatar-check{color:var(--mat-sys-on-primary)}@keyframes ps-avatar-flip{0%{transform:scale(.6) rotate(-30deg);opacity:.4}to{transform:scale(1) rotate(0);opacity:1}}.ps-bs__option-content{flex:1;display:flex;flex-direction:column;gap:2px;min-width:0}.ps-bs__option-label{font:var(--mat-sys-body-large);color:var(--mat-sys-on-surface);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ps-bs__option--selected .ps-bs__option-label{font-weight:600}.ps-bs__option-subtitle{font:var(--mat-sys-body-small);color:var(--mat-sys-on-surface-variant);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ps-bs__option-check{color:var(--mat-sys-primary);font-size:22px;width:22px;height:22px;margin-left:auto;flex-shrink:0}.ps-bs__skeleton{display:flex;align-items:center;gap:14px;padding:8px 12px;margin:2px 0;min-height:56px;border-radius:16px;opacity:0;animation:ps-skeleton-in .4s ease forwards}.ps-bs__skeleton-avatar{width:40px;height:40px;min-width:40px;border-radius:50%;background:linear-gradient(90deg,var(--mat-sys-surface-container) 25%,var(--mat-sys-surface-container-highest) 37%,var(--mat-sys-surface-container) 63%);background-size:400% 100%;animation:ps-shimmer 1.4s ease-in-out infinite}.ps-bs__skeleton-content{flex:1;display:flex;flex-direction:column;gap:10px}.ps-bs__skeleton-line{height:12px;border-radius:6px;background:linear-gradient(90deg,var(--mat-sys-surface-container) 25%,var(--mat-sys-surface-container-highest) 37%,var(--mat-sys-surface-container) 63%);background-size:400% 100%;animation:ps-shimmer 1.4s ease-in-out infinite}.ps-bs__skeleton-line--title{width:60%}.ps-bs__skeleton-line--subtitle{width:38%;height:10px}.ps-bs__skeleton:nth-child(1){animation-delay:0ms}.ps-bs__skeleton:nth-child(2){animation-delay:60ms}.ps-bs__skeleton:nth-child(3){animation-delay:.12s}.ps-bs__skeleton:nth-child(4){animation-delay:.18s}.ps-bs__skeleton:nth-child(5){animation-delay:.24s}.ps-bs__skeleton:nth-child(6){animation-delay:.3s}@keyframes ps-skeleton-in{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@keyframes ps-shimmer{0%{background-position:100% 0}to{background-position:-100% 0}}.ps-bs__loading-more{display:flex;align-items:center;justify-content:center;gap:6px;padding:18px;color:var(--mat-sys-on-surface-variant);font:var(--mat-sys-body-small)}.ps-bs__loading-more-dot{width:6px;height:6px;border-radius:50%;background:var(--mat-sys-primary);animation:ps-bounce 1s ease-in-out infinite}.ps-bs__loading-more-dot:nth-child(2){animation-delay:.15s}.ps-bs__loading-more-dot:nth-child(3){animation-delay:.3s}.ps-bs__loading-more-text{margin-left:6px}@keyframes ps-bounce{0%,80%,to{transform:translateY(0);opacity:.4}40%{transform:translateY(-4px);opacity:1}}.ps-bs__list-end{text-align:center;padding:16px;font:var(--mat-sys-body-small);color:var(--mat-sys-on-surface-variant);opacity:.7}.ps-bs__state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:56px 32px;gap:12px;text-align:center;animation:ps-fade-in .2s ease}.ps-bs__state-icon-wrap{width:72px;height:72px;border-radius:50%;display:flex;align-items:center;justify-content:center;background:var(--mat-sys-surface-container-highest)}.ps-bs__state-icon-wrap mat-icon{font-size:32px;width:32px;height:32px;color:var(--mat-sys-on-surface-variant)}.ps-bs__state-title{font:var(--mat-sys-title-medium);color:var(--mat-sys-on-surface)}.ps-bs__state-hint{font:var(--mat-sys-body-medium);color:var(--mat-sys-on-surface-variant);max-width:280px}.ps-bs__state button{margin-top:4px}.ps-bs__error-icon-wrap{background:color-mix(in srgb,var(--mat-sys-error) 12%,transparent)}.ps-bs__error-icon-wrap mat-icon{color:var(--mat-sys-error)}@keyframes ps-fade-in{0%{opacity:0}to{opacity:1}}.ps-bs__footer{flex:0 0 auto;display:flex;align-items:center;justify-content:space-between;padding:16px 24px;gap:12px;z-index:2;background:var(--mat-sys-surface-container-high);border-top:1px solid var(--mat-sys-outline-variant)}.ps-bs__footer-count{font:var(--mat-sys-body-medium);color:var(--mat-sys-on-surface-variant);font-variant-numeric:tabular-nums;white-space:nowrap}.ps-bs__footer-actions{display:flex;gap:8px;align-items:center}.ps-bs__footer-actions button[matButton=filled]{min-width:96px;border-radius:9999px}@media (max-width: 600px){.cdk-global-overlay-wrapper:has(.ngx-paginated-select-panel){align-items:flex-end!important}.ngx-paginated-select-panel .mat-bottom-sheet-container{width:100vw;max-width:100vw;height:90vh!important;max-height:90vh!important;border-radius:24px 24px 0 0;border-bottom:none}.ps-bs__handle{display:flex}.ps-bs__header{padding:8px 16px 12px}.ps-bs__footer{padding:12px 16px}.ps-bs__body{padding:4px 8px 6px}.ps-bs__select-all{margin:0 -8px}}@media (prefers-reduced-motion: reduce){.ps-bs__badge,.ps-bs__chip,.ps-bs__skeleton,.ps-bs__option-avatar--selected,.ps-bs__state{animation:none}.ps-bs__skeleton-avatar,.ps-bs__skeleton-line{animation:none;background:var(--mat-sys-surface-container-highest)}.ps-bs__loading-more-dot{animation:none;opacity:.7}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i11.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatProgressBarModule }, { kind: "ngmodule", type: MatRippleModule }, { kind: "directive", type: i4$2.MatRipple, selector: "[mat-ripple], [matRipple]", inputs: ["matRippleColor", "matRippleUnbounded", "matRippleCentered", "matRippleRadius", "matRippleAnimation", "matRippleDisabled", "matRippleTrigger"], exportAs: ["matRipple"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i14.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "ngmodule", type: MatBadgeModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
3506
3919
  }
3507
3920
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxPaginatedSelectBottomSheetComponent, decorators: [{
3508
3921
  type: Component,
@@ -3520,7 +3933,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
3520
3933
  MatCheckboxModule,
3521
3934
  MatTooltipModule,
3522
3935
  MatBadgeModule,
3523
- ], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ps-bs\">\n\n <!-- \u2500\u2500 Handle bar (mobile) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"ps-bs__handle\">\n <div class=\"ps-bs__handle-bar\"></div>\n </div>\n\n <!-- \u2500\u2500 Header (pinned: title + search only) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"ps-bs__header\" [class.ps-bs__header--scrolled]=\"headerScrolled()\">\n <div class=\"ps-bs__header-top\">\n <div class=\"ps-bs__title-area\">\n <span class=\"ps-bs__title\">{{ data.title }}</span>\n @if (data.multiple && selectedCount() > 0) {\n <span class=\"ps-bs__badge\">{{ selectedCount() }}</span>\n }\n </div>\n <button mat-icon-button class=\"ps-bs__close-btn\" [attr.aria-label]=\"intl.closeButtonLabel\" (click)=\"close()\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n\n <!-- Pill search -->\n @if (data.showSearch) {\n <div class=\"ps-bs__search\">\n <mat-icon class=\"ps-bs__search-icon\">search</mat-icon>\n <input\n class=\"ps-bs__search-input\"\n #searchInput\n type=\"text\"\n [value]=\"query() ?? ''\"\n [placeholder]=\"data.searchPlaceholder\"\n (input)=\"onQueryInput($event, bodyContainer)\"\n />\n @if (searchInput.value.length > 0) {\n <button\n class=\"ps-bs__search-clear\"\n type=\"button\"\n [attr.aria-label]=\"intl.clearSearchTooltip\"\n (click)=\"clearQuery(bodyContainer); $event.stopPropagation()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n }\n </div>\n }\n </div>\n\n <!-- \u2500\u2500 Body (\u00DANICA zona de scroll: filtros + chips + select-all + lista) \u2500\u2500\u2500\u2500 -->\n <div class=\"ps-bs__body\" #bodyContainer (scroll)=\"onScroll(bodyContainer)\">\n\n <!-- Extra filters projection -->\n @if (data.extraFiltersTemplate) {\n <div class=\"ps-bs__extra-filters\">\n <ng-container *ngTemplateOutlet=\"data.extraFiltersTemplate\" />\n </div>\n }\n\n <!-- Selected chips (custom lightweight chips) -->\n @if (data.multiple && selectedItems().length > 0) {\n <div class=\"ps-bs__selected-chips\">\n @for (item of selectedItems(); track item[data.config.valueKey]) {\n <div class=\"ps-bs__chip\">\n <span class=\"ps-bs__chip-label\">{{ getLabel(item) }}</span>\n <button class=\"ps-bs__chip-remove\" type=\"button\" [attr.aria-label]=\"intl.clearSearchTooltip\" (click)=\"removeSelectedChip(item)\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n }\n </div>\n }\n\n <!-- Select all (sticky top of the scroll area) -->\n @if (data.multiple && data.showSelectAll && options().length > 0) {\n <div class=\"ps-bs__select-all\" matRipple (click)=\"toggleSelectAll()\">\n <mat-checkbox\n [checked]=\"allSelected()\"\n [indeterminate]=\"someSelected()\"\n (click)=\"$event.preventDefault()\"\n />\n <span class=\"ps-bs__select-all-label\">{{ data.selectAllLabel }}</span>\n </div>\n }\n\n <!-- \u2500\u2500 Options list \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"ps-bs__list\">\n\n <!-- Skeleton loading (only for the first page) -->\n @if (isInitialLoading()) {\n @for (i of [1, 2, 3, 4, 5, 6]; track i) {\n <div class=\"ps-bs__skeleton\">\n <div class=\"ps-bs__skeleton-avatar\"></div>\n <div class=\"ps-bs__skeleton-content\">\n <div class=\"ps-bs__skeleton-line ps-bs__skeleton-line--title\"></div>\n <div class=\"ps-bs__skeleton-line ps-bs__skeleton-line--subtitle\"></div>\n </div>\n </div>\n }\n }\n\n <!-- Error state -->\n @if (hasError() && !isLoading() && options().length === 0) {\n <div class=\"ps-bs__state ps-bs__error\">\n <div class=\"ps-bs__state-icon-wrap ps-bs__error-icon-wrap\">\n <mat-icon>error_outline</mat-icon>\n </div>\n <div class=\"ps-bs__state-title\">{{ intl.paginatedSelectErrorTitle }}</div>\n <div class=\"ps-bs__state-hint\">{{ intl.paginatedSelectErrorHint }}</div>\n <button matButton=\"tonal\" (click)=\"retry()\">\n <mat-icon>refresh</mat-icon>\n {{ intl.paginatedSelectRetryLabel }}\n </button>\n </div>\n }\n\n <!-- Empty state -->\n @if (!hasError() && options().length === 0 && !isLoading()) {\n <div class=\"ps-bs__state ps-bs__empty\">\n <div class=\"ps-bs__state-icon-wrap\">\n <mat-icon>search_off</mat-icon>\n </div>\n <div class=\"ps-bs__state-title\">{{ data.noResultsMessage }}</div>\n @if (query()) {\n <div class=\"ps-bs__state-hint\">{{ intl.paginatedSelectNoResultsHint }}</div>\n <button matButton (click)=\"clearQuery(bodyContainer)\">\n {{ intl.paginatedSelectClearSearchLabel }}\n </button>\n }\n </div>\n }\n\n <!-- Option rows -->\n @for (item of options(); track item[data.config.valueKey]) {\n @let disabled = data.config.disabled ? data.config.disabled(item) : false;\n @let selected = isSelected(item);\n @let avatarImg = getAvatarImage(item);\n\n <div\n class=\"ps-bs__option\"\n [class.ps-bs__option--selected]=\"selected\"\n [class.ps-bs__option--disabled]=\"disabled\"\n matRipple\n [matRippleDisabled]=\"disabled\"\n (click)=\"toggleItem(item)\"\n role=\"option\"\n [attr.aria-selected]=\"selected\"\n [attr.aria-disabled]=\"disabled\"\n >\n <!-- Avatar (al seleccionar se voltea a un check, estilo Gmail) -->\n <div class=\"ps-bs__option-avatar\" [class.ps-bs__option-avatar--selected]=\"selected\">\n @if (selected) {\n <mat-icon class=\"ps-bs__option-avatar-check\">check</mat-icon>\n } @else if (avatarImg) {\n <img [src]=\"avatarImg\" [alt]=\"getLabel(item)\" (error)=\"onAvatarError(item)\" loading=\"lazy\" />\n } @else if (data.config.avatarText) {\n {{ getAvatarText(item) }}\n } @else if (data.config.avatarIcon) {\n <mat-icon>{{ data.config.avatarIcon }}</mat-icon>\n } @else {\n {{ getAvatarText(item) }}\n }\n </div>\n\n <!-- Content -->\n <div class=\"ps-bs__option-content\">\n @if (data.optionTemplate) {\n <ng-container *ngTemplateOutlet=\"data.optionTemplate; context: { $implicit: item }\" />\n } @else {\n <span class=\"ps-bs__option-label\">{{ getLabel(item) }}</span>\n @if (data.config.subtitle) {\n <span class=\"ps-bs__option-subtitle\">{{ data.config.subtitle(item) }}</span>\n }\n }\n </div>\n\n <!-- Check indicator -->\n @if (data.multiple) {\n <mat-checkbox [checked]=\"selected\" [disabled]=\"disabled\" (click)=\"$event.preventDefault()\" />\n } @else if (selected) {\n <mat-icon class=\"ps-bs__option-check\">check_circle</mat-icon>\n }\n </div>\n }\n\n <!-- Loading more (pagination) / end of list -->\n @if (isLoadingMore()) {\n <div class=\"ps-bs__loading-more\" aria-live=\"polite\">\n <span class=\"ps-bs__loading-more-dot\"></span>\n <span class=\"ps-bs__loading-more-dot\"></span>\n <span class=\"ps-bs__loading-more-dot\"></span>\n <span class=\"ps-bs__loading-more-text\">{{ intl.paginatedSelectLoadingMoreLabel }}</span>\n </div>\n } @else if (allLoaded() && options().length > 0) {\n <div class=\"ps-bs__list-end\">{{ intl.paginatedSelectEndOfListLabel }}</div>\n }\n </div>\n </div>\n\n <!-- \u2500\u2500 Footer (ALWAYS VISIBLE \u2014 never scrolls) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"ps-bs__footer\">\n <span class=\"ps-bs__footer-count\">\n @if (data.multiple) {\n {{ intl.getPaginatedSelectSelectedCountLabel(selectedCount(), total()) }}\n } @else {\n {{ intl.getPaginatedSelectResultsCountLabel(total()) }}\n }\n </span>\n\n @if (data.multiple) {\n <div class=\"ps-bs__footer-actions\">\n @if (selectedCount() > 0) {\n <button matButton (click)=\"reset()\">{{ data.resetLabel }}</button>\n }\n <button matButton=\"filled\" color=\"primary\" (click)=\"confirm()\">{{ data.confirmLabel }}</button>\n </div>\n }\n </div>\n</div>\n", styles: [".cdk-global-overlay-wrapper:has(.ngx-paginated-select-panel){align-items:center!important;justify-content:center!important}.ngx-paginated-select-backdrop{background:color-mix(in srgb,var(--mat-sys-scrim, #000) 40%,transparent);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.ngx-paginated-select-panel .mat-bottom-sheet-container{padding:0!important;overflow:hidden!important;display:flex!important;flex-direction:column!important;width:min(640px,100vw - 48px);min-width:0;max-width:640px;height:min(86vh,760px)!important;max-height:min(86vh,760px)!important;border-radius:28px;background:var(--mat-sys-surface-container-high);border:1px solid color-mix(in srgb,var(--mat-sys-outline-variant) 60%,transparent);box-shadow:0 1px 3px #0000001f,0 8px 24px #00000024,0 24px 48px #0000001a!important}ngx-paginated-select-bottom-sheet{display:flex;flex-direction:column;flex:1 1 0;min-height:0;overflow:hidden;width:100%}.ps-bs{display:flex;flex-direction:column;height:100%;overflow:hidden}.ps-bs__handle{display:none;justify-content:center;padding:12px 0 4px;flex:0 0 auto}.ps-bs__handle-bar{width:32px;height:4px;border-radius:9999px;background:var(--mat-sys-outline-variant)}.ps-bs__header{flex:0 0 auto;padding:20px 24px 14px;display:flex;flex-direction:column;gap:14px;position:relative;z-index:2;transition:box-shadow .2s cubic-bezier(.2,0,0,1)}.ps-bs__header--scrolled{box-shadow:0 1px 0 0 var(--mat-sys-outline-variant),0 6px 14px -10px #00000059}.ps-bs__header-top{display:flex;align-items:center;justify-content:space-between;gap:8px}.ps-bs__title-area{display:flex;align-items:center;gap:10px;flex:1;min-width:0}.ps-bs__title{font:var(--mat-sys-title-large);font-weight:600;color:var(--mat-sys-on-surface);letter-spacing:-.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ps-bs__badge{display:inline-flex;align-items:center;justify-content:center;min-width:22px;height:22px;padding:0 7px;border-radius:9999px;font:var(--mat-sys-label-medium);font-weight:700;font-variant-numeric:tabular-nums;background:var(--mat-sys-primary);color:var(--mat-sys-on-primary);flex-shrink:0;animation:ps-badge-pop .3s cubic-bezier(.34,1.56,.64,1)}@keyframes ps-badge-pop{0%{transform:scale(0)}to{transform:scale(1)}}.ps-bs__close-btn{flex:0 0 auto}.ps-bs__search{display:flex;align-items:center;gap:10px;height:48px;padding:0 6px 0 16px;background:var(--mat-sys-surface-container-highest);border-radius:9999px;border:1.5px solid transparent;transition:background .2s cubic-bezier(.2,0,0,1),border-color .2s cubic-bezier(.2,0,0,1),box-shadow .2s cubic-bezier(.2,0,0,1)}.ps-bs__search:hover{background:color-mix(in srgb,var(--mat-sys-on-surface) 4%,var(--mat-sys-surface-container-highest))}.ps-bs__search:focus-within{background:var(--mat-sys-surface);border-color:var(--mat-sys-primary);box-shadow:0 0 0 4px color-mix(in srgb,var(--mat-sys-primary) 12%,transparent)}.ps-bs__search-icon{color:var(--mat-sys-on-surface-variant);font-size:22px;width:22px;height:22px;flex-shrink:0;transition:color .2s cubic-bezier(.2,0,0,1)}.ps-bs__search:focus-within .ps-bs__search-icon{color:var(--mat-sys-primary)}.ps-bs__search-input{flex:1;border:none;outline:none;background:transparent;font:var(--mat-sys-body-large);font-family:inherit;color:var(--mat-sys-on-surface);min-width:0}.ps-bs__search-input::placeholder{color:var(--mat-sys-on-surface-variant)}.ps-bs__search-clear{display:flex;align-items:center;justify-content:center;width:34px;height:34px;border-radius:50%;border:none;background:transparent;cursor:pointer;color:var(--mat-sys-on-surface-variant);transition:background .15s cubic-bezier(.2,0,0,1);flex-shrink:0}.ps-bs__search-clear:hover{background:color-mix(in srgb,var(--mat-sys-on-surface) 10%,transparent)}.ps-bs__search-clear mat-icon{font-size:20px;width:20px;height:20px}.ps-bs__body{flex:1 1 auto;min-height:0;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;padding:6px 10px 8px;display:flex;flex-direction:column}.ps-bs__body>*{flex-shrink:0}.ps-bs__extra-filters{width:100%;padding:10px 6px 6px}.ps-bs__selected-chips{display:flex;flex-wrap:wrap;gap:8px;padding:4px 6px 6px}.ps-bs__chip{display:inline-flex;align-items:center;gap:2px;height:32px;padding:0 4px 0 12px;border-radius:9999px;background:var(--mat-sys-secondary-container);color:var(--mat-sys-on-secondary-container);font:var(--mat-sys-label-large);white-space:nowrap;max-width:200px;animation:ps-chip-in .2s cubic-bezier(.2,0,0,1)}.ps-bs__chip-label{overflow:hidden;text-overflow:ellipsis}.ps-bs__chip-remove{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:50%;border:none;background:transparent;cursor:pointer;color:inherit;opacity:.55;transition:opacity .15s,background .15s}.ps-bs__chip-remove:hover{opacity:1;background:color-mix(in srgb,var(--mat-sys-on-secondary-container) 12%,transparent)}.ps-bs__chip-remove mat-icon{font-size:16px;width:16px;height:16px}@keyframes ps-chip-in{0%{transform:scale(.85);opacity:0}to{transform:scale(1);opacity:1}}.ps-bs__select-all.ps-bs__select-all{position:sticky;top:-6px;z-index:3;display:flex;align-items:center;gap:12px;margin:0 -10px;padding:8px 24px;cursor:pointer;background:var(--mat-sys-surface-container-high);border-bottom:1px solid var(--mat-sys-outline-variant);transition:background .15s cubic-bezier(.2,0,0,1)}.ps-bs__select-all.ps-bs__select-all:hover{background:color-mix(in srgb,var(--mat-sys-on-surface) 5%,var(--mat-sys-surface-container-high))}.ps-bs__select-all.ps-bs__select-all-label{font:var(--mat-sys-label-large);color:var(--mat-sys-on-surface)}.ps-bs__list{flex:1 1 auto}.ps-bs__option{display:flex;align-items:center;gap:14px;padding:8px 12px;margin:2px 0;cursor:pointer;border-radius:16px;min-height:56px;transition:background .15s cubic-bezier(.2,0,0,1)}.ps-bs__option:hover:not(.ps-bs__option--disabled){background:color-mix(in srgb,var(--mat-sys-on-surface) 8%,transparent)}.ps-bs__option:active:not(.ps-bs__option--disabled){background:color-mix(in srgb,var(--mat-sys-on-surface) 12%,transparent)}.ps-bs__option--selected{background:color-mix(in srgb,var(--mat-sys-primary) 10%,transparent)}.ps-bs__option--selected:hover{background:color-mix(in srgb,var(--mat-sys-primary) 14%,transparent)}.ps-bs__option--disabled{opacity:.38;cursor:not-allowed}.ps-bs__option .mat-ripple-element{background:color-mix(in srgb,var(--mat-sys-primary) 12%,transparent)}.ps-bs__option .mat-mdc-checkbox{margin-left:auto;margin-right:-8px;flex-shrink:0}.ps-bs__option-avatar{width:40px;height:40px;min-width:40px;border-radius:50%;overflow:hidden;display:flex;align-items:center;justify-content:center;font:var(--mat-sys-label-large);font-weight:600;background:var(--mat-sys-primary-container);color:var(--mat-sys-on-primary-container);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--mat-sys-on-surface) 8%,transparent);transition:box-shadow .18s cubic-bezier(.2,0,0,1)}.ps-bs__option-avatar img{width:100%;height:100%;object-fit:cover;display:block}.ps-bs__option-avatar mat-icon{font-size:20px;width:20px;height:20px}.ps-bs__option-avatar--selected{background:var(--mat-sys-primary);color:var(--mat-sys-on-primary);box-shadow:none;animation:ps-avatar-flip .25s cubic-bezier(.05,.7,.1,1)}.ps-bs__option-avatar-check{color:var(--mat-sys-on-primary)}@keyframes ps-avatar-flip{0%{transform:scale(.6) rotate(-30deg);opacity:.4}to{transform:scale(1) rotate(0);opacity:1}}.ps-bs__option-content{flex:1;display:flex;flex-direction:column;gap:2px;min-width:0}.ps-bs__option-label{font:var(--mat-sys-body-large);color:var(--mat-sys-on-surface);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ps-bs__option--selected .ps-bs__option-label{font-weight:600}.ps-bs__option-subtitle{font:var(--mat-sys-body-small);color:var(--mat-sys-on-surface-variant);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ps-bs__option-check{color:var(--mat-sys-primary);font-size:22px;width:22px;height:22px;margin-left:auto;flex-shrink:0}.ps-bs__skeleton{display:flex;align-items:center;gap:14px;padding:8px 12px;margin:2px 0;min-height:56px;border-radius:16px;opacity:0;animation:ps-skeleton-in .4s ease forwards}.ps-bs__skeleton-avatar{width:40px;height:40px;min-width:40px;border-radius:50%;background:linear-gradient(90deg,var(--mat-sys-surface-container) 25%,var(--mat-sys-surface-container-highest) 37%,var(--mat-sys-surface-container) 63%);background-size:400% 100%;animation:ps-shimmer 1.4s ease-in-out infinite}.ps-bs__skeleton-content{flex:1;display:flex;flex-direction:column;gap:10px}.ps-bs__skeleton-line{height:12px;border-radius:6px;background:linear-gradient(90deg,var(--mat-sys-surface-container) 25%,var(--mat-sys-surface-container-highest) 37%,var(--mat-sys-surface-container) 63%);background-size:400% 100%;animation:ps-shimmer 1.4s ease-in-out infinite}.ps-bs__skeleton-line--title{width:60%}.ps-bs__skeleton-line--subtitle{width:38%;height:10px}.ps-bs__skeleton:nth-child(1){animation-delay:0ms}.ps-bs__skeleton:nth-child(2){animation-delay:60ms}.ps-bs__skeleton:nth-child(3){animation-delay:.12s}.ps-bs__skeleton:nth-child(4){animation-delay:.18s}.ps-bs__skeleton:nth-child(5){animation-delay:.24s}.ps-bs__skeleton:nth-child(6){animation-delay:.3s}@keyframes ps-skeleton-in{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@keyframes ps-shimmer{0%{background-position:100% 0}to{background-position:-100% 0}}.ps-bs__loading-more{display:flex;align-items:center;justify-content:center;gap:6px;padding:18px;color:var(--mat-sys-on-surface-variant);font:var(--mat-sys-body-small)}.ps-bs__loading-more-dot{width:6px;height:6px;border-radius:50%;background:var(--mat-sys-primary);animation:ps-bounce 1s ease-in-out infinite}.ps-bs__loading-more-dot:nth-child(2){animation-delay:.15s}.ps-bs__loading-more-dot:nth-child(3){animation-delay:.3s}.ps-bs__loading-more-text{margin-left:6px}@keyframes ps-bounce{0%,80%,to{transform:translateY(0);opacity:.4}40%{transform:translateY(-4px);opacity:1}}.ps-bs__list-end{text-align:center;padding:16px;font:var(--mat-sys-body-small);color:var(--mat-sys-on-surface-variant);opacity:.7}.ps-bs__state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:56px 32px;gap:12px;text-align:center;animation:ps-fade-in .2s ease}.ps-bs__state-icon-wrap{width:72px;height:72px;border-radius:50%;display:flex;align-items:center;justify-content:center;background:var(--mat-sys-surface-container-highest)}.ps-bs__state-icon-wrap mat-icon{font-size:32px;width:32px;height:32px;color:var(--mat-sys-on-surface-variant)}.ps-bs__state-title{font:var(--mat-sys-title-medium);color:var(--mat-sys-on-surface)}.ps-bs__state-hint{font:var(--mat-sys-body-medium);color:var(--mat-sys-on-surface-variant);max-width:280px}.ps-bs__state button{margin-top:4px}.ps-bs__error-icon-wrap{background:color-mix(in srgb,var(--mat-sys-error) 12%,transparent)}.ps-bs__error-icon-wrap mat-icon{color:var(--mat-sys-error)}@keyframes ps-fade-in{0%{opacity:0}to{opacity:1}}.ps-bs__footer{flex:0 0 auto;display:flex;align-items:center;justify-content:space-between;padding:16px 24px;gap:12px;z-index:2;background:var(--mat-sys-surface-container-high);border-top:1px solid var(--mat-sys-outline-variant)}.ps-bs__footer-count{font:var(--mat-sys-body-medium);color:var(--mat-sys-on-surface-variant);font-variant-numeric:tabular-nums;white-space:nowrap}.ps-bs__footer-actions{display:flex;gap:8px;align-items:center}.ps-bs__footer-actions button[matButton=filled]{min-width:96px;border-radius:9999px}@media (max-width: 600px){.cdk-global-overlay-wrapper:has(.ngx-paginated-select-panel){align-items:flex-end!important}.ngx-paginated-select-panel .mat-bottom-sheet-container{width:100vw;max-width:100vw;height:90vh!important;max-height:90vh!important;border-radius:24px 24px 0 0;border-bottom:none}.ps-bs__handle{display:flex}.ps-bs__header{padding:8px 16px 12px}.ps-bs__footer{padding:12px 16px}.ps-bs__body{padding:4px 8px 6px}.ps-bs__select-all{margin:0 -8px}}@media (prefers-reduced-motion: reduce){.ps-bs__badge,.ps-bs__chip,.ps-bs__skeleton,.ps-bs__option-avatar--selected,.ps-bs__state{animation:none}.ps-bs__skeleton-avatar,.ps-bs__skeleton-line{animation:none;background:var(--mat-sys-surface-container-highest)}.ps-bs__loading-more-dot{animation:none;opacity:.7}}\n"] }]
3936
+ ], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ps-bs\">\r\n\r\n <!-- \u2500\u2500 Handle bar (mobile) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"ps-bs__handle\">\r\n <div class=\"ps-bs__handle-bar\"></div>\r\n </div>\r\n\r\n <!-- \u2500\u2500 Header (pinned: title + search only) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"ps-bs__header\" [class.ps-bs__header--scrolled]=\"headerScrolled()\">\r\n <div class=\"ps-bs__header-top\">\r\n <div class=\"ps-bs__title-area\">\r\n <span class=\"ps-bs__title\">{{ data.title }}</span>\r\n @if (data.multiple && selectedCount() > 0) {\r\n <span class=\"ps-bs__badge\">{{ selectedCount() }}</span>\r\n }\r\n </div>\r\n <button mat-icon-button class=\"ps-bs__close-btn\" [attr.aria-label]=\"texts().common.close\" (click)=\"close()\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <!-- Pill search -->\r\n @if (data.showSearch) {\r\n <div class=\"ps-bs__search\">\r\n <mat-icon class=\"ps-bs__search-icon\">search</mat-icon>\r\n <input\r\n class=\"ps-bs__search-input\"\r\n #searchInput\r\n type=\"text\"\r\n [value]=\"query() ?? ''\"\r\n [placeholder]=\"data.searchPlaceholder\"\r\n (input)=\"onQueryInput($event, bodyContainer)\"\r\n />\r\n @if (searchInput.value.length > 0) {\r\n <button\r\n class=\"ps-bs__search-clear\"\r\n type=\"button\"\r\n [attr.aria-label]=\"texts().common.clearSearch\"\r\n (click)=\"clearQuery(bodyContainer); $event.stopPropagation()\"\r\n >\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- \u2500\u2500 Body (\u00DANICA zona de scroll: filtros + chips + select-all + lista) \u2500\u2500\u2500\u2500 -->\r\n <div class=\"ps-bs__body\" #bodyContainer (scroll)=\"onScroll(bodyContainer)\">\r\n\r\n <!-- Extra filters projection -->\r\n @if (data.extraFiltersTemplate) {\r\n <div class=\"ps-bs__extra-filters\">\r\n <ng-container *ngTemplateOutlet=\"data.extraFiltersTemplate\" />\r\n </div>\r\n }\r\n\r\n <!-- Selected chips (custom lightweight chips) -->\r\n @if (data.multiple && selectedItems().length > 0) {\r\n <div class=\"ps-bs__selected-chips\">\r\n @for (item of selectedItems(); track item[data.config.valueKey]) {\r\n <div class=\"ps-bs__chip\">\r\n <span class=\"ps-bs__chip-label\">{{ getLabel(item) }}</span>\r\n <button class=\"ps-bs__chip-remove\" type=\"button\" [attr.aria-label]=\"texts().common.clearSearch\" (click)=\"removeSelectedChip(item)\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Select all (sticky top of the scroll area) -->\r\n @if (data.multiple && data.showSelectAll && options().length > 0) {\r\n <div class=\"ps-bs__select-all\" matRipple (click)=\"toggleSelectAll()\">\r\n <mat-checkbox\r\n [checked]=\"allSelected()\"\r\n [indeterminate]=\"someSelected()\"\r\n (click)=\"$event.preventDefault()\"\r\n />\r\n <span class=\"ps-bs__select-all-label\">{{ data.selectAllLabel }}</span>\r\n </div>\r\n }\r\n\r\n <!-- \u2500\u2500 Options list \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"ps-bs__list\">\r\n\r\n <!-- Skeleton loading (only for the first page) -->\r\n @if (isInitialLoading()) {\r\n @for (i of [1, 2, 3, 4, 5, 6]; track i) {\r\n <div class=\"ps-bs__skeleton\">\r\n <div class=\"ps-bs__skeleton-avatar\"></div>\r\n <div class=\"ps-bs__skeleton-content\">\r\n <div class=\"ps-bs__skeleton-line ps-bs__skeleton-line--title\"></div>\r\n <div class=\"ps-bs__skeleton-line ps-bs__skeleton-line--subtitle\"></div>\r\n </div>\r\n </div>\r\n }\r\n }\r\n\r\n <!-- Error state -->\r\n @if (hasError() && !isLoading() && options().length === 0) {\r\n <div class=\"ps-bs__state ps-bs__error\">\r\n <div class=\"ps-bs__state-icon-wrap ps-bs__error-icon-wrap\">\r\n <mat-icon>error_outline</mat-icon>\r\n </div>\r\n <div class=\"ps-bs__state-title\">{{ texts().paginatedSelect.errorTitle }}</div>\r\n <div class=\"ps-bs__state-hint\">{{ texts().paginatedSelect.errorHint }}</div>\r\n <button matButton=\"tonal\" (click)=\"retry()\">\r\n <mat-icon>refresh</mat-icon>\r\n {{ texts().paginatedSelect.retry }}\r\n </button>\r\n </div>\r\n }\r\n\r\n <!-- Empty state -->\r\n @if (!hasError() && options().length === 0 && !isLoading()) {\r\n <div class=\"ps-bs__state ps-bs__empty\">\r\n <div class=\"ps-bs__state-icon-wrap\">\r\n <mat-icon>search_off</mat-icon>\r\n </div>\r\n <div class=\"ps-bs__state-title\">{{ data.noResultsMessage }}</div>\r\n @if (query()) {\r\n <div class=\"ps-bs__state-hint\">{{ texts().paginatedSelect.noResultsHint }}</div>\r\n <button matButton (click)=\"clearQuery(bodyContainer)\">\r\n {{ texts().paginatedSelect.clearSearch }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Option rows -->\r\n @for (item of options(); track item[data.config.valueKey]) {\r\n @let disabled = data.config.disabled ? data.config.disabled(item) : false;\r\n @let selected = isSelected(item);\r\n @let avatarImg = getAvatarImage(item);\r\n\r\n <div\r\n class=\"ps-bs__option\"\r\n [class.ps-bs__option--selected]=\"selected\"\r\n [class.ps-bs__option--disabled]=\"disabled\"\r\n matRipple\r\n [matRippleDisabled]=\"disabled\"\r\n (click)=\"toggleItem(item)\"\r\n role=\"option\"\r\n [attr.aria-selected]=\"selected\"\r\n [attr.aria-disabled]=\"disabled\"\r\n >\r\n <!-- Avatar (al seleccionar se voltea a un check, estilo Gmail) -->\r\n <div class=\"ps-bs__option-avatar\" [class.ps-bs__option-avatar--selected]=\"selected\">\r\n @if (selected) {\r\n <mat-icon class=\"ps-bs__option-avatar-check\">check</mat-icon>\r\n } @else if (avatarImg) {\r\n <img [src]=\"avatarImg\" [alt]=\"getLabel(item)\" (error)=\"onAvatarError(item)\" loading=\"lazy\" />\r\n } @else if (data.config.avatarText) {\r\n {{ getAvatarText(item) }}\r\n } @else if (data.config.avatarIcon) {\r\n <mat-icon>{{ data.config.avatarIcon }}</mat-icon>\r\n } @else {\r\n {{ getAvatarText(item) }}\r\n }\r\n </div>\r\n\r\n <!-- Content -->\r\n <div class=\"ps-bs__option-content\">\r\n @if (data.optionTemplate) {\r\n <ng-container *ngTemplateOutlet=\"data.optionTemplate; context: { $implicit: item }\" />\r\n } @else {\r\n <span class=\"ps-bs__option-label\">{{ getLabel(item) }}</span>\r\n @if (data.config.subtitle) {\r\n <span class=\"ps-bs__option-subtitle\">{{ data.config.subtitle(item) }}</span>\r\n }\r\n }\r\n </div>\r\n\r\n <!-- Check indicator -->\r\n @if (data.multiple) {\r\n <mat-checkbox [checked]=\"selected\" [disabled]=\"disabled\" (click)=\"$event.preventDefault()\" />\r\n } @else if (selected) {\r\n <mat-icon class=\"ps-bs__option-check\">check_circle</mat-icon>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Loading more (pagination) / end of list -->\r\n @if (isLoadingMore()) {\r\n <div class=\"ps-bs__loading-more\" aria-live=\"polite\">\r\n <span class=\"ps-bs__loading-more-dot\"></span>\r\n <span class=\"ps-bs__loading-more-dot\"></span>\r\n <span class=\"ps-bs__loading-more-dot\"></span>\r\n <span class=\"ps-bs__loading-more-text\">{{ texts().paginatedSelect.loadingMore }}</span>\r\n </div>\r\n } @else if (allLoaded() && options().length > 0) {\r\n <div class=\"ps-bs__list-end\">{{ texts().paginatedSelect.endOfList }}</div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- \u2500\u2500 Footer (ALWAYS VISIBLE \u2014 never scrolls) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"ps-bs__footer\">\r\n <span class=\"ps-bs__footer-count\">\r\n @if (data.multiple) {\r\n {{ texts().paginatedSelect.selectedCount(selectedCount(), total()) }}\r\n } @else {\r\n {{ texts().paginatedSelect.resultsCount(total()) }}\r\n }\r\n </span>\r\n\r\n @if (data.multiple) {\r\n <div class=\"ps-bs__footer-actions\">\r\n @if (selectedCount() > 0) {\r\n <button matButton (click)=\"reset()\">{{ data.resetLabel }}</button>\r\n }\r\n <button matButton=\"filled\" color=\"primary\" (click)=\"confirm()\">{{ data.confirmLabel }}</button>\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n", styles: [".cdk-global-overlay-wrapper:has(.ngx-paginated-select-panel){align-items:center!important;justify-content:center!important}.ngx-paginated-select-backdrop{background:color-mix(in srgb,var(--mat-sys-scrim, #000) 40%,transparent);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.ngx-paginated-select-panel .mat-bottom-sheet-container{padding:0!important;overflow:hidden!important;display:flex!important;flex-direction:column!important;width:min(640px,100vw - 48px);min-width:0;max-width:640px;height:min(86vh,760px)!important;max-height:min(86vh,760px)!important;border-radius:28px;background:var(--mat-sys-surface-container-high);border:1px solid color-mix(in srgb,var(--mat-sys-outline-variant) 60%,transparent);box-shadow:0 1px 3px #0000001f,0 8px 24px #00000024,0 24px 48px #0000001a!important}ngx-paginated-select-bottom-sheet{display:flex;flex-direction:column;flex:1 1 0;min-height:0;overflow:hidden;width:100%}.ps-bs{display:flex;flex-direction:column;height:100%;overflow:hidden}.ps-bs__handle{display:none;justify-content:center;padding:12px 0 4px;flex:0 0 auto}.ps-bs__handle-bar{width:32px;height:4px;border-radius:9999px;background:var(--mat-sys-outline-variant)}.ps-bs__header{flex:0 0 auto;padding:20px 24px 14px;display:flex;flex-direction:column;gap:14px;position:relative;z-index:2;transition:box-shadow .2s cubic-bezier(.2,0,0,1)}.ps-bs__header--scrolled{box-shadow:0 1px 0 0 var(--mat-sys-outline-variant),0 6px 14px -10px #00000059}.ps-bs__header-top{display:flex;align-items:center;justify-content:space-between;gap:8px}.ps-bs__title-area{display:flex;align-items:center;gap:10px;flex:1;min-width:0}.ps-bs__title{font:var(--mat-sys-title-large);font-weight:600;color:var(--mat-sys-on-surface);letter-spacing:-.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ps-bs__badge{display:inline-flex;align-items:center;justify-content:center;min-width:22px;height:22px;padding:0 7px;border-radius:9999px;font:var(--mat-sys-label-medium);font-weight:700;font-variant-numeric:tabular-nums;background:var(--mat-sys-primary);color:var(--mat-sys-on-primary);flex-shrink:0;animation:ps-badge-pop .3s cubic-bezier(.34,1.56,.64,1)}@keyframes ps-badge-pop{0%{transform:scale(0)}to{transform:scale(1)}}.ps-bs__close-btn{flex:0 0 auto}.ps-bs__search{display:flex;align-items:center;gap:10px;height:48px;padding:0 6px 0 16px;background:var(--mat-sys-surface-container-highest);border-radius:9999px;border:1.5px solid transparent;transition:background .2s cubic-bezier(.2,0,0,1),border-color .2s cubic-bezier(.2,0,0,1),box-shadow .2s cubic-bezier(.2,0,0,1)}.ps-bs__search:hover{background:color-mix(in srgb,var(--mat-sys-on-surface) 4%,var(--mat-sys-surface-container-highest))}.ps-bs__search:focus-within{background:var(--mat-sys-surface);border-color:var(--mat-sys-primary);box-shadow:0 0 0 4px color-mix(in srgb,var(--mat-sys-primary) 12%,transparent)}.ps-bs__search-icon{color:var(--mat-sys-on-surface-variant);font-size:22px;width:22px;height:22px;flex-shrink:0;transition:color .2s cubic-bezier(.2,0,0,1)}.ps-bs__search:focus-within .ps-bs__search-icon{color:var(--mat-sys-primary)}.ps-bs__search-input{flex:1;border:none;outline:none;background:transparent;font:var(--mat-sys-body-large);font-family:inherit;color:var(--mat-sys-on-surface);min-width:0}.ps-bs__search-input::placeholder{color:var(--mat-sys-on-surface-variant)}.ps-bs__search-clear{display:flex;align-items:center;justify-content:center;width:34px;height:34px;border-radius:50%;border:none;background:transparent;cursor:pointer;color:var(--mat-sys-on-surface-variant);transition:background .15s cubic-bezier(.2,0,0,1);flex-shrink:0}.ps-bs__search-clear:hover{background:color-mix(in srgb,var(--mat-sys-on-surface) 10%,transparent)}.ps-bs__search-clear mat-icon{font-size:20px;width:20px;height:20px}.ps-bs__body{flex:1 1 auto;min-height:0;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;padding:6px 10px 8px;display:flex;flex-direction:column}.ps-bs__body>*{flex-shrink:0}.ps-bs__extra-filters{width:100%;padding:10px 6px 6px}.ps-bs__selected-chips{display:flex;flex-wrap:wrap;gap:8px;padding:4px 6px 6px}.ps-bs__chip{display:inline-flex;align-items:center;gap:2px;height:32px;padding:0 4px 0 12px;border-radius:9999px;background:var(--mat-sys-secondary-container);color:var(--mat-sys-on-secondary-container);font:var(--mat-sys-label-large);white-space:nowrap;max-width:200px;animation:ps-chip-in .2s cubic-bezier(.2,0,0,1)}.ps-bs__chip-label{overflow:hidden;text-overflow:ellipsis}.ps-bs__chip-remove{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:50%;border:none;background:transparent;cursor:pointer;color:inherit;opacity:.55;transition:opacity .15s,background .15s}.ps-bs__chip-remove:hover{opacity:1;background:color-mix(in srgb,var(--mat-sys-on-secondary-container) 12%,transparent)}.ps-bs__chip-remove mat-icon{font-size:16px;width:16px;height:16px}@keyframes ps-chip-in{0%{transform:scale(.85);opacity:0}to{transform:scale(1);opacity:1}}.ps-bs__select-all.ps-bs__select-all{position:sticky;top:-6px;z-index:3;display:flex;align-items:center;gap:12px;margin:0 -10px;padding:8px 24px;cursor:pointer;background:var(--mat-sys-surface-container-high);border-bottom:1px solid var(--mat-sys-outline-variant);transition:background .15s cubic-bezier(.2,0,0,1)}.ps-bs__select-all.ps-bs__select-all:hover{background:color-mix(in srgb,var(--mat-sys-on-surface) 5%,var(--mat-sys-surface-container-high))}.ps-bs__select-all.ps-bs__select-all-label{font:var(--mat-sys-label-large);color:var(--mat-sys-on-surface)}.ps-bs__list{flex:1 1 auto}.ps-bs__option{display:flex;align-items:center;gap:14px;padding:8px 12px;margin:2px 0;cursor:pointer;border-radius:16px;min-height:56px;transition:background .15s cubic-bezier(.2,0,0,1)}.ps-bs__option:hover:not(.ps-bs__option--disabled){background:color-mix(in srgb,var(--mat-sys-on-surface) 8%,transparent)}.ps-bs__option:active:not(.ps-bs__option--disabled){background:color-mix(in srgb,var(--mat-sys-on-surface) 12%,transparent)}.ps-bs__option--selected{background:color-mix(in srgb,var(--mat-sys-primary) 10%,transparent)}.ps-bs__option--selected:hover{background:color-mix(in srgb,var(--mat-sys-primary) 14%,transparent)}.ps-bs__option--disabled{opacity:.38;cursor:not-allowed}.ps-bs__option .mat-ripple-element{background:color-mix(in srgb,var(--mat-sys-primary) 12%,transparent)}.ps-bs__option .mat-mdc-checkbox{margin-left:auto;margin-right:-8px;flex-shrink:0}.ps-bs__option-avatar{width:40px;height:40px;min-width:40px;border-radius:50%;overflow:hidden;display:flex;align-items:center;justify-content:center;font:var(--mat-sys-label-large);font-weight:600;background:var(--mat-sys-primary-container);color:var(--mat-sys-on-primary-container);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--mat-sys-on-surface) 8%,transparent);transition:box-shadow .18s cubic-bezier(.2,0,0,1)}.ps-bs__option-avatar img{width:100%;height:100%;object-fit:cover;display:block}.ps-bs__option-avatar mat-icon{font-size:20px;width:20px;height:20px}.ps-bs__option-avatar--selected{background:var(--mat-sys-primary);color:var(--mat-sys-on-primary);box-shadow:none;animation:ps-avatar-flip .25s cubic-bezier(.05,.7,.1,1)}.ps-bs__option-avatar-check{color:var(--mat-sys-on-primary)}@keyframes ps-avatar-flip{0%{transform:scale(.6) rotate(-30deg);opacity:.4}to{transform:scale(1) rotate(0);opacity:1}}.ps-bs__option-content{flex:1;display:flex;flex-direction:column;gap:2px;min-width:0}.ps-bs__option-label{font:var(--mat-sys-body-large);color:var(--mat-sys-on-surface);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ps-bs__option--selected .ps-bs__option-label{font-weight:600}.ps-bs__option-subtitle{font:var(--mat-sys-body-small);color:var(--mat-sys-on-surface-variant);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ps-bs__option-check{color:var(--mat-sys-primary);font-size:22px;width:22px;height:22px;margin-left:auto;flex-shrink:0}.ps-bs__skeleton{display:flex;align-items:center;gap:14px;padding:8px 12px;margin:2px 0;min-height:56px;border-radius:16px;opacity:0;animation:ps-skeleton-in .4s ease forwards}.ps-bs__skeleton-avatar{width:40px;height:40px;min-width:40px;border-radius:50%;background:linear-gradient(90deg,var(--mat-sys-surface-container) 25%,var(--mat-sys-surface-container-highest) 37%,var(--mat-sys-surface-container) 63%);background-size:400% 100%;animation:ps-shimmer 1.4s ease-in-out infinite}.ps-bs__skeleton-content{flex:1;display:flex;flex-direction:column;gap:10px}.ps-bs__skeleton-line{height:12px;border-radius:6px;background:linear-gradient(90deg,var(--mat-sys-surface-container) 25%,var(--mat-sys-surface-container-highest) 37%,var(--mat-sys-surface-container) 63%);background-size:400% 100%;animation:ps-shimmer 1.4s ease-in-out infinite}.ps-bs__skeleton-line--title{width:60%}.ps-bs__skeleton-line--subtitle{width:38%;height:10px}.ps-bs__skeleton:nth-child(1){animation-delay:0ms}.ps-bs__skeleton:nth-child(2){animation-delay:60ms}.ps-bs__skeleton:nth-child(3){animation-delay:.12s}.ps-bs__skeleton:nth-child(4){animation-delay:.18s}.ps-bs__skeleton:nth-child(5){animation-delay:.24s}.ps-bs__skeleton:nth-child(6){animation-delay:.3s}@keyframes ps-skeleton-in{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@keyframes ps-shimmer{0%{background-position:100% 0}to{background-position:-100% 0}}.ps-bs__loading-more{display:flex;align-items:center;justify-content:center;gap:6px;padding:18px;color:var(--mat-sys-on-surface-variant);font:var(--mat-sys-body-small)}.ps-bs__loading-more-dot{width:6px;height:6px;border-radius:50%;background:var(--mat-sys-primary);animation:ps-bounce 1s ease-in-out infinite}.ps-bs__loading-more-dot:nth-child(2){animation-delay:.15s}.ps-bs__loading-more-dot:nth-child(3){animation-delay:.3s}.ps-bs__loading-more-text{margin-left:6px}@keyframes ps-bounce{0%,80%,to{transform:translateY(0);opacity:.4}40%{transform:translateY(-4px);opacity:1}}.ps-bs__list-end{text-align:center;padding:16px;font:var(--mat-sys-body-small);color:var(--mat-sys-on-surface-variant);opacity:.7}.ps-bs__state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:56px 32px;gap:12px;text-align:center;animation:ps-fade-in .2s ease}.ps-bs__state-icon-wrap{width:72px;height:72px;border-radius:50%;display:flex;align-items:center;justify-content:center;background:var(--mat-sys-surface-container-highest)}.ps-bs__state-icon-wrap mat-icon{font-size:32px;width:32px;height:32px;color:var(--mat-sys-on-surface-variant)}.ps-bs__state-title{font:var(--mat-sys-title-medium);color:var(--mat-sys-on-surface)}.ps-bs__state-hint{font:var(--mat-sys-body-medium);color:var(--mat-sys-on-surface-variant);max-width:280px}.ps-bs__state button{margin-top:4px}.ps-bs__error-icon-wrap{background:color-mix(in srgb,var(--mat-sys-error) 12%,transparent)}.ps-bs__error-icon-wrap mat-icon{color:var(--mat-sys-error)}@keyframes ps-fade-in{0%{opacity:0}to{opacity:1}}.ps-bs__footer{flex:0 0 auto;display:flex;align-items:center;justify-content:space-between;padding:16px 24px;gap:12px;z-index:2;background:var(--mat-sys-surface-container-high);border-top:1px solid var(--mat-sys-outline-variant)}.ps-bs__footer-count{font:var(--mat-sys-body-medium);color:var(--mat-sys-on-surface-variant);font-variant-numeric:tabular-nums;white-space:nowrap}.ps-bs__footer-actions{display:flex;gap:8px;align-items:center}.ps-bs__footer-actions button[matButton=filled]{min-width:96px;border-radius:9999px}@media (max-width: 600px){.cdk-global-overlay-wrapper:has(.ngx-paginated-select-panel){align-items:flex-end!important}.ngx-paginated-select-panel .mat-bottom-sheet-container{width:100vw;max-width:100vw;height:90vh!important;max-height:90vh!important;border-radius:24px 24px 0 0;border-bottom:none}.ps-bs__handle{display:flex}.ps-bs__header{padding:8px 16px 12px}.ps-bs__footer{padding:12px 16px}.ps-bs__body{padding:4px 8px 6px}.ps-bs__select-all{margin:0 -8px}}@media (prefers-reduced-motion: reduce){.ps-bs__badge,.ps-bs__chip,.ps-bs__skeleton,.ps-bs__option-avatar--selected,.ps-bs__state{animation:none}.ps-bs__skeleton-avatar,.ps-bs__skeleton-line{animation:none;background:var(--mat-sys-surface-container-highest)}.ps-bs__loading-more-dot{animation:none;opacity:.7}}\n"] }]
3524
3937
  }], ctorParameters: () => [] });
3525
3938
 
3526
3939
  class NgxPaginatedSelect {
@@ -3532,7 +3945,7 @@ class NgxPaginatedSelect {
3532
3945
  _parentFormGroup = inject(FormGroupDirective, { optional: true });
3533
3946
  _parentForm = inject(NgForm, { optional: true });
3534
3947
  _changeDetectorRef = inject(ChangeDetectorRef);
3535
- intl = inject(NgxTablesIntl);
3948
+ texts = inject(NgxTexts).texts;
3536
3949
  // ─── Inputs ────────────────────────────────────────────────────────────────
3537
3950
  /** Label that floats on the form field */
3538
3951
  label = input.required(...(ngDevMode ? [{ debugName: "label" }] : []));
@@ -3565,9 +3978,9 @@ class NgxPaginatedSelect {
3565
3978
  displayMode = input('chips', ...(ngDevMode ? [{ debugName: "displayMode" }] : []));
3566
3979
  /** Whether to show the search input inside the bottom sheet */
3567
3980
  showSearch = input(true, ...(ngDevMode ? [{ debugName: "showSearch", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
3568
- /** Placeholder for the search input inside the bottom sheet (defaults to intl) */
3981
+ /** Placeholder for the search input inside the bottom sheet (defaults to the library texts) */
3569
3982
  searchPlaceholder = input(...(ngDevMode ? [undefined, { debugName: "searchPlaceholder" }] : []));
3570
- /** Message when no results are found (defaults to intl) */
3983
+ /** Message when no results are found (defaults to the library texts) */
3571
3984
  noResultsMessage = input(...(ngDevMode ? [undefined, { debugName: "noResultsMessage" }] : []));
3572
3985
  /** Label for the confirm button (multiple mode, defaults to intl) */
3573
3986
  confirmLabel = input(...(ngDevMode ? [undefined, { debugName: "confirmLabel" }] : []));
@@ -3592,7 +4005,7 @@ class NgxPaginatedSelect {
3592
4005
  chipsDirection = input('column', ...(ngDevMode ? [{ debugName: "chipsDirection" }] : []));
3593
4006
  /** Whether to show a "Select all" toggle in the bottom sheet (multiple mode) */
3594
4007
  showSelectAll = input(false, ...(ngDevMode ? [{ debugName: "showSelectAll", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
3595
- /** Label for the select all toggle (defaults to intl) */
4008
+ /** Label for the select all toggle (defaults to the library texts) */
3596
4009
  selectAllLabel = input(...(ngDevMode ? [undefined, { debugName: "selectAllLabel" }] : []));
3597
4010
  // ─── Outputs ───────────────────────────────────────────────────────────────
3598
4011
  /** Emits the full T object (single) or T[] (multiple) when selection changes */
@@ -3645,12 +4058,12 @@ class NgxPaginatedSelect {
3645
4058
  isRequired() {
3646
4059
  return this._ngControl?.control?.hasValidator(Validators.required) ?? false;
3647
4060
  }
3648
- // Etiquetas efectivas (override por input o valor por defecto de intl)
3649
- effectiveSearchPlaceholder = computed(() => this.searchPlaceholder() ?? this.intl.searchPlaceholder, ...(ngDevMode ? [{ debugName: "effectiveSearchPlaceholder" }] : []));
3650
- effectiveNoResults = computed(() => this.noResultsMessage() ?? this.intl.noResultsMessage, ...(ngDevMode ? [{ debugName: "effectiveNoResults" }] : []));
3651
- effectiveConfirmLabel = computed(() => this.confirmLabel() ?? this.intl.paginatedSelectConfirmLabel, ...(ngDevMode ? [{ debugName: "effectiveConfirmLabel" }] : []));
3652
- effectiveResetLabel = computed(() => this.resetLabel() ?? this.intl.paginatedSelectResetLabel, ...(ngDevMode ? [{ debugName: "effectiveResetLabel" }] : []));
3653
- effectiveSelectAllLabel = computed(() => this.selectAllLabel() ?? this.intl.paginatedSelectSelectAllLabel, ...(ngDevMode ? [{ debugName: "effectiveSelectAllLabel" }] : []));
4061
+ // Etiquetas efectivas (override por input o valor por defecto de NgxTexts)
4062
+ effectiveSearchPlaceholder = computed(() => this.searchPlaceholder() ?? this.texts().common.search, ...(ngDevMode ? [{ debugName: "effectiveSearchPlaceholder" }] : []));
4063
+ effectiveNoResults = computed(() => this.noResultsMessage() ?? this.texts().select.noResults, ...(ngDevMode ? [{ debugName: "effectiveNoResults" }] : []));
4064
+ effectiveConfirmLabel = computed(() => this.confirmLabel() ?? this.texts().paginatedSelect.confirm, ...(ngDevMode ? [{ debugName: "effectiveConfirmLabel" }] : []));
4065
+ effectiveResetLabel = computed(() => this.resetLabel() ?? this.texts().paginatedSelect.reset, ...(ngDevMode ? [{ debugName: "effectiveResetLabel" }] : []));
4066
+ effectiveSelectAllLabel = computed(() => this.selectAllLabel() ?? this.texts().paginatedSelect.selectAll, ...(ngDevMode ? [{ debugName: "effectiveSelectAllLabel" }] : []));
3654
4067
  constructor() {
3655
4068
  if (this._ngControl)
3656
4069
  this._ngControl.valueAccessor = this;
@@ -3837,7 +4250,7 @@ class NgxPaginatedSelect {
3837
4250
  this._ngControl?.control?.markAsTouched();
3838
4251
  }
3839
4252
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxPaginatedSelect, deps: [], target: i0.ɵɵFactoryTarget.Component });
3840
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: NgxPaginatedSelect, isStandalone: true, selector: "ngx-paginated-select", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, endpoint: { classPropertyName: "endpoint", publicName: "endpoint", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, filters: { classPropertyName: "filters", publicName: "filters", isSignal: true, isRequired: false, transformFunction: null }, selectedItems: { classPropertyName: "selectedItems", publicName: "selectedItems", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, displayMode: { classPropertyName: "displayMode", publicName: "displayMode", isSignal: true, isRequired: false, transformFunction: null }, showSearch: { classPropertyName: "showSearch", publicName: "showSearch", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, noResultsMessage: { classPropertyName: "noResultsMessage", publicName: "noResultsMessage", isSignal: true, isRequired: false, transformFunction: null }, confirmLabel: { classPropertyName: "confirmLabel", publicName: "confirmLabel", isSignal: true, isRequired: false, transformFunction: null }, resetLabel: { classPropertyName: "resetLabel", publicName: "resetLabel", isSignal: true, isRequired: false, transformFunction: null }, subscriptSizing: { classPropertyName: "subscriptSizing", publicName: "subscriptSizing", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, optionTemplate: { classPropertyName: "optionTemplate", publicName: "optionTemplate", isSignal: true, isRequired: false, transformFunction: null }, extraFiltersTemplate: { classPropertyName: "extraFiltersTemplate", publicName: "extraFiltersTemplate", isSignal: true, isRequired: false, transformFunction: null }, maxChipsDisplayed: { classPropertyName: "maxChipsDisplayed", publicName: "maxChipsDisplayed", isSignal: true, isRequired: false, transformFunction: null }, chipsDirection: { classPropertyName: "chipsDirection", publicName: "chipsDirection", isSignal: true, isRequired: false, transformFunction: null }, showSelectAll: { classPropertyName: "showSelectAll", publicName: "showSelectAll", isSignal: true, isRequired: false, transformFunction: null }, selectAllLabel: { classPropertyName: "selectAllLabel", publicName: "selectAllLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", selectionChange: "selectionChange" }, ngImport: i0, template: "<!-- \u2500\u2500 Chips mode (multiple + displayMode = 'chips') \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n@if (showChips()) {\n <mat-form-field\n appearance=\"outline\"\n floatLabel=\"always\"\n [subscriptSizing]=\"subscriptSizing()\"\n class=\"ps-trigger\"\n [class.ps-trigger--disabled]=\"isDisabled()\"\n [class.ps-trigger--open]=\"_isOpen()\"\n [class.ps-trigger--row]=\"chipsDirection() === 'row'\"\n (click)=\"openBottomSheet($event)\"\n >\n <mat-label>{{ label() }}</mat-label>\n\n <mat-chip-grid\n #chipGrid\n class=\"ps-trigger__chip-grid\"\n [class.ps-trigger__chip-grid--column]=\"chipsDirection() === 'column'\"\n [formControl]=\"innerControl\"\n [errorStateMatcher]=\"errorStateMatcher\"\n [required]=\"isRequired()\"\n >\n @for (item of displayedChips(); track item[config().valueKey]) {\n <mat-chip-row\n class=\"ps-trigger__chip\"\n [value]=\"item[config().valueKey]\"\n [disabled]=\"isDisabled()\"\n (removed)=\"removeChip(item, $event)\"\n >\n {{ getLabel(item) }}\n <button matChipRemove [disabled]=\"isDisabled()\" (click)=\"$event.stopPropagation()\">\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip-row>\n }\n </mat-chip-grid>\n\n @if (remainingChipsCount() > 0) {\n <span class=\"ps-trigger__remaining\">+{{ remainingChipsCount() }}</span>\n }\n\n <!-- Hidden input required for mat-chip-grid; tambi\u00E9n da foco de teclado al trigger -->\n <input\n matInput\n [matChipInputFor]=\"chipGrid\"\n class=\"ps-trigger__kbd-input\"\n [required]=\"isRequired()\"\n readonly\n role=\"combobox\"\n [attr.aria-haspopup]=\"'dialog'\"\n [attr.aria-expanded]=\"_isOpen()\"\n [attr.aria-label]=\"label()\"\n (keydown)=\"onTriggerKeydown($event)\"\n />\n\n <div matSuffix class=\"ps-trigger__suffix\">\n @if (clearable() && hasSelection() && !isDisabled()) {\n <button matIconButton matSuffix [attr.aria-label]=\"intl.clearSearchTooltip\" (click)=\"clearSelection($event)\">\n <mat-icon>close</mat-icon>\n </button>\n }\n <mat-icon [class.ps-trigger__arrow--open]=\"_isOpen()\">arrow_drop_down</mat-icon>\n </div>\n\n @if (error()) {\n <mat-error>{{ error() }}</mat-error>\n }\n @if (hint()) {\n <mat-hint>{{ hint() }}</mat-hint>\n }\n </mat-form-field>\n}\n\n<!-- \u2500\u2500 Text mode (single or multiple + displayMode = 'text') \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n@if (!showChips()) {\n <mat-form-field\n appearance=\"outline\"\n floatLabel=\"always\"\n [subscriptSizing]=\"subscriptSizing()\"\n class=\"ps-trigger\"\n [class.ps-trigger--disabled]=\"isDisabled()\"\n [class.ps-trigger--open]=\"_isOpen()\"\n (click)=\"openBottomSheet($event)\"\n >\n <mat-label>{{ label() }}</mat-label>\n\n <input\n matInput\n class=\"ps-trigger__input\"\n [required]=\"isRequired()\"\n readonly\n role=\"combobox\"\n [attr.aria-haspopup]=\"'dialog'\"\n [attr.aria-expanded]=\"_isOpen()\"\n [formControl]=\"innerControl\"\n [errorStateMatcher]=\"errorStateMatcher\"\n (keydown)=\"onTriggerKeydown($event)\"\n />\n\n <div matSuffix class=\"ps-trigger__suffix\">\n @if (clearable() && hasSelection() && !isDisabled()) {\n <button matIconButton matSuffix [attr.aria-label]=\"intl.clearSearchTooltip\" (click)=\"clearSelection($event)\">\n <mat-icon>close</mat-icon>\n </button>\n }\n <mat-icon [class.ps-trigger__arrow--open]=\"_isOpen()\">arrow_drop_down</mat-icon>\n </div>\n\n @if (error()) {\n <mat-error>{{ error() }}</mat-error>\n }\n @if (hint()) {\n <mat-hint>{{ hint() }}</mat-hint>\n }\n </mat-form-field>\n}\n", styles: [":host{display:block}.ps-trigger{width:100%;cursor:pointer;--mat-form-field-outlined-focus-outline-color: var(--mat-sys-outline);--mat-form-field-outlined-outline-color: var(--mat-sys-outline);--mat-form-field-outlined-hover-outline-color: var(--mat-sys-outline)}.ps-trigger ::ng-deep .mat-mdc-form-field-flex{cursor:pointer}.ps-trigger--open{--mat-form-field-outlined-outline-color: var(--mat-sys-primary);--mat-form-field-outlined-focus-outline-color: var(--mat-sys-primary);--mat-form-field-outlined-hover-outline-color: var(--mat-sys-primary)}.ps-trigger__input{cursor:pointer!important;caret-color:transparent;pointer-events:none}.ps-trigger__kbd-input{width:0;min-width:0;flex:0 0 0;padding:0;margin:0;caret-color:transparent}.ps-trigger__chip-grid{cursor:pointer;min-height:36px}.ps-trigger__chip-grid ::ng-deep .mdc-evolution-chip-set__chips{flex-wrap:nowrap;overflow:hidden;gap:6px}.ps-trigger__chip-grid--column ::ng-deep .mdc-evolution-chip-set__chips{flex-wrap:wrap;overflow:visible}.ps-trigger__chip.mat-mdc-chip{height:30px;border:none!important;background-color:var(--mat-sys-secondary-container)!important;color:var(--mat-sys-on-secondary-container);font:var(--mat-sys-label-large);box-shadow:none!important;--mdc-chip-elevated-container-elevation: none;--mdc-chip-outline-width: 0}.ps-trigger__chip.mat-mdc-chip ::ng-deep .mat-mdc-chip-focus-overlay{display:none}.ps-trigger__suffix{display:flex;align-items:center;gap:0;flex-shrink:0}.ps-trigger__clear{width:28px;height:28px;line-height:28px;opacity:.6}.ps-trigger__clear:hover{opacity:1}.ps-trigger__clear mat-icon{font-size:18px;width:18px;height:18px}.ps-trigger__remaining{display:inline-flex;align-items:center;justify-content:center;min-width:24px;height:22px;padding:0 7px;font-size:11px;font-weight:600;font-variant-numeric:tabular-nums;background:var(--mat-sys-surface-container-highest);color:var(--mat-sys-on-surface-variant);margin-left:6px;white-space:nowrap;flex-shrink:0}.ps-trigger .ps-trigger__arrow--open{transform:rotate(180deg);transition:transform .2s ease}.ps-trigger mat-icon:not(.ps-trigger__clear mat-icon){transition:transform .2s ease}.ps-trigger--row ::ng-deep .mat-mdc-form-field-infix{display:flex;align-items:center;flex-wrap:nowrap;overflow:hidden;min-height:56px}.ps-trigger--row .ps-trigger__chip-grid{flex:1 1 auto;min-width:0;min-height:0;overflow:hidden}.ps-trigger--row .ps-trigger__chip-grid ::ng-deep .mdc-evolution-chip-set__chips{min-height:0}.ps-trigger--row .ps-trigger__remaining{flex:0 0 auto}.ps-trigger--disabled{cursor:not-allowed}.ps-trigger--disabled ::ng-deep .mat-mdc-form-field-flex{cursor:not-allowed}.ps-trigger--disabled .ps-trigger__input,.ps-trigger--disabled .ps-trigger__chip,.ps-trigger--disabled .ps-trigger__suffix{opacity:.38}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatBottomSheetModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i2$1.MatChipGrid, selector: "mat-chip-grid", inputs: ["disabled", "placeholder", "required", "value", "errorStateMatcher"], outputs: ["change", "valueChange"] }, { kind: "directive", type: i2$1.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled", "readonly", "matChipInputDisabledInteractive"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { kind: "directive", type: i2$1.MatChipRemove, selector: "[matChipRemove]" }, { kind: "component", type: i2$1.MatChipRow, selector: "mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]", inputs: ["editable"], outputs: ["edited"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$2.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i2$2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i2$2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "ngmodule", type: MatProgressSpinnerModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4253
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: NgxPaginatedSelect, isStandalone: true, selector: "ngx-paginated-select", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, endpoint: { classPropertyName: "endpoint", publicName: "endpoint", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, filters: { classPropertyName: "filters", publicName: "filters", isSignal: true, isRequired: false, transformFunction: null }, selectedItems: { classPropertyName: "selectedItems", publicName: "selectedItems", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, displayMode: { classPropertyName: "displayMode", publicName: "displayMode", isSignal: true, isRequired: false, transformFunction: null }, showSearch: { classPropertyName: "showSearch", publicName: "showSearch", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, noResultsMessage: { classPropertyName: "noResultsMessage", publicName: "noResultsMessage", isSignal: true, isRequired: false, transformFunction: null }, confirmLabel: { classPropertyName: "confirmLabel", publicName: "confirmLabel", isSignal: true, isRequired: false, transformFunction: null }, resetLabel: { classPropertyName: "resetLabel", publicName: "resetLabel", isSignal: true, isRequired: false, transformFunction: null }, subscriptSizing: { classPropertyName: "subscriptSizing", publicName: "subscriptSizing", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, optionTemplate: { classPropertyName: "optionTemplate", publicName: "optionTemplate", isSignal: true, isRequired: false, transformFunction: null }, extraFiltersTemplate: { classPropertyName: "extraFiltersTemplate", publicName: "extraFiltersTemplate", isSignal: true, isRequired: false, transformFunction: null }, maxChipsDisplayed: { classPropertyName: "maxChipsDisplayed", publicName: "maxChipsDisplayed", isSignal: true, isRequired: false, transformFunction: null }, chipsDirection: { classPropertyName: "chipsDirection", publicName: "chipsDirection", isSignal: true, isRequired: false, transformFunction: null }, showSelectAll: { classPropertyName: "showSelectAll", publicName: "showSelectAll", isSignal: true, isRequired: false, transformFunction: null }, selectAllLabel: { classPropertyName: "selectAllLabel", publicName: "selectAllLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", selectionChange: "selectionChange" }, ngImport: i0, template: "<!-- \u2500\u2500 Chips mode (multiple + displayMode = 'chips') \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n@if (showChips()) {\r\n <mat-form-field\r\n appearance=\"outline\"\r\n floatLabel=\"always\"\r\n [subscriptSizing]=\"subscriptSizing()\"\r\n class=\"ps-trigger\"\r\n [class.ps-trigger--disabled]=\"isDisabled()\"\r\n [class.ps-trigger--open]=\"_isOpen()\"\r\n [class.ps-trigger--row]=\"chipsDirection() === 'row'\"\r\n (click)=\"openBottomSheet($event)\"\r\n >\r\n <mat-label>{{ label() }}</mat-label>\r\n\r\n <mat-chip-grid\r\n #chipGrid\r\n class=\"ps-trigger__chip-grid\"\r\n [class.ps-trigger__chip-grid--column]=\"chipsDirection() === 'column'\"\r\n [formControl]=\"innerControl\"\r\n [errorStateMatcher]=\"errorStateMatcher\"\r\n [required]=\"isRequired()\"\r\n >\r\n @for (item of displayedChips(); track item[config().valueKey]) {\r\n <mat-chip-row\r\n class=\"ps-trigger__chip\"\r\n [value]=\"item[config().valueKey]\"\r\n [disabled]=\"isDisabled()\"\r\n (removed)=\"removeChip(item, $event)\"\r\n >\r\n {{ getLabel(item) }}\r\n <button matChipRemove [disabled]=\"isDisabled()\" (click)=\"$event.stopPropagation()\">\r\n <mat-icon>cancel</mat-icon>\r\n </button>\r\n </mat-chip-row>\r\n }\r\n </mat-chip-grid>\r\n\r\n @if (remainingChipsCount() > 0) {\r\n <span class=\"ps-trigger__remaining\">+{{ remainingChipsCount() }}</span>\r\n }\r\n\r\n <!-- Hidden input required for mat-chip-grid; tambi\u00E9n da foco de teclado al trigger -->\r\n <input\r\n matInput\r\n [matChipInputFor]=\"chipGrid\"\r\n class=\"ps-trigger__kbd-input\"\r\n [required]=\"isRequired()\"\r\n readonly\r\n role=\"combobox\"\r\n [attr.aria-haspopup]=\"'dialog'\"\r\n [attr.aria-expanded]=\"_isOpen()\"\r\n [attr.aria-label]=\"label()\"\r\n (keydown)=\"onTriggerKeydown($event)\"\r\n />\r\n\r\n <div matSuffix class=\"ps-trigger__suffix\">\r\n @if (clearable() && hasSelection() && !isDisabled()) {\r\n <button matIconButton matSuffix [attr.aria-label]=\"texts().common.clearSearch\" (click)=\"clearSelection($event)\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n }\r\n <mat-icon [class.ps-trigger__arrow--open]=\"_isOpen()\">arrow_drop_down</mat-icon>\r\n </div>\r\n\r\n @if (error()) {\r\n <mat-error>{{ error() }}</mat-error>\r\n }\r\n @if (hint()) {\r\n <mat-hint>{{ hint() }}</mat-hint>\r\n }\r\n </mat-form-field>\r\n}\r\n\r\n<!-- \u2500\u2500 Text mode (single or multiple + displayMode = 'text') \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n@if (!showChips()) {\r\n <mat-form-field\r\n appearance=\"outline\"\r\n floatLabel=\"always\"\r\n [subscriptSizing]=\"subscriptSizing()\"\r\n class=\"ps-trigger\"\r\n [class.ps-trigger--disabled]=\"isDisabled()\"\r\n [class.ps-trigger--open]=\"_isOpen()\"\r\n (click)=\"openBottomSheet($event)\"\r\n >\r\n <mat-label>{{ label() }}</mat-label>\r\n\r\n <input\r\n matInput\r\n class=\"ps-trigger__input\"\r\n [required]=\"isRequired()\"\r\n readonly\r\n role=\"combobox\"\r\n [attr.aria-haspopup]=\"'dialog'\"\r\n [attr.aria-expanded]=\"_isOpen()\"\r\n [formControl]=\"innerControl\"\r\n [errorStateMatcher]=\"errorStateMatcher\"\r\n (keydown)=\"onTriggerKeydown($event)\"\r\n />\r\n\r\n <div matSuffix class=\"ps-trigger__suffix\">\r\n @if (clearable() && hasSelection() && !isDisabled()) {\r\n <button matIconButton matSuffix [attr.aria-label]=\"texts().common.clearSearch\" (click)=\"clearSelection($event)\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n }\r\n <mat-icon [class.ps-trigger__arrow--open]=\"_isOpen()\">arrow_drop_down</mat-icon>\r\n </div>\r\n\r\n @if (error()) {\r\n <mat-error>{{ error() }}</mat-error>\r\n }\r\n @if (hint()) {\r\n <mat-hint>{{ hint() }}</mat-hint>\r\n }\r\n </mat-form-field>\r\n}\r\n", styles: [":host{display:block}.ps-trigger{width:100%;cursor:pointer;--mat-form-field-outlined-focus-outline-color: var(--mat-sys-outline);--mat-form-field-outlined-outline-color: var(--mat-sys-outline);--mat-form-field-outlined-hover-outline-color: var(--mat-sys-outline)}.ps-trigger ::ng-deep .mat-mdc-form-field-flex{cursor:pointer}.ps-trigger--open{--mat-form-field-outlined-outline-color: var(--mat-sys-primary);--mat-form-field-outlined-focus-outline-color: var(--mat-sys-primary);--mat-form-field-outlined-hover-outline-color: var(--mat-sys-primary)}.ps-trigger__input{cursor:pointer!important;caret-color:transparent;pointer-events:none}.ps-trigger__kbd-input{width:0;min-width:0;flex:0 0 0;padding:0;margin:0;caret-color:transparent}.ps-trigger__chip-grid{cursor:pointer;min-height:36px}.ps-trigger__chip-grid ::ng-deep .mdc-evolution-chip-set__chips{flex-wrap:nowrap;overflow:hidden;gap:6px}.ps-trigger__chip-grid--column ::ng-deep .mdc-evolution-chip-set__chips{flex-wrap:wrap;overflow:visible}.ps-trigger__chip.mat-mdc-chip{height:30px;border:none!important;background-color:var(--mat-sys-secondary-container)!important;color:var(--mat-sys-on-secondary-container);font:var(--mat-sys-label-large);box-shadow:none!important;--mdc-chip-elevated-container-elevation: none;--mdc-chip-outline-width: 0}.ps-trigger__chip.mat-mdc-chip ::ng-deep .mat-mdc-chip-focus-overlay{display:none}.ps-trigger__suffix{display:flex;align-items:center;gap:0;flex-shrink:0}.ps-trigger__clear{width:28px;height:28px;line-height:28px;opacity:.6}.ps-trigger__clear:hover{opacity:1}.ps-trigger__clear mat-icon{font-size:18px;width:18px;height:18px}.ps-trigger__remaining{display:inline-flex;align-items:center;justify-content:center;min-width:24px;height:22px;padding:0 7px;font-size:11px;font-weight:600;font-variant-numeric:tabular-nums;background:var(--mat-sys-surface-container-highest);color:var(--mat-sys-on-surface-variant);margin-left:6px;white-space:nowrap;flex-shrink:0}.ps-trigger .ps-trigger__arrow--open{transform:rotate(180deg);transition:transform .2s ease}.ps-trigger mat-icon:not(.ps-trigger__clear mat-icon){transition:transform .2s ease}.ps-trigger--row ::ng-deep .mat-mdc-form-field-infix{display:flex;align-items:center;flex-wrap:nowrap;overflow:hidden;min-height:56px}.ps-trigger--row .ps-trigger__chip-grid{flex:1 1 auto;min-width:0;min-height:0;overflow:hidden}.ps-trigger--row .ps-trigger__chip-grid ::ng-deep .mdc-evolution-chip-set__chips{min-height:0}.ps-trigger--row .ps-trigger__remaining{flex:0 0 auto}.ps-trigger--disabled{cursor:not-allowed}.ps-trigger--disabled ::ng-deep .mat-mdc-form-field-flex{cursor:not-allowed}.ps-trigger--disabled .ps-trigger__input,.ps-trigger--disabled .ps-trigger__chip,.ps-trigger--disabled .ps-trigger__suffix{opacity:.38}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatBottomSheetModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i2$2.MatChipGrid, selector: "mat-chip-grid", inputs: ["disabled", "placeholder", "required", "value", "errorStateMatcher"], outputs: ["change", "valueChange"] }, { kind: "directive", type: i2$2.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled", "readonly", "matChipInputDisabledInteractive"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { kind: "directive", type: i2$2.MatChipRemove, selector: "[matChipRemove]" }, { kind: "component", type: i2$2.MatChipRow, selector: "mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]", inputs: ["editable"], outputs: ["edited"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$3.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i2$3.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i2$3.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "ngmodule", type: MatProgressSpinnerModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3841
4254
  }
3842
4255
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxPaginatedSelect, decorators: [{
3843
4256
  type: Component,
@@ -3852,41 +4265,68 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
3852
4265
  MatInputModule,
3853
4266
  MatTooltipModule,
3854
4267
  MatProgressSpinnerModule,
3855
- ], template: "<!-- \u2500\u2500 Chips mode (multiple + displayMode = 'chips') \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n@if (showChips()) {\n <mat-form-field\n appearance=\"outline\"\n floatLabel=\"always\"\n [subscriptSizing]=\"subscriptSizing()\"\n class=\"ps-trigger\"\n [class.ps-trigger--disabled]=\"isDisabled()\"\n [class.ps-trigger--open]=\"_isOpen()\"\n [class.ps-trigger--row]=\"chipsDirection() === 'row'\"\n (click)=\"openBottomSheet($event)\"\n >\n <mat-label>{{ label() }}</mat-label>\n\n <mat-chip-grid\n #chipGrid\n class=\"ps-trigger__chip-grid\"\n [class.ps-trigger__chip-grid--column]=\"chipsDirection() === 'column'\"\n [formControl]=\"innerControl\"\n [errorStateMatcher]=\"errorStateMatcher\"\n [required]=\"isRequired()\"\n >\n @for (item of displayedChips(); track item[config().valueKey]) {\n <mat-chip-row\n class=\"ps-trigger__chip\"\n [value]=\"item[config().valueKey]\"\n [disabled]=\"isDisabled()\"\n (removed)=\"removeChip(item, $event)\"\n >\n {{ getLabel(item) }}\n <button matChipRemove [disabled]=\"isDisabled()\" (click)=\"$event.stopPropagation()\">\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip-row>\n }\n </mat-chip-grid>\n\n @if (remainingChipsCount() > 0) {\n <span class=\"ps-trigger__remaining\">+{{ remainingChipsCount() }}</span>\n }\n\n <!-- Hidden input required for mat-chip-grid; tambi\u00E9n da foco de teclado al trigger -->\n <input\n matInput\n [matChipInputFor]=\"chipGrid\"\n class=\"ps-trigger__kbd-input\"\n [required]=\"isRequired()\"\n readonly\n role=\"combobox\"\n [attr.aria-haspopup]=\"'dialog'\"\n [attr.aria-expanded]=\"_isOpen()\"\n [attr.aria-label]=\"label()\"\n (keydown)=\"onTriggerKeydown($event)\"\n />\n\n <div matSuffix class=\"ps-trigger__suffix\">\n @if (clearable() && hasSelection() && !isDisabled()) {\n <button matIconButton matSuffix [attr.aria-label]=\"intl.clearSearchTooltip\" (click)=\"clearSelection($event)\">\n <mat-icon>close</mat-icon>\n </button>\n }\n <mat-icon [class.ps-trigger__arrow--open]=\"_isOpen()\">arrow_drop_down</mat-icon>\n </div>\n\n @if (error()) {\n <mat-error>{{ error() }}</mat-error>\n }\n @if (hint()) {\n <mat-hint>{{ hint() }}</mat-hint>\n }\n </mat-form-field>\n}\n\n<!-- \u2500\u2500 Text mode (single or multiple + displayMode = 'text') \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n@if (!showChips()) {\n <mat-form-field\n appearance=\"outline\"\n floatLabel=\"always\"\n [subscriptSizing]=\"subscriptSizing()\"\n class=\"ps-trigger\"\n [class.ps-trigger--disabled]=\"isDisabled()\"\n [class.ps-trigger--open]=\"_isOpen()\"\n (click)=\"openBottomSheet($event)\"\n >\n <mat-label>{{ label() }}</mat-label>\n\n <input\n matInput\n class=\"ps-trigger__input\"\n [required]=\"isRequired()\"\n readonly\n role=\"combobox\"\n [attr.aria-haspopup]=\"'dialog'\"\n [attr.aria-expanded]=\"_isOpen()\"\n [formControl]=\"innerControl\"\n [errorStateMatcher]=\"errorStateMatcher\"\n (keydown)=\"onTriggerKeydown($event)\"\n />\n\n <div matSuffix class=\"ps-trigger__suffix\">\n @if (clearable() && hasSelection() && !isDisabled()) {\n <button matIconButton matSuffix [attr.aria-label]=\"intl.clearSearchTooltip\" (click)=\"clearSelection($event)\">\n <mat-icon>close</mat-icon>\n </button>\n }\n <mat-icon [class.ps-trigger__arrow--open]=\"_isOpen()\">arrow_drop_down</mat-icon>\n </div>\n\n @if (error()) {\n <mat-error>{{ error() }}</mat-error>\n }\n @if (hint()) {\n <mat-hint>{{ hint() }}</mat-hint>\n }\n </mat-form-field>\n}\n", styles: [":host{display:block}.ps-trigger{width:100%;cursor:pointer;--mat-form-field-outlined-focus-outline-color: var(--mat-sys-outline);--mat-form-field-outlined-outline-color: var(--mat-sys-outline);--mat-form-field-outlined-hover-outline-color: var(--mat-sys-outline)}.ps-trigger ::ng-deep .mat-mdc-form-field-flex{cursor:pointer}.ps-trigger--open{--mat-form-field-outlined-outline-color: var(--mat-sys-primary);--mat-form-field-outlined-focus-outline-color: var(--mat-sys-primary);--mat-form-field-outlined-hover-outline-color: var(--mat-sys-primary)}.ps-trigger__input{cursor:pointer!important;caret-color:transparent;pointer-events:none}.ps-trigger__kbd-input{width:0;min-width:0;flex:0 0 0;padding:0;margin:0;caret-color:transparent}.ps-trigger__chip-grid{cursor:pointer;min-height:36px}.ps-trigger__chip-grid ::ng-deep .mdc-evolution-chip-set__chips{flex-wrap:nowrap;overflow:hidden;gap:6px}.ps-trigger__chip-grid--column ::ng-deep .mdc-evolution-chip-set__chips{flex-wrap:wrap;overflow:visible}.ps-trigger__chip.mat-mdc-chip{height:30px;border:none!important;background-color:var(--mat-sys-secondary-container)!important;color:var(--mat-sys-on-secondary-container);font:var(--mat-sys-label-large);box-shadow:none!important;--mdc-chip-elevated-container-elevation: none;--mdc-chip-outline-width: 0}.ps-trigger__chip.mat-mdc-chip ::ng-deep .mat-mdc-chip-focus-overlay{display:none}.ps-trigger__suffix{display:flex;align-items:center;gap:0;flex-shrink:0}.ps-trigger__clear{width:28px;height:28px;line-height:28px;opacity:.6}.ps-trigger__clear:hover{opacity:1}.ps-trigger__clear mat-icon{font-size:18px;width:18px;height:18px}.ps-trigger__remaining{display:inline-flex;align-items:center;justify-content:center;min-width:24px;height:22px;padding:0 7px;font-size:11px;font-weight:600;font-variant-numeric:tabular-nums;background:var(--mat-sys-surface-container-highest);color:var(--mat-sys-on-surface-variant);margin-left:6px;white-space:nowrap;flex-shrink:0}.ps-trigger .ps-trigger__arrow--open{transform:rotate(180deg);transition:transform .2s ease}.ps-trigger mat-icon:not(.ps-trigger__clear mat-icon){transition:transform .2s ease}.ps-trigger--row ::ng-deep .mat-mdc-form-field-infix{display:flex;align-items:center;flex-wrap:nowrap;overflow:hidden;min-height:56px}.ps-trigger--row .ps-trigger__chip-grid{flex:1 1 auto;min-width:0;min-height:0;overflow:hidden}.ps-trigger--row .ps-trigger__chip-grid ::ng-deep .mdc-evolution-chip-set__chips{min-height:0}.ps-trigger--row .ps-trigger__remaining{flex:0 0 auto}.ps-trigger--disabled{cursor:not-allowed}.ps-trigger--disabled ::ng-deep .mat-mdc-form-field-flex{cursor:not-allowed}.ps-trigger--disabled .ps-trigger__input,.ps-trigger--disabled .ps-trigger__chip,.ps-trigger--disabled .ps-trigger__suffix{opacity:.38}\n"] }]
4268
+ ], template: "<!-- \u2500\u2500 Chips mode (multiple + displayMode = 'chips') \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n@if (showChips()) {\r\n <mat-form-field\r\n appearance=\"outline\"\r\n floatLabel=\"always\"\r\n [subscriptSizing]=\"subscriptSizing()\"\r\n class=\"ps-trigger\"\r\n [class.ps-trigger--disabled]=\"isDisabled()\"\r\n [class.ps-trigger--open]=\"_isOpen()\"\r\n [class.ps-trigger--row]=\"chipsDirection() === 'row'\"\r\n (click)=\"openBottomSheet($event)\"\r\n >\r\n <mat-label>{{ label() }}</mat-label>\r\n\r\n <mat-chip-grid\r\n #chipGrid\r\n class=\"ps-trigger__chip-grid\"\r\n [class.ps-trigger__chip-grid--column]=\"chipsDirection() === 'column'\"\r\n [formControl]=\"innerControl\"\r\n [errorStateMatcher]=\"errorStateMatcher\"\r\n [required]=\"isRequired()\"\r\n >\r\n @for (item of displayedChips(); track item[config().valueKey]) {\r\n <mat-chip-row\r\n class=\"ps-trigger__chip\"\r\n [value]=\"item[config().valueKey]\"\r\n [disabled]=\"isDisabled()\"\r\n (removed)=\"removeChip(item, $event)\"\r\n >\r\n {{ getLabel(item) }}\r\n <button matChipRemove [disabled]=\"isDisabled()\" (click)=\"$event.stopPropagation()\">\r\n <mat-icon>cancel</mat-icon>\r\n </button>\r\n </mat-chip-row>\r\n }\r\n </mat-chip-grid>\r\n\r\n @if (remainingChipsCount() > 0) {\r\n <span class=\"ps-trigger__remaining\">+{{ remainingChipsCount() }}</span>\r\n }\r\n\r\n <!-- Hidden input required for mat-chip-grid; tambi\u00E9n da foco de teclado al trigger -->\r\n <input\r\n matInput\r\n [matChipInputFor]=\"chipGrid\"\r\n class=\"ps-trigger__kbd-input\"\r\n [required]=\"isRequired()\"\r\n readonly\r\n role=\"combobox\"\r\n [attr.aria-haspopup]=\"'dialog'\"\r\n [attr.aria-expanded]=\"_isOpen()\"\r\n [attr.aria-label]=\"label()\"\r\n (keydown)=\"onTriggerKeydown($event)\"\r\n />\r\n\r\n <div matSuffix class=\"ps-trigger__suffix\">\r\n @if (clearable() && hasSelection() && !isDisabled()) {\r\n <button matIconButton matSuffix [attr.aria-label]=\"texts().common.clearSearch\" (click)=\"clearSelection($event)\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n }\r\n <mat-icon [class.ps-trigger__arrow--open]=\"_isOpen()\">arrow_drop_down</mat-icon>\r\n </div>\r\n\r\n @if (error()) {\r\n <mat-error>{{ error() }}</mat-error>\r\n }\r\n @if (hint()) {\r\n <mat-hint>{{ hint() }}</mat-hint>\r\n }\r\n </mat-form-field>\r\n}\r\n\r\n<!-- \u2500\u2500 Text mode (single or multiple + displayMode = 'text') \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n@if (!showChips()) {\r\n <mat-form-field\r\n appearance=\"outline\"\r\n floatLabel=\"always\"\r\n [subscriptSizing]=\"subscriptSizing()\"\r\n class=\"ps-trigger\"\r\n [class.ps-trigger--disabled]=\"isDisabled()\"\r\n [class.ps-trigger--open]=\"_isOpen()\"\r\n (click)=\"openBottomSheet($event)\"\r\n >\r\n <mat-label>{{ label() }}</mat-label>\r\n\r\n <input\r\n matInput\r\n class=\"ps-trigger__input\"\r\n [required]=\"isRequired()\"\r\n readonly\r\n role=\"combobox\"\r\n [attr.aria-haspopup]=\"'dialog'\"\r\n [attr.aria-expanded]=\"_isOpen()\"\r\n [formControl]=\"innerControl\"\r\n [errorStateMatcher]=\"errorStateMatcher\"\r\n (keydown)=\"onTriggerKeydown($event)\"\r\n />\r\n\r\n <div matSuffix class=\"ps-trigger__suffix\">\r\n @if (clearable() && hasSelection() && !isDisabled()) {\r\n <button matIconButton matSuffix [attr.aria-label]=\"texts().common.clearSearch\" (click)=\"clearSelection($event)\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n }\r\n <mat-icon [class.ps-trigger__arrow--open]=\"_isOpen()\">arrow_drop_down</mat-icon>\r\n </div>\r\n\r\n @if (error()) {\r\n <mat-error>{{ error() }}</mat-error>\r\n }\r\n @if (hint()) {\r\n <mat-hint>{{ hint() }}</mat-hint>\r\n }\r\n </mat-form-field>\r\n}\r\n", styles: [":host{display:block}.ps-trigger{width:100%;cursor:pointer;--mat-form-field-outlined-focus-outline-color: var(--mat-sys-outline);--mat-form-field-outlined-outline-color: var(--mat-sys-outline);--mat-form-field-outlined-hover-outline-color: var(--mat-sys-outline)}.ps-trigger ::ng-deep .mat-mdc-form-field-flex{cursor:pointer}.ps-trigger--open{--mat-form-field-outlined-outline-color: var(--mat-sys-primary);--mat-form-field-outlined-focus-outline-color: var(--mat-sys-primary);--mat-form-field-outlined-hover-outline-color: var(--mat-sys-primary)}.ps-trigger__input{cursor:pointer!important;caret-color:transparent;pointer-events:none}.ps-trigger__kbd-input{width:0;min-width:0;flex:0 0 0;padding:0;margin:0;caret-color:transparent}.ps-trigger__chip-grid{cursor:pointer;min-height:36px}.ps-trigger__chip-grid ::ng-deep .mdc-evolution-chip-set__chips{flex-wrap:nowrap;overflow:hidden;gap:6px}.ps-trigger__chip-grid--column ::ng-deep .mdc-evolution-chip-set__chips{flex-wrap:wrap;overflow:visible}.ps-trigger__chip.mat-mdc-chip{height:30px;border:none!important;background-color:var(--mat-sys-secondary-container)!important;color:var(--mat-sys-on-secondary-container);font:var(--mat-sys-label-large);box-shadow:none!important;--mdc-chip-elevated-container-elevation: none;--mdc-chip-outline-width: 0}.ps-trigger__chip.mat-mdc-chip ::ng-deep .mat-mdc-chip-focus-overlay{display:none}.ps-trigger__suffix{display:flex;align-items:center;gap:0;flex-shrink:0}.ps-trigger__clear{width:28px;height:28px;line-height:28px;opacity:.6}.ps-trigger__clear:hover{opacity:1}.ps-trigger__clear mat-icon{font-size:18px;width:18px;height:18px}.ps-trigger__remaining{display:inline-flex;align-items:center;justify-content:center;min-width:24px;height:22px;padding:0 7px;font-size:11px;font-weight:600;font-variant-numeric:tabular-nums;background:var(--mat-sys-surface-container-highest);color:var(--mat-sys-on-surface-variant);margin-left:6px;white-space:nowrap;flex-shrink:0}.ps-trigger .ps-trigger__arrow--open{transform:rotate(180deg);transition:transform .2s ease}.ps-trigger mat-icon:not(.ps-trigger__clear mat-icon){transition:transform .2s ease}.ps-trigger--row ::ng-deep .mat-mdc-form-field-infix{display:flex;align-items:center;flex-wrap:nowrap;overflow:hidden;min-height:56px}.ps-trigger--row .ps-trigger__chip-grid{flex:1 1 auto;min-width:0;min-height:0;overflow:hidden}.ps-trigger--row .ps-trigger__chip-grid ::ng-deep .mdc-evolution-chip-set__chips{min-height:0}.ps-trigger--row .ps-trigger__remaining{flex:0 0 auto}.ps-trigger--disabled{cursor:not-allowed}.ps-trigger--disabled ::ng-deep .mat-mdc-form-field-flex{cursor:not-allowed}.ps-trigger--disabled .ps-trigger__input,.ps-trigger--disabled .ps-trigger__chip,.ps-trigger--disabled .ps-trigger__suffix{opacity:.38}\n"] }]
3856
4269
  }], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], endpoint: [{ type: i0.Input, args: [{ isSignal: true, alias: "endpoint", required: true }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], filters: [{ type: i0.Input, args: [{ isSignal: true, alias: "filters", required: false }] }], selectedItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedItems", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], displayMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayMode", required: false }] }], showSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSearch", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], noResultsMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "noResultsMessage", required: false }] }], confirmLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmLabel", required: false }] }], resetLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "resetLabel", required: false }] }], subscriptSizing: [{ type: i0.Input, args: [{ isSignal: true, alias: "subscriptSizing", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], optionTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionTemplate", required: false }] }], extraFiltersTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "extraFiltersTemplate", required: false }] }], maxChipsDisplayed: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxChipsDisplayed", required: false }] }], chipsDirection: [{ type: i0.Input, args: [{ isSignal: true, alias: "chipsDirection", required: false }] }], showSelectAll: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSelectAll", required: false }] }], selectAllLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAllLabel", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }] } });
3857
4270
 
4271
+ const UNITLESS_NUMBER = /^-?\d+(\.\d+)?$/;
4272
+ /**
4273
+ * Convierte un tamaño a CSS: un número, o un texto que solo es un número (`height="56"`
4274
+ * en un atributo estático), se interpreta como píxeles.
4275
+ */
4276
+ function toCssSize(value) {
4277
+ if (typeof value === 'number')
4278
+ return `${value}px`;
4279
+ const trimmed = value.trim();
4280
+ return UNITLESS_NUMBER.test(trimmed) ? `${trimmed}px` : trimmed;
4281
+ }
4282
+ function toOptionalCssSize(value) {
4283
+ return value === null || value === undefined || value === '' ? null : toCssSize(value);
4284
+ }
3858
4285
  class NgxSkeleton {
3859
- /** Shape variant of the skeleton: text (horizontal bars), circle, rect, or rounded rect. */
4286
+ _texts = inject(NgxTexts).texts;
4287
+ /** Forma: text (barras de texto), circle, rect o rounded (rectángulo redondeado). */
3860
4288
  variant = input('rect', ...(ngDevMode ? [{ debugName: "variant" }] : []));
3861
- /** Width of the skeleton element. Accepts any valid CSS value (px, %, rem, etc.). */
3862
- width = input('100%', ...(ngDevMode ? [{ debugName: "width" }] : []));
3863
- /** Height of the skeleton element. Accepts any valid CSS value (px, %, rem, etc.). */
3864
- height = input('1rem', ...(ngDevMode ? [{ debugName: "height" }] : []));
3865
- /** Number of lines to render. Only applies when variant is 'text'. */
3866
- lines = input(1, ...(ngDevMode ? [{ debugName: "lines" }] : []));
3867
- /** Vertical spacing between text lines. Accepts any valid CSS value. */
3868
- lineSpacing = input('0.5rem', ...(ngDevMode ? [{ debugName: "lineSpacing" }] : []));
3869
- /** Width of the last text line for a realistic paragraph effect. Accepts any valid CSS value. */
3870
- lastLineWidth = input('70%', ...(ngDevMode ? [{ debugName: "lastLineWidth" }] : []));
3871
- /** Type of loading animation: shimmer (sliding highlight), pulse (opacity), or none. */
4289
+ /** Ancho. Cualquier valor CSS; un número se interpreta como px. Se ignora en `circle`. */
4290
+ width = input('100%', ...(ngDevMode ? [{ debugName: "width", transform: toCssSize }] : [{ transform: toCssSize }]));
4291
+ /** Alto. Cualquier valor CSS; un número se interpreta como px. En `circle` también es el diámetro. */
4292
+ height = input('1rem', ...(ngDevMode ? [{ debugName: "height", transform: toCssSize }] : [{ transform: toCssSize }]));
4293
+ /** Número de líneas. Solo aplica con `variant="text"`. */
4294
+ lines = input(1, ...(ngDevMode ? [{ debugName: "lines", transform: numberAttribute }] : [{ transform: numberAttribute }]));
4295
+ /** Separación vertical entre líneas de texto. */
4296
+ lineSpacing = input('0.5rem', ...(ngDevMode ? [{ debugName: "lineSpacing", transform: toCssSize }] : [{ transform: toCssSize }]));
4297
+ /** Ancho de la última línea, para que el párrafo parezca real. Solo con varias líneas. */
4298
+ lastLineWidth = input('70%', ...(ngDevMode ? [{ debugName: "lastLineWidth", transform: toCssSize }] : [{ transform: toCssSize }]));
4299
+ /** Animación: shimmer (brillo que se desliza), pulse (opacidad) o none. */
3872
4300
  animation = input('shimmer', ...(ngDevMode ? [{ debugName: "animation" }] : []));
3873
- /** Duration of one full animation cycle. Accepts any valid CSS time value. */
3874
- animationDuration = input('1.5s', ...(ngDevMode ? [{ debugName: "animationDuration" }] : []));
3875
- /** Overrides the default border-radius derived from the variant. */
3876
- borderRadius = input(null, ...(ngDevMode ? [{ debugName: "borderRadius" }] : []));
3877
- /** Accessible label read by screen readers. */
3878
- ariaLabel = input('Cargando...', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
3879
- /** Whether the component should render multiple stacked lines. */
3880
- isMultiLine = computed(() => this.variant() === 'text' && this.lines() > 1, ...(ngDevMode ? [{ debugName: "isMultiLine" }] : []));
3881
- /** Index array used to iterate over text lines in the template. */
4301
+ /**
4302
+ * Duración de un ciclo de animación (cualquier tiempo CSS). Por defecto 1.5s, o el valor
4303
+ * de la variable CSS `--ngx-skeleton-duration` si el consumidor la define.
4304
+ */
4305
+ animationDuration = input(...(ngDevMode ? [undefined, { debugName: "animationDuration" }] : []));
4306
+ /** Sustituye el border-radius que corresponde a la variante. */
4307
+ borderRadius = input(null, ...(ngDevMode ? [{ debugName: "borderRadius", transform: toOptionalCssSize }] : [{ transform: toOptionalCssSize }]));
4308
+ /** Etiqueta accesible. Por defecto, el texto `skeleton.loading` de la librería. */
4309
+ ariaLabel = input(...(ngDevMode ? [undefined, { debugName: "ariaLabel" }] : []));
4310
+ /**
4311
+ * Oculta el skeleton a lectores de pantalla (sin role ni etiqueta). Úsalo cuando varios
4312
+ * skeletons forman una misma pieza: márcalos todos como decorativos y anuncia la carga
4313
+ * una sola vez en el contenedor (p. ej. con `aria-busy` o un skeleton sin `decorative`).
4314
+ */
4315
+ decorative = input(false, ...(ngDevMode ? [{ debugName: "decorative", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
4316
+ resolvedAriaLabel = computed(() => {
4317
+ return this.ariaLabel() ?? this._texts().skeleton.loading;
4318
+ }, ...(ngDevMode ? [{ debugName: "resolvedAriaLabel" }] : []));
4319
+ /** Una entrada por línea a pintar (siempre al menos una). */
3882
4320
  lineIndices = computed(() => {
3883
- const count = this.variant() === 'text' ? this.lines() : 1;
4321
+ const count = this.variant() === 'text' ? Math.max(1, Math.floor(this.lines())) : 1;
3884
4322
  return Array.from({ length: count }, (_, i) => i);
3885
4323
  }, ...(ngDevMode ? [{ debugName: "lineIndices" }] : []));
3886
- /** Resolved border-radius based on variant with optional override. */
4324
+ isMultiLine = computed(() => this.lineIndices().length > 1, ...(ngDevMode ? [{ debugName: "isMultiLine" }] : []));
4325
+ /** border-radius de la variante, salvo que se indique `borderRadius`. */
3887
4326
  computedBorderRadius = computed(() => {
3888
- if (this.borderRadius() !== null)
3889
- return this.borderRadius();
4327
+ const override = this.borderRadius();
4328
+ if (override !== null)
4329
+ return override;
3890
4330
  switch (this.variant()) {
3891
4331
  case 'text': return '4px';
3892
4332
  case 'circle': return '50%';
@@ -3895,23 +4335,21 @@ class NgxSkeleton {
3895
4335
  default: return '0';
3896
4336
  }
3897
4337
  }, ...(ngDevMode ? [{ debugName: "computedBorderRadius" }] : []));
3898
- /** For circle variant, width equals height to ensure a perfect circle. */
3899
- computedWidth = computed(() => {
3900
- if (this.variant() === 'circle')
3901
- return this.height();
3902
- return this.width();
3903
- }, ...(ngDevMode ? [{ debugName: "computedWidth" }] : []));
4338
+ /** En `circle` el ancho es el alto, para que sea un círculo perfecto. */
4339
+ computedWidth = computed(() => this.variant() === 'circle' ? this.height() : this.width(), ...(ngDevMode ? [{ debugName: "computedWidth" }] : []));
3904
4340
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxSkeleton, deps: [], target: i0.ɵɵFactoryTarget.Component });
3905
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: NgxSkeleton, isStandalone: true, selector: "ngx-skeleton", inputs: { variant: { classPropertyName: "variant", publicName: "variant", 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 }, lines: { classPropertyName: "lines", publicName: "lines", isSignal: true, isRequired: false, transformFunction: null }, lineSpacing: { classPropertyName: "lineSpacing", publicName: "lineSpacing", isSignal: true, isRequired: false, transformFunction: null }, lastLineWidth: { classPropertyName: "lastLineWidth", publicName: "lastLineWidth", isSignal: true, isRequired: false, transformFunction: null }, animation: { classPropertyName: "animation", publicName: "animation", isSignal: true, isRequired: false, transformFunction: null }, animationDuration: { classPropertyName: "animationDuration", publicName: "animationDuration", isSignal: true, isRequired: false, transformFunction: null }, borderRadius: { classPropertyName: "borderRadius", publicName: "borderRadius", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "status" }, properties: { "attr.aria-label": "ariaLabel()", "attr.aria-busy": "\"true\"" } }, ngImport: i0, template: "@if (isMultiLine()) {\n <div class=\"ngx-skeleton-text-container\" [style.gap]=\"lineSpacing()\">\n @for (i of lineIndices(); track i) {\n <div\n class=\"ngx-skeleton-bone\"\n [class.ngx-skeleton-shimmer]=\"animation() === 'shimmer'\"\n [class.ngx-skeleton-pulse]=\"animation() === 'pulse'\"\n [style.width]=\"i === lineIndices().length - 1 ? lastLineWidth() : width()\"\n [style.height]=\"height()\"\n [style.border-radius]=\"computedBorderRadius()\"\n [style.--ngx-skeleton-duration]=\"animationDuration()\"\n ></div>\n }\n </div>\n} @else {\n <div\n class=\"ngx-skeleton-bone\"\n [class.ngx-skeleton-shimmer]=\"animation() === 'shimmer'\"\n [class.ngx-skeleton-pulse]=\"animation() === 'pulse'\"\n [style.width]=\"computedWidth()\"\n [style.height]=\"height()\"\n [style.border-radius]=\"computedBorderRadius()\"\n [style.--ngx-skeleton-duration]=\"animationDuration()\"\n ></div>\n}\n", styles: [":host{display:block}.ngx-skeleton-text-container{display:flex;flex-direction:column}.ngx-skeleton-bone{background-color:var(--mat-sys-surface-dim, var(--mat-sys-surface-variant, #e0e0e0));position:relative;overflow:hidden}.ngx-skeleton-bone.ngx-skeleton-shimmer:after{content:\"\";position:absolute;inset:0 0 0 -100%;width:100%;background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.08) 25%,rgba(255,255,255,.18) 45%,rgba(255,255,255,.28) 50%,rgba(255,255,255,.18) 55%,rgba(255,255,255,.08) 75%,transparent 100%);will-change:transform;animation:ngx-skeleton-shimmer var(--ngx-skeleton-duration, 1.5s) infinite ease-in-out}.ngx-skeleton-bone.ngx-skeleton-pulse{animation:ngx-skeleton-pulse var(--ngx-skeleton-duration, 1.5s) infinite ease-in-out}@keyframes ngx-skeleton-shimmer{0%{transform:translate(0)}to{transform:translate(200%)}}@keyframes ngx-skeleton-pulse{0%,to{opacity:1}50%{opacity:.4}}\n"] });
4341
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: NgxSkeleton, isStandalone: true, selector: "ngx-skeleton", inputs: { variant: { classPropertyName: "variant", publicName: "variant", 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 }, lines: { classPropertyName: "lines", publicName: "lines", isSignal: true, isRequired: false, transformFunction: null }, lineSpacing: { classPropertyName: "lineSpacing", publicName: "lineSpacing", isSignal: true, isRequired: false, transformFunction: null }, lastLineWidth: { classPropertyName: "lastLineWidth", publicName: "lastLineWidth", isSignal: true, isRequired: false, transformFunction: null }, animation: { classPropertyName: "animation", publicName: "animation", isSignal: true, isRequired: false, transformFunction: null }, animationDuration: { classPropertyName: "animationDuration", publicName: "animationDuration", isSignal: true, isRequired: false, transformFunction: null }, borderRadius: { classPropertyName: "borderRadius", publicName: "borderRadius", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, decorative: { classPropertyName: "decorative", publicName: "decorative", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.role": "decorative() ? null : \"status\"", "attr.aria-label": "decorative() ? null : resolvedAriaLabel()", "attr.aria-busy": "decorative() ? null : \"true\"", "attr.aria-hidden": "decorative() ? \"true\" : null", "style.--ngx-skeleton-duration": "animationDuration() ?? null" } }, ngImport: i0, template: "<div class=\"ngx-skeleton-lines\" [style.gap]=\"isMultiLine() ? lineSpacing() : null\">\n @for (i of lineIndices(); track i; let last = $last) {\n <div\n class=\"ngx-skeleton-bone\"\n [class.ngx-skeleton-shimmer]=\"animation() === 'shimmer'\"\n [class.ngx-skeleton-pulse]=\"animation() === 'pulse'\"\n [style.width]=\"isMultiLine() && last ? lastLineWidth() : computedWidth()\"\n [style.height]=\"height()\"\n [style.border-radius]=\"computedBorderRadius()\"\n ></div>\n }\n</div>\n", styles: [":host{display:block}.ngx-skeleton-lines{display:flex;flex-direction:column}.ngx-skeleton-bone{position:relative;max-width:100%;overflow:hidden;background-color:var(--ngx-skeleton-color, var(--mat-sys-surface-container-highest))}.ngx-skeleton-bone.ngx-skeleton-shimmer:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent 0%,var(--ngx-skeleton-highlight, color-mix(in srgb, var(--mat-sys-surface) 60%, transparent)) 50%,transparent 100%);will-change:transform;animation:ngx-skeleton-shimmer var(--ngx-skeleton-duration, 1.5s) infinite ease-in-out}.ngx-skeleton-bone.ngx-skeleton-pulse{animation:ngx-skeleton-pulse var(--ngx-skeleton-duration, 1.5s) infinite ease-in-out}@keyframes ngx-skeleton-shimmer{to{transform:translate(100%)}}@keyframes ngx-skeleton-pulse{0%,to{opacity:1}50%{opacity:.4}}@media (prefers-reduced-motion: reduce){.ngx-skeleton-bone.ngx-skeleton-shimmer:after{animation:none;opacity:0}.ngx-skeleton-bone.ngx-skeleton-pulse{animation:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3906
4342
  }
3907
4343
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxSkeleton, decorators: [{
3908
4344
  type: Component,
3909
- args: [{ selector: 'ngx-skeleton', host: {
3910
- 'role': 'status',
3911
- '[attr.aria-label]': 'ariaLabel()',
3912
- '[attr.aria-busy]': '"true"',
3913
- }, template: "@if (isMultiLine()) {\n <div class=\"ngx-skeleton-text-container\" [style.gap]=\"lineSpacing()\">\n @for (i of lineIndices(); track i) {\n <div\n class=\"ngx-skeleton-bone\"\n [class.ngx-skeleton-shimmer]=\"animation() === 'shimmer'\"\n [class.ngx-skeleton-pulse]=\"animation() === 'pulse'\"\n [style.width]=\"i === lineIndices().length - 1 ? lastLineWidth() : width()\"\n [style.height]=\"height()\"\n [style.border-radius]=\"computedBorderRadius()\"\n [style.--ngx-skeleton-duration]=\"animationDuration()\"\n ></div>\n }\n </div>\n} @else {\n <div\n class=\"ngx-skeleton-bone\"\n [class.ngx-skeleton-shimmer]=\"animation() === 'shimmer'\"\n [class.ngx-skeleton-pulse]=\"animation() === 'pulse'\"\n [style.width]=\"computedWidth()\"\n [style.height]=\"height()\"\n [style.border-radius]=\"computedBorderRadius()\"\n [style.--ngx-skeleton-duration]=\"animationDuration()\"\n ></div>\n}\n", styles: [":host{display:block}.ngx-skeleton-text-container{display:flex;flex-direction:column}.ngx-skeleton-bone{background-color:var(--mat-sys-surface-dim, var(--mat-sys-surface-variant, #e0e0e0));position:relative;overflow:hidden}.ngx-skeleton-bone.ngx-skeleton-shimmer:after{content:\"\";position:absolute;inset:0 0 0 -100%;width:100%;background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.08) 25%,rgba(255,255,255,.18) 45%,rgba(255,255,255,.28) 50%,rgba(255,255,255,.18) 55%,rgba(255,255,255,.08) 75%,transparent 100%);will-change:transform;animation:ngx-skeleton-shimmer var(--ngx-skeleton-duration, 1.5s) infinite ease-in-out}.ngx-skeleton-bone.ngx-skeleton-pulse{animation:ngx-skeleton-pulse var(--ngx-skeleton-duration, 1.5s) infinite ease-in-out}@keyframes ngx-skeleton-shimmer{0%{transform:translate(0)}to{transform:translate(200%)}}@keyframes ngx-skeleton-pulse{0%,to{opacity:1}50%{opacity:.4}}\n"] }]
3914
- }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], lines: [{ type: i0.Input, args: [{ isSignal: true, alias: "lines", required: false }] }], lineSpacing: [{ type: i0.Input, args: [{ isSignal: true, alias: "lineSpacing", required: false }] }], lastLineWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "lastLineWidth", required: false }] }], animation: [{ type: i0.Input, args: [{ isSignal: true, alias: "animation", required: false }] }], animationDuration: [{ type: i0.Input, args: [{ isSignal: true, alias: "animationDuration", required: false }] }], borderRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "borderRadius", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }] } });
4345
+ args: [{ selector: 'ngx-skeleton', changeDetection: ChangeDetectionStrategy.OnPush, host: {
4346
+ '[attr.role]': 'decorative() ? null : "status"',
4347
+ '[attr.aria-label]': 'decorative() ? null : resolvedAriaLabel()',
4348
+ '[attr.aria-busy]': 'decorative() ? null : "true"',
4349
+ '[attr.aria-hidden]': 'decorative() ? "true" : null',
4350
+ '[style.--ngx-skeleton-duration]': 'animationDuration() ?? null',
4351
+ }, template: "<div class=\"ngx-skeleton-lines\" [style.gap]=\"isMultiLine() ? lineSpacing() : null\">\n @for (i of lineIndices(); track i; let last = $last) {\n <div\n class=\"ngx-skeleton-bone\"\n [class.ngx-skeleton-shimmer]=\"animation() === 'shimmer'\"\n [class.ngx-skeleton-pulse]=\"animation() === 'pulse'\"\n [style.width]=\"isMultiLine() && last ? lastLineWidth() : computedWidth()\"\n [style.height]=\"height()\"\n [style.border-radius]=\"computedBorderRadius()\"\n ></div>\n }\n</div>\n", styles: [":host{display:block}.ngx-skeleton-lines{display:flex;flex-direction:column}.ngx-skeleton-bone{position:relative;max-width:100%;overflow:hidden;background-color:var(--ngx-skeleton-color, var(--mat-sys-surface-container-highest))}.ngx-skeleton-bone.ngx-skeleton-shimmer:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent 0%,var(--ngx-skeleton-highlight, color-mix(in srgb, var(--mat-sys-surface) 60%, transparent)) 50%,transparent 100%);will-change:transform;animation:ngx-skeleton-shimmer var(--ngx-skeleton-duration, 1.5s) infinite ease-in-out}.ngx-skeleton-bone.ngx-skeleton-pulse{animation:ngx-skeleton-pulse var(--ngx-skeleton-duration, 1.5s) infinite ease-in-out}@keyframes ngx-skeleton-shimmer{to{transform:translate(100%)}}@keyframes ngx-skeleton-pulse{0%,to{opacity:1}50%{opacity:.4}}@media (prefers-reduced-motion: reduce){.ngx-skeleton-bone.ngx-skeleton-shimmer:after{animation:none;opacity:0}.ngx-skeleton-bone.ngx-skeleton-pulse{animation:none}}\n"] }]
4352
+ }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], lines: [{ type: i0.Input, args: [{ isSignal: true, alias: "lines", required: false }] }], lineSpacing: [{ type: i0.Input, args: [{ isSignal: true, alias: "lineSpacing", required: false }] }], lastLineWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "lastLineWidth", required: false }] }], animation: [{ type: i0.Input, args: [{ isSignal: true, alias: "animation", required: false }] }], animationDuration: [{ type: i0.Input, args: [{ isSignal: true, alias: "animationDuration", required: false }] }], borderRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "borderRadius", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], decorative: [{ type: i0.Input, args: [{ isSignal: true, alias: "decorative", required: false }] }] } });
3915
4353
 
3916
4354
  let _uid = 0;
3917
4355
  class NgxFileInput {
@@ -3929,8 +4367,10 @@ class NgxFileInput {
3929
4367
  maxFiles = input(null, ...(ngDevMode ? [{ debugName: "maxFiles" }] : []));
3930
4368
  /** Disables the component. */
3931
4369
  disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
3932
- /** Label text shown inside the drop zone. */
3933
- label = input('Arrastra archivos aquí', ...(ngDevMode ? [{ debugName: "label" }] : []));
4370
+ /** Label text shown inside the drop zone. Por defecto, el texto `fileInput.dropLabel` de la librería. */
4371
+ label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : []));
4372
+ texts = inject(NgxTexts).texts;
4373
+ resolvedLabel = computed(() => this.label() ?? this.texts().fileInput.dropLabel, ...(ngDevMode ? [{ debugName: "resolvedLabel" }] : []));
3934
4374
  /** Secondary hint text (formats, sizes…). */
3935
4375
  hint = input(null, ...(ngDevMode ? [{ debugName: "hint" }] : []));
3936
4376
  /** Show the file preview list below the drop zone. */
@@ -4027,7 +4467,7 @@ class NgxFileInput {
4027
4467
  this.items.update(list => list.filter(i => i.id !== item.id));
4028
4468
  this.fileRemoved.emit(item);
4029
4469
  this._emitChange();
4030
- this.liveAnnouncement.set(`Archivo ${item.name} eliminado`);
4470
+ this.liveAnnouncement.set(this.texts().fileInput.removed(item.name));
4031
4471
  }
4032
4472
  // ── Helpers ─────────────────────────────────────────────────────────────────
4033
4473
  /** Format bytes to human-readable string. */
@@ -4083,7 +4523,7 @@ class NgxFileInput {
4083
4523
  const err = {
4084
4524
  file: f,
4085
4525
  code: 'MAX_FILES_EXCEEDED',
4086
- message: `Máximo ${max} archivos permitidos`,
4526
+ message: this.texts().fileInput.maxFiles(max),
4087
4527
  };
4088
4528
  this.validationError.emit(err);
4089
4529
  }
@@ -4104,7 +4544,7 @@ class NgxFileInput {
4104
4544
  const validCount = newItems.filter(i => i.status === 'valid').length;
4105
4545
  if (validCount > 0) {
4106
4546
  this.filesSelected.emit(newItems.filter(i => i.status === 'valid'));
4107
- this.liveAnnouncement.set(`${validCount} archivo${validCount > 1 ? 's' : ''} añadido${validCount > 1 ? 's' : ''}`);
4547
+ this.liveAnnouncement.set(this.texts().fileInput.added(validCount));
4108
4548
  }
4109
4549
  }
4110
4550
  _validateAndCreate(file) {
@@ -4112,7 +4552,7 @@ class NgxFileInput {
4112
4552
  // Type validation
4113
4553
  if (this.accept() !== '*' && !this._isTypeAllowed(file)) {
4114
4554
  item.status = 'error';
4115
- item.error = `Tipo no permitido: ${file.type || file.name.split('.').pop()}`;
4555
+ item.error = this.texts().fileInput.typeNotAllowed(file.type || file.name.split('.').pop() || '');
4116
4556
  this.validationError.emit({
4117
4557
  file,
4118
4558
  code: 'TYPE_NOT_ALLOWED',
@@ -4124,7 +4564,7 @@ class NgxFileInput {
4124
4564
  const maxSz = this.maxSize();
4125
4565
  if (maxSz !== null && file.size > maxSz) {
4126
4566
  item.status = 'error';
4127
- item.error = `Excede el tamaño máximo (${this.formatSize(maxSz)})`;
4567
+ item.error = this.texts().fileInput.tooLarge(this.formatSize(maxSz));
4128
4568
  this.validationError.emit({
4129
4569
  file,
4130
4570
  code: 'SIZE_EXCEEDED',
@@ -4196,7 +4636,7 @@ class NgxFileInput {
4196
4636
  useExisting: forwardRef(() => NgxFileInput),
4197
4637
  multi: true,
4198
4638
  },
4199
- ], viewQueries: [{ propertyName: "_nativeInput", first: true, predicate: ["nativeInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Hidden native file input \u2014 always in DOM for accessibility -->\r\n<input\r\n #nativeInput\r\n [id]=\"inputId\"\r\n class=\"ngx-fi-native-input\"\r\n type=\"file\"\r\n [accept]=\"accept()\"\r\n [multiple]=\"multiple()\"\r\n [disabled]=\"isDisabled()\"\r\n (change)=\"onFileInputChange($event)\"\r\n tabindex=\"-1\"\r\n aria-hidden=\"true\"\r\n/>\r\n\r\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n VARIANT: DEFAULT \u2014 large drop zone\r\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n@if (variant() === 'default') {\r\n <div\r\n class=\"ngx-fi-zone\"\r\n [class.ngx-fi-zone--dragover]=\"isDragOver()\"\r\n [class.ngx-fi-zone--disabled]=\"isDisabled()\"\r\n role=\"region\"\r\n [attr.aria-label]=\"label()\"\r\n [attr.aria-disabled]=\"isDisabled()\"\r\n tabindex=\"0\"\r\n (click)=\"openFilePicker()\"\r\n (keydown.enter)=\"openFilePicker()\"\r\n (keydown.space)=\"openFilePicker(); $event.preventDefault()\"\r\n (dragover)=\"onDragOver($event)\"\r\n (dragleave)=\"onDragLeave($event)\"\r\n (drop)=\"onDrop($event)\"\r\n >\r\n <mat-icon class=\"ngx-fi-zone__icon\">cloud_upload</mat-icon>\r\n <span class=\"ngx-fi-zone__label\">{{ label() }}</span>\r\n @if (hint()) {\r\n <span class=\"ngx-fi-zone__hint\">{{ hint() }}</span>\r\n }\r\n <span class=\"ngx-fi-zone__btn-text\">o haz clic para seleccionar</span>\r\n\r\n <!-- Drop confirmation flash -->\r\n @if (showDropConfirm()) {\r\n <div class=\"ngx-fi-zone__confirm\">\r\n <mat-icon>check_circle</mat-icon>\r\n </div>\r\n }\r\n </div>\r\n}\r\n\r\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n VARIANT: COMPACT \u2014 horizontal bar\r\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n@if (variant() === 'compact') {\r\n <div\r\n class=\"ngx-fi-compact\"\r\n [class.ngx-fi-compact--dragover]=\"isDragOver()\"\r\n [class.ngx-fi-compact--disabled]=\"isDisabled()\"\r\n role=\"region\"\r\n [attr.aria-label]=\"label()\"\r\n [attr.aria-disabled]=\"isDisabled()\"\r\n tabindex=\"0\"\r\n (click)=\"openFilePicker()\"\r\n (keydown.enter)=\"openFilePicker()\"\r\n (keydown.space)=\"openFilePicker(); $event.preventDefault()\"\r\n (dragover)=\"onDragOver($event)\"\r\n (dragleave)=\"onDragLeave($event)\"\r\n (drop)=\"onDrop($event)\"\r\n >\r\n <mat-icon class=\"ngx-fi-compact__icon\">cloud_upload</mat-icon>\r\n <div class=\"ngx-fi-compact__text\">\r\n <span class=\"ngx-fi-compact__label\">{{ label() }}</span>\r\n @if (hint()) {\r\n <span class=\"ngx-fi-compact__hint\">{{ hint() }}</span>\r\n }\r\n </div>\r\n\r\n @if (showDropConfirm()) {\r\n <div class=\"ngx-fi-zone__confirm\">\r\n <mat-icon>check_circle</mat-icon>\r\n </div>\r\n }\r\n </div>\r\n}\r\n\r\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n VARIANT: BUTTON \u2014 only a button\r\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n@if (variant() === 'button') {\r\n <div\r\n class=\"ngx-fi-button-wrap\"\r\n (dragover)=\"onDragOver($event)\"\r\n (dragleave)=\"onDragLeave($event)\"\r\n (drop)=\"onDrop($event)\"\r\n [class.ngx-fi-button-wrap--dragover]=\"isDragOver()\"\r\n >\r\n <button\r\n mat-raised-button\r\n color=\"primary\"\r\n [disabled]=\"isDisabled()\"\r\n (click)=\"openFilePicker()\"\r\n type=\"button\"\r\n >\r\n <mat-icon>attach_file</mat-icon>\r\n {{ label() }}\r\n </button>\r\n </div>\r\n}\r\n\r\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n FILE PREVIEW LIST\r\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n@if (showPreview() && items().length > 0) {\r\n <div class=\"ngx-fi-list\">\r\n @for (item of items(); track item.id) {\r\n <div\r\n class=\"ngx-fi-item\"\r\n [class.ngx-fi-item--error]=\"item.status === 'error'\"\r\n >\r\n <!-- Thumbnail / Icon -->\r\n <div class=\"ngx-fi-item__thumb\" [class]=\"getFileColorClass(item.type)\">\r\n @if (item.preview) {\r\n <img [src]=\"item.preview\" [alt]=\"item.name\" />\r\n } @else {\r\n <mat-icon>{{ getFileIcon(item.type) }}</mat-icon>\r\n }\r\n </div>\r\n\r\n <!-- Info -->\r\n <div class=\"ngx-fi-item__info\">\r\n <span class=\"ngx-fi-item__name\" [matTooltip]=\"item.name\">{{ item.name }}</span>\r\n <span class=\"ngx-fi-item__meta\">\r\n {{ formatSize(item.size) }}\r\n @if (item.error) {\r\n <span class=\"ngx-fi-item__error\">\r\n <mat-icon>warning</mat-icon> {{ item.error }}\r\n </span>\r\n }\r\n </span>\r\n </div>\r\n\r\n <!-- Remove -->\r\n <button\r\n class=\"ngx-fi-item__remove\"\r\n type=\"button\"\r\n mat-icon-button\r\n (click)=\"removeFile(item); $event.stopPropagation()\"\r\n [matTooltip]=\"'Eliminar ' + item.name\"\r\n >\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n}\r\n\r\n<!-- Screen reader announcements -->\r\n<div class=\"ngx-fi-sr-only\" aria-live=\"polite\">{{ liveAnnouncement() }}</div>\r\n", styles: [".ngx-fi-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.ngx-fi-native-input{position:absolute;width:0;height:0;opacity:0;pointer-events:none}.ngx-fi-zone{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;min-height:180px;padding:2rem 1.5rem;border:2px dashed var(--mat-sys-outline-variant, #c4c4c4);border-radius:12px;background:var(--mat-sys-surface-container-low, #fafafa);cursor:pointer;transition:border-color .2s,background-color .2s,box-shadow .2s;outline:none;-webkit-user-select:none;user-select:none;overflow:hidden}.ngx-fi-zone:hover:not(.ngx-fi-zone--disabled){border-style:solid;background:var(--mat-sys-surface-container, #f0f0f0)}.ngx-fi-zone:focus-visible:not(.ngx-fi-zone--disabled){box-shadow:0 0 0 3px #5c6bc040;border-color:var(--mat-sys-primary, #5c6bc0)}.ngx-fi-zone--dragover{border-color:var(--mat-sys-primary, #5c6bc0);border-style:solid;background:var(--mat-sys-primary-container, rgba(92, 107, 192, .08));box-shadow:inset 0 0 0 2px var(--mat-sys-primary, #5c6bc0),0 0 16px #5c6bc033;animation:ngx-fi-glow 1s ease-in-out infinite}.ngx-fi-zone--dragover .ngx-fi-zone__icon{transform:scale(1.15);color:var(--mat-sys-primary, #5c6bc0)}.ngx-fi-zone--disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.ngx-fi-zone__icon{font-size:48px;width:48px;height:48px;color:var(--mat-sys-on-surface-variant, #666);transition:transform .2s,color .2s}.ngx-fi-zone__label{font-size:1.05rem;font-weight:500;color:var(--mat-sys-on-surface, #333);text-align:center}.ngx-fi-zone__hint{font-size:.82rem;color:var(--mat-sys-on-surface-variant, #666);text-align:center}.ngx-fi-zone__btn-text{font-size:.82rem;color:var(--mat-sys-primary, #5c6bc0);font-weight:500;margin-top:.25rem}.ngx-fi-zone__confirm{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#43a0471f;pointer-events:none;animation:ngx-fi-confirm-flash .4s ease-out forwards}.ngx-fi-zone__confirm mat-icon{font-size:56px;width:56px;height:56px;color:var(--mat-sys-tertiary, #43a047)}.ngx-fi-compact{position:relative;display:flex;align-items:center;gap:1rem;height:80px;padding:0 1.25rem;border:2px dashed var(--mat-sys-outline-variant, #c4c4c4);border-radius:12px;background:var(--mat-sys-surface-container-low, #fafafa);cursor:pointer;transition:border-color .2s,background-color .2s,box-shadow .2s;outline:none;-webkit-user-select:none;user-select:none;overflow:hidden}.ngx-fi-compact:hover:not(.ngx-fi-compact--disabled){border-style:solid;background:var(--mat-sys-surface-container, #f0f0f0)}.ngx-fi-compact:focus-visible:not(.ngx-fi-compact--disabled){box-shadow:0 0 0 3px #5c6bc040;border-color:var(--mat-sys-primary, #5c6bc0)}.ngx-fi-compact--dragover{border-color:var(--mat-sys-primary, #5c6bc0);border-style:solid;background:var(--mat-sys-primary-container, rgba(92, 107, 192, .08));box-shadow:inset 0 0 0 2px var(--mat-sys-primary, #5c6bc0),0 0 16px #5c6bc033;animation:ngx-fi-glow 1s ease-in-out infinite}.ngx-fi-compact--dragover .ngx-fi-compact__icon{transform:scale(1.1);color:var(--mat-sys-primary, #5c6bc0)}.ngx-fi-compact--disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.ngx-fi-compact__icon{font-size:32px;width:32px;height:32px;color:var(--mat-sys-on-surface-variant, #666);flex-shrink:0;transition:transform .2s,color .2s}.ngx-fi-compact__text{display:flex;flex-direction:column;gap:.15rem;min-width:0}.ngx-fi-compact__label{font-size:.95rem;font-weight:500;color:var(--mat-sys-on-surface, #333)}.ngx-fi-compact__hint{font-size:.78rem;color:var(--mat-sys-on-surface-variant, #666)}.ngx-fi-button-wrap{display:inline-block;position:relative;padding:4px;border-radius:8px;transition:background-color .2s,box-shadow .2s}.ngx-fi-button-wrap--dragover{background:var(--mat-sys-primary-container, rgba(92, 107, 192, .08));box-shadow:0 0 12px #5c6bc040}.ngx-fi-list{display:flex;flex-direction:column;gap:.5rem;margin-top:.75rem}.ngx-fi-item{display:flex;align-items:center;gap:.75rem;padding:.5rem .65rem;border-radius:10px;background:var(--mat-sys-surface-container-low, #fafafa);border:1px solid var(--mat-sys-outline-variant, #e0e0e0);transition:border-color .2s,background-color .2s;animation:ngx-fi-item-enter .2s ease-out both}.ngx-fi-item--error{border-color:var(--mat-sys-error, #d32f2f);background:#d32f2f0a}.ngx-fi-item__thumb{width:42px;height:42px;border-radius:8px;display:flex;align-items:center;justify-content:center;flex-shrink:0;overflow:hidden}.ngx-fi-item__thumb img{width:100%;height:100%;object-fit:cover;border-radius:8px}.ngx-fi-item__thumb mat-icon{font-size:24px;width:24px;height:24px}.ngx-fi-item__info{flex:1;min-width:0;display:flex;flex-direction:column;gap:.1rem}.ngx-fi-item__name{font-size:.88rem;font-weight:500;color:var(--mat-sys-on-surface, #333);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ngx-fi-item__meta{font-size:.75rem;color:var(--mat-sys-on-surface-variant, #666);display:flex;align-items:center;gap:.5rem;flex-wrap:wrap}.ngx-fi-item__error{color:var(--mat-sys-error, #d32f2f);display:inline-flex;align-items:center;gap:.2rem;font-weight:500}.ngx-fi-item__error mat-icon{font-size:14px;width:14px;height:14px}.ngx-fi-item__remove{flex-shrink:0}.ngx-fi-icon--image{background:#5c6bc01a}.ngx-fi-icon--image mat-icon{color:#5c6bc0}.ngx-fi-icon--pdf{background:#d32f2f1a}.ngx-fi-icon--pdf mat-icon{color:#d32f2f}.ngx-fi-icon--video{background:#1e88e51a}.ngx-fi-icon--video mat-icon{color:#1e88e5}.ngx-fi-icon--audio{background:#8e24aa1a}.ngx-fi-icon--audio mat-icon{color:#8e24aa}.ngx-fi-icon--generic{background:#0000000f}.ngx-fi-icon--generic mat-icon{color:#757575}@keyframes ngx-fi-item-enter{0%{opacity:0;transform:translateY(8px) scale(.96)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes ngx-fi-confirm-flash{0%{opacity:1}to{opacity:0}}.ngx-fi-item:nth-child(1){animation-delay:0ms}.ngx-fi-item:nth-child(2){animation-delay:50ms}.ngx-fi-item:nth-child(3){animation-delay:.1s}.ngx-fi-item:nth-child(4){animation-delay:.15s}.ngx-fi-item:nth-child(5){animation-delay:.2s}.ngx-fi-item:nth-child(6){animation-delay:.25s}.ngx-fi-item:nth-child(7){animation-delay:.3s}.ngx-fi-item:nth-child(8){animation-delay:.35s}.ngx-fi-item:nth-child(9){animation-delay:.4s}.ngx-fi-item:nth-child(10){animation-delay:.45s}.ngx-fi-item:nth-child(11){animation-delay:.5s}.ngx-fi-item:nth-child(12){animation-delay:.55s}.ngx-fi-item:nth-child(13){animation-delay:.6s}.ngx-fi-item:nth-child(14){animation-delay:.65s}.ngx-fi-item:nth-child(15){animation-delay:.7s}.ngx-fi-item:nth-child(16){animation-delay:.75s}.ngx-fi-item:nth-child(17){animation-delay:.8s}.ngx-fi-item:nth-child(18){animation-delay:.85s}.ngx-fi-item:nth-child(19){animation-delay:.9s}.ngx-fi-item:nth-child(20){animation-delay:.95s}@keyframes ngx-fi-glow{0%,to{box-shadow:inset 0 0 0 2px var(--mat-sys-primary, #5c6bc0),0 0 12px #5c6bc02e}50%{box-shadow:inset 0 0 0 2px var(--mat-sys-primary, #5c6bc0),0 0 22px #5c6bc059}}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], encapsulation: i0.ViewEncapsulation.None });
4639
+ ], viewQueries: [{ propertyName: "_nativeInput", first: true, predicate: ["nativeInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Hidden native file input \u2014 always in DOM for accessibility -->\r\n<input\r\n #nativeInput\r\n [id]=\"inputId\"\r\n class=\"ngx-fi-native-input\"\r\n type=\"file\"\r\n [accept]=\"accept()\"\r\n [multiple]=\"multiple()\"\r\n [disabled]=\"isDisabled()\"\r\n (change)=\"onFileInputChange($event)\"\r\n tabindex=\"-1\"\r\n aria-hidden=\"true\"\r\n/>\r\n\r\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n VARIANT: DEFAULT \u2014 large drop zone\r\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n@if (variant() === 'default') {\r\n <div\r\n class=\"ngx-fi-zone\"\r\n [class.ngx-fi-zone--dragover]=\"isDragOver()\"\r\n [class.ngx-fi-zone--disabled]=\"isDisabled()\"\r\n role=\"region\"\r\n [attr.aria-label]=\"resolvedLabel()\"\r\n [attr.aria-disabled]=\"isDisabled()\"\r\n tabindex=\"0\"\r\n (click)=\"openFilePicker()\"\r\n (keydown.enter)=\"openFilePicker()\"\r\n (keydown.space)=\"openFilePicker(); $event.preventDefault()\"\r\n (dragover)=\"onDragOver($event)\"\r\n (dragleave)=\"onDragLeave($event)\"\r\n (drop)=\"onDrop($event)\"\r\n >\r\n <mat-icon class=\"ngx-fi-zone__icon\">cloud_upload</mat-icon>\r\n <span class=\"ngx-fi-zone__label\">{{ resolvedLabel() }}</span>\r\n @if (hint()) {\r\n <span class=\"ngx-fi-zone__hint\">{{ hint() }}</span>\r\n }\r\n <span class=\"ngx-fi-zone__btn-text\">{{ texts().fileInput.browse }}</span>\r\n\r\n <!-- Drop confirmation flash -->\r\n @if (showDropConfirm()) {\r\n <div class=\"ngx-fi-zone__confirm\">\r\n <mat-icon>check_circle</mat-icon>\r\n </div>\r\n }\r\n </div>\r\n}\r\n\r\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n VARIANT: COMPACT \u2014 horizontal bar\r\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n@if (variant() === 'compact') {\r\n <div\r\n class=\"ngx-fi-compact\"\r\n [class.ngx-fi-compact--dragover]=\"isDragOver()\"\r\n [class.ngx-fi-compact--disabled]=\"isDisabled()\"\r\n role=\"region\"\r\n [attr.aria-label]=\"resolvedLabel()\"\r\n [attr.aria-disabled]=\"isDisabled()\"\r\n tabindex=\"0\"\r\n (click)=\"openFilePicker()\"\r\n (keydown.enter)=\"openFilePicker()\"\r\n (keydown.space)=\"openFilePicker(); $event.preventDefault()\"\r\n (dragover)=\"onDragOver($event)\"\r\n (dragleave)=\"onDragLeave($event)\"\r\n (drop)=\"onDrop($event)\"\r\n >\r\n <mat-icon class=\"ngx-fi-compact__icon\">cloud_upload</mat-icon>\r\n <div class=\"ngx-fi-compact__text\">\r\n <span class=\"ngx-fi-compact__label\">{{ resolvedLabel() }}</span>\r\n @if (hint()) {\r\n <span class=\"ngx-fi-compact__hint\">{{ hint() }}</span>\r\n }\r\n </div>\r\n\r\n @if (showDropConfirm()) {\r\n <div class=\"ngx-fi-zone__confirm\">\r\n <mat-icon>check_circle</mat-icon>\r\n </div>\r\n }\r\n </div>\r\n}\r\n\r\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n VARIANT: BUTTON \u2014 only a button\r\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n@if (variant() === 'button') {\r\n <div\r\n class=\"ngx-fi-button-wrap\"\r\n (dragover)=\"onDragOver($event)\"\r\n (dragleave)=\"onDragLeave($event)\"\r\n (drop)=\"onDrop($event)\"\r\n [class.ngx-fi-button-wrap--dragover]=\"isDragOver()\"\r\n >\r\n <button\r\n mat-raised-button\r\n color=\"primary\"\r\n [disabled]=\"isDisabled()\"\r\n (click)=\"openFilePicker()\"\r\n type=\"button\"\r\n >\r\n <mat-icon>attach_file</mat-icon>\r\n {{ resolvedLabel() }}\r\n </button>\r\n </div>\r\n}\r\n\r\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n FILE PREVIEW LIST\r\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n@if (showPreview() && items().length > 0) {\r\n <div class=\"ngx-fi-list\">\r\n @for (item of items(); track item.id) {\r\n <div\r\n class=\"ngx-fi-item\"\r\n [class.ngx-fi-item--error]=\"item.status === 'error'\"\r\n >\r\n <!-- Thumbnail / Icon -->\r\n <div class=\"ngx-fi-item__thumb\" [class]=\"getFileColorClass(item.type)\">\r\n @if (item.preview) {\r\n <img [src]=\"item.preview\" [alt]=\"item.name\" />\r\n } @else {\r\n <mat-icon>{{ getFileIcon(item.type) }}</mat-icon>\r\n }\r\n </div>\r\n\r\n <!-- Info -->\r\n <div class=\"ngx-fi-item__info\">\r\n <span class=\"ngx-fi-item__name\" [matTooltip]=\"item.name\">{{ item.name }}</span>\r\n <span class=\"ngx-fi-item__meta\">\r\n {{ formatSize(item.size) }}\r\n @if (item.error) {\r\n <span class=\"ngx-fi-item__error\">\r\n <mat-icon>warning</mat-icon> {{ item.error }}\r\n </span>\r\n }\r\n </span>\r\n </div>\r\n\r\n <!-- Remove -->\r\n <button\r\n class=\"ngx-fi-item__remove\"\r\n type=\"button\"\r\n mat-icon-button\r\n (click)=\"removeFile(item); $event.stopPropagation()\"\r\n [matTooltip]=\"texts().fileInput.remove(item.name)\"\r\n >\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n}\r\n\r\n<!-- Screen reader announcements -->\r\n<div class=\"ngx-fi-sr-only\" aria-live=\"polite\">{{ liveAnnouncement() }}</div>\r\n", styles: [".ngx-fi-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.ngx-fi-native-input{position:absolute;width:0;height:0;opacity:0;pointer-events:none}.ngx-fi-zone{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;min-height:180px;padding:2rem 1.5rem;border:2px dashed var(--mat-sys-outline-variant, #c4c4c4);border-radius:12px;background:var(--mat-sys-surface-container-low, #fafafa);cursor:pointer;transition:border-color .2s,background-color .2s,box-shadow .2s;outline:none;-webkit-user-select:none;user-select:none;overflow:hidden}.ngx-fi-zone:hover:not(.ngx-fi-zone--disabled){border-style:solid;background:var(--mat-sys-surface-container, #f0f0f0)}.ngx-fi-zone:focus-visible:not(.ngx-fi-zone--disabled){box-shadow:0 0 0 3px #5c6bc040;border-color:var(--mat-sys-primary, #5c6bc0)}.ngx-fi-zone--dragover{border-color:var(--mat-sys-primary, #5c6bc0);border-style:solid;background:var(--mat-sys-primary-container, rgba(92, 107, 192, .08));box-shadow:inset 0 0 0 2px var(--mat-sys-primary, #5c6bc0),0 0 16px #5c6bc033;animation:ngx-fi-glow 1s ease-in-out infinite}.ngx-fi-zone--dragover .ngx-fi-zone__icon{transform:scale(1.15);color:var(--mat-sys-primary, #5c6bc0)}.ngx-fi-zone--disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.ngx-fi-zone__icon{font-size:48px;width:48px;height:48px;color:var(--mat-sys-on-surface-variant, #666);transition:transform .2s,color .2s}.ngx-fi-zone__label{font-size:1.05rem;font-weight:500;color:var(--mat-sys-on-surface, #333);text-align:center}.ngx-fi-zone__hint{font-size:.82rem;color:var(--mat-sys-on-surface-variant, #666);text-align:center}.ngx-fi-zone__btn-text{font-size:.82rem;color:var(--mat-sys-primary, #5c6bc0);font-weight:500;margin-top:.25rem}.ngx-fi-zone__confirm{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#43a0471f;pointer-events:none;animation:ngx-fi-confirm-flash .4s ease-out forwards}.ngx-fi-zone__confirm mat-icon{font-size:56px;width:56px;height:56px;color:var(--mat-sys-tertiary, #43a047)}.ngx-fi-compact{position:relative;display:flex;align-items:center;gap:1rem;height:80px;padding:0 1.25rem;border:2px dashed var(--mat-sys-outline-variant, #c4c4c4);border-radius:12px;background:var(--mat-sys-surface-container-low, #fafafa);cursor:pointer;transition:border-color .2s,background-color .2s,box-shadow .2s;outline:none;-webkit-user-select:none;user-select:none;overflow:hidden}.ngx-fi-compact:hover:not(.ngx-fi-compact--disabled){border-style:solid;background:var(--mat-sys-surface-container, #f0f0f0)}.ngx-fi-compact:focus-visible:not(.ngx-fi-compact--disabled){box-shadow:0 0 0 3px #5c6bc040;border-color:var(--mat-sys-primary, #5c6bc0)}.ngx-fi-compact--dragover{border-color:var(--mat-sys-primary, #5c6bc0);border-style:solid;background:var(--mat-sys-primary-container, rgba(92, 107, 192, .08));box-shadow:inset 0 0 0 2px var(--mat-sys-primary, #5c6bc0),0 0 16px #5c6bc033;animation:ngx-fi-glow 1s ease-in-out infinite}.ngx-fi-compact--dragover .ngx-fi-compact__icon{transform:scale(1.1);color:var(--mat-sys-primary, #5c6bc0)}.ngx-fi-compact--disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.ngx-fi-compact__icon{font-size:32px;width:32px;height:32px;color:var(--mat-sys-on-surface-variant, #666);flex-shrink:0;transition:transform .2s,color .2s}.ngx-fi-compact__text{display:flex;flex-direction:column;gap:.15rem;min-width:0}.ngx-fi-compact__label{font-size:.95rem;font-weight:500;color:var(--mat-sys-on-surface, #333)}.ngx-fi-compact__hint{font-size:.78rem;color:var(--mat-sys-on-surface-variant, #666)}.ngx-fi-button-wrap{display:inline-block;position:relative;padding:4px;border-radius:8px;transition:background-color .2s,box-shadow .2s}.ngx-fi-button-wrap--dragover{background:var(--mat-sys-primary-container, rgba(92, 107, 192, .08));box-shadow:0 0 12px #5c6bc040}.ngx-fi-list{display:flex;flex-direction:column;gap:.5rem;margin-top:.75rem}.ngx-fi-item{display:flex;align-items:center;gap:.75rem;padding:.5rem .65rem;border-radius:10px;background:var(--mat-sys-surface-container-low, #fafafa);border:1px solid var(--mat-sys-outline-variant, #e0e0e0);transition:border-color .2s,background-color .2s;animation:ngx-fi-item-enter .2s ease-out both}.ngx-fi-item--error{border-color:var(--mat-sys-error, #d32f2f);background:#d32f2f0a}.ngx-fi-item__thumb{width:42px;height:42px;border-radius:8px;display:flex;align-items:center;justify-content:center;flex-shrink:0;overflow:hidden}.ngx-fi-item__thumb img{width:100%;height:100%;object-fit:cover;border-radius:8px}.ngx-fi-item__thumb mat-icon{font-size:24px;width:24px;height:24px}.ngx-fi-item__info{flex:1;min-width:0;display:flex;flex-direction:column;gap:.1rem}.ngx-fi-item__name{font-size:.88rem;font-weight:500;color:var(--mat-sys-on-surface, #333);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ngx-fi-item__meta{font-size:.75rem;color:var(--mat-sys-on-surface-variant, #666);display:flex;align-items:center;gap:.5rem;flex-wrap:wrap}.ngx-fi-item__error{color:var(--mat-sys-error, #d32f2f);display:inline-flex;align-items:center;gap:.2rem;font-weight:500}.ngx-fi-item__error mat-icon{font-size:14px;width:14px;height:14px}.ngx-fi-item__remove{flex-shrink:0}.ngx-fi-icon--image{background:#5c6bc01a}.ngx-fi-icon--image mat-icon{color:#5c6bc0}.ngx-fi-icon--pdf{background:#d32f2f1a}.ngx-fi-icon--pdf mat-icon{color:#d32f2f}.ngx-fi-icon--video{background:#1e88e51a}.ngx-fi-icon--video mat-icon{color:#1e88e5}.ngx-fi-icon--audio{background:#8e24aa1a}.ngx-fi-icon--audio mat-icon{color:#8e24aa}.ngx-fi-icon--generic{background:#0000000f}.ngx-fi-icon--generic mat-icon{color:#757575}@keyframes ngx-fi-item-enter{0%{opacity:0;transform:translateY(8px) scale(.96)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes ngx-fi-confirm-flash{0%{opacity:1}to{opacity:0}}.ngx-fi-item:nth-child(1){animation-delay:0ms}.ngx-fi-item:nth-child(2){animation-delay:50ms}.ngx-fi-item:nth-child(3){animation-delay:.1s}.ngx-fi-item:nth-child(4){animation-delay:.15s}.ngx-fi-item:nth-child(5){animation-delay:.2s}.ngx-fi-item:nth-child(6){animation-delay:.25s}.ngx-fi-item:nth-child(7){animation-delay:.3s}.ngx-fi-item:nth-child(8){animation-delay:.35s}.ngx-fi-item:nth-child(9){animation-delay:.4s}.ngx-fi-item:nth-child(10){animation-delay:.45s}.ngx-fi-item:nth-child(11){animation-delay:.5s}.ngx-fi-item:nth-child(12){animation-delay:.55s}.ngx-fi-item:nth-child(13){animation-delay:.6s}.ngx-fi-item:nth-child(14){animation-delay:.65s}.ngx-fi-item:nth-child(15){animation-delay:.7s}.ngx-fi-item:nth-child(16){animation-delay:.75s}.ngx-fi-item:nth-child(17){animation-delay:.8s}.ngx-fi-item:nth-child(18){animation-delay:.85s}.ngx-fi-item:nth-child(19){animation-delay:.9s}.ngx-fi-item:nth-child(20){animation-delay:.95s}@keyframes ngx-fi-glow{0%,to{box-shadow:inset 0 0 0 2px var(--mat-sys-primary, #5c6bc0),0 0 12px #5c6bc02e}50%{box-shadow:inset 0 0 0 2px var(--mat-sys-primary, #5c6bc0),0 0 22px #5c6bc059}}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], encapsulation: i0.ViewEncapsulation.None });
4200
4640
  }
4201
4641
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxFileInput, decorators: [{
4202
4642
  type: Component,
@@ -4212,149 +4652,83 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
4212
4652
  '[class.ngx-fi--default]': "variant() === 'default'",
4213
4653
  '[class.ngx-fi--compact]': "variant() === 'compact'",
4214
4654
  '[class.ngx-fi--button]': "variant() === 'button'",
4215
- }, template: "<!-- Hidden native file input \u2014 always in DOM for accessibility -->\r\n<input\r\n #nativeInput\r\n [id]=\"inputId\"\r\n class=\"ngx-fi-native-input\"\r\n type=\"file\"\r\n [accept]=\"accept()\"\r\n [multiple]=\"multiple()\"\r\n [disabled]=\"isDisabled()\"\r\n (change)=\"onFileInputChange($event)\"\r\n tabindex=\"-1\"\r\n aria-hidden=\"true\"\r\n/>\r\n\r\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n VARIANT: DEFAULT \u2014 large drop zone\r\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n@if (variant() === 'default') {\r\n <div\r\n class=\"ngx-fi-zone\"\r\n [class.ngx-fi-zone--dragover]=\"isDragOver()\"\r\n [class.ngx-fi-zone--disabled]=\"isDisabled()\"\r\n role=\"region\"\r\n [attr.aria-label]=\"label()\"\r\n [attr.aria-disabled]=\"isDisabled()\"\r\n tabindex=\"0\"\r\n (click)=\"openFilePicker()\"\r\n (keydown.enter)=\"openFilePicker()\"\r\n (keydown.space)=\"openFilePicker(); $event.preventDefault()\"\r\n (dragover)=\"onDragOver($event)\"\r\n (dragleave)=\"onDragLeave($event)\"\r\n (drop)=\"onDrop($event)\"\r\n >\r\n <mat-icon class=\"ngx-fi-zone__icon\">cloud_upload</mat-icon>\r\n <span class=\"ngx-fi-zone__label\">{{ label() }}</span>\r\n @if (hint()) {\r\n <span class=\"ngx-fi-zone__hint\">{{ hint() }}</span>\r\n }\r\n <span class=\"ngx-fi-zone__btn-text\">o haz clic para seleccionar</span>\r\n\r\n <!-- Drop confirmation flash -->\r\n @if (showDropConfirm()) {\r\n <div class=\"ngx-fi-zone__confirm\">\r\n <mat-icon>check_circle</mat-icon>\r\n </div>\r\n }\r\n </div>\r\n}\r\n\r\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n VARIANT: COMPACT \u2014 horizontal bar\r\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n@if (variant() === 'compact') {\r\n <div\r\n class=\"ngx-fi-compact\"\r\n [class.ngx-fi-compact--dragover]=\"isDragOver()\"\r\n [class.ngx-fi-compact--disabled]=\"isDisabled()\"\r\n role=\"region\"\r\n [attr.aria-label]=\"label()\"\r\n [attr.aria-disabled]=\"isDisabled()\"\r\n tabindex=\"0\"\r\n (click)=\"openFilePicker()\"\r\n (keydown.enter)=\"openFilePicker()\"\r\n (keydown.space)=\"openFilePicker(); $event.preventDefault()\"\r\n (dragover)=\"onDragOver($event)\"\r\n (dragleave)=\"onDragLeave($event)\"\r\n (drop)=\"onDrop($event)\"\r\n >\r\n <mat-icon class=\"ngx-fi-compact__icon\">cloud_upload</mat-icon>\r\n <div class=\"ngx-fi-compact__text\">\r\n <span class=\"ngx-fi-compact__label\">{{ label() }}</span>\r\n @if (hint()) {\r\n <span class=\"ngx-fi-compact__hint\">{{ hint() }}</span>\r\n }\r\n </div>\r\n\r\n @if (showDropConfirm()) {\r\n <div class=\"ngx-fi-zone__confirm\">\r\n <mat-icon>check_circle</mat-icon>\r\n </div>\r\n }\r\n </div>\r\n}\r\n\r\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n VARIANT: BUTTON \u2014 only a button\r\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n@if (variant() === 'button') {\r\n <div\r\n class=\"ngx-fi-button-wrap\"\r\n (dragover)=\"onDragOver($event)\"\r\n (dragleave)=\"onDragLeave($event)\"\r\n (drop)=\"onDrop($event)\"\r\n [class.ngx-fi-button-wrap--dragover]=\"isDragOver()\"\r\n >\r\n <button\r\n mat-raised-button\r\n color=\"primary\"\r\n [disabled]=\"isDisabled()\"\r\n (click)=\"openFilePicker()\"\r\n type=\"button\"\r\n >\r\n <mat-icon>attach_file</mat-icon>\r\n {{ label() }}\r\n </button>\r\n </div>\r\n}\r\n\r\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n FILE PREVIEW LIST\r\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n@if (showPreview() && items().length > 0) {\r\n <div class=\"ngx-fi-list\">\r\n @for (item of items(); track item.id) {\r\n <div\r\n class=\"ngx-fi-item\"\r\n [class.ngx-fi-item--error]=\"item.status === 'error'\"\r\n >\r\n <!-- Thumbnail / Icon -->\r\n <div class=\"ngx-fi-item__thumb\" [class]=\"getFileColorClass(item.type)\">\r\n @if (item.preview) {\r\n <img [src]=\"item.preview\" [alt]=\"item.name\" />\r\n } @else {\r\n <mat-icon>{{ getFileIcon(item.type) }}</mat-icon>\r\n }\r\n </div>\r\n\r\n <!-- Info -->\r\n <div class=\"ngx-fi-item__info\">\r\n <span class=\"ngx-fi-item__name\" [matTooltip]=\"item.name\">{{ item.name }}</span>\r\n <span class=\"ngx-fi-item__meta\">\r\n {{ formatSize(item.size) }}\r\n @if (item.error) {\r\n <span class=\"ngx-fi-item__error\">\r\n <mat-icon>warning</mat-icon> {{ item.error }}\r\n </span>\r\n }\r\n </span>\r\n </div>\r\n\r\n <!-- Remove -->\r\n <button\r\n class=\"ngx-fi-item__remove\"\r\n type=\"button\"\r\n mat-icon-button\r\n (click)=\"removeFile(item); $event.stopPropagation()\"\r\n [matTooltip]=\"'Eliminar ' + item.name\"\r\n >\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n}\r\n\r\n<!-- Screen reader announcements -->\r\n<div class=\"ngx-fi-sr-only\" aria-live=\"polite\">{{ liveAnnouncement() }}</div>\r\n", styles: [".ngx-fi-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.ngx-fi-native-input{position:absolute;width:0;height:0;opacity:0;pointer-events:none}.ngx-fi-zone{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;min-height:180px;padding:2rem 1.5rem;border:2px dashed var(--mat-sys-outline-variant, #c4c4c4);border-radius:12px;background:var(--mat-sys-surface-container-low, #fafafa);cursor:pointer;transition:border-color .2s,background-color .2s,box-shadow .2s;outline:none;-webkit-user-select:none;user-select:none;overflow:hidden}.ngx-fi-zone:hover:not(.ngx-fi-zone--disabled){border-style:solid;background:var(--mat-sys-surface-container, #f0f0f0)}.ngx-fi-zone:focus-visible:not(.ngx-fi-zone--disabled){box-shadow:0 0 0 3px #5c6bc040;border-color:var(--mat-sys-primary, #5c6bc0)}.ngx-fi-zone--dragover{border-color:var(--mat-sys-primary, #5c6bc0);border-style:solid;background:var(--mat-sys-primary-container, rgba(92, 107, 192, .08));box-shadow:inset 0 0 0 2px var(--mat-sys-primary, #5c6bc0),0 0 16px #5c6bc033;animation:ngx-fi-glow 1s ease-in-out infinite}.ngx-fi-zone--dragover .ngx-fi-zone__icon{transform:scale(1.15);color:var(--mat-sys-primary, #5c6bc0)}.ngx-fi-zone--disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.ngx-fi-zone__icon{font-size:48px;width:48px;height:48px;color:var(--mat-sys-on-surface-variant, #666);transition:transform .2s,color .2s}.ngx-fi-zone__label{font-size:1.05rem;font-weight:500;color:var(--mat-sys-on-surface, #333);text-align:center}.ngx-fi-zone__hint{font-size:.82rem;color:var(--mat-sys-on-surface-variant, #666);text-align:center}.ngx-fi-zone__btn-text{font-size:.82rem;color:var(--mat-sys-primary, #5c6bc0);font-weight:500;margin-top:.25rem}.ngx-fi-zone__confirm{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#43a0471f;pointer-events:none;animation:ngx-fi-confirm-flash .4s ease-out forwards}.ngx-fi-zone__confirm mat-icon{font-size:56px;width:56px;height:56px;color:var(--mat-sys-tertiary, #43a047)}.ngx-fi-compact{position:relative;display:flex;align-items:center;gap:1rem;height:80px;padding:0 1.25rem;border:2px dashed var(--mat-sys-outline-variant, #c4c4c4);border-radius:12px;background:var(--mat-sys-surface-container-low, #fafafa);cursor:pointer;transition:border-color .2s,background-color .2s,box-shadow .2s;outline:none;-webkit-user-select:none;user-select:none;overflow:hidden}.ngx-fi-compact:hover:not(.ngx-fi-compact--disabled){border-style:solid;background:var(--mat-sys-surface-container, #f0f0f0)}.ngx-fi-compact:focus-visible:not(.ngx-fi-compact--disabled){box-shadow:0 0 0 3px #5c6bc040;border-color:var(--mat-sys-primary, #5c6bc0)}.ngx-fi-compact--dragover{border-color:var(--mat-sys-primary, #5c6bc0);border-style:solid;background:var(--mat-sys-primary-container, rgba(92, 107, 192, .08));box-shadow:inset 0 0 0 2px var(--mat-sys-primary, #5c6bc0),0 0 16px #5c6bc033;animation:ngx-fi-glow 1s ease-in-out infinite}.ngx-fi-compact--dragover .ngx-fi-compact__icon{transform:scale(1.1);color:var(--mat-sys-primary, #5c6bc0)}.ngx-fi-compact--disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.ngx-fi-compact__icon{font-size:32px;width:32px;height:32px;color:var(--mat-sys-on-surface-variant, #666);flex-shrink:0;transition:transform .2s,color .2s}.ngx-fi-compact__text{display:flex;flex-direction:column;gap:.15rem;min-width:0}.ngx-fi-compact__label{font-size:.95rem;font-weight:500;color:var(--mat-sys-on-surface, #333)}.ngx-fi-compact__hint{font-size:.78rem;color:var(--mat-sys-on-surface-variant, #666)}.ngx-fi-button-wrap{display:inline-block;position:relative;padding:4px;border-radius:8px;transition:background-color .2s,box-shadow .2s}.ngx-fi-button-wrap--dragover{background:var(--mat-sys-primary-container, rgba(92, 107, 192, .08));box-shadow:0 0 12px #5c6bc040}.ngx-fi-list{display:flex;flex-direction:column;gap:.5rem;margin-top:.75rem}.ngx-fi-item{display:flex;align-items:center;gap:.75rem;padding:.5rem .65rem;border-radius:10px;background:var(--mat-sys-surface-container-low, #fafafa);border:1px solid var(--mat-sys-outline-variant, #e0e0e0);transition:border-color .2s,background-color .2s;animation:ngx-fi-item-enter .2s ease-out both}.ngx-fi-item--error{border-color:var(--mat-sys-error, #d32f2f);background:#d32f2f0a}.ngx-fi-item__thumb{width:42px;height:42px;border-radius:8px;display:flex;align-items:center;justify-content:center;flex-shrink:0;overflow:hidden}.ngx-fi-item__thumb img{width:100%;height:100%;object-fit:cover;border-radius:8px}.ngx-fi-item__thumb mat-icon{font-size:24px;width:24px;height:24px}.ngx-fi-item__info{flex:1;min-width:0;display:flex;flex-direction:column;gap:.1rem}.ngx-fi-item__name{font-size:.88rem;font-weight:500;color:var(--mat-sys-on-surface, #333);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ngx-fi-item__meta{font-size:.75rem;color:var(--mat-sys-on-surface-variant, #666);display:flex;align-items:center;gap:.5rem;flex-wrap:wrap}.ngx-fi-item__error{color:var(--mat-sys-error, #d32f2f);display:inline-flex;align-items:center;gap:.2rem;font-weight:500}.ngx-fi-item__error mat-icon{font-size:14px;width:14px;height:14px}.ngx-fi-item__remove{flex-shrink:0}.ngx-fi-icon--image{background:#5c6bc01a}.ngx-fi-icon--image mat-icon{color:#5c6bc0}.ngx-fi-icon--pdf{background:#d32f2f1a}.ngx-fi-icon--pdf mat-icon{color:#d32f2f}.ngx-fi-icon--video{background:#1e88e51a}.ngx-fi-icon--video mat-icon{color:#1e88e5}.ngx-fi-icon--audio{background:#8e24aa1a}.ngx-fi-icon--audio mat-icon{color:#8e24aa}.ngx-fi-icon--generic{background:#0000000f}.ngx-fi-icon--generic mat-icon{color:#757575}@keyframes ngx-fi-item-enter{0%{opacity:0;transform:translateY(8px) scale(.96)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes ngx-fi-confirm-flash{0%{opacity:1}to{opacity:0}}.ngx-fi-item:nth-child(1){animation-delay:0ms}.ngx-fi-item:nth-child(2){animation-delay:50ms}.ngx-fi-item:nth-child(3){animation-delay:.1s}.ngx-fi-item:nth-child(4){animation-delay:.15s}.ngx-fi-item:nth-child(5){animation-delay:.2s}.ngx-fi-item:nth-child(6){animation-delay:.25s}.ngx-fi-item:nth-child(7){animation-delay:.3s}.ngx-fi-item:nth-child(8){animation-delay:.35s}.ngx-fi-item:nth-child(9){animation-delay:.4s}.ngx-fi-item:nth-child(10){animation-delay:.45s}.ngx-fi-item:nth-child(11){animation-delay:.5s}.ngx-fi-item:nth-child(12){animation-delay:.55s}.ngx-fi-item:nth-child(13){animation-delay:.6s}.ngx-fi-item:nth-child(14){animation-delay:.65s}.ngx-fi-item:nth-child(15){animation-delay:.7s}.ngx-fi-item:nth-child(16){animation-delay:.75s}.ngx-fi-item:nth-child(17){animation-delay:.8s}.ngx-fi-item:nth-child(18){animation-delay:.85s}.ngx-fi-item:nth-child(19){animation-delay:.9s}.ngx-fi-item:nth-child(20){animation-delay:.95s}@keyframes ngx-fi-glow{0%,to{box-shadow:inset 0 0 0 2px var(--mat-sys-primary, #5c6bc0),0 0 12px #5c6bc02e}50%{box-shadow:inset 0 0 0 2px var(--mat-sys-primary, #5c6bc0),0 0 22px #5c6bc059}}\n"] }]
4655
+ }, template: "<!-- Hidden native file input \u2014 always in DOM for accessibility -->\r\n<input\r\n #nativeInput\r\n [id]=\"inputId\"\r\n class=\"ngx-fi-native-input\"\r\n type=\"file\"\r\n [accept]=\"accept()\"\r\n [multiple]=\"multiple()\"\r\n [disabled]=\"isDisabled()\"\r\n (change)=\"onFileInputChange($event)\"\r\n tabindex=\"-1\"\r\n aria-hidden=\"true\"\r\n/>\r\n\r\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n VARIANT: DEFAULT \u2014 large drop zone\r\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n@if (variant() === 'default') {\r\n <div\r\n class=\"ngx-fi-zone\"\r\n [class.ngx-fi-zone--dragover]=\"isDragOver()\"\r\n [class.ngx-fi-zone--disabled]=\"isDisabled()\"\r\n role=\"region\"\r\n [attr.aria-label]=\"resolvedLabel()\"\r\n [attr.aria-disabled]=\"isDisabled()\"\r\n tabindex=\"0\"\r\n (click)=\"openFilePicker()\"\r\n (keydown.enter)=\"openFilePicker()\"\r\n (keydown.space)=\"openFilePicker(); $event.preventDefault()\"\r\n (dragover)=\"onDragOver($event)\"\r\n (dragleave)=\"onDragLeave($event)\"\r\n (drop)=\"onDrop($event)\"\r\n >\r\n <mat-icon class=\"ngx-fi-zone__icon\">cloud_upload</mat-icon>\r\n <span class=\"ngx-fi-zone__label\">{{ resolvedLabel() }}</span>\r\n @if (hint()) {\r\n <span class=\"ngx-fi-zone__hint\">{{ hint() }}</span>\r\n }\r\n <span class=\"ngx-fi-zone__btn-text\">{{ texts().fileInput.browse }}</span>\r\n\r\n <!-- Drop confirmation flash -->\r\n @if (showDropConfirm()) {\r\n <div class=\"ngx-fi-zone__confirm\">\r\n <mat-icon>check_circle</mat-icon>\r\n </div>\r\n }\r\n </div>\r\n}\r\n\r\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n VARIANT: COMPACT \u2014 horizontal bar\r\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n@if (variant() === 'compact') {\r\n <div\r\n class=\"ngx-fi-compact\"\r\n [class.ngx-fi-compact--dragover]=\"isDragOver()\"\r\n [class.ngx-fi-compact--disabled]=\"isDisabled()\"\r\n role=\"region\"\r\n [attr.aria-label]=\"resolvedLabel()\"\r\n [attr.aria-disabled]=\"isDisabled()\"\r\n tabindex=\"0\"\r\n (click)=\"openFilePicker()\"\r\n (keydown.enter)=\"openFilePicker()\"\r\n (keydown.space)=\"openFilePicker(); $event.preventDefault()\"\r\n (dragover)=\"onDragOver($event)\"\r\n (dragleave)=\"onDragLeave($event)\"\r\n (drop)=\"onDrop($event)\"\r\n >\r\n <mat-icon class=\"ngx-fi-compact__icon\">cloud_upload</mat-icon>\r\n <div class=\"ngx-fi-compact__text\">\r\n <span class=\"ngx-fi-compact__label\">{{ resolvedLabel() }}</span>\r\n @if (hint()) {\r\n <span class=\"ngx-fi-compact__hint\">{{ hint() }}</span>\r\n }\r\n </div>\r\n\r\n @if (showDropConfirm()) {\r\n <div class=\"ngx-fi-zone__confirm\">\r\n <mat-icon>check_circle</mat-icon>\r\n </div>\r\n }\r\n </div>\r\n}\r\n\r\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n VARIANT: BUTTON \u2014 only a button\r\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n@if (variant() === 'button') {\r\n <div\r\n class=\"ngx-fi-button-wrap\"\r\n (dragover)=\"onDragOver($event)\"\r\n (dragleave)=\"onDragLeave($event)\"\r\n (drop)=\"onDrop($event)\"\r\n [class.ngx-fi-button-wrap--dragover]=\"isDragOver()\"\r\n >\r\n <button\r\n mat-raised-button\r\n color=\"primary\"\r\n [disabled]=\"isDisabled()\"\r\n (click)=\"openFilePicker()\"\r\n type=\"button\"\r\n >\r\n <mat-icon>attach_file</mat-icon>\r\n {{ resolvedLabel() }}\r\n </button>\r\n </div>\r\n}\r\n\r\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n FILE PREVIEW LIST\r\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n@if (showPreview() && items().length > 0) {\r\n <div class=\"ngx-fi-list\">\r\n @for (item of items(); track item.id) {\r\n <div\r\n class=\"ngx-fi-item\"\r\n [class.ngx-fi-item--error]=\"item.status === 'error'\"\r\n >\r\n <!-- Thumbnail / Icon -->\r\n <div class=\"ngx-fi-item__thumb\" [class]=\"getFileColorClass(item.type)\">\r\n @if (item.preview) {\r\n <img [src]=\"item.preview\" [alt]=\"item.name\" />\r\n } @else {\r\n <mat-icon>{{ getFileIcon(item.type) }}</mat-icon>\r\n }\r\n </div>\r\n\r\n <!-- Info -->\r\n <div class=\"ngx-fi-item__info\">\r\n <span class=\"ngx-fi-item__name\" [matTooltip]=\"item.name\">{{ item.name }}</span>\r\n <span class=\"ngx-fi-item__meta\">\r\n {{ formatSize(item.size) }}\r\n @if (item.error) {\r\n <span class=\"ngx-fi-item__error\">\r\n <mat-icon>warning</mat-icon> {{ item.error }}\r\n </span>\r\n }\r\n </span>\r\n </div>\r\n\r\n <!-- Remove -->\r\n <button\r\n class=\"ngx-fi-item__remove\"\r\n type=\"button\"\r\n mat-icon-button\r\n (click)=\"removeFile(item); $event.stopPropagation()\"\r\n [matTooltip]=\"texts().fileInput.remove(item.name)\"\r\n >\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n}\r\n\r\n<!-- Screen reader announcements -->\r\n<div class=\"ngx-fi-sr-only\" aria-live=\"polite\">{{ liveAnnouncement() }}</div>\r\n", styles: [".ngx-fi-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.ngx-fi-native-input{position:absolute;width:0;height:0;opacity:0;pointer-events:none}.ngx-fi-zone{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;min-height:180px;padding:2rem 1.5rem;border:2px dashed var(--mat-sys-outline-variant, #c4c4c4);border-radius:12px;background:var(--mat-sys-surface-container-low, #fafafa);cursor:pointer;transition:border-color .2s,background-color .2s,box-shadow .2s;outline:none;-webkit-user-select:none;user-select:none;overflow:hidden}.ngx-fi-zone:hover:not(.ngx-fi-zone--disabled){border-style:solid;background:var(--mat-sys-surface-container, #f0f0f0)}.ngx-fi-zone:focus-visible:not(.ngx-fi-zone--disabled){box-shadow:0 0 0 3px #5c6bc040;border-color:var(--mat-sys-primary, #5c6bc0)}.ngx-fi-zone--dragover{border-color:var(--mat-sys-primary, #5c6bc0);border-style:solid;background:var(--mat-sys-primary-container, rgba(92, 107, 192, .08));box-shadow:inset 0 0 0 2px var(--mat-sys-primary, #5c6bc0),0 0 16px #5c6bc033;animation:ngx-fi-glow 1s ease-in-out infinite}.ngx-fi-zone--dragover .ngx-fi-zone__icon{transform:scale(1.15);color:var(--mat-sys-primary, #5c6bc0)}.ngx-fi-zone--disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.ngx-fi-zone__icon{font-size:48px;width:48px;height:48px;color:var(--mat-sys-on-surface-variant, #666);transition:transform .2s,color .2s}.ngx-fi-zone__label{font-size:1.05rem;font-weight:500;color:var(--mat-sys-on-surface, #333);text-align:center}.ngx-fi-zone__hint{font-size:.82rem;color:var(--mat-sys-on-surface-variant, #666);text-align:center}.ngx-fi-zone__btn-text{font-size:.82rem;color:var(--mat-sys-primary, #5c6bc0);font-weight:500;margin-top:.25rem}.ngx-fi-zone__confirm{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#43a0471f;pointer-events:none;animation:ngx-fi-confirm-flash .4s ease-out forwards}.ngx-fi-zone__confirm mat-icon{font-size:56px;width:56px;height:56px;color:var(--mat-sys-tertiary, #43a047)}.ngx-fi-compact{position:relative;display:flex;align-items:center;gap:1rem;height:80px;padding:0 1.25rem;border:2px dashed var(--mat-sys-outline-variant, #c4c4c4);border-radius:12px;background:var(--mat-sys-surface-container-low, #fafafa);cursor:pointer;transition:border-color .2s,background-color .2s,box-shadow .2s;outline:none;-webkit-user-select:none;user-select:none;overflow:hidden}.ngx-fi-compact:hover:not(.ngx-fi-compact--disabled){border-style:solid;background:var(--mat-sys-surface-container, #f0f0f0)}.ngx-fi-compact:focus-visible:not(.ngx-fi-compact--disabled){box-shadow:0 0 0 3px #5c6bc040;border-color:var(--mat-sys-primary, #5c6bc0)}.ngx-fi-compact--dragover{border-color:var(--mat-sys-primary, #5c6bc0);border-style:solid;background:var(--mat-sys-primary-container, rgba(92, 107, 192, .08));box-shadow:inset 0 0 0 2px var(--mat-sys-primary, #5c6bc0),0 0 16px #5c6bc033;animation:ngx-fi-glow 1s ease-in-out infinite}.ngx-fi-compact--dragover .ngx-fi-compact__icon{transform:scale(1.1);color:var(--mat-sys-primary, #5c6bc0)}.ngx-fi-compact--disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.ngx-fi-compact__icon{font-size:32px;width:32px;height:32px;color:var(--mat-sys-on-surface-variant, #666);flex-shrink:0;transition:transform .2s,color .2s}.ngx-fi-compact__text{display:flex;flex-direction:column;gap:.15rem;min-width:0}.ngx-fi-compact__label{font-size:.95rem;font-weight:500;color:var(--mat-sys-on-surface, #333)}.ngx-fi-compact__hint{font-size:.78rem;color:var(--mat-sys-on-surface-variant, #666)}.ngx-fi-button-wrap{display:inline-block;position:relative;padding:4px;border-radius:8px;transition:background-color .2s,box-shadow .2s}.ngx-fi-button-wrap--dragover{background:var(--mat-sys-primary-container, rgba(92, 107, 192, .08));box-shadow:0 0 12px #5c6bc040}.ngx-fi-list{display:flex;flex-direction:column;gap:.5rem;margin-top:.75rem}.ngx-fi-item{display:flex;align-items:center;gap:.75rem;padding:.5rem .65rem;border-radius:10px;background:var(--mat-sys-surface-container-low, #fafafa);border:1px solid var(--mat-sys-outline-variant, #e0e0e0);transition:border-color .2s,background-color .2s;animation:ngx-fi-item-enter .2s ease-out both}.ngx-fi-item--error{border-color:var(--mat-sys-error, #d32f2f);background:#d32f2f0a}.ngx-fi-item__thumb{width:42px;height:42px;border-radius:8px;display:flex;align-items:center;justify-content:center;flex-shrink:0;overflow:hidden}.ngx-fi-item__thumb img{width:100%;height:100%;object-fit:cover;border-radius:8px}.ngx-fi-item__thumb mat-icon{font-size:24px;width:24px;height:24px}.ngx-fi-item__info{flex:1;min-width:0;display:flex;flex-direction:column;gap:.1rem}.ngx-fi-item__name{font-size:.88rem;font-weight:500;color:var(--mat-sys-on-surface, #333);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ngx-fi-item__meta{font-size:.75rem;color:var(--mat-sys-on-surface-variant, #666);display:flex;align-items:center;gap:.5rem;flex-wrap:wrap}.ngx-fi-item__error{color:var(--mat-sys-error, #d32f2f);display:inline-flex;align-items:center;gap:.2rem;font-weight:500}.ngx-fi-item__error mat-icon{font-size:14px;width:14px;height:14px}.ngx-fi-item__remove{flex-shrink:0}.ngx-fi-icon--image{background:#5c6bc01a}.ngx-fi-icon--image mat-icon{color:#5c6bc0}.ngx-fi-icon--pdf{background:#d32f2f1a}.ngx-fi-icon--pdf mat-icon{color:#d32f2f}.ngx-fi-icon--video{background:#1e88e51a}.ngx-fi-icon--video mat-icon{color:#1e88e5}.ngx-fi-icon--audio{background:#8e24aa1a}.ngx-fi-icon--audio mat-icon{color:#8e24aa}.ngx-fi-icon--generic{background:#0000000f}.ngx-fi-icon--generic mat-icon{color:#757575}@keyframes ngx-fi-item-enter{0%{opacity:0;transform:translateY(8px) scale(.96)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes ngx-fi-confirm-flash{0%{opacity:1}to{opacity:0}}.ngx-fi-item:nth-child(1){animation-delay:0ms}.ngx-fi-item:nth-child(2){animation-delay:50ms}.ngx-fi-item:nth-child(3){animation-delay:.1s}.ngx-fi-item:nth-child(4){animation-delay:.15s}.ngx-fi-item:nth-child(5){animation-delay:.2s}.ngx-fi-item:nth-child(6){animation-delay:.25s}.ngx-fi-item:nth-child(7){animation-delay:.3s}.ngx-fi-item:nth-child(8){animation-delay:.35s}.ngx-fi-item:nth-child(9){animation-delay:.4s}.ngx-fi-item:nth-child(10){animation-delay:.45s}.ngx-fi-item:nth-child(11){animation-delay:.5s}.ngx-fi-item:nth-child(12){animation-delay:.55s}.ngx-fi-item:nth-child(13){animation-delay:.6s}.ngx-fi-item:nth-child(14){animation-delay:.65s}.ngx-fi-item:nth-child(15){animation-delay:.7s}.ngx-fi-item:nth-child(16){animation-delay:.75s}.ngx-fi-item:nth-child(17){animation-delay:.8s}.ngx-fi-item:nth-child(18){animation-delay:.85s}.ngx-fi-item:nth-child(19){animation-delay:.9s}.ngx-fi-item:nth-child(20){animation-delay:.95s}@keyframes ngx-fi-glow{0%,to{box-shadow:inset 0 0 0 2px var(--mat-sys-primary, #5c6bc0),0 0 12px #5c6bc02e}50%{box-shadow:inset 0 0 0 2px var(--mat-sys-primary, #5c6bc0),0 0 22px #5c6bc059}}\n"] }]
4216
4656
  }], propDecorators: { _nativeInput: [{ type: i0.ViewChild, args: ['nativeInput', { isSignal: true }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], maxSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSize", required: false }] }], maxFiles: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFiles", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], showPreview: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPreview", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], filesSelected: [{ type: i0.Output, args: ["filesSelected"] }], fileRemoved: [{ type: i0.Output, args: ["fileRemoved"] }], validationError: [{ type: i0.Output, args: ["validationError"] }] } });
4217
4657
 
4658
+ /**
4659
+ * Ancho mínimo por defecto: 400px, pero nunca más que la pantalla menos un margen
4660
+ * (un 400px fijo se salía de los móviles).
4661
+ */
4662
+ const DEFAULT_MIN_WIDTH = 'min(400px, calc(100vw - 32px))';
4663
+ /**
4664
+ * Abre diálogos de Material con una estructura común: título con icono opcional, subtítulo,
4665
+ * cuerpo (texto, HTML, componente o plantilla) y botones de cancelar/confirmar.
4666
+ *
4667
+ * Todos devuelven un Observable que emite al cerrarse y completa:
4668
+ * - `true` (o el resultado fijado por el contenido) si se confirma,
4669
+ * - `false` si se cancela,
4670
+ * - `undefined` si se cierra sin pulsar ningún botón (Esc o clic fuera).
4671
+ */
4218
4672
  class NgxDialogService {
4219
- // dependencies injection
4220
4673
  _dialog = inject(MatDialog);
4221
- /**
4222
- *
4223
- * @param config
4224
- * @param dialogConfig
4225
- * @returns Observable<DialogResult>
4226
- *
4227
- * Opens a text dialog with the provided configuration.
4228
- */
4674
+ _texts = inject(NgxTexts).texts;
4675
+ /** Diálogo con un texto. Base de `confirm()` e `info()`. */
4229
4676
  openText(config, dialogConfig) {
4230
- return this._dialog.open(NgxDialog, {
4231
- ...dialogConfig,
4232
- data: {
4233
- ...config,
4234
- body: {
4235
- type: DialogBodyType.TEXT,
4236
- content: config.content
4237
- },
4238
- },
4239
- minWidth: dialogConfig?.minWidth ?? '400px',
4240
- autoFocus: dialogConfig?.autoFocus ?? false
4241
- }).afterClosed();
4677
+ const { content, ...header } = config;
4678
+ return this._open(header, { type: DialogBodyType.TEXT, content }, dialogConfig);
4242
4679
  }
4243
- /**
4244
- *
4245
- * @param title
4246
- * @param message
4247
- * @param cancelText
4248
- * @param confirmText
4249
- * @param dialogConfig
4250
- * @returns Observable<DialogResult>
4251
- *
4252
- * Opens a confirmation dialog with cancel and confirm buttons.
4253
- */
4680
+ /** Pregunta de confirmación con botones de cancelar y confirmar. */
4254
4681
  confirm(config, dialogConfig) {
4682
+ const { message, ...header } = config;
4255
4683
  return this.openText({
4256
- title: config.title,
4257
- content: config.message,
4258
- subtitle: config.subtitle,
4259
- icon: config.icon,
4260
- iconColor: config.iconColor,
4261
- cancelText: config.cancelText ?? 'Cancelar',
4262
- confirmText: config.confirmText ?? 'Confirmar'
4684
+ ...header,
4685
+ content: message,
4686
+ cancelText: config.cancelText ?? this._texts().dialog.cancel,
4687
+ confirmText: config.confirmText ?? this._texts().dialog.confirm,
4263
4688
  }, dialogConfig);
4264
4689
  }
4265
- /**
4266
- *
4267
- * @param title
4268
- * @param message
4269
- * @param confirmText
4270
- * @param dialogConfig
4271
- * @returns Observable<DialogResult>
4272
- *
4273
- * Opens an informational dialog with a single confirm button.
4274
- */
4690
+ /** Aviso informativo con un único botón. */
4275
4691
  info(config, dialogConfig) {
4692
+ const { message, ...header } = config;
4276
4693
  return this.openText({
4277
- title: config.title,
4278
- content: config.message,
4279
- subtitle: config.subtitle,
4280
- icon: config.icon,
4281
- iconColor: config.iconColor,
4694
+ ...header,
4695
+ content: message,
4282
4696
  showCancel: false,
4283
- confirmText: config.confirmText ?? 'Aceptar',
4697
+ confirmText: config.confirmText ?? this._texts().dialog.accept,
4284
4698
  }, dialogConfig);
4285
4699
  }
4286
4700
  /**
4287
- *
4288
- * @param config
4289
- * @param dialogConfig
4290
- * @returns Observable<DialogResult>
4291
- *
4292
- * Opens an HTML dialog with the provided configuration.
4701
+ * Diálogo con HTML. Angular sanea el HTML: se quitan scripts, estilos en línea y atributos
4702
+ * peligrosos. Para contenido con interacción, usa `component()` o `template()`.
4293
4703
  */
4294
4704
  html(config, dialogConfig) {
4295
- return this._dialog.open(NgxDialog, {
4296
- ...dialogConfig,
4297
- data: {
4298
- ...config,
4299
- body: {
4300
- type: DialogBodyType.HTML,
4301
- content: config.html
4302
- },
4303
- },
4304
- minWidth: dialogConfig?.minWidth ?? '400px',
4305
- autoFocus: dialogConfig?.autoFocus ?? false
4306
- }).afterClosed();
4705
+ const { html, ...header } = config;
4706
+ return this._open(header, { type: DialogBodyType.HTML, content: html }, dialogConfig);
4307
4707
  }
4308
4708
  /**
4309
- *
4310
- * @param config
4311
- * @return Observable<DialogResult>
4312
- *
4313
- * Opens a component dialog with the provided configuration.
4709
+ * Diálogo con un componente propio. El componente recibe `componentData` por su input `data`
4710
+ * y puede inyectar `NgxDialogContext<R>` para devolver un resultado (`result`), cerrar
4711
+ * (`close()`) o deshabilitar el botón de confirmar (`confirmDisabled`).
4314
4712
  */
4315
4713
  component(config, dialogConfig) {
4316
- return this._dialog.open((NgxDialog), {
4317
- ...dialogConfig,
4318
- data: {
4319
- title: config.title,
4320
- subtitle: config.subtitle,
4321
- icon: config.icon,
4322
- iconColor: config.iconColor,
4323
- body: {
4324
- type: DialogBodyType.COMPONENT,
4325
- content: config.component,
4326
- data: config.componentData
4327
- },
4328
- cancelText: config.cancelText,
4329
- confirmText: config.confirmText,
4330
- showCancel: config.showCancel,
4331
- showConfirm: config.showConfirm,
4332
- },
4333
- minWidth: dialogConfig?.minWidth ?? '400px',
4334
- autoFocus: dialogConfig?.autoFocus ?? false
4335
- }).afterClosed();
4714
+ const { component, componentData, ...header } = config;
4715
+ return this._open(header, { type: DialogBodyType.COMPONENT, content: component, data: componentData }, dialogConfig);
4336
4716
  }
4337
4717
  /**
4338
- *
4339
- * @param config
4340
- * @param dialogConfig
4341
- * @returns Observable<DialogResult>
4342
- *
4343
- * Opens a template dialog with the provided configuration.
4718
+ * Diálogo con una plantilla. La plantilla recibe `templateData` como `$implicit` y el contexto
4719
+ * del diálogo como `dialog` (`let-data let-dialog="dialog"`).
4344
4720
  */
4345
4721
  template(config, dialogConfig) {
4346
- return this._dialog.open((NgxDialog), {
4722
+ const { template, templateData, ...header } = config;
4723
+ return this._open(header, { type: DialogBodyType.TEMPLATE, content: template, data: templateData }, dialogConfig);
4724
+ }
4725
+ _open(header, body, dialogConfig) {
4726
+ const data = { ...header, body };
4727
+ return this._dialog.open(NgxDialog, {
4347
4728
  ...dialogConfig,
4348
- data: {
4349
- ...config,
4350
- body: {
4351
- type: DialogBodyType.TEMPLATE,
4352
- content: config.template,
4353
- data: config.templateData
4354
- },
4355
- },
4356
- minWidth: dialogConfig?.minWidth ?? '400px',
4357
- autoFocus: dialogConfig?.autoFocus ?? false
4729
+ data,
4730
+ minWidth: dialogConfig?.minWidth ?? DEFAULT_MIN_WIDTH,
4731
+ autoFocus: dialogConfig?.autoFocus ?? false,
4358
4732
  }).afterClosed();
4359
4733
  }
4360
4734
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxDialogService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
@@ -4371,5 +4745,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
4371
4745
  * Generated bundle index. Do not edit.
4372
4746
  */
4373
4747
 
4374
- export { AdvancedFilterService, AdvancedFilterUtils, ColumnConfigService, DatosPantallaService, DialogBodyType, DynamicHostDirective, NgxAlert, NgxBasicSelect, NgxBasicTable, NgxConfirmDialogComponent, NgxDialog, NgxDialogService, NgxFileInput, NgxInputFile, NgxLoadingButton, NgxPaginatedSelect, NgxPaginatedSelectBottomSheetComponent, NgxPaginatedTable, NgxSkeleton, NgxTablesIntl, OPERATOR_BY_FILTER_TYPE, PaginatedSearchableSelectComponent, SearchableSelectComponent, USER_ID_FACTORY, base64ToUtf8, includeNoSensible, isFilterOption };
4748
+ export { AdvancedFilterService, AdvancedFilterUtils, ColumnConfigService, DatosPantallaService, DialogBodyType, DynamicHostDirective, NGX_EIFFAGE_DEFAULT_TEXTS, NGX_EIFFAGE_TEXTS, NgxAlert, NgxBasicSelect, NgxBasicTable, NgxConfirmDialogComponent, NgxDialog, NgxDialogContext, NgxDialogService, NgxFileInput, NgxInputFile, NgxLoadingButton, NgxPaginatedSelect, NgxPaginatedSelectBottomSheetComponent, NgxPaginatedTable, NgxSkeleton, NgxTablesIntl, NgxTexts, OPERATOR_BY_FILTER_TYPE, PaginatedSearchableSelectComponent, SearchableSelectComponent, USER_ID_FACTORY, base64ToUtf8, includeNoSensible, isFilterOption, provideNgxEiffageTexts };
4375
4749
  //# sourceMappingURL=ngx-eiffage-material.mjs.map