ln-20-lib-components 0.0.11 → 0.0.13

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.
Files changed (53) hide show
  1. package/fesm2022/ln-20-lib-components-selected-items-management.component-CH9UC-8E.mjs +86 -0
  2. package/fesm2022/ln-20-lib-components-selected-items-management.component-CH9UC-8E.mjs.map +1 -0
  3. package/fesm2022/ln-20-lib-components-selected-items-management.component-CrgtLkUn.mjs +86 -0
  4. package/fesm2022/ln-20-lib-components-selected-items-management.component-CrgtLkUn.mjs.map +1 -0
  5. package/fesm2022/ln-20-lib-components-selected-items-management.component-xRoZB_NZ.mjs +86 -0
  6. package/fesm2022/ln-20-lib-components-selected-items-management.component-xRoZB_NZ.mjs.map +1 -0
  7. package/fesm2022/ln-20-lib-components.mjs +2352 -56
  8. package/fesm2022/ln-20-lib-components.mjs.map +1 -1
  9. package/lib/components/origin/disabled-container/disabled-container.component.d.ts +6 -0
  10. package/lib/components/origin/form/components/custom-input/custom-input.component.d.ts +25 -0
  11. package/lib/components/origin/form/components/form-child/form-child.component.d.ts +13 -0
  12. package/lib/components/origin/form/components/inline-input/inline-input.component.d.ts +78 -0
  13. package/lib/components/origin/form/components/inline-input/interfaces/index.d.ts +26 -0
  14. package/lib/components/origin/form/enums/index.d.ts +36 -0
  15. package/lib/components/origin/form/form.component.d.ts +19 -0
  16. package/lib/components/origin/form/index.d.ts +4 -0
  17. package/lib/components/origin/form/interfaces/index.d.ts +58 -0
  18. package/lib/components/origin/http-message/http-message.component.d.ts +10 -0
  19. package/lib/components/origin/http-message/interfaces/index.d.ts +11 -0
  20. package/lib/components/origin/index.d.ts +1 -2
  21. package/lib/components/origin/pick-list/interfaces/index.d.ts +12 -0
  22. package/lib/components/prime-ng/badge/badge-ng.component.d.ts +11 -0
  23. package/lib/components/prime-ng/badge/interfaces/index.d.ts +8 -0
  24. package/lib/components/prime-ng/dynamic-dialog/components/base-dialog.component.d.ts +21 -0
  25. package/lib/components/prime-ng/index.d.ts +2 -0
  26. package/lib/components/prime-ng/interfaces/index.d.ts +12 -0
  27. package/lib/components/prime-ng/table-ng/components/selected-items-management/selected-items-management.component.d.ts +17 -0
  28. package/lib/components/prime-ng/table-ng/interfaces/index.d.ts +191 -0
  29. package/lib/components/prime-ng/table-ng/services/table-ng-edit.service.d.ts +17 -0
  30. package/lib/components/prime-ng/table-ng/services/table-ng-general.service.d.ts +7 -0
  31. package/lib/components/prime-ng/table-ng/services/table-ng.service.d.ts +32 -0
  32. package/lib/components/prime-ng/table-ng/table-ng.component.d.ts +162 -0
  33. package/lib/components/prime-ng/toolbar-ng/toolbar-ng.component.d.ts +5 -0
  34. package/lib/pipes/index.d.ts +1 -0
  35. package/lib/pipes/key-to-display-name.pipe.d.ts +7 -0
  36. package/lib/utils/api-error.util.d.ts +58 -0
  37. package/lib/utils/cookie.util.d.ts +37 -0
  38. package/lib/utils/currency.util.d.ts +1 -0
  39. package/lib/utils/date.util.d.ts +3 -0
  40. package/lib/utils/documents.util.d.ts +88 -0
  41. package/lib/utils/id.util.d.ts +1 -0
  42. package/lib/utils/index.d.ts +9 -0
  43. package/lib/utils/number.util.d.ts +2 -0
  44. package/lib/utils/objects.util.d.ts +20 -0
  45. package/lib/utils/prime-ng.util.d.ts +3 -0
  46. package/ln-20-lib-components-0.0.12.tgz +0 -0
  47. package/ln-20-lib-components-0.0.13.tgz +0 -0
  48. package/package.json +1 -1
  49. package/lib/components/origin/button/button.component.d.ts +0 -11
  50. package/lib/components/origin/empty-message/empty-message.component.d.ts +0 -6
  51. package/ln-20-lib-components-0.0.10.tgz +0 -0
  52. package/ln-20-lib-components-0.0.11.tgz +0 -0
  53. package/ln-20-lib-components-0.0.9.tgz +0 -0
@@ -1,11 +1,51 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, Component, EventEmitter, Output, Input, input, signal, effect, computed, inject, model, output } from '@angular/core';
3
- import * as i3 from '@angular/common';
4
- import { CommonModule } from '@angular/common';
5
- import * as i1 from 'primeng/button';
6
- import { ButtonModule } from 'primeng/button';
7
- import * as i2 from 'primeng/tooltip';
2
+ import { Injectable, Component, model, input, computed, output, forwardRef, ChangeDetectionStrategy, effect, signal, ContentChildren, inject, Pipe, ContentChild, ViewChild } from '@angular/core';
3
+ import { toObservable, takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
4
+ import * as i1 from '@angular/forms';
5
+ import { ReactiveFormsModule, NG_VALUE_ACCESSOR, FormsModule, NonNullableFormBuilder, FormGroup } from '@angular/forms';
6
+ import { switchMap, debounceTime, filter, map, distinctUntilChanged } from 'rxjs';
7
+ import * as i1$1 from '@angular/common';
8
+ import { NgClass, CommonModule } from '@angular/common';
9
+ import { CheckboxModule } from 'primeng/checkbox';
10
+ import * as i2 from 'primeng/datepicker';
11
+ import { DatePickerModule } from 'primeng/datepicker';
12
+ import { IftaLabelModule } from 'primeng/iftalabel';
13
+ import * as i6 from 'primeng/inputotp';
14
+ import { InputOtpModule } from 'primeng/inputotp';
15
+ import * as i3 from 'primeng/multiselect';
16
+ import { MultiSelectModule } from 'primeng/multiselect';
17
+ import * as i4 from 'primeng/select';
18
+ import { SelectModule } from 'primeng/select';
19
+ import * as i5 from 'primeng/togglebutton';
20
+ import { ToggleButtonModule } from 'primeng/togglebutton';
21
+ import * as i7 from 'primeng/toggleswitch';
22
+ import { ToggleSwitchModule } from 'primeng/toggleswitch';
23
+ import * as i10 from 'primeng/tooltip';
8
24
  import { TooltipModule } from 'primeng/tooltip';
25
+ import * as i8 from 'primeng/inputnumber';
26
+ import { InputNumberModule } from 'primeng/inputnumber';
27
+ import * as i9 from 'primeng/textarea';
28
+ import { TextareaModule } from 'primeng/textarea';
29
+ import * as i2$1 from 'primeng/inputtext';
30
+ import { InputTextModule } from 'primeng/inputtext';
31
+ import { InputMaskModule } from 'primeng/inputmask';
32
+ import * as i9$1 from 'primeng/knob';
33
+ import { KnobModule } from 'primeng/knob';
34
+ import * as i11 from 'primeng/chip';
35
+ import { ChipModule } from 'primeng/chip';
36
+ import * as i4$1 from 'primeng/api';
37
+ import { PrimeTemplate, FilterService } from 'primeng/api';
38
+ import * as i1$2 from 'primeng/button';
39
+ import { ButtonModule } from 'primeng/button';
40
+ import jsPDF from 'jspdf';
41
+ import autoTable from 'jspdf-autotable';
42
+ import * as i2$2 from 'primeng/table';
43
+ import { TableModule } from 'primeng/table';
44
+ import * as XLSX from 'xlsx';
45
+ import * as i1$3 from 'primeng/badge';
46
+ import { BadgeModule } from 'primeng/badge';
47
+ import * as i1$4 from 'primeng/toolbar';
48
+ import { ToolbarModule } from 'primeng/toolbar';
9
49
 
10
50
  class LibComponentsService {
11
51
  constructor() { }
@@ -36,62 +76,591 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
36
76
  ` }]
37
77
  }] });
38
78
 
39
- class ButtonComponent {
40
- variant = 'primary';
41
- disabled = false;
42
- onClick = new EventEmitter();
79
+ var ETypeInput;
80
+ (function (ETypeInput) {
81
+ ETypeInput["TEXT"] = "text";
82
+ ETypeInput["PASSWORD"] = "password";
83
+ ETypeInput["EMAIL"] = "email";
84
+ ETypeInput["NUMBER"] = "number";
85
+ ETypeInput["DATE"] = "date";
86
+ ETypeInput["TIME"] = "time";
87
+ ETypeInput["DATETIME_LOCAL"] = "datetime-local";
88
+ ETypeInput["SEARCH"] = "search";
89
+ ETypeInput["TEL"] = "tel";
90
+ ETypeInput["URL"] = "url";
91
+ ETypeInput["COLOR"] = "color";
92
+ ETypeInput["MONTH"] = "month";
93
+ ETypeInput["WEEK"] = "week";
94
+ ETypeInput["FILE"] = "file";
95
+ ETypeInput["CHECKBOX"] = "checkbox";
96
+ ETypeInput["RADIO"] = "radio";
97
+ ETypeInput["RANGE"] = "range";
98
+ ETypeInput["HIDDEN"] = "hidden";
99
+ ETypeInput["TEXTAREA"] = "textarea";
100
+ ETypeInput["SELECT"] = "select";
101
+ ETypeInput["MULTISELECT"] = "multiselect";
102
+ ETypeInput["AUTOCOMPLETE"] = "autocomplete";
103
+ ETypeInput["SWITCH"] = "switch";
104
+ ETypeInput["CALENDAR"] = "calendar";
105
+ ETypeInput["DROPDOWN"] = "dropdown";
106
+ ETypeInput["CHIPS"] = "chips";
107
+ ETypeInput["TOGGLE"] = "toggle";
108
+ ETypeInput["OTP"] = "otp";
109
+ ETypeInput["CURRENCY"] = "currency";
110
+ ETypeInput["KNOB"] = "knob";
111
+ ETypeInput["BADGE"] = "badge";
112
+ ETypeInput["DECIMAL"] = "decimal";
113
+ ETypeInput["IMAGE"] = "image";
114
+ ETypeInput["COMPONENT"] = "component";
115
+ })(ETypeInput || (ETypeInput = {}));
116
+
117
+ class DisabledContainerComponent {
118
+ disabled = model(false);
119
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: DisabledContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
120
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.17", type: DisabledContainerComponent, isStandalone: true, selector: "lib-disabled-container", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { disabled: "disabledChange" }, ngImport: i0, template: "<fieldset [disabled]=\"disabled()\" class=\"disabled-container\">\r\n <ng-content></ng-content>\r\n</fieldset>\r\n", styles: [".disabled-container{border:none;margin:0;padding:0;min-width:0}.disabled-container:disabled{opacity:.6;cursor:not-allowed}.disabled-container:disabled *{pointer-events:none}\n"] });
121
+ }
122
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: DisabledContainerComponent, decorators: [{
123
+ type: Component,
124
+ args: [{ selector: 'lib-disabled-container', imports: [], template: "<fieldset [disabled]=\"disabled()\" class=\"disabled-container\">\r\n <ng-content></ng-content>\r\n</fieldset>\r\n", styles: [".disabled-container{border:none;margin:0;padding:0;min-width:0}.disabled-container:disabled{opacity:.6;cursor:not-allowed}.disabled-container:disabled *{pointer-events:none}\n"] }]
125
+ }] });
126
+
127
+ class CustomInputComponent {
128
+ controlData = input.required();
129
+ controlUpperName = computed(() => this.controlData().controlName.toLocaleUpperCase());
130
+ showPassword = false;
131
+ output = output();
132
+ onTouched = () => { };
133
+ onChange = (_value) => { };
134
+ constructor() { }
135
+ writeValue(value) {
136
+ if (value !== this.controlData().control.value) {
137
+ this.controlData().control.setValue(value, { emitEvent: false });
138
+ }
139
+ }
140
+ get showLabel() {
141
+ return !this.controlData().hideLabel;
142
+ }
143
+ get inputTypesEnum() {
144
+ return ETypeInput;
145
+ }
146
+ onCheckboxChange(event, control) {
147
+ const input = event.target;
148
+ const isChecked = input.checked;
149
+ control.setValue(isChecked);
150
+ }
151
+ registerOnChange(fn) {
152
+ this.onChange = fn;
153
+ }
154
+ registerOnTouched(fn) {
155
+ this.onTouched = fn;
156
+ }
157
+ // setDisabledState(isDisabled: boolean): void {
158
+ // if (isDisabled) {
159
+ // this.controlData().control.disable()
160
+ // } else {
161
+ // this.controlData().control.enable()
162
+ // }
163
+ // }
164
+ generateUniqueId(baseString) {
165
+ const timestamp = new Date().getTime();
166
+ const random = Math.random().toString(36).substring(2, 8);
167
+ return `${baseString}-${timestamp}-${random}`;
168
+ }
169
+ togglePasswordVisibility() {
170
+ this.showPassword = !this.showPassword;
171
+ }
172
+ onSelectChange() {
173
+ this.output.emit(this.controlData());
174
+ }
175
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: CustomInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
176
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: CustomInputComponent, isStandalone: true, selector: "lib-custom-input", inputs: { controlData: { classPropertyName: "controlData", publicName: "controlData", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { output: "output" }, providers: [{
177
+ provide: NG_VALUE_ACCESSOR,
178
+ useExisting: forwardRef(() => CustomInputComponent),
179
+ multi: true
180
+ }], ngImport: i0, template: "@let localControl = controlData().control;\r\n@let placeholder = controlData().label || controlUpperName();\r\n@let name = controlData().controlName;\r\n@let typeInput = controlData().typeInput;\r\n@let readonly = controlData().readonly || false;\r\n@let dateConfig = controlData().dateConfig;\r\n@let multiSelectConfig = controlData().multiSelectConfig;\r\n@let selectConfig = controlData().selectConfig;\r\n@let toggleConfig = controlData().toggleConfig;\r\n@let textareaConfig = controlData().textareaConfig;\r\n@let currencyConfig = controlData().currencyConfig;\r\n<div class=\"flex flex-col gap-1 \">\r\n <lib-disabled-container [disabled]=\"readonly\">\r\n\r\n <p style=\"font-size: 12px; letter-spacing: 0.5px;\" class=\"text-sm text-gray-600 dark:text-gray-300 truncate\"\r\n [pTooltip]=\"placeholder\" tooltipPosition=\"top\" [showDelay]=\"300\">\r\n {{ placeholder }}\r\n </p>\r\n @switch (typeInput) {\r\n @case (inputTypesEnum.EMAIL) {\r\n <input \r\n [formControl]=\"localControl\" \r\n (blur)=\"onTouched()\" \r\n pInputText \r\n [id]=\"generateUniqueId(name)\" \r\n [name]=\"name\"\r\n [type]=\"typeInput\"\r\n [readOnly]=\"readonly\" \r\n autocomplete=\"email\" \r\n autocorrect=\"on\" \r\n autocapitalize=\"on\" \r\n spellcheck=\"true\" \r\n [ngClass]=\"{\r\n 'border-red-500 focus:ring-red-500':\r\n localControl.invalid &&\r\n (localControl.dirty || localControl.touched),\r\n 'bg-gray-100 cursor-not-allowed': readonly,\r\n }\"\r\n class=\"custom-input h-12 w-full px-3 py-2 border border-gray-300 dark:border-transparent rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100\" />\r\n }\r\n @case (inputTypesEnum.CURRENCY) {\r\n <p-inputnumber [formControl]=\"localControl\" (blur)=\"onTouched()\" [id]=\"generateUniqueId(name)\" mode=\"currency\"\r\n [currency]=\"currencyConfig?.currency ?? 'USD'\" [locale]=\"currencyConfig?.locale ?? 'es-CO'\" [minFractionDigits]=\"2\" [maxFractionDigits]=\"2\" [readonly]=\"readonly\" [disabled]=\"readonly\" />\r\n }\r\n @case (inputTypesEnum.DATE) {\r\n <lib-disabled-container [disabled]=\"readonly\">\r\n <p-datepicker [formControl]=\"localControl\" [selectionMode]=\"dateConfig?.selectionMode || 'single'\"\r\n [maxDate]=\"dateConfig?.maxDate || null\" [minDate]=\"dateConfig?.minDate || null\" class=\"custom-datepicker\"\r\n appendTo=\"body\" />\r\n </lib-disabled-container>\r\n }\r\n @case (inputTypesEnum.TOGGLE) {\r\n <div class=\"flex justify-center items-center p-4\">\r\n <p-togglebutton [formControl]=\"localControl\" [onLabel]=\"toggleConfig?.onLabel || 'Si'\"\r\n [offLabel]=\"toggleConfig?.offLabel || 'No'\" class=\"custom-toggle\" />\r\n </div>\r\n }\r\n @case (inputTypesEnum.MULTISELECT) {\r\n <p-multiselect [filter]=\"true\" [options]=\"multiSelectConfig?.options\" [formControl]=\"localControl\"\r\n [optionLabel]=\"multiSelectConfig?.optionLabel ?? 'name'\" placeholder=\"\" [maxSelectedLabels]=\"3\"\r\n class=\"custom-multiselect\" appendTo=\"body\" />\r\n }\r\n @case (inputTypesEnum.SELECT) {\r\n <p-select [filter]=\"true\" [options]=\"selectConfig?.options\" [formControl]=\"localControl\"\r\n [optionLabel]=\"selectConfig?.optionLabel ?? 'name'\" placeholder=\"\" class=\"custom-select\"\r\n (onChange)=\"onSelectChange()\" appendTo=\"body\" [disabled]=\"readonly\" [readonly]=\"readonly\" [styleClass]=\"\r\n (localControl.invalid && (localControl.dirty || localControl.touched) ? 'border-red-500 focus:ring-red-500 ' : '') +\r\n (readonly ? 'bg-gray-100 cursor-not-allowed' : '')\r\n \" />\r\n }\r\n @case (inputTypesEnum.PASSWORD) {\r\n <div class=\"relative\">\r\n <input [readOnly]=\"readonly || false\" [id]=\"generateUniqueId(name)\" [type]=\"showPassword ? 'text' : 'password'\"\r\n autocomplete=\"new-password\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\"\r\n class=\"custom-password w-full px-3 py-2 border border-gray-300 dark:border-transparent rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 transition-all duration-200\"\r\n aria-describedby=\"password-help\" [formControl]=\"localControl\" />\r\n <button type=\"button\"\r\n class=\"custom-password-toggle absolute inset-y-0 right-0 flex items-center justify-center w-12 h-full text-gray-400 transition-colors duration-200 ease-in-out hover:text-gray-600 focus:outline-none focus:text-gray-600 active:text-gray-700 dark:text-gray-500 dark:hover:text-gray-300 dark:focus:text-gray-300\"\r\n (click)=\"togglePasswordVisibility()\" [attr.aria-label]=\"\r\n showPassword ? 'Ocultar contrase\u00F1a' : 'Mostrar contrase\u00F1a'\r\n \">\r\n <i class=\"fas text-lg transition-all duration-200 ease-in-out\" [ngClass]=\"{\r\n 'fa-solid fa-eye': !showPassword,\r\n 'fa-solid fa-eye-slash': showPassword,\r\n }\"></i>\r\n </button>\r\n </div>\r\n }\r\n @case (inputTypesEnum.CHECKBOX) {\r\n <div class=\"flex justify-center items-center p-4\">\r\n <input [id]=\"generateUniqueId(name)\" [readOnly]=\"readonly\" [type]=\"typeInput\" [checked]=\"localControl.value\"\r\n (change)=\"onCheckboxChange($event, localControl)\"\r\n class=\"custom-checkbox h-5 w-5 border-2 border-gray-300 dark:border-transparent rounded focus:ring-2 focus:ring-blue-500 focus:border-blue-500 bg-white dark:bg-gray-700 transition-all duration-200\"\r\n [formControl]=\"localControl\" />\r\n </div>\r\n }\r\n @case (inputTypesEnum.OTP) {\r\n <div class=\"flex justify-center items-center p-4\">\r\n <p-inputotp [id]=\"generateUniqueId(name)\" (onBlur)=\"onTouched()\" [mask]=\"controlData().otpConfig?.mask ?? false\"\r\n [length]=\"controlData().otpConfig?.length ?? 6\" [integerOnly]=\"controlData().otpConfig?.integerOnly ?? false\"\r\n class=\"custom-otp border-2 border-gray-300 dark:border-transparent rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 bg-white dark:bg-gray-700 transition-all duration-200\"\r\n [formControl]=\"localControl\" />\r\n </div>\r\n }\r\n @case (inputTypesEnum.SWITCH) {\r\n <div class=\"flex justify-center items-center p-4\">\r\n <p-toggleswitch [id]=\"generateUniqueId(name)\" [formControl]=\"localControl\"\r\n class=\"custom-switch border-2 border-gray-300 dark:border-transparent rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 bg-white dark:bg-gray-700 transition-all duration-200\"\r\n (change)=\"onCheckboxChange($event, localControl)\">\r\n <ng-template #handle let-checked=\"checked\">\r\n <span class=\"text-xs bg-gray-100 dark:bg-gray-600 text-gray-800 dark:text-gray-200 rounded-full px-1\">\r\n @if (checked) {\r\n Si\r\n }\r\n @else {\r\n No\r\n }\r\n </span>\r\n </ng-template>\r\n </p-toggleswitch>\r\n </div>\r\n }\r\n @case (inputTypesEnum.DECIMAL) {\r\n <p-inputnumber [formControl]=\"localControl\" (blur)=\"onTouched()\" [id]=\"generateUniqueId(name)\" mode=\"decimal\"\r\n [locale]=\"'es-CO'\" [minFractionDigits]=\"2\" [maxFractionDigits]=\"2\" [readonly]=\"readonly\" [disabled]=\"readonly\" />\r\n }\r\n @case (inputTypesEnum.TEXTAREA) {\r\n <textarea pTextarea [formControl]=\"localControl\" [rows]=\"textareaConfig?.rows ?? 3\"\r\n [cols]=\"textareaConfig?.cols ?? 30\" [autoResize]=\"true\" [variant]=\"textareaConfig?.variant ?? 'outlined'\"\r\n (blur)=\"onTouched()\" [id]=\"generateUniqueId(name)\" [readonly]=\"readonly\" autocomplete=\"off\" autocorrect=\"off\"\r\n autocapitalize=\"off\" spellcheck=\"false\"\r\n class=\"custom-textarea w-full px-3 py-2 border border-gray-300 dark:border-transparent rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100\"></textarea>\r\n }\r\n @default {\r\n <input [formControl]=\"localControl\" (blur)=\"onTouched()\" pInputText [id]=\"generateUniqueId(name)\" [type]=\"typeInput\"\r\n [readOnly]=\"readonly\" autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\" [ngClass]=\"{\r\n 'border-red-500 focus:ring-red-500':\r\n localControl.invalid &&\r\n (localControl.dirty || localControl.touched),\r\n 'bg-gray-100 cursor-not-allowed': readonly,\r\n }\"\r\n class=\"custom-input h-12 w-full px-3 py-2 border border-gray-300 dark:border-transparent rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100\" />\r\n }\r\n }\r\n </lib-disabled-container>\r\n\r\n</div>\r\n\r\n@if (localControl.invalid && (localControl.dirty || localControl.touched)) {\r\n<div class=\"custom-error mt-1 text-sm text-red-600 dark:text-red-400\">\r\n @if (localControl.errors?.[\"required\"]) {\r\n <span style=\"font-size: 0.675rem; font-style: italic; letter-spacing: 0.02em;\">{{\r\n 'El campo es requerido' }}</span>\r\n }\r\n @if (localControl.errors?.[\"min\"]) {\r\n <span style=\"font-size: 0.675rem; font-style: italic; letter-spacing: 0.02em;\">{{ 'El valor m\u00EDnimo es de ' + localControl.errors?.[\"min\"].min.toFixed(2) }}</span>\r\n }\r\n @if (localControl.errors?.[\"max\"]) {\r\n <span style=\"font-size: 0.675rem; font-style: italic; letter-spacing: 0.02em;\">{{ 'El valor m\u00E1ximo es de ' + localControl.errors?.[\"max\"].max.toFixed(2) }}</span>\r\n }\r\n @if (localControl.errors?.[\"minlength\"]) {\r\n <span style=\"font-size: 0.675rem; font-style: italic; letter-spacing: 0.02em;\">{{\r\n 'El largo m\u00EDnimo es de ' + localControl.errors?.[\"minlength\"].requiredLength\r\n }}</span>\r\n }\r\n @if (localControl.errors?.[\"maxlength\"]) {\r\n <span style=\"font-size: 0.675rem; font-style: italic; letter-spacing: 0.02em;\">{{\r\n 'El largo m\u00E1ximo es de ' + localControl.errors?.[\"maxlength\"].requiredLength\r\n }}</span>\r\n }\r\n @if (localControl.errors?.[\"email\"]) {\r\n <span style=\"font-size: 0.675rem; font-style: italic; letter-spacing: 0.02em;\">{{\r\n 'El correo electr\u00F3nico no es v\u00E1lido' }}</span>\r\n }\r\n @if (localControl.errors?.[\"pattern\"]) {\r\n <span style=\"font-size: 0.675rem; font-style: italic; letter-spacing: 0.02em;\">{{\r\n 'El formato no es v\u00E1lido' }}</span>\r\n }\r\n</div>\r\n}", styles: ["@charset \"UTF-8\";:host ::ng-deep p-datepicker>span>.p-inputtext{width:100%;border-radius:.5rem;outline:none;background-color:#f9fafb;height:44px;padding-right:2.5rem;color:#111827;transition:all .2s ease-in-out}:host ::ng-deep p-datepicker>.p-datepicker>.p-inputtext{background:transparent;color:#111827;height:44px;transition:all .2s ease-in-out}:host ::ng-deep .dark p-datepicker>.p-datepicker>.p-inputtext{background:transparent;background-color:#374151;color:#f3f4f6}:host ::ng-deep p-datepicker>span{width:100%;position:relative;display:inline-flex}:host ::ng-deep p-datepicker .p-datepicker-trigger{position:absolute!important;right:0!important;top:0!important;height:44px!important;width:2.5rem!important;background:transparent!important;border:none!important;box-shadow:none!important;color:#6b7280!important;display:flex!important;align-items:center!important;justify-content:center!important;z-index:1!important}:host ::ng-deep .dark p-datepicker .p-datepicker-trigger{color:#9ca3af!important}:host ::ng-deep p-datepicker .p-datepicker-trigger .p-button-icon{font-size:.875rem}:host ::ng-deep p-multiselect{border:1px solid #d1d5db;background:transparent;color:#111827;height:44px;width:100%;border-radius:.5rem;transition:all .2s ease-in-out}:host ::ng-deep .dark p-multiselect{background:transparent;color:#f3f4f6}:host ::ng-deep p-select{background:transparent;color:#111827;height:44px;width:100%;border-radius:.5rem;transition:all .2s ease-in-out}:host ::ng-deep .dark p-select{background:transparent;color:#f3f4f6}:host ::ng-deep p-select>.p-select-label{font-size:small;position:relative}:host ::ng-deep p-inputnumber{background:transparent;color:#111827;height:44px;width:100%;border:1px solid #d1d5db;border-radius:.5rem;transition:all .2s ease-in-out}:host ::ng-deep .dark p-inputnumber{background:transparent;color:#f3f4f6}:host-context(.dark) ::ng-deep .custom-datepicker>.p-inputwrapper>.p-inputtext,:host-context(.my-app-dark) ::ng-deep .custom-datepicker>.p-inputwrapper>.p-inputtext{color:#f3f4f6}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.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: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: IftaLabelModule }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: DatePickerModule }, { kind: "component", type: i2.DatePicker, selector: "p-datePicker, p-datepicker, p-date-picker", inputs: ["iconDisplay", "style", "styleClass", "inputStyle", "inputId", "name", "inputStyleClass", "placeholder", "ariaLabelledBy", "ariaLabel", "iconAriaLabel", "disabled", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "fluid", "icon", "appendTo", "readonlyInput", "shortYearCutoff", "monthNavigator", "yearNavigator", "hourFormat", "timeOnly", "stepHour", "stepMinute", "stepSecond", "showSeconds", "required", "showOnFocus", "showWeek", "startWeekFromFirstDayOfYear", "showClear", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autofocus", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "touchUI", "timeSeparator", "focusTrap", "showTransitionOptions", "hideTransitionOptions", "tabindex", "variant", "size", "minDate", "maxDate", "disabledDates", "disabledDays", "yearRange", "showTime", "responsiveOptions", "numberOfMonths", "firstDayOfWeek", "locale", "view", "defaultDate"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onClear", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }, { kind: "ngmodule", type: CheckboxModule }, { kind: "ngmodule", type: MultiSelectModule }, { kind: "component", type: i3.MultiSelect, selector: "p-multiSelect, p-multiselect, p-multi-select", inputs: ["id", "ariaLabel", "style", "styleClass", "panelStyle", "panelStyleClass", "inputId", "disabled", "fluid", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "variant", "appendTo", "dataKey", "name", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "chipIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "size", "showClear", "autofocus", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "defaultLabel", "placeholder", "options", "filterValue", "itemSize", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus", "highlightOnSelect"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i4.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "name", "style", "panelStyle", "styleClass", "panelStyleClass", "readonly", "required", "editable", "appendTo", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "variant", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "autoDisplayFirst", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "size", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "maxlength", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "fluid", "disabled", "itemSize", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "filterValue", "options"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: ToggleButtonModule }, { kind: "component", type: i5.ToggleButton, selector: "p-toggleButton, p-togglebutton, p-toggle-button", inputs: ["onLabel", "offLabel", "onIcon", "offIcon", "ariaLabel", "ariaLabelledBy", "disabled", "style", "styleClass", "inputId", "tabindex", "size", "iconPos", "autofocus", "allowEmpty"], outputs: ["onChange"] }, { kind: "ngmodule", type: InputOtpModule }, { kind: "component", type: i6.InputOtp, selector: "p-inputOtp, p-inputotp, p-input-otp", inputs: ["invalid", "disabled", "readonly", "variant", "tabindex", "length", "styleClass", "mask", "integerOnly", "autofocus", "size"], outputs: ["onChange", "onFocus", "onBlur"] }, { kind: "ngmodule", type: ToggleSwitchModule }, { kind: "component", type: i7.ToggleSwitch, selector: "p-toggleswitch, p-toggleSwitch, p-toggle-switch", inputs: ["style", "styleClass", "tabindex", "inputId", "name", "disabled", "readonly", "trueValue", "falseValue", "ariaLabel", "ariaLabelledBy", "autofocus"], outputs: ["onChange"] }, { kind: "ngmodule", type: InputNumberModule }, { kind: "component", type: i8.InputNumber, selector: "p-inputNumber, p-inputnumber, p-input-number", inputs: ["showButtons", "format", "buttonLayout", "inputId", "styleClass", "style", "placeholder", "size", "maxlength", "tabindex", "title", "ariaLabelledBy", "ariaDescribedBy", "ariaLabel", "ariaRequired", "name", "required", "autocomplete", "min", "max", "incrementButtonClass", "decrementButtonClass", "incrementButtonIcon", "decrementButtonIcon", "readonly", "step", "allowEmpty", "locale", "localeMatcher", "mode", "currency", "currencyDisplay", "useGrouping", "variant", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "inputStyle", "inputStyleClass", "showClear", "autofocus", "disabled", "fluid"], outputs: ["onInput", "onFocus", "onBlur", "onKeyDown", "onClear"] }, { kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i9.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["autoResize", "variant", "fluid", "pSize"], outputs: ["onResize"] }, { kind: "component", type: DisabledContainerComponent, selector: "lib-disabled-container", inputs: ["disabled"], outputs: ["disabledChange"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i10.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
181
+ }
182
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: CustomInputComponent, decorators: [{
183
+ type: Component,
184
+ args: [{ selector: 'lib-custom-input', imports: [
185
+ ReactiveFormsModule,
186
+ IftaLabelModule,
187
+ NgClass,
188
+ DatePickerModule,
189
+ CheckboxModule,
190
+ MultiSelectModule,
191
+ SelectModule,
192
+ ToggleButtonModule,
193
+ InputOtpModule,
194
+ ToggleSwitchModule,
195
+ InputNumberModule,
196
+ TextareaModule,
197
+ DisabledContainerComponent,
198
+ TooltipModule,
199
+ ], changeDetection: ChangeDetectionStrategy.OnPush, providers: [{
200
+ provide: NG_VALUE_ACCESSOR,
201
+ useExisting: forwardRef(() => CustomInputComponent),
202
+ multi: true
203
+ }], template: "@let localControl = controlData().control;\r\n@let placeholder = controlData().label || controlUpperName();\r\n@let name = controlData().controlName;\r\n@let typeInput = controlData().typeInput;\r\n@let readonly = controlData().readonly || false;\r\n@let dateConfig = controlData().dateConfig;\r\n@let multiSelectConfig = controlData().multiSelectConfig;\r\n@let selectConfig = controlData().selectConfig;\r\n@let toggleConfig = controlData().toggleConfig;\r\n@let textareaConfig = controlData().textareaConfig;\r\n@let currencyConfig = controlData().currencyConfig;\r\n<div class=\"flex flex-col gap-1 \">\r\n <lib-disabled-container [disabled]=\"readonly\">\r\n\r\n <p style=\"font-size: 12px; letter-spacing: 0.5px;\" class=\"text-sm text-gray-600 dark:text-gray-300 truncate\"\r\n [pTooltip]=\"placeholder\" tooltipPosition=\"top\" [showDelay]=\"300\">\r\n {{ placeholder }}\r\n </p>\r\n @switch (typeInput) {\r\n @case (inputTypesEnum.EMAIL) {\r\n <input \r\n [formControl]=\"localControl\" \r\n (blur)=\"onTouched()\" \r\n pInputText \r\n [id]=\"generateUniqueId(name)\" \r\n [name]=\"name\"\r\n [type]=\"typeInput\"\r\n [readOnly]=\"readonly\" \r\n autocomplete=\"email\" \r\n autocorrect=\"on\" \r\n autocapitalize=\"on\" \r\n spellcheck=\"true\" \r\n [ngClass]=\"{\r\n 'border-red-500 focus:ring-red-500':\r\n localControl.invalid &&\r\n (localControl.dirty || localControl.touched),\r\n 'bg-gray-100 cursor-not-allowed': readonly,\r\n }\"\r\n class=\"custom-input h-12 w-full px-3 py-2 border border-gray-300 dark:border-transparent rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100\" />\r\n }\r\n @case (inputTypesEnum.CURRENCY) {\r\n <p-inputnumber [formControl]=\"localControl\" (blur)=\"onTouched()\" [id]=\"generateUniqueId(name)\" mode=\"currency\"\r\n [currency]=\"currencyConfig?.currency ?? 'USD'\" [locale]=\"currencyConfig?.locale ?? 'es-CO'\" [minFractionDigits]=\"2\" [maxFractionDigits]=\"2\" [readonly]=\"readonly\" [disabled]=\"readonly\" />\r\n }\r\n @case (inputTypesEnum.DATE) {\r\n <lib-disabled-container [disabled]=\"readonly\">\r\n <p-datepicker [formControl]=\"localControl\" [selectionMode]=\"dateConfig?.selectionMode || 'single'\"\r\n [maxDate]=\"dateConfig?.maxDate || null\" [minDate]=\"dateConfig?.minDate || null\" class=\"custom-datepicker\"\r\n appendTo=\"body\" />\r\n </lib-disabled-container>\r\n }\r\n @case (inputTypesEnum.TOGGLE) {\r\n <div class=\"flex justify-center items-center p-4\">\r\n <p-togglebutton [formControl]=\"localControl\" [onLabel]=\"toggleConfig?.onLabel || 'Si'\"\r\n [offLabel]=\"toggleConfig?.offLabel || 'No'\" class=\"custom-toggle\" />\r\n </div>\r\n }\r\n @case (inputTypesEnum.MULTISELECT) {\r\n <p-multiselect [filter]=\"true\" [options]=\"multiSelectConfig?.options\" [formControl]=\"localControl\"\r\n [optionLabel]=\"multiSelectConfig?.optionLabel ?? 'name'\" placeholder=\"\" [maxSelectedLabels]=\"3\"\r\n class=\"custom-multiselect\" appendTo=\"body\" />\r\n }\r\n @case (inputTypesEnum.SELECT) {\r\n <p-select [filter]=\"true\" [options]=\"selectConfig?.options\" [formControl]=\"localControl\"\r\n [optionLabel]=\"selectConfig?.optionLabel ?? 'name'\" placeholder=\"\" class=\"custom-select\"\r\n (onChange)=\"onSelectChange()\" appendTo=\"body\" [disabled]=\"readonly\" [readonly]=\"readonly\" [styleClass]=\"\r\n (localControl.invalid && (localControl.dirty || localControl.touched) ? 'border-red-500 focus:ring-red-500 ' : '') +\r\n (readonly ? 'bg-gray-100 cursor-not-allowed' : '')\r\n \" />\r\n }\r\n @case (inputTypesEnum.PASSWORD) {\r\n <div class=\"relative\">\r\n <input [readOnly]=\"readonly || false\" [id]=\"generateUniqueId(name)\" [type]=\"showPassword ? 'text' : 'password'\"\r\n autocomplete=\"new-password\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\"\r\n class=\"custom-password w-full px-3 py-2 border border-gray-300 dark:border-transparent rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 transition-all duration-200\"\r\n aria-describedby=\"password-help\" [formControl]=\"localControl\" />\r\n <button type=\"button\"\r\n class=\"custom-password-toggle absolute inset-y-0 right-0 flex items-center justify-center w-12 h-full text-gray-400 transition-colors duration-200 ease-in-out hover:text-gray-600 focus:outline-none focus:text-gray-600 active:text-gray-700 dark:text-gray-500 dark:hover:text-gray-300 dark:focus:text-gray-300\"\r\n (click)=\"togglePasswordVisibility()\" [attr.aria-label]=\"\r\n showPassword ? 'Ocultar contrase\u00F1a' : 'Mostrar contrase\u00F1a'\r\n \">\r\n <i class=\"fas text-lg transition-all duration-200 ease-in-out\" [ngClass]=\"{\r\n 'fa-solid fa-eye': !showPassword,\r\n 'fa-solid fa-eye-slash': showPassword,\r\n }\"></i>\r\n </button>\r\n </div>\r\n }\r\n @case (inputTypesEnum.CHECKBOX) {\r\n <div class=\"flex justify-center items-center p-4\">\r\n <input [id]=\"generateUniqueId(name)\" [readOnly]=\"readonly\" [type]=\"typeInput\" [checked]=\"localControl.value\"\r\n (change)=\"onCheckboxChange($event, localControl)\"\r\n class=\"custom-checkbox h-5 w-5 border-2 border-gray-300 dark:border-transparent rounded focus:ring-2 focus:ring-blue-500 focus:border-blue-500 bg-white dark:bg-gray-700 transition-all duration-200\"\r\n [formControl]=\"localControl\" />\r\n </div>\r\n }\r\n @case (inputTypesEnum.OTP) {\r\n <div class=\"flex justify-center items-center p-4\">\r\n <p-inputotp [id]=\"generateUniqueId(name)\" (onBlur)=\"onTouched()\" [mask]=\"controlData().otpConfig?.mask ?? false\"\r\n [length]=\"controlData().otpConfig?.length ?? 6\" [integerOnly]=\"controlData().otpConfig?.integerOnly ?? false\"\r\n class=\"custom-otp border-2 border-gray-300 dark:border-transparent rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 bg-white dark:bg-gray-700 transition-all duration-200\"\r\n [formControl]=\"localControl\" />\r\n </div>\r\n }\r\n @case (inputTypesEnum.SWITCH) {\r\n <div class=\"flex justify-center items-center p-4\">\r\n <p-toggleswitch [id]=\"generateUniqueId(name)\" [formControl]=\"localControl\"\r\n class=\"custom-switch border-2 border-gray-300 dark:border-transparent rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 bg-white dark:bg-gray-700 transition-all duration-200\"\r\n (change)=\"onCheckboxChange($event, localControl)\">\r\n <ng-template #handle let-checked=\"checked\">\r\n <span class=\"text-xs bg-gray-100 dark:bg-gray-600 text-gray-800 dark:text-gray-200 rounded-full px-1\">\r\n @if (checked) {\r\n Si\r\n }\r\n @else {\r\n No\r\n }\r\n </span>\r\n </ng-template>\r\n </p-toggleswitch>\r\n </div>\r\n }\r\n @case (inputTypesEnum.DECIMAL) {\r\n <p-inputnumber [formControl]=\"localControl\" (blur)=\"onTouched()\" [id]=\"generateUniqueId(name)\" mode=\"decimal\"\r\n [locale]=\"'es-CO'\" [minFractionDigits]=\"2\" [maxFractionDigits]=\"2\" [readonly]=\"readonly\" [disabled]=\"readonly\" />\r\n }\r\n @case (inputTypesEnum.TEXTAREA) {\r\n <textarea pTextarea [formControl]=\"localControl\" [rows]=\"textareaConfig?.rows ?? 3\"\r\n [cols]=\"textareaConfig?.cols ?? 30\" [autoResize]=\"true\" [variant]=\"textareaConfig?.variant ?? 'outlined'\"\r\n (blur)=\"onTouched()\" [id]=\"generateUniqueId(name)\" [readonly]=\"readonly\" autocomplete=\"off\" autocorrect=\"off\"\r\n autocapitalize=\"off\" spellcheck=\"false\"\r\n class=\"custom-textarea w-full px-3 py-2 border border-gray-300 dark:border-transparent rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100\"></textarea>\r\n }\r\n @default {\r\n <input [formControl]=\"localControl\" (blur)=\"onTouched()\" pInputText [id]=\"generateUniqueId(name)\" [type]=\"typeInput\"\r\n [readOnly]=\"readonly\" autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\" [ngClass]=\"{\r\n 'border-red-500 focus:ring-red-500':\r\n localControl.invalid &&\r\n (localControl.dirty || localControl.touched),\r\n 'bg-gray-100 cursor-not-allowed': readonly,\r\n }\"\r\n class=\"custom-input h-12 w-full px-3 py-2 border border-gray-300 dark:border-transparent rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100\" />\r\n }\r\n }\r\n </lib-disabled-container>\r\n\r\n</div>\r\n\r\n@if (localControl.invalid && (localControl.dirty || localControl.touched)) {\r\n<div class=\"custom-error mt-1 text-sm text-red-600 dark:text-red-400\">\r\n @if (localControl.errors?.[\"required\"]) {\r\n <span style=\"font-size: 0.675rem; font-style: italic; letter-spacing: 0.02em;\">{{\r\n 'El campo es requerido' }}</span>\r\n }\r\n @if (localControl.errors?.[\"min\"]) {\r\n <span style=\"font-size: 0.675rem; font-style: italic; letter-spacing: 0.02em;\">{{ 'El valor m\u00EDnimo es de ' + localControl.errors?.[\"min\"].min.toFixed(2) }}</span>\r\n }\r\n @if (localControl.errors?.[\"max\"]) {\r\n <span style=\"font-size: 0.675rem; font-style: italic; letter-spacing: 0.02em;\">{{ 'El valor m\u00E1ximo es de ' + localControl.errors?.[\"max\"].max.toFixed(2) }}</span>\r\n }\r\n @if (localControl.errors?.[\"minlength\"]) {\r\n <span style=\"font-size: 0.675rem; font-style: italic; letter-spacing: 0.02em;\">{{\r\n 'El largo m\u00EDnimo es de ' + localControl.errors?.[\"minlength\"].requiredLength\r\n }}</span>\r\n }\r\n @if (localControl.errors?.[\"maxlength\"]) {\r\n <span style=\"font-size: 0.675rem; font-style: italic; letter-spacing: 0.02em;\">{{\r\n 'El largo m\u00E1ximo es de ' + localControl.errors?.[\"maxlength\"].requiredLength\r\n }}</span>\r\n }\r\n @if (localControl.errors?.[\"email\"]) {\r\n <span style=\"font-size: 0.675rem; font-style: italic; letter-spacing: 0.02em;\">{{\r\n 'El correo electr\u00F3nico no es v\u00E1lido' }}</span>\r\n }\r\n @if (localControl.errors?.[\"pattern\"]) {\r\n <span style=\"font-size: 0.675rem; font-style: italic; letter-spacing: 0.02em;\">{{\r\n 'El formato no es v\u00E1lido' }}</span>\r\n }\r\n</div>\r\n}", styles: ["@charset \"UTF-8\";:host ::ng-deep p-datepicker>span>.p-inputtext{width:100%;border-radius:.5rem;outline:none;background-color:#f9fafb;height:44px;padding-right:2.5rem;color:#111827;transition:all .2s ease-in-out}:host ::ng-deep p-datepicker>.p-datepicker>.p-inputtext{background:transparent;color:#111827;height:44px;transition:all .2s ease-in-out}:host ::ng-deep .dark p-datepicker>.p-datepicker>.p-inputtext{background:transparent;background-color:#374151;color:#f3f4f6}:host ::ng-deep p-datepicker>span{width:100%;position:relative;display:inline-flex}:host ::ng-deep p-datepicker .p-datepicker-trigger{position:absolute!important;right:0!important;top:0!important;height:44px!important;width:2.5rem!important;background:transparent!important;border:none!important;box-shadow:none!important;color:#6b7280!important;display:flex!important;align-items:center!important;justify-content:center!important;z-index:1!important}:host ::ng-deep .dark p-datepicker .p-datepicker-trigger{color:#9ca3af!important}:host ::ng-deep p-datepicker .p-datepicker-trigger .p-button-icon{font-size:.875rem}:host ::ng-deep p-multiselect{border:1px solid #d1d5db;background:transparent;color:#111827;height:44px;width:100%;border-radius:.5rem;transition:all .2s ease-in-out}:host ::ng-deep .dark p-multiselect{background:transparent;color:#f3f4f6}:host ::ng-deep p-select{background:transparent;color:#111827;height:44px;width:100%;border-radius:.5rem;transition:all .2s ease-in-out}:host ::ng-deep .dark p-select{background:transparent;color:#f3f4f6}:host ::ng-deep p-select>.p-select-label{font-size:small;position:relative}:host ::ng-deep p-inputnumber{background:transparent;color:#111827;height:44px;width:100%;border:1px solid #d1d5db;border-radius:.5rem;transition:all .2s ease-in-out}:host ::ng-deep .dark p-inputnumber{background:transparent;color:#f3f4f6}:host-context(.dark) ::ng-deep .custom-datepicker>.p-inputwrapper>.p-inputtext,:host-context(.my-app-dark) ::ng-deep .custom-datepicker>.p-inputwrapper>.p-inputtext{color:#f3f4f6}\n"] }]
204
+ }], ctorParameters: () => [] });
205
+
206
+ class FormChildComponent {
207
+ controlsData = input.required();
208
+ formGroup = input.required();
209
+ formSubmit = output();
43
210
  constructor() {
44
- console.log('ButtonComponent constructor');
45
211
  }
46
- ngOnInit() {
47
- console.log('ButtonComponent ngOnInit');
48
- }
49
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: ButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
50
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: ButtonComponent, isStandalone: true, selector: "lib-button", inputs: { variant: "variant", disabled: "disabled" }, outputs: { onClick: "onClick" }, ngImport: i0, template: `
51
- <button
52
- [class]="'lib-button ' + (variant || 'primary')"
53
- [disabled]="disabled"
54
- (click)="onClick.emit()">
55
- <ng-content></ng-content>
56
- </button>
57
- `, isInline: true, styles: [".lib-button{padding:8px 16px;border:none;border-radius:4px;cursor:pointer;font-size:14px;transition:opacity .2s ease}.lib-button.primary{background-color:#007bff;color:#fff}.lib-button.primary:hover:not(:disabled){background-color:#0056b3}.lib-button.secondary{background-color:#6c757d;color:#fff}.lib-button.secondary:hover:not(:disabled){background-color:#545b62}.lib-button:disabled{opacity:.6;cursor:not-allowed}\n"] });
58
- }
59
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: ButtonComponent, decorators: [{
212
+ submit() {
213
+ this.formSubmit.emit(this.formGroup());
214
+ }
215
+ onSelectChange(controlConfig) {
216
+ controlConfig.selectConfig?.change?.(controlConfig);
217
+ }
218
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: FormChildComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
219
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: FormChildComponent, isStandalone: true, selector: "lib-form-child", inputs: { controlsData: { classPropertyName: "controlsData", publicName: "controlsData", isSignal: true, isRequired: true, transformFunction: null }, formGroup: { classPropertyName: "formGroup", publicName: "formGroup", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { formSubmit: "formSubmit" }, ngImport: i0, template: "@let controls = controlsData();\r\n\r\n<form\r\n [formGroup]=\"formGroup()\"\r\n (submit)=\"submit()\"\r\n autocomplete=\"off\"\r\n class=\"grid grid-cols-12 gap-3\"\r\n>\r\n @for (controlData of controls; track controlData.controlName) {\r\n <div\r\n class=\"flex flex-col w-full\"\r\n [ngClass]=\"{\r\n 'col-span-1': !controlData.colSpan,\r\n 'col-span-2': controlData.colSpan === 2,\r\n 'col-span-3': controlData.colSpan === 3,\r\n 'col-span-4': controlData.colSpan === 4,\r\n 'col-span-5': controlData.colSpan === 5,\r\n 'col-span-6': controlData.colSpan === 6,\r\n 'col-span-7': controlData.colSpan === 7,\r\n 'col-span-8': controlData.colSpan === 8,\r\n 'col-span-9': controlData.colSpan === 9,\r\n 'col-span-10': controlData.colSpan === 10,\r\n 'col-span-11': controlData.colSpan === 11,\r\n 'col-span-12': controlData.colSpan === 12,\r\n }\"\r\n >\r\n <lib-custom-input\r\n [id]=\"controlData.controlName\"\r\n [controlData]=\"controlData\"\r\n [formControlName]=\"controlData.controlName\"\r\n class=\"w-full\"\r\n (output)=\"onSelectChange($event)\"\r\n >\r\n </lib-custom-input>\r\n </div>\r\n }\r\n</form>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: CustomInputComponent, selector: "lib-custom-input", inputs: ["controlData"], outputs: ["output"] }] });
220
+ }
221
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: FormChildComponent, decorators: [{
60
222
  type: Component,
61
- args: [{ selector: 'lib-button', standalone: true, imports: [], template: `
62
- <button
63
- [class]="'lib-button ' + (variant || 'primary')"
64
- [disabled]="disabled"
65
- (click)="onClick.emit()">
66
- <ng-content></ng-content>
67
- </button>
68
- `, styles: [".lib-button{padding:8px 16px;border:none;border-radius:4px;cursor:pointer;font-size:14px;transition:opacity .2s ease}.lib-button.primary{background-color:#007bff;color:#fff}.lib-button.primary:hover:not(:disabled){background-color:#0056b3}.lib-button.secondary{background-color:#6c757d;color:#fff}.lib-button.secondary:hover:not(:disabled){background-color:#545b62}.lib-button:disabled{opacity:.6;cursor:not-allowed}\n"] }]
69
- }], ctorParameters: () => [], propDecorators: { variant: [{
70
- type: Input
71
- }], disabled: [{
72
- type: Input
73
- }], onClick: [{
74
- type: Output
75
- }] } });
223
+ args: [{ selector: 'lib-form-child', imports: [
224
+ ReactiveFormsModule,
225
+ CommonModule,
226
+ CustomInputComponent
227
+ ], template: "@let controls = controlsData();\r\n\r\n<form\r\n [formGroup]=\"formGroup()\"\r\n (submit)=\"submit()\"\r\n autocomplete=\"off\"\r\n class=\"grid grid-cols-12 gap-3\"\r\n>\r\n @for (controlData of controls; track controlData.controlName) {\r\n <div\r\n class=\"flex flex-col w-full\"\r\n [ngClass]=\"{\r\n 'col-span-1': !controlData.colSpan,\r\n 'col-span-2': controlData.colSpan === 2,\r\n 'col-span-3': controlData.colSpan === 3,\r\n 'col-span-4': controlData.colSpan === 4,\r\n 'col-span-5': controlData.colSpan === 5,\r\n 'col-span-6': controlData.colSpan === 6,\r\n 'col-span-7': controlData.colSpan === 7,\r\n 'col-span-8': controlData.colSpan === 8,\r\n 'col-span-9': controlData.colSpan === 9,\r\n 'col-span-10': controlData.colSpan === 10,\r\n 'col-span-11': controlData.colSpan === 11,\r\n 'col-span-12': controlData.colSpan === 12,\r\n }\"\r\n >\r\n <lib-custom-input\r\n [id]=\"controlData.controlName\"\r\n [controlData]=\"controlData\"\r\n [formControlName]=\"controlData.controlName\"\r\n class=\"w-full\"\r\n (output)=\"onSelectChange($event)\"\r\n >\r\n </lib-custom-input>\r\n </div>\r\n }\r\n</form>\r\n" }]
228
+ }], ctorParameters: () => [] });
76
229
 
77
- class EmptyMessageComponent {
78
- message = input('NO DATA AVAILABLE');
79
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: EmptyMessageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
80
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.17", type: EmptyMessageComponent, isStandalone: true, selector: "lib-empty-message", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
81
- <div class="empty-message">
82
- <p class="empty-message-text">{{ message() }}</p>
83
- </div>
84
- `, isInline: true, styles: [".empty-message{display:flex;align-items:center;justify-content:center;padding:2rem}.empty-message-text{text-align:center;color:#6c757d;margin:0;font-size:1rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
230
+ class HttpMessageComponent {
231
+ httpMessage = model();
232
+ clearMessage() {
233
+ this.httpMessage.set(undefined);
234
+ }
235
+ get isError() {
236
+ const message = this.httpMessage();
237
+ return message?.type === 'error';
238
+ }
239
+ get isSuccess() {
240
+ const message = this.httpMessage();
241
+ return message?.type === 'success';
242
+ }
243
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: HttpMessageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
244
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: HttpMessageComponent, isStandalone: true, selector: "lib-http-message", inputs: { httpMessage: { classPropertyName: "httpMessage", publicName: "httpMessage", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { httpMessage: "httpMessageChange" }, ngImport: i0, template: "@if (httpMessage()) {\r\n @if (isError) {\r\n <div class=\"group relative mt-3 p-3 rounded-lg bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 transition-all duration-200 hover:shadow-md\">\r\n <div class=\"flex items-start gap-2\">\r\n <svg class=\"w-5 h-5 text-red-500 dark:text-red-400 flex-shrink-0 mt-0.5\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\r\n <path fill-rule=\"evenodd\" d=\"M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z\" clip-rule=\"evenodd\" />\r\n </svg>\r\n <p class=\"flex-1 text-red-700 dark:text-red-300 text-sm font-medium leading-relaxed\">\r\n {{ httpMessage()?.message }}\r\n </p>\r\n <button\r\n type=\"button\"\r\n (click)=\"clearMessage()\"\r\n class=\"opacity-0 group-hover:opacity-100 transition-opacity duration-200 text-red-500 dark:text-red-400 hover:text-red-700 dark:hover:text-red-200 p-1 rounded hover:bg-red-100 dark:hover:bg-red-800/30\"\r\n aria-label=\"Cerrar mensaje de error\"\r\n >\r\n <svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\r\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\" />\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n }\r\n @if (isSuccess) {\r\n <div class=\"group relative mt-3 p-3 rounded-lg bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 transition-all duration-200 hover:shadow-md\">\r\n <div class=\"flex items-start gap-2\">\r\n <svg class=\"w-5 h-5 text-green-500 dark:text-green-400 flex-shrink-0 mt-0.5\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\r\n <path fill-rule=\"evenodd\" d=\"M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z\" clip-rule=\"evenodd\" />\r\n </svg>\r\n <p class=\"flex-1 text-green-700 dark:text-green-300 text-sm font-medium leading-relaxed\">\r\n {{ httpMessage()?.message }}\r\n </p>\r\n <button\r\n type=\"button\"\r\n (click)=\"clearMessage()\"\r\n class=\"opacity-0 group-hover:opacity-100 transition-opacity duration-200 text-green-500 dark:text-green-400 hover:text-green-700 dark:hover:text-green-200 p-1 rounded hover:bg-green-100 dark:hover:bg-green-800/30\"\r\n aria-label=\"Cerrar mensaje de \u00E9xito\"\r\n >\r\n <svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\r\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\" />\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n }\r\n}\r\n", styles: [""] });
85
245
  }
86
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: EmptyMessageComponent, decorators: [{
246
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: HttpMessageComponent, decorators: [{
87
247
  type: Component,
88
- args: [{ selector: 'lib-empty-message', standalone: true, imports: [CommonModule], template: `
89
- <div class="empty-message">
90
- <p class="empty-message-text">{{ message() }}</p>
91
- </div>
92
- `, styles: [".empty-message{display:flex;align-items:center;justify-content:center;padding:2rem}.empty-message-text{text-align:center;color:#6c757d;margin:0;font-size:1rem}\n"] }]
248
+ args: [{ selector: 'lib-http-message', imports: [], template: "@if (httpMessage()) {\r\n @if (isError) {\r\n <div class=\"group relative mt-3 p-3 rounded-lg bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 transition-all duration-200 hover:shadow-md\">\r\n <div class=\"flex items-start gap-2\">\r\n <svg class=\"w-5 h-5 text-red-500 dark:text-red-400 flex-shrink-0 mt-0.5\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\r\n <path fill-rule=\"evenodd\" d=\"M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z\" clip-rule=\"evenodd\" />\r\n </svg>\r\n <p class=\"flex-1 text-red-700 dark:text-red-300 text-sm font-medium leading-relaxed\">\r\n {{ httpMessage()?.message }}\r\n </p>\r\n <button\r\n type=\"button\"\r\n (click)=\"clearMessage()\"\r\n class=\"opacity-0 group-hover:opacity-100 transition-opacity duration-200 text-red-500 dark:text-red-400 hover:text-red-700 dark:hover:text-red-200 p-1 rounded hover:bg-red-100 dark:hover:bg-red-800/30\"\r\n aria-label=\"Cerrar mensaje de error\"\r\n >\r\n <svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\r\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\" />\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n }\r\n @if (isSuccess) {\r\n <div class=\"group relative mt-3 p-3 rounded-lg bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 transition-all duration-200 hover:shadow-md\">\r\n <div class=\"flex items-start gap-2\">\r\n <svg class=\"w-5 h-5 text-green-500 dark:text-green-400 flex-shrink-0 mt-0.5\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\r\n <path fill-rule=\"evenodd\" d=\"M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z\" clip-rule=\"evenodd\" />\r\n </svg>\r\n <p class=\"flex-1 text-green-700 dark:text-green-300 text-sm font-medium leading-relaxed\">\r\n {{ httpMessage()?.message }}\r\n </p>\r\n <button\r\n type=\"button\"\r\n (click)=\"clearMessage()\"\r\n class=\"opacity-0 group-hover:opacity-100 transition-opacity duration-200 text-green-500 dark:text-green-400 hover:text-green-700 dark:hover:text-green-200 p-1 rounded hover:bg-green-100 dark:hover:bg-green-800/30\"\r\n aria-label=\"Cerrar mensaje de \u00E9xito\"\r\n >\r\n <svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\r\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\" />\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n }\r\n}\r\n" }]
93
249
  }] });
94
250
 
251
+ class FormComponent {
252
+ formGroup = model.required();
253
+ controls = input.required();
254
+ formConfig = input();
255
+ httpMessage = model();
256
+ formSubmit = output();
257
+ formChanges = output();
258
+ formChangesDebounced = output();
259
+ constructor() {
260
+ effect(() => {
261
+ const controls = this.controls();
262
+ const controlsNames = this.controls().map((controlConfig) => controlConfig.controlName);
263
+ const controlsToDelete = Object.keys(this.formGroup().controls).filter(control => !controlsNames.includes(control));
264
+ controls.forEach((controlData) => {
265
+ this.formGroup.update((formGroup) => {
266
+ if (formGroup.contains(controlData.controlName)) {
267
+ formGroup.setControl(controlData.controlName, controlData.control);
268
+ }
269
+ else {
270
+ formGroup.addControl(controlData.controlName, controlData.control);
271
+ }
272
+ controlsToDelete.forEach(controlName => {
273
+ formGroup.removeControl(controlName);
274
+ });
275
+ return formGroup;
276
+ });
277
+ });
278
+ });
279
+ effect(() => {
280
+ const controlsDataTypeSelect = this.controls().filter((controlData) => controlData.typeInput === ETypeInput.SELECT);
281
+ controlsDataTypeSelect.forEach((controlData) => {
282
+ const control = this.formGroup().get(controlData.controlName);
283
+ const controlValue = control?.value;
284
+ if (controlValue) {
285
+ const options = controlData.selectConfig?.options ?? [];
286
+ const optionSelected = options.find((option) => {
287
+ return option.code === controlValue.code;
288
+ });
289
+ if (optionSelected) {
290
+ control?.setValue(optionSelected);
291
+ }
292
+ }
293
+ });
294
+ });
295
+ effect(() => {
296
+ this.formGroup().valueChanges.subscribe(() => {
297
+ this.formChanges.emit(this.formGroup());
298
+ });
299
+ });
300
+ const fg$ = toObservable(this.formGroup);
301
+ fg$.pipe(switchMap((fg) => fg.valueChanges.pipe(debounceTime(650), filter(() => this.anyInteracted(fg)), map(() => fg))), takeUntilDestroyed())
302
+ .subscribe(() => this.formChangesDebounced.emit(this.formGroup()));
303
+ }
304
+ anyInteracted(formGroup) {
305
+ return Object.values(formGroup.controls).some(control => control.touched || control.dirty);
306
+ }
307
+ submit(formGroup) {
308
+ this.formSubmit.emit(formGroup);
309
+ }
310
+ clearHttpMessage() {
311
+ this.httpMessage.set(undefined);
312
+ }
313
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: FormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
314
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: FormComponent, isStandalone: true, selector: "lib-form", inputs: { formGroup: { classPropertyName: "formGroup", publicName: "formGroup", isSignal: true, isRequired: true, transformFunction: null }, controls: { classPropertyName: "controls", publicName: "controls", isSignal: true, isRequired: true, transformFunction: null }, formConfig: { classPropertyName: "formConfig", publicName: "formConfig", isSignal: true, isRequired: false, transformFunction: null }, httpMessage: { classPropertyName: "httpMessage", publicName: "httpMessage", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { formGroup: "formGroupChange", httpMessage: "httpMessageChange", formSubmit: "formSubmit", formChanges: "formChanges", formChangesDebounced: "formChangesDebounced" }, ngImport: i0, template: "<div class=\"w-full p-2 rounded-lg\" [style.backgroundColor]=\"formConfig()?.backgroundColor || 'transparent'\">\r\n <lib-form-child [controlsData]=\"controls()\" [formGroup]=\"formGroup()\" (formSubmit)=\"submit($event)\">\r\n </lib-form-child>\r\n @if (httpMessage()) {\r\n <lib-http-message [(httpMessage)]=\"httpMessage\"></lib-http-message>\r\n }\r\n</div>", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: FormChildComponent, selector: "lib-form-child", inputs: ["controlsData", "formGroup"], outputs: ["formSubmit"] }, { kind: "component", type: HttpMessageComponent, selector: "lib-http-message", inputs: ["httpMessage"], outputs: ["httpMessageChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
315
+ }
316
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: FormComponent, decorators: [{
317
+ type: Component,
318
+ args: [{ selector: 'lib-form', imports: [
319
+ ReactiveFormsModule,
320
+ FormChildComponent,
321
+ HttpMessageComponent
322
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"w-full p-2 rounded-lg\" [style.backgroundColor]=\"formConfig()?.backgroundColor || 'transparent'\">\r\n <lib-form-child [controlsData]=\"controls()\" [formGroup]=\"formGroup()\" (formSubmit)=\"submit($event)\">\r\n </lib-form-child>\r\n @if (httpMessage()) {\r\n <lib-http-message [(httpMessage)]=\"httpMessage\"></lib-http-message>\r\n }\r\n</div>" }]
323
+ }], ctorParameters: () => [] });
324
+
325
+ class InlineInputComponent {
326
+ config = input({ typeInput: ETypeInput.TEXT });
327
+ value = model(null);
328
+ outputValue = output();
329
+ outputBlur = output();
330
+ outputDebounced = output();
331
+ // Capturar templates proyectados desde el componente padre
332
+ templates;
333
+ // Para el manejo de chips
334
+ chips = [];
335
+ currentInput = '';
336
+ showDuplicateMessage = false;
337
+ duplicateChips = [];
338
+ duplicateMessageTimer = null;
339
+ constructor() {
340
+ effect(() => {
341
+ this.outputValue.emit(this.value());
342
+ });
343
+ const value$ = toObservable(this.value);
344
+ value$
345
+ .pipe(debounceTime(300), // <- adjust ms here
346
+ distinctUntilChanged(), // avoid repeats for same value
347
+ takeUntilDestroyed() // auto-cleanup on destroy
348
+ )
349
+ .subscribe(v => this.outputDebounced.emit(v));
350
+ effect(() => {
351
+ this.valueSelect.update((_prev) => {
352
+ const options = this.config()?.selectConfig?.options;
353
+ const currentValue = this.value();
354
+ if (this.isSelection(currentValue))
355
+ return currentValue;
356
+ if (currentValue === null || currentValue === undefined)
357
+ return undefined;
358
+ return options?.find(option => option.code === currentValue);
359
+ });
360
+ });
361
+ }
362
+ ngOnInit() {
363
+ }
364
+ onChange = () => { };
365
+ onTouched = () => { };
366
+ writeValue(value) {
367
+ this.value.set(value);
368
+ // Si es tipo CHIPS, inicializar los chips desde el valor
369
+ if (this.type === ETypeInput.CHIPS && typeof value === 'string') {
370
+ this.chips = value ? value.split(' ').filter(chip => chip.trim() !== '') : [];
371
+ }
372
+ }
373
+ registerOnChange(fn) {
374
+ this.onChange = fn;
375
+ }
376
+ registerOnTouched(fn) {
377
+ this.onTouched = fn;
378
+ }
379
+ onChangeValue(value) {
380
+ this.value.set(value);
381
+ this.onChange(value);
382
+ }
383
+ onBlur() {
384
+ this.onTouched();
385
+ this.outputBlur.emit(this.value());
386
+ }
387
+ /**
388
+ * Maneja eventos de teclado para prevenir la navegación de PrimeNG Table
389
+ * cuando se usan las flechas izquierda/derecha dentro del input
390
+ */
391
+ onKeyDown(event) {
392
+ // Verificar si son teclas de flecha izquierda o derecha
393
+ if (event.key === 'ArrowLeft' || event.key === 'ArrowRight') {
394
+ // Detener la propagación del evento hacia el table
395
+ event.stopPropagation();
396
+ }
397
+ }
398
+ isSelection(value) {
399
+ return !!value && typeof value === 'object' && 'code' in value && 'name' in value;
400
+ }
401
+ valueSelect = signal(undefined);
402
+ setValueSelect(value) {
403
+ this.valueSelect.set(value);
404
+ }
405
+ get type() {
406
+ return this.config()?.typeInput ?? ETypeInput.TEXT;
407
+ }
408
+ get ETypeInput() {
409
+ return ETypeInput;
410
+ }
411
+ get duplicatesText() {
412
+ return this.duplicateChips.join(', ');
413
+ }
414
+ get currency() {
415
+ return this.config()?.currencyConfig?.currency ?? 'COP';
416
+ }
417
+ get locale() {
418
+ return this.config()?.currencyConfig?.locale ?? 'es-CO';
419
+ }
420
+ get minFractionDigits() {
421
+ return this.config()?.currencyConfig?.minFractionDigits ?? 2;
422
+ }
423
+ get maxFractionDigits() {
424
+ return this.config()?.currencyConfig?.maxFractionDigits ?? 2;
425
+ }
426
+ knobValueInput = computed(() => {
427
+ let response = this.value();
428
+ const knobConfig = this.config()?.knobConfig ?? { min: 0, max: 100, step: 1 };
429
+ response = parseInt(this.value()) ?? 0;
430
+ if (response < (knobConfig?.min ?? 0)) {
431
+ response = knobConfig.min ?? 0;
432
+ }
433
+ if (response > (knobConfig?.max ?? 100)) {
434
+ response = knobConfig.max ?? 100;
435
+ }
436
+ return response;
437
+ });
438
+ knobValueTemplate = computed(() => {
439
+ return this.config()?.knobConfig?.valueTemplate ?? '';
440
+ });
441
+ // Métodos para manejo de chips
442
+ onChipInputChange(event) {
443
+ const target = event.target;
444
+ this.currentInput = target.value;
445
+ }
446
+ onChipKeydown(event) {
447
+ if (event.key === ' ' || event.key === 'Enter') {
448
+ event.preventDefault();
449
+ this.addChip();
450
+ }
451
+ else if (event.key === 'Backspace' && this.currentInput === '' && this.chips.length > 0) {
452
+ // Si no hay texto y hay chips, eliminar el último chip
453
+ this.removeChip(this.chips.length - 1);
454
+ }
455
+ // No interceptar las flechas aquí ya que se maneja en onKeyDown
456
+ }
457
+ onChipPaste(event) {
458
+ event.preventDefault();
459
+ const pastedText = event.clipboardData?.getData('text') || '';
460
+ this.processPastedText(pastedText);
461
+ }
462
+ addChip() {
463
+ const trimmedValue = this.currentInput.trim();
464
+ if (trimmedValue) {
465
+ if (this.chips.includes(trimmedValue)) {
466
+ // Mostrar mensaje de duplicado con el chip específico
467
+ this.duplicateChips = [trimmedValue];
468
+ this.showDuplicateAlert();
469
+ }
470
+ else {
471
+ this.chips.push(trimmedValue);
472
+ this.currentInput = '';
473
+ this.updateChipsValue();
474
+ this.hideDuplicateAlert();
475
+ }
476
+ }
477
+ }
478
+ removeChip(index) {
479
+ this.chips.splice(index, 1);
480
+ this.updateChipsValue();
481
+ }
482
+ updateChipsValue() {
483
+ const chipsValue = this.chips.join(' ');
484
+ this.value.set(chipsValue);
485
+ this.onChange(chipsValue);
486
+ }
487
+ showDuplicateAlert() {
488
+ this.showDuplicateMessage = true;
489
+ // Limpiar timer anterior si existe
490
+ if (this.duplicateMessageTimer) {
491
+ clearTimeout(this.duplicateMessageTimer);
492
+ }
493
+ // Ocultar mensaje después de 3 segundos
494
+ this.duplicateMessageTimer = setTimeout(() => {
495
+ this.hideDuplicateAlert();
496
+ }, 3000);
497
+ }
498
+ hideDuplicateAlert() {
499
+ this.showDuplicateMessage = false;
500
+ this.duplicateChips = [];
501
+ if (this.duplicateMessageTimer) {
502
+ clearTimeout(this.duplicateMessageTimer);
503
+ this.duplicateMessageTimer = null;
504
+ }
505
+ }
506
+ processPastedText(text) {
507
+ // Dividir el texto por espacios y filtrar elementos vacíos
508
+ const newChips = text
509
+ .split(/\s+/) // Dividir por uno o más espacios
510
+ .map(chip => chip.trim()) // Limpiar espacios en cada elemento
511
+ .filter(chip => chip !== ''); // Filtrar elementos vacíos
512
+ const foundDuplicates = [];
513
+ let addedChips = 0;
514
+ // Agregar cada chip nuevo y recopilar duplicados
515
+ newChips.forEach(chipText => {
516
+ if (!this.chips.includes(chipText)) {
517
+ this.chips.push(chipText);
518
+ addedChips++;
519
+ }
520
+ else {
521
+ // Solo agregar a duplicados si no está ya en la lista
522
+ if (!foundDuplicates.includes(chipText)) {
523
+ foundDuplicates.push(chipText);
524
+ }
525
+ }
526
+ });
527
+ // Limpiar el input actual
528
+ this.currentInput = '';
529
+ // Actualizar el valor si se agregaron chips
530
+ if (addedChips > 0) {
531
+ this.updateChipsValue();
532
+ }
533
+ // Mostrar alerta si hubo duplicados
534
+ if (foundDuplicates.length > 0) {
535
+ this.duplicateChips = foundDuplicates;
536
+ this.showDuplicateAlert();
537
+ }
538
+ else {
539
+ this.hideDuplicateAlert();
540
+ }
541
+ }
542
+ /**
543
+ * Método público para establecer chips desde un array externo
544
+ * @param chipsArray Array de strings que representan las chips
545
+ */
546
+ setChipsFromArray(chipsArray) {
547
+ if (!Array.isArray(chipsArray)) {
548
+ console.warn('setChipsFromArray: El parámetro debe ser un array de strings');
549
+ return;
550
+ }
551
+ // Filtrar elementos válidos (strings no vacíos)
552
+ const validChips = chipsArray
553
+ .filter(chip => typeof chip === 'string' && chip.trim() !== '')
554
+ .map(chip => chip.trim());
555
+ // Actualizar el array de chips
556
+ this.chips = [...validChips];
557
+ // Limpiar el input actual
558
+ this.currentInput = '';
559
+ // Actualizar el valor del componente
560
+ this.updateChipsValue();
561
+ // Ocultar cualquier mensaje de duplicado
562
+ this.hideDuplicateAlert();
563
+ }
564
+ /**
565
+ * Método público para obtener las chips actuales como array
566
+ * @returns Array de strings con las chips actuales
567
+ */
568
+ getChipsAsArray() {
569
+ return [...this.chips];
570
+ }
571
+ /**
572
+ * Método público para limpiar todas las chips
573
+ */
574
+ clearAllChips() {
575
+ this.chips = [];
576
+ this.currentInput = '';
577
+ this.updateChipsValue();
578
+ this.hideDuplicateAlert();
579
+ }
580
+ /**
581
+ * Método público para agregar múltiples chips desde un array
582
+ * Evita duplicados y muestra mensajes de alerta si es necesario
583
+ * @param chipsArray Array de strings a agregar
584
+ */
585
+ addChipsFromArray(chipsArray) {
586
+ if (!Array.isArray(chipsArray)) {
587
+ console.warn('addChipsFromArray: El parámetro debe ser un array de strings');
588
+ return;
589
+ }
590
+ // Filtrar elementos válidos
591
+ const validChips = chipsArray
592
+ .filter(chip => typeof chip === 'string' && chip.trim() !== '')
593
+ .map(chip => chip.trim());
594
+ const foundDuplicates = [];
595
+ let addedChips = 0;
596
+ // Agregar cada chip nuevo y recopilar duplicados
597
+ validChips.forEach(chipText => {
598
+ if (!this.chips.includes(chipText)) {
599
+ this.chips.push(chipText);
600
+ addedChips++;
601
+ }
602
+ else {
603
+ // Solo agregar a duplicados si no está ya en la lista
604
+ if (!foundDuplicates.includes(chipText)) {
605
+ foundDuplicates.push(chipText);
606
+ }
607
+ }
608
+ });
609
+ // Actualizar el valor si se agregaron chips
610
+ if (addedChips > 0) {
611
+ this.updateChipsValue();
612
+ }
613
+ // Mostrar alerta si hubo duplicados
614
+ if (foundDuplicates.length > 0) {
615
+ this.duplicateChips = foundDuplicates;
616
+ this.showDuplicateAlert();
617
+ }
618
+ else {
619
+ this.hideDuplicateAlert();
620
+ }
621
+ }
622
+ // Limpiar timer al destruir el componente
623
+ ngOnDestroy() {
624
+ if (this.duplicateMessageTimer) {
625
+ clearTimeout(this.duplicateMessageTimer);
626
+ }
627
+ }
628
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: InlineInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
629
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: InlineInputComponent, isStandalone: true, selector: "lib-inline-input", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", outputValue: "outputValue", outputBlur: "outputBlur", outputDebounced: "outputDebounced" }, providers: [
630
+ {
631
+ provide: NG_VALUE_ACCESSOR,
632
+ useExisting: forwardRef(() => InlineInputComponent),
633
+ multi: true
634
+ }
635
+ ], queries: [{ propertyName: "templates", predicate: PrimeTemplate }], ngImport: i0, template: "@let valueInput = value();\r\n@let isDisabled = config().isDisabled ?? false;\r\n@let knobConfig = config().knobConfig;\r\n@let textareaConfig = config().textareaConfig;\r\n@let dateConfig = config().dateConfig;\r\n\r\n@switch (type) {\r\n@case (ETypeInput.CURRENCY) {\r\n<p-inputnumber [ngModel]=\"valueInput\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\"\r\n (keydown)=\"onKeyDown($event)\" mode=\"currency\" [currency]=\"currency\" [locale]=\"locale\"\r\n [minFractionDigits]=\"minFractionDigits\" [maxFractionDigits]=\"maxFractionDigits\" class=\"w-full\"\r\n [disabled]=\"isDisabled\" />\r\n}\r\n@case (ETypeInput.DECIMAL) {\r\n<p-inputnumber [ngModel]=\"valueInput\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\"\r\n (keydown)=\"onKeyDown($event)\" mode=\"decimal\" [locale]=\"locale\" [minFractionDigits]=\"2\" [maxFractionDigits]=\"2\"\r\n [useGrouping]=\"true\" class=\"w-full\" [disabled]=\"isDisabled\" />\r\n}\r\n@case (ETypeInput.DATE) {\r\n<p-datepicker [ngModel]=\"valueInput\" appendTo=\"body\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\"\r\n (keydown)=\"onKeyDown($event)\" class=\"w-full\" [disabled]=\"isDisabled\" [maxDate]=\"dateConfig?.maxDate || null\"\r\n [minDate]=\"dateConfig?.minDate || null\" [selectionMode]=\"dateConfig?.selectionMode || 'single'\" />\r\n}\r\n@case (ETypeInput.DATETIME_LOCAL) {\r\n<p-datepicker [ngModel]=\"valueInput\" appendTo=\"body\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\"\r\n (keydown)=\"onKeyDown($event)\" class=\"w-full\" [showTime]=\"true\" [hourFormat]=\"'24'\" [disabled]=\"isDisabled\"\r\n [maxDate]=\"dateConfig?.maxDate || null\" [minDate]=\"dateConfig?.minDate || null\" [selectionMode]=\"dateConfig?.selectionMode || 'single'\" />\r\n}\r\n@case (ETypeInput.SELECT) {\r\n<p-select [options]=\"config().selectConfig?.options ?? []\" [optionLabel]=\"config().selectConfig?.optionLabel ?? 'name'\"\r\n [(ngModel)]=\"valueSelect\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\"\r\n appendTo=\"body\" class=\"w-full inline-input-select\" [disabled]=\"config().isDisabled ?? false\" >\r\n @for (template of templates; track $index) {\r\n <ng-template [pTemplate]=\"template.getType()\" let-item>\r\n <ng-container *ngTemplateOutlet=\"template.template; context: { $implicit: item }\"></ng-container>\r\n </ng-template>\r\n }\r\n</p-select>\r\n}\r\n@case (ETypeInput.MULTISELECT) {\r\n<p-multiselect [options]=\"config().multiSelectConfig?.options ?? []\"\r\n [optionLabel]=\"config().multiSelectConfig?.optionLabel ?? 'name'\" [ngModel]=\"valueInput\"\r\n (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\" [filter]=\"true\"\r\n appendTo=\"body\" class=\"w-full\" [disabled]=\"isDisabled\" />\r\n}\r\n@case (ETypeInput.OTP) {\r\n<p-inputotp class=\"w-full\" [mask]=\"config().otpConfig?.mask ?? false\" [length]=\"config().otpConfig?.length ?? 6\"\r\n [integerOnly]=\"config().otpConfig?.integerOnly ?? false\" [ngModel]=\"valueInput\"\r\n (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\" [disabled]=\"isDisabled\" />\r\n}\r\n@case (ETypeInput.KNOB) {\r\n<p-knob [ngModel]=\"knobValueInput()\" (ngModelChange)=\"onChangeValue($event)\" class=\"w-full\" [min]=\"knobConfig?.min ?? 0\"\r\n [max]=\"knobConfig?.max ?? 100\" [step]=\"knobConfig?.step ?? 1\" [disabled]=\"isDisabled\" [readonly]=\"true\"\r\n [valueTemplate]=\"knobValueTemplate()\" [size]=\"knobConfig?.size ?? 100\" />\r\n}\r\n@case (ETypeInput.TEXTAREA) {\r\n<textarea class=\"w-full h-full p-2 border border-gray-300 rounded-md\" pTextarea [rows]=\"textareaConfig?.rows ?? 3\"\r\n [cols]=\"textareaConfig?.cols ?? 30\" [autoResize]=\"true\" [variant]=\"textareaConfig?.variant ?? 'outlined'\"\r\n [disabled]=\"isDisabled\" [ngModel]=\"valueInput\" (ngModelChange)=\"onChangeValue($event)\" (blur)=\"onBlur()\"\r\n (keydown)=\"onKeyDown($event)\"></textarea>\r\n}\r\n@case (ETypeInput.CHIPS) {\r\n<div class=\"chips-input-wrapper\">\r\n <div\r\n class=\"chips-container w-full p-2 border border-gray-300 rounded-md min-h-[40px] flex flex-wrap items-center gap-2\"\r\n [class.border-red-500]=\"showDuplicateMessage\">\r\n @for (chip of chips; track $index) {\r\n <p-chip [label]=\"chip\" [removable]=\"!isDisabled\" (onRemove)=\"removeChip($index)\" class=\"chip-item\" />\r\n }\r\n <input type=\"text\" class=\"chip-input flex-1 border-0 outline-0 bg-transparent min-w-[100px]\" [value]=\"currentInput\"\r\n (input)=\"onChipInputChange($event)\" (keydown)=\"onChipKeydown($event); onKeyDown($event)\"\r\n (paste)=\"onChipPaste($event)\" [disabled]=\"isDisabled\"\r\n placeholder=\"Escribe o pega elementos separados por espacios...\" />\r\n </div>\r\n @if (showDuplicateMessage) {\r\n <div class=\"duplicate-message text-red-500 text-sm mt-1 flex items-center gap-1\">\r\n <i class=\"pi pi-exclamation-triangle text-red-500\"></i>\r\n <span>\r\n @if (duplicateChips.length === 1) {\r\n El elemento \"<strong>{{ duplicatesText }}</strong>\" ya existe en la lista\r\n } @else {\r\n Los elementos \"<strong>{{ duplicatesText }}</strong>\" ya existen en la lista\r\n }\r\n </span>\r\n </div>\r\n }\r\n</div>\r\n}\r\n@default {\r\n<input pInputText class=\"w-full h-full p-2 border border-gray-300 rounded-md\" [type]=\"type\"\r\n [readOnly]=\"config().readonly ?? false\" [ngModel]=\"valueInput\" (ngModelChange)=\"onChangeValue($event)\"\r\n (blur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\" [disabled]=\"isDisabled\" />\r\n}\r\n}", styles: [":host{width:100%;height:100%}.chips-input-wrapper{width:100%}.chips-input-wrapper .chips-container{cursor:text;transition:border-color .2s ease,box-shadow .2s ease}.chips-input-wrapper .chips-container:focus-within{border-color:#007ad9;box-shadow:0 0 0 1px #007ad9}.chips-input-wrapper .chips-container.border-red-500{border-color:#ef4444!important;box-shadow:0 0 0 1px #ef4444!important}.chips-input-wrapper .chips-container .chip-item{margin:0}.chips-input-wrapper .chips-container .chip-input:focus{outline:none}.chips-input-wrapper .chips-container .chip-input::placeholder{color:#6b7280;font-style:italic}.chips-input-wrapper .duplicate-message{animation:slideDown .3s ease-out}.chips-input-wrapper .duplicate-message i{font-size:14px}@keyframes slideDown{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}::ng-deep p-select.inline-input-select{background:transparent;color:#111827;height:44px;width:100%;border-radius:.5rem;transition:all .2s ease-in-out;border:none;display:flex;align-items:center;justify-content:space-between}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.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: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i2$1.InputText, selector: "[pInputText]", inputs: ["variant", "fluid", "pSize"] }, { kind: "ngmodule", type: DatePickerModule }, { kind: "component", type: i2.DatePicker, selector: "p-datePicker, p-datepicker, p-date-picker", inputs: ["iconDisplay", "style", "styleClass", "inputStyle", "inputId", "name", "inputStyleClass", "placeholder", "ariaLabelledBy", "ariaLabel", "iconAriaLabel", "disabled", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "fluid", "icon", "appendTo", "readonlyInput", "shortYearCutoff", "monthNavigator", "yearNavigator", "hourFormat", "timeOnly", "stepHour", "stepMinute", "stepSecond", "showSeconds", "required", "showOnFocus", "showWeek", "startWeekFromFirstDayOfYear", "showClear", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autofocus", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "touchUI", "timeSeparator", "focusTrap", "showTransitionOptions", "hideTransitionOptions", "tabindex", "variant", "size", "minDate", "maxDate", "disabledDates", "disabledDays", "yearRange", "showTime", "responsiveOptions", "numberOfMonths", "firstDayOfWeek", "locale", "view", "defaultDate"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onClear", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }, { kind: "directive", type: i4$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i4.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "name", "style", "panelStyle", "styleClass", "panelStyleClass", "readonly", "required", "editable", "appendTo", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "variant", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "autoDisplayFirst", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "size", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "maxlength", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "fluid", "disabled", "itemSize", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "filterValue", "options"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: MultiSelectModule }, { kind: "component", type: i3.MultiSelect, selector: "p-multiSelect, p-multiselect, p-multi-select", inputs: ["id", "ariaLabel", "style", "styleClass", "panelStyle", "panelStyleClass", "inputId", "disabled", "fluid", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "variant", "appendTo", "dataKey", "name", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "chipIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "size", "showClear", "autofocus", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "defaultLabel", "placeholder", "options", "filterValue", "itemSize", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus", "highlightOnSelect"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "ngmodule", type: InputMaskModule }, { kind: "ngmodule", type: InputNumberModule }, { kind: "component", type: i8.InputNumber, selector: "p-inputNumber, p-inputnumber, p-input-number", inputs: ["showButtons", "format", "buttonLayout", "inputId", "styleClass", "style", "placeholder", "size", "maxlength", "tabindex", "title", "ariaLabelledBy", "ariaDescribedBy", "ariaLabel", "ariaRequired", "name", "required", "autocomplete", "min", "max", "incrementButtonClass", "decrementButtonClass", "incrementButtonIcon", "decrementButtonIcon", "readonly", "step", "allowEmpty", "locale", "localeMatcher", "mode", "currency", "currencyDisplay", "useGrouping", "variant", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "inputStyle", "inputStyleClass", "showClear", "autofocus", "disabled", "fluid"], outputs: ["onInput", "onFocus", "onBlur", "onKeyDown", "onClear"] }, { kind: "ngmodule", type: InputOtpModule }, { kind: "component", type: i6.InputOtp, selector: "p-inputOtp, p-inputotp, p-input-otp", inputs: ["invalid", "disabled", "readonly", "variant", "tabindex", "length", "styleClass", "mask", "integerOnly", "autofocus", "size"], outputs: ["onChange", "onFocus", "onBlur"] }, { kind: "ngmodule", type: KnobModule }, { kind: "component", type: i9$1.Knob, selector: "p-knob", inputs: ["styleClass", "style", "ariaLabel", "ariaLabelledBy", "tabindex", "valueColor", "rangeColor", "textColor", "valueTemplate", "name", "size", "step", "min", "max", "strokeWidth", "disabled", "showValue", "readonly"], outputs: ["onChange"] }, { kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i9.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["autoResize", "variant", "fluid", "pSize"], outputs: ["onResize"] }, { kind: "ngmodule", type: ChipModule }, { kind: "component", type: i11.Chip, selector: "p-chip", inputs: ["label", "icon", "image", "alt", "style", "styleClass", "removable", "removeIcon", "chipProps"], outputs: ["onRemove", "onImageError"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
636
+ }
637
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: InlineInputComponent, decorators: [{
638
+ type: Component,
639
+ args: [{ selector: 'lib-inline-input', standalone: true, imports: [
640
+ FormsModule,
641
+ InputTextModule,
642
+ DatePickerModule,
643
+ SelectModule,
644
+ MultiSelectModule,
645
+ InputMaskModule,
646
+ InputNumberModule,
647
+ InputOtpModule,
648
+ KnobModule,
649
+ TextareaModule,
650
+ ChipModule,
651
+ CommonModule
652
+ ], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
653
+ {
654
+ provide: NG_VALUE_ACCESSOR,
655
+ useExisting: forwardRef(() => InlineInputComponent),
656
+ multi: true
657
+ }
658
+ ], template: "@let valueInput = value();\r\n@let isDisabled = config().isDisabled ?? false;\r\n@let knobConfig = config().knobConfig;\r\n@let textareaConfig = config().textareaConfig;\r\n@let dateConfig = config().dateConfig;\r\n\r\n@switch (type) {\r\n@case (ETypeInput.CURRENCY) {\r\n<p-inputnumber [ngModel]=\"valueInput\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\"\r\n (keydown)=\"onKeyDown($event)\" mode=\"currency\" [currency]=\"currency\" [locale]=\"locale\"\r\n [minFractionDigits]=\"minFractionDigits\" [maxFractionDigits]=\"maxFractionDigits\" class=\"w-full\"\r\n [disabled]=\"isDisabled\" />\r\n}\r\n@case (ETypeInput.DECIMAL) {\r\n<p-inputnumber [ngModel]=\"valueInput\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\"\r\n (keydown)=\"onKeyDown($event)\" mode=\"decimal\" [locale]=\"locale\" [minFractionDigits]=\"2\" [maxFractionDigits]=\"2\"\r\n [useGrouping]=\"true\" class=\"w-full\" [disabled]=\"isDisabled\" />\r\n}\r\n@case (ETypeInput.DATE) {\r\n<p-datepicker [ngModel]=\"valueInput\" appendTo=\"body\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\"\r\n (keydown)=\"onKeyDown($event)\" class=\"w-full\" [disabled]=\"isDisabled\" [maxDate]=\"dateConfig?.maxDate || null\"\r\n [minDate]=\"dateConfig?.minDate || null\" [selectionMode]=\"dateConfig?.selectionMode || 'single'\" />\r\n}\r\n@case (ETypeInput.DATETIME_LOCAL) {\r\n<p-datepicker [ngModel]=\"valueInput\" appendTo=\"body\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\"\r\n (keydown)=\"onKeyDown($event)\" class=\"w-full\" [showTime]=\"true\" [hourFormat]=\"'24'\" [disabled]=\"isDisabled\"\r\n [maxDate]=\"dateConfig?.maxDate || null\" [minDate]=\"dateConfig?.minDate || null\" [selectionMode]=\"dateConfig?.selectionMode || 'single'\" />\r\n}\r\n@case (ETypeInput.SELECT) {\r\n<p-select [options]=\"config().selectConfig?.options ?? []\" [optionLabel]=\"config().selectConfig?.optionLabel ?? 'name'\"\r\n [(ngModel)]=\"valueSelect\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\"\r\n appendTo=\"body\" class=\"w-full inline-input-select\" [disabled]=\"config().isDisabled ?? false\" >\r\n @for (template of templates; track $index) {\r\n <ng-template [pTemplate]=\"template.getType()\" let-item>\r\n <ng-container *ngTemplateOutlet=\"template.template; context: { $implicit: item }\"></ng-container>\r\n </ng-template>\r\n }\r\n</p-select>\r\n}\r\n@case (ETypeInput.MULTISELECT) {\r\n<p-multiselect [options]=\"config().multiSelectConfig?.options ?? []\"\r\n [optionLabel]=\"config().multiSelectConfig?.optionLabel ?? 'name'\" [ngModel]=\"valueInput\"\r\n (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\" [filter]=\"true\"\r\n appendTo=\"body\" class=\"w-full\" [disabled]=\"isDisabled\" />\r\n}\r\n@case (ETypeInput.OTP) {\r\n<p-inputotp class=\"w-full\" [mask]=\"config().otpConfig?.mask ?? false\" [length]=\"config().otpConfig?.length ?? 6\"\r\n [integerOnly]=\"config().otpConfig?.integerOnly ?? false\" [ngModel]=\"valueInput\"\r\n (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\" [disabled]=\"isDisabled\" />\r\n}\r\n@case (ETypeInput.KNOB) {\r\n<p-knob [ngModel]=\"knobValueInput()\" (ngModelChange)=\"onChangeValue($event)\" class=\"w-full\" [min]=\"knobConfig?.min ?? 0\"\r\n [max]=\"knobConfig?.max ?? 100\" [step]=\"knobConfig?.step ?? 1\" [disabled]=\"isDisabled\" [readonly]=\"true\"\r\n [valueTemplate]=\"knobValueTemplate()\" [size]=\"knobConfig?.size ?? 100\" />\r\n}\r\n@case (ETypeInput.TEXTAREA) {\r\n<textarea class=\"w-full h-full p-2 border border-gray-300 rounded-md\" pTextarea [rows]=\"textareaConfig?.rows ?? 3\"\r\n [cols]=\"textareaConfig?.cols ?? 30\" [autoResize]=\"true\" [variant]=\"textareaConfig?.variant ?? 'outlined'\"\r\n [disabled]=\"isDisabled\" [ngModel]=\"valueInput\" (ngModelChange)=\"onChangeValue($event)\" (blur)=\"onBlur()\"\r\n (keydown)=\"onKeyDown($event)\"></textarea>\r\n}\r\n@case (ETypeInput.CHIPS) {\r\n<div class=\"chips-input-wrapper\">\r\n <div\r\n class=\"chips-container w-full p-2 border border-gray-300 rounded-md min-h-[40px] flex flex-wrap items-center gap-2\"\r\n [class.border-red-500]=\"showDuplicateMessage\">\r\n @for (chip of chips; track $index) {\r\n <p-chip [label]=\"chip\" [removable]=\"!isDisabled\" (onRemove)=\"removeChip($index)\" class=\"chip-item\" />\r\n }\r\n <input type=\"text\" class=\"chip-input flex-1 border-0 outline-0 bg-transparent min-w-[100px]\" [value]=\"currentInput\"\r\n (input)=\"onChipInputChange($event)\" (keydown)=\"onChipKeydown($event); onKeyDown($event)\"\r\n (paste)=\"onChipPaste($event)\" [disabled]=\"isDisabled\"\r\n placeholder=\"Escribe o pega elementos separados por espacios...\" />\r\n </div>\r\n @if (showDuplicateMessage) {\r\n <div class=\"duplicate-message text-red-500 text-sm mt-1 flex items-center gap-1\">\r\n <i class=\"pi pi-exclamation-triangle text-red-500\"></i>\r\n <span>\r\n @if (duplicateChips.length === 1) {\r\n El elemento \"<strong>{{ duplicatesText }}</strong>\" ya existe en la lista\r\n } @else {\r\n Los elementos \"<strong>{{ duplicatesText }}</strong>\" ya existen en la lista\r\n }\r\n </span>\r\n </div>\r\n }\r\n</div>\r\n}\r\n@default {\r\n<input pInputText class=\"w-full h-full p-2 border border-gray-300 rounded-md\" [type]=\"type\"\r\n [readOnly]=\"config().readonly ?? false\" [ngModel]=\"valueInput\" (ngModelChange)=\"onChangeValue($event)\"\r\n (blur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\" [disabled]=\"isDisabled\" />\r\n}\r\n}", styles: [":host{width:100%;height:100%}.chips-input-wrapper{width:100%}.chips-input-wrapper .chips-container{cursor:text;transition:border-color .2s ease,box-shadow .2s ease}.chips-input-wrapper .chips-container:focus-within{border-color:#007ad9;box-shadow:0 0 0 1px #007ad9}.chips-input-wrapper .chips-container.border-red-500{border-color:#ef4444!important;box-shadow:0 0 0 1px #ef4444!important}.chips-input-wrapper .chips-container .chip-item{margin:0}.chips-input-wrapper .chips-container .chip-input:focus{outline:none}.chips-input-wrapper .chips-container .chip-input::placeholder{color:#6b7280;font-style:italic}.chips-input-wrapper .duplicate-message{animation:slideDown .3s ease-out}.chips-input-wrapper .duplicate-message i{font-size:14px}@keyframes slideDown{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}::ng-deep p-select.inline-input-select{background:transparent;color:#111827;height:44px;width:100%;border-radius:.5rem;transition:all .2s ease-in-out;border:none;display:flex;align-items:center;justify-content:space-between}\n"] }]
659
+ }], ctorParameters: () => [], propDecorators: { templates: [{
660
+ type: ContentChildren,
661
+ args: [PrimeTemplate]
662
+ }] } });
663
+
95
664
  class AppButtonNgService {
96
665
  buttonConfig = signal({});
97
666
  constructor() {
@@ -167,7 +736,7 @@ class ButtonNgComponent {
167
736
  this.onClick.emit();
168
737
  }
169
738
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: ButtonNgComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
170
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: ButtonNgComponent, isStandalone: true, selector: "lib-button-ng", inputs: { buttonConfig: { classPropertyName: "buttonConfig", publicName: "buttonConfig", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { buttonConfig: "buttonConfigChange", onClick: "onClick" }, providers: [AppButtonNgService], ngImport: i0, template: "@let config = buttonConfig(); @let tooltipConfig = buttonConfig().tooltipConfig;\r\n@if (!config.hideButton) {\r\n <div\r\n [ngClass]=\"{\r\n 'full-width-button': config.fullWidth,\r\n 'full-height-button': config.fullHeight,\r\n 'cursor-pointer': this.onClick\r\n }\"\r\n [class]=\"config.class ?? ''\"\r\n >\r\n <p-button\r\n [label]=\"config.hasTemplate ? undefined : label\"\r\n [icon]=\"config.hasTemplate ? undefined : config.icon\"\r\n [severity]=\"config.hasTemplate ? 'secondary' : config.severity\"\r\n [loading]=\"config.loading || false\"\r\n [disabled]=\"config.disabled || false\"\r\n [rounded]=\"config.rounded || false\"\r\n [raised]=\"config.raised || false\"\r\n [variant]=\"config.hasTemplate ? 'text' : config.variant\"\r\n [badge]=\"config.badge\"\r\n (onClick)=\"config?.onClick?.() ?? onClickButton()\"\r\n [size]=\"config?.size\"\r\n pTooltip=\"{{ tooltipConfig?.pTooltip }}\"\r\n [tooltipPosition]=\"tooltipConfig?.tooltipPosition ?? 'top'\"\r\n [iconPos]=\"config?.iconPos ?? 'left'\"\r\n [ngClass]=\"{\r\n 'cursor-pointer': (config.onClick || config.hasStaticClick) && !config.disabled,\r\n 'cursor-auto': !((config.onClick || config.hasStaticClick) && !config.disabled),\r\n 'no-hover-template': config.hasTemplate\r\n }\"\r\n [outlined]=\"config.outlined || false\"\r\n [text]=\"config.text || false\"\r\n >\r\n @if (config.hasTemplate) {\r\n <ng-content></ng-content>\r\n }\r\n </p-button>\r\n </div>\r\n}\r\n", styles: [".full-width-button ::ng-deep p-button button{width:100%}.full-height-button ::ng-deep p-button button{height:100%}::ng-deep .cursor-auto button{cursor:auto!important}::ng-deep .cursor-pointer button{cursor:pointer!important}::ng-deep .no-hover-template button{background:transparent!important;border:none!important;box-shadow:none!important;padding:0!important}::ng-deep .no-hover-template button:hover,::ng-deep .no-hover-template button:focus,::ng-deep .no-hover-template button:active{background:transparent!important;border:none!important;box-shadow:none!important}\n"], dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "fluid", "buttonProps"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i2.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
739
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: ButtonNgComponent, isStandalone: true, selector: "lib-button-ng", inputs: { buttonConfig: { classPropertyName: "buttonConfig", publicName: "buttonConfig", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { buttonConfig: "buttonConfigChange", onClick: "onClick" }, providers: [AppButtonNgService], ngImport: i0, template: "@let config = buttonConfig(); @let tooltipConfig = buttonConfig().tooltipConfig;\r\n@if (!config.hideButton) {\r\n <div\r\n [ngClass]=\"{\r\n 'full-width-button': config.fullWidth,\r\n 'full-height-button': config.fullHeight,\r\n 'cursor-pointer': this.onClick\r\n }\"\r\n [class]=\"config.class ?? ''\"\r\n >\r\n <p-button\r\n [label]=\"config.hasTemplate ? undefined : label\"\r\n [icon]=\"config.hasTemplate ? undefined : config.icon\"\r\n [severity]=\"config.hasTemplate ? 'secondary' : config.severity\"\r\n [loading]=\"config.loading || false\"\r\n [disabled]=\"config.disabled || false\"\r\n [rounded]=\"config.rounded || false\"\r\n [raised]=\"config.raised || false\"\r\n [variant]=\"config.hasTemplate ? 'text' : config.variant\"\r\n [badge]=\"config.badge\"\r\n (onClick)=\"config?.onClick?.() ?? onClickButton()\"\r\n [size]=\"config?.size\"\r\n pTooltip=\"{{ tooltipConfig?.pTooltip }}\"\r\n [tooltipPosition]=\"tooltipConfig?.tooltipPosition ?? 'top'\"\r\n [iconPos]=\"config?.iconPos ?? 'left'\"\r\n [ngClass]=\"{\r\n 'cursor-pointer': (config.onClick || config.hasStaticClick) && !config.disabled,\r\n 'cursor-auto': !((config.onClick || config.hasStaticClick) && !config.disabled),\r\n 'no-hover-template': config.hasTemplate\r\n }\"\r\n [outlined]=\"config.outlined || false\"\r\n [text]=\"config.text || false\"\r\n >\r\n @if (config.hasTemplate) {\r\n <ng-content></ng-content>\r\n }\r\n </p-button>\r\n </div>\r\n}\r\n", styles: [".full-width-button ::ng-deep p-button button{width:100%}.full-height-button ::ng-deep p-button button{height:100%}::ng-deep .cursor-auto button{cursor:auto!important}::ng-deep .cursor-pointer button{cursor:pointer!important}::ng-deep .no-hover-template button{background:transparent!important;border:none!important;box-shadow:none!important;padding:0!important}::ng-deep .no-hover-template button:hover,::ng-deep .no-hover-template button:focus,::ng-deep .no-hover-template button:active{background:transparent!important;border:none!important;box-shadow:none!important}\n"], dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "fluid", "buttonProps"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i10.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
171
740
  }
172
741
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: ButtonNgComponent, decorators: [{
173
742
  type: Component,
@@ -178,6 +747,1733 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
178
747
  ], providers: [AppButtonNgService], template: "@let config = buttonConfig(); @let tooltipConfig = buttonConfig().tooltipConfig;\r\n@if (!config.hideButton) {\r\n <div\r\n [ngClass]=\"{\r\n 'full-width-button': config.fullWidth,\r\n 'full-height-button': config.fullHeight,\r\n 'cursor-pointer': this.onClick\r\n }\"\r\n [class]=\"config.class ?? ''\"\r\n >\r\n <p-button\r\n [label]=\"config.hasTemplate ? undefined : label\"\r\n [icon]=\"config.hasTemplate ? undefined : config.icon\"\r\n [severity]=\"config.hasTemplate ? 'secondary' : config.severity\"\r\n [loading]=\"config.loading || false\"\r\n [disabled]=\"config.disabled || false\"\r\n [rounded]=\"config.rounded || false\"\r\n [raised]=\"config.raised || false\"\r\n [variant]=\"config.hasTemplate ? 'text' : config.variant\"\r\n [badge]=\"config.badge\"\r\n (onClick)=\"config?.onClick?.() ?? onClickButton()\"\r\n [size]=\"config?.size\"\r\n pTooltip=\"{{ tooltipConfig?.pTooltip }}\"\r\n [tooltipPosition]=\"tooltipConfig?.tooltipPosition ?? 'top'\"\r\n [iconPos]=\"config?.iconPos ?? 'left'\"\r\n [ngClass]=\"{\r\n 'cursor-pointer': (config.onClick || config.hasStaticClick) && !config.disabled,\r\n 'cursor-auto': !((config.onClick || config.hasStaticClick) && !config.disabled),\r\n 'no-hover-template': config.hasTemplate\r\n }\"\r\n [outlined]=\"config.outlined || false\"\r\n [text]=\"config.text || false\"\r\n >\r\n @if (config.hasTemplate) {\r\n <ng-content></ng-content>\r\n }\r\n </p-button>\r\n </div>\r\n}\r\n", styles: [".full-width-button ::ng-deep p-button button{width:100%}.full-height-button ::ng-deep p-button button{height:100%}::ng-deep .cursor-auto button{cursor:auto!important}::ng-deep .cursor-pointer button{cursor:pointer!important}::ng-deep .no-hover-template button{background:transparent!important;border:none!important;box-shadow:none!important;padding:0!important}::ng-deep .no-hover-template button:hover,::ng-deep .no-hover-template button:focus,::ng-deep .no-hover-template button:active{background:transparent!important;border:none!important;box-shadow:none!important}\n"] }]
179
748
  }], ctorParameters: () => [] });
180
749
 
750
+ class KeyToDisplayNamePipe {
751
+ transform(key, keysNames) {
752
+ return keysNames?.[key] ?? key;
753
+ }
754
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: KeyToDisplayNamePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
755
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.17", ngImport: i0, type: KeyToDisplayNamePipe, isStandalone: true, name: "keyToDisplayName" });
756
+ }
757
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: KeyToDisplayNamePipe, decorators: [{
758
+ type: Pipe,
759
+ args: [{
760
+ name: 'keyToDisplayName'
761
+ }]
762
+ }] });
763
+
764
+ /**
765
+ * Utilidades para manejar errores de API según la interfaz IApiError
766
+ */
767
+ class ApiErrorUtil {
768
+ /**
769
+ * Procesa errores de API y extrae el mensaje según la interfaz IApiError
770
+ * @param error - El error HTTP recibido
771
+ * @param fallbackMessage - Mensaje por defecto si no se puede extraer el mensaje del error
772
+ * @returns El mensaje de error procesado
773
+ */
774
+ static handleApiError(error, fallbackMessage) {
775
+ const apiError = error.error;
776
+ const errorMessage = Array.isArray(apiError?.message)
777
+ ? apiError.message.join(', ')
778
+ : apiError?.message ?? fallbackMessage;
779
+ return errorMessage;
780
+ }
781
+ /**
782
+ * Procesa errores de API con información detallada de campos
783
+ * y muestra tanto el mensaje general como los errores específicos de campo
784
+ * @param error - El error HTTP recibido
785
+ * @param fallbackMessage - Mensaje por defecto si no se puede extraer el mensaje del error
786
+ * @returns El mensaje de error procesado con información de campos si está disponible
787
+ */
788
+ static handleApiErrorWithFields(error, fallbackMessage) {
789
+ const apiError = error.error;
790
+ let errorMessage = Array.isArray(apiError?.message)
791
+ ? apiError.message.join(', ')
792
+ : apiError?.message ?? fallbackMessage;
793
+ // Si hay errores de campo específicos, los agregamos al mensaje
794
+ if (apiError?.errors && apiError.errors.length > 0) {
795
+ const fieldErrors = apiError.errors
796
+ .map(fieldError => `${fieldError.field}: ${fieldError.message}`)
797
+ .join(', ');
798
+ errorMessage = `${errorMessage}. Errores de campos: ${fieldErrors}`;
799
+ }
800
+ return errorMessage;
801
+ }
802
+ /**
803
+ * Obtiene solo los errores de campo específicos
804
+ * @param error - El error HTTP recibido
805
+ * @returns Array de errores de campo o array vacío si no hay errores
806
+ */
807
+ static getFieldErrors(error) {
808
+ const apiError = error.error;
809
+ return apiError?.errors ?? [];
810
+ }
811
+ /**
812
+ * Verifica si el error tiene errores de campo específicos
813
+ * @param error - El error HTTP recibido
814
+ * @returns true si hay errores de campo, false en caso contrario
815
+ */
816
+ static hasFieldErrors(error) {
817
+ const apiError = error.error;
818
+ return apiError?.errors && apiError.errors.length > 0;
819
+ }
820
+ /**
821
+ * Obtiene el código de error específico
822
+ * @param error - El error HTTP recibido
823
+ * @returns El código de error o undefined si no está disponible
824
+ */
825
+ static getErrorCode(error) {
826
+ const apiError = error.error;
827
+ return apiError?.errorCode;
828
+ }
829
+ /**
830
+ * Obtiene el timestamp del error
831
+ * @param error - El error HTTP recibido
832
+ * @returns El timestamp del error o undefined si no está disponible
833
+ */
834
+ static getErrorTimestamp(error) {
835
+ const apiError = error.error;
836
+ return apiError?.timestamp;
837
+ }
838
+ }
839
+
840
+ class CookieUtil {
841
+ /**
842
+ * Obtiene el valor de una cookie por su nombre
843
+ * @param name - Nombre de la cookie
844
+ * @returns El valor de la cookie o null si no existe
845
+ */
846
+ static getCookie(name) {
847
+ if (typeof document === 'undefined') {
848
+ return null;
849
+ }
850
+ const nameEQ = name + '=';
851
+ const ca = document.cookie.split(';');
852
+ for (let i = 0; i < ca.length; i++) {
853
+ let c = ca[i];
854
+ while (c.charAt(0) === ' ') {
855
+ c = c.substring(1, c.length);
856
+ }
857
+ if (c.indexOf(nameEQ) === 0) {
858
+ return c.substring(nameEQ.length, c.length);
859
+ }
860
+ }
861
+ return null;
862
+ }
863
+ /**
864
+ * Establece una cookie
865
+ * @param name - Nombre de la cookie
866
+ * @param value - Valor de la cookie
867
+ * @param days - Días hasta que expire (por defecto 365)
868
+ * @param path - Ruta de la cookie (por defecto '/')
869
+ */
870
+ static setCookie(name, value, days = 365, path = '/') {
871
+ if (typeof document === 'undefined') {
872
+ return;
873
+ }
874
+ let expires = '';
875
+ if (days) {
876
+ const date = new Date();
877
+ date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
878
+ expires = '; expires=' + date.toUTCString();
879
+ }
880
+ document.cookie = name + '=' + (value || '') + expires + '; path=' + path;
881
+ }
882
+ /**
883
+ * Elimina una cookie
884
+ * @param name - Nombre de la cookie a eliminar
885
+ * @param path - Ruta de la cookie (por defecto '/')
886
+ */
887
+ static eraseCookie(name, path = '/') {
888
+ if (typeof document === 'undefined') {
889
+ return;
890
+ }
891
+ document.cookie = name + '=; Path=' + path + '; Expires=Thu, 01 Jan 1970 00:00:01 GMT;';
892
+ }
893
+ /**
894
+ * Obtiene un valor booleano desde una cookie
895
+ * @param name - Nombre de la cookie
896
+ * @param defaultValue - Valor por defecto si la cookie no existe
897
+ * @returns El valor booleano
898
+ */
899
+ static getBooleanCookie(name, defaultValue = false) {
900
+ const value = this.getCookie(name);
901
+ if (value === null) {
902
+ return defaultValue;
903
+ }
904
+ return value === 'true';
905
+ }
906
+ /**
907
+ * Establece un valor booleano en una cookie
908
+ * @param name - Nombre de la cookie
909
+ * @param value - Valor booleano
910
+ * @param days - Días hasta que expire (por defecto 365)
911
+ * @param path - Ruta de la cookie (por defecto '/')
912
+ */
913
+ static setBooleanCookie(name, value, days = 365, path = '/') {
914
+ this.setCookie(name, value.toString(), days, path);
915
+ }
916
+ }
917
+
918
+ const formatCurrency = (amount, currency) => {
919
+ return new Intl.NumberFormat('es-CO', {
920
+ style: 'currency',
921
+ currency: currency || 'COP'
922
+ }).format(amount);
923
+ };
924
+
925
+ const isSameDay = (date1, date2) => {
926
+ const date1Copy = new Date(date1.setHours(0, 0, 0, 0));
927
+ const date2Copy = new Date(date2.setHours(0, 0, 0, 0));
928
+ return date1Copy.getTime() === date2Copy.getTime();
929
+ };
930
+ const formatDateDMA = (date) => {
931
+ return new Date(date).toLocaleDateString('es-CO', {
932
+ year: 'numeric',
933
+ month: '2-digit',
934
+ day: '2-digit'
935
+ });
936
+ };
937
+ // Crea una funcion que tambien muestre la hora
938
+ const formatDateDMAWithTime = (date) => {
939
+ return new Date(date).toLocaleDateString('es-CO', {
940
+ year: 'numeric',
941
+ month: '2-digit',
942
+ day: '2-digit',
943
+ hour: '2-digit',
944
+ minute: '2-digit'
945
+ });
946
+ };
947
+
948
+ /**
949
+ * Enum con los tipos de archivos más relevantes para la aplicación
950
+ */
951
+ var EFileType;
952
+ (function (EFileType) {
953
+ // Documentos
954
+ EFileType["PDF"] = "application/pdf";
955
+ EFileType["DOC"] = "application/msword";
956
+ EFileType["DOCX"] = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
957
+ EFileType["XLS"] = "application/vnd.ms-excel";
958
+ EFileType["XLSX"] = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
959
+ EFileType["PPT"] = "application/vnd.ms-powerpoint";
960
+ EFileType["PPTX"] = "application/vnd.openxmlformats-officedocument.presentationml.presentation";
961
+ EFileType["TXT"] = "text/plain";
962
+ EFileType["RTF"] = "application/rtf";
963
+ // Imágenes
964
+ EFileType["JPG"] = "image/jpeg";
965
+ EFileType["PNG"] = "image/png";
966
+ EFileType["GIF"] = "image/gif";
967
+ EFileType["BMP"] = "image/bmp";
968
+ EFileType["SVG"] = "image/svg+xml";
969
+ EFileType["WEBP"] = "image/webp";
970
+ // Archivos comprimidos
971
+ EFileType["ZIP"] = "application/zip";
972
+ EFileType["RAR"] = "application/vnd.rar";
973
+ EFileType["TAR"] = "application/x-tar";
974
+ EFileType["GZ"] = "application/gzip";
975
+ // Archivos de datos
976
+ EFileType["CSV"] = "text/csv";
977
+ EFileType["JSON"] = "application/json";
978
+ EFileType["XML"] = "application/xml";
979
+ // Archivos de audio
980
+ EFileType["MP3"] = "audio/mpeg";
981
+ EFileType["WAV"] = "audio/wav";
982
+ EFileType["OGG"] = "audio/ogg";
983
+ // Archivos de video
984
+ EFileType["MP4"] = "video/mp4";
985
+ EFileType["AVI"] = "video/x-msvideo";
986
+ EFileType["MOV"] = "video/quicktime";
987
+ EFileType["WMV"] = "video/x-ms-wmv";
988
+ // Todos los tipos de imagen
989
+ EFileType["ALL_IMAGES"] = "image/*";
990
+ // Todos los tipos de documento
991
+ EFileType["ALL_DOCUMENTS"] = "application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-powerpoint,application/vnd.openxmlformats-officedocument.presentationml.presentation,text/plain,application/rtf";
992
+ // Todos los tipos de archivo
993
+ EFileType["ALL_FILES"] = "*/*";
994
+ })(EFileType || (EFileType = {}));
995
+ /**
996
+ * Método mejorado para abrir el selector de archivos
997
+ * @param options - Opciones para configurar el input de archivo
998
+ */
999
+ const triggerFileInput = (options = {}) => {
1000
+ const { accept = EFileType.ALL_FILES, multiple = false, onFileSelected } = options;
1001
+ const input = document.createElement('input');
1002
+ input.type = 'file';
1003
+ input.accept = accept;
1004
+ input.multiple = multiple;
1005
+ input.style.display = 'none';
1006
+ input.onchange = (event) => {
1007
+ const target = event.target;
1008
+ const files = target.files;
1009
+ if (files && files.length > 0 && onFileSelected) {
1010
+ if (multiple) {
1011
+ // Si es múltiple, llamar al callback con todos los archivos
1012
+ Array.from(files).forEach(file => {
1013
+ onFileSelected(file);
1014
+ });
1015
+ }
1016
+ else {
1017
+ // Si es único, llamar al callback con el primer archivo
1018
+ const file = files[0];
1019
+ onFileSelected(file);
1020
+ }
1021
+ }
1022
+ document.body.removeChild(input);
1023
+ };
1024
+ document.body.appendChild(input);
1025
+ input.click();
1026
+ };
1027
+ /**
1028
+ * Función para capturar una foto usando la cámara
1029
+ */
1030
+ const capturePhotoFromCamera = async (options = {}) => {
1031
+ const { quality = 0.9, facingMode = 'environment', onPhotoTaken, onError } = options;
1032
+ try {
1033
+ if (!navigator.mediaDevices?.getUserMedia) {
1034
+ throw new Error('Cámara no soportada en este navegador');
1035
+ }
1036
+ const stream = await navigator.mediaDevices.getUserMedia({
1037
+ video: { facingMode }
1038
+ });
1039
+ const video = document.createElement('video');
1040
+ const canvas = document.createElement('canvas');
1041
+ const context = canvas.getContext('2d');
1042
+ // Crear modal
1043
+ const modal = document.createElement('div');
1044
+ modal.style.cssText = `
1045
+ position: fixed; top: 0; left: 0; width: 100%; height: 100%;
1046
+ background: rgba(0,0,0,0.9); display: flex; flex-direction: column;
1047
+ align-items: center; justify-content: center; z-index: 10000;
1048
+ `;
1049
+ video.style.cssText = 'width: 80%; max-width: 500px; border-radius: 8px;';
1050
+ video.srcObject = stream;
1051
+ video.autoplay = true;
1052
+ video.playsInline = true;
1053
+ const buttonsDiv = document.createElement('div');
1054
+ buttonsDiv.style.cssText = 'display: flex; gap: 20px; margin-top: 20px;';
1055
+ const captureBtn = document.createElement('button');
1056
+ captureBtn.textContent = 'Tomar Foto';
1057
+ captureBtn.style.cssText = `
1058
+ padding: 12px 24px; background: #007bff; color: white;
1059
+ border: none; border-radius: 6px; cursor: pointer; font-size: 16px;
1060
+ `;
1061
+ const cancelBtn = document.createElement('button');
1062
+ cancelBtn.textContent = 'Cancelar';
1063
+ cancelBtn.style.cssText = `
1064
+ padding: 12px 24px; background: #6c757d; color: white;
1065
+ border: none; border-radius: 6px; cursor: pointer; font-size: 16px;
1066
+ `;
1067
+ const cleanup = () => {
1068
+ stream.getTracks().forEach(track => track.stop());
1069
+ modal.remove();
1070
+ };
1071
+ captureBtn.onclick = () => {
1072
+ canvas.width = video.videoWidth;
1073
+ canvas.height = video.videoHeight;
1074
+ context.drawImage(video, 0, 0);
1075
+ canvas.toBlob((blob) => {
1076
+ if (blob && onPhotoTaken) {
1077
+ const file = new File([blob], `photo-${Date.now()}.jpg`, { type: 'image/jpeg' });
1078
+ onPhotoTaken(file);
1079
+ }
1080
+ cleanup();
1081
+ }, 'image/jpeg', quality);
1082
+ };
1083
+ cancelBtn.onclick = cleanup;
1084
+ document.addEventListener('keydown', (e) => {
1085
+ if (e.key === 'Escape')
1086
+ cleanup();
1087
+ });
1088
+ buttonsDiv.append(captureBtn, cancelBtn);
1089
+ modal.append(video, buttonsDiv);
1090
+ document.body.appendChild(modal);
1091
+ }
1092
+ catch (error) {
1093
+ if (onError)
1094
+ onError(error);
1095
+ }
1096
+ };
1097
+ var EFileIcons;
1098
+ (function (EFileIcons) {
1099
+ EFileIcons["FILE"] = "file";
1100
+ EFileIcons["IMAGE"] = "image";
1101
+ EFileIcons["VIDEO"] = "video";
1102
+ EFileIcons["FOLDER"] = "folder";
1103
+ EFileIcons["EXCEL"] = "excel";
1104
+ EFileIcons["SIGNATURE"] = "signature";
1105
+ EFileIcons["CONTRACT"] = "contract";
1106
+ EFileIcons["FINGERPRINT"] = "fingerprint";
1107
+ EFileIcons["ID_CARD"] = "id_card";
1108
+ EFileIcons["FILE_BOX"] = "file_box";
1109
+ EFileIcons["SECURE_BUILDING"] = "secure_building";
1110
+ EFileIcons["POLICE"] = "police";
1111
+ })(EFileIcons || (EFileIcons = {}));
1112
+ const DocumentIcon = {
1113
+ [EFileIcons.FILE]: 'fa-solid fa-file-lines',
1114
+ [EFileIcons.IMAGE]: 'fa-solid fa-file-image',
1115
+ [EFileIcons.VIDEO]: 'fa-solid fa-file-video',
1116
+ [EFileIcons.FOLDER]: 'fa-solid fa-folder',
1117
+ [EFileIcons.EXCEL]: 'fa-solid fa-file-excel',
1118
+ [EFileIcons.SIGNATURE]: 'fa-solid fa-signature',
1119
+ [EFileIcons.CONTRACT]: 'fa-solid fa-file-contract',
1120
+ [EFileIcons.FINGERPRINT]: 'fa-solid fa-fingerprint',
1121
+ [EFileIcons.ID_CARD]: 'fa-solid fa-id-card',
1122
+ [EFileIcons.SECURE_BUILDING]: 'fa-solid fa-building-shield',
1123
+ [EFileIcons.POLICE]: 'fa-solid fa-hand-middle-finger',
1124
+ [EFileIcons.FILE_BOX]: 'fa-solid fa-box-archive'
1125
+ };
1126
+ const downloadFile = (blob, fileName) => {
1127
+ const url = window.URL.createObjectURL(blob);
1128
+ const link = document.createElement('a');
1129
+ link.href = url;
1130
+ link.download = fileName;
1131
+ document.body.appendChild(link);
1132
+ link.click();
1133
+ document.body.removeChild(link);
1134
+ window.URL.revokeObjectURL(url);
1135
+ };
1136
+
1137
+ //sin uuid, codigo propio
1138
+ const generateId = () => {
1139
+ return Date.now().toString(36) + Math.random().toString(36).substring(2, 15);
1140
+ };
1141
+
1142
+ const formatNumber = (number) => {
1143
+ return new Intl.NumberFormat('es-CO', {
1144
+ minimumFractionDigits: 2,
1145
+ maximumFractionDigits: 2
1146
+ }).format(number);
1147
+ };
1148
+ const fixedNumber = (number) => {
1149
+ return Number(number.toFixed(2));
1150
+ };
1151
+
1152
+ const hasValues = (obj) => {
1153
+ return Object.values(obj).some(value => value !== null && value !== undefined);
1154
+ };
1155
+ /**
1156
+ * Elimina las propiedades de un objeto que tengan valores null o undefined.
1157
+ * Retorna un nuevo objeto sin mutar el original.
1158
+ * @param obj - Objeto del cual se eliminarán las propiedades null/undefined
1159
+ * @returns Nuevo objeto sin las propiedades con valores null o undefined
1160
+ */
1161
+ const removeNullUndefined = (obj) => {
1162
+ const result = {};
1163
+ Object.keys(obj).forEach(key => {
1164
+ const value = obj[key];
1165
+ if (value !== null && value !== undefined) {
1166
+ result[key] = value;
1167
+ }
1168
+ });
1169
+ return result;
1170
+ };
1171
+ /**
1172
+ * Realiza un upsert en un array de strings. Si el string ya existe, no hace nada.
1173
+ * Si no existe, lo agrega al array.
1174
+ * @param targetArray - Array de strings donde se realizará el upsert
1175
+ * @param value - String o array de strings a insertar
1176
+ * @returns Array actualizado con los nuevos valores
1177
+ */
1178
+ const upsertArrayStrings = (targetArray, value) => {
1179
+ // Crear una copia del array original para evitar mutaciones
1180
+ const result = [...targetArray];
1181
+ // Convertir el valor a array para procesamiento uniforme
1182
+ const valuesToInsert = Array.isArray(value) ? value : [value];
1183
+ // Procesar cada valor
1184
+ valuesToInsert.forEach(stringValue => {
1185
+ // Solo agregar si no existe en el array
1186
+ if (!result.includes(stringValue)) {
1187
+ result.push(stringValue);
1188
+ }
1189
+ });
1190
+ return result;
1191
+ };
1192
+ const sameArray = (arr1, arr2) => {
1193
+ if (arr1.length !== arr2.length)
1194
+ return false;
1195
+ const sorted1 = Array.from(arr1).sort();
1196
+ const sorted2 = Array.from(arr2).sort();
1197
+ return sorted1.every((item, index) => item === sorted2[index]);
1198
+ };
1199
+ const getOptionByCode = (options, code) => {
1200
+ if (!code)
1201
+ return undefined;
1202
+ return options.find((item) => item.code === code);
1203
+ };
1204
+ const createEnumeratedList = (items) => {
1205
+ if (items.length === 0) {
1206
+ return '';
1207
+ }
1208
+ if (items.length === 1) {
1209
+ return `1. ${items[0]}`;
1210
+ }
1211
+ return items
1212
+ .map((item, index) => `${index + 1}. ${item}`)
1213
+ .join('\n');
1214
+ };
1215
+
1216
+ class PrimeNgUtil {
1217
+ static isPrimeNgSelection(value) {
1218
+ return typeof value === 'object' && value !== null && 'name' in value && 'code' in value;
1219
+ }
1220
+ }
1221
+
1222
+ class BadgeNgComponent {
1223
+ config = model.required();
1224
+ get value() {
1225
+ return this.config().value;
1226
+ }
1227
+ get severity() {
1228
+ return this.config().severity;
1229
+ }
1230
+ get badgeSize() {
1231
+ return this.config().badgeSize ?? 'small';
1232
+ }
1233
+ get fullWidth() {
1234
+ return this.config().fullWidth ?? true;
1235
+ }
1236
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: BadgeNgComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1237
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.17", type: BadgeNgComponent, isStandalone: true, selector: "lib-badge-ng", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { config: "configChange" }, ngImport: i0, template: "<p-badge\r\n [style]=\"{\r\n textAlign: 'center',\r\n width: fullWidth ? '100%' : 'auto'\r\n }\"\r\n [value]=\"value\"\r\n [severity]=\"severity\"\r\n [badgeSize]=\"badgeSize\"\r\n/>\r\n", dependencies: [{ kind: "ngmodule", type: BadgeModule }, { kind: "component", type: i1$3.Badge, selector: "p-badge", inputs: ["styleClass", "style", "badgeSize", "size", "severity", "value", "badgeDisabled"] }] });
1238
+ }
1239
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: BadgeNgComponent, decorators: [{
1240
+ type: Component,
1241
+ args: [{ selector: 'lib-badge-ng', imports: [BadgeModule], template: "<p-badge\r\n [style]=\"{\r\n textAlign: 'center',\r\n width: fullWidth ? '100%' : 'auto'\r\n }\"\r\n [value]=\"value\"\r\n [severity]=\"severity\"\r\n [badgeSize]=\"badgeSize\"\r\n/>\r\n" }]
1242
+ }] });
1243
+
1244
+ class ToolbarNgComponent {
1245
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: ToolbarNgComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1246
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: ToolbarNgComponent, isStandalone: true, selector: "lib-toolbar-ng", ngImport: i0, template: "<p-toolbar class=\"border-0 bg-transparent\">\r\n <ng-template pTemplate=\"start\">\r\n <ng-content select=\"[toolbarStart]\"></ng-content>\r\n </ng-template>\r\n\r\n <ng-template pTemplate=\"center\">\r\n <ng-content select=\"[toolbarCenter]\"></ng-content>\r\n </ng-template>\r\n\r\n <ng-template pTemplate=\"end\">\r\n <ng-content select=\"[toolbarEnd]\"></ng-content>\r\n </ng-template>\r\n</p-toolbar>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ToolbarModule }, { kind: "component", type: i1$4.Toolbar, selector: "p-toolbar", inputs: ["style", "styleClass", "ariaLabelledBy"] }, { kind: "directive", type: i4$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }] });
1247
+ }
1248
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: ToolbarNgComponent, decorators: [{
1249
+ type: Component,
1250
+ args: [{ selector: 'lib-toolbar-ng', imports: [
1251
+ ToolbarModule
1252
+ ], template: "<p-toolbar class=\"border-0 bg-transparent\">\r\n <ng-template pTemplate=\"start\">\r\n <ng-content select=\"[toolbarStart]\"></ng-content>\r\n </ng-template>\r\n\r\n <ng-template pTemplate=\"center\">\r\n <ng-content select=\"[toolbarCenter]\"></ng-content>\r\n </ng-template>\r\n\r\n <ng-template pTemplate=\"end\">\r\n <ng-content select=\"[toolbarEnd]\"></ng-content>\r\n </ng-template>\r\n</p-toolbar>\r\n" }]
1253
+ }] });
1254
+
1255
+ class TableNgEditService {
1256
+ editConfig = signal(undefined);
1257
+ keysNames = signal({});
1258
+ constructor() { }
1259
+ setEditConfig(editConfig) {
1260
+ this.editConfig.set(editConfig);
1261
+ }
1262
+ setKeysNames(keysNames) {
1263
+ this.keysNames.set(keysNames);
1264
+ }
1265
+ fb = inject(NonNullableFormBuilder);
1266
+ controls = computed(() => {
1267
+ const formValues = this.searchFormGroup().value;
1268
+ const controls = [
1269
+ {
1270
+ controlName: 'search',
1271
+ control: this.fb.control(formValues.search, { validators: [] }),
1272
+ typeInput: ETypeInput.TEXT,
1273
+ colSpan: 12,
1274
+ label: '-'
1275
+ }
1276
+ ];
1277
+ return controls;
1278
+ });
1279
+ searchFormGroup = signal(new FormGroup({}));
1280
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TableNgEditService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1281
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TableNgEditService, providedIn: 'root' });
1282
+ }
1283
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TableNgEditService, decorators: [{
1284
+ type: Injectable,
1285
+ args: [{
1286
+ providedIn: 'root'
1287
+ }]
1288
+ }], ctorParameters: () => [] });
1289
+
1290
+ class TableNgGeneralService {
1291
+ constructor() { }
1292
+ MOCK_EMPTY_DATE = new Date(1900, 0, 1);
1293
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TableNgGeneralService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1294
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TableNgGeneralService, providedIn: 'root' });
1295
+ }
1296
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TableNgGeneralService, decorators: [{
1297
+ type: Injectable,
1298
+ args: [{
1299
+ providedIn: 'root'
1300
+ }]
1301
+ }], ctorParameters: () => [] });
1302
+
1303
+ // import { CustomDialogService } from '../../dynamic-dialog/services/custom-dialog.service'
1304
+ class TableNgService {
1305
+ tableNgGeneralService = inject(TableNgGeneralService);
1306
+ filterService = inject(FilterService);
1307
+ // private readonly dialogService = inject(CustomDialogService)
1308
+ initialValue;
1309
+ constructor() {
1310
+ this.filterService.register('globalCustomFilter', (rowData, filter) => {
1311
+ if (!filter || filter.trim() === '')
1312
+ return true;
1313
+ const searchTerm = filter.toLowerCase();
1314
+ // Si es string
1315
+ if (typeof rowData === 'string') {
1316
+ return rowData.toLowerCase().includes(searchTerm);
1317
+ }
1318
+ // Si es array de botones
1319
+ if (Array.isArray(rowData)) {
1320
+ return rowData.some((button) => {
1321
+ const label = button.label || '';
1322
+ return label.toLowerCase().includes(searchTerm);
1323
+ });
1324
+ }
1325
+ return false;
1326
+ });
1327
+ /**
1328
+ * Filtro para arrays de strings que verifica si el valor contiene alguno de los strings del filtro.
1329
+ * Uso: dt.filter(['valor1', 'valor2'], 'nombreColumna', 'arrayStringFilter')
1330
+ * @param rowData - Puede ser un string o array de strings
1331
+ * @param filter - Array de strings para filtrar
1332
+ * @returns true si encuentra coincidencias parciales (case-insensitive)
1333
+ */
1334
+ this.filterService.register('arrayStringFilter', (rowData, filter) => {
1335
+ // Si no hay filtro o el filtro está vacío, mostrar todos los elementos
1336
+ if (!filter || !Array.isArray(filter) || filter.length === 0)
1337
+ return true;
1338
+ // Si rowData es null, undefined o vacío, no mostrar el elemento
1339
+ if (rowData == null || rowData === '')
1340
+ return false;
1341
+ // Si rowData es un string
1342
+ if (typeof rowData === 'string') {
1343
+ return filter.some(filterValue => rowData.toLowerCase().includes(filterValue.toLowerCase()));
1344
+ }
1345
+ // Si rowData es un array de strings
1346
+ if (Array.isArray(rowData)) {
1347
+ return rowData.some(dataValue => filter.some(filterValue => typeof dataValue === 'string' &&
1348
+ dataValue.toLowerCase().includes(filterValue.toLowerCase())));
1349
+ }
1350
+ // Para otros tipos de datos, convertir a string si es posible
1351
+ const stringValue = String(rowData);
1352
+ if (stringValue && stringValue !== 'undefined' && stringValue !== 'null') {
1353
+ return filter.some(filterValue => stringValue.toLowerCase().includes(filterValue.toLowerCase()));
1354
+ }
1355
+ return false;
1356
+ });
1357
+ /**
1358
+ * Filtro exacto para arrays de strings que verifica coincidencias exactas.
1359
+ * Uso: dt.filter(['valor1', 'valor2'], 'nombreColumna', 'arrayStringExactFilter')
1360
+ * @param rowData - Puede ser un string o array de strings
1361
+ * @param filter - Array de strings para filtrar
1362
+ * @returns true si encuentra coincidencias exactas (case-sensitive)
1363
+ */
1364
+ this.filterService.register('arrayStringExactFilter', (rowData, filter) => {
1365
+ if (!filter || !Array.isArray(filter) || filter.length === 0)
1366
+ return true;
1367
+ // Si rowData es null, undefined o vacío, no mostrar el elemento
1368
+ if (rowData == null || rowData === '')
1369
+ return false;
1370
+ // Si rowData es un string
1371
+ if (typeof rowData === 'string') {
1372
+ return filter.includes(rowData);
1373
+ }
1374
+ // Si rowData es un array de strings
1375
+ if (Array.isArray(rowData)) {
1376
+ return rowData.some(dataValue => filter.includes(dataValue));
1377
+ }
1378
+ // Para otros tipos de datos, convertir a string si es posible
1379
+ const stringValue = String(rowData);
1380
+ if (stringValue && stringValue !== 'undefined' && stringValue !== 'null') {
1381
+ return filter.includes(stringValue);
1382
+ }
1383
+ return false;
1384
+ });
1385
+ this.filterService.register('customIn', (rowData, filter) => {
1386
+ if (!filter || !Array.isArray(filter) || filter.length === 0)
1387
+ return true;
1388
+ // Si rowData es null, undefined o vacío, no mostrar el elemento
1389
+ if (rowData == null || rowData === '')
1390
+ return false;
1391
+ if (typeof rowData === 'string') {
1392
+ return filter.includes(rowData);
1393
+ }
1394
+ // Para otros tipos de datos, convertir a string si es posible
1395
+ const stringValue = String(rowData);
1396
+ if (stringValue && stringValue !== 'undefined' && stringValue !== 'null') {
1397
+ return filter.includes(stringValue);
1398
+ }
1399
+ return false;
1400
+ });
1401
+ }
1402
+ get MOCK_EMPTY_DATE() {
1403
+ return this.tableNgGeneralService.MOCK_EMPTY_DATE;
1404
+ }
1405
+ setInitialValue(data) {
1406
+ this.initialValue = data;
1407
+ }
1408
+ //#region SORT
1409
+ customSort(event) {
1410
+ let field = undefined;
1411
+ let order = undefined;
1412
+ switch (event.mode) {
1413
+ case 'single':
1414
+ field = event.field;
1415
+ order = event.order;
1416
+ break;
1417
+ case 'multiple': {
1418
+ const multiSortMeta = event.multiSortMeta ?? [];
1419
+ const sortMeta = multiSortMeta[0];
1420
+ field = sortMeta?.field ?? undefined;
1421
+ order = sortMeta?.order ?? undefined;
1422
+ break;
1423
+ }
1424
+ default:
1425
+ break;
1426
+ }
1427
+ if (!field || order === undefined)
1428
+ return;
1429
+ const data = event.data ?? [];
1430
+ if (order === 0) {
1431
+ // Sin sorting - restaurar orden original
1432
+ data.splice(0, data.length, ...this.initialValue);
1433
+ }
1434
+ else {
1435
+ // Aplicar sorting
1436
+ data.sort((a, b) => {
1437
+ const valueA = this.getFieldValue(a, field);
1438
+ const valueB = this.getFieldValue(b, field);
1439
+ const result = this.compareValues(valueA, valueB);
1440
+ return order * result; // 1 para ASC, -1 para DESC
1441
+ });
1442
+ }
1443
+ }
1444
+ getFieldValue(item, field) {
1445
+ const rawValue = item.rowData[field];
1446
+ // Si es un array (probablemente IButtonConfig[])
1447
+ if (Array.isArray(rawValue) && rawValue.length > 0) {
1448
+ // Verificar si tenemos configuración de sorting para este campo
1449
+ const buttonKeyToSort = item.sortConfig?.buttonKeyToSort?.[field];
1450
+ if (buttonKeyToSort) {
1451
+ // Usar la primera configuración de botón del array
1452
+ const firstButton = rawValue[0];
1453
+ return firstButton[buttonKeyToSort];
1454
+ }
1455
+ // Si no hay configuración, intentar usar 'label' por defecto
1456
+ const firstButton = rawValue[0];
1457
+ return firstButton.label || '';
1458
+ }
1459
+ // Si es un string o cualquier otro tipo
1460
+ return rawValue;
1461
+ }
1462
+ compareValues(a, b) {
1463
+ // Manejar valores null/undefined
1464
+ if (a == null && b == null)
1465
+ return 0;
1466
+ if (a == null)
1467
+ return -1;
1468
+ if (b == null)
1469
+ return 1;
1470
+ // Si ambos son strings, usar localeCompare para mejor sorting
1471
+ if (typeof a === 'string' && typeof b === 'string') {
1472
+ return a.toLowerCase().localeCompare(b.toLowerCase());
1473
+ }
1474
+ // Si ambos son números
1475
+ if (typeof a === 'number' && typeof b === 'number') {
1476
+ return a - b;
1477
+ }
1478
+ // Si ambos son booleanos
1479
+ if (typeof a === 'boolean' && typeof b === 'boolean') {
1480
+ return a === b ? 0 : a ? 1 : -1;
1481
+ }
1482
+ // Si son fechas
1483
+ if (a instanceof Date && b instanceof Date) {
1484
+ return a.getTime() - b.getTime();
1485
+ }
1486
+ // Para otros tipos, convertir a string y comparar
1487
+ const strA = String(a).toLowerCase();
1488
+ const strB = String(b).toLowerCase();
1489
+ return strA.localeCompare(strB);
1490
+ }
1491
+ //#endregion
1492
+ //#region Global Filter
1493
+ fb = inject(NonNullableFormBuilder);
1494
+ controls = computed(() => {
1495
+ const formValues = this.searchFormGroup().value;
1496
+ const controls = [
1497
+ {
1498
+ controlName: 'search',
1499
+ control: this.fb.control(formValues.search, { validators: [] }),
1500
+ typeInput: ETypeInput.TEXT,
1501
+ colSpan: 12,
1502
+ label: 'Buscar'
1503
+ }
1504
+ ];
1505
+ return controls;
1506
+ });
1507
+ searchFormGroup = signal(new FormGroup({}));
1508
+ values = toSignal(this.searchFormGroup().valueChanges);
1509
+ submitGlobalSearch(formGroup, dt) {
1510
+ const search = formGroup.value.search ?? '';
1511
+ dt.filterGlobal(search, 'globalCustomFilter');
1512
+ }
1513
+ clearSearchInput() {
1514
+ this.searchFormGroup().get('search')?.setValue('');
1515
+ }
1516
+ //#endregion
1517
+ //#region Selection
1518
+ async openModalManagementSelectedItems(selectedItems, config) {
1519
+ const { SelectedItemsManagementComponent } = await import('./ln-20-lib-components-selected-items-management.component-CrgtLkUn.mjs');
1520
+ let configSelectedItems = config;
1521
+ if (config) {
1522
+ configSelectedItems = structuredClone(config);
1523
+ const selectionTableConfig = {
1524
+ ...(configSelectedItems.selectionTableConfig ?? {}),
1525
+ showManagementConfig: false
1526
+ };
1527
+ delete configSelectedItems.lazyLoadingConfig;
1528
+ configSelectedItems.selectionTableConfig = selectionTableConfig;
1529
+ }
1530
+ // const ref = this.dialogService?.open(SelectedItemsManagementComponent, {
1531
+ // header: 'Gestionar Seleccionados',
1532
+ // data: {
1533
+ // selectedItems: selectedItems(),
1534
+ // config: configSelectedItems
1535
+ // },
1536
+ // width: '90%',
1537
+ // height: '90%',
1538
+ // styleClass: 'overflow-hidden'
1539
+ // })
1540
+ // ref.onClose.subscribe((selectedReturnItems: ITableNgData[] | undefined) => {
1541
+ // if (selectedReturnItems) {
1542
+ // selectedItems.set(selectedReturnItems)
1543
+ // }
1544
+ // })
1545
+ }
1546
+ //#endregion
1547
+ //#region Custom Filter
1548
+ //#endregion
1549
+ excelButton = computed(() => {
1550
+ return {
1551
+ label: '',
1552
+ icon: 'fa-solid fa-file-excel',
1553
+ variant: 'text',
1554
+ severity: 'success',
1555
+ raised: true,
1556
+ size: 'large',
1557
+ tooltipConfig: {
1558
+ pTooltip: 'Exportar a Excel',
1559
+ tooltipPosition: 'top'
1560
+ }
1561
+ };
1562
+ });
1563
+ pdfButton = computed(() => {
1564
+ return {
1565
+ label: '',
1566
+ icon: 'fa-solid fa-file-pdf',
1567
+ variant: 'text',
1568
+ severity: 'danger',
1569
+ raised: true,
1570
+ size: 'large',
1571
+ tooltipConfig: {
1572
+ pTooltip: 'Exportar a PDF',
1573
+ tooltipPosition: 'top'
1574
+ }
1575
+ };
1576
+ });
1577
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TableNgService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1578
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TableNgService, providedIn: 'root' });
1579
+ }
1580
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TableNgService, decorators: [{
1581
+ type: Injectable,
1582
+ args: [{
1583
+ providedIn: 'root'
1584
+ }]
1585
+ }], ctorParameters: () => [] });
1586
+
1587
+ /* eslint-disable @typescript-eslint/no-unsafe-argument */
1588
+ class TableNgComponent {
1589
+ tableNgService = inject(TableNgService);
1590
+ tableNgEditService = inject(TableNgEditService);
1591
+ // private readonly dialogService = inject(CustomDialogService)
1592
+ data = model.required();
1593
+ // Loading state management
1594
+ loadingTimeout = null;
1595
+ isLoading = signal(false);
1596
+ timeoutExpired = signal(false);
1597
+ config = model();
1598
+ editConfig = model();
1599
+ footerConfig = model();
1600
+ toolbarButtons = model([]);
1601
+ sourceElements = model([]);
1602
+ targetElements = model([]);
1603
+ httpMessage = model();
1604
+ lazyLoading = output();
1605
+ outputChangeData = output();
1606
+ outputHandleEditInitButton = output();
1607
+ outputAddRow = output();
1608
+ outputDeleteRow = output();
1609
+ outputRowInlineChange = output();
1610
+ outputRowDataChange = output();
1611
+ outputEditData = output();
1612
+ outputIsEditing = output();
1613
+ resetData() {
1614
+ this.data.set([]);
1615
+ }
1616
+ advancedFiltersPerformed = [];
1617
+ advancedFiltersValues = signal({});
1618
+ dt;
1619
+ fb = inject(NonNullableFormBuilder);
1620
+ constructor() {
1621
+ this.tableNgEditService.setEditConfig(this.editConfig());
1622
+ this.tableNgEditService.setKeysNames(this.config()?.keysNames ?? {});
1623
+ effect(() => {
1624
+ this.outputChangeData.emit([...this.data()]);
1625
+ });
1626
+ // Effect para gestionar el loading basado en el estado de data
1627
+ effect(() => {
1628
+ const currentData = this.data();
1629
+ // Limpiar el timeout anterior si existe
1630
+ if (this.loadingTimeout) {
1631
+ clearTimeout(this.loadingTimeout);
1632
+ this.loadingTimeout = null;
1633
+ }
1634
+ if (currentData.length === 0) {
1635
+ // Si data está vacío, activar loading
1636
+ this.isLoading.set(true);
1637
+ this.loadingTimeout = setTimeout(() => {
1638
+ if (this.data().length === 0) {
1639
+ this.isLoading.set(false);
1640
+ this.timeoutExpired.set(true);
1641
+ }
1642
+ }, 0);
1643
+ }
1644
+ else {
1645
+ // Si hay data, desactivar loading y resetear timeout
1646
+ this.isLoading.set(false);
1647
+ this.timeoutExpired.set(false);
1648
+ }
1649
+ });
1650
+ }
1651
+ ngOnInit() {
1652
+ this.tableNgService.setInitialValue([...this.data()]);
1653
+ }
1654
+ ngOnDestroy() {
1655
+ // Limpiar el timeout al destruir el componente
1656
+ if (this.loadingTimeout) {
1657
+ clearTimeout(this.loadingTimeout);
1658
+ this.loadingTimeout = null;
1659
+ }
1660
+ }
1661
+ get hideToolbar() { return this.config()?.hideToolbar ?? false; }
1662
+ /**
1663
+ * Calcula el número total de columnas para el colspan del mensaje vacío
1664
+ */
1665
+ totalColumns = computed(() => {
1666
+ const selectedColumns = this.config()?.selectedColumns ?? [];
1667
+ const baseColumns = selectedColumns.length > 0 ? selectedColumns.length : this.keys().length;
1668
+ const selectionColumn = this.config()?.selectionTableConfig?.isEnabled ? 1 : 0;
1669
+ const expansionColumn = this.config()?.rowExpansionConfig?.isEnabled ? 1 : 0;
1670
+ const editColumn = (this.editConfig()?.type === 'row' || this.editConfig()?.type === 'cell') && this.editConfig()?.isEnabled ? 1 : 0;
1671
+ return baseColumns + selectionColumn + expansionColumn + editColumn;
1672
+ });
1673
+ isPrimeNgSelection(value) {
1674
+ return PrimeNgUtil.isPrimeNgSelection(value);
1675
+ }
1676
+ hasErrorValues(object) {
1677
+ return Object.keys(object).length > 0;
1678
+ }
1679
+ rowFieldsValue = signal({});
1680
+ rowFieldsHasValue = computed(() => {
1681
+ return Object.keys(this.rowFieldsValue()).reduce((acc, key) => {
1682
+ acc[key] = !!this.rowFieldsValue()[key];
1683
+ return acc;
1684
+ }, {});
1685
+ });
1686
+ inlineChange(value, key) {
1687
+ this.rowFieldsValue.update((prev) => {
1688
+ return { ...prev, [key]: value };
1689
+ });
1690
+ this.outputRowInlineChange.emit({ ...this.rowFieldsValue() });
1691
+ }
1692
+ trackById(index, item) {
1693
+ return item.id;
1694
+ }
1695
+ frozenHandle(value) {
1696
+ return value ? value : false;
1697
+ }
1698
+ isDate(value) {
1699
+ return value instanceof Date;
1700
+ }
1701
+ onFilter(event) {
1702
+ const filters = event.filters;
1703
+ if (!filters)
1704
+ return;
1705
+ const global = filters['global'];
1706
+ if (!global?.['value']) {
1707
+ this.handleAdvancedFiltersPerformed(filters);
1708
+ }
1709
+ }
1710
+ resetRowDatas() {
1711
+ this.data.update((data) => {
1712
+ return data.map((item) => {
1713
+ return {
1714
+ ...item,
1715
+ rowData: {}
1716
+ };
1717
+ });
1718
+ });
1719
+ }
1720
+ get ETypeInput() {
1721
+ return ETypeInput;
1722
+ }
1723
+ handleAdvancedFiltersPerformed(filters) {
1724
+ if (!filters)
1725
+ return;
1726
+ const entriesFilters = Object.entries(filters);
1727
+ const keysColumn = this.config()?.keys ?? [];
1728
+ entriesFilters.forEach(([key, value]) => {
1729
+ const valueArray = value;
1730
+ const hasValue = !!valueArray[0]?.value;
1731
+ const keyColumn = key.split('.')[1];
1732
+ if (keysColumn.includes(keyColumn)) {
1733
+ const index = this.advancedFiltersPerformed.indexOf(keyColumn);
1734
+ if (hasValue && index === -1) {
1735
+ // Agregar si no existe
1736
+ this.advancedFiltersPerformed.push(keyColumn);
1737
+ }
1738
+ else if (!hasValue && index !== -1) {
1739
+ // Quitar si ya no tiene valor
1740
+ this.advancedFiltersPerformed.splice(index, 1);
1741
+ }
1742
+ }
1743
+ });
1744
+ }
1745
+ numberOfRecords = computed(() => {
1746
+ return this.data().length ?? 0;
1747
+ });
1748
+ hasRecords = computed(() => {
1749
+ return this.numberOfRecords() > 0;
1750
+ });
1751
+ /**
1752
+ * Computed que valida si al menos una fila tiene datos válidos en rowData.
1753
+ * Retorna true si al menos una fila tiene un valor que no sea '', null o undefined.
1754
+ * Retorna false si todas las filas tienen valores vacíos, null o undefined.
1755
+ */
1756
+ hasValidRowData = computed(() => {
1757
+ const data = this.data();
1758
+ return data.some(item => {
1759
+ if (!item?.rowData || typeof item.rowData !== 'object') {
1760
+ return false;
1761
+ }
1762
+ const values = Object.values(item.rowData);
1763
+ // Verificar si al menos un valor es válido (no vacío, null o undefined)
1764
+ return values.some(value => {
1765
+ if (value === null || value === undefined || value === '') {
1766
+ return false;
1767
+ }
1768
+ // Si es string, verificar que no esté vacío después de trim
1769
+ if (typeof value === 'string') {
1770
+ return value.trim() !== '';
1771
+ }
1772
+ // Para otros tipos (números, fechas, booleanos, etc.)
1773
+ return true;
1774
+ });
1775
+ });
1776
+ });
1777
+ keys = computed(() => {
1778
+ return this.config()?.keys ?? [];
1779
+ });
1780
+ onRowClick(item) {
1781
+ item.onClick();
1782
+ }
1783
+ //#region Scroll Config
1784
+ scrollHeight = computed(() => {
1785
+ const scrollHeightInitial = this.config()?.scrollConfig?.scrollHeight ?? '58vh';
1786
+ let res = scrollHeightInitial;
1787
+ if (this.showBottomToolbar()) {
1788
+ const { number: size, unit } = this.parseValue(scrollHeightInitial);
1789
+ res = `${size - 7.6}${unit}`;
1790
+ }
1791
+ return res;
1792
+ });
1793
+ parseValue(str) {
1794
+ const match = str.match(/^(-?\d+\.?\d*)(.*)$/);
1795
+ if (match) {
1796
+ return {
1797
+ number: parseFloat(match[1]),
1798
+ unit: match[2]
1799
+ };
1800
+ }
1801
+ return { number: 0, unit: '' };
1802
+ }
1803
+ //#endregion
1804
+ //#region Paginator Config
1805
+ paginatorStyleClass = computed(() => {
1806
+ if (this.showBottomToolbar()) {
1807
+ return 'p-datatable-paginator p-datatable-paginator-bottom sticky bottom-18 z-10';
1808
+ }
1809
+ return 'p-datatable-paginator p-datatable-paginator-bottom sticky bottom-2 z-10';
1810
+ });
1811
+ //#endregion
1812
+ //#region toolbar config
1813
+ showBottomToolbar = computed(() => {
1814
+ return this.showManagementSelectionConfig();
1815
+ });
1816
+ //#endregion
1817
+ //#region Clear Filters
1818
+ clearFilters() {
1819
+ this.tableNgService.clearSearchInput();
1820
+ this.advancedFiltersPerformed = [];
1821
+ this.advancedFiltersValues.set({});
1822
+ this.dt.clear();
1823
+ this.targetElements.set([]);
1824
+ this.handleTableValueToSourceElements();
1825
+ this.selectedItems.set([]);
1826
+ }
1827
+ get filteredValue() {
1828
+ return !!this.dt?.filteredValue && this.dt.filteredValue.length > 0;
1829
+ }
1830
+ clearFiltersButton = computed(() => {
1831
+ return {
1832
+ icon: 'fa-solid fa-filter-circle-xmark',
1833
+ rounded: true,
1834
+ raised: true,
1835
+ severity: 'contrast',
1836
+ tooltipConfig: {
1837
+ pTooltip: 'Limpiar filtros'
1838
+ },
1839
+ onClick: () => {
1840
+ this.clearFilters();
1841
+ }
1842
+ };
1843
+ });
1844
+ //#endregion
1845
+ //#region Global Filter
1846
+ get controlsGlobalFilter() {
1847
+ return this.tableNgService.controls();
1848
+ }
1849
+ get searchFormGroupGlobalFilter() {
1850
+ return this.tableNgService.searchFormGroup();
1851
+ }
1852
+ submitGlobalSearch(formGroup) {
1853
+ this.dt.globalFilterFields = this.config()?.globalFilterConfig?.globalFilterFields ?? [];
1854
+ this.tableNgService.submitGlobalSearch(formGroup, this.dt);
1855
+ }
1856
+ //#endregion
1857
+ //#region SORT
1858
+ customSort(event) {
1859
+ this.tableNgService.customSort(event);
1860
+ }
1861
+ //#endregion
1862
+ //#region Selection
1863
+ selectedItems = model([]);
1864
+ totalItemsSelected = computed(() => this.selectedItems().length);
1865
+ showManagementSelectionConfig = computed(() => this.totalItemsSelected() > 0 && (this.config()?.selectionTableConfig?.showManagementConfig ?? false));
1866
+ buttonTotalItemsSelected = computed(() => {
1867
+ return {
1868
+ label: this.totalItemsSelected().toLocaleString(),
1869
+ variant: 'text',
1870
+ rounded: true
1871
+ };
1872
+ });
1873
+ showSelectedItemsManagementButton = computed(() => {
1874
+ return {
1875
+ icon: 'fa-solid fa-eye',
1876
+ rounded: true,
1877
+ variant: 'text',
1878
+ severity: 'secondary',
1879
+ onClick: () => {
1880
+ this.openModalManagementSelectedItems();
1881
+ }
1882
+ };
1883
+ });
1884
+ openModalManagementSelectedItems() {
1885
+ this.tableNgService.openModalManagementSelectedItems(this.selectedItems, this.config())
1886
+ .then(() => { })
1887
+ .catch(() => { });
1888
+ }
1889
+ //#endregion
1890
+ //#region Custom Filter
1891
+ inlineFormChanges(inlineValue, filter, typeInput, key) {
1892
+ const lazyLoadingConfig = this.config()?.lazyLoadingConfig;
1893
+ if (typeInput === ETypeInput.MULTISELECT) {
1894
+ const options = inlineValue ? inlineValue : undefined;
1895
+ const arrayValue = options ? options.map((data) => lazyLoadingConfig?.isEnabled ? data.code : data.name) : undefined;
1896
+ if (Array.isArray(arrayValue) && arrayValue.length === 0) {
1897
+ if (key) {
1898
+ this.advancedFiltersValues.update((prev) => {
1899
+ const { [key]: _value, ...rest } = prev;
1900
+ return { ...rest };
1901
+ });
1902
+ }
1903
+ }
1904
+ if (inlineValue && (Array.isArray(arrayValue) && arrayValue.length > 0)) {
1905
+ filter(arrayValue);
1906
+ }
1907
+ }
1908
+ }
1909
+ formChanges(formValue, filter, key) {
1910
+ if (Array.isArray(formValue['multiSelect'])) {
1911
+ this.advancedFiltersValues.update((prev) => {
1912
+ return { ...prev, [key]: formValue };
1913
+ });
1914
+ }
1915
+ if (!Array.isArray(formValue['multiSelect']) && this.advancedFiltersValues()?.[key]) {
1916
+ this.advancedFiltersValues.update((prev) => {
1917
+ const { [key]: _value, ...rest } = prev;
1918
+ return { ...rest };
1919
+ });
1920
+ }
1921
+ const arrayValue = Array.isArray(formValue['multiSelect'])
1922
+ ? formValue['multiSelect'].map((data) => data.code)
1923
+ : [];
1924
+ if (arrayValue.length > 0) {
1925
+ filter(arrayValue);
1926
+ }
1927
+ }
1928
+ rowDataKey(key) {
1929
+ return `rowData.${key}`;
1930
+ }
1931
+ //#endregion
1932
+ //#region Lazy Loading
1933
+ onLazyLoad(event) {
1934
+ const filters = event.filters ?? {};
1935
+ const filtersWithValue = this.getFiltersWithValue(filters);
1936
+ const metaPagination = {
1937
+ limit: event.rows ?? undefined,
1938
+ skip: event.first ?? undefined
1939
+ };
1940
+ if (event.sortOrder) {
1941
+ metaPagination.sortOrder = event.sortOrder === 1 ? 'ASC' : 'DESC';
1942
+ }
1943
+ if (event.sortField) {
1944
+ metaPagination.sortBy = event.sortField;
1945
+ }
1946
+ const lazyLoadResponse = {
1947
+ filters: filtersWithValue,
1948
+ metaPagination
1949
+ };
1950
+ this.lazyLoading.emit(lazyLoadResponse);
1951
+ }
1952
+ getFiltersWithValue(filters) {
1953
+ const result = {};
1954
+ Object.entries(filters).forEach(([key, filter]) => {
1955
+ const keyColumn = key.split('.')[1];
1956
+ if (!filter)
1957
+ return;
1958
+ if (Array.isArray(filter)) {
1959
+ // Si es un array, filtrar solo los elementos que tienen value
1960
+ const filtersWithValue = filter.filter(f => f.value !== undefined && f.value !== null && f.value !== '');
1961
+ if (filtersWithValue.length > 0) {
1962
+ result[keyColumn] = filtersWithValue;
1963
+ }
1964
+ }
1965
+ else {
1966
+ // Si es un objeto único, verificar si tiene value
1967
+ if (filter.value !== undefined && filter.value !== null && filter.value !== '') {
1968
+ result[keyColumn] = filter;
1969
+ }
1970
+ }
1971
+ });
1972
+ return result;
1973
+ }
1974
+ //#endregion
1975
+ //#region Edit
1976
+ onCellValueChange() {
1977
+ this.updateDataWithTableValue();
1978
+ }
1979
+ onRowDataChange(_data) {
1980
+ }
1981
+ onEditData() {
1982
+ this.updateDataWithTableValue();
1983
+ this.outputEditData.emit([...this.data()]);
1984
+ }
1985
+ get controlsEdit() {
1986
+ return this.tableNgEditService.controls();
1987
+ }
1988
+ get searchFormGroupEdit() {
1989
+ return this.tableNgEditService.searchFormGroup();
1990
+ }
1991
+ customControlConfig(key, value) {
1992
+ return {
1993
+ controlName: key,
1994
+ control: this.fb.control(value),
1995
+ typeInput: ETypeInput.TEXT
1996
+ };
1997
+ }
1998
+ cellFormGroup = this.fb.group({});
1999
+ //#region Row
2000
+ addRowButton = computed(() => {
2001
+ const editConfig = this.editConfig();
2002
+ const isDisabled = editConfig?.type === 'cell'
2003
+ ? (editConfig?.cellEditConfig?.isDisabledAddButton ?? false)
2004
+ : (editConfig?.rowEditConfig?.isDisabledAddButton ?? false) || this.hasRowInEdit;
2005
+ const button = {
2006
+ icon: 'fa-solid fa-plus',
2007
+ rounded: true,
2008
+ severity: 'success',
2009
+ tooltipConfig: {
2010
+ pTooltip: 'Agregar registro',
2011
+ tooltipPosition: 'top'
2012
+ },
2013
+ onClick: () => {
2014
+ this.addRow();
2015
+ },
2016
+ disabled: isDisabled
2017
+ };
2018
+ return button;
2019
+ });
2020
+ addRow() {
2021
+ const editConfig = this.editConfig();
2022
+ // Si es modo cell y hay defaultTableNgData configurado, agregar la fila directamente
2023
+ if (editConfig?.type === 'cell' && editConfig?.cellEditConfig?.defaultTableNgData) {
2024
+ const newRow = this.editConfig()?.cellEditConfig?.defaultTableNgData;
2025
+ if (newRow) {
2026
+ this.data.update(currentData => [...currentData, newRow]);
2027
+ this.outputChangeData.emit(this.data());
2028
+ return;
2029
+ }
2030
+ }
2031
+ // Comportamiento original para modo row o cuando no hay defaultTableNgData
2032
+ this.outputAddRow.emit(this.data());
2033
+ this.setEditingRowId(null);
2034
+ }
2035
+ defaultTableNgData = computed(() => {
2036
+ const editConfig = this.editConfig();
2037
+ let defaultData;
2038
+ // Usar la configuración apropiada según el tipo de edición
2039
+ if (editConfig?.type === 'cell' && editConfig?.cellEditConfig?.defaultTableNgData) {
2040
+ defaultData = editConfig.cellEditConfig.defaultTableNgData;
2041
+ }
2042
+ else if (editConfig?.type === 'row' && editConfig?.rowEditConfig?.defaultTableNgData) {
2043
+ defaultData = editConfig.rowEditConfig.defaultTableNgData;
2044
+ }
2045
+ const res = { ...defaultData };
2046
+ return {
2047
+ ...res,
2048
+ id: generateId()
2049
+ };
2050
+ });
2051
+ clonedRowData = null;
2052
+ editingRowId = signal(null);
2053
+ /**
2054
+ * Verifica si una fila específica está siendo editada
2055
+ */
2056
+ isRowEditing(id) {
2057
+ return this.editingRowId() === id;
2058
+ }
2059
+ /**
2060
+ * Verifica si hay alguna fila siendo editada actualmente
2061
+ */
2062
+ get hasRowInEdit() {
2063
+ return this.editingRowId() !== null;
2064
+ }
2065
+ onRowEditInit(data) {
2066
+ // Verificar si ya hay una fila en edición
2067
+ this.clonedRowData = structuredClone(data.rowData);
2068
+ this.setEditingRowId(data.id);
2069
+ this.outputHandleEditInitButton.emit(data);
2070
+ }
2071
+ setEditingRowId(id) {
2072
+ this.editingRowId.set(id);
2073
+ this.outputIsEditing.emit(true);
2074
+ }
2075
+ onRowEditSave(_data) {
2076
+ this.clonedRowData = null;
2077
+ this.editingRowId.set(null);
2078
+ this.updateDataWithTableValue();
2079
+ this.setEnableErrors(false);
2080
+ this.outputIsEditing.emit(false);
2081
+ this.outputRowDataChange.emit(_data);
2082
+ }
2083
+ onRowEditCancel(data, index) {
2084
+ if (this.clonedRowData && this.editingRowId() === data.id) {
2085
+ const items = [...this.data()];
2086
+ items[index] = { ...items[index], rowData: this.clonedRowData };
2087
+ this.data.set(items);
2088
+ }
2089
+ this.clonedRowData = null;
2090
+ this.setEditingRowId(null);
2091
+ this.setEnableErrors(false);
2092
+ this.outputIsEditing.emit(false);
2093
+ }
2094
+ updateDataWithTableValue() {
2095
+ const tableValue = (this.dt.value ?? []);
2096
+ this.data.set([...tableValue]);
2097
+ }
2098
+ editInitButton = computed(() => {
2099
+ return {
2100
+ icon: 'fa-solid fa-pencil',
2101
+ rounded: true,
2102
+ variant: 'text',
2103
+ severity: 'secondary'
2104
+ };
2105
+ });
2106
+ getEditInitButton(productId) {
2107
+ return {
2108
+ ...this.editInitButton(),
2109
+ disabled: this.hasRowInEdit && !this.isRowEditing(productId)
2110
+ };
2111
+ }
2112
+ editSaveButton = computed(() => {
2113
+ return {
2114
+ icon: 'fa-solid fa-check',
2115
+ rounded: true,
2116
+ variant: 'text',
2117
+ severity: 'secondary'
2118
+ };
2119
+ });
2120
+ editSaveButtonWithErrors = computed(() => {
2121
+ return {
2122
+ icon: 'fa-solid fa-check',
2123
+ rounded: true,
2124
+ variant: 'text',
2125
+ severity: 'secondary'
2126
+ };
2127
+ });
2128
+ enableErrors = false;
2129
+ setEnableErrors(value) {
2130
+ this.enableErrors = value;
2131
+ }
2132
+ onEditSaveWithErrors() {
2133
+ this.setEnableErrors(true);
2134
+ }
2135
+ editCancelButton = computed(() => {
2136
+ return {
2137
+ icon: 'fa-solid fa-times',
2138
+ rounded: true,
2139
+ variant: 'text',
2140
+ severity: 'secondary'
2141
+ };
2142
+ });
2143
+ deleteRowButton = computed(() => {
2144
+ return {
2145
+ icon: 'fa-solid fa-trash',
2146
+ rounded: true,
2147
+ variant: 'text',
2148
+ severity: 'danger'
2149
+ };
2150
+ });
2151
+ getDeleteRowButton() {
2152
+ return {
2153
+ ...this.deleteRowButton(),
2154
+ disabled: this.hasRowInEdit
2155
+ };
2156
+ }
2157
+ removeRowFromData(data) {
2158
+ const { id } = data;
2159
+ const items = [...this.data()];
2160
+ items.splice(items.findIndex(item => item.id === id), 1);
2161
+ this.data.set(items);
2162
+ this.outputDeleteRow.emit(data);
2163
+ }
2164
+ deleteRow(data) {
2165
+ this.removeRowFromData(data);
2166
+ this.outputEditData.emit(this.data());
2167
+ }
2168
+ //#endregion Row
2169
+ get footerRows() {
2170
+ return this.footerConfig()?.footerRows || [];
2171
+ }
2172
+ applyPipe(value, pipeConfig) {
2173
+ if (!pipeConfig || !pipeConfig.pipe) {
2174
+ return value?.toString() || '';
2175
+ }
2176
+ switch (pipeConfig.pipe) {
2177
+ case 'currency': {
2178
+ const currencyCode = pipeConfig.args?.[0] || 'COP';
2179
+ return new Intl.NumberFormat('es-CO', {
2180
+ style: 'currency',
2181
+ currency: currencyCode
2182
+ }).format(value);
2183
+ }
2184
+ case 'number': {
2185
+ const digits = pipeConfig.args?.[0] || '1.2-2';
2186
+ const [minInteger, fractional] = digits.split('.');
2187
+ const [minFractional, maxFractional] = fractional ? fractional.split('-') : ['0', '0'];
2188
+ return new Intl.NumberFormat('es-CO', {
2189
+ minimumIntegerDigits: parseInt(minInteger),
2190
+ minimumFractionDigits: parseInt(minFractional),
2191
+ maximumFractionDigits: parseInt(maxFractional || minFractional)
2192
+ }).format(value);
2193
+ }
2194
+ case 'date': {
2195
+ if (value instanceof Date) {
2196
+ return value.toLocaleDateString('es-CO');
2197
+ }
2198
+ return value?.toString() || '';
2199
+ }
2200
+ default:
2201
+ return value?.toString() || '';
2202
+ }
2203
+ }
2204
+ // #endregion
2205
+ //#region Row Expansion
2206
+ rowExpansionButton(isRowExpanded) {
2207
+ return computed(() => {
2208
+ return {
2209
+ icon: isRowExpanded ? 'fa-solid fa-chevron-down' : 'fa-solid fa-chevron-right',
2210
+ rounded: true,
2211
+ variant: 'text',
2212
+ severity: 'contrast'
2213
+ };
2214
+ });
2215
+ }
2216
+ //#endregion
2217
+ itemTemplateInput = input(null);
2218
+ itemTemplate;
2219
+ get currentItemTemplate() {
2220
+ return this.itemTemplateInput() || this.itemTemplate || null;
2221
+ }
2222
+ isThatItemInTheProductSelection(field) {
2223
+ const selectedColumns = this.config()?.selectedColumns ?? [];
2224
+ if (!selectedColumns.length) {
2225
+ return true;
2226
+ }
2227
+ return selectedColumns.some((column) => column.field === field);
2228
+ }
2229
+ //#region Advanced Identifier Filters
2230
+ advancedIdentifierFiltersButton = computed(() => {
2231
+ return {
2232
+ icon: 'pi pi-filter',
2233
+ rounded: true,
2234
+ severity: 'warn',
2235
+ raised: true,
2236
+ tooltipConfig: {
2237
+ pTooltip: this.data().length === 0 ? 'No hay datos para filtrar' : 'Filtros avanzados',
2238
+ tooltipPosition: 'top'
2239
+ },
2240
+ onClick: () => {
2241
+ this.openAdvancedIdentifierFilters();
2242
+ },
2243
+ disabled: this.data().length === 0
2244
+ };
2245
+ });
2246
+ openAdvancedIdentifierFilters() {
2247
+ if (this.sourceElements().length === 0) {
2248
+ this.handleTableValueToSourceElements();
2249
+ }
2250
+ this.handleSelectedItemsToSourceElements();
2251
+ if (this.data().length === 0) {
2252
+ return;
2253
+ }
2254
+ // const ref = this.dialogService.open(ModalAdvancedFilterComponent, {
2255
+ // header: 'Filtros Avanzados',
2256
+ // width: '70%',
2257
+ // height: '70%',
2258
+ // styleClass: 'overflow-hidden',
2259
+ // data: {
2260
+ // sourceElements: this.sourceElements(),
2261
+ // targetElements: this.targetElements()
2262
+ // }
2263
+ // })
2264
+ // ref.onClose.subscribe((result: { success: boolean, data: { sourceElements: IPickListElement[], targetElements: IPickListElement[] } }) => {
2265
+ // const { sourceElements, targetElements } = result?.data ?? {}
2266
+ // if (!result?.success) {
2267
+ // return
2268
+ // }
2269
+ // if (result?.data?.targetElements?.length === 0) {
2270
+ // return
2271
+ // }
2272
+ // if (sourceElements.length === 0) {
2273
+ // return
2274
+ // }
2275
+ // this.sourceElements.set(sourceElements ?? [])
2276
+ // this.targetElements.set(targetElements ?? [])
2277
+ // this.identifiersSelected.set((this.targetElements() ?? []).filter((element: IPickListElement) => element.buttonConfig?.label).map((element: IPickListElement) => element.buttonConfig?.label as string) ?? [])
2278
+ // this.dt.filter(this.identifiersSelected(), 'rowData.identifier', 'arrayStringFilter')
2279
+ // })
2280
+ }
2281
+ handleTableValueToSourceElements() {
2282
+ const value = this.data();
2283
+ if (!value.some((item) => item.rowData['identifier'])) {
2284
+ return;
2285
+ }
2286
+ const sourceElements = value.map((item) => ({
2287
+ id: item.id,
2288
+ buttonConfig: {
2289
+ label: item.rowData['identifier'],
2290
+ fullWidth: true,
2291
+ fullHeight: true
2292
+ },
2293
+ isSelected: false
2294
+ }));
2295
+ this.sourceElements.set(sourceElements);
2296
+ }
2297
+ handleSelectedItemsToSourceElements() {
2298
+ const selectedItems = this.selectedItems();
2299
+ if (!selectedItems.some((item) => item.rowData['identifier'])) {
2300
+ return;
2301
+ }
2302
+ const identifiers = selectedItems.map((item) => item.rowData['identifier']);
2303
+ const sourceElements = this.sourceElements().map((item) => ({
2304
+ ...item,
2305
+ isSelected: identifiers.includes(item.buttonConfig?.label)
2306
+ }));
2307
+ this.sourceElements.set(sourceElements);
2308
+ }
2309
+ identifiersSelected = signal([]);
2310
+ //#endregion
2311
+ get excelButton() {
2312
+ return this.tableNgService.excelButton();
2313
+ }
2314
+ get pdfButton() {
2315
+ return this.tableNgService.pdfButton();
2316
+ }
2317
+ lazyLoadingConfig = computed(() => {
2318
+ return this.config()?.lazyLoadingConfig ?? undefined;
2319
+ });
2320
+ isEnabledLazyLoading = computed(() => {
2321
+ return this.lazyLoadingConfig()?.isEnabled ?? false;
2322
+ });
2323
+ prepareDataForExport(dataToExport) {
2324
+ const keys = this.config()?.keys ?? [];
2325
+ const keysNames = this.config()?.keysNames ?? {};
2326
+ return dataToExport.map((item) => {
2327
+ const row = {};
2328
+ const rowData = item.rowData;
2329
+ keys.forEach((key) => {
2330
+ const keyName = keysNames[key] ?? key;
2331
+ if (rowData[key]) {
2332
+ let value = rowData[key];
2333
+ switch (typeof value) {
2334
+ case 'number':
2335
+ value = formatNumber(value);
2336
+ break;
2337
+ default:
2338
+ break;
2339
+ }
2340
+ row[keyName] = value;
2341
+ }
2342
+ });
2343
+ return row;
2344
+ });
2345
+ }
2346
+ exportCSV(data) {
2347
+ // Create a new workbook
2348
+ const workbook = XLSX.utils.book_new();
2349
+ const worksheet = XLSX.utils.json_to_sheet(data);
2350
+ // Get title from config or use default
2351
+ const name = this.config()?.excelConfig?.name ?? 'Report';
2352
+ const fileName = name || 'table-export';
2353
+ // Excel sheet names cannot exceed 31 characters
2354
+ const sheetName = name.substring(0, 31);
2355
+ // Add the worksheet to the workbook
2356
+ XLSX.utils.book_append_sheet(workbook, worksheet, sheetName);
2357
+ // Generate Excel file and trigger download
2358
+ XLSX.writeFile(workbook, `${fileName}.xlsx`);
2359
+ }
2360
+ exportData(dt, endpoint) {
2361
+ if (this.isEnabledLazyLoading()) {
2362
+ const filters = dt.filters ?? {};
2363
+ const filterQuery = {};
2364
+ Object.entries(filters).forEach(([key, value]) => {
2365
+ const keyName = key.split('.')[1];
2366
+ const valueFilter = value[0]?.value;
2367
+ filterQuery[keyName] = valueFilter;
2368
+ });
2369
+ this.lazyLoadingConfig()?.excelLazyLoadingConfig?.callback(removeNullUndefined(filterQuery))
2370
+ .subscribe((response) => {
2371
+ const data = this.prepareDataForExport(response);
2372
+ if (endpoint === 'excel') {
2373
+ this.exportCSV(data);
2374
+ }
2375
+ else {
2376
+ this.exportPDF(data);
2377
+ }
2378
+ });
2379
+ }
2380
+ else {
2381
+ const value = dt.value ?? this.data();
2382
+ const filteredValue = dt.filteredValue ?? [];
2383
+ let dataToExport = [];
2384
+ if (filteredValue.length > 0) {
2385
+ dataToExport = filteredValue;
2386
+ }
2387
+ else {
2388
+ dataToExport = value;
2389
+ }
2390
+ const data = this.prepareDataForExport(dataToExport);
2391
+ if (endpoint === 'excel') {
2392
+ this.exportCSV(data);
2393
+ }
2394
+ else {
2395
+ this.exportPDF(data);
2396
+ }
2397
+ }
2398
+ }
2399
+ exportPDF(data) {
2400
+ // Get title from config or use default
2401
+ const name = this.config()?.pdfConfig?.name ?? this.config()?.excelConfig?.name ?? 'Report';
2402
+ const fileName = name || 'table-export';
2403
+ // Get keys and column names
2404
+ const keys = this.config()?.keys ?? [];
2405
+ const keysNames = this.config()?.keysNames ?? {};
2406
+ // Prepare headers
2407
+ const headers = keys.map((key) => keysNames[key] ?? key);
2408
+ // Prepare rows data
2409
+ const rows = data.map((row) => {
2410
+ return keys.map((key) => {
2411
+ const keyName = keysNames[key] ?? key;
2412
+ return row[keyName] ?? '';
2413
+ });
2414
+ });
2415
+ // Create PDF document
2416
+ const doc = new jsPDF({
2417
+ orientation: 'landscape',
2418
+ unit: 'mm',
2419
+ format: 'a4'
2420
+ });
2421
+ // Add title
2422
+ doc.setFontSize(16);
2423
+ doc.text(name, 14, 15);
2424
+ // Add table
2425
+ autoTable(doc, {
2426
+ head: [headers],
2427
+ body: rows,
2428
+ startY: 20,
2429
+ styles: {
2430
+ fontSize: 8,
2431
+ cellPadding: 2
2432
+ },
2433
+ headStyles: {
2434
+ fillColor: [66, 139, 202],
2435
+ textColor: 255,
2436
+ fontStyle: 'bold'
2437
+ },
2438
+ alternateRowStyles: {
2439
+ fillColor: [245, 245, 245]
2440
+ },
2441
+ margin: { top: 20 }
2442
+ });
2443
+ // Save PDF
2444
+ doc.save(`${fileName}.pdf`);
2445
+ }
2446
+ enableExcelButton = computed(() => {
2447
+ return this.config()?.excelConfig?.isEnabled ?? false;
2448
+ });
2449
+ enablePdfButton = computed(() => {
2450
+ return this.config()?.pdfConfig?.isEnabled ?? false;
2451
+ });
2452
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TableNgComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2453
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: TableNgComponent, isStandalone: true, selector: "lib-table-ng", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, editConfig: { classPropertyName: "editConfig", publicName: "editConfig", isSignal: true, isRequired: false, transformFunction: null }, footerConfig: { classPropertyName: "footerConfig", publicName: "footerConfig", isSignal: true, isRequired: false, transformFunction: null }, toolbarButtons: { classPropertyName: "toolbarButtons", publicName: "toolbarButtons", isSignal: true, isRequired: false, transformFunction: null }, sourceElements: { classPropertyName: "sourceElements", publicName: "sourceElements", isSignal: true, isRequired: false, transformFunction: null }, targetElements: { classPropertyName: "targetElements", publicName: "targetElements", isSignal: true, isRequired: false, transformFunction: null }, httpMessage: { classPropertyName: "httpMessage", publicName: "httpMessage", isSignal: true, isRequired: false, transformFunction: null }, selectedItems: { classPropertyName: "selectedItems", publicName: "selectedItems", isSignal: true, isRequired: false, transformFunction: null }, itemTemplateInput: { classPropertyName: "itemTemplateInput", publicName: "itemTemplateInput", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { data: "dataChange", config: "configChange", editConfig: "editConfigChange", footerConfig: "footerConfigChange", toolbarButtons: "toolbarButtonsChange", sourceElements: "sourceElementsChange", targetElements: "targetElementsChange", httpMessage: "httpMessageChange", lazyLoading: "lazyLoading", outputChangeData: "outputChangeData", outputHandleEditInitButton: "outputHandleEditInitButton", outputAddRow: "outputAddRow", outputDeleteRow: "outputDeleteRow", outputRowInlineChange: "outputRowInlineChange", outputRowDataChange: "outputRowDataChange", outputEditData: "outputEditData", outputIsEditing: "outputIsEditing", selectedItems: "selectedItemsChange" }, providers: [TableNgService, TableNgEditService], queries: [{ propertyName: "itemTemplate", first: true, predicate: ["item"], descendants: true, static: true }], viewQueries: [{ propertyName: "dt", first: true, predicate: ["dt"], descendants: true }], ngImport: i0, template: "@let paginationConfig = config()?.paginationConfig;\r\n@let globalFilterConfig = config()?.globalFilterConfig;\r\n@let selectionTableConfig = config()?.selectionTableConfig;\r\n@let filterConfigByKey = config()?.filterConfigByKey;\r\n@let frozenColumnConfigByKey = config()?.frozenColumnConfigByKey;\r\n@let scrollConfig = config()?.scrollConfig;\r\n@let lazyLoadingConfig = config()?.lazyLoadingConfig;\r\n@let keysNames = config()?.keysNames;\r\n@let columnConfig = config()?.columnConfig;\r\n@let editEnabled = editConfig()?.isEnabled ?? false;\r\n@let editType = editConfig()?.type ?? 'cell';\r\n@let inlineControls = editConfig()?.inlineControls;\r\n@let rowErrorConfig = editConfig()?.rowEditConfig?.rowErrorConfig;\r\n@let footerRows = footerConfig()?.footerRows;\r\n@let footerEnabled = footerConfig()?.isEnabled ?? false;\r\n@let titleConfig = config()?.titleConfig;\r\n@let selectedColumns = config()?.selectedColumns;\r\n@let rowExpansionConfig = config()?.rowExpansionConfig;\r\n@let advancedIdentifierFiltersConfig = config()?.globalFilterConfig?.advancedIdentifierFiltersConfig;\r\n\r\n<div class=\"p-datatable-wrapper\">\r\n @if (titleConfig?.isEnabled && titleConfig?.title) {\r\n <div class=\"table-title-container\">\r\n <h2 class=\"table-title\">{{ titleConfig!.title }}</h2>\r\n </div>\r\n }\r\n @if (!hideToolbar || (filteredValue || advancedFiltersPerformed.length > 0)) {\r\n <lib-toolbar-ng class=\"p-toolbar-header sticky top-0 z-30 dark:bg-gray-800\">\r\n <div class=\"flex gap-2\" toolbarStart>\r\n @if (globalFilterConfig?.isEnabled && !lazyLoadingConfig?.isEnabled) {\r\n <lib-form [controls]=\"controlsGlobalFilter\" [(formGroup)]=\"searchFormGroupGlobalFilter\"\r\n (formSubmit)=\"submitGlobalSearch($event)\"></lib-form>\r\n }\r\n @if (advancedIdentifierFiltersConfig?.isEnabled) {\r\n <lib-button-ng class=\"animate__animated animate__fadeIn\"\r\n [buttonConfig]=\"advancedIdentifierFiltersButton()\"></lib-button-ng>\r\n }\r\n @if (filteredValue || advancedFiltersPerformed.length > 0) {\r\n <lib-button-ng class=\"animate__animated animate__fadeIn\" [buttonConfig]=\"clearFiltersButton()\"></lib-button-ng>\r\n }\r\n </div>\r\n <div class=\"flex gap-2\" toolbarEnd>\r\n @if (toolbarButtons().length > 0) {\r\n @for (button of toolbarButtons(); track $index) {\r\n <lib-button-ng [buttonConfig]=\"button\"></lib-button-ng>\r\n }\r\n }\r\n @if ((editType === 'row' || editType === 'cell') && editEnabled) {\r\n <lib-button-ng [buttonConfig]=\"addRowButton()\"></lib-button-ng>\r\n }\r\n @if (enableExcelButton()) {\r\n <lib-button-ng [buttonConfig]=\"excelButton\" (onClick)=\"exportData(dt,'excel')\"></lib-button-ng>\r\n }\r\n @if (enablePdfButton()) {\r\n <lib-button-ng [buttonConfig]=\"pdfButton\" (onClick)=\"exportData(dt,'pdf')\"></lib-button-ng>\r\n }\r\n </div>\r\n </lib-toolbar-ng>\r\n }\r\n <p-table #dt styleClass=\"p-datatable-sm\" [value]=\"data()\" [lazy]=\"lazyLoadingConfig?.isEnabled ?? false\"\r\n [editMode]=\"editType\" [totalRecords]=\"\r\n lazyLoadingConfig?.isEnabled\r\n ? (lazyLoadingConfig?.totalRecords ?? 0)\r\n : data().length\r\n \" [customSort]=\"true\" [paginator]=\"paginationConfig?.paginator ?? true\" [showCurrentPageReport]=\"true\"\r\n [rows]=\"paginationConfig?.rows ?? 5\" [rowsPerPageOptions]=\"paginationConfig?.rowsPerPageOptions ?? [5, 10, 20]\"\r\n [paginatorStyleClass]=\"paginatorStyleClass()\" [resizableColumns]=\"true\" [rowTrackBy]=\"trackById\"\r\n [columns]=\"selectedColumns\" [scrollable]=\"scrollConfig?.isEnabled ?? false\"\r\n [scrollHeight]=\"scrollConfig?.isEnabled ? scrollHeight() : undefined\" (onLazyLoad)=\"onLazyLoad($event)\"\r\n (sortFunction)=\"customSort($event)\" (onFilter)=\"onFilter($event)\" [(selection)]=\"selectedItems\"\r\n [currentPageReportTemplate]=\"'custom-page-report'\" selectionPageOnly=\"true\" dataKey=\"id\" class=\"w-full\">\r\n <ng-template #header let-columns>\r\n <tr>\r\n @if (rowExpansionConfig?.isEnabled) {\r\n <th alignFrozen=\"left\" pFrozenColumn style=\"width: 2rem\" class=\"p-datatable-header-cell p-frozen-column\">\r\n\r\n </th>\r\n }\r\n @if (selectionTableConfig?.isEnabled) {\r\n <th alignFrozen=\"left\" pFrozenColumn style=\"width: 2rem\" class=\"p-datatable-header-cell p-frozen-column\">\r\n <p-tableHeaderCheckbox />\r\n </th>\r\n }\r\n\r\n @if (selectedColumns) {\r\n @for (column of columns; track $index) {\r\n <th pResizableColumn [id]=\"column.field\" alignFrozen=\"right\" pFrozenColumn\r\n [frozen]=\"frozenHandle(frozenColumnConfigByKey?.[column.field])\" [pSortableColumn]=\"column.field\"\r\n class=\"p-datatable-header-cell\" [style.width.%]=\"columnConfig?.sizeByKey?.[column.field] ?? null\" [ngClass]=\"{\r\n 'p-frozen-column': frozenHandle(\r\n frozenColumnConfigByKey?.[column.field]\r\n ),\r\n }\">\r\n <div class=\"flex gap-2 justify-center items-center py-0 px-0\">\r\n {{ column.field | keyToDisplayName: keysNames }}\r\n @if(!editEnabled){\r\n <p-sortIcon [field]=\"column.field\" />\r\n }\r\n @if (filterConfigByKey?.[column.field]?.isEnabled) {\r\n <p-columnFilter type=\"text\" [field]=\"`rowData.${column.field}`\" display=\"menu\" [ngClass]=\"{\r\n 'bg-green-200 rounded-full p-1 shadow-sm text-green-500 transition-all duration-300 ease-in-out':\r\n advancedFiltersPerformed.includes(column.field),\r\n }\" [type]=\"\r\n filterConfigByKey?.[column.field]?.primeNgColumnFilterConfig?.type ??\r\n 'text'\r\n \" [matchMode]=\"\r\n filterConfigByKey?.[column.field]?.primeNgColumnFilterConfig\r\n ?.matchMode\r\n \" [showMatchModes]=\"\r\n filterConfigByKey?.[column.field]?.primeNgColumnFilterConfig\r\n ?.showMatchModes ?? false\r\n \" [showOperator]=\"\r\n filterConfigByKey?.[column.field]?.primeNgColumnFilterConfig\r\n ?.showOperator ?? false\r\n \" [showAddButton]=\"\r\n filterConfigByKey?.[column.field]?.primeNgColumnFilterConfig\r\n ?.showAddButton ?? false\r\n \" [showApplyButton]=\"\r\n filterConfigByKey?.[column.field]?.primeNgColumnFilterConfig\r\n ?.showApplyButton ?? false\r\n \" [showClearButton]=\"\r\n filterConfigByKey?.[column.field]?.primeNgColumnFilterConfig\r\n ?.showClearButton ?? false\r\n \">\r\n @if (\r\n filterConfigByKey?.[column.field]?.customColumnFilterConfig\r\n ?.isEnabled ?? false\r\n ) {\r\n <ng-template #filter let-value let-filter=\"filterCallback\">\r\n <div style=\"min-width: 20rem\" class=\"\">\r\n <lib-inline-input\r\n (outputValue)=\"inlineFormChanges($event, filter, filterConfigByKey?.[column.field]?.customColumnFilterConfig?.inlineControlConfig?.typeInput, column.field)\"\r\n (outputDebounced)=\"onFilter($event)\" [(ngModel)]=\"advancedFiltersValues()[column.field]\"\r\n [config]=\"filterConfigByKey?.[column.field]?.customColumnFilterConfig?.inlineControlConfig ?? {typeInput: ETypeInput.TEXT}\"></lib-inline-input>\r\n </div>\r\n </ng-template>\r\n }\r\n </p-columnFilter>\r\n }\r\n </div>\r\n </th>\r\n }\r\n }@else {\r\n @for (key of keys(); track $index) {\r\n <th [id]=\"key\" pResizableColumn alignFrozen=\"right\" pFrozenColumn\r\n [frozen]=\"frozenHandle(frozenColumnConfigByKey?.[key])\" [pSortableColumn]=\"key\"\r\n class=\"p-datatable-header-cell\" [style.width.%]=\"columnConfig?.sizeByKey?.[key] ?? null\" [ngClass]=\"{\r\n 'p-frozen-column': frozenHandle(frozenColumnConfigByKey?.[key]),\r\n }\">\r\n <div class=\"flex gap-2 justify-center items-center py-0 px-0\">\r\n {{ key | keyToDisplayName: keysNames }}\r\n @if(!editEnabled){\r\n <p-sortIcon [field]=\"key\" />\r\n }\r\n @if (filterConfigByKey?.[key]?.isEnabled) {\r\n <p-columnFilter type=\"text\" [field]=\"`rowData.${key}`\" display=\"menu\" [ngClass]=\"{\r\n 'bg-green-200 rounded-full p-1 shadow-sm text-green-500 transition-all duration-300 ease-in-out':\r\n advancedFiltersPerformed.includes(key),\r\n }\" [type]=\"filterConfigByKey?.[key]?.primeNgColumnFilterConfig?.type ?? 'text'\"\r\n [matchMode]=\"filterConfigByKey?.[key]?.primeNgColumnFilterConfig?.matchMode\"\r\n [showMatchModes]=\"filterConfigByKey?.[key]?.primeNgColumnFilterConfig?.showMatchModes ?? false\"\r\n [showOperator]=\"filterConfigByKey?.[key]?.primeNgColumnFilterConfig?.showOperator ?? false\"\r\n [showAddButton]=\"filterConfigByKey?.[key]?.primeNgColumnFilterConfig?.showAddButton ?? false\"\r\n [showApplyButton]=\"filterConfigByKey?.[key]?.primeNgColumnFilterConfig?.showApplyButton ?? false\"\r\n [showClearButton]=\"filterConfigByKey?.[key]?.primeNgColumnFilterConfig?.showClearButton ?? false\">\r\n @if (\r\n filterConfigByKey?.[key]?.customColumnFilterConfig\r\n ?.isEnabled ?? false\r\n ) {\r\n <ng-template #filter let-value let-filter=\"filterCallback\">\r\n <div style=\"min-width: 20rem\" class=\"\">\r\n <!-- <app-custom-advanced-filter filter\r\n [customColumnFilterConfig]=\"filterConfigByKey![key]!.customColumnFilterConfig!\"\r\n (formChanges)=\"formChanges($event, filter, key)\"\r\n [initialValue]=\"advancedFiltersValues[key]\"></app-custom-advanced-filter> -->\r\n <lib-inline-input\r\n (outputValue)=\"inlineFormChanges($event, filter, filterConfigByKey?.[key]?.customColumnFilterConfig?.inlineControlConfig?.typeInput, key)\"\r\n [(ngModel)]=\"advancedFiltersValues()[key]\"\r\n [config]=\"filterConfigByKey?.[key]?.customColumnFilterConfig?.inlineControlConfig ?? {typeInput: ETypeInput.TEXT}\"></lib-inline-input>\r\n </div>\r\n </ng-template>\r\n }\r\n </p-columnFilter>\r\n }\r\n </div>\r\n </th>\r\n }\r\n }\r\n\r\n @if (editType === 'cell' && editEnabled) {\r\n <th class=\"p-datatable-header-cell\" style=\"width: 100px\">\r\n </th>\r\n }\r\n @if (editType === 'row' && editEnabled) {\r\n <th class=\"p-datatable-header-cell\" style=\"width: 100px\">\r\n </th>\r\n }\r\n\r\n </tr>\r\n </ng-template>\r\n\r\n <ng-template #emptymessage>\r\n <tr>\r\n <td [attr.colspan]=\"totalColumns()\">\r\n @if (isLoading()) {\r\n <!-- Estado de carga -->\r\n <div class=\"p-8 text-center\">\r\n <div class=\"flex flex-col items-center justify-center gap-4\">\r\n <i class=\"pi pi-spin pi-spinner text-4xl text-blue-500\"></i>\r\n <p class=\"text-gray-600 text-lg\">{{ '' }}</p>\r\n </div>\r\n </div>\r\n } @else if (timeoutExpired()) {\r\n <!-- Timeout expirado sin datos -->\r\n <div class=\"p-8 text-center text-gray-500\">\r\n <div class=\"flex flex-col items-center justify-center gap-3\">\r\n <i class=\"pi pi-info-circle text-4xl text-gray-400\"></i>\r\n <p class=\"text-lg\">{{ '' }}</p>\r\n </div>\r\n </div>\r\n }\r\n </td>\r\n </tr>\r\n </ng-template>\r\n\r\n @if (hasRecords()) {\r\n @if (editEnabled) {\r\n @switch (editType) {\r\n @case ('cell') {\r\n <ng-template #body let-item let-editing=\"editing\">\r\n <tr class=\"p-datatable-row p-selectable-row\">\r\n @if (selectedColumns) {\r\n @for (column of selectedColumns; track $index){\r\n <td [pEditableColumn]=\"column.field\" pEditableColumnField=\"rowData.{{column.field}}\">\r\n <p-cellEditor>\r\n <ng-template #input>\r\n <lib-inline-input [(ngModel)]=\"item.rowData[column.field]\" (outputDebounced)=\"onEditData()\"\r\n [config]=\"inlineControls?.[column.field] ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n </ng-template>\r\n <ng-template #output>\r\n @if (inlineControls?.[column.field]?.typeInput === ETypeInput.NUMBER) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[column.field] | number: '1.2-2' }}\r\n\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.CURRENCY) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[column.field] | currency: item?.currencyTypeCellConfig?.[column.field]?.currency ??\r\n 'USD' }}\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.DATE) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[column.field] | date: \"dd/MM/yyyy\" }}\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.DATETIME_LOCAL) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[column.field] | date: \"dd/MM/yyyy HH:mm\" }}\r\n </div>\r\n } @else {\r\n @if (item.rowData[column.field]?.name) {\r\n {{ item.rowData[column.field]?.name }}\r\n } @else {\r\n {{ item.rowData[column.field] }}\r\n }\r\n }\r\n\r\n </ng-template>\r\n </p-cellEditor>\r\n </td>\r\n }\r\n } @else {\r\n @for (key of keys(); track $index){\r\n <td [pEditableColumn]=\"key\" pEditableColumnField=\"rowData.{{key}}\">\r\n <p-cellEditor>\r\n <ng-template #input>\r\n <lib-inline-input [(ngModel)]=\"item.rowData[key]\" (outputDebounced)=\"onEditData()\"\r\n [config]=\"inlineControls?.[key] ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n </ng-template>\r\n <ng-template #output>\r\n {{ item.rowData[key] }}\r\n </ng-template>\r\n </p-cellEditor>\r\n </td>\r\n }\r\n }\r\n @if (editType === 'cell' && editEnabled) {\r\n <td class=\"px-2 py-1 text-center\">\r\n <div class=\"flex justify-center items-center gap-2\">\r\n <lib-button-ng [buttonConfig]=\"getDeleteRowButton()\" (onClick)=\"deleteRow(item)\"></lib-button-ng>\r\n </div>\r\n </td>\r\n }\r\n </tr>\r\n </ng-template>\r\n }\r\n @case ('row') {\r\n <ng-template #body let-item let-editing=\"editing\" let-ri=\"rowIndex\">\r\n <tr [pEditableRow]=\"item\" class=\"cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 border-b\">\r\n @if (selectedColumns) {\r\n @for (column of selectedColumns; track $index){\r\n <td>\r\n <div class=\"flex flex-col gap-2\">\r\n <p-cellEditor>\r\n <ng-template #input>\r\n <lib-inline-input [(ngModel)]=\"item.rowData[column.field]\"\r\n (outputValue)=\"inlineChange($event, column.field)\" (outputDebounced)=\"onEditData()\"\r\n [config]=\"inlineControls?.[column.field] ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n\r\n </ng-template>\r\n <ng-template #output>\r\n\r\n @if (inlineControls?.[column.field]?.typeInput === ETypeInput.NUMBER) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[column.field] | number: '1.2-2' }}\r\n\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.CURRENCY) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[column.field] | currency: item?.currencyTypeCellConfig?.[column.field]?.currency ??\r\n 'USD' : item?.currencyTypeCellConfig?.[column.field]?.locale ?? 'es-CO' }}\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.DATE) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[column.field] | date: \"dd/MM/yyyy\" }}\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.DATETIME_LOCAL) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[column.field] | date: \"dd/MM/yyyy HH:mm\" }}\r\n </div>\r\n } @else {\r\n @if (item.rowData[column.field]?.name) {\r\n {{ item.rowData[column.field]?.name }}\r\n } @else {\r\n {{ item.rowData[column.field] }}\r\n }\r\n }\r\n\r\n\r\n </ng-template>\r\n </p-cellEditor>\r\n\r\n @if (rowErrorConfig?.isEnabled && enableErrors && !rowFieldsHasValue()[column.field]) {\r\n <span class=\"text-red-500 italic text-xs\">{{\r\n rowErrorConfig?.fieldErrors?.[item.id]?.[column.field]?.message ??\r\n '' }}</span>\r\n }\r\n </div>\r\n </td>\r\n }\r\n } @else {\r\n @for (key of keys(); track $index){\r\n <td>\r\n <div class=\"flex flex-col gap-2\">\r\n <p-cellEditor>\r\n <ng-template #input>\r\n <lib-inline-input [(ngModel)]=\"item.rowData[key]\" (outputValue)=\"inlineChange($event, key)\"\r\n (outputDebounced)=\"onEditData()\" [config]=\"inlineControls?.[key] ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n </ng-template>\r\n <ng-template #output>\r\n\r\n @if (inlineControls?.[key]?.typeInput === ETypeInput.NUMBER) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[key] | number: '1.2-2' }}\r\n\r\n </div>\r\n }\r\n @else if(inlineControls?.[key]?.typeInput === ETypeInput.CURRENCY) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[key] | currency: item?.currencyTypeCellConfig?.[key]?.currency ?? 'USD' }}\r\n </div>\r\n } @else {\r\n @if (item.rowData[key]?.name) {\r\n {{ item.rowData[key]?.name }}\r\n } @else {\r\n {{ item.rowData[key] }}\r\n }\r\n }\r\n\r\n\r\n </ng-template>\r\n </p-cellEditor>\r\n\r\n @if (rowErrorConfig?.isEnabled && enableErrors && !rowFieldsHasValue()[key]) {\r\n <span class=\"text-red-500 italic text-xs\">{{ rowErrorConfig?.fieldErrors?.[item.id]?.[key]?.message ??\r\n '' }}</span>\r\n }\r\n </div>\r\n </td>\r\n }\r\n }\r\n <td>\r\n <div class=\"flex justify-center items-center gap-2\">\r\n @if(!editing){\r\n <lib-button-ng pButton pRipple pInitEditableRow [buttonConfig]=\"getEditInitButton(item.id)\"\r\n (onClick)=\"onRowEditInit(item)\"></lib-button-ng>\r\n @if(!editConfig()?.rowEditConfig?.isDisabledDeleteButton){\r\n <lib-button-ng [buttonConfig]=\"getDeleteRowButton()\" (onClick)=\"deleteRow(item)\"></lib-button-ng>\r\n }\r\n }\r\n @if(editing){\r\n @if (hasErrorValues(rowErrorConfig?.fieldErrors?.[item.id] ?? {})) {\r\n <lib-button-ng [buttonConfig]=\"editSaveButtonWithErrors()\"\r\n (onClick)=\"onEditSaveWithErrors()\"></lib-button-ng>\r\n }\r\n @else {\r\n <lib-button-ng pButton pRipple pSaveEditableRow [buttonConfig]=\"editSaveButton()\"\r\n (onClick)=\"onRowEditSave(item)\"></lib-button-ng>\r\n }\r\n <lib-button-ng pButton pRipple pCancelEditableRow [buttonConfig]=\"editCancelButton()\"\r\n (onClick)=\"onRowEditCancel(item, ri)\"></lib-button-ng>\r\n }\r\n </div>\r\n </td>\r\n </tr>\r\n </ng-template>\r\n }\r\n }\r\n } @else {\r\n\r\n <ng-template #body let-item let-expanded=\"expanded\">\r\n <tr class=\"p-datatable-row p-selectable-row\" [ngClass]=\"{\r\n 'bg-gray-50 dark:bg-gray-800 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700': item.onClick && !item.isSelected && !item.isLoading,\r\n 'bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600': !item.onClick && !item.isSelected && !item.isLoading,\r\n 'bg-blue-100 dark:bg-blue-900 border-l-4 border-blue-500 hover:bg-blue-200 dark:hover:bg-blue-800': item.isSelected && !item.isLoading,\r\n 'skeleton-row': item.isLoading\r\n }\" (click)=\"item?.isLoading ? null : onRowClick(item)\">\r\n\r\n @if (rowExpansionConfig?.isEnabled) {\r\n <td (click)=\"$event.stopPropagation()\" [class.skeleton-cell]=\"item.isLoading\"\r\n [style.height]=\"item.isLoading ? '3rem' : 'auto'\">\r\n @if (!item.isLoading) {\r\n <lib-button-ng [buttonConfig]=\"rowExpansionButton(expanded)()\" type=\"button\" pRipple\r\n [pRowToggler]=\"item\"></lib-button-ng>\r\n } @else {\r\n <div class=\"skeleton-content\"></div>\r\n }\r\n </td>\r\n }\r\n\r\n @if (selectionTableConfig?.isEnabled) {\r\n <td (click)=\"$event.stopPropagation()\" alignFrozen=\"left\" pFrozenColumn class=\"shadow-lg\"\r\n [class.skeleton-cell]=\"item.isLoading\" [style.height]=\"item.isLoading ? '3rem' : 'auto'\">\r\n @if (!item.isLoading) {\r\n <p-tableCheckbox [id]=\"item\" [value]=\"item\" />\r\n } @else {\r\n <div class=\"skeleton-content\"></div>\r\n }\r\n </td>\r\n }\r\n\r\n @for (key of keys(); track $index) {\r\n @if (isThatItemInTheProductSelection(key)) {\r\n <td [id]=\"key\" class=\"p-datatable-cell\" [style.height]=\"item.isLoading ? '3rem' : 'min-content'\"\r\n alignFrozen=\"right\" pFrozenColumn [ngClass]=\"{\r\n 'p-frozen-column': frozenHandle(frozenColumnConfigByKey?.[key]),\r\n 'text-center': item.rowDataButtons?.[key] || item.typeCell?.[key] === ETypeInput.BADGE,\r\n 'skeleton-cell': item.isLoading\r\n }\" [frozen]=\"frozenHandle(frozenColumnConfigByKey?.[key])\">\r\n @if (item.isLoading) {\r\n <div class=\"skeleton-content\"></div>\r\n } @else {\r\n @if (item.rowDataButtons?.[key]) {\r\n <div class=\"flex gap-4 w-full justify-center items-center\">\r\n @for (btn of item.rowDataButtons[key]; track $index) {\r\n @if (btn) {\r\n <lib-button-ng class=\"w-full\" (click)=\"$event.stopPropagation()\" [buttonConfig]=\"btn\"></lib-button-ng>\r\n }\r\n }\r\n </div>\r\n } @else {\r\n @switch (item.typeCell?.[key]) {\r\n @case (ETypeInput.IMAGE) {\r\n <img [src]=\"item.rowData[key]\" alt=\"Image\" class=\"w-10 h-10 mx-auto\">\r\n }\r\n @case (ETypeInput.DATE) {\r\n {{ item.rowData[key] | date: \"dd/MM/yyyy\" }}\r\n }\r\n @case (ETypeInput.DATETIME_LOCAL) {\r\n {{ item.rowData[key] | date: \"dd/MM/yyyy HH:mm\" }}\r\n }\r\n @case (ETypeInput.CURRENCY) {\r\n {{item?.currencyTypeCellConfig?.[key]?.currency}} {{ item.rowData[key] | currency:\r\n item?.currencyTypeCellConfig?.[key]?.currency ?? 'USD' }}\r\n }\r\n @case (ETypeInput.BADGE) {\r\n <lib-badge-ng [config]=\"item.rowData[key]\"></lib-badge-ng>\r\n }\r\n @case (ETypeInput.COMPONENT) {\r\n <ng-container\r\n *ngTemplateOutlet=\"item.rowDataComponents?.[key]; context: { $implicit: item.raw }\"></ng-container>\r\n }\r\n @default {\r\n @if (isDate(item.rowData[key])) {\r\n {{ item.rowData[key] | date: \"dd/MM/yyyy\" }}\r\n } @else if (typeof item.rowData[key] === \"string\") {\r\n {{ item.rowData[key] }}\r\n } @else if (isPrimeNgSelection(item.rowData[key])) {\r\n {{ item.rowData[key].name }}\r\n } @else if(typeof item.rowData[key] === \"number\") {\r\n <p class=\"text-right\">\r\n {{ item.rowData[key] | number: '1.2-2' }}\r\n </p>\r\n }\r\n }\r\n }\r\n }\r\n }\r\n </td>\r\n }\r\n }\r\n </tr>\r\n </ng-template>\r\n }\r\n }\r\n\r\n <ng-template #footer>\r\n @if (footerEnabled) {\r\n @for (row of footerRows; track $index) {\r\n <tr class=\"p-datatable-row p-datatable-footer-row\">\r\n @for (cell of row; track $index) {\r\n <td colSpan=\"{{ cell.colSpan }}\" class=\"{{ cell.class }} text-right font-bold p-3 pb-0\">{{\r\n applyPipe(cell.value,\r\n cell.pipeConfig) }}</td>\r\n\r\n }\r\n </tr>\r\n }\r\n\r\n }\r\n </ng-template>\r\n <ng-template #expandedrow let-item>\r\n <tr>\r\n <td colspan=\"100%\">\r\n <div class=\"p-datatable-row-expansion\">\r\n <ng-container *ngTemplateOutlet=\"currentItemTemplate; context: { $implicit: item }\"></ng-container>\r\n\r\n </div>\r\n </td>\r\n </tr>\r\n </ng-template>\r\n </p-table>\r\n @if (showBottomToolbar()) {\r\n <div class=\"p-datatable-footer sticky bottom-2 z-9 animate__animated animate__fadeIn\">\r\n <lib-toolbar-ng>\r\n @if (showManagementSelectionConfig()) {\r\n <div toolbarStart\r\n class=\"p-datatable-footer-content flex items-center gap-3 px-4 rounded-lg animate__animated animate__fadeIn\">\r\n <span class=\"font-medium text-gray-700\">Has seleccionado</span>\r\n <div class=\"p-datatable-footer-badge flex items-center justify-center min-w-[28px] h-7 px-2 rounded-md\">\r\n <span class=\"font-semibold text-gray-900\">{{\r\n totalItemsSelected().toLocaleString()\r\n }}</span>\r\n </div>\r\n <span class=\"text-sm text-gray-600\">registros</span>\r\n <lib-button-ng [buttonConfig]=\"showSelectedItemsManagementButton()\"></lib-button-ng>\r\n </div>\r\n }\r\n </lib-toolbar-ng>\r\n </div>\r\n }\r\n</div>\r\n@if (httpMessage()) {\r\n<lib-http-message [(httpMessage)]=\"httpMessage\"></lib-http-message>\r\n}", styles: [".cursor-pointer{cursor:pointer}.empty-data-message{text-align:center;padding:2rem;color:#6c757d;font-style:italic}.table-title-container{background:var(--p-surface-50);border-bottom:1px solid var(--p-surface-200);padding:1.25rem 2rem;position:relative}.table-title{color:var(--p-text-color);font-size:1.5rem;font-weight:600;text-align:center;margin:0;letter-spacing:-.025em;text-shadow:0 1px 2px rgba(0,0,0,.05);background:linear-gradient(135deg,var(--p-text-color) 0%,var(--p-text-muted-color) 100%);background-clip:text;-webkit-background-clip:text;-webkit-text-fill-color:transparent;position:relative}.table-title:after{content:\"\";position:absolute;bottom:-.5rem;left:50%;transform:translate(-50%);width:60px;height:2px;background:linear-gradient(90deg,var(--p-primary-color),var(--p-primary-600));border-radius:1px}:host ::ng-deep .p-datatable-paginator{background:var(--p-surface-100);border-top:1px solid var(--p-surface-300);padding:1rem}:host ::ng-deep .p-datatable-paginator .p-paginator{background:transparent;border:none;padding:0}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page{background:var(--p-surface-200);border:1px solid var(--p-surface-300);color:var(--p-text-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page:hover{background:var(--p-surface-300);border-color:var(--p-primary-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page.p-highlight{background:var(--p-primary-color);border-color:var(--p-primary-color);color:var(--p-primary-contrast-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last{background:var(--p-surface-200);border:1px solid var(--p-surface-300);color:var(--p-text-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first:hover,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev:hover,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next:hover,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last:hover{background:var(--p-surface-300);border-color:var(--p-primary-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first:disabled,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev:disabled,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next:disabled,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last:disabled{background:var(--p-surface-100);border-color:var(--p-surface-300);color:var(--p-text-muted-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-current{color:var(--p-text-color);font-weight:500}:host ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown{background:var(--p-surface-200);border:1px solid var(--p-surface-300);color:var(--p-text-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown:hover{border-color:var(--p-primary-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown:focus{border-color:var(--p-primary-color);box-shadow:0 0 0 2px var(--p-primary-color-100)}.skeleton-row{pointer-events:none;-webkit-user-select:none;user-select:none;min-height:3rem}.skeleton-cell{position:relative;overflow:hidden;min-height:3rem;padding:.75rem .5rem!important}.skeleton-cell .skeleton-content{position:absolute;inset:.5rem;min-height:1.5rem;background:linear-gradient(90deg,#d1d5db33,#d1d5db66,#d1d5db33);background-size:200% 100%;animation:skeleton-loading 1.5s ease-in-out infinite;border-radius:4px}@keyframes skeleton-loading{0%{background-position:200% 0}to{background-position:-200% 0}}:host-context(.dark) .skeleton-cell .skeleton-content{background:linear-gradient(90deg,#4b556333,#4b556366,#4b556333);background-size:200% 100%}:host ::ng-deep .p-datatable .p-datatable-tbody .skeleton-row .skeleton-cell{width:auto;min-width:fit-content}:host-context(.my-app-dark) .table-title-container{background:var(--p-surface-800);border-bottom-color:var(--p-surface-700)}:host-context(.my-app-dark) .table-title{color:var(--p-text-color);background:linear-gradient(135deg,var(--p-text-color) 0%,var(--p-text-muted-color) 100%);background-clip:text;-webkit-background-clip:text;-webkit-text-fill-color:transparent}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator{background:var(--p-surface-900);border-top-color:var(--p-surface-800)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page{background:var(--p-surface-800);border-color:var(--p-surface-700);color:var(--p-text-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page:hover{background:var(--p-surface-700);border-color:var(--p-primary-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page.p-highlight{background:var(--p-primary-color);border-color:var(--p-primary-color);color:var(--p-primary-contrast-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last{background:var(--p-surface-800);border-color:var(--p-surface-700);color:var(--p-text-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first:hover,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev:hover,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next:hover,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last:hover{background:var(--p-surface-700);border-color:var(--p-primary-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first:disabled,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev:disabled,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next:disabled,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last:disabled{background:var(--p-surface-900);border-color:var(--p-surface-800);color:var(--p-text-muted-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-current{color:var(--p-text-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown{background:var(--p-surface-800);border-color:var(--p-surface-700);color:var(--p-text-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown:hover{border-color:var(--p-primary-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown:focus{border-color:var(--p-primary-color);box-shadow:0 0 0 2px var(--p-primary-color-100)}.flex{display:flex}.flex-col{flex-direction:column}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.justify-center{justify-content:center}.items-center{align-items:center}.text-center{text-align:center}.text-right{text-align:right}.text-left{text-align:left}.text-gray-400{color:#9ca3af}.text-gray-500{color:#6b7280}.text-gray-600{color:#4b5563}.text-gray-700{color:#374151}.text-gray-900{color:#111827}.text-blue-500{color:#3b82f6}.text-red-500{color:#ef4444}.text-green-500{color:#22c55e}.text-xs{font-size:.75rem;line-height:1rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.font-medium{font-weight:500}.font-semibold{font-weight:600}.font-bold{font-weight:700}.italic{font-style:italic}.w-full{width:100%}.w-10{width:2.5rem}.h-10{height:2.5rem}.h-7{height:1.75rem}.min-w-28{min-width:28px}.mx-auto{margin-left:auto;margin-right:auto}.p-1{padding:.25rem}.p-3{padding:.75rem}.p-8{padding:2rem}.px-0{padding-left:0;padding-right:0}.py-0{padding-top:0;padding-bottom:0}.px-2{padding-left:.5rem;padding-right:.5rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.px-4{padding-left:1rem;padding-right:1rem}.pb-0{padding-bottom:0}.bg-gray-50{background-color:#f9fafb}.bg-gray-100{background-color:#f3f4f6}.bg-gray-200{background-color:#e5e7eb}.bg-gray-600{background-color:#4b5563}.bg-gray-700{background-color:#374151}.bg-gray-800{background-color:#1f2937}.bg-blue-100{background-color:#dbeafe}.bg-blue-200{background-color:#bfdbfe}.bg-blue-800{background-color:#1e40af}.bg-blue-900{background-color:#1e3a8a}.bg-green-200{background-color:#bbf7d0}.border-b{border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:var(--p-surface-300)}.border-l-4{border-left-width:4px;border-left-style:solid}.border-blue-500{border-color:#3b82f6}.rounded-full{border-radius:9999px}.rounded-md{border-radius:.375rem}.rounded-lg{border-radius:.5rem}.shadow-sm{box-shadow:0 1px 2px #0000000d}.shadow-lg{box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -2px #0000000d}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-300{transition-duration:.3s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.sticky{position:sticky}.top-0{top:0}.bottom-2{bottom:.5rem}.bottom-18{bottom:4.5rem}.z-9{z-index:9}.z-10{z-index:10}.z-30{z-index:30}.hover\\:bg-gray-50:hover{background-color:#f9fafb}.hover\\:bg-gray-100:hover{background-color:#f3f4f6}.hover\\:bg-gray-200:hover{background-color:#e5e7eb}.hover\\:bg-blue-200:hover{background-color:#bfdbfe}.hover\\:bg-blue-800:hover{background-color:#1e40af}:host-context(.dark) .dark\\:bg-gray-800{background-color:#1f2937}:host-context(.dark) .dark\\:bg-gray-700{background-color:#374151}:host-context(.dark) .dark\\:bg-gray-600{background-color:#4b5563}:host-context(.dark) .dark\\:bg-blue-900{background-color:#1e3a8a}:host-context(.dark) .dark\\:bg-blue-800{background-color:#1e40af}:host-context(.dark) .dark\\:hover\\:bg-gray-800:hover{background-color:#1f2937}:host-context(.dark) .dark\\:hover\\:bg-gray-700:hover{background-color:#374151}:host-context(.dark) .dark\\:hover\\:bg-gray-600:hover{background-color:#4b5563}:host-context(.dark) .dark\\:hover\\:bg-blue-800:hover{background-color:#1e40af}.animate__animated{animation-duration:1s;animation-fill-mode:both}.animate__fadeIn{animation-name:fadeIn}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i1$1.DecimalPipe, name: "number" }, { kind: "pipe", type: i1$1.CurrencyPipe, name: "currency" }, { kind: "pipe", type: i1$1.DatePipe, name: "date" }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i2$2.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "style", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "scrollDirection", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "responsive", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "autoLayout", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "virtualRowHeight", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i2$2.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "directive", type: i2$2.FrozenColumn, selector: "[pFrozenColumn]", inputs: ["frozen", "alignFrozen"] }, { kind: "directive", type: i2$2.RowToggler, selector: "[pRowToggler]", inputs: ["pRowToggler", "pRowTogglerDisabled"] }, { kind: "directive", type: i2$2.ResizableColumn, selector: "[pResizableColumn]", inputs: ["pResizableColumnDisabled"] }, { kind: "directive", type: i2$2.EditableColumn, selector: "[pEditableColumn]", inputs: ["pEditableColumn", "pEditableColumnField", "pEditableColumnRowIndex", "pEditableColumnDisabled", "pFocusCellSelector"] }, { kind: "component", type: i2$2.CellEditor, selector: "p-cellEditor" }, { kind: "component", type: i2$2.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "component", type: i2$2.TableCheckbox, selector: "p-tableCheckbox", inputs: ["value", "disabled", "required", "index", "inputId", "name", "ariaLabel"] }, { kind: "component", type: i2$2.TableHeaderCheckbox, selector: "p-tableHeaderCheckbox", inputs: ["disabled", "inputId", "name", "ariaLabel"] }, { kind: "directive", type: i2$2.EditableRow, selector: "[pEditableRow]", inputs: ["pEditableRow", "pEditableRowDisabled"] }, { kind: "directive", type: i2$2.InitEditableRow, selector: "[pInitEditableRow]" }, { kind: "directive", type: i2$2.SaveEditableRow, selector: "[pSaveEditableRow]" }, { kind: "directive", type: i2$2.CancelEditableRow, selector: "[pCancelEditableRow]" }, { kind: "component", type: i2$2.ColumnFilter, selector: "p-columnFilter", inputs: ["field", "type", "display", "showMenu", "matchMode", "operator", "showOperator", "showClearButton", "showApplyButton", "showMatchModes", "showAddButton", "hideOnClear", "placeholder", "matchModeOptions", "maxConstraints", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "locale", "localeMatcher", "currency", "currencyDisplay", "useGrouping", "showButtons", "ariaLabel", "filterButtonProps"], outputs: ["onShow", "onHide"] }, { kind: "component", type: ButtonNgComponent, selector: "lib-button-ng", inputs: ["buttonConfig"], outputs: ["buttonConfigChange", "onClick"] }, { kind: "component", type: ToolbarNgComponent, selector: "lib-toolbar-ng" }, { kind: "component", type: FormComponent, selector: "lib-form", inputs: ["formGroup", "controls", "formConfig", "httpMessage"], outputs: ["formGroupChange", "httpMessageChange", "formSubmit", "formChanges", "formChangesDebounced"] }, { kind: "pipe", type: KeyToDisplayNamePipe, name: "keyToDisplayName" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: InlineInputComponent, selector: "lib-inline-input", inputs: ["config", "value"], outputs: ["valueChange", "outputValue", "outputBlur", "outputDebounced"] }, { kind: "component", type: BadgeNgComponent, selector: "lib-badge-ng", inputs: ["config"], outputs: ["configChange"] }, { kind: "component", type: HttpMessageComponent, selector: "lib-http-message", inputs: ["httpMessage"], outputs: ["httpMessageChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2454
+ }
2455
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TableNgComponent, decorators: [{
2456
+ type: Component,
2457
+ args: [{ selector: 'lib-table-ng', imports: [
2458
+ CommonModule,
2459
+ TableModule,
2460
+ ButtonNgComponent,
2461
+ ToolbarNgComponent,
2462
+ FormComponent,
2463
+ KeyToDisplayNamePipe,
2464
+ FormsModule,
2465
+ InlineInputComponent,
2466
+ BadgeNgComponent,
2467
+ HttpMessageComponent
2468
+ ], providers: [TableNgService, TableNgEditService], changeDetection: ChangeDetectionStrategy.OnPush, template: "@let paginationConfig = config()?.paginationConfig;\r\n@let globalFilterConfig = config()?.globalFilterConfig;\r\n@let selectionTableConfig = config()?.selectionTableConfig;\r\n@let filterConfigByKey = config()?.filterConfigByKey;\r\n@let frozenColumnConfigByKey = config()?.frozenColumnConfigByKey;\r\n@let scrollConfig = config()?.scrollConfig;\r\n@let lazyLoadingConfig = config()?.lazyLoadingConfig;\r\n@let keysNames = config()?.keysNames;\r\n@let columnConfig = config()?.columnConfig;\r\n@let editEnabled = editConfig()?.isEnabled ?? false;\r\n@let editType = editConfig()?.type ?? 'cell';\r\n@let inlineControls = editConfig()?.inlineControls;\r\n@let rowErrorConfig = editConfig()?.rowEditConfig?.rowErrorConfig;\r\n@let footerRows = footerConfig()?.footerRows;\r\n@let footerEnabled = footerConfig()?.isEnabled ?? false;\r\n@let titleConfig = config()?.titleConfig;\r\n@let selectedColumns = config()?.selectedColumns;\r\n@let rowExpansionConfig = config()?.rowExpansionConfig;\r\n@let advancedIdentifierFiltersConfig = config()?.globalFilterConfig?.advancedIdentifierFiltersConfig;\r\n\r\n<div class=\"p-datatable-wrapper\">\r\n @if (titleConfig?.isEnabled && titleConfig?.title) {\r\n <div class=\"table-title-container\">\r\n <h2 class=\"table-title\">{{ titleConfig!.title }}</h2>\r\n </div>\r\n }\r\n @if (!hideToolbar || (filteredValue || advancedFiltersPerformed.length > 0)) {\r\n <lib-toolbar-ng class=\"p-toolbar-header sticky top-0 z-30 dark:bg-gray-800\">\r\n <div class=\"flex gap-2\" toolbarStart>\r\n @if (globalFilterConfig?.isEnabled && !lazyLoadingConfig?.isEnabled) {\r\n <lib-form [controls]=\"controlsGlobalFilter\" [(formGroup)]=\"searchFormGroupGlobalFilter\"\r\n (formSubmit)=\"submitGlobalSearch($event)\"></lib-form>\r\n }\r\n @if (advancedIdentifierFiltersConfig?.isEnabled) {\r\n <lib-button-ng class=\"animate__animated animate__fadeIn\"\r\n [buttonConfig]=\"advancedIdentifierFiltersButton()\"></lib-button-ng>\r\n }\r\n @if (filteredValue || advancedFiltersPerformed.length > 0) {\r\n <lib-button-ng class=\"animate__animated animate__fadeIn\" [buttonConfig]=\"clearFiltersButton()\"></lib-button-ng>\r\n }\r\n </div>\r\n <div class=\"flex gap-2\" toolbarEnd>\r\n @if (toolbarButtons().length > 0) {\r\n @for (button of toolbarButtons(); track $index) {\r\n <lib-button-ng [buttonConfig]=\"button\"></lib-button-ng>\r\n }\r\n }\r\n @if ((editType === 'row' || editType === 'cell') && editEnabled) {\r\n <lib-button-ng [buttonConfig]=\"addRowButton()\"></lib-button-ng>\r\n }\r\n @if (enableExcelButton()) {\r\n <lib-button-ng [buttonConfig]=\"excelButton\" (onClick)=\"exportData(dt,'excel')\"></lib-button-ng>\r\n }\r\n @if (enablePdfButton()) {\r\n <lib-button-ng [buttonConfig]=\"pdfButton\" (onClick)=\"exportData(dt,'pdf')\"></lib-button-ng>\r\n }\r\n </div>\r\n </lib-toolbar-ng>\r\n }\r\n <p-table #dt styleClass=\"p-datatable-sm\" [value]=\"data()\" [lazy]=\"lazyLoadingConfig?.isEnabled ?? false\"\r\n [editMode]=\"editType\" [totalRecords]=\"\r\n lazyLoadingConfig?.isEnabled\r\n ? (lazyLoadingConfig?.totalRecords ?? 0)\r\n : data().length\r\n \" [customSort]=\"true\" [paginator]=\"paginationConfig?.paginator ?? true\" [showCurrentPageReport]=\"true\"\r\n [rows]=\"paginationConfig?.rows ?? 5\" [rowsPerPageOptions]=\"paginationConfig?.rowsPerPageOptions ?? [5, 10, 20]\"\r\n [paginatorStyleClass]=\"paginatorStyleClass()\" [resizableColumns]=\"true\" [rowTrackBy]=\"trackById\"\r\n [columns]=\"selectedColumns\" [scrollable]=\"scrollConfig?.isEnabled ?? false\"\r\n [scrollHeight]=\"scrollConfig?.isEnabled ? scrollHeight() : undefined\" (onLazyLoad)=\"onLazyLoad($event)\"\r\n (sortFunction)=\"customSort($event)\" (onFilter)=\"onFilter($event)\" [(selection)]=\"selectedItems\"\r\n [currentPageReportTemplate]=\"'custom-page-report'\" selectionPageOnly=\"true\" dataKey=\"id\" class=\"w-full\">\r\n <ng-template #header let-columns>\r\n <tr>\r\n @if (rowExpansionConfig?.isEnabled) {\r\n <th alignFrozen=\"left\" pFrozenColumn style=\"width: 2rem\" class=\"p-datatable-header-cell p-frozen-column\">\r\n\r\n </th>\r\n }\r\n @if (selectionTableConfig?.isEnabled) {\r\n <th alignFrozen=\"left\" pFrozenColumn style=\"width: 2rem\" class=\"p-datatable-header-cell p-frozen-column\">\r\n <p-tableHeaderCheckbox />\r\n </th>\r\n }\r\n\r\n @if (selectedColumns) {\r\n @for (column of columns; track $index) {\r\n <th pResizableColumn [id]=\"column.field\" alignFrozen=\"right\" pFrozenColumn\r\n [frozen]=\"frozenHandle(frozenColumnConfigByKey?.[column.field])\" [pSortableColumn]=\"column.field\"\r\n class=\"p-datatable-header-cell\" [style.width.%]=\"columnConfig?.sizeByKey?.[column.field] ?? null\" [ngClass]=\"{\r\n 'p-frozen-column': frozenHandle(\r\n frozenColumnConfigByKey?.[column.field]\r\n ),\r\n }\">\r\n <div class=\"flex gap-2 justify-center items-center py-0 px-0\">\r\n {{ column.field | keyToDisplayName: keysNames }}\r\n @if(!editEnabled){\r\n <p-sortIcon [field]=\"column.field\" />\r\n }\r\n @if (filterConfigByKey?.[column.field]?.isEnabled) {\r\n <p-columnFilter type=\"text\" [field]=\"`rowData.${column.field}`\" display=\"menu\" [ngClass]=\"{\r\n 'bg-green-200 rounded-full p-1 shadow-sm text-green-500 transition-all duration-300 ease-in-out':\r\n advancedFiltersPerformed.includes(column.field),\r\n }\" [type]=\"\r\n filterConfigByKey?.[column.field]?.primeNgColumnFilterConfig?.type ??\r\n 'text'\r\n \" [matchMode]=\"\r\n filterConfigByKey?.[column.field]?.primeNgColumnFilterConfig\r\n ?.matchMode\r\n \" [showMatchModes]=\"\r\n filterConfigByKey?.[column.field]?.primeNgColumnFilterConfig\r\n ?.showMatchModes ?? false\r\n \" [showOperator]=\"\r\n filterConfigByKey?.[column.field]?.primeNgColumnFilterConfig\r\n ?.showOperator ?? false\r\n \" [showAddButton]=\"\r\n filterConfigByKey?.[column.field]?.primeNgColumnFilterConfig\r\n ?.showAddButton ?? false\r\n \" [showApplyButton]=\"\r\n filterConfigByKey?.[column.field]?.primeNgColumnFilterConfig\r\n ?.showApplyButton ?? false\r\n \" [showClearButton]=\"\r\n filterConfigByKey?.[column.field]?.primeNgColumnFilterConfig\r\n ?.showClearButton ?? false\r\n \">\r\n @if (\r\n filterConfigByKey?.[column.field]?.customColumnFilterConfig\r\n ?.isEnabled ?? false\r\n ) {\r\n <ng-template #filter let-value let-filter=\"filterCallback\">\r\n <div style=\"min-width: 20rem\" class=\"\">\r\n <lib-inline-input\r\n (outputValue)=\"inlineFormChanges($event, filter, filterConfigByKey?.[column.field]?.customColumnFilterConfig?.inlineControlConfig?.typeInput, column.field)\"\r\n (outputDebounced)=\"onFilter($event)\" [(ngModel)]=\"advancedFiltersValues()[column.field]\"\r\n [config]=\"filterConfigByKey?.[column.field]?.customColumnFilterConfig?.inlineControlConfig ?? {typeInput: ETypeInput.TEXT}\"></lib-inline-input>\r\n </div>\r\n </ng-template>\r\n }\r\n </p-columnFilter>\r\n }\r\n </div>\r\n </th>\r\n }\r\n }@else {\r\n @for (key of keys(); track $index) {\r\n <th [id]=\"key\" pResizableColumn alignFrozen=\"right\" pFrozenColumn\r\n [frozen]=\"frozenHandle(frozenColumnConfigByKey?.[key])\" [pSortableColumn]=\"key\"\r\n class=\"p-datatable-header-cell\" [style.width.%]=\"columnConfig?.sizeByKey?.[key] ?? null\" [ngClass]=\"{\r\n 'p-frozen-column': frozenHandle(frozenColumnConfigByKey?.[key]),\r\n }\">\r\n <div class=\"flex gap-2 justify-center items-center py-0 px-0\">\r\n {{ key | keyToDisplayName: keysNames }}\r\n @if(!editEnabled){\r\n <p-sortIcon [field]=\"key\" />\r\n }\r\n @if (filterConfigByKey?.[key]?.isEnabled) {\r\n <p-columnFilter type=\"text\" [field]=\"`rowData.${key}`\" display=\"menu\" [ngClass]=\"{\r\n 'bg-green-200 rounded-full p-1 shadow-sm text-green-500 transition-all duration-300 ease-in-out':\r\n advancedFiltersPerformed.includes(key),\r\n }\" [type]=\"filterConfigByKey?.[key]?.primeNgColumnFilterConfig?.type ?? 'text'\"\r\n [matchMode]=\"filterConfigByKey?.[key]?.primeNgColumnFilterConfig?.matchMode\"\r\n [showMatchModes]=\"filterConfigByKey?.[key]?.primeNgColumnFilterConfig?.showMatchModes ?? false\"\r\n [showOperator]=\"filterConfigByKey?.[key]?.primeNgColumnFilterConfig?.showOperator ?? false\"\r\n [showAddButton]=\"filterConfigByKey?.[key]?.primeNgColumnFilterConfig?.showAddButton ?? false\"\r\n [showApplyButton]=\"filterConfigByKey?.[key]?.primeNgColumnFilterConfig?.showApplyButton ?? false\"\r\n [showClearButton]=\"filterConfigByKey?.[key]?.primeNgColumnFilterConfig?.showClearButton ?? false\">\r\n @if (\r\n filterConfigByKey?.[key]?.customColumnFilterConfig\r\n ?.isEnabled ?? false\r\n ) {\r\n <ng-template #filter let-value let-filter=\"filterCallback\">\r\n <div style=\"min-width: 20rem\" class=\"\">\r\n <!-- <app-custom-advanced-filter filter\r\n [customColumnFilterConfig]=\"filterConfigByKey![key]!.customColumnFilterConfig!\"\r\n (formChanges)=\"formChanges($event, filter, key)\"\r\n [initialValue]=\"advancedFiltersValues[key]\"></app-custom-advanced-filter> -->\r\n <lib-inline-input\r\n (outputValue)=\"inlineFormChanges($event, filter, filterConfigByKey?.[key]?.customColumnFilterConfig?.inlineControlConfig?.typeInput, key)\"\r\n [(ngModel)]=\"advancedFiltersValues()[key]\"\r\n [config]=\"filterConfigByKey?.[key]?.customColumnFilterConfig?.inlineControlConfig ?? {typeInput: ETypeInput.TEXT}\"></lib-inline-input>\r\n </div>\r\n </ng-template>\r\n }\r\n </p-columnFilter>\r\n }\r\n </div>\r\n </th>\r\n }\r\n }\r\n\r\n @if (editType === 'cell' && editEnabled) {\r\n <th class=\"p-datatable-header-cell\" style=\"width: 100px\">\r\n </th>\r\n }\r\n @if (editType === 'row' && editEnabled) {\r\n <th class=\"p-datatable-header-cell\" style=\"width: 100px\">\r\n </th>\r\n }\r\n\r\n </tr>\r\n </ng-template>\r\n\r\n <ng-template #emptymessage>\r\n <tr>\r\n <td [attr.colspan]=\"totalColumns()\">\r\n @if (isLoading()) {\r\n <!-- Estado de carga -->\r\n <div class=\"p-8 text-center\">\r\n <div class=\"flex flex-col items-center justify-center gap-4\">\r\n <i class=\"pi pi-spin pi-spinner text-4xl text-blue-500\"></i>\r\n <p class=\"text-gray-600 text-lg\">{{ '' }}</p>\r\n </div>\r\n </div>\r\n } @else if (timeoutExpired()) {\r\n <!-- Timeout expirado sin datos -->\r\n <div class=\"p-8 text-center text-gray-500\">\r\n <div class=\"flex flex-col items-center justify-center gap-3\">\r\n <i class=\"pi pi-info-circle text-4xl text-gray-400\"></i>\r\n <p class=\"text-lg\">{{ '' }}</p>\r\n </div>\r\n </div>\r\n }\r\n </td>\r\n </tr>\r\n </ng-template>\r\n\r\n @if (hasRecords()) {\r\n @if (editEnabled) {\r\n @switch (editType) {\r\n @case ('cell') {\r\n <ng-template #body let-item let-editing=\"editing\">\r\n <tr class=\"p-datatable-row p-selectable-row\">\r\n @if (selectedColumns) {\r\n @for (column of selectedColumns; track $index){\r\n <td [pEditableColumn]=\"column.field\" pEditableColumnField=\"rowData.{{column.field}}\">\r\n <p-cellEditor>\r\n <ng-template #input>\r\n <lib-inline-input [(ngModel)]=\"item.rowData[column.field]\" (outputDebounced)=\"onEditData()\"\r\n [config]=\"inlineControls?.[column.field] ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n </ng-template>\r\n <ng-template #output>\r\n @if (inlineControls?.[column.field]?.typeInput === ETypeInput.NUMBER) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[column.field] | number: '1.2-2' }}\r\n\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.CURRENCY) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[column.field] | currency: item?.currencyTypeCellConfig?.[column.field]?.currency ??\r\n 'USD' }}\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.DATE) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[column.field] | date: \"dd/MM/yyyy\" }}\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.DATETIME_LOCAL) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[column.field] | date: \"dd/MM/yyyy HH:mm\" }}\r\n </div>\r\n } @else {\r\n @if (item.rowData[column.field]?.name) {\r\n {{ item.rowData[column.field]?.name }}\r\n } @else {\r\n {{ item.rowData[column.field] }}\r\n }\r\n }\r\n\r\n </ng-template>\r\n </p-cellEditor>\r\n </td>\r\n }\r\n } @else {\r\n @for (key of keys(); track $index){\r\n <td [pEditableColumn]=\"key\" pEditableColumnField=\"rowData.{{key}}\">\r\n <p-cellEditor>\r\n <ng-template #input>\r\n <lib-inline-input [(ngModel)]=\"item.rowData[key]\" (outputDebounced)=\"onEditData()\"\r\n [config]=\"inlineControls?.[key] ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n </ng-template>\r\n <ng-template #output>\r\n {{ item.rowData[key] }}\r\n </ng-template>\r\n </p-cellEditor>\r\n </td>\r\n }\r\n }\r\n @if (editType === 'cell' && editEnabled) {\r\n <td class=\"px-2 py-1 text-center\">\r\n <div class=\"flex justify-center items-center gap-2\">\r\n <lib-button-ng [buttonConfig]=\"getDeleteRowButton()\" (onClick)=\"deleteRow(item)\"></lib-button-ng>\r\n </div>\r\n </td>\r\n }\r\n </tr>\r\n </ng-template>\r\n }\r\n @case ('row') {\r\n <ng-template #body let-item let-editing=\"editing\" let-ri=\"rowIndex\">\r\n <tr [pEditableRow]=\"item\" class=\"cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 border-b\">\r\n @if (selectedColumns) {\r\n @for (column of selectedColumns; track $index){\r\n <td>\r\n <div class=\"flex flex-col gap-2\">\r\n <p-cellEditor>\r\n <ng-template #input>\r\n <lib-inline-input [(ngModel)]=\"item.rowData[column.field]\"\r\n (outputValue)=\"inlineChange($event, column.field)\" (outputDebounced)=\"onEditData()\"\r\n [config]=\"inlineControls?.[column.field] ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n\r\n </ng-template>\r\n <ng-template #output>\r\n\r\n @if (inlineControls?.[column.field]?.typeInput === ETypeInput.NUMBER) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[column.field] | number: '1.2-2' }}\r\n\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.CURRENCY) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[column.field] | currency: item?.currencyTypeCellConfig?.[column.field]?.currency ??\r\n 'USD' : item?.currencyTypeCellConfig?.[column.field]?.locale ?? 'es-CO' }}\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.DATE) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[column.field] | date: \"dd/MM/yyyy\" }}\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.DATETIME_LOCAL) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[column.field] | date: \"dd/MM/yyyy HH:mm\" }}\r\n </div>\r\n } @else {\r\n @if (item.rowData[column.field]?.name) {\r\n {{ item.rowData[column.field]?.name }}\r\n } @else {\r\n {{ item.rowData[column.field] }}\r\n }\r\n }\r\n\r\n\r\n </ng-template>\r\n </p-cellEditor>\r\n\r\n @if (rowErrorConfig?.isEnabled && enableErrors && !rowFieldsHasValue()[column.field]) {\r\n <span class=\"text-red-500 italic text-xs\">{{\r\n rowErrorConfig?.fieldErrors?.[item.id]?.[column.field]?.message ??\r\n '' }}</span>\r\n }\r\n </div>\r\n </td>\r\n }\r\n } @else {\r\n @for (key of keys(); track $index){\r\n <td>\r\n <div class=\"flex flex-col gap-2\">\r\n <p-cellEditor>\r\n <ng-template #input>\r\n <lib-inline-input [(ngModel)]=\"item.rowData[key]\" (outputValue)=\"inlineChange($event, key)\"\r\n (outputDebounced)=\"onEditData()\" [config]=\"inlineControls?.[key] ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n </ng-template>\r\n <ng-template #output>\r\n\r\n @if (inlineControls?.[key]?.typeInput === ETypeInput.NUMBER) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[key] | number: '1.2-2' }}\r\n\r\n </div>\r\n }\r\n @else if(inlineControls?.[key]?.typeInput === ETypeInput.CURRENCY) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[key] | currency: item?.currencyTypeCellConfig?.[key]?.currency ?? 'USD' }}\r\n </div>\r\n } @else {\r\n @if (item.rowData[key]?.name) {\r\n {{ item.rowData[key]?.name }}\r\n } @else {\r\n {{ item.rowData[key] }}\r\n }\r\n }\r\n\r\n\r\n </ng-template>\r\n </p-cellEditor>\r\n\r\n @if (rowErrorConfig?.isEnabled && enableErrors && !rowFieldsHasValue()[key]) {\r\n <span class=\"text-red-500 italic text-xs\">{{ rowErrorConfig?.fieldErrors?.[item.id]?.[key]?.message ??\r\n '' }}</span>\r\n }\r\n </div>\r\n </td>\r\n }\r\n }\r\n <td>\r\n <div class=\"flex justify-center items-center gap-2\">\r\n @if(!editing){\r\n <lib-button-ng pButton pRipple pInitEditableRow [buttonConfig]=\"getEditInitButton(item.id)\"\r\n (onClick)=\"onRowEditInit(item)\"></lib-button-ng>\r\n @if(!editConfig()?.rowEditConfig?.isDisabledDeleteButton){\r\n <lib-button-ng [buttonConfig]=\"getDeleteRowButton()\" (onClick)=\"deleteRow(item)\"></lib-button-ng>\r\n }\r\n }\r\n @if(editing){\r\n @if (hasErrorValues(rowErrorConfig?.fieldErrors?.[item.id] ?? {})) {\r\n <lib-button-ng [buttonConfig]=\"editSaveButtonWithErrors()\"\r\n (onClick)=\"onEditSaveWithErrors()\"></lib-button-ng>\r\n }\r\n @else {\r\n <lib-button-ng pButton pRipple pSaveEditableRow [buttonConfig]=\"editSaveButton()\"\r\n (onClick)=\"onRowEditSave(item)\"></lib-button-ng>\r\n }\r\n <lib-button-ng pButton pRipple pCancelEditableRow [buttonConfig]=\"editCancelButton()\"\r\n (onClick)=\"onRowEditCancel(item, ri)\"></lib-button-ng>\r\n }\r\n </div>\r\n </td>\r\n </tr>\r\n </ng-template>\r\n }\r\n }\r\n } @else {\r\n\r\n <ng-template #body let-item let-expanded=\"expanded\">\r\n <tr class=\"p-datatable-row p-selectable-row\" [ngClass]=\"{\r\n 'bg-gray-50 dark:bg-gray-800 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700': item.onClick && !item.isSelected && !item.isLoading,\r\n 'bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600': !item.onClick && !item.isSelected && !item.isLoading,\r\n 'bg-blue-100 dark:bg-blue-900 border-l-4 border-blue-500 hover:bg-blue-200 dark:hover:bg-blue-800': item.isSelected && !item.isLoading,\r\n 'skeleton-row': item.isLoading\r\n }\" (click)=\"item?.isLoading ? null : onRowClick(item)\">\r\n\r\n @if (rowExpansionConfig?.isEnabled) {\r\n <td (click)=\"$event.stopPropagation()\" [class.skeleton-cell]=\"item.isLoading\"\r\n [style.height]=\"item.isLoading ? '3rem' : 'auto'\">\r\n @if (!item.isLoading) {\r\n <lib-button-ng [buttonConfig]=\"rowExpansionButton(expanded)()\" type=\"button\" pRipple\r\n [pRowToggler]=\"item\"></lib-button-ng>\r\n } @else {\r\n <div class=\"skeleton-content\"></div>\r\n }\r\n </td>\r\n }\r\n\r\n @if (selectionTableConfig?.isEnabled) {\r\n <td (click)=\"$event.stopPropagation()\" alignFrozen=\"left\" pFrozenColumn class=\"shadow-lg\"\r\n [class.skeleton-cell]=\"item.isLoading\" [style.height]=\"item.isLoading ? '3rem' : 'auto'\">\r\n @if (!item.isLoading) {\r\n <p-tableCheckbox [id]=\"item\" [value]=\"item\" />\r\n } @else {\r\n <div class=\"skeleton-content\"></div>\r\n }\r\n </td>\r\n }\r\n\r\n @for (key of keys(); track $index) {\r\n @if (isThatItemInTheProductSelection(key)) {\r\n <td [id]=\"key\" class=\"p-datatable-cell\" [style.height]=\"item.isLoading ? '3rem' : 'min-content'\"\r\n alignFrozen=\"right\" pFrozenColumn [ngClass]=\"{\r\n 'p-frozen-column': frozenHandle(frozenColumnConfigByKey?.[key]),\r\n 'text-center': item.rowDataButtons?.[key] || item.typeCell?.[key] === ETypeInput.BADGE,\r\n 'skeleton-cell': item.isLoading\r\n }\" [frozen]=\"frozenHandle(frozenColumnConfigByKey?.[key])\">\r\n @if (item.isLoading) {\r\n <div class=\"skeleton-content\"></div>\r\n } @else {\r\n @if (item.rowDataButtons?.[key]) {\r\n <div class=\"flex gap-4 w-full justify-center items-center\">\r\n @for (btn of item.rowDataButtons[key]; track $index) {\r\n @if (btn) {\r\n <lib-button-ng class=\"w-full\" (click)=\"$event.stopPropagation()\" [buttonConfig]=\"btn\"></lib-button-ng>\r\n }\r\n }\r\n </div>\r\n } @else {\r\n @switch (item.typeCell?.[key]) {\r\n @case (ETypeInput.IMAGE) {\r\n <img [src]=\"item.rowData[key]\" alt=\"Image\" class=\"w-10 h-10 mx-auto\">\r\n }\r\n @case (ETypeInput.DATE) {\r\n {{ item.rowData[key] | date: \"dd/MM/yyyy\" }}\r\n }\r\n @case (ETypeInput.DATETIME_LOCAL) {\r\n {{ item.rowData[key] | date: \"dd/MM/yyyy HH:mm\" }}\r\n }\r\n @case (ETypeInput.CURRENCY) {\r\n {{item?.currencyTypeCellConfig?.[key]?.currency}} {{ item.rowData[key] | currency:\r\n item?.currencyTypeCellConfig?.[key]?.currency ?? 'USD' }}\r\n }\r\n @case (ETypeInput.BADGE) {\r\n <lib-badge-ng [config]=\"item.rowData[key]\"></lib-badge-ng>\r\n }\r\n @case (ETypeInput.COMPONENT) {\r\n <ng-container\r\n *ngTemplateOutlet=\"item.rowDataComponents?.[key]; context: { $implicit: item.raw }\"></ng-container>\r\n }\r\n @default {\r\n @if (isDate(item.rowData[key])) {\r\n {{ item.rowData[key] | date: \"dd/MM/yyyy\" }}\r\n } @else if (typeof item.rowData[key] === \"string\") {\r\n {{ item.rowData[key] }}\r\n } @else if (isPrimeNgSelection(item.rowData[key])) {\r\n {{ item.rowData[key].name }}\r\n } @else if(typeof item.rowData[key] === \"number\") {\r\n <p class=\"text-right\">\r\n {{ item.rowData[key] | number: '1.2-2' }}\r\n </p>\r\n }\r\n }\r\n }\r\n }\r\n }\r\n </td>\r\n }\r\n }\r\n </tr>\r\n </ng-template>\r\n }\r\n }\r\n\r\n <ng-template #footer>\r\n @if (footerEnabled) {\r\n @for (row of footerRows; track $index) {\r\n <tr class=\"p-datatable-row p-datatable-footer-row\">\r\n @for (cell of row; track $index) {\r\n <td colSpan=\"{{ cell.colSpan }}\" class=\"{{ cell.class }} text-right font-bold p-3 pb-0\">{{\r\n applyPipe(cell.value,\r\n cell.pipeConfig) }}</td>\r\n\r\n }\r\n </tr>\r\n }\r\n\r\n }\r\n </ng-template>\r\n <ng-template #expandedrow let-item>\r\n <tr>\r\n <td colspan=\"100%\">\r\n <div class=\"p-datatable-row-expansion\">\r\n <ng-container *ngTemplateOutlet=\"currentItemTemplate; context: { $implicit: item }\"></ng-container>\r\n\r\n </div>\r\n </td>\r\n </tr>\r\n </ng-template>\r\n </p-table>\r\n @if (showBottomToolbar()) {\r\n <div class=\"p-datatable-footer sticky bottom-2 z-9 animate__animated animate__fadeIn\">\r\n <lib-toolbar-ng>\r\n @if (showManagementSelectionConfig()) {\r\n <div toolbarStart\r\n class=\"p-datatable-footer-content flex items-center gap-3 px-4 rounded-lg animate__animated animate__fadeIn\">\r\n <span class=\"font-medium text-gray-700\">Has seleccionado</span>\r\n <div class=\"p-datatable-footer-badge flex items-center justify-center min-w-[28px] h-7 px-2 rounded-md\">\r\n <span class=\"font-semibold text-gray-900\">{{\r\n totalItemsSelected().toLocaleString()\r\n }}</span>\r\n </div>\r\n <span class=\"text-sm text-gray-600\">registros</span>\r\n <lib-button-ng [buttonConfig]=\"showSelectedItemsManagementButton()\"></lib-button-ng>\r\n </div>\r\n }\r\n </lib-toolbar-ng>\r\n </div>\r\n }\r\n</div>\r\n@if (httpMessage()) {\r\n<lib-http-message [(httpMessage)]=\"httpMessage\"></lib-http-message>\r\n}", styles: [".cursor-pointer{cursor:pointer}.empty-data-message{text-align:center;padding:2rem;color:#6c757d;font-style:italic}.table-title-container{background:var(--p-surface-50);border-bottom:1px solid var(--p-surface-200);padding:1.25rem 2rem;position:relative}.table-title{color:var(--p-text-color);font-size:1.5rem;font-weight:600;text-align:center;margin:0;letter-spacing:-.025em;text-shadow:0 1px 2px rgba(0,0,0,.05);background:linear-gradient(135deg,var(--p-text-color) 0%,var(--p-text-muted-color) 100%);background-clip:text;-webkit-background-clip:text;-webkit-text-fill-color:transparent;position:relative}.table-title:after{content:\"\";position:absolute;bottom:-.5rem;left:50%;transform:translate(-50%);width:60px;height:2px;background:linear-gradient(90deg,var(--p-primary-color),var(--p-primary-600));border-radius:1px}:host ::ng-deep .p-datatable-paginator{background:var(--p-surface-100);border-top:1px solid var(--p-surface-300);padding:1rem}:host ::ng-deep .p-datatable-paginator .p-paginator{background:transparent;border:none;padding:0}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page{background:var(--p-surface-200);border:1px solid var(--p-surface-300);color:var(--p-text-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page:hover{background:var(--p-surface-300);border-color:var(--p-primary-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page.p-highlight{background:var(--p-primary-color);border-color:var(--p-primary-color);color:var(--p-primary-contrast-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last{background:var(--p-surface-200);border:1px solid var(--p-surface-300);color:var(--p-text-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first:hover,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev:hover,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next:hover,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last:hover{background:var(--p-surface-300);border-color:var(--p-primary-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first:disabled,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev:disabled,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next:disabled,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last:disabled{background:var(--p-surface-100);border-color:var(--p-surface-300);color:var(--p-text-muted-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-current{color:var(--p-text-color);font-weight:500}:host ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown{background:var(--p-surface-200);border:1px solid var(--p-surface-300);color:var(--p-text-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown:hover{border-color:var(--p-primary-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown:focus{border-color:var(--p-primary-color);box-shadow:0 0 0 2px var(--p-primary-color-100)}.skeleton-row{pointer-events:none;-webkit-user-select:none;user-select:none;min-height:3rem}.skeleton-cell{position:relative;overflow:hidden;min-height:3rem;padding:.75rem .5rem!important}.skeleton-cell .skeleton-content{position:absolute;inset:.5rem;min-height:1.5rem;background:linear-gradient(90deg,#d1d5db33,#d1d5db66,#d1d5db33);background-size:200% 100%;animation:skeleton-loading 1.5s ease-in-out infinite;border-radius:4px}@keyframes skeleton-loading{0%{background-position:200% 0}to{background-position:-200% 0}}:host-context(.dark) .skeleton-cell .skeleton-content{background:linear-gradient(90deg,#4b556333,#4b556366,#4b556333);background-size:200% 100%}:host ::ng-deep .p-datatable .p-datatable-tbody .skeleton-row .skeleton-cell{width:auto;min-width:fit-content}:host-context(.my-app-dark) .table-title-container{background:var(--p-surface-800);border-bottom-color:var(--p-surface-700)}:host-context(.my-app-dark) .table-title{color:var(--p-text-color);background:linear-gradient(135deg,var(--p-text-color) 0%,var(--p-text-muted-color) 100%);background-clip:text;-webkit-background-clip:text;-webkit-text-fill-color:transparent}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator{background:var(--p-surface-900);border-top-color:var(--p-surface-800)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page{background:var(--p-surface-800);border-color:var(--p-surface-700);color:var(--p-text-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page:hover{background:var(--p-surface-700);border-color:var(--p-primary-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page.p-highlight{background:var(--p-primary-color);border-color:var(--p-primary-color);color:var(--p-primary-contrast-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last{background:var(--p-surface-800);border-color:var(--p-surface-700);color:var(--p-text-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first:hover,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev:hover,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next:hover,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last:hover{background:var(--p-surface-700);border-color:var(--p-primary-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first:disabled,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev:disabled,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next:disabled,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last:disabled{background:var(--p-surface-900);border-color:var(--p-surface-800);color:var(--p-text-muted-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-current{color:var(--p-text-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown{background:var(--p-surface-800);border-color:var(--p-surface-700);color:var(--p-text-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown:hover{border-color:var(--p-primary-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown:focus{border-color:var(--p-primary-color);box-shadow:0 0 0 2px var(--p-primary-color-100)}.flex{display:flex}.flex-col{flex-direction:column}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.justify-center{justify-content:center}.items-center{align-items:center}.text-center{text-align:center}.text-right{text-align:right}.text-left{text-align:left}.text-gray-400{color:#9ca3af}.text-gray-500{color:#6b7280}.text-gray-600{color:#4b5563}.text-gray-700{color:#374151}.text-gray-900{color:#111827}.text-blue-500{color:#3b82f6}.text-red-500{color:#ef4444}.text-green-500{color:#22c55e}.text-xs{font-size:.75rem;line-height:1rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.font-medium{font-weight:500}.font-semibold{font-weight:600}.font-bold{font-weight:700}.italic{font-style:italic}.w-full{width:100%}.w-10{width:2.5rem}.h-10{height:2.5rem}.h-7{height:1.75rem}.min-w-28{min-width:28px}.mx-auto{margin-left:auto;margin-right:auto}.p-1{padding:.25rem}.p-3{padding:.75rem}.p-8{padding:2rem}.px-0{padding-left:0;padding-right:0}.py-0{padding-top:0;padding-bottom:0}.px-2{padding-left:.5rem;padding-right:.5rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.px-4{padding-left:1rem;padding-right:1rem}.pb-0{padding-bottom:0}.bg-gray-50{background-color:#f9fafb}.bg-gray-100{background-color:#f3f4f6}.bg-gray-200{background-color:#e5e7eb}.bg-gray-600{background-color:#4b5563}.bg-gray-700{background-color:#374151}.bg-gray-800{background-color:#1f2937}.bg-blue-100{background-color:#dbeafe}.bg-blue-200{background-color:#bfdbfe}.bg-blue-800{background-color:#1e40af}.bg-blue-900{background-color:#1e3a8a}.bg-green-200{background-color:#bbf7d0}.border-b{border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:var(--p-surface-300)}.border-l-4{border-left-width:4px;border-left-style:solid}.border-blue-500{border-color:#3b82f6}.rounded-full{border-radius:9999px}.rounded-md{border-radius:.375rem}.rounded-lg{border-radius:.5rem}.shadow-sm{box-shadow:0 1px 2px #0000000d}.shadow-lg{box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -2px #0000000d}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-300{transition-duration:.3s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.sticky{position:sticky}.top-0{top:0}.bottom-2{bottom:.5rem}.bottom-18{bottom:4.5rem}.z-9{z-index:9}.z-10{z-index:10}.z-30{z-index:30}.hover\\:bg-gray-50:hover{background-color:#f9fafb}.hover\\:bg-gray-100:hover{background-color:#f3f4f6}.hover\\:bg-gray-200:hover{background-color:#e5e7eb}.hover\\:bg-blue-200:hover{background-color:#bfdbfe}.hover\\:bg-blue-800:hover{background-color:#1e40af}:host-context(.dark) .dark\\:bg-gray-800{background-color:#1f2937}:host-context(.dark) .dark\\:bg-gray-700{background-color:#374151}:host-context(.dark) .dark\\:bg-gray-600{background-color:#4b5563}:host-context(.dark) .dark\\:bg-blue-900{background-color:#1e3a8a}:host-context(.dark) .dark\\:bg-blue-800{background-color:#1e40af}:host-context(.dark) .dark\\:hover\\:bg-gray-800:hover{background-color:#1f2937}:host-context(.dark) .dark\\:hover\\:bg-gray-700:hover{background-color:#374151}:host-context(.dark) .dark\\:hover\\:bg-gray-600:hover{background-color:#4b5563}:host-context(.dark) .dark\\:hover\\:bg-blue-800:hover{background-color:#1e40af}.animate__animated{animation-duration:1s;animation-fill-mode:both}.animate__fadeIn{animation-name:fadeIn}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}\n"] }]
2469
+ }], ctorParameters: () => [], propDecorators: { dt: [{
2470
+ type: ViewChild,
2471
+ args: ['dt']
2472
+ }], itemTemplate: [{
2473
+ type: ContentChild,
2474
+ args: ['item', { static: true }]
2475
+ }] } });
2476
+
181
2477
  /*
182
2478
  * Public API Surface of lib-components
183
2479
 
@@ -193,5 +2489,5 @@ de13d65e8a0357ce9f2e18c899c8e7f6f728181baa031761ecdd7ef5cb166eb2
193
2489
  * Generated bundle index. Do not edit.
194
2490
  */
195
2491
 
196
- export { ButtonComponent, ButtonNgComponent, EmptyMessageComponent, LibComponentsComponent, LibComponentsService };
2492
+ export { ButtonNgComponent, ETypeInput, FormComponent, InlineInputComponent, LibComponentsComponent, LibComponentsService, TableNgComponent };
197
2493
  //# sourceMappingURL=ln-20-lib-components.mjs.map