@mintplayer/ng-bootstrap 21.12.2 → 21.12.4

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.
@@ -6,8 +6,8 @@ import { ScrollingModule } from '@angular/cdk/scrolling';
6
6
  import { BsTableComponent, BsTableStylesComponent } from '@mintplayer/ng-bootstrap/table';
7
7
  import { DatatableSortBase } from '@mintplayer/ng-bootstrap/datatable';
8
8
  import { DataSource } from '@angular/cdk/collections';
9
- import { BehaviorSubject, from, of } from 'rxjs';
10
- import { startWith, filter, map, distinctUntilChanged, switchMap, catchError } from 'rxjs/operators';
9
+ import { BehaviorSubject, Subject, merge, from, of } from 'rxjs';
10
+ import { startWith, map, filter, distinctUntilChanged, switchMap, catchError } from 'rxjs/operators';
11
11
 
12
12
  class BsVirtualDatatableComponent extends DatatableSortBase {
13
13
  constructor() {
@@ -16,6 +16,7 @@ class BsVirtualDatatableComponent extends DatatableSortBase {
16
16
  this.ngZone = inject(NgZone);
17
17
  this.cleanup = [];
18
18
  this.dataSource = input.required(...(ngDevMode ? [{ debugName: "dataSource" }] : []));
19
+ this.isResponsive = input(false, ...(ngDevMode ? [{ debugName: "isResponsive" }] : []));
19
20
  this.itemSize = input(48, ...(ngDevMode ? [{ debugName: "itemSize" }] : []));
20
21
  }
21
22
  ngAfterViewInit() {
@@ -70,6 +71,12 @@ class BsVirtualDatatableComponent extends DatatableSortBase {
70
71
  if (!headerCells.length || !bodyCells?.length)
71
72
  return;
72
73
  const columnCount = Math.min(headerCells.length, bodyCells.length);
74
+ // Save scroll positions before measurement (clearing min-width can shrink
75
+ // the table and cause the browser to clamp scrollLeft to 0).
76
+ const headerScrollContainer = el.querySelector('.table-responsive');
77
+ const viewport = el.querySelector('cdk-virtual-scroll-viewport');
78
+ const savedHeaderScroll = headerScrollContainer?.scrollLeft ?? 0;
79
+ const savedViewportScroll = viewport?.scrollLeft ?? 0;
73
80
  // Clear inline widths so we can measure natural sizes
74
81
  for (let i = 0; i < columnCount; i++) {
75
82
  headerCells[i].style.minWidth = '';
@@ -90,6 +97,11 @@ class BsVirtualDatatableComponent extends DatatableSortBase {
90
97
  headerCells[i].style.minWidth = w;
91
98
  bodyCells[i].style.minWidth = w;
92
99
  }
100
+ // Restore scroll positions after min-widths are re-applied
101
+ if (headerScrollContainer)
102
+ headerScrollContainer.scrollLeft = savedHeaderScroll;
103
+ if (viewport)
104
+ viewport.scrollLeft = savedViewportScroll;
93
105
  };
94
106
  // Sync after first render
95
107
  this.ngZone.runOutsideAngular(() => {
@@ -105,12 +117,12 @@ class BsVirtualDatatableComponent extends DatatableSortBase {
105
117
  this.cleanup.push(() => observer.disconnect());
106
118
  }
107
119
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: BsVirtualDatatableComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
108
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: BsVirtualDatatableComponent, isStandalone: true, selector: "bs-virtual-datatable", inputs: { dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: true, transformFunction: null }, itemSize: { classPropertyName: "itemSize", publicName: "itemSize", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "<div class=\"virtual-datatable-container\">\n <bs-table [isResponsive]=\"true\" [striped]=\"true\" [hover]=\"true\">\n <thead>\n <tr>\n @for (column of columnsArray; track column) {\n <th class=\"text-nowrap\"\n [class.sort]=\"column.sortable\"\n [class.sort-asc]=\"column.sortable && getSortDirection(column.name) === 'ascending'\"\n [class.sort-desc]=\"column.sortable && getSortDirection(column.name) === 'descending'\"\n (mousedown)=\"onHeaderMouseDown($event)\"\n (click)=\"columnHeaderClicked(column, $event)\">\n <ng-container *ngTemplateOutlet=\"column.templateRef\"></ng-container>\n @if (settings().sortColumns.length > 1 && getSortIndex(column.name) >= 0) {\n <span class=\"sort-priority\">{{ getSortIndex(column.name) + 1 }}</span>\n }\n </th>\n }\n </tr>\n </thead>\n </bs-table>\n\n <bs-table-styles>\n <cdk-virtual-scroll-viewport [itemSize]=\"itemSize()\" class=\"virtual-scroll-viewport\">\n <table class=\"table table-striped table-hover\">\n <tbody>\n <tr *cdkVirtualFor=\"let item of dataSource()\" class=\"virtual-row\">\n @if (item && rowTemplate) {\n <ng-container *ngTemplateOutlet=\"rowTemplate; context: { $implicit: item }\"></ng-container>\n } @else {\n @for (column of columnsArray; track column) {\n <td>&nbsp;</td>\n }\n }\n </tr>\n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n </bs-table-styles>\n</div>\n", styles: ["@charset \"UTF-8\";bs-table thead th.sort{position:relative;cursor:pointer;padding-right:2rem}bs-table thead th.sort:before,bs-table thead th.sort:after{position:absolute;display:block;opacity:.3;bottom:.5em}bs-table thead th.sort:before{content:\"\\2191\";right:1em}bs-table thead th.sort:after{content:\"\\2193\";right:.5em}bs-table thead th.sort.sort-asc:after{opacity:1}bs-table thead th.sort.sort-desc:before{opacity:1}bs-table thead th.sort .sort-priority{position:absolute;right:.1em;bottom:.3em;font-size:.65em;font-weight:700;opacity:.7}:host{display:block;height:100%}.virtual-datatable-container{display:flex;flex-direction:column;height:100%}.virtual-datatable-container bs-table{flex-shrink:0}bs-table ::ng-deep table,.virtual-scroll-viewport table{table-layout:auto}bs-table ::ng-deep th,.virtual-scroll-viewport td{white-space:nowrap}bs-table ::ng-deep .table-responsive{overflow-x:hidden;scrollbar-gutter:stable}.virtual-scroll-viewport{flex:1 1 auto;min-height:0;scrollbar-gutter:stable}.virtual-scroll-viewport table{margin-bottom:0}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i1.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i1.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i1.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "component", type: BsTableComponent, selector: "bs-table", inputs: ["isResponsive", "striped", "hover"] }, { kind: "component", type: BsTableStylesComponent, selector: "bs-table-styles" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
120
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: BsVirtualDatatableComponent, isStandalone: true, selector: "bs-virtual-datatable", inputs: { dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: true, transformFunction: null }, isResponsive: { classPropertyName: "isResponsive", publicName: "isResponsive", isSignal: true, isRequired: false, transformFunction: null }, itemSize: { classPropertyName: "itemSize", publicName: "itemSize", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "<div class=\"virtual-datatable-container\">\n <bs-table [isResponsive]=\"isResponsive()\" [striped]=\"true\" [hover]=\"true\">\n <thead>\n <tr>\n @for (column of columnsArray; track column) {\n <th class=\"text-nowrap\"\n [class.sort]=\"column.sortable\"\n [class.sort-asc]=\"column.sortable && getSortDirection(column.name) === 'ascending'\"\n [class.sort-desc]=\"column.sortable && getSortDirection(column.name) === 'descending'\"\n (mousedown)=\"onHeaderMouseDown($event)\"\n (click)=\"columnHeaderClicked(column, $event)\">\n <ng-container *ngTemplateOutlet=\"column.templateRef\"></ng-container>\n @if (settings().sortColumns.length > 1 && getSortIndex(column.name) >= 0) {\n <span class=\"sort-priority\">{{ getSortIndex(column.name) + 1 }}</span>\n }\n </th>\n }\n </tr>\n </thead>\n </bs-table>\n\n <bs-table-styles>\n <cdk-virtual-scroll-viewport [itemSize]=\"itemSize()\" class=\"virtual-scroll-viewport\">\n <table class=\"table table-striped table-hover\" [class.nowrap]=\"isResponsive()\">\n <tbody>\n <tr *cdkVirtualFor=\"let item of dataSource()\" class=\"virtual-row\">\n @if (item && rowTemplate) {\n <ng-container *ngTemplateOutlet=\"rowTemplate; context: { $implicit: item }\"></ng-container>\n } @else {\n @for (column of columnsArray; track column) {\n <td>&nbsp;</td>\n }\n }\n </tr>\n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n </bs-table-styles>\n</div>\n", styles: ["@charset \"UTF-8\";bs-table thead th.sort{position:relative;cursor:pointer;padding-right:2rem}bs-table thead th.sort:before,bs-table thead th.sort:after{position:absolute;display:block;opacity:.3;bottom:.5em}bs-table thead th.sort:before{content:\"\\2191\";right:1em}bs-table thead th.sort:after{content:\"\\2193\";right:.5em}bs-table thead th.sort.sort-asc:after{opacity:1}bs-table thead th.sort.sort-desc:before{opacity:1}bs-table thead th.sort .sort-priority{position:absolute;right:.1em;bottom:.3em;font-size:.65em;font-weight:700;opacity:.7}:host{display:block;height:100%}.virtual-datatable-container{display:flex;flex-direction:column;height:100%}.virtual-datatable-container bs-table{flex-shrink:0}bs-table ::ng-deep table,.virtual-scroll-viewport table{table-layout:auto}.virtual-scroll-viewport .nowrap td{white-space:nowrap}bs-table ::ng-deep .table-responsive{overflow-x:hidden;scrollbar-gutter:stable}.virtual-scroll-viewport{flex:1 1 auto;min-height:0;scrollbar-gutter:stable}.virtual-scroll-viewport table{margin-bottom:0}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i1.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i1.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i1.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "component", type: BsTableComponent, selector: "bs-table", inputs: ["isResponsive", "striped", "hover"] }, { kind: "component", type: BsTableStylesComponent, selector: "bs-table-styles" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
109
121
  }
110
122
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: BsVirtualDatatableComponent, decorators: [{
111
123
  type: Component,
112
- args: [{ selector: 'bs-virtual-datatable', imports: [NgTemplateOutlet, ScrollingModule, BsTableComponent, BsTableStylesComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"virtual-datatable-container\">\n <bs-table [isResponsive]=\"true\" [striped]=\"true\" [hover]=\"true\">\n <thead>\n <tr>\n @for (column of columnsArray; track column) {\n <th class=\"text-nowrap\"\n [class.sort]=\"column.sortable\"\n [class.sort-asc]=\"column.sortable && getSortDirection(column.name) === 'ascending'\"\n [class.sort-desc]=\"column.sortable && getSortDirection(column.name) === 'descending'\"\n (mousedown)=\"onHeaderMouseDown($event)\"\n (click)=\"columnHeaderClicked(column, $event)\">\n <ng-container *ngTemplateOutlet=\"column.templateRef\"></ng-container>\n @if (settings().sortColumns.length > 1 && getSortIndex(column.name) >= 0) {\n <span class=\"sort-priority\">{{ getSortIndex(column.name) + 1 }}</span>\n }\n </th>\n }\n </tr>\n </thead>\n </bs-table>\n\n <bs-table-styles>\n <cdk-virtual-scroll-viewport [itemSize]=\"itemSize()\" class=\"virtual-scroll-viewport\">\n <table class=\"table table-striped table-hover\">\n <tbody>\n <tr *cdkVirtualFor=\"let item of dataSource()\" class=\"virtual-row\">\n @if (item && rowTemplate) {\n <ng-container *ngTemplateOutlet=\"rowTemplate; context: { $implicit: item }\"></ng-container>\n } @else {\n @for (column of columnsArray; track column) {\n <td>&nbsp;</td>\n }\n }\n </tr>\n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n </bs-table-styles>\n</div>\n", styles: ["@charset \"UTF-8\";bs-table thead th.sort{position:relative;cursor:pointer;padding-right:2rem}bs-table thead th.sort:before,bs-table thead th.sort:after{position:absolute;display:block;opacity:.3;bottom:.5em}bs-table thead th.sort:before{content:\"\\2191\";right:1em}bs-table thead th.sort:after{content:\"\\2193\";right:.5em}bs-table thead th.sort.sort-asc:after{opacity:1}bs-table thead th.sort.sort-desc:before{opacity:1}bs-table thead th.sort .sort-priority{position:absolute;right:.1em;bottom:.3em;font-size:.65em;font-weight:700;opacity:.7}:host{display:block;height:100%}.virtual-datatable-container{display:flex;flex-direction:column;height:100%}.virtual-datatable-container bs-table{flex-shrink:0}bs-table ::ng-deep table,.virtual-scroll-viewport table{table-layout:auto}bs-table ::ng-deep th,.virtual-scroll-viewport td{white-space:nowrap}bs-table ::ng-deep .table-responsive{overflow-x:hidden;scrollbar-gutter:stable}.virtual-scroll-viewport{flex:1 1 auto;min-height:0;scrollbar-gutter:stable}.virtual-scroll-viewport table{margin-bottom:0}\n"] }]
113
- }], propDecorators: { dataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataSource", required: true }] }], itemSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemSize", required: false }] }] } });
124
+ args: [{ selector: 'bs-virtual-datatable', imports: [NgTemplateOutlet, ScrollingModule, BsTableComponent, BsTableStylesComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"virtual-datatable-container\">\n <bs-table [isResponsive]=\"isResponsive()\" [striped]=\"true\" [hover]=\"true\">\n <thead>\n <tr>\n @for (column of columnsArray; track column) {\n <th class=\"text-nowrap\"\n [class.sort]=\"column.sortable\"\n [class.sort-asc]=\"column.sortable && getSortDirection(column.name) === 'ascending'\"\n [class.sort-desc]=\"column.sortable && getSortDirection(column.name) === 'descending'\"\n (mousedown)=\"onHeaderMouseDown($event)\"\n (click)=\"columnHeaderClicked(column, $event)\">\n <ng-container *ngTemplateOutlet=\"column.templateRef\"></ng-container>\n @if (settings().sortColumns.length > 1 && getSortIndex(column.name) >= 0) {\n <span class=\"sort-priority\">{{ getSortIndex(column.name) + 1 }}</span>\n }\n </th>\n }\n </tr>\n </thead>\n </bs-table>\n\n <bs-table-styles>\n <cdk-virtual-scroll-viewport [itemSize]=\"itemSize()\" class=\"virtual-scroll-viewport\">\n <table class=\"table table-striped table-hover\" [class.nowrap]=\"isResponsive()\">\n <tbody>\n <tr *cdkVirtualFor=\"let item of dataSource()\" class=\"virtual-row\">\n @if (item && rowTemplate) {\n <ng-container *ngTemplateOutlet=\"rowTemplate; context: { $implicit: item }\"></ng-container>\n } @else {\n @for (column of columnsArray; track column) {\n <td>&nbsp;</td>\n }\n }\n </tr>\n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n </bs-table-styles>\n</div>\n", styles: ["@charset \"UTF-8\";bs-table thead th.sort{position:relative;cursor:pointer;padding-right:2rem}bs-table thead th.sort:before,bs-table thead th.sort:after{position:absolute;display:block;opacity:.3;bottom:.5em}bs-table thead th.sort:before{content:\"\\2191\";right:1em}bs-table thead th.sort:after{content:\"\\2193\";right:.5em}bs-table thead th.sort.sort-asc:after{opacity:1}bs-table thead th.sort.sort-desc:before{opacity:1}bs-table thead th.sort .sort-priority{position:absolute;right:.1em;bottom:.3em;font-size:.65em;font-weight:700;opacity:.7}:host{display:block;height:100%}.virtual-datatable-container{display:flex;flex-direction:column;height:100%}.virtual-datatable-container bs-table{flex-shrink:0}bs-table ::ng-deep table,.virtual-scroll-viewport table{table-layout:auto}.virtual-scroll-viewport .nowrap td{white-space:nowrap}bs-table ::ng-deep .table-responsive{overflow-x:hidden;scrollbar-gutter:stable}.virtual-scroll-viewport{flex:1 1 auto;min-height:0;scrollbar-gutter:stable}.virtual-scroll-viewport table{margin-bottom:0}\n"] }]
125
+ }], propDecorators: { dataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataSource", required: true }] }], isResponsive: [{ type: i0.Input, args: [{ isSignal: true, alias: "isResponsive", required: false }] }], itemSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemSize", required: false }] }] } });
114
126
 
115
127
  class VirtualDatatableDataSource extends DataSource {
116
128
  constructor(fetchFn, pageSize = 50) {
@@ -118,6 +130,8 @@ class VirtualDatatableDataSource extends DataSource {
118
130
  this.cachedPages = new Map();
119
131
  this.totalRecords = 0;
120
132
  this.dataStream = new BehaviorSubject([]);
133
+ this.resetSubject = new Subject();
134
+ this.resetVersion = 0;
121
135
  this.fetchFn = fetchFn;
122
136
  this.pageSize = pageSize;
123
137
  }
@@ -126,7 +140,10 @@ class VirtualDatatableDataSource extends DataSource {
126
140
  this.dataStream = new BehaviorSubject([]);
127
141
  this.cachedPages.clear();
128
142
  this.totalRecords = 0;
129
- this.subscription = collectionViewer.viewChange.pipe(startWith({ start: 0, end: this.pageSize }), filter(range => range.end > range.start), map(range => this.getPageIndices(range)), distinctUntilChanged((a, b) => a.join() === b.join()), switchMap(pages => from(this.fetchPages(pages)).pipe(catchError(() => of(this.dataStream.value))))).subscribe(data => this.dataStream.next(data));
143
+ // Track the last viewport range so reset() can re-trigger a fetch.
144
+ // resetVersion is incremented on reset() to bypass distinctUntilChanged.
145
+ let lastRange = { start: 0, end: this.pageSize };
146
+ this.subscription = merge(collectionViewer.viewChange.pipe(startWith(lastRange)), this.resetSubject.pipe(map(() => lastRange))).pipe(filter(range => range.end > range.start), map(range => { lastRange = range; return { pages: this.getPageIndices(range), version: this.resetVersion }; }), distinctUntilChanged((a, b) => a.version === b.version && a.pages.join() === b.pages.join()), switchMap(({ pages }) => from(this.fetchPages(pages)).pipe(catchError(() => of(this.dataStream.value))))).subscribe(data => this.dataStream.next(data));
130
147
  return this.dataStream;
131
148
  }
132
149
  disconnect() {
@@ -138,8 +155,8 @@ class VirtualDatatableDataSource extends DataSource {
138
155
  }
139
156
  reset() {
140
157
  this.cachedPages.clear();
141
- this.totalRecords = 0;
142
- this.dataStream.next([]);
158
+ this.resetVersion++;
159
+ this.resetSubject.next();
143
160
  }
144
161
  getPageIndices(range) {
145
162
  const startPage = Math.floor(range.start / this.pageSize);
@@ -1 +1 @@
1
- {"version":3,"file":"mintplayer-ng-bootstrap-virtual-datatable.mjs","sources":["../../../../libs/mintplayer-ng-bootstrap/virtual-datatable/src/virtual-datatable/virtual-datatable.component.ts","../../../../libs/mintplayer-ng-bootstrap/virtual-datatable/src/virtual-datatable/virtual-datatable.component.html","../../../../libs/mintplayer-ng-bootstrap/virtual-datatable/src/virtual-datatable-data-source.ts","../../../../libs/mintplayer-ng-bootstrap/virtual-datatable/src/virtual-row-template/virtual-row-template.directive.ts","../../../../libs/mintplayer-ng-bootstrap/virtual-datatable/mintplayer-ng-bootstrap-virtual-datatable.ts"],"sourcesContent":["import { AfterViewInit, ChangeDetectionStrategy, Component, ElementRef, inject, input, NgZone, OnDestroy, TemplateRef } from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { ScrollingModule } from '@angular/cdk/scrolling';\nimport { BsTableComponent, BsTableStylesComponent } from '@mintplayer/ng-bootstrap/table';\nimport { DatatableSortBase } from '@mintplayer/ng-bootstrap/datatable';\nimport { VirtualDatatableDataSource } from '../virtual-datatable-data-source';\nimport { BsVirtualRowTemplateContext } from '../virtual-row-template/virtual-row-template.directive';\n\n@Component({\n selector: 'bs-virtual-datatable',\n templateUrl: './virtual-datatable.component.html',\n styleUrls: ['./virtual-datatable.component.scss'],\n imports: [NgTemplateOutlet, ScrollingModule, BsTableComponent, BsTableStylesComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class BsVirtualDatatableComponent<TData> extends DatatableSortBase implements AfterViewInit, OnDestroy {\n\n private readonly elementRef = inject(ElementRef);\n private readonly ngZone = inject(NgZone);\n private cleanup: (() => void)[] = [];\n\n dataSource = input.required<VirtualDatatableDataSource<TData>>();\n itemSize = input(48);\n\n rowTemplate?: TemplateRef<BsVirtualRowTemplateContext<TData>>;\n\n ngAfterViewInit() {\n this.setupScrollSync();\n this.setupColumnWidthSync();\n }\n\n ngOnDestroy() {\n this.cleanup.forEach(fn => fn());\n }\n\n private setupScrollSync() {\n const el = this.elementRef.nativeElement as HTMLElement;\n const headerScrollContainer = el.querySelector('.table-responsive') as HTMLElement;\n const viewport = el.querySelector('cdk-virtual-scroll-viewport') as HTMLElement;\n\n if (!headerScrollContainer || !viewport) return;\n\n let syncing = false;\n\n const onHeaderScroll = () => {\n if (syncing) return;\n syncing = true;\n viewport.scrollLeft = headerScrollContainer.scrollLeft;\n syncing = false;\n };\n\n const onViewportScroll = () => {\n if (syncing) return;\n syncing = true;\n headerScrollContainer.scrollLeft = viewport.scrollLeft;\n syncing = false;\n };\n\n this.ngZone.runOutsideAngular(() => {\n headerScrollContainer.addEventListener('scroll', onHeaderScroll, { passive: true });\n viewport.addEventListener('scroll', onViewportScroll, { passive: true });\n });\n\n this.cleanup.push(() => {\n headerScrollContainer.removeEventListener('scroll', onHeaderScroll);\n viewport.removeEventListener('scroll', onViewportScroll);\n });\n }\n\n private setupColumnWidthSync() {\n const el = this.elementRef.nativeElement as HTMLElement;\n const bodyTableBody = el.querySelector('cdk-virtual-scroll-viewport tbody') as HTMLElement;\n\n if (!bodyTableBody) return;\n\n // Track the max width seen for each column so we only grow, never shrink\n // (prevents layout jumps as rows scroll in/out of view).\n const maxWidths: number[] = [];\n\n const syncWidths = () => {\n const headerCells = el.querySelectorAll<HTMLElement>('bs-table thead th');\n const firstBodyRow = el.querySelector<HTMLElement>('cdk-virtual-scroll-viewport tbody tr');\n const bodyCells = firstBodyRow?.querySelectorAll<HTMLElement>('td');\n\n if (!headerCells.length || !bodyCells?.length) return;\n\n const columnCount = Math.min(headerCells.length, bodyCells.length);\n\n // Clear inline widths so we can measure natural sizes\n for (let i = 0; i < columnCount; i++) {\n headerCells[i].style.minWidth = '';\n bodyCells[i].style.minWidth = '';\n }\n\n // Measure natural widths and update tracked maximums\n for (let i = 0; i < columnCount; i++) {\n const headerW = headerCells[i].offsetWidth;\n const bodyW = bodyCells[i].offsetWidth;\n const natural = Math.max(headerW, bodyW);\n if (!maxWidths[i] || natural > maxWidths[i]) {\n maxWidths[i] = natural;\n }\n }\n\n // Always re-apply max widths (cells were cleared above for measurement)\n for (let i = 0; i < columnCount; i++) {\n const w = `${maxWidths[i]}px`;\n headerCells[i].style.minWidth = w;\n bodyCells[i].style.minWidth = w;\n }\n };\n\n // Sync after first render\n this.ngZone.runOutsideAngular(() => {\n requestAnimationFrame(() => syncWidths());\n });\n\n // Re-sync when body rows change (virtual scroll swaps rows)\n const observer = new MutationObserver(() => {\n requestAnimationFrame(() => syncWidths());\n });\n\n this.ngZone.runOutsideAngular(() => {\n observer.observe(bodyTableBody, { childList: true, subtree: true });\n });\n\n this.cleanup.push(() => observer.disconnect());\n }\n}\n","<div class=\"virtual-datatable-container\">\n <bs-table [isResponsive]=\"true\" [striped]=\"true\" [hover]=\"true\">\n <thead>\n <tr>\n @for (column of columnsArray; track column) {\n <th class=\"text-nowrap\"\n [class.sort]=\"column.sortable\"\n [class.sort-asc]=\"column.sortable && getSortDirection(column.name) === 'ascending'\"\n [class.sort-desc]=\"column.sortable && getSortDirection(column.name) === 'descending'\"\n (mousedown)=\"onHeaderMouseDown($event)\"\n (click)=\"columnHeaderClicked(column, $event)\">\n <ng-container *ngTemplateOutlet=\"column.templateRef\"></ng-container>\n @if (settings().sortColumns.length > 1 && getSortIndex(column.name) >= 0) {\n <span class=\"sort-priority\">{{ getSortIndex(column.name) + 1 }}</span>\n }\n </th>\n }\n </tr>\n </thead>\n </bs-table>\n\n <bs-table-styles>\n <cdk-virtual-scroll-viewport [itemSize]=\"itemSize()\" class=\"virtual-scroll-viewport\">\n <table class=\"table table-striped table-hover\">\n <tbody>\n <tr *cdkVirtualFor=\"let item of dataSource()\" class=\"virtual-row\">\n @if (item && rowTemplate) {\n <ng-container *ngTemplateOutlet=\"rowTemplate; context: { $implicit: item }\"></ng-container>\n } @else {\n @for (column of columnsArray; track column) {\n <td>&nbsp;</td>\n }\n }\n </tr>\n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n </bs-table-styles>\n</div>\n","import { CollectionViewer, DataSource } from '@angular/cdk/collections';\nimport { BehaviorSubject, Observable, Subscription, from, of } from 'rxjs';\nimport { catchError, distinctUntilChanged, filter, map, startWith, switchMap } from 'rxjs/operators';\n\nexport class VirtualDatatableDataSource<T> extends DataSource<T> {\n private readonly fetchFn: (skip: number, take: number) => Promise<{ data: T[]; totalRecords: number }>;\n private readonly pageSize: number;\n private readonly cachedPages = new Map<number, T[]>();\n private totalRecords = 0;\n private dataStream = new BehaviorSubject<T[]>([]);\n private subscription?: Subscription;\n\n constructor(\n fetchFn: (skip: number, take: number) => Promise<{ data: T[]; totalRecords: number }>,\n pageSize = 50\n ) {\n super();\n this.fetchFn = fetchFn;\n this.pageSize = pageSize;\n }\n\n connect(collectionViewer: CollectionViewer): Observable<T[]> {\n // Support reconnection after disconnect (which completes the previous dataStream)\n this.dataStream = new BehaviorSubject<T[]>([]);\n this.cachedPages.clear();\n this.totalRecords = 0;\n\n this.subscription = collectionViewer.viewChange.pipe(\n startWith({ start: 0, end: this.pageSize }),\n filter(range => range.end > range.start),\n map(range => this.getPageIndices(range)),\n distinctUntilChanged((a, b) => a.join() === b.join()),\n switchMap(pages => from(this.fetchPages(pages)).pipe(\n catchError(() => of(this.dataStream.value))\n ))\n ).subscribe(data => this.dataStream.next(data));\n\n return this.dataStream;\n }\n\n disconnect(): void {\n this.subscription?.unsubscribe();\n this.dataStream.complete();\n }\n\n get length(): number {\n return this.totalRecords;\n }\n\n reset(): void {\n this.cachedPages.clear();\n this.totalRecords = 0;\n this.dataStream.next([]);\n }\n\n private getPageIndices(range: { start: number; end: number }): number[] {\n const startPage = Math.floor(range.start / this.pageSize);\n const endPage = Math.floor((range.end - 1) / this.pageSize);\n const pages: number[] = [];\n for (let i = startPage; i <= endPage; i++) {\n pages.push(i);\n }\n return pages;\n }\n\n private async fetchPages(pageIndices: number[]): Promise<T[]> {\n const uncachedPages = pageIndices.filter(p => !this.cachedPages.has(p));\n\n const results = await Promise.all(\n uncachedPages.map(async pageIndex => {\n const skip = pageIndex * this.pageSize;\n const result = await this.fetchFn(skip, this.pageSize);\n return { pageIndex, result };\n })\n );\n\n for (const { pageIndex, result } of results) {\n this.cachedPages.set(pageIndex, result.data);\n }\n if (results.length > 0) {\n this.totalRecords = results[0].result.totalRecords;\n }\n\n // Build the full data array with placeholders for unloaded pages\n const totalPages = Math.ceil(this.totalRecords / this.pageSize);\n const data: T[] = [];\n for (let i = 0; i < totalPages; i++) {\n const page = this.cachedPages.get(i);\n if (page) {\n data.push(...page);\n } else {\n // Fill with empty slots to maintain correct virtual scroll positioning\n const remaining = Math.min(this.pageSize, this.totalRecords - i * this.pageSize);\n data.push(...new Array<T>(remaining));\n }\n }\n return data;\n }\n}\n","import { Directive, inject, TemplateRef } from '@angular/core';\nimport { BsVirtualDatatableComponent } from '../virtual-datatable/virtual-datatable.component';\n\n@Directive({\n selector: '[bsVirtualRowTemplate]',\n})\nexport class BsVirtualRowTemplateDirective<TData> {\n\n private datatableComponent = inject<BsVirtualDatatableComponent<TData>>(BsVirtualDatatableComponent);\n private templateRef = inject<TemplateRef<BsVirtualRowTemplateContext<TData>>>(TemplateRef);\n\n constructor() {\n this.datatableComponent.rowTemplate = this.templateRef;\n }\n\n public static ngTemplateContextGuard<TData>(\n dir: BsVirtualRowTemplateDirective<TData>,\n ctx: any\n ): ctx is BsVirtualRowTemplateContext<Exclude<TData, false | 0 | '' | null | undefined>> {\n return true;\n }\n}\n\nexport class BsVirtualRowTemplateContext<TData = unknown> {\n public $implicit: TData = null!;\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mintplayer-ng-bootstrap-virtual-datatable.mjs","sources":["../../../../libs/mintplayer-ng-bootstrap/virtual-datatable/src/virtual-datatable/virtual-datatable.component.ts","../../../../libs/mintplayer-ng-bootstrap/virtual-datatable/src/virtual-datatable/virtual-datatable.component.html","../../../../libs/mintplayer-ng-bootstrap/virtual-datatable/src/virtual-datatable-data-source.ts","../../../../libs/mintplayer-ng-bootstrap/virtual-datatable/src/virtual-row-template/virtual-row-template.directive.ts","../../../../libs/mintplayer-ng-bootstrap/virtual-datatable/mintplayer-ng-bootstrap-virtual-datatable.ts"],"sourcesContent":["import { AfterViewInit, ChangeDetectionStrategy, Component, ElementRef, inject, input, NgZone, OnDestroy, TemplateRef } from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { ScrollingModule } from '@angular/cdk/scrolling';\nimport { BsTableComponent, BsTableStylesComponent } from '@mintplayer/ng-bootstrap/table';\nimport { DatatableSortBase } from '@mintplayer/ng-bootstrap/datatable';\nimport { VirtualDatatableDataSource } from '../virtual-datatable-data-source';\nimport { BsVirtualRowTemplateContext } from '../virtual-row-template/virtual-row-template.directive';\n\n@Component({\n selector: 'bs-virtual-datatable',\n templateUrl: './virtual-datatable.component.html',\n styleUrls: ['./virtual-datatable.component.scss'],\n imports: [NgTemplateOutlet, ScrollingModule, BsTableComponent, BsTableStylesComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class BsVirtualDatatableComponent<TData> extends DatatableSortBase implements AfterViewInit, OnDestroy {\n\n private readonly elementRef = inject(ElementRef);\n private readonly ngZone = inject(NgZone);\n private cleanup: (() => void)[] = [];\n\n dataSource = input.required<VirtualDatatableDataSource<TData>>();\n isResponsive = input(false);\n itemSize = input(48);\n\n rowTemplate?: TemplateRef<BsVirtualRowTemplateContext<TData>>;\n\n ngAfterViewInit() {\n this.setupScrollSync();\n this.setupColumnWidthSync();\n }\n\n ngOnDestroy() {\n this.cleanup.forEach(fn => fn());\n }\n\n private setupScrollSync() {\n const el = this.elementRef.nativeElement as HTMLElement;\n const headerScrollContainer = el.querySelector('.table-responsive') as HTMLElement;\n const viewport = el.querySelector('cdk-virtual-scroll-viewport') as HTMLElement;\n\n if (!headerScrollContainer || !viewport) return;\n\n let syncing = false;\n\n const onHeaderScroll = () => {\n if (syncing) return;\n syncing = true;\n viewport.scrollLeft = headerScrollContainer.scrollLeft;\n syncing = false;\n };\n\n const onViewportScroll = () => {\n if (syncing) return;\n syncing = true;\n headerScrollContainer.scrollLeft = viewport.scrollLeft;\n syncing = false;\n };\n\n this.ngZone.runOutsideAngular(() => {\n headerScrollContainer.addEventListener('scroll', onHeaderScroll, { passive: true });\n viewport.addEventListener('scroll', onViewportScroll, { passive: true });\n });\n\n this.cleanup.push(() => {\n headerScrollContainer.removeEventListener('scroll', onHeaderScroll);\n viewport.removeEventListener('scroll', onViewportScroll);\n });\n }\n\n private setupColumnWidthSync() {\n const el = this.elementRef.nativeElement as HTMLElement;\n const bodyTableBody = el.querySelector('cdk-virtual-scroll-viewport tbody') as HTMLElement;\n\n if (!bodyTableBody) return;\n\n // Track the max width seen for each column so we only grow, never shrink\n // (prevents layout jumps as rows scroll in/out of view).\n const maxWidths: number[] = [];\n\n const syncWidths = () => {\n const headerCells = el.querySelectorAll<HTMLElement>('bs-table thead th');\n const firstBodyRow = el.querySelector<HTMLElement>('cdk-virtual-scroll-viewport tbody tr');\n const bodyCells = firstBodyRow?.querySelectorAll<HTMLElement>('td');\n\n if (!headerCells.length || !bodyCells?.length) return;\n\n const columnCount = Math.min(headerCells.length, bodyCells.length);\n\n // Save scroll positions before measurement (clearing min-width can shrink\n // the table and cause the browser to clamp scrollLeft to 0).\n const headerScrollContainer = el.querySelector('.table-responsive') as HTMLElement;\n const viewport = el.querySelector('cdk-virtual-scroll-viewport') as HTMLElement;\n const savedHeaderScroll = headerScrollContainer?.scrollLeft ?? 0;\n const savedViewportScroll = viewport?.scrollLeft ?? 0;\n\n // Clear inline widths so we can measure natural sizes\n for (let i = 0; i < columnCount; i++) {\n headerCells[i].style.minWidth = '';\n bodyCells[i].style.minWidth = '';\n }\n\n // Measure natural widths and update tracked maximums\n for (let i = 0; i < columnCount; i++) {\n const headerW = headerCells[i].offsetWidth;\n const bodyW = bodyCells[i].offsetWidth;\n const natural = Math.max(headerW, bodyW);\n if (!maxWidths[i] || natural > maxWidths[i]) {\n maxWidths[i] = natural;\n }\n }\n\n // Always re-apply max widths (cells were cleared above for measurement)\n for (let i = 0; i < columnCount; i++) {\n const w = `${maxWidths[i]}px`;\n headerCells[i].style.minWidth = w;\n bodyCells[i].style.minWidth = w;\n }\n\n // Restore scroll positions after min-widths are re-applied\n if (headerScrollContainer) headerScrollContainer.scrollLeft = savedHeaderScroll;\n if (viewport) viewport.scrollLeft = savedViewportScroll;\n };\n\n // Sync after first render\n this.ngZone.runOutsideAngular(() => {\n requestAnimationFrame(() => syncWidths());\n });\n\n // Re-sync when body rows change (virtual scroll swaps rows)\n const observer = new MutationObserver(() => {\n requestAnimationFrame(() => syncWidths());\n });\n\n this.ngZone.runOutsideAngular(() => {\n observer.observe(bodyTableBody, { childList: true, subtree: true });\n });\n\n this.cleanup.push(() => observer.disconnect());\n }\n}\n","<div class=\"virtual-datatable-container\">\n <bs-table [isResponsive]=\"isResponsive()\" [striped]=\"true\" [hover]=\"true\">\n <thead>\n <tr>\n @for (column of columnsArray; track column) {\n <th class=\"text-nowrap\"\n [class.sort]=\"column.sortable\"\n [class.sort-asc]=\"column.sortable && getSortDirection(column.name) === 'ascending'\"\n [class.sort-desc]=\"column.sortable && getSortDirection(column.name) === 'descending'\"\n (mousedown)=\"onHeaderMouseDown($event)\"\n (click)=\"columnHeaderClicked(column, $event)\">\n <ng-container *ngTemplateOutlet=\"column.templateRef\"></ng-container>\n @if (settings().sortColumns.length > 1 && getSortIndex(column.name) >= 0) {\n <span class=\"sort-priority\">{{ getSortIndex(column.name) + 1 }}</span>\n }\n </th>\n }\n </tr>\n </thead>\n </bs-table>\n\n <bs-table-styles>\n <cdk-virtual-scroll-viewport [itemSize]=\"itemSize()\" class=\"virtual-scroll-viewport\">\n <table class=\"table table-striped table-hover\" [class.nowrap]=\"isResponsive()\">\n <tbody>\n <tr *cdkVirtualFor=\"let item of dataSource()\" class=\"virtual-row\">\n @if (item && rowTemplate) {\n <ng-container *ngTemplateOutlet=\"rowTemplate; context: { $implicit: item }\"></ng-container>\n } @else {\n @for (column of columnsArray; track column) {\n <td>&nbsp;</td>\n }\n }\n </tr>\n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n </bs-table-styles>\n</div>\n","import { CollectionViewer, DataSource } from '@angular/cdk/collections';\nimport { BehaviorSubject, Observable, Subject, Subscription, from, merge, of } from 'rxjs';\nimport { catchError, distinctUntilChanged, filter, map, startWith, switchMap } from 'rxjs/operators';\n\nexport class VirtualDatatableDataSource<T> extends DataSource<T> {\n private readonly fetchFn: (skip: number, take: number) => Promise<{ data: T[]; totalRecords: number }>;\n private readonly pageSize: number;\n private readonly cachedPages = new Map<number, T[]>();\n private totalRecords = 0;\n private dataStream = new BehaviorSubject<T[]>([]);\n private subscription?: Subscription;\n private resetSubject = new Subject<void>();\n private resetVersion = 0;\n\n constructor(\n fetchFn: (skip: number, take: number) => Promise<{ data: T[]; totalRecords: number }>,\n pageSize = 50\n ) {\n super();\n this.fetchFn = fetchFn;\n this.pageSize = pageSize;\n }\n\n connect(collectionViewer: CollectionViewer): Observable<T[]> {\n // Support reconnection after disconnect (which completes the previous dataStream)\n this.dataStream = new BehaviorSubject<T[]>([]);\n this.cachedPages.clear();\n this.totalRecords = 0;\n\n // Track the last viewport range so reset() can re-trigger a fetch.\n // resetVersion is incremented on reset() to bypass distinctUntilChanged.\n let lastRange = { start: 0, end: this.pageSize };\n this.subscription = merge(\n collectionViewer.viewChange.pipe(startWith(lastRange)),\n this.resetSubject.pipe(map(() => lastRange))\n ).pipe(\n filter(range => range.end > range.start),\n map(range => { lastRange = range; return { pages: this.getPageIndices(range), version: this.resetVersion }; }),\n distinctUntilChanged((a, b) => a.version === b.version && a.pages.join() === b.pages.join()),\n switchMap(({ pages }) => from(this.fetchPages(pages)).pipe(\n catchError(() => of(this.dataStream.value))\n ))\n ).subscribe(data => this.dataStream.next(data));\n\n return this.dataStream;\n }\n\n disconnect(): void {\n this.subscription?.unsubscribe();\n this.dataStream.complete();\n }\n\n get length(): number {\n return this.totalRecords;\n }\n\n reset(): void {\n this.cachedPages.clear();\n this.resetVersion++;\n this.resetSubject.next();\n }\n\n private getPageIndices(range: { start: number; end: number }): number[] {\n const startPage = Math.floor(range.start / this.pageSize);\n const endPage = Math.floor((range.end - 1) / this.pageSize);\n const pages: number[] = [];\n for (let i = startPage; i <= endPage; i++) {\n pages.push(i);\n }\n return pages;\n }\n\n private async fetchPages(pageIndices: number[]): Promise<T[]> {\n const uncachedPages = pageIndices.filter(p => !this.cachedPages.has(p));\n\n const results = await Promise.all(\n uncachedPages.map(async pageIndex => {\n const skip = pageIndex * this.pageSize;\n const result = await this.fetchFn(skip, this.pageSize);\n return { pageIndex, result };\n })\n );\n\n for (const { pageIndex, result } of results) {\n this.cachedPages.set(pageIndex, result.data);\n }\n if (results.length > 0) {\n this.totalRecords = results[0].result.totalRecords;\n }\n\n // Build the full data array with placeholders for unloaded pages\n const totalPages = Math.ceil(this.totalRecords / this.pageSize);\n const data: T[] = [];\n for (let i = 0; i < totalPages; i++) {\n const page = this.cachedPages.get(i);\n if (page) {\n data.push(...page);\n } else {\n // Fill with empty slots to maintain correct virtual scroll positioning\n const remaining = Math.min(this.pageSize, this.totalRecords - i * this.pageSize);\n data.push(...new Array<T>(remaining));\n }\n }\n return data;\n }\n}\n","import { Directive, inject, TemplateRef } from '@angular/core';\nimport { BsVirtualDatatableComponent } from '../virtual-datatable/virtual-datatable.component';\n\n@Directive({\n selector: '[bsVirtualRowTemplate]',\n})\nexport class BsVirtualRowTemplateDirective<TData> {\n\n private datatableComponent = inject<BsVirtualDatatableComponent<TData>>(BsVirtualDatatableComponent);\n private templateRef = inject<TemplateRef<BsVirtualRowTemplateContext<TData>>>(TemplateRef);\n\n constructor() {\n this.datatableComponent.rowTemplate = this.templateRef;\n }\n\n public static ngTemplateContextGuard<TData>(\n dir: BsVirtualRowTemplateDirective<TData>,\n ctx: any\n ): ctx is BsVirtualRowTemplateContext<Exclude<TData, false | 0 | '' | null | undefined>> {\n return true;\n }\n}\n\nexport class BsVirtualRowTemplateContext<TData = unknown> {\n public $implicit: TData = null!;\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mintplayer/ng-bootstrap",
3
3
  "private": false,
4
- "version": "21.12.2",
4
+ "version": "21.12.4",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/MintPlayer/mintplayer-ng-bootstrap",
@@ -11,6 +11,8 @@ declare class VirtualDatatableDataSource<T> extends DataSource<T> {
11
11
  private totalRecords;
12
12
  private dataStream;
13
13
  private subscription?;
14
+ private resetSubject;
15
+ private resetVersion;
14
16
  constructor(fetchFn: (skip: number, take: number) => Promise<{
15
17
  data: T[];
16
18
  totalRecords: number;
@@ -40,6 +42,7 @@ declare class BsVirtualDatatableComponent<TData> extends DatatableSortBase imple
40
42
  private readonly ngZone;
41
43
  private cleanup;
42
44
  dataSource: i0.InputSignal<VirtualDatatableDataSource<TData>>;
45
+ isResponsive: i0.InputSignal<boolean>;
43
46
  itemSize: i0.InputSignal<number>;
44
47
  rowTemplate?: TemplateRef<BsVirtualRowTemplateContext<TData>>;
45
48
  ngAfterViewInit(): void;
@@ -47,7 +50,7 @@ declare class BsVirtualDatatableComponent<TData> extends DatatableSortBase imple
47
50
  private setupScrollSync;
48
51
  private setupColumnWidthSync;
49
52
  static ɵfac: i0.ɵɵFactoryDeclaration<BsVirtualDatatableComponent<any>, never>;
50
- static ɵcmp: i0.ɵɵComponentDeclaration<BsVirtualDatatableComponent<any>, "bs-virtual-datatable", never, { "dataSource": { "alias": "dataSource"; "required": true; "isSignal": true; }; "itemSize": { "alias": "itemSize"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
53
+ static ɵcmp: i0.ɵɵComponentDeclaration<BsVirtualDatatableComponent<any>, "bs-virtual-datatable", never, { "dataSource": { "alias": "dataSource"; "required": true; "isSignal": true; }; "isResponsive": { "alias": "isResponsive"; "required": false; "isSignal": true; }; "itemSize": { "alias": "itemSize"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
51
54
  }
52
55
 
53
56
  export { BsVirtualDatatableComponent, BsVirtualRowTemplateContext, BsVirtualRowTemplateDirective, VirtualDatatableDataSource };