@progress/kendo-angular-grid 24.0.0-develop.19 → 24.0.0-develop.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/databinding.directive.d.ts +1 -0
- package/editing-directives/local-edit.service.d.ts +1 -0
- package/fesm2022/progress-kendo-angular-grid.mjs +2852 -76
- package/grid.component.d.ts +8 -1
- package/grouping/group-settings.d.ts +14 -0
- package/grouping/sticky-groups/models.d.ts +24 -0
- package/grouping/sticky-groups/sticky-group-container.component.d.ts +114 -0
- package/grouping/sticky-groups/sticky-groups-utils.d.ts +71 -0
- package/grouping/sticky-groups/sticky-groups.service.d.ts +132 -0
- package/localization/messages.d.ts +9 -1
- package/navigation/logical-cell.directive.d.ts +4 -2
- package/navigation/navigation.service.d.ts +19 -0
- package/navigation/skip-cell-navigation.d.ts +12 -0
- package/package-metadata.mjs +2 -2
- package/package.json +24 -24
- package/rendering/cell.component.d.ts +16 -4
- package/rendering/list.component.d.ts +67 -1
- package/rendering/table-body.component.d.ts +1 -0
- package/row-pinning/pinned-row-tracking.service.d.ts +64 -0
- package/row-pinning/row-pin-container.component.d.ts +12 -4
- package/schematics/ngAdd/index.js +7 -7
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
4
|
*-------------------------------------------------------------------------------------------*/
|
|
5
5
|
import * as i0 from '@angular/core';
|
|
6
|
-
import { EventEmitter, Injectable, SecurityContext, InjectionToken, Optional, Inject, Input, SkipSelf, Directive, isDevMode, QueryList, ContentChildren, ContentChild, Component, forwardRef, Host, Output, HostBinding, Pipe, TemplateRef, ViewChild, ViewChildren, ChangeDetectionStrategy, Self, NgZone,
|
|
6
|
+
import { EventEmitter, Injectable, SecurityContext, InjectionToken, Optional, Inject, Input, SkipSelf, Directive, isDevMode, QueryList, ContentChildren, ContentChild, Component, forwardRef, Host, Output, HostBinding, HostListener, Pipe, TemplateRef, ViewChild, ViewChildren, ChangeDetectionStrategy, Self, NgZone, ElementRef, ViewContainerRef, ViewEncapsulation, inject, Injector, NgModule } from '@angular/core';
|
|
7
7
|
import { merge, of, Subject, zip as zip$1, from, Subscription, interval, fromEvent, Observable, BehaviorSubject } from 'rxjs';
|
|
8
8
|
import * as i1$3 from '@progress/kendo-angular-common';
|
|
9
9
|
import { isDocumentAvailable, Keys, hasClasses as hasClasses$1, isPresent as isPresent$1, normalizeKeys, anyChanged, TemplateContextDirective, DraggableDirective, EventsOutsideAngularDirective, replaceMessagePlaceholder, isChanged as isChanged$1, KendoInput, guid, areObjectsEqual, PrefixTemplateDirective, closest as closest$1, hasObservers, ResizeSensorComponent, isFirefox, firefoxMaxHeight, closestInScope as closestInScope$1, isFocusable as isFocusable$1, getLicenseMessage, shouldShowValidationUI, WatermarkOverlayComponent, PreventableEvent as PreventableEvent$1, ResizeBatchService } from '@progress/kendo-angular-common';
|
|
@@ -3647,8 +3647,15 @@ class NavigationService {
|
|
|
3647
3647
|
lastCellRowIndex;
|
|
3648
3648
|
isShiftPressed = false;
|
|
3649
3649
|
currentSelection = [];
|
|
3650
|
+
zonePositions = {
|
|
3651
|
+
'pinned-top': null,
|
|
3652
|
+
'main': null,
|
|
3653
|
+
'pinned-bottom': null
|
|
3654
|
+
};
|
|
3655
|
+
currentZone = 'main';
|
|
3650
3656
|
get activeDataRow() {
|
|
3651
|
-
|
|
3657
|
+
const pinnedTopCount = this.meta ? this.meta.pinnedTopRowsCount : 0;
|
|
3658
|
+
return Math.min(Math.max(0, this.activeRowIndex - this.meta.headerRows - pinnedTopCount), this.meta.maxLogicalRowIndex);
|
|
3652
3659
|
}
|
|
3653
3660
|
constructor(zone, domEvents, pagerContextService, scrollRequestService, groupsService, detailsService, focusRoot, editService, cd, ctx, resizeService, focusableParent) {
|
|
3654
3661
|
this.zone = zone;
|
|
@@ -3769,6 +3776,64 @@ class NavigationService {
|
|
|
3769
3776
|
isCellFocused(cell) {
|
|
3770
3777
|
return this.mode === 1 /* NavigationMode.Cursor */ && this.isCellFocusable(cell);
|
|
3771
3778
|
}
|
|
3779
|
+
/**
|
|
3780
|
+
* Returns the navigation zone for a given logical row index.
|
|
3781
|
+
* Rows inside the pinned-top container return `'pinned-top'`,
|
|
3782
|
+
* rows inside the pinned-bottom container return `'pinned-bottom'`,
|
|
3783
|
+
* and all other rows (including header rows) return `'main'`.
|
|
3784
|
+
*/
|
|
3785
|
+
getZone(rowIndex) {
|
|
3786
|
+
if (!this.meta) {
|
|
3787
|
+
return 'main';
|
|
3788
|
+
}
|
|
3789
|
+
const headerRows = this.meta.headerRows;
|
|
3790
|
+
const pinnedTopCount = this.meta.pinnedTopRowsCount;
|
|
3791
|
+
const dataRows = this.meta.dataRows;
|
|
3792
|
+
// Pinned-top rows span [headerRows .. headerRows + pinnedTopCount - 1]
|
|
3793
|
+
if (pinnedTopCount > 0 && rowIndex >= headerRows && rowIndex < headerRows + pinnedTopCount) {
|
|
3794
|
+
return 'pinned-top';
|
|
3795
|
+
}
|
|
3796
|
+
// Pinned-bottom rows start at headerRows + pinnedTopCount + dataRows
|
|
3797
|
+
const pinnedBottomStart = headerRows + pinnedTopCount + dataRows;
|
|
3798
|
+
if (this.meta.pinnedBottomRowsCount > 0 && rowIndex >= pinnedBottomStart && rowIndex < pinnedBottomStart + this.meta.pinnedBottomRowsCount) {
|
|
3799
|
+
return 'pinned-bottom';
|
|
3800
|
+
}
|
|
3801
|
+
return 'main';
|
|
3802
|
+
}
|
|
3803
|
+
/**
|
|
3804
|
+
* Returns `true` when the given cell should carry a `tabIndex="0"` attribute as the
|
|
3805
|
+
* preserved Tab stop for an inactive navigation zone.
|
|
3806
|
+
*
|
|
3807
|
+
* When pinned rows are present, each zone (pinned-top, main body, pinned-bottom) independently
|
|
3808
|
+
* remembers its last active cell. This allows the Tab key to cycle between zones naturally
|
|
3809
|
+
* via DOM order, giving each zone its own Tab stop.
|
|
3810
|
+
*/
|
|
3811
|
+
isCellZonePreserved(rowIndex, colIndex) {
|
|
3812
|
+
if (!this.alive || !this.meta) {
|
|
3813
|
+
return false;
|
|
3814
|
+
}
|
|
3815
|
+
if (this.meta.pinnedTopRowsCount === 0 && this.meta.pinnedBottomRowsCount === 0) {
|
|
3816
|
+
return false;
|
|
3817
|
+
}
|
|
3818
|
+
if (this.mode === 0 /* NavigationMode.Standby */) {
|
|
3819
|
+
return false;
|
|
3820
|
+
}
|
|
3821
|
+
const cellZone = this.getZone(rowIndex);
|
|
3822
|
+
if (cellZone === this.currentZone) {
|
|
3823
|
+
return false;
|
|
3824
|
+
}
|
|
3825
|
+
if (cellZone === 'pinned-top' && this.meta.pinnedTopRowsCount === 0) {
|
|
3826
|
+
return false;
|
|
3827
|
+
}
|
|
3828
|
+
if (cellZone === 'pinned-bottom' && this.meta.pinnedBottomRowsCount === 0) {
|
|
3829
|
+
return false;
|
|
3830
|
+
}
|
|
3831
|
+
const preserved = this.zonePositions[cellZone];
|
|
3832
|
+
const firstInZone = this.firstRowInZone(cellZone);
|
|
3833
|
+
const preservedRow = preserved ? preserved.rowIndex : firstInZone;
|
|
3834
|
+
const preservedCol = preserved ? preserved.colIndex : 0;
|
|
3835
|
+
return rowIndex === preservedRow && colIndex === preservedCol;
|
|
3836
|
+
}
|
|
3772
3837
|
navigateTo(el) {
|
|
3773
3838
|
if (!this.alive || !isDocumentAvailable()) {
|
|
3774
3839
|
return;
|
|
@@ -3836,13 +3901,19 @@ class NavigationService {
|
|
|
3836
3901
|
this.viewport = new NavigationViewport(firstItemIndex, lastItemIndex);
|
|
3837
3902
|
if (this.meta && this.meta.isVirtual && this.activeDataRow > -1) {
|
|
3838
3903
|
const dataRowIndex = this.activeDataRow;
|
|
3839
|
-
|
|
3840
|
-
const
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
this.
|
|
3904
|
+
// Pinned rows are always visible — skip viewport clamping for them
|
|
3905
|
+
const zone = this.getZone(this.activeRowIndex);
|
|
3906
|
+
const isPinnedRow = zone === 'pinned-top' || zone === 'pinned-bottom';
|
|
3907
|
+
if (!isPinnedRow) {
|
|
3908
|
+
const ahead = firstItemIndex - dataRowIndex;
|
|
3909
|
+
const behind = dataRowIndex - lastItemIndex;
|
|
3910
|
+
const logicalOffset = this.meta.headerRows + this.meta.pinnedTopRowsCount;
|
|
3911
|
+
if (ahead > 0) {
|
|
3912
|
+
this.cursor.reset(firstItemIndex + logicalOffset);
|
|
3913
|
+
}
|
|
3914
|
+
else if (behind > 0) {
|
|
3915
|
+
this.cursor.reset(lastItemIndex + logicalOffset);
|
|
3916
|
+
}
|
|
3846
3917
|
}
|
|
3847
3918
|
}
|
|
3848
3919
|
}
|
|
@@ -4013,11 +4084,36 @@ class NavigationService {
|
|
|
4013
4084
|
const isRowReorderable = this.ctx.grid.rowReorderable;
|
|
4014
4085
|
switch (code) {
|
|
4015
4086
|
case Keys.ArrowDown:
|
|
4016
|
-
case Keys.ArrowUp:
|
|
4087
|
+
case Keys.ArrowUp: {
|
|
4017
4088
|
if (rowspan > 1) {
|
|
4018
4089
|
rowspanOffset = this.calculateRowspanOffset(dir, rowspan);
|
|
4019
4090
|
step += rowspanOffset;
|
|
4020
4091
|
}
|
|
4092
|
+
const isDown = code === Keys.ArrowDown;
|
|
4093
|
+
const currentZone = this.meta ? this.getZone(this.activeRowIndex) : 'main';
|
|
4094
|
+
const atPinnedBoundary = this.meta?.isVirtual && ((isDown && currentZone === 'pinned-top' && this.activeRowIndex === this.firstRowInZone('main') - 1) ||
|
|
4095
|
+
(!isDown && currentZone === 'pinned-bottom' && this.activeRowIndex === this.firstRowInZone('pinned-bottom')));
|
|
4096
|
+
if (atPinnedBoundary && !args.shiftKey) {
|
|
4097
|
+
const targetRow = isDown
|
|
4098
|
+
? this.firstRowInZone('main')
|
|
4099
|
+
: this.firstRowInZone('pinned-bottom') - 1;
|
|
4100
|
+
const targetModelRow = this.model.findRow(targetRow);
|
|
4101
|
+
let targetColIndex;
|
|
4102
|
+
if (!targetModelRow) {
|
|
4103
|
+
targetColIndex = 0;
|
|
4104
|
+
this.virtualCell = true;
|
|
4105
|
+
}
|
|
4106
|
+
else if (targetModelRow.groupItem) {
|
|
4107
|
+
targetColIndex = 0;
|
|
4108
|
+
}
|
|
4109
|
+
else {
|
|
4110
|
+
targetColIndex = this.cursor.cell?.colIndex ?? 0;
|
|
4111
|
+
}
|
|
4112
|
+
this.cursor.reset(targetRow, targetColIndex);
|
|
4113
|
+
preventDefault = true;
|
|
4114
|
+
this.lastCellRowIndex = this.activeRowIndex;
|
|
4115
|
+
break;
|
|
4116
|
+
}
|
|
4021
4117
|
if (args.shiftKey && !(isDragCell && isRowReorderable)) {
|
|
4022
4118
|
if (this.ctx.grid.blockArrowSelection) {
|
|
4023
4119
|
return;
|
|
@@ -4034,6 +4130,7 @@ class NavigationService {
|
|
|
4034
4130
|
}
|
|
4035
4131
|
this.lastCellRowIndex = this.activeRowIndex;
|
|
4036
4132
|
break;
|
|
4133
|
+
}
|
|
4037
4134
|
case Keys.ArrowRight:
|
|
4038
4135
|
case Keys.ArrowLeft:
|
|
4039
4136
|
if (args.altKey && !args.shiftKey && !args.ctrlKey && !args.metaKey &&
|
|
@@ -4283,10 +4380,36 @@ class NavigationService {
|
|
|
4283
4380
|
this.cellKeydown.emit(args);
|
|
4284
4381
|
return true;
|
|
4285
4382
|
}
|
|
4383
|
+
firstRowInZone(zone) {
|
|
4384
|
+
if (!this.meta) {
|
|
4385
|
+
return 0;
|
|
4386
|
+
}
|
|
4387
|
+
const headerRows = this.meta.headerRows;
|
|
4388
|
+
const pinnedTopCount = this.meta.pinnedTopRowsCount;
|
|
4389
|
+
const dataRows = this.meta.dataRows;
|
|
4390
|
+
switch (zone) {
|
|
4391
|
+
case 'pinned-top': return headerRows;
|
|
4392
|
+
case 'main': return headerRows + pinnedTopCount;
|
|
4393
|
+
case 'pinned-bottom': return headerRows + pinnedTopCount + dataRows;
|
|
4394
|
+
}
|
|
4395
|
+
}
|
|
4286
4396
|
onCursorChanges(args) {
|
|
4397
|
+
if (this.meta) {
|
|
4398
|
+
const newZone = this.getZone(args.rowIndex);
|
|
4399
|
+
if (newZone !== this.currentZone) {
|
|
4400
|
+
// Save the position we're leaving as the preserved Tab stop for that zone
|
|
4401
|
+
if (args.prevRowIndex >= 0) {
|
|
4402
|
+
this.zonePositions[this.currentZone] = { rowIndex: args.prevRowIndex, colIndex: args.prevColIndex };
|
|
4403
|
+
}
|
|
4404
|
+
this.currentZone = newZone;
|
|
4405
|
+
}
|
|
4406
|
+
}
|
|
4287
4407
|
this.activeRowIndex = args.rowIndex;
|
|
4288
4408
|
const dataRowIndex = this.activeDataRow;
|
|
4289
|
-
|
|
4409
|
+
// Pinned rows are always visible — skip virtual scroll adjustment
|
|
4410
|
+
const zone = this.meta ? this.getZone(args.rowIndex) : 'main';
|
|
4411
|
+
const isPinnedRow = zone === 'pinned-top' || zone === 'pinned-bottom';
|
|
4412
|
+
if (!isPinnedRow && this.meta && (this.meta.isVirtual &&
|
|
4290
4413
|
args.rowIndex >= this.meta.headerRows &&
|
|
4291
4414
|
args.rowIndex <= this.meta.maxLogicalRowIndex - this.meta.footerRow &&
|
|
4292
4415
|
this.viewport &&
|
|
@@ -4294,6 +4417,12 @@ class NavigationService {
|
|
|
4294
4417
|
dataRowIndex > -1)) {
|
|
4295
4418
|
this.scrollRequestService.scrollTo({ row: dataRowIndex });
|
|
4296
4419
|
}
|
|
4420
|
+
if (!isPinnedRow && this.meta && !this.meta.isVirtual && !this.meta.hasPager) {
|
|
4421
|
+
const prevZone = this.meta ? this.getZone(args.prevRowIndex) : 'main';
|
|
4422
|
+
if (prevZone === 'pinned-top' || prevZone === 'pinned-bottom') {
|
|
4423
|
+
this.scrollRequestService.scrollTo({ row: dataRowIndex });
|
|
4424
|
+
}
|
|
4425
|
+
}
|
|
4297
4426
|
if (this.meta.virtualColumns && args.colIndex >= this.meta.columns.lockedLeafColumns.length) {
|
|
4298
4427
|
const cell = this.activeCell;
|
|
4299
4428
|
const { start, end } = this.model.cellRange(cell);
|
|
@@ -5417,6 +5546,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
5417
5546
|
type: Injectable
|
|
5418
5547
|
}] });
|
|
5419
5548
|
|
|
5549
|
+
/**
|
|
5550
|
+
* @hidden
|
|
5551
|
+
* When provided as `true`, LogicalCellDirective instances skip all
|
|
5552
|
+
* registration, focus management, and keyboard handling. Used by the
|
|
5553
|
+
* sticky-group overlay container which manages its own focus independently.
|
|
5554
|
+
*/
|
|
5555
|
+
const SKIP_CELL_NAVIGATION = new InjectionToken('skip-cell-navigation');
|
|
5556
|
+
|
|
5420
5557
|
let id$3 = 0;
|
|
5421
5558
|
function nextId$1() {
|
|
5422
5559
|
return id$3++;
|
|
@@ -5433,6 +5570,7 @@ class LogicalCellDirective {
|
|
|
5433
5570
|
renderer;
|
|
5434
5571
|
zone;
|
|
5435
5572
|
cellContext;
|
|
5573
|
+
skipNavigation;
|
|
5436
5574
|
logicalColIndex;
|
|
5437
5575
|
logicalRowIndex;
|
|
5438
5576
|
logicalSlaveCell = false;
|
|
@@ -5446,6 +5584,9 @@ class LogicalCellDirective {
|
|
|
5446
5584
|
headerLabelText;
|
|
5447
5585
|
uid = nextId$1();
|
|
5448
5586
|
get id() {
|
|
5587
|
+
if (this.skipNavigation) {
|
|
5588
|
+
return undefined;
|
|
5589
|
+
}
|
|
5449
5590
|
if (!this.logicalSlaveCell && this.columnInfoService.isLocked) {
|
|
5450
5591
|
return this.idService.cellId(this.logicalRowIndex, this.logicalColIndex);
|
|
5451
5592
|
}
|
|
@@ -5463,7 +5604,7 @@ class LogicalCellDirective {
|
|
|
5463
5604
|
return this.logicalColIndex + 1;
|
|
5464
5605
|
}
|
|
5465
5606
|
navigationChange;
|
|
5466
|
-
constructor(focusGroup, element, columnInfoService, idService, navigationService, renderer, zone, cellContext) {
|
|
5607
|
+
constructor(focusGroup, element, columnInfoService, idService, navigationService, renderer, zone, cellContext, skipNavigation) {
|
|
5467
5608
|
this.focusGroup = focusGroup;
|
|
5468
5609
|
this.element = element;
|
|
5469
5610
|
this.columnInfoService = columnInfoService;
|
|
@@ -5472,15 +5613,24 @@ class LogicalCellDirective {
|
|
|
5472
5613
|
this.renderer = renderer;
|
|
5473
5614
|
this.zone = zone;
|
|
5474
5615
|
this.cellContext = cellContext;
|
|
5616
|
+
this.skipNavigation = skipNavigation;
|
|
5617
|
+
}
|
|
5618
|
+
onMouseDown() {
|
|
5619
|
+
if (this.skipNavigation) {
|
|
5620
|
+
return;
|
|
5621
|
+
}
|
|
5622
|
+
if (this.logicalSlaveCell && this.navigationService.tableEnabled) {
|
|
5623
|
+
this.navigationService.focusCell(this.logicalRowIndex, this.logicalColIndex);
|
|
5624
|
+
}
|
|
5475
5625
|
}
|
|
5476
5626
|
ngOnInit() {
|
|
5477
|
-
if (!this.navigationService.tableEnabled) {
|
|
5627
|
+
if (this.skipNavigation || !this.navigationService.tableEnabled) {
|
|
5478
5628
|
return;
|
|
5479
5629
|
}
|
|
5480
5630
|
this.navigationChange = this.navigationService.changes.subscribe((e) => this.onNavigationChange(e));
|
|
5481
5631
|
}
|
|
5482
5632
|
ngDoCheck() {
|
|
5483
|
-
if (!this.navigationService.tableEnabled || this.logicalColIndex === -1) {
|
|
5633
|
+
if (this.skipNavigation || !this.navigationService.tableEnabled || this.logicalColIndex === -1) {
|
|
5484
5634
|
return;
|
|
5485
5635
|
}
|
|
5486
5636
|
if (this.cellContext) {
|
|
@@ -5489,7 +5639,7 @@ class LogicalCellDirective {
|
|
|
5489
5639
|
this.registerNoChanges();
|
|
5490
5640
|
}
|
|
5491
5641
|
ngOnChanges(changes) {
|
|
5492
|
-
if (!this.navigationService.tableEnabled) {
|
|
5642
|
+
if (this.skipNavigation || !this.navigationService.tableEnabled) {
|
|
5493
5643
|
return;
|
|
5494
5644
|
}
|
|
5495
5645
|
const keys = Object.keys(changes);
|
|
@@ -5506,6 +5656,9 @@ class LogicalCellDirective {
|
|
|
5506
5656
|
this.updateElement();
|
|
5507
5657
|
}
|
|
5508
5658
|
ngOnDestroy() {
|
|
5659
|
+
if (this.skipNavigation) {
|
|
5660
|
+
return;
|
|
5661
|
+
}
|
|
5509
5662
|
if (this.navigationChange) {
|
|
5510
5663
|
this.navigationChange.unsubscribe();
|
|
5511
5664
|
}
|
|
@@ -5562,13 +5715,14 @@ class LogicalCellDirective {
|
|
|
5562
5715
|
}
|
|
5563
5716
|
}
|
|
5564
5717
|
isFocusable() {
|
|
5565
|
-
return this.navigationService.isCellFocusable(this)
|
|
5718
|
+
return this.navigationService.isCellFocusable(this) ||
|
|
5719
|
+
this.navigationService.isCellZonePreserved(this.logicalRowIndex, this.logicalColIndex);
|
|
5566
5720
|
}
|
|
5567
5721
|
isFocused() {
|
|
5568
5722
|
return this.navigationService.isCellFocused(this);
|
|
5569
5723
|
}
|
|
5570
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: LogicalCellDirective, deps: [{ token: FocusGroup }, { token: i0.ElementRef }, { token: ColumnInfoService }, { token: IdService }, { token: NavigationService }, { token: i0.Renderer2 }, { token: i0.NgZone }, { token: CELL_CONTEXT, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
|
|
5571
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.20", type: LogicalCellDirective, isStandalone: true, selector: "[kendoGridLogicalCell]", inputs: { logicalColIndex: "logicalColIndex", logicalRowIndex: "logicalRowIndex", logicalSlaveCell: "logicalSlaveCell", colIndex: "colIndex", colSpan: "colSpan", rowSpan: "rowSpan", groupItem: "groupItem", dataRowIndex: "dataRowIndex", dataItem: "dataItem", detailExpandCell: "detailExpandCell", headerLabelText: "headerLabelText" }, host: { properties: { "attr.id": "this.id", "attr.rowspan": "this.cellRowspan", "class.k-table-td-row-span": "this.rowspanClass", "attr.aria-colindex": "this.ariaColIndex" } }, providers: [{
|
|
5724
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: LogicalCellDirective, deps: [{ token: FocusGroup }, { token: i0.ElementRef }, { token: ColumnInfoService }, { token: IdService }, { token: NavigationService }, { token: i0.Renderer2 }, { token: i0.NgZone }, { token: CELL_CONTEXT, optional: true }, { token: SKIP_CELL_NAVIGATION, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
|
|
5725
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.20", type: LogicalCellDirective, isStandalone: true, selector: "[kendoGridLogicalCell]", inputs: { logicalColIndex: "logicalColIndex", logicalRowIndex: "logicalRowIndex", logicalSlaveCell: "logicalSlaveCell", colIndex: "colIndex", colSpan: "colSpan", rowSpan: "rowSpan", groupItem: "groupItem", dataRowIndex: "dataRowIndex", dataItem: "dataItem", detailExpandCell: "detailExpandCell", headerLabelText: "headerLabelText" }, host: { listeners: { "mousedown": "onMouseDown()" }, properties: { "attr.id": "this.id", "attr.rowspan": "this.cellRowspan", "class.k-table-td-row-span": "this.rowspanClass", "attr.aria-colindex": "this.ariaColIndex" } }, providers: [{
|
|
5572
5726
|
provide: FocusGroup,
|
|
5573
5727
|
deps: [FocusRoot],
|
|
5574
5728
|
useClass: FocusGroup
|
|
@@ -5590,6 +5744,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
5590
5744
|
}, {
|
|
5591
5745
|
type: Inject,
|
|
5592
5746
|
args: [CELL_CONTEXT]
|
|
5747
|
+
}] }, { type: undefined, decorators: [{
|
|
5748
|
+
type: Optional
|
|
5749
|
+
}, {
|
|
5750
|
+
type: Inject,
|
|
5751
|
+
args: [SKIP_CELL_NAVIGATION]
|
|
5593
5752
|
}] }], propDecorators: { logicalColIndex: [{
|
|
5594
5753
|
type: Input
|
|
5595
5754
|
}], logicalRowIndex: [{
|
|
@@ -5624,6 +5783,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
5624
5783
|
}], ariaColIndex: [{
|
|
5625
5784
|
type: HostBinding,
|
|
5626
5785
|
args: ['attr.aria-colindex']
|
|
5786
|
+
}], onMouseDown: [{
|
|
5787
|
+
type: HostListener,
|
|
5788
|
+
args: ['mousedown']
|
|
5627
5789
|
}] } });
|
|
5628
5790
|
|
|
5629
5791
|
let id$2 = 0;
|
|
@@ -21655,9 +21817,13 @@ class CellComponent {
|
|
|
21655
21817
|
ctx;
|
|
21656
21818
|
detailsService;
|
|
21657
21819
|
localization;
|
|
21820
|
+
elementRef;
|
|
21821
|
+
ngZone;
|
|
21822
|
+
renderer;
|
|
21658
21823
|
rowPinService;
|
|
21659
21824
|
cellContext;
|
|
21660
21825
|
inPinContainer;
|
|
21826
|
+
scrollSyncService;
|
|
21661
21827
|
get commandCellClass() {
|
|
21662
21828
|
return this.isCommand(this.column);
|
|
21663
21829
|
}
|
|
@@ -21667,6 +21833,13 @@ class CellComponent {
|
|
|
21667
21833
|
get dragRowHandleLabel() {
|
|
21668
21834
|
return isRowReorderColumn(this.column) ? this.ctx.localization.get('dragRowHandleLabel') : undefined;
|
|
21669
21835
|
}
|
|
21836
|
+
get rowPinLabel() {
|
|
21837
|
+
const isRowPinned = this.isRowPinnedTop || this.isRowPinnedBottom;
|
|
21838
|
+
if (isRowPinColumn(this.column)) {
|
|
21839
|
+
return isRowPinned ? this.ctx.localization.get('rowUnpinLabel') : this.ctx.localization.get('rowPinLabel');
|
|
21840
|
+
}
|
|
21841
|
+
return undefined;
|
|
21842
|
+
}
|
|
21670
21843
|
pinContextMenu;
|
|
21671
21844
|
pinContextMenuTarget;
|
|
21672
21845
|
column;
|
|
@@ -21698,6 +21871,7 @@ class CellComponent {
|
|
|
21698
21871
|
}
|
|
21699
21872
|
if (gridPinnable === true || gridPinnable === 'both') {
|
|
21700
21873
|
this.pinContextMenu.show(this.pinContextMenuTarget.nativeElement);
|
|
21874
|
+
this.subscribeToScrollClose();
|
|
21701
21875
|
}
|
|
21702
21876
|
else {
|
|
21703
21877
|
let menuItem;
|
|
@@ -21714,6 +21888,7 @@ class CellComponent {
|
|
|
21714
21888
|
}
|
|
21715
21889
|
else {
|
|
21716
21890
|
this.pinContextMenu.show(this.pinContextMenuTarget.nativeElement);
|
|
21891
|
+
this.subscribeToScrollClose();
|
|
21717
21892
|
}
|
|
21718
21893
|
const args = {
|
|
21719
21894
|
menuItem,
|
|
@@ -21858,7 +22033,12 @@ class CellComponent {
|
|
|
21858
22033
|
if (!callback) {
|
|
21859
22034
|
return true;
|
|
21860
22035
|
}
|
|
21861
|
-
|
|
22036
|
+
// For pinned container rows, use the stable pinnedIndex (render position within the
|
|
22037
|
+
// container) rather than rowIndex, which fluctuates as the main table virtual-scrolls.
|
|
22038
|
+
const index = this.inPinContainer && this.item?.pinnedIndex !== undefined
|
|
22039
|
+
? this.item.pinnedIndex
|
|
22040
|
+
: this.rowIndex;
|
|
22041
|
+
return callback({ dataItem: this.dataItem, index });
|
|
21862
22042
|
}
|
|
21863
22043
|
isRowSelectable(column) {
|
|
21864
22044
|
const currentColumn = column || this.column;
|
|
@@ -21875,19 +22055,57 @@ class CellComponent {
|
|
|
21875
22055
|
_templateContext = {};
|
|
21876
22056
|
_editTemplateContext = {};
|
|
21877
22057
|
_rowTemplateContext = {};
|
|
21878
|
-
|
|
22058
|
+
keyDownSub;
|
|
22059
|
+
scrollCloseSub = new Subscription();
|
|
22060
|
+
constructor(editService, idService, ctx, detailsService, localization, elementRef, ngZone, renderer, rowPinService, cellContext, inPinContainer, scrollSyncService) {
|
|
21879
22061
|
this.editService = editService;
|
|
21880
22062
|
this.idService = idService;
|
|
21881
22063
|
this.ctx = ctx;
|
|
21882
22064
|
this.detailsService = detailsService;
|
|
21883
22065
|
this.localization = localization;
|
|
22066
|
+
this.elementRef = elementRef;
|
|
22067
|
+
this.ngZone = ngZone;
|
|
22068
|
+
this.renderer = renderer;
|
|
21884
22069
|
this.rowPinService = rowPinService;
|
|
21885
22070
|
this.cellContext = cellContext;
|
|
21886
22071
|
this.inPinContainer = inPinContainer;
|
|
22072
|
+
this.scrollSyncService = scrollSyncService;
|
|
22073
|
+
}
|
|
22074
|
+
ngOnInit() {
|
|
22075
|
+
this.ngZone.runOutsideAngular(() => {
|
|
22076
|
+
this.keyDownSub = this.renderer.listen(this.elementRef.nativeElement, 'keydown', this.onHostKeydown.bind(this));
|
|
22077
|
+
});
|
|
22078
|
+
}
|
|
22079
|
+
ngOnDestroy() {
|
|
22080
|
+
if (this.keyDownSub) {
|
|
22081
|
+
this.keyDownSub();
|
|
22082
|
+
}
|
|
22083
|
+
this.scrollCloseSub.unsubscribe();
|
|
21887
22084
|
}
|
|
21888
22085
|
ngDoCheck() {
|
|
21889
22086
|
this.updateCellContext();
|
|
21890
22087
|
}
|
|
22088
|
+
subscribeToScrollClose() {
|
|
22089
|
+
this.scrollCloseSub.unsubscribe();
|
|
22090
|
+
this.scrollCloseSub = new Subscription();
|
|
22091
|
+
if (this.scrollSyncService) {
|
|
22092
|
+
this.scrollCloseSub.add(this.scrollSyncService.changes.pipe(skip(1)).subscribe(() => this.pinContextMenu?.hide()));
|
|
22093
|
+
}
|
|
22094
|
+
if (this.ctx.grid?.contentScroll) {
|
|
22095
|
+
this.scrollCloseSub.add(this.ctx.grid.contentScroll.subscribe(() => this.pinContextMenu?.hide()));
|
|
22096
|
+
}
|
|
22097
|
+
}
|
|
22098
|
+
onHostKeydown(e) {
|
|
22099
|
+
if (e.code === Keys.Enter || e.code === Keys.NumpadEnter) {
|
|
22100
|
+
if (!isDocumentAvailable() || document.activeElement !== this.elementRef.nativeElement) {
|
|
22101
|
+
return;
|
|
22102
|
+
}
|
|
22103
|
+
if (!this.isRowPinColumn() || !this.isRowPinnable || this.isNew) {
|
|
22104
|
+
return;
|
|
22105
|
+
}
|
|
22106
|
+
this.onPinIconClick();
|
|
22107
|
+
}
|
|
22108
|
+
}
|
|
21891
22109
|
isCommand(column) {
|
|
21892
22110
|
return column instanceof CommandColumnComponent;
|
|
21893
22111
|
}
|
|
@@ -21906,8 +22124,8 @@ class CellComponent {
|
|
|
21906
22124
|
this.cellContext.inPinContainer = !!this.inPinContainer;
|
|
21907
22125
|
}
|
|
21908
22126
|
}
|
|
21909
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: CellComponent, deps: [{ token: EditService }, { token: IdService }, { token: ContextService }, { token: DetailsService }, { token: i1$2.LocalizationService }, { token: RowPinService, optional: true }, { token: CELL_CONTEXT, optional: true }, { token: IS_PIN_CONTAINER, optional: true }], target: i0.ɵɵFactoryTarget.Component });
|
|
21910
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.20", type: CellComponent, isStandalone: true, selector: "[kendoGridCell]", inputs: { column: "column", columns: "columns", columnIndex: "columnIndex", isNew: "isNew", isLoading: "isLoading", isVirtual: "isVirtual", loadingTemplate: "loadingTemplate", detailTemplate: "detailTemplate", item: "item", rowIndex: "rowIndex", dataItem: "dataItem" }, host: { properties: { "class.k-command-cell": "this.commandCellClass", "class.k-drag-cell": "this.dragHandleCellClass", "class.k-touch-action-none": "this.dragHandleCellClass", "attr.aria-label": "this.
|
|
22127
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: CellComponent, deps: [{ token: EditService }, { token: IdService }, { token: ContextService }, { token: DetailsService }, { token: i1$2.LocalizationService }, { token: i0.ElementRef }, { token: i0.NgZone }, { token: i0.Renderer2 }, { token: RowPinService, optional: true }, { token: CELL_CONTEXT, optional: true }, { token: IS_PIN_CONTAINER, optional: true }, { token: ScrollSyncService, optional: true }], target: i0.ɵɵFactoryTarget.Component });
|
|
22128
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.20", type: CellComponent, isStandalone: true, selector: "[kendoGridCell]", inputs: { column: "column", columns: "columns", columnIndex: "columnIndex", isNew: "isNew", isLoading: "isLoading", isVirtual: "isVirtual", loadingTemplate: "loadingTemplate", detailTemplate: "detailTemplate", item: "item", rowIndex: "rowIndex", dataItem: "dataItem" }, host: { properties: { "class.k-command-cell": "this.commandCellClass", "class.k-drag-cell": "this.dragHandleCellClass", "class.k-touch-action-none": "this.dragHandleCellClass", "attr.aria-label": "this.rowPinLabel" } }, viewQueries: [{ propertyName: "pinContextMenu", first: true, predicate: ["pinContextMenu"], descendants: true }, { propertyName: "pinContextMenuTarget", first: true, predicate: ["target"], descendants: true, read: ElementRef }], ngImport: i0, template: `
|
|
21911
22129
|
@if (isStackedLayoutMode) {
|
|
21912
22130
|
<div class="k-grid-stack-row"
|
|
21913
22131
|
[ngClass]="stackedRowClass"
|
|
@@ -22408,7 +22626,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
22408
22626
|
imports: [NgTemplateOutlet, FocusableDirective, SelectionCheckboxDirective, TemplateContextDirective,
|
|
22409
22627
|
IconWrapperComponent, NumericTextBoxComponent, DatePickerComponent, FieldAccessorPipe, ReactiveFormsModule, CheckBoxComponent, TextBoxComponent, NgClass, NgStyle, ButtonComponent, ContextMenuComponent, EventsOutsideAngularDirective]
|
|
22410
22628
|
}]
|
|
22411
|
-
}], ctorParameters: () => [{ type: EditService }, { type: IdService }, { type: ContextService }, { type: DetailsService }, { type: i1$2.LocalizationService }, { type: RowPinService, decorators: [{
|
|
22629
|
+
}], ctorParameters: () => [{ type: EditService }, { type: IdService }, { type: ContextService }, { type: DetailsService }, { type: i1$2.LocalizationService }, { type: i0.ElementRef }, { type: i0.NgZone }, { type: i0.Renderer2 }, { type: RowPinService, decorators: [{
|
|
22412
22630
|
type: Optional
|
|
22413
22631
|
}] }, { type: undefined, decorators: [{
|
|
22414
22632
|
type: Optional
|
|
@@ -22420,6 +22638,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
22420
22638
|
}, {
|
|
22421
22639
|
type: Inject,
|
|
22422
22640
|
args: [IS_PIN_CONTAINER]
|
|
22641
|
+
}] }, { type: ScrollSyncService, decorators: [{
|
|
22642
|
+
type: Optional
|
|
22423
22643
|
}] }], propDecorators: { commandCellClass: [{
|
|
22424
22644
|
type: HostBinding,
|
|
22425
22645
|
args: ['class.k-command-cell']
|
|
@@ -22432,6 +22652,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
22432
22652
|
}], dragRowHandleLabel: [{
|
|
22433
22653
|
type: HostBinding,
|
|
22434
22654
|
args: ['attr.aria-label']
|
|
22655
|
+
}], rowPinLabel: [{
|
|
22656
|
+
type: HostBinding,
|
|
22657
|
+
args: ['attr.aria-label']
|
|
22435
22658
|
}], pinContextMenu: [{
|
|
22436
22659
|
type: ViewChild,
|
|
22437
22660
|
args: ['pinContextMenu']
|
|
@@ -22522,6 +22745,9 @@ class TableBodyComponent {
|
|
|
22522
22745
|
hostClass = true;
|
|
22523
22746
|
groupHeaderSlaveCellsCount;
|
|
22524
22747
|
groupHeaderColumns;
|
|
22748
|
+
// Cached from navigationService.metadata so logicalRowIndex
|
|
22749
|
+
// returns a stable value within a single CD check (avoids NG0100).
|
|
22750
|
+
cachedDataRows = 0;
|
|
22525
22751
|
clickSubscription;
|
|
22526
22752
|
touchSubscription;
|
|
22527
22753
|
l10nSubscription;
|
|
@@ -22583,7 +22809,8 @@ class TableBodyComponent {
|
|
|
22583
22809
|
return this.ctx.localization.get(messageKey);
|
|
22584
22810
|
}
|
|
22585
22811
|
isOdd(item) {
|
|
22586
|
-
|
|
22812
|
+
const index = this.isPinContainer && item.pinnedIndex !== undefined ? item.pinnedIndex : item.index;
|
|
22813
|
+
return index % 2 !== 0;
|
|
22587
22814
|
}
|
|
22588
22815
|
isSelectable(args) {
|
|
22589
22816
|
const rowSelectable = this.isRowSelectable(args);
|
|
@@ -22603,6 +22830,9 @@ class TableBodyComponent {
|
|
|
22603
22830
|
return this.virtualColumns ? index : item;
|
|
22604
22831
|
}
|
|
22605
22832
|
ngDoCheck() {
|
|
22833
|
+
if (this.pinPosition === 'bottom') {
|
|
22834
|
+
this.cachedDataRows = this.navigationService.metadata?.dataRows ?? 0;
|
|
22835
|
+
}
|
|
22606
22836
|
if (this.rowsToRender) {
|
|
22607
22837
|
this.rowsToRender.forEach((item) => {
|
|
22608
22838
|
if (item.type === 'data') {
|
|
@@ -22644,8 +22874,7 @@ class TableBodyComponent {
|
|
|
22644
22874
|
return headerRowCount + rowIndex + 1;
|
|
22645
22875
|
}
|
|
22646
22876
|
if (this.pinPosition === 'bottom') {
|
|
22647
|
-
|
|
22648
|
-
return headerRowCount + pinnedTopCount + dataRows + rowIndex + 1;
|
|
22877
|
+
return headerRowCount + pinnedTopCount + this.cachedDataRows + rowIndex + 1;
|
|
22649
22878
|
}
|
|
22650
22879
|
const skip = this.skip + (this.ctx.scroller?.virtualSkip ?? 0);
|
|
22651
22880
|
let pos = rowIndex + skip;
|
|
@@ -23040,12 +23269,13 @@ class TableBodyComponent {
|
|
|
23040
23269
|
[groupHeaderColumns]="groupHeaderColumns"
|
|
23041
23270
|
[rowIndex]="rowIndex + 1"
|
|
23042
23271
|
[totalColumnsCount]="totalColumnsCount"
|
|
23272
|
+
[attr.data-group-index]="$any(item).index"
|
|
23043
23273
|
kendoGridLogicalRow
|
|
23044
23274
|
[logicalRowIndex]="logicalRowIndex(rowIndex)"
|
|
23045
23275
|
[logicalSlaveRow]="lockedColumnsCount > 0 && !isStackedMode"
|
|
23046
23276
|
[totalColumns]="totalColumns"
|
|
23047
23277
|
[logicalCellsCount]="columns.length"
|
|
23048
|
-
[logicalSlaveCellsCount]="
|
|
23278
|
+
[logicalSlaveCellsCount]="0">
|
|
23049
23279
|
</tr>
|
|
23050
23280
|
}
|
|
23051
23281
|
@if (item.showDataItem) {
|
|
@@ -23390,12 +23620,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
23390
23620
|
[groupHeaderColumns]="groupHeaderColumns"
|
|
23391
23621
|
[rowIndex]="rowIndex + 1"
|
|
23392
23622
|
[totalColumnsCount]="totalColumnsCount"
|
|
23623
|
+
[attr.data-group-index]="$any(item).index"
|
|
23393
23624
|
kendoGridLogicalRow
|
|
23394
23625
|
[logicalRowIndex]="logicalRowIndex(rowIndex)"
|
|
23395
23626
|
[logicalSlaveRow]="lockedColumnsCount > 0 && !isStackedMode"
|
|
23396
23627
|
[totalColumns]="totalColumns"
|
|
23397
23628
|
[logicalCellsCount]="columns.length"
|
|
23398
|
-
[logicalSlaveCellsCount]="
|
|
23629
|
+
[logicalSlaveCellsCount]="0">
|
|
23399
23630
|
</tr>
|
|
23400
23631
|
}
|
|
23401
23632
|
@if (item.showDataItem) {
|
|
@@ -24569,8 +24800,8 @@ const packageMetadata = {
|
|
|
24569
24800
|
productName: 'Kendo UI for Angular',
|
|
24570
24801
|
productCode: 'KENDOUIANGULAR',
|
|
24571
24802
|
productCodes: ['KENDOUIANGULAR'],
|
|
24572
|
-
publishDate:
|
|
24573
|
-
version: '24.0.0-develop.
|
|
24803
|
+
publishDate: 1778149554,
|
|
24804
|
+
version: '24.0.0-develop.20',
|
|
24574
24805
|
licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/'
|
|
24575
24806
|
};
|
|
24576
24807
|
|
|
@@ -27601,6 +27832,1668 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
27601
27832
|
type: Injectable
|
|
27602
27833
|
}], ctorParameters: () => [{ type: RowspanService }, { type: GroupsService }, { type: DetailsService }, { type: ContextService }] });
|
|
27603
27834
|
|
|
27835
|
+
/**
|
|
27836
|
+
* @hidden
|
|
27837
|
+
* Builds a map of group ranges from the flat data array.
|
|
27838
|
+
* Each group header maps to its footer and child range.
|
|
27839
|
+
*/
|
|
27840
|
+
function buildGroupRangeMap(flatDataArray) {
|
|
27841
|
+
const ranges = [];
|
|
27842
|
+
const stack = [];
|
|
27843
|
+
for (let i = 0; i < flatDataArray.length; i++) {
|
|
27844
|
+
const item = flatDataArray[i];
|
|
27845
|
+
if (item.type === 'group') {
|
|
27846
|
+
// A new header at level N closes any open groups at level >= N
|
|
27847
|
+
for (let s = stack.length - 1; s >= 0; s--) {
|
|
27848
|
+
if (stack[s].level >= item.level) {
|
|
27849
|
+
const headerInfo = stack[s];
|
|
27850
|
+
ranges.push({
|
|
27851
|
+
headerIndex: headerInfo.headerIndex,
|
|
27852
|
+
footerIndex: null,
|
|
27853
|
+
firstChildIndex: headerInfo.headerIndex + 1,
|
|
27854
|
+
lastChildIndex: i - 1,
|
|
27855
|
+
level: headerInfo.level
|
|
27856
|
+
});
|
|
27857
|
+
stack.splice(s, 1);
|
|
27858
|
+
}
|
|
27859
|
+
}
|
|
27860
|
+
stack.push({ headerIndex: i, level: item.level });
|
|
27861
|
+
}
|
|
27862
|
+
else if (item.type === 'footer') {
|
|
27863
|
+
for (let s = stack.length - 1; s >= 0; s--) {
|
|
27864
|
+
if (stack[s].level === item.level) {
|
|
27865
|
+
const headerInfo = stack[s];
|
|
27866
|
+
ranges.push({
|
|
27867
|
+
headerIndex: headerInfo.headerIndex,
|
|
27868
|
+
footerIndex: i,
|
|
27869
|
+
firstChildIndex: headerInfo.headerIndex + 1,
|
|
27870
|
+
lastChildIndex: i - 1,
|
|
27871
|
+
level: item.level
|
|
27872
|
+
});
|
|
27873
|
+
stack.splice(s, 1);
|
|
27874
|
+
break;
|
|
27875
|
+
}
|
|
27876
|
+
}
|
|
27877
|
+
}
|
|
27878
|
+
}
|
|
27879
|
+
// Close remaining open groups that extend to the end of the data
|
|
27880
|
+
for (const headerInfo of stack) {
|
|
27881
|
+
ranges.push({
|
|
27882
|
+
headerIndex: headerInfo.headerIndex,
|
|
27883
|
+
footerIndex: null,
|
|
27884
|
+
firstChildIndex: headerInfo.headerIndex + 1,
|
|
27885
|
+
lastChildIndex: flatDataArray.length - 1,
|
|
27886
|
+
level: headerInfo.level
|
|
27887
|
+
});
|
|
27888
|
+
}
|
|
27889
|
+
const map = new Map();
|
|
27890
|
+
for (const range of ranges) {
|
|
27891
|
+
map.set(range.headerIndex, range);
|
|
27892
|
+
}
|
|
27893
|
+
return map;
|
|
27894
|
+
}
|
|
27895
|
+
/**
|
|
27896
|
+
* @hidden
|
|
27897
|
+
* Selects which group headers should be sticky at the top of the viewport.
|
|
27898
|
+
* A header is sticky when it is scrolled above the viewport but its group
|
|
27899
|
+
* children are still visible below.
|
|
27900
|
+
*/
|
|
27901
|
+
function computeStickyItems(flatDataArray, groupRanges, firstVisibleIndex, lastVisibleIndex, rawFirstVisibleIndex) {
|
|
27902
|
+
const footerThreshold = rawFirstVisibleIndex ?? firstVisibleIndex;
|
|
27903
|
+
const matchingRanges = [];
|
|
27904
|
+
for (const range of groupRanges.values()) {
|
|
27905
|
+
if (range.headerIndex < firstVisibleIndex) {
|
|
27906
|
+
// The sticky header stays as a candidate until the next group
|
|
27907
|
+
// header pushes it out. This matches the push boundary logic.
|
|
27908
|
+
const groupEnd = range.footerIndex !== null
|
|
27909
|
+
? range.footerIndex + 1
|
|
27910
|
+
: range.lastChildIndex + 1;
|
|
27911
|
+
if (groupEnd > range.headerIndex && groupEnd >= footerThreshold) {
|
|
27912
|
+
matchingRanges.push(range);
|
|
27913
|
+
}
|
|
27914
|
+
}
|
|
27915
|
+
}
|
|
27916
|
+
// Per level, pick the header with the highest index (closest to viewport)
|
|
27917
|
+
const bestPerLevel = new Map();
|
|
27918
|
+
for (const range of matchingRanges) {
|
|
27919
|
+
const existing = bestPerLevel.get(range.level);
|
|
27920
|
+
if (!existing || range.headerIndex > existing.headerIndex) {
|
|
27921
|
+
bestPerLevel.set(range.level, range);
|
|
27922
|
+
}
|
|
27923
|
+
}
|
|
27924
|
+
// Sort ascending by level: shallowest at top
|
|
27925
|
+
const sortedLevels = Array.from(bestPerLevel.keys()).sort((a, b) => a - b);
|
|
27926
|
+
const result = [];
|
|
27927
|
+
for (const level of sortedLevels) {
|
|
27928
|
+
const range = bestPerLevel.get(level);
|
|
27929
|
+
result.push({ item: flatDataArray[range.headerIndex], flatIndex: range.headerIndex });
|
|
27930
|
+
}
|
|
27931
|
+
return result;
|
|
27932
|
+
}
|
|
27933
|
+
/**
|
|
27934
|
+
* @hidden
|
|
27935
|
+
* Selects which group footers should be sticky at the bottom of the viewport.
|
|
27936
|
+
* A footer is sticky when it is scrolled below the viewport but its group's
|
|
27937
|
+
* header or first child is still visible above.
|
|
27938
|
+
*/
|
|
27939
|
+
function computeStickyFooterItems(flatDataArray, groupRanges, firstVisibleIndex, lastVisibleIndex) {
|
|
27940
|
+
const matchingRanges = [];
|
|
27941
|
+
for (const range of groupRanges.values()) {
|
|
27942
|
+
if (range.footerIndex === null) {
|
|
27943
|
+
continue;
|
|
27944
|
+
}
|
|
27945
|
+
const match = range.footerIndex > lastVisibleIndex && range.headerIndex <= lastVisibleIndex;
|
|
27946
|
+
if (match) {
|
|
27947
|
+
matchingRanges.push(range);
|
|
27948
|
+
}
|
|
27949
|
+
}
|
|
27950
|
+
// Per level, pick the footer closest to viewport bottom (lowest footerIndex)
|
|
27951
|
+
const bestPerLevel = new Map();
|
|
27952
|
+
for (const range of matchingRanges) {
|
|
27953
|
+
const existing = bestPerLevel.get(range.level);
|
|
27954
|
+
if (!existing || range.footerIndex < existing.footerIndex) {
|
|
27955
|
+
bestPerLevel.set(range.level, range);
|
|
27956
|
+
}
|
|
27957
|
+
}
|
|
27958
|
+
// Sort descending by level: deepest at top (closest to content), shallowest at bottom
|
|
27959
|
+
const sortedLevels = Array.from(bestPerLevel.keys()).sort((a, b) => b - a);
|
|
27960
|
+
const result = [];
|
|
27961
|
+
for (const level of sortedLevels) {
|
|
27962
|
+
const range = bestPerLevel.get(level);
|
|
27963
|
+
result.push({ item: flatDataArray[range.footerIndex], flatIndex: range.footerIndex });
|
|
27964
|
+
}
|
|
27965
|
+
return result;
|
|
27966
|
+
}
|
|
27967
|
+
/**
|
|
27968
|
+
* @hidden
|
|
27969
|
+
* Returns true if the displayed groups differ between current and previous arrays.
|
|
27970
|
+
*/
|
|
27971
|
+
function hasStickyItemsChanged(current, prev) {
|
|
27972
|
+
if (current.length !== prev.length) {
|
|
27973
|
+
return true;
|
|
27974
|
+
}
|
|
27975
|
+
for (let i = 0; i < current.length; i++) {
|
|
27976
|
+
if (current[i].flatIndex !== prev[i].flatIndex) {
|
|
27977
|
+
return true;
|
|
27978
|
+
}
|
|
27979
|
+
}
|
|
27980
|
+
return false;
|
|
27981
|
+
}
|
|
27982
|
+
/**
|
|
27983
|
+
* @hidden
|
|
27984
|
+
* Computes push offsets for sticky header overlay rows.
|
|
27985
|
+
* When a group's boundary approaches the sticky slot, the header is pushed upward.
|
|
27986
|
+
*/
|
|
27987
|
+
function computeHeaderPush(indices, getRowHeight, getRowOffset, scrollTop, groupRanges) {
|
|
27988
|
+
const offsets = [];
|
|
27989
|
+
let cumHeight = 0;
|
|
27990
|
+
for (const flatIdx of indices) {
|
|
27991
|
+
const rowH = getRowHeight(flatIdx);
|
|
27992
|
+
let push = 0;
|
|
27993
|
+
const range = groupRanges.get(flatIdx);
|
|
27994
|
+
if (range) {
|
|
27995
|
+
const nextHeaderIndex = range.footerIndex !== null
|
|
27996
|
+
? range.footerIndex + 1
|
|
27997
|
+
: range.lastChildIndex + 1;
|
|
27998
|
+
const boundaryOffset = getRowOffset(nextHeaderIndex);
|
|
27999
|
+
if (boundaryOffset !== undefined) {
|
|
28000
|
+
const slotBottom = cumHeight + rowH;
|
|
28001
|
+
const boundaryRelative = boundaryOffset - scrollTop;
|
|
28002
|
+
if (boundaryRelative < slotBottom) {
|
|
28003
|
+
push = boundaryRelative - slotBottom;
|
|
28004
|
+
}
|
|
28005
|
+
}
|
|
28006
|
+
}
|
|
28007
|
+
offsets.push(push);
|
|
28008
|
+
cumHeight += Math.max(rowH + push, 0);
|
|
28009
|
+
}
|
|
28010
|
+
return { totalHeight: cumHeight, offsets };
|
|
28011
|
+
}
|
|
28012
|
+
/**
|
|
28013
|
+
* @hidden
|
|
28014
|
+
* Computes push offsets for sticky footer overlay rows.
|
|
28015
|
+
* When a group's header approaches the sticky footer slot, the footer is pushed downward.
|
|
28016
|
+
*/
|
|
28017
|
+
function computeFooterPush(indices, getRowHeight, getRowOffset, scrollTop, viewportHeight, footerRanges) {
|
|
28018
|
+
const offsets = new Array(indices.length).fill(0);
|
|
28019
|
+
let cumHeight = 0;
|
|
28020
|
+
// Footers are rendered bottom-up; iterate in reverse
|
|
28021
|
+
for (let i = indices.length - 1; i >= 0; i--) {
|
|
28022
|
+
const flatIdx = indices[i];
|
|
28023
|
+
const rowH = getRowHeight(flatIdx);
|
|
28024
|
+
let push = 0;
|
|
28025
|
+
const range = footerRanges.get(flatIdx);
|
|
28026
|
+
if (range) {
|
|
28027
|
+
const boundaryOffset = getRowOffset(range.headerIndex);
|
|
28028
|
+
if (boundaryOffset !== undefined) {
|
|
28029
|
+
const boundaryBottom = boundaryOffset + getRowHeight(range.headerIndex);
|
|
28030
|
+
const slotTop = scrollTop + viewportHeight - cumHeight - rowH;
|
|
28031
|
+
if (boundaryBottom > slotTop) {
|
|
28032
|
+
push = boundaryBottom - slotTop;
|
|
28033
|
+
}
|
|
28034
|
+
}
|
|
28035
|
+
}
|
|
28036
|
+
offsets[i] = push;
|
|
28037
|
+
cumHeight += Math.max(rowH - push, 0);
|
|
28038
|
+
}
|
|
28039
|
+
return { totalHeight: cumHeight, offsets };
|
|
28040
|
+
}
|
|
28041
|
+
/**
|
|
28042
|
+
* @hidden
|
|
28043
|
+
* Applies push transforms to sticky header overlay rows.
|
|
28044
|
+
* Negative push values slide rows up with clipPath.
|
|
28045
|
+
* Iterates each tbody independently so locked and non-locked tables
|
|
28046
|
+
* both receive the same transforms.
|
|
28047
|
+
*/
|
|
28048
|
+
function applyHeaderPushTransforms(containerEl, pushOffsets) {
|
|
28049
|
+
const tbodies = containerEl.querySelectorAll('tbody');
|
|
28050
|
+
let maxVisibleHeight = 0;
|
|
28051
|
+
let hasPush = false;
|
|
28052
|
+
for (let t = 0; t < tbodies.length; t++) {
|
|
28053
|
+
const trs = tbodies[t].querySelectorAll(':scope > tr');
|
|
28054
|
+
let totalVisibleHeight = 0;
|
|
28055
|
+
for (let i = 0; i < trs.length && i < pushOffsets.length; i++) {
|
|
28056
|
+
const tr = trs[i];
|
|
28057
|
+
const rowH = tr.offsetHeight || tr.getBoundingClientRect().height;
|
|
28058
|
+
const push = pushOffsets[i];
|
|
28059
|
+
if (push < 0) {
|
|
28060
|
+
hasPush = true;
|
|
28061
|
+
const absPush = -push;
|
|
28062
|
+
const visibleHeight = Math.max(rowH - absPush, 0);
|
|
28063
|
+
totalVisibleHeight += visibleHeight;
|
|
28064
|
+
if (visibleHeight <= 0) {
|
|
28065
|
+
tr.style.display = 'none';
|
|
28066
|
+
tr.style.transform = '';
|
|
28067
|
+
tr.style.clipPath = '';
|
|
28068
|
+
}
|
|
28069
|
+
else {
|
|
28070
|
+
tr.style.display = '';
|
|
28071
|
+
tr.style.transform = `translateY(${push}px)`;
|
|
28072
|
+
tr.style.clipPath = `inset(${absPush}px 0 0 0)`;
|
|
28073
|
+
}
|
|
28074
|
+
}
|
|
28075
|
+
else {
|
|
28076
|
+
totalVisibleHeight += rowH;
|
|
28077
|
+
tr.style.display = '';
|
|
28078
|
+
tr.style.transform = '';
|
|
28079
|
+
tr.style.clipPath = '';
|
|
28080
|
+
}
|
|
28081
|
+
}
|
|
28082
|
+
maxVisibleHeight = Math.max(maxVisibleHeight, totalVisibleHeight);
|
|
28083
|
+
}
|
|
28084
|
+
containerEl.style.height = hasPush ? maxVisibleHeight + 'px' : '';
|
|
28085
|
+
}
|
|
28086
|
+
/**
|
|
28087
|
+
* @hidden
|
|
28088
|
+
* Applies push transforms to sticky footer overlay rows.
|
|
28089
|
+
* Positive push values clip from the bottom. The footer container is bottom-anchored,
|
|
28090
|
+
* so reducing its height shifts content down. Non-pushed rows are translated up to compensate.
|
|
28091
|
+
* Iterates each tbody independently so locked and non-locked tables
|
|
28092
|
+
* both receive the same transforms.
|
|
28093
|
+
*/
|
|
28094
|
+
function applyFooterPushTransforms(containerEl, pushOffsets) {
|
|
28095
|
+
const tbodies = containerEl.querySelectorAll('tbody');
|
|
28096
|
+
let maxVisibleHeight = 0;
|
|
28097
|
+
let hasPush = false;
|
|
28098
|
+
for (let t = 0; t < tbodies.length; t++) {
|
|
28099
|
+
const trs = tbodies[t].querySelectorAll(':scope > tr');
|
|
28100
|
+
let totalVisibleHeight = 0;
|
|
28101
|
+
let totalShrink = 0;
|
|
28102
|
+
// First pass: measure heights and compute total shrink
|
|
28103
|
+
const rowHeights = [];
|
|
28104
|
+
for (let i = 0; i < trs.length && i < pushOffsets.length; i++) {
|
|
28105
|
+
const tr = trs[i];
|
|
28106
|
+
const rowH = tr.offsetHeight || tr.getBoundingClientRect().height;
|
|
28107
|
+
rowHeights.push(rowH);
|
|
28108
|
+
const push = pushOffsets[i];
|
|
28109
|
+
if (push > 0) {
|
|
28110
|
+
hasPush = true;
|
|
28111
|
+
const visibleHeight = Math.max(rowH - push, 0);
|
|
28112
|
+
totalVisibleHeight += visibleHeight;
|
|
28113
|
+
totalShrink += rowH - visibleHeight;
|
|
28114
|
+
}
|
|
28115
|
+
else {
|
|
28116
|
+
totalVisibleHeight += rowH;
|
|
28117
|
+
}
|
|
28118
|
+
}
|
|
28119
|
+
// Second pass: apply transforms
|
|
28120
|
+
for (let i = 0; i < trs.length && i < pushOffsets.length; i++) {
|
|
28121
|
+
const tr = trs[i];
|
|
28122
|
+
const push = pushOffsets[i];
|
|
28123
|
+
const rowH = rowHeights[i];
|
|
28124
|
+
if (push > 0) {
|
|
28125
|
+
const visibleHeight = Math.max(rowH - push, 0);
|
|
28126
|
+
if (visibleHeight <= 0) {
|
|
28127
|
+
tr.style.display = '';
|
|
28128
|
+
tr.style.transform = '';
|
|
28129
|
+
tr.style.clipPath = 'inset(0 0 100% 0)';
|
|
28130
|
+
}
|
|
28131
|
+
else {
|
|
28132
|
+
tr.style.display = '';
|
|
28133
|
+
tr.style.transform = '';
|
|
28134
|
+
tr.style.clipPath = `inset(0 0 ${push}px 0)`;
|
|
28135
|
+
}
|
|
28136
|
+
}
|
|
28137
|
+
else {
|
|
28138
|
+
tr.style.display = '';
|
|
28139
|
+
tr.style.transform = hasPush ? `translateY(${-totalShrink}px)` : '';
|
|
28140
|
+
tr.style.clipPath = '';
|
|
28141
|
+
}
|
|
28142
|
+
}
|
|
28143
|
+
maxVisibleHeight = Math.max(maxVisibleHeight, totalVisibleHeight);
|
|
28144
|
+
}
|
|
28145
|
+
containerEl.style.height = hasPush ? maxVisibleHeight + 'px' : '';
|
|
28146
|
+
}
|
|
28147
|
+
/**
|
|
28148
|
+
* @hidden
|
|
28149
|
+
* Resets all push transform styles on rows within a sticky container.
|
|
28150
|
+
*/
|
|
28151
|
+
function resetRowTransforms(containerEl) {
|
|
28152
|
+
const trs = containerEl.querySelectorAll('tbody > tr');
|
|
28153
|
+
for (let i = 0; i < trs.length; i++) {
|
|
28154
|
+
const tr = trs[i];
|
|
28155
|
+
tr.style.transform = '';
|
|
28156
|
+
tr.style.clipPath = '';
|
|
28157
|
+
tr.style.display = '';
|
|
28158
|
+
}
|
|
28159
|
+
containerEl.style.height = '';
|
|
28160
|
+
}
|
|
28161
|
+
|
|
28162
|
+
/**
|
|
28163
|
+
* @hidden
|
|
28164
|
+
* Manages sticky group header and footer state for the Grid.
|
|
28165
|
+
* Computes which groups to pin on each scroll frame and applies DOM transforms
|
|
28166
|
+
* for the push effect. Runs outside Angular zone for performance.
|
|
28167
|
+
*/
|
|
28168
|
+
class StickyGroupsService {
|
|
28169
|
+
ngZone;
|
|
28170
|
+
headerItems$ = new Subject();
|
|
28171
|
+
footerItems$ = new Subject();
|
|
28172
|
+
scrollToFooter$ = new Subject();
|
|
28173
|
+
scrollToRow$ = new Subject();
|
|
28174
|
+
scrollAndToggle$ = new Subject();
|
|
28175
|
+
stickyHeaderItems = [];
|
|
28176
|
+
stickyFooterItems = [];
|
|
28177
|
+
pendingScrollToFooter = null;
|
|
28178
|
+
/**
|
|
28179
|
+
* When set, after the scroll-to-group completes and the view settles,
|
|
28180
|
+
* the sticky container should focus the real grid row for this group.
|
|
28181
|
+
*/
|
|
28182
|
+
pendingFocusGroupIndex = null;
|
|
28183
|
+
focusReady$ = new Subject();
|
|
28184
|
+
/**
|
|
28185
|
+
* When set, the real grid body should scroll until the target row is
|
|
28186
|
+
* rendered, then focus the corresponding cell.
|
|
28187
|
+
*/
|
|
28188
|
+
pendingFocusRow = null;
|
|
28189
|
+
/**
|
|
28190
|
+
* When true, the next update() call is skipped. Used when programmatically
|
|
28191
|
+
* scrolling to top so stale DOM measurements don't re-show the overlay.
|
|
28192
|
+
*/
|
|
28193
|
+
suppressNextUpdate = false;
|
|
28194
|
+
headerPushOffsets = [];
|
|
28195
|
+
footerPushOffsets = [];
|
|
28196
|
+
groupRangeMap = null;
|
|
28197
|
+
lastFlatDataRef = null;
|
|
28198
|
+
constructor(ngZone) {
|
|
28199
|
+
this.ngZone = ngZone;
|
|
28200
|
+
}
|
|
28201
|
+
ngOnDestroy() {
|
|
28202
|
+
this.headerItems$.complete();
|
|
28203
|
+
this.footerItems$.complete();
|
|
28204
|
+
this.scrollToFooter$.complete();
|
|
28205
|
+
this.scrollToRow$.complete();
|
|
28206
|
+
this.scrollAndToggle$.complete();
|
|
28207
|
+
this.focusReady$.complete();
|
|
28208
|
+
}
|
|
28209
|
+
/**
|
|
28210
|
+
* Requests the list component to scroll to the group header and then
|
|
28211
|
+
* toggle it. Called from sticky overlay click — uses pre-collapse data.
|
|
28212
|
+
*/
|
|
28213
|
+
scrollAndToggle(groupIndex) {
|
|
28214
|
+
this.scrollAndToggle$.next(groupIndex);
|
|
28215
|
+
}
|
|
28216
|
+
/**
|
|
28217
|
+
* Requests the grid to scroll so the real footer row at the given flat index
|
|
28218
|
+
* becomes visible at the bottom of the viewport.
|
|
28219
|
+
*/
|
|
28220
|
+
requestScrollToFooter(flatIndex) {
|
|
28221
|
+
this.pendingScrollToFooter = flatIndex;
|
|
28222
|
+
this.scrollToFooter$.next(flatIndex);
|
|
28223
|
+
}
|
|
28224
|
+
/**
|
|
28225
|
+
* Consumes (returns and clears) any pending scroll-to-footer request.
|
|
28226
|
+
*/
|
|
28227
|
+
consumeScrollToFooter() {
|
|
28228
|
+
const target = this.pendingScrollToFooter;
|
|
28229
|
+
this.pendingScrollToFooter = null;
|
|
28230
|
+
return target;
|
|
28231
|
+
}
|
|
28232
|
+
/**
|
|
28233
|
+
* Requests the real grid body to render the row at the given flat index,
|
|
28234
|
+
* then focus the corresponding cell.
|
|
28235
|
+
*/
|
|
28236
|
+
requestScrollToRow(flatIndex, colIndex) {
|
|
28237
|
+
this.pendingFocusRow = { flatIndex, colIndex };
|
|
28238
|
+
this.scrollToRow$.next();
|
|
28239
|
+
}
|
|
28240
|
+
/**
|
|
28241
|
+
* Consumes and clears the pending scroll-to-row request.
|
|
28242
|
+
*/
|
|
28243
|
+
consumeScrollToRow() {
|
|
28244
|
+
const target = this.pendingFocusRow;
|
|
28245
|
+
this.pendingFocusRow = null;
|
|
28246
|
+
return target;
|
|
28247
|
+
}
|
|
28248
|
+
/**
|
|
28249
|
+
* Clears cached group range map so it is rebuilt on next update.
|
|
28250
|
+
*/
|
|
28251
|
+
invalidateRangeMap() {
|
|
28252
|
+
this.groupRangeMap = null;
|
|
28253
|
+
this.lastFlatDataRef = null;
|
|
28254
|
+
}
|
|
28255
|
+
/**
|
|
28256
|
+
* Main update cycle. Called on every scroll event, outside Angular zone.
|
|
28257
|
+
* Computes which headers/footers should be sticky, applies push transforms,
|
|
28258
|
+
* and emits changes only when the set of sticky items changes.
|
|
28259
|
+
*/
|
|
28260
|
+
update(params) {
|
|
28261
|
+
const { container, tbody, flatData, stickyHeaderEl, stickyFooterEl, enableHeaders, enableFooters, rowHeight, skipOffset, rowHeightService } = params;
|
|
28262
|
+
if (!enableHeaders && !enableFooters) {
|
|
28263
|
+
return;
|
|
28264
|
+
}
|
|
28265
|
+
if (!container || !tbody) {
|
|
28266
|
+
return;
|
|
28267
|
+
}
|
|
28268
|
+
if (this.suppressNextUpdate) {
|
|
28269
|
+
this.suppressNextUpdate = false;
|
|
28270
|
+
return;
|
|
28271
|
+
}
|
|
28272
|
+
// Rebuild range map if flat data reference changed
|
|
28273
|
+
if (flatData !== this.lastFlatDataRef) {
|
|
28274
|
+
this.groupRangeMap = buildGroupRangeMap(flatData);
|
|
28275
|
+
this.lastFlatDataRef = flatData;
|
|
28276
|
+
}
|
|
28277
|
+
const groupRanges = this.groupRangeMap;
|
|
28278
|
+
if (!groupRanges || groupRanges.size === 0) {
|
|
28279
|
+
this.clearAll(stickyHeaderEl, stickyFooterEl, container);
|
|
28280
|
+
return;
|
|
28281
|
+
}
|
|
28282
|
+
const footerRanges = new Map();
|
|
28283
|
+
if (enableFooters) {
|
|
28284
|
+
for (const range of groupRanges.values()) {
|
|
28285
|
+
if (range.footerIndex !== null) {
|
|
28286
|
+
footerRanges.set(range.footerIndex, range);
|
|
28287
|
+
}
|
|
28288
|
+
}
|
|
28289
|
+
}
|
|
28290
|
+
const scrollTop = container.scrollTop;
|
|
28291
|
+
const viewportHeight = container.clientHeight;
|
|
28292
|
+
const rows = tbody.children;
|
|
28293
|
+
if (rows.length === 0) {
|
|
28294
|
+
this.clearAll(stickyHeaderEl, stickyFooterEl, container);
|
|
28295
|
+
return;
|
|
28296
|
+
}
|
|
28297
|
+
const defaultRowHeight = rowHeight || 36;
|
|
28298
|
+
const skip = skipOffset || 0;
|
|
28299
|
+
const rhs = rowHeightService;
|
|
28300
|
+
// Measure DOM row positions
|
|
28301
|
+
const containerRect = container.getBoundingClientRect();
|
|
28302
|
+
const tbodyTop = tbody.getBoundingClientRect().top - containerRect.top + scrollTop;
|
|
28303
|
+
const rowCount = rows.length;
|
|
28304
|
+
const rowTops = new Array(rowCount);
|
|
28305
|
+
const rowHeightsArr = new Array(rowCount);
|
|
28306
|
+
for (let i = 0; i < rowCount; i++) {
|
|
28307
|
+
const row = rows[i];
|
|
28308
|
+
rowTops[i] = tbodyTop + row.offsetTop;
|
|
28309
|
+
rowHeightsArr[i] = row.offsetHeight;
|
|
28310
|
+
}
|
|
28311
|
+
const getRowHeight = (flatIndex) => {
|
|
28312
|
+
const local = flatIndex - skip;
|
|
28313
|
+
if (local >= 0 && local < rowCount) {
|
|
28314
|
+
return rowHeightsArr[local];
|
|
28315
|
+
}
|
|
28316
|
+
// Virtual mode fallback: use RowHeightService for off-screen rows
|
|
28317
|
+
if (rhs && flatIndex >= 0 && flatIndex < flatData.length) {
|
|
28318
|
+
return rhs.height(flatIndex);
|
|
28319
|
+
}
|
|
28320
|
+
return defaultRowHeight;
|
|
28321
|
+
};
|
|
28322
|
+
const getRowOffset = (flatIndex) => {
|
|
28323
|
+
const local = flatIndex - skip;
|
|
28324
|
+
if (local >= 0 && local < rowCount) {
|
|
28325
|
+
return rowTops[local];
|
|
28326
|
+
}
|
|
28327
|
+
// Virtual mode fallback: use RowHeightService for off-screen rows
|
|
28328
|
+
if (rhs && flatIndex >= 0 && flatIndex < flatData.length) {
|
|
28329
|
+
return rhs.offset(flatIndex);
|
|
28330
|
+
}
|
|
28331
|
+
return undefined;
|
|
28332
|
+
};
|
|
28333
|
+
// Binary search: first local index where rowTops[i] >= target
|
|
28334
|
+
const bsFirstGte = (target) => {
|
|
28335
|
+
let lo = 0, hi = rowCount;
|
|
28336
|
+
while (lo < hi) {
|
|
28337
|
+
const mid = (lo + hi) >> 1;
|
|
28338
|
+
if (rowTops[mid] < target) {
|
|
28339
|
+
lo = mid + 1;
|
|
28340
|
+
}
|
|
28341
|
+
else {
|
|
28342
|
+
hi = mid;
|
|
28343
|
+
}
|
|
28344
|
+
}
|
|
28345
|
+
return lo;
|
|
28346
|
+
};
|
|
28347
|
+
const findFirstVisible = (effectiveTop) => {
|
|
28348
|
+
const local = bsFirstGte(effectiveTop);
|
|
28349
|
+
return local < rowCount ? skip + local : skip;
|
|
28350
|
+
};
|
|
28351
|
+
const findLastVisible = (effectiveBottom) => {
|
|
28352
|
+
let lo = 0, hi = rowCount - 1;
|
|
28353
|
+
while (lo <= hi) {
|
|
28354
|
+
const mid = (lo + hi) >> 1;
|
|
28355
|
+
if (rowTops[mid] + rowHeightsArr[mid] <= effectiveBottom) {
|
|
28356
|
+
lo = mid + 1;
|
|
28357
|
+
}
|
|
28358
|
+
else {
|
|
28359
|
+
hi = mid - 1;
|
|
28360
|
+
}
|
|
28361
|
+
}
|
|
28362
|
+
// When all DOM rows fit inside the viewport, off-screen rows
|
|
28363
|
+
// beyond the rendered window may also be "visible". Use RHS
|
|
28364
|
+
// to compute the correct last visible index.
|
|
28365
|
+
if (lo === rowCount && rhs && rowCount > 0) {
|
|
28366
|
+
return Math.min(rhs.index(effectiveBottom), flatData.length - 1);
|
|
28367
|
+
}
|
|
28368
|
+
return hi >= 0 ? skip + hi : flatData.length - 1;
|
|
28369
|
+
};
|
|
28370
|
+
const rawFirstVisibleIndex = Math.min(findFirstVisible(scrollTop), flatData.length - 1);
|
|
28371
|
+
let firstVisibleFlatIndex = rawFirstVisibleIndex;
|
|
28372
|
+
// --- Sticky Headers ---
|
|
28373
|
+
if (enableHeaders && stickyHeaderEl) {
|
|
28374
|
+
let stickyHeaderHeight = 0;
|
|
28375
|
+
let headerPushOffsets = [];
|
|
28376
|
+
let stickyHeaders = [];
|
|
28377
|
+
// Convergence loop: recalculate until both set and height stabilise
|
|
28378
|
+
const seenFirstVisible = new Set();
|
|
28379
|
+
while (true) {
|
|
28380
|
+
firstVisibleFlatIndex = Math.min(findFirstVisible(scrollTop + Math.max(stickyHeaderHeight, 0)), flatData.length - 1);
|
|
28381
|
+
const isHeaderCycle = seenFirstVisible.has(firstVisibleFlatIndex);
|
|
28382
|
+
seenFirstVisible.add(firstVisibleFlatIndex);
|
|
28383
|
+
const lastVisibleFlatIndex = Math.min(findLastVisible(scrollTop + viewportHeight), flatData.length - 1);
|
|
28384
|
+
const result = computeStickyItems(flatData, groupRanges, firstVisibleFlatIndex, lastVisibleFlatIndex, rawFirstVisibleIndex);
|
|
28385
|
+
const headerPush = computeHeaderPush(result.map(s => s.flatIndex), getRowHeight, getRowOffset, scrollTop, groupRanges);
|
|
28386
|
+
const headerConverged = !hasStickyItemsChanged(result, stickyHeaders) &&
|
|
28387
|
+
Math.abs(headerPush.totalHeight - stickyHeaderHeight) < 1;
|
|
28388
|
+
stickyHeaders = result;
|
|
28389
|
+
stickyHeaderHeight = headerPush.totalHeight;
|
|
28390
|
+
headerPushOffsets = headerPush.offsets;
|
|
28391
|
+
if (headerConverged || isHeaderCycle) {
|
|
28392
|
+
break;
|
|
28393
|
+
}
|
|
28394
|
+
}
|
|
28395
|
+
const shouldShow = stickyHeaders.length > 0;
|
|
28396
|
+
const hasChanged = hasStickyItemsChanged(stickyHeaders, this.stickyHeaderItems);
|
|
28397
|
+
if (!shouldShow) {
|
|
28398
|
+
stickyHeaderEl.style.display = 'none';
|
|
28399
|
+
resetRowTransforms(stickyHeaderEl);
|
|
28400
|
+
}
|
|
28401
|
+
else if (!hasChanged) {
|
|
28402
|
+
stickyHeaderEl.style.display = '';
|
|
28403
|
+
if (this.headerPushOffsets.length > 0) {
|
|
28404
|
+
// A re-render is pending — update stored offsets so
|
|
28405
|
+
// ngAfterViewChecked applies fresh values to the new DOM
|
|
28406
|
+
// instead of stale ones from the previous hasChanged call.
|
|
28407
|
+
this.headerPushOffsets = headerPushOffsets;
|
|
28408
|
+
}
|
|
28409
|
+
else {
|
|
28410
|
+
applyHeaderPushTransforms(stickyHeaderEl, headerPushOffsets);
|
|
28411
|
+
}
|
|
28412
|
+
}
|
|
28413
|
+
else {
|
|
28414
|
+
resetRowTransforms(stickyHeaderEl);
|
|
28415
|
+
this.headerPushOffsets = headerPushOffsets;
|
|
28416
|
+
}
|
|
28417
|
+
if (hasChanged) {
|
|
28418
|
+
this.stickyHeaderItems = stickyHeaders;
|
|
28419
|
+
// Emit inside zone so Angular re-renders the overlay
|
|
28420
|
+
this.ngZone.run(() => this.headerItems$.next(stickyHeaders));
|
|
28421
|
+
}
|
|
28422
|
+
}
|
|
28423
|
+
// --- Sticky Footers ---
|
|
28424
|
+
if (enableFooters && stickyFooterEl) {
|
|
28425
|
+
let stickyFooterHeight = 0;
|
|
28426
|
+
let footerPushOffsets = [];
|
|
28427
|
+
let stickyFooters = [];
|
|
28428
|
+
const seenLastVisible = new Set();
|
|
28429
|
+
while (true) {
|
|
28430
|
+
const effectiveLastVisible = Math.min(findLastVisible(scrollTop + viewportHeight - stickyFooterHeight), flatData.length - 1);
|
|
28431
|
+
const isFooterCycle = seenLastVisible.has(effectiveLastVisible);
|
|
28432
|
+
seenLastVisible.add(effectiveLastVisible);
|
|
28433
|
+
const footerResult = computeStickyFooterItems(flatData, groupRanges, firstVisibleFlatIndex, effectiveLastVisible);
|
|
28434
|
+
const footerPush = computeFooterPush(footerResult.map(s => s.flatIndex), getRowHeight, getRowOffset, scrollTop, viewportHeight, footerRanges);
|
|
28435
|
+
const footerConverged = !hasStickyItemsChanged(footerResult, stickyFooters) &&
|
|
28436
|
+
Math.abs(footerPush.totalHeight - stickyFooterHeight) < 1;
|
|
28437
|
+
stickyFooters = footerResult;
|
|
28438
|
+
stickyFooterHeight = footerPush.totalHeight;
|
|
28439
|
+
footerPushOffsets = footerPush.offsets;
|
|
28440
|
+
if (footerConverged || isFooterCycle) {
|
|
28441
|
+
break;
|
|
28442
|
+
}
|
|
28443
|
+
}
|
|
28444
|
+
const shouldShow = stickyFooters.length > 0;
|
|
28445
|
+
const hasChanged = hasStickyItemsChanged(stickyFooters, this.stickyFooterItems);
|
|
28446
|
+
if (!shouldShow) {
|
|
28447
|
+
stickyFooterEl.style.display = 'none';
|
|
28448
|
+
stickyFooterEl.style.marginBlockEnd = '';
|
|
28449
|
+
resetRowTransforms(stickyFooterEl);
|
|
28450
|
+
}
|
|
28451
|
+
else if (!hasChanged) {
|
|
28452
|
+
stickyFooterEl.style.display = '';
|
|
28453
|
+
if (this.footerPushOffsets.length > 0) {
|
|
28454
|
+
// A re-render is pending — update stored offsets so
|
|
28455
|
+
// ngAfterViewChecked applies fresh values to the new DOM.
|
|
28456
|
+
this.footerPushOffsets = footerPushOffsets;
|
|
28457
|
+
}
|
|
28458
|
+
else {
|
|
28459
|
+
applyFooterPushTransforms(stickyFooterEl, footerPushOffsets);
|
|
28460
|
+
}
|
|
28461
|
+
}
|
|
28462
|
+
else {
|
|
28463
|
+
resetRowTransforms(stickyFooterEl);
|
|
28464
|
+
this.footerPushOffsets = footerPushOffsets;
|
|
28465
|
+
}
|
|
28466
|
+
if (hasChanged) {
|
|
28467
|
+
this.stickyFooterItems = stickyFooters;
|
|
28468
|
+
this.ngZone.run(() => this.footerItems$.next(stickyFooters));
|
|
28469
|
+
}
|
|
28470
|
+
// Push footer above horizontal scrollbar when present
|
|
28471
|
+
this.adjustStickyFooterForScrollbar(container, stickyFooterEl);
|
|
28472
|
+
}
|
|
28473
|
+
// Update scroll-padding on the container so scrollIntoView accounts for overlays
|
|
28474
|
+
const headerH = stickyHeaderEl?.offsetHeight || 0;
|
|
28475
|
+
const footerH = stickyFooterEl?.offsetHeight || 0;
|
|
28476
|
+
container.style.scrollPaddingTop = headerH > 0 ? headerH + 'px' : '';
|
|
28477
|
+
container.style.scrollPaddingBottom = footerH > 0 ? footerH + 'px' : '';
|
|
28478
|
+
}
|
|
28479
|
+
/**
|
|
28480
|
+
* Applies pending push transforms after Angular re-renders overlay content.
|
|
28481
|
+
* Called from the overlay component's AfterViewChecked hook.
|
|
28482
|
+
*/
|
|
28483
|
+
applyPendingHeaderTransforms(containerEl) {
|
|
28484
|
+
if (this.headerPushOffsets.length > 0) {
|
|
28485
|
+
applyHeaderPushTransforms(containerEl, this.headerPushOffsets);
|
|
28486
|
+
this.headerPushOffsets = [];
|
|
28487
|
+
}
|
|
28488
|
+
}
|
|
28489
|
+
applyPendingFooterTransforms(containerEl) {
|
|
28490
|
+
if (this.footerPushOffsets.length > 0) {
|
|
28491
|
+
applyFooterPushTransforms(containerEl, this.footerPushOffsets);
|
|
28492
|
+
this.footerPushOffsets = [];
|
|
28493
|
+
}
|
|
28494
|
+
}
|
|
28495
|
+
/**
|
|
28496
|
+
* Clears all sticky state and resets overlays.
|
|
28497
|
+
*/
|
|
28498
|
+
clear() {
|
|
28499
|
+
if (this.stickyHeaderItems.length > 0) {
|
|
28500
|
+
this.stickyHeaderItems = [];
|
|
28501
|
+
this.ngZone.run(() => this.headerItems$.next([]));
|
|
28502
|
+
}
|
|
28503
|
+
if (this.stickyFooterItems.length > 0) {
|
|
28504
|
+
this.stickyFooterItems = [];
|
|
28505
|
+
this.ngZone.run(() => this.footerItems$.next([]));
|
|
28506
|
+
}
|
|
28507
|
+
this.invalidateRangeMap();
|
|
28508
|
+
}
|
|
28509
|
+
/**
|
|
28510
|
+
* Adjusts the container scrollTop so the focused row is not hidden
|
|
28511
|
+
* behind the sticky header or footer overlays.
|
|
28512
|
+
* Intended to be called only from the keyboard navigation path,
|
|
28513
|
+
* outside Angular zone.
|
|
28514
|
+
*/
|
|
28515
|
+
adjustScrollForFocusedCell(containerEl, stickyHeaderEl, stickyFooterEl) {
|
|
28516
|
+
if (!containerEl) {
|
|
28517
|
+
return;
|
|
28518
|
+
}
|
|
28519
|
+
// Use document.activeElement so focus in the locked container is also found
|
|
28520
|
+
const focused = (typeof document !== 'undefined' ? document.activeElement : null);
|
|
28521
|
+
if (!focused) {
|
|
28522
|
+
return;
|
|
28523
|
+
}
|
|
28524
|
+
const focusedRow = focused.closest('tr');
|
|
28525
|
+
if (!focusedRow) {
|
|
28526
|
+
return;
|
|
28527
|
+
}
|
|
28528
|
+
const containerRect = containerEl.getBoundingClientRect();
|
|
28529
|
+
const rowRect = focusedRow.getBoundingClientRect();
|
|
28530
|
+
if (stickyHeaderEl && stickyHeaderEl.offsetHeight > 0 && stickyHeaderEl.style.display !== 'none') {
|
|
28531
|
+
const headerBottom = containerRect.top + stickyHeaderEl.offsetHeight;
|
|
28532
|
+
if (rowRect.top < headerBottom) {
|
|
28533
|
+
containerEl.scrollTop -= (headerBottom - rowRect.top);
|
|
28534
|
+
return;
|
|
28535
|
+
}
|
|
28536
|
+
}
|
|
28537
|
+
if (stickyFooterEl && stickyFooterEl.offsetHeight > 0 && stickyFooterEl.style.display !== 'none') {
|
|
28538
|
+
const footerTop = containerRect.bottom - stickyFooterEl.offsetHeight;
|
|
28539
|
+
if (rowRect.bottom > footerTop) {
|
|
28540
|
+
containerEl.scrollTop += (rowRect.bottom - footerTop);
|
|
28541
|
+
}
|
|
28542
|
+
}
|
|
28543
|
+
}
|
|
28544
|
+
/**
|
|
28545
|
+
* Sets marginBlockEnd on the sticky footer overlay when the container
|
|
28546
|
+
* has a horizontal scrollbar, so the footer does not overlap the scrollbar.
|
|
28547
|
+
*/
|
|
28548
|
+
adjustStickyFooterForScrollbar(container, stickyFooterEl) {
|
|
28549
|
+
if (!stickyFooterEl) {
|
|
28550
|
+
return;
|
|
28551
|
+
}
|
|
28552
|
+
const hasHorizontalScrollbar = container.scrollWidth > container.clientWidth;
|
|
28553
|
+
stickyFooterEl.style.marginBlockEnd = hasHorizontalScrollbar
|
|
28554
|
+
? 'var(--kendo-scrollbar-width, 0px)'
|
|
28555
|
+
: '';
|
|
28556
|
+
}
|
|
28557
|
+
clearAll(headerEl, footerEl, container) {
|
|
28558
|
+
if (headerEl) {
|
|
28559
|
+
headerEl.style.display = 'none';
|
|
28560
|
+
resetRowTransforms(headerEl);
|
|
28561
|
+
}
|
|
28562
|
+
if (footerEl) {
|
|
28563
|
+
footerEl.style.display = 'none';
|
|
28564
|
+
footerEl.style.marginBlockEnd = '';
|
|
28565
|
+
resetRowTransforms(footerEl);
|
|
28566
|
+
}
|
|
28567
|
+
container.style.scrollPaddingTop = '';
|
|
28568
|
+
container.style.scrollPaddingBottom = '';
|
|
28569
|
+
if (this.stickyHeaderItems.length > 0) {
|
|
28570
|
+
this.stickyHeaderItems = [];
|
|
28571
|
+
this.ngZone.run(() => this.headerItems$.next([]));
|
|
28572
|
+
}
|
|
28573
|
+
if (this.stickyFooterItems.length > 0) {
|
|
28574
|
+
this.stickyFooterItems = [];
|
|
28575
|
+
this.ngZone.run(() => this.footerItems$.next([]));
|
|
28576
|
+
}
|
|
28577
|
+
}
|
|
28578
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: StickyGroupsService, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
28579
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: StickyGroupsService });
|
|
28580
|
+
}
|
|
28581
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: StickyGroupsService, decorators: [{
|
|
28582
|
+
type: Injectable
|
|
28583
|
+
}], ctorParameters: () => [{ type: i0.NgZone }] });
|
|
28584
|
+
|
|
28585
|
+
/**
|
|
28586
|
+
* @hidden
|
|
28587
|
+
* Renders the sticky group header or footer overlay container.
|
|
28588
|
+
* When locked columns are present, renders two side-by-side tables
|
|
28589
|
+
* mirroring the grid's locked / non-locked split.
|
|
28590
|
+
*/
|
|
28591
|
+
class StickyGroupContainerComponent {
|
|
28592
|
+
stickyGroupsService;
|
|
28593
|
+
cdr;
|
|
28594
|
+
ctx;
|
|
28595
|
+
el;
|
|
28596
|
+
navigationService;
|
|
28597
|
+
groupsService;
|
|
28598
|
+
zone;
|
|
28599
|
+
position = 'top';
|
|
28600
|
+
set columns(value) {
|
|
28601
|
+
this._columns = value;
|
|
28602
|
+
this.footerColumns = this.expandSpanColumns(value);
|
|
28603
|
+
}
|
|
28604
|
+
get columns() { return this._columns; }
|
|
28605
|
+
set lockedColumns(value) {
|
|
28606
|
+
this._lockedColumns = value;
|
|
28607
|
+
this.lockedFooterColumns = this.expandSpanColumns(value);
|
|
28608
|
+
}
|
|
28609
|
+
get lockedColumns() { return this._lockedColumns; }
|
|
28610
|
+
groups = [];
|
|
28611
|
+
detailTemplate;
|
|
28612
|
+
totalColumnsCount = 0;
|
|
28613
|
+
hasGroupHeaderColumn = false;
|
|
28614
|
+
groupHeaderColumns = [];
|
|
28615
|
+
tableWidth;
|
|
28616
|
+
lockedWidth;
|
|
28617
|
+
isLocked = false;
|
|
28618
|
+
hostClass = true;
|
|
28619
|
+
get isBottom() {
|
|
28620
|
+
return this.position === 'bottom';
|
|
28621
|
+
}
|
|
28622
|
+
hostRole = 'none';
|
|
28623
|
+
items = [];
|
|
28624
|
+
footerColumns = [];
|
|
28625
|
+
lockedFooterColumns = [];
|
|
28626
|
+
wrapWidth;
|
|
28627
|
+
_columns = [];
|
|
28628
|
+
_lockedColumns = [];
|
|
28629
|
+
subscription;
|
|
28630
|
+
constructor(stickyGroupsService, cdr, ctx, el, navigationService, groupsService, zone) {
|
|
28631
|
+
this.stickyGroupsService = stickyGroupsService;
|
|
28632
|
+
this.cdr = cdr;
|
|
28633
|
+
this.ctx = ctx;
|
|
28634
|
+
this.el = el;
|
|
28635
|
+
this.navigationService = navigationService;
|
|
28636
|
+
this.groupsService = groupsService;
|
|
28637
|
+
this.zone = zone;
|
|
28638
|
+
}
|
|
28639
|
+
captureClickHandler = null;
|
|
28640
|
+
ngOnInit() {
|
|
28641
|
+
const source$ = this.position === 'top'
|
|
28642
|
+
? this.stickyGroupsService.headerItems$
|
|
28643
|
+
: this.stickyGroupsService.footerItems$;
|
|
28644
|
+
this.subscription = source$.subscribe(items => {
|
|
28645
|
+
this.items = items;
|
|
28646
|
+
this.el.nativeElement.style.display = items.length === 0 ? 'none' : '';
|
|
28647
|
+
this.cdr.markForCheck();
|
|
28648
|
+
});
|
|
28649
|
+
// Capture-phase listener intercepts <a> clicks before GroupHeaderComponent's
|
|
28650
|
+
// toggleGroup handler fires, so we control the scroll-then-toggle sequence.
|
|
28651
|
+
if (this.position === 'top') {
|
|
28652
|
+
this.captureClickHandler = (e) => this.onCapturedClick(e);
|
|
28653
|
+
this.el.nativeElement.addEventListener('click', this.captureClickHandler, true);
|
|
28654
|
+
}
|
|
28655
|
+
// Subscribe to deferred focus events (used after scroll-to-group in virtual mode)
|
|
28656
|
+
if (this.position === 'top') {
|
|
28657
|
+
this.subscription.add(this.stickyGroupsService.focusReady$.subscribe(({ flatIndex }) => {
|
|
28658
|
+
this.clearStickyFocus();
|
|
28659
|
+
this.focusRealGridRow(flatIndex);
|
|
28660
|
+
}));
|
|
28661
|
+
}
|
|
28662
|
+
}
|
|
28663
|
+
ngAfterViewChecked() {
|
|
28664
|
+
const hostEl = this.el?.nativeElement;
|
|
28665
|
+
if (!hostEl) {
|
|
28666
|
+
return;
|
|
28667
|
+
}
|
|
28668
|
+
// Sync locked/non-locked row heights BEFORE applying transforms,
|
|
28669
|
+
// so transform calculations use consistent row measurements.
|
|
28670
|
+
if (this.isLocked && this.items.length > 0) {
|
|
28671
|
+
this.wrapWidth = Math.max(hostEl.clientWidth - this.lockedWidth, 0);
|
|
28672
|
+
this.syncLockedRowHeights();
|
|
28673
|
+
}
|
|
28674
|
+
if (this.position === 'top') {
|
|
28675
|
+
this.stickyGroupsService.applyPendingHeaderTransforms(hostEl);
|
|
28676
|
+
}
|
|
28677
|
+
else {
|
|
28678
|
+
this.stickyGroupsService.applyPendingFooterTransforms(hostEl);
|
|
28679
|
+
}
|
|
28680
|
+
}
|
|
28681
|
+
ngOnDestroy() {
|
|
28682
|
+
this.subscription?.unsubscribe();
|
|
28683
|
+
if (this.captureClickHandler) {
|
|
28684
|
+
this.el.nativeElement.removeEventListener('click', this.captureClickHandler, true);
|
|
28685
|
+
this.captureClickHandler = null;
|
|
28686
|
+
}
|
|
28687
|
+
}
|
|
28688
|
+
get isStacked() {
|
|
28689
|
+
return this.ctx.grid?.isStacked;
|
|
28690
|
+
}
|
|
28691
|
+
get gridSize() {
|
|
28692
|
+
return this.ctx.grid?.size;
|
|
28693
|
+
}
|
|
28694
|
+
get nativeElement() {
|
|
28695
|
+
return this.el?.nativeElement;
|
|
28696
|
+
}
|
|
28697
|
+
/**
|
|
28698
|
+
* Handles clicks on the sticky container.
|
|
28699
|
+
* For headers: toggle (anchor) clicks scroll grid to real header position;
|
|
28700
|
+
* non-toggle clicks focus the clicked row.
|
|
28701
|
+
* For footers: focus the clicked cell.
|
|
28702
|
+
*/
|
|
28703
|
+
onContainerClick(event) {
|
|
28704
|
+
const target = event.target;
|
|
28705
|
+
const row = target.closest('tr');
|
|
28706
|
+
if (!row) {
|
|
28707
|
+
return;
|
|
28708
|
+
}
|
|
28709
|
+
if (this.position === 'bottom') {
|
|
28710
|
+
const td = target.closest('td[data-col-index]');
|
|
28711
|
+
if (td) {
|
|
28712
|
+
this.focusFooterCell(td);
|
|
28713
|
+
}
|
|
28714
|
+
return;
|
|
28715
|
+
}
|
|
28716
|
+
// Anchor clicks are handled by onStickyHeaderRowClick (template handler)
|
|
28717
|
+
// which stops propagation. If we still get here, just focus the row.
|
|
28718
|
+
if (row) {
|
|
28719
|
+
this.focusStickyCell(row);
|
|
28720
|
+
}
|
|
28721
|
+
}
|
|
28722
|
+
// Prevent focusin from bubbling to the grid wrapper where NavigationService
|
|
28723
|
+
// would misinterpret the sticky row's aria-rowindex as a real grid row.
|
|
28724
|
+
onContainerFocusIn(event) {
|
|
28725
|
+
event.stopPropagation();
|
|
28726
|
+
}
|
|
28727
|
+
onContainerFocusOut(event) {
|
|
28728
|
+
const related = event.relatedTarget;
|
|
28729
|
+
if (!related || !this.el.nativeElement.contains(related)) {
|
|
28730
|
+
this.clearStickyFocus();
|
|
28731
|
+
}
|
|
28732
|
+
}
|
|
28733
|
+
onContainerKeydown(event) {
|
|
28734
|
+
const code = normalizeKeys(event);
|
|
28735
|
+
if (this.position === 'bottom') {
|
|
28736
|
+
this.handleFooterKeydown(event, code);
|
|
28737
|
+
return;
|
|
28738
|
+
}
|
|
28739
|
+
if (code !== Keys.ArrowUp && code !== Keys.ArrowDown && code !== Keys.Enter) {
|
|
28740
|
+
return;
|
|
28741
|
+
}
|
|
28742
|
+
const focusedIndex = this.getFocusedItemIndex();
|
|
28743
|
+
if (focusedIndex < 0) {
|
|
28744
|
+
return;
|
|
28745
|
+
}
|
|
28746
|
+
event.preventDefault();
|
|
28747
|
+
event.stopPropagation();
|
|
28748
|
+
if (code === Keys.Enter) {
|
|
28749
|
+
this.handleEnterKey(focusedIndex);
|
|
28750
|
+
}
|
|
28751
|
+
else if (code === Keys.ArrowUp) {
|
|
28752
|
+
this.handleArrowUp(focusedIndex);
|
|
28753
|
+
}
|
|
28754
|
+
else if (code === Keys.ArrowDown) {
|
|
28755
|
+
this.handleArrowDown(focusedIndex);
|
|
28756
|
+
}
|
|
28757
|
+
}
|
|
28758
|
+
expandSpanColumns(cols) {
|
|
28759
|
+
return Array.from(cols).reduce((result, col) => {
|
|
28760
|
+
const newCols = (col instanceof SpanColumnComponent) ? Array.from(col.children) : [col];
|
|
28761
|
+
return [...result, ...newCols];
|
|
28762
|
+
}, []);
|
|
28763
|
+
}
|
|
28764
|
+
getFocusedItemIndex() {
|
|
28765
|
+
if (!isDocumentAvailable()) {
|
|
28766
|
+
return -1;
|
|
28767
|
+
}
|
|
28768
|
+
const active = document.activeElement;
|
|
28769
|
+
if (!active || !this.el.nativeElement.contains(active)) {
|
|
28770
|
+
return -1;
|
|
28771
|
+
}
|
|
28772
|
+
const row = active.tagName === 'TR' ? active : active.closest('tr');
|
|
28773
|
+
if (!row) {
|
|
28774
|
+
return -1;
|
|
28775
|
+
}
|
|
28776
|
+
const groupIndex = row.getAttribute('data-group-index');
|
|
28777
|
+
return this.items.findIndex(item => item.item.index === groupIndex);
|
|
28778
|
+
}
|
|
28779
|
+
handleArrowUp(currentIndex) {
|
|
28780
|
+
if (currentIndex > 0) {
|
|
28781
|
+
this.focusStickyRowByIndex(currentIndex - 1);
|
|
28782
|
+
}
|
|
28783
|
+
else {
|
|
28784
|
+
// Exit the sticky overlay upward.
|
|
28785
|
+
// The overlay is visible because the real group header scrolled out of view,
|
|
28786
|
+
// so focusing the row above it (flatIndex - 1) would land on a non-visible row.
|
|
28787
|
+
// Navigate to pinned-top rows or the grid header instead.
|
|
28788
|
+
const meta = this.navigationService.metadata;
|
|
28789
|
+
if (meta && meta.pinnedTopRowsCount > 0) {
|
|
28790
|
+
this.clearStickyFocus();
|
|
28791
|
+
// meta.headerRows includes the +1 offset already accounted for in
|
|
28792
|
+
// logicalRowIndex, so the last pinned-top row is at:
|
|
28793
|
+
// (meta.headerRows - 1) + pinnedTopRowsCount
|
|
28794
|
+
const lastPinnedTopRow = meta.headerRows - 1 + meta.pinnedTopRowsCount;
|
|
28795
|
+
const firstCol = meta.hasDetailTemplate && !meta.isStacked ? 1 : 0;
|
|
28796
|
+
this.navigationService.focusCell(lastPinnedTopRow, firstCol);
|
|
28797
|
+
}
|
|
28798
|
+
else {
|
|
28799
|
+
// No pinned-top rows — go to grid header.
|
|
28800
|
+
// Explicitly hide the sticky container and scroll to top before focusing,
|
|
28801
|
+
// so the header area is fully visible.
|
|
28802
|
+
this.clearStickyFocus();
|
|
28803
|
+
this.items = [];
|
|
28804
|
+
this.el.nativeElement.style.display = 'none';
|
|
28805
|
+
this.cdr.markForCheck();
|
|
28806
|
+
if (meta) {
|
|
28807
|
+
const gridContainer = this.el.nativeElement.closest('.k-grid-container');
|
|
28808
|
+
const scrollContainer = gridContainer
|
|
28809
|
+
?.querySelector('.k-grid-content.k-virtual-content');
|
|
28810
|
+
if (scrollContainer) {
|
|
28811
|
+
this.stickyGroupsService.suppressNextUpdate = true;
|
|
28812
|
+
scrollContainer.scrollTop = 0;
|
|
28813
|
+
}
|
|
28814
|
+
this.zone.runOutsideAngular(() => {
|
|
28815
|
+
setTimeout(() => {
|
|
28816
|
+
this.navigationService.focusCell(meta.headerRows - 1, 0);
|
|
28817
|
+
});
|
|
28818
|
+
});
|
|
28819
|
+
}
|
|
28820
|
+
}
|
|
28821
|
+
}
|
|
28822
|
+
}
|
|
28823
|
+
handleArrowDown(currentIndex) {
|
|
28824
|
+
if (currentIndex < this.items.length - 1) {
|
|
28825
|
+
this.focusStickyRowByIndex(currentIndex + 1);
|
|
28826
|
+
}
|
|
28827
|
+
else {
|
|
28828
|
+
// Exit container downward: focus first child of the group
|
|
28829
|
+
const flatIndex = this.items[currentIndex].flatIndex;
|
|
28830
|
+
this.focusRealGridRow(flatIndex + 1);
|
|
28831
|
+
}
|
|
28832
|
+
}
|
|
28833
|
+
handleEnterKey(currentIndex) {
|
|
28834
|
+
const stickyItem = this.items[currentIndex];
|
|
28835
|
+
const groupLevel = stickyItem.item.level;
|
|
28836
|
+
this.scrollToGroupAndToggle(stickyItem, groupLevel);
|
|
28837
|
+
}
|
|
28838
|
+
/**
|
|
28839
|
+
* Capture-phase click handler registered on the host element.
|
|
28840
|
+
* Intercepts <a> clicks inside sticky header rows before
|
|
28841
|
+
* GroupHeaderComponent's toggleGroup fires.
|
|
28842
|
+
*/
|
|
28843
|
+
onCapturedClick(event) {
|
|
28844
|
+
const target = event.target;
|
|
28845
|
+
const anchor = target.closest('a');
|
|
28846
|
+
if (!anchor) {
|
|
28847
|
+
return;
|
|
28848
|
+
}
|
|
28849
|
+
const row = anchor.closest('tr.k-grouping-row');
|
|
28850
|
+
if (!row) {
|
|
28851
|
+
return;
|
|
28852
|
+
}
|
|
28853
|
+
const groupIndex = row.getAttribute('data-group-index');
|
|
28854
|
+
if (!groupIndex) {
|
|
28855
|
+
return;
|
|
28856
|
+
}
|
|
28857
|
+
// Stop the event so GroupHeaderComponent.toggleGroup never fires
|
|
28858
|
+
event.stopPropagation();
|
|
28859
|
+
event.preventDefault();
|
|
28860
|
+
const stickyItem = this.items.find(item => item.item.index === groupIndex);
|
|
28861
|
+
if (stickyItem) {
|
|
28862
|
+
const groupLevel = stickyItem.item.level;
|
|
28863
|
+
this.scrollToGroupAndToggle(stickyItem, groupLevel);
|
|
28864
|
+
}
|
|
28865
|
+
}
|
|
28866
|
+
/**
|
|
28867
|
+
* Triggers the scroll-to-root-and-toggle flow via the service.
|
|
28868
|
+
* The list component handles actual scrolling, toggling, and focus.
|
|
28869
|
+
*/
|
|
28870
|
+
scrollToGroupAndToggle(stickyItem, groupLevel) {
|
|
28871
|
+
const groupItem = stickyItem.item;
|
|
28872
|
+
const groupIndex = groupItem.index;
|
|
28873
|
+
this.stickyGroupsService.pendingFocusGroupIndex = groupIndex;
|
|
28874
|
+
this.stickyGroupsService.scrollAndToggle(groupIndex);
|
|
28875
|
+
}
|
|
28876
|
+
focusStickyRowByIndex(itemIndex) {
|
|
28877
|
+
const hostEl = this.el.nativeElement;
|
|
28878
|
+
if (!hostEl) {
|
|
28879
|
+
return;
|
|
28880
|
+
}
|
|
28881
|
+
const groupIndex = this.items[itemIndex].item.index;
|
|
28882
|
+
const targetRow = hostEl.querySelector(`tr[data-group-index="${groupIndex}"]`);
|
|
28883
|
+
if (targetRow) {
|
|
28884
|
+
this.focusStickyCell(targetRow);
|
|
28885
|
+
}
|
|
28886
|
+
}
|
|
28887
|
+
focusStickyCell(row) {
|
|
28888
|
+
const hostEl = this.el.nativeElement;
|
|
28889
|
+
const groupIndex = row.getAttribute('data-group-index');
|
|
28890
|
+
// Clear grid-level focus so there's no double highlight
|
|
28891
|
+
this.clearGridFocus();
|
|
28892
|
+
this.clearStickyFocus();
|
|
28893
|
+
// In locked mode, always focus the TD in the locked table (contains the toggle)
|
|
28894
|
+
// and visually highlight both locked and non-locked TDs.
|
|
28895
|
+
if (this.isLocked && groupIndex) {
|
|
28896
|
+
const lockedRow = hostEl.querySelector(`.k-grid-content-locked tr[data-group-index="${groupIndex}"]`);
|
|
28897
|
+
const nonLockedRow = hostEl.querySelector(`:scope > .k-grid-header-wrap tr[data-group-index="${groupIndex}"], :scope > .k-grid-footer-wrap tr[data-group-index="${groupIndex}"]`);
|
|
28898
|
+
const lockedTd = lockedRow?.querySelector('td[kendogridlogicalcell]');
|
|
28899
|
+
const nonLockedTd = nonLockedRow?.querySelector('td');
|
|
28900
|
+
if (lockedTd) {
|
|
28901
|
+
if (!lockedTd.hasAttribute('tabindex')) {
|
|
28902
|
+
lockedTd.setAttribute('tabindex', '-1');
|
|
28903
|
+
}
|
|
28904
|
+
lockedTd.classList.add('k-focus');
|
|
28905
|
+
lockedTd.focus();
|
|
28906
|
+
}
|
|
28907
|
+
if (nonLockedTd) {
|
|
28908
|
+
nonLockedTd.classList.add('k-focus');
|
|
28909
|
+
}
|
|
28910
|
+
}
|
|
28911
|
+
else {
|
|
28912
|
+
const td = row.querySelector('td[kendogridlogicalcell]');
|
|
28913
|
+
if (td) {
|
|
28914
|
+
if (!td.hasAttribute('tabindex')) {
|
|
28915
|
+
td.setAttribute('tabindex', '-1');
|
|
28916
|
+
}
|
|
28917
|
+
td.classList.add('k-focus');
|
|
28918
|
+
td.focus();
|
|
28919
|
+
}
|
|
28920
|
+
}
|
|
28921
|
+
}
|
|
28922
|
+
clearStickyFocus() {
|
|
28923
|
+
const hostEl = this.el.nativeElement;
|
|
28924
|
+
hostEl.querySelectorAll('.k-focus').forEach((el) => el.classList.remove('k-focus'));
|
|
28925
|
+
}
|
|
28926
|
+
/**
|
|
28927
|
+
* Clears k-focus from all grid content cells (outside any sticky container)
|
|
28928
|
+
* so that the regular grid and the sticky overlay don't show focus simultaneously.
|
|
28929
|
+
*/
|
|
28930
|
+
clearGridFocus() {
|
|
28931
|
+
const ariaRoot = this.el.nativeElement.closest('.k-grid-aria-root');
|
|
28932
|
+
if (!ariaRoot) {
|
|
28933
|
+
return;
|
|
28934
|
+
}
|
|
28935
|
+
ariaRoot.querySelectorAll('.k-focus').forEach((el) => {
|
|
28936
|
+
if (!el.closest('.k-grid-sticky-container')) {
|
|
28937
|
+
el.classList.remove('k-focus');
|
|
28938
|
+
}
|
|
28939
|
+
});
|
|
28940
|
+
}
|
|
28941
|
+
focusRealGridRow(flatIndex, colIndex = 0) {
|
|
28942
|
+
this.stickyGroupsService.requestScrollToRow(flatIndex, colIndex);
|
|
28943
|
+
}
|
|
28944
|
+
handleFooterKeydown(event, code) {
|
|
28945
|
+
if (code !== Keys.ArrowUp && code !== Keys.ArrowDown &&
|
|
28946
|
+
code !== Keys.ArrowLeft && code !== Keys.ArrowRight) {
|
|
28947
|
+
return;
|
|
28948
|
+
}
|
|
28949
|
+
if (!isDocumentAvailable()) {
|
|
28950
|
+
return;
|
|
28951
|
+
}
|
|
28952
|
+
const active = document.activeElement;
|
|
28953
|
+
if (!active || !this.el.nativeElement.contains(active)) {
|
|
28954
|
+
return;
|
|
28955
|
+
}
|
|
28956
|
+
const td = active.closest('td[data-col-index]');
|
|
28957
|
+
if (!td) {
|
|
28958
|
+
return;
|
|
28959
|
+
}
|
|
28960
|
+
const row = td.closest('tr[data-sticky-row]');
|
|
28961
|
+
if (!row) {
|
|
28962
|
+
return;
|
|
28963
|
+
}
|
|
28964
|
+
const rowIdx = parseInt(row.getAttribute('data-sticky-row'), 10);
|
|
28965
|
+
const colIdx = parseInt(td.getAttribute('data-col-index'), 10);
|
|
28966
|
+
event.preventDefault();
|
|
28967
|
+
event.stopPropagation();
|
|
28968
|
+
if (code === Keys.ArrowLeft) {
|
|
28969
|
+
this.focusFooterCellAt(rowIdx, colIdx, -1);
|
|
28970
|
+
}
|
|
28971
|
+
else if (code === Keys.ArrowRight) {
|
|
28972
|
+
this.focusFooterCellAt(rowIdx, colIdx, 1);
|
|
28973
|
+
}
|
|
28974
|
+
else if (code === Keys.ArrowUp) {
|
|
28975
|
+
if (rowIdx > 0) {
|
|
28976
|
+
this.focusFooterCellInRow(rowIdx - 1, colIdx);
|
|
28977
|
+
}
|
|
28978
|
+
else {
|
|
28979
|
+
// Exit upward: focus the last child row before the topmost footer
|
|
28980
|
+
const topFooter = this.items[0];
|
|
28981
|
+
const targetFlatIndex = topFooter.flatIndex - 1;
|
|
28982
|
+
if (targetFlatIndex >= 0) {
|
|
28983
|
+
this.clearStickyFocus();
|
|
28984
|
+
this.focusRealGridRow(targetFlatIndex, colIdx);
|
|
28985
|
+
}
|
|
28986
|
+
}
|
|
28987
|
+
}
|
|
28988
|
+
else if (code === Keys.ArrowDown) {
|
|
28989
|
+
if (rowIdx < this.items.length - 1) {
|
|
28990
|
+
this.focusFooterCellInRow(rowIdx + 1, colIdx);
|
|
28991
|
+
}
|
|
28992
|
+
else {
|
|
28993
|
+
// Exit downward from the last sticky footer row.
|
|
28994
|
+
// If pinned-bottom rows are present, navigate to the first pinned-bottom row.
|
|
28995
|
+
const meta = this.navigationService.metadata;
|
|
28996
|
+
if (meta && meta.pinnedBottomRowsCount > 0) {
|
|
28997
|
+
// logicalRowIndex for the first pinned-bottom row (rowIndex=0):
|
|
28998
|
+
// (meta.headerRows - 1) + pinnedTopCount + dataRows + 1
|
|
28999
|
+
// = meta.headerRows + pinnedTopCount + dataRows
|
|
29000
|
+
const firstPinnedBottomRow = meta.headerRows + meta.pinnedTopRowsCount + meta.dataRows;
|
|
29001
|
+
this.clearStickyFocus();
|
|
29002
|
+
this.navigationService.focusCell(firstPinnedBottomRow, colIdx);
|
|
29003
|
+
}
|
|
29004
|
+
else {
|
|
29005
|
+
// No pinned-bottom rows — go to next data row or grid footer
|
|
29006
|
+
const bottomFooter = this.items[this.items.length - 1];
|
|
29007
|
+
const targetFlatIndex = bottomFooter.flatIndex + 1;
|
|
29008
|
+
if (meta && targetFlatIndex < meta.dataRows) {
|
|
29009
|
+
this.clearStickyFocus();
|
|
29010
|
+
this.focusRealGridRow(targetFlatIndex, colIdx);
|
|
29011
|
+
}
|
|
29012
|
+
else if (meta && meta.footerRow > 0) {
|
|
29013
|
+
// Last footer in the data — go to grid footer if present
|
|
29014
|
+
this.clearStickyFocus();
|
|
29015
|
+
this.navigationService.focusCell(meta.maxLogicalRowIndex, colIdx);
|
|
29016
|
+
}
|
|
29017
|
+
}
|
|
29018
|
+
}
|
|
29019
|
+
}
|
|
29020
|
+
}
|
|
29021
|
+
focusFooterCell(td) {
|
|
29022
|
+
// Clear grid-level focus so there's no double highlight
|
|
29023
|
+
this.clearGridFocus();
|
|
29024
|
+
this.clearStickyFocus();
|
|
29025
|
+
if (!td.hasAttribute('tabindex')) {
|
|
29026
|
+
td.setAttribute('tabindex', '-1');
|
|
29027
|
+
}
|
|
29028
|
+
td.classList.add('k-focus');
|
|
29029
|
+
td.focus();
|
|
29030
|
+
}
|
|
29031
|
+
/**
|
|
29032
|
+
* Moves focus to the adjacent cell in the given direction (-1 = left, +1 = right).
|
|
29033
|
+
* Crosses the locked/non-locked boundary seamlessly.
|
|
29034
|
+
*/
|
|
29035
|
+
focusFooterCellAt(rowIdx, currentColIdx, direction) {
|
|
29036
|
+
const allCells = this.getFooterRowCells(rowIdx);
|
|
29037
|
+
const currentPos = allCells.findIndex(c => parseInt(c.getAttribute('data-col-index'), 10) === currentColIdx);
|
|
29038
|
+
const nextPos = currentPos + direction;
|
|
29039
|
+
if (nextPos >= 0 && nextPos < allCells.length) {
|
|
29040
|
+
this.focusFooterCell(allCells[nextPos]);
|
|
29041
|
+
}
|
|
29042
|
+
}
|
|
29043
|
+
/**
|
|
29044
|
+
* Focuses the cell with the given column index in a different row.
|
|
29045
|
+
*/
|
|
29046
|
+
focusFooterCellInRow(rowIdx, colIdx) {
|
|
29047
|
+
const allCells = this.getFooterRowCells(rowIdx);
|
|
29048
|
+
const target = allCells.find(c => parseInt(c.getAttribute('data-col-index'), 10) === colIdx)
|
|
29049
|
+
|| allCells[allCells.length - 1];
|
|
29050
|
+
if (target) {
|
|
29051
|
+
this.focusFooterCell(target);
|
|
29052
|
+
}
|
|
29053
|
+
}
|
|
29054
|
+
/**
|
|
29055
|
+
* Returns all data cells (with data-col-index) for a footer row,
|
|
29056
|
+
* combining locked and non-locked tables, sorted by column index.
|
|
29057
|
+
*/
|
|
29058
|
+
getFooterRowCells(rowIdx) {
|
|
29059
|
+
const hostEl = this.el.nativeElement;
|
|
29060
|
+
const cells = Array.from(hostEl.querySelectorAll(`tr[data-sticky-row="${rowIdx}"] td[data-col-index]`));
|
|
29061
|
+
cells.sort((a, b) => parseInt(a.getAttribute('data-col-index'), 10) -
|
|
29062
|
+
parseInt(b.getAttribute('data-col-index'), 10));
|
|
29063
|
+
return cells;
|
|
29064
|
+
}
|
|
29065
|
+
syncLockedRowHeights() {
|
|
29066
|
+
const hostEl = this.el?.nativeElement;
|
|
29067
|
+
if (!hostEl) {
|
|
29068
|
+
return;
|
|
29069
|
+
}
|
|
29070
|
+
const lockedTable = hostEl.querySelector('.k-grid-content-locked table');
|
|
29071
|
+
const wrapSelector = this.position === 'top' ? '.k-grid-header-wrap' : '.k-grid-footer-wrap';
|
|
29072
|
+
const scrollableTable = hostEl.querySelector(`${wrapSelector} table`);
|
|
29073
|
+
if (lockedTable && scrollableTable) {
|
|
29074
|
+
syncRowsHeight(lockedTable, scrollableTable);
|
|
29075
|
+
}
|
|
29076
|
+
}
|
|
29077
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: StickyGroupContainerComponent, deps: [{ token: StickyGroupsService }, { token: i0.ChangeDetectorRef }, { token: ContextService }, { token: i0.ElementRef }, { token: NavigationService }, { token: GroupsService }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
|
|
29078
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.20", type: StickyGroupContainerComponent, isStandalone: true, selector: "[kendoGridStickyGroupContainer]", inputs: { position: "position", columns: "columns", lockedColumns: "lockedColumns", groups: "groups", detailTemplate: "detailTemplate", totalColumnsCount: "totalColumnsCount", hasGroupHeaderColumn: "hasGroupHeaderColumn", groupHeaderColumns: "groupHeaderColumns", tableWidth: "tableWidth", lockedWidth: "lockedWidth", isLocked: "isLocked" }, host: { listeners: { "click": "onContainerClick($event)", "focusin": "onContainerFocusIn($event)", "focusout": "onContainerFocusOut($event)", "keydown": "onContainerKeydown($event)" }, properties: { "class.k-grid-sticky-container": "this.hostClass", "class.k-pos-bottom": "this.isBottom", "attr.role": "this.hostRole" } }, providers: [
|
|
29079
|
+
{ provide: SKIP_CELL_NAVIGATION, useValue: true }
|
|
29080
|
+
], ngImport: i0, template: `
|
|
29081
|
+
@if (isLocked) {
|
|
29082
|
+
<div class="k-grid-content-locked" role="presentation" [style.width.px]="lockedWidth">
|
|
29083
|
+
<table
|
|
29084
|
+
class="k-grid-table k-table"
|
|
29085
|
+
[class.k-grid-group-sticky-header-table]="position === 'top'"
|
|
29086
|
+
[class.k-grid-group-sticky-footer-table]="position === 'bottom'"
|
|
29087
|
+
[class.k-table-sm]="gridSize === 'small'"
|
|
29088
|
+
[class.k-table-md]="gridSize === 'medium'"
|
|
29089
|
+
role="none"
|
|
29090
|
+
[style.width.px]="lockedWidth">
|
|
29091
|
+
<colgroup kendoGridColGroup
|
|
29092
|
+
[groups]="groups"
|
|
29093
|
+
[columns]="$any(lockedColumns)"
|
|
29094
|
+
[detailTemplate]="detailTemplate">
|
|
29095
|
+
</colgroup>
|
|
29096
|
+
<tbody class="k-table-tbody" role="presentation">
|
|
29097
|
+
@if (position === 'top') {
|
|
29098
|
+
@for (stickyItem of items; track stickyItem.flatIndex) {
|
|
29099
|
+
<tr role="row"
|
|
29100
|
+
class="k-grouping-row k-table-group-row k-table-row"
|
|
29101
|
+
kendoGridGroupHeader
|
|
29102
|
+
[columns]="lockedColumns"
|
|
29103
|
+
[groups]="groups"
|
|
29104
|
+
[item]="$any(stickyItem.item)"
|
|
29105
|
+
[hasDetails]="!!detailTemplate?.templateRef"
|
|
29106
|
+
[skipGroupDecoration]="false"
|
|
29107
|
+
[hasGroupHeaderColumn]="false"
|
|
29108
|
+
[groupHeaderColumns]="[]"
|
|
29109
|
+
[rowIndex]="stickyItem.flatIndex + 1"
|
|
29110
|
+
[totalColumnsCount]="totalColumnsCount"
|
|
29111
|
+
[attr.aria-rowindex]="stickyItem.flatIndex + 1"
|
|
29112
|
+
[attr.data-group-index]="$any(stickyItem.item).index"
|
|
29113
|
+
[attr.data-group-level]="$any(stickyItem.item).level"
|
|
29114
|
+
tabindex="-1">
|
|
29115
|
+
</tr>
|
|
29116
|
+
}
|
|
29117
|
+
}
|
|
29118
|
+
@if (position === 'bottom') {
|
|
29119
|
+
@for (stickyItem of items; track stickyItem.flatIndex; let rowIdx = $index) {
|
|
29120
|
+
<tr role="row"
|
|
29121
|
+
class="k-group-footer"
|
|
29122
|
+
[attr.aria-rowindex]="stickyItem.flatIndex + 1"
|
|
29123
|
+
[attr.data-sticky-row]="rowIdx">
|
|
29124
|
+
@for (g of groups; track $index) {
|
|
29125
|
+
<td class="k-group-cell k-table-td k-table-group-td" role="presentation"></td>
|
|
29126
|
+
}
|
|
29127
|
+
@if (detailTemplate?.templateRef) {
|
|
29128
|
+
<td class="k-hierarchy-cell k-table-td" role="gridcell"
|
|
29129
|
+
aria-selected="false">
|
|
29130
|
+
</td>
|
|
29131
|
+
}
|
|
29132
|
+
@for (column of lockedFooterColumns; track $index; let columnIndex = $index) {
|
|
29133
|
+
<td role="gridcell"
|
|
29134
|
+
class="k-table-td"
|
|
29135
|
+
tabindex="-1"
|
|
29136
|
+
[attr.aria-colindex]="columnIndex + 1"
|
|
29137
|
+
[attr.data-col-index]="$any(column).leafIndex">
|
|
29138
|
+
<ng-template
|
|
29139
|
+
[templateContext]="{
|
|
29140
|
+
templateRef: $any(column).groupFooterTemplateRef,
|
|
29141
|
+
group: $any(stickyItem.item).data,
|
|
29142
|
+
field: $any(column).field,
|
|
29143
|
+
column: column,
|
|
29144
|
+
aggregates: $any(stickyItem.item).data?.aggregates,
|
|
29145
|
+
$implicit: $any(stickyItem.item).data?.aggregates
|
|
29146
|
+
}">
|
|
29147
|
+
</ng-template>
|
|
29148
|
+
</td>
|
|
29149
|
+
}
|
|
29150
|
+
</tr>
|
|
29151
|
+
}
|
|
29152
|
+
}
|
|
29153
|
+
</tbody>
|
|
29154
|
+
</table>
|
|
29155
|
+
</div>
|
|
29156
|
+
}
|
|
29157
|
+
<div [class.k-grid-header-wrap]="position === 'top'" [class.k-grid-footer-wrap]="position === 'bottom'" role="presentation"
|
|
29158
|
+
[style.width.px]="isLocked ? wrapWidth : null">
|
|
29159
|
+
<table
|
|
29160
|
+
class="k-grid-table k-table"
|
|
29161
|
+
[class.k-grid-group-sticky-header-table]="position === 'top'"
|
|
29162
|
+
[class.k-grid-group-sticky-footer-table]="position === 'bottom'"
|
|
29163
|
+
[class.k-table-sm]="gridSize === 'small'"
|
|
29164
|
+
[class.k-table-md]="gridSize === 'medium'"
|
|
29165
|
+
role="none"
|
|
29166
|
+
[style.width.px]="tableWidth">
|
|
29167
|
+
<colgroup kendoGridColGroup
|
|
29168
|
+
[groups]="isLocked ? [] : groups"
|
|
29169
|
+
[columns]="$any(columns)"
|
|
29170
|
+
[detailTemplate]="isLocked ? null : detailTemplate">
|
|
29171
|
+
</colgroup>
|
|
29172
|
+
<tbody class="k-table-tbody" role="rowgroup">
|
|
29173
|
+
@if (position === 'top') {
|
|
29174
|
+
@for (stickyItem of items; track stickyItem.flatIndex) {
|
|
29175
|
+
<tr role="row"
|
|
29176
|
+
class="k-grouping-row k-table-group-row k-table-row"
|
|
29177
|
+
kendoGridGroupHeader
|
|
29178
|
+
[columns]="columns"
|
|
29179
|
+
[groups]="groups"
|
|
29180
|
+
[item]="$any(stickyItem.item)"
|
|
29181
|
+
[hasDetails]="!!detailTemplate?.templateRef"
|
|
29182
|
+
[skipGroupDecoration]="isLocked"
|
|
29183
|
+
[hasGroupHeaderColumn]="hasGroupHeaderColumn"
|
|
29184
|
+
[groupHeaderColumns]="groupHeaderColumns"
|
|
29185
|
+
[rowIndex]="stickyItem.flatIndex + 1"
|
|
29186
|
+
[totalColumnsCount]="totalColumnsCount"
|
|
29187
|
+
[attr.aria-rowindex]="stickyItem.flatIndex + 1"
|
|
29188
|
+
[attr.data-group-index]="$any(stickyItem.item).index"
|
|
29189
|
+
[attr.data-group-level]="$any(stickyItem.item).level"
|
|
29190
|
+
tabindex="-1">
|
|
29191
|
+
</tr>
|
|
29192
|
+
}
|
|
29193
|
+
}
|
|
29194
|
+
@if (position === 'bottom') {
|
|
29195
|
+
@for (stickyItem of items; track stickyItem.flatIndex; let rowIdx = $index) {
|
|
29196
|
+
<tr role="row"
|
|
29197
|
+
class="k-group-footer"
|
|
29198
|
+
[attr.aria-rowindex]="stickyItem.flatIndex + 1"
|
|
29199
|
+
[attr.data-sticky-row]="rowIdx">
|
|
29200
|
+
@if (!isLocked) {
|
|
29201
|
+
@for (g of groups; track $index) {
|
|
29202
|
+
<td class="k-group-cell k-table-td k-table-group-td" role="presentation"></td>
|
|
29203
|
+
}
|
|
29204
|
+
@if (detailTemplate?.templateRef && !isStacked) {
|
|
29205
|
+
<td class="k-hierarchy-cell k-table-td" role="gridcell"
|
|
29206
|
+
aria-selected="false">
|
|
29207
|
+
</td>
|
|
29208
|
+
}
|
|
29209
|
+
}
|
|
29210
|
+
@if (!isStacked) {
|
|
29211
|
+
@for (column of footerColumns; track $index; let columnIndex = $index) {
|
|
29212
|
+
<td role="gridcell"
|
|
29213
|
+
class="k-table-td"
|
|
29214
|
+
tabindex="-1"
|
|
29215
|
+
[attr.aria-colindex]="columnIndex + 1"
|
|
29216
|
+
[attr.data-col-index]="$any(column).leafIndex">
|
|
29217
|
+
<ng-template
|
|
29218
|
+
[templateContext]="{
|
|
29219
|
+
templateRef: $any(column).groupFooterTemplateRef,
|
|
29220
|
+
group: $any(stickyItem.item).data,
|
|
29221
|
+
field: $any(column).field,
|
|
29222
|
+
column: column,
|
|
29223
|
+
aggregates: $any(stickyItem.item).data?.aggregates,
|
|
29224
|
+
$implicit: $any(stickyItem.item).data?.aggregates
|
|
29225
|
+
}">
|
|
29226
|
+
</ng-template>
|
|
29227
|
+
</td>
|
|
29228
|
+
}
|
|
29229
|
+
} @else {
|
|
29230
|
+
<td role="gridcell" class="k-table-td">
|
|
29231
|
+
<div class="k-grid-column-template">
|
|
29232
|
+
@for (col of footerColumns; track $index) {
|
|
29233
|
+
@if ($any(col).groupFooterTemplateRef) {
|
|
29234
|
+
<div class="k-column-template-item">
|
|
29235
|
+
<ng-template
|
|
29236
|
+
[templateContext]="{
|
|
29237
|
+
templateRef: $any(col).groupFooterTemplateRef,
|
|
29238
|
+
group: $any(stickyItem.item).data,
|
|
29239
|
+
field: $any(col).field,
|
|
29240
|
+
column: col,
|
|
29241
|
+
aggregates: $any(stickyItem.item).data?.aggregates,
|
|
29242
|
+
$implicit: $any(stickyItem.item).data?.aggregates
|
|
29243
|
+
}">
|
|
29244
|
+
</ng-template>
|
|
29245
|
+
</div>
|
|
29246
|
+
}
|
|
29247
|
+
}
|
|
29248
|
+
</div>
|
|
29249
|
+
</td>
|
|
29250
|
+
}
|
|
29251
|
+
</tr>
|
|
29252
|
+
}
|
|
29253
|
+
}
|
|
29254
|
+
</tbody>
|
|
29255
|
+
</table>
|
|
29256
|
+
</div>
|
|
29257
|
+
`, isInline: true, dependencies: [{ kind: "component", type: ColGroupComponent, selector: "[kendoGridColGroup]", inputs: ["columns", "groups", "detailTemplate", "sort"] }, { kind: "component", type: GroupHeaderComponent, selector: "[kendoGridGroupHeader]", inputs: ["rowIndex", "logicalRowIndex", "item", "skipGroupDecoration", "hasDetails", "totalColumnsCount", "hasGroupHeaderColumn", "groupHeaderColumns", "columns", "groups"] }, { kind: "directive", type: TemplateContextDirective, selector: "[templateContext]", inputs: ["templateContext"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
29258
|
+
}
|
|
29259
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: StickyGroupContainerComponent, decorators: [{
|
|
29260
|
+
type: Component,
|
|
29261
|
+
args: [{
|
|
29262
|
+
selector: '[kendoGridStickyGroupContainer]',
|
|
29263
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
29264
|
+
template: `
|
|
29265
|
+
@if (isLocked) {
|
|
29266
|
+
<div class="k-grid-content-locked" role="presentation" [style.width.px]="lockedWidth">
|
|
29267
|
+
<table
|
|
29268
|
+
class="k-grid-table k-table"
|
|
29269
|
+
[class.k-grid-group-sticky-header-table]="position === 'top'"
|
|
29270
|
+
[class.k-grid-group-sticky-footer-table]="position === 'bottom'"
|
|
29271
|
+
[class.k-table-sm]="gridSize === 'small'"
|
|
29272
|
+
[class.k-table-md]="gridSize === 'medium'"
|
|
29273
|
+
role="none"
|
|
29274
|
+
[style.width.px]="lockedWidth">
|
|
29275
|
+
<colgroup kendoGridColGroup
|
|
29276
|
+
[groups]="groups"
|
|
29277
|
+
[columns]="$any(lockedColumns)"
|
|
29278
|
+
[detailTemplate]="detailTemplate">
|
|
29279
|
+
</colgroup>
|
|
29280
|
+
<tbody class="k-table-tbody" role="presentation">
|
|
29281
|
+
@if (position === 'top') {
|
|
29282
|
+
@for (stickyItem of items; track stickyItem.flatIndex) {
|
|
29283
|
+
<tr role="row"
|
|
29284
|
+
class="k-grouping-row k-table-group-row k-table-row"
|
|
29285
|
+
kendoGridGroupHeader
|
|
29286
|
+
[columns]="lockedColumns"
|
|
29287
|
+
[groups]="groups"
|
|
29288
|
+
[item]="$any(stickyItem.item)"
|
|
29289
|
+
[hasDetails]="!!detailTemplate?.templateRef"
|
|
29290
|
+
[skipGroupDecoration]="false"
|
|
29291
|
+
[hasGroupHeaderColumn]="false"
|
|
29292
|
+
[groupHeaderColumns]="[]"
|
|
29293
|
+
[rowIndex]="stickyItem.flatIndex + 1"
|
|
29294
|
+
[totalColumnsCount]="totalColumnsCount"
|
|
29295
|
+
[attr.aria-rowindex]="stickyItem.flatIndex + 1"
|
|
29296
|
+
[attr.data-group-index]="$any(stickyItem.item).index"
|
|
29297
|
+
[attr.data-group-level]="$any(stickyItem.item).level"
|
|
29298
|
+
tabindex="-1">
|
|
29299
|
+
</tr>
|
|
29300
|
+
}
|
|
29301
|
+
}
|
|
29302
|
+
@if (position === 'bottom') {
|
|
29303
|
+
@for (stickyItem of items; track stickyItem.flatIndex; let rowIdx = $index) {
|
|
29304
|
+
<tr role="row"
|
|
29305
|
+
class="k-group-footer"
|
|
29306
|
+
[attr.aria-rowindex]="stickyItem.flatIndex + 1"
|
|
29307
|
+
[attr.data-sticky-row]="rowIdx">
|
|
29308
|
+
@for (g of groups; track $index) {
|
|
29309
|
+
<td class="k-group-cell k-table-td k-table-group-td" role="presentation"></td>
|
|
29310
|
+
}
|
|
29311
|
+
@if (detailTemplate?.templateRef) {
|
|
29312
|
+
<td class="k-hierarchy-cell k-table-td" role="gridcell"
|
|
29313
|
+
aria-selected="false">
|
|
29314
|
+
</td>
|
|
29315
|
+
}
|
|
29316
|
+
@for (column of lockedFooterColumns; track $index; let columnIndex = $index) {
|
|
29317
|
+
<td role="gridcell"
|
|
29318
|
+
class="k-table-td"
|
|
29319
|
+
tabindex="-1"
|
|
29320
|
+
[attr.aria-colindex]="columnIndex + 1"
|
|
29321
|
+
[attr.data-col-index]="$any(column).leafIndex">
|
|
29322
|
+
<ng-template
|
|
29323
|
+
[templateContext]="{
|
|
29324
|
+
templateRef: $any(column).groupFooterTemplateRef,
|
|
29325
|
+
group: $any(stickyItem.item).data,
|
|
29326
|
+
field: $any(column).field,
|
|
29327
|
+
column: column,
|
|
29328
|
+
aggregates: $any(stickyItem.item).data?.aggregates,
|
|
29329
|
+
$implicit: $any(stickyItem.item).data?.aggregates
|
|
29330
|
+
}">
|
|
29331
|
+
</ng-template>
|
|
29332
|
+
</td>
|
|
29333
|
+
}
|
|
29334
|
+
</tr>
|
|
29335
|
+
}
|
|
29336
|
+
}
|
|
29337
|
+
</tbody>
|
|
29338
|
+
</table>
|
|
29339
|
+
</div>
|
|
29340
|
+
}
|
|
29341
|
+
<div [class.k-grid-header-wrap]="position === 'top'" [class.k-grid-footer-wrap]="position === 'bottom'" role="presentation"
|
|
29342
|
+
[style.width.px]="isLocked ? wrapWidth : null">
|
|
29343
|
+
<table
|
|
29344
|
+
class="k-grid-table k-table"
|
|
29345
|
+
[class.k-grid-group-sticky-header-table]="position === 'top'"
|
|
29346
|
+
[class.k-grid-group-sticky-footer-table]="position === 'bottom'"
|
|
29347
|
+
[class.k-table-sm]="gridSize === 'small'"
|
|
29348
|
+
[class.k-table-md]="gridSize === 'medium'"
|
|
29349
|
+
role="none"
|
|
29350
|
+
[style.width.px]="tableWidth">
|
|
29351
|
+
<colgroup kendoGridColGroup
|
|
29352
|
+
[groups]="isLocked ? [] : groups"
|
|
29353
|
+
[columns]="$any(columns)"
|
|
29354
|
+
[detailTemplate]="isLocked ? null : detailTemplate">
|
|
29355
|
+
</colgroup>
|
|
29356
|
+
<tbody class="k-table-tbody" role="rowgroup">
|
|
29357
|
+
@if (position === 'top') {
|
|
29358
|
+
@for (stickyItem of items; track stickyItem.flatIndex) {
|
|
29359
|
+
<tr role="row"
|
|
29360
|
+
class="k-grouping-row k-table-group-row k-table-row"
|
|
29361
|
+
kendoGridGroupHeader
|
|
29362
|
+
[columns]="columns"
|
|
29363
|
+
[groups]="groups"
|
|
29364
|
+
[item]="$any(stickyItem.item)"
|
|
29365
|
+
[hasDetails]="!!detailTemplate?.templateRef"
|
|
29366
|
+
[skipGroupDecoration]="isLocked"
|
|
29367
|
+
[hasGroupHeaderColumn]="hasGroupHeaderColumn"
|
|
29368
|
+
[groupHeaderColumns]="groupHeaderColumns"
|
|
29369
|
+
[rowIndex]="stickyItem.flatIndex + 1"
|
|
29370
|
+
[totalColumnsCount]="totalColumnsCount"
|
|
29371
|
+
[attr.aria-rowindex]="stickyItem.flatIndex + 1"
|
|
29372
|
+
[attr.data-group-index]="$any(stickyItem.item).index"
|
|
29373
|
+
[attr.data-group-level]="$any(stickyItem.item).level"
|
|
29374
|
+
tabindex="-1">
|
|
29375
|
+
</tr>
|
|
29376
|
+
}
|
|
29377
|
+
}
|
|
29378
|
+
@if (position === 'bottom') {
|
|
29379
|
+
@for (stickyItem of items; track stickyItem.flatIndex; let rowIdx = $index) {
|
|
29380
|
+
<tr role="row"
|
|
29381
|
+
class="k-group-footer"
|
|
29382
|
+
[attr.aria-rowindex]="stickyItem.flatIndex + 1"
|
|
29383
|
+
[attr.data-sticky-row]="rowIdx">
|
|
29384
|
+
@if (!isLocked) {
|
|
29385
|
+
@for (g of groups; track $index) {
|
|
29386
|
+
<td class="k-group-cell k-table-td k-table-group-td" role="presentation"></td>
|
|
29387
|
+
}
|
|
29388
|
+
@if (detailTemplate?.templateRef && !isStacked) {
|
|
29389
|
+
<td class="k-hierarchy-cell k-table-td" role="gridcell"
|
|
29390
|
+
aria-selected="false">
|
|
29391
|
+
</td>
|
|
29392
|
+
}
|
|
29393
|
+
}
|
|
29394
|
+
@if (!isStacked) {
|
|
29395
|
+
@for (column of footerColumns; track $index; let columnIndex = $index) {
|
|
29396
|
+
<td role="gridcell"
|
|
29397
|
+
class="k-table-td"
|
|
29398
|
+
tabindex="-1"
|
|
29399
|
+
[attr.aria-colindex]="columnIndex + 1"
|
|
29400
|
+
[attr.data-col-index]="$any(column).leafIndex">
|
|
29401
|
+
<ng-template
|
|
29402
|
+
[templateContext]="{
|
|
29403
|
+
templateRef: $any(column).groupFooterTemplateRef,
|
|
29404
|
+
group: $any(stickyItem.item).data,
|
|
29405
|
+
field: $any(column).field,
|
|
29406
|
+
column: column,
|
|
29407
|
+
aggregates: $any(stickyItem.item).data?.aggregates,
|
|
29408
|
+
$implicit: $any(stickyItem.item).data?.aggregates
|
|
29409
|
+
}">
|
|
29410
|
+
</ng-template>
|
|
29411
|
+
</td>
|
|
29412
|
+
}
|
|
29413
|
+
} @else {
|
|
29414
|
+
<td role="gridcell" class="k-table-td">
|
|
29415
|
+
<div class="k-grid-column-template">
|
|
29416
|
+
@for (col of footerColumns; track $index) {
|
|
29417
|
+
@if ($any(col).groupFooterTemplateRef) {
|
|
29418
|
+
<div class="k-column-template-item">
|
|
29419
|
+
<ng-template
|
|
29420
|
+
[templateContext]="{
|
|
29421
|
+
templateRef: $any(col).groupFooterTemplateRef,
|
|
29422
|
+
group: $any(stickyItem.item).data,
|
|
29423
|
+
field: $any(col).field,
|
|
29424
|
+
column: col,
|
|
29425
|
+
aggregates: $any(stickyItem.item).data?.aggregates,
|
|
29426
|
+
$implicit: $any(stickyItem.item).data?.aggregates
|
|
29427
|
+
}">
|
|
29428
|
+
</ng-template>
|
|
29429
|
+
</div>
|
|
29430
|
+
}
|
|
29431
|
+
}
|
|
29432
|
+
</div>
|
|
29433
|
+
</td>
|
|
29434
|
+
}
|
|
29435
|
+
</tr>
|
|
29436
|
+
}
|
|
29437
|
+
}
|
|
29438
|
+
</tbody>
|
|
29439
|
+
</table>
|
|
29440
|
+
</div>
|
|
29441
|
+
`,
|
|
29442
|
+
standalone: true,
|
|
29443
|
+
imports: [
|
|
29444
|
+
ColGroupComponent,
|
|
29445
|
+
GroupHeaderComponent,
|
|
29446
|
+
TemplateContextDirective
|
|
29447
|
+
],
|
|
29448
|
+
providers: [
|
|
29449
|
+
{ provide: SKIP_CELL_NAVIGATION, useValue: true }
|
|
29450
|
+
]
|
|
29451
|
+
}]
|
|
29452
|
+
}], ctorParameters: () => [{ type: StickyGroupsService }, { type: i0.ChangeDetectorRef }, { type: ContextService }, { type: i0.ElementRef }, { type: NavigationService }, { type: GroupsService }, { type: i0.NgZone }], propDecorators: { position: [{
|
|
29453
|
+
type: Input
|
|
29454
|
+
}], columns: [{
|
|
29455
|
+
type: Input
|
|
29456
|
+
}], lockedColumns: [{
|
|
29457
|
+
type: Input
|
|
29458
|
+
}], groups: [{
|
|
29459
|
+
type: Input
|
|
29460
|
+
}], detailTemplate: [{
|
|
29461
|
+
type: Input
|
|
29462
|
+
}], totalColumnsCount: [{
|
|
29463
|
+
type: Input
|
|
29464
|
+
}], hasGroupHeaderColumn: [{
|
|
29465
|
+
type: Input
|
|
29466
|
+
}], groupHeaderColumns: [{
|
|
29467
|
+
type: Input
|
|
29468
|
+
}], tableWidth: [{
|
|
29469
|
+
type: Input
|
|
29470
|
+
}], lockedWidth: [{
|
|
29471
|
+
type: Input
|
|
29472
|
+
}], isLocked: [{
|
|
29473
|
+
type: Input
|
|
29474
|
+
}], hostClass: [{
|
|
29475
|
+
type: HostBinding,
|
|
29476
|
+
args: ['class.k-grid-sticky-container']
|
|
29477
|
+
}], isBottom: [{
|
|
29478
|
+
type: HostBinding,
|
|
29479
|
+
args: ['class.k-pos-bottom']
|
|
29480
|
+
}], hostRole: [{
|
|
29481
|
+
type: HostBinding,
|
|
29482
|
+
args: ['attr.role']
|
|
29483
|
+
}], onContainerClick: [{
|
|
29484
|
+
type: HostListener,
|
|
29485
|
+
args: ['click', ['$event']]
|
|
29486
|
+
}], onContainerFocusIn: [{
|
|
29487
|
+
type: HostListener,
|
|
29488
|
+
args: ['focusin', ['$event']]
|
|
29489
|
+
}], onContainerFocusOut: [{
|
|
29490
|
+
type: HostListener,
|
|
29491
|
+
args: ['focusout', ['$event']]
|
|
29492
|
+
}], onContainerKeydown: [{
|
|
29493
|
+
type: HostListener,
|
|
29494
|
+
args: ['keydown', ['$event']]
|
|
29495
|
+
}] } });
|
|
29496
|
+
|
|
27604
29497
|
const elementAt = (index, elements, elementOffset) => {
|
|
27605
29498
|
for (let idx = 0, elementIdx = 0; idx < elements.length; idx++) {
|
|
27606
29499
|
const offset = elementOffset(elements[idx]);
|
|
@@ -27666,6 +29559,7 @@ class ListComponent {
|
|
|
27666
29559
|
pdfService;
|
|
27667
29560
|
columnInfo;
|
|
27668
29561
|
dataMappingService;
|
|
29562
|
+
stickyGroupsService;
|
|
27669
29563
|
hostClass = true;
|
|
27670
29564
|
hostRole = 'presentation';
|
|
27671
29565
|
data;
|
|
@@ -27697,6 +29591,19 @@ class ListComponent {
|
|
|
27697
29591
|
columnsStartIdx = 0;
|
|
27698
29592
|
allItems = [];
|
|
27699
29593
|
itemsToRender = [];
|
|
29594
|
+
stickyGroupHeaderColumns = [];
|
|
29595
|
+
stickyNeedsUpdate = false;
|
|
29596
|
+
stickyWasEnabled = false;
|
|
29597
|
+
pendingToggleScroll = null;
|
|
29598
|
+
skipScrollerAdjust = false;
|
|
29599
|
+
suppressStickyUpdates = false;
|
|
29600
|
+
suppressFocusScrollAdjust = false;
|
|
29601
|
+
get hasStickyHeaders() {
|
|
29602
|
+
return this.groupable && this.groupable.stickyHeaders && this.groups?.length > 0;
|
|
29603
|
+
}
|
|
29604
|
+
get hasStickyFooters() {
|
|
29605
|
+
return this.groupable && this.groupable.stickyFooters && this.groups?.length > 0;
|
|
29606
|
+
}
|
|
27700
29607
|
get showFooter() {
|
|
27701
29608
|
return this.groupable && this.groupable.showFooter;
|
|
27702
29609
|
}
|
|
@@ -27710,6 +29617,8 @@ class ListComponent {
|
|
|
27710
29617
|
lockedTable;
|
|
27711
29618
|
table;
|
|
27712
29619
|
resizeSensors = new QueryList();
|
|
29620
|
+
stickyHeaderContainer;
|
|
29621
|
+
stickyFooterContainer;
|
|
27713
29622
|
scroller;
|
|
27714
29623
|
scrollerFactory;
|
|
27715
29624
|
subscriptions;
|
|
@@ -27759,7 +29668,7 @@ class ListComponent {
|
|
|
27759
29668
|
minRowHeight;
|
|
27760
29669
|
handleSkipOnData = false;
|
|
27761
29670
|
scrollToIndex = null;
|
|
27762
|
-
constructor(scrollerFactory, detailsService, changeNotification, suspendService, groupsService, ngZone, renderer, scrollSyncService, resizeService, editService, supportService, navigationService, scrollRequestService, ctx, columnResizingService, changeDetector, pdfService, columnInfo, dataMappingService) {
|
|
29671
|
+
constructor(scrollerFactory, detailsService, changeNotification, suspendService, groupsService, ngZone, renderer, scrollSyncService, resizeService, editService, supportService, navigationService, scrollRequestService, ctx, columnResizingService, changeDetector, pdfService, columnInfo, dataMappingService, stickyGroupsService) {
|
|
27763
29672
|
this.changeNotification = changeNotification;
|
|
27764
29673
|
this.suspendService = suspendService;
|
|
27765
29674
|
this.groupsService = groupsService;
|
|
@@ -27776,10 +29685,16 @@ class ListComponent {
|
|
|
27776
29685
|
this.pdfService = pdfService;
|
|
27777
29686
|
this.columnInfo = columnInfo;
|
|
27778
29687
|
this.dataMappingService = dataMappingService;
|
|
29688
|
+
this.stickyGroupsService = stickyGroupsService;
|
|
27779
29689
|
this.scrollerFactory = scrollerFactory;
|
|
27780
29690
|
this.scroller = this.ctx.scroller = scrollerFactory(this.dispatcher, this.ctx);
|
|
27781
29691
|
this.subscriptions = detailsService.changes.subscribe(() => this.detailExpand());
|
|
27782
|
-
this.subscriptions.add(scrollRequestService.requests.subscribe(req =>
|
|
29692
|
+
this.subscriptions.add(scrollRequestService.requests.subscribe(req => {
|
|
29693
|
+
if (this.suppressFocusScrollAdjust) {
|
|
29694
|
+
return;
|
|
29695
|
+
}
|
|
29696
|
+
isPresent(req.adjustIndex) ? this.scrollTo(req.request, req.adjustIndex) : this.scrollToItem(req.request);
|
|
29697
|
+
}));
|
|
27783
29698
|
this.subscriptions.add(this.pdfService.restoreDOMVirtualization.subscribe(() => {
|
|
27784
29699
|
this.ngZone.onStable.pipe(take(1)).subscribe(() => {
|
|
27785
29700
|
this.init();
|
|
@@ -27789,7 +29704,8 @@ class ListComponent {
|
|
|
27789
29704
|
}));
|
|
27790
29705
|
}
|
|
27791
29706
|
ngOnInit() {
|
|
27792
|
-
|
|
29707
|
+
const needsMeasuredRowHeight = this.isVirtual || this.hasStickyHeaders || this.hasStickyFooters;
|
|
29708
|
+
this.minRowHeight = needsMeasuredRowHeight ? this.rowHeight || calcRowHeight(this.table.nativeElement) : this.rowHeight;
|
|
27793
29709
|
this.init();
|
|
27794
29710
|
this.subscriptions.add(this.ngZone.runOutsideAngular(this.handleRowSync.bind(this)));
|
|
27795
29711
|
this.subscriptions.add(this.groupsService.changes.subscribe(() => {
|
|
@@ -27805,6 +29721,33 @@ class ListComponent {
|
|
|
27805
29721
|
}
|
|
27806
29722
|
}));
|
|
27807
29723
|
this.subscriptions.add(this.ctx.localization.changes.subscribe(({ rtl }) => this.rtl = rtl));
|
|
29724
|
+
this.subscriptions.add(this.stickyGroupsService.scrollToFooter$.subscribe(() => {
|
|
29725
|
+
this.stickyNeedsUpdate = true;
|
|
29726
|
+
}));
|
|
29727
|
+
this.subscriptions.add(this.stickyGroupsService.scrollToRow$.subscribe(() => {
|
|
29728
|
+
this.stickyNeedsUpdate = true;
|
|
29729
|
+
}));
|
|
29730
|
+
this.subscriptions.add(this.stickyGroupsService.scrollAndToggle$.subscribe((groupIndex) => {
|
|
29731
|
+
this.handleStickyScrollAndToggle(groupIndex);
|
|
29732
|
+
}));
|
|
29733
|
+
this.subscriptions.add(this.ngZone.runOutsideAngular(() => {
|
|
29734
|
+
const navSub = this.navigationService.changes.subscribe(() => {
|
|
29735
|
+
if (!this.hasStickyHeaders && !this.hasStickyFooters) {
|
|
29736
|
+
return;
|
|
29737
|
+
}
|
|
29738
|
+
requestAnimationFrame(() => {
|
|
29739
|
+
if (this.suppressFocusScrollAdjust) {
|
|
29740
|
+
return;
|
|
29741
|
+
}
|
|
29742
|
+
this.stickyGroupsService.adjustScrollForFocusedCell(this.container?.nativeElement, this.stickyHeaderContainer?.nativeElement, this.stickyFooterContainer?.nativeElement);
|
|
29743
|
+
});
|
|
29744
|
+
});
|
|
29745
|
+
return {
|
|
29746
|
+
unsubscribe: () => {
|
|
29747
|
+
navSub.unsubscribe();
|
|
29748
|
+
}
|
|
29749
|
+
};
|
|
29750
|
+
}));
|
|
27808
29751
|
}
|
|
27809
29752
|
ngOnChanges(changes) {
|
|
27810
29753
|
if (!isDocumentAvailable()) {
|
|
@@ -27869,6 +29812,11 @@ class ListComponent {
|
|
|
27869
29812
|
else if (this.totalIsAllItems && totalChanged) {
|
|
27870
29813
|
this.scroller.reset(this.skipScroll);
|
|
27871
29814
|
this.scroller.total = this.allItems.length;
|
|
29815
|
+
// When a sticky toggle is pending, use the pre-computed virtualSkip
|
|
29816
|
+
// (calculated from the OLD measured RHS before toggle).
|
|
29817
|
+
if (this.pendingToggleScroll && this.virtualPageSize) {
|
|
29818
|
+
this.scroller.virtualSkip = this.pendingToggleScroll.virtualSkip;
|
|
29819
|
+
}
|
|
27872
29820
|
this.itemsToRender = this.allItems.slice(this.scroller.virtualSkip, this.scroller.virtualSkip + this.virtualPageSize);
|
|
27873
29821
|
}
|
|
27874
29822
|
else if (totalChanged && !this.ctx.grid?.group?.length) {
|
|
@@ -27931,19 +29879,21 @@ class ListComponent {
|
|
|
27931
29879
|
this.scroller.total = this.allItems.length;
|
|
27932
29880
|
this.rowHeightService = this.scroller.rowHeightService = new RowHeightService(this.scroller.total, this.rowHeight || this.minRowHeight);
|
|
27933
29881
|
}
|
|
27934
|
-
this.isVirtual && this.scroller.update();
|
|
29882
|
+
this.isVirtual && this.scroller.update(this.skipScrollerAdjust);
|
|
29883
|
+
this.skipScrollerAdjust = false;
|
|
27935
29884
|
// Item outside of the viewport is scrolled to programmatically.
|
|
27936
29885
|
// RowHeightService offset for given index still may not match the current scrollTop
|
|
27937
29886
|
// depending on the varying row heights, so we need to adjust the scroll position.
|
|
27938
29887
|
if (isPresent(this.scrollToIndex)) {
|
|
27939
29888
|
const offset = this.scroller.rowHeightService.offset(this.scrollToIndex);
|
|
29889
|
+
const targetScrollTop = this.getStickyAdjustedScrollTop(offset);
|
|
27940
29890
|
const el = this.container.nativeElement;
|
|
27941
29891
|
const maxScrollTop = el.scrollHeight - el.clientHeight;
|
|
27942
29892
|
// Only adjust if scrollTop can actually increase; otherwise adjustScroll
|
|
27943
29893
|
// sets scrollSyncing=true but the scrollTop stays clamped, which blocks
|
|
27944
29894
|
// the pending scroll event from being processed by the scroller.
|
|
27945
|
-
if (
|
|
27946
|
-
this.scroller.adjustScroll(
|
|
29895
|
+
if (targetScrollTop > el.scrollTop && el.scrollTop < maxScrollTop) {
|
|
29896
|
+
this.scroller.adjustScroll(targetScrollTop - el.scrollTop);
|
|
27947
29897
|
}
|
|
27948
29898
|
this.scrollToIndex = null;
|
|
27949
29899
|
}
|
|
@@ -27961,6 +29911,27 @@ class ListComponent {
|
|
|
27961
29911
|
this.zoneSub = null;
|
|
27962
29912
|
});
|
|
27963
29913
|
}
|
|
29914
|
+
const stickyEnabled = this.hasStickyHeaders || this.hasStickyFooters;
|
|
29915
|
+
if (stickyEnabled) {
|
|
29916
|
+
this.updateStickyGroupHeaderColumns();
|
|
29917
|
+
if (totalChanged || dataContentChanged) {
|
|
29918
|
+
this.stickyGroupsService.invalidateRangeMap();
|
|
29919
|
+
this.stickyNeedsUpdate = true;
|
|
29920
|
+
// Rebuild RowHeightService with the new allItems length so
|
|
29921
|
+
// offsets stay in sync after group expand/collapse.
|
|
29922
|
+
this.rowHeightService = this.scroller.rowHeightService =
|
|
29923
|
+
new RowHeightService(this.allItems.length, this.rowHeight || this.minRowHeight);
|
|
29924
|
+
}
|
|
29925
|
+
}
|
|
29926
|
+
else if (this.stickyWasEnabled) {
|
|
29927
|
+
this.stickyGroupsService.clear();
|
|
29928
|
+
const containerEl = this.container?.nativeElement;
|
|
29929
|
+
if (containerEl) {
|
|
29930
|
+
containerEl.style.scrollPaddingTop = '';
|
|
29931
|
+
containerEl.style.scrollPaddingBottom = '';
|
|
29932
|
+
}
|
|
29933
|
+
}
|
|
29934
|
+
this.stickyWasEnabled = stickyEnabled;
|
|
27964
29935
|
}
|
|
27965
29936
|
ngAfterViewInit() {
|
|
27966
29937
|
if (!isDocumentAvailable()) {
|
|
@@ -27976,6 +29947,28 @@ class ListComponent {
|
|
|
27976
29947
|
this.syncRowsHeight();
|
|
27977
29948
|
}
|
|
27978
29949
|
this.hasLockedContainer = isLocked;
|
|
29950
|
+
if (this.pendingToggleScroll) {
|
|
29951
|
+
this.applyPendingToggleScroll();
|
|
29952
|
+
}
|
|
29953
|
+
if (this.stickyNeedsUpdate && isDocumentAvailable()) {
|
|
29954
|
+
this.stickyNeedsUpdate = false;
|
|
29955
|
+
this.updateStickyRowHeights();
|
|
29956
|
+
this.scrollToStickyFooterTarget();
|
|
29957
|
+
if (this.suppressFocusScrollAdjust) {
|
|
29958
|
+
// After a toggle, the row is already positioned correctly —
|
|
29959
|
+
// just focus it without scrolling.
|
|
29960
|
+
const target = this.stickyGroupsService.consumeScrollToRow();
|
|
29961
|
+
if (target) {
|
|
29962
|
+
this.focusRenderedStickyRow(target.flatIndex, target.colIndex);
|
|
29963
|
+
}
|
|
29964
|
+
}
|
|
29965
|
+
else {
|
|
29966
|
+
this.scrollToStickyRowTarget();
|
|
29967
|
+
}
|
|
29968
|
+
if (!this.suppressStickyUpdates) {
|
|
29969
|
+
this.updateStickyGroups();
|
|
29970
|
+
}
|
|
29971
|
+
}
|
|
27979
29972
|
}
|
|
27980
29973
|
syncRowsHeight() {
|
|
27981
29974
|
if (this.lockedContainer) {
|
|
@@ -28000,7 +29993,16 @@ class ListComponent {
|
|
|
28000
29993
|
if (this.suspendService.scroll) {
|
|
28001
29994
|
return;
|
|
28002
29995
|
}
|
|
28003
|
-
|
|
29996
|
+
let total;
|
|
29997
|
+
if (this.isVirtual && this.ctx.grid?.pageable) {
|
|
29998
|
+
total = this.ctx.grid.pageSize;
|
|
29999
|
+
}
|
|
30000
|
+
else if (this.hasStickyHeaders || this.hasStickyFooters) {
|
|
30001
|
+
total = this.allItems.length || this.total;
|
|
30002
|
+
}
|
|
30003
|
+
else {
|
|
30004
|
+
total = this.total;
|
|
30005
|
+
}
|
|
28004
30006
|
this.rowHeightService = this.scroller.rowHeightService = new RowHeightService(total, this.rowHeight || this.minRowHeight);
|
|
28005
30007
|
if (!isUniversal()) {
|
|
28006
30008
|
if (this.skipScroll) {
|
|
@@ -28079,6 +30081,41 @@ class ListComponent {
|
|
|
28079
30081
|
this.itemsToRender = this.allItems.slice(this.scroller.virtualSkip, newEnd);
|
|
28080
30082
|
}
|
|
28081
30083
|
}
|
|
30084
|
+
/**
|
|
30085
|
+
* Recalculates the virtual page size after the scrollable container height changes
|
|
30086
|
+
* due to pinned row containers appearing or disappearing. Expands itemsToRender
|
|
30087
|
+
* if the new viewport can display more rows than currently rendered.
|
|
30088
|
+
* @hidden
|
|
30089
|
+
*/
|
|
30090
|
+
onPinnedContainerHeightChange() {
|
|
30091
|
+
if (!this.isVirtual || !this.container || !this.scroller?.rowHeightService) {
|
|
30092
|
+
return;
|
|
30093
|
+
}
|
|
30094
|
+
// For non-pageable non-grouped virtual, itemsToRender always equals allItems
|
|
30095
|
+
if (!this.ctx.grid?.pageable && !this.ctx.grid?.group?.length) {
|
|
30096
|
+
return;
|
|
30097
|
+
}
|
|
30098
|
+
const newPageSize = this.calcVirtualPageSize();
|
|
30099
|
+
if (newPageSize <= 0 || newPageSize <= this.virtualPageSize) {
|
|
30100
|
+
return;
|
|
30101
|
+
}
|
|
30102
|
+
this.virtualPageSize = this.scroller.virtualPageSize = newPageSize;
|
|
30103
|
+
// Defer the itemsToRender update to a new change detection cycle
|
|
30104
|
+
// to avoid NG0100 (expression changed after check) when this
|
|
30105
|
+
// method is called from onStable after the initial CD pass.
|
|
30106
|
+
this.ngZone.runOutsideAngular(() => {
|
|
30107
|
+
setTimeout(() => {
|
|
30108
|
+
this.ngZone.run(() => {
|
|
30109
|
+
const newEnd = Math.min(this.scroller.virtualSkip + newPageSize, this.allItems.length);
|
|
30110
|
+
const currentEnd = this.scroller.virtualSkip + this.itemsToRender.length;
|
|
30111
|
+
if (newEnd > currentEnd) {
|
|
30112
|
+
this.itemsToRender = this.allItems.slice(this.scroller.virtualSkip, newEnd);
|
|
30113
|
+
}
|
|
30114
|
+
this.scroller.update();
|
|
30115
|
+
});
|
|
30116
|
+
});
|
|
30117
|
+
});
|
|
30118
|
+
}
|
|
28082
30119
|
/**
|
|
28083
30120
|
* Checks if the virtual scroll state is out of sync with the expected position.
|
|
28084
30121
|
* Used to determine if resetVirtualScroll should be called.
|
|
@@ -28150,6 +30187,392 @@ class ListComponent {
|
|
|
28150
30187
|
get isStacked() {
|
|
28151
30188
|
return this.ctx.grid?.isStacked;
|
|
28152
30189
|
}
|
|
30190
|
+
/**
|
|
30191
|
+
* @hidden
|
|
30192
|
+
* Updates sticky group header columns for the overlay. Called in ngDoCheck or on column changes.
|
|
30193
|
+
*/
|
|
30194
|
+
updateStickyGroupHeaderColumns() {
|
|
30195
|
+
if (this.columns.hasGroupHeaderColumn) {
|
|
30196
|
+
this.stickyGroupHeaderColumns = columnsToRender(this.nonLockedLeafColumns.toArray().slice(1));
|
|
30197
|
+
}
|
|
30198
|
+
else {
|
|
30199
|
+
this.stickyGroupHeaderColumns = [];
|
|
30200
|
+
}
|
|
30201
|
+
}
|
|
30202
|
+
/**
|
|
30203
|
+
* Measures actual rendered row heights from the DOM and feeds them into
|
|
30204
|
+
* RowHeightService so its offsets reflect reality. Called in ngAfterViewChecked
|
|
30205
|
+
* when stickyNeedsUpdate is true (data changed or scroll-to-group requested).
|
|
30206
|
+
*/
|
|
30207
|
+
updateStickyRowHeights() {
|
|
30208
|
+
if (!this.rowHeightService) {
|
|
30209
|
+
return;
|
|
30210
|
+
}
|
|
30211
|
+
const tableEl = this.table?.nativeElement;
|
|
30212
|
+
const tbody = tableEl?.querySelector('tbody');
|
|
30213
|
+
if (!tbody?.children.length) {
|
|
30214
|
+
return;
|
|
30215
|
+
}
|
|
30216
|
+
const heights = [];
|
|
30217
|
+
for (let i = 0; i < tbody.children.length; i++) {
|
|
30218
|
+
heights.push(tbody.children[i].getBoundingClientRect().height);
|
|
30219
|
+
}
|
|
30220
|
+
this.rowHeightService.update(this.scroller?.virtualSkip ?? 0, heights);
|
|
30221
|
+
}
|
|
30222
|
+
/**
|
|
30223
|
+
* Handles sticky overlay header click: scrolls to the topmost sticky
|
|
30224
|
+
* group header's real position so all overlay headers become visible
|
|
30225
|
+
* real rows, then toggles the clicked group.
|
|
30226
|
+
*/
|
|
30227
|
+
handleStickyScrollAndToggle(groupIndex) {
|
|
30228
|
+
const containerEl = this.container?.nativeElement;
|
|
30229
|
+
if (!containerEl) {
|
|
30230
|
+
return;
|
|
30231
|
+
}
|
|
30232
|
+
const flatIndex = this.allItems.findIndex(item => item.type === 'group' && item.index === groupIndex);
|
|
30233
|
+
if (flatIndex < 0) {
|
|
30234
|
+
return;
|
|
30235
|
+
}
|
|
30236
|
+
const groupItem = this.allItems[flatIndex];
|
|
30237
|
+
// Find the topmost (root) sticky header — scroll to its real position
|
|
30238
|
+
// so all overlay headers become visible real rows at the top.
|
|
30239
|
+
const stickyItems = this.stickyGroupsService.stickyHeaderItems;
|
|
30240
|
+
const rootStickyItem = stickyItems.length > 0 ? stickyItems[0] : null;
|
|
30241
|
+
const isFirstChild = groupIndex.endsWith('_0');
|
|
30242
|
+
let scrollToIndex;
|
|
30243
|
+
let targetScrollTop;
|
|
30244
|
+
if (isFirstChild) {
|
|
30245
|
+
scrollToIndex = rootStickyItem ? rootStickyItem.flatIndex : flatIndex;
|
|
30246
|
+
targetScrollTop = this.rowHeightService
|
|
30247
|
+
? Math.max(0, this.rowHeightService.offset(scrollToIndex))
|
|
30248
|
+
: containerEl.scrollTop;
|
|
30249
|
+
}
|
|
30250
|
+
else {
|
|
30251
|
+
// Non-first child: scroll so the clicked group will sit just below ancestor headers
|
|
30252
|
+
const parts = groupIndex.split('_');
|
|
30253
|
+
let ancestorHeight = 0;
|
|
30254
|
+
for (let level = 0; level < parts.length - 1; level++) {
|
|
30255
|
+
const ancestorIndex = parts.slice(0, level + 1).join('_');
|
|
30256
|
+
const ancestorFlatIdx = this.allItems.findIndex(item => item.type === 'group' && item.index === ancestorIndex);
|
|
30257
|
+
if (ancestorFlatIdx >= 0 && this.rowHeightService) {
|
|
30258
|
+
ancestorHeight += this.rowHeightService.height(ancestorFlatIdx);
|
|
30259
|
+
}
|
|
30260
|
+
}
|
|
30261
|
+
const clickedOffset = this.rowHeightService
|
|
30262
|
+
? this.rowHeightService.offset(flatIndex)
|
|
30263
|
+
: containerEl.scrollTop;
|
|
30264
|
+
targetScrollTop = Math.max(0, clickedOffset - ancestorHeight);
|
|
30265
|
+
}
|
|
30266
|
+
// Compute virtual page info using the OLD measured RHS (before toggle destroys it)
|
|
30267
|
+
let virtualSkip = this.scroller.virtualSkip;
|
|
30268
|
+
let translateOffset = this.scroller.tableTransformOffset;
|
|
30269
|
+
if (this.isVirtual && this.virtualPageSize && this.rowHeightService) {
|
|
30270
|
+
const firstVisibleIdx = this.rowHeightService.index(targetScrollTop);
|
|
30271
|
+
const buffer = Math.max(Math.floor(this.virtualPageSize * 0.3), 0);
|
|
30272
|
+
virtualSkip = Math.max(firstVisibleIdx - buffer, 0);
|
|
30273
|
+
translateOffset = this.rowHeightService.offset(virtualSkip);
|
|
30274
|
+
}
|
|
30275
|
+
// 1. Suppress scroller from reacting to the scroll position change
|
|
30276
|
+
this.scroller.scrollSyncing = true;
|
|
30277
|
+
// Suppress scroll-triggered sticky updates until RAF completes
|
|
30278
|
+
this.suppressStickyUpdates = true;
|
|
30279
|
+
// 2. Scroll BEFORE toggle — pre-toggle DOM/data are still intact
|
|
30280
|
+
containerEl.scrollTop = targetScrollTop;
|
|
30281
|
+
const lockedEl = this.lockedContainer?.nativeElement;
|
|
30282
|
+
if (lockedEl) {
|
|
30283
|
+
lockedEl.scrollTop = targetScrollTop;
|
|
30284
|
+
}
|
|
30285
|
+
// 3. Store pending state for virtual page fix-up in ngAfterViewChecked
|
|
30286
|
+
this.pendingToggleScroll = { groupIndex, targetScrollTop, virtualSkip, translateOffset };
|
|
30287
|
+
// 4. Toggle — triggers groupsService.changes → skipScroll=true → ngDoCheck rebuilds allItems
|
|
30288
|
+
this.groupsService.toggleRow(groupItem);
|
|
30289
|
+
}
|
|
30290
|
+
/**
|
|
30291
|
+
* After toggle, fixes up the virtual page so the correct rows are rendered
|
|
30292
|
+
* around the target scroll position that was set pre-toggle.
|
|
30293
|
+
*/
|
|
30294
|
+
applyPendingToggleScroll() {
|
|
30295
|
+
const pending = this.pendingToggleScroll;
|
|
30296
|
+
this.pendingToggleScroll = null;
|
|
30297
|
+
if (!pending) {
|
|
30298
|
+
return;
|
|
30299
|
+
}
|
|
30300
|
+
const containerEl = this.container?.nativeElement;
|
|
30301
|
+
if (!containerEl) {
|
|
30302
|
+
return;
|
|
30303
|
+
}
|
|
30304
|
+
// Clear skipScroll so scroller responds to future page changes.
|
|
30305
|
+
// Keep scrollSyncing = true so the async scroll event from the
|
|
30306
|
+
// pre-toggle scrollTop assignment is consumed harmlessly.
|
|
30307
|
+
this.skipScroll = false;
|
|
30308
|
+
this.scroller.scrollSyncing = true;
|
|
30309
|
+
const targetScrollTop = pending.targetScrollTop;
|
|
30310
|
+
// Ensure scrollTop is still at the target (scroller.reset may have nudged it)
|
|
30311
|
+
containerEl.scrollTop = targetScrollTop;
|
|
30312
|
+
// Virtual mode: apply pre-computed virtual page info (from OLD measured RHS)
|
|
30313
|
+
if (this.isVirtual && this.virtualPageSize) {
|
|
30314
|
+
const newVirtualSkip = pending.virtualSkip;
|
|
30315
|
+
const translateOffset = pending.translateOffset;
|
|
30316
|
+
this.scroller.virtualSkip = newVirtualSkip;
|
|
30317
|
+
this.scroller.firstToLoad = newVirtualSkip;
|
|
30318
|
+
this.scroller.lastLoaded = Math.min(newVirtualSkip + this.virtualPageSize, this.allItems.length) - 1;
|
|
30319
|
+
// Re-slice the visible window
|
|
30320
|
+
this.itemsToRender = this.allItems.slice(newVirtualSkip, newVirtualSkip + this.virtualPageSize);
|
|
30321
|
+
// Set table translateY using the pre-computed offset from the measured RHS
|
|
30322
|
+
this.scroller.tableTransformOffset = translateOffset;
|
|
30323
|
+
[
|
|
30324
|
+
this.table?.nativeElement,
|
|
30325
|
+
this.lockedTable?.nativeElement
|
|
30326
|
+
].filter(isPresent).forEach(el => {
|
|
30327
|
+
this.renderer.setStyle(el, 'transform', `translateY(${translateOffset}px)`);
|
|
30328
|
+
});
|
|
30329
|
+
}
|
|
30330
|
+
// Sync locked container
|
|
30331
|
+
const lockedEl = this.lockedContainer?.nativeElement;
|
|
30332
|
+
if (lockedEl) {
|
|
30333
|
+
lockedEl.scrollTop = targetScrollTop;
|
|
30334
|
+
}
|
|
30335
|
+
// Suppress scroller.update() adjustScroll in the upcoming onStable callback
|
|
30336
|
+
this.skipScrollerAdjust = true;
|
|
30337
|
+
// Force sticky overlay update AFTER the DOM catches up.
|
|
30338
|
+
// At this point the DOM still has stale rows (tbodyRows != itemsToRender.length)
|
|
30339
|
+
// because Angular hasn't re-rendered the child table-body component yet.
|
|
30340
|
+
// Defer to requestAnimationFrame so the update sees correct DOM.
|
|
30341
|
+
this.stickyGroupsService.invalidateRangeMap();
|
|
30342
|
+
this.ngZone.runOutsideAngular(() => {
|
|
30343
|
+
requestAnimationFrame(() => {
|
|
30344
|
+
// After scroller.update() has measured actual row heights,
|
|
30345
|
+
// reconcile translateY with the updated RHS and recompute
|
|
30346
|
+
// scrollTop so the root group header sits at viewport top.
|
|
30347
|
+
if (this.isVirtual && this.rowHeightService) {
|
|
30348
|
+
const correctOffset = this.rowHeightService.offset(this.scroller.virtualSkip);
|
|
30349
|
+
const currentOffset = this.scroller.tableTransformOffset;
|
|
30350
|
+
if (Math.abs(currentOffset - correctOffset) > 1) {
|
|
30351
|
+
this.scroller.tableTransformOffset = correctOffset;
|
|
30352
|
+
[
|
|
30353
|
+
this.table?.nativeElement,
|
|
30354
|
+
this.lockedTable?.nativeElement
|
|
30355
|
+
].filter(isPresent).forEach(el => {
|
|
30356
|
+
this.renderer.setStyle(el, 'transform', `translateY(${correctOffset}px)`);
|
|
30357
|
+
});
|
|
30358
|
+
}
|
|
30359
|
+
// Find the root sticky header and scroll to its updated offset
|
|
30360
|
+
const stickyItems = this.stickyGroupsService.stickyHeaderItems;
|
|
30361
|
+
const rootItem = stickyItems.length > 0 ? stickyItems[0] : null;
|
|
30362
|
+
const rootFlatIndex = rootItem ? rootItem.flatIndex : this.allItems.findIndex(item => item.type === 'group' && item.index === pending.groupIndex);
|
|
30363
|
+
const clickedFlatIndex = this.allItems.findIndex(item => item.type === 'group' && item.index === pending.groupIndex);
|
|
30364
|
+
const clickedOffset = clickedFlatIndex >= 0 ? this.rowHeightService.offset(clickedFlatIndex) : -1;
|
|
30365
|
+
const isFirstChild = pending.groupIndex.endsWith('_0');
|
|
30366
|
+
if (isFirstChild && rootFlatIndex >= 0) {
|
|
30367
|
+
// First child: scroll to root so all overlay items become real rows
|
|
30368
|
+
containerEl.scrollTop = this.rowHeightService.offset(rootFlatIndex);
|
|
30369
|
+
}
|
|
30370
|
+
else if (!isFirstChild && clickedFlatIndex >= 0) {
|
|
30371
|
+
// Non-first child: scroll so clicked group sits just below the overlay.
|
|
30372
|
+
// Overlay will contain all ancestor group headers (levels above the clicked group).
|
|
30373
|
+
const parts = pending.groupIndex.split('_');
|
|
30374
|
+
let ancestorHeight = 0;
|
|
30375
|
+
for (let level = 0; level < parts.length - 1; level++) {
|
|
30376
|
+
const ancestorIndex = parts.slice(0, level + 1).join('_');
|
|
30377
|
+
const ancestorFlatIdx = this.allItems.findIndex(item => item.type === 'group' && item.index === ancestorIndex);
|
|
30378
|
+
if (ancestorFlatIdx >= 0) {
|
|
30379
|
+
ancestorHeight += this.rowHeightService.height(ancestorFlatIdx);
|
|
30380
|
+
}
|
|
30381
|
+
}
|
|
30382
|
+
const targetScroll = Math.max(0, clickedOffset - ancestorHeight);
|
|
30383
|
+
containerEl.scrollTop = targetScroll;
|
|
30384
|
+
}
|
|
30385
|
+
this.scroller.scrollSyncing = true;
|
|
30386
|
+
const lockedEl = this.lockedContainer?.nativeElement;
|
|
30387
|
+
if (lockedEl) {
|
|
30388
|
+
lockedEl.scrollTop = containerEl.scrollTop;
|
|
30389
|
+
}
|
|
30390
|
+
}
|
|
30391
|
+
this.suppressStickyUpdates = false;
|
|
30392
|
+
this.updateStickyGroups();
|
|
30393
|
+
// Focus the toggled group header after DOM is settled
|
|
30394
|
+
const pendingFocus = this.stickyGroupsService.pendingFocusGroupIndex;
|
|
30395
|
+
if (pendingFocus) {
|
|
30396
|
+
this.stickyGroupsService.pendingFocusGroupIndex = null;
|
|
30397
|
+
const focusFlatIndex = this.allItems.findIndex(item => item.type === 'group' && item.index === pendingFocus);
|
|
30398
|
+
if (focusFlatIndex >= 0 && !this.stickyGroupsService.focusReady$.closed) {
|
|
30399
|
+
// Suppress the navigation-triggered adjustScrollForFocusedCell
|
|
30400
|
+
// since we already positioned the row correctly.
|
|
30401
|
+
this.suppressFocusScrollAdjust = true;
|
|
30402
|
+
this.ngZone.run(() => {
|
|
30403
|
+
this.stickyGroupsService.focusReady$.next({
|
|
30404
|
+
groupIndex: pendingFocus,
|
|
30405
|
+
flatIndex: focusFlatIndex
|
|
30406
|
+
});
|
|
30407
|
+
});
|
|
30408
|
+
// Clear after next frame so all queued nav-triggered RAFs see the flag
|
|
30409
|
+
requestAnimationFrame(() => {
|
|
30410
|
+
this.suppressFocusScrollAdjust = false;
|
|
30411
|
+
});
|
|
30412
|
+
}
|
|
30413
|
+
}
|
|
30414
|
+
});
|
|
30415
|
+
});
|
|
30416
|
+
}
|
|
30417
|
+
/**
|
|
30418
|
+
* Scrolls the container so the real footer row at the pending flat index
|
|
30419
|
+
* is visible at the bottom edge of the viewport.
|
|
30420
|
+
*/
|
|
30421
|
+
scrollToStickyFooterTarget() {
|
|
30422
|
+
const flatIndex = this.stickyGroupsService.consumeScrollToFooter();
|
|
30423
|
+
if (flatIndex == null) {
|
|
30424
|
+
return;
|
|
30425
|
+
}
|
|
30426
|
+
const containerEl = this.container?.nativeElement;
|
|
30427
|
+
if (!containerEl || !this.rowHeightService) {
|
|
30428
|
+
return;
|
|
30429
|
+
}
|
|
30430
|
+
const targetOffset = this.rowHeightService.offset(flatIndex);
|
|
30431
|
+
const rowHeight = this.rowHeightService.height(flatIndex);
|
|
30432
|
+
const viewportHeight = containerEl.clientHeight;
|
|
30433
|
+
// Scroll so the footer row's bottom edge aligns with the viewport bottom
|
|
30434
|
+
containerEl.scrollTop = Math.max(0, targetOffset + rowHeight - viewportHeight);
|
|
30435
|
+
}
|
|
30436
|
+
/**
|
|
30437
|
+
* Scrolls the real grid body until the requested row is rendered in the real
|
|
30438
|
+
* tbody, then focuses the corresponding real grid cell.
|
|
30439
|
+
*/
|
|
30440
|
+
scrollToStickyRowTarget() {
|
|
30441
|
+
const target = this.stickyGroupsService.consumeScrollToRow();
|
|
30442
|
+
if (!target) {
|
|
30443
|
+
return;
|
|
30444
|
+
}
|
|
30445
|
+
const tbody = this.getStickyTargetTbody(target.colIndex);
|
|
30446
|
+
if (!tbody || !this.rowHeightService) {
|
|
30447
|
+
return;
|
|
30448
|
+
}
|
|
30449
|
+
const logicalCell = this.stickyTargetToLogicalCell(target.flatIndex, target.colIndex);
|
|
30450
|
+
if (!logicalCell) {
|
|
30451
|
+
return;
|
|
30452
|
+
}
|
|
30453
|
+
const emitWhenRendered = () => {
|
|
30454
|
+
const start = this.scroller?.virtualSkip ?? 0;
|
|
30455
|
+
const end = start + this.itemsToRender.length - 1;
|
|
30456
|
+
const row = this.findStickyTargetRow(tbody, logicalCell.logicalRow);
|
|
30457
|
+
if (target.flatIndex < start || target.flatIndex > end || !row) {
|
|
30458
|
+
return false;
|
|
30459
|
+
}
|
|
30460
|
+
this.observer?.disconnect();
|
|
30461
|
+
this.focusRenderedStickyRow(target.flatIndex, target.colIndex);
|
|
30462
|
+
return true;
|
|
30463
|
+
};
|
|
30464
|
+
this.observer?.disconnect();
|
|
30465
|
+
this.scrollToVirtualRow(target.flatIndex, false);
|
|
30466
|
+
if (emitWhenRendered()) {
|
|
30467
|
+
return;
|
|
30468
|
+
}
|
|
30469
|
+
this.observer = new MutationObserver(() => {
|
|
30470
|
+
emitWhenRendered();
|
|
30471
|
+
});
|
|
30472
|
+
this.observer.observe(tbody, { childList: true, subtree: true });
|
|
30473
|
+
}
|
|
30474
|
+
/**
|
|
30475
|
+
* Focuses the rendered row requested from the sticky overlay.
|
|
30476
|
+
*/
|
|
30477
|
+
focusRenderedStickyRow(flatIndex, colIndex) {
|
|
30478
|
+
const logicalCell = this.stickyTargetToLogicalCell(flatIndex, colIndex);
|
|
30479
|
+
if (!logicalCell) {
|
|
30480
|
+
return;
|
|
30481
|
+
}
|
|
30482
|
+
const tbody = this.getStickyTargetTbody(colIndex);
|
|
30483
|
+
const row = this.findStickyTargetRow(tbody, logicalCell.logicalRow);
|
|
30484
|
+
const targetCell = row?.querySelector(`[aria-colindex="${logicalCell.logicalCol + 1}"]`);
|
|
30485
|
+
const firstFocusableCell = row?.querySelector('[kendoGridLogicalCell], [kendogridlogicalcell], [aria-colindex]');
|
|
30486
|
+
let cell = targetCell
|
|
30487
|
+
? this.navigationService.focusCellByElement(targetCell)
|
|
30488
|
+
: undefined;
|
|
30489
|
+
if (!cell && firstFocusableCell) {
|
|
30490
|
+
cell = this.navigationService.focusCellByElement(firstFocusableCell);
|
|
30491
|
+
}
|
|
30492
|
+
if (!cell) {
|
|
30493
|
+
cell = this.navigationService.focusCell(logicalCell.logicalRow, logicalCell.logicalCol);
|
|
30494
|
+
}
|
|
30495
|
+
if (cell && cell.colIndex !== logicalCell.logicalCol) {
|
|
30496
|
+
this.navigationService.focusCell(logicalCell.logicalRow, cell.colIndex);
|
|
30497
|
+
}
|
|
30498
|
+
}
|
|
30499
|
+
getStickyTargetTbody(colIndex) {
|
|
30500
|
+
const table = colIndex < this.lockedLeafColumns.length && this.lockedTable
|
|
30501
|
+
? this.lockedTable.nativeElement
|
|
30502
|
+
: this.table?.nativeElement;
|
|
30503
|
+
return table?.querySelector('tbody');
|
|
30504
|
+
}
|
|
30505
|
+
findStickyTargetRow(tbody, logicalRow) {
|
|
30506
|
+
if (!tbody) {
|
|
30507
|
+
return null;
|
|
30508
|
+
}
|
|
30509
|
+
const rowIndex = String(logicalRow + 1);
|
|
30510
|
+
return tbody.querySelector(`tr[data-kendo-grid-row-index="${rowIndex}"], tr[aria-rowindex="${rowIndex}"]`);
|
|
30511
|
+
}
|
|
30512
|
+
/**
|
|
30513
|
+
* Converts a sticky overlay flat-index request into a logical grid cell
|
|
30514
|
+
* position that NavigationService can focus.
|
|
30515
|
+
*/
|
|
30516
|
+
stickyTargetToLogicalCell(flatIndex, colIndex) {
|
|
30517
|
+
const meta = this.navigationService.metadata;
|
|
30518
|
+
if (!meta) {
|
|
30519
|
+
return null;
|
|
30520
|
+
}
|
|
30521
|
+
const pos = flatIndex + this.skip;
|
|
30522
|
+
const hasDetail = meta.hasDetailTemplate && !meta.isStacked;
|
|
30523
|
+
return {
|
|
30524
|
+
logicalRow: (hasDetail ? pos * 2 : pos) + meta.headerRows,
|
|
30525
|
+
logicalCol: colIndex + (hasDetail ? 1 : 0)
|
|
30526
|
+
};
|
|
30527
|
+
}
|
|
30528
|
+
updateStickyGroups(scrollTarget) {
|
|
30529
|
+
if (!this.hasStickyHeaders && !this.hasStickyFooters) {
|
|
30530
|
+
return;
|
|
30531
|
+
}
|
|
30532
|
+
if (this.suppressStickyUpdates) {
|
|
30533
|
+
return;
|
|
30534
|
+
}
|
|
30535
|
+
const containerEl = this.container?.nativeElement;
|
|
30536
|
+
if (!containerEl) {
|
|
30537
|
+
return;
|
|
30538
|
+
}
|
|
30539
|
+
// Get the tbody from the non-locked table
|
|
30540
|
+
const tableEl = this.table?.nativeElement;
|
|
30541
|
+
const tbody = tableEl?.querySelector('tbody');
|
|
30542
|
+
if (!tbody) {
|
|
30543
|
+
return;
|
|
30544
|
+
}
|
|
30545
|
+
const stickyHeaderEl = this.stickyHeaderContainer?.nativeElement || null;
|
|
30546
|
+
const stickyFooterEl = this.stickyFooterContainer?.nativeElement || null;
|
|
30547
|
+
this.stickyGroupsService.update({
|
|
30548
|
+
container: containerEl,
|
|
30549
|
+
tbody: tbody,
|
|
30550
|
+
flatData: this.allItems,
|
|
30551
|
+
stickyHeaderEl: stickyHeaderEl,
|
|
30552
|
+
stickyFooterEl: stickyFooterEl,
|
|
30553
|
+
enableHeaders: this.hasStickyHeaders,
|
|
30554
|
+
enableFooters: this.hasStickyFooters,
|
|
30555
|
+
rowHeight: this.rowHeight,
|
|
30556
|
+
skipOffset: this.isVirtual ? this.scroller?.virtualSkip : 0,
|
|
30557
|
+
rowHeightService: this.isVirtual ? this.rowHeightService : undefined
|
|
30558
|
+
});
|
|
30559
|
+
// Sync horizontal scroll for sticky containers
|
|
30560
|
+
if (scrollTarget) {
|
|
30561
|
+
const scrollLeft = scrollTarget.scrollLeft;
|
|
30562
|
+
if (stickyHeaderEl) {
|
|
30563
|
+
const scrollableWrapper = stickyHeaderEl.querySelector('.k-grid-header-wrap');
|
|
30564
|
+
if (scrollableWrapper) {
|
|
30565
|
+
scrollableWrapper.scrollLeft = scrollLeft;
|
|
30566
|
+
}
|
|
30567
|
+
}
|
|
30568
|
+
if (stickyFooterEl) {
|
|
30569
|
+
const scrollableWrapper = stickyFooterEl.querySelector('.k-grid-footer-wrap');
|
|
30570
|
+
if (scrollableWrapper) {
|
|
30571
|
+
scrollableWrapper.scrollLeft = scrollLeft;
|
|
30572
|
+
}
|
|
30573
|
+
}
|
|
30574
|
+
}
|
|
30575
|
+
}
|
|
28153
30576
|
resetNavigationViewport() {
|
|
28154
30577
|
if (!isDocumentAvailable()) {
|
|
28155
30578
|
return;
|
|
@@ -28204,6 +30627,7 @@ class ListComponent {
|
|
|
28204
30627
|
if (this.virtualColumns || this.isVirtual) {
|
|
28205
30628
|
this.handleColumnScroll();
|
|
28206
30629
|
}
|
|
30630
|
+
this.updateStickyGroups(target);
|
|
28207
30631
|
const rowViewport = this.navigationService.viewport || EMPTY_OBJECT;
|
|
28208
30632
|
const columnViewport = this.navigationService.columnViewport || EMPTY_OBJECT;
|
|
28209
30633
|
this.contentScroll.emit({
|
|
@@ -28252,7 +30676,7 @@ class ListComponent {
|
|
|
28252
30676
|
if (this.lockedContainer) {
|
|
28253
30677
|
this.lockedContainer.nativeElement.scrollTop = scrollTop;
|
|
28254
30678
|
}
|
|
28255
|
-
// Sync translateY offset during rapid scrolling with virtual
|
|
30679
|
+
// Sync translateY offset during rapid scrolling with virtual paging to prevent blank grid.
|
|
28256
30680
|
if (this.isVirtual && this.ctx.grid?.pageable && this.scroller.rowHeightService) {
|
|
28257
30681
|
const expectedFirstIndex = this.scroller.rowHeightService.index(scrollTop);
|
|
28258
30682
|
const expectedOffset = this.scroller.rowHeightService.offset(expectedFirstIndex);
|
|
@@ -28308,9 +30732,22 @@ class ListComponent {
|
|
|
28308
30732
|
itemIndex = Math.floor(itemIndex / 2);
|
|
28309
30733
|
}
|
|
28310
30734
|
const offset = this.rowHeightService.offset(itemIndex);
|
|
28311
|
-
|
|
30735
|
+
const scrollTop = this.getStickyAdjustedScrollTop(offset);
|
|
30736
|
+
this.container.nativeElement.scrollTop = scrollTop;
|
|
28312
30737
|
this.scrollToIndex = itemIndex;
|
|
28313
30738
|
}
|
|
30739
|
+
getStickyAdjustedScrollTop(offset) {
|
|
30740
|
+
if (!this.hasStickyHeaders && !this.hasStickyFooters) {
|
|
30741
|
+
return offset;
|
|
30742
|
+
}
|
|
30743
|
+
const gridContainer = this.container?.nativeElement?.closest('.k-grid-container');
|
|
30744
|
+
const stickyHeaderEl = gridContainer
|
|
30745
|
+
?.querySelector('.k-grid-sticky-container:not(.k-pos-bottom)');
|
|
30746
|
+
if (!stickyHeaderEl?.offsetHeight) {
|
|
30747
|
+
return offset;
|
|
30748
|
+
}
|
|
30749
|
+
return Math.max(0, offset - stickyHeaderEl.offsetHeight);
|
|
30750
|
+
}
|
|
28314
30751
|
scrollTo({ row, column }, adjustIndex = false) {
|
|
28315
30752
|
if (isNumber(row)) {
|
|
28316
30753
|
if (this.isVirtual) {
|
|
@@ -28476,13 +30913,29 @@ class ListComponent {
|
|
|
28476
30913
|
this.scroller.scrollHeightContainer = this.container.nativeElement.querySelector('.k-height-container');
|
|
28477
30914
|
this.scroller.total = this.isVirtual && !this.ctx.grid?.pageable ? this.total : this.allItems.length;
|
|
28478
30915
|
}
|
|
28479
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: ListComponent, deps: [{ token: SCROLLER_FACTORY_TOKEN }, { token: DetailsService }, { token: ChangeNotificationService }, { token: SuspendService }, { token: GroupsService }, { token: i0.NgZone }, { token: i0.Renderer2 }, { token: ScrollSyncService }, { token: ResizeService }, { token: EditService }, { token: i1$3.ScrollbarService }, { token: NavigationService }, { token: ScrollRequestService }, { token: ContextService }, { token: ColumnResizingService }, { token: i0.ChangeDetectorRef }, { token: PDFService }, { token: ColumnInfoService }, { token: DataMappingService }], target: i0.ɵɵFactoryTarget.Component });
|
|
30916
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: ListComponent, deps: [{ token: SCROLLER_FACTORY_TOKEN }, { token: DetailsService }, { token: ChangeNotificationService }, { token: SuspendService }, { token: GroupsService }, { token: i0.NgZone }, { token: i0.Renderer2 }, { token: ScrollSyncService }, { token: ResizeService }, { token: EditService }, { token: i1$3.ScrollbarService }, { token: NavigationService }, { token: ScrollRequestService }, { token: ContextService }, { token: ColumnResizingService }, { token: i0.ChangeDetectorRef }, { token: PDFService }, { token: ColumnInfoService }, { token: DataMappingService }, { token: StickyGroupsService }], target: i0.ɵɵFactoryTarget.Component });
|
|
28480
30917
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.20", type: ListComponent, isStandalone: true, selector: "kendo-grid-list", inputs: { data: "data", groups: "groups", total: "total", rowHeight: "rowHeight", detailRowHeight: "detailRowHeight", take: "take", skip: "skip", columns: "columns", detailTemplate: "detailTemplate", noRecordsTemplate: "noRecordsTemplate", selectable: "selectable", groupable: "groupable", filterable: "filterable", rowClass: "rowClass", rowSticky: "rowSticky", loading: "loading", trackBy: "trackBy", virtualColumns: "virtualColumns", isVirtual: "isVirtual", cellLoadingTemplate: "cellLoadingTemplate", loadingTemplate: "loadingTemplate", sort: "sort", size: "size" }, outputs: { contentScroll: "contentScroll", pageChange: "pageChange", scrollBottom: "scrollBottom" }, host: { properties: { "class.k-grid-container": "this.hostClass", "attr.role": "this.hostRole" } }, providers: [
|
|
28481
30918
|
{
|
|
28482
30919
|
provide: SCROLLER_FACTORY_TOKEN,
|
|
28483
30920
|
useValue: DEFAULT_SCROLLER_FACTORY
|
|
28484
30921
|
}
|
|
28485
|
-
], viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true, static: true }, { propertyName: "lockedContainer", first: true, predicate: ["lockedContainer"], descendants: true }, { propertyName: "lockedTable", first: true, predicate: ["lockedTable"], descendants: true }, { propertyName: "table", first: true, predicate: ["table"], descendants: true, static: true }, { propertyName: "resizeSensors", predicate: ResizeSensorComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: `
|
|
30922
|
+
], viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true, static: true }, { propertyName: "lockedContainer", first: true, predicate: ["lockedContainer"], descendants: true }, { propertyName: "lockedTable", first: true, predicate: ["lockedTable"], descendants: true }, { propertyName: "table", first: true, predicate: ["table"], descendants: true, static: true }, { propertyName: "stickyHeaderContainer", first: true, predicate: ["stickyHeaderContainer"], descendants: true, read: StickyGroupContainerComponent }, { propertyName: "stickyFooterContainer", first: true, predicate: ["stickyFooterContainer"], descendants: true, read: StickyGroupContainerComponent }, { propertyName: "resizeSensors", predicate: ResizeSensorComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: `
|
|
30923
|
+
@if (hasStickyHeaders) {
|
|
30924
|
+
<div kendoGridStickyGroupContainer
|
|
30925
|
+
#stickyHeaderContainer
|
|
30926
|
+
position="top"
|
|
30927
|
+
[columns]="$any(nonLockedLeafColumns)"
|
|
30928
|
+
[lockedColumns]="$any(lockedLeafColumns)"
|
|
30929
|
+
[groups]="groups"
|
|
30930
|
+
[detailTemplate]="detailTemplate"
|
|
30931
|
+
[totalColumnsCount]="leafColumns.length"
|
|
30932
|
+
[hasGroupHeaderColumn]="columns.hasGroupHeaderColumn"
|
|
30933
|
+
[groupHeaderColumns]="stickyGroupHeaderColumns"
|
|
30934
|
+
[tableWidth]="nonLockedWidth"
|
|
30935
|
+
[lockedWidth]="lockedWidth"
|
|
30936
|
+
[isLocked]="isLocked">
|
|
30937
|
+
</div>
|
|
30938
|
+
}
|
|
28486
30939
|
@if (isLocked && !isStacked) {
|
|
28487
30940
|
<div #lockedContainer class="k-grid-content-locked" role="presentation"
|
|
28488
30941
|
[style.width.px]="lockedWidth" tabindex="-1"
|
|
@@ -28608,7 +31061,23 @@ class ListComponent {
|
|
|
28608
31061
|
</div>
|
|
28609
31062
|
}
|
|
28610
31063
|
</div>
|
|
28611
|
-
|
|
31064
|
+
@if (hasStickyFooters) {
|
|
31065
|
+
<div kendoGridStickyGroupContainer
|
|
31066
|
+
#stickyFooterContainer
|
|
31067
|
+
position="bottom"
|
|
31068
|
+
[columns]="$any(nonLockedLeafColumns)"
|
|
31069
|
+
[lockedColumns]="$any(lockedLeafColumns)"
|
|
31070
|
+
[groups]="groups"
|
|
31071
|
+
[detailTemplate]="detailTemplate"
|
|
31072
|
+
[totalColumnsCount]="leafColumns.length"
|
|
31073
|
+
[hasGroupHeaderColumn]="columns.hasGroupHeaderColumn"
|
|
31074
|
+
[groupHeaderColumns]="stickyGroupHeaderColumns"
|
|
31075
|
+
[tableWidth]="nonLockedWidth"
|
|
31076
|
+
[lockedWidth]="lockedWidth"
|
|
31077
|
+
[isLocked]="isLocked">
|
|
31078
|
+
</div>
|
|
31079
|
+
}
|
|
31080
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: EventsOutsideAngularDirective, selector: "[kendoEventsOutsideAngular]", inputs: ["kendoEventsOutsideAngular", "scope"] }, { kind: "directive", type: TableDirective, selector: "[kendoGridResizableTable]", inputs: ["locked", "virtualColumns"] }, { kind: "directive", type: GridTableDirective, selector: "[kendoGridTable]", inputs: ["size"] }, { kind: "component", type: ColGroupComponent, selector: "[kendoGridColGroup]", inputs: ["columns", "groups", "detailTemplate", "sort"] }, { kind: "component", type: TableBodyComponent, selector: "[kendoGridTableBody]", inputs: ["columns", "allColumns", "groups", "detailTemplate", "noRecordsTemplate", "rowsToRender", "skip", "selectable", "filterable", "noRecordsText", "isLocked", "isLoading", "isVirtual", "cellLoadingTemplate", "skipGroupDecoration", "lockedColumnsCount", "totalColumnsCount", "virtualColumns", "trackBy", "rowSticky", "totalColumns", "rowClass", "rowHeight", "detailRowHeight", "isPinContainer", "pinPosition"] }, { kind: "component", type: ResizeSensorComponent, selector: "kendo-resize-sensor", inputs: ["rateLimit"], outputs: ["resize"] }, { kind: "directive", type: ResizableContainerDirective, selector: "[kendoGridResizableContainer]", inputs: ["lockedWidth", "kendoGridResizableContainer"] }, { kind: "component", type: StickyGroupContainerComponent, selector: "[kendoGridStickyGroupContainer]", inputs: ["position", "columns", "lockedColumns", "groups", "detailTemplate", "totalColumnsCount", "hasGroupHeaderColumn", "groupHeaderColumns", "tableWidth", "lockedWidth", "isLocked"] }] });
|
|
28612
31081
|
}
|
|
28613
31082
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: ListComponent, decorators: [{
|
|
28614
31083
|
type: Component,
|
|
@@ -28621,6 +31090,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
28621
31090
|
],
|
|
28622
31091
|
selector: 'kendo-grid-list',
|
|
28623
31092
|
template: `
|
|
31093
|
+
@if (hasStickyHeaders) {
|
|
31094
|
+
<div kendoGridStickyGroupContainer
|
|
31095
|
+
#stickyHeaderContainer
|
|
31096
|
+
position="top"
|
|
31097
|
+
[columns]="$any(nonLockedLeafColumns)"
|
|
31098
|
+
[lockedColumns]="$any(lockedLeafColumns)"
|
|
31099
|
+
[groups]="groups"
|
|
31100
|
+
[detailTemplate]="detailTemplate"
|
|
31101
|
+
[totalColumnsCount]="leafColumns.length"
|
|
31102
|
+
[hasGroupHeaderColumn]="columns.hasGroupHeaderColumn"
|
|
31103
|
+
[groupHeaderColumns]="stickyGroupHeaderColumns"
|
|
31104
|
+
[tableWidth]="nonLockedWidth"
|
|
31105
|
+
[lockedWidth]="lockedWidth"
|
|
31106
|
+
[isLocked]="isLocked">
|
|
31107
|
+
</div>
|
|
31108
|
+
}
|
|
28624
31109
|
@if (isLocked && !isStacked) {
|
|
28625
31110
|
<div #lockedContainer class="k-grid-content-locked" role="presentation"
|
|
28626
31111
|
[style.width.px]="lockedWidth" tabindex="-1"
|
|
@@ -28746,14 +31231,30 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
28746
31231
|
</div>
|
|
28747
31232
|
}
|
|
28748
31233
|
</div>
|
|
31234
|
+
@if (hasStickyFooters) {
|
|
31235
|
+
<div kendoGridStickyGroupContainer
|
|
31236
|
+
#stickyFooterContainer
|
|
31237
|
+
position="bottom"
|
|
31238
|
+
[columns]="$any(nonLockedLeafColumns)"
|
|
31239
|
+
[lockedColumns]="$any(lockedLeafColumns)"
|
|
31240
|
+
[groups]="groups"
|
|
31241
|
+
[detailTemplate]="detailTemplate"
|
|
31242
|
+
[totalColumnsCount]="leafColumns.length"
|
|
31243
|
+
[hasGroupHeaderColumn]="columns.hasGroupHeaderColumn"
|
|
31244
|
+
[groupHeaderColumns]="stickyGroupHeaderColumns"
|
|
31245
|
+
[tableWidth]="nonLockedWidth"
|
|
31246
|
+
[lockedWidth]="lockedWidth"
|
|
31247
|
+
[isLocked]="isLocked">
|
|
31248
|
+
</div>
|
|
31249
|
+
}
|
|
28749
31250
|
`,
|
|
28750
31251
|
standalone: true,
|
|
28751
|
-
imports: [EventsOutsideAngularDirective, TableDirective, GridTableDirective, ColGroupComponent, TableBodyComponent, ResizeSensorComponent, ResizableContainerDirective]
|
|
31252
|
+
imports: [EventsOutsideAngularDirective, TableDirective, GridTableDirective, ColGroupComponent, TableBodyComponent, ResizeSensorComponent, ResizableContainerDirective, StickyGroupContainerComponent]
|
|
28752
31253
|
}]
|
|
28753
31254
|
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
28754
31255
|
type: Inject,
|
|
28755
31256
|
args: [SCROLLER_FACTORY_TOKEN]
|
|
28756
|
-
}] }, { type: DetailsService }, { type: ChangeNotificationService }, { type: SuspendService }, { type: GroupsService }, { type: i0.NgZone }, { type: i0.Renderer2 }, { type: ScrollSyncService }, { type: ResizeService }, { type: EditService }, { type: i1$3.ScrollbarService }, { type: NavigationService }, { type: ScrollRequestService }, { type: ContextService }, { type: ColumnResizingService }, { type: i0.ChangeDetectorRef }, { type: PDFService }, { type: ColumnInfoService }, { type: DataMappingService }], propDecorators: { hostClass: [{
|
|
31257
|
+
}] }, { type: DetailsService }, { type: ChangeNotificationService }, { type: SuspendService }, { type: GroupsService }, { type: i0.NgZone }, { type: i0.Renderer2 }, { type: ScrollSyncService }, { type: ResizeService }, { type: EditService }, { type: i1$3.ScrollbarService }, { type: NavigationService }, { type: ScrollRequestService }, { type: ContextService }, { type: ColumnResizingService }, { type: i0.ChangeDetectorRef }, { type: PDFService }, { type: ColumnInfoService }, { type: DataMappingService }, { type: StickyGroupsService }], propDecorators: { hostClass: [{
|
|
28757
31258
|
type: HostBinding,
|
|
28758
31259
|
args: ['class.k-grid-container']
|
|
28759
31260
|
}], hostRole: [{
|
|
@@ -28826,6 +31327,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
28826
31327
|
}], resizeSensors: [{
|
|
28827
31328
|
type: ViewChildren,
|
|
28828
31329
|
args: [ResizeSensorComponent]
|
|
31330
|
+
}], stickyHeaderContainer: [{
|
|
31331
|
+
type: ViewChild,
|
|
31332
|
+
args: ['stickyHeaderContainer', { read: StickyGroupContainerComponent }]
|
|
31333
|
+
}], stickyFooterContainer: [{
|
|
31334
|
+
type: ViewChild,
|
|
31335
|
+
args: ['stickyFooterContainer', { read: StickyGroupContainerComponent }]
|
|
28829
31336
|
}] } });
|
|
28830
31337
|
|
|
28831
31338
|
/**
|
|
@@ -29699,8 +32206,16 @@ class GridMessages extends ComponentMessages {
|
|
|
29699
32206
|
* Sets the screen-reader-only content for the pin column header.
|
|
29700
32207
|
*/
|
|
29701
32208
|
pinColumnHeaderLabel;
|
|
32209
|
+
/**
|
|
32210
|
+
* Sets the label for the Grid row pin column icon.
|
|
32211
|
+
*/
|
|
32212
|
+
rowPinLabel;
|
|
32213
|
+
/**
|
|
32214
|
+
* Sets the label for the Grid row unpin column icon.
|
|
32215
|
+
*/
|
|
32216
|
+
rowUnpinLabel;
|
|
29702
32217
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: GridMessages, deps: null, target: i0.ɵɵFactoryTarget.Directive });
|
|
29703
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.20", type: GridMessages, isStandalone: true, selector: "kendo-grid-messages-base", inputs: { groupPanelEmpty: "groupPanelEmpty", noRecords: "noRecords", pagerLabel: "pagerLabel", pagerFirstPage: "pagerFirstPage", pagerLastPage: "pagerLastPage", pagerPreviousPage: "pagerPreviousPage", pagerNextPage: "pagerNextPage", pagerPage: "pagerPage", pagerItemsPerPage: "pagerItemsPerPage", pagerOf: "pagerOf", pagerItems: "pagerItems", pagerPageNumberInputTitle: "pagerPageNumberInputTitle", pagerInputLabel: "pagerInputLabel", pagerSelectPage: "pagerSelectPage", filter: "filter", filterInputLabel: "filterInputLabel", filterMenuTitle: "filterMenuTitle", filterMenuOperatorsDropDownLabel: "filterMenuOperatorsDropDownLabel", filterMenuLogicDropDownLabel: "filterMenuLogicDropDownLabel", filterCellOperatorLabel: "filterCellOperatorLabel", booleanFilterCellLabel: "booleanFilterCellLabel", aiAssistantApplyButtonText: "aiAssistantApplyButtonText", aiAssistantToolbarToolText: "aiAssistantToolbarToolText", aiAssistantWindowTitle: "aiAssistantWindowTitle", aiAssistantWindowCloseTitle: "aiAssistantWindowCloseTitle", aiAssistantOutputCardTitle: "aiAssistantOutputCardTitle", aiAssistantOutputCardBodyContent: "aiAssistantOutputCardBodyContent", aiAssistantSelectionNotEnabled: "aiAssistantSelectionNotEnabled", aiAssistantSelectionRowModeRequired: "aiAssistantSelectionRowModeRequired", aiAssistantSelectionCellModeRequired: "aiAssistantSelectionCellModeRequired", aiAssistantWindowMaximizeTitle: "aiAssistantWindowMaximizeTitle", aiAssistantWindowMinimizeTitle: "aiAssistantWindowMinimizeTitle", aiAssistantWindowRestoreTitle: "aiAssistantWindowRestoreTitle", filterEqOperator: "filterEqOperator", filterNotEqOperator: "filterNotEqOperator", filterIsNullOperator: "filterIsNullOperator", filterIsNotNullOperator: "filterIsNotNullOperator", filterIsEmptyOperator: "filterIsEmptyOperator", filterIsNotEmptyOperator: "filterIsNotEmptyOperator", filterStartsWithOperator: "filterStartsWithOperator", filterContainsOperator: "filterContainsOperator", filterNotContainsOperator: "filterNotContainsOperator", filterEndsWithOperator: "filterEndsWithOperator", filterGteOperator: "filterGteOperator", filterGtOperator: "filterGtOperator", filterLteOperator: "filterLteOperator", filterLtOperator: "filterLtOperator", filterIsTrue: "filterIsTrue", filterIsFalse: "filterIsFalse", filterBooleanAll: "filterBooleanAll", adaptiveFilterOperatorsTitle: "adaptiveFilterOperatorsTitle", filterAfterOrEqualOperator: "filterAfterOrEqualOperator", filterAfterOperator: "filterAfterOperator", filterBeforeOperator: "filterBeforeOperator", filterBeforeOrEqualOperator: "filterBeforeOrEqualOperator", filterFilterButton: "filterFilterButton", filterClearButton: "filterClearButton", adaptiveCloseButtonTitle: "adaptiveCloseButtonTitle", adaptiveBackButtonTitle: "adaptiveBackButtonTitle", filterAndLogic: "filterAndLogic", filterOrLogic: "filterOrLogic", filterToolbarToolText: "filterToolbarToolText", loading: "loading", gridLabel: "gridLabel", columnMenu: "columnMenu", setColumnPosition: "setColumnPosition", columns: "columns", columnChooserSelectAll: "columnChooserSelectAll", columnChooserSearchLabel: "columnChooserSearchLabel", columnChooserSelectedColumnsCount: "columnChooserSelectedColumnsCount", columnsSubtitle: "columnsSubtitle", adaptiveFilterTitle: "adaptiveFilterTitle", adaptiveSortTitle: "adaptiveSortTitle", adaptiveGroupTitle: "adaptiveGroupTitle", filterClearAllButton: "filterClearAllButton", groupClearButton: "groupClearButton", sortClearButton: "sortClearButton", sortDoneButton: "sortDoneButton", groupDoneButton: "groupDoneButton", lock: "lock", unlock: "unlock", stick: "stick", unstick: "unstick", sortable: "sortable", sortAscending: "sortAscending", sortDescending: "sortDescending", autosizeThisColumn: "autosizeThisColumn", autosizeAllColumns: "autosizeAllColumns", sortedAscending: "sortedAscending", sortedDescending: "sortedDescending", sortedDefault: "sortedDefault", sortToolbarToolText: "sortToolbarToolText", columnsApply: "columnsApply", columnsReset: "columnsReset", detailExpand: "detailExpand", detailCollapse: "detailCollapse", filterDateToday: "filterDateToday", filterDateToggle: "filterDateToggle", filterNumericDecrement: "filterNumericDecrement", filterNumericIncrement: "filterNumericIncrement", selectionCheckboxLabel: "selectionCheckboxLabel", selectAllCheckboxLabel: "selectAllCheckboxLabel", checkboxColumnHeaderLabel: "checkboxColumnHeaderLabel", groupCollapse: "groupCollapse", groupExpand: "groupExpand", topToolbarLabel: "topToolbarLabel", bottomToolbarLabel: "bottomToolbarLabel", editToolbarToolText: "editToolbarToolText", saveToolbarToolText: "saveToolbarToolText", addToolbarToolText: "addToolbarToolText", cancelToolbarToolText: "cancelToolbarToolText", removeToolbarToolText: "removeToolbarToolText", excelExportToolbarToolText: "excelExportToolbarToolText", csvExportToolbarToolText: "csvExportToolbarToolText", pdfExportToolbarToolText: "pdfExportToolbarToolText", groupPanelLabel: "groupPanelLabel", dragRowHandleLabel: "dragRowHandleLabel", columnMenuFilterTabTitle: "columnMenuFilterTabTitle", columnMenuGeneralTabTitle: "columnMenuGeneralTabTitle", columnMenuColumnsTabTitle: "columnMenuColumnsTabTitle", groupChipMenuPrevious: "groupChipMenuPrevious", groupChipMenuNext: "groupChipMenuNext", groupToolbarToolText: "groupToolbarToolText", formValidationErrorText: "formValidationErrorText", removeConfirmationDialogTitle: "removeConfirmationDialogTitle", removeConfirmationDialogContent: "removeConfirmationDialogContent", removeConfirmationDialogConfirmText: "removeConfirmationDialogConfirmText", removeConfirmationDialogRejectText: "removeConfirmationDialogRejectText", externalEditingTitle: "externalEditingTitle", externalEditingAddTitle: "externalEditingAddTitle", externalEditingSaveText: "externalEditingSaveText", externalEditingCancelText: "externalEditingCancelText", multiCheckboxFilterSearchPlaceholder: "multiCheckboxFilterSearchPlaceholder", multiCheckboxFilterSelectAllLabel: "multiCheckboxFilterSelectAllLabel", multiCheckboxFilterSelectedItemsCount: "multiCheckboxFilterSelectedItemsCount", smartBoxSpeechToTextButton: "smartBoxSpeechToTextButton", smartBoxSubmitPromptButton: "smartBoxSubmitPromptButton", smartBoxSearchPlaceholder: "smartBoxSearchPlaceholder", smartBoxSemanticSearchPlaceholder: "smartBoxSemanticSearchPlaceholder", smartBoxAIAssistantPlaceholder: "smartBoxAIAssistantPlaceholder", smartBoxSuggestedPrompts: "smartBoxSuggestedPrompts", smartBoxNoPreviousSearches: "smartBoxNoPreviousSearches", smartBoxNoPreviousPrompts: "smartBoxNoPreviousPrompts", smartBoxPreviouslySearched: "smartBoxPreviouslySearched", smartBoxPreviouslyAsked: "smartBoxPreviouslyAsked", searchModeListItemText: "searchModeListItemText", searchModeListItemDescription: "searchModeListItemDescription", semanticSearchModeListItemText: "semanticSearchModeListItemText", semanticSearchModeListItemDescription: "semanticSearchModeListItemDescription", smartBoxSearchModePopupButton: "smartBoxSearchModePopupButton", smartBoxAIAssistantModePopupButton: "smartBoxAIAssistantModePopupButton", detailColumnHeaderLabel: "detailColumnHeaderLabel", dragColumnHeaderLabel: "dragColumnHeaderLabel", commandColumnHeaderLabel: "commandColumnHeaderLabel", pinnedTopRowsLabel: "pinnedTopRowsLabel", pinnedBottomRowsLabel: "pinnedBottomRowsLabel", pinMenuPinToTopText: "pinMenuPinToTopText", pinMenuPinToBottomText: "pinMenuPinToBottomText", pinMenuUnpinText: "pinMenuUnpinText", pinColumnHeaderLabel: "pinColumnHeaderLabel" }, usesInheritance: true, ngImport: i0 });
|
|
32218
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.20", type: GridMessages, isStandalone: true, selector: "kendo-grid-messages-base", inputs: { groupPanelEmpty: "groupPanelEmpty", noRecords: "noRecords", pagerLabel: "pagerLabel", pagerFirstPage: "pagerFirstPage", pagerLastPage: "pagerLastPage", pagerPreviousPage: "pagerPreviousPage", pagerNextPage: "pagerNextPage", pagerPage: "pagerPage", pagerItemsPerPage: "pagerItemsPerPage", pagerOf: "pagerOf", pagerItems: "pagerItems", pagerPageNumberInputTitle: "pagerPageNumberInputTitle", pagerInputLabel: "pagerInputLabel", pagerSelectPage: "pagerSelectPage", filter: "filter", filterInputLabel: "filterInputLabel", filterMenuTitle: "filterMenuTitle", filterMenuOperatorsDropDownLabel: "filterMenuOperatorsDropDownLabel", filterMenuLogicDropDownLabel: "filterMenuLogicDropDownLabel", filterCellOperatorLabel: "filterCellOperatorLabel", booleanFilterCellLabel: "booleanFilterCellLabel", aiAssistantApplyButtonText: "aiAssistantApplyButtonText", aiAssistantToolbarToolText: "aiAssistantToolbarToolText", aiAssistantWindowTitle: "aiAssistantWindowTitle", aiAssistantWindowCloseTitle: "aiAssistantWindowCloseTitle", aiAssistantOutputCardTitle: "aiAssistantOutputCardTitle", aiAssistantOutputCardBodyContent: "aiAssistantOutputCardBodyContent", aiAssistantSelectionNotEnabled: "aiAssistantSelectionNotEnabled", aiAssistantSelectionRowModeRequired: "aiAssistantSelectionRowModeRequired", aiAssistantSelectionCellModeRequired: "aiAssistantSelectionCellModeRequired", aiAssistantWindowMaximizeTitle: "aiAssistantWindowMaximizeTitle", aiAssistantWindowMinimizeTitle: "aiAssistantWindowMinimizeTitle", aiAssistantWindowRestoreTitle: "aiAssistantWindowRestoreTitle", filterEqOperator: "filterEqOperator", filterNotEqOperator: "filterNotEqOperator", filterIsNullOperator: "filterIsNullOperator", filterIsNotNullOperator: "filterIsNotNullOperator", filterIsEmptyOperator: "filterIsEmptyOperator", filterIsNotEmptyOperator: "filterIsNotEmptyOperator", filterStartsWithOperator: "filterStartsWithOperator", filterContainsOperator: "filterContainsOperator", filterNotContainsOperator: "filterNotContainsOperator", filterEndsWithOperator: "filterEndsWithOperator", filterGteOperator: "filterGteOperator", filterGtOperator: "filterGtOperator", filterLteOperator: "filterLteOperator", filterLtOperator: "filterLtOperator", filterIsTrue: "filterIsTrue", filterIsFalse: "filterIsFalse", filterBooleanAll: "filterBooleanAll", adaptiveFilterOperatorsTitle: "adaptiveFilterOperatorsTitle", filterAfterOrEqualOperator: "filterAfterOrEqualOperator", filterAfterOperator: "filterAfterOperator", filterBeforeOperator: "filterBeforeOperator", filterBeforeOrEqualOperator: "filterBeforeOrEqualOperator", filterFilterButton: "filterFilterButton", filterClearButton: "filterClearButton", adaptiveCloseButtonTitle: "adaptiveCloseButtonTitle", adaptiveBackButtonTitle: "adaptiveBackButtonTitle", filterAndLogic: "filterAndLogic", filterOrLogic: "filterOrLogic", filterToolbarToolText: "filterToolbarToolText", loading: "loading", gridLabel: "gridLabel", columnMenu: "columnMenu", setColumnPosition: "setColumnPosition", columns: "columns", columnChooserSelectAll: "columnChooserSelectAll", columnChooserSearchLabel: "columnChooserSearchLabel", columnChooserSelectedColumnsCount: "columnChooserSelectedColumnsCount", columnsSubtitle: "columnsSubtitle", adaptiveFilterTitle: "adaptiveFilterTitle", adaptiveSortTitle: "adaptiveSortTitle", adaptiveGroupTitle: "adaptiveGroupTitle", filterClearAllButton: "filterClearAllButton", groupClearButton: "groupClearButton", sortClearButton: "sortClearButton", sortDoneButton: "sortDoneButton", groupDoneButton: "groupDoneButton", lock: "lock", unlock: "unlock", stick: "stick", unstick: "unstick", sortable: "sortable", sortAscending: "sortAscending", sortDescending: "sortDescending", autosizeThisColumn: "autosizeThisColumn", autosizeAllColumns: "autosizeAllColumns", sortedAscending: "sortedAscending", sortedDescending: "sortedDescending", sortedDefault: "sortedDefault", sortToolbarToolText: "sortToolbarToolText", columnsApply: "columnsApply", columnsReset: "columnsReset", detailExpand: "detailExpand", detailCollapse: "detailCollapse", filterDateToday: "filterDateToday", filterDateToggle: "filterDateToggle", filterNumericDecrement: "filterNumericDecrement", filterNumericIncrement: "filterNumericIncrement", selectionCheckboxLabel: "selectionCheckboxLabel", selectAllCheckboxLabel: "selectAllCheckboxLabel", checkboxColumnHeaderLabel: "checkboxColumnHeaderLabel", groupCollapse: "groupCollapse", groupExpand: "groupExpand", topToolbarLabel: "topToolbarLabel", bottomToolbarLabel: "bottomToolbarLabel", editToolbarToolText: "editToolbarToolText", saveToolbarToolText: "saveToolbarToolText", addToolbarToolText: "addToolbarToolText", cancelToolbarToolText: "cancelToolbarToolText", removeToolbarToolText: "removeToolbarToolText", excelExportToolbarToolText: "excelExportToolbarToolText", csvExportToolbarToolText: "csvExportToolbarToolText", pdfExportToolbarToolText: "pdfExportToolbarToolText", groupPanelLabel: "groupPanelLabel", dragRowHandleLabel: "dragRowHandleLabel", columnMenuFilterTabTitle: "columnMenuFilterTabTitle", columnMenuGeneralTabTitle: "columnMenuGeneralTabTitle", columnMenuColumnsTabTitle: "columnMenuColumnsTabTitle", groupChipMenuPrevious: "groupChipMenuPrevious", groupChipMenuNext: "groupChipMenuNext", groupToolbarToolText: "groupToolbarToolText", formValidationErrorText: "formValidationErrorText", removeConfirmationDialogTitle: "removeConfirmationDialogTitle", removeConfirmationDialogContent: "removeConfirmationDialogContent", removeConfirmationDialogConfirmText: "removeConfirmationDialogConfirmText", removeConfirmationDialogRejectText: "removeConfirmationDialogRejectText", externalEditingTitle: "externalEditingTitle", externalEditingAddTitle: "externalEditingAddTitle", externalEditingSaveText: "externalEditingSaveText", externalEditingCancelText: "externalEditingCancelText", multiCheckboxFilterSearchPlaceholder: "multiCheckboxFilterSearchPlaceholder", multiCheckboxFilterSelectAllLabel: "multiCheckboxFilterSelectAllLabel", multiCheckboxFilterSelectedItemsCount: "multiCheckboxFilterSelectedItemsCount", smartBoxSpeechToTextButton: "smartBoxSpeechToTextButton", smartBoxSubmitPromptButton: "smartBoxSubmitPromptButton", smartBoxSearchPlaceholder: "smartBoxSearchPlaceholder", smartBoxSemanticSearchPlaceholder: "smartBoxSemanticSearchPlaceholder", smartBoxAIAssistantPlaceholder: "smartBoxAIAssistantPlaceholder", smartBoxSuggestedPrompts: "smartBoxSuggestedPrompts", smartBoxNoPreviousSearches: "smartBoxNoPreviousSearches", smartBoxNoPreviousPrompts: "smartBoxNoPreviousPrompts", smartBoxPreviouslySearched: "smartBoxPreviouslySearched", smartBoxPreviouslyAsked: "smartBoxPreviouslyAsked", searchModeListItemText: "searchModeListItemText", searchModeListItemDescription: "searchModeListItemDescription", semanticSearchModeListItemText: "semanticSearchModeListItemText", semanticSearchModeListItemDescription: "semanticSearchModeListItemDescription", smartBoxSearchModePopupButton: "smartBoxSearchModePopupButton", smartBoxAIAssistantModePopupButton: "smartBoxAIAssistantModePopupButton", detailColumnHeaderLabel: "detailColumnHeaderLabel", dragColumnHeaderLabel: "dragColumnHeaderLabel", commandColumnHeaderLabel: "commandColumnHeaderLabel", pinnedTopRowsLabel: "pinnedTopRowsLabel", pinnedBottomRowsLabel: "pinnedBottomRowsLabel", pinMenuPinToTopText: "pinMenuPinToTopText", pinMenuPinToBottomText: "pinMenuPinToBottomText", pinMenuUnpinText: "pinMenuUnpinText", pinColumnHeaderLabel: "pinColumnHeaderLabel", rowPinLabel: "rowPinLabel", rowUnpinLabel: "rowUnpinLabel" }, usesInheritance: true, ngImport: i0 });
|
|
29704
32219
|
}
|
|
29705
32220
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: GridMessages, decorators: [{
|
|
29706
32221
|
type: Directive,
|
|
@@ -30027,6 +32542,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
30027
32542
|
type: Input
|
|
30028
32543
|
}], pinColumnHeaderLabel: [{
|
|
30029
32544
|
type: Input
|
|
32545
|
+
}], rowPinLabel: [{
|
|
32546
|
+
type: Input
|
|
32547
|
+
}], rowUnpinLabel: [{
|
|
32548
|
+
type: Input
|
|
30030
32549
|
}] } });
|
|
30031
32550
|
|
|
30032
32551
|
/**
|
|
@@ -32642,6 +35161,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
32642
35161
|
class RowPinContainerComponent {
|
|
32643
35162
|
localization;
|
|
32644
35163
|
pinnedWrapper;
|
|
35164
|
+
lockedTable;
|
|
35165
|
+
pinnedTable;
|
|
32645
35166
|
hostClass = true;
|
|
32646
35167
|
get bottomClass() {
|
|
32647
35168
|
return this.position === 'bottom';
|
|
@@ -32661,20 +35182,31 @@ class RowPinContainerComponent {
|
|
|
32661
35182
|
groups;
|
|
32662
35183
|
detailTemplate;
|
|
32663
35184
|
filterable;
|
|
35185
|
+
rowHeight;
|
|
35186
|
+
detailRowHeight;
|
|
35187
|
+
loading;
|
|
35188
|
+
size;
|
|
32664
35189
|
constructor(localization) {
|
|
32665
35190
|
this.localization = localization;
|
|
32666
35191
|
}
|
|
35192
|
+
ngAfterViewChecked() {
|
|
35193
|
+
if (this.isLocked && this.lockedTable && this.pinnedTable) {
|
|
35194
|
+
syncRowsHeight(this.lockedTable.nativeElement, this.pinnedTable.nativeElement);
|
|
35195
|
+
}
|
|
35196
|
+
}
|
|
32667
35197
|
get ariaLabel() {
|
|
32668
35198
|
const labelKey = this.position === 'top' ? 'pinnedTopRowsLabel' : 'pinnedBottomRowsLabel';
|
|
32669
35199
|
return this.localization.get(labelKey);
|
|
32670
35200
|
}
|
|
32671
35201
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: RowPinContainerComponent, deps: [{ token: i1$2.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
|
|
32672
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.20", type: RowPinContainerComponent, isStandalone: true, selector: "kendo-grid-rowpin-container", inputs: { leafColumns: "leafColumns", lockedLeafColumns: "lockedLeafColumns", nonLockedLeafColumns: "nonLockedLeafColumns", sort: "sort", position: "position", rowsToRender: "rowsToRender", totalColumns: "totalColumns", lockedWidth: "lockedWidth", nonLockedWidth: "nonLockedWidth", isLocked: "isLocked", selectable: "selectable", trackBy: "trackBy", groups: "groups", detailTemplate: "detailTemplate", filterable: "filterable" }, host: { properties: { "class.k-grid-pinned-container": "this.hostClass", "class.k-pos-bottom": "this.bottomClass" } }, providers: [{ provide: IS_PIN_CONTAINER, useValue: true }], viewQueries: [{ propertyName: "pinnedWrapper", first: true, predicate: ["pinnedWrapper"], descendants: true, static: true }], ngImport: i0, template: `
|
|
35202
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.20", type: RowPinContainerComponent, isStandalone: true, selector: "kendo-grid-rowpin-container", inputs: { leafColumns: "leafColumns", lockedLeafColumns: "lockedLeafColumns", nonLockedLeafColumns: "nonLockedLeafColumns", sort: "sort", position: "position", rowsToRender: "rowsToRender", totalColumns: "totalColumns", lockedWidth: "lockedWidth", nonLockedWidth: "nonLockedWidth", isLocked: "isLocked", selectable: "selectable", trackBy: "trackBy", groups: "groups", detailTemplate: "detailTemplate", filterable: "filterable", rowHeight: "rowHeight", detailRowHeight: "detailRowHeight", loading: "loading", size: "size" }, host: { properties: { "class.k-grid-pinned-container": "this.hostClass", "class.k-pos-bottom": "this.bottomClass" } }, providers: [{ provide: IS_PIN_CONTAINER, useValue: true }], viewQueries: [{ propertyName: "pinnedWrapper", first: true, predicate: ["pinnedWrapper"], descendants: true, static: true }, { propertyName: "lockedTable", first: true, predicate: ["lockedTable"], descendants: true }, { propertyName: "pinnedTable", first: true, predicate: ["pinnedTable"], descendants: true, static: true }], ngImport: i0, template: `
|
|
32673
35203
|
@if (isLocked) {
|
|
32674
35204
|
<div class="k-grid-content-locked" role="presentation" [style.width.px]="lockedWidth">
|
|
32675
|
-
<table class="k-grid-table"
|
|
35205
|
+
<table #lockedTable class="k-grid-table"
|
|
32676
35206
|
kendoGridTable
|
|
32677
35207
|
kendoGridResizableTable
|
|
35208
|
+
[locked]="true"
|
|
35209
|
+
[size]="size"
|
|
32678
35210
|
[style.width.px]="lockedWidth">
|
|
32679
35211
|
<colgroup kendoGridColGroup
|
|
32680
35212
|
[groups]="groups"
|
|
@@ -32687,7 +35219,7 @@ class RowPinContainerComponent {
|
|
|
32687
35219
|
[isLocked]="true"
|
|
32688
35220
|
[rowsToRender]="rowsToRender"
|
|
32689
35221
|
[columns]="$any(lockedLeafColumns)"
|
|
32690
|
-
[totalColumnsCount]="
|
|
35222
|
+
[totalColumnsCount]="leafColumns.length"
|
|
32691
35223
|
[totalColumns]="totalColumns"
|
|
32692
35224
|
[selectable]="selectable"
|
|
32693
35225
|
[trackBy]="trackBy"
|
|
@@ -32695,13 +35227,16 @@ class RowPinContainerComponent {
|
|
|
32695
35227
|
[pinPosition]="position"
|
|
32696
35228
|
[groups]="groups"
|
|
32697
35229
|
[detailTemplate]="detailTemplate"
|
|
32698
|
-
[filterable]="filterable"
|
|
35230
|
+
[filterable]="filterable"
|
|
35231
|
+
[rowHeight]="rowHeight"
|
|
35232
|
+
[detailRowHeight]="detailRowHeight"
|
|
35233
|
+
[isLoading]="loading">
|
|
32699
35234
|
</tbody>
|
|
32700
35235
|
</table>
|
|
32701
35236
|
</div>
|
|
32702
35237
|
}
|
|
32703
35238
|
<div #pinnedWrapper class="k-grid-pinned-wrap">
|
|
32704
|
-
<table class="k-grid-table"
|
|
35239
|
+
<table #pinnedTable class="k-grid-table"
|
|
32705
35240
|
kendoGridTable
|
|
32706
35241
|
kendoGridResizableTable
|
|
32707
35242
|
[style.width.px]="nonLockedWidth"
|
|
@@ -32709,11 +35244,12 @@ class RowPinContainerComponent {
|
|
|
32709
35244
|
<colgroup kendoGridColGroup
|
|
32710
35245
|
[columns]="$any(nonLockedLeafColumns)"
|
|
32711
35246
|
[sort]="sort"
|
|
32712
|
-
[groups]="groups"
|
|
35247
|
+
[groups]="isLocked ? [] : groups"
|
|
32713
35248
|
[detailTemplate]="detailTemplate">
|
|
32714
35249
|
</colgroup>
|
|
32715
35250
|
<tbody kendoGridTableBody
|
|
32716
35251
|
role="presentation"
|
|
35252
|
+
[skipGroupDecoration]="isLocked"
|
|
32717
35253
|
[rowsToRender]="rowsToRender"
|
|
32718
35254
|
[columns]="$any(nonLockedLeafColumns)"
|
|
32719
35255
|
[lockedColumnsCount]="isLocked ? lockedLeafColumns?.length : 0"
|
|
@@ -32725,7 +35261,9 @@ class RowPinContainerComponent {
|
|
|
32725
35261
|
[pinPosition]="position"
|
|
32726
35262
|
[groups]="groups"
|
|
32727
35263
|
[detailTemplate]="detailTemplate"
|
|
32728
|
-
[filterable]="filterable"
|
|
35264
|
+
[filterable]="filterable"
|
|
35265
|
+
[rowHeight]="rowHeight"
|
|
35266
|
+
[detailRowHeight]="detailRowHeight">
|
|
32729
35267
|
</tbody>
|
|
32730
35268
|
</table>
|
|
32731
35269
|
</div>
|
|
@@ -32738,9 +35276,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
32738
35276
|
template: `
|
|
32739
35277
|
@if (isLocked) {
|
|
32740
35278
|
<div class="k-grid-content-locked" role="presentation" [style.width.px]="lockedWidth">
|
|
32741
|
-
<table class="k-grid-table"
|
|
35279
|
+
<table #lockedTable class="k-grid-table"
|
|
32742
35280
|
kendoGridTable
|
|
32743
35281
|
kendoGridResizableTable
|
|
35282
|
+
[locked]="true"
|
|
35283
|
+
[size]="size"
|
|
32744
35284
|
[style.width.px]="lockedWidth">
|
|
32745
35285
|
<colgroup kendoGridColGroup
|
|
32746
35286
|
[groups]="groups"
|
|
@@ -32753,7 +35293,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
32753
35293
|
[isLocked]="true"
|
|
32754
35294
|
[rowsToRender]="rowsToRender"
|
|
32755
35295
|
[columns]="$any(lockedLeafColumns)"
|
|
32756
|
-
[totalColumnsCount]="
|
|
35296
|
+
[totalColumnsCount]="leafColumns.length"
|
|
32757
35297
|
[totalColumns]="totalColumns"
|
|
32758
35298
|
[selectable]="selectable"
|
|
32759
35299
|
[trackBy]="trackBy"
|
|
@@ -32761,13 +35301,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
32761
35301
|
[pinPosition]="position"
|
|
32762
35302
|
[groups]="groups"
|
|
32763
35303
|
[detailTemplate]="detailTemplate"
|
|
32764
|
-
[filterable]="filterable"
|
|
35304
|
+
[filterable]="filterable"
|
|
35305
|
+
[rowHeight]="rowHeight"
|
|
35306
|
+
[detailRowHeight]="detailRowHeight"
|
|
35307
|
+
[isLoading]="loading">
|
|
32765
35308
|
</tbody>
|
|
32766
35309
|
</table>
|
|
32767
35310
|
</div>
|
|
32768
35311
|
}
|
|
32769
35312
|
<div #pinnedWrapper class="k-grid-pinned-wrap">
|
|
32770
|
-
<table class="k-grid-table"
|
|
35313
|
+
<table #pinnedTable class="k-grid-table"
|
|
32771
35314
|
kendoGridTable
|
|
32772
35315
|
kendoGridResizableTable
|
|
32773
35316
|
[style.width.px]="nonLockedWidth"
|
|
@@ -32775,11 +35318,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
32775
35318
|
<colgroup kendoGridColGroup
|
|
32776
35319
|
[columns]="$any(nonLockedLeafColumns)"
|
|
32777
35320
|
[sort]="sort"
|
|
32778
|
-
[groups]="groups"
|
|
35321
|
+
[groups]="isLocked ? [] : groups"
|
|
32779
35322
|
[detailTemplate]="detailTemplate">
|
|
32780
35323
|
</colgroup>
|
|
32781
35324
|
<tbody kendoGridTableBody
|
|
32782
35325
|
role="presentation"
|
|
35326
|
+
[skipGroupDecoration]="isLocked"
|
|
32783
35327
|
[rowsToRender]="rowsToRender"
|
|
32784
35328
|
[columns]="$any(nonLockedLeafColumns)"
|
|
32785
35329
|
[lockedColumnsCount]="isLocked ? lockedLeafColumns?.length : 0"
|
|
@@ -32791,7 +35335,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
32791
35335
|
[pinPosition]="position"
|
|
32792
35336
|
[groups]="groups"
|
|
32793
35337
|
[detailTemplate]="detailTemplate"
|
|
32794
|
-
[filterable]="filterable"
|
|
35338
|
+
[filterable]="filterable"
|
|
35339
|
+
[rowHeight]="rowHeight"
|
|
35340
|
+
[detailRowHeight]="detailRowHeight">
|
|
32795
35341
|
</tbody>
|
|
32796
35342
|
</table>
|
|
32797
35343
|
</div>
|
|
@@ -32803,6 +35349,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
32803
35349
|
}], ctorParameters: () => [{ type: i1$2.LocalizationService }], propDecorators: { pinnedWrapper: [{
|
|
32804
35350
|
type: ViewChild,
|
|
32805
35351
|
args: ['pinnedWrapper', { static: true }]
|
|
35352
|
+
}], lockedTable: [{
|
|
35353
|
+
type: ViewChild,
|
|
35354
|
+
args: ['lockedTable']
|
|
35355
|
+
}], pinnedTable: [{
|
|
35356
|
+
type: ViewChild,
|
|
35357
|
+
args: ['pinnedTable', { static: true }]
|
|
32806
35358
|
}], hostClass: [{
|
|
32807
35359
|
type: HostBinding,
|
|
32808
35360
|
args: ['class.k-grid-pinned-container']
|
|
@@ -32839,8 +35391,128 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
32839
35391
|
type: Input
|
|
32840
35392
|
}], filterable: [{
|
|
32841
35393
|
type: Input
|
|
35394
|
+
}], rowHeight: [{
|
|
35395
|
+
type: Input
|
|
35396
|
+
}], detailRowHeight: [{
|
|
35397
|
+
type: Input
|
|
35398
|
+
}], loading: [{
|
|
35399
|
+
type: Input
|
|
35400
|
+
}], size: [{
|
|
35401
|
+
type: Input
|
|
32842
35402
|
}] } });
|
|
32843
35403
|
|
|
35404
|
+
/**
|
|
35405
|
+
* Tracks the relationship between pinned rows and their counterparts in the main data table.
|
|
35406
|
+
* Use this service to find the main row index for a given pinned row data item,
|
|
35407
|
+
* or to find the pinned counterpart of a main row.
|
|
35408
|
+
*
|
|
35409
|
+
* The service is updated automatically by the Grid when `pinnedTopRows`, `pinnedBottomRows`,
|
|
35410
|
+
* or `data` changes. For reliable index resolution, pinned row data items must be
|
|
35411
|
+
* reference-equal to the corresponding items in the main data array.
|
|
35412
|
+
*
|
|
35413
|
+
* @hidden
|
|
35414
|
+
*/
|
|
35415
|
+
class PinnedRowTrackingService {
|
|
35416
|
+
topIndexMap = new Map();
|
|
35417
|
+
bottomIndexMap = new Map();
|
|
35418
|
+
mainIndexMap = new Map();
|
|
35419
|
+
/**
|
|
35420
|
+
* Updates the internal tracking maps based on the current pinned rows and main data.
|
|
35421
|
+
* Called automatically by the Grid when relevant inputs change.
|
|
35422
|
+
*
|
|
35423
|
+
* @param topRows - The array of data items pinned to the top.
|
|
35424
|
+
* @param bottomRows - The array of data items pinned to the bottom.
|
|
35425
|
+
* @param data - The flat main data array for the current page.
|
|
35426
|
+
* @param skip - The current page skip offset used to compute absolute row indices.
|
|
35427
|
+
*/
|
|
35428
|
+
update(topRows, bottomRows, data, skip) {
|
|
35429
|
+
this.topIndexMap.clear();
|
|
35430
|
+
this.bottomIndexMap.clear();
|
|
35431
|
+
this.mainIndexMap.clear();
|
|
35432
|
+
(topRows || []).forEach(dataItem => {
|
|
35433
|
+
const pageIdx = (data || []).indexOf(dataItem);
|
|
35434
|
+
if (pageIdx >= 0) {
|
|
35435
|
+
const mainIndex = skip + pageIdx;
|
|
35436
|
+
this.topIndexMap.set(dataItem, mainIndex);
|
|
35437
|
+
this.mainIndexMap.set(mainIndex, { dataItem, position: 'top' });
|
|
35438
|
+
}
|
|
35439
|
+
});
|
|
35440
|
+
(bottomRows || []).forEach(dataItem => {
|
|
35441
|
+
const pageIdx = (data || []).indexOf(dataItem);
|
|
35442
|
+
if (pageIdx >= 0) {
|
|
35443
|
+
const mainIndex = skip + pageIdx;
|
|
35444
|
+
this.bottomIndexMap.set(dataItem, mainIndex);
|
|
35445
|
+
this.mainIndexMap.set(mainIndex, { dataItem, position: 'bottom' });
|
|
35446
|
+
}
|
|
35447
|
+
});
|
|
35448
|
+
}
|
|
35449
|
+
/**
|
|
35450
|
+
* Updates the internal tracking maps using a pre-built data-item-to-index map from the main view.
|
|
35451
|
+
* This handles grouping, sorting, and pagination correctly.
|
|
35452
|
+
*
|
|
35453
|
+
* @param topRows - The array of data items pinned to the top.
|
|
35454
|
+
* @param bottomRows - The array of data items pinned to the bottom.
|
|
35455
|
+
* @param dataToIndex - A map from data item references to their absolute row indices in the main view.
|
|
35456
|
+
*/
|
|
35457
|
+
updateFromIndexMap(topRows, bottomRows, dataToIndex) {
|
|
35458
|
+
this.topIndexMap.clear();
|
|
35459
|
+
this.bottomIndexMap.clear();
|
|
35460
|
+
this.mainIndexMap.clear();
|
|
35461
|
+
(topRows || []).forEach(dataItem => {
|
|
35462
|
+
const mainIndex = dataToIndex.get(dataItem);
|
|
35463
|
+
if (mainIndex !== undefined) {
|
|
35464
|
+
this.topIndexMap.set(dataItem, mainIndex);
|
|
35465
|
+
this.mainIndexMap.set(mainIndex, { dataItem, position: 'top' });
|
|
35466
|
+
}
|
|
35467
|
+
});
|
|
35468
|
+
(bottomRows || []).forEach(dataItem => {
|
|
35469
|
+
const mainIndex = dataToIndex.get(dataItem);
|
|
35470
|
+
if (mainIndex !== undefined) {
|
|
35471
|
+
this.bottomIndexMap.set(dataItem, mainIndex);
|
|
35472
|
+
this.mainIndexMap.set(mainIndex, { dataItem, position: 'bottom' });
|
|
35473
|
+
}
|
|
35474
|
+
});
|
|
35475
|
+
}
|
|
35476
|
+
/**
|
|
35477
|
+
* Returns the absolute main row index for a pinned row data item, or `-1` if not found.
|
|
35478
|
+
* The returned index matches the `index` property used by selection and editing services.
|
|
35479
|
+
*/
|
|
35480
|
+
getMainRowIndex(dataItem) {
|
|
35481
|
+
return this.topIndexMap.get(dataItem) ?? this.bottomIndexMap.get(dataItem) ?? -1;
|
|
35482
|
+
}
|
|
35483
|
+
/**
|
|
35484
|
+
* Returns `true` if the given data item is currently pinned to the top or bottom.
|
|
35485
|
+
*/
|
|
35486
|
+
isRowPinned(dataItem) {
|
|
35487
|
+
return this.topIndexMap.has(dataItem) || this.bottomIndexMap.has(dataItem);
|
|
35488
|
+
}
|
|
35489
|
+
/**
|
|
35490
|
+
* Returns the pin position (`'top'` or `'bottom'`) for the given data item,
|
|
35491
|
+
* or `null` if the item is not pinned.
|
|
35492
|
+
*/
|
|
35493
|
+
getPinnedPosition(dataItem) {
|
|
35494
|
+
if (this.topIndexMap.has(dataItem)) {
|
|
35495
|
+
return 'top';
|
|
35496
|
+
}
|
|
35497
|
+
if (this.bottomIndexMap.has(dataItem)) {
|
|
35498
|
+
return 'bottom';
|
|
35499
|
+
}
|
|
35500
|
+
return null;
|
|
35501
|
+
}
|
|
35502
|
+
/**
|
|
35503
|
+
* Returns the pinned counterpart for a given main row index,
|
|
35504
|
+
* or `null` if the main row has no pinned counterpart.
|
|
35505
|
+
*/
|
|
35506
|
+
getPinnedCounterpart(mainIndex) {
|
|
35507
|
+
return this.mainIndexMap.get(mainIndex) || null;
|
|
35508
|
+
}
|
|
35509
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: PinnedRowTrackingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
35510
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: PinnedRowTrackingService });
|
|
35511
|
+
}
|
|
35512
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: PinnedRowTrackingService, decorators: [{
|
|
35513
|
+
type: Injectable
|
|
35514
|
+
}] });
|
|
35515
|
+
|
|
32844
35516
|
const createControl = (source) => (acc, key) => {
|
|
32845
35517
|
acc[key] = new FormControl(source[key]);
|
|
32846
35518
|
return acc;
|
|
@@ -32928,6 +35600,7 @@ class GridComponent {
|
|
|
32928
35600
|
idService;
|
|
32929
35601
|
searchService;
|
|
32930
35602
|
rowPinService;
|
|
35603
|
+
pinnedRowTrackingService;
|
|
32931
35604
|
/**
|
|
32932
35605
|
* Sets the data of the Grid. If you provide an array, the Grid gets the total count automatically.
|
|
32933
35606
|
* ([more information and example](https://www.telerik.com/kendo-angular-ui/components/grid/data-binding/basics)).
|
|
@@ -33820,13 +36493,41 @@ class GridComponent {
|
|
|
33820
36493
|
get flatData() {
|
|
33821
36494
|
return isArray(this.data) ? this.data : this.data.data;
|
|
33822
36495
|
}
|
|
36496
|
+
/**
|
|
36497
|
+
* @hidden
|
|
36498
|
+
*/
|
|
36499
|
+
updatePinnedRowTracking() {
|
|
36500
|
+
const dataToIndex = this.buildViewIndexMap();
|
|
36501
|
+
this.pinnedRowTrackingService.updateFromIndexMap(this.pinnedTopRows, this.pinnedBottomRows, dataToIndex);
|
|
36502
|
+
}
|
|
36503
|
+
buildViewIndexMap() {
|
|
36504
|
+
const dataToIndex = new Map();
|
|
36505
|
+
const iter = this.view[iterator]();
|
|
36506
|
+
let next = iter.next();
|
|
36507
|
+
while (!next.done) {
|
|
36508
|
+
const viewItem = next.value;
|
|
36509
|
+
if (viewItem?.type === 'data') {
|
|
36510
|
+
dataToIndex.set(viewItem.data, viewItem.index);
|
|
36511
|
+
}
|
|
36512
|
+
next = iter.next();
|
|
36513
|
+
}
|
|
36514
|
+
return dataToIndex;
|
|
36515
|
+
}
|
|
33823
36516
|
adjustPinnedItemIndexes(items) {
|
|
33824
|
-
const
|
|
36517
|
+
const dataToIndex = this.buildViewIndexMap();
|
|
33825
36518
|
items.forEach((item) => {
|
|
33826
36519
|
if (item.type === 'data') {
|
|
33827
|
-
|
|
33828
|
-
|
|
33829
|
-
|
|
36520
|
+
// Preserve the render-order position (0, 1, 2...) for stable isOdd styling.
|
|
36521
|
+
item.pinnedIndex = item.index;
|
|
36522
|
+
const mainIndex = dataToIndex.get(item.data);
|
|
36523
|
+
if (mainIndex !== undefined) {
|
|
36524
|
+
item.index = mainIndex;
|
|
36525
|
+
}
|
|
36526
|
+
else {
|
|
36527
|
+
// Use a negative index when the pinned item is absent from the current view
|
|
36528
|
+
// (e.g. filtered out or on a different page) to avoid colliding with main
|
|
36529
|
+
// body row indices, which would cause incorrect selection state sync.
|
|
36530
|
+
item.index = -(item.pinnedIndex + 1);
|
|
33830
36531
|
}
|
|
33831
36532
|
}
|
|
33832
36533
|
});
|
|
@@ -33992,7 +36693,7 @@ class GridComponent {
|
|
|
33992
36693
|
pinnedContainersChangeSubscription;
|
|
33993
36694
|
rtl = false;
|
|
33994
36695
|
_rowSticky;
|
|
33995
|
-
constructor(supportService, selectionService, cellSelectionService, wrapper, groupInfoService, groupsService, changeNotification, detailsService, editService, filterService, pdfService, responsiveService, renderer, excelService, csvService, ngZone, scrollSyncService, domEvents, columnResizingService, changeDetectorRef, columnReorderService, columnInfoService, navigationService, sortService, scrollRequestService, localization, ctx, sizingService, adaptiveGridService, rowReorderService, dataMappingService, aiRequestResponseService, idService, searchService, rowPinService) {
|
|
36696
|
+
constructor(supportService, selectionService, cellSelectionService, wrapper, groupInfoService, groupsService, changeNotification, detailsService, editService, filterService, pdfService, responsiveService, renderer, excelService, csvService, ngZone, scrollSyncService, domEvents, columnResizingService, changeDetectorRef, columnReorderService, columnInfoService, navigationService, sortService, scrollRequestService, localization, ctx, sizingService, adaptiveGridService, rowReorderService, dataMappingService, aiRequestResponseService, idService, searchService, rowPinService, pinnedRowTrackingService) {
|
|
33996
36697
|
this.supportService = supportService;
|
|
33997
36698
|
this.selectionService = selectionService;
|
|
33998
36699
|
this.cellSelectionService = cellSelectionService;
|
|
@@ -34028,9 +36729,13 @@ class GridComponent {
|
|
|
34028
36729
|
this.idService = idService;
|
|
34029
36730
|
this.searchService = searchService;
|
|
34030
36731
|
this.rowPinService = rowPinService;
|
|
36732
|
+
this.pinnedRowTrackingService = pinnedRowTrackingService;
|
|
34031
36733
|
const isValid = validatePackage(packageMetadata);
|
|
34032
36734
|
this.licenseMessage = getLicenseMessage(packageMetadata);
|
|
34033
36735
|
this.showLicenseWatermark = shouldShowValidationUI(isValid);
|
|
36736
|
+
if (isDocumentAvailable()) {
|
|
36737
|
+
document.body.style.setProperty('--kendo-scrollbar-width', `${this.scrollbarWidth}px`);
|
|
36738
|
+
}
|
|
34034
36739
|
this.ctx.grid = this;
|
|
34035
36740
|
this.ctx.navigable = typeof this.navigable === 'boolean' ? this.navigable : this.navigable.includes('table');
|
|
34036
36741
|
this.groupChange = new ZoneAwareEventEmitter(this.ngZone);
|
|
@@ -34185,6 +36890,7 @@ class GridComponent {
|
|
|
34185
36890
|
}
|
|
34186
36891
|
this.initSelectionService();
|
|
34187
36892
|
this.updateNavigationMetadata();
|
|
36893
|
+
this.updatePinnedRowTracking();
|
|
34188
36894
|
}
|
|
34189
36895
|
ngDoCheck() {
|
|
34190
36896
|
if (!this.isScrollable) {
|
|
@@ -34204,6 +36910,9 @@ class GridComponent {
|
|
|
34204
36910
|
if (this.lockedLeafColumns.length && anyChanged(["pageSize", "skip", "sort", "group"], changes)) {
|
|
34205
36911
|
this.changeNotification.notify();
|
|
34206
36912
|
}
|
|
36913
|
+
if (isChanged$1("skip", changes)) {
|
|
36914
|
+
this.updatePinnedRowTracking();
|
|
36915
|
+
}
|
|
34207
36916
|
if (anyChanged(["pageSize", "scrollable", 'virtualColumns'], changes)) {
|
|
34208
36917
|
this.updateNavigationMetadata();
|
|
34209
36918
|
}
|
|
@@ -34229,6 +36938,13 @@ class GridComponent {
|
|
|
34229
36938
|
if (this.isPinnable) {
|
|
34230
36939
|
this.ngZone.onStable.pipe(take(1)).subscribe(() => this.attachScrollSync());
|
|
34231
36940
|
}
|
|
36941
|
+
this.updatePinnedRowTracking();
|
|
36942
|
+
// Pinned container height changes affect the scrollable viewport size
|
|
36943
|
+
if (this.isVirtual && this.listComponent && (isChanged$1("pinnedTopRows", changes) || isChanged$1("pinnedBottomRows", changes))) {
|
|
36944
|
+
this.ngZone.onStable.pipe(take(1)).subscribe(() => {
|
|
36945
|
+
this.listComponent.onPinnedContainerHeightChange();
|
|
36946
|
+
});
|
|
36947
|
+
}
|
|
34232
36948
|
}
|
|
34233
36949
|
if (isChanged$1("selectable", changes) && this.shouldResetSelection(changes['selectable'])) {
|
|
34234
36950
|
if (this.defaultSelection) {
|
|
@@ -35407,7 +38123,7 @@ class GridComponent {
|
|
|
35407
38123
|
this.dragTargetContainer?.notify();
|
|
35408
38124
|
this.dropTargetContainer?.notify();
|
|
35409
38125
|
}
|
|
35410
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: GridComponent, deps: [{ token: i1$3.ScrollbarService }, { token: SelectionService }, { token: CellSelectionService }, { token: i0.ElementRef }, { token: GroupInfoService }, { token: GroupsService }, { token: ChangeNotificationService }, { token: DetailsService }, { token: EditService }, { token: FilterService }, { token: PDFService }, { token: ResponsiveService }, { token: i0.Renderer2 }, { token: ExcelService }, { token: CSVService }, { token: i0.NgZone }, { token: ScrollSyncService }, { token: DomEventsService }, { token: ColumnResizingService }, { token: i0.ChangeDetectorRef }, { token: ColumnReorderService }, { token: ColumnInfoService }, { token: NavigationService }, { token: SortService }, { token: ScrollRequestService }, { token: i1$2.LocalizationService }, { token: ContextService }, { token: SizingOptionsService }, { token: AdaptiveGridService }, { token: RowReorderService }, { token: DataMappingService }, { token: GridAIRequestResponseService }, { token: IdService }, { token: SearchService }, { token: RowPinService }], target: i0.ɵɵFactoryTarget.Component });
|
|
38126
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: GridComponent, deps: [{ token: i1$3.ScrollbarService }, { token: SelectionService }, { token: CellSelectionService }, { token: i0.ElementRef }, { token: GroupInfoService }, { token: GroupsService }, { token: ChangeNotificationService }, { token: DetailsService }, { token: EditService }, { token: FilterService }, { token: PDFService }, { token: ResponsiveService }, { token: i0.Renderer2 }, { token: ExcelService }, { token: CSVService }, { token: i0.NgZone }, { token: ScrollSyncService }, { token: DomEventsService }, { token: ColumnResizingService }, { token: i0.ChangeDetectorRef }, { token: ColumnReorderService }, { token: ColumnInfoService }, { token: NavigationService }, { token: SortService }, { token: ScrollRequestService }, { token: i1$2.LocalizationService }, { token: ContextService }, { token: SizingOptionsService }, { token: AdaptiveGridService }, { token: RowReorderService }, { token: DataMappingService }, { token: GridAIRequestResponseService }, { token: IdService }, { token: SearchService }, { token: RowPinService }, { token: PinnedRowTrackingService }], target: i0.ɵɵFactoryTarget.Component });
|
|
35411
38127
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.20", type: GridComponent, isStandalone: true, selector: "kendo-grid", inputs: { data: "data", pageSize: "pageSize", height: "height", rowHeight: "rowHeight", adaptiveMode: "adaptiveMode", detailRowHeight: "detailRowHeight", skip: "skip", scrollable: "scrollable", selectable: "selectable", sort: "sort", size: "size", trackBy: "trackBy", filter: "filter", group: "group", virtualColumns: "virtualColumns", filterable: "filterable", sortable: "sortable", pageable: "pageable", groupable: "groupable", gridResizable: "gridResizable", rowReorderable: "rowReorderable", navigable: "navigable", autoSize: "autoSize", rowClass: "rowClass", rowSticky: "rowSticky", rowSelected: "rowSelected", isRowSelectable: "isRowSelectable", cellSelected: "cellSelected", resizable: "resizable", reorderable: "reorderable", loading: "loading", columnMenu: "columnMenu", hideHeader: "hideHeader", showInactiveTools: "showInactiveTools", isDetailExpanded: "isDetailExpanded", isGroupExpanded: "isGroupExpanded", dataLayoutMode: "dataLayoutMode", pinnable: "pinnable", pinnedTopRows: "pinnedTopRows", pinnedBottomRows: "pinnedBottomRows", isRowPinnable: "isRowPinnable" }, outputs: { filterChange: "filterChange", pageChange: "pageChange", groupChange: "groupChange", sortChange: "sortChange", selectionChange: "selectionChange", rowReorder: "rowReorder", rowPinChange: "rowPinChange", dataStateChange: "dataStateChange", gridStateChange: "gridStateChange", groupExpand: "groupExpand", groupCollapse: "groupCollapse", detailExpand: "detailExpand", detailCollapse: "detailCollapse", edit: "edit", cancel: "cancel", save: "save", remove: "remove", add: "add", cellClose: "cellClose", cellClick: "cellClick", pdfExport: "pdfExport", excelExport: "excelExport", csvExport: "csvExport", columnResize: "columnResize", columnReorder: "columnReorder", columnVisibilityChange: "columnVisibilityChange", columnLockedChange: "columnLockedChange", columnStickyChange: "columnStickyChange", scrollBottom: "scrollBottom", contentScroll: "contentScroll" }, host: { properties: { "attr.dir": "this.dir", "class.k-grid": "this.hostClass", "class.k-grid-sm": "this.sizeSmallClass", "class.k-grid-md": "this.sizeMediumClass", "class.k-grid-stack": "this.stackedClass", "class.k-grid-lockedcolumns": "this.lockedClasses", "class.k-grid-virtual": "this.virtualClasses", "class.k-grid-no-scrollbar": "this.noScrollbarClass", "class.k-grid-resizable": "this.isResizable", "style.minWidth": "this.minWidth", "style.maxWidth": "this.maxWidth", "style.minHeight": "this.minHeight", "style.maxHeight": "this.maxHeight" } }, providers: [
|
|
35412
38128
|
LocalizationService,
|
|
35413
38129
|
ColumnInfoService,
|
|
@@ -35461,7 +38177,9 @@ class GridComponent {
|
|
|
35461
38177
|
MenuTabbingService,
|
|
35462
38178
|
DataMappingService,
|
|
35463
38179
|
SearchService,
|
|
35464
|
-
RowPinService
|
|
38180
|
+
RowPinService,
|
|
38181
|
+
StickyGroupsService,
|
|
38182
|
+
PinnedRowTrackingService
|
|
35465
38183
|
], queries: [{ propertyName: "columns", predicate: ColumnBase }, { propertyName: "detailTemplateChildren", predicate: DetailTemplateDirective }, { propertyName: "cellLoadingTemplateChildren", predicate: CellLoadingTemplateDirective }, { propertyName: "loadingTemplateChildren", predicate: LoadingTemplateDirective }, { propertyName: "statusBarTemplateChildren", predicate: StatusBarTemplateDirective }, { propertyName: "noRecordsTemplateChildren", predicate: NoRecordsTemplateDirective }, { propertyName: "pagerTemplateChildren", predicate: PagerTemplateDirective }, { propertyName: "toolbarTemplateChildren", predicate: ToolbarTemplateDirective }, { propertyName: "columnMenuTemplates", predicate: ColumnMenuTemplateDirective }], viewQueries: [{ propertyName: "lockedHeader", first: true, predicate: ["lockedHeader"], descendants: true }, { propertyName: "header", first: true, predicate: ["header"], descendants: true }, { propertyName: "ariaRoot", first: true, predicate: ["ariaRoot"], descendants: true, static: true }, { propertyName: "dragTargetContainer", first: true, predicate: DragTargetContainerDirective, descendants: true }, { propertyName: "dropTargetContainer", first: true, predicate: DropTargetContainerDirective, descendants: true }, { propertyName: "dialogContainer", first: true, predicate: ["dialogContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "windowContainer", first: true, predicate: ["windowContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "adaptiveRenderer", first: true, predicate: AdaptiveRendererComponent, descendants: true }, { propertyName: "listComponent", first: true, predicate: ListComponent, descendants: true }, { propertyName: "pinnedContainers", predicate: RowPinContainerComponent, descendants: true }, { propertyName: "footer", predicate: ["footer"], descendants: true }], exportAs: ["kendoGrid"], usesOnChanges: true, ngImport: i0, template: `
|
|
35466
38184
|
<ng-container kendoGridLocalizedMessages
|
|
35467
38185
|
i18n-groupPanelEmpty="kendo.grid.groupPanelEmpty|The label visible in the Grid group panel when it is empty"
|
|
@@ -35943,6 +38661,12 @@ class GridComponent {
|
|
|
35943
38661
|
|
|
35944
38662
|
i18n-pinColumnHeaderLabel="kendo.grid.pinColumnHeaderLabel|The screen-reader-only content for the pin column header"
|
|
35945
38663
|
pinColumnHeaderLabel="Actions"
|
|
38664
|
+
|
|
38665
|
+
i18n-rowPinLabel="kendo.grid.rowPinLabel|Sets the label for the Grid row pin column icon"
|
|
38666
|
+
rowPinLabel="Pin row"
|
|
38667
|
+
|
|
38668
|
+
i18n-rowUnpinLabel="kendo.grid.rowUnpinLabel|Sets the label for the Grid row unpin column icon"
|
|
38669
|
+
rowUnpinLabel="Unpin row"
|
|
35946
38670
|
>
|
|
35947
38671
|
</ng-container>
|
|
35948
38672
|
@if (showTopToolbar) {
|
|
@@ -36142,7 +38866,9 @@ class GridComponent {
|
|
|
36142
38866
|
[trackBy]="trackBy"
|
|
36143
38867
|
[groups]="group"
|
|
36144
38868
|
[detailTemplate]="detailTemplate"
|
|
36145
|
-
[filterable]="filterable"
|
|
38869
|
+
[filterable]="filterable"
|
|
38870
|
+
[rowHeight]="rowHeight"
|
|
38871
|
+
[detailRowHeight]="detailRowHeight">
|
|
36146
38872
|
</kendo-grid-rowpin-container>
|
|
36147
38873
|
}
|
|
36148
38874
|
|
|
@@ -36194,7 +38920,9 @@ class GridComponent {
|
|
|
36194
38920
|
[trackBy]="trackBy"
|
|
36195
38921
|
[groups]="group"
|
|
36196
38922
|
[detailTemplate]="detailTemplate"
|
|
36197
|
-
[filterable]="filterable"
|
|
38923
|
+
[filterable]="filterable"
|
|
38924
|
+
[rowHeight]="rowHeight"
|
|
38925
|
+
[detailRowHeight]="detailRowHeight">
|
|
36198
38926
|
</kendo-grid-rowpin-container>
|
|
36199
38927
|
}
|
|
36200
38928
|
@if (showFooter) {
|
|
@@ -36282,7 +39010,9 @@ class GridComponent {
|
|
|
36282
39010
|
[trackBy]="trackBy"
|
|
36283
39011
|
[groups]="group"
|
|
36284
39012
|
[detailTemplate]="detailTemplate"
|
|
36285
|
-
[filterable]="filterable"
|
|
39013
|
+
[filterable]="filterable"
|
|
39014
|
+
[rowHeight]="rowHeight"
|
|
39015
|
+
[detailRowHeight]="detailRowHeight">
|
|
36286
39016
|
</kendo-grid-rowpin-container>
|
|
36287
39017
|
}
|
|
36288
39018
|
<table
|
|
@@ -36369,7 +39099,11 @@ class GridComponent {
|
|
|
36369
39099
|
[trackBy]="trackBy"
|
|
36370
39100
|
[groups]="group"
|
|
36371
39101
|
[detailTemplate]="detailTemplate"
|
|
36372
|
-
[filterable]="filterable"
|
|
39102
|
+
[filterable]="filterable"
|
|
39103
|
+
[rowHeight]="rowHeight"
|
|
39104
|
+
[detailRowHeight]="detailRowHeight"
|
|
39105
|
+
[size]="size"
|
|
39106
|
+
[loading]="loading">
|
|
36373
39107
|
</kendo-grid-rowpin-container>
|
|
36374
39108
|
}
|
|
36375
39109
|
}
|
|
@@ -36487,7 +39221,7 @@ class GridComponent {
|
|
|
36487
39221
|
@if (showLicenseWatermark) {
|
|
36488
39222
|
<div kendoWatermarkOverlay [licenseMessage]="licenseMessage"></div>
|
|
36489
39223
|
}
|
|
36490
|
-
`, isInline: true, dependencies: [{ kind: "directive", type: LocalizedMessagesDirective, selector: "[kendoGridLocalizedMessages]" }, { kind: "component", type: ToolbarComponent, selector: "kendo-grid-toolbar", inputs: ["position", "size", "navigable"] }, { kind: "component", type: GroupPanelComponent, selector: "kendo-grid-group-panel", inputs: ["text", "navigable", "groups"], outputs: ["change"] }, { kind: "directive", type: TableDirective, selector: "[kendoGridResizableTable]", inputs: ["locked", "virtualColumns"] }, { kind: "directive", type: GridTableDirective, selector: "[kendoGridTable]", inputs: ["size"] }, { kind: "component", type: ColGroupComponent, selector: "[kendoGridColGroup]", inputs: ["columns", "groups", "detailTemplate", "sort"] }, { kind: "component", type: HeaderComponent, selector: "[kendoGridHeader]", inputs: ["totalColumnLevels", "columns", "groups", "detailTemplate", "scrollable", "filterable", "sort", "filter", "sortable", "groupable", "lockedColumnsCount", "resizable", "reorderable", "columnMenu", "columnMenuTemplate", "totalColumnsCount", "totalColumns", "tabIndex", "size"] }, { kind: "directive", type: ResizableContainerDirective, selector: "[kendoGridResizableContainer]", inputs: ["lockedWidth", "kendoGridResizableContainer"] }, { kind: "component", type: ListComponent, selector: "kendo-grid-list", inputs: ["data", "groups", "total", "rowHeight", "detailRowHeight", "take", "skip", "columns", "detailTemplate", "noRecordsTemplate", "selectable", "groupable", "filterable", "rowClass", "rowSticky", "loading", "trackBy", "virtualColumns", "isVirtual", "cellLoadingTemplate", "loadingTemplate", "sort", "size"], outputs: ["contentScroll", "pageChange", "scrollBottom"] }, { kind: "directive", type: DragTargetContainerDirective, selector: "[kendoDragTargetContainer]", inputs: ["hint", "dragTargetFilter", "dragHandle", "dragDelay", "threshold", "dragTargetId", "dragData", "dragDisabled", "mode", "cursorStyle", "hintContext"], outputs: ["onDragReady", "onPress", "onDragStart", "onDrag", "onRelease", "onDragEnd"], exportAs: ["kendoDragTargetContainer"] }, { kind: "directive", type: DropTargetContainerDirective, selector: "[kendoDropTargetContainer]", inputs: ["dropTargetFilter", "dropDisabled"], outputs: ["onDragEnter", "onDragOver", "onDragLeave", "onDrop"], exportAs: ["kendoDropTargetContainer"] }, { kind: "directive", type: DraggableDirective, selector: "[kendoDraggable]", inputs: ["enableDrag"], outputs: ["kendoPress", "kendoDrag", "kendoRelease"] }, { kind: "directive", type: GridMarqueeDirective, selector: "[kendoGridSelectionMarquee]" }, { kind: "component", type: FooterComponent, selector: "[kendoGridFooter]", inputs: ["columns", "groups", "detailTemplate", "scrollable", "lockedColumnsCount", "logicalRowIndex", "totalColumns", "totalColumnsCount"] }, { kind: "component", type: TableBodyComponent, selector: "[kendoGridTableBody]", inputs: ["columns", "allColumns", "groups", "detailTemplate", "noRecordsTemplate", "rowsToRender", "skip", "selectable", "filterable", "noRecordsText", "isLocked", "isLoading", "isVirtual", "cellLoadingTemplate", "skipGroupDecoration", "lockedColumnsCount", "totalColumnsCount", "virtualColumns", "trackBy", "rowSticky", "totalColumns", "rowClass", "rowHeight", "detailRowHeight", "isPinContainer", "pinPosition"] }, { kind: "component", type: LoadingComponent, selector: "[kendoGridLoading]", inputs: ["loadingTemplate"] }, { kind: "component", type: StatusBarComponent, selector: "kendo-grid-status-bar", inputs: ["statusBarTemplate"] }, { kind: "component", type: IconWrapperComponent, selector: "kendo-icon-wrapper", inputs: ["name", "svgIcon", "innerCssClass", "customFontClass", "size"], exportAs: ["kendoIconWrapper"] }, { kind: "component", type: WatermarkOverlayComponent, selector: "div[kendoWatermarkOverlay], kendo-watermark-overlay", inputs: ["licenseMessage"] }, { kind: "component", type: i57.CustomMessagesComponent, selector: "kendo-datapager-messages, kendo-pager-messages" }, { kind: "component", type: i57.PagerInfoComponent, selector: "kendo-datapager-info, kendo-pager-info" }, { kind: "component", type: i57.PagerInputComponent, selector: "kendo-datapager-input, kendo-pager-input", inputs: ["showPageText", "size"] }, { kind: "component", type: i57.PagerNextButtonsComponent, selector: "kendo-datapager-next-buttons, kendo-pager-next-buttons", inputs: ["size"] }, { kind: "component", type: i57.PagerNumericButtonsComponent, selector: "kendo-datapager-numeric-buttons, kendo-pager-numeric-buttons", inputs: ["buttonCount", "size"] }, { kind: "component", type: i57.PagerPageSizesComponent, selector: "kendo-datapager-page-sizes, kendo-pager-page-sizes", inputs: ["showItemsText", "pageSizes", "size", "adaptiveMode"] }, { kind: "component", type: i57.PagerPrevButtonsComponent, selector: "kendo-datapager-prev-buttons, kendo-pager-prev-buttons", inputs: ["size"] }, { kind: "directive", type: i57.PagerTemplateDirective, selector: "[kendoDataPagerTemplate], [kendoPagerTemplate]" }, { kind: "component", type: i57.PagerComponent, selector: "kendo-datapager, kendo-pager", inputs: ["externalTemplate", "total", "skip", "pageSize", "buttonCount", "info", "type", "pageSizeValues", "previousNext", "navigable", "size", "responsive", "adaptiveMode"], outputs: ["pageChange", "pageSizeChange", "pagerInputVisibilityChange", "pageTextVisibilityChange", "itemsTextVisibilityChange"], exportAs: ["kendoDataPager", "kendoPager"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: AdaptiveRendererComponent, selector: "kendo-grid-adaptive-renderer" }, { kind: "component", type: ResizeSensorComponent, selector: "kendo-resize-sensor", inputs: ["rateLimit"], outputs: ["resize"] }, { kind: "component", type: RowPinContainerComponent, selector: "kendo-grid-rowpin-container", inputs: ["leafColumns", "lockedLeafColumns", "nonLockedLeafColumns", "sort", "position", "rowsToRender", "totalColumns", "lockedWidth", "nonLockedWidth", "isLocked", "selectable", "trackBy", "groups", "detailTemplate", "filterable"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
39224
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: LocalizedMessagesDirective, selector: "[kendoGridLocalizedMessages]" }, { kind: "component", type: ToolbarComponent, selector: "kendo-grid-toolbar", inputs: ["position", "size", "navigable"] }, { kind: "component", type: GroupPanelComponent, selector: "kendo-grid-group-panel", inputs: ["text", "navigable", "groups"], outputs: ["change"] }, { kind: "directive", type: TableDirective, selector: "[kendoGridResizableTable]", inputs: ["locked", "virtualColumns"] }, { kind: "directive", type: GridTableDirective, selector: "[kendoGridTable]", inputs: ["size"] }, { kind: "component", type: ColGroupComponent, selector: "[kendoGridColGroup]", inputs: ["columns", "groups", "detailTemplate", "sort"] }, { kind: "component", type: HeaderComponent, selector: "[kendoGridHeader]", inputs: ["totalColumnLevels", "columns", "groups", "detailTemplate", "scrollable", "filterable", "sort", "filter", "sortable", "groupable", "lockedColumnsCount", "resizable", "reorderable", "columnMenu", "columnMenuTemplate", "totalColumnsCount", "totalColumns", "tabIndex", "size"] }, { kind: "directive", type: ResizableContainerDirective, selector: "[kendoGridResizableContainer]", inputs: ["lockedWidth", "kendoGridResizableContainer"] }, { kind: "component", type: ListComponent, selector: "kendo-grid-list", inputs: ["data", "groups", "total", "rowHeight", "detailRowHeight", "take", "skip", "columns", "detailTemplate", "noRecordsTemplate", "selectable", "groupable", "filterable", "rowClass", "rowSticky", "loading", "trackBy", "virtualColumns", "isVirtual", "cellLoadingTemplate", "loadingTemplate", "sort", "size"], outputs: ["contentScroll", "pageChange", "scrollBottom"] }, { kind: "directive", type: DragTargetContainerDirective, selector: "[kendoDragTargetContainer]", inputs: ["hint", "dragTargetFilter", "dragHandle", "dragDelay", "threshold", "dragTargetId", "dragData", "dragDisabled", "mode", "cursorStyle", "hintContext"], outputs: ["onDragReady", "onPress", "onDragStart", "onDrag", "onRelease", "onDragEnd"], exportAs: ["kendoDragTargetContainer"] }, { kind: "directive", type: DropTargetContainerDirective, selector: "[kendoDropTargetContainer]", inputs: ["dropTargetFilter", "dropDisabled"], outputs: ["onDragEnter", "onDragOver", "onDragLeave", "onDrop"], exportAs: ["kendoDropTargetContainer"] }, { kind: "directive", type: DraggableDirective, selector: "[kendoDraggable]", inputs: ["enableDrag"], outputs: ["kendoPress", "kendoDrag", "kendoRelease"] }, { kind: "directive", type: GridMarqueeDirective, selector: "[kendoGridSelectionMarquee]" }, { kind: "component", type: FooterComponent, selector: "[kendoGridFooter]", inputs: ["columns", "groups", "detailTemplate", "scrollable", "lockedColumnsCount", "logicalRowIndex", "totalColumns", "totalColumnsCount"] }, { kind: "component", type: TableBodyComponent, selector: "[kendoGridTableBody]", inputs: ["columns", "allColumns", "groups", "detailTemplate", "noRecordsTemplate", "rowsToRender", "skip", "selectable", "filterable", "noRecordsText", "isLocked", "isLoading", "isVirtual", "cellLoadingTemplate", "skipGroupDecoration", "lockedColumnsCount", "totalColumnsCount", "virtualColumns", "trackBy", "rowSticky", "totalColumns", "rowClass", "rowHeight", "detailRowHeight", "isPinContainer", "pinPosition"] }, { kind: "component", type: LoadingComponent, selector: "[kendoGridLoading]", inputs: ["loadingTemplate"] }, { kind: "component", type: StatusBarComponent, selector: "kendo-grid-status-bar", inputs: ["statusBarTemplate"] }, { kind: "component", type: IconWrapperComponent, selector: "kendo-icon-wrapper", inputs: ["name", "svgIcon", "innerCssClass", "customFontClass", "size"], exportAs: ["kendoIconWrapper"] }, { kind: "component", type: WatermarkOverlayComponent, selector: "div[kendoWatermarkOverlay], kendo-watermark-overlay", inputs: ["licenseMessage"] }, { kind: "component", type: i57.CustomMessagesComponent, selector: "kendo-datapager-messages, kendo-pager-messages" }, { kind: "component", type: i57.PagerInfoComponent, selector: "kendo-datapager-info, kendo-pager-info" }, { kind: "component", type: i57.PagerInputComponent, selector: "kendo-datapager-input, kendo-pager-input", inputs: ["showPageText", "size"] }, { kind: "component", type: i57.PagerNextButtonsComponent, selector: "kendo-datapager-next-buttons, kendo-pager-next-buttons", inputs: ["size"] }, { kind: "component", type: i57.PagerNumericButtonsComponent, selector: "kendo-datapager-numeric-buttons, kendo-pager-numeric-buttons", inputs: ["buttonCount", "size"] }, { kind: "component", type: i57.PagerPageSizesComponent, selector: "kendo-datapager-page-sizes, kendo-pager-page-sizes", inputs: ["showItemsText", "pageSizes", "size", "adaptiveMode"] }, { kind: "component", type: i57.PagerPrevButtonsComponent, selector: "kendo-datapager-prev-buttons, kendo-pager-prev-buttons", inputs: ["size"] }, { kind: "directive", type: i57.PagerTemplateDirective, selector: "[kendoDataPagerTemplate], [kendoPagerTemplate]" }, { kind: "component", type: i57.PagerComponent, selector: "kendo-datapager, kendo-pager", inputs: ["externalTemplate", "total", "skip", "pageSize", "buttonCount", "info", "type", "pageSizeValues", "previousNext", "navigable", "size", "responsive", "adaptiveMode"], outputs: ["pageChange", "pageSizeChange", "pagerInputVisibilityChange", "pageTextVisibilityChange", "itemsTextVisibilityChange"], exportAs: ["kendoDataPager", "kendoPager"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: AdaptiveRendererComponent, selector: "kendo-grid-adaptive-renderer" }, { kind: "component", type: ResizeSensorComponent, selector: "kendo-resize-sensor", inputs: ["rateLimit"], outputs: ["resize"] }, { kind: "component", type: RowPinContainerComponent, selector: "kendo-grid-rowpin-container", inputs: ["leafColumns", "lockedLeafColumns", "nonLockedLeafColumns", "sort", "position", "rowsToRender", "totalColumns", "lockedWidth", "nonLockedWidth", "isLocked", "selectable", "trackBy", "groups", "detailTemplate", "filterable", "rowHeight", "detailRowHeight", "loading", "size"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
36491
39225
|
}
|
|
36492
39226
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: GridComponent, decorators: [{
|
|
36493
39227
|
type: Component,
|
|
@@ -36547,7 +39281,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
36547
39281
|
MenuTabbingService,
|
|
36548
39282
|
DataMappingService,
|
|
36549
39283
|
SearchService,
|
|
36550
|
-
RowPinService
|
|
39284
|
+
RowPinService,
|
|
39285
|
+
StickyGroupsService,
|
|
39286
|
+
PinnedRowTrackingService
|
|
36551
39287
|
],
|
|
36552
39288
|
selector: 'kendo-grid',
|
|
36553
39289
|
template: `
|
|
@@ -37031,6 +39767,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
37031
39767
|
|
|
37032
39768
|
i18n-pinColumnHeaderLabel="kendo.grid.pinColumnHeaderLabel|The screen-reader-only content for the pin column header"
|
|
37033
39769
|
pinColumnHeaderLabel="Actions"
|
|
39770
|
+
|
|
39771
|
+
i18n-rowPinLabel="kendo.grid.rowPinLabel|Sets the label for the Grid row pin column icon"
|
|
39772
|
+
rowPinLabel="Pin row"
|
|
39773
|
+
|
|
39774
|
+
i18n-rowUnpinLabel="kendo.grid.rowUnpinLabel|Sets the label for the Grid row unpin column icon"
|
|
39775
|
+
rowUnpinLabel="Unpin row"
|
|
37034
39776
|
>
|
|
37035
39777
|
</ng-container>
|
|
37036
39778
|
@if (showTopToolbar) {
|
|
@@ -37230,7 +39972,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
37230
39972
|
[trackBy]="trackBy"
|
|
37231
39973
|
[groups]="group"
|
|
37232
39974
|
[detailTemplate]="detailTemplate"
|
|
37233
|
-
[filterable]="filterable"
|
|
39975
|
+
[filterable]="filterable"
|
|
39976
|
+
[rowHeight]="rowHeight"
|
|
39977
|
+
[detailRowHeight]="detailRowHeight">
|
|
37234
39978
|
</kendo-grid-rowpin-container>
|
|
37235
39979
|
}
|
|
37236
39980
|
|
|
@@ -37282,7 +40026,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
37282
40026
|
[trackBy]="trackBy"
|
|
37283
40027
|
[groups]="group"
|
|
37284
40028
|
[detailTemplate]="detailTemplate"
|
|
37285
|
-
[filterable]="filterable"
|
|
40029
|
+
[filterable]="filterable"
|
|
40030
|
+
[rowHeight]="rowHeight"
|
|
40031
|
+
[detailRowHeight]="detailRowHeight">
|
|
37286
40032
|
</kendo-grid-rowpin-container>
|
|
37287
40033
|
}
|
|
37288
40034
|
@if (showFooter) {
|
|
@@ -37370,7 +40116,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
37370
40116
|
[trackBy]="trackBy"
|
|
37371
40117
|
[groups]="group"
|
|
37372
40118
|
[detailTemplate]="detailTemplate"
|
|
37373
|
-
[filterable]="filterable"
|
|
40119
|
+
[filterable]="filterable"
|
|
40120
|
+
[rowHeight]="rowHeight"
|
|
40121
|
+
[detailRowHeight]="detailRowHeight">
|
|
37374
40122
|
</kendo-grid-rowpin-container>
|
|
37375
40123
|
}
|
|
37376
40124
|
<table
|
|
@@ -37457,7 +40205,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
37457
40205
|
[trackBy]="trackBy"
|
|
37458
40206
|
[groups]="group"
|
|
37459
40207
|
[detailTemplate]="detailTemplate"
|
|
37460
|
-
[filterable]="filterable"
|
|
40208
|
+
[filterable]="filterable"
|
|
40209
|
+
[rowHeight]="rowHeight"
|
|
40210
|
+
[detailRowHeight]="detailRowHeight"
|
|
40211
|
+
[size]="size"
|
|
40212
|
+
[loading]="loading">
|
|
37461
40213
|
</kendo-grid-rowpin-container>
|
|
37462
40214
|
}
|
|
37463
40215
|
}
|
|
@@ -37604,7 +40356,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
37604
40356
|
RowPinContainerComponent
|
|
37605
40357
|
]
|
|
37606
40358
|
}]
|
|
37607
|
-
}], ctorParameters: () => [{ type: i1$3.ScrollbarService }, { type: SelectionService }, { type: CellSelectionService }, { type: i0.ElementRef }, { type: GroupInfoService }, { type: GroupsService }, { type: ChangeNotificationService }, { type: DetailsService }, { type: EditService }, { type: FilterService }, { type: PDFService }, { type: ResponsiveService }, { type: i0.Renderer2 }, { type: ExcelService }, { type: CSVService }, { type: i0.NgZone }, { type: ScrollSyncService }, { type: DomEventsService }, { type: ColumnResizingService }, { type: i0.ChangeDetectorRef }, { type: ColumnReorderService }, { type: ColumnInfoService }, { type: NavigationService }, { type: SortService }, { type: ScrollRequestService }, { type: i1$2.LocalizationService }, { type: ContextService }, { type: SizingOptionsService }, { type: AdaptiveGridService }, { type: RowReorderService }, { type: DataMappingService }, { type: GridAIRequestResponseService }, { type: IdService }, { type: SearchService }, { type: RowPinService }], propDecorators: { data: [{
|
|
40359
|
+
}], ctorParameters: () => [{ type: i1$3.ScrollbarService }, { type: SelectionService }, { type: CellSelectionService }, { type: i0.ElementRef }, { type: GroupInfoService }, { type: GroupsService }, { type: ChangeNotificationService }, { type: DetailsService }, { type: EditService }, { type: FilterService }, { type: PDFService }, { type: ResponsiveService }, { type: i0.Renderer2 }, { type: ExcelService }, { type: CSVService }, { type: i0.NgZone }, { type: ScrollSyncService }, { type: DomEventsService }, { type: ColumnResizingService }, { type: i0.ChangeDetectorRef }, { type: ColumnReorderService }, { type: ColumnInfoService }, { type: NavigationService }, { type: SortService }, { type: ScrollRequestService }, { type: i1$2.LocalizationService }, { type: ContextService }, { type: SizingOptionsService }, { type: AdaptiveGridService }, { type: RowReorderService }, { type: DataMappingService }, { type: GridAIRequestResponseService }, { type: IdService }, { type: SearchService }, { type: RowPinService }, { type: PinnedRowTrackingService }], propDecorators: { data: [{
|
|
37608
40360
|
type: Input
|
|
37609
40361
|
}], pageSize: [{
|
|
37610
40362
|
type: Input
|
|
@@ -38063,6 +40815,9 @@ class DataBindingDirective {
|
|
|
38063
40815
|
*/
|
|
38064
40816
|
onRowReorder(ev) {
|
|
38065
40817
|
this.rowReorderService.reorderRows(ev, this.originalData);
|
|
40818
|
+
if (this.grid.pinnable !== false) {
|
|
40819
|
+
this.reorderPinnedRows(ev);
|
|
40820
|
+
}
|
|
38066
40821
|
this.rebind();
|
|
38067
40822
|
}
|
|
38068
40823
|
/**
|
|
@@ -38190,6 +40945,18 @@ class DataBindingDirective {
|
|
|
38190
40945
|
}
|
|
38191
40946
|
return process(data, { sort: this.state.sort }).data;
|
|
38192
40947
|
}
|
|
40948
|
+
reorderPinnedRows(ev) {
|
|
40949
|
+
if (this.grid.pinnedTopRows?.length) {
|
|
40950
|
+
if (this.grid.pinnedTopRows.some(row => row === ev.dropTargetRow?.dataItem)) {
|
|
40951
|
+
this.rowReorderService.reorderRows(ev, this.grid.pinnedTopRows);
|
|
40952
|
+
}
|
|
40953
|
+
}
|
|
40954
|
+
if (this.grid.pinnedBottomRows?.length) {
|
|
40955
|
+
if (this.grid.pinnedBottomRows.some(row => row === ev.dropTargetRow?.dataItem)) {
|
|
40956
|
+
this.rowReorderService.reorderRows(ev, this.grid.pinnedBottomRows);
|
|
40957
|
+
}
|
|
40958
|
+
}
|
|
40959
|
+
}
|
|
38193
40960
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: DataBindingDirective, deps: [{ token: GridComponent }, { token: i0.ChangeDetectorRef }, { token: LocalDataChangesService }, { token: RowReorderService }, { token: SearchService }, { token: RowPinService }, { token: ContextService }], target: i0.ɵɵFactoryTarget.Directive });
|
|
38194
40961
|
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.20", type: DataBindingDirective, isStandalone: true, selector: "[kendoGridBinding]", inputs: { skip: "skip", sort: "sort", filter: "filter", pageSize: "pageSize", group: "group", data: ["kendoGridBinding", "data"] }, exportAs: ["kendoGridBinding"], usesOnChanges: true, ngImport: i0 });
|
|
38195
40962
|
}
|
|
@@ -38287,11 +41054,20 @@ class LocalEditService {
|
|
|
38287
41054
|
for (let idx = 0; idx < data.length; idx++) {
|
|
38288
41055
|
if (item === data[idx]) {
|
|
38289
41056
|
data.splice(idx, 1);
|
|
41057
|
+
this.removePinnedRow(item);
|
|
38290
41058
|
this.dataChanged({ action: 'remove', item: item });
|
|
38291
41059
|
break;
|
|
38292
41060
|
}
|
|
38293
41061
|
}
|
|
38294
41062
|
}
|
|
41063
|
+
removePinnedRow(item) {
|
|
41064
|
+
if (Array.isArray(this.grid.pinnedTopRows) && this.grid.pinnedTopRows.includes(item)) {
|
|
41065
|
+
this.grid.pinnedTopRows = this.grid.pinnedTopRows.filter((r) => r !== item);
|
|
41066
|
+
}
|
|
41067
|
+
if (Array.isArray(this.grid.pinnedBottomRows) && this.grid.pinnedBottomRows.includes(item)) {
|
|
41068
|
+
this.grid.pinnedBottomRows = this.grid.pinnedBottomRows.filter((r) => r !== item);
|
|
41069
|
+
}
|
|
41070
|
+
}
|
|
38295
41071
|
assignValues(target, source) {
|
|
38296
41072
|
Object.assign(target, source);
|
|
38297
41073
|
}
|