@progress/kendo-angular-buttons 11.4.0-develop.5 → 11.4.0-develop.7

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.
@@ -52,14 +52,27 @@ export declare class ChipListComponent implements OnInit, AfterViewInit, AfterCo
52
52
  chips: QueryList<ChipComponent>;
53
53
  get single(): boolean;
54
54
  get multiple(): boolean;
55
+ /**
56
+ * @hidden
57
+ */
55
58
  role: string;
56
59
  private dynamicRTLSubscription;
57
60
  private _size;
58
61
  private subs;
62
+ private _navigable;
59
63
  /**
60
64
  * @hidden
61
65
  */
62
66
  onClick($event: any): void;
67
+ /**
68
+ * When set to `true`, keyboard navigation is available through arrow keys and roving tabindex. Otherwise, all chips
69
+ * are part of the default tabbing sequence of the page.
70
+ *
71
+ * @default false
72
+ */
73
+ set navigable(value: boolean);
74
+ get navigable(): boolean;
75
+ private currentActiveIndex;
63
76
  constructor(localizationService: LocalizationService, renderer: Renderer2, element: ElementRef, ngZone: NgZone);
64
77
  ngOnInit(): void;
65
78
  ngAfterViewInit(): void;
@@ -74,6 +87,9 @@ export declare class ChipListComponent implements OnInit, AfterViewInit, AfterCo
74
87
  private handleClasses;
75
88
  private attachElementEventHandlers;
76
89
  private keyDownHandler;
90
+ private handleArrowKeys;
91
+ private updateChips;
92
+ private normalizeActiveIndex;
77
93
  static ɵfac: i0.ɵɵFactoryDeclaration<ChipListComponent, never>;
78
- static ɵcmp: i0.ɵɵComponentDeclaration<ChipListComponent, "kendo-chiplist, kendo-chip-list", never, { "selection": "selection"; "size": "size"; }, { "selectedChange": "selectedChange"; "remove": "remove"; }, ["chips"], ["*"]>;
94
+ static ɵcmp: i0.ɵɵComponentDeclaration<ChipListComponent, "kendo-chiplist, kendo-chip-list", never, { "selection": "selection"; "size": "size"; "role": "role"; "navigable": "navigable"; }, { "selectedChange": "selectedChange"; "remove": "remove"; }, ["chips"], ["*"]>;
79
95
  }
@@ -9,7 +9,7 @@ import { ChipComponent } from './chip.component';
9
9
  import { closest, getStylingClasses } from '../util';
10
10
  import { validatePackage } from '@progress/kendo-licensing';
11
11
  import { packageMetadata } from '../package-metadata';
12
- import { Keys } from '@progress/kendo-angular-common';
12
+ import { isDocumentAvailable, Keys } from '@progress/kendo-angular-common';
13
13
  import * as i0 from "@angular/core";
14
14
  import * as i1 from "@progress/kendo-angular-l10n";
15
15
  export class ChipListComponent {
@@ -37,9 +37,14 @@ export class ChipListComponent {
37
37
  * Fires each time the user clicks on the remove icon of the Chip.
38
38
  */
39
39
  this.remove = new EventEmitter();
40
+ /**
41
+ * @hidden
42
+ */
40
43
  this.role = 'listbox';
41
44
  this._size = 'medium';
42
45
  this.subs = new Subscription();
46
+ this._navigable = false;
47
+ this.currentActiveIndex = 0;
43
48
  validatePackage(packageMetadata);
44
49
  this.direction = localizationService.rtl ? 'rtl' : 'ltr';
45
50
  }
@@ -75,6 +80,8 @@ export class ChipListComponent {
75
80
  const isRemoveClicked = closest(target, '.k-chip-remove-action');
76
81
  const clickedChip = closest(target, '.k-chip');
77
82
  const chip = this.chips.find((chip) => clickedChip === chip.element.nativeElement);
83
+ this.currentActiveIndex = this.chips.toArray().indexOf(chip);
84
+ chip && chip.focus();
78
85
  if (isRemoveClicked && clickedChip) {
79
86
  const removeEventArgs = { sender: this, originalEvent: $event, removedChip: chip };
80
87
  this.remove.emit(removeEventArgs);
@@ -83,6 +90,20 @@ export class ChipListComponent {
83
90
  this.setSelection(chip);
84
91
  }
85
92
  }
93
+ /**
94
+ * When set to `true`, keyboard navigation is available through arrow keys and roving tabindex. Otherwise, all chips
95
+ * are part of the default tabbing sequence of the page.
96
+ *
97
+ * @default false
98
+ */
99
+ set navigable(value) {
100
+ this._navigable = value;
101
+ this.chips?.forEach(c => this.renderer.setAttribute(c.element.nativeElement, 'tabindex', value ? '-1' : '0'));
102
+ this.chips?.first && this.renderer.setAttribute(this.chips.first.element.nativeElement, 'tabindex', '0');
103
+ }
104
+ get navigable() {
105
+ return this._navigable;
106
+ }
86
107
  ngOnInit() {
87
108
  this.dynamicRTLSubscription = this.localizationService.changes
88
109
  .subscribe(({ rtl }) => this.direction = rtl ? 'rtl' : 'ltr');
@@ -92,18 +113,11 @@ export class ChipListComponent {
92
113
  stylingInputs.forEach(input => {
93
114
  this.handleClasses(this[input], input);
94
115
  });
116
+ this.attachElementEventHandlers();
95
117
  }
96
118
  ngAfterContentInit() {
97
- this.chips.forEach((chip) => {
98
- const chipEl = chip.element.nativeElement;
99
- this.renderer.setAttribute(chipEl, 'role', 'option');
100
- if (chip.removable) {
101
- this.renderer.setAttribute(chipEl, 'aria-keyshortcuts', 'Enter Delete');
102
- }
103
- this.renderer.removeAttribute(chipEl, 'aria-pressed');
104
- this.renderer.setAttribute(chipEl, 'aria-selected', `${chip.selected}`);
105
- });
106
- this.attachElementEventHandlers();
119
+ this.updateChips();
120
+ this.subs.add(this.chips?.changes.subscribe(() => this.updateChips()));
107
121
  }
108
122
  ngOnDestroy() {
109
123
  if (this.dynamicRTLSubscription) {
@@ -153,10 +167,13 @@ export class ChipListComponent {
153
167
  keyDownHandler(e) {
154
168
  const isEnterOrSpace = e.keyCode === Keys.Enter || e.keyCode === Keys.Space;
155
169
  const isDeleteOrBackspace = e.keyCode === Keys.Delete || e.keyCode === Keys.Backspace;
170
+ const isLeftArrow = e.keyCode === Keys.ArrowLeft;
171
+ const isRightArrow = e.keyCode === Keys.ArrowRight;
156
172
  if (isEnterOrSpace) {
157
173
  const target = e.target;
158
174
  const clickedChip = closest(target, '.k-chip');
159
175
  const chip = this.chips.find((chip) => clickedChip === chip.element.nativeElement);
176
+ this.currentActiveIndex = this.chips.toArray().findIndex((chip) => clickedChip === chip.element.nativeElement);
160
177
  if (this.selection !== 'none' && clickedChip) {
161
178
  this.ngZone.run(() => {
162
179
  this.setSelection(chip);
@@ -174,10 +191,60 @@ export class ChipListComponent {
174
191
  });
175
192
  }
176
193
  }
194
+ else if (isLeftArrow) {
195
+ this.handleArrowKeys('left');
196
+ }
197
+ else if (isRightArrow) {
198
+ this.handleArrowKeys('right');
199
+ }
200
+ }
201
+ handleArrowKeys(direction) {
202
+ if (!this.navigable) {
203
+ return;
204
+ }
205
+ const directionDelta = direction === 'left' ? -1 : 1;
206
+ this.currentActiveIndex = this.currentActiveIndex + directionDelta;
207
+ if (this.currentActiveIndex >= this.chips.length) {
208
+ this.currentActiveIndex = 0;
209
+ }
210
+ else if (this.currentActiveIndex < 0) {
211
+ this.currentActiveIndex = this.chips.length - 1;
212
+ }
213
+ this.chips.forEach((chip, idx) => {
214
+ this.renderer.removeAttribute(chip.element.nativeElement, 'tabindex');
215
+ if (idx === this.currentActiveIndex) {
216
+ this.renderer.setAttribute(chip.element.nativeElement, 'tabindex', '0');
217
+ chip.focus();
218
+ }
219
+ });
220
+ }
221
+ updateChips() {
222
+ this.normalizeActiveIndex();
223
+ this.chips.forEach((chip, idx) => {
224
+ const chipEl = chip.element.nativeElement;
225
+ this.renderer.removeAttribute(chip.element.nativeElement, 'tabindex');
226
+ if (idx === this.currentActiveIndex) {
227
+ this.renderer.setAttribute(chip.element.nativeElement, 'tabindex', '0');
228
+ if (isDocumentAvailable() && document.activeElement.closest('.k-chip-list')) {
229
+ chip.focus();
230
+ }
231
+ }
232
+ this.role === 'listbox' && this.renderer.setAttribute(chipEl, 'role', 'option');
233
+ if (chip.removable) {
234
+ this.renderer.setAttribute(chipEl, 'aria-keyshortcuts', 'Enter Delete');
235
+ }
236
+ this.renderer.removeAttribute(chipEl, 'aria-pressed');
237
+ this.renderer.setAttribute(chipEl, 'aria-selected', `${chip.selected}`);
238
+ });
239
+ }
240
+ normalizeActiveIndex() {
241
+ if (this.currentActiveIndex >= this.chips.length) {
242
+ this.currentActiveIndex = Math.max(this.chips.length - 1, 0);
243
+ }
177
244
  }
178
245
  }
179
246
  ChipListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: ChipListComponent, deps: [{ token: i1.LocalizationService }, { token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
180
- ChipListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: ChipListComponent, selector: "kendo-chiplist, kendo-chip-list", inputs: { selection: "selection", size: "size" }, outputs: { selectedChange: "selectedChange", remove: "remove" }, host: { listeners: { "click": "onClick($event)" }, properties: { "class.k-chip-list": "this.hostClass", "attr.aria-orientation": "this.orientation", "attr.dir": "this.direction", "class.k-selection-single": "this.single", "attr.aria-multiselectable": "this.multiple", "class.k-selection-multiple": "this.multiple", "attr.role": "this.role" } }, providers: [
247
+ ChipListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: ChipListComponent, selector: "kendo-chiplist, kendo-chip-list", inputs: { selection: "selection", size: "size", role: "role", navigable: "navigable" }, outputs: { selectedChange: "selectedChange", remove: "remove" }, host: { listeners: { "click": "onClick($event)" }, properties: { "class.k-chip-list": "this.hostClass", "attr.aria-orientation": "this.orientation", "attr.dir": "this.direction", "class.k-selection-single": "this.single", "attr.aria-multiselectable": "this.multiple", "class.k-selection-multiple": "this.multiple", "attr.role": "this.role" } }, providers: [
181
248
  LocalizationService,
182
249
  {
183
250
  provide: L10N_PREFIX,
@@ -233,7 +300,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
233
300
  }], role: [{
234
301
  type: HostBinding,
235
302
  args: ['attr.role']
303
+ }, {
304
+ type: Input
236
305
  }], onClick: [{
237
306
  type: HostListener,
238
307
  args: ['click', ['$event']]
308
+ }], navigable: [{
309
+ type: Input
239
310
  }] } });
@@ -9,7 +9,7 @@ export const packageMetadata = {
9
9
  name: '@progress/kendo-angular-buttons',
10
10
  productName: 'Kendo UI for Angular',
11
11
  productCodes: ['KENDOUIANGULAR', 'KENDOUICOMPLETE'],
12
- publishDate: 1678461431,
13
- version: '11.4.0-develop.5',
12
+ publishDate: 1678790035,
13
+ version: '11.4.0-develop.7',
14
14
  licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/'
15
15
  };
@@ -28,8 +28,8 @@ const packageMetadata = {
28
28
  name: '@progress/kendo-angular-buttons',
29
29
  productName: 'Kendo UI for Angular',
30
30
  productCodes: ['KENDOUIANGULAR', 'KENDOUICOMPLETE'],
31
- publishDate: 1678461431,
32
- version: '11.4.0-develop.5',
31
+ publishDate: 1678790035,
32
+ version: '11.4.0-develop.7',
33
33
  licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/'
34
34
  };
35
35
 
@@ -3736,9 +3736,14 @@ class ChipListComponent {
3736
3736
  * Fires each time the user clicks on the remove icon of the Chip.
3737
3737
  */
3738
3738
  this.remove = new EventEmitter();
3739
+ /**
3740
+ * @hidden
3741
+ */
3739
3742
  this.role = 'listbox';
3740
3743
  this._size = 'medium';
3741
3744
  this.subs = new Subscription();
3745
+ this._navigable = false;
3746
+ this.currentActiveIndex = 0;
3742
3747
  validatePackage(packageMetadata);
3743
3748
  this.direction = localizationService.rtl ? 'rtl' : 'ltr';
3744
3749
  }
@@ -3774,6 +3779,8 @@ class ChipListComponent {
3774
3779
  const isRemoveClicked = closest(target, '.k-chip-remove-action');
3775
3780
  const clickedChip = closest(target, '.k-chip');
3776
3781
  const chip = this.chips.find((chip) => clickedChip === chip.element.nativeElement);
3782
+ this.currentActiveIndex = this.chips.toArray().indexOf(chip);
3783
+ chip && chip.focus();
3777
3784
  if (isRemoveClicked && clickedChip) {
3778
3785
  const removeEventArgs = { sender: this, originalEvent: $event, removedChip: chip };
3779
3786
  this.remove.emit(removeEventArgs);
@@ -3782,6 +3789,21 @@ class ChipListComponent {
3782
3789
  this.setSelection(chip);
3783
3790
  }
3784
3791
  }
3792
+ /**
3793
+ * When set to `true`, keyboard navigation is available through arrow keys and roving tabindex. Otherwise, all chips
3794
+ * are part of the default tabbing sequence of the page.
3795
+ *
3796
+ * @default false
3797
+ */
3798
+ set navigable(value) {
3799
+ var _a, _b;
3800
+ this._navigable = value;
3801
+ (_a = this.chips) === null || _a === void 0 ? void 0 : _a.forEach(c => this.renderer.setAttribute(c.element.nativeElement, 'tabindex', value ? '-1' : '0'));
3802
+ ((_b = this.chips) === null || _b === void 0 ? void 0 : _b.first) && this.renderer.setAttribute(this.chips.first.element.nativeElement, 'tabindex', '0');
3803
+ }
3804
+ get navigable() {
3805
+ return this._navigable;
3806
+ }
3785
3807
  ngOnInit() {
3786
3808
  this.dynamicRTLSubscription = this.localizationService.changes
3787
3809
  .subscribe(({ rtl }) => this.direction = rtl ? 'rtl' : 'ltr');
@@ -3791,18 +3813,12 @@ class ChipListComponent {
3791
3813
  stylingInputs.forEach(input => {
3792
3814
  this.handleClasses(this[input], input);
3793
3815
  });
3816
+ this.attachElementEventHandlers();
3794
3817
  }
3795
3818
  ngAfterContentInit() {
3796
- this.chips.forEach((chip) => {
3797
- const chipEl = chip.element.nativeElement;
3798
- this.renderer.setAttribute(chipEl, 'role', 'option');
3799
- if (chip.removable) {
3800
- this.renderer.setAttribute(chipEl, 'aria-keyshortcuts', 'Enter Delete');
3801
- }
3802
- this.renderer.removeAttribute(chipEl, 'aria-pressed');
3803
- this.renderer.setAttribute(chipEl, 'aria-selected', `${chip.selected}`);
3804
- });
3805
- this.attachElementEventHandlers();
3819
+ var _a;
3820
+ this.updateChips();
3821
+ this.subs.add((_a = this.chips) === null || _a === void 0 ? void 0 : _a.changes.subscribe(() => this.updateChips()));
3806
3822
  }
3807
3823
  ngOnDestroy() {
3808
3824
  if (this.dynamicRTLSubscription) {
@@ -3852,10 +3868,13 @@ class ChipListComponent {
3852
3868
  keyDownHandler(e) {
3853
3869
  const isEnterOrSpace = e.keyCode === Keys.Enter || e.keyCode === Keys.Space;
3854
3870
  const isDeleteOrBackspace = e.keyCode === Keys.Delete || e.keyCode === Keys.Backspace;
3871
+ const isLeftArrow = e.keyCode === Keys.ArrowLeft;
3872
+ const isRightArrow = e.keyCode === Keys.ArrowRight;
3855
3873
  if (isEnterOrSpace) {
3856
3874
  const target = e.target;
3857
3875
  const clickedChip = closest(target, '.k-chip');
3858
3876
  const chip = this.chips.find((chip) => clickedChip === chip.element.nativeElement);
3877
+ this.currentActiveIndex = this.chips.toArray().findIndex((chip) => clickedChip === chip.element.nativeElement);
3859
3878
  if (this.selection !== 'none' && clickedChip) {
3860
3879
  this.ngZone.run(() => {
3861
3880
  this.setSelection(chip);
@@ -3873,10 +3892,60 @@ class ChipListComponent {
3873
3892
  });
3874
3893
  }
3875
3894
  }
3895
+ else if (isLeftArrow) {
3896
+ this.handleArrowKeys('left');
3897
+ }
3898
+ else if (isRightArrow) {
3899
+ this.handleArrowKeys('right');
3900
+ }
3901
+ }
3902
+ handleArrowKeys(direction) {
3903
+ if (!this.navigable) {
3904
+ return;
3905
+ }
3906
+ const directionDelta = direction === 'left' ? -1 : 1;
3907
+ this.currentActiveIndex = this.currentActiveIndex + directionDelta;
3908
+ if (this.currentActiveIndex >= this.chips.length) {
3909
+ this.currentActiveIndex = 0;
3910
+ }
3911
+ else if (this.currentActiveIndex < 0) {
3912
+ this.currentActiveIndex = this.chips.length - 1;
3913
+ }
3914
+ this.chips.forEach((chip, idx) => {
3915
+ this.renderer.removeAttribute(chip.element.nativeElement, 'tabindex');
3916
+ if (idx === this.currentActiveIndex) {
3917
+ this.renderer.setAttribute(chip.element.nativeElement, 'tabindex', '0');
3918
+ chip.focus();
3919
+ }
3920
+ });
3921
+ }
3922
+ updateChips() {
3923
+ this.normalizeActiveIndex();
3924
+ this.chips.forEach((chip, idx) => {
3925
+ const chipEl = chip.element.nativeElement;
3926
+ this.renderer.removeAttribute(chip.element.nativeElement, 'tabindex');
3927
+ if (idx === this.currentActiveIndex) {
3928
+ this.renderer.setAttribute(chip.element.nativeElement, 'tabindex', '0');
3929
+ if (isDocumentAvailable() && document.activeElement.closest('.k-chip-list')) {
3930
+ chip.focus();
3931
+ }
3932
+ }
3933
+ this.role === 'listbox' && this.renderer.setAttribute(chipEl, 'role', 'option');
3934
+ if (chip.removable) {
3935
+ this.renderer.setAttribute(chipEl, 'aria-keyshortcuts', 'Enter Delete');
3936
+ }
3937
+ this.renderer.removeAttribute(chipEl, 'aria-pressed');
3938
+ this.renderer.setAttribute(chipEl, 'aria-selected', `${chip.selected}`);
3939
+ });
3940
+ }
3941
+ normalizeActiveIndex() {
3942
+ if (this.currentActiveIndex >= this.chips.length) {
3943
+ this.currentActiveIndex = Math.max(this.chips.length - 1, 0);
3944
+ }
3876
3945
  }
3877
3946
  }
3878
3947
  ChipListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: ChipListComponent, deps: [{ token: i1.LocalizationService }, { token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
3879
- ChipListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: ChipListComponent, selector: "kendo-chiplist, kendo-chip-list", inputs: { selection: "selection", size: "size" }, outputs: { selectedChange: "selectedChange", remove: "remove" }, host: { listeners: { "click": "onClick($event)" }, properties: { "class.k-chip-list": "this.hostClass", "attr.aria-orientation": "this.orientation", "attr.dir": "this.direction", "class.k-selection-single": "this.single", "attr.aria-multiselectable": "this.multiple", "class.k-selection-multiple": "this.multiple", "attr.role": "this.role" } }, providers: [
3948
+ ChipListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: ChipListComponent, selector: "kendo-chiplist, kendo-chip-list", inputs: { selection: "selection", size: "size", role: "role", navigable: "navigable" }, outputs: { selectedChange: "selectedChange", remove: "remove" }, host: { listeners: { "click": "onClick($event)" }, properties: { "class.k-chip-list": "this.hostClass", "attr.aria-orientation": "this.orientation", "attr.dir": "this.direction", "class.k-selection-single": "this.single", "attr.aria-multiselectable": "this.multiple", "class.k-selection-multiple": "this.multiple", "attr.role": "this.role" } }, providers: [
3880
3949
  LocalizationService,
3881
3950
  {
3882
3951
  provide: L10N_PREFIX,
@@ -3932,9 +4001,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
3932
4001
  }], role: [{
3933
4002
  type: HostBinding,
3934
4003
  args: ['attr.role']
4004
+ }, {
4005
+ type: Input
3935
4006
  }], onClick: [{
3936
4007
  type: HostListener,
3937
4008
  args: ['click', ['$event']]
4009
+ }], navigable: [{
4010
+ type: Input
3938
4011
  }] } });
3939
4012
 
3940
4013
  const exportedModules$1 = [
@@ -46,8 +46,8 @@ const packageMetadata = {
46
46
  name: '@progress/kendo-angular-buttons',
47
47
  productName: 'Kendo UI for Angular',
48
48
  productCodes: ['KENDOUIANGULAR', 'KENDOUICOMPLETE'],
49
- publishDate: 1678461431,
50
- version: '11.4.0-develop.5',
49
+ publishDate: 1678790035,
50
+ version: '11.4.0-develop.7',
51
51
  licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/'
52
52
  };
53
53
 
@@ -3730,9 +3730,14 @@ class ChipListComponent {
3730
3730
  * Fires each time the user clicks on the remove icon of the Chip.
3731
3731
  */
3732
3732
  this.remove = new EventEmitter();
3733
+ /**
3734
+ * @hidden
3735
+ */
3733
3736
  this.role = 'listbox';
3734
3737
  this._size = 'medium';
3735
3738
  this.subs = new Subscription();
3739
+ this._navigable = false;
3740
+ this.currentActiveIndex = 0;
3736
3741
  validatePackage(packageMetadata);
3737
3742
  this.direction = localizationService.rtl ? 'rtl' : 'ltr';
3738
3743
  }
@@ -3768,6 +3773,8 @@ class ChipListComponent {
3768
3773
  const isRemoveClicked = closest(target, '.k-chip-remove-action');
3769
3774
  const clickedChip = closest(target, '.k-chip');
3770
3775
  const chip = this.chips.find((chip) => clickedChip === chip.element.nativeElement);
3776
+ this.currentActiveIndex = this.chips.toArray().indexOf(chip);
3777
+ chip && chip.focus();
3771
3778
  if (isRemoveClicked && clickedChip) {
3772
3779
  const removeEventArgs = { sender: this, originalEvent: $event, removedChip: chip };
3773
3780
  this.remove.emit(removeEventArgs);
@@ -3776,6 +3783,20 @@ class ChipListComponent {
3776
3783
  this.setSelection(chip);
3777
3784
  }
3778
3785
  }
3786
+ /**
3787
+ * When set to `true`, keyboard navigation is available through arrow keys and roving tabindex. Otherwise, all chips
3788
+ * are part of the default tabbing sequence of the page.
3789
+ *
3790
+ * @default false
3791
+ */
3792
+ set navigable(value) {
3793
+ this._navigable = value;
3794
+ this.chips?.forEach(c => this.renderer.setAttribute(c.element.nativeElement, 'tabindex', value ? '-1' : '0'));
3795
+ this.chips?.first && this.renderer.setAttribute(this.chips.first.element.nativeElement, 'tabindex', '0');
3796
+ }
3797
+ get navigable() {
3798
+ return this._navigable;
3799
+ }
3779
3800
  ngOnInit() {
3780
3801
  this.dynamicRTLSubscription = this.localizationService.changes
3781
3802
  .subscribe(({ rtl }) => this.direction = rtl ? 'rtl' : 'ltr');
@@ -3785,18 +3806,11 @@ class ChipListComponent {
3785
3806
  stylingInputs.forEach(input => {
3786
3807
  this.handleClasses(this[input], input);
3787
3808
  });
3809
+ this.attachElementEventHandlers();
3788
3810
  }
3789
3811
  ngAfterContentInit() {
3790
- this.chips.forEach((chip) => {
3791
- const chipEl = chip.element.nativeElement;
3792
- this.renderer.setAttribute(chipEl, 'role', 'option');
3793
- if (chip.removable) {
3794
- this.renderer.setAttribute(chipEl, 'aria-keyshortcuts', 'Enter Delete');
3795
- }
3796
- this.renderer.removeAttribute(chipEl, 'aria-pressed');
3797
- this.renderer.setAttribute(chipEl, 'aria-selected', `${chip.selected}`);
3798
- });
3799
- this.attachElementEventHandlers();
3812
+ this.updateChips();
3813
+ this.subs.add(this.chips?.changes.subscribe(() => this.updateChips()));
3800
3814
  }
3801
3815
  ngOnDestroy() {
3802
3816
  if (this.dynamicRTLSubscription) {
@@ -3846,10 +3860,13 @@ class ChipListComponent {
3846
3860
  keyDownHandler(e) {
3847
3861
  const isEnterOrSpace = e.keyCode === Keys.Enter || e.keyCode === Keys.Space;
3848
3862
  const isDeleteOrBackspace = e.keyCode === Keys.Delete || e.keyCode === Keys.Backspace;
3863
+ const isLeftArrow = e.keyCode === Keys.ArrowLeft;
3864
+ const isRightArrow = e.keyCode === Keys.ArrowRight;
3849
3865
  if (isEnterOrSpace) {
3850
3866
  const target = e.target;
3851
3867
  const clickedChip = closest(target, '.k-chip');
3852
3868
  const chip = this.chips.find((chip) => clickedChip === chip.element.nativeElement);
3869
+ this.currentActiveIndex = this.chips.toArray().findIndex((chip) => clickedChip === chip.element.nativeElement);
3853
3870
  if (this.selection !== 'none' && clickedChip) {
3854
3871
  this.ngZone.run(() => {
3855
3872
  this.setSelection(chip);
@@ -3867,10 +3884,60 @@ class ChipListComponent {
3867
3884
  });
3868
3885
  }
3869
3886
  }
3887
+ else if (isLeftArrow) {
3888
+ this.handleArrowKeys('left');
3889
+ }
3890
+ else if (isRightArrow) {
3891
+ this.handleArrowKeys('right');
3892
+ }
3893
+ }
3894
+ handleArrowKeys(direction) {
3895
+ if (!this.navigable) {
3896
+ return;
3897
+ }
3898
+ const directionDelta = direction === 'left' ? -1 : 1;
3899
+ this.currentActiveIndex = this.currentActiveIndex + directionDelta;
3900
+ if (this.currentActiveIndex >= this.chips.length) {
3901
+ this.currentActiveIndex = 0;
3902
+ }
3903
+ else if (this.currentActiveIndex < 0) {
3904
+ this.currentActiveIndex = this.chips.length - 1;
3905
+ }
3906
+ this.chips.forEach((chip, idx) => {
3907
+ this.renderer.removeAttribute(chip.element.nativeElement, 'tabindex');
3908
+ if (idx === this.currentActiveIndex) {
3909
+ this.renderer.setAttribute(chip.element.nativeElement, 'tabindex', '0');
3910
+ chip.focus();
3911
+ }
3912
+ });
3913
+ }
3914
+ updateChips() {
3915
+ this.normalizeActiveIndex();
3916
+ this.chips.forEach((chip, idx) => {
3917
+ const chipEl = chip.element.nativeElement;
3918
+ this.renderer.removeAttribute(chip.element.nativeElement, 'tabindex');
3919
+ if (idx === this.currentActiveIndex) {
3920
+ this.renderer.setAttribute(chip.element.nativeElement, 'tabindex', '0');
3921
+ if (isDocumentAvailable() && document.activeElement.closest('.k-chip-list')) {
3922
+ chip.focus();
3923
+ }
3924
+ }
3925
+ this.role === 'listbox' && this.renderer.setAttribute(chipEl, 'role', 'option');
3926
+ if (chip.removable) {
3927
+ this.renderer.setAttribute(chipEl, 'aria-keyshortcuts', 'Enter Delete');
3928
+ }
3929
+ this.renderer.removeAttribute(chipEl, 'aria-pressed');
3930
+ this.renderer.setAttribute(chipEl, 'aria-selected', `${chip.selected}`);
3931
+ });
3932
+ }
3933
+ normalizeActiveIndex() {
3934
+ if (this.currentActiveIndex >= this.chips.length) {
3935
+ this.currentActiveIndex = Math.max(this.chips.length - 1, 0);
3936
+ }
3870
3937
  }
3871
3938
  }
3872
3939
  ChipListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: ChipListComponent, deps: [{ token: i1.LocalizationService }, { token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
3873
- ChipListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: ChipListComponent, selector: "kendo-chiplist, kendo-chip-list", inputs: { selection: "selection", size: "size" }, outputs: { selectedChange: "selectedChange", remove: "remove" }, host: { listeners: { "click": "onClick($event)" }, properties: { "class.k-chip-list": "this.hostClass", "attr.aria-orientation": "this.orientation", "attr.dir": "this.direction", "class.k-selection-single": "this.single", "attr.aria-multiselectable": "this.multiple", "class.k-selection-multiple": "this.multiple", "attr.role": "this.role" } }, providers: [
3940
+ ChipListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: ChipListComponent, selector: "kendo-chiplist, kendo-chip-list", inputs: { selection: "selection", size: "size", role: "role", navigable: "navigable" }, outputs: { selectedChange: "selectedChange", remove: "remove" }, host: { listeners: { "click": "onClick($event)" }, properties: { "class.k-chip-list": "this.hostClass", "attr.aria-orientation": "this.orientation", "attr.dir": "this.direction", "class.k-selection-single": "this.single", "attr.aria-multiselectable": "this.multiple", "class.k-selection-multiple": "this.multiple", "attr.role": "this.role" } }, providers: [
3874
3941
  LocalizationService,
3875
3942
  {
3876
3943
  provide: L10N_PREFIX,
@@ -3926,9 +3993,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
3926
3993
  }], role: [{
3927
3994
  type: HostBinding,
3928
3995
  args: ['attr.role']
3996
+ }, {
3997
+ type: Input
3929
3998
  }], onClick: [{
3930
3999
  type: HostListener,
3931
4000
  args: ['click', ['$event']]
4001
+ }], navigable: [{
4002
+ type: Input
3932
4003
  }] } });
3933
4004
 
3934
4005
  const exportedModules$1 = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@progress/kendo-angular-buttons",
3
- "version": "11.4.0-develop.5",
3
+ "version": "11.4.0-develop.7",
4
4
  "description": "Buttons Package for Angular",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "author": "Progress",
@@ -25,15 +25,15 @@
25
25
  "@angular/core": "13 - 15",
26
26
  "@angular/platform-browser": "13 - 15",
27
27
  "@progress/kendo-licensing": "^1.0.2",
28
- "@progress/kendo-angular-common": "11.4.0-develop.5",
29
- "@progress/kendo-angular-l10n": "11.4.0-develop.5",
30
- "@progress/kendo-angular-popup": "11.4.0-develop.5",
31
- "@progress/kendo-angular-icons": "11.4.0-develop.5",
28
+ "@progress/kendo-angular-common": "11.4.0-develop.7",
29
+ "@progress/kendo-angular-l10n": "11.4.0-develop.7",
30
+ "@progress/kendo-angular-popup": "11.4.0-develop.7",
31
+ "@progress/kendo-angular-icons": "11.4.0-develop.7",
32
32
  "rxjs": "^6.5.3 || ^7.0.0"
33
33
  },
34
34
  "dependencies": {
35
35
  "tslib": "^2.3.1",
36
- "@progress/kendo-angular-schematics": "11.4.0-develop.5",
36
+ "@progress/kendo-angular-schematics": "11.4.0-develop.7",
37
37
  "@progress/kendo-common": "^0.2.1"
38
38
  },
39
39
  "schematics": "./schematics/collection.json",