@caribeng/ui 22.1.0 → 22.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -12
- package/fesm2022/caribeng-ui-accordion.mjs +2 -2
- package/fesm2022/caribeng-ui-anchor.mjs +169 -0
- package/fesm2022/caribeng-ui-autocomplete.mjs +10 -8
- package/fesm2022/caribeng-ui-avatargroup.mjs +9 -3
- package/fesm2022/caribeng-ui-blockui.mjs +12 -4
- package/fesm2022/caribeng-ui-breadcrumb.mjs +5 -2
- package/fesm2022/caribeng-ui-button.mjs +22 -2
- package/fesm2022/caribeng-ui-caribe-alert.mjs +5 -2
- package/fesm2022/caribeng-ui-caribe-animation-lottie.mjs +6 -3
- package/fesm2022/caribeng-ui-caribe-button-group.mjs +6 -3
- package/fesm2022/caribeng-ui-caribe-calendar.mjs +11 -6
- package/fesm2022/caribeng-ui-caribe-card-content.mjs +6 -3
- package/fesm2022/caribeng-ui-caribe-card-move.mjs +29 -7
- package/fesm2022/caribeng-ui-caribe-card-select.mjs +56 -14
- package/fesm2022/caribeng-ui-caribe-circle-loading.mjs +10 -7
- package/fesm2022/caribeng-ui-caribe-coachmark.mjs +42 -19
- package/fesm2022/caribeng-ui-caribe-data-table.mjs +15 -9
- package/fesm2022/caribeng-ui-caribe-dots-indicator.mjs +38 -5
- package/fesm2022/caribeng-ui-caribe-expansion-panel.mjs +16 -5
- package/fesm2022/caribeng-ui-caribe-fab-menu.mjs +56 -7
- package/fesm2022/caribeng-ui-caribe-file-download.mjs +68 -27
- package/fesm2022/caribeng-ui-caribe-file-select.mjs +22 -17
- package/fesm2022/caribeng-ui-caribe-float-menu.mjs +6 -3
- package/fesm2022/caribeng-ui-caribe-footer.mjs +8 -4
- package/fesm2022/caribeng-ui-caribe-header.mjs +6 -3
- package/fesm2022/caribeng-ui-caribe-icon-button.mjs +6 -3
- package/fesm2022/caribeng-ui-caribe-illustration.mjs +6 -3
- package/fesm2022/caribeng-ui-caribe-inline-alert.mjs +5 -2
- package/fesm2022/caribeng-ui-caribe-input-search.mjs +14 -10
- package/fesm2022/caribeng-ui-caribe-input-select.mjs +12 -10
- package/fesm2022/caribeng-ui-caribe-input-token.mjs +61 -11
- package/fesm2022/caribeng-ui-caribe-link.mjs +7 -2
- package/fesm2022/caribeng-ui-caribe-loader.mjs +8 -5
- package/fesm2022/caribeng-ui-caribe-modal.mjs +32 -16
- package/fesm2022/caribeng-ui-caribe-off-canvas.mjs +26 -12
- package/fesm2022/caribeng-ui-caribe-onboarding.mjs +44 -19
- package/fesm2022/caribeng-ui-caribe-pictogram.mjs +6 -3
- package/fesm2022/caribeng-ui-caribe-pop-over.mjs +34 -10
- package/fesm2022/caribeng-ui-caribe-preloader.mjs +9 -6
- package/fesm2022/caribeng-ui-caribe-progress-bar.mjs +5 -2
- package/fesm2022/caribeng-ui-caribe-shortcut.mjs +8 -3
- package/fesm2022/caribeng-ui-caribe-step-indicator.mjs +12 -5
- package/fesm2022/caribeng-ui-caribe-stroke.mjs +6 -3
- package/fesm2022/caribeng-ui-caribe-switch.mjs +5 -3
- package/fesm2022/caribeng-ui-caribe-tag-button.mjs +1 -1
- package/fesm2022/caribeng-ui-caribe-tracker.mjs +5 -2
- package/fesm2022/caribeng-ui-caribe-transaction-status.mjs +1 -1
- package/fesm2022/caribeng-ui-caribe-voucher.mjs +11 -8
- package/fesm2022/caribeng-ui-carousel.mjs +49 -14
- package/fesm2022/caribeng-ui-cascadeselect.mjs +22 -8
- package/fesm2022/caribeng-ui-chart.mjs +2598 -303
- package/fesm2022/caribeng-ui-chip.mjs +9 -4
- package/fesm2022/caribeng-ui-chips.mjs +9 -5
- package/fesm2022/caribeng-ui-colorpicker.mjs +9 -7
- package/fesm2022/caribeng-ui-confirmdialog.mjs +74 -9
- package/fesm2022/caribeng-ui-confirmpopup.mjs +134 -9
- package/fesm2022/caribeng-ui-contextmenu.mjs +6 -3
- package/fesm2022/caribeng-ui-dataview.mjs +211 -6
- package/fesm2022/caribeng-ui-datepicker.mjs +1630 -393
- package/fesm2022/caribeng-ui-descriptions.mjs +124 -0
- package/fesm2022/caribeng-ui-dialog.mjs +10 -7
- package/fesm2022/caribeng-ui-dock.mjs +6 -3
- package/fesm2022/caribeng-ui-drawer.mjs +10 -7
- package/fesm2022/caribeng-ui-dynamicdialog.mjs +210 -6
- package/fesm2022/caribeng-ui-editor.mjs +4392 -243
- package/fesm2022/caribeng-ui-empty.mjs +80 -0
- package/fesm2022/caribeng-ui-file-card.mjs +2 -2
- package/fesm2022/caribeng-ui-fileupload.mjs +96 -19
- package/fesm2022/caribeng-ui-floatlabel.mjs +4 -2
- package/fesm2022/caribeng-ui-folder-card.mjs +10 -3
- package/fesm2022/caribeng-ui-galleria.mjs +76 -45
- package/fesm2022/caribeng-ui-image.mjs +52 -29
- package/fesm2022/caribeng-ui-inplace.mjs +22 -6
- package/fesm2022/caribeng-ui-input-number.mjs +9 -7
- package/fesm2022/caribeng-ui-inputgroup.mjs +2 -2
- package/fesm2022/caribeng-ui-inputmask.mjs +14 -11
- package/fesm2022/caribeng-ui-inputotp.mjs +12 -6
- package/fesm2022/caribeng-ui-keyfilter.mjs +72 -0
- package/fesm2022/caribeng-ui-listbox.mjs +13 -11
- package/fesm2022/caribeng-ui-megamenu.mjs +222 -30
- package/fesm2022/caribeng-ui-menu.mjs +11 -5
- package/fesm2022/caribeng-ui-menubar.mjs +10 -5
- package/fesm2022/caribeng-ui-message.mjs +7 -4
- package/fesm2022/caribeng-ui-metergroup.mjs +29 -11
- package/fesm2022/caribeng-ui-multiselect.mjs +399 -97
- package/fesm2022/caribeng-ui-orderlist.mjs +230 -11
- package/fesm2022/caribeng-ui-organizationchart.mjs +12 -7
- package/fesm2022/caribeng-ui-paginator.mjs +18 -15
- package/fesm2022/caribeng-ui-panel.mjs +5 -2
- package/fesm2022/caribeng-ui-panelmenu.mjs +6 -3
- package/fesm2022/caribeng-ui-password.mjs +8 -6
- package/fesm2022/caribeng-ui-pdfviewer.mjs +1553 -0
- package/fesm2022/caribeng-ui-picklist.mjs +251 -14
- package/fesm2022/caribeng-ui-pricing.mjs +17 -14
- package/fesm2022/caribeng-ui-rating.mjs +7 -3
- package/fesm2022/caribeng-ui-repeater.mjs +223 -0
- package/fesm2022/caribeng-ui-result.mjs +91 -0
- package/fesm2022/caribeng-ui-scrollpanel.mjs +6 -3
- package/fesm2022/caribeng-ui-scrolltop.mjs +6 -3
- package/fesm2022/caribeng-ui-select.mjs +379 -87
- package/fesm2022/caribeng-ui-selectbutton.mjs +2 -2
- package/fesm2022/caribeng-ui-slider.mjs +171 -75
- package/fesm2022/caribeng-ui-speeddial.mjs +7 -4
- package/fesm2022/caribeng-ui-spinner.mjs +5 -2
- package/fesm2022/caribeng-ui-splitbutton.mjs +163 -0
- package/fesm2022/caribeng-ui-splitter.mjs +5 -2
- package/fesm2022/caribeng-ui-statistic.mjs +183 -0
- package/fesm2022/caribeng-ui-stepper.mjs +8 -5
- package/fesm2022/caribeng-ui-steps.mjs +6 -3
- package/fesm2022/caribeng-ui-table.mjs +708 -82
- package/fesm2022/caribeng-ui-tabmenu.mjs +6 -3
- package/fesm2022/caribeng-ui-tag.mjs +2 -2
- package/fesm2022/caribeng-ui-terminal.mjs +45 -9
- package/fesm2022/caribeng-ui-themetoggle.mjs +82 -0
- package/fesm2022/caribeng-ui-tieredmenu.mjs +9 -6
- package/fesm2022/caribeng-ui-timeline.mjs +175 -6
- package/fesm2022/caribeng-ui-toast.mjs +7 -4
- package/fesm2022/caribeng-ui-togglebutton.mjs +8 -6
- package/fesm2022/caribeng-ui-toolbar.mjs +6 -3
- package/fesm2022/caribeng-ui-tree.mjs +302 -6
- package/fesm2022/caribeng-ui-treeselect.mjs +26 -10
- package/fesm2022/caribeng-ui-treetable.mjs +269 -6
- package/fesm2022/caribeng-ui-virtualscroller.mjs +123 -10
- package/fesm2022/caribeng-ui.mjs +829 -6
- package/package.json +70 -11
- package/schematics/collection.json +10 -0
- package/schematics/ng-add/index.js +125 -0
- package/schematics/ng-add/schema.js +2 -0
- package/schematics/ng-add/schema.json +66 -0
- package/styles/caribeng.css +380 -0
- package/styles/scss/_mixins.scss +46 -0
- package/styles/scss/_overlay.scss +15 -0
- package/styles/scss/_tokens.scss +267 -0
- package/styles/scss/_utilities.scss +73 -0
- package/styles/scss/_variables.scss +33 -0
- package/styles/scss/index.scss +16 -0
- package/types/caribeng-ui-anchor.d.ts +50 -0
- package/types/caribeng-ui-autocomplete.d.ts +4 -2
- package/types/caribeng-ui-avatargroup.d.ts +3 -1
- package/types/caribeng-ui-blockui.d.ts +9 -4
- package/types/caribeng-ui-breadcrumb.d.ts +3 -0
- package/types/caribeng-ui-button.d.ts +9 -1
- package/types/caribeng-ui-caribe-alert.d.ts +3 -0
- package/types/caribeng-ui-caribe-animation-lottie.d.ts +4 -1
- package/types/caribeng-ui-caribe-button-group.d.ts +4 -1
- package/types/caribeng-ui-caribe-calendar.d.ts +5 -1
- package/types/caribeng-ui-caribe-card-content.d.ts +4 -1
- package/types/caribeng-ui-caribe-card-move.d.ts +13 -13
- package/types/caribeng-ui-caribe-card-select.d.ts +10 -1
- package/types/caribeng-ui-caribe-circle-loading.d.ts +4 -1
- package/types/caribeng-ui-caribe-coachmark.d.ts +6 -0
- package/types/caribeng-ui-caribe-data-table.d.ts +7 -2
- package/types/caribeng-ui-caribe-dots-indicator.d.ts +9 -0
- package/types/caribeng-ui-caribe-expansion-panel.d.ts +7 -10
- package/types/caribeng-ui-caribe-fab-menu.d.ts +10 -1
- package/types/caribeng-ui-caribe-file-download.d.ts +8 -10
- package/types/caribeng-ui-caribe-file-select.d.ts +7 -1
- package/types/caribeng-ui-caribe-float-menu.d.ts +4 -1
- package/types/caribeng-ui-caribe-header.d.ts +3 -0
- package/types/caribeng-ui-caribe-icon-button.d.ts +4 -1
- package/types/caribeng-ui-caribe-illustration.d.ts +4 -1
- package/types/caribeng-ui-caribe-inline-alert.d.ts +3 -0
- package/types/caribeng-ui-caribe-input-search.d.ts +4 -2
- package/types/caribeng-ui-caribe-input-select.d.ts +4 -2
- package/types/caribeng-ui-caribe-input-token.d.ts +16 -1
- package/types/caribeng-ui-caribe-link.d.ts +3 -0
- package/types/caribeng-ui-caribe-loader.d.ts +4 -1
- package/types/caribeng-ui-caribe-modal.d.ts +7 -10
- package/types/caribeng-ui-caribe-off-canvas.d.ts +6 -1
- package/types/caribeng-ui-caribe-onboarding.d.ts +6 -0
- package/types/caribeng-ui-caribe-pictogram.d.ts +4 -1
- package/types/caribeng-ui-caribe-pop-over.d.ts +7 -10
- package/types/caribeng-ui-caribe-preloader.d.ts +4 -1
- package/types/caribeng-ui-caribe-progress-bar.d.ts +3 -0
- package/types/caribeng-ui-caribe-shortcut.d.ts +3 -1
- package/types/caribeng-ui-caribe-step-indicator.d.ts +6 -0
- package/types/caribeng-ui-caribe-stroke.d.ts +4 -1
- package/types/caribeng-ui-caribe-switch.d.ts +3 -1
- package/types/caribeng-ui-caribe-tracker.d.ts +3 -0
- package/types/caribeng-ui-caribe-voucher.d.ts +5 -2
- package/types/caribeng-ui-carousel.d.ts +10 -1
- package/types/caribeng-ui-cascadeselect.d.ts +7 -2
- package/types/caribeng-ui-chart.d.ts +469 -44
- package/types/caribeng-ui-chip.d.ts +6 -0
- package/types/caribeng-ui-chips.d.ts +6 -2
- package/types/caribeng-ui-colorpicker.d.ts +3 -1
- package/types/caribeng-ui-confirmdialog.d.ts +25 -6
- package/types/caribeng-ui-confirmpopup.d.ts +37 -5
- package/types/caribeng-ui-contextmenu.d.ts +4 -1
- package/types/caribeng-ui-dataview.d.ts +63 -5
- package/types/caribeng-ui-datepicker.d.ts +186 -21
- package/types/caribeng-ui-descriptions.d.ts +63 -0
- package/types/caribeng-ui-dialog.d.ts +4 -1
- package/types/caribeng-ui-dock.d.ts +4 -1
- package/types/caribeng-ui-drawer.d.ts +4 -1
- package/types/caribeng-ui-dynamicdialog.d.ts +93 -3
- package/types/caribeng-ui-editor.d.ts +486 -13
- package/types/caribeng-ui-empty.d.ts +34 -0
- package/types/caribeng-ui-file-card.d.ts +1 -1
- package/types/caribeng-ui-fileupload.d.ts +27 -4
- package/types/caribeng-ui-folder-card.d.ts +4 -1
- package/types/caribeng-ui-galleria.d.ts +9 -0
- package/types/caribeng-ui-image.d.ts +10 -0
- package/types/caribeng-ui-inplace.d.ts +8 -0
- package/types/caribeng-ui-input-number.d.ts +3 -1
- package/types/caribeng-ui-inputmask.d.ts +5 -0
- package/types/caribeng-ui-inputotp.d.ts +7 -2
- package/types/caribeng-ui-keyfilter.d.ts +30 -0
- package/types/caribeng-ui-listbox.d.ts +5 -3
- package/types/caribeng-ui-megamenu.d.ts +26 -2
- package/types/caribeng-ui-menu.d.ts +7 -2
- package/types/caribeng-ui-menubar.d.ts +5 -1
- package/types/caribeng-ui-message.d.ts +3 -0
- package/types/caribeng-ui-metergroup.d.ts +9 -1
- package/types/caribeng-ui-multiselect.d.ts +71 -10
- package/types/caribeng-ui-orderlist.d.ts +58 -6
- package/types/caribeng-ui-organizationchart.d.ts +7 -1
- package/types/caribeng-ui-paginator.d.ts +3 -0
- package/types/caribeng-ui-panel.d.ts +3 -0
- package/types/caribeng-ui-panelmenu.d.ts +4 -1
- package/types/caribeng-ui-password.d.ts +4 -2
- package/types/caribeng-ui-pdfviewer.d.ts +258 -0
- package/types/caribeng-ui-picklist.d.ts +67 -7
- package/types/caribeng-ui-pricing.d.ts +8 -5
- package/types/caribeng-ui-rating.d.ts +6 -2
- package/types/caribeng-ui-repeater.d.ts +79 -0
- package/types/caribeng-ui-result.d.ts +35 -0
- package/types/caribeng-ui-scrollpanel.d.ts +4 -1
- package/types/caribeng-ui-scrolltop.d.ts +4 -1
- package/types/caribeng-ui-select.d.ts +73 -9
- package/types/caribeng-ui-slider.d.ts +63 -10
- package/types/caribeng-ui-speeddial.d.ts +5 -2
- package/types/caribeng-ui-spinner.d.ts +3 -0
- package/types/caribeng-ui-splitbutton.d.ts +49 -0
- package/types/caribeng-ui-splitter.d.ts +3 -0
- package/types/caribeng-ui-statistic.d.ts +65 -0
- package/types/caribeng-ui-stepper.d.ts +3 -0
- package/types/caribeng-ui-steps.d.ts +4 -1
- package/types/caribeng-ui-table.d.ts +184 -16
- package/types/caribeng-ui-tabmenu.d.ts +4 -1
- package/types/caribeng-ui-terminal.d.ts +10 -0
- package/types/caribeng-ui-themetoggle.d.ts +32 -0
- package/types/caribeng-ui-tieredmenu.d.ts +5 -2
- package/types/caribeng-ui-timeline.d.ts +63 -4
- package/types/caribeng-ui-toast.d.ts +3 -0
- package/types/caribeng-ui-togglebutton.d.ts +5 -3
- package/types/caribeng-ui-toolbar.d.ts +7 -4
- package/types/caribeng-ui-tree.d.ts +76 -4
- package/types/caribeng-ui-treeselect.d.ts +10 -2
- package/types/caribeng-ui-treetable.d.ts +68 -4
- package/types/caribeng-ui-virtualscroller.d.ts +45 -5
- package/types/caribeng-ui.d.ts +501 -12
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, inject, TemplateRef, Directive, contentChildren, model, output, signal, computed, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
-
import { NgTemplateOutlet } from '@angular/common';
|
|
2
|
+
import { input, inject, TemplateRef, Directive, contentChildren, contentChild, viewChild, model, output, signal, computed, linkedSignal, DestroyRef, afterNextRender, afterEveryRender, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
+
import { DOCUMENT, NgTemplateOutlet } from '@angular/common';
|
|
4
4
|
import { CbIcon } from '@caribeng/ui/icon';
|
|
5
5
|
import { CbPaginator } from '@caribeng/ui/paginator';
|
|
6
|
+
import { injectCbTranslation, cbFormat } from '@caribeng/ui';
|
|
6
7
|
|
|
8
|
+
/** Plantilla de las celdas de una columna: `<ng-template cbTableCell="campo" let-row let-value="value">`. */
|
|
7
9
|
class CbTableCellDirective {
|
|
8
10
|
constructor() {
|
|
9
11
|
this.cbTableCell = input.required(/* @ts-ignore */
|
|
10
12
|
...(ngDevMode ? [{ debugName: "cbTableCell" }] : /* istanbul ignore next */ []));
|
|
11
13
|
this.template = inject(TemplateRef);
|
|
12
14
|
}
|
|
15
|
+
static ngTemplateContextGuard(_dir, ctx) {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
13
18
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: CbTableCellDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
14
19
|
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.5", type: CbTableCellDirective, isStandalone: true, selector: "ng-template[cbTableCell]", inputs: { cbTableCell: { classPropertyName: "cbTableCell", publicName: "cbTableCell", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 }); }
|
|
15
20
|
}
|
|
@@ -20,20 +25,77 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
|
|
|
20
25
|
standalone: true,
|
|
21
26
|
}]
|
|
22
27
|
}], propDecorators: { cbTableCell: [{ type: i0.Input, args: [{ isSignal: true, alias: "cbTableCell", required: true }] }] } });
|
|
28
|
+
/** Contenido de la fila expandida: `<ng-template cbTableRowExpansion let-row>`. */
|
|
29
|
+
class CbTableRowExpansion {
|
|
30
|
+
constructor() {
|
|
31
|
+
this.template = inject(TemplateRef);
|
|
32
|
+
}
|
|
33
|
+
static ngTemplateContextGuard(_dir, ctx) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: CbTableRowExpansion, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
37
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.5", type: CbTableRowExpansion, isStandalone: true, selector: "ng-template[cbTableRowExpansion]", ngImport: i0 }); }
|
|
38
|
+
}
|
|
39
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: CbTableRowExpansion, decorators: [{
|
|
40
|
+
type: Directive,
|
|
41
|
+
args: [{
|
|
42
|
+
selector: 'ng-template[cbTableRowExpansion]',
|
|
43
|
+
standalone: true,
|
|
44
|
+
}]
|
|
45
|
+
}] });
|
|
46
|
+
/** Cabecera de grupo: `<ng-template cbTableGroupHeader let-valor let-count="count">`. */
|
|
47
|
+
class CbTableGroupHeader {
|
|
48
|
+
constructor() {
|
|
49
|
+
this.template = inject(TemplateRef);
|
|
50
|
+
}
|
|
51
|
+
static ngTemplateContextGuard(_dir, ctx) {
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: CbTableGroupHeader, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
55
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.5", type: CbTableGroupHeader, isStandalone: true, selector: "ng-template[cbTableGroupHeader]", ngImport: i0 }); }
|
|
56
|
+
}
|
|
57
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: CbTableGroupHeader, decorators: [{
|
|
58
|
+
type: Directive,
|
|
59
|
+
args: [{
|
|
60
|
+
selector: 'ng-template[cbTableGroupHeader]',
|
|
61
|
+
standalone: true,
|
|
62
|
+
}]
|
|
63
|
+
}] });
|
|
64
|
+
let nextId = 0;
|
|
65
|
+
const MIN_COLUMN_WIDTH = 48;
|
|
23
66
|
/**
|
|
24
67
|
* Table de CaribeNG: tabla de datos con columnas declarativas, ordenación,
|
|
25
|
-
*
|
|
68
|
+
* filtros (global y por columna), paginación, selección (simple/múltiple),
|
|
69
|
+
* columnas redimensionables y fijas, cabecera fija, filas expandibles y
|
|
70
|
+
* agrupadas, exportación a CSV y carga desde el servidor (`lazy`).
|
|
26
71
|
*
|
|
27
72
|
* @example
|
|
28
73
|
* ```html
|
|
29
|
-
* <
|
|
30
|
-
*
|
|
74
|
+
* <input type="search" [(ngModel)]="busqueda" aria-label="Buscar" />
|
|
75
|
+
* <cb-table [value]="productos" [columns]="cols" [globalFilter]="busqueda" [paginator]="true" [rows]="5"
|
|
76
|
+
* striped selectionMode="multiple" dataKey="id" [(selection)]="sel" resizableColumns>
|
|
77
|
+
* <ng-template cbTableRowExpansion let-producto>{{ producto.descripcion }}</ng-template>
|
|
78
|
+
* </cb-table>
|
|
31
79
|
* ```
|
|
32
80
|
*/
|
|
33
81
|
class CbTable {
|
|
34
82
|
constructor() {
|
|
83
|
+
/** Textos de interfaz en el idioma activo (`provideCaribeNG({ locale })`). */
|
|
84
|
+
this.t = injectCbTranslation();
|
|
85
|
+
/** Rellena `{0}`, `{1}`… de un texto traducido. */
|
|
86
|
+
this.fmt = cbFormat;
|
|
87
|
+
this.minColumnWidth = MIN_COLUMN_WIDTH;
|
|
88
|
+
this.document = inject(DOCUMENT);
|
|
35
89
|
this.cellTemplates = contentChildren(CbTableCellDirective, /* @ts-ignore */
|
|
36
90
|
...(ngDevMode ? [{ debugName: "cellTemplates" }] : /* istanbul ignore next */ []));
|
|
91
|
+
/** Plantilla de fila expandida; si existe, se añade la columna de expandir. */
|
|
92
|
+
this.expansion = contentChild(CbTableRowExpansion, /* @ts-ignore */
|
|
93
|
+
...(ngDevMode ? [{ debugName: "expansion" }] : /* istanbul ignore next */ []));
|
|
94
|
+
/** Plantilla de cabecera de grupo (con `groupRowsBy`). */
|
|
95
|
+
this.groupHeader = contentChild(CbTableGroupHeader, /* @ts-ignore */
|
|
96
|
+
...(ngDevMode ? [{ debugName: "groupHeader" }] : /* istanbul ignore next */ []));
|
|
97
|
+
this.tableRef = viewChild('table', /* @ts-ignore */
|
|
98
|
+
...(ngDevMode ? [{ debugName: "tableRef" }] : /* istanbul ignore next */ []));
|
|
37
99
|
this.value = input([], /* @ts-ignore */
|
|
38
100
|
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
39
101
|
this.columns = input([], /* @ts-ignore */
|
|
@@ -47,50 +109,194 @@ class CbTable {
|
|
|
47
109
|
this.rowHover = input(true, { ...(ngDevMode ? { debugName: "rowHover" } : /* istanbul ignore next */ {}), transform: toBoolean });
|
|
48
110
|
this.size = input('md', /* @ts-ignore */
|
|
49
111
|
...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
50
|
-
this.emptyMessage = input(
|
|
112
|
+
this.emptyMessage = input(undefined, /* @ts-ignore */
|
|
51
113
|
...(ngDevMode ? [{ debugName: "emptyMessage" }] : /* istanbul ignore next */ []));
|
|
114
|
+
/** Nombre accesible de la tabla. */
|
|
115
|
+
this.ariaLabel = input(undefined, /* @ts-ignore */
|
|
116
|
+
...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
52
117
|
/** `single`, `multiple` o `null` (sin selección). */
|
|
53
118
|
this.selectionMode = input(null, /* @ts-ignore */
|
|
54
119
|
...(ngDevMode ? [{ debugName: "selectionMode" }] : /* istanbul ignore next */ []));
|
|
55
|
-
/** Propiedad identificadora para comparar selección (si no, por referencia). */
|
|
120
|
+
/** Propiedad identificadora para comparar selección y filas expandidas (si no, por referencia). */
|
|
56
121
|
this.dataKey = input(null, /* @ts-ignore */
|
|
57
122
|
...(ngDevMode ? [{ debugName: "dataKey" }] : /* istanbul ignore next */ []));
|
|
123
|
+
/** Texto del filtro global (two-way). Busca en `globalFilterFields`. */
|
|
124
|
+
this.globalFilter = model('', /* @ts-ignore */
|
|
125
|
+
...(ngDevMode ? [{ debugName: "globalFilter" }] : /* istanbul ignore next */ []));
|
|
126
|
+
/** Campos en los que busca el filtro global. Por defecto, los de todas las columnas. */
|
|
127
|
+
this.globalFilterFields = input(null, /* @ts-ignore */
|
|
128
|
+
...(ngDevMode ? [{ debugName: "globalFilterFields" }] : /* istanbul ignore next */ []));
|
|
129
|
+
/** Permite cambiar el ancho de las columnas arrastrando o con el teclado. */
|
|
130
|
+
this.resizableColumns = input(false, { ...(ngDevMode ? { debugName: "resizableColumns" } : /* istanbul ignore next */ {}), transform: toBoolean });
|
|
131
|
+
/** Claves (`dataKey`) o filas expandidas (two-way). */
|
|
132
|
+
this.expandedRowKeys = model([], /* @ts-ignore */
|
|
133
|
+
...(ngDevMode ? [{ debugName: "expandedRowKeys" }] : /* istanbul ignore next */ []));
|
|
134
|
+
/** Alto máximo (CSS) de la tabla: hace scroll con la cabecera fija. */
|
|
135
|
+
this.scrollHeight = input(null, /* @ts-ignore */
|
|
136
|
+
...(ngDevMode ? [{ debugName: "scrollHeight" }] : /* istanbul ignore next */ []));
|
|
137
|
+
/** Agrupa las filas por este campo, con una fila de cabecera por grupo. */
|
|
138
|
+
this.groupRowsBy = input(null, /* @ts-ignore */
|
|
139
|
+
...(ngDevMode ? [{ debugName: "groupRowsBy" }] : /* istanbul ignore next */ []));
|
|
140
|
+
/**
|
|
141
|
+
* Datos desde el servidor: la tabla no filtra, ordena ni pagina; emite `lazyLoad`
|
|
142
|
+
* y muestra `value` tal cual (la página actual).
|
|
143
|
+
*/
|
|
144
|
+
this.lazy = input(false, { ...(ngDevMode ? { debugName: "lazy" } : /* istanbul ignore next */ {}), transform: toBoolean });
|
|
145
|
+
/** Total de filas en el servidor (modo `lazy`), para el paginador. */
|
|
146
|
+
this.totalRecords = input(null, /* @ts-ignore */
|
|
147
|
+
...(ngDevMode ? [{ debugName: "totalRecords" }] : /* istanbul ignore next */ []));
|
|
148
|
+
/** Muestra la capa de carga y marca la tabla con `aria-busy`. */
|
|
149
|
+
this.loading = input(false, { ...(ngDevMode ? { debugName: "loading" } : /* istanbul ignore next */ {}), transform: toBoolean });
|
|
58
150
|
this.selection = model(null, /* @ts-ignore */
|
|
59
151
|
...(ngDevMode ? [{ debugName: "selection" }] : /* istanbul ignore next */ []));
|
|
60
152
|
this.sortChange = output();
|
|
61
|
-
this.
|
|
62
|
-
|
|
153
|
+
this.filterChange = output();
|
|
154
|
+
this.columnResize = output();
|
|
155
|
+
this.rowExpand = output();
|
|
156
|
+
this.rowCollapse = output();
|
|
157
|
+
/** En modo `lazy`: página, orden y filtros que hay que pedir al servidor. */
|
|
158
|
+
this.lazyLoad = output();
|
|
63
159
|
this.sortField = signal(null, /* @ts-ignore */
|
|
64
160
|
...(ngDevMode ? [{ debugName: "sortField" }] : /* istanbul ignore next */ []));
|
|
65
161
|
this.sortOrder = signal(1, /* @ts-ignore */
|
|
66
162
|
...(ngDevMode ? [{ debugName: "sortOrder" }] : /* istanbul ignore next */ []));
|
|
163
|
+
this.columnFilters = signal({}, /* @ts-ignore */
|
|
164
|
+
...(ngDevMode ? [{ debugName: "columnFilters" }] : /* istanbul ignore next */ []));
|
|
165
|
+
this.widths = signal({}, /* @ts-ignore */
|
|
166
|
+
...(ngDevMode ? [{ debugName: "widths" }] : /* istanbul ignore next */ []));
|
|
167
|
+
/** Columnas en orden de pantalla: las fijas primero. */
|
|
168
|
+
this.displayColumns = computed(() => [
|
|
169
|
+
...this.columns().filter((c) => c.frozen),
|
|
170
|
+
...this.columns().filter((c) => !c.frozen),
|
|
171
|
+
], /* @ts-ignore */
|
|
172
|
+
...(ngDevMode ? [{ debugName: "displayColumns" }] : /* istanbul ignore next */ []));
|
|
173
|
+
this.hasFrozen = computed(() => this.columns().some((c) => c.frozen), /* @ts-ignore */
|
|
174
|
+
...(ngDevMode ? [{ debugName: "hasFrozen" }] : /* istanbul ignore next */ []));
|
|
175
|
+
this.lastFrozen = computed(() => this.displayColumns().filter((c) => c.frozen).at(-1)?.field ?? null, /* @ts-ignore */
|
|
176
|
+
...(ngDevMode ? [{ debugName: "lastFrozen" }] : /* istanbul ignore next */ []));
|
|
177
|
+
/** Desplazamiento `left` (px) de cada celda fija, medido tras el render. */
|
|
178
|
+
this.frozenOffsets = signal({}, /* @ts-ignore */
|
|
179
|
+
...(ngDevMode ? [{ debugName: "frozenOffsets" }] : /* istanbul ignore next */ []));
|
|
180
|
+
this.hasColumnFilters = computed(() => this.columns().some((c) => c.filter), /* @ts-ignore */
|
|
181
|
+
...(ngDevMode ? [{ debugName: "hasColumnFilters" }] : /* istanbul ignore next */ []));
|
|
182
|
+
this.isFiltering = computed(() => !!this.globalFilter().trim() || Object.values(this.columnFilters()).some((v) => !!v?.trim()), /* @ts-ignore */
|
|
183
|
+
...(ngDevMode ? [{ debugName: "isFiltering" }] : /* istanbul ignore next */ []));
|
|
184
|
+
this.filtered = computed(() => {
|
|
185
|
+
if (this.lazy())
|
|
186
|
+
return this.value();
|
|
187
|
+
const global = normalize(this.globalFilter());
|
|
188
|
+
const globalFields = this.globalFilterFields() ?? this.columns().map((c) => c.field);
|
|
189
|
+
const columnFilters = Object.entries(this.columnFilters())
|
|
190
|
+
.map(([field, text]) => ({ field, text: normalize(text), mode: this.matchMode(field) }))
|
|
191
|
+
.filter((f) => f.text);
|
|
192
|
+
return this.value().filter((row) => (!global || globalFields.some((field) => matches(fieldValue(row, field), global, 'contains'))) &&
|
|
193
|
+
columnFilters.every((f) => matches(fieldValue(row, f.field), f.text, f.mode)));
|
|
194
|
+
}, /* @ts-ignore */
|
|
195
|
+
...(ngDevMode ? [{ debugName: "filtered" }] : /* istanbul ignore next */ []));
|
|
67
196
|
this.sorted = computed(() => {
|
|
197
|
+
if (this.lazy())
|
|
198
|
+
return this.value();
|
|
68
199
|
const field = this.sortField();
|
|
69
|
-
const
|
|
70
|
-
|
|
200
|
+
const group = this.groupRowsBy();
|
|
201
|
+
const data = [...this.filtered()];
|
|
202
|
+
if (!field && !group)
|
|
71
203
|
return data;
|
|
72
204
|
const order = this.sortOrder();
|
|
73
|
-
|
|
205
|
+
// Con grupos, primero se ordena por el campo del grupo para que sus filas queden juntas.
|
|
206
|
+
return data.sort((a, b) => (group ? this.compare(a, b, group) : 0) || (field ? this.compare(a, b, field) * order : 0));
|
|
74
207
|
}, /* @ts-ignore */
|
|
75
208
|
...(ngDevMode ? [{ debugName: "sorted" }] : /* istanbul ignore next */ []));
|
|
209
|
+
/** Filas totales: las del servidor en modo `lazy`, las filtradas si no. */
|
|
210
|
+
this.total = computed(() => (this.lazy() ? (this.totalRecords() ?? this.value().length) : this.sorted().length), /* @ts-ignore */
|
|
211
|
+
...(ngDevMode ? [{ debugName: "total" }] : /* istanbul ignore next */ []));
|
|
212
|
+
/** Primera fila de la página; vuelve a 0 al filtrar u ordenar (y, sin `lazy`, al cambiar los datos). */
|
|
213
|
+
this.first = linkedSignal({ ...(ngDevMode ? { debugName: "first" } : /* istanbul ignore next */ {}), source: () => [
|
|
214
|
+
this.sortField(),
|
|
215
|
+
this.sortOrder(),
|
|
216
|
+
this.globalFilter(),
|
|
217
|
+
this.columnFilters(),
|
|
218
|
+
this.lazy() ? null : this.value(),
|
|
219
|
+
],
|
|
220
|
+
computation: () => 0 });
|
|
221
|
+
/** Filas por grupo en todos los datos (no solo en la página). */
|
|
222
|
+
this.groupCounts = computed(() => {
|
|
223
|
+
const field = this.groupRowsBy();
|
|
224
|
+
const counts = new Map();
|
|
225
|
+
if (!field)
|
|
226
|
+
return counts;
|
|
227
|
+
for (const row of this.sorted()) {
|
|
228
|
+
const key = fieldValue(row, field);
|
|
229
|
+
counts.set(key, (counts.get(key) ?? 0) + 1);
|
|
230
|
+
}
|
|
231
|
+
return counts;
|
|
232
|
+
}, /* @ts-ignore */
|
|
233
|
+
...(ngDevMode ? [{ debugName: "groupCounts" }] : /* istanbul ignore next */ []));
|
|
76
234
|
this.pageRows = computed(() => {
|
|
77
235
|
const data = this.sorted();
|
|
78
|
-
if (!this.paginator())
|
|
236
|
+
if (!this.paginator() || this.lazy())
|
|
79
237
|
return data;
|
|
80
238
|
const start = Math.min(this.first(), Math.max(0, data.length - 1));
|
|
81
239
|
return data.slice(start, start + this.rows());
|
|
82
240
|
}, /* @ts-ignore */
|
|
83
241
|
...(ngDevMode ? [{ debugName: "pageRows" }] : /* istanbul ignore next */ []));
|
|
84
|
-
this.colspan = computed(() => this.
|
|
242
|
+
this.colspan = computed(() => this.displayColumns().length + (this.selectionMode() ? 1 : 0) + (this.expansion() ? 1 : 0), /* @ts-ignore */
|
|
85
243
|
...(ngDevMode ? [{ debugName: "colspan" }] : /* istanbul ignore next */ []));
|
|
86
|
-
this.
|
|
87
|
-
const data = this.sorted();
|
|
88
|
-
if (!data.length)
|
|
89
|
-
return false;
|
|
244
|
+
this.selectedCount = computed(() => {
|
|
90
245
|
const sel = Array.isArray(this.selection()) ? this.selection() : [];
|
|
91
|
-
return
|
|
246
|
+
return this.sorted().filter((row) => sel.some((s) => this.same(s, row))).length;
|
|
92
247
|
}, /* @ts-ignore */
|
|
248
|
+
...(ngDevMode ? [{ debugName: "selectedCount" }] : /* istanbul ignore next */ []));
|
|
249
|
+
this.allSelected = computed(() => this.sorted().length > 0 && this.selectedCount() === this.sorted().length, /* @ts-ignore */
|
|
93
250
|
...(ngDevMode ? [{ debugName: "allSelected" }] : /* istanbul ignore next */ []));
|
|
251
|
+
this.someSelected = computed(() => this.selectedCount() > 0 && !this.allSelected(), /* @ts-ignore */
|
|
252
|
+
...(ngDevMode ? [{ debugName: "someSelected" }] : /* istanbul ignore next */ []));
|
|
253
|
+
this.uid = `cb-table-${++nextId}`;
|
|
254
|
+
this.stopResize = null;
|
|
255
|
+
inject(DestroyRef).onDestroy(() => this.stopResize?.());
|
|
256
|
+
// En modo lazy, la primera página se pide al montar la tabla.
|
|
257
|
+
afterNextRender(() => {
|
|
258
|
+
if (this.lazy())
|
|
259
|
+
this.emitLazy();
|
|
260
|
+
});
|
|
261
|
+
// Columnas fijas: se miden los encabezados para saber dónde anclar cada una.
|
|
262
|
+
afterEveryRender(() => this.measureFrozen());
|
|
263
|
+
}
|
|
264
|
+
// --- Filtros ---------------------------------------------------------------
|
|
265
|
+
/** Aplica el filtro global (equivale a `[globalFilter]`). */
|
|
266
|
+
filterGlobal(text) {
|
|
267
|
+
this.globalFilter.set(text);
|
|
268
|
+
this.emitFilters();
|
|
269
|
+
}
|
|
270
|
+
/** Aplica el filtro de una columna. */
|
|
271
|
+
filterColumn(field, text) {
|
|
272
|
+
this.columnFilters.update((f) => ({ ...f, [field]: text }));
|
|
273
|
+
this.emitFilters();
|
|
274
|
+
}
|
|
275
|
+
/** Quita todos los filtros. */
|
|
276
|
+
clearFilters() {
|
|
277
|
+
this.globalFilter.set('');
|
|
278
|
+
this.columnFilters.set({});
|
|
279
|
+
this.emitFilters();
|
|
280
|
+
}
|
|
281
|
+
emitFilters() {
|
|
282
|
+
this.filterChange.emit({ global: this.globalFilter(), columns: this.columnFilters() });
|
|
283
|
+
this.emitLazy(0);
|
|
284
|
+
}
|
|
285
|
+
/** Pide al servidor la página actual (solo en modo `lazy`). */
|
|
286
|
+
emitLazy(first = this.first()) {
|
|
287
|
+
if (!this.lazy())
|
|
288
|
+
return;
|
|
289
|
+
this.lazyLoad.emit({
|
|
290
|
+
first,
|
|
291
|
+
rows: this.rows(),
|
|
292
|
+
sortField: this.sortField(),
|
|
293
|
+
sortOrder: this.sortOrder(),
|
|
294
|
+
globalFilter: this.globalFilter(),
|
|
295
|
+
filters: this.columnFilters(),
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
matchMode(field) {
|
|
299
|
+
return this.columns().find((c) => c.field === field)?.filterMatchMode ?? 'contains';
|
|
94
300
|
}
|
|
95
301
|
// --- Ordenación ------------------------------------------------------------
|
|
96
302
|
onSort(col) {
|
|
@@ -103,8 +309,8 @@ class CbTable {
|
|
|
103
309
|
this.sortField.set(col.field);
|
|
104
310
|
this.sortOrder.set(1);
|
|
105
311
|
}
|
|
106
|
-
this.first.set(0);
|
|
107
312
|
this.sortChange.emit({ field: this.sortField(), order: this.sortOrder() });
|
|
313
|
+
this.emitLazy(0);
|
|
108
314
|
}
|
|
109
315
|
sortIcon(col) {
|
|
110
316
|
if (this.sortField() !== col.field)
|
|
@@ -138,16 +344,138 @@ class CbTable {
|
|
|
138
344
|
const sel = this.selection();
|
|
139
345
|
return Array.isArray(sel) ? sel.some((s) => this.same(s, row)) : this.same(sel, row);
|
|
140
346
|
}
|
|
347
|
+
// --- Filas expandibles -------------------------------------------------------
|
|
348
|
+
isExpanded(row) {
|
|
349
|
+
const key = this.keyOf(row);
|
|
350
|
+
return this.expandedRowKeys().some((k) => k === key);
|
|
351
|
+
}
|
|
352
|
+
/** Expande o contrae una fila. */
|
|
353
|
+
toggleExpansion(row) {
|
|
354
|
+
const key = this.keyOf(row);
|
|
355
|
+
if (this.isExpanded(row)) {
|
|
356
|
+
this.expandedRowKeys.update((keys) => keys.filter((k) => k !== key));
|
|
357
|
+
this.rowCollapse.emit(row);
|
|
358
|
+
}
|
|
359
|
+
else {
|
|
360
|
+
this.expandedRowKeys.update((keys) => [...keys, key]);
|
|
361
|
+
this.rowExpand.emit(row);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
expansionId(index) {
|
|
365
|
+
return `${this.uid}-expansion-${index}`;
|
|
366
|
+
}
|
|
367
|
+
// --- Columnas redimensionables ---------------------------------------------------
|
|
368
|
+
columnWidth(col) {
|
|
369
|
+
const px = this.widths()[col.field];
|
|
370
|
+
return px != null ? `${px}px` : col.width || null;
|
|
371
|
+
}
|
|
372
|
+
startResize(event, col) {
|
|
373
|
+
event.preventDefault();
|
|
374
|
+
event.stopPropagation();
|
|
375
|
+
const th = event.target.closest('th');
|
|
376
|
+
const startX = event.clientX;
|
|
377
|
+
const startWidth = this.currentWidth(th, col);
|
|
378
|
+
const move = (e) => this.setWidth(col.field, startWidth + e.clientX - startX);
|
|
379
|
+
const up = () => {
|
|
380
|
+
this.stopResize?.();
|
|
381
|
+
this.columnResize.emit({ field: col.field, width: this.widths()[col.field] ?? startWidth });
|
|
382
|
+
};
|
|
383
|
+
this.stopResize?.();
|
|
384
|
+
this.document.addEventListener('pointermove', move);
|
|
385
|
+
this.document.addEventListener('pointerup', up);
|
|
386
|
+
this.stopResize = () => {
|
|
387
|
+
this.document.removeEventListener('pointermove', move);
|
|
388
|
+
this.document.removeEventListener('pointerup', up);
|
|
389
|
+
this.stopResize = null;
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
/** Flecha izquierda / derecha cambian el ancho (10 px; 50 px con Mayús). */
|
|
393
|
+
onResizerKeydown(event, col) {
|
|
394
|
+
if (event.key !== 'ArrowLeft' && event.key !== 'ArrowRight')
|
|
395
|
+
return;
|
|
396
|
+
event.preventDefault();
|
|
397
|
+
const step = (event.shiftKey ? 50 : 10) * (event.key === 'ArrowLeft' ? -1 : 1);
|
|
398
|
+
const th = event.target.closest('th');
|
|
399
|
+
this.setWidth(col.field, this.currentWidth(th, col) + step);
|
|
400
|
+
this.columnResize.emit({ field: col.field, width: this.widths()[col.field] ?? MIN_COLUMN_WIDTH });
|
|
401
|
+
}
|
|
402
|
+
currentWidth(th, col) {
|
|
403
|
+
return this.widths()[col.field] ?? (th?.getBoundingClientRect().width || parseFloat(col.width ?? '') || 120);
|
|
404
|
+
}
|
|
405
|
+
setWidth(field, width) {
|
|
406
|
+
this.widths.update((w) => ({ ...w, [field]: Math.max(MIN_COLUMN_WIDTH, Math.round(width)) }));
|
|
407
|
+
}
|
|
141
408
|
// --- Paginación ------------------------------------------------------------
|
|
142
409
|
onPageChange(state) {
|
|
143
410
|
this.first.set(state.first);
|
|
144
411
|
this.rows.set(state.rows);
|
|
412
|
+
this.emitLazy(state.first);
|
|
413
|
+
}
|
|
414
|
+
// --- Grupos --------------------------------------------------------------------
|
|
415
|
+
groupOf(row) {
|
|
416
|
+
const field = this.groupRowsBy();
|
|
417
|
+
return field ? fieldValue(row, field) : null;
|
|
418
|
+
}
|
|
419
|
+
groupCount(row) {
|
|
420
|
+
return this.groupCounts().get(this.groupOf(row)) ?? 0;
|
|
421
|
+
}
|
|
422
|
+
/** La fila abre grupo si es la primera de la página o cambia el valor del grupo. */
|
|
423
|
+
isGroupStart(index) {
|
|
424
|
+
const rows = this.pageRows();
|
|
425
|
+
return index === 0 || this.groupOf(rows[index - 1]) !== this.groupOf(rows[index]);
|
|
426
|
+
}
|
|
427
|
+
// --- Columnas fijas ----------------------------------------------------------------
|
|
428
|
+
frozenLeft(key) {
|
|
429
|
+
return this.hasFrozen() ? (this.frozenOffsets()[key] ?? 0) : null;
|
|
430
|
+
}
|
|
431
|
+
/** Suma los anchos de las celdas fijas anteriores (expandir, selección y columnas `frozen`). */
|
|
432
|
+
measureFrozen() {
|
|
433
|
+
const table = this.tableRef()?.nativeElement;
|
|
434
|
+
if (!table || !this.hasFrozen())
|
|
435
|
+
return;
|
|
436
|
+
const frozen = new Set(['__exp', '__sel', ...this.columns().filter((c) => c.frozen).map((c) => c.field)]);
|
|
437
|
+
const offsets = {};
|
|
438
|
+
let left = 0;
|
|
439
|
+
for (const th of Array.from(table.querySelectorAll('thead tr:first-child > th[data-key]'))) {
|
|
440
|
+
const key = th.dataset['key'];
|
|
441
|
+
if (!frozen.has(key))
|
|
442
|
+
break;
|
|
443
|
+
offsets[key] = Math.round(left);
|
|
444
|
+
left += th.getBoundingClientRect().width;
|
|
445
|
+
}
|
|
446
|
+
const current = this.frozenOffsets();
|
|
447
|
+
const changed = Object.keys(offsets).some((k) => current[k] !== offsets[k]) || Object.keys(current).length !== Object.keys(offsets).length;
|
|
448
|
+
if (changed)
|
|
449
|
+
this.frozenOffsets.set(offsets);
|
|
450
|
+
}
|
|
451
|
+
// --- Exportación ---------------------------------------------------------------------
|
|
452
|
+
/**
|
|
453
|
+
* Datos en CSV: columnas visibles (salvo `exportable: false`) y todas las filas
|
|
454
|
+
* filtradas y ordenadas (no solo la página), o las seleccionadas con `selectionOnly`.
|
|
455
|
+
*/
|
|
456
|
+
toCSV(options = {}) {
|
|
457
|
+
const sep = options.separator ?? ',';
|
|
458
|
+
const cols = this.displayColumns().filter((c) => c.exportable !== false);
|
|
459
|
+
const rows = options.selectionOnly ? this.sorted().filter((row) => this.isSelected(row)) : this.sorted();
|
|
460
|
+
const cell = (v) => {
|
|
461
|
+
const text = v == null ? '' : String(v);
|
|
462
|
+
return /["\n\r]/.test(text) || text.includes(sep) ? `"${text.replace(/"/g, '""')}"` : text;
|
|
463
|
+
};
|
|
464
|
+
return [cols.map((c) => cell(c.header)).join(sep), ...rows.map((row) => cols.map((c) => cell(fieldValue(row, c.field))).join(sep))].join('\r\n');
|
|
465
|
+
}
|
|
466
|
+
/** Descarga el CSV (`nombre.csv`), con BOM para que Excel respete tildes y eñes. */
|
|
467
|
+
exportCSV(filename = 'datos', options = {}) {
|
|
468
|
+
const blob = new Blob(['\uFEFF' + this.toCSV(options)], { type: 'text/csv;charset=utf-8' });
|
|
469
|
+
const url = URL.createObjectURL(blob);
|
|
470
|
+
const link = this.document.createElement('a');
|
|
471
|
+
link.href = url;
|
|
472
|
+
link.download = filename.endsWith('.csv') ? filename : `${filename}.csv`;
|
|
473
|
+
link.click();
|
|
474
|
+
setTimeout(() => URL.revokeObjectURL(url));
|
|
145
475
|
}
|
|
146
476
|
// --- Helpers ---------------------------------------------------------------
|
|
147
477
|
cellValue(row, col) {
|
|
148
|
-
return row != null && typeof row === 'object'
|
|
149
|
-
? row[col.field]
|
|
150
|
-
: row;
|
|
478
|
+
return row != null && typeof row === 'object' ? row[col.field] : row;
|
|
151
479
|
}
|
|
152
480
|
cellTemplate(field) {
|
|
153
481
|
return this.cellTemplates().find((cell) => cell.cbTableCell() === field);
|
|
@@ -162,6 +490,11 @@ class CbTable {
|
|
|
162
490
|
}
|
|
163
491
|
return index;
|
|
164
492
|
}
|
|
493
|
+
/** Clave de una fila: su `dataKey` o la propia fila. */
|
|
494
|
+
keyOf(row) {
|
|
495
|
+
const key = this.dataKey();
|
|
496
|
+
return key && row != null && typeof row === 'object' ? row[key] : row;
|
|
497
|
+
}
|
|
165
498
|
same(a, b) {
|
|
166
499
|
if (a == null || b == null)
|
|
167
500
|
return a === b;
|
|
@@ -183,193 +516,486 @@ class CbTable {
|
|
|
183
516
|
return String(av).localeCompare(String(bv), undefined, { numeric: true });
|
|
184
517
|
}
|
|
185
518
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: CbTable, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
186
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: CbTable, isStandalone: true, selector: "cb-table", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, paginator: { classPropertyName: "paginator", publicName: "paginator", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, rowsPerPageOptions: { classPropertyName: "rowsPerPageOptions", publicName: "rowsPerPageOptions", isSignal: true, isRequired: false, transformFunction: null }, striped: { classPropertyName: "striped", publicName: "striped", isSignal: true, isRequired: false, transformFunction: null }, rowHover: { classPropertyName: "rowHover", publicName: "rowHover", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, selectionMode: { classPropertyName: "selectionMode", publicName: "selectionMode", isSignal: true, isRequired: false, transformFunction: null }, dataKey: { classPropertyName: "dataKey", publicName: "dataKey", isSignal: true, isRequired: false, transformFunction: null }, selection: { classPropertyName: "selection", publicName: "selection", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { rows: "rowsChange", selection: "selectionChange", sortChange: "sortChange" }, host: { classAttribute: "cb-table-host" }, queries: [{ propertyName: "cellTemplates", predicate: CbTableCellDirective, isSignal: true }], ngImport: i0, template: `
|
|
187
|
-
<
|
|
188
|
-
|
|
519
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: CbTable, isStandalone: true, selector: "cb-table", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, paginator: { classPropertyName: "paginator", publicName: "paginator", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, rowsPerPageOptions: { classPropertyName: "rowsPerPageOptions", publicName: "rowsPerPageOptions", isSignal: true, isRequired: false, transformFunction: null }, striped: { classPropertyName: "striped", publicName: "striped", isSignal: true, isRequired: false, transformFunction: null }, rowHover: { classPropertyName: "rowHover", publicName: "rowHover", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, selectionMode: { classPropertyName: "selectionMode", publicName: "selectionMode", isSignal: true, isRequired: false, transformFunction: null }, dataKey: { classPropertyName: "dataKey", publicName: "dataKey", isSignal: true, isRequired: false, transformFunction: null }, globalFilter: { classPropertyName: "globalFilter", publicName: "globalFilter", isSignal: true, isRequired: false, transformFunction: null }, globalFilterFields: { classPropertyName: "globalFilterFields", publicName: "globalFilterFields", isSignal: true, isRequired: false, transformFunction: null }, resizableColumns: { classPropertyName: "resizableColumns", publicName: "resizableColumns", isSignal: true, isRequired: false, transformFunction: null }, expandedRowKeys: { classPropertyName: "expandedRowKeys", publicName: "expandedRowKeys", isSignal: true, isRequired: false, transformFunction: null }, scrollHeight: { classPropertyName: "scrollHeight", publicName: "scrollHeight", isSignal: true, isRequired: false, transformFunction: null }, groupRowsBy: { classPropertyName: "groupRowsBy", publicName: "groupRowsBy", isSignal: true, isRequired: false, transformFunction: null }, lazy: { classPropertyName: "lazy", publicName: "lazy", isSignal: true, isRequired: false, transformFunction: null }, totalRecords: { classPropertyName: "totalRecords", publicName: "totalRecords", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, selection: { classPropertyName: "selection", publicName: "selection", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { rows: "rowsChange", globalFilter: "globalFilterChange", expandedRowKeys: "expandedRowKeysChange", selection: "selectionChange", sortChange: "sortChange", filterChange: "filterChange", columnResize: "columnResize", rowExpand: "rowExpand", rowCollapse: "rowCollapse", lazyLoad: "lazyLoad" }, host: { classAttribute: "cb-table-host" }, queries: [{ propertyName: "cellTemplates", predicate: CbTableCellDirective, isSignal: true }, { propertyName: "expansion", first: true, predicate: CbTableRowExpansion, descendants: true, isSignal: true }, { propertyName: "groupHeader", first: true, predicate: CbTableGroupHeader, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "tableRef", first: true, predicate: ["table"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
520
|
+
<ng-content select="[cbTableHeader]" />
|
|
521
|
+
<div class="cb-table__wrap" [class.cb-table__wrap--scroll]="!!scrollHeight()" [style.max-height]="scrollHeight()">
|
|
522
|
+
<table
|
|
523
|
+
#table
|
|
524
|
+
class="cb-table"
|
|
525
|
+
[class]="'cb-table--' + size()"
|
|
526
|
+
[class.cb-table--striped]="striped()"
|
|
527
|
+
[class.cb-table--hover]="rowHover()"
|
|
528
|
+
[class.cb-table--resizable]="resizableColumns()"
|
|
529
|
+
[class.cb-table--scroll]="!!scrollHeight()"
|
|
530
|
+
[attr.aria-label]="ariaLabel() || null"
|
|
531
|
+
[attr.aria-busy]="loading() || null"
|
|
532
|
+
>
|
|
189
533
|
<thead>
|
|
190
534
|
<tr>
|
|
535
|
+
@if (expansion()) {
|
|
536
|
+
<th class="cb-table__sel" scope="col" data-key="__exp" [class.cb-is-frozen]="hasFrozen()" [style.left.px]="frozenLeft('__exp')">
|
|
537
|
+
<span class="cb-table__sr">{{ t().details }}</span>
|
|
538
|
+
</th>
|
|
539
|
+
}
|
|
191
540
|
@if (selectionMode() === 'multiple') {
|
|
192
|
-
<th class="cb-table__sel">
|
|
541
|
+
<th class="cb-table__sel" scope="col" data-key="__sel" [class.cb-is-frozen]="hasFrozen()" [style.left.px]="frozenLeft('__sel')">
|
|
193
542
|
<span
|
|
194
543
|
class="cb-table__check"
|
|
195
544
|
[class.cb-is-checked]="allSelected()"
|
|
545
|
+
[class.cb-is-mixed]="someSelected()"
|
|
196
546
|
role="checkbox"
|
|
197
|
-
[attr.aria-checked]="allSelected()"
|
|
547
|
+
[attr.aria-checked]="allSelected() ? 'true' : someSelected() ? 'mixed' : 'false'"
|
|
548
|
+
[attr.aria-label]="t().selectAllRows"
|
|
198
549
|
tabindex="0"
|
|
199
550
|
(click)="toggleAll()"
|
|
200
|
-
(keydown.enter)="toggleAll()"
|
|
201
551
|
(keydown.space)="toggleAll(); $event.preventDefault()"
|
|
202
552
|
>
|
|
203
|
-
@if (allSelected()) {
|
|
553
|
+
@if (allSelected()) {
|
|
554
|
+
<cb-icon name="check" [size]="13" aria-hidden="true" />
|
|
555
|
+
} @else if (someSelected()) {
|
|
556
|
+
<cb-icon name="minus" [size]="13" aria-hidden="true" />
|
|
557
|
+
}
|
|
204
558
|
</span>
|
|
205
559
|
</th>
|
|
206
560
|
} @else if (selectionMode() === 'single') {
|
|
207
|
-
<th class="cb-table__sel"
|
|
561
|
+
<th class="cb-table__sel" scope="col" data-key="__sel" [class.cb-is-frozen]="hasFrozen()" [style.left.px]="frozenLeft('__sel')">
|
|
562
|
+
<span class="cb-table__sr">{{ t().select }}</span>
|
|
563
|
+
</th>
|
|
208
564
|
}
|
|
209
|
-
@for (col of
|
|
565
|
+
@for (col of displayColumns(); track col.field) {
|
|
210
566
|
<th
|
|
211
567
|
class="cb-table__th"
|
|
568
|
+
scope="col"
|
|
569
|
+
[attr.data-key]="col.field"
|
|
570
|
+
[class.cb-is-frozen]="!!col.frozen"
|
|
571
|
+
[class.cb-is-frozen-last]="col.field === lastFrozen()"
|
|
572
|
+
[style.left.px]="col.frozen ? frozenLeft(col.field) : null"
|
|
212
573
|
[class.cb-is-sortable]="col.sortable"
|
|
213
|
-
[style.width]="col
|
|
574
|
+
[style.width]="columnWidth(col)"
|
|
214
575
|
[style.text-align]="col.align || null"
|
|
215
576
|
[attr.aria-sort]="ariaSort(col)"
|
|
216
|
-
(click)="onSort(col)"
|
|
217
577
|
>
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
578
|
+
@if (col.sortable) {
|
|
579
|
+
<button
|
|
580
|
+
type="button"
|
|
581
|
+
class="cb-table__th-inner cb-table__sort-btn"
|
|
582
|
+
[attr.aria-label]="fmt(t().sortBy, col.header)"
|
|
583
|
+
(click)="onSort(col)"
|
|
584
|
+
>
|
|
585
|
+
{{ col.header }}
|
|
221
586
|
<cb-icon class="cb-table__sort" [name]="sortIcon(col)" [size]="15" aria-hidden="true" />
|
|
222
|
-
|
|
223
|
-
|
|
587
|
+
</button>
|
|
588
|
+
} @else {
|
|
589
|
+
<span class="cb-table__th-inner">{{ col.header }}</span>
|
|
590
|
+
}
|
|
591
|
+
@if (resizableColumns()) {
|
|
592
|
+
<span
|
|
593
|
+
class="cb-table__resizer"
|
|
594
|
+
role="separator"
|
|
595
|
+
aria-orientation="vertical"
|
|
596
|
+
tabindex="0"
|
|
597
|
+
[attr.aria-label]="fmt(t().resizeColumn, col.header)"
|
|
598
|
+
[attr.aria-valuenow]="widths()[col.field] ?? null"
|
|
599
|
+
[attr.aria-valuemin]="minColumnWidth"
|
|
600
|
+
(pointerdown)="startResize($event, col)"
|
|
601
|
+
(keydown)="onResizerKeydown($event, col)"
|
|
602
|
+
></span>
|
|
603
|
+
}
|
|
224
604
|
</th>
|
|
225
605
|
}
|
|
226
606
|
</tr>
|
|
607
|
+
@if (hasColumnFilters()) {
|
|
608
|
+
<tr class="cb-table__filter-row">
|
|
609
|
+
@if (expansion()) {
|
|
610
|
+
<td class="cb-table__sel" [class.cb-is-frozen]="hasFrozen()" [style.left.px]="frozenLeft('__exp')"></td>
|
|
611
|
+
}
|
|
612
|
+
@if (selectionMode()) {
|
|
613
|
+
<td class="cb-table__sel" [class.cb-is-frozen]="hasFrozen()" [style.left.px]="frozenLeft('__sel')"></td>
|
|
614
|
+
}
|
|
615
|
+
@for (col of displayColumns(); track col.field) {
|
|
616
|
+
<td
|
|
617
|
+
class="cb-table__filter-cell"
|
|
618
|
+
[class.cb-is-frozen]="!!col.frozen"
|
|
619
|
+
[class.cb-is-frozen-last]="col.field === lastFrozen()"
|
|
620
|
+
[style.left.px]="col.frozen ? frozenLeft(col.field) : null"
|
|
621
|
+
>
|
|
622
|
+
@if (col.filter) {
|
|
623
|
+
<input
|
|
624
|
+
type="search"
|
|
625
|
+
class="cb-table__filter"
|
|
626
|
+
[value]="columnFilters()[col.field] ?? ''"
|
|
627
|
+
[placeholder]="col.filterPlaceholder ?? t().search"
|
|
628
|
+
[attr.aria-label]="fmt(t().filterBy, col.header)"
|
|
629
|
+
(input)="filterColumn(col.field, $any($event.target).value)"
|
|
630
|
+
/>
|
|
631
|
+
}
|
|
632
|
+
</td>
|
|
633
|
+
}
|
|
634
|
+
</tr>
|
|
635
|
+
}
|
|
227
636
|
</thead>
|
|
228
637
|
<tbody>
|
|
229
|
-
@for (row of pageRows(); track rowKey(row, $index)) {
|
|
638
|
+
@for (row of pageRows(); track rowKey(row, $index); let i = $index) {
|
|
639
|
+
@if (groupRowsBy() && isGroupStart(i)) {
|
|
640
|
+
<tr class="cb-table__group">
|
|
641
|
+
<th scope="rowgroup" [attr.colspan]="colspan()">
|
|
642
|
+
@if (groupHeader(); as gh) {
|
|
643
|
+
<ng-container
|
|
644
|
+
[ngTemplateOutlet]="gh.template"
|
|
645
|
+
[ngTemplateOutletContext]="{ $implicit: groupOf(row), count: groupCount(row) }"
|
|
646
|
+
/>
|
|
647
|
+
} @else {
|
|
648
|
+
{{ groupOf(row) }} <span class="cb-table__group-count">({{ groupCount(row) }})</span>
|
|
649
|
+
}
|
|
650
|
+
</th>
|
|
651
|
+
</tr>
|
|
652
|
+
}
|
|
230
653
|
<tr
|
|
231
654
|
class="cb-table__row"
|
|
232
655
|
[class.cb-is-selected]="isSelected(row)"
|
|
233
656
|
[class.cb-is-selectable]="!!selectionMode()"
|
|
234
657
|
(click)="onRowClick(row)"
|
|
235
658
|
>
|
|
659
|
+
@if (expansion()) {
|
|
660
|
+
<td class="cb-table__sel" [class.cb-is-frozen]="hasFrozen()" [style.left.px]="frozenLeft('__exp')">
|
|
661
|
+
<button
|
|
662
|
+
type="button"
|
|
663
|
+
class="cb-table__expander"
|
|
664
|
+
[attr.aria-expanded]="isExpanded(row)"
|
|
665
|
+
[attr.aria-controls]="isExpanded(row) ? expansionId(first() + i) : null"
|
|
666
|
+
[attr.aria-label]="fmt(t().expandRow, first() + i + 1)"
|
|
667
|
+
(click)="toggleExpansion(row); $event.stopPropagation()"
|
|
668
|
+
>
|
|
669
|
+
<cb-icon [name]="isExpanded(row) ? 'chevron-down' : 'chevron-right'" [size]="15" aria-hidden="true" />
|
|
670
|
+
</button>
|
|
671
|
+
</td>
|
|
672
|
+
}
|
|
236
673
|
@if (selectionMode()) {
|
|
237
|
-
<td class="cb-table__sel">
|
|
238
|
-
<span
|
|
239
|
-
|
|
674
|
+
<td class="cb-table__sel" [class.cb-is-frozen]="hasFrozen()" [style.left.px]="frozenLeft('__sel')">
|
|
675
|
+
<span
|
|
676
|
+
class="cb-table__check"
|
|
677
|
+
[class.cb-table__check--radio]="selectionMode() === 'single'"
|
|
678
|
+
[class.cb-is-checked]="isSelected(row)"
|
|
679
|
+
[attr.role]="selectionMode() === 'single' ? 'radio' : 'checkbox'"
|
|
680
|
+
[attr.aria-checked]="isSelected(row)"
|
|
681
|
+
[attr.aria-label]="fmt(t().selectRow, first() + i + 1)"
|
|
682
|
+
tabindex="0"
|
|
683
|
+
(keydown.space)="onRowClick(row); $event.preventDefault()"
|
|
684
|
+
>
|
|
685
|
+
@if (isSelected(row)) {
|
|
686
|
+
<cb-icon name="check" [size]="13" aria-hidden="true" />
|
|
687
|
+
}
|
|
240
688
|
</span>
|
|
241
689
|
</td>
|
|
242
690
|
}
|
|
243
|
-
@for (col of
|
|
244
|
-
<td
|
|
691
|
+
@for (col of displayColumns(); track col.field) {
|
|
692
|
+
<td
|
|
693
|
+
class="cb-table__td"
|
|
694
|
+
[class.cb-is-frozen]="!!col.frozen"
|
|
695
|
+
[class.cb-is-frozen-last]="col.field === lastFrozen()"
|
|
696
|
+
[style.left.px]="col.frozen ? frozenLeft(col.field) : null"
|
|
697
|
+
[style.text-align]="col.align || null"
|
|
698
|
+
>
|
|
245
699
|
@if (cellTemplate(col.field); as cell) {
|
|
246
|
-
<ng-container
|
|
247
|
-
[ngTemplateOutlet]="cell.template"
|
|
248
|
-
[ngTemplateOutletContext]="cellContext(row, col)"
|
|
249
|
-
/>
|
|
700
|
+
<ng-container [ngTemplateOutlet]="cell.template" [ngTemplateOutletContext]="cellContext(row, col)" />
|
|
250
701
|
} @else {
|
|
251
702
|
{{ cellValue(row, col) }}
|
|
252
703
|
}
|
|
253
704
|
</td>
|
|
254
705
|
}
|
|
255
706
|
</tr>
|
|
707
|
+
@if (expansion(); as exp) {
|
|
708
|
+
@if (isExpanded(row)) {
|
|
709
|
+
<tr class="cb-table__expansion" [id]="expansionId(first() + i)">
|
|
710
|
+
<td [attr.colspan]="colspan()">
|
|
711
|
+
<ng-container
|
|
712
|
+
[ngTemplateOutlet]="exp.template"
|
|
713
|
+
[ngTemplateOutletContext]="{ $implicit: row, index: first() + i }"
|
|
714
|
+
/>
|
|
715
|
+
</td>
|
|
716
|
+
</tr>
|
|
717
|
+
}
|
|
718
|
+
}
|
|
256
719
|
} @empty {
|
|
257
720
|
<tr>
|
|
258
|
-
<td class="cb-table__empty" [attr.colspan]="colspan()">{{ emptyMessage() }}</td>
|
|
721
|
+
<td class="cb-table__empty" [attr.colspan]="colspan()">{{ (emptyMessage() ?? t().noData) }}</td>
|
|
259
722
|
</tr>
|
|
260
723
|
}
|
|
261
724
|
</tbody>
|
|
262
725
|
</table>
|
|
726
|
+
@if (loading()) {
|
|
727
|
+
<div class="cb-table__loading" role="status">
|
|
728
|
+
<cb-icon name="loader" [size]="22" [spin]="true" aria-hidden="true" />
|
|
729
|
+
<span class="cb-table__sr">{{ t().loading }}</span>
|
|
730
|
+
</div>
|
|
731
|
+
}
|
|
263
732
|
</div>
|
|
733
|
+
@if (isFiltering()) {
|
|
734
|
+
<span class="cb-table__sr" aria-live="polite">{{ fmt(t().resultsCount, total()) }}</span>
|
|
735
|
+
}
|
|
264
736
|
|
|
265
737
|
@if (paginator()) {
|
|
266
738
|
<cb-paginator
|
|
267
739
|
class="cb-table__paginator"
|
|
268
|
-
[totalRecords]="
|
|
740
|
+
[totalRecords]="total()"
|
|
269
741
|
[(first)]="first"
|
|
270
742
|
[(rows)]="rows"
|
|
271
743
|
[rowsPerPageOptions]="rowsPerPageOptions()"
|
|
272
744
|
(pageChange)="onPageChange($event)"
|
|
273
745
|
/>
|
|
274
746
|
}
|
|
275
|
-
`, isInline: true, styles: [":host{display:block;font-family:var(--cb-font-sans);color:var(--cb-color-text)}.cb-table__wrap{overflow-x:auto;border:var(--cb-border-width) solid var(--cb-color-border);border-radius:var(--cb-radius-md)}.cb-table{width:100%;border-collapse:collapse;font-size:var(--cb-text-sm)}.cb-table__th,.cb-table__td,.cb-table__sel{padding:var(--cb-space-3) var(--cb-space-4);text-align:left;border-bottom:var(--cb-border-width) solid var(--cb-color-border);vertical-align:middle}.cb-table--sm .cb-table__th,.cb-table--sm .cb-table__td,.cb-table--sm .cb-table__sel{padding:var(--cb-space-2) var(--cb-space-3)}.cb-table--lg .cb-table__th,.cb-table--lg .cb-table__td,.cb-table--lg .cb-table__sel{padding:var(--cb-space-4) var(--cb-space-5)}.cb-table thead .cb-table__th,.cb-table thead .cb-table__sel{background-color:var(--cb-color-surface-
|
|
747
|
+
`, isInline: true, styles: [":host{display:block;font-family:var(--cb-font-sans);color:var(--cb-color-text)}.cb-table__wrap{overflow-x:auto;border:var(--cb-border-width) solid var(--cb-color-border);border-radius:var(--cb-radius-md)}.cb-table{width:100%;border-collapse:collapse;font-size:var(--cb-text-sm)}.cb-table__th,.cb-table__td,.cb-table__sel{padding:var(--cb-space-3) var(--cb-space-4);text-align:left;border-bottom:var(--cb-border-width) solid var(--cb-color-border);vertical-align:middle}.cb-table--sm .cb-table__th,.cb-table--sm .cb-table__td,.cb-table--sm .cb-table__sel{padding:var(--cb-space-2) var(--cb-space-3)}.cb-table--lg .cb-table__th,.cb-table--lg .cb-table__td,.cb-table--lg .cb-table__sel{padding:var(--cb-space-4) var(--cb-space-5)}.cb-table thead .cb-table__th,.cb-table thead .cb-table__sel{background-color:var(--cb-color-surface-subtle);color:var(--cb-color-text);font-weight:var(--cb-font-weight-semibold);white-space:nowrap;border-bottom-width:2px}.cb-table__th-inner{display:inline-flex;align-items:center;gap:var(--cb-space-1)}.cb-table__th{position:relative}.cb-table__th.cb-is-sortable:hover{background-color:var(--cb-color-surface-hover)}.cb-table__sort-btn{margin:0;padding:0;font:inherit;color:inherit;text-align:inherit;background:none;border:none;border-radius:var(--cb-radius-sm);cursor:pointer;-webkit-user-select:none;user-select:none}.cb-table__sort-btn:focus-visible{outline:2px solid var(--cb-color-focus-ring);outline-offset:2px}.cb-table--resizable{table-layout:fixed}.cb-table--resizable .cb-table__th{overflow:hidden;text-overflow:ellipsis}.cb-table__resizer{position:absolute;top:0;right:0;width:.5rem;height:100%;cursor:col-resize;touch-action:none}.cb-table__resizer:after{content:\"\";position:absolute;top:25%;right:.2rem;width:2px;height:50%;background-color:var(--cb-color-border-strong);border-radius:1px}.cb-table__resizer:hover:after,.cb-table__resizer:focus-visible:after{background-color:var(--cb-color-primary-500)}.cb-table__resizer:focus-visible{outline:2px solid var(--cb-color-focus-ring);outline-offset:-2px}.cb-table__filter-row td{padding:var(--cb-space-2) var(--cb-space-4);background-color:var(--cb-color-surface-subtle);border-bottom:var(--cb-border-width) solid var(--cb-color-border)}.cb-table__filter{box-sizing:border-box;width:100%;min-width:6rem;padding:var(--cb-space-1) var(--cb-space-2);font:inherit;font-size:var(--cb-text-sm);color:var(--cb-color-text);background-color:var(--cb-color-surface-0);border:var(--cb-border-width) solid var(--cb-color-border-strong);border-radius:var(--cb-radius-sm)}.cb-table__filter:focus-visible{outline:2px solid var(--cb-color-focus-ring);outline-offset:1px}.cb-table__expander{display:inline-flex;align-items:center;justify-content:center;width:1.75rem;height:1.75rem;padding:0;color:var(--cb-color-text-muted);background:none;border:none;border-radius:var(--cb-radius-sm);cursor:pointer}.cb-table__expander:hover{background-color:var(--cb-color-surface-hover)}.cb-table__expander:focus-visible{outline:2px solid var(--cb-color-focus-ring);outline-offset:1px}.cb-table__expansion>td{padding:var(--cb-space-4);background-color:var(--cb-color-surface-subtle);border-bottom:var(--cb-border-width) solid var(--cb-color-border)}.cb-table__sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.cb-table__sort{color:var(--cb-color-text-muted)}.cb-table tbody tr:last-child .cb-table__td,.cb-table tbody tr:last-child .cb-table__sel{border-bottom:none}.cb-table--striped tbody tr:nth-child(2n){background-color:var(--cb-color-surface-subtle)}.cb-table--hover tbody .cb-table__row:hover{background-color:var(--cb-color-surface-hover)}.cb-table__row.cb-is-selectable{cursor:pointer}.cb-table__row.cb-is-selected{background-color:var(--cb-color-primary-50)!important}.cb-table__sel{width:1px;white-space:nowrap}.cb-table__check{display:inline-flex;align-items:center;justify-content:center;width:1.1rem;height:1.1rem;border:var(--cb-border-width) solid var(--cb-color-border-strong);border-radius:var(--cb-radius-sm);color:var(--cb-color-primary-contrast);outline:none}.cb-table__check:focus-visible{box-shadow:0 0 0 3px var(--cb-color-focus-ring)}.cb-table__check.cb-is-checked,.cb-table__check.cb-is-mixed{background-color:var(--cb-color-primary-500);border-color:var(--cb-color-primary-500)}.cb-table__check--radio{border-radius:50%}.cb-table__empty{padding:var(--cb-space-6);text-align:center;color:var(--cb-color-text-muted)}.cb-table__paginator{margin-top:var(--cb-space-3)}:host-context([data-theme=\"dark\"]) .cb-table__row.cb-is-selected{background-color:color-mix(in srgb,var(--cb-color-primary-500) 20%,transparent)!important}.cb-table__wrap{position:relative}.cb-table__wrap--scroll{overflow:auto}.cb-table--scroll thead{position:sticky;top:0;z-index:2}.cb-is-frozen{position:sticky;z-index:1;background-color:var(--cb-color-surface-raised)}thead .cb-is-frozen{z-index:3;background-color:var(--cb-color-surface-subtle)}.cb-table--striped tbody tr:nth-child(2n) .cb-is-frozen{background-color:var(--cb-color-surface-subtle)}.cb-table--hover tbody .cb-table__row:hover .cb-is-frozen{background-color:var(--cb-color-surface-hover)}.cb-is-frozen-last{box-shadow:4px 0 6px -4px #00000040}.cb-table__group>th{padding:var(--cb-space-2) var(--cb-space-4);font-size:var(--cb-text-sm);font-weight:var(--cb-font-weight-semibold);text-align:left;color:var(--cb-color-text-strong);background-color:var(--cb-color-surface-subtle);border-bottom:var(--cb-border-width) solid var(--cb-color-border)}.cb-table__group-count{font-weight:var(--cb-font-weight-normal, 400);color:var(--cb-color-text-muted)}.cb-table__loading{position:absolute;inset:0;z-index:4;display:flex;align-items:center;justify-content:center;color:var(--cb-color-primary-500);background-color:color-mix(in srgb,var(--cb-color-surface-raised) 65%,transparent)}\n"], dependencies: [{ kind: "component", type: CbIcon, selector: "cb-icon", inputs: ["name", "size", "spin", "ariaLabel"] }, { kind: "component", type: CbPaginator, selector: "cb-paginator", inputs: ["totalRecords", "rows", "first", "rowsPerPageOptions", "showReport", "maxPageLinks"], outputs: ["rowsChange", "firstChange", "pageChange"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
276
748
|
}
|
|
277
749
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: CbTable, decorators: [{
|
|
278
750
|
type: Component,
|
|
279
751
|
args: [{ selector: 'cb-table', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.Emulated, imports: [CbIcon, CbPaginator, NgTemplateOutlet], host: { class: 'cb-table-host' }, template: `
|
|
280
|
-
<
|
|
281
|
-
|
|
752
|
+
<ng-content select="[cbTableHeader]" />
|
|
753
|
+
<div class="cb-table__wrap" [class.cb-table__wrap--scroll]="!!scrollHeight()" [style.max-height]="scrollHeight()">
|
|
754
|
+
<table
|
|
755
|
+
#table
|
|
756
|
+
class="cb-table"
|
|
757
|
+
[class]="'cb-table--' + size()"
|
|
758
|
+
[class.cb-table--striped]="striped()"
|
|
759
|
+
[class.cb-table--hover]="rowHover()"
|
|
760
|
+
[class.cb-table--resizable]="resizableColumns()"
|
|
761
|
+
[class.cb-table--scroll]="!!scrollHeight()"
|
|
762
|
+
[attr.aria-label]="ariaLabel() || null"
|
|
763
|
+
[attr.aria-busy]="loading() || null"
|
|
764
|
+
>
|
|
282
765
|
<thead>
|
|
283
766
|
<tr>
|
|
767
|
+
@if (expansion()) {
|
|
768
|
+
<th class="cb-table__sel" scope="col" data-key="__exp" [class.cb-is-frozen]="hasFrozen()" [style.left.px]="frozenLeft('__exp')">
|
|
769
|
+
<span class="cb-table__sr">{{ t().details }}</span>
|
|
770
|
+
</th>
|
|
771
|
+
}
|
|
284
772
|
@if (selectionMode() === 'multiple') {
|
|
285
|
-
<th class="cb-table__sel">
|
|
773
|
+
<th class="cb-table__sel" scope="col" data-key="__sel" [class.cb-is-frozen]="hasFrozen()" [style.left.px]="frozenLeft('__sel')">
|
|
286
774
|
<span
|
|
287
775
|
class="cb-table__check"
|
|
288
776
|
[class.cb-is-checked]="allSelected()"
|
|
777
|
+
[class.cb-is-mixed]="someSelected()"
|
|
289
778
|
role="checkbox"
|
|
290
|
-
[attr.aria-checked]="allSelected()"
|
|
779
|
+
[attr.aria-checked]="allSelected() ? 'true' : someSelected() ? 'mixed' : 'false'"
|
|
780
|
+
[attr.aria-label]="t().selectAllRows"
|
|
291
781
|
tabindex="0"
|
|
292
782
|
(click)="toggleAll()"
|
|
293
|
-
(keydown.enter)="toggleAll()"
|
|
294
783
|
(keydown.space)="toggleAll(); $event.preventDefault()"
|
|
295
784
|
>
|
|
296
|
-
@if (allSelected()) {
|
|
785
|
+
@if (allSelected()) {
|
|
786
|
+
<cb-icon name="check" [size]="13" aria-hidden="true" />
|
|
787
|
+
} @else if (someSelected()) {
|
|
788
|
+
<cb-icon name="minus" [size]="13" aria-hidden="true" />
|
|
789
|
+
}
|
|
297
790
|
</span>
|
|
298
791
|
</th>
|
|
299
792
|
} @else if (selectionMode() === 'single') {
|
|
300
|
-
<th class="cb-table__sel"
|
|
793
|
+
<th class="cb-table__sel" scope="col" data-key="__sel" [class.cb-is-frozen]="hasFrozen()" [style.left.px]="frozenLeft('__sel')">
|
|
794
|
+
<span class="cb-table__sr">{{ t().select }}</span>
|
|
795
|
+
</th>
|
|
301
796
|
}
|
|
302
|
-
@for (col of
|
|
797
|
+
@for (col of displayColumns(); track col.field) {
|
|
303
798
|
<th
|
|
304
799
|
class="cb-table__th"
|
|
800
|
+
scope="col"
|
|
801
|
+
[attr.data-key]="col.field"
|
|
802
|
+
[class.cb-is-frozen]="!!col.frozen"
|
|
803
|
+
[class.cb-is-frozen-last]="col.field === lastFrozen()"
|
|
804
|
+
[style.left.px]="col.frozen ? frozenLeft(col.field) : null"
|
|
305
805
|
[class.cb-is-sortable]="col.sortable"
|
|
306
|
-
[style.width]="col
|
|
806
|
+
[style.width]="columnWidth(col)"
|
|
307
807
|
[style.text-align]="col.align || null"
|
|
308
808
|
[attr.aria-sort]="ariaSort(col)"
|
|
309
|
-
(click)="onSort(col)"
|
|
310
809
|
>
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
810
|
+
@if (col.sortable) {
|
|
811
|
+
<button
|
|
812
|
+
type="button"
|
|
813
|
+
class="cb-table__th-inner cb-table__sort-btn"
|
|
814
|
+
[attr.aria-label]="fmt(t().sortBy, col.header)"
|
|
815
|
+
(click)="onSort(col)"
|
|
816
|
+
>
|
|
817
|
+
{{ col.header }}
|
|
314
818
|
<cb-icon class="cb-table__sort" [name]="sortIcon(col)" [size]="15" aria-hidden="true" />
|
|
315
|
-
|
|
316
|
-
|
|
819
|
+
</button>
|
|
820
|
+
} @else {
|
|
821
|
+
<span class="cb-table__th-inner">{{ col.header }}</span>
|
|
822
|
+
}
|
|
823
|
+
@if (resizableColumns()) {
|
|
824
|
+
<span
|
|
825
|
+
class="cb-table__resizer"
|
|
826
|
+
role="separator"
|
|
827
|
+
aria-orientation="vertical"
|
|
828
|
+
tabindex="0"
|
|
829
|
+
[attr.aria-label]="fmt(t().resizeColumn, col.header)"
|
|
830
|
+
[attr.aria-valuenow]="widths()[col.field] ?? null"
|
|
831
|
+
[attr.aria-valuemin]="minColumnWidth"
|
|
832
|
+
(pointerdown)="startResize($event, col)"
|
|
833
|
+
(keydown)="onResizerKeydown($event, col)"
|
|
834
|
+
></span>
|
|
835
|
+
}
|
|
317
836
|
</th>
|
|
318
837
|
}
|
|
319
838
|
</tr>
|
|
839
|
+
@if (hasColumnFilters()) {
|
|
840
|
+
<tr class="cb-table__filter-row">
|
|
841
|
+
@if (expansion()) {
|
|
842
|
+
<td class="cb-table__sel" [class.cb-is-frozen]="hasFrozen()" [style.left.px]="frozenLeft('__exp')"></td>
|
|
843
|
+
}
|
|
844
|
+
@if (selectionMode()) {
|
|
845
|
+
<td class="cb-table__sel" [class.cb-is-frozen]="hasFrozen()" [style.left.px]="frozenLeft('__sel')"></td>
|
|
846
|
+
}
|
|
847
|
+
@for (col of displayColumns(); track col.field) {
|
|
848
|
+
<td
|
|
849
|
+
class="cb-table__filter-cell"
|
|
850
|
+
[class.cb-is-frozen]="!!col.frozen"
|
|
851
|
+
[class.cb-is-frozen-last]="col.field === lastFrozen()"
|
|
852
|
+
[style.left.px]="col.frozen ? frozenLeft(col.field) : null"
|
|
853
|
+
>
|
|
854
|
+
@if (col.filter) {
|
|
855
|
+
<input
|
|
856
|
+
type="search"
|
|
857
|
+
class="cb-table__filter"
|
|
858
|
+
[value]="columnFilters()[col.field] ?? ''"
|
|
859
|
+
[placeholder]="col.filterPlaceholder ?? t().search"
|
|
860
|
+
[attr.aria-label]="fmt(t().filterBy, col.header)"
|
|
861
|
+
(input)="filterColumn(col.field, $any($event.target).value)"
|
|
862
|
+
/>
|
|
863
|
+
}
|
|
864
|
+
</td>
|
|
865
|
+
}
|
|
866
|
+
</tr>
|
|
867
|
+
}
|
|
320
868
|
</thead>
|
|
321
869
|
<tbody>
|
|
322
|
-
@for (row of pageRows(); track rowKey(row, $index)) {
|
|
870
|
+
@for (row of pageRows(); track rowKey(row, $index); let i = $index) {
|
|
871
|
+
@if (groupRowsBy() && isGroupStart(i)) {
|
|
872
|
+
<tr class="cb-table__group">
|
|
873
|
+
<th scope="rowgroup" [attr.colspan]="colspan()">
|
|
874
|
+
@if (groupHeader(); as gh) {
|
|
875
|
+
<ng-container
|
|
876
|
+
[ngTemplateOutlet]="gh.template"
|
|
877
|
+
[ngTemplateOutletContext]="{ $implicit: groupOf(row), count: groupCount(row) }"
|
|
878
|
+
/>
|
|
879
|
+
} @else {
|
|
880
|
+
{{ groupOf(row) }} <span class="cb-table__group-count">({{ groupCount(row) }})</span>
|
|
881
|
+
}
|
|
882
|
+
</th>
|
|
883
|
+
</tr>
|
|
884
|
+
}
|
|
323
885
|
<tr
|
|
324
886
|
class="cb-table__row"
|
|
325
887
|
[class.cb-is-selected]="isSelected(row)"
|
|
326
888
|
[class.cb-is-selectable]="!!selectionMode()"
|
|
327
889
|
(click)="onRowClick(row)"
|
|
328
890
|
>
|
|
891
|
+
@if (expansion()) {
|
|
892
|
+
<td class="cb-table__sel" [class.cb-is-frozen]="hasFrozen()" [style.left.px]="frozenLeft('__exp')">
|
|
893
|
+
<button
|
|
894
|
+
type="button"
|
|
895
|
+
class="cb-table__expander"
|
|
896
|
+
[attr.aria-expanded]="isExpanded(row)"
|
|
897
|
+
[attr.aria-controls]="isExpanded(row) ? expansionId(first() + i) : null"
|
|
898
|
+
[attr.aria-label]="fmt(t().expandRow, first() + i + 1)"
|
|
899
|
+
(click)="toggleExpansion(row); $event.stopPropagation()"
|
|
900
|
+
>
|
|
901
|
+
<cb-icon [name]="isExpanded(row) ? 'chevron-down' : 'chevron-right'" [size]="15" aria-hidden="true" />
|
|
902
|
+
</button>
|
|
903
|
+
</td>
|
|
904
|
+
}
|
|
329
905
|
@if (selectionMode()) {
|
|
330
|
-
<td class="cb-table__sel">
|
|
331
|
-
<span
|
|
332
|
-
|
|
906
|
+
<td class="cb-table__sel" [class.cb-is-frozen]="hasFrozen()" [style.left.px]="frozenLeft('__sel')">
|
|
907
|
+
<span
|
|
908
|
+
class="cb-table__check"
|
|
909
|
+
[class.cb-table__check--radio]="selectionMode() === 'single'"
|
|
910
|
+
[class.cb-is-checked]="isSelected(row)"
|
|
911
|
+
[attr.role]="selectionMode() === 'single' ? 'radio' : 'checkbox'"
|
|
912
|
+
[attr.aria-checked]="isSelected(row)"
|
|
913
|
+
[attr.aria-label]="fmt(t().selectRow, first() + i + 1)"
|
|
914
|
+
tabindex="0"
|
|
915
|
+
(keydown.space)="onRowClick(row); $event.preventDefault()"
|
|
916
|
+
>
|
|
917
|
+
@if (isSelected(row)) {
|
|
918
|
+
<cb-icon name="check" [size]="13" aria-hidden="true" />
|
|
919
|
+
}
|
|
333
920
|
</span>
|
|
334
921
|
</td>
|
|
335
922
|
}
|
|
336
|
-
@for (col of
|
|
337
|
-
<td
|
|
923
|
+
@for (col of displayColumns(); track col.field) {
|
|
924
|
+
<td
|
|
925
|
+
class="cb-table__td"
|
|
926
|
+
[class.cb-is-frozen]="!!col.frozen"
|
|
927
|
+
[class.cb-is-frozen-last]="col.field === lastFrozen()"
|
|
928
|
+
[style.left.px]="col.frozen ? frozenLeft(col.field) : null"
|
|
929
|
+
[style.text-align]="col.align || null"
|
|
930
|
+
>
|
|
338
931
|
@if (cellTemplate(col.field); as cell) {
|
|
339
|
-
<ng-container
|
|
340
|
-
[ngTemplateOutlet]="cell.template"
|
|
341
|
-
[ngTemplateOutletContext]="cellContext(row, col)"
|
|
342
|
-
/>
|
|
932
|
+
<ng-container [ngTemplateOutlet]="cell.template" [ngTemplateOutletContext]="cellContext(row, col)" />
|
|
343
933
|
} @else {
|
|
344
934
|
{{ cellValue(row, col) }}
|
|
345
935
|
}
|
|
346
936
|
</td>
|
|
347
937
|
}
|
|
348
938
|
</tr>
|
|
939
|
+
@if (expansion(); as exp) {
|
|
940
|
+
@if (isExpanded(row)) {
|
|
941
|
+
<tr class="cb-table__expansion" [id]="expansionId(first() + i)">
|
|
942
|
+
<td [attr.colspan]="colspan()">
|
|
943
|
+
<ng-container
|
|
944
|
+
[ngTemplateOutlet]="exp.template"
|
|
945
|
+
[ngTemplateOutletContext]="{ $implicit: row, index: first() + i }"
|
|
946
|
+
/>
|
|
947
|
+
</td>
|
|
948
|
+
</tr>
|
|
949
|
+
}
|
|
950
|
+
}
|
|
349
951
|
} @empty {
|
|
350
952
|
<tr>
|
|
351
|
-
<td class="cb-table__empty" [attr.colspan]="colspan()">{{ emptyMessage() }}</td>
|
|
953
|
+
<td class="cb-table__empty" [attr.colspan]="colspan()">{{ (emptyMessage() ?? t().noData) }}</td>
|
|
352
954
|
</tr>
|
|
353
955
|
}
|
|
354
956
|
</tbody>
|
|
355
957
|
</table>
|
|
958
|
+
@if (loading()) {
|
|
959
|
+
<div class="cb-table__loading" role="status">
|
|
960
|
+
<cb-icon name="loader" [size]="22" [spin]="true" aria-hidden="true" />
|
|
961
|
+
<span class="cb-table__sr">{{ t().loading }}</span>
|
|
962
|
+
</div>
|
|
963
|
+
}
|
|
356
964
|
</div>
|
|
965
|
+
@if (isFiltering()) {
|
|
966
|
+
<span class="cb-table__sr" aria-live="polite">{{ fmt(t().resultsCount, total()) }}</span>
|
|
967
|
+
}
|
|
357
968
|
|
|
358
969
|
@if (paginator()) {
|
|
359
970
|
<cb-paginator
|
|
360
971
|
class="cb-table__paginator"
|
|
361
|
-
[totalRecords]="
|
|
972
|
+
[totalRecords]="total()"
|
|
362
973
|
[(first)]="first"
|
|
363
974
|
[(rows)]="rows"
|
|
364
975
|
[rowsPerPageOptions]="rowsPerPageOptions()"
|
|
365
976
|
(pageChange)="onPageChange($event)"
|
|
366
977
|
/>
|
|
367
978
|
}
|
|
368
|
-
`, styles: [":host{display:block;font-family:var(--cb-font-sans);color:var(--cb-color-text)}.cb-table__wrap{overflow-x:auto;border:var(--cb-border-width) solid var(--cb-color-border);border-radius:var(--cb-radius-md)}.cb-table{width:100%;border-collapse:collapse;font-size:var(--cb-text-sm)}.cb-table__th,.cb-table__td,.cb-table__sel{padding:var(--cb-space-3) var(--cb-space-4);text-align:left;border-bottom:var(--cb-border-width) solid var(--cb-color-border);vertical-align:middle}.cb-table--sm .cb-table__th,.cb-table--sm .cb-table__td,.cb-table--sm .cb-table__sel{padding:var(--cb-space-2) var(--cb-space-3)}.cb-table--lg .cb-table__th,.cb-table--lg .cb-table__td,.cb-table--lg .cb-table__sel{padding:var(--cb-space-4) var(--cb-space-5)}.cb-table thead .cb-table__th,.cb-table thead .cb-table__sel{background-color:var(--cb-color-surface-
|
|
369
|
-
}], propDecorators: { cellTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => CbTableCellDirective), { isSignal: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], paginator: [{ type: i0.Input, args: [{ isSignal: true, alias: "paginator", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }, { type: i0.Output, args: ["rowsChange"] }], rowsPerPageOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowsPerPageOptions", required: false }] }], striped: [{ type: i0.Input, args: [{ isSignal: true, alias: "striped", required: false }] }], rowHover: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHover", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], selectionMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionMode", required: false }] }], dataKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataKey", required: false }] }], selection: [{ type: i0.Input, args: [{ isSignal: true, alias: "selection", required: false }] }, { type: i0.Output, args: ["selectionChange"] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }] } });
|
|
979
|
+
`, styles: [":host{display:block;font-family:var(--cb-font-sans);color:var(--cb-color-text)}.cb-table__wrap{overflow-x:auto;border:var(--cb-border-width) solid var(--cb-color-border);border-radius:var(--cb-radius-md)}.cb-table{width:100%;border-collapse:collapse;font-size:var(--cb-text-sm)}.cb-table__th,.cb-table__td,.cb-table__sel{padding:var(--cb-space-3) var(--cb-space-4);text-align:left;border-bottom:var(--cb-border-width) solid var(--cb-color-border);vertical-align:middle}.cb-table--sm .cb-table__th,.cb-table--sm .cb-table__td,.cb-table--sm .cb-table__sel{padding:var(--cb-space-2) var(--cb-space-3)}.cb-table--lg .cb-table__th,.cb-table--lg .cb-table__td,.cb-table--lg .cb-table__sel{padding:var(--cb-space-4) var(--cb-space-5)}.cb-table thead .cb-table__th,.cb-table thead .cb-table__sel{background-color:var(--cb-color-surface-subtle);color:var(--cb-color-text);font-weight:var(--cb-font-weight-semibold);white-space:nowrap;border-bottom-width:2px}.cb-table__th-inner{display:inline-flex;align-items:center;gap:var(--cb-space-1)}.cb-table__th{position:relative}.cb-table__th.cb-is-sortable:hover{background-color:var(--cb-color-surface-hover)}.cb-table__sort-btn{margin:0;padding:0;font:inherit;color:inherit;text-align:inherit;background:none;border:none;border-radius:var(--cb-radius-sm);cursor:pointer;-webkit-user-select:none;user-select:none}.cb-table__sort-btn:focus-visible{outline:2px solid var(--cb-color-focus-ring);outline-offset:2px}.cb-table--resizable{table-layout:fixed}.cb-table--resizable .cb-table__th{overflow:hidden;text-overflow:ellipsis}.cb-table__resizer{position:absolute;top:0;right:0;width:.5rem;height:100%;cursor:col-resize;touch-action:none}.cb-table__resizer:after{content:\"\";position:absolute;top:25%;right:.2rem;width:2px;height:50%;background-color:var(--cb-color-border-strong);border-radius:1px}.cb-table__resizer:hover:after,.cb-table__resizer:focus-visible:after{background-color:var(--cb-color-primary-500)}.cb-table__resizer:focus-visible{outline:2px solid var(--cb-color-focus-ring);outline-offset:-2px}.cb-table__filter-row td{padding:var(--cb-space-2) var(--cb-space-4);background-color:var(--cb-color-surface-subtle);border-bottom:var(--cb-border-width) solid var(--cb-color-border)}.cb-table__filter{box-sizing:border-box;width:100%;min-width:6rem;padding:var(--cb-space-1) var(--cb-space-2);font:inherit;font-size:var(--cb-text-sm);color:var(--cb-color-text);background-color:var(--cb-color-surface-0);border:var(--cb-border-width) solid var(--cb-color-border-strong);border-radius:var(--cb-radius-sm)}.cb-table__filter:focus-visible{outline:2px solid var(--cb-color-focus-ring);outline-offset:1px}.cb-table__expander{display:inline-flex;align-items:center;justify-content:center;width:1.75rem;height:1.75rem;padding:0;color:var(--cb-color-text-muted);background:none;border:none;border-radius:var(--cb-radius-sm);cursor:pointer}.cb-table__expander:hover{background-color:var(--cb-color-surface-hover)}.cb-table__expander:focus-visible{outline:2px solid var(--cb-color-focus-ring);outline-offset:1px}.cb-table__expansion>td{padding:var(--cb-space-4);background-color:var(--cb-color-surface-subtle);border-bottom:var(--cb-border-width) solid var(--cb-color-border)}.cb-table__sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.cb-table__sort{color:var(--cb-color-text-muted)}.cb-table tbody tr:last-child .cb-table__td,.cb-table tbody tr:last-child .cb-table__sel{border-bottom:none}.cb-table--striped tbody tr:nth-child(2n){background-color:var(--cb-color-surface-subtle)}.cb-table--hover tbody .cb-table__row:hover{background-color:var(--cb-color-surface-hover)}.cb-table__row.cb-is-selectable{cursor:pointer}.cb-table__row.cb-is-selected{background-color:var(--cb-color-primary-50)!important}.cb-table__sel{width:1px;white-space:nowrap}.cb-table__check{display:inline-flex;align-items:center;justify-content:center;width:1.1rem;height:1.1rem;border:var(--cb-border-width) solid var(--cb-color-border-strong);border-radius:var(--cb-radius-sm);color:var(--cb-color-primary-contrast);outline:none}.cb-table__check:focus-visible{box-shadow:0 0 0 3px var(--cb-color-focus-ring)}.cb-table__check.cb-is-checked,.cb-table__check.cb-is-mixed{background-color:var(--cb-color-primary-500);border-color:var(--cb-color-primary-500)}.cb-table__check--radio{border-radius:50%}.cb-table__empty{padding:var(--cb-space-6);text-align:center;color:var(--cb-color-text-muted)}.cb-table__paginator{margin-top:var(--cb-space-3)}:host-context([data-theme=\"dark\"]) .cb-table__row.cb-is-selected{background-color:color-mix(in srgb,var(--cb-color-primary-500) 20%,transparent)!important}.cb-table__wrap{position:relative}.cb-table__wrap--scroll{overflow:auto}.cb-table--scroll thead{position:sticky;top:0;z-index:2}.cb-is-frozen{position:sticky;z-index:1;background-color:var(--cb-color-surface-raised)}thead .cb-is-frozen{z-index:3;background-color:var(--cb-color-surface-subtle)}.cb-table--striped tbody tr:nth-child(2n) .cb-is-frozen{background-color:var(--cb-color-surface-subtle)}.cb-table--hover tbody .cb-table__row:hover .cb-is-frozen{background-color:var(--cb-color-surface-hover)}.cb-is-frozen-last{box-shadow:4px 0 6px -4px #00000040}.cb-table__group>th{padding:var(--cb-space-2) var(--cb-space-4);font-size:var(--cb-text-sm);font-weight:var(--cb-font-weight-semibold);text-align:left;color:var(--cb-color-text-strong);background-color:var(--cb-color-surface-subtle);border-bottom:var(--cb-border-width) solid var(--cb-color-border)}.cb-table__group-count{font-weight:var(--cb-font-weight-normal, 400);color:var(--cb-color-text-muted)}.cb-table__loading{position:absolute;inset:0;z-index:4;display:flex;align-items:center;justify-content:center;color:var(--cb-color-primary-500);background-color:color-mix(in srgb,var(--cb-color-surface-raised) 65%,transparent)}\n"] }]
|
|
980
|
+
}], ctorParameters: () => [], propDecorators: { cellTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => CbTableCellDirective), { isSignal: true }] }], expansion: [{ type: i0.ContentChild, args: [i0.forwardRef(() => CbTableRowExpansion), { isSignal: true }] }], groupHeader: [{ type: i0.ContentChild, args: [i0.forwardRef(() => CbTableGroupHeader), { isSignal: true }] }], tableRef: [{ type: i0.ViewChild, args: ['table', { isSignal: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], paginator: [{ type: i0.Input, args: [{ isSignal: true, alias: "paginator", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }, { type: i0.Output, args: ["rowsChange"] }], rowsPerPageOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowsPerPageOptions", required: false }] }], striped: [{ type: i0.Input, args: [{ isSignal: true, alias: "striped", required: false }] }], rowHover: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHover", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], selectionMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionMode", required: false }] }], dataKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataKey", required: false }] }], globalFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "globalFilter", required: false }] }, { type: i0.Output, args: ["globalFilterChange"] }], globalFilterFields: [{ type: i0.Input, args: [{ isSignal: true, alias: "globalFilterFields", required: false }] }], resizableColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "resizableColumns", required: false }] }], expandedRowKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandedRowKeys", required: false }] }, { type: i0.Output, args: ["expandedRowKeysChange"] }], scrollHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollHeight", required: false }] }], groupRowsBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupRowsBy", required: false }] }], lazy: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazy", required: false }] }], totalRecords: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalRecords", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], selection: [{ type: i0.Input, args: [{ isSignal: true, alias: "selection", required: false }] }, { type: i0.Output, args: ["selectionChange"] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], filterChange: [{ type: i0.Output, args: ["filterChange"] }], columnResize: [{ type: i0.Output, args: ["columnResize"] }], rowExpand: [{ type: i0.Output, args: ["rowExpand"] }], rowCollapse: [{ type: i0.Output, args: ["rowCollapse"] }], lazyLoad: [{ type: i0.Output, args: ["lazyLoad"] }] } });
|
|
370
981
|
function toBoolean(value) {
|
|
371
982
|
return value !== false && value != null && `${value}` !== 'false';
|
|
372
983
|
}
|
|
984
|
+
function fieldValue(row, field) {
|
|
985
|
+
return row != null && typeof row === 'object' ? row[field] : row;
|
|
986
|
+
}
|
|
987
|
+
/** Minúsculas y sin tildes, para que "jose" encuentre "José". */
|
|
988
|
+
function normalize(text) {
|
|
989
|
+
return String(text ?? '')
|
|
990
|
+
.normalize('NFD')
|
|
991
|
+
.replace(/[̀-ͯ]/g, '')
|
|
992
|
+
.toLocaleLowerCase()
|
|
993
|
+
.trim();
|
|
994
|
+
}
|
|
995
|
+
function matches(value, text, mode) {
|
|
996
|
+
const v = normalize(value);
|
|
997
|
+
return mode === 'equals' ? v === text : mode === 'startsWith' ? v.startsWith(text) : v.includes(text);
|
|
998
|
+
}
|
|
373
999
|
|
|
374
1000
|
/*
|
|
375
1001
|
* Public API Surface de @caribeng/ui/table
|
|
@@ -379,4 +1005,4 @@ function toBoolean(value) {
|
|
|
379
1005
|
* Generated bundle index. Do not edit.
|
|
380
1006
|
*/
|
|
381
1007
|
|
|
382
|
-
export { CbTable, CbTableCellDirective };
|
|
1008
|
+
export { CbTable, CbTableCellDirective, CbTableGroupHeader, CbTableRowExpansion };
|