ngx-gem-spaas
Version:
This library contains services, components, images and styles to provide a unified look and way-of-working throughout GEM SPaaS.
829 lines • 53.5 kB
JavaScript
import * as i0 from '@angular/core';
import { EventEmitter, Directive, Input, Output, HostListener, Component, ViewChild, ContentChildren, NgModule } from '@angular/core';
import { Subject, debounceTime } from 'rxjs';
import { BaseComponent, UtilsService } from 'ngx-gem-spaas';
import { takeUntil } from 'rxjs/operators';
import * as i1 from '@angular/common';
import { CommonModule } from '@angular/common';
import * as i2 from '@angular/material/icon';
import { MatIconModule } from '@angular/material/icon';
import * as i3 from '@angular/material/sort';
import { MatSortModule } from '@angular/material/sort';
import * as i4 from '@angular/material/tooltip';
import { MatTooltipModule } from '@angular/material/tooltip';
import * as i5 from '@angular/cdk/scrolling';
import { ScrollingModule } from '@angular/cdk/scrolling';
import * as i6 from '@angular/forms';
import { FormGroup, FormControl, ReactiveFormsModule } from '@angular/forms';
import * as i2$1 from '@angular/material/form-field';
import { MatFormFieldModule } from '@angular/material/form-field';
import * as i3$1 from '@angular/material/input';
import { MatInputModule } from '@angular/material/input';
import * as i4$1 from '@angular/material/select';
import { MatSelectModule } from '@angular/material/select';
import * as i5$1 from '@angular/material/core';
class TableSelectionFreeDirective {
constructor() {
this.freeSelectionMatrix = [];
this.freeSelectionLockAxis = '';
this.selectionChanged = new EventEmitter(); // will emit the last selected row and column
this.isSelecting = false;
this.selectionId = 1;
// set the from/to variables to public because it's very handy to be able to access these directly in the template
this.fromCol = 0;
this.fromRow = 0;
this.toCol = 0;
this.toRow = 0;
this.onDestroy = new Subject();
}
mouseDown(e) {
const mouseData = this.checkMouseData(e);
if (mouseData.valid) {
this.onClickCell(e, mouseData.rowIdx, mouseData.colIdx);
}
}
mouseMove(e) {
const mouseData = this.checkMouseData(e);
if (this.isSelecting &&
mouseData.valid &&
(mouseData.rowIdx !== this.toRow || mouseData.colIdx !== this.toCol)) {
this.onSelecting(mouseData.rowIdx, mouseData.colIdx);
}
}
mouseUp() {
this.onStopSelect('mouseup');
}
mouseLeave() {
this.onStopSelect('mouseleave');
}
sort() {
this.resetSelectionRange(true, true);
this.emitNewSelection();
}
ngOnDestroy() {
this.onDestroy.next();
this.onDestroy.complete();
}
checkMouseData(e) {
const target = (e.target);
let dataset = target?.dataset;
if (!dataset?.rowIdx) {
// also check the offsetParent, for cells with sub-divs
dataset = (target?.offsetParent).dataset;
}
let rowIdx = -1, colIdx = -1;
if (dataset?.rowIdx && dataset.colIdx) {
rowIdx = Number.isNaN((Number(dataset.rowIdx))) ? -1 : Number(dataset.rowIdx);
colIdx = Number.isNaN((Number(dataset.colIdx))) ? -1 : Number(dataset.colIdx);
}
return {
valid: rowIdx > -1 && colIdx > -1,
rowIdx: rowIdx,
colIdx: colIdx
};
}
onClickCell(e, rowIdx, colIdx) {
if (!e) {
return;
}
this.isSelecting = true;
if (!e.shiftKey && !e.ctrlKey) {
// normal click: update all selection variables
++this.selectionId;
this.fromRow = rowIdx;
this.fromCol = colIdx;
this.toRow = rowIdx;
this.toCol = colIdx;
this.resetSelectionRange(true);
}
else if (e.shiftKey) {
// shift click: set last variables for range selection
document.getSelection()?.removeAllRanges();
this.setTo(rowIdx, colIdx);
this.updateSelectionRange();
}
else if (e.ctrlKey) {
// ctrl-click in non-origin row/col and lock-axis is active: reset all (considered a regular click in this case)
if ((this.freeSelectionLockAxis === 'x' && rowIdx !== this.fromRow) ||
(this.freeSelectionLockAxis === 'y' && colIdx !== this.fromCol)) {
this.resetSelectionRange(true);
}
// ctrl key: just set for cell itself
++this.selectionId;
this.freeSelectionMatrix[rowIdx][colIdx] = !this.freeSelectionMatrix[rowIdx][colIdx] ? this.selectionId : 0;
if (this.freeSelectionMatrix[rowIdx][colIdx]) {
this.fromRow = rowIdx;
this.fromCol = colIdx;
this.setTo(rowIdx, colIdx);
}
else {
// it's a deselection: search for last selected cell to put focus on
for (let row = 0; row < this.freeSelectionMatrix.length; row++) {
for (let col = 0; col < this.freeSelectionMatrix[row].length; col++) {
if (this.freeSelectionMatrix[row][col]) {
this.toRow = row;
this.toCol = col;
}
}
}
}
}
}
onSelecting(rowIdx, colIdx) {
if (this.isSelecting) {
document.getSelection()?.removeAllRanges();
this.setTo(rowIdx, colIdx);
this.resetSelectionRange();
this.updateSelectionRange();
}
}
onStopSelect(fromMouseEvent) {
if (this.isSelecting) {
this.isSelecting = false;
if (fromMouseEvent === 'mouseup') {
this.emitNewSelection();
}
}
}
emitNewSelection() {
this.selectionChanged.emit(this.freeSelectionMatrix[this.toRow][this.toCol] > 0 ?
{ row: this.toRow, column: this.toCol } :
{ row: -1, column: -1 });
}
setTo(rowIdx, colIdx) {
this.toRow = this.freeSelectionLockAxis === 'x' ? this.fromRow : rowIdx;
this.toCol = this.freeSelectionLockAxis === 'y' ? this.fromCol : colIdx;
}
resetSelectionRange(fullReset = false, fromSort = false) {
const wasSelected = this.freeSelectionMatrix[this.toRow][this.toCol] > 0;
for (let rowIdx = 0; rowIdx < this.freeSelectionMatrix.length; rowIdx++) {
for (let colIdx = 0; colIdx < this.freeSelectionMatrix[rowIdx].length; colIdx++) {
if (fullReset || this.freeSelectionMatrix[rowIdx][colIdx] === this.selectionId) {
this.freeSelectionMatrix[rowIdx][colIdx] = 0;
}
}
}
this.freeSelectionMatrix[this.toRow][this.toCol] = fromSort || wasSelected ? 0 : this.selectionId;
}
updateSelectionRange() {
const fromRow = Math.min(this.fromRow, this.toRow);
const toRow = Math.max(this.fromRow, this.toRow);
const fromCol = Math.min(this.fromCol, this.toCol);
const toCol = Math.max(this.fromCol, this.toCol);
for (let rowIdx = fromRow; rowIdx <= toRow; rowIdx++) {
for (let colIdx = fromCol; colIdx <= toCol; colIdx++) {
this.freeSelectionMatrix[rowIdx][colIdx] = this.selectionId;
}
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TableSelectionFreeDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: TableSelectionFreeDirective, selector: "[spaasTableSelectionFree]", inputs: { freeSelectionMatrix: "freeSelectionMatrix", freeSelectionLockAxis: "freeSelectionLockAxis" }, outputs: { selectionChanged: "selectionChanged" }, host: { listeners: { "mousedown": "mouseDown($event)", "mousemove": "mouseMove($event)", "mouseup": "mouseUp($event)", "mouseleave": "mouseLeave($event)", "tableSortedOrFiltered": "sort($event)" } }, exportAs: ["spaasTableSelectionFree"], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TableSelectionFreeDirective, decorators: [{
type: Directive,
args: [{
selector: '[spaasTableSelectionFree]',
exportAs: 'spaasTableSelectionFree'
}]
}], propDecorators: { freeSelectionMatrix: [{
type: Input
}], freeSelectionLockAxis: [{
type: Input
}], selectionChanged: [{
type: Output
}], mouseDown: [{
type: HostListener,
args: ['mousedown', ['$event']]
}], mouseMove: [{
type: HostListener,
args: ['mousemove', ['$event']]
}], mouseUp: [{
type: HostListener,
args: ['mouseup', ['$event']]
}], mouseLeave: [{
type: HostListener,
args: ['mouseleave', ['$event']]
}], sort: [{
type: HostListener,
args: ['tableSortedOrFiltered', ['$event']]
}] } });
class TableHeaderDirective {
constructor(templateRef) {
this.templateRef = templateRef;
this.spaasTableHeader = '';
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TableHeaderDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: TableHeaderDirective, selector: "[spaasTableHeader]", inputs: { spaasTableHeader: "spaasTableHeader" }, exportAs: ["spaasTableHeader"], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TableHeaderDirective, decorators: [{
type: Directive,
args: [{
selector: '[spaasTableHeader]',
exportAs: 'spaasTableHeader'
}]
}], ctorParameters: () => [{ type: i0.TemplateRef }], propDecorators: { spaasTableHeader: [{
type: Input
}] } });
class TableCellDirective {
constructor(templateRef) {
this.templateRef = templateRef;
this.spaasTableCell = '';
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TableCellDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: TableCellDirective, selector: "[spaasTableCell]", inputs: { spaasTableCell: "spaasTableCell" }, exportAs: ["spaasTableCell"], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TableCellDirective, decorators: [{
type: Directive,
args: [{
selector: '[spaasTableCell]',
exportAs: 'spaasTableCell'
}]
}], ctorParameters: () => [{ type: i0.TemplateRef }], propDecorators: { spaasTableCell: [{
type: Input
}] } });
class TableComponent extends BaseComponent {
constructor() {
super(...arguments);
this.tableData = [];
this.columns = [];
this.columnMaxWidth = 214;
this.freeSelectionMatrix = null;
this.rowSelectionMatrix = null;
this.orientation = 'vertical';
this.showToTop = false;
this.withSort = true;
this.filter = null;
this.align = '';
// do not just change the name of this emitter. Selection directives listen to it.
this.tableSortedOrFiltered = new EventEmitter();
this.vScroller = null;
// these shallow copies are necessary because we want to keep the reference to the parent tableData
// aka, we want the parent tableData to also get sorted and filtered
this.origData = []; // a shallow copy for the original order
this.domData = []; // a shallow copy for the DOM rendering (without this copying, the changeDetection would not fire on sort)
this.toTopActive = false;
this.scrolling$ = new Subject();
this.activeSort = null;
}
static compare(a, b, isAsc) {
const conv = isAsc ? 1 : -1;
if (typeof a === 'string' && typeof b === 'string') {
return ((a || '').toLowerCase() < (b || '').toLowerCase() ? -1 : 1) * conv;
}
return ((a || '') < (b || '') ? -1 : 1) * conv;
}
ngOnInit() {
if (this.showToTop) {
this.checkToTop();
}
if (this.filter) {
this.filter.filterChanged
.pipe(takeUntil(this.onDestroy$))
.subscribe(() => {
this.sortAndFilter();
});
}
}
ngAfterContentInit() {
for (const col of this.columns) {
// set optional booleans that should be true by default
if (!col.hasOwnProperty('withSort')) {
col.withSort = true;
}
// then set the templates, if any provided
const headerTemplate = this.headerTemplates.find((h) => h.spaasTableHeader === col.dataField);
if (headerTemplate) {
col.headerTemplate = headerTemplate.templateRef;
}
const cellTemplate = this.cellTemplates.find((h) => h.spaasTableCell === col.dataField);
if (cellTemplate) {
col.cellTemplate = cellTemplate.templateRef;
}
}
}
ngOnChanges(changes) {
if (changes.hasOwnProperty('tableData')) {
this.origData = this.tableData.slice();
this.sortAndFilter();
}
}
ngOnDestroy() {
this.resetTableData();
super.ngOnDestroy();
}
onScroll() {
this.scrolling$.next();
}
checkToTop() {
this.scrolling$
.pipe(debounceTime(400))
.subscribe(() => {
if (this.vScroller) {
this.toTopActive = (this.vScroller.getOffsetToRenderedContentStart() || 0) > 400;
}
});
}
onGoToTop() {
if (this.vScroller) {
this.vScroller.scrollToOffset(0);
}
}
onSort(matSort) {
this.activeSort = matSort;
this.sortAndFilter();
}
sortAndFilter() {
// first always reset to avoid strange sorting behaviour
this.resetTableData();
// first filter
if (this.filter?.filterString) {
// filter tableData itself, so the parent data is also filtered (necessary for selection)
const func = this.createFilterFunction(this.filter.filterString);
for (let rowIdx = 0; rowIdx < this.tableData.length; rowIdx++) {
if (!(func(this.tableData[rowIdx]))) {
this.tableData.splice(rowIdx, 1);
rowIdx--;
}
}
}
// then sort
if (this.activeSort?.active && this.activeSort?.direction) {
// sort tableData itself, so the parent data is also sorted (necessary for selection)
const isAsc = this.activeSort.direction === 'asc';
this.tableData.sort((a, b) => {
return TableComponent.compare(a[this.activeSort?.active || ''], b[this.activeSort?.active || ''], isAsc);
});
}
this.updateDomData();
this.onGoToTop();
}
;
createFilterFunction(funcBody) {
return Function.call(this, 'e', 'return ' + funcBody + ';');
}
resetTableData() {
// reset tableData to the origData order, without breaking reference with the parent data
this.tableData.length = 0;
this.tableData.push(...this.origData);
}
updateDomData() {
this.domData = this.tableData.slice();
// only emit when there is actual data...
// else it's not a real sort or filter (can't change anything to non-existing data)
if (this.origData?.length) {
// wrap it in setTimeout to avoid "expression has changed after it was checked" errors that might occur if
// the parent component is displaying the number of rows in the data (new js VM turn invoked)
setTimeout(() => {
this.tableSortedOrFiltered.emit(this.domData.length);
});
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TableComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: TableComponent, selector: "spaas-table", inputs: { tableData: "tableData", columns: "columns", columnMaxWidth: "columnMaxWidth", freeSelectionMatrix: "freeSelectionMatrix", rowSelectionMatrix: "rowSelectionMatrix", orientation: "orientation", showToTop: "showToTop", withSort: "withSort", filter: "filter", align: "align" }, outputs: { tableSortedOrFiltered: "tableSortedOrFiltered" }, queries: [{ propertyName: "headerTemplates", predicate: TableHeaderDirective }, { propertyName: "cellTemplates", predicate: TableCellDirective }], viewQueries: [{ propertyName: "vScroller", first: true, predicate: ["vScroller"], descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<div class=\"spaas-table pos-relative\">\r\n\r\n @if (orientation === 'vertical') {\r\n <div (matSortChange)=\"onSort($event)\"\r\n (scroll)=\"onScroll()\"\r\n [matSortDisabled]=\"!withSort\"\r\n cdkVirtualScrollingElement\r\n class=\"flextable by-row striped flex col {{align}}\"\r\n matSort>\r\n <!-- header row -->\r\n <div class=\"row header pos-sticky-vertical\">\r\n @for (column of columns; track column) {\r\n <div [disabled]=\"!column.withSort\"\r\n [mat-sort-header]=\"column.dataField\"\r\n class=\"cell {{column.cssClasses}}\">\r\n <ng-container [ngTemplateOutlet]=\"column.headerTemplate || NoVertHeaderTemplate\">\r\n </ng-container>\r\n <ng-template #NoVertHeaderTemplate>\r\n {{ column.columnLabel || column.dataField }}\r\n </ng-template>\r\n </div>\r\n }\r\n </div>\r\n <!-- virtual scroller with data rows -->\r\n <cdk-virtual-scroll-viewport #vScroller itemSize=\"36\">\r\n <div *cdkVirtualFor=\"let row of domData; let rowIdx = index\"\r\n [class.selected]=\"rowSelectionMatrix?.[rowIdx]\"\r\n class=\"row\">\r\n @for (column of columns; track column; let colIdx = $index) {\r\n <div [attr.data-col-idx]=\"colIdx\"\r\n [attr.data-row-idx]=\"rowIdx\"\r\n [class.selected]=\"freeSelectionMatrix?.[rowIdx]?.[colIdx]\"\r\n class=\"cell {{column.cssClasses}}\">\r\n <ng-container [ngTemplateOutletContext]=\"{row: row}\"\r\n [ngTemplateOutlet]=\"column.cellTemplate || NoVertCellTemplate\">\r\n </ng-container>\r\n <ng-template #NoVertCellTemplate>\r\n {{ row[column.dataField] }}\r\n </ng-template>\r\n </div>\r\n }\r\n </div>\r\n </cdk-virtual-scroll-viewport>\r\n </div>\r\n } @else {\r\n <div (matSortChange)=\"onSort($event)\"\r\n (scroll)=\"onScroll()\"\r\n [matSortDisabled]=\"!withSort\"\r\n cdkVirtualScrollingElement\r\n class=\"flextable by-column striped {{align}}\"\r\n matSort>\r\n <!-- header column -->\r\n <div class=\"column header pos-sticky-horizontal\">\r\n @for (column of columns; track column) {\r\n <div [disabled]=\"!column.withSort\"\r\n [mat-sort-header]=\"column.dataField\"\r\n [style.max-width.px]=\"columnMaxWidth\"\r\n class=\"cell {{column.cssClasses}}\">\r\n <ng-container [ngTemplateOutlet]=\"column.headerTemplate || NoHorHeaderTemplate\">\r\n </ng-container>\r\n <ng-template #NoHorHeaderTemplate>\r\n {{ column.columnLabel || column.dataField }}\r\n </ng-template>\r\n </div>\r\n }\r\n </div>\r\n <!-- virtual scroller with data columns -->\r\n <cdk-virtual-scroll-viewport #vScroller [orientation]=\"'horizontal'\" itemSize=\"114\">\r\n <div *cdkVirtualFor=\"let row of domData; let rowIdx = index\"\r\n [class.selected]=\"rowSelectionMatrix?.[rowIdx]\"\r\n [style.max-width.px]=\"columnMaxWidth\"\r\n class=\"column\">\r\n @for (column of columns; track column; let colIdx = $index) {\r\n <div [attr.data-col-idx]=\"colIdx\"\r\n [attr.data-row-idx]=\"rowIdx\"\r\n [class.selected]=\"freeSelectionMatrix?.[rowIdx]?.[colIdx]\"\r\n class=\"cell {{column.cssClasses}}\">\r\n <ng-container [ngTemplateOutletContext]=\"{row: row}\"\r\n [ngTemplateOutlet]=\"column.cellTemplate || NoHorCellTemplate\">\r\n </ng-container>\r\n <ng-template #NoHorCellTemplate>\r\n {{ row[column.dataField] }}\r\n </ng-template>\r\n </div>\r\n }\r\n </div>\r\n </cdk-virtual-scroll-viewport>\r\n </div>\r\n }\r\n\r\n @if (showToTop && toTopActive) {\r\n <div (click)=\"onGoToTop()\"\r\n [matTooltip]=\"orientation === 'vertical' ? 'to top' : 'to left'\"\r\n class=\"flextable__to-top\"\r\n matTooltipClass=\"bg-accent\">\r\n <mat-icon [fontIcon]=\"orientation === 'vertical' ? 'arrow_upward' : 'arrow_back'\" class=\"small\">\r\n </mat-icon>\r\n </div>\r\n }\r\n\r\n</div>\r\n", styles: [".spaas-table{height:100%;width:100%}\n"], dependencies: [{ kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i3.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i3.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: i5.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i5.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i5.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "directive", type: i5.CdkVirtualScrollableElement, selector: "[cdkVirtualScrollingElement]" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TableComponent, decorators: [{
type: Component,
args: [{ selector: 'spaas-table', template: "<div class=\"spaas-table pos-relative\">\r\n\r\n @if (orientation === 'vertical') {\r\n <div (matSortChange)=\"onSort($event)\"\r\n (scroll)=\"onScroll()\"\r\n [matSortDisabled]=\"!withSort\"\r\n cdkVirtualScrollingElement\r\n class=\"flextable by-row striped flex col {{align}}\"\r\n matSort>\r\n <!-- header row -->\r\n <div class=\"row header pos-sticky-vertical\">\r\n @for (column of columns; track column) {\r\n <div [disabled]=\"!column.withSort\"\r\n [mat-sort-header]=\"column.dataField\"\r\n class=\"cell {{column.cssClasses}}\">\r\n <ng-container [ngTemplateOutlet]=\"column.headerTemplate || NoVertHeaderTemplate\">\r\n </ng-container>\r\n <ng-template #NoVertHeaderTemplate>\r\n {{ column.columnLabel || column.dataField }}\r\n </ng-template>\r\n </div>\r\n }\r\n </div>\r\n <!-- virtual scroller with data rows -->\r\n <cdk-virtual-scroll-viewport #vScroller itemSize=\"36\">\r\n <div *cdkVirtualFor=\"let row of domData; let rowIdx = index\"\r\n [class.selected]=\"rowSelectionMatrix?.[rowIdx]\"\r\n class=\"row\">\r\n @for (column of columns; track column; let colIdx = $index) {\r\n <div [attr.data-col-idx]=\"colIdx\"\r\n [attr.data-row-idx]=\"rowIdx\"\r\n [class.selected]=\"freeSelectionMatrix?.[rowIdx]?.[colIdx]\"\r\n class=\"cell {{column.cssClasses}}\">\r\n <ng-container [ngTemplateOutletContext]=\"{row: row}\"\r\n [ngTemplateOutlet]=\"column.cellTemplate || NoVertCellTemplate\">\r\n </ng-container>\r\n <ng-template #NoVertCellTemplate>\r\n {{ row[column.dataField] }}\r\n </ng-template>\r\n </div>\r\n }\r\n </div>\r\n </cdk-virtual-scroll-viewport>\r\n </div>\r\n } @else {\r\n <div (matSortChange)=\"onSort($event)\"\r\n (scroll)=\"onScroll()\"\r\n [matSortDisabled]=\"!withSort\"\r\n cdkVirtualScrollingElement\r\n class=\"flextable by-column striped {{align}}\"\r\n matSort>\r\n <!-- header column -->\r\n <div class=\"column header pos-sticky-horizontal\">\r\n @for (column of columns; track column) {\r\n <div [disabled]=\"!column.withSort\"\r\n [mat-sort-header]=\"column.dataField\"\r\n [style.max-width.px]=\"columnMaxWidth\"\r\n class=\"cell {{column.cssClasses}}\">\r\n <ng-container [ngTemplateOutlet]=\"column.headerTemplate || NoHorHeaderTemplate\">\r\n </ng-container>\r\n <ng-template #NoHorHeaderTemplate>\r\n {{ column.columnLabel || column.dataField }}\r\n </ng-template>\r\n </div>\r\n }\r\n </div>\r\n <!-- virtual scroller with data columns -->\r\n <cdk-virtual-scroll-viewport #vScroller [orientation]=\"'horizontal'\" itemSize=\"114\">\r\n <div *cdkVirtualFor=\"let row of domData; let rowIdx = index\"\r\n [class.selected]=\"rowSelectionMatrix?.[rowIdx]\"\r\n [style.max-width.px]=\"columnMaxWidth\"\r\n class=\"column\">\r\n @for (column of columns; track column; let colIdx = $index) {\r\n <div [attr.data-col-idx]=\"colIdx\"\r\n [attr.data-row-idx]=\"rowIdx\"\r\n [class.selected]=\"freeSelectionMatrix?.[rowIdx]?.[colIdx]\"\r\n class=\"cell {{column.cssClasses}}\">\r\n <ng-container [ngTemplateOutletContext]=\"{row: row}\"\r\n [ngTemplateOutlet]=\"column.cellTemplate || NoHorCellTemplate\">\r\n </ng-container>\r\n <ng-template #NoHorCellTemplate>\r\n {{ row[column.dataField] }}\r\n </ng-template>\r\n </div>\r\n }\r\n </div>\r\n </cdk-virtual-scroll-viewport>\r\n </div>\r\n }\r\n\r\n @if (showToTop && toTopActive) {\r\n <div (click)=\"onGoToTop()\"\r\n [matTooltip]=\"orientation === 'vertical' ? 'to top' : 'to left'\"\r\n class=\"flextable__to-top\"\r\n matTooltipClass=\"bg-accent\">\r\n <mat-icon [fontIcon]=\"orientation === 'vertical' ? 'arrow_upward' : 'arrow_back'\" class=\"small\">\r\n </mat-icon>\r\n </div>\r\n }\r\n\r\n</div>\r\n", styles: [".spaas-table{height:100%;width:100%}\n"] }]
}], propDecorators: { tableData: [{
type: Input,
args: [{ required: true }]
}], columns: [{
type: Input,
args: [{ required: true }]
}], columnMaxWidth: [{
type: Input
}], freeSelectionMatrix: [{
type: Input
}], rowSelectionMatrix: [{
type: Input
}], orientation: [{
type: Input
}], showToTop: [{
type: Input
}], withSort: [{
type: Input
}], filter: [{
type: Input
}], align: [{
type: Input
}], tableSortedOrFiltered: [{
type: Output
}], vScroller: [{
type: ViewChild,
args: ['vScroller']
}], headerTemplates: [{
type: ContentChildren,
args: [TableHeaderDirective]
}], cellTemplates: [{
type: ContentChildren,
args: [TableCellDirective]
}] } });
class TableSelectionRowDirective {
constructor() {
this.rowSelectionMatrix = [];
this.multiSelect = false;
this.selectionChanged = new EventEmitter(); // will emit last selected row index
this.isSelecting = false;
this.selectionId = 1;
// set the from/to variables to public because it's very handy to be able to access these directly in the template
this.fromRow = 0;
this.toRow = 0;
this.onDestroy = new Subject();
}
mouseDown(e) {
const mouseData = this.checkMouseData(e);
if (mouseData.valid) {
this.onClickCell(e, mouseData.rowIdx);
}
}
mouseMove(e) {
const mouseData = this.checkMouseData(e);
if (this.isSelecting && mouseData.valid && mouseData.rowIdx !== this.toRow) {
this.onSelecting(mouseData.rowIdx);
}
}
mouseUp() {
this.onStopSelect('mouseup');
}
mouseLeave() {
this.onStopSelect('mouseleave');
}
sort() {
this.resetSelectionRange(true, true);
this.emitNewSelection();
}
ngOnDestroy() {
this.onDestroy.next();
this.onDestroy.complete();
}
checkMouseData(e) {
const target = (e.target);
let dataset = target?.dataset;
if (!dataset?.rowIdx) {
// also check the offsetParent, for cells with sub-divs
dataset = (target?.offsetParent).dataset;
}
let rowIdx = -1;
if (dataset?.rowIdx) {
rowIdx = Number.isNaN((Number(dataset.rowIdx))) ? -1 : Number(dataset.rowIdx);
}
return {
valid: rowIdx > -1,
rowIdx: rowIdx,
};
}
onClickCell(e, rowIdx) {
if (!e) {
return;
}
this.isSelecting = true;
if (!e.shiftKey && !e.ctrlKey) {
// normal click: update all selection variables
++this.selectionId;
this.fromRow = rowIdx;
this.toRow = rowIdx;
this.resetSelectionRange(true);
}
else if (e.shiftKey && this.multiSelect) {
// shift click: set last variables for range selection
document.getSelection()?.removeAllRanges();
this.toRow = rowIdx;
this.updateSelectionRange();
}
else if (e.ctrlKey && this.multiSelect) {
// ctrl key: just set for row itself
++this.selectionId;
this.rowSelectionMatrix[rowIdx] = !this.rowSelectionMatrix[rowIdx] ? this.selectionId : 0;
if (this.rowSelectionMatrix[rowIdx]) {
this.fromRow = rowIdx;
this.toRow = rowIdx;
}
else {
// it's a deselection: search for last selected row to put focus on
for (let row = 0; row < this.rowSelectionMatrix.length; row++) {
if (this.rowSelectionMatrix[row]) {
this.toRow = row;
}
}
}
}
}
onSelecting(rowIdx) {
if (this.isSelecting && this.multiSelect) {
document.getSelection()?.removeAllRanges();
this.toRow = rowIdx;
this.resetSelectionRange();
this.updateSelectionRange();
}
}
onStopSelect(fromMouseEvent) {
if (this.isSelecting) {
this.isSelecting = false;
if (fromMouseEvent === 'mouseup') {
this.emitNewSelection();
}
}
}
emitNewSelection() {
this.selectionChanged.emit(this.rowSelectionMatrix[this.toRow] > 0 ? this.toRow : -1);
}
resetSelectionRange(fullReset = false, fromSort = false) {
const wasSelected = this.rowSelectionMatrix[this.toRow] > 0;
for (let rowIdx = 0; rowIdx < this.rowSelectionMatrix.length; rowIdx++) {
if (fullReset || this.rowSelectionMatrix[rowIdx] === this.selectionId) {
this.rowSelectionMatrix[rowIdx] = 0;
}
}
this.rowSelectionMatrix[this.toRow] = fromSort || wasSelected ? 0 : this.selectionId;
}
updateSelectionRange() {
const fromRow = Math.min(this.fromRow, this.toRow);
const toRow = Math.max(this.fromRow, this.toRow);
for (let rowIdx = fromRow; rowIdx <= toRow; rowIdx++) {
this.rowSelectionMatrix[rowIdx] = this.selectionId;
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TableSelectionRowDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: TableSelectionRowDirective, selector: "[spaasTableSelectionRow]", inputs: { rowSelectionMatrix: "rowSelectionMatrix", multiSelect: "multiSelect" }, outputs: { selectionChanged: "selectionChanged" }, host: { listeners: { "mousedown": "mouseDown($event)", "mousemove": "mouseMove($event)", "mouseup": "mouseUp($event)", "mouseleave": "mouseLeave($event)", "tableSortedOrFiltered": "sort($event)" } }, exportAs: ["spaasTableSelectionRow"], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TableSelectionRowDirective, decorators: [{
type: Directive,
args: [{
selector: '[spaasTableSelectionRow]',
exportAs: 'spaasTableSelectionRow'
}]
}], propDecorators: { rowSelectionMatrix: [{
type: Input
}], multiSelect: [{
type: Input
}], selectionChanged: [{
type: Output
}], mouseDown: [{
type: HostListener,
args: ['mousedown', ['$event']]
}], mouseMove: [{
type: HostListener,
args: ['mousemove', ['$event']]
}], mouseUp: [{
type: HostListener,
args: ['mouseup', ['$event']]
}], mouseLeave: [{
type: HostListener,
args: ['mouseleave', ['$event']]
}], sort: [{
type: HostListener,
args: ['tableSortedOrFiltered', ['$event']]
}] } });
class TableColumnModel {
constructor() {
this.cellTemplate = null;
this.columnLabel = '';
this.dataField = '';
this.withFilterDefault = '';
this.withFilterSelect = '';
this.withSort = true;
}
}
class TableColumnFilterModel extends TableColumnModel {
constructor() {
super(...arguments);
this.filterDropdownValues = [];
}
update(col) {
Object.assign(this, col);
}
}
class TableFilterComponent {
static cleanValue(val) {
// trim, escape backslashes and lowercase the value
return (val + '').trim().replace(/\\/g, '\\\\').toLowerCase();
}
constructor() {
this.tableData = [];
this.columns = [];
this.withFreeSearch = true;
this.filterChanged = new EventEmitter();
// also emit separately that the "clear all" button has been clicked (for parent components with additional filtering)
this.filterCleared = new EventEmitter();
this.filterString = '';
this.filterForm = new FormGroup({});
this.filterColumns = [];
this.FREESEARCH_CTRL = 'freeSearch';
this.ALL_VALUE = '';
this.filterForm.addControl(this.FREESEARCH_CTRL, new FormControl(''));
}
ngOnChanges(changes) {
if (changes.hasOwnProperty('columns')) {
this.setFilterFormAndColumns();
}
if (changes.hasOwnProperty('tableData') && this.tableData?.length) {
this.setDropdownLists();
}
}
setFilterFormAndColumns() {
this.filterColumns = [];
let hasValidDefault = false;
for (const col of this.columns) {
if (col.withFilterSelect) {
let newValidDefault = false;
const filterCol = new TableColumnFilterModel();
filterCol.update(col);
this.filterColumns.push(filterCol);
if (col.withFilterSelect === 'single') {
newValidDefault = !!col.withFilterDefault && typeof col.withFilterDefault === 'string';
const filterDefault = newValidDefault ? col.withFilterDefault : '';
this.filterForm.addControl(col.dataField, new FormControl(filterDefault));
}
else {
newValidDefault = !!col.withFilterDefault && Array.isArray(col.withFilterDefault) && col.withFilterDefault.length > 0;
const filterDefault = newValidDefault ? col.withFilterDefault : [this.ALL_VALUE];
this.filterForm.addControl(col.dataField, new FormControl(filterDefault));
}
hasValidDefault = hasValidDefault || newValidDefault;
}
}
if (hasValidDefault) {
this.updateFilter();
}
}
setDropdownLists() {
if (!this.filterColumns.length) {
// should not happen since the columns should always be initialised before the data, but do the check anyway
this.setFilterFormAndColumns();
}
for (const col of this.filterColumns) {
const allColValues = this.tableData.map((t) => t[col.dataField] === null ? '' : '' + t[col.dataField]);
col.filterDropdownValues = UtilsService.distinct(allColValues);
}
}
onSelectAll(column) {
if (column.withFilterSelect === 'multiple') {
this.filterForm.controls[column.dataField].patchValue([this.ALL_VALUE]);
}
this.updateFilter();
}
onSelectOne(column) {
if (column.withFilterSelect === 'multiple') {
const val = this.filterForm.controls[column.dataField].value;
if (!val.length) {
// user has deselected the only selected value => set to "all" value
this.filterForm.controls[column.dataField].patchValue([this.ALL_VALUE]);
}
else {
// user has selected an option, deselect "all" value
this.filterForm.controls[column.dataField].patchValue(val.filter((v) => v !== this.ALL_VALUE));
}
}
this.updateFilter();
}
updateFilter() {
let freeValueFilter = '';
let dropdownFilter = '';
// first free search
const freeValue = TableFilterComponent.cleanValue(this.filterForm.controls[this.FREESEARCH_CTRL].value);
if (freeValue) {
// here we add ALL columns, not just the ones with filter === true
for (const col of this.columns) {
freeValueFilter += '("" + e["' + col.dataField + '"]).toLowerCase().includes("' + freeValue + '") || ';
}
freeValueFilter = '(' + freeValueFilter.substring(0, freeValueFilter.length - 4) + ') ';
}
// then dropdown fields
for (const col of this.filterColumns) {
if (col.withFilterSelect == 'single') {
const colFilterValue = TableFilterComponent.cleanValue(this.filterForm.controls[col.dataField].value);
if (colFilterValue) {
dropdownFilter += '("" + e["' + col.dataField + '"]).toLowerCase() === "' + colFilterValue + '" && ';
}
}
else {
const colFilterValues = this.filterForm.controls[col.dataField].value;
let multiGroup = '';
for (const val of colFilterValues) {
if (val) {
multiGroup += '("" + e["' + col.dataField + '"]).toLowerCase() === "' + TableFilterComponent.cleanValue(val) + '" || ';
}
}
if (multiGroup) {
dropdownFilter += '(' + multiGroup.substring(0, multiGroup.length - 4) + ') && ';
}
}
}
if (dropdownFilter) {
dropdownFilter = '(' + dropdownFilter.substring(0, dropdownFilter.length - 4) + ') ';
}
const concatFilter = freeValueFilter && dropdownFilter ? freeValueFilter + ' && ' + dropdownFilter : freeValueFilter || dropdownFilter;
this.emitFilter(concatFilter);
}
onReset() {
this.filterForm.controls[this.FREESEARCH_CTRL].patchValue('');
for (const col of this.filterColumns) {
const ctrl = this.filterForm.controls[col.dataField];
ctrl.patchValue(col.withFilterSelect === 'single' ? '' : [this.ALL_VALUE]);
}
this.emitFilter('');
this.filterCleared.emit();
}
emitFilter(filter) {
this.filterString = filter;
this.filterChanged.emit(filter);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TableFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: TableFilterComponent, selector: "spaas-table-filter", inputs: { tableData: "tableData", columns: "columns", withFreeSearch: "withFreeSearch" }, outputs: { filterChanged: "filterChanged", filterCleared: "filterCleared" }, usesOnChanges: true, ngImport: i0, template: "<div [formGroup]=\"filterForm\"\r\n [ngClass]=\"{\r\n 'column': withFreeSearch,\r\n 'row-reverse': !withFreeSearch,\r\n }\"\r\n class=\"filter pad-small flex column-gap-10\">\r\n\r\n <div class=\"flex wrap column-gap-10 align-center\">\r\n\r\n @if (withFreeSearch) {\r\n <mat-form-field class=\"grow-h free-search\"\r\n floatLabel=\"always\">\r\n <mat-label>search any field...</mat-label>\r\n <input matInput\r\n type=\"search\"\r\n (search)=\"updateFilter()\"\r\n formControlName=\"freeSearch\">\r\n </mat-form-field>\r\n }\r\n\r\n <div class=\"flex column-gap-10 pad-small-top\">\r\n @if (withFreeSearch) {\r\n <button class=\"primary\"\r\n (click)=\"updateFilter()\">\r\n search\r\n </button>\r\n }\r\n @if (filterColumns?.length) {\r\n <button class=\"error\"\r\n (click)=\"onReset()\">\r\n clear all\r\n </button>\r\n }\r\n </div>\r\n\r\n </div>\r\n\r\n <div class=\"flex wrap column-gap-10 align-center\"\r\n [class.grow-h]=\"!withFreeSearch\">\r\n\r\n @for (column of filterColumns; track column) {\r\n <mat-form-field class=\"grow-h\"\r\n floatLabel=\"always\">\r\n <mat-label>{{ column.columnLabel || column.dataField }}</mat-label>\r\n <mat-select [formControlName]=\"column.dataField\"\r\n [multiple]=\"column.withFilterSelect === 'multiple'\">\r\n <mat-option (click)=\"onSelectAll(column)\" [value]=\"ALL_VALUE\">all</mat-option>\r\n @for (val of column.filterDropdownValues; track val) {\r\n <mat-option (click)=\"onSelectOne(column)\"\r\n [value]=\"val\">\r\n {{ val }}\r\n </mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n }\r\n\r\n </div>\r\n\r\n</div>\r\n", styles: [".filter .mat-mdc-form-field{min-width:140px}.filter .mat-mdc-form-field.free-search{max-width:300px}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i4$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i5$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i6.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i6.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i6.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TableFilterComponent, decorators: [{
type: Component,
args: [{ selector: 'spaas-table-filter', template: "<div [formGroup]=\"filterForm\"\r\n [ngClass]=\"{\r\n 'column': withFreeSearch,\r\n 'row-reverse': !withFreeSearch,\r\n }\"\r\n class=\"filter pad-small flex column-gap-10\">\r\n\r\n <div class=\"flex wrap column-gap-10 align-center\">\r\n\r\n @if (withFreeSearch) {\r\n <mat-form-field class=\"grow-h free-search\"\r\n floatLabel=\"always\">\r\n <mat-label>search any field...</mat-label>\r\n <input matInput\r\n type=\"search\"\r\n (search)=\"updateFilter()\"\r\n formControlName=\"freeSearch\">\r\n </mat-form-field>\r\n }\r\n\r\n <div class=\"flex column-gap-10 pad-small-top\">\r\n @if (withFreeSearch) {\r\n <button class=\"primary\"\r\n (click)=\"updateFilter()\">\r\n search\r\n </button>\r\n }\r\n @if (filterColumns?.length) {\r\n <button class=\"error\"\r\n (click)=\"onReset()\">\r\n clear all\r\n </button>\r\n }\r\n </div>\r\n\r\n </div>\r\n\r\n <div class=\"flex wrap column-gap-10 align-center\"\r\n [class.grow-h]=\"!withFreeSearch\">\r\n\r\n @for (column of filterColumns; track column) {\r\n <mat-form-field class=\"grow-h\"\r\n floatLabel=\"always\">\r\n <mat-label>{{ column.columnLabel || column.dataField }}</mat-label>\r\n <mat-select [formControlName]=\"column.dataField\"\r\n [multiple]=\"column.withFilterSelect === 'multiple'\">\r\n <mat-option (click)=\"onSelectAll(column)\" [value]=\"ALL_VALUE\">all</mat-option>\r\n @for (val of column.filterDropdownValues; track val) {\r\n <mat-option (click)=\"onSelectOne(column)\"\r\n [value]=\"val\">\r\n {{ val }}\r\n </mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n }\r\n\r\n </div>\r\n\r\n</div>\r\n", styles: [".filter .mat-mdc-form-field{min-width:140px}.filter .mat-mdc-form-field.free-search{max-width:300px}\n"] }]
}], ctorParameters: () => [], propDecorators: { tableData: [{
type: Input
}], columns: [{
type: Input
}], withFreeSearch: [{
type: Input
}], filterChanged: [{
type: Output
}], filterCleared: [{
type: Output
}] } });
class SpaasTableModule {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SpaasTableModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.3.12", ngImport: i0, type: SpaasTableModule, declarations: [TableCellDirective,
TableComponent,
TableFilterComponent,
TableHeaderDirective,
TableSelectionFreeDirective,
TableSelectionRowDirective], imports: [CommonModule,
MatFormFieldModule,
MatIconModule,
MatInputModule,
MatSelectModule,
MatSortModule,
MatTooltipModule,
ReactiveFormsModule,
ScrollingModule], exports: [TableCellDirective,
TableComponent,
TableFilterComponent,
TableHeaderDirective,
TableSelectionFreeDirective,
TableSelectionRowDirective] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SpaasTableModule, imports: [CommonModule,
MatFormFieldModule,
MatIconModule,
MatInputModule,
MatSelectModule,
MatSortModule,
MatTooltipModule,
ReactiveFormsModule,
ScrollingModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SpaasTableModule, decorators: [{
type: NgModule,
args: [{
declarations: [
TableCellDirective,
TableComponent,
TableFilterComponent,
TableHeaderDirective,
TableSelectionFreeDirective,
TableSelectionRowDirective,
],
exports: [
TableCellDirective,
TableComponent,
TableFilterComponent,
TableHeaderDirective,
TableSelectionFreeDirective,
TableSelectionRowDirective,
],
imports: [
CommonModule,
MatFormFieldModule,
MatIconModule,
MatInputModule,
MatSelectModule,
MatSortModule,
MatTooltipModule,
ReactiveFormsModule,
ScrollingModule,
],
providers: []
}]
}] });
// MODULE
/**
* Generated bundle index. Do not edit.
*/
export { SpaasTableModule, TableCellDirective, TableColumnFilterModel, TableColumnModel, TableComponent, TableFilterComponent, TableHeaderDirective, TableSelectionFreeDirective, TableSelectionRowDirective };
//# sourceMappingURL=ngx-gem-spaas-table.mjs.map