@progress/kendo-angular-grid 20.1.0-develop.9 → 20.1.1-develop.1

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.
Files changed (33) hide show
  1. package/columns/column.component.d.ts +8 -1
  2. package/databinding.directive.d.ts +1 -1
  3. package/esm2022/columns/column.component.mjs +9 -1
  4. package/esm2022/common/clipboard.directive.mjs +3 -0
  5. package/esm2022/databinding.directive.mjs +1 -1
  6. package/esm2022/filtering/menu/filter-menu-container.component.mjs +120 -31
  7. package/esm2022/filtering/menu/filter-menu.component.mjs +4 -6
  8. package/esm2022/filtering/multicheckbox-filter.component.mjs +313 -0
  9. package/esm2022/grid.component.mjs +25 -12
  10. package/esm2022/index.mjs +1 -0
  11. package/esm2022/localization/messages.mjs +28 -1
  12. package/esm2022/package-metadata.mjs +2 -2
  13. package/esm2022/pdf/pdf.component.mjs +8 -3
  14. package/esm2022/rendering/cell.component.mjs +2 -2
  15. package/esm2022/rendering/common/field-accessor.pipe.mjs +1 -1
  16. package/esm2022/rendering/common/format.pipe.mjs +37 -0
  17. package/esm2022/rendering/header/header.component.mjs +1 -1
  18. package/esm2022/rendering/list.component.mjs +2 -2
  19. package/esm2022/rendering/table-body.component.mjs +4 -2
  20. package/esm2022/rendering/toolbar/tools/group-toolbar-tool.component.mjs +4 -3
  21. package/esm2022/row-reordering/row-reorder.service.mjs +3 -1
  22. package/esm2022/scrolling/scroller.service.mjs +0 -3
  23. package/fesm2022/progress-kendo-angular-grid.mjs +1969 -1502
  24. package/filtering/filterable.d.ts +23 -0
  25. package/filtering/menu/filter-menu-container.component.d.ts +5 -1
  26. package/filtering/menu/filter-menu.component.d.ts +3 -4
  27. package/filtering/multicheckbox-filter.component.d.ts +50 -0
  28. package/grid.component.d.ts +4 -6
  29. package/index.d.ts +1 -0
  30. package/localization/messages.d.ts +22 -1
  31. package/package.json +21 -21
  32. package/rendering/common/format.pipe.d.ts +17 -0
  33. package/schematics/ngAdd/index.js +4 -4
@@ -0,0 +1,313 @@
1
+ /**-----------------------------------------------------------------------------------------
2
+ * Copyright © 2025 Progress Software Corporation. All rights reserved.
3
+ * Licensed under commercial license. See LICENSE.md in the project root for more information
4
+ *-------------------------------------------------------------------------------------------*/
5
+ import { Component, Input, EventEmitter, Output, ViewChild } from '@angular/core';
6
+ import { filterBy } from '@progress/kendo-data-query';
7
+ import { NgFor, NgIf } from '@angular/common';
8
+ import { CheckBoxComponent, TextBoxComponent, TextBoxPrefixTemplateDirective } from '@progress/kendo-angular-inputs';
9
+ import { IconWrapperComponent } from '@progress/kendo-angular-icons';
10
+ import { searchIcon } from '@progress/kendo-svg-icons';
11
+ import { ContextService } from '../common/provider.service';
12
+ import { LocalDataChangesService } from '../editing/local-data-changes.service';
13
+ import { FormatPipe } from '../rendering/common/format.pipe';
14
+ import { isPresent, replaceMessagePlaceholder } from '@progress/kendo-angular-common';
15
+ import { FilterInputDirective } from './filter-input.directive';
16
+ import * as i0 from "@angular/core";
17
+ import * as i1 from "../common/provider.service";
18
+ import * as i2 from "../editing/local-data-changes.service";
19
+ /**
20
+ * @hidden
21
+ */
22
+ export class MultiCheckboxFilterComponent {
23
+ ctx;
24
+ dataChangesService;
25
+ column;
26
+ filterChange = new EventEmitter();
27
+ filterInput;
28
+ constructor(ctx, dataChangesService) {
29
+ this.ctx = ctx;
30
+ this.dataChangesService = dataChangesService;
31
+ }
32
+ listData = [];
33
+ searchIcon = searchIcon;
34
+ showSelectAll = true;
35
+ currentlySelected = new Set();
36
+ isSearched = false;
37
+ currentFilter;
38
+ filterChangeSub;
39
+ baseListData = [];
40
+ ngOnInit() {
41
+ this.initializeData();
42
+ this.currentFilter = this.ctx.grid?.filter ?? this.emptyFilter();
43
+ this.updateSelectionFromFilter();
44
+ if (this.currentFilter) {
45
+ this.filterChange.emit(this.currentFilter);
46
+ }
47
+ }
48
+ ngAfterViewInit() {
49
+ if (this.filterInput) {
50
+ this.filterChangeSub = this.filterInput.change.subscribe(this.onSearch.bind(this));
51
+ }
52
+ }
53
+ ngOnDestroy() {
54
+ if (this.filterChangeSub) {
55
+ this.filterChangeSub.unsubscribe();
56
+ this.filterChangeSub = null;
57
+ }
58
+ }
59
+ isItemSelected(item) {
60
+ return this.currentlySelected.has(item);
61
+ }
62
+ onSearch(value) {
63
+ const searchValue = value;
64
+ this.isSearched = searchValue.length > 0;
65
+ this.showSelectAll = !this.isSearched;
66
+ if (!searchValue) {
67
+ this.listData = [...this.baseListData];
68
+ }
69
+ else {
70
+ this.listData = filterBy(this.baseListData, { operator: 'contains', value: searchValue });
71
+ }
72
+ }
73
+ handleCheckBoxChange(checkedState, value, selectAllChecked) {
74
+ const field = this.column?.field;
75
+ if (!field) {
76
+ return;
77
+ }
78
+ if (!this.currentFilter) {
79
+ this.currentFilter = this.emptyFilter();
80
+ }
81
+ const newFilter = this.currentFilter;
82
+ const filters = [...newFilter.filters];
83
+ const compositeIndex = this.getCompositeFilterIndex(newFilter);
84
+ let fieldFilters = [];
85
+ if (compositeIndex !== -1 && filters[compositeIndex].filters && !selectAllChecked) {
86
+ fieldFilters = [...filters[compositeIndex].filters];
87
+ }
88
+ if (checkedState && selectAllChecked) {
89
+ this.listData.forEach(item => {
90
+ if (!fieldFilters.some(f => f.value === item)) {
91
+ fieldFilters.push({ field, operator: 'eq', value: item });
92
+ }
93
+ });
94
+ }
95
+ else if (!checkedState && selectAllChecked) {
96
+ fieldFilters = [];
97
+ }
98
+ else if (checkedState) {
99
+ if (!fieldFilters.some(f => f.value === value)) {
100
+ fieldFilters.push({ field, operator: 'eq', value });
101
+ }
102
+ }
103
+ else {
104
+ const idx = fieldFilters.findIndex(f => f.value === value);
105
+ if (idx > -1) {
106
+ fieldFilters.splice(idx, 1);
107
+ }
108
+ }
109
+ if (fieldFilters.length === 0) {
110
+ if (compositeIndex !== -1) {
111
+ filters.splice(compositeIndex, 1);
112
+ }
113
+ }
114
+ else {
115
+ const block = { logic: 'or', filters: fieldFilters };
116
+ if (compositeIndex !== -1) {
117
+ filters[compositeIndex] = block;
118
+ }
119
+ else {
120
+ filters.push(block);
121
+ }
122
+ }
123
+ newFilter.logic = 'and';
124
+ newFilter.filters = filters;
125
+ this.currentFilter = newFilter;
126
+ this.updateSelectionFromFilter();
127
+ this.filterChange.emit(this.currentFilter);
128
+ }
129
+ get filteredGridData() {
130
+ return filterBy(this.gridData, this.ctx.grid?.filter);
131
+ }
132
+ get selectAllChecked() {
133
+ if (!this.listData || this.listData.length === 0) {
134
+ return false;
135
+ }
136
+ const total = this.listData.length;
137
+ const selectedInView = this.listData.filter(i => this.currentlySelected.has(i)).length;
138
+ if (selectedInView === 0) {
139
+ return false;
140
+ }
141
+ if (selectedInView === total) {
142
+ return true;
143
+ }
144
+ return 'indeterminate';
145
+ }
146
+ get gridData() {
147
+ let data = [];
148
+ const isLocalData = isPresent(this.ctx?.dataBindingDirective);
149
+ if (isPresent(this.normalizedFilterVariant.data)) {
150
+ data = this.normalizedFilterVariant.data;
151
+ }
152
+ else if (isLocalData) {
153
+ data = this.dataChangesService.data;
154
+ }
155
+ else {
156
+ data = this.ctx.grid?.flatData;
157
+ }
158
+ return data || [];
159
+ }
160
+ get normalizedFilterVariant() {
161
+ const defaultMultiCheckboxSettings = { variant: 'multiCheckbox', search: true };
162
+ if (typeof this.column?.filterVariant === 'string') {
163
+ return {
164
+ variant: this.column.filterVariant,
165
+ search: true
166
+ };
167
+ }
168
+ return Object.assign(defaultMultiCheckboxSettings, this.column?.filterVariant);
169
+ }
170
+ get selectedItemsMessage() {
171
+ const localizationMsg = this.messageFor('multiCheckboxFilterSelectedItemsCount') || '';
172
+ return replaceMessagePlaceholder(localizationMsg, 'selectedItemsCount', this.currentlySelected.size.toString());
173
+ }
174
+ messageFor(key) {
175
+ return this.ctx.localization.get(key);
176
+ }
177
+ getUniqueDateValues(data) {
178
+ return data.reduce((acc, current) => {
179
+ const value = current[this.column.field];
180
+ if (value instanceof Date && acc.findIndex(d => d.getTime() === value.getTime()) === -1) {
181
+ acc.push(value);
182
+ }
183
+ return acc;
184
+ }, []);
185
+ }
186
+ initializeData() {
187
+ if (!this.column) {
188
+ this.baseListData = [];
189
+ return;
190
+ }
191
+ const isDate = this.column.filter === 'date';
192
+ if (isDate) {
193
+ const dates = this.getUniqueDateValues(this.gridData);
194
+ const sortedDates = [...dates].sort((a, b) => a - b);
195
+ this.baseListData = sortedDates;
196
+ }
197
+ else {
198
+ const field = this.column.field;
199
+ const mapped = this.gridData.map(item => item?.[field]);
200
+ this.baseListData = [...new Set(mapped)].sort((a, b) => {
201
+ if (a > b) {
202
+ return 1;
203
+ }
204
+ if (a < b) {
205
+ return -1;
206
+ }
207
+ return 0;
208
+ });
209
+ }
210
+ this.listData = [...this.baseListData];
211
+ }
212
+ emptyFilter() { return { filters: [], logic: 'and' }; }
213
+ getCompositeFilterIndex(filter) {
214
+ const field = this.column?.field;
215
+ return filter.filters.findIndex((f) => f.filters?.length && f.filters[0].field === field);
216
+ }
217
+ updateSelectionFromFilter() {
218
+ this.currentlySelected.clear();
219
+ if (!this.currentFilter || !this.column?.field) {
220
+ return;
221
+ }
222
+ const idx = this.getCompositeFilterIndex(this.currentFilter);
223
+ if (idx === -1) {
224
+ return;
225
+ }
226
+ const block = this.currentFilter.filters[idx];
227
+ if (block && Array.isArray(block.filters)) {
228
+ block.filters.forEach((f) => {
229
+ if (f.field === this.column.field && f.operator === 'eq') {
230
+ this.currentlySelected.add(f.value);
231
+ }
232
+ });
233
+ }
234
+ }
235
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: MultiCheckboxFilterComponent, deps: [{ token: i1.ContextService }, { token: i2.LocalDataChangesService }], target: i0.ɵɵFactoryTarget.Component });
236
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: MultiCheckboxFilterComponent, isStandalone: true, selector: "kendo-grid-multicheckbox-filter", inputs: { column: "column" }, outputs: { filterChange: "filterChange" }, viewQueries: [{ propertyName: "filterInput", first: true, predicate: FilterInputDirective, descendants: true }], ngImport: i0, template: `
237
+ <kendo-textbox *ngIf="normalizedFilterVariant.search"
238
+ kendoFilterInput
239
+ class="k-searchbox"
240
+ [placeholder]="messageFor('multiCheckboxFilterSearchPlaceholder')">
241
+ <ng-template kendoTextBoxPrefixTemplate>
242
+ <kendo-icon-wrapper innerCssClass="k-input-icon" name="search" [svgIcon]="searchIcon"></kendo-icon-wrapper>
243
+ </ng-template>
244
+ </kendo-textbox>
245
+ <ul class="k-reset k-multicheck-wrap">
246
+ <li class="k-item k-check-all-wrap" *ngIf="showSelectAll">
247
+ <label class="k-label k-checkbox-label" role="option">
248
+ <kendo-checkbox
249
+ [checkedState]="selectAllChecked"
250
+ (checkedStateChange)="handleCheckBoxChange($event, null, true)">
251
+ </kendo-checkbox>
252
+ <span>{{ messageFor('multiCheckboxFilterSelectAllLabel') }}</span>
253
+ </label>
254
+ </li>
255
+ <li class="k-item" *ngFor="let item of listData">
256
+ <label class="k-label k-checkbox-label" role="option">
257
+ <kendo-checkbox
258
+ [checkedState]="isItemSelected(item)"
259
+ (checkedStateChange)="handleCheckBoxChange($event, item)">
260
+ </kendo-checkbox>
261
+ <span>{{ item | format: column.format }}</span>
262
+ </label>
263
+ </li>
264
+ </ul>
265
+ <div class="k-filter-selected-items">{{selectedItemsMessage}}</div>
266
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: CheckBoxComponent, selector: "kendo-checkbox", inputs: ["checkedState", "rounded"], outputs: ["checkedStateChange"], exportAs: ["kendoCheckBox"] }, { kind: "component", type: TextBoxComponent, selector: "kendo-textbox", inputs: ["focusableId", "title", "type", "disabled", "readonly", "tabindex", "value", "selectOnFocus", "showSuccessIcon", "showErrorIcon", "clearButton", "successIcon", "successSvgIcon", "errorIcon", "errorSvgIcon", "clearButtonIcon", "clearButtonSvgIcon", "size", "rounded", "fillMode", "tabIndex", "placeholder", "maxlength", "inputAttributes"], outputs: ["valueChange", "inputFocus", "inputBlur", "focus", "blur"], exportAs: ["kendoTextBox"] }, { kind: "directive", type: TextBoxPrefixTemplateDirective, selector: "[kendoTextBoxPrefixTemplate]", inputs: ["showSeparator"] }, { kind: "component", type: IconWrapperComponent, selector: "kendo-icon-wrapper", inputs: ["name", "svgIcon", "innerCssClass", "customFontClass", "size"], exportAs: ["kendoIconWrapper"] }, { kind: "pipe", type: FormatPipe, name: "format" }, { kind: "directive", type: FilterInputDirective, selector: "[kendoFilterInput]", inputs: ["filterDelay", "columnLabel", "value"] }] });
267
+ }
268
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: MultiCheckboxFilterComponent, decorators: [{
269
+ type: Component,
270
+ args: [{
271
+ selector: 'kendo-grid-multicheckbox-filter',
272
+ template: `
273
+ <kendo-textbox *ngIf="normalizedFilterVariant.search"
274
+ kendoFilterInput
275
+ class="k-searchbox"
276
+ [placeholder]="messageFor('multiCheckboxFilterSearchPlaceholder')">
277
+ <ng-template kendoTextBoxPrefixTemplate>
278
+ <kendo-icon-wrapper innerCssClass="k-input-icon" name="search" [svgIcon]="searchIcon"></kendo-icon-wrapper>
279
+ </ng-template>
280
+ </kendo-textbox>
281
+ <ul class="k-reset k-multicheck-wrap">
282
+ <li class="k-item k-check-all-wrap" *ngIf="showSelectAll">
283
+ <label class="k-label k-checkbox-label" role="option">
284
+ <kendo-checkbox
285
+ [checkedState]="selectAllChecked"
286
+ (checkedStateChange)="handleCheckBoxChange($event, null, true)">
287
+ </kendo-checkbox>
288
+ <span>{{ messageFor('multiCheckboxFilterSelectAllLabel') }}</span>
289
+ </label>
290
+ </li>
291
+ <li class="k-item" *ngFor="let item of listData">
292
+ <label class="k-label k-checkbox-label" role="option">
293
+ <kendo-checkbox
294
+ [checkedState]="isItemSelected(item)"
295
+ (checkedStateChange)="handleCheckBoxChange($event, item)">
296
+ </kendo-checkbox>
297
+ <span>{{ item | format: column.format }}</span>
298
+ </label>
299
+ </li>
300
+ </ul>
301
+ <div class="k-filter-selected-items">{{selectedItemsMessage}}</div>
302
+ `,
303
+ standalone: true,
304
+ imports: [NgFor, NgIf, CheckBoxComponent, TextBoxComponent, TextBoxPrefixTemplateDirective, IconWrapperComponent, FormatPipe, FilterInputDirective]
305
+ }]
306
+ }], ctorParameters: function () { return [{ type: i1.ContextService }, { type: i2.LocalDataChangesService }]; }, propDecorators: { column: [{
307
+ type: Input
308
+ }], filterChange: [{
309
+ type: Output
310
+ }], filterInput: [{
311
+ type: ViewChild,
312
+ args: [FilterInputDirective]
313
+ }] } });
@@ -2,7 +2,7 @@
2
2
  * Copyright © 2025 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 { Component, ContentChildren, ElementRef, EventEmitter, HostBinding, Input, Output, Renderer2, QueryList, ViewChild, isDevMode, NgZone, ViewChildren, ChangeDetectorRef, ViewEncapsulation, ViewContainerRef, ContentChild } from '@angular/core';
5
+ import { Component, ContentChildren, ElementRef, EventEmitter, HostBinding, Input, Output, Renderer2, QueryList, ViewChild, isDevMode, NgZone, ViewChildren, ChangeDetectorRef, ViewEncapsulation, ViewContainerRef } from '@angular/core';
6
6
  import { ZoneAwareEventEmitter } from './common/event-emitter';
7
7
  import { FormControl, FormGroup } from '@angular/forms';
8
8
  import { merge } from 'rxjs';
@@ -101,7 +101,6 @@ import { AdaptiveRendererComponent } from './adaptiveness/adaptive-renderer.comp
101
101
  import { ColumnMenuService } from './column-menu/column-menu.service';
102
102
  import { MenuTabbingService } from './filtering/menu/menu-tabbing.service';
103
103
  import { DataMappingService } from './data/data-mapping.service';
104
- import { AIAssistantToolbarDirective } from './rendering/toolbar/tools/ai-assistant/ai-tool.directive';
105
104
  import * as i0 from "@angular/core";
106
105
  import * as i1 from "./layout/browser-support.service";
107
106
  import * as i2 from "./selection/selection.service";
@@ -312,7 +311,7 @@ export class GridComponent {
312
311
  */
313
312
  selectable = false;
314
313
  /**
315
- * Sets the descriptors for sorting the data ([see example]({% slug sorting_grid %})).
314
+ * Sets the descriptors for sorting the data ([see example](slug:manual_sorting_grid)).
316
315
  */
317
316
  set sort(value) {
318
317
  if (isArray(value)) {
@@ -345,11 +344,11 @@ export class GridComponent {
345
344
  */
346
345
  trackBy = defaultTrackBy;
347
346
  /**
348
- * Sets the filter descriptor for the data ([see examples]({% slug filtering_grid %})).
347
+ * Sets the filter descriptor for the data ([see examples](slug:manual_filtering_grid)).
349
348
  */
350
349
  filter;
351
350
  /**
352
- * Sets the descriptors for grouping the data ([see example]({% slug grouping_grid %})).
351
+ * Sets the descriptors for grouping the data ([see example](slug:manual_grouping_grid)).
353
352
  */
354
353
  set group(value) {
355
354
  if (isArray(value)) {
@@ -924,7 +923,6 @@ export class GridComponent {
924
923
  this._customToolbarTemplate = customToolbarTemplate;
925
924
  }
926
925
  columnMenuTemplates;
927
- aiAssistantToolbarTool;
928
926
  lockedHeader;
929
927
  header;
930
928
  footer = new QueryList();
@@ -2494,7 +2492,7 @@ export class GridComponent {
2494
2492
  ColumnMenuService,
2495
2493
  MenuTabbingService,
2496
2494
  DataMappingService
2497
- ], queries: [{ propertyName: "aiAssistantToolbarTool", first: true, predicate: AIAssistantToolbarDirective, descendants: true }, { 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: "footer", predicate: ["footer"], descendants: true }], exportAs: ["kendoGrid"], usesOnChanges: true, ngImport: i0, template: `
2495
+ ], 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: "footer", predicate: ["footer"], descendants: true }], exportAs: ["kendoGrid"], usesOnChanges: true, ngImport: i0, template: `
2498
2496
  <ng-container kendoGridLocalizedMessages
2499
2497
  i18n-groupPanelEmpty="kendo.grid.groupPanelEmpty|The label visible in the Grid group panel when it is empty"
2500
2498
  groupPanelEmpty="Drag a column header and drop it here to group by that column"
@@ -2870,6 +2868,15 @@ export class GridComponent {
2870
2868
 
2871
2869
  i18n-columnChooserSelectedColumnsCount="kendo.grid.columnChooserSelectedColumnsCount|The text displayed in the Column Chooser for the number of selected columns"
2872
2870
  columnChooserSelectedColumnsCount="{{ '{selectedColumnsCount} Selected items' }}"
2871
+
2872
+ i18n-multiCheckboxFilterSearchPlaceholder="kendo.grid.multiCheckboxFilterSearchPlaceholder|The placeholder text for the multi-checkbox filter search input"
2873
+ multiCheckboxFilterSearchPlaceholder="Search..."
2874
+
2875
+ i18n-multiCheckboxFilterSelectAllLabel="kendo.grid.multiCheckboxFilterSelectAllLabel|The label for the multi-checkbox filter select all option"
2876
+ multiCheckboxFilterSelectAllLabel="Select all"
2877
+
2878
+ i18n-multiCheckboxFilterSelectedItemsCount="kendo.grid.multiCheckboxFilterSelectedItemsCount|The text for the multi-checkbox filter selected items count"
2879
+ multiCheckboxFilterSelectedItemsCount="{{ '{selectedItemsCount} selected items' }}"
2873
2880
  >
2874
2881
  </ng-container>
2875
2882
  <kendo-grid-toolbar
@@ -3288,10 +3295,10 @@ export class GridComponent {
3288
3295
  </kendo-pager-info>
3289
3296
  </ng-template>
3290
3297
  <div #dialogContainer></div>
3298
+ <div #windowContainer></div>
3291
3299
 
3292
3300
  <kendo-grid-adaptive-renderer *ngIf="isAdaptiveModeEnabled"></kendo-grid-adaptive-renderer>
3293
3301
  <kendo-resize-sensor *ngIf="isVirtual" (resize)="onResize()"></kendo-resize-sensor>
3294
- <div *ngIf="aiAssistantToolbarTool" #windowContainer></div>
3295
3302
 
3296
3303
  <div kendoWatermarkOverlay *ngIf="showLicenseWatermark" [licenseMessage]="licenseMessage"></div>
3297
3304
  `, isInline: true, dependencies: [{ kind: "directive", type: LocalizedMessagesDirective, selector: "[kendoGridLocalizedMessages]" }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: GridToolbarComponent, 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"] }, { 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]", inputs: ["licenseMessage"] }, { kind: "component", type: i27.CustomMessagesComponent, selector: "kendo-datapager-messages, kendo-pager-messages" }, { kind: "component", type: i27.PagerInfoComponent, selector: "kendo-datapager-info, kendo-pager-info" }, { kind: "component", type: i27.PagerInputComponent, selector: "kendo-datapager-input, kendo-pager-input", inputs: ["showPageText", "size"] }, { kind: "component", type: i27.PagerNextButtonsComponent, selector: "kendo-datapager-next-buttons, kendo-pager-next-buttons", inputs: ["size"] }, { kind: "component", type: i27.PagerNumericButtonsComponent, selector: "kendo-datapager-numeric-buttons, kendo-pager-numeric-buttons", inputs: ["buttonCount", "size"] }, { kind: "component", type: i27.PagerPageSizesComponent, selector: "kendo-datapager-page-sizes, kendo-pager-page-sizes", inputs: ["showItemsText", "pageSizes", "size", "adaptiveMode"] }, { kind: "component", type: i27.PagerPrevButtonsComponent, selector: "kendo-datapager-prev-buttons, kendo-pager-prev-buttons", inputs: ["size"] }, { kind: "directive", type: i27.PagerTemplateDirective, selector: "[kendoDataPagerTemplate], [kendoPagerTemplate]" }, { kind: "component", type: i27.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"] }], encapsulation: i0.ViewEncapsulation.None });
@@ -3730,6 +3737,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
3730
3737
 
3731
3738
  i18n-columnChooserSelectedColumnsCount="kendo.grid.columnChooserSelectedColumnsCount|The text displayed in the Column Chooser for the number of selected columns"
3732
3739
  columnChooserSelectedColumnsCount="{{ '{selectedColumnsCount} Selected items' }}"
3740
+
3741
+ i18n-multiCheckboxFilterSearchPlaceholder="kendo.grid.multiCheckboxFilterSearchPlaceholder|The placeholder text for the multi-checkbox filter search input"
3742
+ multiCheckboxFilterSearchPlaceholder="Search..."
3743
+
3744
+ i18n-multiCheckboxFilterSelectAllLabel="kendo.grid.multiCheckboxFilterSelectAllLabel|The label for the multi-checkbox filter select all option"
3745
+ multiCheckboxFilterSelectAllLabel="Select all"
3746
+
3747
+ i18n-multiCheckboxFilterSelectedItemsCount="kendo.grid.multiCheckboxFilterSelectedItemsCount|The text for the multi-checkbox filter selected items count"
3748
+ multiCheckboxFilterSelectedItemsCount="{{ '{selectedItemsCount} selected items' }}"
3733
3749
  >
3734
3750
  </ng-container>
3735
3751
  <kendo-grid-toolbar
@@ -4148,10 +4164,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
4148
4164
  </kendo-pager-info>
4149
4165
  </ng-template>
4150
4166
  <div #dialogContainer></div>
4167
+ <div #windowContainer></div>
4151
4168
 
4152
4169
  <kendo-grid-adaptive-renderer *ngIf="isAdaptiveModeEnabled"></kendo-grid-adaptive-renderer>
4153
4170
  <kendo-resize-sensor *ngIf="isVirtual" (resize)="onResize()"></kendo-resize-sensor>
4154
- <div *ngIf="aiAssistantToolbarTool" #windowContainer></div>
4155
4171
 
4156
4172
  <div kendoWatermarkOverlay *ngIf="showLicenseWatermark" [licenseMessage]="licenseMessage"></div>
4157
4173
  `,
@@ -4360,9 +4376,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
4360
4376
  }], columnMenuTemplates: [{
4361
4377
  type: ContentChildren,
4362
4378
  args: [ColumnMenuTemplateDirective]
4363
- }], aiAssistantToolbarTool: [{
4364
- type: ContentChild,
4365
- args: [AIAssistantToolbarDirective]
4366
4379
  }], lockedHeader: [{
4367
4380
  type: ViewChild,
4368
4381
  args: ['lockedHeader']
package/esm2022/index.mjs CHANGED
@@ -46,6 +46,7 @@ export { DropCueService } from './dragdrop/drop-cue.service';
46
46
  export { EditService as EditServiceClass } from './editing/edit.service';
47
47
  export { NumericFilterComponent } from './filtering/numeric-filter.component';
48
48
  export { StringFilterComponent } from './filtering/string-filter.component';
49
+ export { MultiCheckboxFilterComponent } from './filtering/multicheckbox-filter.component';
49
50
  export { GroupInfoService } from './grouping/group-info.service';
50
51
  export { GroupsService } from './grouping/groups.service';
51
52
  export { BrowserSupportService } from './layout/browser-support.service';
@@ -582,8 +582,29 @@ export class GridMessages extends ComponentMessages {
582
582
  * Sets the text for the external editing Dialog <b>Cancel</b> button.
583
583
  */
584
584
  externalEditingCancelText;
585
+ /**
586
+ * The placeholder text for the multi-checkbox filter search input
587
+ */
588
+ multiCheckboxFilterSearchPlaceholder;
589
+ /**
590
+ * The label for the multi-checkbox filter select all option
591
+ */
592
+ multiCheckboxFilterSelectAllLabel;
593
+ /**
594
+ * The text for the multi-checkbox filter selected items count
595
+ *
596
+ * The text includes the selected items count and a localizable string.
597
+ * For 3 selected items the default text is `3 selected items`.
598
+ *
599
+ * To customize the text, use the `{selectedItemsCount}` placeholder and a custom localizable string.
600
+ * For example, `{selectedItemsCount} items are selected`.
601
+ *
602
+ * The `{selectedItemsCount}` placeholder is replaced with the count of selected items,
603
+ * and the message is rendered as `3 items are selected`.
604
+ */
605
+ multiCheckboxFilterSelectedItemsCount;
585
606
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: GridMessages, deps: null, target: i0.ɵɵFactoryTarget.Directive });
586
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: GridMessages, 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", 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", 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", groupCollapse: "groupCollapse", groupExpand: "groupExpand", topToolbarLabel: "topToolbarLabel", bottomToolbarLabel: "bottomToolbarLabel", editToolbarToolText: "editToolbarToolText", saveToolbarToolText: "saveToolbarToolText", addToolbarToolText: "addToolbarToolText", cancelToolbarToolText: "cancelToolbarToolText", removeToolbarToolText: "removeToolbarToolText", excelExportToolbarToolText: "excelExportToolbarToolText", 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" }, usesInheritance: true, ngImport: i0 });
607
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: GridMessages, 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", 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", 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", groupCollapse: "groupCollapse", groupExpand: "groupExpand", topToolbarLabel: "topToolbarLabel", bottomToolbarLabel: "bottomToolbarLabel", editToolbarToolText: "editToolbarToolText", saveToolbarToolText: "saveToolbarToolText", addToolbarToolText: "addToolbarToolText", cancelToolbarToolText: "cancelToolbarToolText", removeToolbarToolText: "removeToolbarToolText", excelExportToolbarToolText: "excelExportToolbarToolText", 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" }, usesInheritance: true, ngImport: i0 });
587
608
  }
588
609
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: GridMessages, decorators: [{
589
610
  type: Directive,
@@ -841,4 +862,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
841
862
  type: Input
842
863
  }], externalEditingCancelText: [{
843
864
  type: Input
865
+ }], multiCheckboxFilterSearchPlaceholder: [{
866
+ type: Input
867
+ }], multiCheckboxFilterSelectAllLabel: [{
868
+ type: Input
869
+ }], multiCheckboxFilterSelectedItemsCount: [{
870
+ type: Input
844
871
  }] } });
@@ -10,7 +10,7 @@ export const packageMetadata = {
10
10
  productName: 'Kendo UI for Angular',
11
11
  productCode: 'KENDOUIANGULAR',
12
12
  productCodes: ['KENDOUIANGULAR'],
13
- publishDate: 1759490932,
14
- version: '20.1.0-develop.9',
13
+ publishDate: 1761222945,
14
+ version: '20.1.1-develop.1',
15
15
  licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/'
16
16
  };
@@ -176,11 +176,16 @@ export class PDFComponent extends PDFExportComponent {
176
176
  overlayContent.scrollTop = content.scrollTop;
177
177
  overlayContent.scrollLeft = content.scrollLeft;
178
178
  if (!this.ctx?.grid?.isStacked) {
179
- overlayQuery.header().scrollLeft = query.header().scrollLeft;
179
+ const header = query.header();
180
+ const overlayHeader = overlayQuery.header();
181
+ if (header && overlayHeader) {
182
+ overlayHeader.scrollLeft = header.scrollLeft;
183
+ }
180
184
  }
181
185
  const footer = query.footer();
182
- if (footer) {
183
- overlayQuery.footer().scrollLeft = footer.scrollLeft;
186
+ const overlayFooter = overlayQuery.footer();
187
+ if (footer && overlayFooter) {
188
+ overlayFooter.scrollLeft = footer.scrollLeft;
184
189
  }
185
190
  const lockedContent = query.content(true);
186
191
  if (lockedContent) {
@@ -312,7 +312,7 @@ export class CellComponent {
312
312
  </ng-container>
313
313
  </div>
314
314
  </div>
315
- <div class="k-grid-stack-cell" *ngIf="detailTemplate?.showIf(item.data, $any(item).index)">
315
+ <div class="k-grid-stack-cell" *ngIf="detailTemplate?.showIf(item.data, $any(item).index)" [attr.aria-expanded]="item.isExpanded">
316
316
  <div class="k-grid-stack-content">
317
317
  <button kendoButton
318
318
  fillMode="flat"
@@ -520,7 +520,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
520
520
  </ng-container>
521
521
  </div>
522
522
  </div>
523
- <div class="k-grid-stack-cell" *ngIf="detailTemplate?.showIf(item.data, $any(item).index)">
523
+ <div class="k-grid-stack-cell" *ngIf="detailTemplate?.showIf(item.data, $any(item).index)" [attr.aria-expanded]="item.isExpanded">
524
524
  <div class="k-grid-stack-content">
525
525
  <button kendoButton
526
526
  fillMode="flat"
@@ -29,7 +29,7 @@ export class FieldAccessorPipe {
29
29
  }
30
30
  formatValue(format, value) {
31
31
  const intl = this.intlService;
32
- if (isString(format) && format.match(FORMAT_REGEX)) {
32
+ if (isString(format) && FORMAT_REGEX.exec(format)) {
33
33
  return intl.format(format, value);
34
34
  }
35
35
  return intl.toString(value, format);
@@ -0,0 +1,37 @@
1
+ /**-----------------------------------------------------------------------------------------
2
+ * Copyright © 2025 Progress Software Corporation. All rights reserved.
3
+ * Licensed under commercial license. See LICENSE.md in the project root for more information
4
+ *-------------------------------------------------------------------------------------------*/
5
+ import { Pipe } from '@angular/core';
6
+ import { isString } from '../../utils';
7
+ import { IntlService } from '@progress/kendo-angular-intl';
8
+ import * as i0 from "@angular/core";
9
+ import * as i1 from "@progress/kendo-angular-intl";
10
+ const FORMAT_REGEX = /\{\d+:?/;
11
+ /**
12
+ * @hidden
13
+ */
14
+ export class FormatPipe {
15
+ intlService;
16
+ constructor(intlService) {
17
+ this.intlService = intlService;
18
+ }
19
+ transform(value, format) {
20
+ const intl = this.intlService;
21
+ if (isString(format) && FORMAT_REGEX.exec(format)) {
22
+ return intl.format(format, value);
23
+ }
24
+ return intl.toString(value, format);
25
+ }
26
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FormatPipe, deps: [{ token: i1.IntlService }], target: i0.ɵɵFactoryTarget.Pipe });
27
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: FormatPipe, isStandalone: true, name: "format", pure: false });
28
+ }
29
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FormatPipe, decorators: [{
30
+ type: Pipe,
31
+ args: [{
32
+ // eslint-disable-next-line @angular-eslint/pipe-prefix
33
+ name: 'format',
34
+ pure: false,
35
+ standalone: true
36
+ }]
37
+ }], ctorParameters: function () { return [{ type: i1.IntlService }]; } });
@@ -169,7 +169,7 @@ export class HeaderComponent {
169
169
  }
170
170
  onHeaderKeydown(column, args) {
171
171
  const code = normalizeNumpadKeys(args);
172
- if (code === Keys.ArrowDown && args.altKey && this.showFilterMenu) {
172
+ if (code === Keys.ArrowDown && args.altKey && this.showFilterMenu && this.isFilterable(column)) {
173
173
  args.preventDefault();
174
174
  args.stopImmediatePropagation();
175
175
  const filterMenu = this.filterMenus.find(fm => fm.column === column);