@progress/kendo-angular-grid 11.4.0-develop.1 → 11.4.0-develop.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/common/provider.service.d.ts +6 -0
  2. package/esm2020/column-menu/column-list.component.mjs +1 -1
  3. package/esm2020/column-menu/column-menu-chooser.component.mjs +1 -1
  4. package/esm2020/column-menu/column-menu-filter.component.mjs +1 -1
  5. package/esm2020/column-menu/column-menu-position.component.mjs +1 -1
  6. package/esm2020/common/provider.service.mjs +9 -3
  7. package/esm2020/filtering/cell/date-filter-cell.component.mjs +1 -1
  8. package/esm2020/filtering/cell/filter-cell.component.mjs +7 -3
  9. package/esm2020/filtering/menu/date-filter-menu-input.component.mjs +1 -1
  10. package/esm2020/filtering/menu/filter-menu-container.component.mjs +1 -1
  11. package/esm2020/filtering/shared-filtering.module.mjs +1 -1
  12. package/esm2020/grid.component.mjs +54 -4
  13. package/esm2020/grid.module.mjs +8 -3
  14. package/esm2020/grouping/group-panel.component.mjs +16 -4
  15. package/esm2020/index.mjs +2 -0
  16. package/esm2020/localization/messages.mjs +7 -1
  17. package/esm2020/navigation/navigation.service.mjs +5 -0
  18. package/esm2020/package-metadata.mjs +2 -2
  19. package/esm2020/rendering/cell.component.mjs +1 -1
  20. package/esm2020/rendering/footer/footer.component.mjs +7 -3
  21. package/esm2020/rendering/header/header.component.mjs +72 -22
  22. package/esm2020/rendering/list.component.mjs +8 -12
  23. package/esm2020/rendering/table-body.component.mjs +4 -2
  24. package/esm2020/rendering/toolbar/toolbar-focusable.directive.mjs +63 -0
  25. package/esm2020/rendering/toolbar/toolbar-navigation.service.mjs +53 -0
  26. package/esm2020/rendering/toolbar/toolbar-position.mjs +5 -0
  27. package/esm2020/rendering/toolbar/toolbar-template.directive.mjs +1 -1
  28. package/esm2020/rendering/toolbar/toolbar.component.mjs +74 -9
  29. package/fesm2015/progress-kendo-angular-grid.mjs +366 -63
  30. package/fesm2020/progress-kendo-angular-grid.mjs +363 -63
  31. package/filtering/cell/filter-cell.component.d.ts +1 -0
  32. package/grid.component.d.ts +5 -0
  33. package/grid.module.d.ts +97 -96
  34. package/grouping/group-panel.component.d.ts +5 -1
  35. package/index.d.ts +2 -0
  36. package/localization/messages.d.ts +13 -1
  37. package/navigation/navigable-settings.d.ts +1 -1
  38. package/navigation/navigation.service.d.ts +2 -0
  39. package/package.json +14 -14
  40. package/rendering/footer/footer.component.d.ts +1 -0
  41. package/rendering/header/header.component.d.ts +5 -1
  42. package/rendering/list.component.d.ts +2 -2
  43. package/rendering/toolbar/toolbar-focusable.directive.d.ts +29 -0
  44. package/rendering/toolbar/toolbar-navigation.service.d.ts +21 -0
  45. package/rendering/toolbar/toolbar-position.d.ts +5 -0
  46. package/rendering/toolbar/toolbar.component.d.ts +11 -2
  47. package/schematics/ngAdd/index.js +2 -2
@@ -24,6 +24,7 @@ export class FooterComponent {
24
24
  this.lockedColumnsCount = 0;
25
25
  this.logicalRowIndex = 0;
26
26
  this.hostClass = true;
27
+ this.hostRole = 'rowgroup';
27
28
  }
28
29
  get footerClass() {
29
30
  return !this.scrollable;
@@ -44,7 +45,7 @@ export class FooterComponent {
44
45
  }
45
46
  }
46
47
  FooterComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FooterComponent, deps: [{ token: i1.ColumnInfoService }], target: i0.ɵɵFactoryTarget.Component });
47
- FooterComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: FooterComponent, selector: "[kendoGridFooter]", inputs: { columns: "columns", groups: "groups", detailTemplate: "detailTemplate", scrollable: "scrollable", lockedColumnsCount: "lockedColumnsCount", logicalRowIndex: "logicalRowIndex" }, host: { properties: { "class.k-grid-footer": "this.footerClass", "class.k-table-tfoot": "this.hostClass" } }, ngImport: i0, template: `
48
+ FooterComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: FooterComponent, selector: "[kendoGridFooter]", inputs: { columns: "columns", groups: "groups", detailTemplate: "detailTemplate", scrollable: "scrollable", lockedColumnsCount: "lockedColumnsCount", logicalRowIndex: "logicalRowIndex" }, host: { properties: { "class.k-grid-footer": "this.footerClass", "class.k-table-tfoot": "this.hostClass", "attr.role": "this.hostRole" } }, ngImport: i0, template: `
48
49
  <ng-container>
49
50
  <tr
50
51
  [class.k-footer-template]="true"
@@ -70,7 +71,7 @@ FooterComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", versio
70
71
  class="k-table-td"
71
72
  [logicalRowIndex]="logicalRowIndex"
72
73
  [logicalColIndex]="logicalColumnIndex(column)"
73
- role="columnfooter"
74
+ role="gridcell"
74
75
  aria-selected="false"
75
76
  [class.k-grid-footer-sticky]="column.sticky"
76
77
  [ngClass]="column.footerClass"
@@ -117,7 +118,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
117
118
  class="k-table-td"
118
119
  [logicalRowIndex]="logicalRowIndex"
119
120
  [logicalColIndex]="logicalColumnIndex(column)"
120
- role="columnfooter"
121
+ role="gridcell"
121
122
  aria-selected="false"
122
123
  [class.k-grid-footer-sticky]="column.sticky"
123
124
  [ngClass]="column.footerClass"
@@ -153,4 +154,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
153
154
  }], hostClass: [{
154
155
  type: HostBinding,
155
156
  args: ['class.k-table-tfoot']
157
+ }], hostRole: [{
158
+ type: HostBinding,
159
+ args: ['attr.role']
156
160
  }] } });
@@ -29,6 +29,8 @@ import { closestInScope, isFocusable } from '../common/dom-queries';
29
29
  import { FilterMenuComponent } from '../../filtering/menu/filter-menu.component';
30
30
  import { ColumnMenuComponent } from '../../column-menu/column-menu.component';
31
31
  import { sortAscSmallIcon, sortDescSmallIcon } from '@progress/kendo-svg-icons';
32
+ import { ContextService } from '../../common/provider.service';
33
+ import { ColumnReorderEvent } from '../../dragdrop/column-reorder-event';
32
34
  import * as i0 from "@angular/core";
33
35
  import * as i1 from "../../common/single-popup.service";
34
36
  import * as i2 from "../../dragdrop/drag-hint.service";
@@ -38,20 +40,21 @@ import * as i5 from "../../common/id.service";
38
40
  import * as i6 from "../../common/sort.service";
39
41
  import * as i7 from "@progress/kendo-angular-l10n";
40
42
  import * as i8 from "./../../common/column-info.service";
41
- import * as i9 from "../../filtering/menu/filter-menu.component";
42
- import * as i10 from "../../column-menu/column-menu.component";
43
- import * as i11 from "@progress/kendo-angular-icons";
44
- import * as i12 from "../../filtering/filter-row.component";
45
- import * as i13 from "@angular/common";
46
- import * as i14 from "../../navigation/logical-row.directive";
47
- import * as i15 from "../../navigation/logical-cell.directive";
48
- import * as i16 from "../../dragdrop/drop-target.directive";
49
- import * as i17 from "@progress/kendo-angular-common";
50
- import * as i18 from "../../dragdrop/draggable-column.directive";
51
- import * as i19 from "../common/template-context.directive";
52
- import * as i20 from "../../selection/selectall-checkbox.directive";
53
- import * as i21 from "../../navigation/focusable.directive";
54
- import * as i22 from "../../column-resizing/column-handle.directive";
43
+ import * as i9 from "../../common/provider.service";
44
+ import * as i10 from "../../filtering/menu/filter-menu.component";
45
+ import * as i11 from "../../column-menu/column-menu.component";
46
+ import * as i12 from "@progress/kendo-angular-icons";
47
+ import * as i13 from "../../filtering/filter-row.component";
48
+ import * as i14 from "@angular/common";
49
+ import * as i15 from "../../navigation/logical-row.directive";
50
+ import * as i16 from "../../navigation/logical-cell.directive";
51
+ import * as i17 from "../../dragdrop/drop-target.directive";
52
+ import * as i18 from "@progress/kendo-angular-common";
53
+ import * as i19 from "../../dragdrop/draggable-column.directive";
54
+ import * as i20 from "../common/template-context.directive";
55
+ import * as i21 from "../../selection/selectall-checkbox.directive";
56
+ import * as i22 from "../../navigation/focusable.directive";
57
+ import * as i23 from "../../column-resizing/column-handle.directive";
55
58
  const mergeObjects = (...args) => Object.assign.apply(null, [{}].concat(args));
56
59
  const directions = initialDirection => initialDirection === "asc" ? ["asc", "desc"] : ["desc", "asc"];
57
60
  /**
@@ -77,7 +80,7 @@ const modifierKeys = ['alt', 'ctrl', 'shift', 'meta'];
77
80
  * @hidden
78
81
  */
79
82
  export class HeaderComponent {
80
- constructor(popupService, hint, cue, reorderService, idService, sortService, localization, columnInfoService, cd) {
83
+ constructor(popupService, hint, cue, reorderService, idService, sortService, localization, columnInfoService, cd, contextService) {
81
84
  this.popupService = popupService;
82
85
  this.hint = hint;
83
86
  this.cue = cue;
@@ -87,6 +90,7 @@ export class HeaderComponent {
87
90
  this.localization = localization;
88
91
  this.columnInfoService = columnInfoService;
89
92
  this.cd = cd;
93
+ this.contextService = contextService;
90
94
  this.columns = [];
91
95
  this.groups = [];
92
96
  this.sort = new Array();
@@ -143,12 +147,50 @@ export class HeaderComponent {
143
147
  args.stopImmediatePropagation();
144
148
  const filterMenu = this.filterMenus.find(fm => fm.column === column);
145
149
  filterMenu.toggle(filterMenu.anchor.nativeElement, filterMenu.template);
150
+ return;
146
151
  }
147
152
  if (args.keyCode === Keys.ArrowDown && args.altKey && this.showColumnMenu(column)) {
148
153
  args.preventDefault();
149
154
  args.stopImmediatePropagation();
150
155
  const columnMenu = this.columnMenus.find(cm => cm.column === column);
151
156
  columnMenu.toggle(null, columnMenu.anchor.nativeElement, columnMenu.template);
157
+ return;
158
+ }
159
+ const isCtrlOrMeta = args.ctrlKey || args.metaKey;
160
+ const isGroupingKeyShortcut = (args.keyCode === Keys.Enter || args.keyCode === Keys.Space) && isCtrlOrMeta;
161
+ if (isGroupingKeyShortcut && this.isGroupable(column)) {
162
+ args.preventDefault();
163
+ args.stopImmediatePropagation();
164
+ const isGroupedByField = this.groups.some(gr => gr.field === column.field);
165
+ if (isGroupedByField) {
166
+ this.groups = this.groups.filter(gr => gr.field !== column.field);
167
+ }
168
+ else {
169
+ this.groups.push({
170
+ field: column.field
171
+ });
172
+ }
173
+ this.contextService.grid.groupChange.emit(this.groups);
174
+ return;
175
+ }
176
+ const isLeftOrRightArrow = args.keyCode === Keys.ArrowLeft || args.keyCode === Keys.ArrowRight;
177
+ const isReorderingKeyShortcut = isLeftOrRightArrow && isCtrlOrMeta;
178
+ if (isReorderingKeyShortcut && this.isReorderable(column)) {
179
+ args.preventDefault();
180
+ const columnsCount = this.columnInfoService.leafNamedColumns.length;
181
+ const reorderDirection = args.keyCode === Keys.ArrowLeft ? -1 : 1;
182
+ const rtlMultiplier = this.localization.rtl ? -1 : 1;
183
+ const reorderDirectionOffset = reorderDirection * rtlMultiplier;
184
+ const newIndex = column.leafIndex + reorderDirectionOffset;
185
+ const normalizedNewIndex = Math.min(Math.max(0, newIndex), columnsCount - 1);
186
+ const gridInstance = this.contextService.grid;
187
+ gridInstance.reorderColumn(column, normalizedNewIndex, { before: reorderDirectionOffset < 0 });
188
+ gridInstance.columnReorder.emit(new ColumnReorderEvent({
189
+ column,
190
+ newIndex: normalizedNewIndex,
191
+ oldIndex: column.leafIndex
192
+ }));
193
+ return;
152
194
  }
153
195
  if (!this.sortable || args.defaultPrevented || column.sortable === false) {
154
196
  return;
@@ -288,11 +330,11 @@ export class HeaderComponent {
288
330
  return this.reorderable && rules({ draggable, target });
289
331
  }
290
332
  shouldActivate(column) {
291
- const canReorder = this.reorderable && column.reorderable;
333
+ const canReorder = this.isReorderable(column);
292
334
  if (!canReorder && !isColumnComponent(column)) {
293
335
  return false;
294
336
  }
295
- const groupable = this.groupable && isColumnComponent(column) && column.groupable !== false;
337
+ const groupable = this.isGroupable(column);
296
338
  return groupable || canReorder;
297
339
  }
298
340
  isSortable(column) {
@@ -337,6 +379,12 @@ export class HeaderComponent {
337
379
  get leafColumns() {
338
380
  return this._leafColumns;
339
381
  }
382
+ isReorderable(column) {
383
+ return this.reorderable && column.reorderable;
384
+ }
385
+ isGroupable(column) {
386
+ return this.groupable && isColumnComponent(column) && column.groupable !== false;
387
+ }
340
388
  attachTargets() {
341
389
  if (this.targetSubscription) {
342
390
  this.targetSubscription.unsubscribe();
@@ -418,7 +466,7 @@ export class HeaderComponent {
418
466
  });
419
467
  }
420
468
  }
421
- HeaderComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: HeaderComponent, deps: [{ token: i1.SinglePopupService }, { token: i2.DragHintService }, { token: i3.DropCueService }, { token: i4.ColumnReorderService }, { token: i5.IdService }, { token: i6.SortService }, { token: i7.LocalizationService }, { token: i8.ColumnInfoService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
469
+ HeaderComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: HeaderComponent, deps: [{ token: i1.SinglePopupService }, { token: i2.DragHintService }, { token: i3.DropCueService }, { token: i4.ColumnReorderService }, { token: i5.IdService }, { token: i6.SortService }, { token: i7.LocalizationService }, { token: i8.ColumnInfoService }, { token: i0.ChangeDetectorRef }, { token: i9.ContextService }], target: i0.ɵɵFactoryTarget.Component });
422
470
  HeaderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: HeaderComponent, selector: "[kendoGridHeader]", inputs: { totalColumnLevels: "totalColumnLevels", columns: "columns", groups: "groups", detailTemplate: "detailTemplate", scrollable: "scrollable", filterable: "filterable", sort: "sort", filter: "filter", sortable: "sortable", groupable: "groupable", lockedColumnsCount: "lockedColumnsCount", resizable: "resizable", reorderable: "reorderable", columnMenu: "columnMenu", columnMenuTemplate: "columnMenuTemplate", totalColumnsCount: "totalColumnsCount", tabIndex: "tabIndex", size: "size" }, host: { properties: { "class.k-grid-header": "this.headerClass", "class.k-table-thead": "this.hostClass" } }, viewQueries: [{ propertyName: "dropTargets", predicate: DropTargetDirective, descendants: true }, { propertyName: "filterMenus", predicate: FilterMenuComponent, descendants: true }, { propertyName: "columnMenus", predicate: ColumnMenuComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: `
423
471
  <ng-container>
424
472
  <tr *ngFor="let i of columnLevels; let levelIndex = index"
@@ -472,7 +520,8 @@ HeaderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", versio
472
520
  [ngClass]="column.headerClass"
473
521
  [ngStyle]="column.sticky ? addStickyStyles(column) : column.headerStyle"
474
522
  [attr.rowspan]="column.rowspan(totalColumnLevels)"
475
- [attr.colspan]="column.colspan">
523
+ [attr.colspan]="column.colspan"
524
+ [attr.aria-haspopup]="(showFilterMenu || showColumnMenu(column)) ? 'dialog' : undefined">
476
525
 
477
526
  <ng-container *ngIf="!isSortable(getColumnComponent(column))">
478
527
  <span class="k-cell-inner">
@@ -643,7 +692,7 @@ HeaderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", versio
643
692
  [logicalSlaveCellsCount]="unlockedColumnsCount"
644
693
  ></tr>
645
694
  </ng-container>
646
- `, isInline: true, components: [{ type: i9.FilterMenuComponent, selector: "kendo-grid-filter-menu", inputs: ["column", "filter", "tabIndex"] }, { type: i10.ColumnMenuComponent, selector: "kendo-grid-column-menu", inputs: ["standalone", "column", "settings", "sort", "filter", "sortable", "columnMenuTemplate", "tabIndex"] }, { type: i11.IconWrapperComponent, selector: "kendo-icon-wrapper", inputs: ["name", "svgIcon", "innerCssClass", "customFontClass"], exportAs: ["kendoIconWrapper"] }, { type: i12.FilterRowComponent, selector: "[kendoGridFilterRow]", inputs: ["columns", "filter", "groups", "detailTemplate", "logicalRowIndex", "lockedColumnsCount"] }], directives: [{ type: i13.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i14.LogicalRowDirective, selector: "[kendoGridLogicalRow]", inputs: ["logicalRowIndex", "logicalSlaveRow", "logicalCellsCount", "logicalSlaveCellsCount", "dataRowIndex", "dataItem"] }, { type: i13.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i15.LogicalCellDirective, selector: "[kendoGridLogicalCell]", inputs: ["logicalColIndex", "logicalRowIndex", "logicalSlaveCell", "colIndex", "colSpan", "rowSpan", "groupItem", "dataRowIndex", "dataItem", "detailExpandCell", "headerLabelText"] }, { type: i16.DropTargetDirective, selector: "[kendoDropTarget]", inputs: ["context"], outputs: ["enter", "leave", "drop"] }, { type: i17.DraggableDirective, selector: "[kendoDraggable]", inputs: ["enableDrag"], outputs: ["kendoPress", "kendoDrag", "kendoRelease"] }, { type: i18.DraggableColumnDirective, selector: "[kendoDraggableColumn]", inputs: ["context", "enableDrag"], outputs: ["drag"] }, { type: i13.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i13.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i19.TemplateContextDirective, selector: "[templateContext]", inputs: ["templateContext"] }, { type: i20.SelectAllCheckboxDirective, selector: "[kendoGridSelectAllCheckbox]", inputs: ["state"], outputs: ["selectAllChange"] }, { type: i21.FocusableDirective, selector: "[kendoGridFocusable],\n [kendoGridEditCommand],\n [kendoGridRemoveCommand],\n [kendoGridSaveCommand],\n [kendoGridCancelCommand],\n [kendoGridSelectionCheckbox]\n ", inputs: ["kendoGridFocusable"] }, { type: i22.ColumnHandleDirective, selector: "[kendoGridColumnHandle]", inputs: ["columns", "column"] }] });
695
+ `, isInline: true, components: [{ type: i10.FilterMenuComponent, selector: "kendo-grid-filter-menu", inputs: ["column", "filter", "tabIndex"] }, { type: i11.ColumnMenuComponent, selector: "kendo-grid-column-menu", inputs: ["standalone", "column", "settings", "sort", "filter", "sortable", "columnMenuTemplate", "tabIndex"] }, { type: i12.IconWrapperComponent, selector: "kendo-icon-wrapper", inputs: ["name", "svgIcon", "innerCssClass", "customFontClass"], exportAs: ["kendoIconWrapper"] }, { type: i13.FilterRowComponent, selector: "[kendoGridFilterRow]", inputs: ["columns", "filter", "groups", "detailTemplate", "logicalRowIndex", "lockedColumnsCount"] }], directives: [{ type: i14.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i15.LogicalRowDirective, selector: "[kendoGridLogicalRow]", inputs: ["logicalRowIndex", "logicalSlaveRow", "logicalCellsCount", "logicalSlaveCellsCount", "dataRowIndex", "dataItem"] }, { type: i14.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i16.LogicalCellDirective, selector: "[kendoGridLogicalCell]", inputs: ["logicalColIndex", "logicalRowIndex", "logicalSlaveCell", "colIndex", "colSpan", "rowSpan", "groupItem", "dataRowIndex", "dataItem", "detailExpandCell", "headerLabelText"] }, { type: i17.DropTargetDirective, selector: "[kendoDropTarget]", inputs: ["context"], outputs: ["enter", "leave", "drop"] }, { type: i18.DraggableDirective, selector: "[kendoDraggable]", inputs: ["enableDrag"], outputs: ["kendoPress", "kendoDrag", "kendoRelease"] }, { type: i19.DraggableColumnDirective, selector: "[kendoDraggableColumn]", inputs: ["context", "enableDrag"], outputs: ["drag"] }, { type: i14.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i14.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i20.TemplateContextDirective, selector: "[templateContext]", inputs: ["templateContext"] }, { type: i21.SelectAllCheckboxDirective, selector: "[kendoGridSelectAllCheckbox]", inputs: ["state"], outputs: ["selectAllChange"] }, { type: i22.FocusableDirective, selector: "[kendoGridFocusable],\n [kendoGridEditCommand],\n [kendoGridRemoveCommand],\n [kendoGridSaveCommand],\n [kendoGridCancelCommand],\n [kendoGridSelectionCheckbox]\n ", inputs: ["kendoGridFocusable"] }, { type: i23.ColumnHandleDirective, selector: "[kendoGridColumnHandle]", inputs: ["columns", "column"] }] });
647
696
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: HeaderComponent, decorators: [{
648
697
  type: Component,
649
698
  args: [{
@@ -701,7 +750,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
701
750
  [ngClass]="column.headerClass"
702
751
  [ngStyle]="column.sticky ? addStickyStyles(column) : column.headerStyle"
703
752
  [attr.rowspan]="column.rowspan(totalColumnLevels)"
704
- [attr.colspan]="column.colspan">
753
+ [attr.colspan]="column.colspan"
754
+ [attr.aria-haspopup]="(showFilterMenu || showColumnMenu(column)) ? 'dialog' : undefined">
705
755
 
706
756
  <ng-container *ngIf="!isSortable(getColumnComponent(column))">
707
757
  <span class="k-cell-inner">
@@ -874,7 +924,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
874
924
  </ng-container>
875
925
  `
876
926
  }]
877
- }], ctorParameters: function () { return [{ type: i1.SinglePopupService }, { type: i2.DragHintService }, { type: i3.DropCueService }, { type: i4.ColumnReorderService }, { type: i5.IdService }, { type: i6.SortService }, { type: i7.LocalizationService }, { type: i8.ColumnInfoService }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { totalColumnLevels: [{
927
+ }], ctorParameters: function () { return [{ type: i1.SinglePopupService }, { type: i2.DragHintService }, { type: i3.DropCueService }, { type: i4.ColumnReorderService }, { type: i5.IdService }, { type: i6.SortService }, { type: i7.LocalizationService }, { type: i8.ColumnInfoService }, { type: i0.ChangeDetectorRef }, { type: i9.ContextService }]; }, propDecorators: { totalColumnLevels: [{
878
928
  type: Input
879
929
  }], columns: [{
880
930
  type: Input
@@ -121,6 +121,8 @@ export class ListComponent {
121
121
  this.changeDetector = changeDetector;
122
122
  this.pdfService = pdfService;
123
123
  this.columnInfo = columnInfo;
124
+ this.hostClass = true;
125
+ this.hostRole = 'presentation';
124
126
  this.groups = [];
125
127
  this.skip = 0;
126
128
  this.columns = new ColumnsContainer(() => []);
@@ -142,12 +144,6 @@ export class ListComponent {
142
144
  this.subscriptions = detailsService.changes.subscribe(x => this.detailExpand(x));
143
145
  this.subscriptions.add(scrollRequestService.requests.subscribe(x => this.scrollTo(x)));
144
146
  }
145
- get hostClass() {
146
- return true;
147
- }
148
- get hostRole() {
149
- return 'presentation';
150
- }
151
147
  get showFooter() {
152
148
  return this.groupable && this.groupable.showFooter;
153
149
  }
@@ -211,7 +207,7 @@ export class ListComponent {
211
207
  this.skipScroll = true;
212
208
  this.container.nativeElement.scrollTop = this.rowHeightService.offset(this.skip);
213
209
  }
214
- if (anyChanged(["total", "take"], changes)) {
210
+ if (anyChanged(['total', 'take'], changes)) {
215
211
  this.init();
216
212
  }
217
213
  this.rebind = false;
@@ -319,7 +315,7 @@ export class ListComponent {
319
315
  });
320
316
  })).subscribe(this.dispatcher));
321
317
  });
322
- this.scrollSyncService.registerEmitter(this.container.nativeElement, "body");
318
+ this.scrollSyncService.registerEmitter(this.container.nativeElement, 'body');
323
319
  }
324
320
  createScroller() {
325
321
  this.cleanupScroller();
@@ -672,7 +668,7 @@ ListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version:
672
668
  [sort]="sort">
673
669
  </colgroup>
674
670
  <tbody kendoGridTableBody
675
- role="presentation"
671
+ role="rowgroup"
676
672
  [skipGroupDecoration]="isLocked"
677
673
  [data]="data"
678
674
  [groups]="groups"
@@ -791,7 +787,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
791
787
  [sort]="sort">
792
788
  </colgroup>
793
789
  <tbody kendoGridTableBody
794
- role="presentation"
790
+ role="rowgroup"
795
791
  [skipGroupDecoration]="isLocked"
796
792
  [data]="data"
797
793
  [groups]="groups"
@@ -831,10 +827,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
831
827
  args: [SCROLLER_FACTORY_TOKEN]
832
828
  }] }, { type: i1.DetailsService }, { type: i2.ChangeNotificationService }, { type: i3.SuspendService }, { type: i4.GroupsService }, { type: i0.NgZone }, { type: i0.Renderer2 }, { type: i5.ScrollSyncService }, { type: i6.ResizeService }, { type: i7.EditService }, { type: i8.BrowserSupportService }, { type: i9.NavigationService }, { type: i10.ScrollRequestService }, { type: i11.LocalizationService }, { type: i12.ColumnResizingService }, { type: i0.ChangeDetectorRef }, { type: i13.PDFService }, { type: i14.ColumnInfoService }]; }, propDecorators: { hostClass: [{
833
829
  type: HostBinding,
834
- args: ["class.k-grid-container"]
830
+ args: ['class.k-grid-container']
835
831
  }], hostRole: [{
836
832
  type: HostBinding,
837
- args: ["attr.role"]
833
+ args: ['attr.role']
838
834
  }], data: [{
839
835
  type: Input
840
836
  }], groups: [{
@@ -429,7 +429,7 @@ TableBodyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", ver
429
429
  </td>
430
430
  </tr>
431
431
  </ng-container>
432
- <tr *ngIf="data?.length === 0 || data === null" class="k-grid-norecords">
432
+ <tr *ngIf="data?.length === 0 || data === null" class="k-grid-norecords" role="row">
433
433
  <td [attr.colspan]="colSpan" class="k-table-td">
434
434
  <ng-template
435
435
  *ngIf="noRecordsTemplate?.templateRef"
@@ -475,6 +475,7 @@ TableBodyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", ver
475
475
  [ngClass]="rowClass({ dataItem: item.data, index: $any(item).index })"
476
476
  [class.k-master-row]="true"
477
477
  [class.k-grid-edit-row]="isEditingRow($any(item).index)"
478
+ [attr.aria-selected]="isSelectable() && isRowSelected(item)"
478
479
  [attr.data-kendo-grid-item-index]="$any(item).index"
479
480
  [class.k-selected]="isSelectable() && isRowSelected(item)">
480
481
  <ng-container *ngIf="!skipGroupDecoration">
@@ -654,7 +655,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
654
655
  </td>
655
656
  </tr>
656
657
  </ng-container>
657
- <tr *ngIf="data?.length === 0 || data === null" class="k-grid-norecords">
658
+ <tr *ngIf="data?.length === 0 || data === null" class="k-grid-norecords" role="row">
658
659
  <td [attr.colspan]="colSpan" class="k-table-td">
659
660
  <ng-template
660
661
  *ngIf="noRecordsTemplate?.templateRef"
@@ -700,6 +701,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
700
701
  [ngClass]="rowClass({ dataItem: item.data, index: $any(item).index })"
701
702
  [class.k-master-row]="true"
702
703
  [class.k-grid-edit-row]="isEditingRow($any(item).index)"
704
+ [attr.aria-selected]="isSelectable() && isRowSelected(item)"
703
705
  [attr.data-kendo-grid-item-index]="$any(item).index"
704
706
  [class.k-selected]="isSelectable() && isRowSelected(item)">
705
707
  <ng-container *ngIf="!skipGroupDecoration">
@@ -0,0 +1,63 @@
1
+ /**-----------------------------------------------------------------------------------------
2
+ * Copyright © 2023 Progress Software Corporation. All rights reserved.
3
+ * Licensed under commercial license. See LICENSE.md in the project root for more information
4
+ *-------------------------------------------------------------------------------------------*/
5
+ import { Directive, ElementRef } from '@angular/core';
6
+ import { isDocumentAvailable } from '@progress/kendo-angular-common';
7
+ import { ContextService } from '../../common/provider.service';
8
+ import * as i0 from "@angular/core";
9
+ import * as i1 from "../../common/provider.service";
10
+ /**
11
+ * A directive applied to all toolbar elements that need to be a part of the Grid
12
+ * keyboard navigation.
13
+ */
14
+ export class GridToolbarFocusableDirective {
15
+ constructor(host, ctx) {
16
+ this.host = host;
17
+ this.ctx = ctx;
18
+ }
19
+ /**
20
+ * @hidden
21
+ */
22
+ get element() {
23
+ return this.host.nativeElement;
24
+ }
25
+ /**
26
+ * @hidden
27
+ */
28
+ get toolbarPosition() {
29
+ return isDocumentAvailable() && this.host.nativeElement.closest('.k-toolbar')?.getAttribute('position');
30
+ }
31
+ ngAfterViewInit() {
32
+ if (!isDocumentAvailable() || !this.toolbarPosition) {
33
+ return;
34
+ }
35
+ this.ctx[`${this.toolbarPosition}ToolbarNavigation`]?.navigableElements.push(this.element);
36
+ this.ctx[`${this.toolbarPosition}ToolbarNavigation`]?.notify();
37
+ }
38
+ ngOnDestroy() {
39
+ if (!isDocumentAvailable() || !this.toolbarPosition) {
40
+ return;
41
+ }
42
+ const elements = this.ctx[`${this.toolbarPosition}ToolbarNavigation`].navigableElements;
43
+ this.ctx[`${this.toolbarPosition}ToolbarNavigation`].navigableElements = elements.filter(el => el !== this.element);
44
+ this.ctx[`${this.toolbarPosition}ToolbarNavigation`].notify();
45
+ }
46
+ }
47
+ GridToolbarFocusableDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: GridToolbarFocusableDirective, deps: [{ token: i0.ElementRef }, { token: i1.ContextService }], target: i0.ɵɵFactoryTarget.Directive });
48
+ GridToolbarFocusableDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.12", type: GridToolbarFocusableDirective, selector: "\n [kendoGridToolbarFocusable],\n [kendoGridAddCommand],\n [kendoGridCancelCommand],\n [kendoGridEditCommand],\n [kendoGridRemoveCommand],\n [kendoGridSaveCommand],\n [kendoGridExcelCommand],\n [kendoGridPDFCommand]\n ", ngImport: i0 });
49
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: GridToolbarFocusableDirective, decorators: [{
50
+ type: Directive,
51
+ args: [{
52
+ selector: `
53
+ [kendoGridToolbarFocusable],
54
+ [kendoGridAddCommand],
55
+ [kendoGridCancelCommand],
56
+ [kendoGridEditCommand],
57
+ [kendoGridRemoveCommand],
58
+ [kendoGridSaveCommand],
59
+ [kendoGridExcelCommand],
60
+ [kendoGridPDFCommand]
61
+ `
62
+ }]
63
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i1.ContextService }]; } });
@@ -0,0 +1,53 @@
1
+ /**-----------------------------------------------------------------------------------------
2
+ * Copyright © 2023 Progress Software Corporation. All rights reserved.
3
+ * Licensed under commercial license. See LICENSE.md in the project root for more information
4
+ *-------------------------------------------------------------------------------------------*/
5
+ import { Injectable, Renderer2 } from '@angular/core';
6
+ import { isDocumentAvailable } from '@progress/kendo-angular-common';
7
+ import * as i0 from "@angular/core";
8
+ /**
9
+ * @hidden
10
+ */
11
+ export class GridToolbarNavigationService {
12
+ constructor(renderer) {
13
+ this.renderer = renderer;
14
+ this.navigableElements = [];
15
+ this.currentActiveIndex = 0;
16
+ this.defaultFocusableSelector = `
17
+ [kendogridtoolbarfocusable],
18
+ [kendogridaddcommand],
19
+ [kendogridcancelcommand],
20
+ [kendogrideditcommand],
21
+ [kendogridremovecommand],
22
+ [kendogridsavecommand],
23
+ [kendogridexcelcommand],
24
+ [kendogridpdfcommand]
25
+ `;
26
+ }
27
+ notify() {
28
+ // ensure focusable elements are in the same order as in the DOM
29
+ this.navigableElements = this.navigableElements.length && Array.from(this.navigableElements[0].parentElement.querySelectorAll(this.defaultFocusableSelector)) || [];
30
+ this.currentActiveIndex = 0;
31
+ this.updateFocus();
32
+ }
33
+ focus() {
34
+ this.navigableElements[this.currentActiveIndex]?.focus();
35
+ }
36
+ updateFocus() {
37
+ if (!this.navigableElements.length) {
38
+ return;
39
+ }
40
+ this.navigableElements.forEach(el => {
41
+ this.renderer.setAttribute(el, 'tabindex', '-1');
42
+ });
43
+ this.renderer.setAttribute(this.navigableElements[this.currentActiveIndex], 'tabindex', '0');
44
+ if (isDocumentAvailable() && document.activeElement.closest('.k-toolbar')) {
45
+ this.navigableElements[this.currentActiveIndex].focus();
46
+ }
47
+ }
48
+ }
49
+ GridToolbarNavigationService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: GridToolbarNavigationService, deps: [{ token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Injectable });
50
+ GridToolbarNavigationService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: GridToolbarNavigationService });
51
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: GridToolbarNavigationService, decorators: [{
52
+ type: Injectable
53
+ }], ctorParameters: function () { return [{ type: i0.Renderer2 }]; } });
@@ -0,0 +1,5 @@
1
+ /**-----------------------------------------------------------------------------------------
2
+ * Copyright © 2023 Progress Software Corporation. All rights reserved.
3
+ * Licensed under commercial license. See LICENSE.md in the project root for more information
4
+ *-------------------------------------------------------------------------------------------*/
5
+ export {};
@@ -66,7 +66,7 @@ import * as i0 from "@angular/core";
66
66
  export class ToolbarTemplateDirective {
67
67
  constructor(templateRef) {
68
68
  this.templateRef = templateRef;
69
- this._position = "top";
69
+ this._position = 'top';
70
70
  }
71
71
  /**
72
72
  * The position of the toolbar ([see example]({% slug toolbartemplate_grid %})).
@@ -2,7 +2,8 @@
2
2
  * Copyright © 2023 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, Input, ElementRef, HostBinding } from '@angular/core';
5
+ import { Component, Input, ElementRef, HostBinding, HostListener } from '@angular/core';
6
+ import { closest, isDocumentAvailable, isFocusable } from '@progress/kendo-angular-common';
6
7
  import { ContextService } from './../../common/provider.service';
7
8
  import * as i0 from "@angular/core";
8
9
  import * as i1 from "./../../common/provider.service";
@@ -15,7 +16,9 @@ export class ToolbarComponent {
15
16
  this.ctx = ctx;
16
17
  this.wrapper = wrapper;
17
18
  this.context = {};
19
+ this.role = 'toolbar';
18
20
  this._size = 'medium';
21
+ this.navigationService = this.ctx[`${this.wrapper.nativeElement.getAttribute('position')}ToolbarNavigation`];
19
22
  }
20
23
  get sizeSmallClass() {
21
24
  return this.size === 'small';
@@ -36,18 +39,62 @@ export class ToolbarComponent {
36
39
  get size() {
37
40
  return this._size;
38
41
  }
42
+ clickHandler(ev) {
43
+ if (this.navigable && isDocumentAvailable()) {
44
+ const closestFocusable = closest(ev.target, isFocusable);
45
+ const targetIndex = this.navigationService.navigableElements.indexOf(closestFocusable);
46
+ if (targetIndex > -1) {
47
+ this.navigationService.currentActiveIndex = targetIndex;
48
+ }
49
+ this.navigationService.updateFocus();
50
+ if (ev.target === this.wrapper.nativeElement) {
51
+ this.navigationService.focus();
52
+ }
53
+ }
54
+ }
55
+ ;
56
+ arrowLeftListener() {
57
+ if (this.navigable && isDocumentAvailable() && this.navigationService.navigableElements.length) {
58
+ this.navigationService.currentActiveIndex--;
59
+ if (this.navigationService.currentActiveIndex < 0) {
60
+ this.navigationService.currentActiveIndex = this.navigationService.navigableElements.length - 1;
61
+ }
62
+ this.navigationService.updateFocus();
63
+ }
64
+ }
65
+ arrowRightListener() {
66
+ if (this.navigable && isDocumentAvailable() && this.navigationService.navigableElements.length) {
67
+ this.navigationService.currentActiveIndex++;
68
+ if (this.navigationService.currentActiveIndex >= this.navigationService.navigableElements.length) {
69
+ this.navigationService.currentActiveIndex = 0;
70
+ }
71
+ this.navigationService.updateFocus();
72
+ }
73
+ }
74
+ homeKeyListener(e) {
75
+ if (this.navigable && isDocumentAvailable() && this.navigationService.navigableElements.length) {
76
+ e.preventDefault();
77
+ this.navigationService.currentActiveIndex = 0;
78
+ this.navigationService.updateFocus();
79
+ }
80
+ }
81
+ endKeyListener(e) {
82
+ if (this.navigable && isDocumentAvailable() && this.navigationService.navigableElements.length) {
83
+ e.preventDefault();
84
+ this.navigationService.currentActiveIndex = this.navigationService.navigableElements.length - 1;
85
+ this.navigationService.updateFocus();
86
+ }
87
+ }
39
88
  get toolbarTemplateRef() {
40
89
  return this.ctx.grid.toolbarTemplate ? this.ctx.grid.toolbarTemplate.templateRef : undefined;
41
90
  }
42
91
  }
43
92
  ToolbarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: ToolbarComponent, deps: [{ token: i1.ContextService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
44
- ToolbarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: ToolbarComponent, selector: "kendo-grid-toolbar", inputs: { position: "position", size: "size" }, host: { properties: { "class.k-toolbar-sm": "this.sizeSmallClass", "class.k-toolbar-md": "this.sizeMediumClass" } }, ngImport: i0, template: `
93
+ ToolbarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: ToolbarComponent, selector: "kendo-grid-toolbar", inputs: { position: "position", size: "size", navigable: "navigable" }, host: { listeners: { "click": "clickHandler($event)", "keydown.arrowleft": "arrowLeftListener($event)", "keydown.arrowright": "arrowRightListener($event)", "keydown.home": "homeKeyListener($event)", "keydown.end": "endKeyListener($event)" }, properties: { "attr.role": "this.role", "class.k-toolbar-sm": "this.sizeSmallClass", "class.k-toolbar-md": "this.sizeMediumClass" } }, ngImport: i0, template: `
45
94
  <ng-template
46
95
  *ngIf="toolbarTemplateRef"
47
96
  [ngTemplateOutlet]="toolbarTemplateRef"
48
- [ngTemplateOutletContext]="context"
49
- >
50
- </ng-template>
97
+ [ngTemplateOutletContext]="context"></ng-template>
51
98
  `, isInline: true, directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }] });
52
99
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: ToolbarComponent, decorators: [{
53
100
  type: Component,
@@ -57,12 +104,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
57
104
  <ng-template
58
105
  *ngIf="toolbarTemplateRef"
59
106
  [ngTemplateOutlet]="toolbarTemplateRef"
60
- [ngTemplateOutletContext]="context"
61
- >
62
- </ng-template>
107
+ [ngTemplateOutletContext]="context"></ng-template>
63
108
  `
64
109
  }]
65
- }], ctorParameters: function () { return [{ type: i1.ContextService }, { type: i0.ElementRef }]; }, propDecorators: { sizeSmallClass: [{
110
+ }], ctorParameters: function () { return [{ type: i1.ContextService }, { type: i0.ElementRef }]; }, propDecorators: { role: [{
111
+ type: HostBinding,
112
+ args: ['attr.role']
113
+ }], sizeSmallClass: [{
66
114
  type: HostBinding,
67
115
  args: ['class.k-toolbar-sm']
68
116
  }], sizeMediumClass: [{
@@ -72,4 +120,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
72
120
  type: Input
73
121
  }], size: [{
74
122
  type: Input
123
+ }], clickHandler: [{
124
+ type: HostListener,
125
+ args: ['click', ['$event']]
126
+ }], arrowLeftListener: [{
127
+ type: HostListener,
128
+ args: ['keydown.arrowleft', ['$event']]
129
+ }], arrowRightListener: [{
130
+ type: HostListener,
131
+ args: ['keydown.arrowright', ['$event']]
132
+ }], homeKeyListener: [{
133
+ type: HostListener,
134
+ args: ['keydown.home', ['$event']]
135
+ }], endKeyListener: [{
136
+ type: HostListener,
137
+ args: ['keydown.end', ['$event']]
138
+ }], navigable: [{
139
+ type: Input
75
140
  }] } });