@c80/ui 1.1.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/lib/action-list/action-list.component.js +5 -5
- package/esm2022/lib/action-list/action-list.component.js.map +1 -1
- package/esm2022/lib/action-list/action-list.types.js +0 -1
- package/esm2022/lib/card-level/card-level.component.js +12 -12
- package/esm2022/lib/card-level/card-level.component.js.map +1 -1
- package/esm2022/lib/card-level/card-level.interface.js +0 -1
- package/esm2022/lib/error-notification/error-notification.component.js +5 -5
- package/esm2022/lib/error-notification/error-notification.component.js.map +1 -1
- package/esm2022/lib/error-notification/error-notification.types.js +0 -1
- package/esm2022/lib/header/header.component.js +5 -5
- package/esm2022/lib/header/header.component.js.map +1 -1
- package/esm2022/lib/header/header.types.js +0 -1
- package/esm2022/lib/icon/icon.component.js +26 -26
- package/esm2022/lib/icon/icon.component.js.map +1 -1
- package/esm2022/lib/icon/icon.definitions.js.map +1 -1
- package/esm2022/lib/icon/icon.types.js +0 -1
- package/esm2022/lib/icon/theme.service.js +4 -4
- package/esm2022/lib/icon/theme.service.js.map +1 -1
- package/esm2022/lib/info-list/info-list.component.js +4 -4
- package/esm2022/lib/info-list/info-list.component.js.map +1 -1
- package/esm2022/lib/info-list/info-list.types.js +0 -1
- package/esm2022/lib/info-message/info-message.component.js +6 -6
- package/esm2022/lib/info-message/info-message.component.js.map +1 -1
- package/esm2022/lib/info-message/info-message.types.js +0 -1
- package/esm2022/lib/input-field/input-field.component.js +11 -11
- package/esm2022/lib/input-field/input-field.component.js.map +1 -1
- package/esm2022/lib/input-search/c80-input-search.component.js +5 -5
- package/esm2022/lib/input-search/c80-input-search.component.js.map +1 -1
- package/esm2022/lib/legal-disclaimer/legal-disclaimer.component.js +4 -4
- package/esm2022/lib/legal-disclaimer/legal-disclaimer.component.js.map +1 -1
- package/esm2022/lib/modal/modal.component.js +4 -4
- package/esm2022/lib/modal/modal.component.js.map +1 -1
- package/esm2022/lib/modal/modal.service.js +5 -5
- package/esm2022/lib/modal/modal.service.js.map +1 -1
- package/esm2022/lib/modal/modal.types.js +0 -1
- package/esm2022/lib/navigation-card/navigation-card.component.js +5 -5
- package/esm2022/lib/navigation-card/navigation-card.component.js.map +1 -1
- package/esm2022/lib/navigation-card/navigation-card.types.js +0 -1
- package/esm2022/lib/profile-stats/profile-stats.component.js +4 -4
- package/esm2022/lib/profile-stats/profile-stats.component.js.map +1 -1
- package/esm2022/lib/profile-stats/profile-stats.types.js +0 -1
- package/esm2022/lib/rating-display/rating-display.component.js +7 -7
- package/esm2022/lib/rating-display/rating-display.component.js.map +1 -1
- package/esm2022/lib/rating-stars/rating-stars.component.js +8 -8
- package/esm2022/lib/rating-stars/rating-stars.component.js.map +1 -1
- package/esm2022/lib/select/select.component.js +17 -17
- package/esm2022/lib/select/select.component.js.map +1 -1
- package/esm2022/lib/select/select.types.js +0 -1
- package/esm2022/lib/snackbar/snackbar.component.js +6 -6
- package/esm2022/lib/snackbar/snackbar.component.js.map +1 -1
- package/esm2022/lib/snackbar/snackbar.service.js +3 -3
- package/esm2022/lib/snackbar/snackbar.types.js +0 -1
- package/esm2022/lib/spinner/spinner.component.js +7 -7
- package/esm2022/lib/spinner/spinner.component.js.map +1 -1
- package/esm2022/lib/stat-card/stat-card.component.js +5 -5
- package/esm2022/lib/stat-card/stat-card.component.js.map +1 -1
- package/esm2022/lib/stat-card/stat-card.types.js +0 -1
- package/esm2022/lib/tab/c80-tab.component.js +6 -6
- package/esm2022/lib/tab/c80-tab.component.js.map +1 -1
- package/esm2022/lib/tab/c80-tab.types.js +0 -1
- package/esm2022/lib/tab/directives/c80-tab-item.directive.js +3 -3
- package/esm2022/lib/tab/directives/c80-tab-label.directive.js +3 -3
- package/esm2022/lib/table/table-column-visibility.service.js +3 -3
- package/esm2022/lib/table/table-crud-state.service.js +7 -7
- package/esm2022/lib/table/table-crud-state.service.js.map +1 -1
- package/esm2022/lib/table/table-data-converter.service.js +3 -3
- package/esm2022/lib/table/table-data-utils.service.js +3 -3
- package/esm2022/lib/table/table-dto-mapper.service.js +3 -3
- package/esm2022/lib/table/table-pagination.service.js +10 -10
- package/esm2022/lib/table/table-pagination.service.js.map +1 -1
- package/esm2022/lib/table/table-selection.service.js +6 -6
- package/esm2022/lib/table/table-selection.service.js.map +1 -1
- package/esm2022/lib/table/table.component.js +26 -26
- package/esm2022/lib/table/table.component.js.map +1 -1
- package/esm2022/lib/table/table.types.js +0 -1
- package/package.json +4 -3
|
@@ -143,29 +143,29 @@ import * as i0 from "@angular/core";
|
|
|
143
143
|
paginationService = inject(TablePaginationService);
|
|
144
144
|
// Inputs
|
|
145
145
|
/* v8 ignore next */
|
|
146
|
-
data$ = input.required(...(ngDevMode ? [{ debugName: "data$" }] : []));
|
|
146
|
+
data$ = input.required(...(ngDevMode ? [{ debugName: "data$" }] : /* istanbul ignore next */ []));
|
|
147
147
|
/* v8 ignore next */
|
|
148
|
-
columns = input([], ...(ngDevMode ? [{ debugName: "columns" }] : []));
|
|
148
|
+
columns = input([], ...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
|
|
149
149
|
/* v8 ignore next */
|
|
150
|
-
inputValues$ = input(...(ngDevMode ? [undefined, { debugName: "inputValues$" }] : [])); // Observable para actualizar valores de inputs dinámicamente en creación/edición
|
|
150
|
+
inputValues$ = input(...(ngDevMode ? [undefined, { debugName: "inputValues$" }] : /* istanbul ignore next */ [])); // Observable para actualizar valores de inputs dinámicamente en creación/edición
|
|
151
151
|
/* v8 ignore next */
|
|
152
|
-
customActions = input([], ...(ngDevMode ? [{ debugName: "customActions" }] : [])); // Acciones personalizadas dinámicas
|
|
152
|
+
customActions = input([], ...(ngDevMode ? [{ debugName: "customActions" }] : /* istanbul ignore next */ [])); // Acciones personalizadas dinámicas
|
|
153
153
|
/* v8 ignore next */
|
|
154
|
-
size = input(0, ...(ngDevMode ? [{ debugName: "size" }] : [])); // Tamaño de la tabla (0 = sin límite, > 0 aplica max-height)
|
|
154
|
+
size = input(0, ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ [])); // Tamaño de la tabla (0 = sin límite, > 0 aplica max-height)
|
|
155
155
|
/* v8 ignore next */
|
|
156
|
-
multiple = input(true, ...(ngDevMode ? [{ debugName: "multiple" }] : [])); // Permite selección múltiple por defecto
|
|
156
|
+
multiple = input(true, ...(ngDevMode ? [{ debugName: "multiple" }] : /* istanbul ignore next */ [])); // Permite selección múltiple por defecto
|
|
157
157
|
/* v8 ignore next */
|
|
158
|
-
rowId = input('id', ...(ngDevMode ? [{ debugName: "rowId" }] : [])); // Accessor de la PK de cada fila (default 'id'); usar si la entidad no usa 'id'
|
|
158
|
+
rowId = input('id', ...(ngDevMode ? [{ debugName: "rowId" }] : /* istanbul ignore next */ [])); // Accessor de la PK de cada fila (default 'id'); usar si la entidad no usa 'id'
|
|
159
159
|
/* v8 ignore next */
|
|
160
|
-
searchable = input(false, ...(ngDevMode ?
|
|
160
|
+
searchable = input(false, { ...(ngDevMode ? { debugName: "searchable" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); // Si es true, muestra barra de búsqueda
|
|
161
161
|
/* v8 ignore next */
|
|
162
|
-
allowSelection = input(false, ...(ngDevMode ?
|
|
162
|
+
allowSelection = input(false, { ...(ngDevMode ? { debugName: "allowSelection" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); // Si es true, permite selección de filas
|
|
163
163
|
/* v8 ignore next */
|
|
164
|
-
noConfirm = input(false, ...(ngDevMode ?
|
|
164
|
+
noConfirm = input(false, { ...(ngDevMode ? { debugName: "noConfirm" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); // Si es true, no muestra confirmaciones modales
|
|
165
165
|
/* v8 ignore next */
|
|
166
|
-
paginated = input(false, ...(ngDevMode ?
|
|
166
|
+
paginated = input(false, { ...(ngDevMode ? { debugName: "paginated" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); // Si es true, habilita paginación con limit/offset
|
|
167
167
|
/* v8 ignore next */
|
|
168
|
-
paginationConfig = input({ pageSize: 10 }, ...(ngDevMode ? [{ debugName: "paginationConfig" }] : [])); // Configuración de paginación (tamaño de página, total items)
|
|
168
|
+
paginationConfig = input({ pageSize: 10 }, ...(ngDevMode ? [{ debugName: "paginationConfig" }] : /* istanbul ignore next */ [])); // Configuración de paginación (tamaño de página, total items)
|
|
169
169
|
// Outputs - Acciones unificadas (Angular 18+ output API)
|
|
170
170
|
/* v8 ignore next */
|
|
171
171
|
actionClick = output(); // Output unificado para TODAS las acciones (CRUD + custom)
|
|
@@ -177,8 +177,8 @@ import * as i0 from "@angular/core";
|
|
|
177
177
|
paginationChange = output(); // Output para cambios de paginación (page, limit, offset)
|
|
178
178
|
// Estado principal
|
|
179
179
|
/* v8 ignore next 2 */
|
|
180
|
-
data = signal([], ...(ngDevMode ? [{ debugName: "data" }] : []));
|
|
181
|
-
searchValue = signal('', ...(ngDevMode ? [{ debugName: "searchValue" }] : []));
|
|
180
|
+
data = signal([], ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
|
|
181
|
+
searchValue = signal('', ...(ngDevMode ? [{ debugName: "searchValue" }] : /* istanbul ignore next */ []));
|
|
182
182
|
// Estado de selección (delegado a servicio)
|
|
183
183
|
/* v8 ignore next 4 */
|
|
184
184
|
selectionState = this.selectionService.createSelectionState((item) => item[this.rowId()]);
|
|
@@ -202,24 +202,24 @@ import * as i0 from "@angular/core";
|
|
|
202
202
|
hasPrevPage = this.paginationState.hasPrevPage;
|
|
203
203
|
// Keys visibles computed automáticamente
|
|
204
204
|
/* v8 ignore next 7 */
|
|
205
|
-
keys = computed(() => this.visibilityService.updateVisibleKeys(this.columns(), { data: this.data(), creating: this.creating(), editing: this.editing() }), ...(ngDevMode ? [{ debugName: "keys" }] : []));
|
|
205
|
+
keys = computed(() => this.visibilityService.updateVisibleKeys(this.columns(), { data: this.data(), creating: this.creating(), editing: this.editing() }), ...(ngDevMode ? [{ debugName: "keys" }] : /* istanbul ignore next */ []));
|
|
206
206
|
// Computed - Detecta acciones CRUD y custom
|
|
207
207
|
/* v8 ignore next 5 */
|
|
208
|
-
hasAnyActions = computed(() => this.customActions().length > 0, ...(ngDevMode ? [{ debugName: "hasAnyActions" }] : []));
|
|
209
|
-
hasCrudCreate = computed(() => this.customActions().some(a => a.name === 'create'), ...(ngDevMode ? [{ debugName: "hasCrudCreate" }] : []));
|
|
210
|
-
hasCrudUpdate = computed(() => this.customActions().some(a => a.name === 'update'), ...(ngDevMode ? [{ debugName: "hasCrudUpdate" }] : []));
|
|
211
|
-
hasCrudDelete = computed(() => this.customActions().some(a => a.name === 'delete'), ...(ngDevMode ? [{ debugName: "hasCrudDelete" }] : []));
|
|
212
|
-
hasCrudCancel = computed(() => this.customActions().some(a => a.name === 'cancel'), ...(ngDevMode ? [{ debugName: "hasCrudCancel" }] : []));
|
|
208
|
+
hasAnyActions = computed(() => this.customActions().length > 0, ...(ngDevMode ? [{ debugName: "hasAnyActions" }] : /* istanbul ignore next */ []));
|
|
209
|
+
hasCrudCreate = computed(() => this.customActions().some(a => a.name === 'create'), ...(ngDevMode ? [{ debugName: "hasCrudCreate" }] : /* istanbul ignore next */ []));
|
|
210
|
+
hasCrudUpdate = computed(() => this.customActions().some(a => a.name === 'update'), ...(ngDevMode ? [{ debugName: "hasCrudUpdate" }] : /* istanbul ignore next */ []));
|
|
211
|
+
hasCrudDelete = computed(() => this.customActions().some(a => a.name === 'delete'), ...(ngDevMode ? [{ debugName: "hasCrudDelete" }] : /* istanbul ignore next */ []));
|
|
212
|
+
hasCrudCancel = computed(() => this.customActions().some(a => a.name === 'cancel'), ...(ngDevMode ? [{ debugName: "hasCrudCancel" }] : /* istanbul ignore next */ []));
|
|
213
213
|
/* v8 ignore next 5 */
|
|
214
214
|
shouldShowCreateButton = computed(() => {
|
|
215
215
|
const createAction = this.customActions().find(a => a.name === 'create');
|
|
216
216
|
if (!createAction)
|
|
217
217
|
return false;
|
|
218
218
|
return !createAction.condition || createAction.condition({}, this.data());
|
|
219
|
-
}, ...(ngDevMode ? [{ debugName: "shouldShowCreateButton" }] : []));
|
|
219
|
+
}, ...(ngDevMode ? [{ debugName: "shouldShowCreateButton" }] : /* istanbul ignore next */ []));
|
|
220
220
|
// Table max height computed
|
|
221
221
|
/* v8 ignore next 3 */
|
|
222
|
-
tableMaxHeight = computed(() => this.dataUtils.getTableMaxHeight(this.size()), ...(ngDevMode ? [{ debugName: "tableMaxHeight" }] : []));
|
|
222
|
+
tableMaxHeight = computed(() => this.dataUtils.getTableMaxHeight(this.size()), ...(ngDevMode ? [{ debugName: "tableMaxHeight" }] : /* istanbul ignore next */ []));
|
|
223
223
|
/* v8 ignore next 2 */
|
|
224
224
|
dataSub;
|
|
225
225
|
inputValuesSub;
|
|
@@ -556,11 +556,11 @@ import * as i0 from "@angular/core";
|
|
|
556
556
|
// Para acciones sin color explícito, usar el color de dark mode
|
|
557
557
|
return '#e9ecef';
|
|
558
558
|
}
|
|
559
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
560
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.10", type: TableComponent, isStandalone: true, selector: "c80-table", inputs: { data$: { classPropertyName: "data$", publicName: "data$", isSignal: true, isRequired: true, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, inputValues$: { classPropertyName: "inputValues$", publicName: "inputValues$", isSignal: true, isRequired: false, transformFunction: null }, customActions: { classPropertyName: "customActions", publicName: "customActions", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, rowId: { classPropertyName: "rowId", publicName: "rowId", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, allowSelection: { classPropertyName: "allowSelection", publicName: "allowSelection", isSignal: true, isRequired: false, transformFunction: null }, noConfirm: { classPropertyName: "noConfirm", publicName: "noConfirm", isSignal: true, isRequired: false, transformFunction: null }, paginated: { classPropertyName: "paginated", publicName: "paginated", isSignal: true, isRequired: false, transformFunction: null }, paginationConfig: { classPropertyName: "paginationConfig", publicName: "paginationConfig", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { actionClick: "actionClick", searchTerm: "searchTerm", errorEvent: "errorEvent", selectable: "selectable", paginationChange: "paginationChange" }, ngImport: i0, template: "<!-- eslint-disable-next-line @angular-eslint/template/no-inline-styles -->\n<div class=\"table-responsive\" [style.max-height]=\"tableMaxHeight()\" [style.overflow-y]=\"size() > 0 ? 'auto' : 'visible'\">\n <!-- Search Bar -->\n @if (searchable()) {\n <div class=\"search-container\">\n <div class=\"search-input-wrapper\">\n <div class=\"input-group\">\n <span class=\"input-group-text\">\n <c80-icon icon=\"search\" [size]=\".65\" [button]=\"false\" />\n </span>\n <input type=\"text\" class=\"form-control search-input\" placeholder=\"Buscar...\" [value]=\"searchValue()\" (input)=\"onSearchInput($event)\" aria-label=\"Buscar en la tabla\" />\n @if (searchValue()) {\n <button class=\"btn btn-outline-secondary btn-borrar\" type=\"button\" (click)=\"clearSearch()\" title=\"Limpiar b\u00FAsqueda\">\n <c80-icon icon=\"cancel\" [size]=\".6\" />\n </button>\n }\n </div>\n </div>\n </div>\n }\n\n <table class=\"table table-bordered table-hover align-middle\">\n <thead class=\"thead table-light sticky-header\">\n <tr>\n @if (allowSelection() && data().length !== 0) {\n <th class=\"text-center selection-column\">\n @if (multiple()) {\n <input type=\"checkbox\" [checked]=\"selectAllChecked()\" [indeterminate]=\"selectAllIndeterminate()\" (change)=\"toggleSelectAll()\" aria-label=\"Seleccionar todo\" />\n }\n </th>\n }\n @for (col of columns(); track col) {\n @if (isColumnVisibleInHeader(col)) {\n @if (col.type === 'boolean') {\n <th class=\"text-center boolean-column\">{{ col.label }}</th>\n }\n @else if (col.type === 'number' || col.type === 'integer') {\n <th class=\"text-center number-column\">{{ col.label }}</th>\n }\n @else if (col.type === 'date') {\n <th class=\"text-center date-column\">{{ col.label }}</th>\n }\n @else {\n <th>{{ col.label }}</th>\n }\n }\n }\n @if (hasAnyActions()) {\n <th class=\"table-actions-header\">\n <div class=\"actions-wrapper\">\n <span>Actions</span>\n @if (shouldShowCreateButton()) {\n <c80-icon button icon=\"add\" [disabled]=\"creating()\" title=\"Agregar\" [size]=\".6\" (iconClick)=\"startCreate()\" />\n }\n </div>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of data(); track trackById(i, row); let i = $index) {\n <tr>\n @if (allowSelection() && data().length !== 0) {\n <td class=\"text-center selection-column\">\n <input type=\"checkbox\" [checked]=\"isItemSelected(row)\" (change)=\"toggleItemSelection(row)\" [attr.aria-label]=\"'Seleccionar fila ' + (i + 1)\" />\n </td>\n }\n @for (col of columns(); track col) {\n @if (isColumnVisibleForRow(col, row)) {\n @if (col.type === 'boolean') {\n <td class=\"text-center boolean-column\">\n @if (editing() === row['id'] && !col.readOnly) {\n <input type=\"checkbox\" [checked]=\"!!editRow()?.[col.accessor]\" (change)=\"onEditInput($event, col.accessor, col)\" [attr.aria-label]=\"col.label\" />\n }\n @else {\n @if (getCellValue(row, col.accessor) === true) {\n <c80-icon icon=\"check\" [size]=\".7\" />\n <br />\n }\n @else if (getCellValue(row, col.accessor) === false) {\n <c80-icon icon=\"cancel\" [size]=\".7\" />\n <br />\n }\n }\n </td>\n }\n @else if (col.type === 'number' || col.type === 'integer') {\n <td class=\"text-center number-column\">\n @if (editing() === row['id'] && !col.readOnly) {\n <input class=\"form-control form-control-sm\" type=\"number\" [value]=\"editRow()?.[col.accessor] ?? ''\" [placeholder]=\"col.label\" [min]=\"col.min\" [max]=\"col.max\" [step]=\"col.type === 'integer' ? '1' : 'any'\"\n (input)=\"onEditInput($event, col.accessor, col)\" />\n }\n @else {\n <!-- eslint-disable-next-line @angular-eslint/template/no-inline-styles -->\n <span [style.color]=\"getCellColor(getCellValue(row, col.accessor), col)\">{{ getDisplayValue(getCellValue(row,\n col.accessor), col) }}</span>\n }\n </td>\n }\n @else if (col.type === 'date') {\n <td class=\"text-center date-column\">\n @if (editing() === row['id'] && !col.readOnly) {\n <input class=\"form-control form-control-sm\" type=\"datetime-local\" [value]=\"editRow()?.[col.accessor] ?? ''\" [placeholder]=\"col.label\" (input)=\"onEditInput($event, col.accessor, col)\" />\n }\n @else {\n <!-- eslint-disable-next-line @angular-eslint/template/no-inline-styles -->\n <span [style.color]=\"getCellColor(getCellValue(row, col.accessor), col)\">{{ getDisplayValue(getCellValue(row,\n col.accessor), col) }}</span>\n }\n </td>\n }\n @else {\n <td>\n @if (editing() === row['id'] && !col.readOnly) {\n @if (col.type === 'enum') {\n <select class=\"form-control form-control-sm\" [value]=\"editRow()?.[col.accessor] ?? ''\" (change)=\"onEditInput($event, col.accessor, col)\">\n <option value=\"\">{{ col.label }}</option>\n @for (option of getEnumOptions(col); track option.value) {\n <option [value]=\"option.value\">{{ option.label }}</option>\n }\n </select>\n }\n @else {\n <input class=\"form-control form-control-sm\" [type]=\"col.type === 'password' ? 'password' : 'text'\" [value]=\"editRow()?.[col.accessor] ?? ''\" [placeholder]=\"col.label\" (input)=\"onEditInput($event, col.accessor, col)\" />\n }\n }\n @else {\n @if (col.type === 'password') {\n <!-- eslint-disable-next-line @angular-eslint/template/no-inline-styles -->\n <span [style.color]=\"getCellColor(getCellValue(row, col.accessor), col)\">******</span>\n }\n @else if (col.type === 'enum') {\n <!-- eslint-disable-next-line @angular-eslint/template/no-inline-styles -->\n <span [style.color]=\"getCellColor(getCellValue(row, col.accessor), col)\">{{\n getEnumDisplayValue(getCellValue(row, col.accessor), col)\n }}</span>\n }\n @else if (getCellValue(row, col.accessor) === true) {\n <c80-icon icon=\"check\" [size]=\".7\" />\n }\n @else if (getCellValue(row, col.accessor) === false) {\n <c80-icon icon=\"cancel\" [size]=\".7\" />\n }\n @else {\n <!-- eslint-disable-next-line @angular-eslint/template/no-inline-styles -->\n <span [style.color]=\"getCellColor(getCellValue(row, col.accessor), col)\">{{ getDisplayValue(getCellValue(row,\n col.accessor), col) }}</span>\n }\n }\n </td>\n }\n }\n }\n @if (hasAnyActions()) {\n <td class=\"text-end actions-cell\">\n <div class=\"actions-container\" [class.centered-actions]=\"editing() === row['id']\">\n @if (editing() === row['id']) {\n <!-- Modo edici\u00F3n: mostrar guardar y cancelar -->\n @if (hasCrudUpdate()) {\n <c80-icon button icon=\"check\" title=\"Guardar\" (iconClick)=\"saveEdit(row)\" [size]=\".7\" />\n }\n <c80-icon button icon=\"cancel\" color=\"warn\" title=\"Cancelar\" (iconClick)=\"cancelEdit()\" [size]=\".7\" />\n }\n @else {\n @for (action of customActions(); track action.name) {\n @if (shouldShowAction(action, row, data())) {\n <c80-icon button [icon]=\"action.icon\" [customColor]=\"getActionColor(action)\" [color]=\"action.name === 'delete' ? 'warn' : 'primary'\" [title]=\"getActionTooltip(action)\" (iconClick)=\"onDynamicAction(action, row)\" [size]=\".7\" />\n }\n }\n }\n </div>\n </td>\n }\n </tr>\n }\n @if (creating() && hasCrudCreate()) {\n <tr>\n @if (allowSelection() && data().length !== 0) {\n <td class=\"text-center selection-column\">\n <!-- Empty cell for alignment -->\n </td>\n }\n @for (col of columns(); track col) {\n @if (isColumnVisible(col)) {\n @if (col.type === 'boolean') {\n <td class=\"text-center\">\n @if (!col.readOnly) {\n <input type=\"checkbox\" [checked]=\"!!newRow()?.[col.accessor]\" (change)=\"onInput($event, col.accessor, col)\" [attr.aria-label]=\"col.label\" />\n }\n @else {\n <!-- ReadOnly boolean column in create mode shows empty -->\n <span class=\"text-muted\">-</span>\n }\n </td>\n } @else if (col.type === 'number' || col.type === 'integer') {\n <td class=\"text-center number-column\">\n @if (!col.readOnly) {\n <input class=\"form-control form-control-sm\" type=\"number\" [value]=\"newRow()?.[col.accessor] ?? ''\" [placeholder]=\"col.label\" [min]=\"col.min\" [max]=\"col.max\" [step]=\"col.type === 'integer' ? '1' : 'any'\"\n (input)=\"onInput($event, col.accessor, col)\" />\n }\n @else {\n <!-- ReadOnly number column in create mode shows empty -->\n <span class=\"text-muted\">-</span>\n }\n </td>\n } @else {\n <td>\n @if (!col.readOnly) {\n @if (col.type === 'enum') {\n <select class=\"form-control form-control-sm\" [value]=\"newRow()?.[col.accessor] ?? ''\" (change)=\"onInput($event, col.accessor, col)\">\n <option value=\"\">{{ col.label }}</option>\n @for (option of getEnumOptions(col); track option.value) {\n <option [value]=\"option.value\">{{ option.label }}</option>\n }\n </select>\n }\n @else {\n <input class=\"form-control form-control-sm\" type=\"text\" [value]=\"newRow()?.[col.accessor] ?? ''\" [placeholder]=\"col.label\" (input)=\"onInput($event, col.accessor, col)\" />\n }\n }\n @else {\n <!-- ReadOnly column in create mode shows empty -->\n <span class=\"text-muted\">-</span>\n }\n </td>\n }\n }\n }\n <td class=\"text-end actions-cell\">\n <div class=\"actions-container centered-actions\">\n @if (hasCrudCreate()) {\n <c80-icon button icon=\"check\" title=\"Guardar\" (iconClick)=\"saveCreate()\" [size]=\".7\" />\n }\n <c80-icon button icon=\"cancel\" color=\"warn\" title=\"Cancelar\" (iconClick)=\"cancelCreate()\" [size]=\".7\" />\n </div>\n </td>\n </tr>\n }\n </tbody>\n </table>\n @if (data().length === 0 && !creating()) {\n <div class=\"text-center text-muted py-3 small\">\n No hay datos para mostrar.\n </div>\n }\n\n <!-- Pagination Controls -->\n @if (paginated() && data().length > 0) {\n <div class=\"pagination-container\">\n <div class=\"pagination-info\">\n P\u00E1gina {{ currentPage() }} de {{ totalPages() }}\n </div>\n <div class=\"pagination-controls\">\n <button type=\"button\" class=\"btn btn-sm\" [disabled]=\"!hasPrevPage()\" (click)=\"onPrevPage()\" title=\"P\u00E1gina anterior\">\n <c80-icon icon=\"arrowLeft\" [size]=\".6\" [button]=\"false\" />\n </button>\n <button type=\"button\" class=\"btn btn-sm\" [disabled]=\"!hasNextPage()\" (click)=\"onNextPage()\" title=\"P\u00E1gina siguiente\">\n <c80-icon icon=\"arrowRight\" [size]=\".6\" [button]=\"false\" />\n </button>\n </div>\n </div>\n }\n</div>\n\n<c80-modal />", styles: ["@charset \"UTF-8\";input[type=checkbox]{width:1.3rem!important;height:1.3rem!important;accent-color:var(--color-icon-danger);background:var(--color-bg-primary);margin:0 .25rem;vertical-align:middle;cursor:pointer}.table-responsive{width:100%;overflow-x:auto}.table-responsive .search-container{margin-bottom:-.06rem}.table-responsive .search-container .search-input-wrapper .input-group .btn-borrar{border-bottom-right-radius:0;border-color:var(--color-border-default);height:32px}.table-responsive .search-container .search-input-wrapper .input-group .input-group-text{background-color:var(--color-bg-secondary);border-color:var(--color-border-default);border-bottom-left-radius:0;color:var(--color-text-secondary);width:56.1px;height:32px;padding:.25rem .5rem}.table-responsive .search-container .search-input-wrapper .input-group .input-group-text c80-icon{display:flex;align-items:center;justify-content:center}.table-responsive .search-container .search-input-wrapper .input-group .search-input{border-color:var(--color-border-default);border-bottom-right-radius:0;font-size:.75rem;height:32px;padding:.25rem .5rem;outline:none!important;background-color:var(--color-bg-primary);color:var(--color-text-primary)}.table-responsive .search-container .search-input-wrapper .input-group .search-input:focus{outline:none!important}.table-responsive .search-container .search-input-wrapper .input-group .search-input::placeholder{color:var(--color-text-muted);font-style:italic}.table-responsive .table{min-width:0px;margin-bottom:0;background-color:var(--color-bg-primary);color:var(--color-text-primary);border-color:var(--color-border-default)}.table-responsive .table.table-bordered,.table-responsive .table.table-bordered th,.table-responsive .table.table-bordered td{border-color:var(--color-border-default)}.table-responsive .table.table-hover tbody tr:hover{background-color:var(--color-bg-hover)!important;color:var(--color-text-primary)}.table-responsive .table.table-hover tbody tr:hover td{background-color:var(--color-bg-hover)}.table-responsive .table .sticky-header{position:sticky;top:0;z-index:10;background-color:var(--color-bg-secondary)!important}.table-responsive .table .sticky-header .table-actions-header{display:table-cell;vertical-align:middle;padding:.2rem .6rem!important;background-color:var(--color-bg-secondary)!important}.table-responsive .table .sticky-header .actions-wrapper{display:flex;align-items:center;justify-content:center;gap:.5rem;height:100%}.table-responsive .table .sticky-header th{max-height:31px!important;vertical-align:middle!important;padding:.2rem .6rem!important;font-size:small!important;background-color:var(--color-bg-secondary)!important;border-bottom:2px solid var(--color-border-default);color:var(--color-text-primary)}.table-responsive .table tbody{background-color:var(--color-bg-primary)}.table-responsive .table tbody td{height:35px!important;min-height:35px!important;max-height:35px!important;vertical-align:middle!important;padding:.2rem .8rem!important;font-size:small;color:var(--color-text-primary);background-color:var(--color-bg-primary);border-color:var(--color-border-default)}.table-responsive .table tbody tr{height:35px!important;min-height:35px!important;max-height:35px!important;cursor:pointer;background-color:var(--color-bg-primary)}.table-responsive .table tbody tr:hover{background-color:var(--color-bg-hover)!important}.table-responsive .table tbody tr:hover td{background-color:var(--color-bg-hover)}.table-responsive .table tbody .text-muted{color:var(--color-text-muted)!important}.table-responsive .table tbody input,.table-responsive .table tbody select{border:1px solid var(--color-border-default);height:100%!important;font-size:smaller!important;background-color:var(--color-bg-primary);color:var(--color-text-primary)}.table-responsive .table tbody input:focus,.table-responsive .table tbody select:focus{border-color:var(--color-border-focus);box-shadow:var(--shadow-focus)}.table-responsive .table tbody input::placeholder,.table-responsive .table tbody select::placeholder{color:var(--color-text-muted)}.table-responsive .table tbody input[type=text],.table-responsive .table tbody input:not([type]){width:100%!important}.table-responsive .table tbody input[type=number]{min-width:80px!important;width:80px!important;text-align:center}.table-responsive .table tbody select{width:100%!important;padding:.25rem .5rem}.table-responsive .table thead th.boolean-column,.table-responsive .table tbody td.boolean-column,.table-responsive .table thead th.selection-column,.table-responsive .table tbody td.selection-column,.table-responsive .table thead th.table-actions-header,.table-responsive .table tbody td.table-actions-header{width:1%;white-space:nowrap}.table-responsive .table thead th.number-column,.table-responsive .table tbody td.number-column{width:1%;white-space:nowrap;text-align:center}.table-responsive .table thead th.number-column input[type=number],.table-responsive .table tbody td.number-column input[type=number]{min-width:80px!important;width:80px!important;text-align:center}.table-responsive .table thead th.date-column,.table-responsive .table tbody td.date-column{width:1%;white-space:nowrap;text-align:center}.table-responsive .table thead th.date-column input[type=datetime-local],.table-responsive .table tbody td.date-column input[type=datetime-local]{min-width:200px!important;width:200px!important;text-align:center}.table-responsive .table .actions-cell{white-space:nowrap;padding:0!important}.table-responsive .table .actions-container{display:flex;flex-direction:row;justify-content:flex-end;align-items:center;width:100%;height:100%}.table-responsive .table .actions-container.centered-actions{justify-content:center}.table-responsive .text-center.text-muted{color:var(--color-text-muted)!important}.table-responsive .btn-outline-secondary{background-color:var(--color-bg-primary);color:var(--color-text-primary);border-color:var(--color-border-default)}.table-responsive .btn-outline-secondary:hover{background-color:var(--color-bg-hover);border-color:var(--color-border-medium)}.table-responsive .btn-outline-secondary:focus{box-shadow:var(--shadow-focus)}.table-responsive .pagination-container{display:flex;justify-content:space-between;align-items:center;padding:.2rem .5rem;background-color:var(--color-bg-secondary);border:1px solid var(--color-border-default);border-top:none;border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}.table-responsive .pagination-container .pagination-info{font-size:.875rem;color:var(--color-text-secondary);font-weight:500}.table-responsive .pagination-container .pagination-controls{display:flex;gap:.5rem}.table-responsive .pagination-container .pagination-controls button{min-width:36px;height:32px;padding:.25rem .5rem;display:flex;align-items:center;justify-content:center;background-color:var(--color-bg-primary);color:var(--color-text-primary);border:none}.table-responsive .pagination-container .pagination-controls button:hover:not(:disabled){background-color:var(--color-bg-hover);border:none}.table-responsive .pagination-container .pagination-controls button:disabled{opacity:.5;cursor:auto;background-color:var(--color-bg-primary);border:none}\n"], dependencies: [{ kind: "component", type: IconComponent, selector: "c80-icon", inputs: ["icon", "color", "customColor", "disabled", "size", "button", "border", "type", "textLeft", "textRight", "dark"], outputs: ["iconClick"] }, { kind: "component", type: ModalComponent, selector: "c80-modal" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
559
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: TableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
560
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: TableComponent, isStandalone: true, selector: "c80-table", inputs: { data$: { classPropertyName: "data$", publicName: "data$", isSignal: true, isRequired: true, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, inputValues$: { classPropertyName: "inputValues$", publicName: "inputValues$", isSignal: true, isRequired: false, transformFunction: null }, customActions: { classPropertyName: "customActions", publicName: "customActions", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, rowId: { classPropertyName: "rowId", publicName: "rowId", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, allowSelection: { classPropertyName: "allowSelection", publicName: "allowSelection", isSignal: true, isRequired: false, transformFunction: null }, noConfirm: { classPropertyName: "noConfirm", publicName: "noConfirm", isSignal: true, isRequired: false, transformFunction: null }, paginated: { classPropertyName: "paginated", publicName: "paginated", isSignal: true, isRequired: false, transformFunction: null }, paginationConfig: { classPropertyName: "paginationConfig", publicName: "paginationConfig", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { actionClick: "actionClick", searchTerm: "searchTerm", errorEvent: "errorEvent", selectable: "selectable", paginationChange: "paginationChange" }, ngImport: i0, template: "<div class=\"table-responsive\" [style.max-height]=\"tableMaxHeight()\" [style.overflow-y]=\"size() > 0 ? 'auto' : 'visible'\">\r\n <!-- Search Bar -->\r\n @if (searchable()) {\r\n <div class=\"search-container\">\r\n <div class=\"search-input-wrapper\">\r\n <div class=\"input-group\">\r\n <span class=\"input-group-text\">\r\n <c80-icon icon=\"search\" [size]=\".65\" [button]=\"false\" />\r\n </span>\r\n <input type=\"text\" class=\"form-control search-input\" placeholder=\"Buscar...\" [value]=\"searchValue()\" (input)=\"onSearchInput($event)\" aria-label=\"Buscar en la tabla\" />\r\n @if (searchValue()) {\r\n <button class=\"btn btn-outline-secondary btn-borrar\" type=\"button\" (click)=\"clearSearch()\" title=\"Limpiar b\u00FAsqueda\">\r\n <c80-icon icon=\"cancel\" [size]=\".6\" />\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n <table class=\"table table-bordered table-hover align-middle\">\r\n <thead class=\"thead table-light sticky-header\">\r\n <tr>\r\n @if (allowSelection() && data().length !== 0) {\r\n <th class=\"text-center selection-column\">\r\n @if (multiple()) {\r\n <input type=\"checkbox\" [checked]=\"selectAllChecked()\" [indeterminate]=\"selectAllIndeterminate()\" (change)=\"toggleSelectAll()\" aria-label=\"Seleccionar todo\" />\r\n }\r\n </th>\r\n }\r\n @for (col of columns(); track col) {\r\n @if (isColumnVisibleInHeader(col)) {\r\n @if (col.type === 'boolean') {\r\n <th class=\"text-center boolean-column\">{{ col.label }}</th>\r\n }\r\n @else if (col.type === 'number' || col.type === 'integer') {\r\n <th class=\"text-center number-column\">{{ col.label }}</th>\r\n }\r\n @else if (col.type === 'date') {\r\n <th class=\"text-center date-column\">{{ col.label }}</th>\r\n }\r\n @else {\r\n <th>{{ col.label }}</th>\r\n }\r\n }\r\n }\r\n @if (hasAnyActions()) {\r\n <th class=\"table-actions-header\">\r\n <div class=\"actions-wrapper\">\r\n <span>Actions</span>\r\n @if (shouldShowCreateButton()) {\r\n <c80-icon button icon=\"add\" [disabled]=\"creating()\" title=\"Agregar\" [size]=\".6\" (iconClick)=\"startCreate()\" />\r\n }\r\n </div>\r\n </th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (row of data(); track trackById(i, row); let i = $index) {\r\n <tr>\r\n @if (allowSelection() && data().length !== 0) {\r\n <td class=\"text-center selection-column\">\r\n <input type=\"checkbox\" [checked]=\"isItemSelected(row)\" (change)=\"toggleItemSelection(row)\" [attr.aria-label]=\"'Seleccionar fila ' + (i + 1)\" />\r\n </td>\r\n }\r\n @for (col of columns(); track col) {\r\n @if (isColumnVisibleForRow(col, row)) {\r\n @if (col.type === 'boolean') {\r\n <td class=\"text-center boolean-column\">\r\n @if (editing() === row['id'] && !col.readOnly) {\r\n <input type=\"checkbox\" [checked]=\"!!editRow()?.[col.accessor]\" (change)=\"onEditInput($event, col.accessor, col)\" [attr.aria-label]=\"col.label\" />\r\n }\r\n @else {\r\n @if (getCellValue(row, col.accessor) === true) {\r\n <c80-icon icon=\"check\" [size]=\".7\" />\r\n <br />\r\n }\r\n @else if (getCellValue(row, col.accessor) === false) {\r\n <c80-icon icon=\"cancel\" [size]=\".7\" />\r\n <br />\r\n }\r\n }\r\n </td>\r\n }\r\n @else if (col.type === 'number' || col.type === 'integer') {\r\n <td class=\"text-center number-column\">\r\n @if (editing() === row['id'] && !col.readOnly) {\r\n <input class=\"form-control form-control-sm\" type=\"number\" [value]=\"editRow()?.[col.accessor] ?? ''\" [placeholder]=\"col.label\" [min]=\"col.min\" [max]=\"col.max\" [step]=\"col.type === 'integer' ? '1' : 'any'\"\r\n (input)=\"onEditInput($event, col.accessor, col)\" />\r\n }\r\n @else {\r\n <span [style.color]=\"getCellColor(getCellValue(row, col.accessor), col)\">{{ getDisplayValue(getCellValue(row,\r\n col.accessor), col) }}</span>\r\n }\r\n </td>\r\n }\r\n @else if (col.type === 'date') {\r\n <td class=\"text-center date-column\">\r\n @if (editing() === row['id'] && !col.readOnly) {\r\n <input class=\"form-control form-control-sm\" type=\"datetime-local\" [value]=\"editRow()?.[col.accessor] ?? ''\" [placeholder]=\"col.label\" (input)=\"onEditInput($event, col.accessor, col)\" />\r\n }\r\n @else {\r\n <span [style.color]=\"getCellColor(getCellValue(row, col.accessor), col)\">{{ getDisplayValue(getCellValue(row,\r\n col.accessor), col) }}</span>\r\n }\r\n </td>\r\n }\r\n @else {\r\n <td>\r\n @if (editing() === row['id'] && !col.readOnly) {\r\n @if (col.type === 'enum') {\r\n <select class=\"form-control form-control-sm\" [value]=\"editRow()?.[col.accessor] ?? ''\" (change)=\"onEditInput($event, col.accessor, col)\">\r\n <option value=\"\">{{ col.label }}</option>\r\n @for (option of getEnumOptions(col); track option.value) {\r\n <option [value]=\"option.value\">{{ option.label }}</option>\r\n }\r\n </select>\r\n }\r\n @else {\r\n <input class=\"form-control form-control-sm\" [type]=\"col.type === 'password' ? 'password' : 'text'\" [value]=\"editRow()?.[col.accessor] ?? ''\" [placeholder]=\"col.label\" (input)=\"onEditInput($event, col.accessor, col)\" />\r\n }\r\n }\r\n @else {\r\n @if (col.type === 'password') {\r\n <span [style.color]=\"getCellColor(getCellValue(row, col.accessor), col)\">******</span>\r\n }\r\n @else if (col.type === 'enum') {\r\n <span [style.color]=\"getCellColor(getCellValue(row, col.accessor), col)\">{{\r\n getEnumDisplayValue(getCellValue(row, col.accessor), col)\r\n }}</span>\r\n }\r\n @else if (getCellValue(row, col.accessor) === true) {\r\n <c80-icon icon=\"check\" [size]=\".7\" />\r\n }\r\n @else if (getCellValue(row, col.accessor) === false) {\r\n <c80-icon icon=\"cancel\" [size]=\".7\" />\r\n }\r\n @else {\r\n <span [style.color]=\"getCellColor(getCellValue(row, col.accessor), col)\">{{ getDisplayValue(getCellValue(row,\r\n col.accessor), col) }}</span>\r\n }\r\n }\r\n </td>\r\n }\r\n }\r\n }\r\n @if (hasAnyActions()) {\r\n <td class=\"text-end actions-cell\">\r\n <div class=\"actions-container\" [class.centered-actions]=\"editing() === row['id']\">\r\n @if (editing() === row['id']) {\r\n <!-- Modo edici\u00F3n: mostrar guardar y cancelar -->\r\n @if (hasCrudUpdate()) {\r\n <c80-icon button icon=\"check\" title=\"Guardar\" (iconClick)=\"saveEdit(row)\" [size]=\".7\" />\r\n }\r\n <c80-icon button icon=\"cancel\" color=\"warn\" title=\"Cancelar\" (iconClick)=\"cancelEdit()\" [size]=\".7\" />\r\n }\r\n @else {\r\n @for (action of customActions(); track action.name) {\r\n @if (shouldShowAction(action, row, data())) {\r\n <c80-icon button [icon]=\"action.icon\" [customColor]=\"getActionColor(action)\" [color]=\"action.name === 'delete' ? 'warn' : 'primary'\" [title]=\"getActionTooltip(action)\" (iconClick)=\"onDynamicAction(action, row)\" [size]=\".7\" />\r\n }\r\n }\r\n }\r\n </div>\r\n </td>\r\n }\r\n </tr>\r\n }\r\n @if (creating() && hasCrudCreate()) {\r\n <tr>\r\n @if (allowSelection() && data().length !== 0) {\r\n <td class=\"text-center selection-column\">\r\n <!-- Empty cell for alignment -->\r\n </td>\r\n }\r\n @for (col of columns(); track col) {\r\n @if (isColumnVisible(col)) {\r\n @if (col.type === 'boolean') {\r\n <td class=\"text-center\">\r\n @if (!col.readOnly) {\r\n <input type=\"checkbox\" [checked]=\"!!newRow()?.[col.accessor]\" (change)=\"onInput($event, col.accessor, col)\" [attr.aria-label]=\"col.label\" />\r\n }\r\n @else {\r\n <!-- ReadOnly boolean column in create mode shows empty -->\r\n <span class=\"text-muted\">-</span>\r\n }\r\n </td>\r\n } @else if (col.type === 'number' || col.type === 'integer') {\r\n <td class=\"text-center number-column\">\r\n @if (!col.readOnly) {\r\n <input class=\"form-control form-control-sm\" type=\"number\" [value]=\"newRow()?.[col.accessor] ?? ''\" [placeholder]=\"col.label\" [min]=\"col.min\" [max]=\"col.max\" [step]=\"col.type === 'integer' ? '1' : 'any'\"\r\n (input)=\"onInput($event, col.accessor, col)\" />\r\n }\r\n @else {\r\n <!-- ReadOnly number column in create mode shows empty -->\r\n <span class=\"text-muted\">-</span>\r\n }\r\n </td>\r\n } @else {\r\n <td>\r\n @if (!col.readOnly) {\r\n @if (col.type === 'enum') {\r\n <select class=\"form-control form-control-sm\" [value]=\"newRow()?.[col.accessor] ?? ''\" (change)=\"onInput($event, col.accessor, col)\">\r\n <option value=\"\">{{ col.label }}</option>\r\n @for (option of getEnumOptions(col); track option.value) {\r\n <option [value]=\"option.value\">{{ option.label }}</option>\r\n }\r\n </select>\r\n }\r\n @else {\r\n <input class=\"form-control form-control-sm\" type=\"text\" [value]=\"newRow()?.[col.accessor] ?? ''\" [placeholder]=\"col.label\" (input)=\"onInput($event, col.accessor, col)\" />\r\n }\r\n }\r\n @else {\r\n <!-- ReadOnly column in create mode shows empty -->\r\n <span class=\"text-muted\">-</span>\r\n }\r\n </td>\r\n }\r\n }\r\n }\r\n <td class=\"text-end actions-cell\">\r\n <div class=\"actions-container centered-actions\">\r\n @if (hasCrudCreate()) {\r\n <c80-icon button icon=\"check\" title=\"Guardar\" (iconClick)=\"saveCreate()\" [size]=\".7\" />\r\n }\r\n <c80-icon button icon=\"cancel\" color=\"warn\" title=\"Cancelar\" (iconClick)=\"cancelCreate()\" [size]=\".7\" />\r\n </div>\r\n </td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n @if (data().length === 0 && !creating()) {\r\n <div class=\"text-center text-muted py-3 small\">\r\n No hay datos para mostrar.\r\n </div>\r\n }\r\n\r\n <!-- Pagination Controls -->\r\n @if (paginated() && data().length > 0) {\r\n <div class=\"pagination-container\">\r\n <div class=\"pagination-info\">\r\n P\u00E1gina {{ currentPage() }} de {{ totalPages() }}\r\n </div>\r\n <div class=\"pagination-controls\">\r\n <button type=\"button\" class=\"btn btn-sm\" [disabled]=\"!hasPrevPage()\" (click)=\"onPrevPage()\" title=\"P\u00E1gina anterior\">\r\n <c80-icon icon=\"arrowLeft\" [size]=\".6\" [button]=\"false\" />\r\n </button>\r\n <button type=\"button\" class=\"btn btn-sm\" [disabled]=\"!hasNextPage()\" (click)=\"onNextPage()\" title=\"P\u00E1gina siguiente\">\r\n <c80-icon icon=\"arrowRight\" [size]=\".6\" [button]=\"false\" />\r\n </button>\r\n </div>\r\n </div>\r\n }\r\n</div>\r\n\r\n<c80-modal />", styles: ["@charset \"UTF-8\";input[type=checkbox]{width:1.3rem!important;height:1.3rem!important;accent-color:var(--color-icon-danger);background:var(--color-bg-primary);margin:0 .25rem;vertical-align:middle;cursor:pointer}.table-responsive{width:100%;overflow-x:auto}.table-responsive .search-container{margin-bottom:-.06rem}.table-responsive .search-container .search-input-wrapper .input-group .btn-borrar{border-bottom-right-radius:0;border-color:var(--color-border-default);height:32px}.table-responsive .search-container .search-input-wrapper .input-group .input-group-text{background-color:var(--color-bg-secondary);border-color:var(--color-border-default);border-bottom-left-radius:0;color:var(--color-text-secondary);width:56.1px;height:32px;padding:.25rem .5rem}.table-responsive .search-container .search-input-wrapper .input-group .input-group-text c80-icon{display:flex;align-items:center;justify-content:center}.table-responsive .search-container .search-input-wrapper .input-group .search-input{border-color:var(--color-border-default);border-bottom-right-radius:0;font-size:.75rem;height:32px;padding:.25rem .5rem;outline:none!important;background-color:var(--color-bg-primary);color:var(--color-text-primary)}.table-responsive .search-container .search-input-wrapper .input-group .search-input:focus{outline:none!important}.table-responsive .search-container .search-input-wrapper .input-group .search-input::placeholder{color:var(--color-text-muted);font-style:italic}.table-responsive .table{min-width:0px;margin-bottom:0;background-color:var(--color-bg-primary);color:var(--color-text-primary);border-color:var(--color-border-default)}.table-responsive .table.table-bordered,.table-responsive .table.table-bordered th,.table-responsive .table.table-bordered td{border-color:var(--color-border-default)}.table-responsive .table.table-hover tbody tr:hover{background-color:var(--color-bg-hover)!important;color:var(--color-text-primary)}.table-responsive .table.table-hover tbody tr:hover td{background-color:var(--color-bg-hover)}.table-responsive .table .sticky-header{position:sticky;top:0;z-index:10;background-color:var(--color-bg-secondary)!important}.table-responsive .table .sticky-header .table-actions-header{display:table-cell;vertical-align:middle;padding:.2rem .6rem!important;background-color:var(--color-bg-secondary)!important}.table-responsive .table .sticky-header .actions-wrapper{display:flex;align-items:center;justify-content:center;gap:.5rem;height:100%}.table-responsive .table .sticky-header th{max-height:31px!important;vertical-align:middle!important;padding:.2rem .6rem!important;font-size:small!important;background-color:var(--color-bg-secondary)!important;border-bottom:2px solid var(--color-border-default);color:var(--color-text-primary)}.table-responsive .table tbody{background-color:var(--color-bg-primary)}.table-responsive .table tbody td{height:35px!important;min-height:35px!important;max-height:35px!important;vertical-align:middle!important;padding:.2rem .8rem!important;font-size:small;color:var(--color-text-primary);background-color:var(--color-bg-primary);border-color:var(--color-border-default)}.table-responsive .table tbody tr{height:35px!important;min-height:35px!important;max-height:35px!important;cursor:pointer;background-color:var(--color-bg-primary)}.table-responsive .table tbody tr:hover{background-color:var(--color-bg-hover)!important}.table-responsive .table tbody tr:hover td{background-color:var(--color-bg-hover)}.table-responsive .table tbody .text-muted{color:var(--color-text-muted)!important}.table-responsive .table tbody input,.table-responsive .table tbody select{border:1px solid var(--color-border-default);height:100%!important;font-size:smaller!important;background-color:var(--color-bg-primary);color:var(--color-text-primary)}.table-responsive .table tbody input:focus,.table-responsive .table tbody select:focus{border-color:var(--color-border-focus);box-shadow:var(--shadow-focus)}.table-responsive .table tbody input::placeholder,.table-responsive .table tbody select::placeholder{color:var(--color-text-muted)}.table-responsive .table tbody input[type=text],.table-responsive .table tbody input:not([type]){width:100%!important}.table-responsive .table tbody input[type=number]{min-width:80px!important;width:80px!important;text-align:center}.table-responsive .table tbody select{width:100%!important;padding:.25rem .5rem}.table-responsive .table thead th.boolean-column,.table-responsive .table tbody td.boolean-column,.table-responsive .table thead th.selection-column,.table-responsive .table tbody td.selection-column,.table-responsive .table thead th.table-actions-header,.table-responsive .table tbody td.table-actions-header{width:1%;white-space:nowrap}.table-responsive .table thead th.number-column,.table-responsive .table tbody td.number-column{width:1%;white-space:nowrap;text-align:center}.table-responsive .table thead th.number-column input[type=number],.table-responsive .table tbody td.number-column input[type=number]{min-width:80px!important;width:80px!important;text-align:center}.table-responsive .table thead th.date-column,.table-responsive .table tbody td.date-column{width:1%;white-space:nowrap;text-align:center}.table-responsive .table thead th.date-column input[type=datetime-local],.table-responsive .table tbody td.date-column input[type=datetime-local]{min-width:200px!important;width:200px!important;text-align:center}.table-responsive .table .actions-cell{white-space:nowrap;padding:0!important}.table-responsive .table .actions-container{display:flex;flex-direction:row;justify-content:flex-end;align-items:center;width:100%;height:100%}.table-responsive .table .actions-container.centered-actions{justify-content:center}.table-responsive .text-center.text-muted{color:var(--color-text-muted)!important}.table-responsive .btn-outline-secondary{background-color:var(--color-bg-primary);color:var(--color-text-primary);border-color:var(--color-border-default)}.table-responsive .btn-outline-secondary:hover{background-color:var(--color-bg-hover);border-color:var(--color-border-medium)}.table-responsive .btn-outline-secondary:focus{box-shadow:var(--shadow-focus)}.table-responsive .pagination-container{display:flex;justify-content:space-between;align-items:center;padding:.2rem .5rem;background-color:var(--color-bg-secondary);border:1px solid var(--color-border-default);border-top:none;border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}.table-responsive .pagination-container .pagination-info{font-size:.875rem;color:var(--color-text-secondary);font-weight:500}.table-responsive .pagination-container .pagination-controls{display:flex;gap:.5rem}.table-responsive .pagination-container .pagination-controls button{min-width:36px;height:32px;padding:.25rem .5rem;display:flex;align-items:center;justify-content:center;background-color:var(--color-bg-primary);color:var(--color-text-primary);border:none}.table-responsive .pagination-container .pagination-controls button:hover:not(:disabled){background-color:var(--color-bg-hover);border:none}.table-responsive .pagination-container .pagination-controls button:disabled{opacity:.5;cursor:auto;background-color:var(--color-bg-primary);border:none}\n"], dependencies: [{ kind: "component", type: IconComponent, selector: "c80-icon", inputs: ["icon", "color", "customColor", "disabled", "size", "button", "border", "type", "textLeft", "textRight", "dark"], outputs: ["iconClick"] }, { kind: "component", type: ModalComponent, selector: "c80-modal" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
561
561
|
}
|
|
562
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
562
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: TableComponent, decorators: [{
|
|
563
563
|
type: Component,
|
|
564
|
-
args: [{ selector: 'c80-table', standalone: true, imports: [IconComponent, ModalComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- eslint-disable-next-line @angular-eslint/template/no-inline-styles -->\n<div class=\"table-responsive\" [style.max-height]=\"tableMaxHeight()\" [style.overflow-y]=\"size() > 0 ? 'auto' : 'visible'\">\n <!-- Search Bar -->\n @if (searchable()) {\n <div class=\"search-container\">\n <div class=\"search-input-wrapper\">\n <div class=\"input-group\">\n <span class=\"input-group-text\">\n <c80-icon icon=\"search\" [size]=\".65\" [button]=\"false\" />\n </span>\n <input type=\"text\" class=\"form-control search-input\" placeholder=\"Buscar...\" [value]=\"searchValue()\" (input)=\"onSearchInput($event)\" aria-label=\"Buscar en la tabla\" />\n @if (searchValue()) {\n <button class=\"btn btn-outline-secondary btn-borrar\" type=\"button\" (click)=\"clearSearch()\" title=\"Limpiar b\u00FAsqueda\">\n <c80-icon icon=\"cancel\" [size]=\".6\" />\n </button>\n }\n </div>\n </div>\n </div>\n }\n\n <table class=\"table table-bordered table-hover align-middle\">\n <thead class=\"thead table-light sticky-header\">\n <tr>\n @if (allowSelection() && data().length !== 0) {\n <th class=\"text-center selection-column\">\n @if (multiple()) {\n <input type=\"checkbox\" [checked]=\"selectAllChecked()\" [indeterminate]=\"selectAllIndeterminate()\" (change)=\"toggleSelectAll()\" aria-label=\"Seleccionar todo\" />\n }\n </th>\n }\n @for (col of columns(); track col) {\n @if (isColumnVisibleInHeader(col)) {\n @if (col.type === 'boolean') {\n <th class=\"text-center boolean-column\">{{ col.label }}</th>\n }\n @else if (col.type === 'number' || col.type === 'integer') {\n <th class=\"text-center number-column\">{{ col.label }}</th>\n }\n @else if (col.type === 'date') {\n <th class=\"text-center date-column\">{{ col.label }}</th>\n }\n @else {\n <th>{{ col.label }}</th>\n }\n }\n }\n @if (hasAnyActions()) {\n <th class=\"table-actions-header\">\n <div class=\"actions-wrapper\">\n <span>Actions</span>\n @if (shouldShowCreateButton()) {\n <c80-icon button icon=\"add\" [disabled]=\"creating()\" title=\"Agregar\" [size]=\".6\" (iconClick)=\"startCreate()\" />\n }\n </div>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of data(); track trackById(i, row); let i = $index) {\n <tr>\n @if (allowSelection() && data().length !== 0) {\n <td class=\"text-center selection-column\">\n <input type=\"checkbox\" [checked]=\"isItemSelected(row)\" (change)=\"toggleItemSelection(row)\" [attr.aria-label]=\"'Seleccionar fila ' + (i + 1)\" />\n </td>\n }\n @for (col of columns(); track col) {\n @if (isColumnVisibleForRow(col, row)) {\n @if (col.type === 'boolean') {\n <td class=\"text-center boolean-column\">\n @if (editing() === row['id'] && !col.readOnly) {\n <input type=\"checkbox\" [checked]=\"!!editRow()?.[col.accessor]\" (change)=\"onEditInput($event, col.accessor, col)\" [attr.aria-label]=\"col.label\" />\n }\n @else {\n @if (getCellValue(row, col.accessor) === true) {\n <c80-icon icon=\"check\" [size]=\".7\" />\n <br />\n }\n @else if (getCellValue(row, col.accessor) === false) {\n <c80-icon icon=\"cancel\" [size]=\".7\" />\n <br />\n }\n }\n </td>\n }\n @else if (col.type === 'number' || col.type === 'integer') {\n <td class=\"text-center number-column\">\n @if (editing() === row['id'] && !col.readOnly) {\n <input class=\"form-control form-control-sm\" type=\"number\" [value]=\"editRow()?.[col.accessor] ?? ''\" [placeholder]=\"col.label\" [min]=\"col.min\" [max]=\"col.max\" [step]=\"col.type === 'integer' ? '1' : 'any'\"\n (input)=\"onEditInput($event, col.accessor, col)\" />\n }\n @else {\n <!-- eslint-disable-next-line @angular-eslint/template/no-inline-styles -->\n <span [style.color]=\"getCellColor(getCellValue(row, col.accessor), col)\">{{ getDisplayValue(getCellValue(row,\n col.accessor), col) }}</span>\n }\n </td>\n }\n @else if (col.type === 'date') {\n <td class=\"text-center date-column\">\n @if (editing() === row['id'] && !col.readOnly) {\n <input class=\"form-control form-control-sm\" type=\"datetime-local\" [value]=\"editRow()?.[col.accessor] ?? ''\" [placeholder]=\"col.label\" (input)=\"onEditInput($event, col.accessor, col)\" />\n }\n @else {\n <!-- eslint-disable-next-line @angular-eslint/template/no-inline-styles -->\n <span [style.color]=\"getCellColor(getCellValue(row, col.accessor), col)\">{{ getDisplayValue(getCellValue(row,\n col.accessor), col) }}</span>\n }\n </td>\n }\n @else {\n <td>\n @if (editing() === row['id'] && !col.readOnly) {\n @if (col.type === 'enum') {\n <select class=\"form-control form-control-sm\" [value]=\"editRow()?.[col.accessor] ?? ''\" (change)=\"onEditInput($event, col.accessor, col)\">\n <option value=\"\">{{ col.label }}</option>\n @for (option of getEnumOptions(col); track option.value) {\n <option [value]=\"option.value\">{{ option.label }}</option>\n }\n </select>\n }\n @else {\n <input class=\"form-control form-control-sm\" [type]=\"col.type === 'password' ? 'password' : 'text'\" [value]=\"editRow()?.[col.accessor] ?? ''\" [placeholder]=\"col.label\" (input)=\"onEditInput($event, col.accessor, col)\" />\n }\n }\n @else {\n @if (col.type === 'password') {\n <!-- eslint-disable-next-line @angular-eslint/template/no-inline-styles -->\n <span [style.color]=\"getCellColor(getCellValue(row, col.accessor), col)\">******</span>\n }\n @else if (col.type === 'enum') {\n <!-- eslint-disable-next-line @angular-eslint/template/no-inline-styles -->\n <span [style.color]=\"getCellColor(getCellValue(row, col.accessor), col)\">{{\n getEnumDisplayValue(getCellValue(row, col.accessor), col)\n }}</span>\n }\n @else if (getCellValue(row, col.accessor) === true) {\n <c80-icon icon=\"check\" [size]=\".7\" />\n }\n @else if (getCellValue(row, col.accessor) === false) {\n <c80-icon icon=\"cancel\" [size]=\".7\" />\n }\n @else {\n <!-- eslint-disable-next-line @angular-eslint/template/no-inline-styles -->\n <span [style.color]=\"getCellColor(getCellValue(row, col.accessor), col)\">{{ getDisplayValue(getCellValue(row,\n col.accessor), col) }}</span>\n }\n }\n </td>\n }\n }\n }\n @if (hasAnyActions()) {\n <td class=\"text-end actions-cell\">\n <div class=\"actions-container\" [class.centered-actions]=\"editing() === row['id']\">\n @if (editing() === row['id']) {\n <!-- Modo edici\u00F3n: mostrar guardar y cancelar -->\n @if (hasCrudUpdate()) {\n <c80-icon button icon=\"check\" title=\"Guardar\" (iconClick)=\"saveEdit(row)\" [size]=\".7\" />\n }\n <c80-icon button icon=\"cancel\" color=\"warn\" title=\"Cancelar\" (iconClick)=\"cancelEdit()\" [size]=\".7\" />\n }\n @else {\n @for (action of customActions(); track action.name) {\n @if (shouldShowAction(action, row, data())) {\n <c80-icon button [icon]=\"action.icon\" [customColor]=\"getActionColor(action)\" [color]=\"action.name === 'delete' ? 'warn' : 'primary'\" [title]=\"getActionTooltip(action)\" (iconClick)=\"onDynamicAction(action, row)\" [size]=\".7\" />\n }\n }\n }\n </div>\n </td>\n }\n </tr>\n }\n @if (creating() && hasCrudCreate()) {\n <tr>\n @if (allowSelection() && data().length !== 0) {\n <td class=\"text-center selection-column\">\n <!-- Empty cell for alignment -->\n </td>\n }\n @for (col of columns(); track col) {\n @if (isColumnVisible(col)) {\n @if (col.type === 'boolean') {\n <td class=\"text-center\">\n @if (!col.readOnly) {\n <input type=\"checkbox\" [checked]=\"!!newRow()?.[col.accessor]\" (change)=\"onInput($event, col.accessor, col)\" [attr.aria-label]=\"col.label\" />\n }\n @else {\n <!-- ReadOnly boolean column in create mode shows empty -->\n <span class=\"text-muted\">-</span>\n }\n </td>\n } @else if (col.type === 'number' || col.type === 'integer') {\n <td class=\"text-center number-column\">\n @if (!col.readOnly) {\n <input class=\"form-control form-control-sm\" type=\"number\" [value]=\"newRow()?.[col.accessor] ?? ''\" [placeholder]=\"col.label\" [min]=\"col.min\" [max]=\"col.max\" [step]=\"col.type === 'integer' ? '1' : 'any'\"\n (input)=\"onInput($event, col.accessor, col)\" />\n }\n @else {\n <!-- ReadOnly number column in create mode shows empty -->\n <span class=\"text-muted\">-</span>\n }\n </td>\n } @else {\n <td>\n @if (!col.readOnly) {\n @if (col.type === 'enum') {\n <select class=\"form-control form-control-sm\" [value]=\"newRow()?.[col.accessor] ?? ''\" (change)=\"onInput($event, col.accessor, col)\">\n <option value=\"\">{{ col.label }}</option>\n @for (option of getEnumOptions(col); track option.value) {\n <option [value]=\"option.value\">{{ option.label }}</option>\n }\n </select>\n }\n @else {\n <input class=\"form-control form-control-sm\" type=\"text\" [value]=\"newRow()?.[col.accessor] ?? ''\" [placeholder]=\"col.label\" (input)=\"onInput($event, col.accessor, col)\" />\n }\n }\n @else {\n <!-- ReadOnly column in create mode shows empty -->\n <span class=\"text-muted\">-</span>\n }\n </td>\n }\n }\n }\n <td class=\"text-end actions-cell\">\n <div class=\"actions-container centered-actions\">\n @if (hasCrudCreate()) {\n <c80-icon button icon=\"check\" title=\"Guardar\" (iconClick)=\"saveCreate()\" [size]=\".7\" />\n }\n <c80-icon button icon=\"cancel\" color=\"warn\" title=\"Cancelar\" (iconClick)=\"cancelCreate()\" [size]=\".7\" />\n </div>\n </td>\n </tr>\n }\n </tbody>\n </table>\n @if (data().length === 0 && !creating()) {\n <div class=\"text-center text-muted py-3 small\">\n No hay datos para mostrar.\n </div>\n }\n\n <!-- Pagination Controls -->\n @if (paginated() && data().length > 0) {\n <div class=\"pagination-container\">\n <div class=\"pagination-info\">\n P\u00E1gina {{ currentPage() }} de {{ totalPages() }}\n </div>\n <div class=\"pagination-controls\">\n <button type=\"button\" class=\"btn btn-sm\" [disabled]=\"!hasPrevPage()\" (click)=\"onPrevPage()\" title=\"P\u00E1gina anterior\">\n <c80-icon icon=\"arrowLeft\" [size]=\".6\" [button]=\"false\" />\n </button>\n <button type=\"button\" class=\"btn btn-sm\" [disabled]=\"!hasNextPage()\" (click)=\"onNextPage()\" title=\"P\u00E1gina siguiente\">\n <c80-icon icon=\"arrowRight\" [size]=\".6\" [button]=\"false\" />\n </button>\n </div>\n </div>\n }\n</div>\n\n<c80-modal />", styles: ["@charset \"UTF-8\";input[type=checkbox]{width:1.3rem!important;height:1.3rem!important;accent-color:var(--color-icon-danger);background:var(--color-bg-primary);margin:0 .25rem;vertical-align:middle;cursor:pointer}.table-responsive{width:100%;overflow-x:auto}.table-responsive .search-container{margin-bottom:-.06rem}.table-responsive .search-container .search-input-wrapper .input-group .btn-borrar{border-bottom-right-radius:0;border-color:var(--color-border-default);height:32px}.table-responsive .search-container .search-input-wrapper .input-group .input-group-text{background-color:var(--color-bg-secondary);border-color:var(--color-border-default);border-bottom-left-radius:0;color:var(--color-text-secondary);width:56.1px;height:32px;padding:.25rem .5rem}.table-responsive .search-container .search-input-wrapper .input-group .input-group-text c80-icon{display:flex;align-items:center;justify-content:center}.table-responsive .search-container .search-input-wrapper .input-group .search-input{border-color:var(--color-border-default);border-bottom-right-radius:0;font-size:.75rem;height:32px;padding:.25rem .5rem;outline:none!important;background-color:var(--color-bg-primary);color:var(--color-text-primary)}.table-responsive .search-container .search-input-wrapper .input-group .search-input:focus{outline:none!important}.table-responsive .search-container .search-input-wrapper .input-group .search-input::placeholder{color:var(--color-text-muted);font-style:italic}.table-responsive .table{min-width:0px;margin-bottom:0;background-color:var(--color-bg-primary);color:var(--color-text-primary);border-color:var(--color-border-default)}.table-responsive .table.table-bordered,.table-responsive .table.table-bordered th,.table-responsive .table.table-bordered td{border-color:var(--color-border-default)}.table-responsive .table.table-hover tbody tr:hover{background-color:var(--color-bg-hover)!important;color:var(--color-text-primary)}.table-responsive .table.table-hover tbody tr:hover td{background-color:var(--color-bg-hover)}.table-responsive .table .sticky-header{position:sticky;top:0;z-index:10;background-color:var(--color-bg-secondary)!important}.table-responsive .table .sticky-header .table-actions-header{display:table-cell;vertical-align:middle;padding:.2rem .6rem!important;background-color:var(--color-bg-secondary)!important}.table-responsive .table .sticky-header .actions-wrapper{display:flex;align-items:center;justify-content:center;gap:.5rem;height:100%}.table-responsive .table .sticky-header th{max-height:31px!important;vertical-align:middle!important;padding:.2rem .6rem!important;font-size:small!important;background-color:var(--color-bg-secondary)!important;border-bottom:2px solid var(--color-border-default);color:var(--color-text-primary)}.table-responsive .table tbody{background-color:var(--color-bg-primary)}.table-responsive .table tbody td{height:35px!important;min-height:35px!important;max-height:35px!important;vertical-align:middle!important;padding:.2rem .8rem!important;font-size:small;color:var(--color-text-primary);background-color:var(--color-bg-primary);border-color:var(--color-border-default)}.table-responsive .table tbody tr{height:35px!important;min-height:35px!important;max-height:35px!important;cursor:pointer;background-color:var(--color-bg-primary)}.table-responsive .table tbody tr:hover{background-color:var(--color-bg-hover)!important}.table-responsive .table tbody tr:hover td{background-color:var(--color-bg-hover)}.table-responsive .table tbody .text-muted{color:var(--color-text-muted)!important}.table-responsive .table tbody input,.table-responsive .table tbody select{border:1px solid var(--color-border-default);height:100%!important;font-size:smaller!important;background-color:var(--color-bg-primary);color:var(--color-text-primary)}.table-responsive .table tbody input:focus,.table-responsive .table tbody select:focus{border-color:var(--color-border-focus);box-shadow:var(--shadow-focus)}.table-responsive .table tbody input::placeholder,.table-responsive .table tbody select::placeholder{color:var(--color-text-muted)}.table-responsive .table tbody input[type=text],.table-responsive .table tbody input:not([type]){width:100%!important}.table-responsive .table tbody input[type=number]{min-width:80px!important;width:80px!important;text-align:center}.table-responsive .table tbody select{width:100%!important;padding:.25rem .5rem}.table-responsive .table thead th.boolean-column,.table-responsive .table tbody td.boolean-column,.table-responsive .table thead th.selection-column,.table-responsive .table tbody td.selection-column,.table-responsive .table thead th.table-actions-header,.table-responsive .table tbody td.table-actions-header{width:1%;white-space:nowrap}.table-responsive .table thead th.number-column,.table-responsive .table tbody td.number-column{width:1%;white-space:nowrap;text-align:center}.table-responsive .table thead th.number-column input[type=number],.table-responsive .table tbody td.number-column input[type=number]{min-width:80px!important;width:80px!important;text-align:center}.table-responsive .table thead th.date-column,.table-responsive .table tbody td.date-column{width:1%;white-space:nowrap;text-align:center}.table-responsive .table thead th.date-column input[type=datetime-local],.table-responsive .table tbody td.date-column input[type=datetime-local]{min-width:200px!important;width:200px!important;text-align:center}.table-responsive .table .actions-cell{white-space:nowrap;padding:0!important}.table-responsive .table .actions-container{display:flex;flex-direction:row;justify-content:flex-end;align-items:center;width:100%;height:100%}.table-responsive .table .actions-container.centered-actions{justify-content:center}.table-responsive .text-center.text-muted{color:var(--color-text-muted)!important}.table-responsive .btn-outline-secondary{background-color:var(--color-bg-primary);color:var(--color-text-primary);border-color:var(--color-border-default)}.table-responsive .btn-outline-secondary:hover{background-color:var(--color-bg-hover);border-color:var(--color-border-medium)}.table-responsive .btn-outline-secondary:focus{box-shadow:var(--shadow-focus)}.table-responsive .pagination-container{display:flex;justify-content:space-between;align-items:center;padding:.2rem .5rem;background-color:var(--color-bg-secondary);border:1px solid var(--color-border-default);border-top:none;border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}.table-responsive .pagination-container .pagination-info{font-size:.875rem;color:var(--color-text-secondary);font-weight:500}.table-responsive .pagination-container .pagination-controls{display:flex;gap:.5rem}.table-responsive .pagination-container .pagination-controls button{min-width:36px;height:32px;padding:.25rem .5rem;display:flex;align-items:center;justify-content:center;background-color:var(--color-bg-primary);color:var(--color-text-primary);border:none}.table-responsive .pagination-container .pagination-controls button:hover:not(:disabled){background-color:var(--color-bg-hover);border:none}.table-responsive .pagination-container .pagination-controls button:disabled{opacity:.5;cursor:auto;background-color:var(--color-bg-primary);border:none}\n"] }]
|
|
564
|
+
args: [{ selector: 'c80-table', standalone: true, imports: [IconComponent, ModalComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"table-responsive\" [style.max-height]=\"tableMaxHeight()\" [style.overflow-y]=\"size() > 0 ? 'auto' : 'visible'\">\r\n <!-- Search Bar -->\r\n @if (searchable()) {\r\n <div class=\"search-container\">\r\n <div class=\"search-input-wrapper\">\r\n <div class=\"input-group\">\r\n <span class=\"input-group-text\">\r\n <c80-icon icon=\"search\" [size]=\".65\" [button]=\"false\" />\r\n </span>\r\n <input type=\"text\" class=\"form-control search-input\" placeholder=\"Buscar...\" [value]=\"searchValue()\" (input)=\"onSearchInput($event)\" aria-label=\"Buscar en la tabla\" />\r\n @if (searchValue()) {\r\n <button class=\"btn btn-outline-secondary btn-borrar\" type=\"button\" (click)=\"clearSearch()\" title=\"Limpiar b\u00FAsqueda\">\r\n <c80-icon icon=\"cancel\" [size]=\".6\" />\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n <table class=\"table table-bordered table-hover align-middle\">\r\n <thead class=\"thead table-light sticky-header\">\r\n <tr>\r\n @if (allowSelection() && data().length !== 0) {\r\n <th class=\"text-center selection-column\">\r\n @if (multiple()) {\r\n <input type=\"checkbox\" [checked]=\"selectAllChecked()\" [indeterminate]=\"selectAllIndeterminate()\" (change)=\"toggleSelectAll()\" aria-label=\"Seleccionar todo\" />\r\n }\r\n </th>\r\n }\r\n @for (col of columns(); track col) {\r\n @if (isColumnVisibleInHeader(col)) {\r\n @if (col.type === 'boolean') {\r\n <th class=\"text-center boolean-column\">{{ col.label }}</th>\r\n }\r\n @else if (col.type === 'number' || col.type === 'integer') {\r\n <th class=\"text-center number-column\">{{ col.label }}</th>\r\n }\r\n @else if (col.type === 'date') {\r\n <th class=\"text-center date-column\">{{ col.label }}</th>\r\n }\r\n @else {\r\n <th>{{ col.label }}</th>\r\n }\r\n }\r\n }\r\n @if (hasAnyActions()) {\r\n <th class=\"table-actions-header\">\r\n <div class=\"actions-wrapper\">\r\n <span>Actions</span>\r\n @if (shouldShowCreateButton()) {\r\n <c80-icon button icon=\"add\" [disabled]=\"creating()\" title=\"Agregar\" [size]=\".6\" (iconClick)=\"startCreate()\" />\r\n }\r\n </div>\r\n </th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (row of data(); track trackById(i, row); let i = $index) {\r\n <tr>\r\n @if (allowSelection() && data().length !== 0) {\r\n <td class=\"text-center selection-column\">\r\n <input type=\"checkbox\" [checked]=\"isItemSelected(row)\" (change)=\"toggleItemSelection(row)\" [attr.aria-label]=\"'Seleccionar fila ' + (i + 1)\" />\r\n </td>\r\n }\r\n @for (col of columns(); track col) {\r\n @if (isColumnVisibleForRow(col, row)) {\r\n @if (col.type === 'boolean') {\r\n <td class=\"text-center boolean-column\">\r\n @if (editing() === row['id'] && !col.readOnly) {\r\n <input type=\"checkbox\" [checked]=\"!!editRow()?.[col.accessor]\" (change)=\"onEditInput($event, col.accessor, col)\" [attr.aria-label]=\"col.label\" />\r\n }\r\n @else {\r\n @if (getCellValue(row, col.accessor) === true) {\r\n <c80-icon icon=\"check\" [size]=\".7\" />\r\n <br />\r\n }\r\n @else if (getCellValue(row, col.accessor) === false) {\r\n <c80-icon icon=\"cancel\" [size]=\".7\" />\r\n <br />\r\n }\r\n }\r\n </td>\r\n }\r\n @else if (col.type === 'number' || col.type === 'integer') {\r\n <td class=\"text-center number-column\">\r\n @if (editing() === row['id'] && !col.readOnly) {\r\n <input class=\"form-control form-control-sm\" type=\"number\" [value]=\"editRow()?.[col.accessor] ?? ''\" [placeholder]=\"col.label\" [min]=\"col.min\" [max]=\"col.max\" [step]=\"col.type === 'integer' ? '1' : 'any'\"\r\n (input)=\"onEditInput($event, col.accessor, col)\" />\r\n }\r\n @else {\r\n <span [style.color]=\"getCellColor(getCellValue(row, col.accessor), col)\">{{ getDisplayValue(getCellValue(row,\r\n col.accessor), col) }}</span>\r\n }\r\n </td>\r\n }\r\n @else if (col.type === 'date') {\r\n <td class=\"text-center date-column\">\r\n @if (editing() === row['id'] && !col.readOnly) {\r\n <input class=\"form-control form-control-sm\" type=\"datetime-local\" [value]=\"editRow()?.[col.accessor] ?? ''\" [placeholder]=\"col.label\" (input)=\"onEditInput($event, col.accessor, col)\" />\r\n }\r\n @else {\r\n <span [style.color]=\"getCellColor(getCellValue(row, col.accessor), col)\">{{ getDisplayValue(getCellValue(row,\r\n col.accessor), col) }}</span>\r\n }\r\n </td>\r\n }\r\n @else {\r\n <td>\r\n @if (editing() === row['id'] && !col.readOnly) {\r\n @if (col.type === 'enum') {\r\n <select class=\"form-control form-control-sm\" [value]=\"editRow()?.[col.accessor] ?? ''\" (change)=\"onEditInput($event, col.accessor, col)\">\r\n <option value=\"\">{{ col.label }}</option>\r\n @for (option of getEnumOptions(col); track option.value) {\r\n <option [value]=\"option.value\">{{ option.label }}</option>\r\n }\r\n </select>\r\n }\r\n @else {\r\n <input class=\"form-control form-control-sm\" [type]=\"col.type === 'password' ? 'password' : 'text'\" [value]=\"editRow()?.[col.accessor] ?? ''\" [placeholder]=\"col.label\" (input)=\"onEditInput($event, col.accessor, col)\" />\r\n }\r\n }\r\n @else {\r\n @if (col.type === 'password') {\r\n <span [style.color]=\"getCellColor(getCellValue(row, col.accessor), col)\">******</span>\r\n }\r\n @else if (col.type === 'enum') {\r\n <span [style.color]=\"getCellColor(getCellValue(row, col.accessor), col)\">{{\r\n getEnumDisplayValue(getCellValue(row, col.accessor), col)\r\n }}</span>\r\n }\r\n @else if (getCellValue(row, col.accessor) === true) {\r\n <c80-icon icon=\"check\" [size]=\".7\" />\r\n }\r\n @else if (getCellValue(row, col.accessor) === false) {\r\n <c80-icon icon=\"cancel\" [size]=\".7\" />\r\n }\r\n @else {\r\n <span [style.color]=\"getCellColor(getCellValue(row, col.accessor), col)\">{{ getDisplayValue(getCellValue(row,\r\n col.accessor), col) }}</span>\r\n }\r\n }\r\n </td>\r\n }\r\n }\r\n }\r\n @if (hasAnyActions()) {\r\n <td class=\"text-end actions-cell\">\r\n <div class=\"actions-container\" [class.centered-actions]=\"editing() === row['id']\">\r\n @if (editing() === row['id']) {\r\n <!-- Modo edici\u00F3n: mostrar guardar y cancelar -->\r\n @if (hasCrudUpdate()) {\r\n <c80-icon button icon=\"check\" title=\"Guardar\" (iconClick)=\"saveEdit(row)\" [size]=\".7\" />\r\n }\r\n <c80-icon button icon=\"cancel\" color=\"warn\" title=\"Cancelar\" (iconClick)=\"cancelEdit()\" [size]=\".7\" />\r\n }\r\n @else {\r\n @for (action of customActions(); track action.name) {\r\n @if (shouldShowAction(action, row, data())) {\r\n <c80-icon button [icon]=\"action.icon\" [customColor]=\"getActionColor(action)\" [color]=\"action.name === 'delete' ? 'warn' : 'primary'\" [title]=\"getActionTooltip(action)\" (iconClick)=\"onDynamicAction(action, row)\" [size]=\".7\" />\r\n }\r\n }\r\n }\r\n </div>\r\n </td>\r\n }\r\n </tr>\r\n }\r\n @if (creating() && hasCrudCreate()) {\r\n <tr>\r\n @if (allowSelection() && data().length !== 0) {\r\n <td class=\"text-center selection-column\">\r\n <!-- Empty cell for alignment -->\r\n </td>\r\n }\r\n @for (col of columns(); track col) {\r\n @if (isColumnVisible(col)) {\r\n @if (col.type === 'boolean') {\r\n <td class=\"text-center\">\r\n @if (!col.readOnly) {\r\n <input type=\"checkbox\" [checked]=\"!!newRow()?.[col.accessor]\" (change)=\"onInput($event, col.accessor, col)\" [attr.aria-label]=\"col.label\" />\r\n }\r\n @else {\r\n <!-- ReadOnly boolean column in create mode shows empty -->\r\n <span class=\"text-muted\">-</span>\r\n }\r\n </td>\r\n } @else if (col.type === 'number' || col.type === 'integer') {\r\n <td class=\"text-center number-column\">\r\n @if (!col.readOnly) {\r\n <input class=\"form-control form-control-sm\" type=\"number\" [value]=\"newRow()?.[col.accessor] ?? ''\" [placeholder]=\"col.label\" [min]=\"col.min\" [max]=\"col.max\" [step]=\"col.type === 'integer' ? '1' : 'any'\"\r\n (input)=\"onInput($event, col.accessor, col)\" />\r\n }\r\n @else {\r\n <!-- ReadOnly number column in create mode shows empty -->\r\n <span class=\"text-muted\">-</span>\r\n }\r\n </td>\r\n } @else {\r\n <td>\r\n @if (!col.readOnly) {\r\n @if (col.type === 'enum') {\r\n <select class=\"form-control form-control-sm\" [value]=\"newRow()?.[col.accessor] ?? ''\" (change)=\"onInput($event, col.accessor, col)\">\r\n <option value=\"\">{{ col.label }}</option>\r\n @for (option of getEnumOptions(col); track option.value) {\r\n <option [value]=\"option.value\">{{ option.label }}</option>\r\n }\r\n </select>\r\n }\r\n @else {\r\n <input class=\"form-control form-control-sm\" type=\"text\" [value]=\"newRow()?.[col.accessor] ?? ''\" [placeholder]=\"col.label\" (input)=\"onInput($event, col.accessor, col)\" />\r\n }\r\n }\r\n @else {\r\n <!-- ReadOnly column in create mode shows empty -->\r\n <span class=\"text-muted\">-</span>\r\n }\r\n </td>\r\n }\r\n }\r\n }\r\n <td class=\"text-end actions-cell\">\r\n <div class=\"actions-container centered-actions\">\r\n @if (hasCrudCreate()) {\r\n <c80-icon button icon=\"check\" title=\"Guardar\" (iconClick)=\"saveCreate()\" [size]=\".7\" />\r\n }\r\n <c80-icon button icon=\"cancel\" color=\"warn\" title=\"Cancelar\" (iconClick)=\"cancelCreate()\" [size]=\".7\" />\r\n </div>\r\n </td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n @if (data().length === 0 && !creating()) {\r\n <div class=\"text-center text-muted py-3 small\">\r\n No hay datos para mostrar.\r\n </div>\r\n }\r\n\r\n <!-- Pagination Controls -->\r\n @if (paginated() && data().length > 0) {\r\n <div class=\"pagination-container\">\r\n <div class=\"pagination-info\">\r\n P\u00E1gina {{ currentPage() }} de {{ totalPages() }}\r\n </div>\r\n <div class=\"pagination-controls\">\r\n <button type=\"button\" class=\"btn btn-sm\" [disabled]=\"!hasPrevPage()\" (click)=\"onPrevPage()\" title=\"P\u00E1gina anterior\">\r\n <c80-icon icon=\"arrowLeft\" [size]=\".6\" [button]=\"false\" />\r\n </button>\r\n <button type=\"button\" class=\"btn btn-sm\" [disabled]=\"!hasNextPage()\" (click)=\"onNextPage()\" title=\"P\u00E1gina siguiente\">\r\n <c80-icon icon=\"arrowRight\" [size]=\".6\" [button]=\"false\" />\r\n </button>\r\n </div>\r\n </div>\r\n }\r\n</div>\r\n\r\n<c80-modal />", styles: ["@charset \"UTF-8\";input[type=checkbox]{width:1.3rem!important;height:1.3rem!important;accent-color:var(--color-icon-danger);background:var(--color-bg-primary);margin:0 .25rem;vertical-align:middle;cursor:pointer}.table-responsive{width:100%;overflow-x:auto}.table-responsive .search-container{margin-bottom:-.06rem}.table-responsive .search-container .search-input-wrapper .input-group .btn-borrar{border-bottom-right-radius:0;border-color:var(--color-border-default);height:32px}.table-responsive .search-container .search-input-wrapper .input-group .input-group-text{background-color:var(--color-bg-secondary);border-color:var(--color-border-default);border-bottom-left-radius:0;color:var(--color-text-secondary);width:56.1px;height:32px;padding:.25rem .5rem}.table-responsive .search-container .search-input-wrapper .input-group .input-group-text c80-icon{display:flex;align-items:center;justify-content:center}.table-responsive .search-container .search-input-wrapper .input-group .search-input{border-color:var(--color-border-default);border-bottom-right-radius:0;font-size:.75rem;height:32px;padding:.25rem .5rem;outline:none!important;background-color:var(--color-bg-primary);color:var(--color-text-primary)}.table-responsive .search-container .search-input-wrapper .input-group .search-input:focus{outline:none!important}.table-responsive .search-container .search-input-wrapper .input-group .search-input::placeholder{color:var(--color-text-muted);font-style:italic}.table-responsive .table{min-width:0px;margin-bottom:0;background-color:var(--color-bg-primary);color:var(--color-text-primary);border-color:var(--color-border-default)}.table-responsive .table.table-bordered,.table-responsive .table.table-bordered th,.table-responsive .table.table-bordered td{border-color:var(--color-border-default)}.table-responsive .table.table-hover tbody tr:hover{background-color:var(--color-bg-hover)!important;color:var(--color-text-primary)}.table-responsive .table.table-hover tbody tr:hover td{background-color:var(--color-bg-hover)}.table-responsive .table .sticky-header{position:sticky;top:0;z-index:10;background-color:var(--color-bg-secondary)!important}.table-responsive .table .sticky-header .table-actions-header{display:table-cell;vertical-align:middle;padding:.2rem .6rem!important;background-color:var(--color-bg-secondary)!important}.table-responsive .table .sticky-header .actions-wrapper{display:flex;align-items:center;justify-content:center;gap:.5rem;height:100%}.table-responsive .table .sticky-header th{max-height:31px!important;vertical-align:middle!important;padding:.2rem .6rem!important;font-size:small!important;background-color:var(--color-bg-secondary)!important;border-bottom:2px solid var(--color-border-default);color:var(--color-text-primary)}.table-responsive .table tbody{background-color:var(--color-bg-primary)}.table-responsive .table tbody td{height:35px!important;min-height:35px!important;max-height:35px!important;vertical-align:middle!important;padding:.2rem .8rem!important;font-size:small;color:var(--color-text-primary);background-color:var(--color-bg-primary);border-color:var(--color-border-default)}.table-responsive .table tbody tr{height:35px!important;min-height:35px!important;max-height:35px!important;cursor:pointer;background-color:var(--color-bg-primary)}.table-responsive .table tbody tr:hover{background-color:var(--color-bg-hover)!important}.table-responsive .table tbody tr:hover td{background-color:var(--color-bg-hover)}.table-responsive .table tbody .text-muted{color:var(--color-text-muted)!important}.table-responsive .table tbody input,.table-responsive .table tbody select{border:1px solid var(--color-border-default);height:100%!important;font-size:smaller!important;background-color:var(--color-bg-primary);color:var(--color-text-primary)}.table-responsive .table tbody input:focus,.table-responsive .table tbody select:focus{border-color:var(--color-border-focus);box-shadow:var(--shadow-focus)}.table-responsive .table tbody input::placeholder,.table-responsive .table tbody select::placeholder{color:var(--color-text-muted)}.table-responsive .table tbody input[type=text],.table-responsive .table tbody input:not([type]){width:100%!important}.table-responsive .table tbody input[type=number]{min-width:80px!important;width:80px!important;text-align:center}.table-responsive .table tbody select{width:100%!important;padding:.25rem .5rem}.table-responsive .table thead th.boolean-column,.table-responsive .table tbody td.boolean-column,.table-responsive .table thead th.selection-column,.table-responsive .table tbody td.selection-column,.table-responsive .table thead th.table-actions-header,.table-responsive .table tbody td.table-actions-header{width:1%;white-space:nowrap}.table-responsive .table thead th.number-column,.table-responsive .table tbody td.number-column{width:1%;white-space:nowrap;text-align:center}.table-responsive .table thead th.number-column input[type=number],.table-responsive .table tbody td.number-column input[type=number]{min-width:80px!important;width:80px!important;text-align:center}.table-responsive .table thead th.date-column,.table-responsive .table tbody td.date-column{width:1%;white-space:nowrap;text-align:center}.table-responsive .table thead th.date-column input[type=datetime-local],.table-responsive .table tbody td.date-column input[type=datetime-local]{min-width:200px!important;width:200px!important;text-align:center}.table-responsive .table .actions-cell{white-space:nowrap;padding:0!important}.table-responsive .table .actions-container{display:flex;flex-direction:row;justify-content:flex-end;align-items:center;width:100%;height:100%}.table-responsive .table .actions-container.centered-actions{justify-content:center}.table-responsive .text-center.text-muted{color:var(--color-text-muted)!important}.table-responsive .btn-outline-secondary{background-color:var(--color-bg-primary);color:var(--color-text-primary);border-color:var(--color-border-default)}.table-responsive .btn-outline-secondary:hover{background-color:var(--color-bg-hover);border-color:var(--color-border-medium)}.table-responsive .btn-outline-secondary:focus{box-shadow:var(--shadow-focus)}.table-responsive .pagination-container{display:flex;justify-content:space-between;align-items:center;padding:.2rem .5rem;background-color:var(--color-bg-secondary);border:1px solid var(--color-border-default);border-top:none;border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}.table-responsive .pagination-container .pagination-info{font-size:.875rem;color:var(--color-text-secondary);font-weight:500}.table-responsive .pagination-container .pagination-controls{display:flex;gap:.5rem}.table-responsive .pagination-container .pagination-controls button{min-width:36px;height:32px;padding:.25rem .5rem;display:flex;align-items:center;justify-content:center;background-color:var(--color-bg-primary);color:var(--color-text-primary);border:none}.table-responsive .pagination-container .pagination-controls button:hover:not(:disabled){background-color:var(--color-bg-hover);border:none}.table-responsive .pagination-container .pagination-controls button:disabled{opacity:.5;cursor:auto;background-color:var(--color-bg-primary);border:none}\n"] }]
|
|
565
565
|
}], ctorParameters: () => [], propDecorators: { data$: [{ type: i0.Input, args: [{ isSignal: true, alias: "data$", required: true }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], inputValues$: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputValues$", required: false }] }], customActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "customActions", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], rowId: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowId", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], allowSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowSelection", required: false }] }], noConfirm: [{ type: i0.Input, args: [{ isSignal: true, alias: "noConfirm", required: false }] }], paginated: [{ type: i0.Input, args: [{ isSignal: true, alias: "paginated", required: false }] }], paginationConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "paginationConfig", required: false }] }], actionClick: [{ type: i0.Output, args: ["actionClick"] }], searchTerm: [{ type: i0.Output, args: ["searchTerm"] }], errorEvent: [{ type: i0.Output, args: ["errorEvent"] }], selectable: [{ type: i0.Output, args: ["selectable"] }], paginationChange: [{ type: i0.Output, args: ["paginationChange"] }] } });
|
|
566
566
|
//# sourceMappingURL=table.component.js.map
|