@progress/kendo-angular-pivotgrid 16.6.0-develop.1 → 16.6.0-develop.10

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.
@@ -278,19 +278,19 @@ const matchAriaAttributes = (wrapper) => {
278
278
  const firstColHeaderRowCellsIds = Array.from(firstColHeadersRow?.children).map(el => el.getAttribute('id')).join(' ');
279
279
  firstColHeadersRow.setAttribute('aria-owns', `${emptyCell.getAttribute('id')} ${firstColHeaderRowCellsIds}`);
280
280
  rowHeaderRows.forEach((row, index) => {
281
- const valueCellsIds = filterAndMap(Array.from(valueTableCells), c => c.getAttribute('id').split('-')[4] === (index + 1).toString(), c => c.getAttribute('id'));
281
+ const valueCellsIds = filterAndMap(Array.from(valueTableCells), c => c.getAttribute('id')?.split('-')[4] === (index + 1).toString(), c => c.getAttribute('id'));
282
282
  row.setAttribute('aria-owns', valueCellsIds.join(' '));
283
283
  });
284
284
  valueTableCells.forEach(cell => {
285
- const cellColIndex = +cell.getAttribute('id').split('-')[5];
285
+ const cellColIndex = +cell.getAttribute('id')?.split('-')[5];
286
286
  const colHeaderCellsIds = filterAndMap(Array.from(colHeaderCells), c => {
287
- const headerCellColIndex = +c.getAttribute('id').split('-')[5];
287
+ const headerCellColIndex = +c.getAttribute('id')?.split('-')[5];
288
288
  const headerCellColspan = +c.getAttribute('colspan');
289
289
  const colIndexIsEqual = cellColIndex === headerCellColIndex;
290
- const cellColIndexIsWithinHeaderCellRange = headerCellColspan > 1 && (headerCellColIndex + headerCellColspan - 1 >= cellColIndex);
290
+ const cellColIndexIsWithinHeaderCellRange = headerCellColIndex < cellColIndex && headerCellColspan > 1 && (headerCellColIndex + headerCellColspan - 1 >= cellColIndex);
291
291
  return colIndexIsEqual || cellColIndexIsWithinHeaderCellRange;
292
292
  }, c => c.getAttribute('id'));
293
- cell.setAttribute('aria-describedby', colHeaderCellsIds.join(' '));
293
+ colHeaderCellsIds.length && cell.setAttribute('aria-describedby', colHeaderCellsIds.join(' '));
294
294
  });
295
295
  };
296
296
  /**
@@ -365,6 +365,31 @@ const swapItems = (arr, i1, i2) => {
365
365
  arr[i1] = arr[i2];
366
366
  arr[i2] = temp;
367
367
  };
368
+ /**
369
+ * @hidden
370
+ */
371
+ const isVisible = (el, container, offsetY, rtl) => {
372
+ const elTop = el.offsetTop;
373
+ const elBottom = elTop + el.clientHeight;
374
+ let rect;
375
+ let containerRect;
376
+ if (rtl) {
377
+ rect = el.getBoundingClientRect();
378
+ containerRect = container.getBoundingClientRect();
379
+ }
380
+ const elLeft = rtl ? rect.left : el.offsetLeft;
381
+ const elRight = rtl ? rect.right : elLeft + el.clientWidth;
382
+ const containerTop = container.scrollTop;
383
+ const containerBottom = containerTop + container.clientHeight;
384
+ const containerLeft = rtl ? containerRect.left : container.scrollLeft;
385
+ const containerRight = rtl ? containerRect.right : containerLeft + container.clientWidth;
386
+ const visibleY = elTop >= containerTop - offsetY && elBottom <= containerBottom - offsetY;
387
+ const visibleX = rtl ? elRight <= containerRight && elLeft >= containerLeft : elLeft >= containerLeft && elRight <= containerRight;
388
+ return {
389
+ visibleX,
390
+ visibleY
391
+ };
392
+ };
368
393
 
369
394
  /**
370
395
  * @hidden
@@ -3346,8 +3371,8 @@ const packageMetadata = {
3346
3371
  name: '@progress/kendo-angular-pivotgrid',
3347
3372
  productName: 'Kendo UI for Angular',
3348
3373
  productCodes: ['KENDOUIANGULAR', 'KENDOUICOMPLETE'],
3349
- publishDate: 1721827976,
3350
- version: '16.6.0-develop.1',
3374
+ publishDate: 1722607163,
3375
+ version: '16.6.0-develop.10',
3351
3376
  licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/?utm_medium=product&utm_source=kendoangular&utm_campaign=kendo-ui-angular-purchase-license-keys-warning'
3352
3377
  };
3353
3378
 
@@ -3498,6 +3523,117 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
3498
3523
  }]
3499
3524
  }], ctorParameters: function () { return [{ type: i0.TemplateRef }]; } });
3500
3525
 
3526
+ /**
3527
+ * @hidden
3528
+ */
3529
+ class ScrollableTable {
3530
+ constructor(element, handlers, options) {
3531
+ this.element = element;
3532
+ this.handlers = handlers;
3533
+ this.options = options;
3534
+ this.startRow = 0;
3535
+ this.startCol = 0;
3536
+ this.lastKnownScrollPosition = { top: 0, left: 0 };
3537
+ this.offsetFirst = 0;
3538
+ this.scrollHandler = (e) => {
3539
+ const verticalDir = this.element.scrollTop - this.lastKnownScrollPosition.top;
3540
+ const horizontalDir = Math.abs(this.element.scrollLeft) - this.lastKnownScrollPosition.left;
3541
+ if (this.options.rowVirtualization) {
3542
+ if (verticalDir > 0) {
3543
+ if (this.element.scrollTop > (this.renderedRows * this.options.itemHeight + this.offsetFirst - this.rect.height)) {
3544
+ this.startRow = Math.floor(this.element.scrollTop / this.options.itemHeight);
3545
+ this.rowVirtualizationUpdate();
3546
+ }
3547
+ }
3548
+ else {
3549
+ if (this.element.scrollTop <= this.offsetFirst) {
3550
+ this.startRow = Math.max(0, Math.ceil(this.element.scrollTop / this.options.itemHeight) - Math.ceil(this.options.renderedRows / 3));
3551
+ this.rowVirtualizationUpdate();
3552
+ }
3553
+ }
3554
+ }
3555
+ if (this.options.columnVirtualization) {
3556
+ if (horizontalDir > 0) {
3557
+ if (Math.abs(this.element.scrollLeft) - (Math.max(this.startCol - 1, 0) * (this.options.colWidth || 200)) > (this.options.colWidth || 200)) {
3558
+ this.startCol = Math.min(Math.max(Math.floor(Math.abs(this.element.scrollLeft) / this.options.itemWidth) - 1, 0), this.totalCols - this.renderedCols);
3559
+ this.handlers.onScroll();
3560
+ }
3561
+ }
3562
+ else {
3563
+ if (Math.abs(this.element.scrollLeft) <= (this.startCol + 1) * (this.options.colWidth || 200)) {
3564
+ this.startCol = Math.min(Math.max(Math.floor(Math.abs(this.element.scrollLeft) / this.options.itemWidth) - 1, 0), this.totalCols - this.renderedCols);
3565
+ this.handlers.onScroll();
3566
+ }
3567
+ }
3568
+ }
3569
+ this.lastKnownScrollPosition = {
3570
+ top: this.element.scrollTop,
3571
+ left: Math.abs(this.element.scrollLeft)
3572
+ };
3573
+ };
3574
+ this.scrollEndHandler = () => {
3575
+ this.handlers.onScrollEnd();
3576
+ };
3577
+ this.initialize();
3578
+ }
3579
+ onNewData(recalculateSize = false) {
3580
+ this.offsetFirst = this.startRow * this.options.itemHeight;
3581
+ this.renderedRows = Math.min(this.options.renderedRows || Math.ceil(this.visibleRows * 3), this.total);
3582
+ this.endRow = this.startRow + this.renderedRows;
3583
+ this.renderedCols = Math.min(this.options.renderedCols || Math.ceil(this.visibleCols * 1.3), this.totalCols);
3584
+ this.element.querySelector('table').style.transform = `translateY(${this.offsetFirst}px)`;
3585
+ recalculateSize && this.recalculateSize();
3586
+ }
3587
+ destroy() {
3588
+ this.element.removeEventListener('scroll', this.scrollHandler);
3589
+ this.element.removeEventListener('scrollend', this.scrollEndHandler);
3590
+ this.element.removeChild(this.stretcher);
3591
+ }
3592
+ initialize() {
3593
+ this.rtl = this.options.rtl;
3594
+ this.rect = this.element.getBoundingClientRect();
3595
+ // visible rows and cols
3596
+ this.visibleRows = Math.ceil(this.rect.height / this.options.itemHeight);
3597
+ this.visibleCols = Math.ceil(this.rect.width / this.options.itemWidth);
3598
+ // current totals
3599
+ this.total = this.options.total;
3600
+ this.totalCols = this.options.totalCols;
3601
+ const totalHeight = this.total * this.options.itemHeight;
3602
+ const totalWidth = this.totalCols * this.options.itemWidth;
3603
+ // "page" size (rows and cols)
3604
+ this.renderedRows = Math.min(this.options.renderedRows || Math.ceil(this.visibleRows * 3), this.total);
3605
+ this.renderedCols = Math.min(this.options.renderedCols || Math.ceil(this.visibleCols * 1.3), this.totalCols);
3606
+ // start and end row/col
3607
+ this.startRow = 0;
3608
+ this.startCol = 0;
3609
+ this.endRow = this.startRow + this.renderedRows;
3610
+ this.endCol = this.startCol + this.renderedCols;
3611
+ // element that ensures correct scrolling dimensions of the container
3612
+ this.stretcher = document.createElement('DIV');
3613
+ this.stretcher.style.height = `${totalHeight}px`;
3614
+ this.stretcher.style.width = `${totalWidth}px`;
3615
+ this.element.appendChild(this.stretcher);
3616
+ this.element.addEventListener('scroll', this.scrollHandler);
3617
+ this.element.addEventListener('scrollend', this.scrollEndHandler);
3618
+ }
3619
+ recalculateSize() {
3620
+ const totalHeight = this.total * this.options.itemHeight;
3621
+ const totalWidth = this.totalCols * this.options.itemWidth;
3622
+ this.stretcher.style.height = `${totalHeight}px`;
3623
+ this.stretcher.style.width = `${totalWidth}px`;
3624
+ this.rect = this.element.getBoundingClientRect();
3625
+ // visible rows and cols
3626
+ this.visibleRows = Math.ceil(this.rect.height / this.options.itemHeight);
3627
+ this.visibleCols = Math.ceil(this.rect.width / this.options.itemWidth);
3628
+ }
3629
+ rowVirtualizationUpdate() {
3630
+ this.endRow = Math.min(this.startRow + this.renderedRows, this.total);
3631
+ this.offsetFirst = this.startRow * this.options.itemHeight;
3632
+ this.element.querySelector('table').style.transform = `translateY(${this.offsetFirst}px)`;
3633
+ this.handlers.onScroll();
3634
+ }
3635
+ }
3636
+
3501
3637
  /**
3502
3638
  * @hidden
3503
3639
  */
@@ -3696,42 +3832,201 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
3696
3832
  type: Input
3697
3833
  }] } });
3698
3834
 
3835
+ /**
3836
+ * @hidden
3837
+ */
3838
+ class PivotGridScrollService {
3839
+ constructor() {
3840
+ this.virtualScrolling = false;
3841
+ }
3842
+ }
3843
+ PivotGridScrollService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PivotGridScrollService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3844
+ PivotGridScrollService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PivotGridScrollService });
3845
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PivotGridScrollService, decorators: [{
3846
+ type: Injectable
3847
+ }] });
3848
+
3699
3849
  /**
3700
3850
  * @hidden
3701
3851
  */
3702
3852
  class PivotGridTableComponent {
3703
- constructor(dataService) {
3853
+ constructor(host, dataService, localization, zone, scrollService) {
3854
+ this.host = host;
3704
3855
  this.dataService = dataService;
3705
- this.dataChangeSubs = new Subscription();
3856
+ this.localization = localization;
3857
+ this.zone = zone;
3858
+ this.scrollService = scrollService;
3859
+ this.startRowIndex = 0;
3860
+ this.startColIndex = 0;
3861
+ this.rtl = false;
3862
+ this.subs = new Subscription();
3863
+ this.colsUpdateCallback = (cols) => {
3864
+ this.renderedCols = Math.min(cols.length, this.scrollableSettings?.columns);
3865
+ this.renderedCols && this.scrollable && (this.scrollable.totalCols = cols.length);
3866
+ (this.scrollableSettings && this.scrollableSettings.type !== 'row') && this.scrollable?.onNewData(true);
3867
+ this.headerItems = cols;
3868
+ isDocumentAvailable() && !this.scrollable && this.tableType === 'values' && (this.columnVirtualization || this.rowVirtualization) && this.initScrollable();
3869
+ };
3870
+ this.initScrollable = () => {
3871
+ this.scrollable = new ScrollableTable(this.host.nativeElement, {
3872
+ onScroll: () => {
3873
+ this.startRowIndex = this.scrollable.startRow;
3874
+ this.startColIndex = this.scrollable.startCol;
3875
+ this.renderedRows = this.rows.slice(this.startRowIndex, this.startRowIndex + this.scrollableSettings.rows);
3876
+ this.scrollable.renderedRows = this.renderedRows.length;
3877
+ this.scrollable.renderedCols = this.renderedCols;
3878
+ },
3879
+ onScrollEnd: () => {
3880
+ matchAriaAttributes(this.host.nativeElement.closest('.k-pivotgrid'));
3881
+ }
3882
+ }, {
3883
+ itemHeight: this.scrollableSettings.rowHeight,
3884
+ itemWidth: this.colWidth || 200,
3885
+ total: this.totalRows,
3886
+ totalCols: this.headerItems.length,
3887
+ renderedRows: this.scrollableSettings.rows,
3888
+ renderedCols: this.scrollableSettings.columns,
3889
+ columnVirtualization: this.columnVirtualization,
3890
+ rowVirtualization: this.rowVirtualization,
3891
+ rtl: this.rtl
3892
+ });
3893
+ };
3894
+ this.subs.add(this.localization.changes.subscribe(({ rtl }) => {
3895
+ this.rtl = rtl;
3896
+ this.scrollable && (this.scrollable.rtl = rtl);
3897
+ }));
3706
3898
  }
3707
3899
  get pivotGridId() {
3708
3900
  return `kendo-pivotgrid-${this.dataService.pivotGridId}-`;
3709
3901
  }
3902
+ get columnVirtualization() {
3903
+ return this.scrollableSettings?.type && this.scrollableSettings?.type !== 'row';
3904
+ }
3905
+ get rowVirtualization() {
3906
+ return this.scrollableSettings?.type && this.scrollableSettings?.type !== 'column';
3907
+ }
3710
3908
  ngOnInit() {
3711
- this.dataChangeSubs.add(this.dataService[`${this.tableType}Rows`].subscribe(rows => this.rows = rows));
3712
- this.dataChangeSubs.add(this.tableType === 'values' ?
3713
- this.dataService.columnHeaderCols.subscribe(cols => this.headerItems = cols) :
3714
- this.dataService[`${this.tableType}Cols`].subscribe(cols => this.headerItems = cols));
3909
+ this.subs.add(this.dataService[`${this.tableType}Rows`].subscribe(rows => {
3910
+ this.rows = rows;
3911
+ this.renderedRows = this.scrollableSettings ? rows.slice(this.startRowIndex, this.startRowIndex + this.scrollableSettings.rows) : rows;
3912
+ this.totalRows && this.totalRows !== rows.length && this.scrollable && (this.scrollable.total = rows.length);
3913
+ this.scrollable && this.scrollable.onNewData(this.totalRows && this.totalRows !== rows.length);
3914
+ this.totalRows = rows.length;
3915
+ }));
3916
+ this.subs.add(this.tableType === 'values' ?
3917
+ this.dataService.columnHeaderCols.subscribe(this.colsUpdateCallback) :
3918
+ this.dataService[`${this.tableType}Cols`].subscribe(this.colsUpdateCallback));
3919
+ }
3920
+ ngAfterViewInit() {
3921
+ if (isDocumentAvailable() && this.scrollService.virtualScrolling) {
3922
+ this.initScrollableKeyboardNavigation();
3923
+ }
3715
3924
  }
3716
3925
  ngOnDestroy() {
3717
- this.dataChangeSubs.unsubscribe();
3926
+ this.subs.unsubscribe();
3927
+ this.scrollable?.destroy();
3928
+ }
3929
+ initScrollableKeyboardNavigation() {
3930
+ const pivotGrid = this.scrollService.pivotGrid;
3931
+ this.host.nativeElement.addEventListener('keydown', (e) => {
3932
+ if (this.tableType === 'values' && e.target.tagName === 'TD') {
3933
+ e.stopImmediatePropagation();
3934
+ e.preventDefault();
3935
+ if (e.keyCode === Keys.ArrowLeft) {
3936
+ const id = e.target.getAttribute('id');
3937
+ if (id.split('-')[5] === '1') {
3938
+ const target = document.querySelector(`tr[aria-owns*="${id}"]`);
3939
+ pivotGrid.navigation.focusElement(target.lastElementChild, e.target);
3940
+ }
3941
+ else {
3942
+ pivotGrid.navigation.focusElement(e.target.previousElementSibling, e.target);
3943
+ if (!isVisible(e.target.previousElementSibling, this.host.nativeElement, this.scrollable.offsetFirst, this.rtl).visibleX) {
3944
+ e.target.previousElementSibling.scrollIntoView({ behavior: 'auto', block: 'nearest', inline: 'start' });
3945
+ }
3946
+ }
3947
+ }
3948
+ else if (e.keyCode === Keys.ArrowRight) {
3949
+ const id = e.target.getAttribute('id');
3950
+ if (id.split('-')[5] !== this.headerItems.length.toString()) {
3951
+ pivotGrid.navigation.focusElement(e.target.nextElementSibling, e.target);
3952
+ if (!isVisible(e.target.nextElementSibling, this.host.nativeElement, this.scrollable.offsetFirst, this.rtl).visibleX) {
3953
+ e.target.nextElementSibling.scrollIntoView({ behavior: 'auto', block: 'nearest', inline: 'start' });
3954
+ }
3955
+ }
3956
+ }
3957
+ else if (e.keyCode === Keys.ArrowUp) {
3958
+ const id = e.target.getAttribute('id');
3959
+ if (id.split('-')[4] === '1') {
3960
+ const target = document.getElementById(e.target.getAttribute('aria-describedby').split(' ').pop());
3961
+ pivotGrid.navigation.focusElement(target, e.target);
3962
+ }
3963
+ else {
3964
+ const index = Array.from(e.target.parentElement.children).findIndex(el => el === e.target);
3965
+ const elementToFocus = e.target.parentElement.previousElementSibling.children[index];
3966
+ pivotGrid.navigation.focusElement(elementToFocus, e.target);
3967
+ if (!isVisible(elementToFocus, this.host.nativeElement, this.scrollable.offsetFirst, this.rtl).visibleY) {
3968
+ elementToFocus.scrollIntoView();
3969
+ }
3970
+ }
3971
+ }
3972
+ else if (e.keyCode === Keys.ArrowDown) {
3973
+ const id = e.target.getAttribute('id');
3974
+ if (id.split('-')[4] !== this.totalRows.toString()) {
3975
+ const index = Array.from(e.target.parentElement.children).findIndex(el => el === e.target);
3976
+ const elementToFocus = e.target.parentElement.nextElementSibling.children[index];
3977
+ pivotGrid.navigation.focusElement(elementToFocus, e.target);
3978
+ if (!isVisible(elementToFocus, this.host.nativeElement, this.scrollable.offsetFirst, this.rtl).visibleY) {
3979
+ elementToFocus.scrollIntoView(false);
3980
+ }
3981
+ }
3982
+ }
3983
+ }
3984
+ if (this.tableType === 'rowHeader' && e.target.tagName === 'TH' && e.keyCode === Keys.ArrowRight) {
3985
+ if (e.target.matches(':last-child')) {
3986
+ e.stopImmediatePropagation();
3987
+ e.preventDefault();
3988
+ const valuesContainer = this.host.nativeElement.nextElementSibling;
3989
+ valuesContainer.scrollLeft = this.rtl ? valuesContainer.scrollWidth : 0;
3990
+ this.zone.runOutsideAngular(() => setTimeout(() => {
3991
+ const elementToFocusId = e.target.parentElement.getAttribute('aria-owns').split(' ')[0];
3992
+ const elementToFocus = document.getElementById(elementToFocusId);
3993
+ pivotGrid.navigation.focusElement(elementToFocus, e.target);
3994
+ }));
3995
+ }
3996
+ }
3997
+ if (this.tableType === 'columnHeader' && e.target.tagName === 'TH' && e.keyCode === Keys.ArrowDown) {
3998
+ if (e.target.parentElement.matches(':last-child')) {
3999
+ e.stopImmediatePropagation();
4000
+ e.preventDefault();
4001
+ const valuesContainer = this.host.nativeElement.nextElementSibling.nextElementSibling;
4002
+ valuesContainer.scrollTop = 0;
4003
+ this.zone.runOutsideAngular(() => setTimeout(() => {
4004
+ const elementToFocus = valuesContainer.querySelector(`td[aria-describedby*="${e.target.getAttribute('id')}"]`);
4005
+ pivotGrid.navigation.focusElement(elementToFocus, e.target);
4006
+ }));
4007
+ }
4008
+ }
4009
+ }, true);
3718
4010
  }
3719
4011
  }
3720
- PivotGridTableComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PivotGridTableComponent, deps: [{ token: PivotGridDataService }], target: i0.ɵɵFactoryTarget.Component });
3721
- PivotGridTableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: PivotGridTableComponent, isStandalone: true, selector: "kendo-pivotgrid-table", inputs: { tableType: "tableType", colWidth: "colWidth", customCellTemplate: "customCellTemplate", valueCellTemplate: "valueCellTemplate", rowHeaderCellTemplate: "rowHeaderCellTemplate", columnHeaderCellTemplate: "columnHeaderCellTemplate" }, ngImport: i0, template: `
4012
+ PivotGridTableComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PivotGridTableComponent, deps: [{ token: i0.ElementRef }, { token: PivotGridDataService }, { token: i1$1.LocalizationService }, { token: i0.NgZone }, { token: PivotGridScrollService }], target: i0.ɵɵFactoryTarget.Component });
4013
+ PivotGridTableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: PivotGridTableComponent, isStandalone: true, selector: "kendo-pivotgrid-table", inputs: { tableType: "tableType", colWidth: "colWidth", customCellTemplate: "customCellTemplate", valueCellTemplate: "valueCellTemplate", rowHeaderCellTemplate: "rowHeaderCellTemplate", columnHeaderCellTemplate: "columnHeaderCellTemplate", scrollableSettings: "scrollableSettings" }, ngImport: i0, template: `
3722
4014
  <table
3723
4015
  class="k-pivotgrid-table"
3724
- role="presentation">
4016
+ role="presentation"
4017
+ [ngStyle]="{float: this.tableType === 'values' ? this.rtl ? 'right' : 'left' : 'initial'}">
3725
4018
  <colgroup>
4019
+ <col *ngIf="tableType === 'values' && columnVirtualization && startColIndex > 0" [style.width]="startColIndex * (colWidth >= 0 ? colWidth : 200) + 'px'"/>
3726
4020
  <col
3727
- *ngFor="let item of headerItems;"
4021
+ *ngFor="let item of (tableType === 'values' && columnVirtualization ? headerItems?.slice(0, renderedCols) : headerItems);"
3728
4022
  [style.width]="tableType !== 'rowHeader' ? colWidth >= 0 ? colWidth + 'px' : '200px' : undefined" />
3729
4023
  </colgroup>
3730
4024
  <tbody class="k-pivotgrid-tbody" [attr.role]="tableType === 'values' ? 'none' : 'rowgroup'">
3731
- <tr *ngFor="let row of rows; index as rowIndex"
4025
+ <tr *ngFor="let row of (tableType === 'values' && rowVirtualization ? renderedRows : rows); index as rowIndex"
3732
4026
  class="k-pivotgrid-row"
3733
4027
  [attr.role]="tableType === 'values' ? 'none' : 'row'">
3734
- <ng-container *ngFor="let cell of row.cells; index as colIndex">
4028
+ <td *ngIf="tableType === 'values' && columnVirtualization && startColIndex > 0" class="k-pivotgrid-cell"></td>
4029
+ <ng-container *ngFor="let cell of (tableType === 'values' && columnVirtualization ? row.cells.slice(startColIndex, (startColIndex + renderedCols)) : row.cells); index as colIndex">
3735
4030
  <th
3736
4031
  *ngIf="cell && tableType !== 'values'"
3737
4032
  [kendoPivotGridCell]="cell"
@@ -3739,8 +4034,8 @@ PivotGridTableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0"
3739
4034
  [rowHeaderCellTemplate]="rowHeaderCellTemplate"
3740
4035
  [columnHeaderCellTemplate]="columnHeaderCellTemplate"
3741
4036
  [tableType]="tableType"
3742
- [colIndex]="colIndex"
3743
- [rowIndex]="rowIndex"
4037
+ [colIndex]="colIndex + startColIndex"
4038
+ [rowIndex]="rowIndex + startRowIndex"
3744
4039
  [attr.aria-expanded]="cell.hasChildren && cell.children.length ? 'true' : 'false'"
3745
4040
  [attr.role]="tableType === 'columnHeader' ? 'columnheader' : tableType === 'rowHeader' ? 'rowheader' : 'none'"
3746
4041
  [attr.id]="pivotGridId + (tableType === 'columnHeader' ? 'ch-' : 'rh-') + (rowIndex + 1) + '-' + (colIndex + 1)"></th>
@@ -3750,15 +4045,15 @@ PivotGridTableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0"
3750
4045
  [valueCellTemplate]="valueCellTemplate"
3751
4046
  [kendoPivotGridCell]="cell"
3752
4047
  tableType="values"
3753
- [colIndex]="colIndex"
3754
- [rowIndex]="rowIndex"
4048
+ [colIndex]="colIndex + startColIndex"
4049
+ [rowIndex]="rowIndex + startRowIndex"
3755
4050
  role="gridcell"
3756
- [attr.id]="pivotGridId + 'cell-' + (rowIndex + 1) + '-' + (colIndex + 1)"></td>
4051
+ [attr.id]="pivotGridId + 'cell-' + (rowIndex + startRowIndex + 1) + '-' + (colIndex + startColIndex + 1)"></td>
3757
4052
  </ng-container>
3758
4053
  </tr>
3759
4054
  </tbody>
3760
4055
  </table>
3761
- `, isInline: true, dependencies: [{ kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: PivotGridCellDirective, selector: "[kendoPivotGridCell]", inputs: ["kendoPivotGridCell", "tableType", "rowIndex", "colIndex", "customCellTemplate", "valueCellTemplate", "rowHeaderCellTemplate", "columnHeaderCellTemplate"] }] });
4056
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: PivotGridCellDirective, selector: "[kendoPivotGridCell]", inputs: ["kendoPivotGridCell", "tableType", "rowIndex", "colIndex", "customCellTemplate", "valueCellTemplate", "rowHeaderCellTemplate", "columnHeaderCellTemplate"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
3762
4057
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PivotGridTableComponent, decorators: [{
3763
4058
  type: Component,
3764
4059
  args: [{
@@ -3766,17 +4061,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
3766
4061
  template: `
3767
4062
  <table
3768
4063
  class="k-pivotgrid-table"
3769
- role="presentation">
4064
+ role="presentation"
4065
+ [ngStyle]="{float: this.tableType === 'values' ? this.rtl ? 'right' : 'left' : 'initial'}">
3770
4066
  <colgroup>
4067
+ <col *ngIf="tableType === 'values' && columnVirtualization && startColIndex > 0" [style.width]="startColIndex * (colWidth >= 0 ? colWidth : 200) + 'px'"/>
3771
4068
  <col
3772
- *ngFor="let item of headerItems;"
4069
+ *ngFor="let item of (tableType === 'values' && columnVirtualization ? headerItems?.slice(0, renderedCols) : headerItems);"
3773
4070
  [style.width]="tableType !== 'rowHeader' ? colWidth >= 0 ? colWidth + 'px' : '200px' : undefined" />
3774
4071
  </colgroup>
3775
4072
  <tbody class="k-pivotgrid-tbody" [attr.role]="tableType === 'values' ? 'none' : 'rowgroup'">
3776
- <tr *ngFor="let row of rows; index as rowIndex"
4073
+ <tr *ngFor="let row of (tableType === 'values' && rowVirtualization ? renderedRows : rows); index as rowIndex"
3777
4074
  class="k-pivotgrid-row"
3778
4075
  [attr.role]="tableType === 'values' ? 'none' : 'row'">
3779
- <ng-container *ngFor="let cell of row.cells; index as colIndex">
4076
+ <td *ngIf="tableType === 'values' && columnVirtualization && startColIndex > 0" class="k-pivotgrid-cell"></td>
4077
+ <ng-container *ngFor="let cell of (tableType === 'values' && columnVirtualization ? row.cells.slice(startColIndex, (startColIndex + renderedCols)) : row.cells); index as colIndex">
3780
4078
  <th
3781
4079
  *ngIf="cell && tableType !== 'values'"
3782
4080
  [kendoPivotGridCell]="cell"
@@ -3784,8 +4082,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
3784
4082
  [rowHeaderCellTemplate]="rowHeaderCellTemplate"
3785
4083
  [columnHeaderCellTemplate]="columnHeaderCellTemplate"
3786
4084
  [tableType]="tableType"
3787
- [colIndex]="colIndex"
3788
- [rowIndex]="rowIndex"
4085
+ [colIndex]="colIndex + startColIndex"
4086
+ [rowIndex]="rowIndex + startRowIndex"
3789
4087
  [attr.aria-expanded]="cell.hasChildren && cell.children.length ? 'true' : 'false'"
3790
4088
  [attr.role]="tableType === 'columnHeader' ? 'columnheader' : tableType === 'rowHeader' ? 'rowheader' : 'none'"
3791
4089
  [attr.id]="pivotGridId + (tableType === 'columnHeader' ? 'ch-' : 'rh-') + (rowIndex + 1) + '-' + (colIndex + 1)"></th>
@@ -3795,19 +4093,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
3795
4093
  [valueCellTemplate]="valueCellTemplate"
3796
4094
  [kendoPivotGridCell]="cell"
3797
4095
  tableType="values"
3798
- [colIndex]="colIndex"
3799
- [rowIndex]="rowIndex"
4096
+ [colIndex]="colIndex + startColIndex"
4097
+ [rowIndex]="rowIndex + startRowIndex"
3800
4098
  role="gridcell"
3801
- [attr.id]="pivotGridId + 'cell-' + (rowIndex + 1) + '-' + (colIndex + 1)"></td>
4099
+ [attr.id]="pivotGridId + 'cell-' + (rowIndex + startRowIndex + 1) + '-' + (colIndex + startColIndex + 1)"></td>
3802
4100
  </ng-container>
3803
4101
  </tr>
3804
4102
  </tbody>
3805
4103
  </table>
3806
4104
  `,
3807
4105
  standalone: true,
3808
- imports: [NgFor, NgIf, PivotGridCellDirective]
4106
+ imports: [NgFor, NgIf, PivotGridCellDirective, NgStyle]
3809
4107
  }]
3810
- }], ctorParameters: function () { return [{ type: PivotGridDataService }]; }, propDecorators: { tableType: [{
4108
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: PivotGridDataService }, { type: i1$1.LocalizationService }, { type: i0.NgZone }, { type: PivotGridScrollService }]; }, propDecorators: { tableType: [{
3811
4109
  type: Input
3812
4110
  }], colWidth: [{
3813
4111
  type: Input
@@ -3819,8 +4117,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
3819
4117
  type: Input
3820
4118
  }], columnHeaderCellTemplate: [{
3821
4119
  type: Input
4120
+ }], scrollableSettings: [{
4121
+ type: Input
3822
4122
  }] } });
3823
4123
 
4124
+ /**
4125
+ * @hidden
4126
+ */
4127
+ const DEFAULT_VIRTUALIZATION_SETTINGS = {
4128
+ type: 'both',
4129
+ rowHeight: 37,
4130
+ rows: 50,
4131
+ columns: 10
4132
+ };
4133
+ /**
4134
+ * @hidden
4135
+ */
4136
+ const normalizeVirtualSettings = (settings) => {
4137
+ if (settings === true) {
4138
+ return { ...DEFAULT_VIRTUALIZATION_SETTINGS };
4139
+ }
4140
+ if (!settings) {
4141
+ return null;
4142
+ }
4143
+ return { ...DEFAULT_VIRTUALIZATION_SETTINGS, ...settings };
4144
+ };
4145
+
3824
4146
  const DEFAULT_LOADER_SETTINGS = {
3825
4147
  type: 'converging-spinner',
3826
4148
  themeColor: 'primary',
@@ -3834,12 +4156,13 @@ const DEFAULT_CONFIGURATOR_SETTINGS = {
3834
4156
  * Represents the Kendo UI PivotGrid component for Angular.
3835
4157
  */
3836
4158
  class PivotGridComponent {
3837
- constructor(hostEl, zone, dataService, localization, renderer, _scrollbarWidthService) {
4159
+ constructor(hostEl, zone, dataService, localization, renderer, _scrollbarWidthService, scrollService) {
3838
4160
  this.hostEl = hostEl;
3839
4161
  this.zone = zone;
3840
4162
  this.dataService = dataService;
3841
4163
  this.localization = localization;
3842
4164
  this.renderer = renderer;
4165
+ this.scrollService = scrollService;
3843
4166
  this.hostClass = true;
3844
4167
  /**
3845
4168
  * Specify the width of the column header and data cells. Value is treated as pixels [(see example)]({% slug appearance_pivotgrid %}#toc-column-headers-width).
@@ -3859,6 +4182,7 @@ class PivotGridComponent {
3859
4182
  this.gearSVGIcon = gearIcon;
3860
4183
  this.resizeObservers = [];
3861
4184
  this._loaderSettings = DEFAULT_LOADER_SETTINGS;
4185
+ this._virtualScrolling = normalizeVirtualSettings(false);
3862
4186
  this.subs = new Subscription();
3863
4187
  this.rtl = false;
3864
4188
  this.resizeContainer = (axis, element) => {
@@ -3888,6 +4212,7 @@ class PivotGridComponent {
3888
4212
  this.direction = this.rtl ? 'rtl' : 'ltr';
3889
4213
  }));
3890
4214
  dataService.wrapper = this.hostEl.nativeElement;
4215
+ this.scrollService.pivotGrid = this;
3891
4216
  }
3892
4217
  get rightPositionClass() {
3893
4218
  return this.configuratorSettings?.position === 'right';
@@ -3924,6 +4249,18 @@ class PivotGridComponent {
3924
4249
  get loadingText() {
3925
4250
  return this.localization.get('loading');
3926
4251
  }
4252
+ /**
4253
+ * Sets the virtualization options of the component. By default the virtual scrolling functionality is disabled.
4254
+ *
4255
+ * @default false
4256
+ */
4257
+ set virtualScrolling(value) {
4258
+ this._virtualScrolling = normalizeVirtualSettings(value);
4259
+ this.scrollService.virtualScrolling = !!value;
4260
+ }
4261
+ get virtualScrolling() {
4262
+ return this._virtualScrolling;
4263
+ }
3927
4264
  get configuratorSettings() {
3928
4265
  return this.configurator && Object.assign({}, DEFAULT_CONFIGURATOR_SETTINGS, this.configurator);
3929
4266
  }
@@ -3998,6 +4335,9 @@ class PivotGridComponent {
3998
4335
  }
3999
4336
  }
4000
4337
  }
4338
+ /**
4339
+ * @hidden
4340
+ */
4001
4341
  initNavigation() {
4002
4342
  this.stopNavigation();
4003
4343
  this.navigation = new PivotGridNavigation({ tabIndex: 0 });
@@ -4038,15 +4378,16 @@ class PivotGridComponent {
4038
4378
  }
4039
4379
  }
4040
4380
  }
4041
- PivotGridComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PivotGridComponent, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }, { token: PivotGridDataService }, { token: i1$1.LocalizationService }, { token: i0.Renderer2 }, { token: i1$4.ScrollbarWidthService }], target: i0.ɵɵFactoryTarget.Component });
4042
- PivotGridComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: PivotGridComponent, isStandalone: true, selector: "kendo-pivotgrid", inputs: { loaderSettings: "loaderSettings", configurator: "configurator", columnHeadersWidth: "columnHeadersWidth", navigable: "navigable" }, host: { properties: { "class.k-d-flex": "this.hostClass", "class.k-pos-relative": "this.hostClass", "class.k-flex-row": "this.rightPositionClass", "class.k-flex-row-reverse": "this.leftPositionClass", "class.k-flex-column": "this.bottomPositionClass", "class.k-flex-column-reverse": "this.topPositionClass", "attr.dir": "this.dir" } }, providers: [
4381
+ PivotGridComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PivotGridComponent, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }, { token: PivotGridDataService }, { token: i1$1.LocalizationService }, { token: i0.Renderer2 }, { token: i1$4.ScrollbarWidthService }, { token: PivotGridScrollService }], target: i0.ɵɵFactoryTarget.Component });
4382
+ PivotGridComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: PivotGridComponent, isStandalone: true, selector: "kendo-pivotgrid", inputs: { loaderSettings: "loaderSettings", configurator: "configurator", virtualScrolling: "virtualScrolling", columnHeadersWidth: "columnHeadersWidth", navigable: "navigable" }, host: { properties: { "class.k-d-flex": "this.hostClass", "class.k-pos-relative": "this.hostClass", "class.k-flex-row": "this.rightPositionClass", "class.k-flex-row-reverse": "this.leftPositionClass", "class.k-flex-column": "this.bottomPositionClass", "class.k-flex-column-reverse": "this.topPositionClass", "attr.dir": "this.dir" } }, providers: [
4043
4383
  PivotGridDataService,
4044
4384
  LocalizationService,
4045
4385
  PivotLocalizationService,
4046
4386
  {
4047
4387
  provide: L10N_PREFIX,
4048
4388
  useValue: 'kendo.pivotgrid'
4049
- }
4389
+ },
4390
+ PivotGridScrollService
4050
4391
  ], queries: [{ propertyName: "customCellTemplate", first: true, predicate: CellTemplateDirective, descendants: true }, { propertyName: "valueCellTemplate", first: true, predicate: ValueCellTemplateDirective, descendants: true }, { propertyName: "rowHeaderCellTemplate", first: true, predicate: RowHeaderCellTemplateDirective, descendants: true }, { propertyName: "columnHeaderCellTemplate", first: true, predicate: ColumnHeaderCellTemplateDirective, descendants: true }], viewQueries: [{ propertyName: "colHeadersTable", first: true, predicate: ["colHeadersTable"], descendants: true, read: ElementRef }, { propertyName: "rowHeadersTable", first: true, predicate: ["rowHeadersTable"], descendants: true, read: ElementRef }, { propertyName: "valuesTable", first: true, predicate: ["valuesTable"], descendants: true, read: ElementRef }, { propertyName: "table", first: true, predicate: ["table"], descendants: true, read: ElementRef }, { propertyName: "configuratorWrapper", first: true, predicate: ["configurator"], descendants: true, read: ElementRef }], usesOnChanges: true, ngImport: i0, template: `
4051
4392
  <ng-container kendoPivotGridLocalizedMessages
4052
4393
  i18n-loading="kendo.pivotgrid.loading|The loading text"
@@ -4177,6 +4518,7 @@ PivotGridComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", ver
4177
4518
  [valueCellTemplate]="valueCellTemplate"
4178
4519
  [colWidth]="columnHeadersWidth"
4179
4520
  class="k-pivotgrid-values"
4521
+ [scrollableSettings]="virtualScrolling"
4180
4522
  tableType="values"></kendo-pivotgrid-table>
4181
4523
 
4182
4524
  <div *ngIf="loading" [style]="'position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);'">
@@ -4204,7 +4546,7 @@ PivotGridComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", ver
4204
4546
  <span>{{messageFor('configuratorButtonText')}}<kendo-icon-wrapper name="gear" innerCssClass="k-color-inherit" [svgIcon]="gearSVGIcon"></kendo-icon-wrapper>
4205
4547
  </span>
4206
4548
  </div>
4207
- `, isInline: true, dependencies: [{ kind: "directive", type: LocalizedMessagesDirective, selector: "[kendoPivotGridLocalizedMessages]" }, { kind: "component", type: PivotGridTableComponent, selector: "kendo-pivotgrid-table", inputs: ["tableType", "colWidth", "customCellTemplate", "valueCellTemplate", "rowHeaderCellTemplate", "columnHeaderCellTemplate"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: LoaderComponent, selector: "kendo-loader", inputs: ["type", "themeColor", "size"] }, { kind: "component", type: PivotGridConfiguratorComponent, selector: "kendo-pivotgrid-configurator", inputs: ["orientation", "sort", "filter", "navigation"], outputs: ["close"] }, { kind: "component", type: IconWrapperComponent, selector: "kendo-icon-wrapper", inputs: ["name", "svgIcon", "innerCssClass", "customFontClass", "size"], exportAs: ["kendoIconWrapper"] }] });
4549
+ `, isInline: true, dependencies: [{ kind: "directive", type: LocalizedMessagesDirective, selector: "[kendoPivotGridLocalizedMessages]" }, { kind: "component", type: PivotGridTableComponent, selector: "kendo-pivotgrid-table", inputs: ["tableType", "colWidth", "customCellTemplate", "valueCellTemplate", "rowHeaderCellTemplate", "columnHeaderCellTemplate", "scrollableSettings"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: LoaderComponent, selector: "kendo-loader", inputs: ["type", "themeColor", "size"] }, { kind: "component", type: PivotGridConfiguratorComponent, selector: "kendo-pivotgrid-configurator", inputs: ["orientation", "sort", "filter", "navigation"], outputs: ["close"] }, { kind: "component", type: IconWrapperComponent, selector: "kendo-icon-wrapper", inputs: ["name", "svgIcon", "innerCssClass", "customFontClass", "size"], exportAs: ["kendoIconWrapper"] }] });
4208
4550
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PivotGridComponent, decorators: [{
4209
4551
  type: Component,
4210
4552
  args: [{
@@ -4216,7 +4558,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
4216
4558
  {
4217
4559
  provide: L10N_PREFIX,
4218
4560
  useValue: 'kendo.pivotgrid'
4219
- }
4561
+ },
4562
+ PivotGridScrollService
4220
4563
  ],
4221
4564
  template: `
4222
4565
  <ng-container kendoPivotGridLocalizedMessages
@@ -4348,6 +4691,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
4348
4691
  [valueCellTemplate]="valueCellTemplate"
4349
4692
  [colWidth]="columnHeadersWidth"
4350
4693
  class="k-pivotgrid-values"
4694
+ [scrollableSettings]="virtualScrolling"
4351
4695
  tableType="values"></kendo-pivotgrid-table>
4352
4696
 
4353
4697
  <div *ngIf="loading" [style]="'position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);'">
@@ -4379,7 +4723,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
4379
4723
  standalone: true,
4380
4724
  imports: [LocalizedMessagesDirective, PivotGridTableComponent, NgIf, LoaderComponent, PivotGridConfiguratorComponent, IconWrapperComponent]
4381
4725
  }]
4382
- }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.NgZone }, { type: PivotGridDataService }, { type: i1$1.LocalizationService }, { type: i0.Renderer2 }, { type: i1$4.ScrollbarWidthService }]; }, propDecorators: { hostClass: [{
4726
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.NgZone }, { type: PivotGridDataService }, { type: i1$1.LocalizationService }, { type: i0.Renderer2 }, { type: i1$4.ScrollbarWidthService }, { type: PivotGridScrollService }]; }, propDecorators: { hostClass: [{
4383
4727
  type: HostBinding,
4384
4728
  args: ['class.k-d-flex']
4385
4729
  }, {
@@ -4431,6 +4775,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
4431
4775
  type: Input
4432
4776
  }], configurator: [{
4433
4777
  type: Input
4778
+ }], virtualScrolling: [{
4779
+ type: Input
4434
4780
  }], columnHeadersWidth: [{
4435
4781
  type: Input
4436
4782
  }], navigable: [{