@progress/kendo-angular-grid 24.0.0-develop.3 → 24.0.0-develop.31
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/NOTICE.txt +2599 -172
- package/columns/column-base.d.ts +4 -0
- package/columns/pin-column.component.d.ts +45 -0
- package/databinding.directive.d.ts +11 -1
- package/directives.d.ts +4 -3
- package/editing/edit.service.d.ts +1 -0
- package/editing/form/models.d.ts +1 -5
- package/editing-directives/local-edit.service.d.ts +1 -0
- package/fesm2022/progress-kendo-angular-grid.mjs +4083 -379
- package/grid.component.d.ts +64 -3
- package/grid.module.d.ts +106 -105
- package/grouping/group-header.component.d.ts +3 -3
- 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/index.d.ts +3 -0
- package/localization/messages.d.ts +33 -1
- package/navigation/logical-cell.directive.d.ts +4 -2
- package/navigation/navigation-metadata.d.ts +3 -1
- 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 +25 -25
- package/rendering/cell.component.d.ts +33 -6
- package/rendering/common/cell-context.d.ts +5 -0
- package/rendering/grid-table.directive.d.ts +0 -3
- package/rendering/list.component.d.ts +67 -1
- package/rendering/table-body.component.d.ts +5 -1
- package/rendering/toolbar/tools/smartbox/smartbox-component/smartbox.component.d.ts +4 -4
- package/row-pinning/pinned-row-tracking.service.d.ts +64 -0
- package/row-pinning/row-pin-container.component.d.ts +56 -0
- package/row-pinning/row-pin.service.d.ts +28 -0
- package/row-pinning/types.d.ts +42 -0
- package/schematics/ngAdd/index.js +7 -7
- package/scrolling/scroll-sync.service.d.ts +2 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@progress/kendo-angular-grid",
|
|
3
|
-
"version": "24.0.0-develop.
|
|
3
|
+
"version": "24.0.0-develop.31",
|
|
4
4
|
"description": "Kendo UI Grid for Angular - high performance data grid with paging, filtering, virtualization, CRUD, and more.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
6
6
|
"author": "Progress",
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
"package": {
|
|
95
95
|
"productName": "Kendo UI for Angular",
|
|
96
96
|
"productCode": "KENDOUIANGULAR",
|
|
97
|
-
"publishDate":
|
|
97
|
+
"publishDate": 1778841783,
|
|
98
98
|
"licensingDocsUrl": "https://www.telerik.com/kendo-angular-ui/my-license/"
|
|
99
99
|
}
|
|
100
100
|
},
|
|
@@ -105,34 +105,34 @@
|
|
|
105
105
|
"@angular/forms": "19 - 21",
|
|
106
106
|
"@angular/platform-browser": "19 - 21",
|
|
107
107
|
"@progress/kendo-data-query": "^1.7.3",
|
|
108
|
-
"@progress/kendo-drawing": "^1.
|
|
108
|
+
"@progress/kendo-drawing": "^1.25.0",
|
|
109
109
|
"@progress/kendo-licensing": "^1.11.0",
|
|
110
|
-
"@progress/kendo-angular-buttons": "24.0.0-develop.
|
|
111
|
-
"@progress/kendo-angular-common": "24.0.0-develop.
|
|
112
|
-
"@progress/kendo-angular-dateinputs": "24.0.0-develop.
|
|
113
|
-
"@progress/kendo-angular-layout": "24.0.0-develop.
|
|
114
|
-
"@progress/kendo-angular-navigation": "24.0.0-develop.
|
|
115
|
-
"@progress/kendo-angular-dropdowns": "24.0.0-develop.
|
|
116
|
-
"@progress/kendo-angular-excel-export": "24.0.0-develop.
|
|
117
|
-
"@progress/kendo-angular-icons": "24.0.0-develop.
|
|
118
|
-
"@progress/kendo-angular-indicators": "24.0.0-develop.
|
|
119
|
-
"@progress/kendo-angular-inputs": "24.0.0-develop.
|
|
120
|
-
"@progress/kendo-angular-conversational-ui": "24.0.0-develop.
|
|
121
|
-
"@progress/kendo-angular-intl": "24.0.0-develop.
|
|
122
|
-
"@progress/kendo-angular-l10n": "24.0.0-develop.
|
|
123
|
-
"@progress/kendo-angular-label": "24.0.0-develop.
|
|
124
|
-
"@progress/kendo-angular-menu": "24.0.0-develop.
|
|
125
|
-
"@progress/kendo-angular-pager": "24.0.0-develop.
|
|
126
|
-
"@progress/kendo-angular-pdf-export": "24.0.0-develop.
|
|
127
|
-
"@progress/kendo-angular-popup": "24.0.0-develop.
|
|
128
|
-
"@progress/kendo-angular-toolbar": "24.0.0-develop.
|
|
129
|
-
"@progress/kendo-angular-upload": "24.0.0-develop.
|
|
130
|
-
"@progress/kendo-angular-utils": "24.0.0-develop.
|
|
110
|
+
"@progress/kendo-angular-buttons": "24.0.0-develop.31",
|
|
111
|
+
"@progress/kendo-angular-common": "24.0.0-develop.31",
|
|
112
|
+
"@progress/kendo-angular-dateinputs": "24.0.0-develop.31",
|
|
113
|
+
"@progress/kendo-angular-layout": "24.0.0-develop.31",
|
|
114
|
+
"@progress/kendo-angular-navigation": "24.0.0-develop.31",
|
|
115
|
+
"@progress/kendo-angular-dropdowns": "24.0.0-develop.31",
|
|
116
|
+
"@progress/kendo-angular-excel-export": "24.0.0-develop.31",
|
|
117
|
+
"@progress/kendo-angular-icons": "24.0.0-develop.31",
|
|
118
|
+
"@progress/kendo-angular-indicators": "24.0.0-develop.31",
|
|
119
|
+
"@progress/kendo-angular-inputs": "24.0.0-develop.31",
|
|
120
|
+
"@progress/kendo-angular-conversational-ui": "24.0.0-develop.31",
|
|
121
|
+
"@progress/kendo-angular-intl": "24.0.0-develop.31",
|
|
122
|
+
"@progress/kendo-angular-l10n": "24.0.0-develop.31",
|
|
123
|
+
"@progress/kendo-angular-label": "24.0.0-develop.31",
|
|
124
|
+
"@progress/kendo-angular-menu": "24.0.0-develop.31",
|
|
125
|
+
"@progress/kendo-angular-pager": "24.0.0-develop.31",
|
|
126
|
+
"@progress/kendo-angular-pdf-export": "24.0.0-develop.31",
|
|
127
|
+
"@progress/kendo-angular-popup": "24.0.0-develop.31",
|
|
128
|
+
"@progress/kendo-angular-toolbar": "24.0.0-develop.31",
|
|
129
|
+
"@progress/kendo-angular-upload": "24.0.0-develop.31",
|
|
130
|
+
"@progress/kendo-angular-utils": "24.0.0-develop.31",
|
|
131
131
|
"rxjs": "^6.5.3 || ^7.0.0"
|
|
132
132
|
},
|
|
133
133
|
"dependencies": {
|
|
134
134
|
"tslib": "^2.3.1",
|
|
135
|
-
"@progress/kendo-angular-schematics": "24.0.0-develop.
|
|
135
|
+
"@progress/kendo-angular-schematics": "24.0.0-develop.31",
|
|
136
136
|
"@progress/kendo-common": "^1.0.1",
|
|
137
137
|
"@progress/kendo-file-saver": "^1.0.0",
|
|
138
138
|
"@progress/kendo-csv": "^1.0.0"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright © 2026 Progress Software Corporation. All rights reserved.
|
|
3
3
|
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
4
|
*-------------------------------------------------------------------------------------------*/
|
|
5
|
-
import { DoCheck, TemplateRef } from '@angular/core';
|
|
5
|
+
import { DoCheck, OnInit, OnDestroy, TemplateRef, ElementRef, NgZone, Renderer2 } from '@angular/core';
|
|
6
6
|
import { EditService } from '../editing/edit.service';
|
|
7
7
|
import { CommandColumnComponent } from '../columns/command-column.component';
|
|
8
8
|
import { ColumnComponent } from '../columns/column.component';
|
|
@@ -14,20 +14,32 @@ import { ContextService } from '../common/provider.service';
|
|
|
14
14
|
import { DetailTemplateDirective } from './details/detail-template.directive';
|
|
15
15
|
import { DetailsService } from './details/details.service';
|
|
16
16
|
import { LocalizationService } from '@progress/kendo-angular-l10n';
|
|
17
|
+
import { ContextMenuSelectEvent } from '@progress/kendo-angular-menu';
|
|
18
|
+
import { RowPinService } from '../row-pinning/row-pin.service';
|
|
19
|
+
import { ScrollSyncService } from '../scrolling/scroll-sync.service';
|
|
17
20
|
import * as i0 from "@angular/core";
|
|
18
21
|
/**
|
|
19
22
|
* @hidden
|
|
20
23
|
*/
|
|
21
|
-
export declare class CellComponent implements DoCheck {
|
|
24
|
+
export declare class CellComponent implements DoCheck, OnInit, OnDestroy {
|
|
22
25
|
private editService;
|
|
23
26
|
private idService;
|
|
24
27
|
private ctx;
|
|
25
28
|
private detailsService;
|
|
26
29
|
private localization;
|
|
30
|
+
private elementRef;
|
|
31
|
+
private ngZone;
|
|
32
|
+
private renderer;
|
|
33
|
+
private rowPinService;
|
|
27
34
|
private cellContext;
|
|
35
|
+
private inPinContainer;
|
|
36
|
+
private scrollSyncService;
|
|
28
37
|
get commandCellClass(): boolean;
|
|
29
38
|
get dragHandleCellClass(): boolean;
|
|
30
39
|
get dragRowHandleLabel(): string;
|
|
40
|
+
get rowPinLabel(): string;
|
|
41
|
+
private pinContextMenu;
|
|
42
|
+
private pinContextMenuTarget;
|
|
31
43
|
column: any;
|
|
32
44
|
columns: Array<any>;
|
|
33
45
|
columnIndex: number;
|
|
@@ -41,8 +53,13 @@ export declare class CellComponent implements DoCheck {
|
|
|
41
53
|
get rowIndex(): number;
|
|
42
54
|
dataItem: any;
|
|
43
55
|
reorderIcon: SVGIcon;
|
|
56
|
+
pinIcon: SVGIcon;
|
|
57
|
+
unpinIcon: SVGIcon;
|
|
44
58
|
minusIcon: SVGIcon;
|
|
45
59
|
plusIcon: SVGIcon;
|
|
60
|
+
onPinIconClick: () => void;
|
|
61
|
+
get pinMenuItems(): any[];
|
|
62
|
+
onContextMenuSelect(ev: ContextMenuSelectEvent): void;
|
|
46
63
|
detailButtonIconName(viewItem: any): string;
|
|
47
64
|
detailButtonSvgIcon(viewItem: any): SVGIcon;
|
|
48
65
|
detailButtonText(viewItem: any): string;
|
|
@@ -55,7 +72,7 @@ export declare class CellComponent implements DoCheck {
|
|
|
55
72
|
getTemplateContext(column?: any): any;
|
|
56
73
|
get isStackedLayoutMode(): boolean;
|
|
57
74
|
getEditTemplateContext(column?: any): any;
|
|
58
|
-
get
|
|
75
|
+
get rowTemplateContext(): any;
|
|
59
76
|
get format(): any;
|
|
60
77
|
isBoundColumn(column?: any): boolean;
|
|
61
78
|
isCheckboxColumn(column?: any): boolean;
|
|
@@ -64,17 +81,27 @@ export declare class CellComponent implements DoCheck {
|
|
|
64
81
|
get isSpanColumn(): boolean;
|
|
65
82
|
get children(): ColumnComponent[];
|
|
66
83
|
isRowReorderColumn(column?: any): boolean;
|
|
84
|
+
isRowPinColumn(column?: any): boolean;
|
|
85
|
+
get isRowPinnedTop(): boolean;
|
|
86
|
+
get isRowPinnedBottom(): boolean;
|
|
87
|
+
get isRowPinnable(): boolean;
|
|
67
88
|
isRowSelectable(column?: any): boolean;
|
|
68
89
|
private _rowIndex;
|
|
69
90
|
private isColumnEditable;
|
|
70
91
|
private _templateContext;
|
|
71
92
|
private _editTemplateContext;
|
|
72
|
-
private
|
|
73
|
-
|
|
93
|
+
private _rowTemplateContext;
|
|
94
|
+
private keyDownSub;
|
|
95
|
+
private scrollCloseSub;
|
|
96
|
+
constructor(editService: EditService, idService: IdService, ctx: ContextService, detailsService: DetailsService, localization: LocalizationService, elementRef: ElementRef, ngZone: NgZone, renderer: Renderer2, rowPinService: RowPinService, cellContext: CellContext, inPinContainer: boolean, scrollSyncService: ScrollSyncService);
|
|
97
|
+
ngOnInit(): void;
|
|
98
|
+
ngOnDestroy(): void;
|
|
74
99
|
ngDoCheck(): void;
|
|
100
|
+
private subscribeToScrollClose;
|
|
101
|
+
private onHostKeydown;
|
|
75
102
|
isCommand(column: any): column is CommandColumnComponent;
|
|
76
103
|
private isFieldEditable;
|
|
77
104
|
private updateCellContext;
|
|
78
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<CellComponent, [null, null, null, null, null, { optional: true; }]>;
|
|
105
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<CellComponent, [null, null, null, null, null, null, null, null, { optional: true; }, { optional: true; }, { optional: true; }, { optional: true; }]>;
|
|
79
106
|
static ɵcmp: i0.ɵɵComponentDeclaration<CellComponent, "[kendoGridCell]", never, { "column": { "alias": "column"; "required": false; }; "columns": { "alias": "columns"; "required": false; }; "columnIndex": { "alias": "columnIndex"; "required": false; }; "isNew": { "alias": "isNew"; "required": false; }; "isLoading": { "alias": "isLoading"; "required": false; }; "isVirtual": { "alias": "isVirtual"; "required": false; }; "loadingTemplate": { "alias": "loadingTemplate"; "required": false; }; "detailTemplate": { "alias": "detailTemplate"; "required": false; }; "item": { "alias": "item"; "required": false; }; "rowIndex": { "alias": "rowIndex"; "required": false; }; "dataItem": { "alias": "dataItem"; "required": false; }; }, {}, never, never, true, never>;
|
|
80
107
|
}
|
|
@@ -8,12 +8,17 @@ import { FocusGroup } from '../../navigation/focus-group';
|
|
|
8
8
|
* @hidden
|
|
9
9
|
*/
|
|
10
10
|
export declare const CELL_CONTEXT: InjectionToken<string>;
|
|
11
|
+
/**
|
|
12
|
+
* @hidden
|
|
13
|
+
*/
|
|
14
|
+
export declare const IS_PIN_CONTAINER: InjectionToken<boolean>;
|
|
11
15
|
/**
|
|
12
16
|
* @hidden
|
|
13
17
|
*/
|
|
14
18
|
export type CellContext = {
|
|
15
19
|
rowIndex?: number;
|
|
16
20
|
focusGroup?: FocusGroup;
|
|
21
|
+
inPinContainer?: boolean;
|
|
17
22
|
};
|
|
18
23
|
/**
|
|
19
24
|
* @hidden
|
|
@@ -2,21 +2,18 @@
|
|
|
2
2
|
* Copyright © 2026 Progress Software Corporation. All rights reserved.
|
|
3
3
|
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
4
|
*-------------------------------------------------------------------------------------------*/
|
|
5
|
-
import { ElementRef } from '@angular/core';
|
|
6
5
|
import { GridSize } from '../common/size-options';
|
|
7
6
|
import * as i0 from "@angular/core";
|
|
8
7
|
/**
|
|
9
8
|
* @hidden
|
|
10
9
|
*/
|
|
11
10
|
export declare class GridTableDirective {
|
|
12
|
-
private wrapper;
|
|
13
11
|
hostClass: boolean;
|
|
14
12
|
get sizeSmallClass(): boolean;
|
|
15
13
|
get sizeMediumClass(): boolean;
|
|
16
14
|
set size(size: GridSize);
|
|
17
15
|
get size(): GridSize;
|
|
18
16
|
private _size;
|
|
19
|
-
constructor(wrapper: ElementRef);
|
|
20
17
|
static ɵfac: i0.ɵɵFactoryDeclaration<GridTableDirective, never>;
|
|
21
18
|
static ɵdir: i0.ɵɵDirectiveDeclaration<GridTableDirective, "[kendoGridTable]", never, { "size": { "alias": "size"; "required": false; }; }, {}, never, never, true, never>;
|
|
22
19
|
}
|
|
@@ -33,6 +33,8 @@ import { ColumnInfoService } from '../common/column-info.service';
|
|
|
33
33
|
import { GridSize } from '../common/size-options';
|
|
34
34
|
import { ContextService } from '../common/provider.service';
|
|
35
35
|
import { DataMappingService } from '../data/data-mapping.service';
|
|
36
|
+
import { StickyGroupContainerComponent } from '../grouping/sticky-groups/sticky-group-container.component';
|
|
37
|
+
import { StickyGroupsService } from '../grouping/sticky-groups/sticky-groups.service';
|
|
36
38
|
import * as i0 from "@angular/core";
|
|
37
39
|
/**
|
|
38
40
|
* @hidden
|
|
@@ -62,6 +64,7 @@ export declare class ListComponent implements OnInit, OnDestroy, AfterViewInit,
|
|
|
62
64
|
private pdfService;
|
|
63
65
|
private columnInfo;
|
|
64
66
|
private dataMappingService;
|
|
67
|
+
private stickyGroupsService;
|
|
65
68
|
hostClass: boolean;
|
|
66
69
|
hostRole: string;
|
|
67
70
|
data: Array<any>;
|
|
@@ -93,6 +96,15 @@ export declare class ListComponent implements OnInit, OnDestroy, AfterViewInit,
|
|
|
93
96
|
columnsStartIdx: number;
|
|
94
97
|
allItems: any[];
|
|
95
98
|
itemsToRender: any[];
|
|
99
|
+
stickyGroupHeaderColumns: any[];
|
|
100
|
+
private stickyNeedsUpdate;
|
|
101
|
+
private stickyWasEnabled;
|
|
102
|
+
private pendingToggleScroll;
|
|
103
|
+
private skipScrollerAdjust;
|
|
104
|
+
private suppressStickyUpdates;
|
|
105
|
+
private suppressFocusScrollAdjust;
|
|
106
|
+
get hasStickyHeaders(): boolean;
|
|
107
|
+
get hasStickyFooters(): boolean;
|
|
96
108
|
get showFooter(): boolean;
|
|
97
109
|
get totalWidth(): number;
|
|
98
110
|
container: ElementRef;
|
|
@@ -100,6 +112,8 @@ export declare class ListComponent implements OnInit, OnDestroy, AfterViewInit,
|
|
|
100
112
|
lockedTable: ElementRef;
|
|
101
113
|
table: ElementRef;
|
|
102
114
|
resizeSensors: QueryList<ResizeSensorComponent>;
|
|
115
|
+
stickyHeaderContainer: StickyGroupContainerComponent;
|
|
116
|
+
stickyFooterContainer: StickyGroupContainerComponent;
|
|
103
117
|
private scroller;
|
|
104
118
|
private scrollerFactory;
|
|
105
119
|
private subscriptions;
|
|
@@ -128,7 +142,7 @@ export declare class ListComponent implements OnInit, OnDestroy, AfterViewInit,
|
|
|
128
142
|
private minRowHeight;
|
|
129
143
|
private handleSkipOnData;
|
|
130
144
|
private scrollToIndex;
|
|
131
|
-
constructor(scrollerFactory: any, detailsService: DetailsService, changeNotification: ChangeNotificationService, suspendService: SuspendService, groupsService: GroupsService, ngZone: NgZone, renderer: Renderer2, scrollSyncService: ScrollSyncService, resizeService: ResizeService, editService: EditService, supportService: ScrollbarService, navigationService: NavigationService, scrollRequestService: ScrollRequestService, ctx: ContextService, columnResizingService: ColumnResizingService, changeDetector: ChangeDetectorRef, pdfService: PDFService, columnInfo: ColumnInfoService, dataMappingService: DataMappingService);
|
|
145
|
+
constructor(scrollerFactory: any, detailsService: DetailsService, changeNotification: ChangeNotificationService, suspendService: SuspendService, groupsService: GroupsService, ngZone: NgZone, renderer: Renderer2, scrollSyncService: ScrollSyncService, resizeService: ResizeService, editService: EditService, supportService: ScrollbarService, navigationService: NavigationService, scrollRequestService: ScrollRequestService, ctx: ContextService, columnResizingService: ColumnResizingService, changeDetector: ChangeDetectorRef, pdfService: PDFService, columnInfo: ColumnInfoService, dataMappingService: DataMappingService, stickyGroupsService: StickyGroupsService);
|
|
132
146
|
ngOnInit(): void;
|
|
133
147
|
ngOnChanges(changes: {
|
|
134
148
|
[propertyName: string]: SimpleChange;
|
|
@@ -156,6 +170,13 @@ export declare class ListComponent implements OnInit, OnDestroy, AfterViewInit,
|
|
|
156
170
|
* @hidden
|
|
157
171
|
*/
|
|
158
172
|
fillViewportAfterColumnChange(): void;
|
|
173
|
+
/**
|
|
174
|
+
* Recalculates the virtual page size after the scrollable container height changes
|
|
175
|
+
* due to pinned row containers appearing or disappearing. Expands itemsToRender
|
|
176
|
+
* if the new viewport can display more rows than currently rendered.
|
|
177
|
+
* @hidden
|
|
178
|
+
*/
|
|
179
|
+
onPinnedContainerHeightChange(): void;
|
|
159
180
|
/**
|
|
160
181
|
* Checks if the virtual scroll state is out of sync with the expected position.
|
|
161
182
|
* Used to determine if resetVirtualScroll should be called.
|
|
@@ -170,6 +191,50 @@ export declare class ListComponent implements OnInit, OnDestroy, AfterViewInit,
|
|
|
170
191
|
* @hidden
|
|
171
192
|
*/
|
|
172
193
|
get isStacked(): boolean;
|
|
194
|
+
/**
|
|
195
|
+
* @hidden
|
|
196
|
+
* Updates sticky group header columns for the overlay. Called in ngDoCheck or on column changes.
|
|
197
|
+
*/
|
|
198
|
+
updateStickyGroupHeaderColumns(): void;
|
|
199
|
+
/**
|
|
200
|
+
* Measures actual rendered row heights from the DOM and feeds them into
|
|
201
|
+
* RowHeightService so its offsets reflect reality. Called in ngAfterViewChecked
|
|
202
|
+
* when stickyNeedsUpdate is true (data changed or scroll-to-group requested).
|
|
203
|
+
*/
|
|
204
|
+
private updateStickyRowHeights;
|
|
205
|
+
/**
|
|
206
|
+
* Handles sticky overlay header click: scrolls to the topmost sticky
|
|
207
|
+
* group header's real position so all overlay headers become visible
|
|
208
|
+
* real rows, then toggles the clicked group.
|
|
209
|
+
*/
|
|
210
|
+
private handleStickyScrollAndToggle;
|
|
211
|
+
/**
|
|
212
|
+
* After toggle, fixes up the virtual page so the correct rows are rendered
|
|
213
|
+
* around the target scroll position that was set pre-toggle.
|
|
214
|
+
*/
|
|
215
|
+
private applyPendingToggleScroll;
|
|
216
|
+
/**
|
|
217
|
+
* Scrolls the container so the real footer row at the pending flat index
|
|
218
|
+
* is visible at the bottom edge of the viewport.
|
|
219
|
+
*/
|
|
220
|
+
private scrollToStickyFooterTarget;
|
|
221
|
+
/**
|
|
222
|
+
* Scrolls the real grid body until the requested row is rendered in the real
|
|
223
|
+
* tbody, then focuses the corresponding real grid cell.
|
|
224
|
+
*/
|
|
225
|
+
private scrollToStickyRowTarget;
|
|
226
|
+
/**
|
|
227
|
+
* Focuses the rendered row requested from the sticky overlay.
|
|
228
|
+
*/
|
|
229
|
+
private focusRenderedStickyRow;
|
|
230
|
+
private getStickyTargetTbody;
|
|
231
|
+
private findStickyTargetRow;
|
|
232
|
+
/**
|
|
233
|
+
* Converts a sticky overlay flat-index request into a logical grid cell
|
|
234
|
+
* position that NavigationService can focus.
|
|
235
|
+
*/
|
|
236
|
+
private stickyTargetToLogicalCell;
|
|
237
|
+
private updateStickyGroups;
|
|
173
238
|
resetNavigationViewport(): void;
|
|
174
239
|
private detailExpand;
|
|
175
240
|
private attachContainerScroll;
|
|
@@ -179,6 +244,7 @@ export declare class ListComponent implements OnInit, OnDestroy, AfterViewInit,
|
|
|
179
244
|
private handleRowSync;
|
|
180
245
|
private handleRowNavigationLocked;
|
|
181
246
|
private scrollToVirtualRow;
|
|
247
|
+
private getStickyAdjustedScrollTop;
|
|
182
248
|
private scrollTo;
|
|
183
249
|
private scrollToItem;
|
|
184
250
|
private cleanupScroller;
|
|
@@ -72,9 +72,12 @@ export declare class TableBodyComponent implements OnInit, OnDestroy, OnChanges,
|
|
|
72
72
|
rowClass: RowClassFn;
|
|
73
73
|
rowHeight: number;
|
|
74
74
|
detailRowHeight: number;
|
|
75
|
+
isPinContainer: boolean;
|
|
76
|
+
pinPosition: 'top' | 'bottom' | null;
|
|
75
77
|
hostClass: boolean;
|
|
76
78
|
groupHeaderSlaveCellsCount: number;
|
|
77
79
|
groupHeaderColumns: any[];
|
|
80
|
+
private cachedDataRows;
|
|
78
81
|
private clickSubscription;
|
|
79
82
|
private touchSubscription;
|
|
80
83
|
private l10nSubscription;
|
|
@@ -108,6 +111,7 @@ export declare class TableBodyComponent implements OnInit, OnDestroy, OnChanges,
|
|
|
108
111
|
ngOnDestroy(): void;
|
|
109
112
|
isEditingCell(index: number, column: any): boolean;
|
|
110
113
|
isEditingRow(index: number): boolean;
|
|
114
|
+
isRowPinned(dataItem: any): boolean;
|
|
111
115
|
get isStackedMode(): boolean;
|
|
112
116
|
get hasGroupHeaderColumn(): boolean;
|
|
113
117
|
get columnsContainer(): any;
|
|
@@ -127,5 +131,5 @@ export declare class TableBodyComponent implements OnInit, OnDestroy, OnChanges,
|
|
|
127
131
|
private eventTarget;
|
|
128
132
|
private applyStickyRowsStyling;
|
|
129
133
|
static ɵfac: i0.ɵɵFactoryDeclaration<TableBodyComponent, never>;
|
|
130
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<TableBodyComponent, "[kendoGridTableBody]", never, { "columns": { "alias": "columns"; "required": false; }; "allColumns": { "alias": "allColumns"; "required": false; }; "groups": { "alias": "groups"; "required": false; }; "detailTemplate": { "alias": "detailTemplate"; "required": false; }; "noRecordsTemplate": { "alias": "noRecordsTemplate"; "required": false; }; "rowsToRender": { "alias": "rowsToRender"; "required": false; }; "skip": { "alias": "skip"; "required": false; }; "selectable": { "alias": "selectable"; "required": false; }; "filterable": { "alias": "filterable"; "required": false; }; "noRecordsText": { "alias": "noRecordsText"; "required": false; }; "isLocked": { "alias": "isLocked"; "required": false; }; "isLoading": { "alias": "isLoading"; "required": false; }; "isVirtual": { "alias": "isVirtual"; "required": false; }; "cellLoadingTemplate": { "alias": "cellLoadingTemplate"; "required": false; }; "skipGroupDecoration": { "alias": "skipGroupDecoration"; "required": false; }; "lockedColumnsCount": { "alias": "lockedColumnsCount"; "required": false; }; "totalColumnsCount": { "alias": "totalColumnsCount"; "required": false; }; "virtualColumns": { "alias": "virtualColumns"; "required": false; }; "trackBy": { "alias": "trackBy"; "required": false; }; "rowSticky": { "alias": "rowSticky"; "required": false; }; "totalColumns": { "alias": "totalColumns"; "required": false; }; "rowClass": { "alias": "rowClass"; "required": false; }; "rowHeight": { "alias": "rowHeight"; "required": false; }; "detailRowHeight": { "alias": "detailRowHeight"; "required": false; }; }, {}, never, never, true, never>;
|
|
134
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<TableBodyComponent, "[kendoGridTableBody]", never, { "columns": { "alias": "columns"; "required": false; }; "allColumns": { "alias": "allColumns"; "required": false; }; "groups": { "alias": "groups"; "required": false; }; "detailTemplate": { "alias": "detailTemplate"; "required": false; }; "noRecordsTemplate": { "alias": "noRecordsTemplate"; "required": false; }; "rowsToRender": { "alias": "rowsToRender"; "required": false; }; "skip": { "alias": "skip"; "required": false; }; "selectable": { "alias": "selectable"; "required": false; }; "filterable": { "alias": "filterable"; "required": false; }; "noRecordsText": { "alias": "noRecordsText"; "required": false; }; "isLocked": { "alias": "isLocked"; "required": false; }; "isLoading": { "alias": "isLoading"; "required": false; }; "isVirtual": { "alias": "isVirtual"; "required": false; }; "cellLoadingTemplate": { "alias": "cellLoadingTemplate"; "required": false; }; "skipGroupDecoration": { "alias": "skipGroupDecoration"; "required": false; }; "lockedColumnsCount": { "alias": "lockedColumnsCount"; "required": false; }; "totalColumnsCount": { "alias": "totalColumnsCount"; "required": false; }; "virtualColumns": { "alias": "virtualColumns"; "required": false; }; "trackBy": { "alias": "trackBy"; "required": false; }; "rowSticky": { "alias": "rowSticky"; "required": false; }; "totalColumns": { "alias": "totalColumns"; "required": false; }; "rowClass": { "alias": "rowClass"; "required": false; }; "rowHeight": { "alias": "rowHeight"; "required": false; }; "detailRowHeight": { "alias": "detailRowHeight"; "required": false; }; "isPinContainer": { "alias": "isPinContainer"; "required": false; }; "pinPosition": { "alias": "pinPosition"; "required": false; }; }, {}, never, never, true, never>;
|
|
131
135
|
}
|
|
@@ -77,14 +77,14 @@ export declare class SmartBoxComponent implements AfterViewInit, OnChanges, OnDe
|
|
|
77
77
|
isOpen: boolean;
|
|
78
78
|
checkIcon: SVGIcon;
|
|
79
79
|
clockArrowRotateIcon: SVGIcon;
|
|
80
|
-
|
|
80
|
+
fileClockIcon: SVGIcon;
|
|
81
81
|
searchIcon: SVGIcon;
|
|
82
82
|
zoomSparkleIcon: SVGIcon;
|
|
83
83
|
sparklesIcon: SVGIcon;
|
|
84
|
-
|
|
85
|
-
|
|
84
|
+
arrowUpIcon: SVGIcon;
|
|
85
|
+
stopIcon: SVGIcon;
|
|
86
86
|
xIcon: SVGIcon;
|
|
87
|
-
|
|
87
|
+
lightbulbIcon: SVGIcon;
|
|
88
88
|
searchListData: Array<{
|
|
89
89
|
text: string;
|
|
90
90
|
description: string;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**-----------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright © 2026 Progress Software Corporation. All rights reserved.
|
|
3
|
+
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
|
+
*-------------------------------------------------------------------------------------------*/
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
/**
|
|
7
|
+
* Tracks the relationship between pinned rows and their counterparts in the main data table.
|
|
8
|
+
* Use this service to find the main row index for a given pinned row data item,
|
|
9
|
+
* or to find the pinned counterpart of a main row.
|
|
10
|
+
*
|
|
11
|
+
* The service is updated automatically by the Grid when `pinnedTopRows`, `pinnedBottomRows`,
|
|
12
|
+
* or `data` changes. For reliable index resolution, pinned row data items must be
|
|
13
|
+
* reference-equal to the corresponding items in the main data array.
|
|
14
|
+
*
|
|
15
|
+
* @hidden
|
|
16
|
+
*/
|
|
17
|
+
export declare class PinnedRowTrackingService {
|
|
18
|
+
private topIndexMap;
|
|
19
|
+
private bottomIndexMap;
|
|
20
|
+
private mainIndexMap;
|
|
21
|
+
/**
|
|
22
|
+
* Updates the internal tracking maps based on the current pinned rows and main data.
|
|
23
|
+
* Called automatically by the Grid when relevant inputs change.
|
|
24
|
+
*
|
|
25
|
+
* @param topRows - The array of data items pinned to the top.
|
|
26
|
+
* @param bottomRows - The array of data items pinned to the bottom.
|
|
27
|
+
* @param data - The flat main data array for the current page.
|
|
28
|
+
* @param skip - The current page skip offset used to compute absolute row indices.
|
|
29
|
+
*/
|
|
30
|
+
update(topRows: any[], bottomRows: any[], data: any[], skip: number): void;
|
|
31
|
+
/**
|
|
32
|
+
* Updates the internal tracking maps using a pre-built data-item-to-index map from the main view.
|
|
33
|
+
* This handles grouping, sorting, and pagination correctly.
|
|
34
|
+
*
|
|
35
|
+
* @param topRows - The array of data items pinned to the top.
|
|
36
|
+
* @param bottomRows - The array of data items pinned to the bottom.
|
|
37
|
+
* @param dataToIndex - A map from data item references to their absolute row indices in the main view.
|
|
38
|
+
*/
|
|
39
|
+
updateFromIndexMap(topRows: any[], bottomRows: any[], dataToIndex: Map<any, number>): void;
|
|
40
|
+
/**
|
|
41
|
+
* Returns the absolute main row index for a pinned row data item, or `-1` if not found.
|
|
42
|
+
* The returned index matches the `index` property used by selection and editing services.
|
|
43
|
+
*/
|
|
44
|
+
getMainRowIndex(dataItem: any): number;
|
|
45
|
+
/**
|
|
46
|
+
* Returns `true` if the given data item is currently pinned to the top or bottom.
|
|
47
|
+
*/
|
|
48
|
+
isRowPinned(dataItem: any): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Returns the pin position (`'top'` or `'bottom'`) for the given data item,
|
|
51
|
+
* or `null` if the item is not pinned.
|
|
52
|
+
*/
|
|
53
|
+
getPinnedPosition(dataItem: any): 'top' | 'bottom' | null;
|
|
54
|
+
/**
|
|
55
|
+
* Returns the pinned counterpart for a given main row index,
|
|
56
|
+
* or `null` if the main row has no pinned counterpart.
|
|
57
|
+
*/
|
|
58
|
+
getPinnedCounterpart(mainIndex: number): {
|
|
59
|
+
dataItem: any;
|
|
60
|
+
position: 'top' | 'bottom';
|
|
61
|
+
} | null;
|
|
62
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<PinnedRowTrackingService, never>;
|
|
63
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<PinnedRowTrackingService>;
|
|
64
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**-----------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright © 2026 Progress Software Corporation. All rights reserved.
|
|
3
|
+
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
|
+
*-------------------------------------------------------------------------------------------*/
|
|
5
|
+
import { AfterViewChecked, ElementRef, TrackByFunction, QueryList } from '@angular/core';
|
|
6
|
+
import { LocalizationService } from '@progress/kendo-angular-l10n';
|
|
7
|
+
import { GridItem } from '../data/grid-item.interface';
|
|
8
|
+
import { ColumnsContainer } from '../columns/columns-container';
|
|
9
|
+
import { SelectableSettings } from '../selection/types';
|
|
10
|
+
import { ColumnBase } from '../columns/column-base';
|
|
11
|
+
import { GroupDescriptor } from '@progress/kendo-data-query';
|
|
12
|
+
import { DetailTemplateDirective } from '../rendering/details/detail-template.directive';
|
|
13
|
+
import { FilterableSettings } from '../filtering/filterable';
|
|
14
|
+
import { GridSize } from '../common/size-options';
|
|
15
|
+
import * as i0 from "@angular/core";
|
|
16
|
+
/**
|
|
17
|
+
* @hidden
|
|
18
|
+
*/
|
|
19
|
+
export declare class RowPinContainerComponent implements AfterViewChecked {
|
|
20
|
+
private readonly localization;
|
|
21
|
+
pinnedWrapper: ElementRef;
|
|
22
|
+
private readonly lockedTable;
|
|
23
|
+
private readonly pinnedTable;
|
|
24
|
+
hostClass: boolean;
|
|
25
|
+
get bottomClass(): boolean;
|
|
26
|
+
leafColumns: any[];
|
|
27
|
+
lockedLeafColumns: QueryList<ColumnBase>;
|
|
28
|
+
nonLockedLeafColumns: QueryList<ColumnBase>;
|
|
29
|
+
sort: any;
|
|
30
|
+
position: 'top' | 'bottom';
|
|
31
|
+
rowsToRender: Array<GridItem & {
|
|
32
|
+
showDetailRow?: boolean;
|
|
33
|
+
cells?: any[];
|
|
34
|
+
isExpanded?: boolean;
|
|
35
|
+
showDataItem?: boolean;
|
|
36
|
+
isHighlighted?: boolean;
|
|
37
|
+
}>;
|
|
38
|
+
totalColumns: ColumnsContainer;
|
|
39
|
+
lockedWidth: number;
|
|
40
|
+
nonLockedWidth: number;
|
|
41
|
+
isLocked: boolean;
|
|
42
|
+
selectable: SelectableSettings | boolean;
|
|
43
|
+
trackBy: TrackByFunction<any>;
|
|
44
|
+
groups: Array<GroupDescriptor>;
|
|
45
|
+
detailTemplate: DetailTemplateDirective;
|
|
46
|
+
filterable: FilterableSettings;
|
|
47
|
+
rowHeight: number;
|
|
48
|
+
detailRowHeight: number;
|
|
49
|
+
loading: boolean;
|
|
50
|
+
size: GridSize;
|
|
51
|
+
constructor(localization: LocalizationService);
|
|
52
|
+
ngAfterViewChecked(): void;
|
|
53
|
+
get ariaLabel(): string;
|
|
54
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<RowPinContainerComponent, never>;
|
|
55
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<RowPinContainerComponent, "kendo-grid-rowpin-container", never, { "leafColumns": { "alias": "leafColumns"; "required": false; }; "lockedLeafColumns": { "alias": "lockedLeafColumns"; "required": false; }; "nonLockedLeafColumns": { "alias": "nonLockedLeafColumns"; "required": false; }; "sort": { "alias": "sort"; "required": false; }; "position": { "alias": "position"; "required": false; }; "rowsToRender": { "alias": "rowsToRender"; "required": false; }; "totalColumns": { "alias": "totalColumns"; "required": false; }; "lockedWidth": { "alias": "lockedWidth"; "required": false; }; "nonLockedWidth": { "alias": "nonLockedWidth"; "required": false; }; "isLocked": { "alias": "isLocked"; "required": false; }; "selectable": { "alias": "selectable"; "required": false; }; "trackBy": { "alias": "trackBy"; "required": false; }; "groups": { "alias": "groups"; "required": false; }; "detailTemplate": { "alias": "detailTemplate"; "required": false; }; "filterable": { "alias": "filterable"; "required": false; }; "rowHeight": { "alias": "rowHeight"; "required": false; }; "detailRowHeight": { "alias": "detailRowHeight"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; "size": { "alias": "size"; "required": false; }; }, {}, never, never, true, never>;
|
|
56
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**-----------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright © 2026 Progress Software Corporation. All rights reserved.
|
|
3
|
+
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
|
+
*-------------------------------------------------------------------------------------------*/
|
|
5
|
+
import { EventEmitter } from '@angular/core';
|
|
6
|
+
import { ContextService } from '../common/provider.service';
|
|
7
|
+
import { LocalizationService } from '@progress/kendo-angular-l10n';
|
|
8
|
+
import { RowPinEvent } from './types';
|
|
9
|
+
import * as i0 from "@angular/core";
|
|
10
|
+
/**
|
|
11
|
+
* @hidden
|
|
12
|
+
*/
|
|
13
|
+
export declare class RowPinService {
|
|
14
|
+
private ctx;
|
|
15
|
+
private localization;
|
|
16
|
+
changes: EventEmitter<RowPinEvent>;
|
|
17
|
+
constructor(ctx: ContextService, localization: LocalizationService);
|
|
18
|
+
handleContextMenuAction(ev: any): void;
|
|
19
|
+
updatePinnedRows(ev: RowPinEvent): void;
|
|
20
|
+
get pinnedTopRowMenuItems(): any[];
|
|
21
|
+
get pinnedBottomRowMenuItems(): any[];
|
|
22
|
+
get unpinnedRowMenuItems(): any[];
|
|
23
|
+
get unpinRowMenuItem(): any;
|
|
24
|
+
get pinToTopMenuItem(): any;
|
|
25
|
+
get pinToBottomMenuItem(): any;
|
|
26
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<RowPinService, never>;
|
|
27
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<RowPinService>;
|
|
28
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**-----------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright © 2026 Progress Software Corporation. All rights reserved.
|
|
3
|
+
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
|
+
*-------------------------------------------------------------------------------------------*/
|
|
5
|
+
import { RowArgs } from "../rendering/common/row-args";
|
|
6
|
+
/**
|
|
7
|
+
* Arguments for the [`rowPinChange`](https://www.telerik.com/kendo-angular-ui/components/grid/api/gridcomponent#rowpinchange) event.
|
|
8
|
+
*/
|
|
9
|
+
export interface RowPinEvent {
|
|
10
|
+
/**
|
|
11
|
+
* The data item that triggered the pin update.
|
|
12
|
+
*/
|
|
13
|
+
dataItem: any;
|
|
14
|
+
/**
|
|
15
|
+
* The updated collection of items pinned to the top of the Grid.
|
|
16
|
+
*/
|
|
17
|
+
pinnedTopRows: Array<any>;
|
|
18
|
+
/**
|
|
19
|
+
* The updated collection of items pinned to the bottom of the Grid.
|
|
20
|
+
*/
|
|
21
|
+
pinnedBottomRows: Array<any>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Sets the allowed position for pinning rows in the Grid.
|
|
25
|
+
*
|
|
26
|
+
* The available values are:
|
|
27
|
+
* * `top`—Allows pinning rows to the top of the Grid only.
|
|
28
|
+
* * `bottom`—Allows pinning rows to the bottom of the Grid only.
|
|
29
|
+
* * `both`—Allows pinning rows to both the top and bottom of the Grid.
|
|
30
|
+
*/
|
|
31
|
+
export type GridRowPinLocation = 'top' | 'bottom' | 'both';
|
|
32
|
+
/**
|
|
33
|
+
* Represents the callback used to determine whether a data row is pinnable. Used by the [`isRowPinnable`](https://www.telerik.com/kendo-angular-ui/components/grid/api/gridcomponent#isrowpinnable) property.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* isRowPinnableCallback({ dataItem, index }) {
|
|
38
|
+
* return index % 2 === 0;
|
|
39
|
+
* }
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export type RowPinnableFn = (context: RowArgs) => boolean;
|
|
@@ -9,19 +9,19 @@ const schematics_1 = require("@angular-devkit/schematics");
|
|
|
9
9
|
function default_1(options) {
|
|
10
10
|
const finalOptions = Object.assign(Object.assign({}, options), { mainNgModule: 'GridModule', package: 'grid', peerDependencies: {
|
|
11
11
|
// peer deps of the dropdowns
|
|
12
|
-
'@progress/kendo-angular-treeview': '24.0.0-develop.
|
|
13
|
-
'@progress/kendo-angular-navigation': '24.0.0-develop.
|
|
12
|
+
'@progress/kendo-angular-treeview': '24.0.0-develop.31',
|
|
13
|
+
'@progress/kendo-angular-navigation': '24.0.0-develop.31',
|
|
14
14
|
// peer dependency of kendo-angular-inputs
|
|
15
|
-
'@progress/kendo-angular-dialog': '24.0.0-develop.
|
|
15
|
+
'@progress/kendo-angular-dialog': '24.0.0-develop.31',
|
|
16
16
|
// peer dependency of kendo-angular-icons
|
|
17
17
|
'@progress/kendo-svg-icons': '^4.0.0',
|
|
18
18
|
// peer dependency of kendo-angular-layout
|
|
19
|
-
'@progress/kendo-angular-progressbar': '24.0.0-develop.
|
|
19
|
+
'@progress/kendo-angular-progressbar': '24.0.0-develop.31',
|
|
20
20
|
// transitive peer dependencies from toolbar
|
|
21
|
-
'@progress/kendo-angular-indicators': '24.0.0-develop.
|
|
21
|
+
'@progress/kendo-angular-indicators': '24.0.0-develop.31',
|
|
22
22
|
// transitive peer dependencies from conversational-ui
|
|
23
|
-
'@progress/kendo-angular-menu': '24.0.0-develop.
|
|
24
|
-
'@progress/kendo-angular-upload': '24.0.0-develop.
|
|
23
|
+
'@progress/kendo-angular-menu': '24.0.0-develop.31',
|
|
24
|
+
'@progress/kendo-angular-upload': '24.0.0-develop.31'
|
|
25
25
|
} });
|
|
26
26
|
return (0, schematics_1.externalSchematic)('@progress/kendo-angular-schematics', 'ng-add', finalOptions);
|
|
27
27
|
}
|
|
@@ -21,10 +21,9 @@ export declare class ScrollSyncService {
|
|
|
21
21
|
private elements;
|
|
22
22
|
private source;
|
|
23
23
|
private subscriptions;
|
|
24
|
-
private
|
|
25
|
-
private bodySubscription;
|
|
24
|
+
private elementSubscriptions;
|
|
26
25
|
constructor(ngZone: NgZone);
|
|
27
|
-
registerEmitter(el: any, sourceType: "body" | "header" | "footer"): void;
|
|
26
|
+
registerEmitter(el: any, sourceType: "body" | "header" | "footer" | "pinnedContainer"): void;
|
|
28
27
|
/**
|
|
29
28
|
* destroy
|
|
30
29
|
*/
|