sapenlinea-components 0.0.27 → 0.0.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,267 +1,293 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, output, signal, computed, effect, forwardRef, Component, EventEmitter, Output, Input, HostListener, ViewChildren } from '@angular/core';
3
- import * as i1$1 from '@angular/forms';
4
- import { ReactiveFormsModule, NG_VALUE_ACCESSOR, FormsModule, FormGroup, FormControl, Validators } from '@angular/forms';
2
+ import { EventEmitter, signal, computed, Output, Input as Input$1, Component, input, output, HostListener, ViewChildren, forwardRef, effect, model, Injectable } from '@angular/core';
5
3
  import * as i1 from '@angular/common';
6
4
  import { CommonModule } from '@angular/common';
5
+ import * as i1$1 from '@angular/forms';
6
+ import { NG_VALUE_ACCESSOR, ReactiveFormsModule, FormsModule, FormGroup, FormControl, Validators } from '@angular/forms';
7
+ import PubSub from 'pubsub-js';
7
8
 
8
- class DateTimeFilter {
9
- elementRef;
10
- ngZone;
11
- // Inputs
12
- filters = input([], ...(ngDevMode ? [{ debugName: "filters" }] : []));
13
- // Outputs
14
- dateSelected = output();
15
- dateChange = output();
16
- // Internal State
17
- activeFilterType = signal(null, ...(ngDevMode ? [{ debugName: "activeFilterType" }] : []));
9
+ class PaginationComponent {
10
+ page = 1;
11
+ pageSize = 10;
12
+ totalItems = 0;
13
+ showPageSizeSelector = false;
14
+ pageSizeOptions = [5, 10, 20, 50];
15
+ pageChange = new EventEmitter();
16
+ pageSizeChange = new EventEmitter();
17
+ pageSizeValue = signal(this.pageSize, ...(ngDevMode ? [{ debugName: "pageSizeValue" }] : []));
18
18
  isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
19
- selectedDate = signal(null, ...(ngDevMode ? [{ debugName: "selectedDate" }] : []));
20
- inputTextValue = signal('', ...(ngDevMode ? [{ debugName: "inputTextValue" }] : []));
21
19
  isDisabled = signal(false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : []));
22
- isTouched = signal(false, ...(ngDevMode ? [{ debugName: "isTouched" }] : []));
23
- // Máscara visual dinámica para la guía de fecha __/__/____
24
- // Devuelve un arreglo de caracteres con flag "filled" para poder dar color distinto
25
- inputMask = computed(() => {
26
- const raw = this.inputTextValue() || '';
27
- const numbersOnly = raw.replace(/\D/g, '');
28
- const template = [
29
- { char: 'd', filled: false },
30
- { char: 'd', filled: false },
31
- { char: '/', filled: false },
32
- { char: 'm', filled: false },
33
- { char: 'm', filled: false },
34
- { char: '/', filled: false },
35
- { char: 'y', filled: false },
36
- { char: 'y', filled: false },
37
- { char: 'y', filled: false },
38
- { char: 'y', filled: false },
39
- ];
40
- let index = 0;
41
- for (let i = 0; i < template.length && index < numbersOnly.length; i++) {
42
- if (template[i].char === '/')
43
- continue;
44
- template[i] = { char: numbersOnly[index++], filled: true };
45
- }
46
- // Cuando se completa el segmento, el slash correspondiente pasa a "filled"
47
- if (numbersOnly.length >= 2) {
48
- template[2] = { char: '/', filled: true }; // después de DD
49
- }
50
- if (numbersOnly.length >= 4) {
51
- template[5] = { char: '/', filled: true }; // después de MM
52
- }
53
- return template; // para usar en el template y colorear por carácter
54
- }, ...(ngDevMode ? [{ debugName: "inputMask" }] : []));
55
- clearTrigger = input(0, ...(ngDevMode ? [{ debugName: "clearTrigger" }] : []));
56
- // Computed Properties based on active filter
57
- activeFilter = computed(() => {
58
- const type = this.activeFilterType();
59
- return this.filters().find(f => f.value === type) || null;
60
- }, ...(ngDevMode ? [{ debugName: "activeFilter" }] : []));
61
- mode = computed(() => {
62
- const filter = this.activeFilter();
63
- return filter?.type === 'datetime' ? 'datetime' : 'date';
64
- }, ...(ngDevMode ? [{ debugName: "mode" }] : []));
65
- placeholder = computed(() => this.activeFilter()?.placeholder || 'Seleccionar fecha', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
66
- minDate = computed(() => this.activeFilter()?.minDate || null, ...(ngDevMode ? [{ debugName: "minDate" }] : []));
67
- maxDate = computed(() => this.activeFilter()?.maxDate || null, ...(ngDevMode ? [{ debugName: "maxDate" }] : []));
68
- filterValue = computed(() => this.activeFilter()?.value || '', ...(ngDevMode ? [{ debugName: "filterValue" }] : []));
69
- // Calendar Navigation
70
- currentMonth = signal(new Date().getMonth(), ...(ngDevMode ? [{ debugName: "currentMonth" }] : []));
71
- currentYear = signal(new Date().getFullYear(), ...(ngDevMode ? [{ debugName: "currentYear" }] : []));
72
- // Time State
73
- selectedHour = signal(0, ...(ngDevMode ? [{ debugName: "selectedHour" }] : []));
74
- selectedMinute = signal(0, ...(ngDevMode ? [{ debugName: "selectedMinute" }] : []));
75
- selectedAmPm = signal('AM', ...(ngDevMode ? [{ debugName: "selectedAmPm" }] : []));
76
- documentClickListener;
77
- onChange = () => { };
78
- onTouched = () => { };
79
- constructor(elementRef, ngZone) {
80
- this.elementRef = elementRef;
81
- this.ngZone = ngZone;
82
- effect(() => {
83
- const trigger = this.clearTrigger();
84
- if (trigger > 0) {
85
- this.clear();
86
- }
87
- });
20
+ showPageSizeMenu = signal(false, ...(ngDevMode ? [{ debugName: "showPageSizeMenu" }] : []));
21
+ totalPages = computed(() => {
22
+ const size = this.pageSizeValue();
23
+ const total = this.totalItems;
24
+ return size > 0 ? Math.ceil(total / size) : 1;
25
+ }, ...(ngDevMode ? [{ debugName: "totalPages" }] : []));
26
+ pages = computed(() => {
27
+ const tp = this.totalPages();
28
+ return Array.from({ length: tp }, (_, i) => i + 1);
29
+ }, ...(ngDevMode ? [{ debugName: "pages" }] : []));
30
+ selectedPageSize = computed(() => this.pageSizeValue(), ...(ngDevMode ? [{ debugName: "selectedPageSize" }] : []));
31
+ goToPage(p) {
32
+ if (p < 1 || p > this.totalPages())
33
+ return;
34
+ this.pageChange.emit(p);
88
35
  }
89
- ngOnDestroy() {
90
- this.removeDocumentListener();
36
+ togglePageSizeMenu() {
37
+ this.isOpen.update(v => !v);
38
+ this.showPageSizeMenu.update(v => !v);
91
39
  }
92
- // ControlValueAccessor Implementation
93
- writeValue(value) {
94
- let date = null;
95
- if (value instanceof Date) {
96
- date = value;
97
- }
98
- else if (typeof value === 'string' && value) {
99
- const parsedDate = new Date(value);
100
- if (!isNaN(parsedDate.getTime())) {
101
- date = parsedDate;
102
- }
103
- }
104
- if (date) {
105
- this.updateInternalState(date);
106
- }
107
- else {
108
- this.resetInternalState();
109
- }
40
+ selectPageSize(size) {
41
+ this.pageSizeValue.set(size);
42
+ this.pageSizeChange.emit(size);
43
+ this.showPageSizeMenu.set(false);
44
+ this.isOpen.set(false);
110
45
  }
111
- registerOnChange(fn) {
112
- this.onChange = fn;
46
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: PaginationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
47
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: PaginationComponent, isStandalone: true, selector: "lib-pagination", inputs: { page: "page", pageSize: "pageSize", totalItems: "totalItems", showPageSizeSelector: "showPageSizeSelector", pageSizeOptions: "pageSizeOptions" }, outputs: { pageChange: "pageChange", pageSizeChange: "pageSizeChange" }, ngImport: i0, template: "<div class=\"pagination-container\">\r\n <div class=\"pagination\">\r\n <!-- Bot\u00F3n doble atr\u00E1s -->\r\n <button class=\"icon-button\" (click)=\"goToPage(1)\" [disabled]=\"page === 1\">\r\n \u00AB\u00AB\r\n </button>\r\n\r\n <!-- Bot\u00F3n atr\u00E1s -->\r\n <button class=\"icon-button\" (click)=\"goToPage(page - 1)\" [disabled]=\"page === 1\">\r\n \u00AB\r\n </button>\r\n\r\n <!-- N\u00FAmeros de p\u00E1gina -->\r\n <div class=\"pages\">\r\n <button\r\n class=\"page-btn\"\r\n *ngFor=\"let p of pages(); let idx = index\"\r\n [class.active]=\"page === idx + 1\"\r\n (click)=\"goToPage(idx + 1)\"\r\n >\r\n {{ idx + 1 }}\r\n </button>\r\n </div>\r\n\r\n <!-- Bot\u00F3n siguiente -->\r\n <button class=\"icon-button\" (click)=\"goToPage(page + 1)\" [disabled]=\"page === totalPages()\">\r\n \u00BB\r\n </button>\r\n\r\n <!-- Bot\u00F3n doble adelante -->\r\n <button class=\"icon-button\" (click)=\"goToPage(totalPages())\" [disabled]=\"page === totalPages()\">\r\n \u00BB\u00BB\r\n </button>\r\n </div>\r\n\r\n <!-- Selector Items por p\u00E1gina -->\r\n <div *ngIf=\"showPageSizeSelector\">\r\n <div class=\"pagination-v-4\">\r\n <div class=\"label-pagination\">Items por p\u00E1gina</div>\r\n <div class=\"elements-pagination\">\r\n <div class=\"split-button\" (click)=\"togglePageSizeMenu()\">\r\n <div class=\"leading-button\">\r\n <div class=\"state-layer\">\r\n <div class=\"label\">{{ pageSizeValue() }}</div>\r\n </div>\r\n </div>\r\n <div class=\"trailing-button\">\r\n <div class=\"arrow\" [class.open]=\"isOpen()\">\r\n <svg class=\"arrow\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" fill=\"none\" stroke-width=\"2\">\r\n <polyline points=\"6 9 12 15 18 9\"></polyline>\r\n </svg>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Men\u00FA desplegable -->\r\n <div class=\"page-size-menu\" *ngIf=\"showPageSizeMenu()\">\r\n <div\r\n class=\"menu-option\"\r\n *ngFor=\"let opt of pageSizeOptions\"\r\n [class.active]=\"opt === pageSizeValue()\"\r\n (click)=\"selectPageSize(opt)\"\r\n >\r\n {{ opt }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".pagination-container{display:flex;flex-direction:row;justify-content:center;width:100%;padding:8px 0;position:relative}.pagination{display:flex;align-items:center;gap:12px;padding:12px;justify-content:center;flex:1}.icon-button{width:40px;height:40px;border-radius:50%;background:var(--primary, #596300);color:var(--surface, #ffffff);border:none;cursor:pointer;font-size:16px;font-weight:700;display:flex;align-items:center;justify-content:center;box-shadow:0 1px 2px #00000026;transition:background .2s ease,transform .1s ease}.icon-button:disabled{background:#969696;color:var(--on-surface, #171c1f);opacity:.45;cursor:not-allowed}.pages{display:flex;gap:4px;overflow:hidden;border-radius:20px}.page-btn{background:var(--secondary-container, #dee58f);width:40px;height:40px;border:none;cursor:pointer;padding:8px 14px;font-size:14px;color:var(--schemes-on-surface, #3a3a3a);font-family:Roboto,sans-serif;border-radius:8px;transition:background .2s ease}.page-btn:hover:not(.active){background:var(--schemes-on-secondary-container, #61661f);color:var(--schemes-secondary-container, #dee58f)}.page-btn.active{background:var(--schemes-primary, #596300);color:var(--schemes-on-primary, #ffffff);font-weight:600;border-radius:20px}.pagination-v-4{display:flex;gap:10px;align-items:center;margin-left:auto}.label-pagination{font-size:14px;font-weight:600;color:var(--schemes-on-surface)}.elements-pagination{position:relative;display:flex;gap:4px;border-radius:20px}.split-button{display:flex;cursor:pointer;border-radius:20px;overflow:hidden}.leading-button{background:var(--schemes-secondary-container);border-radius:20px 4px 4px 20px;display:flex;align-items:center;height:40px}.state-layer{padding:10px 16px;background-color:#dee58f;margin-right:4px;border-radius:8px}.state-layer:open{color:#f5f5e0;background-color:#596300}.label{font-size:14px;font-weight:500;color:var(--schemes-on-secondary-container)}.trailing-button{background:var(--secondary-container, #dee58f);padding-left:12px;padding-right:12px;border:none;cursor:pointer;font-size:14px;color:var(--schemes-on-surface, #3a3a3a);font-family:Roboto,sans-serif;border-radius:8px;transition:background .2s ease;align-items:center;align-content:center}.arrow{width:20px;height:20px;color:#171c1f;transition:transform .25s ease}.arrow.open{transform:rotate(180deg)}.page-size-menu{background:#f5f5e0;position:absolute;min-width:100px;border-radius:4px;box-shadow:0 2px 8px #0003;overflow:hidden;z-index:999;bottom:50px;right:0;transform-origin:top right}.menu-option{padding:8px 12px;cursor:pointer}.menu-option:hover{background:#dee58f5b}.menu-option.active{background:#dee58f;color:#61661f}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
48
+ }
49
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: PaginationComponent, decorators: [{
50
+ type: Component,
51
+ args: [{ selector: 'lib-pagination', standalone: true, imports: [CommonModule], template: "<div class=\"pagination-container\">\r\n <div class=\"pagination\">\r\n <!-- Bot\u00F3n doble atr\u00E1s -->\r\n <button class=\"icon-button\" (click)=\"goToPage(1)\" [disabled]=\"page === 1\">\r\n \u00AB\u00AB\r\n </button>\r\n\r\n <!-- Bot\u00F3n atr\u00E1s -->\r\n <button class=\"icon-button\" (click)=\"goToPage(page - 1)\" [disabled]=\"page === 1\">\r\n \u00AB\r\n </button>\r\n\r\n <!-- N\u00FAmeros de p\u00E1gina -->\r\n <div class=\"pages\">\r\n <button\r\n class=\"page-btn\"\r\n *ngFor=\"let p of pages(); let idx = index\"\r\n [class.active]=\"page === idx + 1\"\r\n (click)=\"goToPage(idx + 1)\"\r\n >\r\n {{ idx + 1 }}\r\n </button>\r\n </div>\r\n\r\n <!-- Bot\u00F3n siguiente -->\r\n <button class=\"icon-button\" (click)=\"goToPage(page + 1)\" [disabled]=\"page === totalPages()\">\r\n \u00BB\r\n </button>\r\n\r\n <!-- Bot\u00F3n doble adelante -->\r\n <button class=\"icon-button\" (click)=\"goToPage(totalPages())\" [disabled]=\"page === totalPages()\">\r\n \u00BB\u00BB\r\n </button>\r\n </div>\r\n\r\n <!-- Selector Items por p\u00E1gina -->\r\n <div *ngIf=\"showPageSizeSelector\">\r\n <div class=\"pagination-v-4\">\r\n <div class=\"label-pagination\">Items por p\u00E1gina</div>\r\n <div class=\"elements-pagination\">\r\n <div class=\"split-button\" (click)=\"togglePageSizeMenu()\">\r\n <div class=\"leading-button\">\r\n <div class=\"state-layer\">\r\n <div class=\"label\">{{ pageSizeValue() }}</div>\r\n </div>\r\n </div>\r\n <div class=\"trailing-button\">\r\n <div class=\"arrow\" [class.open]=\"isOpen()\">\r\n <svg class=\"arrow\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" fill=\"none\" stroke-width=\"2\">\r\n <polyline points=\"6 9 12 15 18 9\"></polyline>\r\n </svg>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Men\u00FA desplegable -->\r\n <div class=\"page-size-menu\" *ngIf=\"showPageSizeMenu()\">\r\n <div\r\n class=\"menu-option\"\r\n *ngFor=\"let opt of pageSizeOptions\"\r\n [class.active]=\"opt === pageSizeValue()\"\r\n (click)=\"selectPageSize(opt)\"\r\n >\r\n {{ opt }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".pagination-container{display:flex;flex-direction:row;justify-content:center;width:100%;padding:8px 0;position:relative}.pagination{display:flex;align-items:center;gap:12px;padding:12px;justify-content:center;flex:1}.icon-button{width:40px;height:40px;border-radius:50%;background:var(--primary, #596300);color:var(--surface, #ffffff);border:none;cursor:pointer;font-size:16px;font-weight:700;display:flex;align-items:center;justify-content:center;box-shadow:0 1px 2px #00000026;transition:background .2s ease,transform .1s ease}.icon-button:disabled{background:#969696;color:var(--on-surface, #171c1f);opacity:.45;cursor:not-allowed}.pages{display:flex;gap:4px;overflow:hidden;border-radius:20px}.page-btn{background:var(--secondary-container, #dee58f);width:40px;height:40px;border:none;cursor:pointer;padding:8px 14px;font-size:14px;color:var(--schemes-on-surface, #3a3a3a);font-family:Roboto,sans-serif;border-radius:8px;transition:background .2s ease}.page-btn:hover:not(.active){background:var(--schemes-on-secondary-container, #61661f);color:var(--schemes-secondary-container, #dee58f)}.page-btn.active{background:var(--schemes-primary, #596300);color:var(--schemes-on-primary, #ffffff);font-weight:600;border-radius:20px}.pagination-v-4{display:flex;gap:10px;align-items:center;margin-left:auto}.label-pagination{font-size:14px;font-weight:600;color:var(--schemes-on-surface)}.elements-pagination{position:relative;display:flex;gap:4px;border-radius:20px}.split-button{display:flex;cursor:pointer;border-radius:20px;overflow:hidden}.leading-button{background:var(--schemes-secondary-container);border-radius:20px 4px 4px 20px;display:flex;align-items:center;height:40px}.state-layer{padding:10px 16px;background-color:#dee58f;margin-right:4px;border-radius:8px}.state-layer:open{color:#f5f5e0;background-color:#596300}.label{font-size:14px;font-weight:500;color:var(--schemes-on-secondary-container)}.trailing-button{background:var(--secondary-container, #dee58f);padding-left:12px;padding-right:12px;border:none;cursor:pointer;font-size:14px;color:var(--schemes-on-surface, #3a3a3a);font-family:Roboto,sans-serif;border-radius:8px;transition:background .2s ease;align-items:center;align-content:center}.arrow{width:20px;height:20px;color:#171c1f;transition:transform .25s ease}.arrow.open{transform:rotate(180deg)}.page-size-menu{background:#f5f5e0;position:absolute;min-width:100px;border-radius:4px;box-shadow:0 2px 8px #0003;overflow:hidden;z-index:999;bottom:50px;right:0;transform-origin:top right}.menu-option{padding:8px 12px;cursor:pointer}.menu-option:hover{background:#dee58f5b}.menu-option.active{background:#dee58f;color:#61661f}\n"] }]
52
+ }], propDecorators: { page: [{
53
+ type: Input$1
54
+ }], pageSize: [{
55
+ type: Input$1
56
+ }], totalItems: [{
57
+ type: Input$1
58
+ }], showPageSizeSelector: [{
59
+ type: Input$1
60
+ }], pageSizeOptions: [{
61
+ type: Input$1
62
+ }], pageChange: [{
63
+ type: Output
64
+ }], pageSizeChange: [{
65
+ type: Output
66
+ }] } });
67
+
68
+ const STATUS_TONE_STYLES = {
69
+ success: { bg: '#E6F4EA', color: '#1E8E3E' },
70
+ error: { bg: '#FCE8E6', color: '#D93025' },
71
+ warning: { bg: '#FFF4E5', color: '#E67E22' },
72
+ info: { bg: '#E6F4EA', color: '#0077B6' },
73
+ neutral: { bg: '#F4F4F4', color: '#5F6368' },
74
+ };
75
+ class Table {
76
+ columns = input([], ...(ngDevMode ? [{ debugName: "columns" }] : []));
77
+ data = input([], ...(ngDevMode ? [{ debugName: "data" }] : []));
78
+ actions = input([], ...(ngDevMode ? [{ debugName: "actions" }] : []));
79
+ showActions = input(true, ...(ngDevMode ? [{ debugName: "showActions" }] : []));
80
+ openedMenu = signal(null, ...(ngDevMode ? [{ debugName: "openedMenu" }] : []));
81
+ selectedRow = signal(null, ...(ngDevMode ? [{ debugName: "selectedRow" }] : []));
82
+ sortColumn = signal(null, ...(ngDevMode ? [{ debugName: "sortColumn" }] : []));
83
+ sortDirection = signal('desc', ...(ngDevMode ? [{ debugName: "sortDirection" }] : []));
84
+ optionSelected = output();
85
+ iconAction = output();
86
+ statusToneMap = input({}, ...(ngDevMode ? [{ debugName: "statusToneMap" }] : []));
87
+ chips;
88
+ ngAfterViewInit() {
89
+ setTimeout(() => {
90
+ const chipEls = this.chips.map(c => c.nativeElement);
91
+ const widths = chipEls.map(el => el.scrollWidth);
92
+ const maxContentWidth = Math.max(...widths);
93
+ chipEls.forEach(el => {
94
+ el.style.width = maxContentWidth + 'px';
95
+ });
96
+ });
113
97
  }
114
- registerOnTouched(fn) {
115
- this.onTouched = fn;
98
+ toggleMenu(index) {
99
+ this.openedMenu.set(this.openedMenu() === index ? null : index);
116
100
  }
117
- setDisabledState(isDisabled) {
118
- this.isDisabled.set(isDisabled);
101
+ onOptionClick(option, row) {
102
+ this.optionSelected.emit({ action: option.label, row });
103
+ this.openedMenu.set(null);
119
104
  }
120
- // Public Methods
121
- toggle(filterValue) {
122
- if (this.isDisabled())
123
- return;
124
- if (this.activeFilterType() === filterValue && this.isOpen()) {
125
- this.close();
105
+ openModal(row, event) {
106
+ event?.stopPropagation();
107
+ if (this.selectedRow()?.['id'] === row['id']) {
108
+ this.selectedRow.set(null);
126
109
  }
127
110
  else {
128
- this.activeFilterType.set(filterValue);
129
- this.open();
111
+ this.selectedRow.set(row);
130
112
  }
131
113
  }
132
- open() {
133
- if (this.isDisabled())
134
- return;
135
- this.markAsTouched();
136
- this.isOpen.set(true);
137
- this.addDocumentListener();
138
- const selected = this.selectedDate();
139
- if (selected) {
140
- this.currentMonth.set(selected.getMonth());
141
- this.currentYear.set(selected.getFullYear());
114
+ onClickOutside(event) {
115
+ const target = event.target;
116
+ if (!target.closest('.menu-acciones')) {
117
+ this.selectedRow.set(null);
142
118
  }
143
119
  }
144
- close() {
145
- this.isOpen.set(false);
146
- this.removeDocumentListener();
147
- this.markAsTouched();
148
- // Don't clear activeFilterType here to keep the chip active if needed,
149
- // or clear it if you want the chip to look inactive when closed.
150
- // For now, let's keep it active only if a date is selected?
151
- // Or maybe we want to close the dropdown but keep the filter "selected" in UI?
152
- // Let's just close the dropdown.
153
- }
154
- // Calendar Logic
155
- selectDay(day) {
156
- if (!day || this.isDisabled())
157
- return;
158
- const newDate = new Date(this.currentYear(), this.currentMonth(), day, this.selectedHour(), this.selectedMinute());
159
- if (this.isDateDisabled(newDate))
160
- return;
161
- this.updateInternalState(newDate);
162
- this.onChange(newDate.toISOString());
163
- this.markAsTouched();
164
- this.dateChange.emit(newDate);
165
- this.dateSelected.emit({
166
- filter: this.filterValue(),
167
- value: newDate,
168
- });
169
- if (this.mode() === 'date') {
170
- this.close();
120
+ getAlignment(col) {
121
+ if (col.align && col.align !== 'auto')
122
+ return col.align;
123
+ switch (col.type) {
124
+ case 'number':
125
+ case 'money':
126
+ case 'percentage':
127
+ return 'right';
128
+ case 'status':
129
+ return 'center';
130
+ default:
131
+ return 'left';
171
132
  }
172
133
  }
173
- // ... (Rest of the helper methods like previousMonth, nextMonth, etc. remain largely the same)
174
- displayValue = computed(() => {
175
- const date = this.selectedDate();
176
- if (!date)
134
+ formatValue(col, value) {
135
+ if (value === null || value === undefined)
177
136
  return '';
178
- const options = {
179
- day: '2-digit',
180
- month: '2-digit',
181
- year: 'numeric',
182
- };
183
- if (this.mode() === 'datetime') {
184
- options.hour = '2-digit';
185
- options.minute = '2-digit';
186
- options.hour12 = true;
137
+ switch (col.type) {
138
+ case 'money':
139
+ return new Intl.NumberFormat('es-CO', {
140
+ style: 'currency',
141
+ currency: 'COP',
142
+ minimumFractionDigits: 0
143
+ }).format(value);
144
+ case 'number':
145
+ return new Intl.NumberFormat('es-CO').format(value);
146
+ case 'percentage':
147
+ return `${value}%`;
148
+ case 'date':
149
+ const d = new Date(value);
150
+ return d.toLocaleDateString('es-CO'); // dd/mm/yyyy
151
+ default:
152
+ return String(value);
187
153
  }
188
- return date.toLocaleDateString('es-ES', options);
189
- }, ...(ngDevMode ? [{ debugName: "displayValue" }] : []));
190
- // Input text handling
191
- onInputChange(event, filterValue) {
192
- if (this.isDisabled())
193
- return;
194
- const input = event.target;
195
- let value = input.value;
196
- // Remove all non-numeric characters
197
- const numbersOnly = value.replace(/\D/g, '');
198
- // Limit to 8 digits (DD/MM/YYYY)
199
- const limitedNumbers = numbersOnly.slice(0, 8);
200
- // Format with slashes: DD/MM/YYYY
201
- let formatted = '';
202
- if (limitedNumbers.length > 0) {
203
- formatted = limitedNumbers.slice(0, 2);
204
- if (limitedNumbers.length > 2) {
205
- formatted += '/' + limitedNumbers.slice(2, 4);
154
+ }
155
+ getStatusStyle(value) {
156
+ if (!value) {
157
+ return STATUS_TONE_STYLES.neutral;
158
+ }
159
+ const key = this.normalizeStatus(value);
160
+ const tone = this.statusToneMap()?.[key] ?? 'neutral';
161
+ return STATUS_TONE_STYLES[tone];
162
+ }
163
+ normalizeStatus(value) {
164
+ return String(value ?? '')
165
+ .toLowerCase()
166
+ .trim()
167
+ .replace(/\s+/g, '_');
168
+ }
169
+ /**
170
+ * Devuelve las acciones para una fila.
171
+ * Puede ser que `actions` sea un arreglo (se muestra tal cual) o una función
172
+ * que recibe la fila y retorna las acciones correspondientes.
173
+ */
174
+ getActionsForRow(row) {
175
+ const acts = this.actions();
176
+ if (!acts)
177
+ return [];
178
+ if (typeof acts === 'function') {
179
+ try {
180
+ return acts(row) ?? [];
206
181
  }
207
- if (limitedNumbers.length > 4) {
208
- formatted += '/' + limitedNumbers.slice(4, 8);
182
+ catch {
183
+ return [];
209
184
  }
210
185
  }
211
- // Update the input value
212
- this.inputTextValue.set(formatted);
213
- input.value = formatted;
214
- this.markAsTouched();
215
- // Only parse when we have a complete date (DD/MM/YYYY = 10 characters)
216
- if (formatted.length === 10) {
217
- const parsedDate = this.parseDateInput(formatted);
218
- if (parsedDate) {
219
- if (this.isDateDisabled(parsedDate)) {
220
- // Invalid date (out of range), but keep the text
221
- return;
222
- }
223
- this.updateInternalState(parsedDate);
224
- this.onChange(parsedDate.toISOString());
225
- this.dateChange.emit(parsedDate);
226
- this.dateSelected.emit({
227
- filter: filterValue,
228
- value: parsedDate,
229
- });
186
+ return acts;
187
+ }
188
+ sortData() {
189
+ const col = this.sortColumn();
190
+ if (!col)
191
+ return this.data();
192
+ const dir = this.sortDirection();
193
+ return [...this.data()].sort((a, b) => {
194
+ const x = a[col] ?? '';
195
+ const y = b[col] ?? '';
196
+ // Caso: fechas
197
+ if (this.isDate(x) && this.isDate(y)) {
198
+ return dir === 'asc'
199
+ ? new Date(x).getTime() - new Date(y).getTime()
200
+ : new Date(y).getTime() - new Date(x).getTime();
201
+ }
202
+ // Caso: números
203
+ if (!isNaN(Number(x)) && !isNaN(Number(y))) {
204
+ return dir === 'asc' ? Number(x) - Number(y) : Number(y) - Number(x);
230
205
  }
206
+ // Caso: strings
207
+ return dir === 'asc'
208
+ ? x.toString().localeCompare(y.toString())
209
+ : y.toString().localeCompare(x.toString());
210
+ });
211
+ }
212
+ isDate(value) {
213
+ return (typeof value === 'string' &&
214
+ value.length > 5 &&
215
+ !isNaN(Date.parse(value)));
216
+ }
217
+ onSort(col) {
218
+ if (this.sortColumn() === col.key) {
219
+ // cambiar asc <-> desc
220
+ this.sortDirection.set(this.sortDirection() === 'asc' ? 'desc' : 'asc');
231
221
  }
232
- else if (formatted.trim() === '') {
233
- // Clear if input is empty
234
- this.resetInternalState();
235
- this.onChange(null);
236
- this.dateChange.emit(null);
222
+ else {
223
+ // nueva columna empieza en desc (más reciente primero)
224
+ this.sortColumn.set(col.key);
225
+ this.sortDirection.set('desc');
237
226
  }
238
227
  }
239
- onInputFocus(filterValue) {
240
- if (this.isDisabled())
241
- return;
242
- this.activeFilterType.set(filterValue);
243
- this.open();
228
+ onIconColumnClick(col, row, event) {
229
+ event.stopPropagation();
230
+ this.iconAction.emit({
231
+ action: col.iconKey ?? col.key,
232
+ row
233
+ });
244
234
  }
245
- parseDateInput(input) {
246
- if (!input || input.trim() === '')
247
- return null;
248
- // Only accept DD/MM/YYYY format
249
- const match = input.trim().match(/^(\d{2})\/(\d{2})\/(\d{4})$/);
250
- if (match) {
251
- const day = parseInt(match[1], 10);
252
- const month = parseInt(match[2], 10) - 1;
253
- const year = parseInt(match[3], 10);
254
- // Validate date
255
- if (day >= 1 && day <= 31 && month >= 0 && month <= 11 && year >= 1900 && year <= 2100) {
256
- const date = new Date(year, month, day);
257
- // Check if date is valid (handles invalid dates like 31/02/2024)
258
- if (date.getDate() === day && date.getMonth() === month && date.getFullYear() === year) {
259
- return date;
260
- }
261
- }
235
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Table, deps: [], target: i0.ɵɵFactoryTarget.Component });
236
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: Table, isStandalone: true, selector: "lib-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, showActions: { classPropertyName: "showActions", publicName: "showActions", isSignal: true, isRequired: false, transformFunction: null }, statusToneMap: { classPropertyName: "statusToneMap", publicName: "statusToneMap", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { optionSelected: "optionSelected", iconAction: "iconAction" }, host: { listeners: { "document:click": "onClickOutside($event)" } }, viewQueries: [{ propertyName: "chips", predicate: ["statusChip"], descendants: true }], ngImport: i0, template: "<div class=\"table-wrapper\">\r\n <table class=\"inner-table\">\r\n <thead>\r\n <tr>\r\n @for (col of columns(); track col.key) {\r\n <th\r\n (click)=\"col.sortable !== false && onSort(col)\"\r\n [class.sortable]=\"col.sortable !== false\"\r\n [class]=\"getAlignment(col)\"\r\n >\r\n {{ col.label }}\r\n\r\n <!-- iconos de orden opcionales -->\r\n @if (sortColumn() === col.key) {\r\n <span class=\"sort-icon\">\r\n {{ sortDirection() === 'asc' ? '\u25B2' : '\u25BC' }}\r\n </span>\r\n }\r\n </th>\r\n }\r\n\r\n <!-- columna para acciones -->\r\n @if (showActions()) {\r\n <th></th>\r\n }\r\n </tr>\r\n </thead>\r\n\r\n <tbody>\r\n @for (row of sortData(); track $index) {\r\n <tr>\r\n @for (col of columns(); track col.key) {\r\n <td [class]=\"getAlignment(col)\">\r\n @if (col.type === 'status') { @let style =\r\n getStatusStyle(row[col.key]);\r\n <span #statusChip\r\n class=\"status-chip\"\r\n [style.background-color]=\"style.bg\"\r\n [style.color]=\"style.color\"\r\n >\r\n <span\r\n class=\"status-dot\"\r\n [style.background-color]=\"style.color\"\r\n ></span>\r\n\r\n {{ row[col.key]?.toString().toUpperCase() }}\r\n </span>\r\n\r\n } @else if (col.type === 'icon-button') {\r\n\r\n <button (click)=\"onIconColumnClick(col, row, $event)\">\r\n <span\r\n class=\"icon\"\r\n [class]=\"col.icon\"\r\n [style.color]=\"col.iconColor\"\r\n ></span>\r\n </button>\r\n\r\n } @else { {{ formatValue(col, row[col.key]) }} }\r\n </td>\r\n }\r\n\r\n <!-- Celda de acciones -->\r\n @if (showActions()) {\r\n <td class=\"acciones-cell\">\r\n <div class=\"menu-acciones\">\r\n <button class=\"icon-button\" (click)=\"openModal(row)\">\r\n <div class=\"content\">\r\n <div class=\"state-layer\">\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n class=\"more-vert\"\r\n width=\"20\"\r\n height=\"20\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n >\r\n <circle cx=\"12\" cy=\"5\" r=\"1\" />\r\n <circle cx=\"12\" cy=\"12\" r=\"1\" />\r\n <circle cx=\"12\" cy=\"19\" r=\"1\" />\r\n </svg>\r\n </div>\r\n </div>\r\n </button>\r\n @if(selectedRow()?.['id'] === row['id']){\r\n <div class=\"modal-options\" (click)=\"$event.stopPropagation()\">\r\n <div class=\"modal-content\">\r\n <ul>\r\n @for (option of getActionsForRow(row); track $index) {\r\n <li\r\n class=\"option-item\"\r\n [style.color]=\"option.color\"\r\n (click)=\"onOptionClick(option, row)\"\r\n >\r\n <span class=\"icon\" [class]=\"option.icon\"></span>\r\n <span class=\"label\">{{ option.label }}</span>\r\n </li>\r\n }\r\n </ul>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </td>\r\n }\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n</div>\r\n", styles: [".table-wrapper{width:100%;border-radius:20px;border:1px solid #c7c7ad}.inner-table{width:100%;border-collapse:separate;font-size:14px;border-spacing:0;border-radius:20px;background:#ebe8d6}.inner-table thead{background:#f0f0db}.inner-table thead tr th:first-child{border-top-left-radius:20px}.inner-table thead tr th:last-child{border-top-right-radius:20px}.inner-table th{text-align:left;padding:12px 16px;font-weight:600;color:#3a3a3a;text-transform:uppercase}.inner-table td{padding:12px 16px;color:#4a4a4a;border-top:1px solid #c7c7ad;table-layout:auto}.acciones-cell{text-align:center;padding:6px;position:relative}.menu-acciones{display:flex;align-items:center;justify-content:center;position:relative}button{background-color:transparent;border:none}.icon-button{background-color:var(--secondary-container, #dee58f);width:36px;height:36px;border:none;cursor:pointer;padding:0;border-radius:100%;display:flex;align-items:center;justify-content:center}.icon-button:hover{background:#0000000f}.more-vert{color:#4a4a4a;display:block}.modal-options{display:flex;justify-items:center;align-items:center;background-color:var(--surface-container-lowest, #ffffff);width:200px;border-radius:8px;position:absolute;top:100%;right:0;z-index:99}.modal-content{width:100%;border-radius:8px;border:1px solid var(--outline-variant, #c7c7ad);overflow:hidden}.option-item{display:flex;align-items:center;height:56px;padding:8px 12px;cursor:pointer}.option-item:hover{background-color:#0000001a}.option-item:active{background-color:#dee58f}.icon{margin-right:8px}.option-item .label{font-weight:500;font-size:16px}.icon-refresh,.icon-delete,.icon-edit,.icon-activate,.icon-deactivate,.icon-view,.icon-sanction,.icon-file{width:24px;height:24px;background-color:currentColor;color:currentColor;-webkit-mask-size:contain;-webkit-mask-repeat:no-repeat;mask-size:contain;mask-repeat:no-repeat;display:inline-block;cursor:pointer}.icon-refresh{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M20 11a8.1 8.1 0 0 0 -15.5 -2m-.5 -4v4h4\"/><path d=\"M4 13a8.1 8.1 0 0 0 15.5 2m.5 4v-4h-4\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M20 11a8.1 8.1 0 0 0 -15.5 -2m-.5 -4v4h4\"/><path d=\"M4 13a8.1 8.1 0 0 0 15.5 2m.5 4v-4h-4\"/></svg>')}.icon-delete{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M20 6a1 1 0 0 1 .117 1.993l-.117 .007h-.081l-.919 11a3 3 0 0 1 -2.824 2.995l-.176 .005h-8c-1.598 0 -2.904 -1.249 -2.992 -2.75l-.005 -.167l-.923 -11.083h-.08a1 1 0 0 1 -.117 -1.993l.117 -.007h16z\"/><path d=\"M14 2a2 2 0 0 1 2 2a1 1 0 0 1 -1.993 .117l-.007 -.117h-4l-.007 .117a1 1 0 0 1 -1.993 -.117a2 2 0 0 1 1.85 -1.995l.15 -.005h4z\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M20 6a1 1 0 0 1 .117 1.993l-.117 .007h-.081l-.919 11a3 3 0 0 1 -2.824 2.995l-.176 .005h-8c-1.598 0 -2.904 -1.249 -2.992 -2.75l-.005 -.167l-.923 -11.083h-.08a1 1 0 0 1 -.117 -1.993l.117 -.007h16z\"/><path d=\"M14 2a2 2 0 0 1 2 2a1 1 0 0 1 -1.993 .117l-.007 -.117h-4l-.007 .117a1 1 0 0 1 -1.993 -.117a2 2 0 0 1 1.85 -1.995l.15 -.005h4z\"/></svg>')}.icon-edit{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M4 20h4l10.5 -10.5a2.828 2.828 0 1 0 -4 -4l-10.5 10.5v4\"/><path d=\"M13.5 6.5l4 4\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M4 20h4l10.5 -10.5a2.828 2.828 0 1 0 -4 -4l-10.5 10.5v4\"/><path d=\"M13.5 6.5l4 4\"/></svg>')}.icon-activate{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M17 3.34a10 10 0 1 1 -14.995 8.984l-.005 -.324l.005 -.324a10 10 0 0 1 14.995 -8.336zm-1.293 5.953a1 1 0 0 0 -1.32 -.083l-.094 .083l-3.293 3.292l-1.293 -1.292l-.094 -.083a1 1 0 0 0 -1.403 1.403l.083 .094l2 2l.094 .083a1 1 0 0 0 1.226 0l.094 -.083l4 -4l.083 -.094a1 1 0 0 0 -.083 -1.32z\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M17 3.34a10 10 0 1 1 -14.995 8.984l-.005 -.324l.005 -.324a10 10 0 0 1 14.995 -8.336zm-1.293 5.953a1 1 0 0 0 -1.32 -.083l-.094 .083l-3.293 3.292l-1.293 -1.292l-.094 -.083a1 1 0 0 0 -1.403 1.403l.083 .094l2 2l.094 .083a1 1 0 0 0 1.226 0l.094 -.083l4 -4l.083 -.094a1 1 0 0 0 -.083 -1.32z\"/></svg>')}.icon-deactivate{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M15 9l-6 6M9 9l6 6\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M15 9l-6 6M9 9l6 6\"/></svg>')}.icon-view{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0\"/><path d=\"M21 12c-2.4 4 -5.4 6 -9 6c-3.6 0 -6.6 -2 -9 -6c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0\"/><path d=\"M21 12c-2.4 4 -5.4 6 -9 6c-3.6 0 -6.6 -2 -9 -6c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6\"/></svg>')}.icon-sanction{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M3 12a9 9 0 1 0 18 0a9 9 0 1 0 -18 0\"/><path d=\"M9 15l6 -6\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M3 12a9 9 0 1 0 18 0a9 9 0 1 0 -18 0\"/><path d=\"M9 15l6 -6\"/></svg>')}.icon-file{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M14 3v4a1 1 0 0 0 1 1h4\"/><path d=\"M5 12v-7a2 2 0 0 1 2 -2h7l5 5v4\"/><path d=\"M5 18h1.5a1.5 1.5 0 0 0 0 -3h-1.5v6\"/><path d=\"M17 18h2\"/><path d=\"M20 15h-3v6\"/><path d=\"M11 15v6h1a2 2 0 0 0 2 -2v-2a2 2 0 0 0 -2 -2h-1\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M14 3v4a1 1 0 0 0 1 1h4\"/><path d=\"M5 12v-7a2 2 0 0 1 2 -2h7l5 5v4\"/><path d=\"M5 18h1.5a1.5 1.5 0 0 0 0 -3h-1.5v6\"/><path d=\"M17 18h2\"/><path d=\"M20 15h-3v6\"/><path d=\"M11 15v6h1a2 2 0 0 0 2 -2v-2a2 2 0 0 0 -2 -2h-1\"/></svg>')}th.left.sortable,th.left,td.left{text-align:left}th.right.sortable,th.right,td.right{text-align:right}th.center.sortable,th.center,td.center{text-align:center}.status-chip{display:inline-flex;align-items:center;gap:.5rem;padding:.375rem .75rem;border-radius:6px;font-size:.875rem;font-weight:500;white-space:nowrap;box-sizing:border-box}.status-dot{width:6px;height:6px;border-radius:50%;flex-shrink:0}.sortable{cursor:pointer;-webkit-user-select:none;user-select:none}.sortable:hover{opacity:.7}.sort-icon{margin-left:6px;font-size:12px;pointer-events:none}\n"] });
237
+ }
238
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Table, decorators: [{
239
+ type: Component,
240
+ args: [{ selector: 'lib-table', imports: [], standalone: true, template: "<div class=\"table-wrapper\">\r\n <table class=\"inner-table\">\r\n <thead>\r\n <tr>\r\n @for (col of columns(); track col.key) {\r\n <th\r\n (click)=\"col.sortable !== false && onSort(col)\"\r\n [class.sortable]=\"col.sortable !== false\"\r\n [class]=\"getAlignment(col)\"\r\n >\r\n {{ col.label }}\r\n\r\n <!-- iconos de orden opcionales -->\r\n @if (sortColumn() === col.key) {\r\n <span class=\"sort-icon\">\r\n {{ sortDirection() === 'asc' ? '\u25B2' : '\u25BC' }}\r\n </span>\r\n }\r\n </th>\r\n }\r\n\r\n <!-- columna para acciones -->\r\n @if (showActions()) {\r\n <th></th>\r\n }\r\n </tr>\r\n </thead>\r\n\r\n <tbody>\r\n @for (row of sortData(); track $index) {\r\n <tr>\r\n @for (col of columns(); track col.key) {\r\n <td [class]=\"getAlignment(col)\">\r\n @if (col.type === 'status') { @let style =\r\n getStatusStyle(row[col.key]);\r\n <span #statusChip\r\n class=\"status-chip\"\r\n [style.background-color]=\"style.bg\"\r\n [style.color]=\"style.color\"\r\n >\r\n <span\r\n class=\"status-dot\"\r\n [style.background-color]=\"style.color\"\r\n ></span>\r\n\r\n {{ row[col.key]?.toString().toUpperCase() }}\r\n </span>\r\n\r\n } @else if (col.type === 'icon-button') {\r\n\r\n <button (click)=\"onIconColumnClick(col, row, $event)\">\r\n <span\r\n class=\"icon\"\r\n [class]=\"col.icon\"\r\n [style.color]=\"col.iconColor\"\r\n ></span>\r\n </button>\r\n\r\n } @else { {{ formatValue(col, row[col.key]) }} }\r\n </td>\r\n }\r\n\r\n <!-- Celda de acciones -->\r\n @if (showActions()) {\r\n <td class=\"acciones-cell\">\r\n <div class=\"menu-acciones\">\r\n <button class=\"icon-button\" (click)=\"openModal(row)\">\r\n <div class=\"content\">\r\n <div class=\"state-layer\">\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n class=\"more-vert\"\r\n width=\"20\"\r\n height=\"20\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n >\r\n <circle cx=\"12\" cy=\"5\" r=\"1\" />\r\n <circle cx=\"12\" cy=\"12\" r=\"1\" />\r\n <circle cx=\"12\" cy=\"19\" r=\"1\" />\r\n </svg>\r\n </div>\r\n </div>\r\n </button>\r\n @if(selectedRow()?.['id'] === row['id']){\r\n <div class=\"modal-options\" (click)=\"$event.stopPropagation()\">\r\n <div class=\"modal-content\">\r\n <ul>\r\n @for (option of getActionsForRow(row); track $index) {\r\n <li\r\n class=\"option-item\"\r\n [style.color]=\"option.color\"\r\n (click)=\"onOptionClick(option, row)\"\r\n >\r\n <span class=\"icon\" [class]=\"option.icon\"></span>\r\n <span class=\"label\">{{ option.label }}</span>\r\n </li>\r\n }\r\n </ul>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </td>\r\n }\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n</div>\r\n", styles: [".table-wrapper{width:100%;border-radius:20px;border:1px solid #c7c7ad}.inner-table{width:100%;border-collapse:separate;font-size:14px;border-spacing:0;border-radius:20px;background:#ebe8d6}.inner-table thead{background:#f0f0db}.inner-table thead tr th:first-child{border-top-left-radius:20px}.inner-table thead tr th:last-child{border-top-right-radius:20px}.inner-table th{text-align:left;padding:12px 16px;font-weight:600;color:#3a3a3a;text-transform:uppercase}.inner-table td{padding:12px 16px;color:#4a4a4a;border-top:1px solid #c7c7ad;table-layout:auto}.acciones-cell{text-align:center;padding:6px;position:relative}.menu-acciones{display:flex;align-items:center;justify-content:center;position:relative}button{background-color:transparent;border:none}.icon-button{background-color:var(--secondary-container, #dee58f);width:36px;height:36px;border:none;cursor:pointer;padding:0;border-radius:100%;display:flex;align-items:center;justify-content:center}.icon-button:hover{background:#0000000f}.more-vert{color:#4a4a4a;display:block}.modal-options{display:flex;justify-items:center;align-items:center;background-color:var(--surface-container-lowest, #ffffff);width:200px;border-radius:8px;position:absolute;top:100%;right:0;z-index:99}.modal-content{width:100%;border-radius:8px;border:1px solid var(--outline-variant, #c7c7ad);overflow:hidden}.option-item{display:flex;align-items:center;height:56px;padding:8px 12px;cursor:pointer}.option-item:hover{background-color:#0000001a}.option-item:active{background-color:#dee58f}.icon{margin-right:8px}.option-item .label{font-weight:500;font-size:16px}.icon-refresh,.icon-delete,.icon-edit,.icon-activate,.icon-deactivate,.icon-view,.icon-sanction,.icon-file{width:24px;height:24px;background-color:currentColor;color:currentColor;-webkit-mask-size:contain;-webkit-mask-repeat:no-repeat;mask-size:contain;mask-repeat:no-repeat;display:inline-block;cursor:pointer}.icon-refresh{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M20 11a8.1 8.1 0 0 0 -15.5 -2m-.5 -4v4h4\"/><path d=\"M4 13a8.1 8.1 0 0 0 15.5 2m.5 4v-4h-4\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M20 11a8.1 8.1 0 0 0 -15.5 -2m-.5 -4v4h4\"/><path d=\"M4 13a8.1 8.1 0 0 0 15.5 2m.5 4v-4h-4\"/></svg>')}.icon-delete{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M20 6a1 1 0 0 1 .117 1.993l-.117 .007h-.081l-.919 11a3 3 0 0 1 -2.824 2.995l-.176 .005h-8c-1.598 0 -2.904 -1.249 -2.992 -2.75l-.005 -.167l-.923 -11.083h-.08a1 1 0 0 1 -.117 -1.993l.117 -.007h16z\"/><path d=\"M14 2a2 2 0 0 1 2 2a1 1 0 0 1 -1.993 .117l-.007 -.117h-4l-.007 .117a1 1 0 0 1 -1.993 -.117a2 2 0 0 1 1.85 -1.995l.15 -.005h4z\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M20 6a1 1 0 0 1 .117 1.993l-.117 .007h-.081l-.919 11a3 3 0 0 1 -2.824 2.995l-.176 .005h-8c-1.598 0 -2.904 -1.249 -2.992 -2.75l-.005 -.167l-.923 -11.083h-.08a1 1 0 0 1 -.117 -1.993l.117 -.007h16z\"/><path d=\"M14 2a2 2 0 0 1 2 2a1 1 0 0 1 -1.993 .117l-.007 -.117h-4l-.007 .117a1 1 0 0 1 -1.993 -.117a2 2 0 0 1 1.85 -1.995l.15 -.005h4z\"/></svg>')}.icon-edit{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M4 20h4l10.5 -10.5a2.828 2.828 0 1 0 -4 -4l-10.5 10.5v4\"/><path d=\"M13.5 6.5l4 4\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M4 20h4l10.5 -10.5a2.828 2.828 0 1 0 -4 -4l-10.5 10.5v4\"/><path d=\"M13.5 6.5l4 4\"/></svg>')}.icon-activate{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M17 3.34a10 10 0 1 1 -14.995 8.984l-.005 -.324l.005 -.324a10 10 0 0 1 14.995 -8.336zm-1.293 5.953a1 1 0 0 0 -1.32 -.083l-.094 .083l-3.293 3.292l-1.293 -1.292l-.094 -.083a1 1 0 0 0 -1.403 1.403l.083 .094l2 2l.094 .083a1 1 0 0 0 1.226 0l.094 -.083l4 -4l.083 -.094a1 1 0 0 0 -.083 -1.32z\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M17 3.34a10 10 0 1 1 -14.995 8.984l-.005 -.324l.005 -.324a10 10 0 0 1 14.995 -8.336zm-1.293 5.953a1 1 0 0 0 -1.32 -.083l-.094 .083l-3.293 3.292l-1.293 -1.292l-.094 -.083a1 1 0 0 0 -1.403 1.403l.083 .094l2 2l.094 .083a1 1 0 0 0 1.226 0l.094 -.083l4 -4l.083 -.094a1 1 0 0 0 -.083 -1.32z\"/></svg>')}.icon-deactivate{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M15 9l-6 6M9 9l6 6\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M15 9l-6 6M9 9l6 6\"/></svg>')}.icon-view{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0\"/><path d=\"M21 12c-2.4 4 -5.4 6 -9 6c-3.6 0 -6.6 -2 -9 -6c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0\"/><path d=\"M21 12c-2.4 4 -5.4 6 -9 6c-3.6 0 -6.6 -2 -9 -6c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6\"/></svg>')}.icon-sanction{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M3 12a9 9 0 1 0 18 0a9 9 0 1 0 -18 0\"/><path d=\"M9 15l6 -6\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M3 12a9 9 0 1 0 18 0a9 9 0 1 0 -18 0\"/><path d=\"M9 15l6 -6\"/></svg>')}.icon-file{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M14 3v4a1 1 0 0 0 1 1h4\"/><path d=\"M5 12v-7a2 2 0 0 1 2 -2h7l5 5v4\"/><path d=\"M5 18h1.5a1.5 1.5 0 0 0 0 -3h-1.5v6\"/><path d=\"M17 18h2\"/><path d=\"M20 15h-3v6\"/><path d=\"M11 15v6h1a2 2 0 0 0 2 -2v-2a2 2 0 0 0 -2 -2h-1\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M14 3v4a1 1 0 0 0 1 1h4\"/><path d=\"M5 12v-7a2 2 0 0 1 2 -2h7l5 5v4\"/><path d=\"M5 18h1.5a1.5 1.5 0 0 0 0 -3h-1.5v6\"/><path d=\"M17 18h2\"/><path d=\"M20 15h-3v6\"/><path d=\"M11 15v6h1a2 2 0 0 0 2 -2v-2a2 2 0 0 0 -2 -2h-1\"/></svg>')}th.left.sortable,th.left,td.left{text-align:left}th.right.sortable,th.right,td.right{text-align:right}th.center.sortable,th.center,td.center{text-align:center}.status-chip{display:inline-flex;align-items:center;gap:.5rem;padding:.375rem .75rem;border-radius:6px;font-size:.875rem;font-weight:500;white-space:nowrap;box-sizing:border-box}.status-dot{width:6px;height:6px;border-radius:50%;flex-shrink:0}.sortable{cursor:pointer;-webkit-user-select:none;user-select:none}.sortable:hover{opacity:.7}.sort-icon{margin-left:6px;font-size:12px;pointer-events:none}\n"] }]
241
+ }], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], actions: [{ type: i0.Input, args: [{ isSignal: true, alias: "actions", required: false }] }], showActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "showActions", required: false }] }], optionSelected: [{ type: i0.Output, args: ["optionSelected"] }], iconAction: [{ type: i0.Output, args: ["iconAction"] }], statusToneMap: [{ type: i0.Input, args: [{ isSignal: true, alias: "statusToneMap", required: false }] }], chips: [{
242
+ type: ViewChildren,
243
+ args: ['statusChip']
244
+ }], onClickOutside: [{
245
+ type: HostListener,
246
+ args: ['document:click', ['$event']]
247
+ }] } });
248
+
249
+ class DateTimePicker {
250
+ elementRef;
251
+ ngZone;
252
+ mode = input('date', ...(ngDevMode ? [{ debugName: "mode" }] : []));
253
+ placeholder = input('Seleccionar fecha', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
254
+ minDate = input(null, ...(ngDevMode ? [{ debugName: "minDate" }] : []));
255
+ maxDate = input(null, ...(ngDevMode ? [{ debugName: "maxDate" }] : []));
256
+ dateChange = output();
257
+ isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
258
+ selectedDate = signal(null, ...(ngDevMode ? [{ debugName: "selectedDate" }] : []));
259
+ isDisabled = signal(false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : []));
260
+ isTouched = signal(false, ...(ngDevMode ? [{ debugName: "isTouched" }] : []));
261
+ readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : []));
262
+ isBlocked = computed(() => this.isDisabled() || this.readonly(), ...(ngDevMode ? [{ debugName: "isBlocked" }] : []));
263
+ // Texto que escribe el usuario (DD/MM/YYYY)
264
+ inputTextValue = signal('', ...(ngDevMode ? [{ debugName: "inputTextValue" }] : []));
265
+ // Navegación del calendario
266
+ currentMonth = signal(new Date().getMonth(), ...(ngDevMode ? [{ debugName: "currentMonth" }] : []));
267
+ currentYear = signal(new Date().getFullYear(), ...(ngDevMode ? [{ debugName: "currentYear" }] : []));
268
+ // Hora en formato 24h (para el backend)
269
+ selectedHour = signal(0, ...(ngDevMode ? [{ debugName: "selectedHour" }] : []));
270
+ selectedMinute = signal(0, ...(ngDevMode ? [{ debugName: "selectedMinute" }] : []));
271
+ // Estado AM/PM
272
+ selectedAmPm = signal('AM', ...(ngDevMode ? [{ debugName: "selectedAmPm" }] : []));
273
+ documentClickListener;
274
+ /**
275
+ * Valor que se muestra en el campo de texto.
276
+ * Siempre muestra la fecha en formato DD/MM/YYYY.
277
+ */
278
+ displayValue = computed(() => {
279
+ const text = this.inputTextValue().trim();
280
+ if (text) {
281
+ return text;
262
282
  }
263
- return null;
264
- }
283
+ const date = this.selectedDate();
284
+ if (!date)
285
+ return '';
286
+ const day = date.getDate().toString().padStart(2, '0');
287
+ const month = (date.getMonth() + 1).toString().padStart(2, '0');
288
+ const year = date.getFullYear();
289
+ return `${day}/${month}/${year}`;
290
+ }, ...(ngDevMode ? [{ debugName: "displayValue" }] : []));
265
291
  monthName = computed(() => {
266
292
  const months = [
267
293
  'Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
@@ -277,12 +303,17 @@ class DateTimeFilter {
277
303
  const daysInMonth = lastDay.getDate();
278
304
  const startingDayOfWeek = firstDay.getDay();
279
305
  const days = [];
280
- for (let i = 0; i < startingDayOfWeek; i++)
306
+ // Días vacíos al inicio
307
+ for (let i = 0; i < startingDayOfWeek; i++) {
281
308
  days.push(null);
282
- for (let day = 1; day <= daysInMonth; day++)
309
+ }
310
+ // Días del mes
311
+ for (let day = 1; day <= daysInMonth; day++) {
283
312
  days.push(day);
313
+ }
284
314
  return days;
285
315
  }, ...(ngDevMode ? [{ debugName: "calendarDays" }] : []));
316
+ // Horas en formato 12h
286
317
  hours12 = computed(() => {
287
318
  return Array.from({ length: 12 }, (_, i) => {
288
319
  const hour12 = i === 0 ? 12 : i;
@@ -292,6 +323,7 @@ class DateTimeFilter {
292
323
  };
293
324
  });
294
325
  }, ...(ngDevMode ? [{ debugName: "hours12" }] : []));
326
+ // Hora seleccionada en formato 12h
295
327
  selectedHour12 = computed(() => {
296
328
  const hour24 = this.selectedHour();
297
329
  if (hour24 === 0)
@@ -301,62 +333,124 @@ class DateTimeFilter {
301
333
  return hour24;
302
334
  }, ...(ngDevMode ? [{ debugName: "selectedHour12" }] : []));
303
335
  minutes = computed(() => Array.from({ length: 60 }, (_, i) => i), ...(ngDevMode ? [{ debugName: "minutes" }] : []));
304
- // Helper methods
305
- updateInternalState(date) {
306
- this.selectedDate.set(date);
307
- this.currentMonth.set(date.getMonth());
308
- this.currentYear.set(date.getFullYear());
309
- this.selectedHour.set(date.getHours());
310
- this.selectedMinute.set(date.getMinutes());
311
- this.selectedAmPm.set(date.getHours() >= 12 ? 'PM' : 'AM');
312
- // Update input text value to match the formatted date
313
- const formatted = this.formatDateForInput(date);
314
- this.inputTextValue.set(formatted);
336
+ onChange = (value) => { };
337
+ onTouched = () => { };
338
+ constructor(elementRef, ngZone) {
339
+ this.elementRef = elementRef;
340
+ this.ngZone = ngZone;
315
341
  }
316
- resetInternalState() {
317
- this.selectedDate.set(null);
318
- this.inputTextValue.set('');
319
- this.selectedHour.set(0);
320
- this.selectedMinute.set(0);
321
- this.selectedAmPm.set('AM');
342
+ ngOnDestroy() {
343
+ this.removeDocumentListener();
322
344
  }
323
- formatDateForInput(date) {
324
- const day = date.getDate().toString().padStart(2, '0');
325
- const month = (date.getMonth() + 1).toString().padStart(2, '0');
326
- const year = date.getFullYear();
327
- return `${day}/${month}/${year}`;
345
+ writeValue(value) {
346
+ let date = null;
347
+ if (value instanceof Date) {
348
+ date = value;
349
+ }
350
+ else if (typeof value === 'string' && value) {
351
+ // Manejar tanto fechas ISO como otros formatos de string
352
+ const parsedDate = new Date(value);
353
+ if (!isNaN(parsedDate.getTime())) {
354
+ date = parsedDate;
355
+ }
356
+ }
357
+ if (date) {
358
+ this.updateInternalState(date);
359
+ }
360
+ else {
361
+ this.resetInternalState();
362
+ }
328
363
  }
329
- markAsTouched() {
330
- if (!this.isTouched()) {
331
- this.isTouched.set(true);
332
- this.onTouched();
364
+ registerOnChange(fn) {
365
+ this.onChange = fn;
366
+ }
367
+ registerOnTouched(fn) {
368
+ this.onTouched = fn;
369
+ }
370
+ setDisabledState(isDisabled) {
371
+ this.isDisabled.set(isDisabled);
372
+ }
373
+ toggle() {
374
+ if (this.isBlocked())
375
+ return;
376
+ this.markAsTouched();
377
+ if (this.isOpen()) {
378
+ this.close();
379
+ }
380
+ else {
381
+ this.open();
333
382
  }
334
383
  }
335
- addDocumentListener() {
336
- if (this.documentClickListener)
337
- this.removeDocumentListener();
338
- this.ngZone.runOutsideAngular(() => {
339
- this.documentClickListener = (event) => {
340
- const target = event.target;
341
- if (!this.elementRef.nativeElement.contains(target)) {
342
- this.ngZone.run(() => {
343
- if (this.isOpen()) {
344
- this.markAsTouched();
345
- this.close();
346
- }
347
- });
348
- }
349
- };
350
- setTimeout(() => document.addEventListener('click', this.documentClickListener, true), 10);
351
- });
384
+ open() {
385
+ if (this.isBlocked())
386
+ return;
387
+ this.markAsTouched();
388
+ this.isOpen.set(true);
389
+ this.addDocumentListener();
390
+ // Si hay fecha seleccionada, navegar a ese mes/año
391
+ const selected = this.selectedDate();
392
+ if (selected) {
393
+ this.currentMonth.set(selected.getMonth());
394
+ this.currentYear.set(selected.getFullYear());
395
+ }
352
396
  }
353
- removeDocumentListener() {
354
- if (this.documentClickListener) {
355
- document.removeEventListener('click', this.documentClickListener, true);
356
- this.documentClickListener = undefined;
397
+ close() {
398
+ this.isOpen.set(false);
399
+ this.removeDocumentListener();
400
+ this.markAsTouched();
401
+ }
402
+ selectDay(day) {
403
+ if (!day || this.isBlocked())
404
+ return;
405
+ const newDate = new Date(this.currentYear(), this.currentMonth(), day, this.selectedHour(), this.selectedMinute());
406
+ if (this.isDateDisabled(newDate))
407
+ return;
408
+ this.updateInternalState(newDate);
409
+ this.onChange(newDate.toISOString());
410
+ this.markAsTouched();
411
+ this.dateChange.emit(newDate);
412
+ // Solo cerrar automáticamente si es modo 'date'
413
+ if (this.mode() === 'date') {
414
+ this.close();
357
415
  }
358
416
  }
359
- // Navigation methods
417
+ setHour12(hour12) {
418
+ if (this.isBlocked())
419
+ return;
420
+ // Convertir de 12h a 24h
421
+ let hour24;
422
+ const amPm = this.selectedAmPm();
423
+ if (hour12 === 12) {
424
+ hour24 = amPm === 'AM' ? 0 : 12;
425
+ }
426
+ else {
427
+ hour24 = amPm === 'AM' ? hour12 : hour12 + 12;
428
+ }
429
+ this.selectedHour.set(hour24);
430
+ this.updateDateTime();
431
+ }
432
+ setMinute(minute) {
433
+ if (this.isBlocked())
434
+ return;
435
+ this.selectedMinute.set(minute);
436
+ this.updateDateTime();
437
+ }
438
+ setAmPm(amPm) {
439
+ if (this.isBlocked())
440
+ return;
441
+ const currentHour24 = this.selectedHour();
442
+ const currentHour12 = this.selectedHour12();
443
+ let newHour24;
444
+ if (amPm === 'AM') {
445
+ newHour24 = currentHour12 === 12 ? 0 : currentHour12;
446
+ }
447
+ else {
448
+ newHour24 = currentHour12 === 12 ? 12 : currentHour12 + 12;
449
+ }
450
+ this.selectedAmPm.set(amPm);
451
+ this.selectedHour.set(newHour24);
452
+ this.updateDateTime();
453
+ }
360
454
  previousMonth() {
361
455
  const currentMonth = this.currentMonth();
362
456
  const currentYear = this.currentYear();
@@ -379,85 +473,63 @@ class DateTimeFilter {
379
473
  this.currentMonth.set(currentMonth + 1);
380
474
  }
381
475
  }
382
- previousYear() { this.currentYear.set(this.currentYear() - 1); }
383
- nextYear() { this.currentYear.set(this.currentYear() + 1); }
476
+ previousYear() {
477
+ this.currentYear.set(this.currentYear() - 1);
478
+ }
479
+ nextYear() {
480
+ this.currentYear.set(this.currentYear() + 1);
481
+ }
384
482
  today() {
385
483
  const today = new Date();
386
484
  this.updateInternalState(today);
387
485
  this.onChange(today.toISOString());
388
486
  this.markAsTouched();
389
487
  this.dateChange.emit(today);
390
- this.dateSelected.emit({ filter: this.filterValue(), value: today });
391
- if (this.mode() === 'date')
392
- this.close();
393
- }
394
- clear() {
395
- this.resetInternalState();
396
- this.onChange(null);
397
- this.markAsTouched();
398
- this.dateChange.emit(null);
399
- this.close();
400
- }
401
- // Time setters
402
- setHour12(hour12) {
403
- if (this.isDisabled())
404
- return;
405
- const amPm = this.selectedAmPm();
406
- const hour24 = hour12 === 12 ? (amPm === 'AM' ? 0 : 12) : (amPm === 'AM' ? hour12 : hour12 + 12);
407
- this.selectedHour.set(hour24);
408
- this.updateDateTime();
409
- }
410
- setMinute(minute) {
411
- if (this.isDisabled())
412
- return;
413
- this.selectedMinute.set(minute);
414
- this.updateDateTime();
415
- }
416
- setAmPm(amPm) {
417
- if (this.isDisabled())
418
- return;
419
- const currentHour12 = this.selectedHour12();
420
- const newHour24 = amPm === 'AM' ? (currentHour12 === 12 ? 0 : currentHour12) : (currentHour12 === 12 ? 12 : currentHour12 + 12);
421
- this.selectedAmPm.set(amPm);
422
- this.selectedHour.set(newHour24);
423
- this.updateDateTime();
424
- }
425
- updateDateTime() {
426
- const selected = this.selectedDate();
427
- if (!selected)
428
- return;
429
- const newDate = new Date(selected);
430
- newDate.setHours(this.selectedHour());
431
- newDate.setMinutes(this.selectedMinute());
432
- this.selectedDate.set(newDate);
433
- // Update input text value
434
- const formatted = this.formatDateForInput(newDate);
435
- this.inputTextValue.set(formatted);
436
- this.onChange(newDate.toISOString());
488
+ if (this.mode() === 'date') {
489
+ this.close();
490
+ }
491
+ }
492
+ clear() {
493
+ this.resetInternalState();
494
+ this.onChange(null);
437
495
  this.markAsTouched();
438
- this.dateChange.emit(newDate);
439
- this.dateSelected.emit({
440
- filter: this.filterValue(),
441
- value: newDate,
442
- });
496
+ this.dateChange.emit(null);
497
+ this.close();
498
+ }
499
+ onKeyDown(event) {
500
+ if (this.isBlocked())
501
+ return;
502
+ if (event.key === 'Escape') {
503
+ this.close();
504
+ }
505
+ else if (event.key === 'Tab') {
506
+ this.markAsTouched();
507
+ this.close();
508
+ }
443
509
  }
444
- // Validation helpers
445
510
  isDaySelected(day) {
446
511
  if (!day)
447
512
  return false;
448
513
  const selected = this.selectedDate();
449
- return !!selected && selected.getDate() === day && selected.getMonth() === this.currentMonth() && selected.getFullYear() === this.currentYear();
514
+ if (!selected)
515
+ return false;
516
+ return (selected.getDate() === day &&
517
+ selected.getMonth() === this.currentMonth() &&
518
+ selected.getFullYear() === this.currentYear());
450
519
  }
451
520
  isToday(day) {
452
521
  if (!day)
453
522
  return false;
454
523
  const today = new Date();
455
- return today.getDate() === day && today.getMonth() === this.currentMonth() && today.getFullYear() === this.currentYear();
524
+ return (today.getDate() === day &&
525
+ today.getMonth() === this.currentMonth() &&
526
+ today.getFullYear() === this.currentYear());
456
527
  }
457
528
  isDayDisabled(day) {
458
529
  if (!day)
459
530
  return true;
460
- return this.isDateDisabled(new Date(this.currentYear(), this.currentMonth(), day));
531
+ const date = new Date(this.currentYear(), this.currentMonth(), day);
532
+ return this.isDateDisabled(date);
461
533
  }
462
534
  isDateDisabled(date) {
463
535
  const minDate = this.minDate();
@@ -468,371 +540,278 @@ class DateTimeFilter {
468
540
  return true;
469
541
  return false;
470
542
  }
471
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DateTimeFilter, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
472
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DateTimeFilter, isStandalone: true, selector: "lib-date-time-filter", inputs: { filters: { classPropertyName: "filters", publicName: "filters", isSignal: true, isRequired: false, transformFunction: null }, clearTrigger: { classPropertyName: "clearTrigger", publicName: "clearTrigger", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dateSelected: "dateSelected", dateChange: "dateChange" }, providers: [
473
- {
474
- provide: NG_VALUE_ACCESSOR,
475
- useExisting: forwardRef(() => DateTimeFilter),
476
- multi: true,
477
- },
478
- ], ngImport: i0, template: "<div class=\"datetime-container\">\r\n <div class=\"filter-chips\">\r\n @for (item of filters(); track item.value) {\r\n <div\r\n class=\"chip-input-wrapper\"\r\n [class.has-value]=\"selectedDate() || inputTextValue()\"\r\n [class.active]=\"activeFilterType() === item.value\"\r\n >\r\n <!-- Etiqueta flotante -->\r\n <label class=\"floating-label\">{{ item.placeholder || item.label || 'dd/mm/aaaa' }}</label>\r\n\r\n <!-- M\u00E1scara de gu\u00EDa de fecha din\u00E1mica (__/__/____) -->\r\n <div class=\"chip-input-mask\">\r\n @for (part of inputMask(); track $index) {\r\n <span\r\n class=\"mask-char\"\r\n [class.mask-char-filled]=\"part.filled\"\r\n [class.mask-char-placeholder]=\"!part.filled\"\r\n >\r\n {{ part.char }}\r\n </span>\r\n }\r\n </div>\r\n\r\n <input\r\n type=\"text\"\r\n [value]=\"inputTextValue()\"\r\n (input)=\"onInputChange($event, item.value)\"\r\n (focus)=\"onInputFocus(item.value)\"\r\n [placeholder]=\"''\"\r\n class=\"chip-input\"\r\n [disabled]=\"isDisabled()\"\r\n />\r\n\r\n <button\r\n type=\"button\"\r\n class=\"calendar-icon-button\"\r\n (click)=\"toggle(item.value)\"\r\n title=\"Abrir calendario\"\r\n >\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n width=\"18\"\r\n height=\"18\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n class=\"icon icon-tabler icons-tabler-outline icon-tabler-calendar-event\"\r\n >\r\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\" />\r\n <path\r\n d=\"M4 5m0 2a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2z\"\r\n />\r\n <path d=\"M16 3l0 4\" />\r\n <path d=\"M8 3l0 4\" />\r\n <path d=\"M4 11l16 0\" />\r\n <path d=\"M8 15h2v2h-2z\" />\r\n </svg>\r\n </button>\r\n\r\n @if (isOpen() && activeFilterType() === item.value) {\r\n <div class=\"dropdown\">\r\n <div class=\"datetime-content\">\r\n <!-- Secci\u00F3n del calendario -->\r\n <div class=\"calendar-section\">\r\n <!-- Navegaci\u00F3n -->\r\n <div class=\"calendar-nav\">\r\n <div class=\"nav-section\">\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"previousYear()\"\r\n title=\"A\u00F1o anterior\"\r\n >\r\n \u2039\u2039\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"previousMonth()\"\r\n title=\"Mes anterior\"\r\n >\r\n \u2039\r\n </button>\r\n </div>\r\n\r\n <div class=\"current-date\">\r\n {{ monthName() }} {{ currentYear() }}\r\n </div>\r\n\r\n <div class=\"nav-section\">\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"nextMonth()\"\r\n title=\"Siguiente mes\"\r\n >\r\n \u203A\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"nextYear()\"\r\n title=\"Siguiente a\u00F1o\"\r\n >\r\n \u203A\u203A\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- D\u00EDas de la semana -->\r\n <div class=\"weekdays\">\r\n <div class=\"weekday\">Dom</div>\r\n <div class=\"weekday\">Lun</div>\r\n <div class=\"weekday\">Mar</div>\r\n <div class=\"weekday\">Mi\u00E9</div>\r\n <div class=\"weekday\">Jue</div>\r\n <div class=\"weekday\">Vie</div>\r\n <div class=\"weekday\">S\u00E1b</div>\r\n </div>\r\n\r\n <!-- D\u00EDas -->\r\n <div class=\"calendar-grid\">\r\n @for (day of calendarDays(); track $index) {\r\n <div\r\n class=\"calendar-day\"\r\n [class.selected]=\"isDaySelected(day)\"\r\n [class.today]=\"isToday(day)\"\r\n [class.disabled]=\"isDayDisabled(day)\"\r\n [class.empty]=\"!day\"\r\n (click)=\"selectDay(day)\"\r\n >\r\n {{ day || \"\" }}\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- TIME PICKER -->\r\n @if (mode() === 'datetime') {\r\n <div class=\"time-section\">\r\n <div class=\"time-header\">Horario</div>\r\n\r\n <div class=\"time-selectors\">\r\n <div class=\"time-group\">\r\n <div class=\"time-column\">\r\n <div class=\"time-label\">Hora</div>\r\n <div class=\"time-scroll\">\r\n @for (hour of hours12(); track hour.value) {\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"hour.value === selectedHour12()\"\r\n (click)=\"setHour12(hour.value)\"\r\n >\r\n {{ hour.display }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"time-separator-vertical\">:</div>\r\n\r\n <div class=\"time-column\">\r\n <div class=\"time-label\">Min</div>\r\n <div class=\"time-scroll\">\r\n @for (minute of minutes(); track minute) {\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"minute === selectedMinute()\"\r\n (click)=\"setMinute(minute)\"\r\n >\r\n {{ minute.toString().padStart(2, \"0\") }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"time-column\">\r\n <div class=\"time-label\">AM/PM</div>\r\n <div class=\"time-scroll ampm\">\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"selectedAmPm() === 'AM'\"\r\n (click)=\"setAmPm('AM')\"\r\n >\r\n AM\r\n </div>\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"selectedAmPm() === 'PM'\"\r\n (click)=\"setAmPm('PM')\"\r\n >\r\n PM\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- botones -->\r\n <div class=\"action-buttons\">\r\n <button type=\"button\" class=\"action-btn secondary\" (click)=\"today()\">\r\n Hoy\r\n </button>\r\n\r\n @if (mode() === 'datetime') {\r\n <button type=\"button\" class=\"action-btn primary\" (click)=\"close()\">\r\n Aceptar\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n", styles: [".datetime-container{position:relative;width:100%}.filter-chips{display:flex;gap:10px;padding:8px;border-radius:12px;position:relative}.chip-input-wrapper{position:relative;display:flex;align-items:center;border-radius:8px;border-style:solid;border-color:var(--schemes-outline-variant, #c0c7cd);border-width:1px;height:32px;flex-shrink:0;transition:.2s ease;background-color:transparent}.chip-input-wrapper:hover{background-color:#ececcf}.chip-input-wrapper:focus-within,.chip-input-wrapper.active{color:var(--on-surface, #171c1f);border-color:#b6b69b}.floating-label{position:absolute;left:12px;top:-8px;color:var(--schemes-on-surface-variant, #454733);font-family:var( --theme-label-large-font-family, \"Roboto-Medium\", sans-serif );font-size:11px;line-height:12px;letter-spacing:var(--theme-label-large-letter-spacing, .1px);font-weight:var(--theme-label-large-font-weight, 500);opacity:0;pointer-events:none;transition:all .2s ease;z-index:2;background-color:#ebeccf;padding:0 4px;border-radius:2px}.chip-input-wrapper.has-value .floating-label{opacity:.6}.chip-input{border:none;outline:none;background:transparent;padding:6px 40px 6px 16px;height:100%;width:100%;color:transparent;caret-color:var(--schemes-on-surface-variant, #454733);font-family:var( --theme-label-large-font-family, \"Roboto-Medium\", sans-serif );font-size:var(--theme-label-large-font-size, 14px);line-height:var(--theme-label-large-line-height, 20px);letter-spacing:var(--theme-label-large-letter-spacing, .1px);font-weight:var(--theme-label-large-font-weight, 500);border-radius:8px;position:relative;z-index:2}.chip-input::placeholder{color:var(--schemes-on-surface-variant, #454733);opacity:.6}.chip-input:disabled{cursor:not-allowed;opacity:.6}.chip-input-mask{position:absolute;left:16px;right:40px;top:50%;transform:translateY(-50%);pointer-events:none;font-family:var( --theme-label-large-font-family, \"Roboto-Medium\", sans-serif );font-size:var(--theme-label-large-font-size, 14px);line-height:var(--theme-label-large-line-height, 20px);letter-spacing:var(--theme-label-large-letter-spacing, .1px);font-weight:var(--theme-label-large-font-weight, 500);z-index:1;display:flex}.mask-char-placeholder{color:var(--schemes-on-surface-variant, #454733);opacity:.4}.mask-char-filled{color:var(--schemes-on-surface, #171c1f);opacity:1}.calendar-icon-button{position:absolute;right:8px;top:50%;transform:translateY(-50%);background:none;border:none;cursor:pointer;padding:4px;display:flex;align-items:center;justify-content:center;color:var(--schemes-on-surface-variant, #454733);border-radius:4px;transition:all .2s;z-index:1}.calendar-icon-button:hover{background-color:#7878611a;color:var(--schemes-on-surface-variant, #454733)}.calendar-icon-button:active{background-color:#78786133}.calendar-icon-button svg{width:18px;height:18px}.icon.icon-tabler-calendar-event{width:18px;height:18px;color:var(--on-surface-variant, #40484c)}.date-picker-container{margin-top:12px;width:100%;display:flex;justify-content:flex-start}.datetime-header{width:100%;border:1px solid #787861;border-radius:5px;padding:15px;background-color:transparent;cursor:pointer;display:flex;justify-content:space-between;align-items:center;min-height:auto;transition:border-color .2s}.datetime-header:hover,.datetime-header:focus{outline:none;border-color:#a9a97f}.datetime-header.active{border-color:#a9a97f;outline:none}.datetime-header.disabled{cursor:not-allowed;opacity:.6}.selected-text{color:#454733;font-size:1.3rem;flex:1}.selected-text.placeholder{color:#787861}.header-icons{display:flex;align-items:center;gap:8px}.clear-icon{width:20px;height:20px;display:flex;align-items:center;justify-content:center;color:#787861;font-size:1.5rem;cursor:pointer;border-radius:50%;transition:all .2s}.clear-icon:hover{background-color:#7878611a;color:#454733}.arrow{width:15px;height:15px;background-image:url(\"data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e\");background-repeat:no-repeat;background-size:15px;background-position:center;color:#787861;flex-shrink:0;transition:transform .2s}.arrow.open{transform:rotate(180deg)}.dropdown{position:absolute;top:100%;left:0;right:0;background:#e3e3d1;border:1px solid #787861;border-top:none;border-radius:0 0 5px 5px;z-index:1000;box-shadow:0 4px 12px #00000026;min-width:400px}.datetime-content{display:flex}.calendar-section{flex:1;min-width:280px}.calendar-nav{display:flex;justify-content:space-between;align-items:center;padding:15px;border-bottom:1px solid rgba(120,120,97,.2)}.nav-section{display:flex;gap:5px}.nav-btn{background:none;border:none;color:#787861;cursor:pointer;font-size:1.2rem;padding:5px 10px;border-radius:3px;transition:all .2s}.nav-btn:hover{background-color:#a9a97f1a;color:#454733}.current-date{font-weight:500;color:#454733;font-size:1.1rem}.weekdays{display:grid;grid-template-columns:repeat(7,1fr);background:#7878611a}.weekday{padding:10px 5px;text-align:center;font-size:.9rem;font-weight:500;color:#787861}.calendar-grid{display:grid;grid-template-columns:repeat(7,1fr)}.calendar-day{padding:12px 5px;text-align:center;cursor:pointer;color:#454733;font-size:1rem;border-right:1px solid rgba(120,120,97,.1);border-bottom:1px solid rgba(120,120,97,.1);transition:all .2s}.calendar-day:hover:not(.disabled):not(.empty){background-color:#a9a97f33}.calendar-day.selected{background-color:#a9a97f;color:#e3e3d1;font-weight:500}.calendar-day.today:not(.selected){background-color:#a9a97f4d;font-weight:500}.calendar-day.disabled{color:#78786166;cursor:not-allowed}.calendar-day.empty{cursor:default}.calendar-day:nth-child(7n){border-right:none}.time-section{border-left:1px solid rgba(120,120,97,.2);min-width:140px;display:flex;flex-direction:column;background:#a9a97f0d}.time-header{padding:15px;border-bottom:1px solid rgba(120,120,97,.2);text-align:center;font-weight:500;color:#454733;background:#a9a97f1a}.time-selectors{display:flex;flex-direction:column;padding:15px;gap:20px;flex:1}.time-group{display:flex;align-items:center;gap:10px}.time-column{flex:1;display:flex;flex-direction:column;align-items:center}.time-label{font-size:.9rem;color:#787861;margin-bottom:10px;font-weight:500}.time-scroll{max-height:150px;overflow-y:auto;border:1px solid rgba(120,120,97,.2);border-radius:3px;width:50px;background:#a9a97f}.time-option{padding:8px 12px;text-align:center;cursor:pointer;color:#454733;font-size:1rem;transition:all .2s}.time-option:hover{background-color:#a9a97f1a}.time-option.selected{background-color:#a9a97f;color:#e3e3d1;font-weight:500}.time-separator-vertical{font-size:1.5rem;color:#787861;font-weight:700;align-self:flex-end;margin-bottom:10px}.time-scroll::-webkit-scrollbar{width:4px}.time-scroll::-webkit-scrollbar-track{background:#7878611a}.time-scroll::-webkit-scrollbar-thumb{background:#787861;border-radius:2px}.time-scroll::-webkit-scrollbar-thumb:hover{background:#a9a97f}.action-buttons{display:flex;justify-content:space-between;padding:15px;border-top:1px solid rgba(120,120,97,.2);gap:10px}.action-btn{padding:10px 20px;border:none;border-radius:3px;cursor:pointer;font-size:1rem;transition:all .2s}.action-btn.secondary{background:transparent;color:#787861;border:1px solid #787861}.action-btn.secondary:hover{background:#7878611a;color:#454733}.action-btn.primary{background:#a9a97f;color:#e3e3d1;border:1px solid #a9a97f}.action-btn.primary:hover{background:#969669;border-color:#969669}@media (max-width: 768px){.dropdown{min-width:320px}.datetime-content{flex-direction:column}.time-section{border-left:none;border-top:1px solid rgba(120,120,97,.2)}.time-selectors{flex-direction:row;justify-content:center;padding:15px}.time-group{gap:15px}.datetime-header{padding:12px 15px}.calendar-nav{padding:12px}.calendar-day{padding:10px 3px;font-size:.9rem}.action-buttons{padding:12px}}@media (max-width: 480px){.dropdown{min-width:280px}.time-section{min-width:auto}.time-scroll{width:45px}.time-selectors{padding:10px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }] });
479
- }
480
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DateTimeFilter, decorators: [{
481
- type: Component,
482
- args: [{ selector: 'lib-date-time-filter', standalone: true, imports: [CommonModule, ReactiveFormsModule], providers: [
483
- {
484
- provide: NG_VALUE_ACCESSOR,
485
- useExisting: forwardRef(() => DateTimeFilter),
486
- multi: true,
487
- },
488
- ], template: "<div class=\"datetime-container\">\r\n <div class=\"filter-chips\">\r\n @for (item of filters(); track item.value) {\r\n <div\r\n class=\"chip-input-wrapper\"\r\n [class.has-value]=\"selectedDate() || inputTextValue()\"\r\n [class.active]=\"activeFilterType() === item.value\"\r\n >\r\n <!-- Etiqueta flotante -->\r\n <label class=\"floating-label\">{{ item.placeholder || item.label || 'dd/mm/aaaa' }}</label>\r\n\r\n <!-- M\u00E1scara de gu\u00EDa de fecha din\u00E1mica (__/__/____) -->\r\n <div class=\"chip-input-mask\">\r\n @for (part of inputMask(); track $index) {\r\n <span\r\n class=\"mask-char\"\r\n [class.mask-char-filled]=\"part.filled\"\r\n [class.mask-char-placeholder]=\"!part.filled\"\r\n >\r\n {{ part.char }}\r\n </span>\r\n }\r\n </div>\r\n\r\n <input\r\n type=\"text\"\r\n [value]=\"inputTextValue()\"\r\n (input)=\"onInputChange($event, item.value)\"\r\n (focus)=\"onInputFocus(item.value)\"\r\n [placeholder]=\"''\"\r\n class=\"chip-input\"\r\n [disabled]=\"isDisabled()\"\r\n />\r\n\r\n <button\r\n type=\"button\"\r\n class=\"calendar-icon-button\"\r\n (click)=\"toggle(item.value)\"\r\n title=\"Abrir calendario\"\r\n >\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n width=\"18\"\r\n height=\"18\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n class=\"icon icon-tabler icons-tabler-outline icon-tabler-calendar-event\"\r\n >\r\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\" />\r\n <path\r\n d=\"M4 5m0 2a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2z\"\r\n />\r\n <path d=\"M16 3l0 4\" />\r\n <path d=\"M8 3l0 4\" />\r\n <path d=\"M4 11l16 0\" />\r\n <path d=\"M8 15h2v2h-2z\" />\r\n </svg>\r\n </button>\r\n\r\n @if (isOpen() && activeFilterType() === item.value) {\r\n <div class=\"dropdown\">\r\n <div class=\"datetime-content\">\r\n <!-- Secci\u00F3n del calendario -->\r\n <div class=\"calendar-section\">\r\n <!-- Navegaci\u00F3n -->\r\n <div class=\"calendar-nav\">\r\n <div class=\"nav-section\">\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"previousYear()\"\r\n title=\"A\u00F1o anterior\"\r\n >\r\n \u2039\u2039\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"previousMonth()\"\r\n title=\"Mes anterior\"\r\n >\r\n \u2039\r\n </button>\r\n </div>\r\n\r\n <div class=\"current-date\">\r\n {{ monthName() }} {{ currentYear() }}\r\n </div>\r\n\r\n <div class=\"nav-section\">\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"nextMonth()\"\r\n title=\"Siguiente mes\"\r\n >\r\n \u203A\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"nextYear()\"\r\n title=\"Siguiente a\u00F1o\"\r\n >\r\n \u203A\u203A\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- D\u00EDas de la semana -->\r\n <div class=\"weekdays\">\r\n <div class=\"weekday\">Dom</div>\r\n <div class=\"weekday\">Lun</div>\r\n <div class=\"weekday\">Mar</div>\r\n <div class=\"weekday\">Mi\u00E9</div>\r\n <div class=\"weekday\">Jue</div>\r\n <div class=\"weekday\">Vie</div>\r\n <div class=\"weekday\">S\u00E1b</div>\r\n </div>\r\n\r\n <!-- D\u00EDas -->\r\n <div class=\"calendar-grid\">\r\n @for (day of calendarDays(); track $index) {\r\n <div\r\n class=\"calendar-day\"\r\n [class.selected]=\"isDaySelected(day)\"\r\n [class.today]=\"isToday(day)\"\r\n [class.disabled]=\"isDayDisabled(day)\"\r\n [class.empty]=\"!day\"\r\n (click)=\"selectDay(day)\"\r\n >\r\n {{ day || \"\" }}\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- TIME PICKER -->\r\n @if (mode() === 'datetime') {\r\n <div class=\"time-section\">\r\n <div class=\"time-header\">Horario</div>\r\n\r\n <div class=\"time-selectors\">\r\n <div class=\"time-group\">\r\n <div class=\"time-column\">\r\n <div class=\"time-label\">Hora</div>\r\n <div class=\"time-scroll\">\r\n @for (hour of hours12(); track hour.value) {\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"hour.value === selectedHour12()\"\r\n (click)=\"setHour12(hour.value)\"\r\n >\r\n {{ hour.display }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"time-separator-vertical\">:</div>\r\n\r\n <div class=\"time-column\">\r\n <div class=\"time-label\">Min</div>\r\n <div class=\"time-scroll\">\r\n @for (minute of minutes(); track minute) {\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"minute === selectedMinute()\"\r\n (click)=\"setMinute(minute)\"\r\n >\r\n {{ minute.toString().padStart(2, \"0\") }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"time-column\">\r\n <div class=\"time-label\">AM/PM</div>\r\n <div class=\"time-scroll ampm\">\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"selectedAmPm() === 'AM'\"\r\n (click)=\"setAmPm('AM')\"\r\n >\r\n AM\r\n </div>\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"selectedAmPm() === 'PM'\"\r\n (click)=\"setAmPm('PM')\"\r\n >\r\n PM\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- botones -->\r\n <div class=\"action-buttons\">\r\n <button type=\"button\" class=\"action-btn secondary\" (click)=\"today()\">\r\n Hoy\r\n </button>\r\n\r\n @if (mode() === 'datetime') {\r\n <button type=\"button\" class=\"action-btn primary\" (click)=\"close()\">\r\n Aceptar\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n", styles: [".datetime-container{position:relative;width:100%}.filter-chips{display:flex;gap:10px;padding:8px;border-radius:12px;position:relative}.chip-input-wrapper{position:relative;display:flex;align-items:center;border-radius:8px;border-style:solid;border-color:var(--schemes-outline-variant, #c0c7cd);border-width:1px;height:32px;flex-shrink:0;transition:.2s ease;background-color:transparent}.chip-input-wrapper:hover{background-color:#ececcf}.chip-input-wrapper:focus-within,.chip-input-wrapper.active{color:var(--on-surface, #171c1f);border-color:#b6b69b}.floating-label{position:absolute;left:12px;top:-8px;color:var(--schemes-on-surface-variant, #454733);font-family:var( --theme-label-large-font-family, \"Roboto-Medium\", sans-serif );font-size:11px;line-height:12px;letter-spacing:var(--theme-label-large-letter-spacing, .1px);font-weight:var(--theme-label-large-font-weight, 500);opacity:0;pointer-events:none;transition:all .2s ease;z-index:2;background-color:#ebeccf;padding:0 4px;border-radius:2px}.chip-input-wrapper.has-value .floating-label{opacity:.6}.chip-input{border:none;outline:none;background:transparent;padding:6px 40px 6px 16px;height:100%;width:100%;color:transparent;caret-color:var(--schemes-on-surface-variant, #454733);font-family:var( --theme-label-large-font-family, \"Roboto-Medium\", sans-serif );font-size:var(--theme-label-large-font-size, 14px);line-height:var(--theme-label-large-line-height, 20px);letter-spacing:var(--theme-label-large-letter-spacing, .1px);font-weight:var(--theme-label-large-font-weight, 500);border-radius:8px;position:relative;z-index:2}.chip-input::placeholder{color:var(--schemes-on-surface-variant, #454733);opacity:.6}.chip-input:disabled{cursor:not-allowed;opacity:.6}.chip-input-mask{position:absolute;left:16px;right:40px;top:50%;transform:translateY(-50%);pointer-events:none;font-family:var( --theme-label-large-font-family, \"Roboto-Medium\", sans-serif );font-size:var(--theme-label-large-font-size, 14px);line-height:var(--theme-label-large-line-height, 20px);letter-spacing:var(--theme-label-large-letter-spacing, .1px);font-weight:var(--theme-label-large-font-weight, 500);z-index:1;display:flex}.mask-char-placeholder{color:var(--schemes-on-surface-variant, #454733);opacity:.4}.mask-char-filled{color:var(--schemes-on-surface, #171c1f);opacity:1}.calendar-icon-button{position:absolute;right:8px;top:50%;transform:translateY(-50%);background:none;border:none;cursor:pointer;padding:4px;display:flex;align-items:center;justify-content:center;color:var(--schemes-on-surface-variant, #454733);border-radius:4px;transition:all .2s;z-index:1}.calendar-icon-button:hover{background-color:#7878611a;color:var(--schemes-on-surface-variant, #454733)}.calendar-icon-button:active{background-color:#78786133}.calendar-icon-button svg{width:18px;height:18px}.icon.icon-tabler-calendar-event{width:18px;height:18px;color:var(--on-surface-variant, #40484c)}.date-picker-container{margin-top:12px;width:100%;display:flex;justify-content:flex-start}.datetime-header{width:100%;border:1px solid #787861;border-radius:5px;padding:15px;background-color:transparent;cursor:pointer;display:flex;justify-content:space-between;align-items:center;min-height:auto;transition:border-color .2s}.datetime-header:hover,.datetime-header:focus{outline:none;border-color:#a9a97f}.datetime-header.active{border-color:#a9a97f;outline:none}.datetime-header.disabled{cursor:not-allowed;opacity:.6}.selected-text{color:#454733;font-size:1.3rem;flex:1}.selected-text.placeholder{color:#787861}.header-icons{display:flex;align-items:center;gap:8px}.clear-icon{width:20px;height:20px;display:flex;align-items:center;justify-content:center;color:#787861;font-size:1.5rem;cursor:pointer;border-radius:50%;transition:all .2s}.clear-icon:hover{background-color:#7878611a;color:#454733}.arrow{width:15px;height:15px;background-image:url(\"data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e\");background-repeat:no-repeat;background-size:15px;background-position:center;color:#787861;flex-shrink:0;transition:transform .2s}.arrow.open{transform:rotate(180deg)}.dropdown{position:absolute;top:100%;left:0;right:0;background:#e3e3d1;border:1px solid #787861;border-top:none;border-radius:0 0 5px 5px;z-index:1000;box-shadow:0 4px 12px #00000026;min-width:400px}.datetime-content{display:flex}.calendar-section{flex:1;min-width:280px}.calendar-nav{display:flex;justify-content:space-between;align-items:center;padding:15px;border-bottom:1px solid rgba(120,120,97,.2)}.nav-section{display:flex;gap:5px}.nav-btn{background:none;border:none;color:#787861;cursor:pointer;font-size:1.2rem;padding:5px 10px;border-radius:3px;transition:all .2s}.nav-btn:hover{background-color:#a9a97f1a;color:#454733}.current-date{font-weight:500;color:#454733;font-size:1.1rem}.weekdays{display:grid;grid-template-columns:repeat(7,1fr);background:#7878611a}.weekday{padding:10px 5px;text-align:center;font-size:.9rem;font-weight:500;color:#787861}.calendar-grid{display:grid;grid-template-columns:repeat(7,1fr)}.calendar-day{padding:12px 5px;text-align:center;cursor:pointer;color:#454733;font-size:1rem;border-right:1px solid rgba(120,120,97,.1);border-bottom:1px solid rgba(120,120,97,.1);transition:all .2s}.calendar-day:hover:not(.disabled):not(.empty){background-color:#a9a97f33}.calendar-day.selected{background-color:#a9a97f;color:#e3e3d1;font-weight:500}.calendar-day.today:not(.selected){background-color:#a9a97f4d;font-weight:500}.calendar-day.disabled{color:#78786166;cursor:not-allowed}.calendar-day.empty{cursor:default}.calendar-day:nth-child(7n){border-right:none}.time-section{border-left:1px solid rgba(120,120,97,.2);min-width:140px;display:flex;flex-direction:column;background:#a9a97f0d}.time-header{padding:15px;border-bottom:1px solid rgba(120,120,97,.2);text-align:center;font-weight:500;color:#454733;background:#a9a97f1a}.time-selectors{display:flex;flex-direction:column;padding:15px;gap:20px;flex:1}.time-group{display:flex;align-items:center;gap:10px}.time-column{flex:1;display:flex;flex-direction:column;align-items:center}.time-label{font-size:.9rem;color:#787861;margin-bottom:10px;font-weight:500}.time-scroll{max-height:150px;overflow-y:auto;border:1px solid rgba(120,120,97,.2);border-radius:3px;width:50px;background:#a9a97f}.time-option{padding:8px 12px;text-align:center;cursor:pointer;color:#454733;font-size:1rem;transition:all .2s}.time-option:hover{background-color:#a9a97f1a}.time-option.selected{background-color:#a9a97f;color:#e3e3d1;font-weight:500}.time-separator-vertical{font-size:1.5rem;color:#787861;font-weight:700;align-self:flex-end;margin-bottom:10px}.time-scroll::-webkit-scrollbar{width:4px}.time-scroll::-webkit-scrollbar-track{background:#7878611a}.time-scroll::-webkit-scrollbar-thumb{background:#787861;border-radius:2px}.time-scroll::-webkit-scrollbar-thumb:hover{background:#a9a97f}.action-buttons{display:flex;justify-content:space-between;padding:15px;border-top:1px solid rgba(120,120,97,.2);gap:10px}.action-btn{padding:10px 20px;border:none;border-radius:3px;cursor:pointer;font-size:1rem;transition:all .2s}.action-btn.secondary{background:transparent;color:#787861;border:1px solid #787861}.action-btn.secondary:hover{background:#7878611a;color:#454733}.action-btn.primary{background:#a9a97f;color:#e3e3d1;border:1px solid #a9a97f}.action-btn.primary:hover{background:#969669;border-color:#969669}@media (max-width: 768px){.dropdown{min-width:320px}.datetime-content{flex-direction:column}.time-section{border-left:none;border-top:1px solid rgba(120,120,97,.2)}.time-selectors{flex-direction:row;justify-content:center;padding:15px}.time-group{gap:15px}.datetime-header{padding:12px 15px}.calendar-nav{padding:12px}.calendar-day{padding:10px 3px;font-size:.9rem}.action-buttons{padding:12px}}@media (max-width: 480px){.dropdown{min-width:280px}.time-section{min-width:auto}.time-scroll{width:45px}.time-selectors{padding:10px}}\n"] }]
489
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.NgZone }], propDecorators: { filters: [{ type: i0.Input, args: [{ isSignal: true, alias: "filters", required: false }] }], dateSelected: [{ type: i0.Output, args: ["dateSelected"] }], dateChange: [{ type: i0.Output, args: ["dateChange"] }], clearTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearTrigger", required: false }] }] } });
490
-
491
- class PaginationComponent {
492
- page = 1;
493
- pageSize = 10;
494
- totalItems = 0;
495
- showPageSizeSelector = false;
496
- pageSizeOptions = [5, 10, 20, 50];
497
- pageChange = new EventEmitter();
498
- pageSizeChange = new EventEmitter();
499
- pageSizeValue = signal(this.pageSize, ...(ngDevMode ? [{ debugName: "pageSizeValue" }] : []));
500
- isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
501
- isDisabled = signal(false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : []));
502
- showPageSizeMenu = signal(false, ...(ngDevMode ? [{ debugName: "showPageSizeMenu" }] : []));
503
- totalPages = computed(() => {
504
- const size = this.pageSizeValue();
505
- const total = this.totalItems;
506
- return size > 0 ? Math.ceil(total / size) : 1;
507
- }, ...(ngDevMode ? [{ debugName: "totalPages" }] : []));
508
- pages = computed(() => {
509
- const tp = this.totalPages();
510
- return Array.from({ length: tp }, (_, i) => i + 1);
511
- }, ...(ngDevMode ? [{ debugName: "pages" }] : []));
512
- selectedPageSize = computed(() => this.pageSizeValue(), ...(ngDevMode ? [{ debugName: "selectedPageSize" }] : []));
513
- goToPage(p) {
514
- if (p < 1 || p > this.totalPages())
543
+ updateDateTime() {
544
+ const selected = this.selectedDate();
545
+ if (!selected)
515
546
  return;
516
- this.pageChange.emit(p);
517
- }
518
- togglePageSizeMenu() {
519
- this.isOpen.update(v => !v);
520
- this.showPageSizeMenu.update(v => !v);
547
+ const newDate = new Date(selected);
548
+ newDate.setHours(this.selectedHour());
549
+ newDate.setMinutes(this.selectedMinute());
550
+ this.updateInternalState(newDate);
551
+ this.onChange(newDate.toISOString());
552
+ this.markAsTouched();
553
+ this.dateChange.emit(newDate);
521
554
  }
522
- selectPageSize(size) {
523
- this.pageSizeValue.set(size);
524
- this.pageSizeChange.emit(size);
525
- this.showPageSizeMenu.set(false);
526
- this.isOpen.set(false);
555
+ // Manejo de input de texto (DD/MM/YYYY)
556
+ onInputChange(event) {
557
+ if (this.isBlocked())
558
+ return;
559
+ const input = event.target;
560
+ let value = input.value;
561
+ // Eliminar todo lo que no sea número
562
+ const numbersOnly = value.replace(/\D/g, '');
563
+ // Limitar a 8 dígitos (DDMMYYYY)
564
+ const limitedNumbers = numbersOnly.slice(0, 8);
565
+ // Formatear con barras: DD/MM/YYYY
566
+ let formatted = '';
567
+ if (limitedNumbers.length > 0) {
568
+ formatted = limitedNumbers.slice(0, 2);
569
+ if (limitedNumbers.length > 2) {
570
+ formatted += '/' + limitedNumbers.slice(2, 4);
571
+ }
572
+ if (limitedNumbers.length > 4) {
573
+ formatted += '/' + limitedNumbers.slice(4, 8);
574
+ }
575
+ }
576
+ this.inputTextValue.set(formatted);
577
+ input.value = formatted;
578
+ this.markAsTouched();
579
+ // Solo intentamos parsear cuando tenemos DD/MM/YYYY completo (10 caracteres)
580
+ if (formatted.length === 10) {
581
+ const parsedDate = this.parseDateInput(formatted);
582
+ if (parsedDate) {
583
+ if (this.isDateDisabled(parsedDate)) {
584
+ // Está fuera de rango, dejamos el texto pero no cambiamos el valor
585
+ return;
586
+ }
587
+ this.updateInternalState(parsedDate);
588
+ this.onChange(parsedDate.toISOString());
589
+ this.dateChange.emit(parsedDate);
590
+ }
591
+ }
592
+ else if (formatted.trim() === '') {
593
+ // Si el campo queda vacío, limpiamos el valor
594
+ this.resetInternalState();
595
+ this.onChange(null);
596
+ this.dateChange.emit(null);
597
+ }
527
598
  }
528
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: PaginationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
529
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: PaginationComponent, isStandalone: true, selector: "lib-pagination", inputs: { page: "page", pageSize: "pageSize", totalItems: "totalItems", showPageSizeSelector: "showPageSizeSelector", pageSizeOptions: "pageSizeOptions" }, outputs: { pageChange: "pageChange", pageSizeChange: "pageSizeChange" }, ngImport: i0, template: "<div class=\"pagination-container\">\r\n <div class=\"pagination\">\r\n <!-- Bot\u00F3n doble atr\u00E1s -->\r\n <button class=\"icon-button\" (click)=\"goToPage(1)\" [disabled]=\"page === 1\">\r\n \u00AB\u00AB\r\n </button>\r\n\r\n <!-- Bot\u00F3n atr\u00E1s -->\r\n <button class=\"icon-button\" (click)=\"goToPage(page - 1)\" [disabled]=\"page === 1\">\r\n \u00AB\r\n </button>\r\n\r\n <!-- N\u00FAmeros de p\u00E1gina -->\r\n <div class=\"pages\">\r\n <button\r\n class=\"page-btn\"\r\n *ngFor=\"let p of pages(); let idx = index\"\r\n [class.active]=\"page === idx + 1\"\r\n (click)=\"goToPage(idx + 1)\"\r\n >\r\n {{ idx + 1 }}\r\n </button>\r\n </div>\r\n\r\n <!-- Bot\u00F3n siguiente -->\r\n <button class=\"icon-button\" (click)=\"goToPage(page + 1)\" [disabled]=\"page === totalPages()\">\r\n \u00BB\r\n </button>\r\n\r\n <!-- Bot\u00F3n doble adelante -->\r\n <button class=\"icon-button\" (click)=\"goToPage(totalPages())\" [disabled]=\"page === totalPages()\">\r\n \u00BB\u00BB\r\n </button>\r\n </div>\r\n\r\n <!-- Selector Items por p\u00E1gina -->\r\n <div *ngIf=\"showPageSizeSelector\">\r\n <div class=\"pagination-v-4\">\r\n <div class=\"label-pagination\">Items por p\u00E1gina</div>\r\n <div class=\"elements-pagination\">\r\n <div class=\"split-button\" (click)=\"togglePageSizeMenu()\">\r\n <div class=\"leading-button\">\r\n <div class=\"state-layer\">\r\n <div class=\"label\">{{ pageSizeValue() }}</div>\r\n </div>\r\n </div>\r\n <div class=\"trailing-button\">\r\n <div class=\"arrow\" [class.open]=\"isOpen()\">\r\n <svg class=\"arrow\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" fill=\"none\" stroke-width=\"2\">\r\n <polyline points=\"6 9 12 15 18 9\"></polyline>\r\n </svg>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Men\u00FA desplegable -->\r\n <div class=\"page-size-menu\" *ngIf=\"showPageSizeMenu()\">\r\n <div\r\n class=\"menu-option\"\r\n *ngFor=\"let opt of pageSizeOptions\"\r\n [class.active]=\"opt === pageSizeValue()\"\r\n (click)=\"selectPageSize(opt)\"\r\n >\r\n {{ opt }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".pagination-container{display:flex;flex-direction:row;justify-content:center;width:100%;padding:8px 0;position:relative}.pagination{display:flex;align-items:center;gap:12px;padding:12px;justify-content:center;flex:1}.icon-button{width:40px;height:40px;border-radius:50%;background:var(--primary, #596300);color:var(--surface, #ffffff);border:none;cursor:pointer;font-size:16px;font-weight:700;display:flex;align-items:center;justify-content:center;box-shadow:0 1px 2px #00000026;transition:background .2s ease,transform .1s ease}.icon-button:disabled{background:#969696;color:var(--on-surface, #171c1f);opacity:.45;cursor:not-allowed}.pages{display:flex;gap:4px;overflow:hidden;border-radius:20px}.page-btn{background:var(--secondary-container, #dee58f);width:40px;height:40px;border:none;cursor:pointer;padding:8px 14px;font-size:14px;color:var(--schemes-on-surface, #3a3a3a);font-family:Roboto,sans-serif;border-radius:8px;transition:background .2s ease}.page-btn:hover:not(.active){background:var(--schemes-on-secondary-container, #61661f);color:var(--schemes-secondary-container, #dee58f)}.page-btn.active{background:var(--schemes-primary, #596300);color:var(--schemes-on-primary, #ffffff);font-weight:600;border-radius:20px}.pagination-v-4{display:flex;gap:10px;align-items:center;margin-left:auto}.label-pagination{font-size:14px;font-weight:600;color:var(--schemes-on-surface)}.elements-pagination{position:relative;display:flex;gap:4px;border-radius:20px}.split-button{display:flex;cursor:pointer;border-radius:20px;overflow:hidden}.leading-button{background:var(--schemes-secondary-container);border-radius:20px 4px 4px 20px;display:flex;align-items:center;height:40px}.state-layer{padding:10px 16px;background-color:#dee58f;margin-right:4px;border-radius:8px}.state-layer:open{color:#f5f5e0;background-color:#596300}.label{font-size:14px;font-weight:500;color:var(--schemes-on-secondary-container)}.trailing-button{background:var(--secondary-container, #dee58f);padding-left:12px;padding-right:12px;border:none;cursor:pointer;font-size:14px;color:var(--schemes-on-surface, #3a3a3a);font-family:Roboto,sans-serif;border-radius:8px;transition:background .2s ease;align-items:center;align-content:center}.arrow{width:20px;height:20px;color:#171c1f;transition:transform .25s ease}.arrow.open{transform:rotate(180deg)}.page-size-menu{background:#f5f5e0;position:absolute;min-width:100px;border-radius:4px;box-shadow:0 2px 8px #0003;overflow:hidden;z-index:999;bottom:50px;right:0;transform-origin:top right}.menu-option{padding:8px 12px;cursor:pointer}.menu-option:hover{background:#dee58f5b}.menu-option.active{background:#dee58f;color:#61661f}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
530
- }
531
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: PaginationComponent, decorators: [{
532
- type: Component,
533
- args: [{ selector: 'lib-pagination', standalone: true, imports: [CommonModule], template: "<div class=\"pagination-container\">\r\n <div class=\"pagination\">\r\n <!-- Bot\u00F3n doble atr\u00E1s -->\r\n <button class=\"icon-button\" (click)=\"goToPage(1)\" [disabled]=\"page === 1\">\r\n \u00AB\u00AB\r\n </button>\r\n\r\n <!-- Bot\u00F3n atr\u00E1s -->\r\n <button class=\"icon-button\" (click)=\"goToPage(page - 1)\" [disabled]=\"page === 1\">\r\n \u00AB\r\n </button>\r\n\r\n <!-- N\u00FAmeros de p\u00E1gina -->\r\n <div class=\"pages\">\r\n <button\r\n class=\"page-btn\"\r\n *ngFor=\"let p of pages(); let idx = index\"\r\n [class.active]=\"page === idx + 1\"\r\n (click)=\"goToPage(idx + 1)\"\r\n >\r\n {{ idx + 1 }}\r\n </button>\r\n </div>\r\n\r\n <!-- Bot\u00F3n siguiente -->\r\n <button class=\"icon-button\" (click)=\"goToPage(page + 1)\" [disabled]=\"page === totalPages()\">\r\n \u00BB\r\n </button>\r\n\r\n <!-- Bot\u00F3n doble adelante -->\r\n <button class=\"icon-button\" (click)=\"goToPage(totalPages())\" [disabled]=\"page === totalPages()\">\r\n \u00BB\u00BB\r\n </button>\r\n </div>\r\n\r\n <!-- Selector Items por p\u00E1gina -->\r\n <div *ngIf=\"showPageSizeSelector\">\r\n <div class=\"pagination-v-4\">\r\n <div class=\"label-pagination\">Items por p\u00E1gina</div>\r\n <div class=\"elements-pagination\">\r\n <div class=\"split-button\" (click)=\"togglePageSizeMenu()\">\r\n <div class=\"leading-button\">\r\n <div class=\"state-layer\">\r\n <div class=\"label\">{{ pageSizeValue() }}</div>\r\n </div>\r\n </div>\r\n <div class=\"trailing-button\">\r\n <div class=\"arrow\" [class.open]=\"isOpen()\">\r\n <svg class=\"arrow\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" fill=\"none\" stroke-width=\"2\">\r\n <polyline points=\"6 9 12 15 18 9\"></polyline>\r\n </svg>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Men\u00FA desplegable -->\r\n <div class=\"page-size-menu\" *ngIf=\"showPageSizeMenu()\">\r\n <div\r\n class=\"menu-option\"\r\n *ngFor=\"let opt of pageSizeOptions\"\r\n [class.active]=\"opt === pageSizeValue()\"\r\n (click)=\"selectPageSize(opt)\"\r\n >\r\n {{ opt }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".pagination-container{display:flex;flex-direction:row;justify-content:center;width:100%;padding:8px 0;position:relative}.pagination{display:flex;align-items:center;gap:12px;padding:12px;justify-content:center;flex:1}.icon-button{width:40px;height:40px;border-radius:50%;background:var(--primary, #596300);color:var(--surface, #ffffff);border:none;cursor:pointer;font-size:16px;font-weight:700;display:flex;align-items:center;justify-content:center;box-shadow:0 1px 2px #00000026;transition:background .2s ease,transform .1s ease}.icon-button:disabled{background:#969696;color:var(--on-surface, #171c1f);opacity:.45;cursor:not-allowed}.pages{display:flex;gap:4px;overflow:hidden;border-radius:20px}.page-btn{background:var(--secondary-container, #dee58f);width:40px;height:40px;border:none;cursor:pointer;padding:8px 14px;font-size:14px;color:var(--schemes-on-surface, #3a3a3a);font-family:Roboto,sans-serif;border-radius:8px;transition:background .2s ease}.page-btn:hover:not(.active){background:var(--schemes-on-secondary-container, #61661f);color:var(--schemes-secondary-container, #dee58f)}.page-btn.active{background:var(--schemes-primary, #596300);color:var(--schemes-on-primary, #ffffff);font-weight:600;border-radius:20px}.pagination-v-4{display:flex;gap:10px;align-items:center;margin-left:auto}.label-pagination{font-size:14px;font-weight:600;color:var(--schemes-on-surface)}.elements-pagination{position:relative;display:flex;gap:4px;border-radius:20px}.split-button{display:flex;cursor:pointer;border-radius:20px;overflow:hidden}.leading-button{background:var(--schemes-secondary-container);border-radius:20px 4px 4px 20px;display:flex;align-items:center;height:40px}.state-layer{padding:10px 16px;background-color:#dee58f;margin-right:4px;border-radius:8px}.state-layer:open{color:#f5f5e0;background-color:#596300}.label{font-size:14px;font-weight:500;color:var(--schemes-on-secondary-container)}.trailing-button{background:var(--secondary-container, #dee58f);padding-left:12px;padding-right:12px;border:none;cursor:pointer;font-size:14px;color:var(--schemes-on-surface, #3a3a3a);font-family:Roboto,sans-serif;border-radius:8px;transition:background .2s ease;align-items:center;align-content:center}.arrow{width:20px;height:20px;color:#171c1f;transition:transform .25s ease}.arrow.open{transform:rotate(180deg)}.page-size-menu{background:#f5f5e0;position:absolute;min-width:100px;border-radius:4px;box-shadow:0 2px 8px #0003;overflow:hidden;z-index:999;bottom:50px;right:0;transform-origin:top right}.menu-option{padding:8px 12px;cursor:pointer}.menu-option:hover{background:#dee58f5b}.menu-option.active{background:#dee58f;color:#61661f}\n"] }]
534
- }], propDecorators: { page: [{
535
- type: Input
536
- }], pageSize: [{
537
- type: Input
538
- }], totalItems: [{
539
- type: Input
540
- }], showPageSizeSelector: [{
541
- type: Input
542
- }], pageSizeOptions: [{
543
- type: Input
544
- }], pageChange: [{
545
- type: Output
546
- }], pageSizeChange: [{
547
- type: Output
548
- }] } });
549
-
550
- const STATUS_TONE_STYLES = {
551
- success: { bg: '#E6F4EA', color: '#1E8E3E' },
552
- error: { bg: '#FCE8E6', color: '#D93025' },
553
- warning: { bg: '#FFF4E5', color: '#E67E22' },
554
- info: { bg: '#E6F4EA', color: '#0077B6' },
555
- neutral: { bg: '#F4F4F4', color: '#5F6368' },
556
- };
557
- class Table {
558
- columns = input([], ...(ngDevMode ? [{ debugName: "columns" }] : []));
559
- data = input([], ...(ngDevMode ? [{ debugName: "data" }] : []));
560
- actions = input([], ...(ngDevMode ? [{ debugName: "actions" }] : []));
561
- showActions = input(true, ...(ngDevMode ? [{ debugName: "showActions" }] : []));
562
- openedMenu = signal(null, ...(ngDevMode ? [{ debugName: "openedMenu" }] : []));
563
- selectedRow = signal(null, ...(ngDevMode ? [{ debugName: "selectedRow" }] : []));
564
- sortColumn = signal(null, ...(ngDevMode ? [{ debugName: "sortColumn" }] : []));
565
- sortDirection = signal('desc', ...(ngDevMode ? [{ debugName: "sortDirection" }] : []));
566
- optionSelected = output();
567
- iconAction = output();
568
- statusToneMap = input({}, ...(ngDevMode ? [{ debugName: "statusToneMap" }] : []));
569
- chips;
570
- ngAfterViewInit() {
571
- setTimeout(() => {
572
- const chipEls = this.chips.map(c => c.nativeElement);
573
- const parentWidth = chipEls[0]?.parentElement.offsetWidth || 0;
574
- const widths = chipEls.map(el => el.scrollWidth);
575
- const maxContentWidth = Math.max(...widths);
576
- const finalWidth = Math.min(maxContentWidth, parentWidth);
577
- chipEls.forEach(el => {
578
- el.style.width = finalWidth + 'px';
579
- });
580
- });
599
+ onInputFocus() {
600
+ if (this.isBlocked())
601
+ return;
602
+ this.open();
581
603
  }
582
- toggleMenu(index) {
583
- this.openedMenu.set(this.openedMenu() === index ? null : index);
604
+ parseDateInput(input) {
605
+ if (!input || input.trim() === '')
606
+ return null;
607
+ const match = input.trim().match(/^(\d{2})\/(\d{2})\/(\d{4})$/);
608
+ if (match) {
609
+ const day = parseInt(match[1], 10);
610
+ const month = parseInt(match[2], 10) - 1;
611
+ const year = parseInt(match[3], 10);
612
+ if (day >= 1 && day <= 31 && month >= 0 && month <= 11 && year >= 1900 && year <= 2100) {
613
+ const date = new Date(year, month, day);
614
+ if (date.getDate() === day && date.getMonth() === month && date.getFullYear() === year) {
615
+ return date;
616
+ }
617
+ }
618
+ }
619
+ return null;
584
620
  }
585
- onOptionClick(option, row) {
586
- this.optionSelected.emit({ action: option.label, row });
587
- this.openedMenu.set(null);
621
+ formatDateForInput(date) {
622
+ const day = date.getDate().toString().padStart(2, '0');
623
+ const month = (date.getMonth() + 1).toString().padStart(2, '0');
624
+ const year = date.getFullYear();
625
+ return `${day}/${month}/${year}`;
588
626
  }
589
- openModal(row, event) {
590
- event?.stopPropagation();
591
- if (this.selectedRow()?.['id'] === row['id']) {
592
- this.selectedRow.set(null);
593
- }
594
- else {
595
- this.selectedRow.set(row);
596
- }
627
+ updateInternalState(date) {
628
+ this.selectedDate.set(date);
629
+ this.currentMonth.set(date.getMonth());
630
+ this.currentYear.set(date.getFullYear());
631
+ this.selectedHour.set(date.getHours());
632
+ this.selectedMinute.set(date.getMinutes());
633
+ this.selectedAmPm.set(date.getHours() >= 12 ? 'PM' : 'AM');
634
+ const formatted = this.formatDateForInput(date);
635
+ this.inputTextValue.set(formatted);
597
636
  }
598
- onClickOutside(event) {
599
- const target = event.target;
600
- if (!target.closest('.menu-acciones')) {
601
- this.selectedRow.set(null);
602
- }
637
+ resetInternalState() {
638
+ this.selectedDate.set(null);
639
+ this.inputTextValue.set('');
640
+ this.selectedHour.set(0);
641
+ this.selectedMinute.set(0);
642
+ this.selectedAmPm.set('AM');
603
643
  }
604
- getAlignment(col) {
605
- if (col.align && col.align !== 'auto')
606
- return col.align;
607
- switch (col.type) {
608
- case 'number':
609
- case 'money':
610
- case 'percentage':
611
- return 'right';
612
- case 'status':
613
- return 'center';
614
- default:
615
- return 'left';
644
+ markAsTouched() {
645
+ if (!this.isTouched()) {
646
+ this.isTouched.set(true);
647
+ this.onTouched();
616
648
  }
617
649
  }
618
- formatValue(col, value) {
619
- if (value === null || value === undefined)
620
- return '';
621
- switch (col.type) {
622
- case 'money':
623
- return new Intl.NumberFormat('es-CO', {
624
- style: 'currency',
625
- currency: 'COP',
626
- minimumFractionDigits: 0
627
- }).format(value);
628
- case 'number':
629
- return new Intl.NumberFormat('es-CO').format(value);
630
- case 'percentage':
631
- return `${value}%`;
632
- case 'date':
633
- const d = new Date(value);
634
- return d.toLocaleDateString('es-CO'); // dd/mm/yyyy
635
- default:
636
- return String(value);
650
+ addDocumentListener() {
651
+ if (this.documentClickListener) {
652
+ this.removeDocumentListener();
637
653
  }
654
+ this.ngZone.runOutsideAngular(() => {
655
+ this.documentClickListener = (event) => {
656
+ const target = event.target;
657
+ if (!this.elementRef.nativeElement.contains(target)) {
658
+ this.ngZone.run(() => {
659
+ if (this.isOpen()) {
660
+ this.markAsTouched();
661
+ this.close();
662
+ }
663
+ });
664
+ }
665
+ };
666
+ setTimeout(() => {
667
+ document.addEventListener('click', this.documentClickListener, true);
668
+ }, 10);
669
+ });
638
670
  }
639
- getStatusStyle(value) {
640
- if (!value) {
641
- return STATUS_TONE_STYLES.neutral;
671
+ removeDocumentListener() {
672
+ if (this.documentClickListener) {
673
+ document.removeEventListener('click', this.documentClickListener, true);
674
+ this.documentClickListener = undefined;
642
675
  }
643
- const key = this.normalizeStatus(value);
644
- const tone = this.statusToneMap()?.[key] ?? 'neutral';
645
- return STATUS_TONE_STYLES[tone];
646
676
  }
647
- normalizeStatus(value) {
648
- return String(value ?? '')
649
- .toLowerCase()
650
- .trim()
651
- .replace(/\s+/g, '_');
677
+ markTouched() {
678
+ this.markAsTouched();
652
679
  }
653
680
  /**
654
- * Devuelve las acciones para una fila.
655
- * Puede ser que `actions` sea un arreglo (se muestra tal cual) o una función
656
- * que recibe la fila y retorna las acciones correspondientes.
681
+ * Obtiene la fecha seleccionada en formato ISO string
682
+ * @returns string ISO o null si no hay fecha seleccionada
657
683
  */
658
- getActionsForRow(row) {
659
- const acts = this.actions();
660
- if (!acts)
661
- return [];
662
- if (typeof acts === 'function') {
663
- try {
664
- return acts(row) ?? [];
665
- }
666
- catch {
667
- return [];
668
- }
669
- }
670
- return acts;
684
+ getISOString() {
685
+ const date = this.selectedDate();
686
+ return date ? date.toISOString() : null;
671
687
  }
672
- sortData() {
673
- const col = this.sortColumn();
674
- if (!col)
675
- return this.data();
676
- const dir = this.sortDirection();
677
- return [...this.data()].sort((a, b) => {
678
- const x = a[col] ?? '';
679
- const y = b[col] ?? '';
680
- // Caso: fechas
681
- if (this.isDate(x) && this.isDate(y)) {
682
- return dir === 'asc'
683
- ? new Date(x).getTime() - new Date(y).getTime()
684
- : new Date(y).getTime() - new Date(x).getTime();
685
- }
686
- // Caso: números
687
- if (!isNaN(Number(x)) && !isNaN(Number(y))) {
688
- return dir === 'asc' ? Number(x) - Number(y) : Number(y) - Number(x);
688
+ /**
689
+ * Establece la fecha desde un string ISO
690
+ * @param isoString - Fecha en formato ISO
691
+ */
692
+ setFromISOString(isoString) {
693
+ if (isoString) {
694
+ const date = new Date(isoString);
695
+ if (!isNaN(date.getTime())) {
696
+ this.writeValue(date);
697
+ this.onChange(isoString);
689
698
  }
690
- // Caso: strings
691
- return dir === 'asc'
692
- ? x.toString().localeCompare(y.toString())
693
- : y.toString().localeCompare(x.toString());
694
- });
695
- }
696
- isDate(value) {
697
- return (typeof value === 'string' &&
698
- value.length > 5 &&
699
- !isNaN(Date.parse(value)));
700
- }
701
- onSort(col) {
702
- if (this.sortColumn() === col.key) {
703
- // cambiar asc <-> desc
704
- this.sortDirection.set(this.sortDirection() === 'asc' ? 'desc' : 'asc');
705
699
  }
706
700
  else {
707
- // nueva columna → empieza en desc (más reciente primero)
708
- this.sortColumn.set(col.key);
709
- this.sortDirection.set('desc');
701
+ this.clear();
710
702
  }
711
703
  }
712
- onIconColumnClick(col, row, event) {
713
- event.stopPropagation();
714
- this.iconAction.emit({
715
- action: col.iconKey ?? col.key,
716
- row
717
- });
718
- }
719
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: Table, deps: [], target: i0.ɵɵFactoryTarget.Component });
720
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: Table, isStandalone: true, selector: "lib-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, showActions: { classPropertyName: "showActions", publicName: "showActions", isSignal: true, isRequired: false, transformFunction: null }, statusToneMap: { classPropertyName: "statusToneMap", publicName: "statusToneMap", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { optionSelected: "optionSelected", iconAction: "iconAction" }, host: { listeners: { "document:click": "onClickOutside($event)" } }, viewQueries: [{ propertyName: "chips", predicate: ["status-chip"], descendants: true }], ngImport: i0, template: "<div class=\"table-wrapper\">\r\n <table class=\"inner-table\">\r\n <thead>\r\n <tr>\r\n @for (col of columns(); track col.key) {\r\n <th\r\n (click)=\"col.sortable !== false && onSort(col)\"\r\n [class.sortable]=\"col.sortable !== false\"\r\n [class]=\"getAlignment(col)\"\r\n >\r\n {{ col.label }}\r\n\r\n <!-- iconos de orden opcionales -->\r\n @if (sortColumn() === col.key) {\r\n <span class=\"sort-icon\">\r\n {{ sortDirection() === 'asc' ? '\u25B2' : '\u25BC' }}\r\n </span>\r\n }\r\n </th>\r\n }\r\n\r\n <!-- columna para acciones -->\r\n @if (showActions()) {\r\n <th></th>\r\n }\r\n </tr>\r\n </thead>\r\n\r\n <tbody>\r\n @for (row of sortData(); track $index) {\r\n <tr>\r\n @for (col of columns(); track col.key) {\r\n <td [class]=\"getAlignment(col)\">\r\n @if (col.type === 'status') { @let style =\r\n getStatusStyle(row[col.key]);\r\n <span\r\n class=\"status-chip\"\r\n id=\"status-chip\"\r\n [style.background-color]=\"style.bg\"\r\n [style.color]=\"style.color\"\r\n >\r\n <span\r\n class=\"status-dot\"\r\n [style.background-color]=\"style.color\"\r\n ></span>\r\n\r\n {{ row[col.key]?.toString().toUpperCase() }}\r\n </span>\r\n\r\n } @else if (col.type === 'icon-button') {\r\n\r\n <button (click)=\"onIconColumnClick(col, row, $event)\">\r\n <span\r\n class=\"icon\"\r\n [class]=\"col.icon\"\r\n [style.color]=\"col.iconColor\"\r\n ></span>\r\n </button>\r\n\r\n } @else { {{ formatValue(col, row[col.key]) }} }\r\n </td>\r\n }\r\n\r\n <!-- Celda de acciones -->\r\n @if (showActions()) {\r\n <td class=\"acciones-cell\">\r\n <div class=\"menu-acciones\">\r\n <button class=\"icon-button\" (click)=\"openModal(row)\">\r\n <div class=\"content\">\r\n <div class=\"state-layer\">\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n class=\"more-vert\"\r\n width=\"20\"\r\n height=\"20\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n >\r\n <circle cx=\"12\" cy=\"5\" r=\"1\" />\r\n <circle cx=\"12\" cy=\"12\" r=\"1\" />\r\n <circle cx=\"12\" cy=\"19\" r=\"1\" />\r\n </svg>\r\n </div>\r\n </div>\r\n </button>\r\n @if(selectedRow()?.['id'] === row['id']){\r\n <div class=\"modal-options\" (click)=\"$event.stopPropagation()\">\r\n <div class=\"modal-content\">\r\n <ul>\r\n @for (option of getActionsForRow(row); track $index) {\r\n <li\r\n class=\"option-item\"\r\n [style.color]=\"option.color\"\r\n (click)=\"onOptionClick(option, row)\"\r\n >\r\n <span class=\"icon\" [class]=\"option.icon\"></span>\r\n <span class=\"label\">{{ option.label }}</span>\r\n </li>\r\n }\r\n </ul>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </td>\r\n }\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n</div>\r\n", styles: [".table-wrapper{width:100%;border-radius:20px;border:1px solid #c7c7ad}.inner-table{width:100%;border-collapse:separate;font-size:14px;border-spacing:0;border-radius:20px;background:#ebe8d6}.inner-table thead{background:#f0f0db}.inner-table thead tr th:first-child{border-top-left-radius:20px}.inner-table thead tr th:last-child{border-top-right-radius:20px}.inner-table th{text-align:left;padding:12px 16px;font-weight:600;color:#3a3a3a;text-transform:uppercase}.inner-table td{padding:12px 16px;color:#4a4a4a;border-top:1px solid #c7c7ad;table-layout:auto}.acciones-cell{text-align:center;padding:6px;position:relative}.menu-acciones{display:flex;align-items:center;justify-content:center;position:relative}button{background-color:transparent;border:none}.icon-button{background-color:var(--secondary-container, #dee58f);width:36px;height:36px;border:none;cursor:pointer;padding:0;border-radius:100%;display:flex;align-items:center;justify-content:center}.icon-button:hover{background:#0000000f}.more-vert{color:#4a4a4a;display:block}.modal-options{display:flex;justify-items:center;align-items:center;background-color:var(--surface-container-lowest, #ffffff);width:200px;border-radius:8px;position:absolute;top:100%;right:0;z-index:99}.modal-content{width:100%;border-radius:8px;border:1px solid var(--outline-variant, #c7c7ad);overflow:hidden}.option-item{display:flex;align-items:center;height:56px;padding:8px 12px;cursor:pointer}.option-item:hover{background-color:#0000001a}.option-item:active{background-color:#dee58f}.icon{margin-right:8px}.option-item .label{font-weight:500;font-size:16px}.icon-refresh,.icon-delete,.icon-edit,.icon-activate,.icon-deactivate,.icon-view,.icon-sanction,.icon-file{width:24px;height:24px;background-color:currentColor;color:currentColor;-webkit-mask-size:contain;-webkit-mask-repeat:no-repeat;mask-size:contain;mask-repeat:no-repeat;display:inline-block;cursor:pointer}.icon-refresh{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M20 11a8.1 8.1 0 0 0 -15.5 -2m-.5 -4v4h4\"/><path d=\"M4 13a8.1 8.1 0 0 0 15.5 2m.5 4v-4h-4\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M20 11a8.1 8.1 0 0 0 -15.5 -2m-.5 -4v4h4\"/><path d=\"M4 13a8.1 8.1 0 0 0 15.5 2m.5 4v-4h-4\"/></svg>')}.icon-delete{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M20 6a1 1 0 0 1 .117 1.993l-.117 .007h-.081l-.919 11a3 3 0 0 1 -2.824 2.995l-.176 .005h-8c-1.598 0 -2.904 -1.249 -2.992 -2.75l-.005 -.167l-.923 -11.083h-.08a1 1 0 0 1 -.117 -1.993l.117 -.007h16z\"/><path d=\"M14 2a2 2 0 0 1 2 2a1 1 0 0 1 -1.993 .117l-.007 -.117h-4l-.007 .117a1 1 0 0 1 -1.993 -.117a2 2 0 0 1 1.85 -1.995l.15 -.005h4z\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M20 6a1 1 0 0 1 .117 1.993l-.117 .007h-.081l-.919 11a3 3 0 0 1 -2.824 2.995l-.176 .005h-8c-1.598 0 -2.904 -1.249 -2.992 -2.75l-.005 -.167l-.923 -11.083h-.08a1 1 0 0 1 -.117 -1.993l.117 -.007h16z\"/><path d=\"M14 2a2 2 0 0 1 2 2a1 1 0 0 1 -1.993 .117l-.007 -.117h-4l-.007 .117a1 1 0 0 1 -1.993 -.117a2 2 0 0 1 1.85 -1.995l.15 -.005h4z\"/></svg>')}.icon-edit{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M4 20h4l10.5 -10.5a2.828 2.828 0 1 0 -4 -4l-10.5 10.5v4\"/><path d=\"M13.5 6.5l4 4\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M4 20h4l10.5 -10.5a2.828 2.828 0 1 0 -4 -4l-10.5 10.5v4\"/><path d=\"M13.5 6.5l4 4\"/></svg>')}.icon-activate{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M17 3.34a10 10 0 1 1 -14.995 8.984l-.005 -.324l.005 -.324a10 10 0 0 1 14.995 -8.336zm-1.293 5.953a1 1 0 0 0 -1.32 -.083l-.094 .083l-3.293 3.292l-1.293 -1.292l-.094 -.083a1 1 0 0 0 -1.403 1.403l.083 .094l2 2l.094 .083a1 1 0 0 0 1.226 0l.094 -.083l4 -4l.083 -.094a1 1 0 0 0 -.083 -1.32z\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M17 3.34a10 10 0 1 1 -14.995 8.984l-.005 -.324l.005 -.324a10 10 0 0 1 14.995 -8.336zm-1.293 5.953a1 1 0 0 0 -1.32 -.083l-.094 .083l-3.293 3.292l-1.293 -1.292l-.094 -.083a1 1 0 0 0 -1.403 1.403l.083 .094l2 2l.094 .083a1 1 0 0 0 1.226 0l.094 -.083l4 -4l.083 -.094a1 1 0 0 0 -.083 -1.32z\"/></svg>')}.icon-deactivate{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M15 9l-6 6M9 9l6 6\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M15 9l-6 6M9 9l6 6\"/></svg>')}.icon-view{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0\"/><path d=\"M21 12c-2.4 4 -5.4 6 -9 6c-3.6 0 -6.6 -2 -9 -6c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0\"/><path d=\"M21 12c-2.4 4 -5.4 6 -9 6c-3.6 0 -6.6 -2 -9 -6c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6\"/></svg>')}.icon-sanction{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M3 12a9 9 0 1 0 18 0a9 9 0 1 0 -18 0\"/><path d=\"M9 15l6 -6\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M3 12a9 9 0 1 0 18 0a9 9 0 1 0 -18 0\"/><path d=\"M9 15l6 -6\"/></svg>')}.icon-file{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M14 3v4a1 1 0 0 0 1 1h4\"/><path d=\"M5 12v-7a2 2 0 0 1 2 -2h7l5 5v4\"/><path d=\"M5 18h1.5a1.5 1.5 0 0 0 0 -3h-1.5v6\"/><path d=\"M17 18h2\"/><path d=\"M20 15h-3v6\"/><path d=\"M11 15v6h1a2 2 0 0 0 2 -2v-2a2 2 0 0 0 -2 -2h-1\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M14 3v4a1 1 0 0 0 1 1h4\"/><path d=\"M5 12v-7a2 2 0 0 1 2 -2h7l5 5v4\"/><path d=\"M5 18h1.5a1.5 1.5 0 0 0 0 -3h-1.5v6\"/><path d=\"M17 18h2\"/><path d=\"M20 15h-3v6\"/><path d=\"M11 15v6h1a2 2 0 0 0 2 -2v-2a2 2 0 0 0 -2 -2h-1\"/></svg>')}th.left.sortable,th.left,td.left{text-align:left}th.right.sortable,th.right,td.right{text-align:right}th.center.sortable,th.center,td.center{text-align:center}.status-chip{display:inline-flex;align-items:center;gap:.5rem;width:100%;padding:.375rem .75rem;border-radius:8px;font-size:.875rem;font-weight:500;white-space:nowrap}.status-dot{width:6px;height:6px;border-radius:50%;flex-shrink:0}.sortable{cursor:pointer;-webkit-user-select:none;user-select:none}.sortable:hover{opacity:.7}.sort-icon{margin-left:6px;font-size:12px;pointer-events:none}\n"] });
704
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DateTimePicker, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
705
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DateTimePicker, isStandalone: true, selector: "lib-date-time-picker", inputs: { mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dateChange: "dateChange" }, providers: [
706
+ {
707
+ provide: NG_VALUE_ACCESSOR,
708
+ useExisting: forwardRef(() => DateTimePicker),
709
+ multi: true,
710
+ },
711
+ ], ngImport: i0, template: "<div class=\"datetime-container\">\r\n <div\r\n class=\"datetime-header\"\r\n [class.active]=\"isOpen()\"\r\n [class.disabled]=\"isBlocked()\"\r\n [class.readonly]=\"isBlocked()\"\r\n (click)=\"!isBlocked() && toggle()\"\r\n (keydown)=\"!isBlocked() && onKeyDown($event)\"\r\n tabindex=\"0\"\r\n >\r\n <input\r\n type=\"text\"\r\n class=\"datetime-input\"\r\n [value]=\"displayValue()\"\r\n [placeholder]=\"placeholder()\"\r\n (input)=\"onInputChange($event)\"\r\n (focus)=\"!isBlocked() && onInputFocus()\"\r\n (click)=\"$event.stopPropagation()\"\r\n [disabled]=\"isDisabled()\"\r\n [readOnly]=\"readonly()\"\r\n />\r\n\r\n <div class=\"header-icons\">\r\n @if (selectedDate()) {\r\n <span\r\n class=\"clear-icon\"\r\n (click)=\"!isBlocked() && clear(); $event.stopPropagation()\"\r\n title=\"Limpiar\"\r\n >\r\n \u00D7\r\n </span>\r\n }\r\n <span class=\"arrow\" [class.open]=\"isOpen()\"></span>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n@if (isOpen()) {\r\n<div class=\"dropdown\">\r\n <div class=\"datetime-content\">\r\n <!-- Secci\u00F3n del calendario -->\r\n <div class=\"calendar-section\">\r\n <!-- Navegaci\u00F3n del calendario -->\r\n <div class=\"calendar-nav\">\r\n <div class=\"nav-section\">\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"previousYear()\"\r\n title=\"A\u00F1o anterior\"\r\n >\r\n \u2039\u2039\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"previousMonth()\"\r\n title=\"Mes anterior\"\r\n >\r\n \u2039\r\n </button>\r\n </div>\r\n\r\n <div class=\"current-date\">{{ monthName() }} {{ currentYear() }}</div>\r\n\r\n <div class=\"nav-section\">\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"nextMonth()\"\r\n title=\"Siguiente mes\"\r\n >\r\n \u203A\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"nextYear()\"\r\n title=\"Siguiente a\u00F1o\"\r\n >\r\n \u203A\u203A\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- D\u00EDas de la semana -->\r\n <div class=\"weekdays\">\r\n <div class=\"weekday\">Dom</div>\r\n <div class=\"weekday\">Lun</div>\r\n <div class=\"weekday\">Mar</div>\r\n <div class=\"weekday\">Mi\u00E9</div>\r\n <div class=\"weekday\">Jue</div>\r\n <div class=\"weekday\">Vie</div>\r\n <div class=\"weekday\">S\u00E1b</div>\r\n </div>\r\n\r\n <!-- D\u00EDas del mes -->\r\n <div class=\"calendar-grid\">\r\n @for (day of calendarDays(); track $index) {\r\n <div\r\n class=\"calendar-day\"\r\n [class.selected]=\"isDaySelected(day)\"\r\n [class.today]=\"isToday(day)\"\r\n [class.disabled]=\"isDayDisabled(day)\"\r\n [class.empty]=\"!day\"\r\n (click)=\"selectDay(day)\"\r\n >\r\n {{ day || '' }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- Selector de tiempo (solo si mode === 'datetime') -->\r\n @if (mode() === 'datetime') {\r\n <div class=\"time-section\">\r\n <div class=\"time-header\">Horario</div>\r\n\r\n <div class=\"time-selectors\">\r\n <div class=\"time-group\">\r\n <div class=\"time-column\">\r\n <div class=\"time-label\">Hora</div>\r\n <div class=\"time-scroll\">\r\n @for (hour of hours12(); track hour.value) {\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"hour.value === selectedHour12()\"\r\n (click)=\"setHour12(hour.value)\"\r\n >\r\n {{ hour.display }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"time-separator-vertical\">:</div>\r\n\r\n <div class=\"time-column\">\r\n <div class=\"time-label\">Min</div>\r\n <div class=\"time-scroll\">\r\n @for (minute of minutes(); track minute) {\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"minute === selectedMinute()\"\r\n (click)=\"setMinute(minute)\"\r\n >\r\n {{ minute.toString().padStart(2, '0') }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"time-column\">\r\n <div class=\"time-label\">AM/PM</div>\r\n <div class=\"time-scroll ampm\">\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"selectedAmPm() === 'AM'\"\r\n (click)=\"setAmPm('AM')\"\r\n >\r\n AM\r\n </div>\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"selectedAmPm() === 'PM'\"\r\n (click)=\"setAmPm('PM')\"\r\n >\r\n PM\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Botones de acci\u00F3n -->\r\n <div class=\"action-buttons\">\r\n <button type=\"button\" class=\"action-btn secondary\" (click)=\"today()\">\r\n Hoy\r\n </button>\r\n @if (mode() === 'datetime') {\r\n <button type=\"button\" class=\"action-btn primary\" (click)=\"close()\">\r\n Aceptar\r\n </button>\r\n }\r\n </div>\r\n</div>\r\n}\r\n", styles: [".datetime-container{position:relative;width:100%}.datetime-header{width:100%;border:1px solid #787861;border-radius:5px;padding:12px 15px;background-color:transparent;cursor:pointer;display:flex;justify-content:space-between;align-items:center;min-height:auto;transition:border-color .2s}.datetime-input{flex:1;border:none;outline:none;background:transparent;font-size:1.3rem;color:#454733;padding:0;margin:0}.datetime-input::placeholder{color:#787861}.datetime-input:disabled{cursor:not-allowed}.datetime-header:hover,.datetime-header:focus{outline:none;border-color:#a9a97f}.datetime-header.active{border-color:#a9a97f;outline:none}.datetime-header.disabled,.datetime-header.readonly{pointer-events:none;opacity:.6;cursor:not-allowed}.selected-text{color:#454733;font-size:1.3rem;flex:1}.selected-text.placeholder{color:#787861}.header-icons{display:flex;align-items:center;gap:8px}.clear-icon{width:20px;height:20px;display:flex;align-items:center;justify-content:center;color:#787861;font-size:1.5rem;cursor:pointer;border-radius:50%;transition:all .2s}.clear-icon:hover{background-color:#7878611a;color:#454733}.arrow{width:20px;height:20px;background-image:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='icon icon-tabler icons-tabler-outline icon-tabler-calendar-event'%3e%3cpath stroke='none' d='M0 0h24v24H0z' fill='none'/%3e%3cpath d='M4 5m0 2a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2z' /%3e%3cpath d='M16 3l0 4' /%3e%3cpath d='M8 3l0 4' /%3e%3cpath d='M4 11l16 0' /%3e%3cpath d='M8 15h2v2h-2z' /%3e%3c/svg%3e\");background-repeat:no-repeat;background-size:20px;background-position:center;color:#787861;flex-shrink:0;transition:transform .2s}.arrow.open{background-image:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='currentColor' class='icon icon-tabler icons-tabler-filled icon-tabler-calendar-event'%3e%3cpath stroke='none' d='M0 0h24v24H0z' fill='none'/%3e%3cpath d='M16 2a1 1 0 0 1 .993 .883l.007 .117v1h1a3 3 0 0 1 2.995 2.824l.005 .176v12a3 3 0 0 1 -2.824 2.995l-.176 .005h-12a3 3 0 0 1 -2.995 -2.824l-.005 -.176v-12a3 3 0 0 1 2.824 -2.995l.176 -.005h1v-1a1 1 0 0 1 1.993 -.117l.007 .117v1h6v-1a1 1 0 0 1 1 -1m3 7h-14v9.625c0 .705 .386 1.286 .883 1.366l.117 .009h12c.513 0 .936 -.53 .993 -1.215l.007 -.16z' /%3e%3cpath d='M8 14h2v2h-2z' /%3e%3c/svg%3e\")}.dropdown{position:absolute;top:100%;left:0;right:0;background:#e3e3d1;border:1px solid #787861;border-top:none;border-radius:0 0 5px 5px;z-index:1000;box-shadow:0 4px 12px #00000026;min-width:400px}.datetime-content{display:flex}.calendar-section{flex:1;min-width:280px}.calendar-nav{display:flex;justify-content:space-between;align-items:center;padding:15px;border-bottom:1px solid rgba(120,120,97,.2)}.nav-section{display:flex;gap:5px}.nav-btn{background:none;border:none;color:#787861;cursor:pointer;font-size:1.2rem;padding:5px 10px;border-radius:3px;transition:all .2s}.nav-btn:hover{background-color:#a9a97f1a;color:#454733}.current-date{font-weight:500;color:#454733;font-size:1.1rem}.weekdays{display:grid;grid-template-columns:repeat(7,1fr);background:#7878611a}.weekday{padding:10px 5px;text-align:center;font-size:.9rem;font-weight:500;color:#787861}.calendar-grid{display:grid;grid-template-columns:repeat(7,1fr)}.calendar-day{padding:12px 5px;text-align:center;cursor:pointer;color:#454733;font-size:1rem;border-right:1px solid rgba(120,120,97,.1);border-bottom:1px solid rgba(120,120,97,.1);transition:all .2s}.calendar-day:hover:not(.disabled):not(.empty){background-color:#a9a97f33}.calendar-day.selected{background-color:#a9a97f;color:#e3e3d1;font-weight:500}.calendar-day.today:not(.selected){background-color:#a9a97f4d;font-weight:500}.calendar-day.disabled{color:#78786166;cursor:not-allowed}.calendar-day.empty{cursor:default}.calendar-day:nth-child(7n){border-right:none}.time-section{border-left:1px solid rgba(120,120,97,.2);min-width:140px;display:flex;flex-direction:column;background:#a9a97f0d}.time-header{padding:15px;border-bottom:1px solid rgba(120,120,97,.2);text-align:center;font-weight:500;color:#454733;background:#a9a97f1a}.time-selectors{display:flex;flex-direction:column;padding:15px;gap:20px;flex:1}.time-group{display:flex;align-items:center;gap:10px}.time-column{flex:1;display:flex;flex-direction:column;align-items:center}.time-label{font-size:.9rem;color:#787861;margin-bottom:10px;font-weight:500}.time-scroll{max-height:150px;overflow-y:auto;border:1px solid rgba(120,120,97,.2);border-radius:3px;width:50px;background:#a9a97f}.time-option{padding:8px 12px;text-align:center;cursor:pointer;color:#454733;font-size:1rem;transition:all .2s}.time-option:hover{background-color:#a9a97f1a}.time-option.selected{background-color:#a9a97f;color:#e3e3d1;font-weight:500}.time-separator-vertical{font-size:1.5rem;color:#787861;font-weight:700;align-self:flex-end;margin-bottom:10px}.time-scroll::-webkit-scrollbar{width:4px}.time-scroll::-webkit-scrollbar-track{background:#7878611a}.time-scroll::-webkit-scrollbar-thumb{background:#787861;border-radius:2px}.time-scroll::-webkit-scrollbar-thumb:hover{background:#a9a97f}.action-buttons{display:flex;justify-content:space-between;padding:15px;border-top:1px solid rgba(120,120,97,.2);gap:10px}.action-btn{padding:10px 20px;border:none;border-radius:3px;cursor:pointer;font-size:1rem;transition:all .2s}.action-btn.secondary{background:transparent;color:#787861;border:1px solid #787861}.action-btn.secondary:hover{background:#7878611a;color:#454733}.action-btn.primary{background:#a9a97f;color:#e3e3d1;border:1px solid #a9a97f}.action-btn.primary:hover{background:#969669;border-color:#969669}@media (max-width: 768px){.dropdown{min-width:320px}.datetime-content{flex-direction:column}.time-section{border-left:none;border-top:1px solid rgba(120,120,97,.2)}.time-selectors{flex-direction:row;justify-content:center;padding:15px}.time-group{gap:15px}.datetime-header{padding:10px 15px}.calendar-nav{padding:12px}.calendar-day{padding:10px 3px;font-size:.9rem}.action-buttons{padding:12px}}@media (max-width: 480px){.dropdown{min-width:280px}.time-section{min-width:auto}.time-scroll{width:45px}.time-selectors{padding:10px}}\n"] });
721
712
  }
722
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: Table, decorators: [{
713
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DateTimePicker, decorators: [{
723
714
  type: Component,
724
- args: [{ selector: 'lib-table', imports: [], standalone: true, template: "<div class=\"table-wrapper\">\r\n <table class=\"inner-table\">\r\n <thead>\r\n <tr>\r\n @for (col of columns(); track col.key) {\r\n <th\r\n (click)=\"col.sortable !== false && onSort(col)\"\r\n [class.sortable]=\"col.sortable !== false\"\r\n [class]=\"getAlignment(col)\"\r\n >\r\n {{ col.label }}\r\n\r\n <!-- iconos de orden opcionales -->\r\n @if (sortColumn() === col.key) {\r\n <span class=\"sort-icon\">\r\n {{ sortDirection() === 'asc' ? '\u25B2' : '\u25BC' }}\r\n </span>\r\n }\r\n </th>\r\n }\r\n\r\n <!-- columna para acciones -->\r\n @if (showActions()) {\r\n <th></th>\r\n }\r\n </tr>\r\n </thead>\r\n\r\n <tbody>\r\n @for (row of sortData(); track $index) {\r\n <tr>\r\n @for (col of columns(); track col.key) {\r\n <td [class]=\"getAlignment(col)\">\r\n @if (col.type === 'status') { @let style =\r\n getStatusStyle(row[col.key]);\r\n <span\r\n class=\"status-chip\"\r\n id=\"status-chip\"\r\n [style.background-color]=\"style.bg\"\r\n [style.color]=\"style.color\"\r\n >\r\n <span\r\n class=\"status-dot\"\r\n [style.background-color]=\"style.color\"\r\n ></span>\r\n\r\n {{ row[col.key]?.toString().toUpperCase() }}\r\n </span>\r\n\r\n } @else if (col.type === 'icon-button') {\r\n\r\n <button (click)=\"onIconColumnClick(col, row, $event)\">\r\n <span\r\n class=\"icon\"\r\n [class]=\"col.icon\"\r\n [style.color]=\"col.iconColor\"\r\n ></span>\r\n </button>\r\n\r\n } @else { {{ formatValue(col, row[col.key]) }} }\r\n </td>\r\n }\r\n\r\n <!-- Celda de acciones -->\r\n @if (showActions()) {\r\n <td class=\"acciones-cell\">\r\n <div class=\"menu-acciones\">\r\n <button class=\"icon-button\" (click)=\"openModal(row)\">\r\n <div class=\"content\">\r\n <div class=\"state-layer\">\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n class=\"more-vert\"\r\n width=\"20\"\r\n height=\"20\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n >\r\n <circle cx=\"12\" cy=\"5\" r=\"1\" />\r\n <circle cx=\"12\" cy=\"12\" r=\"1\" />\r\n <circle cx=\"12\" cy=\"19\" r=\"1\" />\r\n </svg>\r\n </div>\r\n </div>\r\n </button>\r\n @if(selectedRow()?.['id'] === row['id']){\r\n <div class=\"modal-options\" (click)=\"$event.stopPropagation()\">\r\n <div class=\"modal-content\">\r\n <ul>\r\n @for (option of getActionsForRow(row); track $index) {\r\n <li\r\n class=\"option-item\"\r\n [style.color]=\"option.color\"\r\n (click)=\"onOptionClick(option, row)\"\r\n >\r\n <span class=\"icon\" [class]=\"option.icon\"></span>\r\n <span class=\"label\">{{ option.label }}</span>\r\n </li>\r\n }\r\n </ul>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </td>\r\n }\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n</div>\r\n", styles: [".table-wrapper{width:100%;border-radius:20px;border:1px solid #c7c7ad}.inner-table{width:100%;border-collapse:separate;font-size:14px;border-spacing:0;border-radius:20px;background:#ebe8d6}.inner-table thead{background:#f0f0db}.inner-table thead tr th:first-child{border-top-left-radius:20px}.inner-table thead tr th:last-child{border-top-right-radius:20px}.inner-table th{text-align:left;padding:12px 16px;font-weight:600;color:#3a3a3a;text-transform:uppercase}.inner-table td{padding:12px 16px;color:#4a4a4a;border-top:1px solid #c7c7ad;table-layout:auto}.acciones-cell{text-align:center;padding:6px;position:relative}.menu-acciones{display:flex;align-items:center;justify-content:center;position:relative}button{background-color:transparent;border:none}.icon-button{background-color:var(--secondary-container, #dee58f);width:36px;height:36px;border:none;cursor:pointer;padding:0;border-radius:100%;display:flex;align-items:center;justify-content:center}.icon-button:hover{background:#0000000f}.more-vert{color:#4a4a4a;display:block}.modal-options{display:flex;justify-items:center;align-items:center;background-color:var(--surface-container-lowest, #ffffff);width:200px;border-radius:8px;position:absolute;top:100%;right:0;z-index:99}.modal-content{width:100%;border-radius:8px;border:1px solid var(--outline-variant, #c7c7ad);overflow:hidden}.option-item{display:flex;align-items:center;height:56px;padding:8px 12px;cursor:pointer}.option-item:hover{background-color:#0000001a}.option-item:active{background-color:#dee58f}.icon{margin-right:8px}.option-item .label{font-weight:500;font-size:16px}.icon-refresh,.icon-delete,.icon-edit,.icon-activate,.icon-deactivate,.icon-view,.icon-sanction,.icon-file{width:24px;height:24px;background-color:currentColor;color:currentColor;-webkit-mask-size:contain;-webkit-mask-repeat:no-repeat;mask-size:contain;mask-repeat:no-repeat;display:inline-block;cursor:pointer}.icon-refresh{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M20 11a8.1 8.1 0 0 0 -15.5 -2m-.5 -4v4h4\"/><path d=\"M4 13a8.1 8.1 0 0 0 15.5 2m.5 4v-4h-4\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M20 11a8.1 8.1 0 0 0 -15.5 -2m-.5 -4v4h4\"/><path d=\"M4 13a8.1 8.1 0 0 0 15.5 2m.5 4v-4h-4\"/></svg>')}.icon-delete{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M20 6a1 1 0 0 1 .117 1.993l-.117 .007h-.081l-.919 11a3 3 0 0 1 -2.824 2.995l-.176 .005h-8c-1.598 0 -2.904 -1.249 -2.992 -2.75l-.005 -.167l-.923 -11.083h-.08a1 1 0 0 1 -.117 -1.993l.117 -.007h16z\"/><path d=\"M14 2a2 2 0 0 1 2 2a1 1 0 0 1 -1.993 .117l-.007 -.117h-4l-.007 .117a1 1 0 0 1 -1.993 -.117a2 2 0 0 1 1.85 -1.995l.15 -.005h4z\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M20 6a1 1 0 0 1 .117 1.993l-.117 .007h-.081l-.919 11a3 3 0 0 1 -2.824 2.995l-.176 .005h-8c-1.598 0 -2.904 -1.249 -2.992 -2.75l-.005 -.167l-.923 -11.083h-.08a1 1 0 0 1 -.117 -1.993l.117 -.007h16z\"/><path d=\"M14 2a2 2 0 0 1 2 2a1 1 0 0 1 -1.993 .117l-.007 -.117h-4l-.007 .117a1 1 0 0 1 -1.993 -.117a2 2 0 0 1 1.85 -1.995l.15 -.005h4z\"/></svg>')}.icon-edit{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M4 20h4l10.5 -10.5a2.828 2.828 0 1 0 -4 -4l-10.5 10.5v4\"/><path d=\"M13.5 6.5l4 4\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M4 20h4l10.5 -10.5a2.828 2.828 0 1 0 -4 -4l-10.5 10.5v4\"/><path d=\"M13.5 6.5l4 4\"/></svg>')}.icon-activate{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M17 3.34a10 10 0 1 1 -14.995 8.984l-.005 -.324l.005 -.324a10 10 0 0 1 14.995 -8.336zm-1.293 5.953a1 1 0 0 0 -1.32 -.083l-.094 .083l-3.293 3.292l-1.293 -1.292l-.094 -.083a1 1 0 0 0 -1.403 1.403l.083 .094l2 2l.094 .083a1 1 0 0 0 1.226 0l.094 -.083l4 -4l.083 -.094a1 1 0 0 0 -.083 -1.32z\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M17 3.34a10 10 0 1 1 -14.995 8.984l-.005 -.324l.005 -.324a10 10 0 0 1 14.995 -8.336zm-1.293 5.953a1 1 0 0 0 -1.32 -.083l-.094 .083l-3.293 3.292l-1.293 -1.292l-.094 -.083a1 1 0 0 0 -1.403 1.403l.083 .094l2 2l.094 .083a1 1 0 0 0 1.226 0l.094 -.083l4 -4l.083 -.094a1 1 0 0 0 -.083 -1.32z\"/></svg>')}.icon-deactivate{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M15 9l-6 6M9 9l6 6\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M15 9l-6 6M9 9l6 6\"/></svg>')}.icon-view{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0\"/><path d=\"M21 12c-2.4 4 -5.4 6 -9 6c-3.6 0 -6.6 -2 -9 -6c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0\"/><path d=\"M21 12c-2.4 4 -5.4 6 -9 6c-3.6 0 -6.6 -2 -9 -6c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6\"/></svg>')}.icon-sanction{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M3 12a9 9 0 1 0 18 0a9 9 0 1 0 -18 0\"/><path d=\"M9 15l6 -6\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M3 12a9 9 0 1 0 18 0a9 9 0 1 0 -18 0\"/><path d=\"M9 15l6 -6\"/></svg>')}.icon-file{-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M14 3v4a1 1 0 0 0 1 1h4\"/><path d=\"M5 12v-7a2 2 0 0 1 2 -2h7l5 5v4\"/><path d=\"M5 18h1.5a1.5 1.5 0 0 0 0 -3h-1.5v6\"/><path d=\"M17 18h2\"/><path d=\"M20 15h-3v6\"/><path d=\"M11 15v6h1a2 2 0 0 0 2 -2v-2a2 2 0 0 0 -2 -2h-1\"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 24 24\"><path d=\"M14 3v4a1 1 0 0 0 1 1h4\"/><path d=\"M5 12v-7a2 2 0 0 1 2 -2h7l5 5v4\"/><path d=\"M5 18h1.5a1.5 1.5 0 0 0 0 -3h-1.5v6\"/><path d=\"M17 18h2\"/><path d=\"M20 15h-3v6\"/><path d=\"M11 15v6h1a2 2 0 0 0 2 -2v-2a2 2 0 0 0 -2 -2h-1\"/></svg>')}th.left.sortable,th.left,td.left{text-align:left}th.right.sortable,th.right,td.right{text-align:right}th.center.sortable,th.center,td.center{text-align:center}.status-chip{display:inline-flex;align-items:center;gap:.5rem;width:100%;padding:.375rem .75rem;border-radius:8px;font-size:.875rem;font-weight:500;white-space:nowrap}.status-dot{width:6px;height:6px;border-radius:50%;flex-shrink:0}.sortable{cursor:pointer;-webkit-user-select:none;user-select:none}.sortable:hover{opacity:.7}.sort-icon{margin-left:6px;font-size:12px;pointer-events:none}\n"] }]
725
- }], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], actions: [{ type: i0.Input, args: [{ isSignal: true, alias: "actions", required: false }] }], showActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "showActions", required: false }] }], optionSelected: [{ type: i0.Output, args: ["optionSelected"] }], iconAction: [{ type: i0.Output, args: ["iconAction"] }], statusToneMap: [{ type: i0.Input, args: [{ isSignal: true, alias: "statusToneMap", required: false }] }], chips: [{
726
- type: ViewChildren,
727
- args: ['status-chip']
728
- }], onClickOutside: [{
729
- type: HostListener,
730
- args: ['document:click', ['$event']]
731
- }] } });
715
+ args: [{ selector: 'lib-date-time-picker', imports: [], providers: [
716
+ {
717
+ provide: NG_VALUE_ACCESSOR,
718
+ useExisting: forwardRef(() => DateTimePicker),
719
+ multi: true,
720
+ },
721
+ ], template: "<div class=\"datetime-container\">\r\n <div\r\n class=\"datetime-header\"\r\n [class.active]=\"isOpen()\"\r\n [class.disabled]=\"isBlocked()\"\r\n [class.readonly]=\"isBlocked()\"\r\n (click)=\"!isBlocked() && toggle()\"\r\n (keydown)=\"!isBlocked() && onKeyDown($event)\"\r\n tabindex=\"0\"\r\n >\r\n <input\r\n type=\"text\"\r\n class=\"datetime-input\"\r\n [value]=\"displayValue()\"\r\n [placeholder]=\"placeholder()\"\r\n (input)=\"onInputChange($event)\"\r\n (focus)=\"!isBlocked() && onInputFocus()\"\r\n (click)=\"$event.stopPropagation()\"\r\n [disabled]=\"isDisabled()\"\r\n [readOnly]=\"readonly()\"\r\n />\r\n\r\n <div class=\"header-icons\">\r\n @if (selectedDate()) {\r\n <span\r\n class=\"clear-icon\"\r\n (click)=\"!isBlocked() && clear(); $event.stopPropagation()\"\r\n title=\"Limpiar\"\r\n >\r\n \u00D7\r\n </span>\r\n }\r\n <span class=\"arrow\" [class.open]=\"isOpen()\"></span>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n@if (isOpen()) {\r\n<div class=\"dropdown\">\r\n <div class=\"datetime-content\">\r\n <!-- Secci\u00F3n del calendario -->\r\n <div class=\"calendar-section\">\r\n <!-- Navegaci\u00F3n del calendario -->\r\n <div class=\"calendar-nav\">\r\n <div class=\"nav-section\">\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"previousYear()\"\r\n title=\"A\u00F1o anterior\"\r\n >\r\n \u2039\u2039\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"previousMonth()\"\r\n title=\"Mes anterior\"\r\n >\r\n \u2039\r\n </button>\r\n </div>\r\n\r\n <div class=\"current-date\">{{ monthName() }} {{ currentYear() }}</div>\r\n\r\n <div class=\"nav-section\">\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"nextMonth()\"\r\n title=\"Siguiente mes\"\r\n >\r\n \u203A\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"nextYear()\"\r\n title=\"Siguiente a\u00F1o\"\r\n >\r\n \u203A\u203A\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- D\u00EDas de la semana -->\r\n <div class=\"weekdays\">\r\n <div class=\"weekday\">Dom</div>\r\n <div class=\"weekday\">Lun</div>\r\n <div class=\"weekday\">Mar</div>\r\n <div class=\"weekday\">Mi\u00E9</div>\r\n <div class=\"weekday\">Jue</div>\r\n <div class=\"weekday\">Vie</div>\r\n <div class=\"weekday\">S\u00E1b</div>\r\n </div>\r\n\r\n <!-- D\u00EDas del mes -->\r\n <div class=\"calendar-grid\">\r\n @for (day of calendarDays(); track $index) {\r\n <div\r\n class=\"calendar-day\"\r\n [class.selected]=\"isDaySelected(day)\"\r\n [class.today]=\"isToday(day)\"\r\n [class.disabled]=\"isDayDisabled(day)\"\r\n [class.empty]=\"!day\"\r\n (click)=\"selectDay(day)\"\r\n >\r\n {{ day || '' }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- Selector de tiempo (solo si mode === 'datetime') -->\r\n @if (mode() === 'datetime') {\r\n <div class=\"time-section\">\r\n <div class=\"time-header\">Horario</div>\r\n\r\n <div class=\"time-selectors\">\r\n <div class=\"time-group\">\r\n <div class=\"time-column\">\r\n <div class=\"time-label\">Hora</div>\r\n <div class=\"time-scroll\">\r\n @for (hour of hours12(); track hour.value) {\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"hour.value === selectedHour12()\"\r\n (click)=\"setHour12(hour.value)\"\r\n >\r\n {{ hour.display }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"time-separator-vertical\">:</div>\r\n\r\n <div class=\"time-column\">\r\n <div class=\"time-label\">Min</div>\r\n <div class=\"time-scroll\">\r\n @for (minute of minutes(); track minute) {\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"minute === selectedMinute()\"\r\n (click)=\"setMinute(minute)\"\r\n >\r\n {{ minute.toString().padStart(2, '0') }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"time-column\">\r\n <div class=\"time-label\">AM/PM</div>\r\n <div class=\"time-scroll ampm\">\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"selectedAmPm() === 'AM'\"\r\n (click)=\"setAmPm('AM')\"\r\n >\r\n AM\r\n </div>\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"selectedAmPm() === 'PM'\"\r\n (click)=\"setAmPm('PM')\"\r\n >\r\n PM\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Botones de acci\u00F3n -->\r\n <div class=\"action-buttons\">\r\n <button type=\"button\" class=\"action-btn secondary\" (click)=\"today()\">\r\n Hoy\r\n </button>\r\n @if (mode() === 'datetime') {\r\n <button type=\"button\" class=\"action-btn primary\" (click)=\"close()\">\r\n Aceptar\r\n </button>\r\n }\r\n </div>\r\n</div>\r\n}\r\n", styles: [".datetime-container{position:relative;width:100%}.datetime-header{width:100%;border:1px solid #787861;border-radius:5px;padding:12px 15px;background-color:transparent;cursor:pointer;display:flex;justify-content:space-between;align-items:center;min-height:auto;transition:border-color .2s}.datetime-input{flex:1;border:none;outline:none;background:transparent;font-size:1.3rem;color:#454733;padding:0;margin:0}.datetime-input::placeholder{color:#787861}.datetime-input:disabled{cursor:not-allowed}.datetime-header:hover,.datetime-header:focus{outline:none;border-color:#a9a97f}.datetime-header.active{border-color:#a9a97f;outline:none}.datetime-header.disabled,.datetime-header.readonly{pointer-events:none;opacity:.6;cursor:not-allowed}.selected-text{color:#454733;font-size:1.3rem;flex:1}.selected-text.placeholder{color:#787861}.header-icons{display:flex;align-items:center;gap:8px}.clear-icon{width:20px;height:20px;display:flex;align-items:center;justify-content:center;color:#787861;font-size:1.5rem;cursor:pointer;border-radius:50%;transition:all .2s}.clear-icon:hover{background-color:#7878611a;color:#454733}.arrow{width:20px;height:20px;background-image:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='icon icon-tabler icons-tabler-outline icon-tabler-calendar-event'%3e%3cpath stroke='none' d='M0 0h24v24H0z' fill='none'/%3e%3cpath d='M4 5m0 2a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2z' /%3e%3cpath d='M16 3l0 4' /%3e%3cpath d='M8 3l0 4' /%3e%3cpath d='M4 11l16 0' /%3e%3cpath d='M8 15h2v2h-2z' /%3e%3c/svg%3e\");background-repeat:no-repeat;background-size:20px;background-position:center;color:#787861;flex-shrink:0;transition:transform .2s}.arrow.open{background-image:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='currentColor' class='icon icon-tabler icons-tabler-filled icon-tabler-calendar-event'%3e%3cpath stroke='none' d='M0 0h24v24H0z' fill='none'/%3e%3cpath d='M16 2a1 1 0 0 1 .993 .883l.007 .117v1h1a3 3 0 0 1 2.995 2.824l.005 .176v12a3 3 0 0 1 -2.824 2.995l-.176 .005h-12a3 3 0 0 1 -2.995 -2.824l-.005 -.176v-12a3 3 0 0 1 2.824 -2.995l.176 -.005h1v-1a1 1 0 0 1 1.993 -.117l.007 .117v1h6v-1a1 1 0 0 1 1 -1m3 7h-14v9.625c0 .705 .386 1.286 .883 1.366l.117 .009h12c.513 0 .936 -.53 .993 -1.215l.007 -.16z' /%3e%3cpath d='M8 14h2v2h-2z' /%3e%3c/svg%3e\")}.dropdown{position:absolute;top:100%;left:0;right:0;background:#e3e3d1;border:1px solid #787861;border-top:none;border-radius:0 0 5px 5px;z-index:1000;box-shadow:0 4px 12px #00000026;min-width:400px}.datetime-content{display:flex}.calendar-section{flex:1;min-width:280px}.calendar-nav{display:flex;justify-content:space-between;align-items:center;padding:15px;border-bottom:1px solid rgba(120,120,97,.2)}.nav-section{display:flex;gap:5px}.nav-btn{background:none;border:none;color:#787861;cursor:pointer;font-size:1.2rem;padding:5px 10px;border-radius:3px;transition:all .2s}.nav-btn:hover{background-color:#a9a97f1a;color:#454733}.current-date{font-weight:500;color:#454733;font-size:1.1rem}.weekdays{display:grid;grid-template-columns:repeat(7,1fr);background:#7878611a}.weekday{padding:10px 5px;text-align:center;font-size:.9rem;font-weight:500;color:#787861}.calendar-grid{display:grid;grid-template-columns:repeat(7,1fr)}.calendar-day{padding:12px 5px;text-align:center;cursor:pointer;color:#454733;font-size:1rem;border-right:1px solid rgba(120,120,97,.1);border-bottom:1px solid rgba(120,120,97,.1);transition:all .2s}.calendar-day:hover:not(.disabled):not(.empty){background-color:#a9a97f33}.calendar-day.selected{background-color:#a9a97f;color:#e3e3d1;font-weight:500}.calendar-day.today:not(.selected){background-color:#a9a97f4d;font-weight:500}.calendar-day.disabled{color:#78786166;cursor:not-allowed}.calendar-day.empty{cursor:default}.calendar-day:nth-child(7n){border-right:none}.time-section{border-left:1px solid rgba(120,120,97,.2);min-width:140px;display:flex;flex-direction:column;background:#a9a97f0d}.time-header{padding:15px;border-bottom:1px solid rgba(120,120,97,.2);text-align:center;font-weight:500;color:#454733;background:#a9a97f1a}.time-selectors{display:flex;flex-direction:column;padding:15px;gap:20px;flex:1}.time-group{display:flex;align-items:center;gap:10px}.time-column{flex:1;display:flex;flex-direction:column;align-items:center}.time-label{font-size:.9rem;color:#787861;margin-bottom:10px;font-weight:500}.time-scroll{max-height:150px;overflow-y:auto;border:1px solid rgba(120,120,97,.2);border-radius:3px;width:50px;background:#a9a97f}.time-option{padding:8px 12px;text-align:center;cursor:pointer;color:#454733;font-size:1rem;transition:all .2s}.time-option:hover{background-color:#a9a97f1a}.time-option.selected{background-color:#a9a97f;color:#e3e3d1;font-weight:500}.time-separator-vertical{font-size:1.5rem;color:#787861;font-weight:700;align-self:flex-end;margin-bottom:10px}.time-scroll::-webkit-scrollbar{width:4px}.time-scroll::-webkit-scrollbar-track{background:#7878611a}.time-scroll::-webkit-scrollbar-thumb{background:#787861;border-radius:2px}.time-scroll::-webkit-scrollbar-thumb:hover{background:#a9a97f}.action-buttons{display:flex;justify-content:space-between;padding:15px;border-top:1px solid rgba(120,120,97,.2);gap:10px}.action-btn{padding:10px 20px;border:none;border-radius:3px;cursor:pointer;font-size:1rem;transition:all .2s}.action-btn.secondary{background:transparent;color:#787861;border:1px solid #787861}.action-btn.secondary:hover{background:#7878611a;color:#454733}.action-btn.primary{background:#a9a97f;color:#e3e3d1;border:1px solid #a9a97f}.action-btn.primary:hover{background:#969669;border-color:#969669}@media (max-width: 768px){.dropdown{min-width:320px}.datetime-content{flex-direction:column}.time-section{border-left:none;border-top:1px solid rgba(120,120,97,.2)}.time-selectors{flex-direction:row;justify-content:center;padding:15px}.time-group{gap:15px}.datetime-header{padding:10px 15px}.calendar-nav{padding:12px}.calendar-day{padding:10px 3px;font-size:.9rem}.action-buttons{padding:12px}}@media (max-width: 480px){.dropdown{min-width:280px}.time-section{min-width:auto}.time-scroll{width:45px}.time-selectors{padding:10px}}\n"] }]
722
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.NgZone }], propDecorators: { mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], minDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "minDate", required: false }] }], maxDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDate", required: false }] }], dateChange: [{ type: i0.Output, args: ["dateChange"] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }] } });
732
723
 
733
- class DateTimePicker {
724
+ class DateTimeFilter {
734
725
  elementRef;
735
726
  ngZone;
736
- mode = input('date', ...(ngDevMode ? [{ debugName: "mode" }] : []));
737
- placeholder = input('Seleccionar fecha', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
738
- minDate = input(null, ...(ngDevMode ? [{ debugName: "minDate" }] : []));
739
- maxDate = input(null, ...(ngDevMode ? [{ debugName: "maxDate" }] : []));
727
+ // Inputs
728
+ filters = input([], ...(ngDevMode ? [{ debugName: "filters" }] : []));
729
+ // Outputs
730
+ dateSelected = output();
740
731
  dateChange = output();
732
+ // Internal State
733
+ activeFilterType = signal(null, ...(ngDevMode ? [{ debugName: "activeFilterType" }] : []));
741
734
  isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
742
735
  selectedDate = signal(null, ...(ngDevMode ? [{ debugName: "selectedDate" }] : []));
736
+ inputTextValue = signal('', ...(ngDevMode ? [{ debugName: "inputTextValue" }] : []));
743
737
  isDisabled = signal(false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : []));
744
738
  isTouched = signal(false, ...(ngDevMode ? [{ debugName: "isTouched" }] : []));
745
- readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : []));
746
- isBlocked = computed(() => this.isDisabled() || this.readonly(), ...(ngDevMode ? [{ debugName: "isBlocked" }] : []));
747
- // Texto que escribe el usuario (DD/MM/YYYY)
748
- inputTextValue = signal('', ...(ngDevMode ? [{ debugName: "inputTextValue" }] : []));
749
- // Navegación del calendario
750
- currentMonth = signal(new Date().getMonth(), ...(ngDevMode ? [{ debugName: "currentMonth" }] : []));
751
- currentYear = signal(new Date().getFullYear(), ...(ngDevMode ? [{ debugName: "currentYear" }] : []));
752
- // Hora en formato 24h (para el backend)
753
- selectedHour = signal(0, ...(ngDevMode ? [{ debugName: "selectedHour" }] : []));
754
- selectedMinute = signal(0, ...(ngDevMode ? [{ debugName: "selectedMinute" }] : []));
755
- // Estado AM/PM
756
- selectedAmPm = signal('AM', ...(ngDevMode ? [{ debugName: "selectedAmPm" }] : []));
757
- documentClickListener;
758
- /**
759
- * Valor que se muestra en el campo de texto.
760
- * Siempre muestra la fecha en formato DD/MM/YYYY.
761
- */
762
- displayValue = computed(() => {
763
- const text = this.inputTextValue().trim();
764
- if (text) {
765
- return text;
766
- }
767
- const date = this.selectedDate();
768
- if (!date)
769
- return '';
770
- const day = date.getDate().toString().padStart(2, '0');
771
- const month = (date.getMonth() + 1).toString().padStart(2, '0');
772
- const year = date.getFullYear();
773
- return `${day}/${month}/${year}`;
774
- }, ...(ngDevMode ? [{ debugName: "displayValue" }] : []));
775
- monthName = computed(() => {
776
- const months = [
777
- 'Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
778
- 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'
779
- ];
780
- return months[this.currentMonth()];
781
- }, ...(ngDevMode ? [{ debugName: "monthName" }] : []));
782
- calendarDays = computed(() => {
783
- const year = this.currentYear();
784
- const month = this.currentMonth();
785
- const firstDay = new Date(year, month, 1);
786
- const lastDay = new Date(year, month + 1, 0);
787
- const daysInMonth = lastDay.getDate();
788
- const startingDayOfWeek = firstDay.getDay();
789
- const days = [];
790
- // Días vacíos al inicio
791
- for (let i = 0; i < startingDayOfWeek; i++) {
792
- days.push(null);
793
- }
794
- // Días del mes
795
- for (let day = 1; day <= daysInMonth; day++) {
796
- days.push(day);
797
- }
798
- return days;
799
- }, ...(ngDevMode ? [{ debugName: "calendarDays" }] : []));
800
- // Horas en formato 12h
801
- hours12 = computed(() => {
802
- return Array.from({ length: 12 }, (_, i) => {
803
- const hour12 = i === 0 ? 12 : i;
804
- return {
805
- value: hour12,
806
- display: hour12.toString().padStart(2, '0')
807
- };
808
- });
809
- }, ...(ngDevMode ? [{ debugName: "hours12" }] : []));
810
- // Hora seleccionada en formato 12h
811
- selectedHour12 = computed(() => {
812
- const hour24 = this.selectedHour();
813
- if (hour24 === 0)
814
- return 12;
815
- if (hour24 > 12)
816
- return hour24 - 12;
817
- return hour24;
818
- }, ...(ngDevMode ? [{ debugName: "selectedHour12" }] : []));
819
- minutes = computed(() => Array.from({ length: 60 }, (_, i) => i), ...(ngDevMode ? [{ debugName: "minutes" }] : []));
820
- onChange = (value) => { };
739
+ // Máscara visual dinámica para la guía de fecha __/__/____
740
+ // Devuelve un arreglo de caracteres con flag "filled" para poder dar color distinto
741
+ inputMask = computed(() => {
742
+ const raw = this.inputTextValue() || '';
743
+ const numbersOnly = raw.replace(/\D/g, '');
744
+ const template = [
745
+ { char: 'd', filled: false },
746
+ { char: 'd', filled: false },
747
+ { char: '/', filled: false },
748
+ { char: 'm', filled: false },
749
+ { char: 'm', filled: false },
750
+ { char: '/', filled: false },
751
+ { char: 'y', filled: false },
752
+ { char: 'y', filled: false },
753
+ { char: 'y', filled: false },
754
+ { char: 'y', filled: false },
755
+ ];
756
+ let index = 0;
757
+ for (let i = 0; i < template.length && index < numbersOnly.length; i++) {
758
+ if (template[i].char === '/')
759
+ continue;
760
+ template[i] = { char: numbersOnly[index++], filled: true };
761
+ }
762
+ // Cuando se completa el segmento, el slash correspondiente pasa a "filled"
763
+ if (numbersOnly.length >= 2) {
764
+ template[2] = { char: '/', filled: true }; // después de DD
765
+ }
766
+ if (numbersOnly.length >= 4) {
767
+ template[5] = { char: '/', filled: true }; // después de MM
768
+ }
769
+ return template; // para usar en el template y colorear por carácter
770
+ }, ...(ngDevMode ? [{ debugName: "inputMask" }] : []));
771
+ clearTrigger = input(0, ...(ngDevMode ? [{ debugName: "clearTrigger" }] : []));
772
+ // Computed Properties based on active filter
773
+ activeFilter = computed(() => {
774
+ const type = this.activeFilterType();
775
+ return this.filters().find(f => f.value === type) || null;
776
+ }, ...(ngDevMode ? [{ debugName: "activeFilter" }] : []));
777
+ mode = computed(() => {
778
+ const filter = this.activeFilter();
779
+ return filter?.type === 'datetime' ? 'datetime' : 'date';
780
+ }, ...(ngDevMode ? [{ debugName: "mode" }] : []));
781
+ placeholder = computed(() => this.activeFilter()?.placeholder || 'Seleccionar fecha', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
782
+ minDate = computed(() => this.activeFilter()?.minDate || null, ...(ngDevMode ? [{ debugName: "minDate" }] : []));
783
+ maxDate = computed(() => this.activeFilter()?.maxDate || null, ...(ngDevMode ? [{ debugName: "maxDate" }] : []));
784
+ filterValue = computed(() => this.activeFilter()?.value || '', ...(ngDevMode ? [{ debugName: "filterValue" }] : []));
785
+ // Calendar Navigation
786
+ currentMonth = signal(new Date().getMonth(), ...(ngDevMode ? [{ debugName: "currentMonth" }] : []));
787
+ currentYear = signal(new Date().getFullYear(), ...(ngDevMode ? [{ debugName: "currentYear" }] : []));
788
+ // Time State
789
+ selectedHour = signal(0, ...(ngDevMode ? [{ debugName: "selectedHour" }] : []));
790
+ selectedMinute = signal(0, ...(ngDevMode ? [{ debugName: "selectedMinute" }] : []));
791
+ selectedAmPm = signal('AM', ...(ngDevMode ? [{ debugName: "selectedAmPm" }] : []));
792
+ documentClickListener;
793
+ onChange = () => { };
821
794
  onTouched = () => { };
822
795
  constructor(elementRef, ngZone) {
823
796
  this.elementRef = elementRef;
824
797
  this.ngZone = ngZone;
798
+ effect(() => {
799
+ const trigger = this.clearTrigger();
800
+ if (trigger > 0) {
801
+ this.clear();
802
+ }
803
+ });
825
804
  }
826
805
  ngOnDestroy() {
827
806
  this.removeDocumentListener();
828
807
  }
808
+ // ControlValueAccessor Implementation
829
809
  writeValue(value) {
830
810
  let date = null;
831
811
  if (value instanceof Date) {
832
812
  date = value;
833
813
  }
834
814
  else if (typeof value === 'string' && value) {
835
- // Manejar tanto fechas ISO como otros formatos de string
836
815
  const parsedDate = new Date(value);
837
816
  if (!isNaN(parsedDate.getTime())) {
838
817
  date = parsedDate;
@@ -854,24 +833,24 @@ class DateTimePicker {
854
833
  setDisabledState(isDisabled) {
855
834
  this.isDisabled.set(isDisabled);
856
835
  }
857
- toggle() {
858
- if (this.isBlocked())
836
+ // Public Methods
837
+ toggle(filterValue) {
838
+ if (this.isDisabled())
859
839
  return;
860
- this.markAsTouched();
861
- if (this.isOpen()) {
840
+ if (this.activeFilterType() === filterValue && this.isOpen()) {
862
841
  this.close();
863
842
  }
864
843
  else {
844
+ this.activeFilterType.set(filterValue);
865
845
  this.open();
866
846
  }
867
847
  }
868
848
  open() {
869
- if (this.isBlocked())
849
+ if (this.isDisabled())
870
850
  return;
871
851
  this.markAsTouched();
872
852
  this.isOpen.set(true);
873
853
  this.addDocumentListener();
874
- // Si hay fecha seleccionada, navegar a ese mes/año
875
854
  const selected = this.selectedDate();
876
855
  if (selected) {
877
856
  this.currentMonth.set(selected.getMonth());
@@ -882,9 +861,15 @@ class DateTimePicker {
882
861
  this.isOpen.set(false);
883
862
  this.removeDocumentListener();
884
863
  this.markAsTouched();
864
+ // Don't clear activeFilterType here to keep the chip active if needed,
865
+ // or clear it if you want the chip to look inactive when closed.
866
+ // For now, let's keep it active only if a date is selected?
867
+ // Or maybe we want to close the dropdown but keep the filter "selected" in UI?
868
+ // Let's just close the dropdown.
885
869
  }
870
+ // Calendar Logic
886
871
  selectDay(day) {
887
- if (!day || this.isBlocked())
872
+ if (!day || this.isDisabled())
888
873
  return;
889
874
  const newDate = new Date(this.currentYear(), this.currentMonth(), day, this.selectedHour(), this.selectedMinute());
890
875
  if (this.isDateDisabled(newDate))
@@ -893,160 +878,42 @@ class DateTimePicker {
893
878
  this.onChange(newDate.toISOString());
894
879
  this.markAsTouched();
895
880
  this.dateChange.emit(newDate);
896
- // Solo cerrar automáticamente si es modo 'date'
897
- if (this.mode() === 'date') {
898
- this.close();
899
- }
900
- }
901
- setHour12(hour12) {
902
- if (this.isBlocked())
903
- return;
904
- // Convertir de 12h a 24h
905
- let hour24;
906
- const amPm = this.selectedAmPm();
907
- if (hour12 === 12) {
908
- hour24 = amPm === 'AM' ? 0 : 12;
909
- }
910
- else {
911
- hour24 = amPm === 'AM' ? hour12 : hour12 + 12;
912
- }
913
- this.selectedHour.set(hour24);
914
- this.updateDateTime();
915
- }
916
- setMinute(minute) {
917
- if (this.isBlocked())
918
- return;
919
- this.selectedMinute.set(minute);
920
- this.updateDateTime();
921
- }
922
- setAmPm(amPm) {
923
- if (this.isBlocked())
924
- return;
925
- const currentHour24 = this.selectedHour();
926
- const currentHour12 = this.selectedHour12();
927
- let newHour24;
928
- if (amPm === 'AM') {
929
- newHour24 = currentHour12 === 12 ? 0 : currentHour12;
930
- }
931
- else {
932
- newHour24 = currentHour12 === 12 ? 12 : currentHour12 + 12;
933
- }
934
- this.selectedAmPm.set(amPm);
935
- this.selectedHour.set(newHour24);
936
- this.updateDateTime();
937
- }
938
- previousMonth() {
939
- const currentMonth = this.currentMonth();
940
- const currentYear = this.currentYear();
941
- if (currentMonth === 0) {
942
- this.currentMonth.set(11);
943
- this.currentYear.set(currentYear - 1);
944
- }
945
- else {
946
- this.currentMonth.set(currentMonth - 1);
947
- }
948
- }
949
- nextMonth() {
950
- const currentMonth = this.currentMonth();
951
- const currentYear = this.currentYear();
952
- if (currentMonth === 11) {
953
- this.currentMonth.set(0);
954
- this.currentYear.set(currentYear + 1);
955
- }
956
- else {
957
- this.currentMonth.set(currentMonth + 1);
958
- }
959
- }
960
- previousYear() {
961
- this.currentYear.set(this.currentYear() - 1);
962
- }
963
- nextYear() {
964
- this.currentYear.set(this.currentYear() + 1);
965
- }
966
- today() {
967
- const today = new Date();
968
- this.updateInternalState(today);
969
- this.onChange(today.toISOString());
970
- this.markAsTouched();
971
- this.dateChange.emit(today);
881
+ this.dateSelected.emit({
882
+ filter: this.filterValue(),
883
+ value: newDate,
884
+ });
972
885
  if (this.mode() === 'date') {
973
886
  this.close();
974
887
  }
975
888
  }
976
- clear() {
977
- this.resetInternalState();
978
- this.onChange(null);
979
- this.markAsTouched();
980
- this.dateChange.emit(null);
981
- this.close();
982
- }
983
- onKeyDown(event) {
984
- if (this.isBlocked())
985
- return;
986
- if (event.key === 'Escape') {
987
- this.close();
988
- }
989
- else if (event.key === 'Tab') {
990
- this.markAsTouched();
991
- this.close();
889
+ // ... (Rest of the helper methods like previousMonth, nextMonth, etc. remain largely the same)
890
+ displayValue = computed(() => {
891
+ const date = this.selectedDate();
892
+ if (!date)
893
+ return '';
894
+ const options = {
895
+ day: '2-digit',
896
+ month: '2-digit',
897
+ year: 'numeric',
898
+ };
899
+ if (this.mode() === 'datetime') {
900
+ options.hour = '2-digit';
901
+ options.minute = '2-digit';
902
+ options.hour12 = true;
992
903
  }
993
- }
994
- isDaySelected(day) {
995
- if (!day)
996
- return false;
997
- const selected = this.selectedDate();
998
- if (!selected)
999
- return false;
1000
- return (selected.getDate() === day &&
1001
- selected.getMonth() === this.currentMonth() &&
1002
- selected.getFullYear() === this.currentYear());
1003
- }
1004
- isToday(day) {
1005
- if (!day)
1006
- return false;
1007
- const today = new Date();
1008
- return (today.getDate() === day &&
1009
- today.getMonth() === this.currentMonth() &&
1010
- today.getFullYear() === this.currentYear());
1011
- }
1012
- isDayDisabled(day) {
1013
- if (!day)
1014
- return true;
1015
- const date = new Date(this.currentYear(), this.currentMonth(), day);
1016
- return this.isDateDisabled(date);
1017
- }
1018
- isDateDisabled(date) {
1019
- const minDate = this.minDate();
1020
- const maxDate = this.maxDate();
1021
- if (minDate && date < minDate)
1022
- return true;
1023
- if (maxDate && date > maxDate)
1024
- return true;
1025
- return false;
1026
- }
1027
- updateDateTime() {
1028
- const selected = this.selectedDate();
1029
- if (!selected)
1030
- return;
1031
- const newDate = new Date(selected);
1032
- newDate.setHours(this.selectedHour());
1033
- newDate.setMinutes(this.selectedMinute());
1034
- this.updateInternalState(newDate);
1035
- this.onChange(newDate.toISOString());
1036
- this.markAsTouched();
1037
- this.dateChange.emit(newDate);
1038
- }
1039
- // Manejo de input de texto (DD/MM/YYYY)
1040
- onInputChange(event) {
1041
- if (this.isBlocked())
904
+ return date.toLocaleDateString('es-ES', options);
905
+ }, ...(ngDevMode ? [{ debugName: "displayValue" }] : []));
906
+ // Input text handling
907
+ onInputChange(event, filterValue) {
908
+ if (this.isDisabled())
1042
909
  return;
1043
910
  const input = event.target;
1044
911
  let value = input.value;
1045
- // Eliminar todo lo que no sea número
912
+ // Remove all non-numeric characters
1046
913
  const numbersOnly = value.replace(/\D/g, '');
1047
- // Limitar a 8 dígitos (DDMMYYYY)
914
+ // Limit to 8 digits (DD/MM/YYYY)
1048
915
  const limitedNumbers = numbersOnly.slice(0, 8);
1049
- // Formatear con barras: DD/MM/YYYY
916
+ // Format with slashes: DD/MM/YYYY
1050
917
  let formatted = '';
1051
918
  if (limitedNumbers.length > 0) {
1052
919
  formatted = limitedNumbers.slice(0, 2);
@@ -1057,44 +924,53 @@ class DateTimePicker {
1057
924
  formatted += '/' + limitedNumbers.slice(4, 8);
1058
925
  }
1059
926
  }
927
+ // Update the input value
1060
928
  this.inputTextValue.set(formatted);
1061
929
  input.value = formatted;
1062
930
  this.markAsTouched();
1063
- // Solo intentamos parsear cuando tenemos DD/MM/YYYY completo (10 caracteres)
931
+ // Only parse when we have a complete date (DD/MM/YYYY = 10 characters)
1064
932
  if (formatted.length === 10) {
1065
933
  const parsedDate = this.parseDateInput(formatted);
1066
934
  if (parsedDate) {
1067
935
  if (this.isDateDisabled(parsedDate)) {
1068
- // Está fuera de rango, dejamos el texto pero no cambiamos el valor
936
+ // Invalid date (out of range), but keep the text
1069
937
  return;
1070
938
  }
1071
939
  this.updateInternalState(parsedDate);
1072
940
  this.onChange(parsedDate.toISOString());
1073
941
  this.dateChange.emit(parsedDate);
942
+ this.dateSelected.emit({
943
+ filter: filterValue,
944
+ value: parsedDate,
945
+ });
1074
946
  }
1075
947
  }
1076
948
  else if (formatted.trim() === '') {
1077
- // Si el campo queda vacío, limpiamos el valor
949
+ // Clear if input is empty
1078
950
  this.resetInternalState();
1079
951
  this.onChange(null);
1080
952
  this.dateChange.emit(null);
1081
953
  }
1082
954
  }
1083
- onInputFocus() {
1084
- if (this.isBlocked())
955
+ onInputFocus(filterValue) {
956
+ if (this.isDisabled())
1085
957
  return;
958
+ this.activeFilterType.set(filterValue);
1086
959
  this.open();
1087
960
  }
1088
961
  parseDateInput(input) {
1089
962
  if (!input || input.trim() === '')
1090
963
  return null;
964
+ // Only accept DD/MM/YYYY format
1091
965
  const match = input.trim().match(/^(\d{2})\/(\d{2})\/(\d{4})$/);
1092
966
  if (match) {
1093
967
  const day = parseInt(match[1], 10);
1094
968
  const month = parseInt(match[2], 10) - 1;
1095
969
  const year = parseInt(match[3], 10);
970
+ // Validate date
1096
971
  if (day >= 1 && day <= 31 && month >= 0 && month <= 11 && year >= 1900 && year <= 2100) {
1097
972
  const date = new Date(year, month, day);
973
+ // Check if date is valid (handles invalid dates like 31/02/2024)
1098
974
  if (date.getDate() === day && date.getMonth() === month && date.getFullYear() === year) {
1099
975
  return date;
1100
976
  }
@@ -1102,12 +978,46 @@ class DateTimePicker {
1102
978
  }
1103
979
  return null;
1104
980
  }
1105
- formatDateForInput(date) {
1106
- const day = date.getDate().toString().padStart(2, '0');
1107
- const month = (date.getMonth() + 1).toString().padStart(2, '0');
1108
- const year = date.getFullYear();
1109
- return `${day}/${month}/${year}`;
1110
- }
981
+ monthName = computed(() => {
982
+ const months = [
983
+ 'Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
984
+ 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'
985
+ ];
986
+ return months[this.currentMonth()];
987
+ }, ...(ngDevMode ? [{ debugName: "monthName" }] : []));
988
+ calendarDays = computed(() => {
989
+ const year = this.currentYear();
990
+ const month = this.currentMonth();
991
+ const firstDay = new Date(year, month, 1);
992
+ const lastDay = new Date(year, month + 1, 0);
993
+ const daysInMonth = lastDay.getDate();
994
+ const startingDayOfWeek = firstDay.getDay();
995
+ const days = [];
996
+ for (let i = 0; i < startingDayOfWeek; i++)
997
+ days.push(null);
998
+ for (let day = 1; day <= daysInMonth; day++)
999
+ days.push(day);
1000
+ return days;
1001
+ }, ...(ngDevMode ? [{ debugName: "calendarDays" }] : []));
1002
+ hours12 = computed(() => {
1003
+ return Array.from({ length: 12 }, (_, i) => {
1004
+ const hour12 = i === 0 ? 12 : i;
1005
+ return {
1006
+ value: hour12,
1007
+ display: hour12.toString().padStart(2, '0')
1008
+ };
1009
+ });
1010
+ }, ...(ngDevMode ? [{ debugName: "hours12" }] : []));
1011
+ selectedHour12 = computed(() => {
1012
+ const hour24 = this.selectedHour();
1013
+ if (hour24 === 0)
1014
+ return 12;
1015
+ if (hour24 > 12)
1016
+ return hour24 - 12;
1017
+ return hour24;
1018
+ }, ...(ngDevMode ? [{ debugName: "selectedHour12" }] : []));
1019
+ minutes = computed(() => Array.from({ length: 60 }, (_, i) => i), ...(ngDevMode ? [{ debugName: "minutes" }] : []));
1020
+ // Helper methods
1111
1021
  updateInternalState(date) {
1112
1022
  this.selectedDate.set(date);
1113
1023
  this.currentMonth.set(date.getMonth());
@@ -1115,6 +1025,7 @@ class DateTimePicker {
1115
1025
  this.selectedHour.set(date.getHours());
1116
1026
  this.selectedMinute.set(date.getMinutes());
1117
1027
  this.selectedAmPm.set(date.getHours() >= 12 ? 'PM' : 'AM');
1028
+ // Update input text value to match the formatted date
1118
1029
  const formatted = this.formatDateForInput(date);
1119
1030
  this.inputTextValue.set(formatted);
1120
1031
  }
@@ -1125,6 +1036,12 @@ class DateTimePicker {
1125
1036
  this.selectedMinute.set(0);
1126
1037
  this.selectedAmPm.set('AM');
1127
1038
  }
1039
+ formatDateForInput(date) {
1040
+ const day = date.getDate().toString().padStart(2, '0');
1041
+ const month = (date.getMonth() + 1).toString().padStart(2, '0');
1042
+ const year = date.getFullYear();
1043
+ return `${day}/${month}/${year}`;
1044
+ }
1128
1045
  markAsTouched() {
1129
1046
  if (!this.isTouched()) {
1130
1047
  this.isTouched.set(true);
@@ -1132,9 +1049,8 @@ class DateTimePicker {
1132
1049
  }
1133
1050
  }
1134
1051
  addDocumentListener() {
1135
- if (this.documentClickListener) {
1052
+ if (this.documentClickListener)
1136
1053
  this.removeDocumentListener();
1137
- }
1138
1054
  this.ngZone.runOutsideAngular(() => {
1139
1055
  this.documentClickListener = (event) => {
1140
1056
  const target = event.target;
@@ -1147,9 +1063,7 @@ class DateTimePicker {
1147
1063
  });
1148
1064
  }
1149
1065
  };
1150
- setTimeout(() => {
1151
- document.addEventListener('click', this.documentClickListener, true);
1152
- }, 10);
1066
+ setTimeout(() => document.addEventListener('click', this.documentClickListener, true), 10);
1153
1067
  });
1154
1068
  }
1155
1069
  removeDocumentListener() {
@@ -1158,52 +1072,137 @@ class DateTimePicker {
1158
1072
  this.documentClickListener = undefined;
1159
1073
  }
1160
1074
  }
1161
- markTouched() {
1162
- this.markAsTouched();
1163
- }
1164
- /**
1165
- * Obtiene la fecha seleccionada en formato ISO string
1166
- * @returns string ISO o null si no hay fecha seleccionada
1167
- */
1168
- getISOString() {
1169
- const date = this.selectedDate();
1170
- return date ? date.toISOString() : null;
1075
+ // Navigation methods
1076
+ previousMonth() {
1077
+ const currentMonth = this.currentMonth();
1078
+ const currentYear = this.currentYear();
1079
+ if (currentMonth === 0) {
1080
+ this.currentMonth.set(11);
1081
+ this.currentYear.set(currentYear - 1);
1082
+ }
1083
+ else {
1084
+ this.currentMonth.set(currentMonth - 1);
1085
+ }
1171
1086
  }
1172
- /**
1173
- * Establece la fecha desde un string ISO
1174
- * @param isoString - Fecha en formato ISO
1175
- */
1176
- setFromISOString(isoString) {
1177
- if (isoString) {
1178
- const date = new Date(isoString);
1179
- if (!isNaN(date.getTime())) {
1180
- this.writeValue(date);
1181
- this.onChange(isoString);
1182
- }
1087
+ nextMonth() {
1088
+ const currentMonth = this.currentMonth();
1089
+ const currentYear = this.currentYear();
1090
+ if (currentMonth === 11) {
1091
+ this.currentMonth.set(0);
1092
+ this.currentYear.set(currentYear + 1);
1183
1093
  }
1184
1094
  else {
1185
- this.clear();
1095
+ this.currentMonth.set(currentMonth + 1);
1186
1096
  }
1187
1097
  }
1188
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DateTimePicker, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
1189
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DateTimePicker, isStandalone: true, selector: "lib-date-time-picker", inputs: { mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dateChange: "dateChange" }, providers: [
1098
+ previousYear() { this.currentYear.set(this.currentYear() - 1); }
1099
+ nextYear() { this.currentYear.set(this.currentYear() + 1); }
1100
+ today() {
1101
+ const today = new Date();
1102
+ this.updateInternalState(today);
1103
+ this.onChange(today.toISOString());
1104
+ this.markAsTouched();
1105
+ this.dateChange.emit(today);
1106
+ this.dateSelected.emit({ filter: this.filterValue(), value: today });
1107
+ if (this.mode() === 'date')
1108
+ this.close();
1109
+ }
1110
+ clear() {
1111
+ this.resetInternalState();
1112
+ this.onChange(null);
1113
+ this.markAsTouched();
1114
+ this.dateChange.emit(null);
1115
+ this.close();
1116
+ }
1117
+ // Time setters
1118
+ setHour12(hour12) {
1119
+ if (this.isDisabled())
1120
+ return;
1121
+ const amPm = this.selectedAmPm();
1122
+ const hour24 = hour12 === 12 ? (amPm === 'AM' ? 0 : 12) : (amPm === 'AM' ? hour12 : hour12 + 12);
1123
+ this.selectedHour.set(hour24);
1124
+ this.updateDateTime();
1125
+ }
1126
+ setMinute(minute) {
1127
+ if (this.isDisabled())
1128
+ return;
1129
+ this.selectedMinute.set(minute);
1130
+ this.updateDateTime();
1131
+ }
1132
+ setAmPm(amPm) {
1133
+ if (this.isDisabled())
1134
+ return;
1135
+ const currentHour12 = this.selectedHour12();
1136
+ const newHour24 = amPm === 'AM' ? (currentHour12 === 12 ? 0 : currentHour12) : (currentHour12 === 12 ? 12 : currentHour12 + 12);
1137
+ this.selectedAmPm.set(amPm);
1138
+ this.selectedHour.set(newHour24);
1139
+ this.updateDateTime();
1140
+ }
1141
+ updateDateTime() {
1142
+ const selected = this.selectedDate();
1143
+ if (!selected)
1144
+ return;
1145
+ const newDate = new Date(selected);
1146
+ newDate.setHours(this.selectedHour());
1147
+ newDate.setMinutes(this.selectedMinute());
1148
+ this.selectedDate.set(newDate);
1149
+ // Update input text value
1150
+ const formatted = this.formatDateForInput(newDate);
1151
+ this.inputTextValue.set(formatted);
1152
+ this.onChange(newDate.toISOString());
1153
+ this.markAsTouched();
1154
+ this.dateChange.emit(newDate);
1155
+ this.dateSelected.emit({
1156
+ filter: this.filterValue(),
1157
+ value: newDate,
1158
+ });
1159
+ }
1160
+ // Validation helpers
1161
+ isDaySelected(day) {
1162
+ if (!day)
1163
+ return false;
1164
+ const selected = this.selectedDate();
1165
+ return !!selected && selected.getDate() === day && selected.getMonth() === this.currentMonth() && selected.getFullYear() === this.currentYear();
1166
+ }
1167
+ isToday(day) {
1168
+ if (!day)
1169
+ return false;
1170
+ const today = new Date();
1171
+ return today.getDate() === day && today.getMonth() === this.currentMonth() && today.getFullYear() === this.currentYear();
1172
+ }
1173
+ isDayDisabled(day) {
1174
+ if (!day)
1175
+ return true;
1176
+ return this.isDateDisabled(new Date(this.currentYear(), this.currentMonth(), day));
1177
+ }
1178
+ isDateDisabled(date) {
1179
+ const minDate = this.minDate();
1180
+ const maxDate = this.maxDate();
1181
+ if (minDate && date < minDate)
1182
+ return true;
1183
+ if (maxDate && date > maxDate)
1184
+ return true;
1185
+ return false;
1186
+ }
1187
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DateTimeFilter, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
1188
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DateTimeFilter, isStandalone: true, selector: "lib-date-time-filter", inputs: { filters: { classPropertyName: "filters", publicName: "filters", isSignal: true, isRequired: false, transformFunction: null }, clearTrigger: { classPropertyName: "clearTrigger", publicName: "clearTrigger", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dateSelected: "dateSelected", dateChange: "dateChange" }, providers: [
1190
1189
  {
1191
1190
  provide: NG_VALUE_ACCESSOR,
1192
- useExisting: forwardRef(() => DateTimePicker),
1191
+ useExisting: forwardRef(() => DateTimeFilter),
1193
1192
  multi: true,
1194
1193
  },
1195
- ], ngImport: i0, template: "<div class=\"datetime-container\">\r\n <div\r\n class=\"datetime-header\"\r\n [class.active]=\"isOpen()\"\r\n [class.disabled]=\"isBlocked()\"\r\n [class.readonly]=\"isBlocked()\"\r\n (click)=\"!isBlocked() && toggle()\"\r\n (keydown)=\"!isBlocked() && onKeyDown($event)\"\r\n tabindex=\"0\"\r\n >\r\n <input\r\n type=\"text\"\r\n class=\"datetime-input\"\r\n [value]=\"displayValue()\"\r\n [placeholder]=\"placeholder()\"\r\n (input)=\"onInputChange($event)\"\r\n (focus)=\"!isBlocked() && onInputFocus()\"\r\n (click)=\"$event.stopPropagation()\"\r\n [disabled]=\"isDisabled()\"\r\n [readOnly]=\"readonly()\"\r\n />\r\n\r\n <div class=\"header-icons\">\r\n @if (selectedDate()) {\r\n <span\r\n class=\"clear-icon\"\r\n (click)=\"!isBlocked() && clear(); $event.stopPropagation()\"\r\n title=\"Limpiar\"\r\n >\r\n \u00D7\r\n </span>\r\n }\r\n <span class=\"arrow\" [class.open]=\"isOpen()\"></span>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n@if (isOpen()) {\r\n<div class=\"dropdown\">\r\n <div class=\"datetime-content\">\r\n <!-- Secci\u00F3n del calendario -->\r\n <div class=\"calendar-section\">\r\n <!-- Navegaci\u00F3n del calendario -->\r\n <div class=\"calendar-nav\">\r\n <div class=\"nav-section\">\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"previousYear()\"\r\n title=\"A\u00F1o anterior\"\r\n >\r\n \u2039\u2039\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"previousMonth()\"\r\n title=\"Mes anterior\"\r\n >\r\n \u2039\r\n </button>\r\n </div>\r\n\r\n <div class=\"current-date\">{{ monthName() }} {{ currentYear() }}</div>\r\n\r\n <div class=\"nav-section\">\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"nextMonth()\"\r\n title=\"Siguiente mes\"\r\n >\r\n \u203A\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"nextYear()\"\r\n title=\"Siguiente a\u00F1o\"\r\n >\r\n \u203A\u203A\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- D\u00EDas de la semana -->\r\n <div class=\"weekdays\">\r\n <div class=\"weekday\">Dom</div>\r\n <div class=\"weekday\">Lun</div>\r\n <div class=\"weekday\">Mar</div>\r\n <div class=\"weekday\">Mi\u00E9</div>\r\n <div class=\"weekday\">Jue</div>\r\n <div class=\"weekday\">Vie</div>\r\n <div class=\"weekday\">S\u00E1b</div>\r\n </div>\r\n\r\n <!-- D\u00EDas del mes -->\r\n <div class=\"calendar-grid\">\r\n @for (day of calendarDays(); track $index) {\r\n <div\r\n class=\"calendar-day\"\r\n [class.selected]=\"isDaySelected(day)\"\r\n [class.today]=\"isToday(day)\"\r\n [class.disabled]=\"isDayDisabled(day)\"\r\n [class.empty]=\"!day\"\r\n (click)=\"selectDay(day)\"\r\n >\r\n {{ day || '' }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- Selector de tiempo (solo si mode === 'datetime') -->\r\n @if (mode() === 'datetime') {\r\n <div class=\"time-section\">\r\n <div class=\"time-header\">Horario</div>\r\n\r\n <div class=\"time-selectors\">\r\n <div class=\"time-group\">\r\n <div class=\"time-column\">\r\n <div class=\"time-label\">Hora</div>\r\n <div class=\"time-scroll\">\r\n @for (hour of hours12(); track hour.value) {\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"hour.value === selectedHour12()\"\r\n (click)=\"setHour12(hour.value)\"\r\n >\r\n {{ hour.display }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"time-separator-vertical\">:</div>\r\n\r\n <div class=\"time-column\">\r\n <div class=\"time-label\">Min</div>\r\n <div class=\"time-scroll\">\r\n @for (minute of minutes(); track minute) {\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"minute === selectedMinute()\"\r\n (click)=\"setMinute(minute)\"\r\n >\r\n {{ minute.toString().padStart(2, '0') }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"time-column\">\r\n <div class=\"time-label\">AM/PM</div>\r\n <div class=\"time-scroll ampm\">\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"selectedAmPm() === 'AM'\"\r\n (click)=\"setAmPm('AM')\"\r\n >\r\n AM\r\n </div>\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"selectedAmPm() === 'PM'\"\r\n (click)=\"setAmPm('PM')\"\r\n >\r\n PM\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Botones de acci\u00F3n -->\r\n <div class=\"action-buttons\">\r\n <button type=\"button\" class=\"action-btn secondary\" (click)=\"today()\">\r\n Hoy\r\n </button>\r\n @if (mode() === 'datetime') {\r\n <button type=\"button\" class=\"action-btn primary\" (click)=\"close()\">\r\n Aceptar\r\n </button>\r\n }\r\n </div>\r\n</div>\r\n}\r\n", styles: [".datetime-container{position:relative;width:100%}.datetime-header{width:100%;border:1px solid #787861;border-radius:5px;padding:12px 15px;background-color:transparent;cursor:pointer;display:flex;justify-content:space-between;align-items:center;min-height:auto;transition:border-color .2s}.datetime-input{flex:1;border:none;outline:none;background:transparent;font-size:1.3rem;color:#454733;padding:0;margin:0}.datetime-input::placeholder{color:#787861}.datetime-input:disabled{cursor:not-allowed}.datetime-header:hover,.datetime-header:focus{outline:none;border-color:#a9a97f}.datetime-header.active{border-color:#a9a97f;outline:none}.datetime-header.disabled,.datetime-header.readonly{pointer-events:none;opacity:.6;cursor:not-allowed}.selected-text{color:#454733;font-size:1.3rem;flex:1}.selected-text.placeholder{color:#787861}.header-icons{display:flex;align-items:center;gap:8px}.clear-icon{width:20px;height:20px;display:flex;align-items:center;justify-content:center;color:#787861;font-size:1.5rem;cursor:pointer;border-radius:50%;transition:all .2s}.clear-icon:hover{background-color:#7878611a;color:#454733}.arrow{width:20px;height:20px;background-image:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='icon icon-tabler icons-tabler-outline icon-tabler-calendar-event'%3e%3cpath stroke='none' d='M0 0h24v24H0z' fill='none'/%3e%3cpath d='M4 5m0 2a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2z' /%3e%3cpath d='M16 3l0 4' /%3e%3cpath d='M8 3l0 4' /%3e%3cpath d='M4 11l16 0' /%3e%3cpath d='M8 15h2v2h-2z' /%3e%3c/svg%3e\");background-repeat:no-repeat;background-size:20px;background-position:center;color:#787861;flex-shrink:0;transition:transform .2s}.arrow.open{background-image:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='currentColor' class='icon icon-tabler icons-tabler-filled icon-tabler-calendar-event'%3e%3cpath stroke='none' d='M0 0h24v24H0z' fill='none'/%3e%3cpath d='M16 2a1 1 0 0 1 .993 .883l.007 .117v1h1a3 3 0 0 1 2.995 2.824l.005 .176v12a3 3 0 0 1 -2.824 2.995l-.176 .005h-12a3 3 0 0 1 -2.995 -2.824l-.005 -.176v-12a3 3 0 0 1 2.824 -2.995l.176 -.005h1v-1a1 1 0 0 1 1.993 -.117l.007 .117v1h6v-1a1 1 0 0 1 1 -1m3 7h-14v9.625c0 .705 .386 1.286 .883 1.366l.117 .009h12c.513 0 .936 -.53 .993 -1.215l.007 -.16z' /%3e%3cpath d='M8 14h2v2h-2z' /%3e%3c/svg%3e\")}.dropdown{position:absolute;top:100%;left:0;right:0;background:#e3e3d1;border:1px solid #787861;border-top:none;border-radius:0 0 5px 5px;z-index:1000;box-shadow:0 4px 12px #00000026;min-width:400px}.datetime-content{display:flex}.calendar-section{flex:1;min-width:280px}.calendar-nav{display:flex;justify-content:space-between;align-items:center;padding:15px;border-bottom:1px solid rgba(120,120,97,.2)}.nav-section{display:flex;gap:5px}.nav-btn{background:none;border:none;color:#787861;cursor:pointer;font-size:1.2rem;padding:5px 10px;border-radius:3px;transition:all .2s}.nav-btn:hover{background-color:#a9a97f1a;color:#454733}.current-date{font-weight:500;color:#454733;font-size:1.1rem}.weekdays{display:grid;grid-template-columns:repeat(7,1fr);background:#7878611a}.weekday{padding:10px 5px;text-align:center;font-size:.9rem;font-weight:500;color:#787861}.calendar-grid{display:grid;grid-template-columns:repeat(7,1fr)}.calendar-day{padding:12px 5px;text-align:center;cursor:pointer;color:#454733;font-size:1rem;border-right:1px solid rgba(120,120,97,.1);border-bottom:1px solid rgba(120,120,97,.1);transition:all .2s}.calendar-day:hover:not(.disabled):not(.empty){background-color:#a9a97f33}.calendar-day.selected{background-color:#a9a97f;color:#e3e3d1;font-weight:500}.calendar-day.today:not(.selected){background-color:#a9a97f4d;font-weight:500}.calendar-day.disabled{color:#78786166;cursor:not-allowed}.calendar-day.empty{cursor:default}.calendar-day:nth-child(7n){border-right:none}.time-section{border-left:1px solid rgba(120,120,97,.2);min-width:140px;display:flex;flex-direction:column;background:#a9a97f0d}.time-header{padding:15px;border-bottom:1px solid rgba(120,120,97,.2);text-align:center;font-weight:500;color:#454733;background:#a9a97f1a}.time-selectors{display:flex;flex-direction:column;padding:15px;gap:20px;flex:1}.time-group{display:flex;align-items:center;gap:10px}.time-column{flex:1;display:flex;flex-direction:column;align-items:center}.time-label{font-size:.9rem;color:#787861;margin-bottom:10px;font-weight:500}.time-scroll{max-height:150px;overflow-y:auto;border:1px solid rgba(120,120,97,.2);border-radius:3px;width:50px;background:#a9a97f}.time-option{padding:8px 12px;text-align:center;cursor:pointer;color:#454733;font-size:1rem;transition:all .2s}.time-option:hover{background-color:#a9a97f1a}.time-option.selected{background-color:#a9a97f;color:#e3e3d1;font-weight:500}.time-separator-vertical{font-size:1.5rem;color:#787861;font-weight:700;align-self:flex-end;margin-bottom:10px}.time-scroll::-webkit-scrollbar{width:4px}.time-scroll::-webkit-scrollbar-track{background:#7878611a}.time-scroll::-webkit-scrollbar-thumb{background:#787861;border-radius:2px}.time-scroll::-webkit-scrollbar-thumb:hover{background:#a9a97f}.action-buttons{display:flex;justify-content:space-between;padding:15px;border-top:1px solid rgba(120,120,97,.2);gap:10px}.action-btn{padding:10px 20px;border:none;border-radius:3px;cursor:pointer;font-size:1rem;transition:all .2s}.action-btn.secondary{background:transparent;color:#787861;border:1px solid #787861}.action-btn.secondary:hover{background:#7878611a;color:#454733}.action-btn.primary{background:#a9a97f;color:#e3e3d1;border:1px solid #a9a97f}.action-btn.primary:hover{background:#969669;border-color:#969669}@media (max-width: 768px){.dropdown{min-width:320px}.datetime-content{flex-direction:column}.time-section{border-left:none;border-top:1px solid rgba(120,120,97,.2)}.time-selectors{flex-direction:row;justify-content:center;padding:15px}.time-group{gap:15px}.datetime-header{padding:10px 15px}.calendar-nav{padding:12px}.calendar-day{padding:10px 3px;font-size:.9rem}.action-buttons{padding:12px}}@media (max-width: 480px){.dropdown{min-width:280px}.time-section{min-width:auto}.time-scroll{width:45px}.time-selectors{padding:10px}}\n"] });
1194
+ ], ngImport: i0, template: "<div class=\"datetime-container\">\r\n <div class=\"filter-chips\">\r\n @for (item of filters(); track item.value) {\r\n <div\r\n class=\"chip-input-wrapper\"\r\n [class.has-value]=\"selectedDate() || inputTextValue()\"\r\n [class.active]=\"activeFilterType() === item.value\"\r\n >\r\n <!-- Etiqueta flotante -->\r\n <label class=\"floating-label\">{{ item.placeholder || item.label || 'dd/mm/aaaa' }}</label>\r\n\r\n <!-- M\u00E1scara de gu\u00EDa de fecha din\u00E1mica (__/__/____) -->\r\n <div class=\"chip-input-mask\">\r\n @for (part of inputMask(); track $index) {\r\n <span\r\n class=\"mask-char\"\r\n [class.mask-char-filled]=\"part.filled\"\r\n [class.mask-char-placeholder]=\"!part.filled\"\r\n >\r\n {{ part.char }}\r\n </span>\r\n }\r\n </div>\r\n\r\n <input\r\n type=\"text\"\r\n [value]=\"inputTextValue()\"\r\n (input)=\"onInputChange($event, item.value)\"\r\n (focus)=\"onInputFocus(item.value)\"\r\n [placeholder]=\"''\"\r\n class=\"chip-input\"\r\n [disabled]=\"isDisabled()\"\r\n />\r\n\r\n <button\r\n type=\"button\"\r\n class=\"calendar-icon-button\"\r\n (click)=\"toggle(item.value)\"\r\n title=\"Abrir calendario\"\r\n >\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n width=\"18\"\r\n height=\"18\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n class=\"icon icon-tabler icons-tabler-outline icon-tabler-calendar-event\"\r\n >\r\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\" />\r\n <path\r\n d=\"M4 5m0 2a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2z\"\r\n />\r\n <path d=\"M16 3l0 4\" />\r\n <path d=\"M8 3l0 4\" />\r\n <path d=\"M4 11l16 0\" />\r\n <path d=\"M8 15h2v2h-2z\" />\r\n </svg>\r\n </button>\r\n\r\n @if (isOpen() && activeFilterType() === item.value) {\r\n <div class=\"dropdown\">\r\n <div class=\"datetime-content\">\r\n <!-- Secci\u00F3n del calendario -->\r\n <div class=\"calendar-section\">\r\n <!-- Navegaci\u00F3n -->\r\n <div class=\"calendar-nav\">\r\n <div class=\"nav-section\">\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"previousYear()\"\r\n title=\"A\u00F1o anterior\"\r\n >\r\n \u2039\u2039\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"previousMonth()\"\r\n title=\"Mes anterior\"\r\n >\r\n \u2039\r\n </button>\r\n </div>\r\n\r\n <div class=\"current-date\">\r\n {{ monthName() }} {{ currentYear() }}\r\n </div>\r\n\r\n <div class=\"nav-section\">\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"nextMonth()\"\r\n title=\"Siguiente mes\"\r\n >\r\n \u203A\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"nextYear()\"\r\n title=\"Siguiente a\u00F1o\"\r\n >\r\n \u203A\u203A\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- D\u00EDas de la semana -->\r\n <div class=\"weekdays\">\r\n <div class=\"weekday\">Dom</div>\r\n <div class=\"weekday\">Lun</div>\r\n <div class=\"weekday\">Mar</div>\r\n <div class=\"weekday\">Mi\u00E9</div>\r\n <div class=\"weekday\">Jue</div>\r\n <div class=\"weekday\">Vie</div>\r\n <div class=\"weekday\">S\u00E1b</div>\r\n </div>\r\n\r\n <!-- D\u00EDas -->\r\n <div class=\"calendar-grid\">\r\n @for (day of calendarDays(); track $index) {\r\n <div\r\n class=\"calendar-day\"\r\n [class.selected]=\"isDaySelected(day)\"\r\n [class.today]=\"isToday(day)\"\r\n [class.disabled]=\"isDayDisabled(day)\"\r\n [class.empty]=\"!day\"\r\n (click)=\"selectDay(day)\"\r\n >\r\n {{ day || \"\" }}\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- TIME PICKER -->\r\n @if (mode() === 'datetime') {\r\n <div class=\"time-section\">\r\n <div class=\"time-header\">Horario</div>\r\n\r\n <div class=\"time-selectors\">\r\n <div class=\"time-group\">\r\n <div class=\"time-column\">\r\n <div class=\"time-label\">Hora</div>\r\n <div class=\"time-scroll\">\r\n @for (hour of hours12(); track hour.value) {\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"hour.value === selectedHour12()\"\r\n (click)=\"setHour12(hour.value)\"\r\n >\r\n {{ hour.display }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"time-separator-vertical\">:</div>\r\n\r\n <div class=\"time-column\">\r\n <div class=\"time-label\">Min</div>\r\n <div class=\"time-scroll\">\r\n @for (minute of minutes(); track minute) {\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"minute === selectedMinute()\"\r\n (click)=\"setMinute(minute)\"\r\n >\r\n {{ minute.toString().padStart(2, \"0\") }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"time-column\">\r\n <div class=\"time-label\">AM/PM</div>\r\n <div class=\"time-scroll ampm\">\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"selectedAmPm() === 'AM'\"\r\n (click)=\"setAmPm('AM')\"\r\n >\r\n AM\r\n </div>\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"selectedAmPm() === 'PM'\"\r\n (click)=\"setAmPm('PM')\"\r\n >\r\n PM\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- botones -->\r\n <div class=\"action-buttons\">\r\n <button type=\"button\" class=\"action-btn secondary\" (click)=\"today()\">\r\n Hoy\r\n </button>\r\n\r\n @if (mode() === 'datetime') {\r\n <button type=\"button\" class=\"action-btn primary\" (click)=\"close()\">\r\n Aceptar\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n", styles: [".datetime-container{position:relative;width:100%}.filter-chips{display:flex;gap:10px;padding:8px;border-radius:12px;position:relative}.chip-input-wrapper{position:relative;display:flex;align-items:center;border-radius:8px;border-style:solid;border-color:var(--schemes-outline-variant, #c0c7cd);border-width:1px;height:32px;flex-shrink:0;transition:.2s ease;background-color:transparent}.chip-input-wrapper:hover{background-color:#ececcf}.chip-input-wrapper:focus-within,.chip-input-wrapper.active{color:var(--on-surface, #171c1f);border-color:#b6b69b}.floating-label{position:absolute;left:12px;top:-8px;color:var(--schemes-on-surface-variant, #454733);font-family:var( --theme-label-large-font-family, \"Roboto-Medium\", sans-serif );font-size:11px;line-height:12px;letter-spacing:var(--theme-label-large-letter-spacing, .1px);font-weight:var(--theme-label-large-font-weight, 500);opacity:0;pointer-events:none;transition:all .2s ease;z-index:2;background-color:#ebeccf;padding:0 4px;border-radius:2px}.chip-input-wrapper.has-value .floating-label{opacity:.6}.chip-input{border:none;outline:none;background:transparent;padding:6px 40px 6px 16px;height:100%;width:100%;color:transparent;caret-color:var(--schemes-on-surface-variant, #454733);font-family:var( --theme-label-large-font-family, \"Roboto-Medium\", sans-serif );font-size:var(--theme-label-large-font-size, 14px);line-height:var(--theme-label-large-line-height, 20px);letter-spacing:var(--theme-label-large-letter-spacing, .1px);font-weight:var(--theme-label-large-font-weight, 500);border-radius:8px;position:relative;z-index:2}.chip-input::placeholder{color:var(--schemes-on-surface-variant, #454733);opacity:.6}.chip-input:disabled{cursor:not-allowed;opacity:.6}.chip-input-mask{position:absolute;left:16px;right:40px;top:50%;transform:translateY(-50%);pointer-events:none;font-family:var( --theme-label-large-font-family, \"Roboto-Medium\", sans-serif );font-size:var(--theme-label-large-font-size, 14px);line-height:var(--theme-label-large-line-height, 20px);letter-spacing:var(--theme-label-large-letter-spacing, .1px);font-weight:var(--theme-label-large-font-weight, 500);z-index:1;display:flex}.mask-char-placeholder{color:var(--schemes-on-surface-variant, #454733);opacity:.4}.mask-char-filled{color:var(--schemes-on-surface, #171c1f);opacity:1}.calendar-icon-button{position:absolute;right:8px;top:50%;transform:translateY(-50%);background:none;border:none;cursor:pointer;padding:4px;display:flex;align-items:center;justify-content:center;color:var(--schemes-on-surface-variant, #454733);border-radius:4px;transition:all .2s;z-index:1}.calendar-icon-button:hover{background-color:#7878611a;color:var(--schemes-on-surface-variant, #454733)}.calendar-icon-button:active{background-color:#78786133}.calendar-icon-button svg{width:18px;height:18px}.icon.icon-tabler-calendar-event{width:18px;height:18px;color:var(--on-surface-variant, #40484c)}.date-picker-container{margin-top:12px;width:100%;display:flex;justify-content:flex-start}.datetime-header{width:100%;border:1px solid #787861;border-radius:5px;padding:15px;background-color:transparent;cursor:pointer;display:flex;justify-content:space-between;align-items:center;min-height:auto;transition:border-color .2s}.datetime-header:hover,.datetime-header:focus{outline:none;border-color:#a9a97f}.datetime-header.active{border-color:#a9a97f;outline:none}.datetime-header.disabled{cursor:not-allowed;opacity:.6}.selected-text{color:#454733;font-size:1.3rem;flex:1}.selected-text.placeholder{color:#787861}.header-icons{display:flex;align-items:center;gap:8px}.clear-icon{width:20px;height:20px;display:flex;align-items:center;justify-content:center;color:#787861;font-size:1.5rem;cursor:pointer;border-radius:50%;transition:all .2s}.clear-icon:hover{background-color:#7878611a;color:#454733}.arrow{width:15px;height:15px;background-image:url(\"data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e\");background-repeat:no-repeat;background-size:15px;background-position:center;color:#787861;flex-shrink:0;transition:transform .2s}.arrow.open{transform:rotate(180deg)}.dropdown{position:absolute;top:100%;left:0;right:0;background:#e3e3d1;border:1px solid #787861;border-top:none;border-radius:0 0 5px 5px;z-index:1000;box-shadow:0 4px 12px #00000026;min-width:400px}.datetime-content{display:flex}.calendar-section{flex:1;min-width:280px}.calendar-nav{display:flex;justify-content:space-between;align-items:center;padding:15px;border-bottom:1px solid rgba(120,120,97,.2)}.nav-section{display:flex;gap:5px}.nav-btn{background:none;border:none;color:#787861;cursor:pointer;font-size:1.2rem;padding:5px 10px;border-radius:3px;transition:all .2s}.nav-btn:hover{background-color:#a9a97f1a;color:#454733}.current-date{font-weight:500;color:#454733;font-size:1.1rem}.weekdays{display:grid;grid-template-columns:repeat(7,1fr);background:#7878611a}.weekday{padding:10px 5px;text-align:center;font-size:.9rem;font-weight:500;color:#787861}.calendar-grid{display:grid;grid-template-columns:repeat(7,1fr)}.calendar-day{padding:12px 5px;text-align:center;cursor:pointer;color:#454733;font-size:1rem;border-right:1px solid rgba(120,120,97,.1);border-bottom:1px solid rgba(120,120,97,.1);transition:all .2s}.calendar-day:hover:not(.disabled):not(.empty){background-color:#a9a97f33}.calendar-day.selected{background-color:#a9a97f;color:#e3e3d1;font-weight:500}.calendar-day.today:not(.selected){background-color:#a9a97f4d;font-weight:500}.calendar-day.disabled{color:#78786166;cursor:not-allowed}.calendar-day.empty{cursor:default}.calendar-day:nth-child(7n){border-right:none}.time-section{border-left:1px solid rgba(120,120,97,.2);min-width:140px;display:flex;flex-direction:column;background:#a9a97f0d}.time-header{padding:15px;border-bottom:1px solid rgba(120,120,97,.2);text-align:center;font-weight:500;color:#454733;background:#a9a97f1a}.time-selectors{display:flex;flex-direction:column;padding:15px;gap:20px;flex:1}.time-group{display:flex;align-items:center;gap:10px}.time-column{flex:1;display:flex;flex-direction:column;align-items:center}.time-label{font-size:.9rem;color:#787861;margin-bottom:10px;font-weight:500}.time-scroll{max-height:150px;overflow-y:auto;border:1px solid rgba(120,120,97,.2);border-radius:3px;width:50px;background:#a9a97f}.time-option{padding:8px 12px;text-align:center;cursor:pointer;color:#454733;font-size:1rem;transition:all .2s}.time-option:hover{background-color:#a9a97f1a}.time-option.selected{background-color:#a9a97f;color:#e3e3d1;font-weight:500}.time-separator-vertical{font-size:1.5rem;color:#787861;font-weight:700;align-self:flex-end;margin-bottom:10px}.time-scroll::-webkit-scrollbar{width:4px}.time-scroll::-webkit-scrollbar-track{background:#7878611a}.time-scroll::-webkit-scrollbar-thumb{background:#787861;border-radius:2px}.time-scroll::-webkit-scrollbar-thumb:hover{background:#a9a97f}.action-buttons{display:flex;justify-content:space-between;padding:15px;border-top:1px solid rgba(120,120,97,.2);gap:10px}.action-btn{padding:10px 20px;border:none;border-radius:3px;cursor:pointer;font-size:1rem;transition:all .2s}.action-btn.secondary{background:transparent;color:#787861;border:1px solid #787861}.action-btn.secondary:hover{background:#7878611a;color:#454733}.action-btn.primary{background:#a9a97f;color:#e3e3d1;border:1px solid #a9a97f}.action-btn.primary:hover{background:#969669;border-color:#969669}@media (max-width: 768px){.dropdown{min-width:320px}.datetime-content{flex-direction:column}.time-section{border-left:none;border-top:1px solid rgba(120,120,97,.2)}.time-selectors{flex-direction:row;justify-content:center;padding:15px}.time-group{gap:15px}.datetime-header{padding:12px 15px}.calendar-nav{padding:12px}.calendar-day{padding:10px 3px;font-size:.9rem}.action-buttons{padding:12px}}@media (max-width: 480px){.dropdown{min-width:280px}.time-section{min-width:auto}.time-scroll{width:45px}.time-selectors{padding:10px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }] });
1196
1195
  }
1197
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DateTimePicker, decorators: [{
1196
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DateTimeFilter, decorators: [{
1198
1197
  type: Component,
1199
- args: [{ selector: 'lib-date-time-picker', imports: [], providers: [
1198
+ args: [{ selector: 'lib-date-time-filter', standalone: true, imports: [CommonModule, ReactiveFormsModule], providers: [
1200
1199
  {
1201
1200
  provide: NG_VALUE_ACCESSOR,
1202
- useExisting: forwardRef(() => DateTimePicker),
1201
+ useExisting: forwardRef(() => DateTimeFilter),
1203
1202
  multi: true,
1204
1203
  },
1205
- ], template: "<div class=\"datetime-container\">\r\n <div\r\n class=\"datetime-header\"\r\n [class.active]=\"isOpen()\"\r\n [class.disabled]=\"isBlocked()\"\r\n [class.readonly]=\"isBlocked()\"\r\n (click)=\"!isBlocked() && toggle()\"\r\n (keydown)=\"!isBlocked() && onKeyDown($event)\"\r\n tabindex=\"0\"\r\n >\r\n <input\r\n type=\"text\"\r\n class=\"datetime-input\"\r\n [value]=\"displayValue()\"\r\n [placeholder]=\"placeholder()\"\r\n (input)=\"onInputChange($event)\"\r\n (focus)=\"!isBlocked() && onInputFocus()\"\r\n (click)=\"$event.stopPropagation()\"\r\n [disabled]=\"isDisabled()\"\r\n [readOnly]=\"readonly()\"\r\n />\r\n\r\n <div class=\"header-icons\">\r\n @if (selectedDate()) {\r\n <span\r\n class=\"clear-icon\"\r\n (click)=\"!isBlocked() && clear(); $event.stopPropagation()\"\r\n title=\"Limpiar\"\r\n >\r\n \u00D7\r\n </span>\r\n }\r\n <span class=\"arrow\" [class.open]=\"isOpen()\"></span>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n@if (isOpen()) {\r\n<div class=\"dropdown\">\r\n <div class=\"datetime-content\">\r\n <!-- Secci\u00F3n del calendario -->\r\n <div class=\"calendar-section\">\r\n <!-- Navegaci\u00F3n del calendario -->\r\n <div class=\"calendar-nav\">\r\n <div class=\"nav-section\">\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"previousYear()\"\r\n title=\"A\u00F1o anterior\"\r\n >\r\n \u2039\u2039\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"previousMonth()\"\r\n title=\"Mes anterior\"\r\n >\r\n \u2039\r\n </button>\r\n </div>\r\n\r\n <div class=\"current-date\">{{ monthName() }} {{ currentYear() }}</div>\r\n\r\n <div class=\"nav-section\">\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"nextMonth()\"\r\n title=\"Siguiente mes\"\r\n >\r\n \u203A\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"nextYear()\"\r\n title=\"Siguiente a\u00F1o\"\r\n >\r\n \u203A\u203A\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- D\u00EDas de la semana -->\r\n <div class=\"weekdays\">\r\n <div class=\"weekday\">Dom</div>\r\n <div class=\"weekday\">Lun</div>\r\n <div class=\"weekday\">Mar</div>\r\n <div class=\"weekday\">Mi\u00E9</div>\r\n <div class=\"weekday\">Jue</div>\r\n <div class=\"weekday\">Vie</div>\r\n <div class=\"weekday\">S\u00E1b</div>\r\n </div>\r\n\r\n <!-- D\u00EDas del mes -->\r\n <div class=\"calendar-grid\">\r\n @for (day of calendarDays(); track $index) {\r\n <div\r\n class=\"calendar-day\"\r\n [class.selected]=\"isDaySelected(day)\"\r\n [class.today]=\"isToday(day)\"\r\n [class.disabled]=\"isDayDisabled(day)\"\r\n [class.empty]=\"!day\"\r\n (click)=\"selectDay(day)\"\r\n >\r\n {{ day || '' }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- Selector de tiempo (solo si mode === 'datetime') -->\r\n @if (mode() === 'datetime') {\r\n <div class=\"time-section\">\r\n <div class=\"time-header\">Horario</div>\r\n\r\n <div class=\"time-selectors\">\r\n <div class=\"time-group\">\r\n <div class=\"time-column\">\r\n <div class=\"time-label\">Hora</div>\r\n <div class=\"time-scroll\">\r\n @for (hour of hours12(); track hour.value) {\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"hour.value === selectedHour12()\"\r\n (click)=\"setHour12(hour.value)\"\r\n >\r\n {{ hour.display }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"time-separator-vertical\">:</div>\r\n\r\n <div class=\"time-column\">\r\n <div class=\"time-label\">Min</div>\r\n <div class=\"time-scroll\">\r\n @for (minute of minutes(); track minute) {\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"minute === selectedMinute()\"\r\n (click)=\"setMinute(minute)\"\r\n >\r\n {{ minute.toString().padStart(2, '0') }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"time-column\">\r\n <div class=\"time-label\">AM/PM</div>\r\n <div class=\"time-scroll ampm\">\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"selectedAmPm() === 'AM'\"\r\n (click)=\"setAmPm('AM')\"\r\n >\r\n AM\r\n </div>\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"selectedAmPm() === 'PM'\"\r\n (click)=\"setAmPm('PM')\"\r\n >\r\n PM\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Botones de acci\u00F3n -->\r\n <div class=\"action-buttons\">\r\n <button type=\"button\" class=\"action-btn secondary\" (click)=\"today()\">\r\n Hoy\r\n </button>\r\n @if (mode() === 'datetime') {\r\n <button type=\"button\" class=\"action-btn primary\" (click)=\"close()\">\r\n Aceptar\r\n </button>\r\n }\r\n </div>\r\n</div>\r\n}\r\n", styles: [".datetime-container{position:relative;width:100%}.datetime-header{width:100%;border:1px solid #787861;border-radius:5px;padding:12px 15px;background-color:transparent;cursor:pointer;display:flex;justify-content:space-between;align-items:center;min-height:auto;transition:border-color .2s}.datetime-input{flex:1;border:none;outline:none;background:transparent;font-size:1.3rem;color:#454733;padding:0;margin:0}.datetime-input::placeholder{color:#787861}.datetime-input:disabled{cursor:not-allowed}.datetime-header:hover,.datetime-header:focus{outline:none;border-color:#a9a97f}.datetime-header.active{border-color:#a9a97f;outline:none}.datetime-header.disabled,.datetime-header.readonly{pointer-events:none;opacity:.6;cursor:not-allowed}.selected-text{color:#454733;font-size:1.3rem;flex:1}.selected-text.placeholder{color:#787861}.header-icons{display:flex;align-items:center;gap:8px}.clear-icon{width:20px;height:20px;display:flex;align-items:center;justify-content:center;color:#787861;font-size:1.5rem;cursor:pointer;border-radius:50%;transition:all .2s}.clear-icon:hover{background-color:#7878611a;color:#454733}.arrow{width:20px;height:20px;background-image:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='icon icon-tabler icons-tabler-outline icon-tabler-calendar-event'%3e%3cpath stroke='none' d='M0 0h24v24H0z' fill='none'/%3e%3cpath d='M4 5m0 2a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2z' /%3e%3cpath d='M16 3l0 4' /%3e%3cpath d='M8 3l0 4' /%3e%3cpath d='M4 11l16 0' /%3e%3cpath d='M8 15h2v2h-2z' /%3e%3c/svg%3e\");background-repeat:no-repeat;background-size:20px;background-position:center;color:#787861;flex-shrink:0;transition:transform .2s}.arrow.open{background-image:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='currentColor' class='icon icon-tabler icons-tabler-filled icon-tabler-calendar-event'%3e%3cpath stroke='none' d='M0 0h24v24H0z' fill='none'/%3e%3cpath d='M16 2a1 1 0 0 1 .993 .883l.007 .117v1h1a3 3 0 0 1 2.995 2.824l.005 .176v12a3 3 0 0 1 -2.824 2.995l-.176 .005h-12a3 3 0 0 1 -2.995 -2.824l-.005 -.176v-12a3 3 0 0 1 2.824 -2.995l.176 -.005h1v-1a1 1 0 0 1 1.993 -.117l.007 .117v1h6v-1a1 1 0 0 1 1 -1m3 7h-14v9.625c0 .705 .386 1.286 .883 1.366l.117 .009h12c.513 0 .936 -.53 .993 -1.215l.007 -.16z' /%3e%3cpath d='M8 14h2v2h-2z' /%3e%3c/svg%3e\")}.dropdown{position:absolute;top:100%;left:0;right:0;background:#e3e3d1;border:1px solid #787861;border-top:none;border-radius:0 0 5px 5px;z-index:1000;box-shadow:0 4px 12px #00000026;min-width:400px}.datetime-content{display:flex}.calendar-section{flex:1;min-width:280px}.calendar-nav{display:flex;justify-content:space-between;align-items:center;padding:15px;border-bottom:1px solid rgba(120,120,97,.2)}.nav-section{display:flex;gap:5px}.nav-btn{background:none;border:none;color:#787861;cursor:pointer;font-size:1.2rem;padding:5px 10px;border-radius:3px;transition:all .2s}.nav-btn:hover{background-color:#a9a97f1a;color:#454733}.current-date{font-weight:500;color:#454733;font-size:1.1rem}.weekdays{display:grid;grid-template-columns:repeat(7,1fr);background:#7878611a}.weekday{padding:10px 5px;text-align:center;font-size:.9rem;font-weight:500;color:#787861}.calendar-grid{display:grid;grid-template-columns:repeat(7,1fr)}.calendar-day{padding:12px 5px;text-align:center;cursor:pointer;color:#454733;font-size:1rem;border-right:1px solid rgba(120,120,97,.1);border-bottom:1px solid rgba(120,120,97,.1);transition:all .2s}.calendar-day:hover:not(.disabled):not(.empty){background-color:#a9a97f33}.calendar-day.selected{background-color:#a9a97f;color:#e3e3d1;font-weight:500}.calendar-day.today:not(.selected){background-color:#a9a97f4d;font-weight:500}.calendar-day.disabled{color:#78786166;cursor:not-allowed}.calendar-day.empty{cursor:default}.calendar-day:nth-child(7n){border-right:none}.time-section{border-left:1px solid rgba(120,120,97,.2);min-width:140px;display:flex;flex-direction:column;background:#a9a97f0d}.time-header{padding:15px;border-bottom:1px solid rgba(120,120,97,.2);text-align:center;font-weight:500;color:#454733;background:#a9a97f1a}.time-selectors{display:flex;flex-direction:column;padding:15px;gap:20px;flex:1}.time-group{display:flex;align-items:center;gap:10px}.time-column{flex:1;display:flex;flex-direction:column;align-items:center}.time-label{font-size:.9rem;color:#787861;margin-bottom:10px;font-weight:500}.time-scroll{max-height:150px;overflow-y:auto;border:1px solid rgba(120,120,97,.2);border-radius:3px;width:50px;background:#a9a97f}.time-option{padding:8px 12px;text-align:center;cursor:pointer;color:#454733;font-size:1rem;transition:all .2s}.time-option:hover{background-color:#a9a97f1a}.time-option.selected{background-color:#a9a97f;color:#e3e3d1;font-weight:500}.time-separator-vertical{font-size:1.5rem;color:#787861;font-weight:700;align-self:flex-end;margin-bottom:10px}.time-scroll::-webkit-scrollbar{width:4px}.time-scroll::-webkit-scrollbar-track{background:#7878611a}.time-scroll::-webkit-scrollbar-thumb{background:#787861;border-radius:2px}.time-scroll::-webkit-scrollbar-thumb:hover{background:#a9a97f}.action-buttons{display:flex;justify-content:space-between;padding:15px;border-top:1px solid rgba(120,120,97,.2);gap:10px}.action-btn{padding:10px 20px;border:none;border-radius:3px;cursor:pointer;font-size:1rem;transition:all .2s}.action-btn.secondary{background:transparent;color:#787861;border:1px solid #787861}.action-btn.secondary:hover{background:#7878611a;color:#454733}.action-btn.primary{background:#a9a97f;color:#e3e3d1;border:1px solid #a9a97f}.action-btn.primary:hover{background:#969669;border-color:#969669}@media (max-width: 768px){.dropdown{min-width:320px}.datetime-content{flex-direction:column}.time-section{border-left:none;border-top:1px solid rgba(120,120,97,.2)}.time-selectors{flex-direction:row;justify-content:center;padding:15px}.time-group{gap:15px}.datetime-header{padding:10px 15px}.calendar-nav{padding:12px}.calendar-day{padding:10px 3px;font-size:.9rem}.action-buttons{padding:12px}}@media (max-width: 480px){.dropdown{min-width:280px}.time-section{min-width:auto}.time-scroll{width:45px}.time-selectors{padding:10px}}\n"] }]
1206
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.NgZone }], propDecorators: { mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], minDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "minDate", required: false }] }], maxDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDate", required: false }] }], dateChange: [{ type: i0.Output, args: ["dateChange"] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }] } });
1204
+ ], template: "<div class=\"datetime-container\">\r\n <div class=\"filter-chips\">\r\n @for (item of filters(); track item.value) {\r\n <div\r\n class=\"chip-input-wrapper\"\r\n [class.has-value]=\"selectedDate() || inputTextValue()\"\r\n [class.active]=\"activeFilterType() === item.value\"\r\n >\r\n <!-- Etiqueta flotante -->\r\n <label class=\"floating-label\">{{ item.placeholder || item.label || 'dd/mm/aaaa' }}</label>\r\n\r\n <!-- M\u00E1scara de gu\u00EDa de fecha din\u00E1mica (__/__/____) -->\r\n <div class=\"chip-input-mask\">\r\n @for (part of inputMask(); track $index) {\r\n <span\r\n class=\"mask-char\"\r\n [class.mask-char-filled]=\"part.filled\"\r\n [class.mask-char-placeholder]=\"!part.filled\"\r\n >\r\n {{ part.char }}\r\n </span>\r\n }\r\n </div>\r\n\r\n <input\r\n type=\"text\"\r\n [value]=\"inputTextValue()\"\r\n (input)=\"onInputChange($event, item.value)\"\r\n (focus)=\"onInputFocus(item.value)\"\r\n [placeholder]=\"''\"\r\n class=\"chip-input\"\r\n [disabled]=\"isDisabled()\"\r\n />\r\n\r\n <button\r\n type=\"button\"\r\n class=\"calendar-icon-button\"\r\n (click)=\"toggle(item.value)\"\r\n title=\"Abrir calendario\"\r\n >\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n width=\"18\"\r\n height=\"18\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n class=\"icon icon-tabler icons-tabler-outline icon-tabler-calendar-event\"\r\n >\r\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\" />\r\n <path\r\n d=\"M4 5m0 2a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2z\"\r\n />\r\n <path d=\"M16 3l0 4\" />\r\n <path d=\"M8 3l0 4\" />\r\n <path d=\"M4 11l16 0\" />\r\n <path d=\"M8 15h2v2h-2z\" />\r\n </svg>\r\n </button>\r\n\r\n @if (isOpen() && activeFilterType() === item.value) {\r\n <div class=\"dropdown\">\r\n <div class=\"datetime-content\">\r\n <!-- Secci\u00F3n del calendario -->\r\n <div class=\"calendar-section\">\r\n <!-- Navegaci\u00F3n -->\r\n <div class=\"calendar-nav\">\r\n <div class=\"nav-section\">\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"previousYear()\"\r\n title=\"A\u00F1o anterior\"\r\n >\r\n \u2039\u2039\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"previousMonth()\"\r\n title=\"Mes anterior\"\r\n >\r\n \u2039\r\n </button>\r\n </div>\r\n\r\n <div class=\"current-date\">\r\n {{ monthName() }} {{ currentYear() }}\r\n </div>\r\n\r\n <div class=\"nav-section\">\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"nextMonth()\"\r\n title=\"Siguiente mes\"\r\n >\r\n \u203A\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"nav-btn\"\r\n (click)=\"nextYear()\"\r\n title=\"Siguiente a\u00F1o\"\r\n >\r\n \u203A\u203A\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- D\u00EDas de la semana -->\r\n <div class=\"weekdays\">\r\n <div class=\"weekday\">Dom</div>\r\n <div class=\"weekday\">Lun</div>\r\n <div class=\"weekday\">Mar</div>\r\n <div class=\"weekday\">Mi\u00E9</div>\r\n <div class=\"weekday\">Jue</div>\r\n <div class=\"weekday\">Vie</div>\r\n <div class=\"weekday\">S\u00E1b</div>\r\n </div>\r\n\r\n <!-- D\u00EDas -->\r\n <div class=\"calendar-grid\">\r\n @for (day of calendarDays(); track $index) {\r\n <div\r\n class=\"calendar-day\"\r\n [class.selected]=\"isDaySelected(day)\"\r\n [class.today]=\"isToday(day)\"\r\n [class.disabled]=\"isDayDisabled(day)\"\r\n [class.empty]=\"!day\"\r\n (click)=\"selectDay(day)\"\r\n >\r\n {{ day || \"\" }}\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- TIME PICKER -->\r\n @if (mode() === 'datetime') {\r\n <div class=\"time-section\">\r\n <div class=\"time-header\">Horario</div>\r\n\r\n <div class=\"time-selectors\">\r\n <div class=\"time-group\">\r\n <div class=\"time-column\">\r\n <div class=\"time-label\">Hora</div>\r\n <div class=\"time-scroll\">\r\n @for (hour of hours12(); track hour.value) {\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"hour.value === selectedHour12()\"\r\n (click)=\"setHour12(hour.value)\"\r\n >\r\n {{ hour.display }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"time-separator-vertical\">:</div>\r\n\r\n <div class=\"time-column\">\r\n <div class=\"time-label\">Min</div>\r\n <div class=\"time-scroll\">\r\n @for (minute of minutes(); track minute) {\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"minute === selectedMinute()\"\r\n (click)=\"setMinute(minute)\"\r\n >\r\n {{ minute.toString().padStart(2, \"0\") }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"time-column\">\r\n <div class=\"time-label\">AM/PM</div>\r\n <div class=\"time-scroll ampm\">\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"selectedAmPm() === 'AM'\"\r\n (click)=\"setAmPm('AM')\"\r\n >\r\n AM\r\n </div>\r\n <div\r\n class=\"time-option\"\r\n [class.selected]=\"selectedAmPm() === 'PM'\"\r\n (click)=\"setAmPm('PM')\"\r\n >\r\n PM\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- botones -->\r\n <div class=\"action-buttons\">\r\n <button type=\"button\" class=\"action-btn secondary\" (click)=\"today()\">\r\n Hoy\r\n </button>\r\n\r\n @if (mode() === 'datetime') {\r\n <button type=\"button\" class=\"action-btn primary\" (click)=\"close()\">\r\n Aceptar\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n", styles: [".datetime-container{position:relative;width:100%}.filter-chips{display:flex;gap:10px;padding:8px;border-radius:12px;position:relative}.chip-input-wrapper{position:relative;display:flex;align-items:center;border-radius:8px;border-style:solid;border-color:var(--schemes-outline-variant, #c0c7cd);border-width:1px;height:32px;flex-shrink:0;transition:.2s ease;background-color:transparent}.chip-input-wrapper:hover{background-color:#ececcf}.chip-input-wrapper:focus-within,.chip-input-wrapper.active{color:var(--on-surface, #171c1f);border-color:#b6b69b}.floating-label{position:absolute;left:12px;top:-8px;color:var(--schemes-on-surface-variant, #454733);font-family:var( --theme-label-large-font-family, \"Roboto-Medium\", sans-serif );font-size:11px;line-height:12px;letter-spacing:var(--theme-label-large-letter-spacing, .1px);font-weight:var(--theme-label-large-font-weight, 500);opacity:0;pointer-events:none;transition:all .2s ease;z-index:2;background-color:#ebeccf;padding:0 4px;border-radius:2px}.chip-input-wrapper.has-value .floating-label{opacity:.6}.chip-input{border:none;outline:none;background:transparent;padding:6px 40px 6px 16px;height:100%;width:100%;color:transparent;caret-color:var(--schemes-on-surface-variant, #454733);font-family:var( --theme-label-large-font-family, \"Roboto-Medium\", sans-serif );font-size:var(--theme-label-large-font-size, 14px);line-height:var(--theme-label-large-line-height, 20px);letter-spacing:var(--theme-label-large-letter-spacing, .1px);font-weight:var(--theme-label-large-font-weight, 500);border-radius:8px;position:relative;z-index:2}.chip-input::placeholder{color:var(--schemes-on-surface-variant, #454733);opacity:.6}.chip-input:disabled{cursor:not-allowed;opacity:.6}.chip-input-mask{position:absolute;left:16px;right:40px;top:50%;transform:translateY(-50%);pointer-events:none;font-family:var( --theme-label-large-font-family, \"Roboto-Medium\", sans-serif );font-size:var(--theme-label-large-font-size, 14px);line-height:var(--theme-label-large-line-height, 20px);letter-spacing:var(--theme-label-large-letter-spacing, .1px);font-weight:var(--theme-label-large-font-weight, 500);z-index:1;display:flex}.mask-char-placeholder{color:var(--schemes-on-surface-variant, #454733);opacity:.4}.mask-char-filled{color:var(--schemes-on-surface, #171c1f);opacity:1}.calendar-icon-button{position:absolute;right:8px;top:50%;transform:translateY(-50%);background:none;border:none;cursor:pointer;padding:4px;display:flex;align-items:center;justify-content:center;color:var(--schemes-on-surface-variant, #454733);border-radius:4px;transition:all .2s;z-index:1}.calendar-icon-button:hover{background-color:#7878611a;color:var(--schemes-on-surface-variant, #454733)}.calendar-icon-button:active{background-color:#78786133}.calendar-icon-button svg{width:18px;height:18px}.icon.icon-tabler-calendar-event{width:18px;height:18px;color:var(--on-surface-variant, #40484c)}.date-picker-container{margin-top:12px;width:100%;display:flex;justify-content:flex-start}.datetime-header{width:100%;border:1px solid #787861;border-radius:5px;padding:15px;background-color:transparent;cursor:pointer;display:flex;justify-content:space-between;align-items:center;min-height:auto;transition:border-color .2s}.datetime-header:hover,.datetime-header:focus{outline:none;border-color:#a9a97f}.datetime-header.active{border-color:#a9a97f;outline:none}.datetime-header.disabled{cursor:not-allowed;opacity:.6}.selected-text{color:#454733;font-size:1.3rem;flex:1}.selected-text.placeholder{color:#787861}.header-icons{display:flex;align-items:center;gap:8px}.clear-icon{width:20px;height:20px;display:flex;align-items:center;justify-content:center;color:#787861;font-size:1.5rem;cursor:pointer;border-radius:50%;transition:all .2s}.clear-icon:hover{background-color:#7878611a;color:#454733}.arrow{width:15px;height:15px;background-image:url(\"data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e\");background-repeat:no-repeat;background-size:15px;background-position:center;color:#787861;flex-shrink:0;transition:transform .2s}.arrow.open{transform:rotate(180deg)}.dropdown{position:absolute;top:100%;left:0;right:0;background:#e3e3d1;border:1px solid #787861;border-top:none;border-radius:0 0 5px 5px;z-index:1000;box-shadow:0 4px 12px #00000026;min-width:400px}.datetime-content{display:flex}.calendar-section{flex:1;min-width:280px}.calendar-nav{display:flex;justify-content:space-between;align-items:center;padding:15px;border-bottom:1px solid rgba(120,120,97,.2)}.nav-section{display:flex;gap:5px}.nav-btn{background:none;border:none;color:#787861;cursor:pointer;font-size:1.2rem;padding:5px 10px;border-radius:3px;transition:all .2s}.nav-btn:hover{background-color:#a9a97f1a;color:#454733}.current-date{font-weight:500;color:#454733;font-size:1.1rem}.weekdays{display:grid;grid-template-columns:repeat(7,1fr);background:#7878611a}.weekday{padding:10px 5px;text-align:center;font-size:.9rem;font-weight:500;color:#787861}.calendar-grid{display:grid;grid-template-columns:repeat(7,1fr)}.calendar-day{padding:12px 5px;text-align:center;cursor:pointer;color:#454733;font-size:1rem;border-right:1px solid rgba(120,120,97,.1);border-bottom:1px solid rgba(120,120,97,.1);transition:all .2s}.calendar-day:hover:not(.disabled):not(.empty){background-color:#a9a97f33}.calendar-day.selected{background-color:#a9a97f;color:#e3e3d1;font-weight:500}.calendar-day.today:not(.selected){background-color:#a9a97f4d;font-weight:500}.calendar-day.disabled{color:#78786166;cursor:not-allowed}.calendar-day.empty{cursor:default}.calendar-day:nth-child(7n){border-right:none}.time-section{border-left:1px solid rgba(120,120,97,.2);min-width:140px;display:flex;flex-direction:column;background:#a9a97f0d}.time-header{padding:15px;border-bottom:1px solid rgba(120,120,97,.2);text-align:center;font-weight:500;color:#454733;background:#a9a97f1a}.time-selectors{display:flex;flex-direction:column;padding:15px;gap:20px;flex:1}.time-group{display:flex;align-items:center;gap:10px}.time-column{flex:1;display:flex;flex-direction:column;align-items:center}.time-label{font-size:.9rem;color:#787861;margin-bottom:10px;font-weight:500}.time-scroll{max-height:150px;overflow-y:auto;border:1px solid rgba(120,120,97,.2);border-radius:3px;width:50px;background:#a9a97f}.time-option{padding:8px 12px;text-align:center;cursor:pointer;color:#454733;font-size:1rem;transition:all .2s}.time-option:hover{background-color:#a9a97f1a}.time-option.selected{background-color:#a9a97f;color:#e3e3d1;font-weight:500}.time-separator-vertical{font-size:1.5rem;color:#787861;font-weight:700;align-self:flex-end;margin-bottom:10px}.time-scroll::-webkit-scrollbar{width:4px}.time-scroll::-webkit-scrollbar-track{background:#7878611a}.time-scroll::-webkit-scrollbar-thumb{background:#787861;border-radius:2px}.time-scroll::-webkit-scrollbar-thumb:hover{background:#a9a97f}.action-buttons{display:flex;justify-content:space-between;padding:15px;border-top:1px solid rgba(120,120,97,.2);gap:10px}.action-btn{padding:10px 20px;border:none;border-radius:3px;cursor:pointer;font-size:1rem;transition:all .2s}.action-btn.secondary{background:transparent;color:#787861;border:1px solid #787861}.action-btn.secondary:hover{background:#7878611a;color:#454733}.action-btn.primary{background:#a9a97f;color:#e3e3d1;border:1px solid #a9a97f}.action-btn.primary:hover{background:#969669;border-color:#969669}@media (max-width: 768px){.dropdown{min-width:320px}.datetime-content{flex-direction:column}.time-section{border-left:none;border-top:1px solid rgba(120,120,97,.2)}.time-selectors{flex-direction:row;justify-content:center;padding:15px}.time-group{gap:15px}.datetime-header{padding:12px 15px}.calendar-nav{padding:12px}.calendar-day{padding:10px 3px;font-size:.9rem}.action-buttons{padding:12px}}@media (max-width: 480px){.dropdown{min-width:280px}.time-section{min-width:auto}.time-scroll{width:45px}.time-selectors{padding:10px}}\n"] }]
1205
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.NgZone }], propDecorators: { filters: [{ type: i0.Input, args: [{ isSignal: true, alias: "filters", required: false }] }], dateSelected: [{ type: i0.Output, args: ["dateSelected"] }], dateChange: [{ type: i0.Output, args: ["dateChange"] }], clearTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearTrigger", required: false }] }] } });
1207
1206
 
1208
1207
  class InputNumberFilter {
1209
1208
  // Inputs
@@ -1273,8 +1272,8 @@ class InputNumberFilter {
1273
1272
  this.onTouched();
1274
1273
  }
1275
1274
  }
1276
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: InputNumberFilter, deps: [], target: i0.ɵɵFactoryTarget.Component });
1277
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: InputNumberFilter, isStandalone: true, selector: "lib-input-number-filter", inputs: { filters: { classPropertyName: "filters", publicName: "filters", isSignal: true, isRequired: false, transformFunction: null }, clearTrigger: { classPropertyName: "clearTrigger", publicName: "clearTrigger", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { filterSelected: "filterSelected", valueChange: "valueChange" }, providers: [
1275
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: InputNumberFilter, deps: [], target: i0.ɵɵFactoryTarget.Component });
1276
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: InputNumberFilter, isStandalone: true, selector: "lib-input-number-filter", inputs: { filters: { classPropertyName: "filters", publicName: "filters", isSignal: true, isRequired: false, transformFunction: null }, clearTrigger: { classPropertyName: "clearTrigger", publicName: "clearTrigger", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { filterSelected: "filterSelected", valueChange: "valueChange" }, providers: [
1278
1277
  {
1279
1278
  provide: NG_VALUE_ACCESSOR,
1280
1279
  useExisting: forwardRef(() => InputNumberFilter),
@@ -1282,7 +1281,7 @@ class InputNumberFilter {
1282
1281
  },
1283
1282
  ], ngImport: i0, template: "<div class=\"input-filter-container\">\r\n <div class=\"filter-chips\">\r\n @for (item of filters(); track item.value) {\r\n <div class=\"chip-input-wrapper\" [class.has-value]=\"filterValues()[item.value]\">\r\n <label class=\"floating-label\">{{ item.placeholder || item.label || 'Escribir N\u00FAmero' }}</label>\r\n <input\r\n type=\"number\"\r\n [value]=\"filterValues()[item.value] || ''\"\r\n (input)=\"onInputChange($event, item.value)\"\r\n [placeholder]=\"filterValues()[item.value] ? '' : (item.placeholder || item.label || 'Escribir N\u00FAmero')\"\r\n class=\"chip-input\"\r\n [disabled]=\"isDisabled()\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n", styles: [".input-filter-container{position:relative;width:100%}.filter-chips{display:flex;gap:10px;padding:8px;border-radius:12px;position:relative}.chip-input-wrapper{position:relative;display:flex;align-items:center;border-radius:8px;border-style:solid;border-color:var(--schemes-outline-variant, #c0c7cd);border-width:1px;height:32px;flex-shrink:0;transition:.2s ease;background-color:transparent}.chip-input-wrapper:hover{background-color:#ececcf}.chip-input-wrapper:focus-within{color:var(--on-surface, #171c1f);border-color:#b6b69b}.floating-label{position:absolute;left:12px;top:-8px;color:var(--schemes-on-surface-variant, #454733);font-family:var( --theme-label-large-font-family, \"Roboto-Medium\", sans-serif );font-size:11px;line-height:12px;letter-spacing:var(--theme-label-large-letter-spacing, .1px);font-weight:var(--theme-label-large-font-weight, 500);opacity:0;pointer-events:none;transition:all .2s ease;z-index:2;background-color:#ebeccf;padding:0 4px;border-radius:2px}.chip-input-wrapper.has-value .floating-label{opacity:.6}.chip-input{border:none;outline:none;background:transparent;padding:6px 30px 6px 16px;height:100%;width:100%;color:var(--schemes-on-surface-variant, #454733);font-family:var( --theme-label-large-font-family, \"Roboto-Medium\", sans-serif );font-size:var(--theme-label-large-font-size, 14px);line-height:var(--theme-label-large-line-height, 20px);letter-spacing:var(--theme-label-large-letter-spacing, .1px);font-weight:var(--theme-label-large-font-weight, 500);border-radius:8px;-moz-appearance:textfield;appearance:textfield}.chip-input::placeholder{color:var(--schemes-on-surface-variant, #454733);opacity:.6}.chip-input:disabled{cursor:not-allowed;opacity:.6}.chip-input::-webkit-inner-spin-button{opacity:1;cursor:pointer;background-color:transparent;height:100%;width:20px;margin:0;padding:0;position:absolute;right:0;top:0}.chip-input::-webkit-outer-spin-button{background-color:transparent;opacity:1;cursor:pointer;height:100%;width:20px;margin:0;padding:0;position:absolute;right:0;top:0}.icon.icon-tabler-abc{width:18px;height:18px;color:var(--on-surface-variant, #40484c)}.action-buttons{display:flex;justify-content:flex-end;gap:10px}.action-btn{padding:8px 16px;border:none;border-radius:3px;cursor:pointer;font-size:.9rem;transition:all .2s}.action-btn.secondary{background:transparent;color:#787861;border:1px solid #787861}.action-btn.secondary:hover{background:#7878611a;color:#454733}.action-btn.primary{background:#a9a97f;color:#e3e3d1;border:1px solid #a9a97f}.action-btn.primary:hover{background:#969669;border-color:#969669}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: FormsModule }] });
1284
1283
  }
1285
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: InputNumberFilter, decorators: [{
1284
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: InputNumberFilter, decorators: [{
1286
1285
  type: Component,
1287
1286
  args: [{ selector: 'lib-input-number-filter', standalone: true, imports: [CommonModule, ReactiveFormsModule, FormsModule], providers: [
1288
1287
  {
@@ -1487,8 +1486,8 @@ class InputSelectFilter {
1487
1486
  this.documentClickListener = undefined;
1488
1487
  }
1489
1488
  }
1490
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: InputSelectFilter, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
1491
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: InputSelectFilter, isStandalone: true, selector: "lib-input-select-filter", inputs: { filters: { classPropertyName: "filters", publicName: "filters", isSignal: true, isRequired: false, transformFunction: null }, clearTrigger: { classPropertyName: "clearTrigger", publicName: "clearTrigger", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { filterSelected: "filterSelected", valueChange: "valueChange" }, providers: [
1489
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: InputSelectFilter, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
1490
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: InputSelectFilter, isStandalone: true, selector: "lib-input-select-filter", inputs: { filters: { classPropertyName: "filters", publicName: "filters", isSignal: true, isRequired: false, transformFunction: null }, clearTrigger: { classPropertyName: "clearTrigger", publicName: "clearTrigger", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { filterSelected: "filterSelected", valueChange: "valueChange" }, providers: [
1492
1491
  {
1493
1492
  provide: NG_VALUE_ACCESSOR,
1494
1493
  useExisting: forwardRef(() => InputSelectFilter),
@@ -1496,7 +1495,7 @@ class InputSelectFilter {
1496
1495
  },
1497
1496
  ], ngImport: i0, template: "<div class=\"input-filter-container\">\r\n <div class=\"filter-chips\">\r\n @for (item of filters(); track item.value) {\r\n <div class=\"chip\" [class.active]=\"activeFilterType() === item.value\" [class.has-value]=\"filterValues()[item.value]\">\r\n <label class=\"floating-label\">{{ item.placeholder || item.label || 'Seleccionar' }}</label>\r\n <div class=\"content-chip\">\r\n <input\r\n type=\"text\"\r\n class=\"chip-input\"\r\n [value]=\"filterValues()[item.value] || ''\"\r\n (input)=\"onInputChange($event, item.value)\"\r\n (focus)=\"onFocusFilter(item.value)\"\r\n (click)=\"$event.stopPropagation()\"\r\n (keydown)=\"onKeyDown($event)\"\r\n [placeholder]=\"filterValues()[item.value] ? '' : (item.placeholder || item.label || 'Seleccionar')\"\r\n [disabled]=\"isDisabled()\"\r\n />\r\n\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\r\n class=\"icon icon-tabler icons-tabler-outline icon-tabler-list\">\r\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\" />\r\n <path d=\"M9 6l11 0\" />\r\n <path d=\"M9 12l11 0\" />\r\n <path d=\"M9 18l11 0\" />\r\n <path d=\"M5 6l0 .01\" />\r\n <path d=\"M5 12l0 .01\" />\r\n <path d=\"M5 18l0 .01\" />\r\n </svg>\r\n </div>\r\n\r\n @if (isOpen() && activeFilterType() === item.value) {\r\n <div class=\"dropdown\">\r\n <div class=\"options-list\">\r\n @for (option of filteredOptions(); track option.value) {\r\n <div class=\"option-item\" (click)=\"selectOption(option)\">\r\n {{ option.label }}\r\n </div>\r\n }\r\n @if (filteredOptions().length === 0) {\r\n <div class=\"no-options\">No hay opciones</div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n", styles: [".input-filter-container{position:relative;width:100%}.filter-chips{display:flex;gap:10px;padding:8px;border-radius:12px;position:relative}.chip{border-radius:8px;border-style:solid;border-color:var(--schemes-outline-variant, #c0c7cd);border-width:1px;display:flex;flex-direction:row;align-items:center;justify-content:center;flex-shrink:0;height:32px;cursor:pointer;transition:.2s ease;position:relative}.chip:hover{background-color:#ececcf}.chip.active{color:var(--on-surface, #171c1f);border-color:#b6b69b}.floating-label{position:absolute;left:12px;top:-8px;color:var(--schemes-on-surface-variant, #454733);font-family:var( --theme-label-large-font-family, \"Roboto-Medium\", sans-serif );font-size:11px;line-height:12px;letter-spacing:var(--theme-label-large-letter-spacing, .1px);font-weight:var(--theme-label-large-font-weight, 500);opacity:0;pointer-events:none;transition:all .2s ease;z-index:2;background-color:#ebeccf;padding:0 4px;border-radius:2px}.chip.has-value .floating-label{opacity:.6}.content-chip{padding:0 8px;display:flex;flex-direction:row;gap:8px;align-items:center;justify-items:center;height:32px}.label-text{display:none}.chip-input{border:none;outline:none;background:transparent;height:100%;width:100%;color:var(--schemes-on-surface-variant, #454733);font-family:var( --theme-label-large-font-family, \"Roboto-Medium\", sans-serif );font-size:var(--theme-label-large-font-size, 14px);line-height:var(--theme-label-large-line-height, 20px);letter-spacing:var(--theme-label-large-letter-spacing, .1px);font-weight:var(--theme-label-large-font-weight, 500)}.chip-input::placeholder{color:var(--schemes-on-surface-variant, #454733);opacity:.6}.chip-input:disabled{cursor:not-allowed;opacity:.6}.icon{width:18px;height:18px;color:var(--on-surface-variant, #40484c)}.dropdown{position:absolute;top:100%;left:0;right:0;background:#e3e3d1;border:1px solid #787861;border-top:none;border-radius:0 0 5px 5px;z-index:1000;box-shadow:0 4px 12px #00000026;min-width:200px;padding:0;overflow:hidden}.options-list{display:flex;flex-direction:column;max-height:200px;overflow-y:auto}.option-item{padding:10px 15px;cursor:pointer;color:#454733;font-size:.9rem;transition:background-color .2s}.option-item:hover{background-color:#7878611a}.no-options{padding:10px 15px;color:#787861;font-size:.9rem;font-style:italic}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: FormsModule }] });
1498
1497
  }
1499
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: InputSelectFilter, decorators: [{
1498
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: InputSelectFilter, decorators: [{
1500
1499
  type: Component,
1501
1500
  args: [{ selector: 'lib-input-select-filter', standalone: true, imports: [CommonModule, ReactiveFormsModule, FormsModule], providers: [
1502
1501
  {
@@ -1593,8 +1592,8 @@ class InputTextFilter {
1593
1592
  this.onTouched();
1594
1593
  }
1595
1594
  }
1596
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: InputTextFilter, deps: [], target: i0.ɵɵFactoryTarget.Component });
1597
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: InputTextFilter, isStandalone: true, selector: "lib-input-text-filter", inputs: { filters: { classPropertyName: "filters", publicName: "filters", isSignal: true, isRequired: false, transformFunction: null }, clearTrigger: { classPropertyName: "clearTrigger", publicName: "clearTrigger", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { filterSelected: "filterSelected", valueChange: "valueChange" }, providers: [
1595
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: InputTextFilter, deps: [], target: i0.ɵɵFactoryTarget.Component });
1596
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: InputTextFilter, isStandalone: true, selector: "lib-input-text-filter", inputs: { filters: { classPropertyName: "filters", publicName: "filters", isSignal: true, isRequired: false, transformFunction: null }, clearTrigger: { classPropertyName: "clearTrigger", publicName: "clearTrigger", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { filterSelected: "filterSelected", valueChange: "valueChange" }, providers: [
1598
1597
  {
1599
1598
  provide: NG_VALUE_ACCESSOR,
1600
1599
  useExisting: forwardRef(() => InputTextFilter),
@@ -1602,7 +1601,7 @@ class InputTextFilter {
1602
1601
  },
1603
1602
  ], ngImport: i0, template: "<div class=\"input-filter-container\">\r\n <div class=\"filter-chips\">\r\n @for (item of filters(); track item.value) {\r\n <div class=\"chip-input-wrapper\" [class.has-value]=\"filterValues()[item.value]\">\r\n <label class=\"floating-label\">{{ item.placeholder || item.label || 'Escribir' }}</label>\r\n <input\r\n type=\"text\"\r\n [value]=\"filterValues()[item.value] || ''\"\r\n (input)=\"onInputChange($event, item.value)\"\r\n [placeholder]=\"filterValues()[item.value] ? '' : (item.placeholder || item.label || 'Escribir')\"\r\n class=\"chip-input\"\r\n [disabled]=\"isDisabled()\"\r\n />\r\n @if (filterValues()[item.value]) {\r\n <button\r\n type=\"button\"\r\n class=\"clear-button\"\r\n (click)=\"clearFilter(item.value)\"\r\n title=\"Limpiar\"\r\n >\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/>\r\n <path d=\"M18 6l-12 12\" />\r\n <path d=\"M6 6l12 12\" />\r\n </svg>\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n", styles: [".input-filter-container{position:relative;width:100%}.filter-chips{display:flex;gap:10px;padding:8px;border-radius:12px;position:relative}.chip-input-wrapper{position:relative;display:flex;align-items:center;border-radius:8px;border-style:solid;border-color:var(--schemes-outline-variant, #c0c7cd);border-width:1px;height:32px;flex-shrink:0;transition:.2s ease;background-color:transparent}.chip-input-wrapper:hover{background-color:#ececcf}.chip-input-wrapper:focus-within{color:var(--on-surface, #171c1f);border-color:#b6b69b}.floating-label{position:absolute;left:12px;top:-8px;color:var(--schemes-on-surface-variant, #454733);font-family:var( --theme-label-large-font-family, \"Roboto-Medium\", sans-serif );font-size:11px;line-height:12px;letter-spacing:var(--theme-label-large-letter-spacing, .1px);font-weight:var(--theme-label-large-font-weight, 500);opacity:0;pointer-events:none;transition:all .2s ease;z-index:2;background-color:#ebeccf;padding:0 4px;border-radius:2px}.chip-input-wrapper.has-value .floating-label{opacity:.6}.chip-input{border:none;outline:none;background:transparent;padding:6px 35px 6px 16px;height:100%;width:100%;color:var(--schemes-on-surface-variant, #454733);font-family:var( --theme-label-large-font-family, \"Roboto-Medium\", sans-serif );font-size:var(--theme-label-large-font-size, 14px);line-height:var(--theme-label-large-line-height, 20px);letter-spacing:var(--theme-label-large-letter-spacing, .1px);font-weight:var(--theme-label-large-font-weight, 500);border-radius:8px}.chip-input::placeholder{color:var(--schemes-on-surface-variant, #454733);opacity:.6}.chip-input:disabled{cursor:not-allowed;opacity:.6}.icon.icon-tabler-abc{width:18px;height:18px;color:var(--on-surface-variant, #40484c)}.clear-button{position:absolute;right:8px;top:50%;transform:translateY(-50%);background:none;border:none;cursor:pointer;padding:4px;display:flex;align-items:center;justify-content:center;color:var(--schemes-on-surface-variant, #454733);border-radius:4px;transition:all .2s;z-index:1}.clear-button:hover{background-color:#7878611a;color:var(--schemes-on-surface-variant, #454733)}.clear-button:active{background-color:#78786133}.clear-button svg{width:16px;height:16px}.action-buttons{display:flex;justify-content:flex-end;gap:10px}.action-btn{padding:8px 16px;border:none;border-radius:3px;cursor:pointer;font-size:.9rem;transition:all .2s}.action-btn.secondary{background:transparent;color:#787861;border:1px solid #787861}.action-btn.secondary:hover{background:#7878611a;color:#454733}.action-btn.primary{background:#a9a97f;color:#e3e3d1;border:1px solid #a9a97f}.action-btn.primary:hover{background:#969669;border-color:#969669}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: FormsModule }] });
1604
1603
  }
1605
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: InputTextFilter, decorators: [{
1604
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: InputTextFilter, decorators: [{
1606
1605
  type: Component,
1607
1606
  args: [{ selector: 'lib-input-text-filter', standalone: true, imports: [CommonModule, ReactiveFormsModule, FormsModule], providers: [
1608
1607
  {
@@ -1613,6 +1612,39 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
1613
1612
  ], template: "<div class=\"input-filter-container\">\r\n <div class=\"filter-chips\">\r\n @for (item of filters(); track item.value) {\r\n <div class=\"chip-input-wrapper\" [class.has-value]=\"filterValues()[item.value]\">\r\n <label class=\"floating-label\">{{ item.placeholder || item.label || 'Escribir' }}</label>\r\n <input\r\n type=\"text\"\r\n [value]=\"filterValues()[item.value] || ''\"\r\n (input)=\"onInputChange($event, item.value)\"\r\n [placeholder]=\"filterValues()[item.value] ? '' : (item.placeholder || item.label || 'Escribir')\"\r\n class=\"chip-input\"\r\n [disabled]=\"isDisabled()\"\r\n />\r\n @if (filterValues()[item.value]) {\r\n <button\r\n type=\"button\"\r\n class=\"clear-button\"\r\n (click)=\"clearFilter(item.value)\"\r\n title=\"Limpiar\"\r\n >\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/>\r\n <path d=\"M18 6l-12 12\" />\r\n <path d=\"M6 6l12 12\" />\r\n </svg>\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n", styles: [".input-filter-container{position:relative;width:100%}.filter-chips{display:flex;gap:10px;padding:8px;border-radius:12px;position:relative}.chip-input-wrapper{position:relative;display:flex;align-items:center;border-radius:8px;border-style:solid;border-color:var(--schemes-outline-variant, #c0c7cd);border-width:1px;height:32px;flex-shrink:0;transition:.2s ease;background-color:transparent}.chip-input-wrapper:hover{background-color:#ececcf}.chip-input-wrapper:focus-within{color:var(--on-surface, #171c1f);border-color:#b6b69b}.floating-label{position:absolute;left:12px;top:-8px;color:var(--schemes-on-surface-variant, #454733);font-family:var( --theme-label-large-font-family, \"Roboto-Medium\", sans-serif );font-size:11px;line-height:12px;letter-spacing:var(--theme-label-large-letter-spacing, .1px);font-weight:var(--theme-label-large-font-weight, 500);opacity:0;pointer-events:none;transition:all .2s ease;z-index:2;background-color:#ebeccf;padding:0 4px;border-radius:2px}.chip-input-wrapper.has-value .floating-label{opacity:.6}.chip-input{border:none;outline:none;background:transparent;padding:6px 35px 6px 16px;height:100%;width:100%;color:var(--schemes-on-surface-variant, #454733);font-family:var( --theme-label-large-font-family, \"Roboto-Medium\", sans-serif );font-size:var(--theme-label-large-font-size, 14px);line-height:var(--theme-label-large-line-height, 20px);letter-spacing:var(--theme-label-large-letter-spacing, .1px);font-weight:var(--theme-label-large-font-weight, 500);border-radius:8px}.chip-input::placeholder{color:var(--schemes-on-surface-variant, #454733);opacity:.6}.chip-input:disabled{cursor:not-allowed;opacity:.6}.icon.icon-tabler-abc{width:18px;height:18px;color:var(--on-surface-variant, #40484c)}.clear-button{position:absolute;right:8px;top:50%;transform:translateY(-50%);background:none;border:none;cursor:pointer;padding:4px;display:flex;align-items:center;justify-content:center;color:var(--schemes-on-surface-variant, #454733);border-radius:4px;transition:all .2s;z-index:1}.clear-button:hover{background-color:#7878611a;color:var(--schemes-on-surface-variant, #454733)}.clear-button:active{background-color:#78786133}.clear-button svg{width:16px;height:16px}.action-buttons{display:flex;justify-content:flex-end;gap:10px}.action-btn{padding:8px 16px;border:none;border-radius:3px;cursor:pointer;font-size:.9rem;transition:all .2s}.action-btn.secondary{background:transparent;color:#787861;border:1px solid #787861}.action-btn.secondary:hover{background:#7878611a;color:#454733}.action-btn.primary{background:#a9a97f;color:#e3e3d1;border:1px solid #a9a97f}.action-btn.primary:hover{background:#969669;border-color:#969669}\n"] }]
1614
1613
  }], ctorParameters: () => [], propDecorators: { filters: [{ type: i0.Input, args: [{ isSignal: true, alias: "filters", required: false }] }], clearTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearTrigger", required: false }] }], filterSelected: [{ type: i0.Output, args: ["filterSelected"] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
1615
1614
 
1615
+ class Input {
1616
+ placeholder = input(...(ngDevMode ? [undefined, { debugName: "placeholder" }] : []));
1617
+ type = input('text', ...(ngDevMode ? [{ debugName: "type" }] : []));
1618
+ value = model('', ...(ngDevMode ? [{ debugName: "value" }] : []));
1619
+ valueChange = output();
1620
+ onSearch = output();
1621
+ onClear = output();
1622
+ clear() {
1623
+ this.value.set('');
1624
+ this.valueChange.emit('');
1625
+ this.onClear.emit();
1626
+ }
1627
+ search() {
1628
+ this.onSearch.emit(this.value());
1629
+ }
1630
+ handleInput(event) {
1631
+ const target = event.target;
1632
+ let inputValue = target.value;
1633
+ if (this.type() === 'number') {
1634
+ inputValue = inputValue.replace(/[^0-9]/g, '');
1635
+ target.value = inputValue;
1636
+ }
1637
+ this.value.set(inputValue);
1638
+ this.valueChange.emit(inputValue);
1639
+ }
1640
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Input, deps: [], target: i0.ɵɵFactoryTarget.Component });
1641
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: Input, isStandalone: true, selector: "lib-input", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", valueChange: "valueChange", onSearch: "onSearch", onClear: "onClear" }, ngImport: i0, template: "<div class=\"input-wrapper\">\r\n <input\r\n [type]=\"type()\"\r\n [placeholder]=\"placeholder()\"\r\n class=\"custom-input\"\r\n [value]=\"value()\"\r\n (input)=\"handleInput($event)\"\r\n (keyup.enter)=\"search()\"\r\n />\r\n\r\n @if (value()) {\r\n <button class=\"clear-btn\" (click)=\"clear()\" type=\"button\">\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n width=\"20\"\r\n height=\"20\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n >\r\n <path d=\"M18 6l-12 12\" />\r\n <path d=\"M6 6l12 12\" />\r\n </svg>\r\n </button>\r\n }\r\n\r\n <button class=\"search-btn\" (click)=\"search()\" type=\"button\">\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n width=\"56\"\r\n height=\"56\"\r\n fill=\"none\"\r\n viewBox=\"0 0 56 56\"\r\n >\r\n <g clip-path=\"url(#clip0_190_2403)\">\r\n <path\r\n fill=\"#454733\"\r\n d=\"M31.755 30.255h-.79l-.28-.27a6.47 6.47 0 0 0 1.57-4.23 6.5 6.5 0 1 0-6.5 6.5c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99 1.49-1.49zm-6 0c-2.49 0-4.5-2.01-4.5-4.5s2.01-4.5 4.5-4.5 4.5 2.01 4.5 4.5-2.01 4.5-4.5 4.5\"\r\n />\r\n </g>\r\n <defs>\r\n <clipPath id=\"clip0_190_2403\">\r\n <rect width=\"56\" height=\"56\" fill=\"#fff\" rx=\"28\" />\r\n </clipPath>\r\n </defs>\r\n </svg>\r\n </button>\r\n</div>\r\n", styles: [".input-wrapper{position:relative;width:100%}.custom-input{width:100%;padding:20px 50px 20px 20px;border-radius:32px;font-size:16px;background-color:#fff;border:none}custom-input::placeholder{color:#40484c;opacity:1}.custom-input:focus{outline:none;box-shadow:0 0 0 3px #8bc34a1a}.custom-input:hover{background-color:#d8dfe4;transform:translateY(-1px)}.clear-btn{position:absolute;right:55px;top:50%;transform:translateY(-50%);background:none;border:none;cursor:pointer;font-size:10px;color:#596300;padding:5px}.clear-btn svg{height:50px;pointer-events:none;transition:filter .2s ease}.clear-btn:hover{color:red}.clear-btn:hover svg{filter:brightness(0) saturate(100%) invert(27%) sepia(51%) saturate(2878%) hue-rotate(346deg) brightness(104%) contrast(97%)}.search-btn{position:absolute;right:5px;top:50%;transform:translateY(-50%);background:none;border:none;cursor:pointer;font-size:18px;border-radius:50%;background-color:#596300;display:flex;justify-content:center;align-items:center;width:50px;height:50px}.search-btn svg{filter:brightness(0) invert(1)}.search-btn:hover{background:#7cb342}input[type=number]::-webkit-outer-spin-button,input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}\n"] });
1642
+ }
1643
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Input, decorators: [{
1644
+ type: Component,
1645
+ args: [{ selector: 'lib-input', standalone: true, imports: [], template: "<div class=\"input-wrapper\">\r\n <input\r\n [type]=\"type()\"\r\n [placeholder]=\"placeholder()\"\r\n class=\"custom-input\"\r\n [value]=\"value()\"\r\n (input)=\"handleInput($event)\"\r\n (keyup.enter)=\"search()\"\r\n />\r\n\r\n @if (value()) {\r\n <button class=\"clear-btn\" (click)=\"clear()\" type=\"button\">\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n width=\"20\"\r\n height=\"20\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n >\r\n <path d=\"M18 6l-12 12\" />\r\n <path d=\"M6 6l12 12\" />\r\n </svg>\r\n </button>\r\n }\r\n\r\n <button class=\"search-btn\" (click)=\"search()\" type=\"button\">\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n width=\"56\"\r\n height=\"56\"\r\n fill=\"none\"\r\n viewBox=\"0 0 56 56\"\r\n >\r\n <g clip-path=\"url(#clip0_190_2403)\">\r\n <path\r\n fill=\"#454733\"\r\n d=\"M31.755 30.255h-.79l-.28-.27a6.47 6.47 0 0 0 1.57-4.23 6.5 6.5 0 1 0-6.5 6.5c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99 1.49-1.49zm-6 0c-2.49 0-4.5-2.01-4.5-4.5s2.01-4.5 4.5-4.5 4.5 2.01 4.5 4.5-2.01 4.5-4.5 4.5\"\r\n />\r\n </g>\r\n <defs>\r\n <clipPath id=\"clip0_190_2403\">\r\n <rect width=\"56\" height=\"56\" fill=\"#fff\" rx=\"28\" />\r\n </clipPath>\r\n </defs>\r\n </svg>\r\n </button>\r\n</div>\r\n", styles: [".input-wrapper{position:relative;width:100%}.custom-input{width:100%;padding:20px 50px 20px 20px;border-radius:32px;font-size:16px;background-color:#fff;border:none}custom-input::placeholder{color:#40484c;opacity:1}.custom-input:focus{outline:none;box-shadow:0 0 0 3px #8bc34a1a}.custom-input:hover{background-color:#d8dfe4;transform:translateY(-1px)}.clear-btn{position:absolute;right:55px;top:50%;transform:translateY(-50%);background:none;border:none;cursor:pointer;font-size:10px;color:#596300;padding:5px}.clear-btn svg{height:50px;pointer-events:none;transition:filter .2s ease}.clear-btn:hover{color:red}.clear-btn:hover svg{filter:brightness(0) saturate(100%) invert(27%) sepia(51%) saturate(2878%) hue-rotate(346deg) brightness(104%) contrast(97%)}.search-btn{position:absolute;right:5px;top:50%;transform:translateY(-50%);background:none;border:none;cursor:pointer;font-size:18px;border-radius:50%;background-color:#596300;display:flex;justify-content:center;align-items:center;width:50px;height:50px}.search-btn svg{filter:brightness(0) invert(1)}.search-btn:hover{background:#7cb342}input[type=number]::-webkit-outer-spin-button,input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}\n"] }]
1646
+ }], propDecorators: { placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], onSearch: [{ type: i0.Output, args: ["onSearch"] }], onClear: [{ type: i0.Output, args: ["onClear"] }] } });
1647
+
1616
1648
  class SelectCustomSearch {
1617
1649
  elementRef;
1618
1650
  options = input([], ...(ngDevMode ? [{ debugName: "options" }] : []));
@@ -1711,8 +1743,8 @@ class SelectCustomSearch {
1711
1743
  this.close();
1712
1744
  }
1713
1745
  }
1714
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SelectCustomSearch, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
1715
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: SelectCustomSearch, isStandalone: true, selector: "lib-select-custom-search", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, providers: [
1746
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: SelectCustomSearch, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
1747
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: SelectCustomSearch, isStandalone: true, selector: "lib-select-custom-search", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, providers: [
1716
1748
  {
1717
1749
  provide: NG_VALUE_ACCESSOR,
1718
1750
  useExisting: forwardRef(() => SelectCustomSearch),
@@ -1720,7 +1752,7 @@ class SelectCustomSearch {
1720
1752
  },
1721
1753
  ], ngImport: i0, template: "<div class=\"select-container\">\r\n <div\r\n class=\"select-header\"\r\n [class.active]=\"isOpen()\"\r\n [class.disabled]=\"isBlocked()\"\r\n [class.readonly]=\"isBlocked()\"\r\n (click)=\"!isBlocked() && toggle()\"\r\n (keydown)=\"!isBlocked() && onKeyDown($event)\"\r\n tabindex=\"0\"\r\n >\r\n <span class=\"selected-text\" [class.placeholder]=\"!selectedOption()\">\r\n {{ selectedOption()?.label || placeholder() }}\r\n </span>\r\n\r\n <span class=\"arrow\" [class.open]=\"isOpen()\"></span>\r\n </div>\r\n\r\n @if (isOpen()) {\r\n <div class=\"dropdown\">\r\n <input\r\n type=\"text\"\r\n class=\"search-input\"\r\n [value]=\"searchTerm()\"\r\n placeholder=\"Buscar...\"\r\n (input)=\"!isBlocked() &&onSearch($event)\"\r\n (keydown)=\"!isBlocked() && onKeyDown($event)\"\r\n />\r\n\r\n @if (filteredOptions().length > 0) {\r\n <div class=\"options\">\r\n @for (option of filteredOptions(); track option.value) {\r\n <div\r\n class=\"option\"\r\n [class.selected]=\"option.value === selectedValue()\"\r\n (click)=\"!isBlocked() && selectOption(option)\"\r\n [attr.disabled]=\"isBlocked()\"\r\n >\r\n {{ option.label }}\r\n </div>\r\n }\r\n </div>\r\n } @else {\r\n <div class=\"no-results\">No se encontraron resultados</div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".select-container{position:relative;width:100%}.select-header{width:100%;border:1px solid #787861;border-radius:5px;padding:15px;background-color:transparent;cursor:pointer;display:flex;justify-content:space-between;align-items:center;min-height:auto}.select-header:hover,.select-header:focus{outline:none;border-color:#a9a97f}.select-header.active{border-color:#a9a97f;outline:none}.select-header.disabled,.select-header.readonly{cursor:not-allowed;opacity:.6;pointer-events:none}.selected-text{color:#454733;font-size:1.3rem}.selected-text.placeholder{color:#787861}.arrow{width:15px;height:15px;background-image:url(\"data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e\");background-repeat:no-repeat;background-size:15px;background-position:center;color:#787861;flex-shrink:0;transition:transform .2s}.arrow.open{transform:rotate(180deg)}.dropdown{position:absolute;top:100%;left:0;right:0;background:#e3e3d1;border:1px solid #787861;border-top:none;border-radius:0 0 5px 5px;max-height:250px;overflow:hidden;z-index:1000;box-shadow:0 2px 8px #0000001a}.search-input{width:100%;border:none;border-bottom:1px solid #787861;border-radius:0;padding:15px;background-color:transparent;outline:none;font-size:inherit;color:#454733;font-size:1.3rem}.search-input::placeholder{color:#787861}.search-input:focus{outline:none;border-bottom-color:#a9a97f}.options{max-height:180px;overflow-y:auto;background:#e3e3d1}.option{padding:15px;cursor:pointer;border-bottom:1px solid rgba(120,120,97,.2);color:#454733;background:#e3e3d1;font-size:1.3rem}.option:hover{background-color:#a9a97f1a;color:#454733}.option.selected{background-color:#a9a97f;color:#e3e3d1;font-weight:500}.option:last-child{border-bottom:none}.no-results{padding:15px;text-align:center;color:#787861;font-style:italic;background:#e3e3d1;font-size:1.3rem}.options::-webkit-scrollbar{width:6px}.options::-webkit-scrollbar-track{background:#7878611a}.options::-webkit-scrollbar-thumb{background:#787861;border-radius:3px}.options::-webkit-scrollbar-thumb:hover{background:#a9a97f}@media (max-width: 768px){.select-header,.search-input,.option{padding:12px 15px}}\n"] });
1722
1754
  }
1723
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SelectCustomSearch, decorators: [{
1755
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: SelectCustomSearch, decorators: [{
1724
1756
  type: Component,
1725
1757
  args: [{ selector: 'lib-select-custom-search', imports: [], providers: [
1726
1758
  {
@@ -1840,12 +1872,12 @@ class DynamicFormFields {
1840
1872
  }
1841
1873
  onCancel() {
1842
1874
  }
1843
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DynamicFormFields, deps: [], target: i0.ɵɵFactoryTarget.Component });
1844
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DynamicFormFields, isStandalone: true, selector: "lib-dynamic-form-fields", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null }, sections: { classPropertyName: "sections", publicName: "sections", isSignal: true, isRequired: false, transformFunction: null }, compact: { classPropertyName: "compact", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (form()) {\r\n<form class=\"form\" [formGroup]=\"form()\" [class.form--compact]=\"compact()\">\r\n @for (sec of sections(); track $index) {\r\n <section class=\"section\">\r\n @if (sec.title) {\r\n <h3 class=\"section-title\">{{ sec.title }}</h3>\r\n } @if (sec.description) {\r\n <p class=\"section-desc\">{{ sec.description }}</p>\r\n }\r\n\r\n <div class=\"grid\">\r\n @for (f of sec.fields; track f.key) {\r\n <div class=\"col\" [style.--col-span]=\"f.col || 6\">\r\n @if(f.label) {\r\n <label\r\n [class.label-radio]=\"f.type === 'radio'\"\r\n [class.label-checkbox]=\"f.type === 'checkbox'\"\r\n [class.label-disabled]=\"f.readonly || f.disabled\"\r\n class=\"label\"\r\n >\r\n {{ f.label }} </label\r\n >} @if (['text','number','email', 'password', 'time'].includes(f.type))\r\n {\r\n <input\r\n class=\"input\"\r\n [type]=\"f.type\"\r\n [placeholder]=\"f.placeholder\"\r\n [formControlName]=\"f.key\"\r\n [disabled]=\"f.disabled || false\"\r\n [readonly]=\"f.readonly || false\"\r\n />\r\n } @if (['date', 'datetime-local'].includes(f.type)) {\r\n <lib-date-time-picker\r\n [mode]=\"getDatePickerMode(f.type)\"\r\n [placeholder]=\"\r\n f.placeholder ||\r\n (f.type === 'date'\r\n ? 'Seleccionar fecha'\r\n : 'Seleccionar fecha y hora')\r\n \"\r\n [formControlName]=\"f.key\"\r\n [minDate]=\"f.minDate || null\"\r\n [maxDate]=\"f.maxDate || null\"\r\n [readonly]=\"f.readonly || false\"\r\n [disabled]=\"f.disabled || false\"\r\n />\r\n } @if (f.type === 'textarea') {\r\n <textarea\r\n class=\"input textarea\"\r\n [placeholder]=\"f.placeholder\"\r\n [formControlName]=\"f.key\"\r\n rows=\"6\"\r\n [readonly]=\"f.readonly || false\"\r\n [disabled]=\"f.disabled || false\"\r\n ></textarea>\r\n }@if (f.type === 'select') {\r\n\r\n <lib-select-custom-search\r\n [options]=\"f.options ?? []\"\r\n [placeholder]=\"f.placeholder || 'Seleccionar...'\"\r\n [formControlName]=\"f.key\"\r\n [readonly]=\"f.readonly || false\"\r\n [disabled]=\"f.disabled || false\"\r\n />\r\n } @if (f.type === 'radio') {\r\n <div class=\"radio-group\">\r\n @for (o of f.options ?? []; track o.value) {\r\n <label class=\"radio\">\r\n {{ o.label }}\r\n <input type=\"radio\" [value]=\"o.value\" [formControlName]=\"f.key\" [readonly]=\"f.readonly || false\"\r\n [disabled]=\"f.disabled || false\" />\r\n </label>\r\n }\r\n </div>\r\n } @if (f.type === 'checkbox') {\r\n <div class=\"checkbox-group\">\r\n @for (o of f.options ?? []; track o.value; let i = $index) {\r\n <label class=\"checkbox\">\r\n {{ o.label }}\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"getCheckboxArray(f.key).at(i).value\"\r\n (change)=\"onCheckboxChange($event, f.key, i)\"\r\n />\r\n </label>\r\n }\r\n </div>\r\n } @if (f.type === 'disabled') {\r\n <label class=\"label\">{{ f.label }}</label>\r\n <input\r\n class=\"input input--disabled\"\r\n [placeholder]=\"f.placeholder || 'Autom\u00E1tico'\"\r\n disabled\r\n />\r\n } @if (ctrl(f.key)?.touched && ctrl(f.key)?.invalid) {\r\n <div class=\"error\">\r\n @if (ctrl(f.key)?.errors?.['required']) {\r\n <span>Campo requerido</span>\r\n } @if (ctrl(f.key)?.errors?.['email']) {\r\n <span>Correo inv\u00E1lido</span>\r\n } @if (ctrl(f.key)?.errors?.['pattern']) {\r\n <span>\r\n @switch (f.patternType) { @case ('numbers') { Solo se permiten\r\n n\u00FAmeros } @case ('phone') { Formato de tel\u00E9fono inv\u00E1lido } @case\r\n ('text') { Solo se permiten letras y espacios } @case ('username') {\r\n Solo se permiten letras, n\u00FAmeros, puntos y guiones bajos (no al\r\n inicio ni al final) } @case ('alphanumeric') { Solo se permiten\r\n letras y n\u00FAmeros } @default { Formato inv\u00E1lido } }\r\n </span>\r\n } @if (ctrl(f.key)?.errors?.['notMatching']) {\r\n <span>Las contrase\u00F1as no coinciden</span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </section>\r\n }\r\n</form>\r\n}\r\n", styles: [".form{width:100%}.form{display:grid}.section{padding:20px 0 0}.section-title{font-size:1.6rem;font-weight:700;margin-bottom:30px}.section-desc{margin:0 0 .75rem;color:#666}.grid{display:grid;grid-template-columns:repeat(12,1fr);gap:16px}.col{grid-column:span var(--col-span, 6);min-width:0;width:100%;position:relative;padding-bottom:20px}.label{position:absolute;top:-8px;left:12px;font-size:1.2rem;color:#454733;background-color:var(--surface-container-high, #ebe8d6);padding:0 4px;font-weight:500;z-index:1}.input{width:100%;border:1px solid #787861;border-radius:5px;padding:15px;background-color:transparent}input[type=number]::-webkit-outer-spin-button,input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}input[type=date]::-webkit-calendar-picker-indicator{position:absolute;inset:0;width:auto;height:auto;color:transparent;background:transparent}.input:focus{outline:none;border-color:#a9a97f}.input--disabled{color:#888}.label-radio{font-size:1.4rem;position:static;padding-left:0}.radio-group{display:flex;gap:1rem;padding:.5rem 0}.radio{font-size:1.4rem;display:flex;align-items:center;gap:10px;color:#1c1c12;margin-top:20px}.error{position:absolute;bottom:0;left:0;font-size:1.2rem;color:#b00020;width:100%;height:15px;display:none}.col:has(.error) .error{display:block}.textarea{resize:vertical;min-height:100px;line-height:1.5}select{appearance:none;-webkit-appearance:none;-moz-appearance:none;background-image:url(\"data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e\");background-repeat:no-repeat;background-size:15px;background-position:right 15px center;cursor:pointer}select:invalid{color:#787861}select.placeholder-selected{color:#787861}select:not(.placeholder-selected){color:#000}select option{color:#454733;cursor:pointer}input[type=date]{color:#787861!important}input[type=date]:valid{color:#454733!important}.label-disabled{color:#1c1c1266}.input:disabled,.input--disabled,.input.disabled,.input[readonly]{border:1px solid #a9a97f;color:#a9a97f;cursor:not-allowed;pointer-events:none}@media (max-width: 768px){.grid{grid-template-columns:1fr}.col{grid-column:span 1!important}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.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$1.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: SelectCustomSearch, selector: "lib-select-custom-search", inputs: ["options", "placeholder", "readonly"], outputs: ["selectionChange"] }, { kind: "component", type: DateTimePicker, selector: "lib-date-time-picker", inputs: ["mode", "placeholder", "minDate", "maxDate", "readonly"], outputs: ["dateChange"] }] });
1875
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DynamicFormFields, deps: [], target: i0.ɵɵFactoryTarget.Component });
1876
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DynamicFormFields, isStandalone: true, selector: "lib-dynamic-form-fields", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null }, sections: { classPropertyName: "sections", publicName: "sections", isSignal: true, isRequired: false, transformFunction: null }, compact: { classPropertyName: "compact", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (form()) {\r\n<form class=\"form\" [formGroup]=\"form()\" [class.form--compact]=\"compact()\">\r\n @for (sec of sections(); track $index) {\r\n <section class=\"section\">\r\n @if (sec.title) {\r\n <h3 class=\"section-title\">{{ sec.title }}</h3>\r\n } @if (sec.description) {\r\n <p class=\"section-desc\">{{ sec.description }}</p>\r\n }\r\n\r\n <div class=\"grid\">\r\n @for (f of sec.fields; track f.key) {\r\n <div class=\"col\" [style.--col-span]=\"f.col || 6\">\r\n @if(f.label) {\r\n <label\r\n [class.label-radio]=\"f.type === 'radio'\"\r\n [class.label-checkbox]=\"f.type === 'checkbox'\"\r\n [class.label-disabled]=\"f.readonly || f.disabled\"\r\n class=\"label\"\r\n >\r\n {{ f.label }} </label\r\n >} @if (['text','number','email', 'password', 'time'].includes(f.type))\r\n {\r\n <input\r\n class=\"input\"\r\n [type]=\"f.type\"\r\n [placeholder]=\"f.placeholder\"\r\n [formControlName]=\"f.key\"\r\n [disabled]=\"f.disabled || false\"\r\n [readonly]=\"f.readonly || false\"\r\n />\r\n } @if (['date', 'datetime-local'].includes(f.type)) {\r\n <lib-date-time-picker\r\n [mode]=\"getDatePickerMode(f.type)\"\r\n [placeholder]=\"\r\n f.placeholder ||\r\n (f.type === 'date'\r\n ? 'Seleccionar fecha'\r\n : 'Seleccionar fecha y hora')\r\n \"\r\n [formControlName]=\"f.key\"\r\n [minDate]=\"f.minDate || null\"\r\n [maxDate]=\"f.maxDate || null\"\r\n [readonly]=\"f.readonly || false\"\r\n [disabled]=\"f.disabled || false\"\r\n />\r\n } @if (f.type === 'textarea') {\r\n <textarea\r\n class=\"input textarea\"\r\n [placeholder]=\"f.placeholder\"\r\n [formControlName]=\"f.key\"\r\n rows=\"6\"\r\n [readonly]=\"f.readonly || false\"\r\n [disabled]=\"f.disabled || false\"\r\n ></textarea>\r\n }@if (f.type === 'select') {\r\n\r\n <lib-select-custom-search\r\n [options]=\"f.options ?? []\"\r\n [placeholder]=\"f.placeholder || 'Seleccionar...'\"\r\n [formControlName]=\"f.key\"\r\n [readonly]=\"f.readonly || false\"\r\n [disabled]=\"f.disabled || false\"\r\n />\r\n } @if (f.type === 'radio') {\r\n <div class=\"radio-group\">\r\n @for (o of f.options ?? []; track o.value) {\r\n <label class=\"radio\">\r\n {{ o.label }}\r\n <input type=\"radio\" [value]=\"o.value\" [formControlName]=\"f.key\" [readonly]=\"f.readonly || false\"\r\n [disabled]=\"f.disabled || false\" />\r\n </label>\r\n }\r\n </div>\r\n } @if (f.type === 'checkbox') {\r\n <div class=\"checkbox-group\">\r\n @for (o of f.options ?? []; track o.value; let i = $index) {\r\n <label class=\"checkbox\">\r\n {{ o.label }}\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"getCheckboxArray(f.key).at(i).value\"\r\n (change)=\"onCheckboxChange($event, f.key, i)\"\r\n />\r\n </label>\r\n }\r\n </div>\r\n } @if (f.type === 'disabled') {\r\n <label class=\"label\">{{ f.label }}</label>\r\n <input\r\n class=\"input input--disabled\"\r\n [placeholder]=\"f.placeholder || 'Autom\u00E1tico'\"\r\n disabled\r\n />\r\n } @if (ctrl(f.key)?.touched && ctrl(f.key)?.invalid) {\r\n <div class=\"error\">\r\n @if (ctrl(f.key)?.errors?.['required']) {\r\n <span>Campo requerido</span>\r\n } @if (ctrl(f.key)?.errors?.['email']) {\r\n <span>Correo inv\u00E1lido</span>\r\n } @if (ctrl(f.key)?.errors?.['pattern']) {\r\n <span>\r\n @switch (f.patternType) { @case ('numbers') { Solo se permiten\r\n n\u00FAmeros } @case ('phone') { Formato de tel\u00E9fono inv\u00E1lido } @case\r\n ('text') { Solo se permiten letras y espacios } @case ('username') {\r\n Solo se permiten letras, n\u00FAmeros, puntos y guiones bajos (no al\r\n inicio ni al final) } @case ('alphanumeric') { Solo se permiten\r\n letras y n\u00FAmeros } @default { Formato inv\u00E1lido } }\r\n </span>\r\n } @if (ctrl(f.key)?.errors?.['notMatching']) {\r\n <span>Las contrase\u00F1as no coinciden</span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </section>\r\n }\r\n</form>\r\n}\r\n", styles: [".form{width:100%}.form{display:grid}.section{padding:20px 0 0}.section-title{font-size:1.6rem;font-weight:700;margin-bottom:30px}.section-desc{margin:0 0 .75rem;color:#666}.grid{display:grid;grid-template-columns:repeat(12,1fr);gap:16px}.col{grid-column:span var(--col-span, 6);min-width:0;width:100%;position:relative;padding-bottom:20px}.label{position:absolute;top:-8px;left:12px;font-size:1.2rem;color:#454733;background-color:var(--surface-container-high, #ebe8d6);padding:0 4px;font-weight:500;z-index:1}.input{width:100%;border:1px solid #787861;border-radius:5px;padding:15px;background-color:transparent}input[type=number]::-webkit-outer-spin-button,input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}input[type=date]::-webkit-calendar-picker-indicator{position:absolute;inset:0;width:auto;height:auto;color:transparent;background:transparent}.input:focus{outline:none;border-color:#a9a97f}.input--disabled{color:#888}.label-radio{font-size:1.4rem;position:static;padding-left:0}.radio-group{display:flex;gap:1rem;padding:.5rem 0}.radio{font-size:1.4rem;display:flex;align-items:center;gap:10px;color:#1c1c12;margin-top:20px}.error{position:absolute;bottom:0;left:0;font-size:1.2rem;color:#b00020;width:100%;height:15px;display:none}.col:has(.error) .error{display:block}.textarea{resize:vertical;min-height:100px;max-height:300px;line-height:1.5}select{appearance:none;-webkit-appearance:none;-moz-appearance:none;background-image:url(\"data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e\");background-repeat:no-repeat;background-size:15px;background-position:right 15px center;cursor:pointer}select:invalid{color:#787861}select.placeholder-selected{color:#787861}select:not(.placeholder-selected){color:#000}select option{color:#454733;cursor:pointer}input[type=date]{color:#787861!important}input[type=date]:valid{color:#454733!important}.label-disabled{color:#1c1c1266}.input:disabled,.input--disabled,.input.disabled,.input[readonly]{border:1px solid #a9a97f;color:#a9a97f;cursor:not-allowed;pointer-events:none}@media (max-width: 768px){.grid{grid-template-columns:1fr}.col{grid-column:span 1!important}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.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$1.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: SelectCustomSearch, selector: "lib-select-custom-search", inputs: ["options", "placeholder", "readonly"], outputs: ["selectionChange"] }, { kind: "component", type: DateTimePicker, selector: "lib-date-time-picker", inputs: ["mode", "placeholder", "minDate", "maxDate", "readonly"], outputs: ["dateChange"] }] });
1845
1877
  }
1846
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DynamicFormFields, decorators: [{
1878
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DynamicFormFields, decorators: [{
1847
1879
  type: Component,
1848
- args: [{ selector: 'lib-dynamic-form-fields', standalone: true, imports: [ReactiveFormsModule, SelectCustomSearch, DateTimePicker], template: "@if (form()) {\r\n<form class=\"form\" [formGroup]=\"form()\" [class.form--compact]=\"compact()\">\r\n @for (sec of sections(); track $index) {\r\n <section class=\"section\">\r\n @if (sec.title) {\r\n <h3 class=\"section-title\">{{ sec.title }}</h3>\r\n } @if (sec.description) {\r\n <p class=\"section-desc\">{{ sec.description }}</p>\r\n }\r\n\r\n <div class=\"grid\">\r\n @for (f of sec.fields; track f.key) {\r\n <div class=\"col\" [style.--col-span]=\"f.col || 6\">\r\n @if(f.label) {\r\n <label\r\n [class.label-radio]=\"f.type === 'radio'\"\r\n [class.label-checkbox]=\"f.type === 'checkbox'\"\r\n [class.label-disabled]=\"f.readonly || f.disabled\"\r\n class=\"label\"\r\n >\r\n {{ f.label }} </label\r\n >} @if (['text','number','email', 'password', 'time'].includes(f.type))\r\n {\r\n <input\r\n class=\"input\"\r\n [type]=\"f.type\"\r\n [placeholder]=\"f.placeholder\"\r\n [formControlName]=\"f.key\"\r\n [disabled]=\"f.disabled || false\"\r\n [readonly]=\"f.readonly || false\"\r\n />\r\n } @if (['date', 'datetime-local'].includes(f.type)) {\r\n <lib-date-time-picker\r\n [mode]=\"getDatePickerMode(f.type)\"\r\n [placeholder]=\"\r\n f.placeholder ||\r\n (f.type === 'date'\r\n ? 'Seleccionar fecha'\r\n : 'Seleccionar fecha y hora')\r\n \"\r\n [formControlName]=\"f.key\"\r\n [minDate]=\"f.minDate || null\"\r\n [maxDate]=\"f.maxDate || null\"\r\n [readonly]=\"f.readonly || false\"\r\n [disabled]=\"f.disabled || false\"\r\n />\r\n } @if (f.type === 'textarea') {\r\n <textarea\r\n class=\"input textarea\"\r\n [placeholder]=\"f.placeholder\"\r\n [formControlName]=\"f.key\"\r\n rows=\"6\"\r\n [readonly]=\"f.readonly || false\"\r\n [disabled]=\"f.disabled || false\"\r\n ></textarea>\r\n }@if (f.type === 'select') {\r\n\r\n <lib-select-custom-search\r\n [options]=\"f.options ?? []\"\r\n [placeholder]=\"f.placeholder || 'Seleccionar...'\"\r\n [formControlName]=\"f.key\"\r\n [readonly]=\"f.readonly || false\"\r\n [disabled]=\"f.disabled || false\"\r\n />\r\n } @if (f.type === 'radio') {\r\n <div class=\"radio-group\">\r\n @for (o of f.options ?? []; track o.value) {\r\n <label class=\"radio\">\r\n {{ o.label }}\r\n <input type=\"radio\" [value]=\"o.value\" [formControlName]=\"f.key\" [readonly]=\"f.readonly || false\"\r\n [disabled]=\"f.disabled || false\" />\r\n </label>\r\n }\r\n </div>\r\n } @if (f.type === 'checkbox') {\r\n <div class=\"checkbox-group\">\r\n @for (o of f.options ?? []; track o.value; let i = $index) {\r\n <label class=\"checkbox\">\r\n {{ o.label }}\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"getCheckboxArray(f.key).at(i).value\"\r\n (change)=\"onCheckboxChange($event, f.key, i)\"\r\n />\r\n </label>\r\n }\r\n </div>\r\n } @if (f.type === 'disabled') {\r\n <label class=\"label\">{{ f.label }}</label>\r\n <input\r\n class=\"input input--disabled\"\r\n [placeholder]=\"f.placeholder || 'Autom\u00E1tico'\"\r\n disabled\r\n />\r\n } @if (ctrl(f.key)?.touched && ctrl(f.key)?.invalid) {\r\n <div class=\"error\">\r\n @if (ctrl(f.key)?.errors?.['required']) {\r\n <span>Campo requerido</span>\r\n } @if (ctrl(f.key)?.errors?.['email']) {\r\n <span>Correo inv\u00E1lido</span>\r\n } @if (ctrl(f.key)?.errors?.['pattern']) {\r\n <span>\r\n @switch (f.patternType) { @case ('numbers') { Solo se permiten\r\n n\u00FAmeros } @case ('phone') { Formato de tel\u00E9fono inv\u00E1lido } @case\r\n ('text') { Solo se permiten letras y espacios } @case ('username') {\r\n Solo se permiten letras, n\u00FAmeros, puntos y guiones bajos (no al\r\n inicio ni al final) } @case ('alphanumeric') { Solo se permiten\r\n letras y n\u00FAmeros } @default { Formato inv\u00E1lido } }\r\n </span>\r\n } @if (ctrl(f.key)?.errors?.['notMatching']) {\r\n <span>Las contrase\u00F1as no coinciden</span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </section>\r\n }\r\n</form>\r\n}\r\n", styles: [".form{width:100%}.form{display:grid}.section{padding:20px 0 0}.section-title{font-size:1.6rem;font-weight:700;margin-bottom:30px}.section-desc{margin:0 0 .75rem;color:#666}.grid{display:grid;grid-template-columns:repeat(12,1fr);gap:16px}.col{grid-column:span var(--col-span, 6);min-width:0;width:100%;position:relative;padding-bottom:20px}.label{position:absolute;top:-8px;left:12px;font-size:1.2rem;color:#454733;background-color:var(--surface-container-high, #ebe8d6);padding:0 4px;font-weight:500;z-index:1}.input{width:100%;border:1px solid #787861;border-radius:5px;padding:15px;background-color:transparent}input[type=number]::-webkit-outer-spin-button,input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}input[type=date]::-webkit-calendar-picker-indicator{position:absolute;inset:0;width:auto;height:auto;color:transparent;background:transparent}.input:focus{outline:none;border-color:#a9a97f}.input--disabled{color:#888}.label-radio{font-size:1.4rem;position:static;padding-left:0}.radio-group{display:flex;gap:1rem;padding:.5rem 0}.radio{font-size:1.4rem;display:flex;align-items:center;gap:10px;color:#1c1c12;margin-top:20px}.error{position:absolute;bottom:0;left:0;font-size:1.2rem;color:#b00020;width:100%;height:15px;display:none}.col:has(.error) .error{display:block}.textarea{resize:vertical;min-height:100px;line-height:1.5}select{appearance:none;-webkit-appearance:none;-moz-appearance:none;background-image:url(\"data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e\");background-repeat:no-repeat;background-size:15px;background-position:right 15px center;cursor:pointer}select:invalid{color:#787861}select.placeholder-selected{color:#787861}select:not(.placeholder-selected){color:#000}select option{color:#454733;cursor:pointer}input[type=date]{color:#787861!important}input[type=date]:valid{color:#454733!important}.label-disabled{color:#1c1c1266}.input:disabled,.input--disabled,.input.disabled,.input[readonly]{border:1px solid #a9a97f;color:#a9a97f;cursor:not-allowed;pointer-events:none}@media (max-width: 768px){.grid{grid-template-columns:1fr}.col{grid-column:span 1!important}}\n"] }]
1880
+ args: [{ selector: 'lib-dynamic-form-fields', standalone: true, imports: [ReactiveFormsModule, SelectCustomSearch, DateTimePicker], template: "@if (form()) {\r\n<form class=\"form\" [formGroup]=\"form()\" [class.form--compact]=\"compact()\">\r\n @for (sec of sections(); track $index) {\r\n <section class=\"section\">\r\n @if (sec.title) {\r\n <h3 class=\"section-title\">{{ sec.title }}</h3>\r\n } @if (sec.description) {\r\n <p class=\"section-desc\">{{ sec.description }}</p>\r\n }\r\n\r\n <div class=\"grid\">\r\n @for (f of sec.fields; track f.key) {\r\n <div class=\"col\" [style.--col-span]=\"f.col || 6\">\r\n @if(f.label) {\r\n <label\r\n [class.label-radio]=\"f.type === 'radio'\"\r\n [class.label-checkbox]=\"f.type === 'checkbox'\"\r\n [class.label-disabled]=\"f.readonly || f.disabled\"\r\n class=\"label\"\r\n >\r\n {{ f.label }} </label\r\n >} @if (['text','number','email', 'password', 'time'].includes(f.type))\r\n {\r\n <input\r\n class=\"input\"\r\n [type]=\"f.type\"\r\n [placeholder]=\"f.placeholder\"\r\n [formControlName]=\"f.key\"\r\n [disabled]=\"f.disabled || false\"\r\n [readonly]=\"f.readonly || false\"\r\n />\r\n } @if (['date', 'datetime-local'].includes(f.type)) {\r\n <lib-date-time-picker\r\n [mode]=\"getDatePickerMode(f.type)\"\r\n [placeholder]=\"\r\n f.placeholder ||\r\n (f.type === 'date'\r\n ? 'Seleccionar fecha'\r\n : 'Seleccionar fecha y hora')\r\n \"\r\n [formControlName]=\"f.key\"\r\n [minDate]=\"f.minDate || null\"\r\n [maxDate]=\"f.maxDate || null\"\r\n [readonly]=\"f.readonly || false\"\r\n [disabled]=\"f.disabled || false\"\r\n />\r\n } @if (f.type === 'textarea') {\r\n <textarea\r\n class=\"input textarea\"\r\n [placeholder]=\"f.placeholder\"\r\n [formControlName]=\"f.key\"\r\n rows=\"6\"\r\n [readonly]=\"f.readonly || false\"\r\n [disabled]=\"f.disabled || false\"\r\n ></textarea>\r\n }@if (f.type === 'select') {\r\n\r\n <lib-select-custom-search\r\n [options]=\"f.options ?? []\"\r\n [placeholder]=\"f.placeholder || 'Seleccionar...'\"\r\n [formControlName]=\"f.key\"\r\n [readonly]=\"f.readonly || false\"\r\n [disabled]=\"f.disabled || false\"\r\n />\r\n } @if (f.type === 'radio') {\r\n <div class=\"radio-group\">\r\n @for (o of f.options ?? []; track o.value) {\r\n <label class=\"radio\">\r\n {{ o.label }}\r\n <input type=\"radio\" [value]=\"o.value\" [formControlName]=\"f.key\" [readonly]=\"f.readonly || false\"\r\n [disabled]=\"f.disabled || false\" />\r\n </label>\r\n }\r\n </div>\r\n } @if (f.type === 'checkbox') {\r\n <div class=\"checkbox-group\">\r\n @for (o of f.options ?? []; track o.value; let i = $index) {\r\n <label class=\"checkbox\">\r\n {{ o.label }}\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"getCheckboxArray(f.key).at(i).value\"\r\n (change)=\"onCheckboxChange($event, f.key, i)\"\r\n />\r\n </label>\r\n }\r\n </div>\r\n } @if (f.type === 'disabled') {\r\n <label class=\"label\">{{ f.label }}</label>\r\n <input\r\n class=\"input input--disabled\"\r\n [placeholder]=\"f.placeholder || 'Autom\u00E1tico'\"\r\n disabled\r\n />\r\n } @if (ctrl(f.key)?.touched && ctrl(f.key)?.invalid) {\r\n <div class=\"error\">\r\n @if (ctrl(f.key)?.errors?.['required']) {\r\n <span>Campo requerido</span>\r\n } @if (ctrl(f.key)?.errors?.['email']) {\r\n <span>Correo inv\u00E1lido</span>\r\n } @if (ctrl(f.key)?.errors?.['pattern']) {\r\n <span>\r\n @switch (f.patternType) { @case ('numbers') { Solo se permiten\r\n n\u00FAmeros } @case ('phone') { Formato de tel\u00E9fono inv\u00E1lido } @case\r\n ('text') { Solo se permiten letras y espacios } @case ('username') {\r\n Solo se permiten letras, n\u00FAmeros, puntos y guiones bajos (no al\r\n inicio ni al final) } @case ('alphanumeric') { Solo se permiten\r\n letras y n\u00FAmeros } @default { Formato inv\u00E1lido } }\r\n </span>\r\n } @if (ctrl(f.key)?.errors?.['notMatching']) {\r\n <span>Las contrase\u00F1as no coinciden</span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </section>\r\n }\r\n</form>\r\n}\r\n", styles: [".form{width:100%}.form{display:grid}.section{padding:20px 0 0}.section-title{font-size:1.6rem;font-weight:700;margin-bottom:30px}.section-desc{margin:0 0 .75rem;color:#666}.grid{display:grid;grid-template-columns:repeat(12,1fr);gap:16px}.col{grid-column:span var(--col-span, 6);min-width:0;width:100%;position:relative;padding-bottom:20px}.label{position:absolute;top:-8px;left:12px;font-size:1.2rem;color:#454733;background-color:var(--surface-container-high, #ebe8d6);padding:0 4px;font-weight:500;z-index:1}.input{width:100%;border:1px solid #787861;border-radius:5px;padding:15px;background-color:transparent}input[type=number]::-webkit-outer-spin-button,input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}input[type=date]::-webkit-calendar-picker-indicator{position:absolute;inset:0;width:auto;height:auto;color:transparent;background:transparent}.input:focus{outline:none;border-color:#a9a97f}.input--disabled{color:#888}.label-radio{font-size:1.4rem;position:static;padding-left:0}.radio-group{display:flex;gap:1rem;padding:.5rem 0}.radio{font-size:1.4rem;display:flex;align-items:center;gap:10px;color:#1c1c12;margin-top:20px}.error{position:absolute;bottom:0;left:0;font-size:1.2rem;color:#b00020;width:100%;height:15px;display:none}.col:has(.error) .error{display:block}.textarea{resize:vertical;min-height:100px;max-height:300px;line-height:1.5}select{appearance:none;-webkit-appearance:none;-moz-appearance:none;background-image:url(\"data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e\");background-repeat:no-repeat;background-size:15px;background-position:right 15px center;cursor:pointer}select:invalid{color:#787861}select.placeholder-selected{color:#787861}select:not(.placeholder-selected){color:#000}select option{color:#454733;cursor:pointer}input[type=date]{color:#787861!important}input[type=date]:valid{color:#454733!important}.label-disabled{color:#1c1c1266}.input:disabled,.input--disabled,.input.disabled,.input[readonly]{border:1px solid #a9a97f;color:#a9a97f;cursor:not-allowed;pointer-events:none}@media (max-width: 768px){.grid{grid-template-columns:1fr}.col{grid-column:span 1!important}}\n"] }]
1849
1881
  }], propDecorators: { form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: true }] }], sections: [{ type: i0.Input, args: [{ isSignal: true, alias: "sections", required: false }] }], compact: [{ type: i0.Input, args: [{ isSignal: true, alias: "compact", required: false }] }] } });
1850
1882
 
1851
1883
  class WizardForm {
@@ -1883,10 +1915,10 @@ class WizardForm {
1883
1915
  const index = this.currentStep() - 1;
1884
1916
  return this.steps()[index].component;
1885
1917
  }, ...(ngDevMode ? [{ debugName: "currentGroupComponent" }] : []));
1886
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: WizardForm, deps: [], target: i0.ɵɵFactoryTarget.Component });
1887
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: WizardForm, isStandalone: true, selector: "lib-wizard-form", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null }, currentStep: { classPropertyName: "currentStep", publicName: "currentStep", isSignal: true, isRequired: false, transformFunction: null }, steps: { classPropertyName: "steps", publicName: "steps", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { canContinue: "canContinue" }, ngImport: i0, template: "<ng-container>\r\n\r\n @if (currentGroup()) {\r\n <ng-container\r\n *ngComponentOutlet=\"currentGroupComponent(); inputs: { group: currentGroup() }\"\r\n ></ng-container>\r\n }\r\n\r\n</ng-container>\r\n", styles: [".actions{display:flex;gap:10px;justify-content:flex-end;position:fixed;bottom:50px;right:50px;z-index:9999}.btn,.btn--ghost{width:100px;font-size:1.4rem;border:0;border-radius:40px;padding:15px;background-color:#596300;color:#fff;cursor:pointer;margin:0;transition:background-color .3s ease}.btn--ghost{background-color:#dee58f;color:#61661f}.btn:hover{background-color:#6b7400}.btn--ghost:hover{background-color:#c9d171}@media (max-width: 768px){.actions{bottom:10px;right:10px}.btn,.btn--ghost{font-size:1.2rem}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }] });
1918
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: WizardForm, deps: [], target: i0.ɵɵFactoryTarget.Component });
1919
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: WizardForm, isStandalone: true, selector: "lib-wizard-form", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null }, currentStep: { classPropertyName: "currentStep", publicName: "currentStep", isSignal: true, isRequired: false, transformFunction: null }, steps: { classPropertyName: "steps", publicName: "steps", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { canContinue: "canContinue" }, ngImport: i0, template: "<ng-container>\r\n\r\n @if (currentGroup()) {\r\n <ng-container\r\n *ngComponentOutlet=\"currentGroupComponent(); inputs: { group: currentGroup() }\"\r\n ></ng-container>\r\n }\r\n\r\n</ng-container>\r\n", styles: [".actions{display:flex;gap:10px;justify-content:flex-end;position:fixed;bottom:50px;right:50px;z-index:9999}.btn,.btn--ghost{width:100px;font-size:1.4rem;border:0;border-radius:40px;padding:15px;background-color:#596300;color:#fff;cursor:pointer;margin:0;transition:background-color .3s ease}.btn--ghost{background-color:#dee58f;color:#61661f}.btn:hover{background-color:#6b7400}.btn--ghost:hover{background-color:#c9d171}@media (max-width: 768px){.actions{bottom:10px;right:10px}.btn,.btn--ghost{font-size:1.2rem}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }] });
1888
1920
  }
1889
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: WizardForm, decorators: [{
1921
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: WizardForm, decorators: [{
1890
1922
  type: Component,
1891
1923
  args: [{ selector: 'lib-wizard-form', standalone: true, imports: [CommonModule], template: "<ng-container>\r\n\r\n @if (currentGroup()) {\r\n <ng-container\r\n *ngComponentOutlet=\"currentGroupComponent(); inputs: { group: currentGroup() }\"\r\n ></ng-container>\r\n }\r\n\r\n</ng-container>\r\n", styles: [".actions{display:flex;gap:10px;justify-content:flex-end;position:fixed;bottom:50px;right:50px;z-index:9999}.btn,.btn--ghost{width:100px;font-size:1.4rem;border:0;border-radius:40px;padding:15px;background-color:#596300;color:#fff;cursor:pointer;margin:0;transition:background-color .3s ease}.btn--ghost{background-color:#dee58f;color:#61661f}.btn:hover{background-color:#6b7400}.btn--ghost:hover{background-color:#c9d171}@media (max-width: 768px){.actions{bottom:10px;right:10px}.btn,.btn--ghost{font-size:1.2rem}}\n"] }]
1892
1924
  }], ctorParameters: () => [], propDecorators: { form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: false }] }], currentStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentStep", required: false }] }], steps: [{ type: i0.Input, args: [{ isSignal: true, alias: "steps", required: false }] }], canContinue: [{ type: i0.Output, args: ["canContinue"] }] } });
@@ -1923,12 +1955,12 @@ class ModalForm {
1923
1955
  submitForm() {
1924
1956
  this.onSubmit.emit(this.form()?.value);
1925
1957
  }
1926
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ModalForm, deps: [], target: i0.ɵɵFactoryTarget.Component });
1927
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: ModalForm, isStandalone: true, selector: "lib-modal-form", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, submitLabel: { classPropertyName: "submitLabel", publicName: "submitLabel", isSignal: true, isRequired: false, transformFunction: null }, form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null }, steps: { classPropertyName: "steps", publicName: "steps", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSubmit: "onSubmit", onCancel: "onCancel" }, ngImport: i0, template: "<div class=\"modal-form-container\">\r\n <div class=\"header-content\">\r\n <h1>{{ title() }}</h1>\r\n </div>\r\n\r\n @if (steps() && steps().length > 1) {\r\n <div class=\"steps\">\r\n @for (step of steps(); track $index) {\r\n <div\r\n class=\"step\"\r\n [class.step-active]=\"currentStep() === $index + 1\"\r\n [class.step-completed]=\"currentStep() > $index + 1\"\r\n >\r\n @if (currentStep() > $index + 1) {\r\n <span class=\"check-icon\">\u2714</span>\r\n }\r\n <span>Paso {{ $index + 1 }}: {{ step.label }}</span>\r\n </div>\r\n\r\n @if ($index < steps().length - 1) {\r\n <span class=\"separator\">\u203A</span>\r\n } }\r\n </div>\r\n }\r\n\r\n <div class=\"divider\"></div>\r\n\r\n <div class=\"body-content\">\r\n @if (!steps() || !steps().length) {\r\n <ng-content></ng-content>\r\n } @else {\r\n <!-- Render din\u00E1mico del paso actual -->\r\n <lib-wizard-form\r\n [form]=\"form()\"\r\n [currentStep]=\"currentStep()\"\r\n [steps]=\"steps()\"\r\n (canContinue)=\"canContinue.set($event)\"\r\n ></lib-wizard-form>\r\n }\r\n </div>\r\n\r\n <div class=\"actions\">\r\n @if (!steps() || steps().length <= 1) {\r\n <button type=\"button\" class=\"btn--ghost\" (click)=\"onCancel.emit()\">\r\n Cancelar\r\n </button>\r\n } @else if (currentStep() === 1) {\r\n <button type=\"button\" class=\"btn--ghost\" (click)=\"onCancel.emit()\">\r\n Cancelar\r\n </button>\r\n } @else {\r\n <button type=\"button\" class=\"btn--ghost\" (click)=\"prevStep()\">\r\n Volver\r\n </button>\r\n }\r\n\r\n <button\r\n type=\"button\"\r\n class=\"btn\"\r\n (click)=\"!steps() || !steps().length ? submitForm() :\r\n currentStep() === steps().length ? submitForm() : nextStep()\"\r\n [disabled]=\"!canContinue()\"\r\n >\r\n {{ !steps() || !steps().length ? submitLabel() : currentStep() ===\r\n steps().length ? submitLabel() : 'Continuar' }}\r\n </button>\r\n </div>\r\n</div>\r\n", styles: [":host{position:fixed;inset:0;background:#0006;display:flex;justify-content:center;align-items:center;z-index:9999;padding:16px;box-sizing:border-box}.modal-form-container{background-color:#ebe8d6;width:100%;max-width:1200px;max-height:calc(100vh - 40px);display:flex;flex-direction:column;justify-content:flex-start;align-items:stretch;padding:24px 48px;border-radius:24px;box-shadow:0 10px 25px #00000026}.header-content{padding-top:16px;padding-bottom:16px}.body-content{flex:1;overflow:auto}.steps{display:flex;flex-direction:row;gap:16px;justify-content:flex-start;align-items:center}.step{padding:12px;font-size:1.4rem;font-weight:600;text-align:center;border-radius:8px;height:32px;display:flex;align-items:center;justify-content:center;color:#40484c;border:1px solid #c7c7ad;box-shadow:none;transition:box-shadow .3s ease,background-color .3s ease,border-color .3s ease;position:relative}.separator{font-size:1.6rem;color:#61661f}.step-active{box-shadow:0 2px 4px #0003;background-color:#f5f5e0;border-color:#a3a375;border:none}.step-completed{box-shadow:none;background-color:#dee58f;border:none;color:#61661f;justify-content:center;gap:8px}.check-icon{align-content:center;justify-content:center;color:#61661f}.divider{width:calc(100% + 100px);margin-left:-52px;height:1px;background-color:#7878612c;margin-top:24px;margin-bottom:16px}.actions{display:flex;gap:10px;justify-content:flex-end;width:100%;margin-top:24px}.btn,.btn--ghost{font-size:1.4rem;border:0;border-radius:40px;padding:15px 24px;background-color:#596300;color:#fff;cursor:pointer;margin:0;transition:background-color .3s ease}.btn--ghost{background-color:#dee58f;color:#61661f}.btn:hover{background-color:#6b7400}.btn:disabled{background-color:#0000001a;color:#00000043;cursor:default}.btn--ghost:hover{background-color:#c9d171}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: WizardForm, selector: "lib-wizard-form", inputs: ["form", "currentStep", "steps"], outputs: ["canContinue"] }] });
1958
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ModalForm, deps: [], target: i0.ɵɵFactoryTarget.Component });
1959
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: ModalForm, isStandalone: true, selector: "lib-modal-form", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, submitLabel: { classPropertyName: "submitLabel", publicName: "submitLabel", isSignal: true, isRequired: false, transformFunction: null }, form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null }, steps: { classPropertyName: "steps", publicName: "steps", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSubmit: "onSubmit", onCancel: "onCancel" }, ngImport: i0, template: "<div class=\"modal-form-container\">\r\n <div class=\"header-content\">\r\n <h1>{{ title() }}</h1>\r\n </div>\r\n\r\n @if (steps() && steps().length > 1) {\r\n <div class=\"steps\">\r\n @for (step of steps(); track $index) {\r\n <div\r\n class=\"step\"\r\n [class.step-active]=\"currentStep() === $index + 1\"\r\n [class.step-completed]=\"currentStep() > $index + 1\"\r\n >\r\n @if (currentStep() > $index + 1) {\r\n <span class=\"check-icon\">\u2714</span>\r\n }\r\n <span>Paso {{ $index + 1 }}: {{ step.label }}</span>\r\n </div>\r\n\r\n @if ($index < steps().length - 1) {\r\n <span class=\"separator\">\u203A</span>\r\n } }\r\n </div>\r\n }\r\n\r\n <div class=\"divider\"></div>\r\n\r\n <div class=\"body-content\">\r\n @if (!steps() || !steps().length) {\r\n <ng-content></ng-content>\r\n } @else {\r\n <!-- Render din\u00E1mico del paso actual -->\r\n <lib-wizard-form\r\n [form]=\"form()\"\r\n [currentStep]=\"currentStep()\"\r\n [steps]=\"steps()\"\r\n (canContinue)=\"canContinue.set($event)\"\r\n ></lib-wizard-form>\r\n }\r\n </div>\r\n\r\n <div class=\"actions\">\r\n @if (!steps() || steps().length <= 1) {\r\n <button type=\"button\" class=\"btn--ghost\" (click)=\"onCancel.emit()\">\r\n Cancelar\r\n </button>\r\n } @else if (currentStep() === 1) {\r\n <button type=\"button\" class=\"btn--ghost\" (click)=\"onCancel.emit()\">\r\n Cancelar\r\n </button>\r\n } @else {\r\n <button type=\"button\" class=\"btn--ghost\" (click)=\"prevStep()\">\r\n Volver\r\n </button>\r\n }\r\n\r\n <button\r\n type=\"button\"\r\n class=\"btn\"\r\n (click)=\"!steps() || !steps().length ? submitForm() :\r\n currentStep() === steps().length ? submitForm() : nextStep()\"\r\n [disabled]=\"!canContinue()\"\r\n >\r\n {{ !steps() || !steps().length ? submitLabel() : currentStep() ===\r\n steps().length ? submitLabel() : 'Continuar' }}\r\n </button>\r\n </div>\r\n</div>\r\n", styles: [":host{position:fixed;inset:0;background:#0006;display:flex;justify-content:center;align-items:center;z-index:9999;padding:16px;box-sizing:border-box}.modal-form-container{background-color:#ebe8d6;width:100%;max-width:1200px;max-height:80dvh;display:flex;flex-direction:column;align-items:stretch;padding:24px 48px;border-radius:24px;box-shadow:0 10px 25px #00000026}.header-content{padding-top:16px;padding-bottom:16px}.body-content{flex:1;overflow-y:auto;padding-right:6px}.body-content::-webkit-scrollbar{width:6px;background:transparent}.body-content::-webkit-scrollbar-track{background:transparent}.body-content::-webkit-scrollbar-thumb{background:#00000059;border-radius:6px}.body-content::-webkit-scrollbar-thumb:hover{background:#00000080}.steps{display:flex;flex-direction:row;gap:16px;justify-content:flex-start;align-items:center}.step{padding:12px;font-size:1.4rem;font-weight:600;text-align:center;border-radius:8px;height:32px;display:flex;align-items:center;justify-content:center;color:#40484c;border:1px solid #c7c7ad;box-shadow:none;transition:box-shadow .3s ease,background-color .3s ease,border-color .3s ease;position:relative}.separator{font-size:1.6rem;color:#61661f}.step-active{box-shadow:0 2px 4px #0003;background-color:#f5f5e0;border-color:#a3a375;border:none}.step-completed{box-shadow:none;background-color:#dee58f;border:none;color:#61661f;justify-content:center;gap:8px}.check-icon{align-content:center;justify-content:center;color:#61661f}.divider{width:calc(100% + 100px);margin-left:-52px;height:1px;background-color:#7878612c;margin-top:24px;margin-bottom:16px}.actions{display:flex;gap:10px;justify-content:flex-end;width:100%;margin-top:24px}.btn,.btn--ghost{font-size:1.4rem;border:0;border-radius:40px;padding:15px 24px;background-color:#596300;color:#fff;cursor:pointer;margin:0;transition:background-color .3s ease}.btn--ghost{background-color:#dee58f;color:#61661f}.btn:hover{background-color:#6b7400}.btn:disabled{background-color:#0000001a;color:#00000043;cursor:default}.btn--ghost:hover{background-color:#c9d171}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: WizardForm, selector: "lib-wizard-form", inputs: ["form", "currentStep", "steps"], outputs: ["canContinue"] }] });
1928
1960
  }
1929
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ModalForm, decorators: [{
1961
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ModalForm, decorators: [{
1930
1962
  type: Component,
1931
- args: [{ selector: 'lib-modal-form', standalone: true, imports: [CommonModule, WizardForm], template: "<div class=\"modal-form-container\">\r\n <div class=\"header-content\">\r\n <h1>{{ title() }}</h1>\r\n </div>\r\n\r\n @if (steps() && steps().length > 1) {\r\n <div class=\"steps\">\r\n @for (step of steps(); track $index) {\r\n <div\r\n class=\"step\"\r\n [class.step-active]=\"currentStep() === $index + 1\"\r\n [class.step-completed]=\"currentStep() > $index + 1\"\r\n >\r\n @if (currentStep() > $index + 1) {\r\n <span class=\"check-icon\">\u2714</span>\r\n }\r\n <span>Paso {{ $index + 1 }}: {{ step.label }}</span>\r\n </div>\r\n\r\n @if ($index < steps().length - 1) {\r\n <span class=\"separator\">\u203A</span>\r\n } }\r\n </div>\r\n }\r\n\r\n <div class=\"divider\"></div>\r\n\r\n <div class=\"body-content\">\r\n @if (!steps() || !steps().length) {\r\n <ng-content></ng-content>\r\n } @else {\r\n <!-- Render din\u00E1mico del paso actual -->\r\n <lib-wizard-form\r\n [form]=\"form()\"\r\n [currentStep]=\"currentStep()\"\r\n [steps]=\"steps()\"\r\n (canContinue)=\"canContinue.set($event)\"\r\n ></lib-wizard-form>\r\n }\r\n </div>\r\n\r\n <div class=\"actions\">\r\n @if (!steps() || steps().length <= 1) {\r\n <button type=\"button\" class=\"btn--ghost\" (click)=\"onCancel.emit()\">\r\n Cancelar\r\n </button>\r\n } @else if (currentStep() === 1) {\r\n <button type=\"button\" class=\"btn--ghost\" (click)=\"onCancel.emit()\">\r\n Cancelar\r\n </button>\r\n } @else {\r\n <button type=\"button\" class=\"btn--ghost\" (click)=\"prevStep()\">\r\n Volver\r\n </button>\r\n }\r\n\r\n <button\r\n type=\"button\"\r\n class=\"btn\"\r\n (click)=\"!steps() || !steps().length ? submitForm() :\r\n currentStep() === steps().length ? submitForm() : nextStep()\"\r\n [disabled]=\"!canContinue()\"\r\n >\r\n {{ !steps() || !steps().length ? submitLabel() : currentStep() ===\r\n steps().length ? submitLabel() : 'Continuar' }}\r\n </button>\r\n </div>\r\n</div>\r\n", styles: [":host{position:fixed;inset:0;background:#0006;display:flex;justify-content:center;align-items:center;z-index:9999;padding:16px;box-sizing:border-box}.modal-form-container{background-color:#ebe8d6;width:100%;max-width:1200px;max-height:calc(100vh - 40px);display:flex;flex-direction:column;justify-content:flex-start;align-items:stretch;padding:24px 48px;border-radius:24px;box-shadow:0 10px 25px #00000026}.header-content{padding-top:16px;padding-bottom:16px}.body-content{flex:1;overflow:auto}.steps{display:flex;flex-direction:row;gap:16px;justify-content:flex-start;align-items:center}.step{padding:12px;font-size:1.4rem;font-weight:600;text-align:center;border-radius:8px;height:32px;display:flex;align-items:center;justify-content:center;color:#40484c;border:1px solid #c7c7ad;box-shadow:none;transition:box-shadow .3s ease,background-color .3s ease,border-color .3s ease;position:relative}.separator{font-size:1.6rem;color:#61661f}.step-active{box-shadow:0 2px 4px #0003;background-color:#f5f5e0;border-color:#a3a375;border:none}.step-completed{box-shadow:none;background-color:#dee58f;border:none;color:#61661f;justify-content:center;gap:8px}.check-icon{align-content:center;justify-content:center;color:#61661f}.divider{width:calc(100% + 100px);margin-left:-52px;height:1px;background-color:#7878612c;margin-top:24px;margin-bottom:16px}.actions{display:flex;gap:10px;justify-content:flex-end;width:100%;margin-top:24px}.btn,.btn--ghost{font-size:1.4rem;border:0;border-radius:40px;padding:15px 24px;background-color:#596300;color:#fff;cursor:pointer;margin:0;transition:background-color .3s ease}.btn--ghost{background-color:#dee58f;color:#61661f}.btn:hover{background-color:#6b7400}.btn:disabled{background-color:#0000001a;color:#00000043;cursor:default}.btn--ghost:hover{background-color:#c9d171}\n"] }]
1963
+ args: [{ selector: 'lib-modal-form', standalone: true, imports: [CommonModule, WizardForm], template: "<div class=\"modal-form-container\">\r\n <div class=\"header-content\">\r\n <h1>{{ title() }}</h1>\r\n </div>\r\n\r\n @if (steps() && steps().length > 1) {\r\n <div class=\"steps\">\r\n @for (step of steps(); track $index) {\r\n <div\r\n class=\"step\"\r\n [class.step-active]=\"currentStep() === $index + 1\"\r\n [class.step-completed]=\"currentStep() > $index + 1\"\r\n >\r\n @if (currentStep() > $index + 1) {\r\n <span class=\"check-icon\">\u2714</span>\r\n }\r\n <span>Paso {{ $index + 1 }}: {{ step.label }}</span>\r\n </div>\r\n\r\n @if ($index < steps().length - 1) {\r\n <span class=\"separator\">\u203A</span>\r\n } }\r\n </div>\r\n }\r\n\r\n <div class=\"divider\"></div>\r\n\r\n <div class=\"body-content\">\r\n @if (!steps() || !steps().length) {\r\n <ng-content></ng-content>\r\n } @else {\r\n <!-- Render din\u00E1mico del paso actual -->\r\n <lib-wizard-form\r\n [form]=\"form()\"\r\n [currentStep]=\"currentStep()\"\r\n [steps]=\"steps()\"\r\n (canContinue)=\"canContinue.set($event)\"\r\n ></lib-wizard-form>\r\n }\r\n </div>\r\n\r\n <div class=\"actions\">\r\n @if (!steps() || steps().length <= 1) {\r\n <button type=\"button\" class=\"btn--ghost\" (click)=\"onCancel.emit()\">\r\n Cancelar\r\n </button>\r\n } @else if (currentStep() === 1) {\r\n <button type=\"button\" class=\"btn--ghost\" (click)=\"onCancel.emit()\">\r\n Cancelar\r\n </button>\r\n } @else {\r\n <button type=\"button\" class=\"btn--ghost\" (click)=\"prevStep()\">\r\n Volver\r\n </button>\r\n }\r\n\r\n <button\r\n type=\"button\"\r\n class=\"btn\"\r\n (click)=\"!steps() || !steps().length ? submitForm() :\r\n currentStep() === steps().length ? submitForm() : nextStep()\"\r\n [disabled]=\"!canContinue()\"\r\n >\r\n {{ !steps() || !steps().length ? submitLabel() : currentStep() ===\r\n steps().length ? submitLabel() : 'Continuar' }}\r\n </button>\r\n </div>\r\n</div>\r\n", styles: [":host{position:fixed;inset:0;background:#0006;display:flex;justify-content:center;align-items:center;z-index:9999;padding:16px;box-sizing:border-box}.modal-form-container{background-color:#ebe8d6;width:100%;max-width:1200px;max-height:80dvh;display:flex;flex-direction:column;align-items:stretch;padding:24px 48px;border-radius:24px;box-shadow:0 10px 25px #00000026}.header-content{padding-top:16px;padding-bottom:16px}.body-content{flex:1;overflow-y:auto;padding-right:6px}.body-content::-webkit-scrollbar{width:6px;background:transparent}.body-content::-webkit-scrollbar-track{background:transparent}.body-content::-webkit-scrollbar-thumb{background:#00000059;border-radius:6px}.body-content::-webkit-scrollbar-thumb:hover{background:#00000080}.steps{display:flex;flex-direction:row;gap:16px;justify-content:flex-start;align-items:center}.step{padding:12px;font-size:1.4rem;font-weight:600;text-align:center;border-radius:8px;height:32px;display:flex;align-items:center;justify-content:center;color:#40484c;border:1px solid #c7c7ad;box-shadow:none;transition:box-shadow .3s ease,background-color .3s ease,border-color .3s ease;position:relative}.separator{font-size:1.6rem;color:#61661f}.step-active{box-shadow:0 2px 4px #0003;background-color:#f5f5e0;border-color:#a3a375;border:none}.step-completed{box-shadow:none;background-color:#dee58f;border:none;color:#61661f;justify-content:center;gap:8px}.check-icon{align-content:center;justify-content:center;color:#61661f}.divider{width:calc(100% + 100px);margin-left:-52px;height:1px;background-color:#7878612c;margin-top:24px;margin-bottom:16px}.actions{display:flex;gap:10px;justify-content:flex-end;width:100%;margin-top:24px}.btn,.btn--ghost{font-size:1.4rem;border:0;border-radius:40px;padding:15px 24px;background-color:#596300;color:#fff;cursor:pointer;margin:0;transition:background-color .3s ease}.btn--ghost{background-color:#dee58f;color:#61661f}.btn:hover{background-color:#6b7400}.btn:disabled{background-color:#0000001a;color:#00000043;cursor:default}.btn--ghost:hover{background-color:#c9d171}\n"] }]
1932
1964
  }], ctorParameters: () => [], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], submitLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitLabel", required: false }] }], form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: false }] }], steps: [{ type: i0.Input, args: [{ isSignal: true, alias: "steps", required: false }] }], onSubmit: [{ type: i0.Output, args: ["onSubmit"] }], onCancel: [{ type: i0.Output, args: ["onCancel"] }] } });
1933
1965
 
1934
1966
  class DialogAlertComponent {
@@ -2012,30 +2044,30 @@ class DialogAlertComponent {
2012
2044
  onCancel() {
2013
2045
  this.close.emit(false);
2014
2046
  }
2015
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DialogAlertComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2016
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DialogAlertComponent, isStandalone: true, selector: "lib-dialog-alert-component", inputs: { title: "title", message: "message", type: "type", action: "action", showReason: "showReason", confirm: "confirm", confirmLabel: "confirmLabel", reasonOptions: "reasonOptions" }, outputs: { close: "close", confirmReason: "confirmReason" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"modal-backdrop\">\r\n <div class=\"modal-card\" [class.modal-card-compact]=\"!isReasonNeeded\">\r\n <div class=\"modal-header\">\r\n <h2>{{ title }}</h2>\r\n </div>\r\n <div class=\"modal-body\">\r\n <p>{{ message }}</p>\r\n <lib-dynamic-form-fields [form]=\"form\" [sections]=\"sections\"></lib-dynamic-form-fields>\r\n </div>\r\n <div class=\"modal-footer\">\r\n @if (confirm) {\r\n <button class=\"btn cancel\" (click)=\"onCancel()\">Cancelar</button>\r\n <button class=\"btn confirm\" [ngClass]=\"type\" (click)=\"onConfirm()\">{{ confirmLabel }}</button>\r\n } @else {\r\n <button class=\"btn confirm\" [ngClass]=\"type\" (click)=\"onConfirm()\">{{ confirmLabel }}</button>\r\n }\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".modal-backdrop{position:fixed;inset:0;background:#00000073;display:flex;align-items:center;justify-content:center;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);z-index:10000}.modal-card{width:30%;max-width:50%;background:#ebe8d6;border-radius:14px;padding:32px 48px;animation:fadeIn .25s ease;border:1px solid rgba(255,255,255,.07);box-shadow:0 8px 20px #0003}.modal-card-compact{width:100%;max-width:25%;padding:24px 32px}.modal-header{display:flex;align-items:center;gap:12px;color:#0c0c0c;justify-content:center}.modal-header h2{font-weight:700;font-size:24px;margin:0;text-transform:uppercase}.modal-body{text-align:center}.modal-body p{color:#555;margin:0;font-size:14px;line-height:1.5;padding-top:21px}.modal-footer{margin-top:25px;display:flex;justify-content:center;gap:10px}.btn{padding:10px 16px;border-radius:99px;font-weight:700;cursor:pointer;border:none}.btn:hover{background-color:#61661f}.btn.cancel{background:transparent;border:1px solid #454733;color:#454733}.btn.cancel:hover{background-color:#454733;color:#fff}.btn.confirm{background:#596300;color:#fff}@keyframes fadeIn{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.btn.confirm.warning,.btn.confirm.error{background-color:#ba1a1a;color:#fff}.btn.confirm.info{background-color:#063546;color:#fff}.btn.confirm.success{background-color:#596300;color:#fff}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: DynamicFormFields, selector: "lib-dynamic-form-fields", inputs: ["form", "sections", "compact"] }] });
2047
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DialogAlertComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2048
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DialogAlertComponent, isStandalone: true, selector: "lib-dialog-alert-component", inputs: { title: "title", message: "message", type: "type", action: "action", showReason: "showReason", confirm: "confirm", confirmLabel: "confirmLabel", reasonOptions: "reasonOptions" }, outputs: { close: "close", confirmReason: "confirmReason" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"modal-backdrop\">\r\n <div class=\"modal-card\" [class.modal-card-compact]=\"!isReasonNeeded\">\r\n <div class=\"modal-header\">\r\n <h2>{{ title }}</h2>\r\n </div>\r\n <div class=\"modal-body\">\r\n <p>{{ message }}</p>\r\n <lib-dynamic-form-fields [form]=\"form\" [sections]=\"sections\"></lib-dynamic-form-fields>\r\n </div>\r\n <div class=\"modal-footer\">\r\n @if (confirm) {\r\n <button class=\"btn cancel\" (click)=\"onCancel()\">Cancelar</button>\r\n <button class=\"btn confirm\" [ngClass]=\"type\" (click)=\"onConfirm()\">{{ confirmLabel }}</button>\r\n } @else {\r\n <button class=\"btn confirm\" [ngClass]=\"type\" (click)=\"onConfirm()\">{{ confirmLabel }}</button>\r\n }\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".modal-backdrop{position:fixed;inset:0;background:#00000073;display:flex;align-items:center;justify-content:center;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);z-index:10000}.modal-card{width:30%;max-width:50%;max-height:80dvh;background:#ebe8d6;border-radius:14px;padding:32px 48px;animation:fadeIn .25s ease;border:1px solid rgba(255,255,255,.07);box-shadow:0 8px 20px #0003;overflow:hidden;box-sizing:border-box}.modal-card-compact{width:100%;max-width:25%;padding:24px 32px}.modal-header{display:flex;align-items:center;gap:12px;color:#0c0c0c;justify-content:center}.modal-header h2{font-weight:700;font-size:24px;margin:0;text-transform:uppercase}.modal-body{text-align:center;max-height:400px;overflow:hidden;box-sizing:border-box}.modal-body p{color:#555;margin:0;font-size:14px;line-height:1.5;padding-top:21px}.modal-footer{margin-top:25px;display:flex;justify-content:center;gap:10px}.btn{padding:10px 16px;border-radius:99px;font-weight:700;cursor:pointer;border:none}.btn:hover{background-color:#61661f}.btn.cancel{background:transparent;border:1px solid #454733;color:#454733}.btn.cancel:hover{background-color:#454733;color:#fff}.btn.confirm{background:#596300;color:#fff}@keyframes fadeIn{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.btn.confirm.warning,.btn.confirm.error{background-color:#ba1a1a;color:#fff}.btn.confirm.info{background-color:#063546;color:#fff}.btn.confirm.success{background-color:#596300;color:#fff}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: DynamicFormFields, selector: "lib-dynamic-form-fields", inputs: ["form", "sections", "compact"] }] });
2017
2049
  }
2018
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DialogAlertComponent, decorators: [{
2050
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DialogAlertComponent, decorators: [{
2019
2051
  type: Component,
2020
- args: [{ selector: 'lib-dialog-alert-component', standalone: true, imports: [CommonModule, ReactiveFormsModule, DynamicFormFields], template: "<div class=\"modal-backdrop\">\r\n <div class=\"modal-card\" [class.modal-card-compact]=\"!isReasonNeeded\">\r\n <div class=\"modal-header\">\r\n <h2>{{ title }}</h2>\r\n </div>\r\n <div class=\"modal-body\">\r\n <p>{{ message }}</p>\r\n <lib-dynamic-form-fields [form]=\"form\" [sections]=\"sections\"></lib-dynamic-form-fields>\r\n </div>\r\n <div class=\"modal-footer\">\r\n @if (confirm) {\r\n <button class=\"btn cancel\" (click)=\"onCancel()\">Cancelar</button>\r\n <button class=\"btn confirm\" [ngClass]=\"type\" (click)=\"onConfirm()\">{{ confirmLabel }}</button>\r\n } @else {\r\n <button class=\"btn confirm\" [ngClass]=\"type\" (click)=\"onConfirm()\">{{ confirmLabel }}</button>\r\n }\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".modal-backdrop{position:fixed;inset:0;background:#00000073;display:flex;align-items:center;justify-content:center;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);z-index:10000}.modal-card{width:30%;max-width:50%;background:#ebe8d6;border-radius:14px;padding:32px 48px;animation:fadeIn .25s ease;border:1px solid rgba(255,255,255,.07);box-shadow:0 8px 20px #0003}.modal-card-compact{width:100%;max-width:25%;padding:24px 32px}.modal-header{display:flex;align-items:center;gap:12px;color:#0c0c0c;justify-content:center}.modal-header h2{font-weight:700;font-size:24px;margin:0;text-transform:uppercase}.modal-body{text-align:center}.modal-body p{color:#555;margin:0;font-size:14px;line-height:1.5;padding-top:21px}.modal-footer{margin-top:25px;display:flex;justify-content:center;gap:10px}.btn{padding:10px 16px;border-radius:99px;font-weight:700;cursor:pointer;border:none}.btn:hover{background-color:#61661f}.btn.cancel{background:transparent;border:1px solid #454733;color:#454733}.btn.cancel:hover{background-color:#454733;color:#fff}.btn.confirm{background:#596300;color:#fff}@keyframes fadeIn{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.btn.confirm.warning,.btn.confirm.error{background-color:#ba1a1a;color:#fff}.btn.confirm.info{background-color:#063546;color:#fff}.btn.confirm.success{background-color:#596300;color:#fff}\n"] }]
2052
+ args: [{ selector: 'lib-dialog-alert-component', standalone: true, imports: [CommonModule, ReactiveFormsModule, DynamicFormFields], template: "<div class=\"modal-backdrop\">\r\n <div class=\"modal-card\" [class.modal-card-compact]=\"!isReasonNeeded\">\r\n <div class=\"modal-header\">\r\n <h2>{{ title }}</h2>\r\n </div>\r\n <div class=\"modal-body\">\r\n <p>{{ message }}</p>\r\n <lib-dynamic-form-fields [form]=\"form\" [sections]=\"sections\"></lib-dynamic-form-fields>\r\n </div>\r\n <div class=\"modal-footer\">\r\n @if (confirm) {\r\n <button class=\"btn cancel\" (click)=\"onCancel()\">Cancelar</button>\r\n <button class=\"btn confirm\" [ngClass]=\"type\" (click)=\"onConfirm()\">{{ confirmLabel }}</button>\r\n } @else {\r\n <button class=\"btn confirm\" [ngClass]=\"type\" (click)=\"onConfirm()\">{{ confirmLabel }}</button>\r\n }\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".modal-backdrop{position:fixed;inset:0;background:#00000073;display:flex;align-items:center;justify-content:center;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);z-index:10000}.modal-card{width:30%;max-width:50%;max-height:80dvh;background:#ebe8d6;border-radius:14px;padding:32px 48px;animation:fadeIn .25s ease;border:1px solid rgba(255,255,255,.07);box-shadow:0 8px 20px #0003;overflow:hidden;box-sizing:border-box}.modal-card-compact{width:100%;max-width:25%;padding:24px 32px}.modal-header{display:flex;align-items:center;gap:12px;color:#0c0c0c;justify-content:center}.modal-header h2{font-weight:700;font-size:24px;margin:0;text-transform:uppercase}.modal-body{text-align:center;max-height:400px;overflow:hidden;box-sizing:border-box}.modal-body p{color:#555;margin:0;font-size:14px;line-height:1.5;padding-top:21px}.modal-footer{margin-top:25px;display:flex;justify-content:center;gap:10px}.btn{padding:10px 16px;border-radius:99px;font-weight:700;cursor:pointer;border:none}.btn:hover{background-color:#61661f}.btn.cancel{background:transparent;border:1px solid #454733;color:#454733}.btn.cancel:hover{background-color:#454733;color:#fff}.btn.confirm{background:#596300;color:#fff}@keyframes fadeIn{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.btn.confirm.warning,.btn.confirm.error{background-color:#ba1a1a;color:#fff}.btn.confirm.info{background-color:#063546;color:#fff}.btn.confirm.success{background-color:#596300;color:#fff}\n"] }]
2021
2053
  }], propDecorators: { title: [{
2022
- type: Input
2054
+ type: Input$1
2023
2055
  }], message: [{
2024
- type: Input
2056
+ type: Input$1
2025
2057
  }], type: [{
2026
- type: Input
2058
+ type: Input$1
2027
2059
  }], action: [{
2028
- type: Input
2060
+ type: Input$1
2029
2061
  }], showReason: [{
2030
- type: Input
2062
+ type: Input$1
2031
2063
  }], confirm: [{
2032
- type: Input
2064
+ type: Input$1
2033
2065
  }], confirmLabel: [{
2034
- type: Input
2066
+ type: Input$1
2035
2067
  }], close: [{
2036
2068
  type: Output
2037
2069
  }], reasonOptions: [{
2038
- type: Input
2070
+ type: Input$1
2039
2071
  }], confirmReason: [{
2040
2072
  type: Output
2041
2073
  }] } });
@@ -2057,24 +2089,195 @@ class DialogConfirmation {
2057
2089
  onCancel() {
2058
2090
  this.close.emit(false);
2059
2091
  }
2060
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DialogConfirmation, deps: [], target: i0.ɵɵFactoryTarget.Component });
2061
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DialogConfirmation, isStandalone: true, selector: "lib-dialog-confirmation", inputs: { title: "title", confirm: "confirm", confirmLabel: "confirmLabel", items: "items" }, outputs: { close: "close" }, ngImport: i0, template: "<div class=\"modal-backdrop\">\r\n <div class=\"modal-card\">\r\n <div class=\"modal-header\">\r\n <h2>{{ title }}</h2>\r\n <button class=\"close-btn\" (click)=\"onCancel()\" aria-label=\"Cerrar\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\"\r\n viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M18 6l-12 12\" />\r\n <path d=\"M6 6l12 12\" />\r\n </svg>\r\n </button>\r\n </div>\r\n <div class=\"modal-body\">\r\n <div class=\"info-container\" [class.expanded]=\"expandedIndex !== null\">\r\n @for (item of items; track item.key; let i = $index) {\r\n\r\n <div class=\"info-item\">\r\n <div\r\n class=\"info-main\"\r\n [class.info-main-expanded]=\"item.expandible\"\r\n (click)=\"item.expandible && toggle(i)\"\r\n >\r\n <span class=\"label\"\r\n >{{ item.label }} @if (item.expandible) {\r\n <span class=\"arrow\"> {{ expandedIndex === i ? '\u25B2' : '\u25BC' }} </span>\r\n }\r\n </span>\r\n <span class=\"value\"> {{ item.value }} </span>\r\n </div>\r\n\r\n @if (expandedIndex === i && item.children?.length) {\r\n <div class=\"info-children\">\r\n @for (child of item.children; track child.key) {\r\n <div class=\"info-item child-item\">\r\n <div class=\"info-main\">\r\n <span class=\"label\">{{ child.label }}</span>\r\n <span class=\"value\">{{ child.value }}</span>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n }\r\n </div>\r\n </div>\r\n <div class=\"modal-footer\">\r\n @if (confirm) {\r\n <button class=\"btn cancel\" (click)=\"onCancel()\">Cancelar</button>\r\n <button class=\"btn confirm\" (click)=\"onConfirm()\">\r\n {{ confirmLabel }}\r\n </button>\r\n } @else {\r\n <button class=\"btn confirm\" (click)=\"onConfirm()\">\r\n {{ confirmLabel }}\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".modal-backdrop{position:fixed;inset:0;background:#00000073;display:flex;align-items:center;justify-content:center;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);z-index:10000}.modal-card{width:30%;max-width:50%;max-height:90%;background:#ebe8d6;border-radius:28px;padding:32px 48px;animation:fadeIn .25s ease;border:1px solid rgba(255,255,255,.07);box-shadow:0 8px 20px #0003;overflow:hidden;display:flex;flex-direction:column;transition:max-height .35s cubic-bezier(.4,0,.2,1)}.modal-header{position:relative;display:flex;align-items:center;gap:12px;color:#0c0c0c;justify-content:center}.modal-header h2{font-weight:700;font-size:24px;margin:0;text-transform:uppercase}.close-btn{position:absolute;right:-36px;top:-24px;width:36px;height:36px;border-radius:50%;background:#ebe8d6;display:flex;align-items:center;justify-content:center;cursor:pointer;color:#333;transition:background .2s ease,transform .2s ease}.close-btn:hover{background:#d8d6c0;transform:scale(1.05)}.close-btn svg{width:18px;height:18px}.modal-body{position:relative;margin-top:16px;text-align:center;flex:1;overflow:hidden;display:flex;flex-direction:column;transition:all .35s cubic-bezier(.4,0,.2,1)}.modal-body p{color:#555;margin:0;font-size:14px;line-height:1.5;padding-top:21px}.modal-footer{margin-top:25px;display:flex;justify-content:center;gap:10px;flex-shrink:0}button{background-color:transparent;border:none}.btn{padding:10px 16px;border-radius:99px;font-weight:700;cursor:pointer;border:none}.btn:hover{background-color:#61661f}.btn.cancel{background:transparent;border:1px solid #454733;color:#454733}.btn.cancel:hover{background-color:#454733;color:#fff}.btn.confirm{background:#596300;color:#fff}@keyframes fadeIn{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.btn.confirm.warning,.btn.confirm.error{background-color:#ba1a1a;color:#fff}.btn.confirm.info{background-color:#063546;color:#fff}.btn.confirm.success{background-color:#596300;color:#fff}.info-container{max-height:400;background:#e3e3d1;border-radius:20px;padding:24px;flex:1;overflow-y:auto;scrollbar-width:thin;scrollbar-color:rgba(0,0,0,.35) transparent;transition:max-height .35s cubic-bezier(.4,0,.2,1)}.info-container.expanded{max-height:600px}.info-container::-webkit-scrollbar{width:6px;background:transparent}.info-container::-webkit-scrollbar-track{background:transparent}.info-container::-webkit-scrollbar-thumb{background:#00000059;border-radius:6px}.info-container::-webkit-scrollbar-thumb:hover{background:#00000080}.info-item{border-bottom:1px solid rgba(0,0,0,.05);padding:16px 0}.info-item:last-child{border-bottom:none}.info-main{display:flex;flex-direction:column;text-align:center}.info-main-expanded{cursor:pointer}.info-children{margin-top:12px}.child-item{padding:16px 0;border-bottom:1px solid rgba(0,0,0,.05);margin:0 16px}.child-item:first-child{border-top:1px solid rgba(0,0,0,.05)}.child-item:last-child{border-bottom:none}.label{font-size:16px;color:#555;text-transform:uppercase}.value{font-size:16px;font-weight:700;display:flex;justify-content:center;gap:6px;align-items:center}.arrow{font-size:12px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
2092
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DialogConfirmation, deps: [], target: i0.ɵɵFactoryTarget.Component });
2093
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DialogConfirmation, isStandalone: true, selector: "lib-dialog-confirmation", inputs: { title: "title", confirm: "confirm", confirmLabel: "confirmLabel", items: "items" }, outputs: { close: "close" }, ngImport: i0, template: "<div class=\"modal-backdrop\">\r\n <div class=\"modal-card\">\r\n <div class=\"modal-header\">\r\n <h2>{{ title }}</h2>\r\n <button class=\"close-btn\" (click)=\"onCancel()\" aria-label=\"Cerrar\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\"\r\n viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M18 6l-12 12\" />\r\n <path d=\"M6 6l12 12\" />\r\n </svg>\r\n </button>\r\n </div>\r\n <div class=\"modal-body\">\r\n <div class=\"info-container\" [class.expanded]=\"expandedIndex !== null\">\r\n @for (item of items; track item.key; let i = $index) {\r\n\r\n <div class=\"info-item\">\r\n <div\r\n class=\"info-main\"\r\n [class.info-main-expanded]=\"item.expandible\"\r\n (click)=\"item.expandible && toggle(i)\"\r\n >\r\n <span class=\"label\"\r\n >{{ item.label }} @if (item.expandible) {\r\n <span class=\"arrow\"> {{ expandedIndex === i ? '\u25B2' : '\u25BC' }} </span>\r\n }\r\n </span>\r\n <span class=\"value\"> {{ item.value }} </span>\r\n </div>\r\n\r\n @if (expandedIndex === i && item.children?.length) {\r\n <div class=\"info-children\">\r\n @for (child of item.children; track child.key) {\r\n <div class=\"info-item child-item\">\r\n <div class=\"info-main\">\r\n <span class=\"label\">{{ child.label }}</span>\r\n <span class=\"value\">{{ child.value }}</span>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n }\r\n </div>\r\n </div>\r\n <div class=\"modal-footer\">\r\n @if (confirm) {\r\n <button class=\"btn cancel\" (click)=\"onCancel()\">Cancelar</button>\r\n <button class=\"btn confirm\" (click)=\"onConfirm()\">\r\n {{ confirmLabel }}\r\n </button>\r\n } @else {\r\n <button class=\"btn confirm\" (click)=\"onConfirm()\">\r\n {{ confirmLabel }}\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".modal-backdrop{position:fixed;inset:0;background:#00000073;display:flex;align-items:center;justify-content:center;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);z-index:10000}.modal-card{width:35%;max-width:50%;max-height:90%;background:#ebe8d6;border-radius:28px;padding:32px 48px;animation:fadeIn .25s ease;border:1px solid rgba(255,255,255,.07);box-shadow:0 8px 20px #0003;overflow:hidden;display:flex;flex-direction:column;transition:max-height .35s cubic-bezier(.4,0,.2,1)}.modal-header{position:relative;display:flex;align-items:center;gap:12px;color:#0c0c0c;justify-content:center}.modal-header h2{font-weight:700;font-size:24px;margin:0;text-transform:uppercase}.close-btn{position:absolute;right:-36px;top:-24px;width:36px;height:36px;border-radius:50%;background:#ebe8d6;display:flex;align-items:center;justify-content:center;cursor:pointer;color:#333;transition:background .2s ease,transform .2s ease}.close-btn:hover{background:#d8d6c0;transform:scale(1.05)}.close-btn svg{width:18px;height:18px}.modal-body{position:relative;margin-top:16px;text-align:center;flex:1;overflow:hidden;display:flex;flex-direction:column;transition:all .35s cubic-bezier(.4,0,.2,1)}.modal-body p{color:#555;margin:0;font-size:14px;line-height:1.5;padding-top:21px}.modal-footer{margin-top:25px;display:flex;justify-content:center;gap:10px;flex-shrink:0}button{background-color:transparent;border:none}.btn{padding:10px 16px;border-radius:99px;font-weight:700;cursor:pointer;border:none}.btn:hover{background-color:#61661f}.btn.cancel{background:transparent;border:1px solid #454733;color:#454733}.btn.cancel:hover{background-color:#454733;color:#fff}.btn.confirm{background:#596300;color:#fff}@keyframes fadeIn{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.btn.confirm.warning,.btn.confirm.error{background-color:#ba1a1a;color:#fff}.btn.confirm.info{background-color:#063546;color:#fff}.btn.confirm.success{background-color:#596300;color:#fff}.info-container{max-height:400;background:#e3e3d1;border-radius:20px;padding:24px;flex:1;overflow-y:auto;scrollbar-width:thin;scrollbar-color:rgba(0,0,0,.35) transparent;transition:max-height .35s cubic-bezier(.4,0,.2,1)}.info-container.expanded{max-height:600px}.info-container::-webkit-scrollbar{width:6px;background:transparent}.info-container::-webkit-scrollbar-track{background:transparent}.info-container::-webkit-scrollbar-thumb{background:#00000059;border-radius:6px}.info-container::-webkit-scrollbar-thumb:hover{background:#00000080}.info-item{border-bottom:1px solid rgba(0,0,0,.05);padding:16px 0}.info-item:last-child{border-bottom:none}.info-main{display:flex;flex-direction:column;text-align:center}.info-main-expanded{cursor:pointer}.info-children{margin-top:12px}.child-item{padding:16px 0;border-bottom:1px solid rgba(0,0,0,.05);margin:0 16px}.child-item:first-child{border-top:1px solid rgba(0,0,0,.05)}.child-item:last-child{border-bottom:none}.label{font-size:16px;color:#555;text-transform:uppercase}.value{font-size:16px;font-weight:700;display:flex;justify-content:center;gap:6px;align-items:center}.arrow{font-size:12px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
2062
2094
  }
2063
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DialogConfirmation, decorators: [{
2095
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DialogConfirmation, decorators: [{
2064
2096
  type: Component,
2065
- args: [{ selector: 'lib-dialog-confirmation', imports: [CommonModule], template: "<div class=\"modal-backdrop\">\r\n <div class=\"modal-card\">\r\n <div class=\"modal-header\">\r\n <h2>{{ title }}</h2>\r\n <button class=\"close-btn\" (click)=\"onCancel()\" aria-label=\"Cerrar\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\"\r\n viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M18 6l-12 12\" />\r\n <path d=\"M6 6l12 12\" />\r\n </svg>\r\n </button>\r\n </div>\r\n <div class=\"modal-body\">\r\n <div class=\"info-container\" [class.expanded]=\"expandedIndex !== null\">\r\n @for (item of items; track item.key; let i = $index) {\r\n\r\n <div class=\"info-item\">\r\n <div\r\n class=\"info-main\"\r\n [class.info-main-expanded]=\"item.expandible\"\r\n (click)=\"item.expandible && toggle(i)\"\r\n >\r\n <span class=\"label\"\r\n >{{ item.label }} @if (item.expandible) {\r\n <span class=\"arrow\"> {{ expandedIndex === i ? '\u25B2' : '\u25BC' }} </span>\r\n }\r\n </span>\r\n <span class=\"value\"> {{ item.value }} </span>\r\n </div>\r\n\r\n @if (expandedIndex === i && item.children?.length) {\r\n <div class=\"info-children\">\r\n @for (child of item.children; track child.key) {\r\n <div class=\"info-item child-item\">\r\n <div class=\"info-main\">\r\n <span class=\"label\">{{ child.label }}</span>\r\n <span class=\"value\">{{ child.value }}</span>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n }\r\n </div>\r\n </div>\r\n <div class=\"modal-footer\">\r\n @if (confirm) {\r\n <button class=\"btn cancel\" (click)=\"onCancel()\">Cancelar</button>\r\n <button class=\"btn confirm\" (click)=\"onConfirm()\">\r\n {{ confirmLabel }}\r\n </button>\r\n } @else {\r\n <button class=\"btn confirm\" (click)=\"onConfirm()\">\r\n {{ confirmLabel }}\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".modal-backdrop{position:fixed;inset:0;background:#00000073;display:flex;align-items:center;justify-content:center;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);z-index:10000}.modal-card{width:30%;max-width:50%;max-height:90%;background:#ebe8d6;border-radius:28px;padding:32px 48px;animation:fadeIn .25s ease;border:1px solid rgba(255,255,255,.07);box-shadow:0 8px 20px #0003;overflow:hidden;display:flex;flex-direction:column;transition:max-height .35s cubic-bezier(.4,0,.2,1)}.modal-header{position:relative;display:flex;align-items:center;gap:12px;color:#0c0c0c;justify-content:center}.modal-header h2{font-weight:700;font-size:24px;margin:0;text-transform:uppercase}.close-btn{position:absolute;right:-36px;top:-24px;width:36px;height:36px;border-radius:50%;background:#ebe8d6;display:flex;align-items:center;justify-content:center;cursor:pointer;color:#333;transition:background .2s ease,transform .2s ease}.close-btn:hover{background:#d8d6c0;transform:scale(1.05)}.close-btn svg{width:18px;height:18px}.modal-body{position:relative;margin-top:16px;text-align:center;flex:1;overflow:hidden;display:flex;flex-direction:column;transition:all .35s cubic-bezier(.4,0,.2,1)}.modal-body p{color:#555;margin:0;font-size:14px;line-height:1.5;padding-top:21px}.modal-footer{margin-top:25px;display:flex;justify-content:center;gap:10px;flex-shrink:0}button{background-color:transparent;border:none}.btn{padding:10px 16px;border-radius:99px;font-weight:700;cursor:pointer;border:none}.btn:hover{background-color:#61661f}.btn.cancel{background:transparent;border:1px solid #454733;color:#454733}.btn.cancel:hover{background-color:#454733;color:#fff}.btn.confirm{background:#596300;color:#fff}@keyframes fadeIn{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.btn.confirm.warning,.btn.confirm.error{background-color:#ba1a1a;color:#fff}.btn.confirm.info{background-color:#063546;color:#fff}.btn.confirm.success{background-color:#596300;color:#fff}.info-container{max-height:400;background:#e3e3d1;border-radius:20px;padding:24px;flex:1;overflow-y:auto;scrollbar-width:thin;scrollbar-color:rgba(0,0,0,.35) transparent;transition:max-height .35s cubic-bezier(.4,0,.2,1)}.info-container.expanded{max-height:600px}.info-container::-webkit-scrollbar{width:6px;background:transparent}.info-container::-webkit-scrollbar-track{background:transparent}.info-container::-webkit-scrollbar-thumb{background:#00000059;border-radius:6px}.info-container::-webkit-scrollbar-thumb:hover{background:#00000080}.info-item{border-bottom:1px solid rgba(0,0,0,.05);padding:16px 0}.info-item:last-child{border-bottom:none}.info-main{display:flex;flex-direction:column;text-align:center}.info-main-expanded{cursor:pointer}.info-children{margin-top:12px}.child-item{padding:16px 0;border-bottom:1px solid rgba(0,0,0,.05);margin:0 16px}.child-item:first-child{border-top:1px solid rgba(0,0,0,.05)}.child-item:last-child{border-bottom:none}.label{font-size:16px;color:#555;text-transform:uppercase}.value{font-size:16px;font-weight:700;display:flex;justify-content:center;gap:6px;align-items:center}.arrow{font-size:12px}\n"] }]
2097
+ args: [{ selector: 'lib-dialog-confirmation', imports: [CommonModule], template: "<div class=\"modal-backdrop\">\r\n <div class=\"modal-card\">\r\n <div class=\"modal-header\">\r\n <h2>{{ title }}</h2>\r\n <button class=\"close-btn\" (click)=\"onCancel()\" aria-label=\"Cerrar\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\"\r\n viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M18 6l-12 12\" />\r\n <path d=\"M6 6l12 12\" />\r\n </svg>\r\n </button>\r\n </div>\r\n <div class=\"modal-body\">\r\n <div class=\"info-container\" [class.expanded]=\"expandedIndex !== null\">\r\n @for (item of items; track item.key; let i = $index) {\r\n\r\n <div class=\"info-item\">\r\n <div\r\n class=\"info-main\"\r\n [class.info-main-expanded]=\"item.expandible\"\r\n (click)=\"item.expandible && toggle(i)\"\r\n >\r\n <span class=\"label\"\r\n >{{ item.label }} @if (item.expandible) {\r\n <span class=\"arrow\"> {{ expandedIndex === i ? '\u25B2' : '\u25BC' }} </span>\r\n }\r\n </span>\r\n <span class=\"value\"> {{ item.value }} </span>\r\n </div>\r\n\r\n @if (expandedIndex === i && item.children?.length) {\r\n <div class=\"info-children\">\r\n @for (child of item.children; track child.key) {\r\n <div class=\"info-item child-item\">\r\n <div class=\"info-main\">\r\n <span class=\"label\">{{ child.label }}</span>\r\n <span class=\"value\">{{ child.value }}</span>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n }\r\n </div>\r\n </div>\r\n <div class=\"modal-footer\">\r\n @if (confirm) {\r\n <button class=\"btn cancel\" (click)=\"onCancel()\">Cancelar</button>\r\n <button class=\"btn confirm\" (click)=\"onConfirm()\">\r\n {{ confirmLabel }}\r\n </button>\r\n } @else {\r\n <button class=\"btn confirm\" (click)=\"onConfirm()\">\r\n {{ confirmLabel }}\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".modal-backdrop{position:fixed;inset:0;background:#00000073;display:flex;align-items:center;justify-content:center;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);z-index:10000}.modal-card{width:35%;max-width:50%;max-height:90%;background:#ebe8d6;border-radius:28px;padding:32px 48px;animation:fadeIn .25s ease;border:1px solid rgba(255,255,255,.07);box-shadow:0 8px 20px #0003;overflow:hidden;display:flex;flex-direction:column;transition:max-height .35s cubic-bezier(.4,0,.2,1)}.modal-header{position:relative;display:flex;align-items:center;gap:12px;color:#0c0c0c;justify-content:center}.modal-header h2{font-weight:700;font-size:24px;margin:0;text-transform:uppercase}.close-btn{position:absolute;right:-36px;top:-24px;width:36px;height:36px;border-radius:50%;background:#ebe8d6;display:flex;align-items:center;justify-content:center;cursor:pointer;color:#333;transition:background .2s ease,transform .2s ease}.close-btn:hover{background:#d8d6c0;transform:scale(1.05)}.close-btn svg{width:18px;height:18px}.modal-body{position:relative;margin-top:16px;text-align:center;flex:1;overflow:hidden;display:flex;flex-direction:column;transition:all .35s cubic-bezier(.4,0,.2,1)}.modal-body p{color:#555;margin:0;font-size:14px;line-height:1.5;padding-top:21px}.modal-footer{margin-top:25px;display:flex;justify-content:center;gap:10px;flex-shrink:0}button{background-color:transparent;border:none}.btn{padding:10px 16px;border-radius:99px;font-weight:700;cursor:pointer;border:none}.btn:hover{background-color:#61661f}.btn.cancel{background:transparent;border:1px solid #454733;color:#454733}.btn.cancel:hover{background-color:#454733;color:#fff}.btn.confirm{background:#596300;color:#fff}@keyframes fadeIn{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.btn.confirm.warning,.btn.confirm.error{background-color:#ba1a1a;color:#fff}.btn.confirm.info{background-color:#063546;color:#fff}.btn.confirm.success{background-color:#596300;color:#fff}.info-container{max-height:400;background:#e3e3d1;border-radius:20px;padding:24px;flex:1;overflow-y:auto;scrollbar-width:thin;scrollbar-color:rgba(0,0,0,.35) transparent;transition:max-height .35s cubic-bezier(.4,0,.2,1)}.info-container.expanded{max-height:600px}.info-container::-webkit-scrollbar{width:6px;background:transparent}.info-container::-webkit-scrollbar-track{background:transparent}.info-container::-webkit-scrollbar-thumb{background:#00000059;border-radius:6px}.info-container::-webkit-scrollbar-thumb:hover{background:#00000080}.info-item{border-bottom:1px solid rgba(0,0,0,.05);padding:16px 0}.info-item:last-child{border-bottom:none}.info-main{display:flex;flex-direction:column;text-align:center}.info-main-expanded{cursor:pointer}.info-children{margin-top:12px}.child-item{padding:16px 0;border-bottom:1px solid rgba(0,0,0,.05);margin:0 16px}.child-item:first-child{border-top:1px solid rgba(0,0,0,.05)}.child-item:last-child{border-bottom:none}.label{font-size:16px;color:#555;text-transform:uppercase}.value{font-size:16px;font-weight:700;display:flex;justify-content:center;gap:6px;align-items:center}.arrow{font-size:12px}\n"] }]
2066
2098
  }], propDecorators: { title: [{
2067
- type: Input
2099
+ type: Input$1
2068
2100
  }], confirm: [{
2069
- type: Input
2101
+ type: Input$1
2070
2102
  }], confirmLabel: [{
2071
- type: Input
2103
+ type: Input$1
2072
2104
  }], items: [{
2073
- type: Input
2105
+ type: Input$1
2074
2106
  }], close: [{
2075
2107
  type: Output
2076
2108
  }] } });
2077
2109
 
2110
+ const TOAST_EVENTS = {
2111
+ SHOW_TOAST: 'SHOW_TOAST',
2112
+ SHOW_TOAST_WITH_ACTION: 'SHOW_TOAST_WITH_ACTION',
2113
+ HIDE_TOAST: 'HIDE_TOAST',
2114
+ };
2115
+ class ToastHelper {
2116
+ static show(description, duration) {
2117
+ PubSub.publish(TOAST_EVENTS.SHOW_TOAST, {
2118
+ description,
2119
+ duration,
2120
+ });
2121
+ }
2122
+ static showWithAction(description, buttonText, action, duration) {
2123
+ PubSub.publish(TOAST_EVENTS.SHOW_TOAST_WITH_ACTION, {
2124
+ description,
2125
+ buttonText,
2126
+ action,
2127
+ duration,
2128
+ });
2129
+ }
2130
+ static success(message, duration) {
2131
+ this.show(`${message}`, duration);
2132
+ }
2133
+ static error(message, duration) {
2134
+ this.show(`${message}`, duration || 6000);
2135
+ }
2136
+ static warning(message, duration) {
2137
+ this.show(`${message}`, duration);
2138
+ }
2139
+ static info(message, duration) {
2140
+ this.show(`ℹ${message}`, duration);
2141
+ }
2142
+ static hide() {
2143
+ PubSub.publish(TOAST_EVENTS.HIDE_TOAST);
2144
+ }
2145
+ static showUndo(message, undoAction, duration = 8000) {
2146
+ this.showWithAction(message, 'Deshacer', undoAction, duration);
2147
+ }
2148
+ }
2149
+
2150
+ class NotFoundModal {
2151
+ isVisible = input(false, ...(ngDevMode ? [{ debugName: "isVisible" }] : []));
2152
+ title = input('Documento no encontrado', ...(ngDevMode ? [{ debugName: "title" }] : []));
2153
+ message = input('No encontrado', ...(ngDevMode ? [{ debugName: "message" }] : []));
2154
+ onClose = output();
2155
+ onOverlayClick(event) {
2156
+ if (event.target === event.currentTarget) {
2157
+ this.onClose.emit();
2158
+ }
2159
+ }
2160
+ onAccept() {
2161
+ this.onClose.emit();
2162
+ }
2163
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: NotFoundModal, deps: [], target: i0.ɵɵFactoryTarget.Component });
2164
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.16", type: NotFoundModal, isStandalone: true, selector: "lib-not-found-modal", inputs: { isVisible: { classPropertyName: "isVisible", publicName: "isVisible", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onClose: "onClose" }, ngImport: i0, template: "<div\r\n class=\"modal-overlay\"\r\n (click)=\"onOverlayClick($event)\"\r\n role=\"dialog\"\r\n aria-modal=\"true\"\r\n>\r\n <div class=\"modal-content\" (click)=\"$event.stopPropagation()\">\r\n <div class=\"modal-header\">\r\n <div class=\"icon-container\">\r\n <svg\r\n width=\"48\"\r\n height=\"48\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n class=\"error-icon\"\r\n >\r\n <circle cx=\"12\" cy=\"12\" r=\"10\" stroke=\"#ef4444\" stroke-width=\"2\" />\r\n <path\r\n d=\"M15 9l-6 6\"\r\n stroke=\"#ef4444\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n />\r\n <path\r\n d=\"M9 9l6 6\"\r\n stroke=\"#ef4444\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n />\r\n </svg>\r\n </div>\r\n <h2 class=\"modal-title\">{{ title() }}</h2>\r\n </div>\r\n\r\n <div class=\"modal-body\">\r\n <p class=\"modal-message\">{{ message() }}</p>\r\n </div>\r\n\r\n <div class=\"modal-footer\">\r\n <button\r\n class=\"btn-primary\"\r\n (click)=\"onAccept()\"\r\n type=\"button\"\r\n [attr.aria-label]=\"'Cerrar modal de documento no encontrado'\"\r\n >\r\n Aceptar\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n", styles: [".modal-overlay{position:fixed;top:0;left:0;width:100vw;height:100vh;background-color:#0006;display:flex;justify-content:center;align-items:center;z-index:10000;animation:fadeIn .3s ease-out;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.modal-content{background:#fff;border-radius:16px;box-shadow:0 20px 25px -5px #0000001a,0 10px 10px -5px #0000000a,0 0 0 1px #0000000d;max-width:500px;width:90%;max-height:90vh;overflow:auto;animation:slideIn .3s cubic-bezier(.34,1.56,.64,1);position:relative;padding:10px}.modal-header{padding:32px 32px 24px;text-align:center;border-bottom:1px solid #f3f4f6;position:relative}.icon-container{margin-bottom:16px;display:flex;justify-content:center}.icon-container svg{width:50px;height:50px}.error-icon{animation:shake .6s ease-in-out;filter:drop-shadow(0 2px 4px rgba(239,68,68,.1))}.modal-title{font-size:3.2rem;font-weight:600;color:#111827;margin:0}.modal-message{font-size:1.6rem;color:#111827;line-height:1.6;margin:0;text-align:center}.modal-footer{padding:24px 32px 32px;display:flex;justify-content:center;border-top:1px solid #f3f4f6}.btn-primary{padding:14px;border-radius:8px;font-weight:600;font-size:1.4rem;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);border:none;font-family:system-ui,-apple-system,Segoe UI,sans-serif;min-width:120px;position:relative;overflow:hidden}.btn-primary{background-color:#3b82f6;color:#fff;box-shadow:0 1px 2px #0000000d}.btn-primary:hover{background-color:#2563eb;transform:translateY(-1px);box-shadow:0 4px 8px #3b82f64d}.btn-primary:active{transform:translateY(0);box-shadow:0 1px 2px #0000000d}.btn-primary:focus,.btn-secondary:focus{outline:2px solid #3b82f6;outline-offset:2px}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideIn{0%{opacity:0;transform:translateY(-20px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes shake{0%,to{transform:translate(0)}10%,30%,50%,70%,90%{transform:translate(-3px)}20%,40%,60%,80%{transform:translate(3px)}}@media (max-width: 640px){.modal-content{width:95%;margin:20px;border-radius:12px}.modal-header,.modal-body,.modal-footer{padding-left:20px;padding-right:20px}.modal-header{padding-top:24px;padding-bottom:20px}.modal-body{padding-top:20px;padding-bottom:20px}.modal-footer{flex-direction:column-reverse;padding-top:20px;padding-bottom:24px}.btn-primary,.btn-secondary{width:100%;min-width:unset}.modal-title{font-size:20px}.modal-message{font-size:14px}}@media (max-width: 480px){.modal-content{width:100%;margin:10px;border-radius:8px}}\n"] });
2165
+ }
2166
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: NotFoundModal, decorators: [{
2167
+ type: Component,
2168
+ args: [{ selector: 'lib-not-found-modal', standalone: true, imports: [], template: "<div\r\n class=\"modal-overlay\"\r\n (click)=\"onOverlayClick($event)\"\r\n role=\"dialog\"\r\n aria-modal=\"true\"\r\n>\r\n <div class=\"modal-content\" (click)=\"$event.stopPropagation()\">\r\n <div class=\"modal-header\">\r\n <div class=\"icon-container\">\r\n <svg\r\n width=\"48\"\r\n height=\"48\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n class=\"error-icon\"\r\n >\r\n <circle cx=\"12\" cy=\"12\" r=\"10\" stroke=\"#ef4444\" stroke-width=\"2\" />\r\n <path\r\n d=\"M15 9l-6 6\"\r\n stroke=\"#ef4444\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n />\r\n <path\r\n d=\"M9 9l6 6\"\r\n stroke=\"#ef4444\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n />\r\n </svg>\r\n </div>\r\n <h2 class=\"modal-title\">{{ title() }}</h2>\r\n </div>\r\n\r\n <div class=\"modal-body\">\r\n <p class=\"modal-message\">{{ message() }}</p>\r\n </div>\r\n\r\n <div class=\"modal-footer\">\r\n <button\r\n class=\"btn-primary\"\r\n (click)=\"onAccept()\"\r\n type=\"button\"\r\n [attr.aria-label]=\"'Cerrar modal de documento no encontrado'\"\r\n >\r\n Aceptar\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n", styles: [".modal-overlay{position:fixed;top:0;left:0;width:100vw;height:100vh;background-color:#0006;display:flex;justify-content:center;align-items:center;z-index:10000;animation:fadeIn .3s ease-out;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.modal-content{background:#fff;border-radius:16px;box-shadow:0 20px 25px -5px #0000001a,0 10px 10px -5px #0000000a,0 0 0 1px #0000000d;max-width:500px;width:90%;max-height:90vh;overflow:auto;animation:slideIn .3s cubic-bezier(.34,1.56,.64,1);position:relative;padding:10px}.modal-header{padding:32px 32px 24px;text-align:center;border-bottom:1px solid #f3f4f6;position:relative}.icon-container{margin-bottom:16px;display:flex;justify-content:center}.icon-container svg{width:50px;height:50px}.error-icon{animation:shake .6s ease-in-out;filter:drop-shadow(0 2px 4px rgba(239,68,68,.1))}.modal-title{font-size:3.2rem;font-weight:600;color:#111827;margin:0}.modal-message{font-size:1.6rem;color:#111827;line-height:1.6;margin:0;text-align:center}.modal-footer{padding:24px 32px 32px;display:flex;justify-content:center;border-top:1px solid #f3f4f6}.btn-primary{padding:14px;border-radius:8px;font-weight:600;font-size:1.4rem;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);border:none;font-family:system-ui,-apple-system,Segoe UI,sans-serif;min-width:120px;position:relative;overflow:hidden}.btn-primary{background-color:#3b82f6;color:#fff;box-shadow:0 1px 2px #0000000d}.btn-primary:hover{background-color:#2563eb;transform:translateY(-1px);box-shadow:0 4px 8px #3b82f64d}.btn-primary:active{transform:translateY(0);box-shadow:0 1px 2px #0000000d}.btn-primary:focus,.btn-secondary:focus{outline:2px solid #3b82f6;outline-offset:2px}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideIn{0%{opacity:0;transform:translateY(-20px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes shake{0%,to{transform:translate(0)}10%,30%,50%,70%,90%{transform:translate(-3px)}20%,40%,60%,80%{transform:translate(3px)}}@media (max-width: 640px){.modal-content{width:95%;margin:20px;border-radius:12px}.modal-header,.modal-body,.modal-footer{padding-left:20px;padding-right:20px}.modal-header{padding-top:24px;padding-bottom:20px}.modal-body{padding-top:20px;padding-bottom:20px}.modal-footer{flex-direction:column-reverse;padding-top:20px;padding-bottom:24px}.btn-primary,.btn-secondary{width:100%;min-width:unset}.modal-title{font-size:20px}.modal-message{font-size:14px}}@media (max-width: 480px){.modal-content{width:100%;margin:10px;border-radius:8px}}\n"] }]
2169
+ }], propDecorators: { isVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "isVisible", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: false }] }], onClose: [{ type: i0.Output, args: ["onClose"] }] } });
2170
+
2171
+ class Loader {
2172
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Loader, deps: [], target: i0.ɵɵFactoryTarget.Component });
2173
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: Loader, isStandalone: true, selector: "lib-loader", ngImport: i0, template: "<div class=\"loader-overlay\">\r\n <div class=\"loader\"></div>\r\n</div>\r\n", styles: [".loader-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background-color:#0006;display:flex;align-items:center;justify-content:center;z-index:99999}.loader{width:40px;height:40px;--c: no-repeat linear-gradient(#596300 0 0);background:var(--c),var(--c),var(--c),var(--c);background-size:21px 21px;animation:l5 1.5s infinite cubic-bezier(.3,1,0,1)}@keyframes l5{0%{background-position:0 0,100% 0,100% 100%,0 100%}33%{background-position:0 0,100% 0,100% 100%,0 100%;width:60px;height:60px}66%{background-position:100% 0,100% 100%,0 100%,0 0;width:60px;height:60px}to{background-position:100% 0,100% 100%,0 100%,0 0}}\n"] });
2174
+ }
2175
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Loader, decorators: [{
2176
+ type: Component,
2177
+ args: [{ selector: 'lib-loader', imports: [], template: "<div class=\"loader-overlay\">\r\n <div class=\"loader\"></div>\r\n</div>\r\n", styles: [".loader-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background-color:#0006;display:flex;align-items:center;justify-content:center;z-index:99999}.loader{width:40px;height:40px;--c: no-repeat linear-gradient(#596300 0 0);background:var(--c),var(--c),var(--c),var(--c);background-size:21px 21px;animation:l5 1.5s infinite cubic-bezier(.3,1,0,1)}@keyframes l5{0%{background-position:0 0,100% 0,100% 100%,0 100%}33%{background-position:0 0,100% 0,100% 100%,0 100%;width:60px;height:60px}66%{background-position:100% 0,100% 100%,0 100%,0 0;width:60px;height:60px}to{background-position:100% 0,100% 100%,0 100%,0 0}}\n"] }]
2178
+ }] });
2179
+
2180
+ class ProgressFormService {
2181
+ currentPage = signal(1, ...(ngDevMode ? [{ debugName: "currentPage" }] : []));
2182
+ totalPages = signal(6, ...(ngDevMode ? [{ debugName: "totalPages" }] : []));
2183
+ stepsConfig = {
2184
+ 1: { title: 'Paso 1', key: 'step1' },
2185
+ 2: { title: 'Paso 2', key: 'step2' },
2186
+ };
2187
+ resetData() {
2188
+ this.currentPage.set(1);
2189
+ }
2190
+ getProgressText() {
2191
+ return `${this.currentPage()}/${this.totalPages()}`;
2192
+ }
2193
+ getCurrentPageTitle() {
2194
+ const currentPage = this.currentPage();
2195
+ return this.stepsConfig[currentPage]?.title || `Página ${currentPage}`;
2196
+ }
2197
+ nextPage() {
2198
+ const current = this.currentPage();
2199
+ if (current < this.totalPages()) {
2200
+ this.currentPage.set(current + 1);
2201
+ return true;
2202
+ }
2203
+ return false;
2204
+ }
2205
+ prevPage() {
2206
+ const current = this.currentPage();
2207
+ if (current > 1) {
2208
+ this.currentPage.set(current - 1);
2209
+ return true;
2210
+ }
2211
+ return false;
2212
+ }
2213
+ getProgressPercentage() {
2214
+ const current = this.currentPage();
2215
+ const total = this.totalPages();
2216
+ return Math.round((current / total) * 100);
2217
+ }
2218
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ProgressFormService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2219
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ProgressFormService, providedIn: 'root' });
2220
+ }
2221
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ProgressFormService, decorators: [{
2222
+ type: Injectable,
2223
+ args: [{
2224
+ providedIn: 'root',
2225
+ }]
2226
+ }] });
2227
+
2228
+ class ProgressBar {
2229
+ progress;
2230
+ constructor(progress) {
2231
+ this.progress = progress;
2232
+ }
2233
+ title = input('', ...(ngDevMode ? [{ debugName: "title" }] : []));
2234
+ current = input(1, ...(ngDevMode ? [{ debugName: "current" }] : []));
2235
+ total = input(1, ...(ngDevMode ? [{ debugName: "total" }] : []));
2236
+ get percentage() {
2237
+ return Math.round((this.current() / this.total()) * 100);
2238
+ }
2239
+ get text() {
2240
+ return `Paso ${this.current()} de ${this.total()}`;
2241
+ }
2242
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ProgressBar, deps: [{ token: ProgressFormService }], target: i0.ɵɵFactoryTarget.Component });
2243
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.16", type: ProgressBar, isStandalone: true, selector: "lib-progress-bar", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, current: { classPropertyName: "current", publicName: "current", isSignal: true, isRequired: false, transformFunction: null }, total: { classPropertyName: "total", publicName: "total", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"progress-container\">\r\n <div class=\"progress-header\">\r\n <span class=\"progress-title\">{{ title() }}</span>\r\n <span class=\"progress-fraction\">{{ text }}</span>\r\n </div>\r\n\r\n <div class=\"progress-bar\">\r\n <div\r\n class=\"progress-fill\"\r\n [style.width.%]=\"percentage\"\r\n ></div>\r\n </div>\r\n</div>\r\n", styles: [".progress-container{width:100%}.progress-header{display:flex;justify-content:center;align-items:center;margin-bottom:7px;gap:4px}.progress-title{color:#454733;font-size:1rem;font-size:400}.progress-fraction{font-size:1rem;color:#454733;font-size:400}.progress-bar{width:100%;height:8px;background-color:#dee58f;border-radius:4px;overflow:hidden;margin-bottom:8px}.progress-fill{height:100%;background-color:#596300;border-radius:4px;transition:width .4s ease-in-out}.progress-percentage{text-align:center;font-size:12px;color:#6c757d}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
2244
+ }
2245
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ProgressBar, decorators: [{
2246
+ type: Component,
2247
+ args: [{ selector: 'lib-progress-bar', standalone: true, imports: [CommonModule], template: "<div class=\"progress-container\">\r\n <div class=\"progress-header\">\r\n <span class=\"progress-title\">{{ title() }}</span>\r\n <span class=\"progress-fraction\">{{ text }}</span>\r\n </div>\r\n\r\n <div class=\"progress-bar\">\r\n <div\r\n class=\"progress-fill\"\r\n [style.width.%]=\"percentage\"\r\n ></div>\r\n </div>\r\n</div>\r\n", styles: [".progress-container{width:100%}.progress-header{display:flex;justify-content:center;align-items:center;margin-bottom:7px;gap:4px}.progress-title{color:#454733;font-size:1rem;font-size:400}.progress-fraction{font-size:1rem;color:#454733;font-size:400}.progress-bar{width:100%;height:8px;background-color:#dee58f;border-radius:4px;overflow:hidden;margin-bottom:8px}.progress-fill{height:100%;background-color:#596300;border-radius:4px;transition:width .4s ease-in-out}.progress-percentage{text-align:center;font-size:12px;color:#6c757d}\n"] }]
2248
+ }], ctorParameters: () => [{ type: ProgressFormService }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], current: [{ type: i0.Input, args: [{ isSignal: true, alias: "current", required: false }] }], total: [{ type: i0.Input, args: [{ isSignal: true, alias: "total", required: false }] }] } });
2249
+
2250
+ class ProcessingOverlay {
2251
+ loadingText = input('', ...(ngDevMode ? [{ debugName: "loadingText" }] : []));
2252
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ProcessingOverlay, deps: [], target: i0.ɵɵFactoryTarget.Component });
2253
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.16", type: ProcessingOverlay, isStandalone: true, selector: "lib-processing-overlay", inputs: { loadingText: { classPropertyName: "loadingText", publicName: "loadingText", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"loading-container\">\r\n <div class=\"loading-content\">\r\n <figure>\r\n <svg width=\"128\" height=\"128\" viewBox=\"0 0 128 128\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M58.8943 10.1325C61.244 6.40017 66.7559 6.40017 69.1056 10.1325L74.7379 19.079C76.2827 21.5328 79.399 22.5304 82.1127 21.4398L92.0068 17.4636C96.1345 15.8048 100.594 18.9967 100.268 23.3769L99.487 33.8765C99.2728 36.7562 101.199 39.368 104.045 40.0572L114.422 42.57C118.751 43.6183 120.454 48.783 117.577 52.138L110.681 60.18C108.79 62.3857 108.79 65.6141 110.681 67.8198L117.577 75.8619C120.454 79.2169 118.751 84.3816 114.422 85.4298L104.045 87.9427C101.199 88.6319 99.2728 91.2436 99.487 94.1234L100.268 104.623C100.594 109.003 96.1345 112.195 92.0069 110.536L82.1127 106.56C79.399 105.469 76.2827 106.467 74.7379 108.921L69.1056 117.867C66.756 121.6 61.244 121.6 58.8943 117.867L53.2621 108.921C51.7173 106.467 48.6009 105.469 45.8872 106.56L35.9931 110.536C31.8655 112.195 27.4062 109.003 27.732 104.623L28.5129 94.1234C28.7271 91.2436 26.8011 88.6319 23.955 87.9427L13.5783 85.4299C9.24928 84.3816 7.546 79.2169 10.4228 75.8619L17.3186 67.8198C19.21 65.6141 19.21 62.3857 17.3186 60.18L10.4228 52.138C7.546 48.783 9.24928 43.6183 13.5783 42.57L23.955 40.0572C26.8011 39.368 28.7271 36.7562 28.5129 33.8765L27.732 23.3769C27.4062 18.9967 31.8655 15.8048 35.9931 17.4636L45.8872 21.4398C48.6009 22.5304 51.7173 21.5328 53.2621 19.079L58.8943 10.1325Z\" fill=\"#BFD100\"/>\r\n </svg> \r\n </figure>\r\n <p class=\"loading-text\">{{ loadingText() }}</p>\r\n </div>\r\n</div>\r\n", styles: [".loading-container{position:fixed;top:0;left:0;width:100vw;height:100vh;background-color:#00000076;display:flex;justify-content:center;align-items:center;z-index:9999}.loading-content{display:flex;flex-direction:column;align-items:center;gap:20px}.loading-content figure{margin:0;display:flex;justify-content:center;align-items:center}.loading-content figure svg{width:80px;height:80px;animation:svgSpin 2s linear infinite}@keyframes svgSpin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes svgPulse{0%{opacity:1;transform:scale(1)}50%{opacity:.6;transform:scale(1.1)}to{opacity:1;transform:scale(1)}}@keyframes svgBounce{0%,20%,50%,80%,to{transform:translateY(0)}40%{transform:translateY(-10px)}60%{transform:translateY(-5px)}}.loading-text{color:#fafae8;font-size:18px;font-weight:500;margin:0;font-family:Segoe UI,Tahoma,Geneva,Verdana,sans-serif}\n"] });
2254
+ }
2255
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ProcessingOverlay, decorators: [{
2256
+ type: Component,
2257
+ args: [{ selector: 'lib-processing-overlay', imports: [], template: "<div class=\"loading-container\">\r\n <div class=\"loading-content\">\r\n <figure>\r\n <svg width=\"128\" height=\"128\" viewBox=\"0 0 128 128\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M58.8943 10.1325C61.244 6.40017 66.7559 6.40017 69.1056 10.1325L74.7379 19.079C76.2827 21.5328 79.399 22.5304 82.1127 21.4398L92.0068 17.4636C96.1345 15.8048 100.594 18.9967 100.268 23.3769L99.487 33.8765C99.2728 36.7562 101.199 39.368 104.045 40.0572L114.422 42.57C118.751 43.6183 120.454 48.783 117.577 52.138L110.681 60.18C108.79 62.3857 108.79 65.6141 110.681 67.8198L117.577 75.8619C120.454 79.2169 118.751 84.3816 114.422 85.4298L104.045 87.9427C101.199 88.6319 99.2728 91.2436 99.487 94.1234L100.268 104.623C100.594 109.003 96.1345 112.195 92.0069 110.536L82.1127 106.56C79.399 105.469 76.2827 106.467 74.7379 108.921L69.1056 117.867C66.756 121.6 61.244 121.6 58.8943 117.867L53.2621 108.921C51.7173 106.467 48.6009 105.469 45.8872 106.56L35.9931 110.536C31.8655 112.195 27.4062 109.003 27.732 104.623L28.5129 94.1234C28.7271 91.2436 26.8011 88.6319 23.955 87.9427L13.5783 85.4299C9.24928 84.3816 7.546 79.2169 10.4228 75.8619L17.3186 67.8198C19.21 65.6141 19.21 62.3857 17.3186 60.18L10.4228 52.138C7.546 48.783 9.24928 43.6183 13.5783 42.57L23.955 40.0572C26.8011 39.368 28.7271 36.7562 28.5129 33.8765L27.732 23.3769C27.4062 18.9967 31.8655 15.8048 35.9931 17.4636L45.8872 21.4398C48.6009 22.5304 51.7173 21.5328 53.2621 19.079L58.8943 10.1325Z\" fill=\"#BFD100\"/>\r\n </svg> \r\n </figure>\r\n <p class=\"loading-text\">{{ loadingText() }}</p>\r\n </div>\r\n</div>\r\n", styles: [".loading-container{position:fixed;top:0;left:0;width:100vw;height:100vh;background-color:#00000076;display:flex;justify-content:center;align-items:center;z-index:9999}.loading-content{display:flex;flex-direction:column;align-items:center;gap:20px}.loading-content figure{margin:0;display:flex;justify-content:center;align-items:center}.loading-content figure svg{width:80px;height:80px;animation:svgSpin 2s linear infinite}@keyframes svgSpin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes svgPulse{0%{opacity:1;transform:scale(1)}50%{opacity:.6;transform:scale(1.1)}to{opacity:1;transform:scale(1)}}@keyframes svgBounce{0%,20%,50%,80%,to{transform:translateY(0)}40%{transform:translateY(-10px)}60%{transform:translateY(-5px)}}.loading-text{color:#fafae8;font-size:18px;font-weight:500;margin:0;font-family:Segoe UI,Tahoma,Geneva,Verdana,sans-serif}\n"] }]
2258
+ }], propDecorators: { loadingText: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingText", required: false }] }] } });
2259
+
2260
+ class InfoGroup {
2261
+ items = input([], ...(ngDevMode ? [{ debugName: "items" }] : []));
2262
+ title = input(null, ...(ngDevMode ? [{ debugName: "title" }] : []));
2263
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: InfoGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
2264
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: InfoGroup, isStandalone: true, selector: "lib-info-group", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"info-card\">\r\n @if (title()) {\r\n <h3 class=\"info-title\">{{ title() }}</h3>\r\n }\r\n\r\n <div class=\"info-grid\">\r\n @for (item of items(); track item.label) {\r\n <div class=\"info-row\">\r\n <span class=\"info-label\">{{ item.label }}</span>\r\n <span class=\"info-value\">\r\n {{\r\n item.value === true ? \"S\u00CD\" :\r\n item.value === false ? \"NO\" :\r\n item.value || \"-\"\r\n }}\r\n </span>\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n", styles: [".info-card{background:#f7f6e3;border-radius:18px;padding:20px 24px;width:100%}.info-title{font-size:14px;font-weight:700;color:#40484c;margin-bottom:16px}.info-grid{display:grid;grid-template-columns:1fr 1fr;column-gap:32px;row-gap:14px}.info-row{display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid rgba(64,72,76,.15);padding-bottom:14px}.info-label{font-size:13px;color:#40484c;font-weight:500}.info-value{font-size:13px;color:#40484c;font-weight:600}@media (max-width: 768px){.info-grid{grid-template-columns:1fr}}\n"] });
2265
+ }
2266
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: InfoGroup, decorators: [{
2267
+ type: Component,
2268
+ args: [{ selector: 'lib-info-group', imports: [], template: "<div class=\"info-card\">\r\n @if (title()) {\r\n <h3 class=\"info-title\">{{ title() }}</h3>\r\n }\r\n\r\n <div class=\"info-grid\">\r\n @for (item of items(); track item.label) {\r\n <div class=\"info-row\">\r\n <span class=\"info-label\">{{ item.label }}</span>\r\n <span class=\"info-value\">\r\n {{\r\n item.value === true ? \"S\u00CD\" :\r\n item.value === false ? \"NO\" :\r\n item.value || \"-\"\r\n }}\r\n </span>\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n", styles: [".info-card{background:#f7f6e3;border-radius:18px;padding:20px 24px;width:100%}.info-title{font-size:14px;font-weight:700;color:#40484c;margin-bottom:16px}.info-grid{display:grid;grid-template-columns:1fr 1fr;column-gap:32px;row-gap:14px}.info-row{display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid rgba(64,72,76,.15);padding-bottom:14px}.info-label{font-size:13px;color:#40484c;font-weight:500}.info-value{font-size:13px;color:#40484c;font-weight:600}@media (max-width: 768px){.info-grid{grid-template-columns:1fr}}\n"] }]
2269
+ }], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }] } });
2270
+
2271
+ class FeatureCard {
2272
+ feature = input(...(ngDevMode ? [undefined, { debugName: "feature" }] : []));
2273
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: FeatureCard, deps: [], target: i0.ɵɵFactoryTarget.Component });
2274
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.16", type: FeatureCard, isStandalone: true, selector: "lib-feature-card", inputs: { feature: { classPropertyName: "feature", publicName: "feature", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"feature-card\">\r\n <div class=\"feature-icon\">\r\n <img [src]=\"feature()?.icon\" alt=\"{{ feature()?.title }}\" />\r\n </div>\r\n <div>\r\n <h3>{{ feature()?.title }}</h3>\r\n <p>{{ feature()?.description }}</p>\r\n </div>\r\n</div>\r\n\r\n", styles: [".feature-card{position:relative;flex:1;padding:8px;display:flex;align-items:center;gap:8px;border-radius:8px}.feature-icon{flex:0 0 50px;height:50px;border-radius:50%;display:flex;align-items:center;justify-content:center;background-color:#dee58f;margin-right:10px}.feature-icon img{width:28px;height:28px;color:#61661f}.feature-content{flex:1;display:flex;flex-direction:column}.feature-card h3{margin:0 0 5px;font-size:1.6rem;font-weight:600;color:#171c1f;transition:color .3s ease}.feature-card p{margin:0;color:#171c1f;font-weight:400;line-height:1.6;font-size:1.4rem}@media (max-width: 768px){.feature-card{padding:12px;gap:12px}.feature-icon{flex:0 0 48px;height:48px;margin-right:8px}.feature-icon img{width:28px;height:28px}.feature-card h3{font-size:1.5rem}.feature-card p{font-size:1.3rem}}@media (max-width: 640px){.feature-card{flex-direction:column;align-items:center;text-align:center;padding:16px 12px;gap:12px;min-height:140px}.feature-icon{flex:none;margin-right:0;margin-bottom:8px;width:56px;height:56px}.feature-icon img{width:32px;height:32px}.feature-content{align-items:center;text-align:center}.feature-card h3{margin-bottom:8px;font-size:1.4rem;line-height:1.3}.feature-card p{font-size:1.2rem;line-height:1.5;max-width:200px}}@media (max-width: 480px){.feature-card{padding:14px 10px;min-height:130px;gap:10px}.feature-icon{width:52px;height:52px;margin-bottom:6px}.feature-icon img{width:30px;height:30px}.feature-card h3{font-size:1.3rem;margin-bottom:6px}.feature-card p{font-size:1.1rem;line-height:1.4;max-width:180px}}@media (max-width: 360px){.feature-card{padding:12px 8px;min-height:120px;gap:8px}.feature-icon{width:48px;height:48px;margin-bottom:4px}.feature-icon img{width:28px;height:28px}.feature-card h3{font-size:1.2rem;margin-bottom:4px;line-height:1.2}.feature-card p{font-size:1rem;line-height:1.3;max-width:160px}}.features-grid{display:flex;gap:16px;flex-wrap:wrap}\n"] });
2275
+ }
2276
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: FeatureCard, decorators: [{
2277
+ type: Component,
2278
+ args: [{ selector: 'lib-feature-card', standalone: true, template: "<div class=\"feature-card\">\r\n <div class=\"feature-icon\">\r\n <img [src]=\"feature()?.icon\" alt=\"{{ feature()?.title }}\" />\r\n </div>\r\n <div>\r\n <h3>{{ feature()?.title }}</h3>\r\n <p>{{ feature()?.description }}</p>\r\n </div>\r\n</div>\r\n\r\n", styles: [".feature-card{position:relative;flex:1;padding:8px;display:flex;align-items:center;gap:8px;border-radius:8px}.feature-icon{flex:0 0 50px;height:50px;border-radius:50%;display:flex;align-items:center;justify-content:center;background-color:#dee58f;margin-right:10px}.feature-icon img{width:28px;height:28px;color:#61661f}.feature-content{flex:1;display:flex;flex-direction:column}.feature-card h3{margin:0 0 5px;font-size:1.6rem;font-weight:600;color:#171c1f;transition:color .3s ease}.feature-card p{margin:0;color:#171c1f;font-weight:400;line-height:1.6;font-size:1.4rem}@media (max-width: 768px){.feature-card{padding:12px;gap:12px}.feature-icon{flex:0 0 48px;height:48px;margin-right:8px}.feature-icon img{width:28px;height:28px}.feature-card h3{font-size:1.5rem}.feature-card p{font-size:1.3rem}}@media (max-width: 640px){.feature-card{flex-direction:column;align-items:center;text-align:center;padding:16px 12px;gap:12px;min-height:140px}.feature-icon{flex:none;margin-right:0;margin-bottom:8px;width:56px;height:56px}.feature-icon img{width:32px;height:32px}.feature-content{align-items:center;text-align:center}.feature-card h3{margin-bottom:8px;font-size:1.4rem;line-height:1.3}.feature-card p{font-size:1.2rem;line-height:1.5;max-width:200px}}@media (max-width: 480px){.feature-card{padding:14px 10px;min-height:130px;gap:10px}.feature-icon{width:52px;height:52px;margin-bottom:6px}.feature-icon img{width:30px;height:30px}.feature-card h3{font-size:1.3rem;margin-bottom:6px}.feature-card p{font-size:1.1rem;line-height:1.4;max-width:180px}}@media (max-width: 360px){.feature-card{padding:12px 8px;min-height:120px;gap:8px}.feature-icon{width:48px;height:48px;margin-bottom:4px}.feature-icon img{width:28px;height:28px}.feature-card h3{font-size:1.2rem;margin-bottom:4px;line-height:1.2}.feature-card p{font-size:1rem;line-height:1.3;max-width:160px}}.features-grid{display:flex;gap:16px;flex-wrap:wrap}\n"] }]
2279
+ }], propDecorators: { feature: [{ type: i0.Input, args: [{ isSignal: true, alias: "feature", required: false }] }] } });
2280
+
2078
2281
  // src/app/components/public-api.ts
2079
2282
  // Exportar el componente
2080
2283
 
@@ -2082,5 +2285,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
2082
2285
  * Generated bundle index. Do not edit.
2083
2286
  */
2084
2287
 
2085
- export { DateTimeFilter, DateTimePicker, DialogAlertComponent, DialogConfirmation, DynamicFormFields, InputNumberFilter, InputSelectFilter, InputTextFilter, ModalForm, PaginationComponent, STATUS_TONE_STYLES, SelectCustomSearch, Table, WizardForm };
2288
+ export { DateTimeFilter, DateTimePicker, DialogAlertComponent, DialogConfirmation, DynamicFormFields, FeatureCard, InfoGroup, Input, InputNumberFilter, InputSelectFilter, InputTextFilter, Loader, ModalForm, NotFoundModal, PaginationComponent, ProcessingOverlay, ProgressBar, ProgressFormService, STATUS_TONE_STYLES, SelectCustomSearch, TOAST_EVENTS, Table, ToastHelper, WizardForm };
2086
2289
  //# sourceMappingURL=sapenlinea-components.mjs.map