sapenlinea-components 0.9.74 → 0.9.76

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,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { model, input, signal, computed, Component, output, HostListener, ViewChildren, forwardRef, effect, ViewChild, inject, ElementRef, booleanAttribute, DestroyRef, EventEmitter, Output, Input as Input$1, Injectable, viewChildren, ChangeDetectionStrategy } from '@angular/core';
2
+ import { model, input, signal, computed, Component, Injectable, inject, output, HostListener, ViewChildren, forwardRef, effect, ViewChild, ElementRef, booleanAttribute, DestroyRef, EventEmitter, Output, Input as Input$1, viewChildren, ChangeDetectionStrategy } from '@angular/core';
3
3
  import * as i1$1 from '@angular/common';
4
4
  import { CommonModule, UpperCasePipe } from '@angular/common';
5
5
  import * as i1 from '@angular/forms';
@@ -96,6 +96,33 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
96
96
  args: [{ selector: 'lib-pagination', standalone: true, imports: [CommonModule], template: "<div class=\"pagination-container\">\r\n <div class=\"pagination\" role=\"navigation\" aria-label=\"Pagination\">\r\n <!-- Bot\u00F3n doble atr\u00E1s -->\r\n <button class=\"icon-button\" (click)=\"goToPage(1)\" [disabled]=\"page() === 1\" aria-label=\"Ir a la primera p\u00E1gina\">\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 aria-label=\"Ir a la p\u00E1gina anterior\">\r\n \u00AB\r\n </button>\r\n\r\n <!-- N\u00FAmeros de p\u00E1gina -->\r\n <div class=\"pages\">\r\n @for (p of visiblePages(); track $index) {\r\n <button class=\"page-btn\" [class.active]=\"p === page()\" [disabled]=\"p === '...'\" (click)=\"goToPage(p)\"\r\n [attr.aria-current]=\"p === page() ? 'page' : null\"\r\n [attr.aria-label]=\"p === '...' ? 'M\u00E1s p\u00E1ginas' : 'Ir a la p\u00E1gina ' + p\">\r\n {{ p }}\r\n </button>\r\n }\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 aria-label=\"Ir a la p\u00E1gina siguiente\">\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 aria-label=\"Ir a la \u00FAltima p\u00E1gina\">\r\n \u00BB\u00BB\r\n </button>\r\n </div>\r\n\r\n <!-- Selector Items por p\u00E1gina -->\r\n @if (showPageSizeSelector() && totalPages() > 1) {\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\">{{ pageSize() }}</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 @if (showPageSizeMenu()) {\r\n <div class=\"page-size-menu\">\r\n @for (opt of pageSizeOptions(); track $index) {\r\n <div class=\"menu-option\" [class.active]=\"opt === pageSize()\" (click)=\"selectPageSize(opt)\">\r\n {{ opt }}\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n</div>", 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):not(:disabled){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}.page-btn:disabled{background:transparent;cursor:default;box-shadow:none;pointer-events:none}.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"] }]
97
97
  }], propDecorators: { page: [{ type: i0.Input, args: [{ isSignal: true, alias: "page", required: false }] }, { type: i0.Output, args: ["pageChange"] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }, { type: i0.Output, args: ["pageSizeChange"] }], totalItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalItems", required: false }] }], showPageSizeSelector: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPageSizeSelector", required: false }] }], pageSizeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizeOptions", required: false }] }] } });
98
98
 
99
+ class PdfViewerService {
100
+ showModalDocuments = signal(false, ...(ngDevMode ? [{ debugName: "showModalDocuments" }] : []));
101
+ selectedPdf = signal(null, ...(ngDevMode ? [{ debugName: "selectedPdf" }] : []));
102
+ openModal() {
103
+ this.showModalDocuments.set(true);
104
+ }
105
+ closeModal() {
106
+ this.showModalDocuments.set(false);
107
+ }
108
+ setSelectedPdf(pdf) {
109
+ this.selectedPdf.set(pdf);
110
+ }
111
+ /** Abre el visor directamente con el documento indicado */
112
+ open(doc) {
113
+ this.selectedPdf.set(doc);
114
+ this.showModalDocuments.set(true);
115
+ }
116
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: PdfViewerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
117
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: PdfViewerService, providedIn: 'root' });
118
+ }
119
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: PdfViewerService, decorators: [{
120
+ type: Injectable,
121
+ args: [{
122
+ providedIn: 'root',
123
+ }]
124
+ }] });
125
+
99
126
  const STATUS_TONE_STYLES = {
100
127
  success: { bg: '#9ED89D', color: '#006D2F' },
101
128
  error: { bg: '#D89D9D', color: '#CF0707' },
@@ -121,6 +148,7 @@ const currencyFormatter = new Intl.NumberFormat('es-CO', {
121
148
  minimumFractionDigits: 0,
122
149
  });
123
150
  class Table {
151
+ pdfViewerService = inject(PdfViewerService);
124
152
  columns = input([], ...(ngDevMode ? [{ debugName: "columns" }] : []));
125
153
  data = input([], ...(ngDevMode ? [{ debugName: "data" }] : []));
126
154
  actions = input([], ...(ngDevMode ? [{ debugName: "actions" }] : []));
@@ -493,12 +521,35 @@ class Table {
493
521
  event.stopPropagation();
494
522
  this.iconAction.emit({ action: col.iconKey ?? col.key, row });
495
523
  }
524
+ /** Indica si el checkbox marcado tiene un archivo asociado para visualizar */
525
+ hasCheckboxFile(col, row) {
526
+ if (!row[col.key])
527
+ return false;
528
+ if (col.fileUrlKey)
529
+ return !!row[col.fileUrlKey];
530
+ return typeof row[col.key] === 'string' && !!row[col.key];
531
+ }
532
+ onGroupCheckboxClick(col, row, event) {
533
+ event.stopPropagation();
534
+ if (!row[col.key])
535
+ return;
536
+ const raw = col.fileUrlKey
537
+ ? row[col.fileUrlKey]
538
+ : typeof row[col.key] === 'string' ? row[col.key] : null;
539
+ const urls = Array.isArray(raw)
540
+ ? raw.filter(Boolean)
541
+ : raw ? [raw] : [];
542
+ if (!urls.length)
543
+ return;
544
+ const name = col.fileNameKey ? row[col.fileNameKey] : col.label;
545
+ this.pdfViewerService.open({ name, urls });
546
+ }
496
547
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Table, deps: [], target: i0.ɵɵFactoryTarget.Component });
497
- 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 }, statusEnumMap: { classPropertyName: "statusEnumMap", publicName: "statusEnumMap", isSignal: true, isRequired: false, transformFunction: null }, subColumns: { classPropertyName: "subColumns", publicName: "subColumns", isSignal: true, isRequired: false, transformFunction: null }, isRowExpandable: { classPropertyName: "isRowExpandable", publicName: "isRowExpandable", isSignal: true, isRequired: false, transformFunction: null }, expandedChildren: { classPropertyName: "expandedChildren", publicName: "expandedChildren", isSignal: true, isRequired: false, transformFunction: null }, rowIdKey: { classPropertyName: "rowIdKey", publicName: "rowIdKey", isSignal: true, isRequired: false, transformFunction: null }, showSelection: { classPropertyName: "showSelection", publicName: "showSelection", isSignal: true, isRequired: false, transformFunction: null }, showTotals: { classPropertyName: "showTotals", publicName: "showTotals", isSignal: true, isRequired: false, transformFunction: null }, columnGroups: { classPropertyName: "columnGroups", publicName: "columnGroups", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { optionSelected: "optionSelected", iconAction: "iconAction", columnGroupChange: "columnGroupChange" }, host: { listeners: { "document:click": "onClickOutside($event)" } }, viewQueries: [{ propertyName: "chips", predicate: ["statusChip"], descendants: true }], ngImport: i0, template: "<div class=\"table-wrapper\">\n <table class=\"inner-table\">\n <thead>\n <!-- Fila 1 -->\n <tr>\n\n @if (showSelection()) {\n <th class=\"checkbox-header\" [attr.rowspan]=\"hasColumnGroups() ? 2 : null\">\n <label class=\"custom-checkbox\" (click)=\"$event.stopPropagation()\">\n <input type=\"checkbox\" [checked]=\"isAllSelected()\" (change)=\"toggleAllRows($event.target.checked)\" />\n <span class=\"checkmark\"></span>\n </label>\n </th>\n }\n\n @for (col of columns(); track col.key) {\n <th (click)=\"col.sortable !== false && onSort(col)\" [class.sortable]=\"col.sortable !== false\"\n [class]=\"getAlignment(col)\" [attr.rowspan]=\"hasColumnGroups() ? 2 : null\">\n {{ col.label }}\n\n <!-- iconos de orden opcionales -->\n @if (sortColumn() === col.key) {\n <span class=\"sort-icon\">\n {{ sortDirection() === 'asc' ? '\u25B2' : '\u25BC' }}\n </span>\n }\n </th>\n }\n\n <!-- headers de grupo (colspan = n\u00FAmero de sub-columnas) -->\n @for (group of columnGroups(); track group.groupLabel) {\n <th class=\"column-group-header\" [attr.colspan]=\"group.columns.length\">\n {{ group.groupLabel }}\n </th>\n }\n\n <!-- columna para acciones -->\n @if (showActions()) {\n <th class=\"actions-header\" [attr.rowspan]=\"hasColumnGroups() ? 2 : null\">Acciones</th>\n }\n </tr>\n\n <!-- Fila 2: sub-headers de grupo (solo si hay groups) -->\n @if (hasColumnGroups()) {\n <tr>\n @for (group of columnGroups(); track group.groupLabel) {\n @for (subCol of group.columns; track subCol.key) {\n <th class=\"column-group-sub-header\">{{ subCol.label }}</th>\n }\n }\n </tr>\n }\n </thead>\n\n <tbody>\n @for (row of sortedData(); track row['id']) {\n <tr class=\"parent-row\"\n [class.expandable]=\"isRowExpandable()(row)\"\n [class.expanded]=\"isExpanded(row)\"\n [class.selected]=\"isRowSelected(row)\"\n (click)=\"toggleRowExpand(row, $event)\">\n\n @if (showSelection()) {\n <td class=\"checkbox-cell\">\n <label class=\"custom-checkbox\" (click)=\"$event.stopPropagation()\">\n <input type=\"checkbox\" [checked]=\"isRowSelected(row)\" (change)=\"toggleRow(row, $event.target.checked)\" />\n <span class=\"checkmark\"></span>\n </label>\n </td>\n }\n\n @for (col of columns(); track col.key) {\n <td [class]=\"getAlignment(col)\">\n @if (col.type === 'status') { @let style =\n getStatusStyle(row[col.key]);\n <span #statusChip class=\"status-chip\" [style.background-color]=\"style.bg\" [style.color]=\"style.color\">\n {{ getStatusLabel(row[col.key]) }}\n </span>\n\n } @else if (col.type === 'icon-button') {\n\n <button (click)=\"onIconColumnClick(col, row, $event)\">\n <span class=\"icon\" [class]=\"col.icon\"></span>\n </button>\n } @else if (col.type === 'grade') {\n @let style = getGradeStyle(row[col.key]);\n <span class=\"status-chip\" [style.background-color]=\"style.bg\" [style.color]=\"style.color\">\n {{ formatValue(col, row[col.key]) }}\n </span>\n } @else {\n {{ formatValue(col, row[col.key]) }}\n\n }\n </td>\n }\n\n <!-- Celdas de grupo -->\n @for (group of columnGroups(); track group.groupLabel) {\n @for (subCol of group.columns; track subCol.key) {\n <td class=\"column-group-cell\">\n @if (!subCol.type || subCol.type === 'checkbox') {\n <label class=\"custom-checkbox\" (click)=\"$event.stopPropagation()\">\n <input type=\"checkbox\" disabled [checked]=\"row[subCol.key]\" />\n <span class=\"checkmark\"></span>\n </label>\n } @else if (subCol.type === 'number') {\n {{ row[subCol.key] }}\n } @else if (subCol.type === 'percentage') {\n {{ row[subCol.key] }}%\n } @else if (subCol.type === 'icon-button') {\n <button (click)=\"onGroupIconClick(subCol, row, $event)\">\n <span class=\"icon\" [class]=\"subCol.icon\"></span>\n </button>\n }\n </td>\n }\n }\n\n <!-- Celda de acciones -->\n @if (showActions()) {\n <td class=\"acciones-cell\">\n <div class=\"menu-acciones\">\n <button class=\"icon-button\" (click)=\"openModal(row); $event.stopPropagation()\">\n <div class=\"content\">\n <div class=\"state-layer\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"more-vert\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\"\n fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <circle cx=\"12\" cy=\"5\" r=\"1\" />\n <circle cx=\"12\" cy=\"12\" r=\"1\" />\n <circle cx=\"12\" cy=\"19\" r=\"1\" />\n </svg>\n </div>\n </div>\n </button>\n @if(selectedRow()?.['id'] === row['id']){\n <div class=\"modal-options-table\" (click)=\"$event.stopPropagation()\">\n <div class=\"modal-content-table\">\n <ul>\n @for (option of getActionsForRow(row); track $index) {\n <li class=\"option-item-table\" [style.color]=\"getActionColor(option)\"\n (click)=\"onOptionClick(option, row)\">\n <span class=\"icon\" [class]=\"option.icon\"></span>\n <span class=\"label\">{{ option.label }}</span>\n </li>\n }\n </ul>\n </div>\n </div>\n }\n </div>\n </td>\n }\n </tr>\n <!-- Subfilas (solo si es expandible y est\u00E1 expandida) -->\n @if (isRowExpandable()(row) && isExpanded(row)) {\n <tr class=\"child-row child-header-row\">\n <td class=\"child-cell-full\"\n [attr.colspan]=\"totalColspan()\">\n <div class=\"child-grid\">\n @for (subCol of subColumns(); track subCol.key) {\n <div class=\"child-item\">\n <span class=\"child-label\">{{ subCol.label }}</span>\n </div>\n }\n </div>\n </td>\n </tr>\n\n @for (child of getChildRows(row); track child['id']) {\n <tr class=\"child-row\">\n <td class=\"child-cell-full\" [attr.colspan]=\"totalColspan()\">\n <div class=\"child-grid\">\n @for (subCol of subColumns(); track subCol.key) {\n <div class=\"child-item\">\n\n @if (subCol.type === 'status') {\n @let style = getStatusStyle(child[subCol.key]);\n <span class=\"status-chip child-status-chip\" [style.background-color]=\"style.bg\"\n [style.color]=\"style.color\">\n {{ getStatusLabel(child[subCol.key]) }}\n </span>\n } @else {\n <span class=\"child-value\">\n {{ formatValue(subCol, child[subCol.key]) }}\n </span>\n }\n\n </div>\n }\n </div>\n </td>\n </tr>\n }\n }\n }\n @if (showTotals()) {\n <tr class=\"total-row\">\n \n <!-- checkbox -->\n @if (showSelection()) {\n <td class=\"checkbox-cell\"></td>\n }\n \n @for (col of columns(); track col.key) {\n <td [class]=\"getAlignment(col)\">\n \n @if (col.type === 'money' && col.totalizable) {\n {{ formatValue(col, getMoneyTotal(col)) }}\n } @else if (col === columns()[0]) {\n <strong>Total</strong>\n }\n \n </td>\n }\n\n <!-- celdas vac\u00EDas para sub-columnas de grupo -->\n @for (group of columnGroups(); track group.groupLabel) {\n @for (subCol of group.columns; track subCol.key) {\n <td></td>\n }\n }\n \n @if (showActions()) {\n <td></td>\n }\n \n </tr>\n }\n\n <!-- Fila de leyenda (solo si hay columnGroups) -->\n @for (group of columnGroups(); track group.groupLabel) {\n <tr class=\"legend-row\">\n <td class=\"legend-cell\" [attr.colspan]=\"totalColspan()\">\n <span class=\"legend-title\">{{ group.groupLabel | uppercase }}:</span>\n @for (col of group.columns; track col.key; let last = $last) {\n <span class=\"legend-item\">{{ col.label }}:\n {{ col.description }}{{ last ? '' : ' \u00B7 ' }}</span>\n }\n </td>\n </tr>\n }\n \n </tbody>\n </table>\n</div>", 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:center;padding:8px 12px;font-weight:600;color:#3a3a3a;text-transform:uppercase}.inner-table td{padding:8px 12px;color:#4a4a4a;border-top:1px solid #c7c7ad}.inner-table thead .actions-header{text-align:center}.custom-checkbox{position:relative;display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;cursor:pointer}.custom-checkbox input{position:absolute;opacity:0;pointer-events:none}.custom-checkbox .checkmark{width:14px;height:14px;border:1.5px solid #7a7a5a;border-radius:3px;box-sizing:border-box;transition:all .15s ease;background:transparent;position:relative;display:flex;align-items:center;justify-content:center}.custom-checkbox input:checked+.checkmark{background-color:#596300;border-color:#596300}.custom-checkbox input:checked+.checkmark:after{content:\"\";position:absolute;top:50%;left:50%;width:4px;height:8px;border:solid #ffffff;border-width:0 2px 2px 0;transform:translate(-50%,-60%) rotate(45deg)}.custom-checkbox:hover .checkmark{border-color:#596300}.checkbox-header,.checkbox-cell{width:32px;padding:0;text-align:center}.acciones-cell{text-align:center;padding:6px}.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:inline-flex;align-items:center;justify-content:center}.icon-button:hover{background:#0000000f}.more-vert{color:#4a4a4a;display:block}.modal-options-table{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-table{width:100%;border-radius:8px;border:1px solid var(--outline-variant, #c7c7ad);overflow:hidden}.option-item-table{display:flex;align-items:center;height:56px;padding:8px 12px;cursor:pointer}.option-item-table:hover{background-color:#0000001a}.option-item-table:active{background-color:#dee58f}.option-item-table .icon{margin-right:8px}.option-item-table .label{font-weight:500;font-size:16px;text-transform:capitalize}.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>')}.icon-add{-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=\"M12 5l0 14\"/><path d=\"M5 12l14 0\"/></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=\"M12 5l0 14\"/><path d=\"M5 12l14 0\"/></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;justify-content:center;gap:.5rem;padding:.375rem .75rem;border-radius:6px;font-size:1rem;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;box-sizing:border-box;text-transform:uppercase}.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}.inner-table tbody tr.parent-row{transition:background-color .15s ease;cursor:default}.inner-table tbody tr.parent-row:hover{background-color:transparent}.inner-table tbody tr.parent-row.expandable{cursor:pointer}.inner-table tbody tr.parent-row.expandable:hover{background-color:#e3dfcc}.inner-table tbody tr.parent-row.expandable.expanded{background-color:#d2cdb7}.inner-table tbody tr.parent-row.selected{background-color:#cfd8a5}.child-cell-full{padding:16px 24px;border-top:1px dashed #c7c7ad;background-color:#e5e2d1}.child-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px 24px}.child-item{display:flex;flex-direction:column;gap:4px;padding-left:48px}.child-label{font-size:12px;font-weight:600;text-transform:uppercase;color:#596300;text-align:start}.child-value{font-size:14px;color:#444;text-align:start}.total-row{background-color:#d9ddad;border-top:2px solid #596300}.total-row td{font-weight:600;color:#3a3a3a}.total-row td:first-child{border-bottom-left-radius:20px}.total-row td:last-child{border-bottom-right-radius:20px}.column-group-header{text-align:center;padding:4px 8px}.column-group-sub-header{text-align:center;padding:4px 6px;font-size:12px;font-weight:700;white-space:nowrap}.column-group-sub-header:first-child{border-radius:0}.column-group-sub-header:last-child{border-radius:0}.column-group-cell{text-align:center;vertical-align:middle;padding:4px 6px}.legend-row td{border-top:1px solid #c7c7ad}.legend-cell{padding:10px 16px;font-size:12px;color:#5a5a5a;font-style:italic}.legend-title{font-weight:700;font-style:italic;color:#3a3a3a;margin-right:4px}.legend-item{color:#5a5a5a}.legend-row:last-child td{border-bottom-left-radius:20px;border-bottom-right-radius:20px}.inner-table tbody tr.total-row:has(+.legend-row) td:first-child{border-bottom-left-radius:0}.inner-table tbody tr.total-row:has(+.legend-row) td:last-child{border-bottom-right-radius:0}\n"], dependencies: [{ kind: "pipe", type: UpperCasePipe, name: "uppercase" }] });
548
+ 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 }, statusEnumMap: { classPropertyName: "statusEnumMap", publicName: "statusEnumMap", isSignal: true, isRequired: false, transformFunction: null }, subColumns: { classPropertyName: "subColumns", publicName: "subColumns", isSignal: true, isRequired: false, transformFunction: null }, isRowExpandable: { classPropertyName: "isRowExpandable", publicName: "isRowExpandable", isSignal: true, isRequired: false, transformFunction: null }, expandedChildren: { classPropertyName: "expandedChildren", publicName: "expandedChildren", isSignal: true, isRequired: false, transformFunction: null }, rowIdKey: { classPropertyName: "rowIdKey", publicName: "rowIdKey", isSignal: true, isRequired: false, transformFunction: null }, showSelection: { classPropertyName: "showSelection", publicName: "showSelection", isSignal: true, isRequired: false, transformFunction: null }, showTotals: { classPropertyName: "showTotals", publicName: "showTotals", isSignal: true, isRequired: false, transformFunction: null }, columnGroups: { classPropertyName: "columnGroups", publicName: "columnGroups", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { optionSelected: "optionSelected", iconAction: "iconAction", columnGroupChange: "columnGroupChange" }, host: { listeners: { "document:click": "onClickOutside($event)" } }, viewQueries: [{ propertyName: "chips", predicate: ["statusChip"], descendants: true }], ngImport: i0, template: "<div class=\"table-wrapper\">\n <table class=\"inner-table\">\n <thead>\n <!-- Fila 1 -->\n <tr>\n\n @if (showSelection()) {\n <th class=\"checkbox-header\" [attr.rowspan]=\"hasColumnGroups() ? 2 : null\">\n <label class=\"custom-checkbox\" (click)=\"$event.stopPropagation()\">\n <input type=\"checkbox\" [checked]=\"isAllSelected()\" (change)=\"toggleAllRows($event.target.checked)\" />\n <span class=\"checkmark\"></span>\n </label>\n </th>\n }\n\n @for (col of columns(); track col.key) {\n <th (click)=\"col.sortable !== false && onSort(col)\" [class.sortable]=\"col.sortable !== false\"\n [class]=\"getAlignment(col)\" [attr.rowspan]=\"hasColumnGroups() ? 2 : null\">\n {{ col.label }}\n\n <!-- iconos de orden opcionales -->\n @if (sortColumn() === col.key) {\n <span class=\"sort-icon\">\n {{ sortDirection() === 'asc' ? '\u25B2' : '\u25BC' }}\n </span>\n }\n </th>\n }\n\n <!-- headers de grupo (colspan = n\u00FAmero de sub-columnas) -->\n @for (group of columnGroups(); track group.groupLabel) {\n <th class=\"column-group-header\" [attr.colspan]=\"group.columns.length\">\n {{ group.groupLabel }}\n </th>\n }\n\n <!-- columna para acciones -->\n @if (showActions()) {\n <th class=\"actions-header\" [attr.rowspan]=\"hasColumnGroups() ? 2 : null\">Acciones</th>\n }\n </tr>\n\n <!-- Fila 2: sub-headers de grupo (solo si hay groups) -->\n @if (hasColumnGroups()) {\n <tr>\n @for (group of columnGroups(); track group.groupLabel) {\n @for (subCol of group.columns; track subCol.key) {\n <th class=\"column-group-sub-header\">{{ subCol.label }}</th>\n }\n }\n </tr>\n }\n </thead>\n\n <tbody>\n @for (row of sortedData(); track row['id']) {\n <tr class=\"parent-row\"\n [class.expandable]=\"isRowExpandable()(row)\"\n [class.expanded]=\"isExpanded(row)\"\n [class.selected]=\"isRowSelected(row)\"\n (click)=\"toggleRowExpand(row, $event)\">\n\n @if (showSelection()) {\n <td class=\"checkbox-cell\">\n <label class=\"custom-checkbox\" (click)=\"$event.stopPropagation()\">\n <input type=\"checkbox\" [checked]=\"isRowSelected(row)\" (change)=\"toggleRow(row, $event.target.checked)\" />\n <span class=\"checkmark\"></span>\n </label>\n </td>\n }\n\n @for (col of columns(); track col.key) {\n <td [class]=\"getAlignment(col)\">\n @if (col.type === 'status') { @let style =\n getStatusStyle(row[col.key]);\n <span #statusChip class=\"status-chip\" [style.background-color]=\"style.bg\" [style.color]=\"style.color\">\n {{ getStatusLabel(row[col.key]) }}\n </span>\n\n } @else if (col.type === 'icon-button') {\n\n <button (click)=\"onIconColumnClick(col, row, $event)\">\n <span class=\"icon\" [class]=\"col.icon\"></span>\n </button>\n } @else if (col.type === 'grade') {\n @let style = getGradeStyle(row[col.key]);\n <span class=\"status-chip\" [style.background-color]=\"style.bg\" [style.color]=\"style.color\">\n {{ formatValue(col, row[col.key]) }}\n </span>\n } @else {\n {{ formatValue(col, row[col.key]) }}\n\n }\n </td>\n }\n\n <!-- Celdas de grupo -->\n @for (group of columnGroups(); track group.groupLabel) {\n @for (subCol of group.columns; track subCol.key) {\n <td class=\"column-group-cell\">\n @if (!subCol.type || subCol.type === 'checkbox') {\n <label class=\"custom-checkbox\"\n [class.custom-checkbox--file]=\"hasCheckboxFile(subCol, row)\"\n (click)=\"onGroupCheckboxClick(subCol, row, $event)\">\n <input type=\"checkbox\" disabled [checked]=\"row[subCol.key]\" />\n <span class=\"checkmark\"></span>\n </label>\n } @else if (subCol.type === 'number') {\n {{ row[subCol.key] }}\n } @else if (subCol.type === 'percentage') {\n {{ row[subCol.key] }}%\n } @else if (subCol.type === 'icon-button') {\n <button (click)=\"onGroupIconClick(subCol, row, $event)\">\n <span class=\"icon\" [class]=\"subCol.icon\"></span>\n </button>\n }\n </td>\n }\n }\n\n <!-- Celda de acciones -->\n @if (showActions()) {\n <td class=\"acciones-cell\">\n <div class=\"menu-acciones\">\n <button class=\"icon-button\" (click)=\"openModal(row); $event.stopPropagation()\">\n <div class=\"content\">\n <div class=\"state-layer\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"more-vert\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\"\n fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <circle cx=\"12\" cy=\"5\" r=\"1\" />\n <circle cx=\"12\" cy=\"12\" r=\"1\" />\n <circle cx=\"12\" cy=\"19\" r=\"1\" />\n </svg>\n </div>\n </div>\n </button>\n @if(selectedRow()?.['id'] === row['id']){\n <div class=\"modal-options-table\" (click)=\"$event.stopPropagation()\">\n <div class=\"modal-content-table\">\n <ul>\n @for (option of getActionsForRow(row); track $index) {\n <li class=\"option-item-table\" [style.color]=\"getActionColor(option)\"\n (click)=\"onOptionClick(option, row)\">\n <span class=\"icon\" [class]=\"option.icon\"></span>\n <span class=\"label\">{{ option.label }}</span>\n </li>\n }\n </ul>\n </div>\n </div>\n }\n </div>\n </td>\n }\n </tr>\n <!-- Subfilas (solo si es expandible y est\u00E1 expandida) -->\n @if (isRowExpandable()(row) && isExpanded(row)) {\n <tr class=\"child-row child-header-row\">\n <td class=\"child-cell-full\"\n [attr.colspan]=\"totalColspan()\">\n <div class=\"child-grid\">\n @for (subCol of subColumns(); track subCol.key) {\n <div class=\"child-item\">\n <span class=\"child-label\">{{ subCol.label }}</span>\n </div>\n }\n </div>\n </td>\n </tr>\n\n @for (child of getChildRows(row); track child['id']) {\n <tr class=\"child-row\">\n <td class=\"child-cell-full\" [attr.colspan]=\"totalColspan()\">\n <div class=\"child-grid\">\n @for (subCol of subColumns(); track subCol.key) {\n <div class=\"child-item\">\n\n @if (subCol.type === 'status') {\n @let style = getStatusStyle(child[subCol.key]);\n <span class=\"status-chip child-status-chip\" [style.background-color]=\"style.bg\"\n [style.color]=\"style.color\">\n {{ getStatusLabel(child[subCol.key]) }}\n </span>\n } @else {\n <span class=\"child-value\">\n {{ formatValue(subCol, child[subCol.key]) }}\n </span>\n }\n\n </div>\n }\n </div>\n </td>\n </tr>\n }\n }\n }\n @if (showTotals()) {\n <tr class=\"total-row\">\n \n <!-- checkbox -->\n @if (showSelection()) {\n <td class=\"checkbox-cell\"></td>\n }\n \n @for (col of columns(); track col.key) {\n <td [class]=\"getAlignment(col)\">\n \n @if (col.type === 'money' && col.totalizable) {\n {{ formatValue(col, getMoneyTotal(col)) }}\n } @else if (col === columns()[0]) {\n <strong>Total</strong>\n }\n \n </td>\n }\n\n <!-- celdas vac\u00EDas para sub-columnas de grupo -->\n @for (group of columnGroups(); track group.groupLabel) {\n @for (subCol of group.columns; track subCol.key) {\n <td></td>\n }\n }\n \n @if (showActions()) {\n <td></td>\n }\n \n </tr>\n }\n\n <!-- Fila de leyenda (solo si hay columnGroups) -->\n @for (group of columnGroups(); track group.groupLabel) {\n <tr class=\"legend-row\">\n <td class=\"legend-cell\" [attr.colspan]=\"totalColspan()\">\n <span class=\"legend-title\">{{ group.groupLabel | uppercase }}:</span>\n @for (col of group.columns; track col.key; let last = $last) {\n <span class=\"legend-item\">{{ col.label }}:\n {{ col.description }}{{ last ? '' : ' \u00B7 ' }}</span>\n }\n </td>\n </tr>\n }\n \n </tbody>\n </table>\n</div>", 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:center;padding:8px 12px;font-weight:600;color:#3a3a3a;text-transform:uppercase}.inner-table td{padding:8px 12px;color:#4a4a4a;border-top:1px solid #c7c7ad}.inner-table thead .actions-header{text-align:center}.custom-checkbox{position:relative;display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;cursor:pointer}.custom-checkbox input{position:absolute;opacity:0;pointer-events:none}.custom-checkbox .checkmark{width:14px;height:14px;border:1.5px solid #7a7a5a;border-radius:3px;box-sizing:border-box;transition:all .15s ease;background:transparent;position:relative;display:flex;align-items:center;justify-content:center}.custom-checkbox input:checked+.checkmark{background-color:#596300;border-color:#596300}.custom-checkbox input:checked+.checkmark:after{content:\"\";position:absolute;top:50%;left:50%;width:4px;height:8px;border:solid #ffffff;border-width:0 2px 2px 0;transform:translate(-50%,-60%) rotate(45deg)}.custom-checkbox:hover .checkmark{border-color:#596300}.custom-checkbox--file{cursor:pointer}.custom-checkbox--file .checkmark{box-shadow:0 0 0 2px #59630033}.custom-checkbox--file:hover .checkmark{box-shadow:0 0 0 3px #59630059}.checkbox-header,.checkbox-cell{width:32px;padding:0;text-align:center}.acciones-cell{text-align:center;padding:6px}.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:inline-flex;align-items:center;justify-content:center}.icon-button:hover{background:#0000000f}.more-vert{color:#4a4a4a;display:block}.modal-options-table{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-table{width:100%;border-radius:8px;border:1px solid var(--outline-variant, #c7c7ad);overflow:hidden}.option-item-table{display:flex;align-items:center;height:56px;padding:8px 12px;cursor:pointer}.option-item-table:hover{background-color:#0000001a}.option-item-table:active{background-color:#dee58f}.option-item-table .icon{margin-right:8px}.option-item-table .label{font-weight:500;font-size:16px;text-transform:capitalize}.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>')}.icon-add{-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=\"M12 5l0 14\"/><path d=\"M5 12l14 0\"/></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=\"M12 5l0 14\"/><path d=\"M5 12l14 0\"/></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;justify-content:center;gap:.5rem;padding:.375rem .75rem;border-radius:6px;font-size:1rem;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;box-sizing:border-box;text-transform:uppercase}.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}.inner-table tbody tr.parent-row{transition:background-color .15s ease;cursor:default}.inner-table tbody tr.parent-row:hover{background-color:transparent}.inner-table tbody tr.parent-row.expandable{cursor:pointer}.inner-table tbody tr.parent-row.expandable:hover{background-color:#e3dfcc}.inner-table tbody tr.parent-row.expandable.expanded{background-color:#d2cdb7}.inner-table tbody tr.parent-row.selected{background-color:#cfd8a5}.child-cell-full{padding:16px 24px;border-top:1px dashed #c7c7ad;background-color:#e5e2d1}.child-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px 24px}.child-item{display:flex;flex-direction:column;gap:4px;padding-left:48px}.child-label{font-size:12px;font-weight:600;text-transform:uppercase;color:#596300;text-align:start}.child-value{font-size:14px;color:#444;text-align:start}.total-row{background-color:#d9ddad;border-top:2px solid #596300}.total-row td{font-weight:600;color:#3a3a3a}.total-row td:first-child{border-bottom-left-radius:20px}.total-row td:last-child{border-bottom-right-radius:20px}.column-group-header{text-align:center;padding:4px 8px}.column-group-sub-header{text-align:center;padding:4px 6px;font-size:12px;font-weight:700;white-space:nowrap}.column-group-sub-header:first-child{border-radius:0}.column-group-sub-header:last-child{border-radius:0}.column-group-cell{text-align:center;vertical-align:middle;padding:4px 6px}.legend-row td{border-top:1px solid #c7c7ad}.legend-cell{padding:10px 16px;font-size:12px;color:#5a5a5a;font-style:italic}.legend-title{font-weight:700;font-style:italic;color:#3a3a3a;margin-right:4px}.legend-item{color:#5a5a5a}.legend-row:last-child td{border-bottom-left-radius:20px;border-bottom-right-radius:20px}.inner-table tbody tr.total-row:has(+.legend-row) td:first-child{border-bottom-left-radius:0}.inner-table tbody tr.total-row:has(+.legend-row) td:last-child{border-bottom-right-radius:0}\n"], dependencies: [{ kind: "pipe", type: UpperCasePipe, name: "uppercase" }] });
498
549
  }
499
550
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Table, decorators: [{
500
551
  type: Component,
501
- args: [{ selector: 'lib-table', imports: [UpperCasePipe], standalone: true, template: "<div class=\"table-wrapper\">\n <table class=\"inner-table\">\n <thead>\n <!-- Fila 1 -->\n <tr>\n\n @if (showSelection()) {\n <th class=\"checkbox-header\" [attr.rowspan]=\"hasColumnGroups() ? 2 : null\">\n <label class=\"custom-checkbox\" (click)=\"$event.stopPropagation()\">\n <input type=\"checkbox\" [checked]=\"isAllSelected()\" (change)=\"toggleAllRows($event.target.checked)\" />\n <span class=\"checkmark\"></span>\n </label>\n </th>\n }\n\n @for (col of columns(); track col.key) {\n <th (click)=\"col.sortable !== false && onSort(col)\" [class.sortable]=\"col.sortable !== false\"\n [class]=\"getAlignment(col)\" [attr.rowspan]=\"hasColumnGroups() ? 2 : null\">\n {{ col.label }}\n\n <!-- iconos de orden opcionales -->\n @if (sortColumn() === col.key) {\n <span class=\"sort-icon\">\n {{ sortDirection() === 'asc' ? '\u25B2' : '\u25BC' }}\n </span>\n }\n </th>\n }\n\n <!-- headers de grupo (colspan = n\u00FAmero de sub-columnas) -->\n @for (group of columnGroups(); track group.groupLabel) {\n <th class=\"column-group-header\" [attr.colspan]=\"group.columns.length\">\n {{ group.groupLabel }}\n </th>\n }\n\n <!-- columna para acciones -->\n @if (showActions()) {\n <th class=\"actions-header\" [attr.rowspan]=\"hasColumnGroups() ? 2 : null\">Acciones</th>\n }\n </tr>\n\n <!-- Fila 2: sub-headers de grupo (solo si hay groups) -->\n @if (hasColumnGroups()) {\n <tr>\n @for (group of columnGroups(); track group.groupLabel) {\n @for (subCol of group.columns; track subCol.key) {\n <th class=\"column-group-sub-header\">{{ subCol.label }}</th>\n }\n }\n </tr>\n }\n </thead>\n\n <tbody>\n @for (row of sortedData(); track row['id']) {\n <tr class=\"parent-row\"\n [class.expandable]=\"isRowExpandable()(row)\"\n [class.expanded]=\"isExpanded(row)\"\n [class.selected]=\"isRowSelected(row)\"\n (click)=\"toggleRowExpand(row, $event)\">\n\n @if (showSelection()) {\n <td class=\"checkbox-cell\">\n <label class=\"custom-checkbox\" (click)=\"$event.stopPropagation()\">\n <input type=\"checkbox\" [checked]=\"isRowSelected(row)\" (change)=\"toggleRow(row, $event.target.checked)\" />\n <span class=\"checkmark\"></span>\n </label>\n </td>\n }\n\n @for (col of columns(); track col.key) {\n <td [class]=\"getAlignment(col)\">\n @if (col.type === 'status') { @let style =\n getStatusStyle(row[col.key]);\n <span #statusChip class=\"status-chip\" [style.background-color]=\"style.bg\" [style.color]=\"style.color\">\n {{ getStatusLabel(row[col.key]) }}\n </span>\n\n } @else if (col.type === 'icon-button') {\n\n <button (click)=\"onIconColumnClick(col, row, $event)\">\n <span class=\"icon\" [class]=\"col.icon\"></span>\n </button>\n } @else if (col.type === 'grade') {\n @let style = getGradeStyle(row[col.key]);\n <span class=\"status-chip\" [style.background-color]=\"style.bg\" [style.color]=\"style.color\">\n {{ formatValue(col, row[col.key]) }}\n </span>\n } @else {\n {{ formatValue(col, row[col.key]) }}\n\n }\n </td>\n }\n\n <!-- Celdas de grupo -->\n @for (group of columnGroups(); track group.groupLabel) {\n @for (subCol of group.columns; track subCol.key) {\n <td class=\"column-group-cell\">\n @if (!subCol.type || subCol.type === 'checkbox') {\n <label class=\"custom-checkbox\" (click)=\"$event.stopPropagation()\">\n <input type=\"checkbox\" disabled [checked]=\"row[subCol.key]\" />\n <span class=\"checkmark\"></span>\n </label>\n } @else if (subCol.type === 'number') {\n {{ row[subCol.key] }}\n } @else if (subCol.type === 'percentage') {\n {{ row[subCol.key] }}%\n } @else if (subCol.type === 'icon-button') {\n <button (click)=\"onGroupIconClick(subCol, row, $event)\">\n <span class=\"icon\" [class]=\"subCol.icon\"></span>\n </button>\n }\n </td>\n }\n }\n\n <!-- Celda de acciones -->\n @if (showActions()) {\n <td class=\"acciones-cell\">\n <div class=\"menu-acciones\">\n <button class=\"icon-button\" (click)=\"openModal(row); $event.stopPropagation()\">\n <div class=\"content\">\n <div class=\"state-layer\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"more-vert\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\"\n fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <circle cx=\"12\" cy=\"5\" r=\"1\" />\n <circle cx=\"12\" cy=\"12\" r=\"1\" />\n <circle cx=\"12\" cy=\"19\" r=\"1\" />\n </svg>\n </div>\n </div>\n </button>\n @if(selectedRow()?.['id'] === row['id']){\n <div class=\"modal-options-table\" (click)=\"$event.stopPropagation()\">\n <div class=\"modal-content-table\">\n <ul>\n @for (option of getActionsForRow(row); track $index) {\n <li class=\"option-item-table\" [style.color]=\"getActionColor(option)\"\n (click)=\"onOptionClick(option, row)\">\n <span class=\"icon\" [class]=\"option.icon\"></span>\n <span class=\"label\">{{ option.label }}</span>\n </li>\n }\n </ul>\n </div>\n </div>\n }\n </div>\n </td>\n }\n </tr>\n <!-- Subfilas (solo si es expandible y est\u00E1 expandida) -->\n @if (isRowExpandable()(row) && isExpanded(row)) {\n <tr class=\"child-row child-header-row\">\n <td class=\"child-cell-full\"\n [attr.colspan]=\"totalColspan()\">\n <div class=\"child-grid\">\n @for (subCol of subColumns(); track subCol.key) {\n <div class=\"child-item\">\n <span class=\"child-label\">{{ subCol.label }}</span>\n </div>\n }\n </div>\n </td>\n </tr>\n\n @for (child of getChildRows(row); track child['id']) {\n <tr class=\"child-row\">\n <td class=\"child-cell-full\" [attr.colspan]=\"totalColspan()\">\n <div class=\"child-grid\">\n @for (subCol of subColumns(); track subCol.key) {\n <div class=\"child-item\">\n\n @if (subCol.type === 'status') {\n @let style = getStatusStyle(child[subCol.key]);\n <span class=\"status-chip child-status-chip\" [style.background-color]=\"style.bg\"\n [style.color]=\"style.color\">\n {{ getStatusLabel(child[subCol.key]) }}\n </span>\n } @else {\n <span class=\"child-value\">\n {{ formatValue(subCol, child[subCol.key]) }}\n </span>\n }\n\n </div>\n }\n </div>\n </td>\n </tr>\n }\n }\n }\n @if (showTotals()) {\n <tr class=\"total-row\">\n \n <!-- checkbox -->\n @if (showSelection()) {\n <td class=\"checkbox-cell\"></td>\n }\n \n @for (col of columns(); track col.key) {\n <td [class]=\"getAlignment(col)\">\n \n @if (col.type === 'money' && col.totalizable) {\n {{ formatValue(col, getMoneyTotal(col)) }}\n } @else if (col === columns()[0]) {\n <strong>Total</strong>\n }\n \n </td>\n }\n\n <!-- celdas vac\u00EDas para sub-columnas de grupo -->\n @for (group of columnGroups(); track group.groupLabel) {\n @for (subCol of group.columns; track subCol.key) {\n <td></td>\n }\n }\n \n @if (showActions()) {\n <td></td>\n }\n \n </tr>\n }\n\n <!-- Fila de leyenda (solo si hay columnGroups) -->\n @for (group of columnGroups(); track group.groupLabel) {\n <tr class=\"legend-row\">\n <td class=\"legend-cell\" [attr.colspan]=\"totalColspan()\">\n <span class=\"legend-title\">{{ group.groupLabel | uppercase }}:</span>\n @for (col of group.columns; track col.key; let last = $last) {\n <span class=\"legend-item\">{{ col.label }}:\n {{ col.description }}{{ last ? '' : ' \u00B7 ' }}</span>\n }\n </td>\n </tr>\n }\n \n </tbody>\n </table>\n</div>", 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:center;padding:8px 12px;font-weight:600;color:#3a3a3a;text-transform:uppercase}.inner-table td{padding:8px 12px;color:#4a4a4a;border-top:1px solid #c7c7ad}.inner-table thead .actions-header{text-align:center}.custom-checkbox{position:relative;display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;cursor:pointer}.custom-checkbox input{position:absolute;opacity:0;pointer-events:none}.custom-checkbox .checkmark{width:14px;height:14px;border:1.5px solid #7a7a5a;border-radius:3px;box-sizing:border-box;transition:all .15s ease;background:transparent;position:relative;display:flex;align-items:center;justify-content:center}.custom-checkbox input:checked+.checkmark{background-color:#596300;border-color:#596300}.custom-checkbox input:checked+.checkmark:after{content:\"\";position:absolute;top:50%;left:50%;width:4px;height:8px;border:solid #ffffff;border-width:0 2px 2px 0;transform:translate(-50%,-60%) rotate(45deg)}.custom-checkbox:hover .checkmark{border-color:#596300}.checkbox-header,.checkbox-cell{width:32px;padding:0;text-align:center}.acciones-cell{text-align:center;padding:6px}.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:inline-flex;align-items:center;justify-content:center}.icon-button:hover{background:#0000000f}.more-vert{color:#4a4a4a;display:block}.modal-options-table{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-table{width:100%;border-radius:8px;border:1px solid var(--outline-variant, #c7c7ad);overflow:hidden}.option-item-table{display:flex;align-items:center;height:56px;padding:8px 12px;cursor:pointer}.option-item-table:hover{background-color:#0000001a}.option-item-table:active{background-color:#dee58f}.option-item-table .icon{margin-right:8px}.option-item-table .label{font-weight:500;font-size:16px;text-transform:capitalize}.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>')}.icon-add{-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=\"M12 5l0 14\"/><path d=\"M5 12l14 0\"/></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=\"M12 5l0 14\"/><path d=\"M5 12l14 0\"/></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;justify-content:center;gap:.5rem;padding:.375rem .75rem;border-radius:6px;font-size:1rem;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;box-sizing:border-box;text-transform:uppercase}.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}.inner-table tbody tr.parent-row{transition:background-color .15s ease;cursor:default}.inner-table tbody tr.parent-row:hover{background-color:transparent}.inner-table tbody tr.parent-row.expandable{cursor:pointer}.inner-table tbody tr.parent-row.expandable:hover{background-color:#e3dfcc}.inner-table tbody tr.parent-row.expandable.expanded{background-color:#d2cdb7}.inner-table tbody tr.parent-row.selected{background-color:#cfd8a5}.child-cell-full{padding:16px 24px;border-top:1px dashed #c7c7ad;background-color:#e5e2d1}.child-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px 24px}.child-item{display:flex;flex-direction:column;gap:4px;padding-left:48px}.child-label{font-size:12px;font-weight:600;text-transform:uppercase;color:#596300;text-align:start}.child-value{font-size:14px;color:#444;text-align:start}.total-row{background-color:#d9ddad;border-top:2px solid #596300}.total-row td{font-weight:600;color:#3a3a3a}.total-row td:first-child{border-bottom-left-radius:20px}.total-row td:last-child{border-bottom-right-radius:20px}.column-group-header{text-align:center;padding:4px 8px}.column-group-sub-header{text-align:center;padding:4px 6px;font-size:12px;font-weight:700;white-space:nowrap}.column-group-sub-header:first-child{border-radius:0}.column-group-sub-header:last-child{border-radius:0}.column-group-cell{text-align:center;vertical-align:middle;padding:4px 6px}.legend-row td{border-top:1px solid #c7c7ad}.legend-cell{padding:10px 16px;font-size:12px;color:#5a5a5a;font-style:italic}.legend-title{font-weight:700;font-style:italic;color:#3a3a3a;margin-right:4px}.legend-item{color:#5a5a5a}.legend-row:last-child td{border-bottom-left-radius:20px;border-bottom-right-radius:20px}.inner-table tbody tr.total-row:has(+.legend-row) td:first-child{border-bottom-left-radius:0}.inner-table tbody tr.total-row:has(+.legend-row) td:last-child{border-bottom-right-radius:0}\n"] }]
552
+ args: [{ selector: 'lib-table', imports: [UpperCasePipe], standalone: true, template: "<div class=\"table-wrapper\">\n <table class=\"inner-table\">\n <thead>\n <!-- Fila 1 -->\n <tr>\n\n @if (showSelection()) {\n <th class=\"checkbox-header\" [attr.rowspan]=\"hasColumnGroups() ? 2 : null\">\n <label class=\"custom-checkbox\" (click)=\"$event.stopPropagation()\">\n <input type=\"checkbox\" [checked]=\"isAllSelected()\" (change)=\"toggleAllRows($event.target.checked)\" />\n <span class=\"checkmark\"></span>\n </label>\n </th>\n }\n\n @for (col of columns(); track col.key) {\n <th (click)=\"col.sortable !== false && onSort(col)\" [class.sortable]=\"col.sortable !== false\"\n [class]=\"getAlignment(col)\" [attr.rowspan]=\"hasColumnGroups() ? 2 : null\">\n {{ col.label }}\n\n <!-- iconos de orden opcionales -->\n @if (sortColumn() === col.key) {\n <span class=\"sort-icon\">\n {{ sortDirection() === 'asc' ? '\u25B2' : '\u25BC' }}\n </span>\n }\n </th>\n }\n\n <!-- headers de grupo (colspan = n\u00FAmero de sub-columnas) -->\n @for (group of columnGroups(); track group.groupLabel) {\n <th class=\"column-group-header\" [attr.colspan]=\"group.columns.length\">\n {{ group.groupLabel }}\n </th>\n }\n\n <!-- columna para acciones -->\n @if (showActions()) {\n <th class=\"actions-header\" [attr.rowspan]=\"hasColumnGroups() ? 2 : null\">Acciones</th>\n }\n </tr>\n\n <!-- Fila 2: sub-headers de grupo (solo si hay groups) -->\n @if (hasColumnGroups()) {\n <tr>\n @for (group of columnGroups(); track group.groupLabel) {\n @for (subCol of group.columns; track subCol.key) {\n <th class=\"column-group-sub-header\">{{ subCol.label }}</th>\n }\n }\n </tr>\n }\n </thead>\n\n <tbody>\n @for (row of sortedData(); track row['id']) {\n <tr class=\"parent-row\"\n [class.expandable]=\"isRowExpandable()(row)\"\n [class.expanded]=\"isExpanded(row)\"\n [class.selected]=\"isRowSelected(row)\"\n (click)=\"toggleRowExpand(row, $event)\">\n\n @if (showSelection()) {\n <td class=\"checkbox-cell\">\n <label class=\"custom-checkbox\" (click)=\"$event.stopPropagation()\">\n <input type=\"checkbox\" [checked]=\"isRowSelected(row)\" (change)=\"toggleRow(row, $event.target.checked)\" />\n <span class=\"checkmark\"></span>\n </label>\n </td>\n }\n\n @for (col of columns(); track col.key) {\n <td [class]=\"getAlignment(col)\">\n @if (col.type === 'status') { @let style =\n getStatusStyle(row[col.key]);\n <span #statusChip class=\"status-chip\" [style.background-color]=\"style.bg\" [style.color]=\"style.color\">\n {{ getStatusLabel(row[col.key]) }}\n </span>\n\n } @else if (col.type === 'icon-button') {\n\n <button (click)=\"onIconColumnClick(col, row, $event)\">\n <span class=\"icon\" [class]=\"col.icon\"></span>\n </button>\n } @else if (col.type === 'grade') {\n @let style = getGradeStyle(row[col.key]);\n <span class=\"status-chip\" [style.background-color]=\"style.bg\" [style.color]=\"style.color\">\n {{ formatValue(col, row[col.key]) }}\n </span>\n } @else {\n {{ formatValue(col, row[col.key]) }}\n\n }\n </td>\n }\n\n <!-- Celdas de grupo -->\n @for (group of columnGroups(); track group.groupLabel) {\n @for (subCol of group.columns; track subCol.key) {\n <td class=\"column-group-cell\">\n @if (!subCol.type || subCol.type === 'checkbox') {\n <label class=\"custom-checkbox\"\n [class.custom-checkbox--file]=\"hasCheckboxFile(subCol, row)\"\n (click)=\"onGroupCheckboxClick(subCol, row, $event)\">\n <input type=\"checkbox\" disabled [checked]=\"row[subCol.key]\" />\n <span class=\"checkmark\"></span>\n </label>\n } @else if (subCol.type === 'number') {\n {{ row[subCol.key] }}\n } @else if (subCol.type === 'percentage') {\n {{ row[subCol.key] }}%\n } @else if (subCol.type === 'icon-button') {\n <button (click)=\"onGroupIconClick(subCol, row, $event)\">\n <span class=\"icon\" [class]=\"subCol.icon\"></span>\n </button>\n }\n </td>\n }\n }\n\n <!-- Celda de acciones -->\n @if (showActions()) {\n <td class=\"acciones-cell\">\n <div class=\"menu-acciones\">\n <button class=\"icon-button\" (click)=\"openModal(row); $event.stopPropagation()\">\n <div class=\"content\">\n <div class=\"state-layer\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"more-vert\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\"\n fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <circle cx=\"12\" cy=\"5\" r=\"1\" />\n <circle cx=\"12\" cy=\"12\" r=\"1\" />\n <circle cx=\"12\" cy=\"19\" r=\"1\" />\n </svg>\n </div>\n </div>\n </button>\n @if(selectedRow()?.['id'] === row['id']){\n <div class=\"modal-options-table\" (click)=\"$event.stopPropagation()\">\n <div class=\"modal-content-table\">\n <ul>\n @for (option of getActionsForRow(row); track $index) {\n <li class=\"option-item-table\" [style.color]=\"getActionColor(option)\"\n (click)=\"onOptionClick(option, row)\">\n <span class=\"icon\" [class]=\"option.icon\"></span>\n <span class=\"label\">{{ option.label }}</span>\n </li>\n }\n </ul>\n </div>\n </div>\n }\n </div>\n </td>\n }\n </tr>\n <!-- Subfilas (solo si es expandible y est\u00E1 expandida) -->\n @if (isRowExpandable()(row) && isExpanded(row)) {\n <tr class=\"child-row child-header-row\">\n <td class=\"child-cell-full\"\n [attr.colspan]=\"totalColspan()\">\n <div class=\"child-grid\">\n @for (subCol of subColumns(); track subCol.key) {\n <div class=\"child-item\">\n <span class=\"child-label\">{{ subCol.label }}</span>\n </div>\n }\n </div>\n </td>\n </tr>\n\n @for (child of getChildRows(row); track child['id']) {\n <tr class=\"child-row\">\n <td class=\"child-cell-full\" [attr.colspan]=\"totalColspan()\">\n <div class=\"child-grid\">\n @for (subCol of subColumns(); track subCol.key) {\n <div class=\"child-item\">\n\n @if (subCol.type === 'status') {\n @let style = getStatusStyle(child[subCol.key]);\n <span class=\"status-chip child-status-chip\" [style.background-color]=\"style.bg\"\n [style.color]=\"style.color\">\n {{ getStatusLabel(child[subCol.key]) }}\n </span>\n } @else {\n <span class=\"child-value\">\n {{ formatValue(subCol, child[subCol.key]) }}\n </span>\n }\n\n </div>\n }\n </div>\n </td>\n </tr>\n }\n }\n }\n @if (showTotals()) {\n <tr class=\"total-row\">\n \n <!-- checkbox -->\n @if (showSelection()) {\n <td class=\"checkbox-cell\"></td>\n }\n \n @for (col of columns(); track col.key) {\n <td [class]=\"getAlignment(col)\">\n \n @if (col.type === 'money' && col.totalizable) {\n {{ formatValue(col, getMoneyTotal(col)) }}\n } @else if (col === columns()[0]) {\n <strong>Total</strong>\n }\n \n </td>\n }\n\n <!-- celdas vac\u00EDas para sub-columnas de grupo -->\n @for (group of columnGroups(); track group.groupLabel) {\n @for (subCol of group.columns; track subCol.key) {\n <td></td>\n }\n }\n \n @if (showActions()) {\n <td></td>\n }\n \n </tr>\n }\n\n <!-- Fila de leyenda (solo si hay columnGroups) -->\n @for (group of columnGroups(); track group.groupLabel) {\n <tr class=\"legend-row\">\n <td class=\"legend-cell\" [attr.colspan]=\"totalColspan()\">\n <span class=\"legend-title\">{{ group.groupLabel | uppercase }}:</span>\n @for (col of group.columns; track col.key; let last = $last) {\n <span class=\"legend-item\">{{ col.label }}:\n {{ col.description }}{{ last ? '' : ' \u00B7 ' }}</span>\n }\n </td>\n </tr>\n }\n \n </tbody>\n </table>\n</div>", 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:center;padding:8px 12px;font-weight:600;color:#3a3a3a;text-transform:uppercase}.inner-table td{padding:8px 12px;color:#4a4a4a;border-top:1px solid #c7c7ad}.inner-table thead .actions-header{text-align:center}.custom-checkbox{position:relative;display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;cursor:pointer}.custom-checkbox input{position:absolute;opacity:0;pointer-events:none}.custom-checkbox .checkmark{width:14px;height:14px;border:1.5px solid #7a7a5a;border-radius:3px;box-sizing:border-box;transition:all .15s ease;background:transparent;position:relative;display:flex;align-items:center;justify-content:center}.custom-checkbox input:checked+.checkmark{background-color:#596300;border-color:#596300}.custom-checkbox input:checked+.checkmark:after{content:\"\";position:absolute;top:50%;left:50%;width:4px;height:8px;border:solid #ffffff;border-width:0 2px 2px 0;transform:translate(-50%,-60%) rotate(45deg)}.custom-checkbox:hover .checkmark{border-color:#596300}.custom-checkbox--file{cursor:pointer}.custom-checkbox--file .checkmark{box-shadow:0 0 0 2px #59630033}.custom-checkbox--file:hover .checkmark{box-shadow:0 0 0 3px #59630059}.checkbox-header,.checkbox-cell{width:32px;padding:0;text-align:center}.acciones-cell{text-align:center;padding:6px}.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:inline-flex;align-items:center;justify-content:center}.icon-button:hover{background:#0000000f}.more-vert{color:#4a4a4a;display:block}.modal-options-table{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-table{width:100%;border-radius:8px;border:1px solid var(--outline-variant, #c7c7ad);overflow:hidden}.option-item-table{display:flex;align-items:center;height:56px;padding:8px 12px;cursor:pointer}.option-item-table:hover{background-color:#0000001a}.option-item-table:active{background-color:#dee58f}.option-item-table .icon{margin-right:8px}.option-item-table .label{font-weight:500;font-size:16px;text-transform:capitalize}.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>')}.icon-add{-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=\"M12 5l0 14\"/><path d=\"M5 12l14 0\"/></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=\"M12 5l0 14\"/><path d=\"M5 12l14 0\"/></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;justify-content:center;gap:.5rem;padding:.375rem .75rem;border-radius:6px;font-size:1rem;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;box-sizing:border-box;text-transform:uppercase}.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}.inner-table tbody tr.parent-row{transition:background-color .15s ease;cursor:default}.inner-table tbody tr.parent-row:hover{background-color:transparent}.inner-table tbody tr.parent-row.expandable{cursor:pointer}.inner-table tbody tr.parent-row.expandable:hover{background-color:#e3dfcc}.inner-table tbody tr.parent-row.expandable.expanded{background-color:#d2cdb7}.inner-table tbody tr.parent-row.selected{background-color:#cfd8a5}.child-cell-full{padding:16px 24px;border-top:1px dashed #c7c7ad;background-color:#e5e2d1}.child-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px 24px}.child-item{display:flex;flex-direction:column;gap:4px;padding-left:48px}.child-label{font-size:12px;font-weight:600;text-transform:uppercase;color:#596300;text-align:start}.child-value{font-size:14px;color:#444;text-align:start}.total-row{background-color:#d9ddad;border-top:2px solid #596300}.total-row td{font-weight:600;color:#3a3a3a}.total-row td:first-child{border-bottom-left-radius:20px}.total-row td:last-child{border-bottom-right-radius:20px}.column-group-header{text-align:center;padding:4px 8px}.column-group-sub-header{text-align:center;padding:4px 6px;font-size:12px;font-weight:700;white-space:nowrap}.column-group-sub-header:first-child{border-radius:0}.column-group-sub-header:last-child{border-radius:0}.column-group-cell{text-align:center;vertical-align:middle;padding:4px 6px}.legend-row td{border-top:1px solid #c7c7ad}.legend-cell{padding:10px 16px;font-size:12px;color:#5a5a5a;font-style:italic}.legend-title{font-weight:700;font-style:italic;color:#3a3a3a;margin-right:4px}.legend-item{color:#5a5a5a}.legend-row:last-child td{border-bottom-left-radius:20px;border-bottom-right-radius:20px}.inner-table tbody tr.total-row:has(+.legend-row) td:first-child{border-bottom-left-radius:0}.inner-table tbody tr.total-row:has(+.legend-row) td:last-child{border-bottom-right-radius:0}\n"] }]
502
553
  }], 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 }] }], statusEnumMap: [{ type: i0.Input, args: [{ isSignal: true, alias: "statusEnumMap", required: false }] }], subColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "subColumns", required: false }] }], isRowExpandable: [{ type: i0.Input, args: [{ isSignal: true, alias: "isRowExpandable", required: false }] }], expandedChildren: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandedChildren", required: false }] }], rowIdKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowIdKey", required: false }] }], showSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSelection", required: false }] }], showTotals: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTotals", required: false }] }], columnGroups: [{ type: i0.Input, args: [{ isSignal: true, alias: "columnGroups", required: false }] }], columnGroupChange: [{ type: i0.Output, args: ["columnGroupChange"] }], chips: [{
503
554
  type: ViewChildren,
504
555
  args: ['statusChip']
@@ -516,6 +567,7 @@ class DateTimePicker {
516
567
  maxDate = input(null, ...(ngDevMode ? [{ debugName: "maxDate" }] : []));
517
568
  dateChange = output();
518
569
  isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
570
+ openUpward = signal(false, ...(ngDevMode ? [{ debugName: "openUpward" }] : []));
519
571
  selectedDate = signal(null, ...(ngDevMode ? [{ debugName: "selectedDate" }] : []));
520
572
  isDisabled = signal(false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : []));
521
573
  isTouched = signal(false, ...(ngDevMode ? [{ debugName: "isTouched" }] : []));
@@ -646,6 +698,9 @@ class DateTimePicker {
646
698
  if (this.isBlocked())
647
699
  return;
648
700
  this.markAsTouched();
701
+ const rect = this.elementRef.nativeElement.getBoundingClientRect();
702
+ const spaceBelow = window.innerHeight - rect.bottom;
703
+ this.openUpward.set(spaceBelow < 420);
649
704
  this.isOpen.set(true);
650
705
  this.addDocumentListener();
651
706
  // Si hay fecha seleccionada, navegar a ese mes/año
@@ -1008,7 +1063,7 @@ class DateTimePicker {
1008
1063
  useExisting: forwardRef(() => DateTimePicker),
1009
1064
  multi: true,
1010
1065
  },
1011
- ], 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 (click)=\"onInputClick($event)\"\r\n (focus)=\"!isBlocked() && onInputFocus()\"\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;text-transform:capitalize}.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:100000;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}}.datetime-input:-webkit-autofill,.datetime-input:-webkit-autofill:hover,.datetime-input:-webkit-autofill:focus{-webkit-box-shadow:0 0 0 1000px var(--sl-form-surface, #E3E3D1) inset;-webkit-text-fill-color:#454733;transition:background-color 5000s ease-in-out 0s}.datetime-input:-moz-autofill{box-shadow:0 0 0 1000px var(--sl-form-surface, #E3E3D1) inset}.datetime-input[readonly]:-webkit-autofill,.datetime-input:disabled:-webkit-autofill{-webkit-box-shadow:0 0 0 1000px var(--sl-form-surface, #E3E3D1) inset;-webkit-text-fill-color:#a9a97f}\n"] });
1066
+ ], 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 (click)=\"onInputClick($event)\"\r\n (focus)=\"!isBlocked() && onInputFocus()\"\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\" [class.dropdown--upward]=\"openUpward()\">\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;text-transform:capitalize}.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:100000;box-shadow:0 4px 12px #00000026;min-width:400px}.dropdown--upward{top:auto;bottom:100%;border-top:1px solid #787861;border-bottom:none;border-radius:5px 5px 0 0;box-shadow:0 -4px 12px #00000026}.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}}.datetime-input:-webkit-autofill,.datetime-input:-webkit-autofill:hover,.datetime-input:-webkit-autofill:focus{-webkit-box-shadow:0 0 0 1000px var(--sl-form-surface, #E3E3D1) inset;-webkit-text-fill-color:#454733;transition:background-color 5000s ease-in-out 0s}.datetime-input:-moz-autofill{box-shadow:0 0 0 1000px var(--sl-form-surface, #E3E3D1) inset}.datetime-input[readonly]:-webkit-autofill,.datetime-input:disabled:-webkit-autofill{-webkit-box-shadow:0 0 0 1000px var(--sl-form-surface, #E3E3D1) inset;-webkit-text-fill-color:#a9a97f}\n"] });
1012
1067
  }
1013
1068
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DateTimePicker, decorators: [{
1014
1069
  type: Component,
@@ -1018,7 +1073,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
1018
1073
  useExisting: forwardRef(() => DateTimePicker),
1019
1074
  multi: true,
1020
1075
  },
1021
- ], 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 (click)=\"onInputClick($event)\"\r\n (focus)=\"!isBlocked() && onInputFocus()\"\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;text-transform:capitalize}.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:100000;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}}.datetime-input:-webkit-autofill,.datetime-input:-webkit-autofill:hover,.datetime-input:-webkit-autofill:focus{-webkit-box-shadow:0 0 0 1000px var(--sl-form-surface, #E3E3D1) inset;-webkit-text-fill-color:#454733;transition:background-color 5000s ease-in-out 0s}.datetime-input:-moz-autofill{box-shadow:0 0 0 1000px var(--sl-form-surface, #E3E3D1) inset}.datetime-input[readonly]:-webkit-autofill,.datetime-input:disabled:-webkit-autofill{-webkit-box-shadow:0 0 0 1000px var(--sl-form-surface, #E3E3D1) inset;-webkit-text-fill-color:#a9a97f}\n"] }]
1076
+ ], 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 (click)=\"onInputClick($event)\"\r\n (focus)=\"!isBlocked() && onInputFocus()\"\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\" [class.dropdown--upward]=\"openUpward()\">\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;text-transform:capitalize}.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:100000;box-shadow:0 4px 12px #00000026;min-width:400px}.dropdown--upward{top:auto;bottom:100%;border-top:1px solid #787861;border-bottom:none;border-radius:5px 5px 0 0;box-shadow:0 -4px 12px #00000026}.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}}.datetime-input:-webkit-autofill,.datetime-input:-webkit-autofill:hover,.datetime-input:-webkit-autofill:focus{-webkit-box-shadow:0 0 0 1000px var(--sl-form-surface, #E3E3D1) inset;-webkit-text-fill-color:#454733;transition:background-color 5000s ease-in-out 0s}.datetime-input:-moz-autofill{box-shadow:0 0 0 1000px var(--sl-form-surface, #E3E3D1) inset}.datetime-input[readonly]:-webkit-autofill,.datetime-input:disabled:-webkit-autofill{-webkit-box-shadow:0 0 0 1000px var(--sl-form-surface, #E3E3D1) inset;-webkit-text-fill-color:#a9a97f}\n"] }]
1022
1077
  }], 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 }] }] } });
1023
1078
 
1024
1079
  class DateTimeFilter {
@@ -2285,6 +2340,7 @@ class SelectCustomSearch {
2285
2340
  placeholder = input('Seleccionar opción', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
2286
2341
  selectionChange = output();
2287
2342
  isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
2343
+ openUpward = signal(false, ...(ngDevMode ? [{ debugName: "openUpward" }] : []));
2288
2344
  searchTerm = signal('', ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
2289
2345
  selectedValue = signal(null, ...(ngDevMode ? [{ debugName: "selectedValue" }] : []));
2290
2346
  isDisabled = signal(false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : []));
@@ -2332,6 +2388,9 @@ class SelectCustomSearch {
2332
2388
  open() {
2333
2389
  if (this.isBlocked())
2334
2390
  return;
2391
+ const rect = this.elementRef.nativeElement.getBoundingClientRect();
2392
+ const spaceBelow = window.innerHeight - rect.bottom;
2393
+ this.openUpward.set(spaceBelow < 260);
2335
2394
  this.isOpen.set(true);
2336
2395
  this.searchTerm.set('');
2337
2396
  setTimeout(() => {
@@ -2393,7 +2452,7 @@ class SelectCustomSearch {
2393
2452
  useExisting: forwardRef(() => SelectCustomSearch),
2394
2453
  multi: true,
2395
2454
  },
2396
- ], 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 <div\r\n class=\"option default-option\"\r\n [class.selected]=\"selectedValue() === null\"\r\n (click)=\"!isBlocked() && clearSelection()\"\r\n >\r\n {{ placeholder() }}\r\n </div>\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;text-transform:capitalize}.selected-text.placeholder{color:#787861;text-transform:capitalize}.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:100000;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;text-transform:capitalize}.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;text-transform:capitalize}.option:hover{background-color:#a9a97f1a;color:#454733}.option.selected{background-color:#a9a97f;color:#e3e3d1;font-weight:500}.option.default-option{color:#787861;font-style:italic;border-bottom:1px solid rgba(120,120,97,.35)}.option.default-option.selected{background-color:transparent;color:#787861;font-weight:400}.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"] });
2455
+ ], 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\" [class.dropdown--upward]=\"openUpward()\">\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 <div\r\n class=\"option default-option\"\r\n [class.selected]=\"selectedValue() === null\"\r\n (click)=\"!isBlocked() && clearSelection()\"\r\n >\r\n {{ placeholder() }}\r\n </div>\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;text-transform:capitalize}.selected-text.placeholder{color:#787861;text-transform:capitalize}.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:100000;box-shadow:0 2px 8px #0000001a}.dropdown--upward{top:auto;bottom:100%;border-top:1px solid #787861;border-bottom:none;border-radius:5px 5px 0 0;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;text-transform:capitalize}.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;text-transform:capitalize}.option:hover{background-color:#a9a97f1a;color:#454733}.option.selected{background-color:#a9a97f;color:#e3e3d1;font-weight:500}.option.default-option{color:#787861;font-style:italic;border-bottom:1px solid rgba(120,120,97,.35)}.option.default-option.selected{background-color:transparent;color:#787861;font-weight:400}.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"] });
2397
2456
  }
2398
2457
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: SelectCustomSearch, decorators: [{
2399
2458
  type: Component,
@@ -2403,7 +2462,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
2403
2462
  useExisting: forwardRef(() => SelectCustomSearch),
2404
2463
  multi: true,
2405
2464
  },
2406
- ], 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 <div\r\n class=\"option default-option\"\r\n [class.selected]=\"selectedValue() === null\"\r\n (click)=\"!isBlocked() && clearSelection()\"\r\n >\r\n {{ placeholder() }}\r\n </div>\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;text-transform:capitalize}.selected-text.placeholder{color:#787861;text-transform:capitalize}.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:100000;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;text-transform:capitalize}.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;text-transform:capitalize}.option:hover{background-color:#a9a97f1a;color:#454733}.option.selected{background-color:#a9a97f;color:#e3e3d1;font-weight:500}.option.default-option{color:#787861;font-style:italic;border-bottom:1px solid rgba(120,120,97,.35)}.option.default-option.selected{background-color:transparent;color:#787861;font-weight:400}.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"] }]
2465
+ ], 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\" [class.dropdown--upward]=\"openUpward()\">\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 <div\r\n class=\"option default-option\"\r\n [class.selected]=\"selectedValue() === null\"\r\n (click)=\"!isBlocked() && clearSelection()\"\r\n >\r\n {{ placeholder() }}\r\n </div>\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;text-transform:capitalize}.selected-text.placeholder{color:#787861;text-transform:capitalize}.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:100000;box-shadow:0 2px 8px #0000001a}.dropdown--upward{top:auto;bottom:100%;border-top:1px solid #787861;border-bottom:none;border-radius:5px 5px 0 0;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;text-transform:capitalize}.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;text-transform:capitalize}.option:hover{background-color:#a9a97f1a;color:#454733}.option.selected{background-color:#a9a97f;color:#e3e3d1;font-weight:500}.option.default-option{color:#787861;font-style:italic;border-bottom:1px solid rgba(120,120,97,.35)}.option.default-option.selected{background-color:transparent;color:#787861;font-weight:400}.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"] }]
2407
2466
  }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], onDocumentClick: [{
2408
2467
  type: HostListener,
2409
2468
  args: ['document:click', ['$event']]
@@ -2854,11 +2913,11 @@ class ModalForm {
2854
2913
  this.evidenceChange.emit(file);
2855
2914
  }
2856
2915
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ModalForm, deps: [], target: i0.ɵɵFactoryTarget.Component });
2857
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: ModalForm, isStandalone: true, selector: "lib-modal-form", inputs: { isFull: { classPropertyName: "isFull", publicName: "isFull", isSignal: true, isRequired: false, transformFunction: null }, scrollBody: { classPropertyName: "scrollBody", publicName: "scrollBody", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", 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 }, showActionsLeft: { classPropertyName: "showActionsLeft", publicName: "showActionsLeft", isSignal: true, isRequired: false, transformFunction: null }, evidenceLabel: { classPropertyName: "evidenceLabel", publicName: "evidenceLabel", isSignal: true, isRequired: false, transformFunction: null }, evidenceHelperText: { classPropertyName: "evidenceHelperText", publicName: "evidenceHelperText", isSignal: true, isRequired: false, transformFunction: null }, evidenceAccept: { classPropertyName: "evidenceAccept", publicName: "evidenceAccept", isSignal: true, isRequired: false, transformFunction: null }, maxSizeMB: { classPropertyName: "maxSizeMB", publicName: "maxSizeMB", isSignal: true, isRequired: false, transformFunction: null }, hiddenFooterActions: { classPropertyName: "hiddenFooterActions", publicName: "hiddenFooterActions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSubmit: "onSubmit", onCancel: "onCancel", evidenceChange: "evidenceChange" }, ngImport: i0, template: "<div class=\"modal-form-container\" [class.expanded]=\"isFull()\">\r\n <div class=\"header-content\">\r\n <div class=\"header-top\">\r\n <div class=\"header-text\">\r\n <h1>{{ title() }}</h1>\r\n @if(subtitle()){\r\n <p>{{ subtitle() }}</p>\r\n }\r\n </div>\r\n \r\n <button class=\"close-btn\" type=\"button\" (click)=\"onCancel.emit()\">\r\n \u2715\r\n </button>\r\n </div>\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 class=\"step\" [class.step-active]=\"currentStep() === $index + 1\"\r\n [class.step-completed]=\"currentStep() > $index + 1\">\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) { <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\" [class.scrollable]=\"scrollBody()\">\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 [form]=\"form()\" [currentStep]=\"currentStep()\" [steps]=\"steps()\"\r\n (canContinue)=\"canContinue.set($event)\"></lib-wizard-form>\r\n }\r\n </div>\r\n\r\n @if (!hiddenFooterActions()) {\r\n <div class=\"actions\">\r\n @if (showActionsLeft()){\r\n <div class=\"actions-left\">\r\n <p class=\"file-type\">{{ evidenceHelperText() }}</p>\r\n <lib-button variant=\"outline\" type=\"button\" (clicked)=\"fileInput.click()\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\"\r\n class=\"upload-icon icon icon-tabler icons-tabler-outline icon-tabler-cloud-upload\" width=\"24\" height=\"24\"\r\n viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\">\r\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\" />\r\n <path d=\"M7 18a4.6 4.4 0 0 1 0 -9a5 4.5 0 0 1 11 2h1a3.5 3.5 0 0 1 0 7h-1\" />\r\n <path d=\"M9 15l3 -3l3 3\" />\r\n <path d=\"M12 12l0 9\" />\r\n </svg>\r\n <span class=\"label-button\">\r\n {{ evidenceFileName() || evidenceLabel() }}\r\n </span>\r\n </lib-button>\r\n <input #fileInput type=\"file\" hidden [accept]=\"evidenceAccept()\" (change)=\"onFileSelected($event)\" />\r\n </div>\r\n }\r\n\r\n <div class=\"actions-right\">\r\n @if (!steps() || steps().length <= 1) { \r\n <lib-button variant=\"secondary\" type=\"button\" (clicked)=\"onCancel.emit()\">\r\n Cancelar\r\n </lib-button>\r\n } @else if (currentStep() === 1) {\r\n <lib-button variant=\"secondary\" type=\"button\" (clicked)=\"onCancel.emit()\">\r\n Cancelar\r\n </lib-button>\r\n } @else {\r\n <lib-button variant=\"secondary\" type=\"button\" (clicked)=\"prevStep()\">\r\n Volver\r\n </lib-button>\r\n }\r\n\r\n <lib-button\r\n variant=\"primary\"\r\n type=\"button\"\r\n [disabled]=\"!canContinue()\"\r\n (clicked)=\"!steps() || !steps().length ? submitForm() : (currentStep() === steps().length ? submitForm() : nextStep())\"\r\n >\r\n {{ !steps() || !steps().length ? submitLabel() : currentStep() ===\r\n steps().length ? submitLabel() : 'Continuar' }}\r\n </lib-button>\r\n </div>\r\n </div>\r\n }\r\n</div>", styles: [":host{position:fixed;inset:0;background:#0006;backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);display:flex;justify-content:center;align-items:center;z-index:9999;padding:12px;box-sizing:border-box;overflow-y:auto}.modal-form-container{background-color:#ebe8d6;--sl-form-surface: #ebe8d6;width:100%;max-width:1200px;max-height:90dvh;display:flex;flex-direction:column;align-items:stretch;padding:24px 48px;border-radius:24px;box-shadow:0 10px 25px #00000026}.header-content{display:flex;flex-direction:column;gap:6px;padding:16px 0;position:sticky;top:0;z-index:10}.header-top{display:flex;justify-content:space-between;align-items:center}.header-text{display:flex;flex-direction:column;gap:6px}.close-btn{background:transparent;border:none;font-size:2rem;font-weight:500;cursor:pointer;color:#596300;padding:4px 10px;border-radius:50%;transition:background-color .2s ease,transform .2s ease}.close-btn:hover{background-color:#00000010;transform:scale(1.1)}.header-content h1{font-size:2.4rem;font-weight:700;color:#1c1c12}.header-content p{font-size:1.4rem;font-weight:300;color:#454733}.divider{width:calc(100% + 100px);margin-left:-52px;height:1px;background-color:#7878612c;margin-top:16px}.body-content{flex:1 1 auto;min-height:0}.body-content.scrollable{overflow-y:auto}.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}.actions{display:flex;justify-content:space-between;align-items:end;width:100%;margin-top:8px;padding:8px 0;position:sticky;bottom:0;z-index:10}.actions-left{display:flex;flex-direction:column;gap:4px}.actions-right{display:flex;gap:10px;margin-left:auto}.upload-icon{width:28px;height:28px;color:#6a750a;cursor:pointer;transition:transform .2s ease,color .2s ease}.label-button{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;flex:1}.file-type{margin-left:8px;font-size:11px;color:#8a8a8a}.modal-form-container.expanded{position:relative;width:100%;max-width:100dvw;height:100%;max-height:100dvh;background-color:#ebe8d6;--sl-form-surface: #ebe8d6;display:flex;flex-direction:column;align-items:stretch;padding:18px 0 14px;border-radius:24px}.modal-form-container.expanded .header-content,.modal-form-container.expanded .actions{padding:8px 24px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: WizardForm, selector: "lib-wizard-form", inputs: ["form", "currentStep", "steps"], outputs: ["canContinue"] }, { kind: "component", type: Button, selector: "lib-button", inputs: ["variant", "type", "disabled", "fullWidth", "size"], outputs: ["clicked"] }] });
2916
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: ModalForm, isStandalone: true, selector: "lib-modal-form", inputs: { isFull: { classPropertyName: "isFull", publicName: "isFull", isSignal: true, isRequired: false, transformFunction: null }, scrollBody: { classPropertyName: "scrollBody", publicName: "scrollBody", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", 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 }, showActionsLeft: { classPropertyName: "showActionsLeft", publicName: "showActionsLeft", isSignal: true, isRequired: false, transformFunction: null }, evidenceLabel: { classPropertyName: "evidenceLabel", publicName: "evidenceLabel", isSignal: true, isRequired: false, transformFunction: null }, evidenceHelperText: { classPropertyName: "evidenceHelperText", publicName: "evidenceHelperText", isSignal: true, isRequired: false, transformFunction: null }, evidenceAccept: { classPropertyName: "evidenceAccept", publicName: "evidenceAccept", isSignal: true, isRequired: false, transformFunction: null }, maxSizeMB: { classPropertyName: "maxSizeMB", publicName: "maxSizeMB", isSignal: true, isRequired: false, transformFunction: null }, hiddenFooterActions: { classPropertyName: "hiddenFooterActions", publicName: "hiddenFooterActions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSubmit: "onSubmit", onCancel: "onCancel", evidenceChange: "evidenceChange" }, ngImport: i0, template: "<div class=\"modal-form-container\" [class.expanded]=\"isFull()\" [class.no-scroll]=\"!scrollBody()\">\r\n <div class=\"header-content\">\r\n <div class=\"header-top\">\r\n <div class=\"header-text\">\r\n <h1>{{ title() }}</h1>\r\n @if(subtitle()){\r\n <p>{{ subtitle() }}</p>\r\n }\r\n </div>\r\n \r\n <button class=\"close-btn\" type=\"button\" (click)=\"onCancel.emit()\">\r\n \u2715\r\n </button>\r\n </div>\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 class=\"step\" [class.step-active]=\"currentStep() === $index + 1\"\r\n [class.step-completed]=\"currentStep() > $index + 1\">\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) { <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\" [class.scrollable]=\"scrollBody()\" [class.no-scroll]=\"!scrollBody()\">\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 [form]=\"form()\" [currentStep]=\"currentStep()\" [steps]=\"steps()\"\r\n (canContinue)=\"canContinue.set($event)\"></lib-wizard-form>\r\n }\r\n </div>\r\n\r\n @if (!hiddenFooterActions()) {\r\n <div class=\"actions\">\r\n @if (showActionsLeft()){\r\n <div class=\"actions-left\">\r\n <p class=\"file-type\">{{ evidenceHelperText() }}</p>\r\n <lib-button variant=\"outline\" type=\"button\" (clicked)=\"fileInput.click()\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\"\r\n class=\"upload-icon icon icon-tabler icons-tabler-outline icon-tabler-cloud-upload\" width=\"24\" height=\"24\"\r\n viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\">\r\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\" />\r\n <path d=\"M7 18a4.6 4.4 0 0 1 0 -9a5 4.5 0 0 1 11 2h1a3.5 3.5 0 0 1 0 7h-1\" />\r\n <path d=\"M9 15l3 -3l3 3\" />\r\n <path d=\"M12 12l0 9\" />\r\n </svg>\r\n <span class=\"label-button\">\r\n {{ evidenceFileName() || evidenceLabel() }}\r\n </span>\r\n </lib-button>\r\n <input #fileInput type=\"file\" hidden [accept]=\"evidenceAccept()\" (change)=\"onFileSelected($event)\" />\r\n </div>\r\n }\r\n\r\n <div class=\"actions-right\">\r\n @if (!steps() || steps().length <= 1) { \r\n <lib-button variant=\"secondary\" type=\"button\" (clicked)=\"onCancel.emit()\">\r\n Cancelar\r\n </lib-button>\r\n } @else if (currentStep() === 1) {\r\n <lib-button variant=\"secondary\" type=\"button\" (clicked)=\"onCancel.emit()\">\r\n Cancelar\r\n </lib-button>\r\n } @else {\r\n <lib-button variant=\"secondary\" type=\"button\" (clicked)=\"prevStep()\">\r\n Volver\r\n </lib-button>\r\n }\r\n\r\n <lib-button\r\n variant=\"primary\"\r\n type=\"button\"\r\n [disabled]=\"!canContinue()\"\r\n (clicked)=\"!steps() || !steps().length ? submitForm() : (currentStep() === steps().length ? submitForm() : nextStep())\"\r\n >\r\n {{ !steps() || !steps().length ? submitLabel() : currentStep() ===\r\n steps().length ? submitLabel() : 'Continuar' }}\r\n </lib-button>\r\n </div>\r\n </div>\r\n }\r\n</div>", styles: [":host{position:fixed;inset:0;background:#0006;backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);display:flex;justify-content:center;align-items:center;z-index:9999;padding:12px;box-sizing:border-box;overflow-y:auto}.modal-form-container{background-color:#ebe8d6;--sl-form-surface: #ebe8d6;width:100%;max-width:1200px;max-height:90dvh;display:flex;flex-direction:column;align-items:stretch;padding:24px 48px;border-radius:24px;box-shadow:0 10px 25px #00000026}.header-content{display:flex;flex-direction:column;gap:6px;padding:16px 0;position:sticky;top:0;z-index:10}.header-top{display:flex;justify-content:space-between;align-items:center}.header-text{display:flex;flex-direction:column;gap:6px}.close-btn{background:transparent;border:none;font-size:2rem;font-weight:500;cursor:pointer;color:#596300;padding:4px 10px;border-radius:50%;transition:background-color .2s ease,transform .2s ease}.close-btn:hover{background-color:#00000010;transform:scale(1.1)}.header-content h1{font-size:2.4rem;font-weight:700;color:#1c1c12}.header-content p{font-size:1.4rem;font-weight:300;color:#454733}.divider{width:calc(100% + 100px);margin-left:-52px;height:1px;background-color:#7878612c;margin-top:16px}.body-content{flex:1 1 auto;min-height:0}.body-content.scrollable{overflow-y:auto}.modal-form-container.no-scroll,.body-content.no-scroll{overflow:visible}.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}.actions{display:flex;justify-content:space-between;align-items:end;width:100%;margin-top:8px;padding:8px 0;position:sticky;bottom:0;z-index:10}.actions-left{display:flex;flex-direction:column;gap:4px}.actions-right{display:flex;gap:10px;margin-left:auto}.upload-icon{width:28px;height:28px;color:#6a750a;cursor:pointer;transition:transform .2s ease,color .2s ease}.label-button{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;flex:1}.file-type{margin-left:8px;font-size:11px;color:#8a8a8a}.modal-form-container.expanded{position:relative;width:100%;max-width:100dvw;height:100%;max-height:100dvh;background-color:#ebe8d6;--sl-form-surface: #ebe8d6;display:flex;flex-direction:column;align-items:stretch;padding:18px 0 14px;border-radius:24px}.modal-form-container.expanded .header-content,.modal-form-container.expanded .actions{padding:8px 24px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: WizardForm, selector: "lib-wizard-form", inputs: ["form", "currentStep", "steps"], outputs: ["canContinue"] }, { kind: "component", type: Button, selector: "lib-button", inputs: ["variant", "type", "disabled", "fullWidth", "size"], outputs: ["clicked"] }] });
2858
2917
  }
2859
2918
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ModalForm, decorators: [{
2860
2919
  type: Component,
2861
- args: [{ selector: 'lib-modal-form', standalone: true, imports: [CommonModule, WizardForm, Button], template: "<div class=\"modal-form-container\" [class.expanded]=\"isFull()\">\r\n <div class=\"header-content\">\r\n <div class=\"header-top\">\r\n <div class=\"header-text\">\r\n <h1>{{ title() }}</h1>\r\n @if(subtitle()){\r\n <p>{{ subtitle() }}</p>\r\n }\r\n </div>\r\n \r\n <button class=\"close-btn\" type=\"button\" (click)=\"onCancel.emit()\">\r\n \u2715\r\n </button>\r\n </div>\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 class=\"step\" [class.step-active]=\"currentStep() === $index + 1\"\r\n [class.step-completed]=\"currentStep() > $index + 1\">\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) { <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\" [class.scrollable]=\"scrollBody()\">\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 [form]=\"form()\" [currentStep]=\"currentStep()\" [steps]=\"steps()\"\r\n (canContinue)=\"canContinue.set($event)\"></lib-wizard-form>\r\n }\r\n </div>\r\n\r\n @if (!hiddenFooterActions()) {\r\n <div class=\"actions\">\r\n @if (showActionsLeft()){\r\n <div class=\"actions-left\">\r\n <p class=\"file-type\">{{ evidenceHelperText() }}</p>\r\n <lib-button variant=\"outline\" type=\"button\" (clicked)=\"fileInput.click()\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\"\r\n class=\"upload-icon icon icon-tabler icons-tabler-outline icon-tabler-cloud-upload\" width=\"24\" height=\"24\"\r\n viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\">\r\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\" />\r\n <path d=\"M7 18a4.6 4.4 0 0 1 0 -9a5 4.5 0 0 1 11 2h1a3.5 3.5 0 0 1 0 7h-1\" />\r\n <path d=\"M9 15l3 -3l3 3\" />\r\n <path d=\"M12 12l0 9\" />\r\n </svg>\r\n <span class=\"label-button\">\r\n {{ evidenceFileName() || evidenceLabel() }}\r\n </span>\r\n </lib-button>\r\n <input #fileInput type=\"file\" hidden [accept]=\"evidenceAccept()\" (change)=\"onFileSelected($event)\" />\r\n </div>\r\n }\r\n\r\n <div class=\"actions-right\">\r\n @if (!steps() || steps().length <= 1) { \r\n <lib-button variant=\"secondary\" type=\"button\" (clicked)=\"onCancel.emit()\">\r\n Cancelar\r\n </lib-button>\r\n } @else if (currentStep() === 1) {\r\n <lib-button variant=\"secondary\" type=\"button\" (clicked)=\"onCancel.emit()\">\r\n Cancelar\r\n </lib-button>\r\n } @else {\r\n <lib-button variant=\"secondary\" type=\"button\" (clicked)=\"prevStep()\">\r\n Volver\r\n </lib-button>\r\n }\r\n\r\n <lib-button\r\n variant=\"primary\"\r\n type=\"button\"\r\n [disabled]=\"!canContinue()\"\r\n (clicked)=\"!steps() || !steps().length ? submitForm() : (currentStep() === steps().length ? submitForm() : nextStep())\"\r\n >\r\n {{ !steps() || !steps().length ? submitLabel() : currentStep() ===\r\n steps().length ? submitLabel() : 'Continuar' }}\r\n </lib-button>\r\n </div>\r\n </div>\r\n }\r\n</div>", styles: [":host{position:fixed;inset:0;background:#0006;backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);display:flex;justify-content:center;align-items:center;z-index:9999;padding:12px;box-sizing:border-box;overflow-y:auto}.modal-form-container{background-color:#ebe8d6;--sl-form-surface: #ebe8d6;width:100%;max-width:1200px;max-height:90dvh;display:flex;flex-direction:column;align-items:stretch;padding:24px 48px;border-radius:24px;box-shadow:0 10px 25px #00000026}.header-content{display:flex;flex-direction:column;gap:6px;padding:16px 0;position:sticky;top:0;z-index:10}.header-top{display:flex;justify-content:space-between;align-items:center}.header-text{display:flex;flex-direction:column;gap:6px}.close-btn{background:transparent;border:none;font-size:2rem;font-weight:500;cursor:pointer;color:#596300;padding:4px 10px;border-radius:50%;transition:background-color .2s ease,transform .2s ease}.close-btn:hover{background-color:#00000010;transform:scale(1.1)}.header-content h1{font-size:2.4rem;font-weight:700;color:#1c1c12}.header-content p{font-size:1.4rem;font-weight:300;color:#454733}.divider{width:calc(100% + 100px);margin-left:-52px;height:1px;background-color:#7878612c;margin-top:16px}.body-content{flex:1 1 auto;min-height:0}.body-content.scrollable{overflow-y:auto}.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}.actions{display:flex;justify-content:space-between;align-items:end;width:100%;margin-top:8px;padding:8px 0;position:sticky;bottom:0;z-index:10}.actions-left{display:flex;flex-direction:column;gap:4px}.actions-right{display:flex;gap:10px;margin-left:auto}.upload-icon{width:28px;height:28px;color:#6a750a;cursor:pointer;transition:transform .2s ease,color .2s ease}.label-button{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;flex:1}.file-type{margin-left:8px;font-size:11px;color:#8a8a8a}.modal-form-container.expanded{position:relative;width:100%;max-width:100dvw;height:100%;max-height:100dvh;background-color:#ebe8d6;--sl-form-surface: #ebe8d6;display:flex;flex-direction:column;align-items:stretch;padding:18px 0 14px;border-radius:24px}.modal-form-container.expanded .header-content,.modal-form-container.expanded .actions{padding:8px 24px}\n"] }]
2920
+ args: [{ selector: 'lib-modal-form', standalone: true, imports: [CommonModule, WizardForm, Button], template: "<div class=\"modal-form-container\" [class.expanded]=\"isFull()\" [class.no-scroll]=\"!scrollBody()\">\r\n <div class=\"header-content\">\r\n <div class=\"header-top\">\r\n <div class=\"header-text\">\r\n <h1>{{ title() }}</h1>\r\n @if(subtitle()){\r\n <p>{{ subtitle() }}</p>\r\n }\r\n </div>\r\n \r\n <button class=\"close-btn\" type=\"button\" (click)=\"onCancel.emit()\">\r\n \u2715\r\n </button>\r\n </div>\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 class=\"step\" [class.step-active]=\"currentStep() === $index + 1\"\r\n [class.step-completed]=\"currentStep() > $index + 1\">\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) { <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\" [class.scrollable]=\"scrollBody()\" [class.no-scroll]=\"!scrollBody()\">\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 [form]=\"form()\" [currentStep]=\"currentStep()\" [steps]=\"steps()\"\r\n (canContinue)=\"canContinue.set($event)\"></lib-wizard-form>\r\n }\r\n </div>\r\n\r\n @if (!hiddenFooterActions()) {\r\n <div class=\"actions\">\r\n @if (showActionsLeft()){\r\n <div class=\"actions-left\">\r\n <p class=\"file-type\">{{ evidenceHelperText() }}</p>\r\n <lib-button variant=\"outline\" type=\"button\" (clicked)=\"fileInput.click()\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\"\r\n class=\"upload-icon icon icon-tabler icons-tabler-outline icon-tabler-cloud-upload\" width=\"24\" height=\"24\"\r\n viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\">\r\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\" />\r\n <path d=\"M7 18a4.6 4.4 0 0 1 0 -9a5 4.5 0 0 1 11 2h1a3.5 3.5 0 0 1 0 7h-1\" />\r\n <path d=\"M9 15l3 -3l3 3\" />\r\n <path d=\"M12 12l0 9\" />\r\n </svg>\r\n <span class=\"label-button\">\r\n {{ evidenceFileName() || evidenceLabel() }}\r\n </span>\r\n </lib-button>\r\n <input #fileInput type=\"file\" hidden [accept]=\"evidenceAccept()\" (change)=\"onFileSelected($event)\" />\r\n </div>\r\n }\r\n\r\n <div class=\"actions-right\">\r\n @if (!steps() || steps().length <= 1) { \r\n <lib-button variant=\"secondary\" type=\"button\" (clicked)=\"onCancel.emit()\">\r\n Cancelar\r\n </lib-button>\r\n } @else if (currentStep() === 1) {\r\n <lib-button variant=\"secondary\" type=\"button\" (clicked)=\"onCancel.emit()\">\r\n Cancelar\r\n </lib-button>\r\n } @else {\r\n <lib-button variant=\"secondary\" type=\"button\" (clicked)=\"prevStep()\">\r\n Volver\r\n </lib-button>\r\n }\r\n\r\n <lib-button\r\n variant=\"primary\"\r\n type=\"button\"\r\n [disabled]=\"!canContinue()\"\r\n (clicked)=\"!steps() || !steps().length ? submitForm() : (currentStep() === steps().length ? submitForm() : nextStep())\"\r\n >\r\n {{ !steps() || !steps().length ? submitLabel() : currentStep() ===\r\n steps().length ? submitLabel() : 'Continuar' }}\r\n </lib-button>\r\n </div>\r\n </div>\r\n }\r\n</div>", styles: [":host{position:fixed;inset:0;background:#0006;backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);display:flex;justify-content:center;align-items:center;z-index:9999;padding:12px;box-sizing:border-box;overflow-y:auto}.modal-form-container{background-color:#ebe8d6;--sl-form-surface: #ebe8d6;width:100%;max-width:1200px;max-height:90dvh;display:flex;flex-direction:column;align-items:stretch;padding:24px 48px;border-radius:24px;box-shadow:0 10px 25px #00000026}.header-content{display:flex;flex-direction:column;gap:6px;padding:16px 0;position:sticky;top:0;z-index:10}.header-top{display:flex;justify-content:space-between;align-items:center}.header-text{display:flex;flex-direction:column;gap:6px}.close-btn{background:transparent;border:none;font-size:2rem;font-weight:500;cursor:pointer;color:#596300;padding:4px 10px;border-radius:50%;transition:background-color .2s ease,transform .2s ease}.close-btn:hover{background-color:#00000010;transform:scale(1.1)}.header-content h1{font-size:2.4rem;font-weight:700;color:#1c1c12}.header-content p{font-size:1.4rem;font-weight:300;color:#454733}.divider{width:calc(100% + 100px);margin-left:-52px;height:1px;background-color:#7878612c;margin-top:16px}.body-content{flex:1 1 auto;min-height:0}.body-content.scrollable{overflow-y:auto}.modal-form-container.no-scroll,.body-content.no-scroll{overflow:visible}.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}.actions{display:flex;justify-content:space-between;align-items:end;width:100%;margin-top:8px;padding:8px 0;position:sticky;bottom:0;z-index:10}.actions-left{display:flex;flex-direction:column;gap:4px}.actions-right{display:flex;gap:10px;margin-left:auto}.upload-icon{width:28px;height:28px;color:#6a750a;cursor:pointer;transition:transform .2s ease,color .2s ease}.label-button{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;flex:1}.file-type{margin-left:8px;font-size:11px;color:#8a8a8a}.modal-form-container.expanded{position:relative;width:100%;max-width:100dvw;height:100%;max-height:100dvh;background-color:#ebe8d6;--sl-form-surface: #ebe8d6;display:flex;flex-direction:column;align-items:stretch;padding:18px 0 14px;border-radius:24px}.modal-form-container.expanded .header-content,.modal-form-container.expanded .actions{padding:8px 24px}\n"] }]
2862
2921
  }], ctorParameters: () => [], propDecorators: { isFull: [{ type: i0.Input, args: [{ isSignal: true, alias: "isFull", required: false }] }], scrollBody: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollBody", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", 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"] }], evidenceChange: [{ type: i0.Output, args: ["evidenceChange"] }], showActionsLeft: [{ type: i0.Input, args: [{ isSignal: true, alias: "showActionsLeft", required: false }] }], evidenceLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "evidenceLabel", required: false }] }], evidenceHelperText: [{ type: i0.Input, args: [{ isSignal: true, alias: "evidenceHelperText", required: false }] }], evidenceAccept: [{ type: i0.Input, args: [{ isSignal: true, alias: "evidenceAccept", required: false }] }], maxSizeMB: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSizeMB", required: false }] }], hiddenFooterActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "hiddenFooterActions", required: false }] }] } });
2863
2922
 
2864
2923
  class DialogAlertComponent {
@@ -5076,6 +5135,82 @@ function getTotal(data) {
5076
5135
  function buildDonutChartOptions(data) {
5077
5136
  const total = getTotal(data);
5078
5137
  const showLegend = data.length > 10;
5138
+ const splitLegend = data.length > 14;
5139
+ let legendConfig = {};
5140
+ if (showLegend) {
5141
+ if (splitLegend) {
5142
+ const half = Math.ceil(data.length / 2);
5143
+ const leftData = data.slice(0, half).map(d => d.label);
5144
+ const rightData = data.slice(half).map(d => d.label);
5145
+ legendConfig = {
5146
+ legend: [
5147
+ {
5148
+ data: leftData,
5149
+ type: 'scroll',
5150
+ orient: 'vertical',
5151
+ left: '5%',
5152
+ top: 'center',
5153
+ itemWidth: 12,
5154
+ itemHeight: 12,
5155
+ itemGap: 10,
5156
+ textStyle: {
5157
+ fontSize: 11,
5158
+ fontFamily: UI_CHART_TOKENS.fontFamily,
5159
+ color: UI_CHART_TOKENS.muted,
5160
+ },
5161
+ pageTextStyle: { color: UI_CHART_TOKENS.muted },
5162
+ pageIconColor: UI_CHART_TOKENS.centerText,
5163
+ pageIconInactiveColor: '#ccc',
5164
+ },
5165
+ {
5166
+ data: rightData,
5167
+ type: 'scroll',
5168
+ orient: 'vertical',
5169
+ right: '5%',
5170
+ top: 'center',
5171
+ itemWidth: 12,
5172
+ itemHeight: 12,
5173
+ itemGap: 10,
5174
+ textStyle: {
5175
+ fontSize: 11,
5176
+ fontFamily: UI_CHART_TOKENS.fontFamily,
5177
+ color: UI_CHART_TOKENS.muted,
5178
+ },
5179
+ pageTextStyle: { color: UI_CHART_TOKENS.muted },
5180
+ pageIconColor: UI_CHART_TOKENS.centerText,
5181
+ pageIconInactiveColor: '#ccc',
5182
+ }
5183
+ ]
5184
+ };
5185
+ }
5186
+ else {
5187
+ legendConfig = {
5188
+ legend: {
5189
+ type: 'scroll',
5190
+ orient: 'vertical',
5191
+ right: '5%',
5192
+ top: 'center',
5193
+ itemWidth: 12,
5194
+ itemHeight: 12,
5195
+ itemGap: 10,
5196
+ textStyle: {
5197
+ fontSize: 11,
5198
+ fontFamily: UI_CHART_TOKENS.fontFamily,
5199
+ color: UI_CHART_TOKENS.muted,
5200
+ },
5201
+ pageTextStyle: {
5202
+ color: UI_CHART_TOKENS.muted,
5203
+ },
5204
+ pageIconColor: UI_CHART_TOKENS.centerText,
5205
+ pageIconInactiveColor: '#ccc',
5206
+ }
5207
+ };
5208
+ }
5209
+ }
5210
+ let centerX = '50%';
5211
+ if (showLegend) {
5212
+ centerX = splitLegend ? '50%' : '35%';
5213
+ }
5079
5214
  return {
5080
5215
  animation: true,
5081
5216
  backgroundColor: 'transparent',
@@ -5105,32 +5240,12 @@ function buildDonutChartOptions(data) {
5105
5240
  `,
5106
5241
  formatter: (params) => `${params.name}: ${params.value}`,
5107
5242
  },
5108
- ...(showLegend ? {
5109
- legend: {
5110
- type: 'scroll',
5111
- orient: 'horizontal',
5112
- bottom: 0,
5113
- left: 'center',
5114
- itemWidth: 12,
5115
- itemHeight: 12,
5116
- itemGap: 10,
5117
- textStyle: {
5118
- fontSize: 11,
5119
- fontFamily: UI_CHART_TOKENS.fontFamily,
5120
- color: UI_CHART_TOKENS.muted,
5121
- },
5122
- pageTextStyle: {
5123
- color: UI_CHART_TOKENS.muted,
5124
- },
5125
- pageIconColor: UI_CHART_TOKENS.centerText,
5126
- pageIconInactiveColor: '#ccc',
5127
- },
5128
- } : {}),
5243
+ ...legendConfig,
5129
5244
  series: [
5130
5245
  {
5131
5246
  type: 'pie',
5132
5247
  radius: ['44%', '72%'],
5133
- center: ['50%', showLegend ? '46%' : '52%'],
5248
+ center: [centerX, '50%'],
5134
5249
  avoidLabelOverlap: true,
5135
5250
  minAngle: 4,
5136
5251
  itemStyle: {
@@ -5183,21 +5298,19 @@ function buildDonutChartOptions(data) {
5183
5298
  })),
5184
5299
  },
5185
5300
  ],
5186
- graphic: [
5187
- {
5188
- type: 'text',
5189
- left: 'center',
5190
- top: showLegend ? '42%' : '48%',
5191
- style: {
5192
- text: `${total}`,
5193
- textAlign: 'center',
5194
- fill: UI_CHART_TOKENS.centerText,
5195
- fontSize: 24,
5196
- fontWeight: 700,
5197
- fontFamily: UI_CHART_TOKENS.fontFamily,
5198
- },
5301
+ title: {
5302
+ text: `${total}`,
5303
+ left: centerX,
5304
+ top: '48%',
5305
+ textAlign: 'center',
5306
+ textVerticalAlign: 'middle',
5307
+ textStyle: {
5308
+ color: UI_CHART_TOKENS.centerText,
5309
+ fontSize: 24,
5310
+ fontWeight: 700,
5311
+ fontFamily: UI_CHART_TOKENS.fontFamily,
5199
5312
  },
5200
- ],
5313
+ },
5201
5314
  };
5202
5315
  }
5203
5316
  class DonutChart {
@@ -5335,6 +5448,7 @@ function buildHeatmapOptions(config) {
5335
5448
  visualMap: {
5336
5449
  min: minVal,
5337
5450
  max: maxVal,
5451
+ calculable: false,
5338
5452
  orient: 'horizontal',
5339
5453
  left: 'center',
5340
5454
  bottom: '0',
@@ -5716,49 +5830,137 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
5716
5830
  args: ['fileInput']
5717
5831
  }] } });
5718
5832
 
5719
- class PdfViewerService {
5720
- showModalDocuments = signal(false, ...(ngDevMode ? [{ debugName: "showModalDocuments" }] : []));
5721
- selectedPdf = signal(null, ...(ngDevMode ? [{ debugName: "selectedPdf" }] : []));
5722
- openModal() {
5723
- this.showModalDocuments.set(true);
5724
- }
5725
- closeModal() {
5726
- this.showModalDocuments.set(false);
5727
- }
5728
- setSelectedPdf(pdf) {
5729
- this.selectedPdf.set(pdf);
5730
- }
5731
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: PdfViewerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
5732
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: PdfViewerService, providedIn: 'root' });
5733
- }
5734
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: PdfViewerService, decorators: [{
5735
- type: Injectable,
5736
- args: [{
5737
- providedIn: 'root',
5738
- }]
5739
- }] });
5740
-
5833
+ const IMAGE_EXTENSIONS = /\.(jpg|jpeg|png|gif|webp|svg|bmp|avif)(\?.*)?$/i;
5741
5834
  class PdfViewer {
5742
5835
  pdfViewerService = inject(PdfViewerService);
5743
5836
  sanitizer = inject(DomSanitizer);
5837
+ currentIndex = signal(0, ...(ngDevMode ? [{ debugName: "currentIndex" }] : []));
5744
5838
  get isShowModal() {
5745
5839
  return this.pdfViewerService.showModalDocuments();
5746
5840
  }
5747
- pdf = computed(() => this.pdfViewerService.selectedPdf(), ...(ngDevMode ? [{ debugName: "pdf" }] : []));
5841
+ doc = computed(() => this.pdfViewerService.selectedPdf(), ...(ngDevMode ? [{ debugName: "doc" }] : []));
5842
+ currentUrl = computed(() => this.doc()?.urls[this.currentIndex()] ?? '', ...(ngDevMode ? [{ debugName: "currentUrl" }] : []));
5843
+ hasMultiple = computed(() => (this.doc()?.urls.length ?? 0) > 1, ...(ngDevMode ? [{ debugName: "hasMultiple" }] : []));
5844
+ isImage = computed(() => {
5845
+ const d = this.doc();
5846
+ if (!d)
5847
+ return false;
5848
+ if (d.type === 'image')
5849
+ return true;
5850
+ if (d.type === 'pdf')
5851
+ return false;
5852
+ // Detectar por la primera URL
5853
+ return IMAGE_EXTENSIONS.test(d.urls[0] ?? '');
5854
+ }, ...(ngDevMode ? [{ debugName: "isImage" }] : []));
5855
+ constructor() {
5856
+ // Reiniciar al índice 0 cada vez que cambia el documento
5857
+ effect(() => {
5858
+ this.doc();
5859
+ this.currentIndex.set(0);
5860
+ });
5861
+ }
5862
+ prev() {
5863
+ if (this.currentIndex() > 0)
5864
+ this.currentIndex.update(i => i - 1);
5865
+ }
5866
+ next() {
5867
+ const total = this.doc()?.urls.length ?? 0;
5868
+ if (this.currentIndex() < total - 1)
5869
+ this.currentIndex.update(i => i + 1);
5870
+ }
5748
5871
  getSafePdfUrl(url) {
5749
5872
  return this.sanitizer.bypassSecurityTrustResourceUrl(url);
5750
5873
  }
5874
+ getSafeImageUrl(url) {
5875
+ return this.sanitizer.bypassSecurityTrustUrl(url);
5876
+ }
5751
5877
  closeModal() {
5752
5878
  this.pdfViewerService.closeModal();
5753
5879
  this.pdfViewerService.setSelectedPdf(null);
5754
5880
  }
5755
5881
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: PdfViewer, deps: [], target: i0.ɵɵFactoryTarget.Component });
5756
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: PdfViewer, isStandalone: true, selector: "lib-pdf-viewer", ngImport: i0, template: "@if (isShowModal) {\r\n<section class=\"modal-container\" (click)=\"closeModal()\">\r\n <div class=\"modal-content\" (click)=\"$event.stopPropagation()\">\r\n <div class=\"modal-header\">\r\n <h1>{{ pdf()?.name || 'Documento' }}</h1>\r\n <button type=\"button\" class=\"close-btn\" (click)=\"closeModal()\">\r\n &times;\r\n </button>\r\n </div>\r\n <div class=\"modal-body\">\r\n @if (pdf(); as doc) {\r\n <iframe [src]=\"getSafePdfUrl(doc.url)\" class=\"pdf-viewer\" frameborder=\"0\" width=\"100%\" height=\"700px\"></iframe>\r\n } @else {\r\n <p>No hay documento disponible</p>\r\n }\r\n </div>\r\n </div>\r\n</section>\r\n}", styles: [".modal-container{position:fixed;top:0;left:0;width:100%;height:100%;z-index:999;background-color:#00000080;display:flex;justify-content:center;align-items:center;opacity:1;transition:opacity .3s ease}.modal-content{width:80%;height:80%;background-color:#ebe8d6;border-radius:20px;box-shadow:0 4px 20px #0000004d;margin:20px;display:flex;flex-direction:column;overflow:hidden;animation:slideIn .3s ease-out}.modal-header{display:flex;justify-content:space-between;align-items:center;padding:15px 20px;border-bottom:1px solid #c7c7ad;border-radius:20px 20px 0 0;flex-shrink:0}.modal-header h1{margin:0;font-size:2rem;color:#333}.close-btn{background:none;border:none;font-size:2rem;cursor:pointer;color:#666;transition:color .2s ease;padding:0;width:30px;height:30px;display:flex;align-items:center;justify-content:center;border-radius:50%;flex-shrink:0}.close-btn:hover{color:#333;background-color:#0000001a}.modal-body{padding:20px;overflow:auto;flex:1;display:flex;flex-direction:column}.pdf-viewer{width:100%;height:100%;border:none;border-radius:0}@media (max-width: 850px){.modal-content{width:95vw;height:90vh;margin:10px}.modal-header h1{font-size:1.4rem}}@media (max-width: 480px){.modal-content{width:95vw;height:90vh}.modal-header h1{font-size:1.2rem}}@keyframes slideIn{0%{opacity:0;transform:scale(.9)}to{opacity:1;transform:scale(1)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
5882
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: PdfViewer, isStandalone: true, selector: "lib-pdf-viewer", ngImport: i0, template: "@if (isShowModal) {\r\n<section class=\"modal-container\" (click)=\"closeModal()\">\r\n <div class=\"modal-content\" (click)=\"$event.stopPropagation()\">\r\n\r\n <div class=\"modal-header\">\r\n <h1 class=\"modal-title\" [title]=\"doc()?.name || ''\">\r\n {{ doc()?.name || 'Documento' }}\r\n </h1>\r\n @if (hasMultiple()) {\r\n <span class=\"gallery-counter-header\">\r\n {{ currentIndex() + 1 }} / {{ doc()!.urls.length }}\r\n </span>\r\n }\r\n <button type=\"button\" class=\"close-btn\" (click)=\"closeModal()\">&times;</button>\r\n </div>\r\n\r\n <div class=\"modal-body\">\r\n @if (doc(); as d) {\r\n @if (isImage()) {\r\n <div class=\"image-wrapper\">\r\n @if (hasMultiple()) {\r\n <button type=\"button\" class=\"gallery-arrow gallery-arrow--prev\"\r\n [disabled]=\"currentIndex() === 0\"\r\n (click)=\"prev()\">\r\n &#8249;\r\n </button>\r\n }\r\n <img [src]=\"getSafeImageUrl(currentUrl())\" [alt]=\"d.name\" class=\"image-viewer\" />\r\n @if (hasMultiple()) {\r\n <button type=\"button\" class=\"gallery-arrow gallery-arrow--next\"\r\n [disabled]=\"currentIndex() === d.urls.length - 1\"\r\n (click)=\"next()\">\r\n &#8250;\r\n </button>\r\n }\r\n </div>\r\n @if (hasMultiple()) {\r\n <div class=\"gallery-dots\">\r\n @for (url of d.urls; track $index) {\r\n <button type=\"button\" class=\"gallery-dot\"\r\n [class.gallery-dot--active]=\"$index === currentIndex()\"\r\n (click)=\"currentIndex.set($index)\">\r\n </button>\r\n }\r\n </div>\r\n }\r\n } @else {\r\n <iframe [src]=\"getSafePdfUrl(currentUrl())\" class=\"pdf-viewer\" frameborder=\"0\"></iframe>\r\n }\r\n } @else {\r\n <p class=\"no-doc\">No hay documento disponible</p>\r\n }\r\n </div>\r\n\r\n </div>\r\n</section>\r\n}", styles: [".modal-container{position:fixed;top:0;left:0;width:100%;height:100%;z-index:99999;background-color:#00000080;display:flex;justify-content:center;align-items:center;opacity:1;transition:opacity .3s ease}.modal-content{width:95%;height:95%;background-color:#ebe8d6;border-radius:20px;box-shadow:0 4px 20px #0000004d;margin:20px;display:flex;flex-direction:column;overflow:hidden;animation:slideIn .3s ease-out}.modal-header{display:flex;justify-content:space-between;align-items:center;padding:15px 20px;border-bottom:1px solid #c7c7ad;border-radius:20px 20px 0 0;flex-shrink:0}.modal-header h1{margin:0;font-size:2rem;color:#333;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.close-btn{background:none;border:none;font-size:2rem;cursor:pointer;color:#666;transition:color .2s ease;padding:0;width:30px;height:30px;display:flex;align-items:center;justify-content:center;border-radius:50%;flex-shrink:0}.close-btn:hover{color:#333;background-color:#0000001a}.modal-body{padding:20px;overflow:auto;flex:1;display:flex;flex-direction:column}.pdf-viewer{width:100%;height:100%;border:none;border-radius:0;flex:1}.image-wrapper{flex:1;display:flex;align-items:center;justify-content:center;position:relative;overflow:hidden;min-height:0}.image-viewer{max-width:100%;max-height:100%;object-fit:contain;border-radius:8px;box-shadow:0 2px 12px #00000026;display:block;-webkit-user-select:none;user-select:none}.gallery-arrow{position:absolute;top:50%;transform:translateY(-50%);z-index:2;background:#ebe8d6eb;border:1px solid #c7c7ad;border-radius:50%;width:44px;height:44px;font-size:2.4rem;line-height:1;cursor:pointer;color:#454733;display:flex;align-items:center;justify-content:center;transition:background .15s,opacity .15s;padding:0}.gallery-arrow:hover:not(:disabled){background:#d4d4b8}.gallery-arrow:disabled{opacity:.3;cursor:not-allowed}.gallery-arrow--prev{left:12px}.gallery-arrow--next{right:12px}.gallery-counter-header{font-size:1.3rem;color:#787861;font-weight:500;flex-shrink:0;margin-left:auto;margin-right:12px}.gallery-dots{display:flex;justify-content:center;align-items:center;gap:8px;padding:10px 0 4px;flex-shrink:0}.gallery-dot{width:8px;height:8px;border-radius:50%;border:none;background:#c7c7ad;cursor:pointer;padding:0;transition:background .2s,transform .2s}.gallery-dot--active{background:#596300;transform:scale(1.3)}.no-doc{color:#888;text-align:center;margin:auto}@media (max-width: 850px){.modal-content{width:95vw;height:90vh;margin:10px}.modal-header h1{font-size:1.4rem}}@media (max-width: 480px){.modal-content{width:95vw;height:90vh}.modal-header h1{font-size:1.2rem}}@keyframes slideIn{0%{opacity:0;transform:scale(.9)}to{opacity:1;transform:scale(1)}}\n"] });
5757
5883
  }
5758
5884
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: PdfViewer, decorators: [{
5759
5885
  type: Component,
5760
- args: [{ selector: 'lib-pdf-viewer', imports: [CommonModule], template: "@if (isShowModal) {\r\n<section class=\"modal-container\" (click)=\"closeModal()\">\r\n <div class=\"modal-content\" (click)=\"$event.stopPropagation()\">\r\n <div class=\"modal-header\">\r\n <h1>{{ pdf()?.name || 'Documento' }}</h1>\r\n <button type=\"button\" class=\"close-btn\" (click)=\"closeModal()\">\r\n &times;\r\n </button>\r\n </div>\r\n <div class=\"modal-body\">\r\n @if (pdf(); as doc) {\r\n <iframe [src]=\"getSafePdfUrl(doc.url)\" class=\"pdf-viewer\" frameborder=\"0\" width=\"100%\" height=\"700px\"></iframe>\r\n } @else {\r\n <p>No hay documento disponible</p>\r\n }\r\n </div>\r\n </div>\r\n</section>\r\n}", styles: [".modal-container{position:fixed;top:0;left:0;width:100%;height:100%;z-index:999;background-color:#00000080;display:flex;justify-content:center;align-items:center;opacity:1;transition:opacity .3s ease}.modal-content{width:80%;height:80%;background-color:#ebe8d6;border-radius:20px;box-shadow:0 4px 20px #0000004d;margin:20px;display:flex;flex-direction:column;overflow:hidden;animation:slideIn .3s ease-out}.modal-header{display:flex;justify-content:space-between;align-items:center;padding:15px 20px;border-bottom:1px solid #c7c7ad;border-radius:20px 20px 0 0;flex-shrink:0}.modal-header h1{margin:0;font-size:2rem;color:#333}.close-btn{background:none;border:none;font-size:2rem;cursor:pointer;color:#666;transition:color .2s ease;padding:0;width:30px;height:30px;display:flex;align-items:center;justify-content:center;border-radius:50%;flex-shrink:0}.close-btn:hover{color:#333;background-color:#0000001a}.modal-body{padding:20px;overflow:auto;flex:1;display:flex;flex-direction:column}.pdf-viewer{width:100%;height:100%;border:none;border-radius:0}@media (max-width: 850px){.modal-content{width:95vw;height:90vh;margin:10px}.modal-header h1{font-size:1.4rem}}@media (max-width: 480px){.modal-content{width:95vw;height:90vh}.modal-header h1{font-size:1.2rem}}@keyframes slideIn{0%{opacity:0;transform:scale(.9)}to{opacity:1;transform:scale(1)}}\n"] }]
5761
- }] });
5886
+ args: [{ selector: 'lib-pdf-viewer', imports: [], template: "@if (isShowModal) {\r\n<section class=\"modal-container\" (click)=\"closeModal()\">\r\n <div class=\"modal-content\" (click)=\"$event.stopPropagation()\">\r\n\r\n <div class=\"modal-header\">\r\n <h1 class=\"modal-title\" [title]=\"doc()?.name || ''\">\r\n {{ doc()?.name || 'Documento' }}\r\n </h1>\r\n @if (hasMultiple()) {\r\n <span class=\"gallery-counter-header\">\r\n {{ currentIndex() + 1 }} / {{ doc()!.urls.length }}\r\n </span>\r\n }\r\n <button type=\"button\" class=\"close-btn\" (click)=\"closeModal()\">&times;</button>\r\n </div>\r\n\r\n <div class=\"modal-body\">\r\n @if (doc(); as d) {\r\n @if (isImage()) {\r\n <div class=\"image-wrapper\">\r\n @if (hasMultiple()) {\r\n <button type=\"button\" class=\"gallery-arrow gallery-arrow--prev\"\r\n [disabled]=\"currentIndex() === 0\"\r\n (click)=\"prev()\">\r\n &#8249;\r\n </button>\r\n }\r\n <img [src]=\"getSafeImageUrl(currentUrl())\" [alt]=\"d.name\" class=\"image-viewer\" />\r\n @if (hasMultiple()) {\r\n <button type=\"button\" class=\"gallery-arrow gallery-arrow--next\"\r\n [disabled]=\"currentIndex() === d.urls.length - 1\"\r\n (click)=\"next()\">\r\n &#8250;\r\n </button>\r\n }\r\n </div>\r\n @if (hasMultiple()) {\r\n <div class=\"gallery-dots\">\r\n @for (url of d.urls; track $index) {\r\n <button type=\"button\" class=\"gallery-dot\"\r\n [class.gallery-dot--active]=\"$index === currentIndex()\"\r\n (click)=\"currentIndex.set($index)\">\r\n </button>\r\n }\r\n </div>\r\n }\r\n } @else {\r\n <iframe [src]=\"getSafePdfUrl(currentUrl())\" class=\"pdf-viewer\" frameborder=\"0\"></iframe>\r\n }\r\n } @else {\r\n <p class=\"no-doc\">No hay documento disponible</p>\r\n }\r\n </div>\r\n\r\n </div>\r\n</section>\r\n}", styles: [".modal-container{position:fixed;top:0;left:0;width:100%;height:100%;z-index:99999;background-color:#00000080;display:flex;justify-content:center;align-items:center;opacity:1;transition:opacity .3s ease}.modal-content{width:95%;height:95%;background-color:#ebe8d6;border-radius:20px;box-shadow:0 4px 20px #0000004d;margin:20px;display:flex;flex-direction:column;overflow:hidden;animation:slideIn .3s ease-out}.modal-header{display:flex;justify-content:space-between;align-items:center;padding:15px 20px;border-bottom:1px solid #c7c7ad;border-radius:20px 20px 0 0;flex-shrink:0}.modal-header h1{margin:0;font-size:2rem;color:#333;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.close-btn{background:none;border:none;font-size:2rem;cursor:pointer;color:#666;transition:color .2s ease;padding:0;width:30px;height:30px;display:flex;align-items:center;justify-content:center;border-radius:50%;flex-shrink:0}.close-btn:hover{color:#333;background-color:#0000001a}.modal-body{padding:20px;overflow:auto;flex:1;display:flex;flex-direction:column}.pdf-viewer{width:100%;height:100%;border:none;border-radius:0;flex:1}.image-wrapper{flex:1;display:flex;align-items:center;justify-content:center;position:relative;overflow:hidden;min-height:0}.image-viewer{max-width:100%;max-height:100%;object-fit:contain;border-radius:8px;box-shadow:0 2px 12px #00000026;display:block;-webkit-user-select:none;user-select:none}.gallery-arrow{position:absolute;top:50%;transform:translateY(-50%);z-index:2;background:#ebe8d6eb;border:1px solid #c7c7ad;border-radius:50%;width:44px;height:44px;font-size:2.4rem;line-height:1;cursor:pointer;color:#454733;display:flex;align-items:center;justify-content:center;transition:background .15s,opacity .15s;padding:0}.gallery-arrow:hover:not(:disabled){background:#d4d4b8}.gallery-arrow:disabled{opacity:.3;cursor:not-allowed}.gallery-arrow--prev{left:12px}.gallery-arrow--next{right:12px}.gallery-counter-header{font-size:1.3rem;color:#787861;font-weight:500;flex-shrink:0;margin-left:auto;margin-right:12px}.gallery-dots{display:flex;justify-content:center;align-items:center;gap:8px;padding:10px 0 4px;flex-shrink:0}.gallery-dot{width:8px;height:8px;border-radius:50%;border:none;background:#c7c7ad;cursor:pointer;padding:0;transition:background .2s,transform .2s}.gallery-dot--active{background:#596300;transform:scale(1.3)}.no-doc{color:#888;text-align:center;margin:auto}@media (max-width: 850px){.modal-content{width:95vw;height:90vh;margin:10px}.modal-header h1{font-size:1.4rem}}@media (max-width: 480px){.modal-content{width:95vw;height:90vh}.modal-header h1{font-size:1.2rem}}@keyframes slideIn{0%{opacity:0;transform:scale(.9)}to{opacity:1;transform:scale(1)}}\n"] }]
5887
+ }], ctorParameters: () => [] });
5888
+
5889
+ class DocumentUpload {
5890
+ filesChanged = output();
5891
+ files = signal([], ...(ngDevMode ? [{ debugName: "files" }] : []));
5892
+ isDragging = signal(false, ...(ngDevMode ? [{ debugName: "isDragging" }] : []));
5893
+ label = input('Arrastra los archivos aquí o haz clic para seleccionar', ...(ngDevMode ? [{ debugName: "label" }] : []));
5894
+ helperText = input('Máximo 25 MB por archivo', ...(ngDevMode ? [{ debugName: "helperText" }] : []));
5895
+ /** Valor para el atributo accept del input (ej: ".pdf", "image/*", ".pdf,.png") */
5896
+ accept = input('.pdf,application/pdf', ...(ngDevMode ? [{ debugName: "accept" }] : []));
5897
+ maxSizeMB = input(25, ...(ngDevMode ? [{ debugName: "maxSizeMB" }] : []));
5898
+ multiple = input(true, ...(ngDevMode ? [{ debugName: "multiple" }] : []));
5899
+ onDragOver(event) {
5900
+ event.preventDefault();
5901
+ this.isDragging.set(true);
5902
+ }
5903
+ onDragLeave() {
5904
+ this.isDragging.set(false);
5905
+ }
5906
+ onDrop(event) {
5907
+ event.preventDefault();
5908
+ this.isDragging.set(false);
5909
+ const droppedFiles = Array.from(event.dataTransfer?.files ?? []);
5910
+ this.processFiles(droppedFiles);
5911
+ }
5912
+ onFileSelect(event) {
5913
+ const input = event.target;
5914
+ const selectedFiles = Array.from(input.files ?? []);
5915
+ this.processFiles(selectedFiles);
5916
+ input.value = '';
5917
+ }
5918
+ isFileTypeValid(file) {
5919
+ const accept = this.accept();
5920
+ if (!accept)
5921
+ return true;
5922
+ return accept.split(',').map(t => t.trim()).some(type => {
5923
+ if (type.startsWith('.'))
5924
+ return file.name.toLowerCase().endsWith(type.toLowerCase());
5925
+ if (type.endsWith('/*'))
5926
+ return file.type.startsWith(type.split('/')[0] + '/');
5927
+ return file.type === type;
5928
+ });
5929
+ }
5930
+ processFiles(newFiles) {
5931
+ const valid = newFiles.filter(f => {
5932
+ if (!this.isFileTypeValid(f)) {
5933
+ alert(`El archivo "${f.name}" no tiene un formato permitido.`);
5934
+ return false;
5935
+ }
5936
+ if (f.size > this.maxSizeMB() * 1024 * 1024) {
5937
+ alert(`El archivo "${f.name}" supera los ${this.maxSizeMB()} MB.`);
5938
+ return false;
5939
+ }
5940
+ return true;
5941
+ });
5942
+ this.files.update(current => [...current, ...valid]);
5943
+ this.filesChanged.emit(this.files());
5944
+ }
5945
+ removeFile(file) {
5946
+ this.files.update(current => current.filter(f => f !== file));
5947
+ this.filesChanged.emit(this.files());
5948
+ }
5949
+ formatSize(bytes) {
5950
+ if (bytes < 1024 * 1024)
5951
+ return (bytes / 1024).toFixed(1) + ' KB';
5952
+ return (bytes / 1024 / 1024).toFixed(2) + ' MB';
5953
+ }
5954
+ getFileExtension(file) {
5955
+ return file.name.split('.').pop()?.toUpperCase() ?? 'FILE';
5956
+ }
5957
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DocumentUpload, deps: [], target: i0.ɵɵFactoryTarget.Component });
5958
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DocumentUpload, isStandalone: true, selector: "lib-document-upload", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, helperText: { classPropertyName: "helperText", publicName: "helperText", isSignal: true, isRequired: false, transformFunction: null }, accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, maxSizeMB: { classPropertyName: "maxSizeMB", publicName: "maxSizeMB", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { filesChanged: "filesChanged" }, ngImport: i0, template: "<div class=\"upload-container\" (dragover)=\"onDragOver($event)\" (dragleave)=\"onDragLeave()\" (drop)=\"onDrop($event)\"\r\n [class.dragging]=\"isDragging()\">\r\n\r\n <input type=\"file\" #fileInput [accept]=\"accept()\" [multiple]=\"multiple()\" (change)=\"onFileSelect($event)\" hidden />\r\n\r\n <div class=\"upload-zone\" (click)=\"fileInput.click()\">\r\n <svg class=\"upload-icon\" viewBox=\"0 0 486.3 486.3\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <g>\r\n <path d=\"M395.5,135.8c-5.2-30.9-20.5-59.1-43.9-80.5c-26-23.8-59.8-36.9-95-36.9c-27.2,0-53.7,7.8-76.4,22.5 c-18.9,12.2-34.6,28.7-45.7,48.1c-4.8-0.9-9.8-1.4-14.8-1.4c-42.5,0-77.1,34.6-77.1,77.1c0,5.5,0.6,10.8,1.6,16 C16.7,200.7,0,232.9,0,267.2c0,27.7,10.3,54.6,29.1,75.9c19.3,21.8,44.8,34.7,72,36.2c0.3,0,0.5,0,0.8,0h86 c7.5,0,13.5-6,13.5-13.5s-6-13.5-13.5-13.5h-85.6C61.4,349.8,27,310.9,27,267.1c0-28.3,15.2-54.7,39.7-69 c5.7-3.3,8.1-10.2,5.9-16.4c-2-5.4-3-11.1-3-17.2c0-27.6,22.5-50.1,50.1-50.1c5.9,0,11.7,1,17.1,3c6.6,2.4,13.9-0.6,16.9-6.9 c18.7-39.7,59.1-65.3,103-65.3c59,0,107.7,44.2,113.3,102.8c0.6,6.1,5.2,11,11.2,12c44.5,7.6,78.1,48.7,78.1,95.6 c0,49.7-39.1,92.9-87.3,96.6h-73.7c-7.5,0-13.5,6-13.5,13.5s6,13.5,13.5,13.5h74.2c0.3,0,0.6,0,1,0c30.5-2.2,59-16.2,80.2-39.6 c21.1-23.2,32.6-53,32.6-84C486.2,199.5,447.9,149.6,395.5,135.8z\"/>\r\n <path d=\"M324.2,280c5.3-5.3,5.3-13.8,0-19.1l-71.5-71.5c-2.5-2.5-6-4-9.5-4s-7,1.4-9.5,4l-71.5,71.5c-5.3,5.3-5.3,13.8,0,19.1 c2.6,2.6,6.1,4,9.5,4s6.9-1.3,9.5-4l48.5-48.5v222.9c0,7.5,6,13.5,13.5,13.5s13.5-6,13.5-13.5V231.5l48.5,48.5 C310.4,285.3,318.9,285.3,324.2,280z\"/>\r\n </g>\r\n </svg>\r\n <p class=\"upload-label\"><strong>{{ label() }}</strong></p>\r\n <small class=\"upload-helper\">{{ helperText() }}</small>\r\n </div>\r\n\r\n @if (files().length > 0) {\r\n <div class=\"files-row\">\r\n @for (file of files(); track file.name) {\r\n <div class=\"file-card\">\r\n <button type=\"button\" class=\"file-card-remove\" (click)=\"removeFile(file)\" title=\"Eliminar archivo\">\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>\r\n </svg>\r\n </button>\r\n <svg class=\"file-card-icon\" viewBox=\"0 0 64 64\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M12 4 L12 60 L52 60 L52 20 L36 4 Z\" fill=\"#e3e3d1\" stroke=\"#8a9a2f\" stroke-width=\"2.5\" stroke-linejoin=\"round\"/>\r\n <path d=\"M36 4 L36 20 L52 20\" fill=\"none\" stroke=\"#8a9a2f\" stroke-width=\"2.5\" stroke-linejoin=\"round\"/>\r\n <rect x=\"20\" y=\"30\" width=\"24\" height=\"2.5\" rx=\"1.25\" fill=\"#8a9a2f\"/>\r\n <rect x=\"20\" y=\"37\" width=\"24\" height=\"2.5\" rx=\"1.25\" fill=\"#8a9a2f\"/>\r\n <rect x=\"20\" y=\"44\" width=\"16\" height=\"2.5\" rx=\"1.25\" fill=\"#8a9a2f\"/>\r\n </svg>\r\n <span class=\"file-card-ext\">{{ getFileExtension(file) }}</span>\r\n <span class=\"file-card-name\" [title]=\"file.name\">{{ file.name }}</span>\r\n <span class=\"file-card-size\">{{ formatSize(file.size) }}</span>\r\n </div>\r\n }\r\n </div>\r\n }\r\n</div>", styles: [".upload-container{display:flex;flex-direction:column;gap:16px}.upload-zone{border:2px dashed #8a9a2f;border-radius:8px;padding:48px;text-align:center;cursor:pointer;background-color:#f5f7e8;transition:background .2s}.upload-zone:hover,.dragging .upload-zone{background-color:#eaeecc}.upload-icon{width:56px;height:56px;fill:#8a9a2f;display:block;margin:0 auto 12px}.upload-label{font-size:1.4rem;color:#454733;margin:0 0 6px}.upload-helper{font-size:1.2rem;color:#8a9a2f}.files-row{display:flex;flex-direction:row;gap:12px;overflow-x:auto;padding:4px 2px 8px;scrollbar-width:thin;scrollbar-color:#8a9a2f #f0f0e0}.files-row::-webkit-scrollbar{height:6px}.files-row::-webkit-scrollbar-track{background:#f0f0e0;border-radius:3px}.files-row::-webkit-scrollbar-thumb{background:#8a9a2f;border-radius:3px}.file-card{position:relative;flex-shrink:0;width:132px;height:140px;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;gap:4px;padding:10px 10px 12px;border:1px solid #c5c9a0;border-radius:10px;background-color:#f5f7e8;transition:border-color .2s,background .2s;overflow:hidden}.file-card:hover{border-color:#8a9a2f;background-color:#eaeecc}.file-card-icon{width:52px;height:52px;flex-shrink:0;margin-bottom:2px}.file-card-ext{font-size:1rem;font-weight:700;color:#8a9a2f;letter-spacing:.04em;line-height:1}.file-card-name{width:100%;font-size:1.1rem;color:#454733;text-align:center;overflow:hidden;display:-webkit-box;line-clamp:2;-webkit-box-orient:vertical;line-height:1.3;word-break:break-all}.file-card-size{font-size:1rem;color:#8a9a6e;line-height:1}.file-card-remove{position:absolute;top:6px;right:6px;width:22px;height:22px;display:flex;align-items:center;justify-content:center;background:#ffffffd9;border:1px solid #c5c9a0;border-radius:50%;cursor:pointer;color:#787861;padding:0;transition:background .15s,color .15s,border-color .15s;line-height:1}.file-card-remove:hover{background:#c33;border-color:#c33;color:#fff}.file-card-remove svg{width:12px;height:12px}\n"] });
5959
+ }
5960
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DocumentUpload, decorators: [{
5961
+ type: Component,
5962
+ args: [{ selector: 'lib-document-upload', standalone: true, imports: [], template: "<div class=\"upload-container\" (dragover)=\"onDragOver($event)\" (dragleave)=\"onDragLeave()\" (drop)=\"onDrop($event)\"\r\n [class.dragging]=\"isDragging()\">\r\n\r\n <input type=\"file\" #fileInput [accept]=\"accept()\" [multiple]=\"multiple()\" (change)=\"onFileSelect($event)\" hidden />\r\n\r\n <div class=\"upload-zone\" (click)=\"fileInput.click()\">\r\n <svg class=\"upload-icon\" viewBox=\"0 0 486.3 486.3\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <g>\r\n <path d=\"M395.5,135.8c-5.2-30.9-20.5-59.1-43.9-80.5c-26-23.8-59.8-36.9-95-36.9c-27.2,0-53.7,7.8-76.4,22.5 c-18.9,12.2-34.6,28.7-45.7,48.1c-4.8-0.9-9.8-1.4-14.8-1.4c-42.5,0-77.1,34.6-77.1,77.1c0,5.5,0.6,10.8,1.6,16 C16.7,200.7,0,232.9,0,267.2c0,27.7,10.3,54.6,29.1,75.9c19.3,21.8,44.8,34.7,72,36.2c0.3,0,0.5,0,0.8,0h86 c7.5,0,13.5-6,13.5-13.5s-6-13.5-13.5-13.5h-85.6C61.4,349.8,27,310.9,27,267.1c0-28.3,15.2-54.7,39.7-69 c5.7-3.3,8.1-10.2,5.9-16.4c-2-5.4-3-11.1-3-17.2c0-27.6,22.5-50.1,50.1-50.1c5.9,0,11.7,1,17.1,3c6.6,2.4,13.9-0.6,16.9-6.9 c18.7-39.7,59.1-65.3,103-65.3c59,0,107.7,44.2,113.3,102.8c0.6,6.1,5.2,11,11.2,12c44.5,7.6,78.1,48.7,78.1,95.6 c0,49.7-39.1,92.9-87.3,96.6h-73.7c-7.5,0-13.5,6-13.5,13.5s6,13.5,13.5,13.5h74.2c0.3,0,0.6,0,1,0c30.5-2.2,59-16.2,80.2-39.6 c21.1-23.2,32.6-53,32.6-84C486.2,199.5,447.9,149.6,395.5,135.8z\"/>\r\n <path d=\"M324.2,280c5.3-5.3,5.3-13.8,0-19.1l-71.5-71.5c-2.5-2.5-6-4-9.5-4s-7,1.4-9.5,4l-71.5,71.5c-5.3,5.3-5.3,13.8,0,19.1 c2.6,2.6,6.1,4,9.5,4s6.9-1.3,9.5-4l48.5-48.5v222.9c0,7.5,6,13.5,13.5,13.5s13.5-6,13.5-13.5V231.5l48.5,48.5 C310.4,285.3,318.9,285.3,324.2,280z\"/>\r\n </g>\r\n </svg>\r\n <p class=\"upload-label\"><strong>{{ label() }}</strong></p>\r\n <small class=\"upload-helper\">{{ helperText() }}</small>\r\n </div>\r\n\r\n @if (files().length > 0) {\r\n <div class=\"files-row\">\r\n @for (file of files(); track file.name) {\r\n <div class=\"file-card\">\r\n <button type=\"button\" class=\"file-card-remove\" (click)=\"removeFile(file)\" title=\"Eliminar archivo\">\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>\r\n </svg>\r\n </button>\r\n <svg class=\"file-card-icon\" viewBox=\"0 0 64 64\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M12 4 L12 60 L52 60 L52 20 L36 4 Z\" fill=\"#e3e3d1\" stroke=\"#8a9a2f\" stroke-width=\"2.5\" stroke-linejoin=\"round\"/>\r\n <path d=\"M36 4 L36 20 L52 20\" fill=\"none\" stroke=\"#8a9a2f\" stroke-width=\"2.5\" stroke-linejoin=\"round\"/>\r\n <rect x=\"20\" y=\"30\" width=\"24\" height=\"2.5\" rx=\"1.25\" fill=\"#8a9a2f\"/>\r\n <rect x=\"20\" y=\"37\" width=\"24\" height=\"2.5\" rx=\"1.25\" fill=\"#8a9a2f\"/>\r\n <rect x=\"20\" y=\"44\" width=\"16\" height=\"2.5\" rx=\"1.25\" fill=\"#8a9a2f\"/>\r\n </svg>\r\n <span class=\"file-card-ext\">{{ getFileExtension(file) }}</span>\r\n <span class=\"file-card-name\" [title]=\"file.name\">{{ file.name }}</span>\r\n <span class=\"file-card-size\">{{ formatSize(file.size) }}</span>\r\n </div>\r\n }\r\n </div>\r\n }\r\n</div>", styles: [".upload-container{display:flex;flex-direction:column;gap:16px}.upload-zone{border:2px dashed #8a9a2f;border-radius:8px;padding:48px;text-align:center;cursor:pointer;background-color:#f5f7e8;transition:background .2s}.upload-zone:hover,.dragging .upload-zone{background-color:#eaeecc}.upload-icon{width:56px;height:56px;fill:#8a9a2f;display:block;margin:0 auto 12px}.upload-label{font-size:1.4rem;color:#454733;margin:0 0 6px}.upload-helper{font-size:1.2rem;color:#8a9a2f}.files-row{display:flex;flex-direction:row;gap:12px;overflow-x:auto;padding:4px 2px 8px;scrollbar-width:thin;scrollbar-color:#8a9a2f #f0f0e0}.files-row::-webkit-scrollbar{height:6px}.files-row::-webkit-scrollbar-track{background:#f0f0e0;border-radius:3px}.files-row::-webkit-scrollbar-thumb{background:#8a9a2f;border-radius:3px}.file-card{position:relative;flex-shrink:0;width:132px;height:140px;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;gap:4px;padding:10px 10px 12px;border:1px solid #c5c9a0;border-radius:10px;background-color:#f5f7e8;transition:border-color .2s,background .2s;overflow:hidden}.file-card:hover{border-color:#8a9a2f;background-color:#eaeecc}.file-card-icon{width:52px;height:52px;flex-shrink:0;margin-bottom:2px}.file-card-ext{font-size:1rem;font-weight:700;color:#8a9a2f;letter-spacing:.04em;line-height:1}.file-card-name{width:100%;font-size:1.1rem;color:#454733;text-align:center;overflow:hidden;display:-webkit-box;line-clamp:2;-webkit-box-orient:vertical;line-height:1.3;word-break:break-all}.file-card-size{font-size:1rem;color:#8a9a6e;line-height:1}.file-card-remove{position:absolute;top:6px;right:6px;width:22px;height:22px;display:flex;align-items:center;justify-content:center;background:#ffffffd9;border:1px solid #c5c9a0;border-radius:50%;cursor:pointer;color:#787861;padding:0;transition:background .15s,color .15s,border-color .15s;line-height:1}.file-card-remove:hover{background:#c33;border-color:#c33;color:#fff}.file-card-remove svg{width:12px;height:12px}\n"] }]
5963
+ }], propDecorators: { filesChanged: [{ type: i0.Output, args: ["filesChanged"] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], helperText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helperText", required: false }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], maxSizeMB: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSizeMB", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }] } });
5762
5964
 
5763
5965
  // src/app/components/public-api.ts
5764
5966
  // Exportar los componentes
@@ -5767,5 +5969,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
5767
5969
  * Generated bundle index. Do not edit.
5768
5970
  */
5769
5971
 
5770
- export { BarChart, BaseChart, Button, ButtonCards, CARD_BG, CardContent, Colors, DateTimeFilter, DateTimePicker, DevicesCarousel, DialogAlertComponent, DialogConfirmation, DonutChart, DynamicFormFields, FeatureCard, Footer, GeoAPIMaps, Heatmap, InfoGroup, Input, InputNumberFilter, InputSelectFilter, InputTextFilter, InputTimeFilter, KpiCard, LineChart, LoadImage, Loader, MapGeo, ModalForm, NotFoundModal, NotFoundSection, NotificationModal, OptionCard, PaginationComponent, PdfViewer, PdfViewerService, ProcessingOverlay, ProgressBar, ProgressFormService, QuickAccessCards, SelectCustomSearch, SideCard, SideCardDetail, TOAST_EVENTS, Table, TableChart, Tabs, TitleFilters, Toast, ToastHelper, ToastService, ToggleCustom, UI_CHART_TOKENS, WizardForm };
5972
+ export { BarChart, BaseChart, Button, ButtonCards, CARD_BG, CardContent, Colors, DateTimeFilter, DateTimePicker, DevicesCarousel, DialogAlertComponent, DialogConfirmation, DocumentUpload, DonutChart, DynamicFormFields, FeatureCard, Footer, GeoAPIMaps, Heatmap, InfoGroup, Input, InputNumberFilter, InputSelectFilter, InputTextFilter, InputTimeFilter, KpiCard, LineChart, LoadImage, Loader, MapGeo, ModalForm, NotFoundModal, NotFoundSection, NotificationModal, OptionCard, PaginationComponent, PdfViewer, PdfViewerService, ProcessingOverlay, ProgressBar, ProgressFormService, QuickAccessCards, SelectCustomSearch, SideCard, SideCardDetail, TOAST_EVENTS, Table, TableChart, Tabs, TitleFilters, Toast, ToastHelper, ToastService, ToggleCustom, UI_CHART_TOKENS, WizardForm };
5771
5973
  //# sourceMappingURL=sapenlinea-components.mjs.map