@progress/kendo-angular-listbox 21.0.0-develop.9 → 21.0.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.
@@ -22,11 +22,13 @@ export class KeyboardNavigationService {
22
22
  onTransferAllEvent = new EventEmitter();
23
23
  onShiftSelectedItem = new EventEmitter();
24
24
  onSelectionChange = new EventEmitter();
25
+ onSelectAll = new EventEmitter();
26
+ onSelectToEnd = new EventEmitter();
25
27
  constructor(renderer, zone) {
26
28
  this.renderer = renderer;
27
29
  this.zone = zone;
28
30
  }
29
- onKeyDown(event, toolsRef, toolbar, childListbox, parentListbox, listboxItems) {
31
+ onKeyDown(event, toolsRef, toolbar, childListbox, parentListbox, listboxItems, currentListbox) {
30
32
  const target = event.target;
31
33
  const keyCode = normalizeNumpadKeys(event);
32
34
  const ctrlOrMetaKey = event.ctrlKey || event.metaKey;
@@ -48,6 +50,17 @@ export class KeyboardNavigationService {
48
50
  this.onDeleteEvent.emit(this.selectedListboxItemIndex);
49
51
  }
50
52
  }
53
+ if (ctrlOrMetaKey && (event.key === 'a' || event.key === 'A')) {
54
+ event.preventDefault();
55
+ this.onSelectAll.emit();
56
+ return;
57
+ }
58
+ if (ctrlOrMetaKey && event.shiftKey && (keyCode === Keys.Home || keyCode === Keys.End)) {
59
+ event.preventDefault();
60
+ const direction = keyCode === Keys.Home ? 'home' : 'end';
61
+ this.onSelectToEnd.emit({ direction });
62
+ return;
63
+ }
51
64
  const isTargetListboxItem = listboxItems.find(elem => elem.nativeElement === target);
52
65
  if (isTargetListboxItem) {
53
66
  let isTransferToolVisible;
@@ -55,7 +68,7 @@ export class KeyboardNavigationService {
55
68
  isTransferToolVisible = activeToolbar.some(tool => tool.name.startsWith('transfer'));
56
69
  }
57
70
  if ((keyCode === Keys.ArrowRight || keyCode === Keys.ArrowLeft) && ctrlOrMetaKey && isTransferToolVisible) {
58
- this.onArrowLeftOrRight(keyCode, parentListbox, childListbox, event, listboxItems);
71
+ this.onArrowLeftOrRight(keyCode, parentListbox, childListbox, event, listboxItems, currentListbox);
59
72
  }
60
73
  else if ((keyCode === Keys.ArrowUp || keyCode === Keys.ArrowDown)) {
61
74
  this.onArrowUpOrDown(keyCode, ctrlOrMetaKey, event, activeToolbar, listboxItems);
@@ -64,9 +77,7 @@ export class KeyboardNavigationService {
64
77
  this.onSelectChange(event, listboxItems);
65
78
  }
66
79
  else if (keyCode === Keys.Space) {
67
- if (this.selectedListboxItemIndex !== this.focusedListboxItemIndex) {
68
- this.onSpaceKey(event, listboxItems);
69
- }
80
+ this.onSpaceKey(event, listboxItems);
70
81
  }
71
82
  }
72
83
  }
@@ -90,17 +101,27 @@ export class KeyboardNavigationService {
90
101
  }
91
102
  const offset = dir === 'up' ? -1 : 1;
92
103
  this.focusedToolIndex += offset;
93
- const prevItem = toolsRef[this.focusedToolIndex + (offset * -1)].element;
94
- const currentItem = toolsRef[this.focusedToolIndex].element;
104
+ const prevItem = toolsRef[this.focusedToolIndex + (offset * -1)]?.element;
105
+ const currentItem = toolsRef[this.focusedToolIndex]?.element;
95
106
  this.changeTabindex(prevItem, currentItem);
96
107
  }
97
108
  onSpaceKey(event, listboxItems) {
98
109
  event.stopImmediatePropagation();
99
110
  event.preventDefault();
100
- const previousItem = listboxItems[this.selectedListboxItemIndex]?.nativeElement;
101
- const currentItem = listboxItems[this.focusedListboxItemIndex]?.nativeElement;
102
- this.changeTabindex(previousItem, currentItem);
103
- this.onSelectionChange.emit({ index: this.focusedListboxItemIndex, prevIndex: this.selectedListboxItemIndex });
111
+ event.stopPropagation();
112
+ const ctrlKey = event.ctrlKey || event.metaKey;
113
+ const shiftKey = event.shiftKey;
114
+ if (this.selectedListboxItemIndex !== this.focusedListboxItemIndex) {
115
+ const previousItem = listboxItems[this.selectedListboxItemIndex]?.nativeElement;
116
+ const currentItem = listboxItems[this.focusedListboxItemIndex]?.nativeElement;
117
+ this.changeTabindex(previousItem, currentItem);
118
+ }
119
+ this.onSelectionChange.emit({
120
+ index: this.focusedListboxItemIndex,
121
+ prevIndex: this.selectedListboxItemIndex,
122
+ ctrlKey,
123
+ shiftKey
124
+ });
104
125
  this.selectedListboxItemIndex = this.focusedListboxItemIndex;
105
126
  }
106
127
  onArrowUpOrDown(keyCode, ctrlOrMetaKey, event, activeToolbar, listboxItems) {
@@ -118,17 +139,24 @@ export class KeyboardNavigationService {
118
139
  this.changeFocusedItem(dir, listboxItems);
119
140
  return;
120
141
  }
142
+ if (event.shiftKey) {
143
+ this.onShiftArrow(dir, listboxItems);
144
+ return;
145
+ }
121
146
  dir === 'moveUp' ? this.onArrowUp(listboxItems) : this.onArrowDown(listboxItems);
122
147
  this.onSelectionChange.emit({ index: this.selectedListboxItemIndex, prevIndex: this.focusedListboxItemIndex });
123
148
  this.focusedListboxItemIndex = this.selectedListboxItemIndex;
124
149
  }
125
- onArrowLeftOrRight(keyCode, parentListbox, childListbox, event, listboxItems) {
150
+ onArrowLeftOrRight(keyCode, parentListbox, childListbox, event, listboxItems, currentListbox) {
126
151
  event.preventDefault();
127
152
  if (event.shiftKey) {
128
153
  this.transferAllItems(keyCode, childListbox, parentListbox);
129
154
  return;
130
155
  }
131
- if (this.selectedListboxItemIndex >= 0) {
156
+ const isArrowRight = keyCode === Keys.ArrowRight;
157
+ const sourceListbox = isArrowRight ? currentListbox : childListbox || parentListbox?.childListbox;
158
+ const hasSelection = sourceListbox?.selectedIndices && sourceListbox.selectedIndices.length > 0;
159
+ if (hasSelection) {
132
160
  this.transferItem(keyCode, childListbox, parentListbox, listboxItems);
133
161
  }
134
162
  }
@@ -151,7 +179,8 @@ export class KeyboardNavigationService {
151
179
  this.selectedListboxItemIndex = this.focusedListboxItemIndex;
152
180
  }
153
181
  this.changeTabindex(previousItem, currentItem, !!currentItem);
154
- this.onSelectionChange.emit({ index: this.selectedListboxItemIndex, prevIndex });
182
+ const ctrlKey = event.ctrlKey || event.metaKey;
183
+ this.onSelectionChange.emit({ index: this.selectedListboxItemIndex, prevIndex, ctrlKey });
155
184
  }
156
185
  onF10Key(tools) {
157
186
  if (this.focusedToolIndex && this.focusedToolIndex > -1) {
@@ -253,29 +282,49 @@ export class KeyboardNavigationService {
253
282
  });
254
283
  }
255
284
  changeFocusedItem(dir, listboxItems) {
256
- listboxItems[this.focusedListboxItemIndex].nativeElement.blur();
285
+ const previousIndex = this.focusedListboxItemIndex;
286
+ const previousItem = listboxItems[previousIndex].nativeElement;
257
287
  if (this.focusedListboxItemIndex > 0 && dir === 'moveUp') {
258
288
  this.focusedListboxItemIndex -= 1;
259
289
  }
260
290
  else if (this.focusedListboxItemIndex < listboxItems.length - 1 && dir === 'moveDown') {
261
291
  this.focusedListboxItemIndex += 1;
262
292
  }
263
- listboxItems[this.focusedListboxItemIndex].nativeElement.focus();
293
+ const currentItem = listboxItems[this.focusedListboxItemIndex].nativeElement;
294
+ this.changeTabindex(previousItem, currentItem);
295
+ }
296
+ onShiftArrow(dir, listboxItems) {
297
+ const previousFocusIndex = this.focusedListboxItemIndex;
298
+ if (dir === 'moveUp' && this.focusedListboxItemIndex > 0) {
299
+ this.focusedListboxItemIndex -= 1;
300
+ }
301
+ else if (dir === 'moveDown' && this.focusedListboxItemIndex < listboxItems.length - 1) {
302
+ this.focusedListboxItemIndex += 1;
303
+ }
304
+ if (previousFocusIndex !== this.focusedListboxItemIndex) {
305
+ const previousItem = listboxItems[previousFocusIndex]?.nativeElement;
306
+ const currentItem = listboxItems[this.focusedListboxItemIndex]?.nativeElement;
307
+ this.changeTabindex(previousItem, currentItem);
308
+ this.onSelectionChange.emit({
309
+ index: this.focusedListboxItemIndex,
310
+ prevIndex: this.selectedListboxItemIndex,
311
+ shiftKey: true
312
+ });
313
+ this.selectedListboxItemIndex = this.focusedListboxItemIndex;
314
+ }
264
315
  }
265
316
  onArrowDown(listboxItems) {
266
- if (this.selectedListboxItemIndex < listboxItems.length - 1) {
267
- const offset = this.selectedListboxItemIndex ? this.selectedListboxItemIndex : this.focusedListboxItemIndex;
268
- this.selectedListboxItemIndex = offset + 1;
269
- const previousItem = listboxItems[this.selectedListboxItemIndex - 1]?.nativeElement;
317
+ if (this.focusedListboxItemIndex < listboxItems.length - 1) {
318
+ this.selectedListboxItemIndex = this.focusedListboxItemIndex + 1;
319
+ const previousItem = listboxItems[this.focusedListboxItemIndex]?.nativeElement;
270
320
  const currentItem = listboxItems[this.selectedListboxItemIndex]?.nativeElement;
271
321
  this.changeTabindex(previousItem, currentItem);
272
322
  }
273
323
  }
274
324
  onArrowUp(listboxItems) {
275
- if (this.selectedListboxItemIndex > 0 || this.focusedListboxItemIndex > 0) {
276
- const offset = this.selectedListboxItemIndex ? this.selectedListboxItemIndex : this.focusedListboxItemIndex;
277
- this.selectedListboxItemIndex = offset - 1;
278
- const previousItem = listboxItems[this.selectedListboxItemIndex + 1]?.nativeElement;
325
+ if (this.focusedListboxItemIndex > 0) {
326
+ this.selectedListboxItemIndex = this.focusedListboxItemIndex - 1;
327
+ const previousItem = listboxItems[this.focusedListboxItemIndex]?.nativeElement;
279
328
  const currentItem = listboxItems[this.selectedListboxItemIndex]?.nativeElement;
280
329
  this.changeTabindex(previousItem, currentItem);
281
330
  }
@@ -20,7 +20,7 @@ import { caretAltLeftIcon, caretAltRightIcon } from '@progress/kendo-svg-icons';
20
20
  import { ItemSelectableDirective } from './item-selectable.directive';
21
21
  import { NgIf, NgFor } from '@angular/common';
22
22
  import { LocalizedMessagesDirective } from './localization/localized-messages.directive';
23
- import { TemplateContextDirective } from '@progress/kendo-angular-common';
23
+ import { isPresent, TemplateContextDirective } from '@progress/kendo-angular-common';
24
24
  import * as i0 from "@angular/core";
25
25
  import * as i1 from "./keyboard-navigation.service";
26
26
  import * as i2 from "./selection.service";
@@ -62,7 +62,7 @@ export class ListBoxComponent {
62
62
  renderer;
63
63
  zone;
64
64
  localization;
65
- changeDetector;
65
+ cdr;
66
66
  /**
67
67
  * @hidden
68
68
  */
@@ -95,6 +95,18 @@ export class ListBoxComponent {
95
95
  * Specifies the field of the data item that provides the text content of the nodes.
96
96
  */
97
97
  textField;
98
+ /**
99
+ * Sets the selection mode of the ListBox.
100
+ *
101
+ * @default 'single'
102
+ */
103
+ set selectable(mode) {
104
+ this._selectable = mode;
105
+ this.selectionService.selectionMode = mode;
106
+ }
107
+ get selectable() {
108
+ return this._selectable;
109
+ }
98
110
  /**
99
111
  * Specifies the data that the ListBox displays.
100
112
  *
@@ -117,6 +129,8 @@ export class ListBoxComponent {
117
129
  /**
118
130
  * Configures the toolbar of the ListBox.
119
131
  * Specifies whether to display a toolbar and which tools and position to use.
132
+ *
133
+ * @default false
120
134
  */
121
135
  set toolbar(config) {
122
136
  let position = DEFAULT_TOOLBAR_POSITION;
@@ -155,7 +169,7 @@ export class ListBoxComponent {
155
169
  /**
156
170
  * Fires when you click a ListBox item.
157
171
  */
158
- actionClick = new EventEmitter();
172
+ action = new EventEmitter();
159
173
  /**
160
174
  * @hidden
161
175
  */
@@ -175,7 +189,7 @@ export class ListBoxComponent {
175
189
  /**
176
190
  * @hidden
177
191
  */
178
- selectedTools = allTools;
192
+ selectedTools = [];
179
193
  /**
180
194
  * @hidden
181
195
  */
@@ -203,15 +217,16 @@ export class ListBoxComponent {
203
217
  localizationSubscription;
204
218
  _size = DEFAULT_SIZE;
205
219
  subs = new Subscription();
206
- shouldFireFocusIn = true;
207
- constructor(keyboardNavigationService, selectionService, hostElement, renderer, zone, localization, changeDetector) {
220
+ shouldFireFocusIn = false;
221
+ _selectable = 'single';
222
+ constructor(keyboardNavigationService, selectionService, hostElement, renderer, zone, localization, cdr) {
208
223
  this.keyboardNavigationService = keyboardNavigationService;
209
224
  this.selectionService = selectionService;
210
225
  this.hostElement = hostElement;
211
226
  this.renderer = renderer;
212
227
  this.zone = zone;
213
228
  this.localization = localization;
214
- this.changeDetector = changeDetector;
229
+ this.cdr = cdr;
215
230
  validatePackage(packageMetadata);
216
231
  this.setToolbarClass(DEFAULT_TOOLBAR_POSITION);
217
232
  this.setSizingClass(this.size);
@@ -224,9 +239,6 @@ export class ListBoxComponent {
224
239
  // This allows us to know to which parent Listbox the child Listbox is connected to
225
240
  this.childListbox.parentListbox = this;
226
241
  }
227
- if (this.selectedIndex) {
228
- this.keyboardNavigationService.focusedToolIndex = this.selectedIndex;
229
- }
230
242
  this.localizationSubscription = this.localization.changes.subscribe(({ rtl }) => {
231
243
  this.direction = rtl ? 'rtl' : 'ltr';
232
244
  });
@@ -250,11 +262,12 @@ export class ListBoxComponent {
250
262
  const isListboxChild = this.parentListbox && !this.childListbox;
251
263
  const isListboxParentAndChild = !!(this.parentListbox && this.childListbox);
252
264
  const isListboxParent = !!(this.childListbox || (!this.childListbox && !this.parentListbox));
265
+ this.shouldFireFocusIn = false;
253
266
  if (isListboxChild || (isListboxParentAndChild && isActionTransferFrom)) {
254
- this.parentListbox.actionClick.next(actionName);
267
+ this.parentListbox.action.next(actionName);
255
268
  }
256
269
  else if (isListboxParent || (isListboxParentAndChild && !isActionTransferFrom)) {
257
- this.actionClick.next(actionName);
270
+ this.action.next(actionName);
258
271
  }
259
272
  const toolsRef = this.tools.toArray() || this.parentListbox.tools.toArray();
260
273
  const focusedToolIndex = toolsRef.findIndex(elem => elem.nativeElement === document.activeElement);
@@ -266,12 +279,27 @@ export class ListBoxComponent {
266
279
  const currentTool = toolsRef[navService.focusedToolIndex]?.element;
267
280
  navService.changeTabindex(prevTool, currentTool);
268
281
  }
282
+ this.cdr.markForCheck();
283
+ this.zone.runOutsideAngular(() => setTimeout(() => {
284
+ this.shouldFireFocusIn = true;
285
+ }));
286
+ }
287
+ /**
288
+ * Selects multiple ListBox nodes programmatically.
289
+ */
290
+ select(indices) {
291
+ const validIndices = indices.filter(index => index >= 0 && index < this.data.length);
292
+ this.selectionService.setSelectedIndices(validIndices);
269
293
  }
270
294
  /**
271
295
  * Selects a ListBox node programmatically.
296
+ *
297
+ * @hidden
272
298
  */
273
299
  selectItem(index) {
274
- this.selectionService.selectedIndex = index;
300
+ if (index >= 0 && index < this.data.length) {
301
+ this.select([index]);
302
+ }
275
303
  }
276
304
  /**
277
305
  * Clears the ListBox selection programmatically.
@@ -280,10 +308,10 @@ export class ListBoxComponent {
280
308
  this.selectionService.clearSelection();
281
309
  }
282
310
  /**
283
- * Gets the index of the currently selected item in the ListBox.
311
+ * Gets the indexes of the currently selected items in the ListBox.
284
312
  */
285
- get selectedIndex() {
286
- return this.selectionService.selectedIndex;
313
+ get selectedIndices() {
314
+ return this.selectionService.selectedIndices;
287
315
  }
288
316
  /**
289
317
  * @hidden
@@ -326,36 +354,84 @@ export class ListBoxComponent {
326
354
  this.caretAltLeftIcon :
327
355
  icon;
328
356
  }
329
- onClickEvent(prevIndex, index) {
330
- this.shouldFireFocusIn = false;
331
- this.selectionChange.next({ index, prevIndex: this.keyboardNavigationService.selectedListboxItemIndex });
332
- this.keyboardNavigationService.selectedListboxItemIndex = index;
333
- this.keyboardNavigationService.focusedListboxItemIndex = index;
334
- this.zone.onStable.pipe(take(1)).subscribe(() => {
335
- const listboxItems = this.listboxItems.toArray();
336
- const previousItem = prevIndex ? listboxItems[prevIndex].nativeElement : listboxItems[0].nativeElement;
337
- const currentItem = listboxItems[index].nativeElement;
338
- this.keyboardNavigationService.changeTabindex(previousItem, currentItem);
339
- });
340
- this.zone.onStable.pipe(take(1)).subscribe(() => {
341
- this.shouldFireFocusIn = true;
342
- });
343
- }
344
357
  initSubscriptions(navService, hostEl, toolsRef) {
345
358
  this.subs.add(navService.onShiftSelectedItem.subscribe((actionToPerform) => this.performAction(actionToPerform)));
346
359
  this.subs.add(navService.onTransferAllEvent.subscribe((actionToPerform) => this.performAction(actionToPerform)));
347
- this.subs.add(this.selectionService.onSelect.subscribe((e) => this.onClickEvent(e.prevIndex, e.index)));
360
+ this.subs.add(this.selectionService.onSelect.subscribe((event) => {
361
+ this.shouldFireFocusIn = false;
362
+ this.selectionChange.next(event);
363
+ const newFocusIndex = isPresent(this.selectionService.rangeSelectionTargetIndex)
364
+ ? this.selectionService.rangeSelectionTargetIndex
365
+ : this.selectionService.lastSelectedOrUnselectedIndex;
366
+ if (isPresent(newFocusIndex)) {
367
+ const listboxItems = this.listboxItems.toArray();
368
+ const previousItem = listboxItems[navService.focusedListboxItemIndex]?.nativeElement;
369
+ const currentItem = listboxItems[newFocusIndex]?.nativeElement;
370
+ if (previousItem && currentItem) {
371
+ navService.changeTabindex(previousItem, currentItem, false);
372
+ navService.focusedListboxItemIndex = newFocusIndex;
373
+ navService.selectedListboxItemIndex = newFocusIndex;
374
+ }
375
+ }
376
+ this.cdr.markForCheck();
377
+ this.zone.runOutsideAngular(() => setTimeout(() => {
378
+ this.shouldFireFocusIn = true;
379
+ }));
380
+ }));
348
381
  this.subs.add(navService.onDeleteEvent.subscribe((index) => this.onDeleteEvent(index, navService)));
349
382
  this.subs.add(navService.onMoveSelectedItem.subscribe((dir) => this.performAction(dir)));
383
+ this.subs.add(navService.onSelectAll.subscribe(() => {
384
+ if (this.selectable === 'multiple') {
385
+ const previousSelection = [...this.selectionService.selectedIndices];
386
+ const allSelected = this.selectionService.areAllSelected(this.data.length);
387
+ if (allSelected) {
388
+ this.selectionService.clearSelection();
389
+ this.selectionChange.next({
390
+ selectedIndices: null,
391
+ deselectedIndices: previousSelection.length > 0 ? previousSelection : null
392
+ });
393
+ }
394
+ else {
395
+ this.selectionService.selectAll(this.data.length);
396
+ const selectedIndices = this.selectionService.selectedIndices.filter(i => !previousSelection.includes(i));
397
+ this.selectionChange.next({
398
+ selectedIndices: selectedIndices.length > 0 ? selectedIndices : null,
399
+ deselectedIndices: null
400
+ });
401
+ }
402
+ this.cdr.markForCheck();
403
+ }
404
+ }));
405
+ this.subs.add(navService.onSelectToEnd.subscribe(({ direction }) => {
406
+ if (this.selectable === 'multiple') {
407
+ this.shouldFireFocusIn = false;
408
+ const previousSelection = [...this.selectionService.selectedIndices];
409
+ const targetIndex = direction === 'home' ? 0 : this.data.length - 1;
410
+ this.selectionService.selectRange(targetIndex);
411
+ const selectedIndices = this.selectionService.selectedIndices.filter(i => !previousSelection.includes(i));
412
+ const deselectedIndices = previousSelection.filter(i => !this.selectionService.selectedIndices.includes(i));
413
+ this.selectionChange.next({
414
+ selectedIndices: selectedIndices.length > 0 ? selectedIndices : null,
415
+ deselectedIndices: deselectedIndices.length > 0 ? deselectedIndices : null
416
+ });
417
+ const listboxItems = this.listboxItems.toArray();
418
+ const currentItem = listboxItems[navService.focusedListboxItemIndex]?.nativeElement;
419
+ const targetItem = listboxItems[targetIndex]?.nativeElement;
420
+ navService.changeTabindex(currentItem, targetItem);
421
+ navService.focusedListboxItemIndex = targetIndex;
422
+ this.cdr.markForCheck();
423
+ this.zone.runOutsideAngular(() => setTimeout(() => {
424
+ this.shouldFireFocusIn = true;
425
+ }));
426
+ }
427
+ }));
350
428
  if (this.listboxElement) {
351
429
  this.subs.add(this.renderer.listen(this.listboxElement.nativeElement, 'focusin', (event) => this.onFocusIn(event)));
352
430
  }
353
- this.subs.add(this.renderer.listen(hostEl, 'keydown', (event) => navService.onKeyDown(event, toolsRef, this.selectedTools, this.childListbox, this.parentListbox, this.listboxItems.toArray())));
354
- this.subs.add(navService.onSelectionChange.subscribe((indexes) => {
355
- const { prevIndex, index } = indexes;
356
- this.selectionService.selectedIndex = index;
357
- this.selectionChange.next({ index, prevIndex });
358
- this.changeDetector.markForCheck();
431
+ this.subs.add(this.renderer.listen(hostEl, 'keydown', (event) => navService.onKeyDown(event, toolsRef, this.selectedTools, this.childListbox, this.parentListbox, this.listboxItems.toArray(), this)));
432
+ this.subs.add(navService.onSelectionChange.subscribe((event) => {
433
+ const { index, ctrlKey, shiftKey } = event;
434
+ this.selectionService.select(index, ctrlKey, shiftKey);
359
435
  }));
360
436
  }
361
437
  onFocusIn(event) {
@@ -366,8 +442,15 @@ export class ListBoxComponent {
366
442
  if (index === -1) {
367
443
  return;
368
444
  }
369
- this.selectionService.selectedIndex = index;
370
- this.selectionChange.next({ index, prevIndex: null });
445
+ const previousSelection = [...this.selectionService.selectedIndices];
446
+ this.selectionService.addToSelectedIndices(index);
447
+ navService.focusedListboxItemIndex = index;
448
+ navService.selectedListboxItemIndex = index;
449
+ const deselected = previousSelection.filter(i => i !== index);
450
+ this.selectionChange.next({
451
+ selectedIndices: [index],
452
+ deselectedIndices: deselected.length > 0 ? deselected : null
453
+ });
371
454
  const previousItem = items[navService.selectedListboxItemIndex]?.nativeElement;
372
455
  const currentItem = items[index]?.nativeElement;
373
456
  this.renderer.setAttribute(previousItem, 'tabindex', '-1');
@@ -409,17 +492,20 @@ export class ListBoxComponent {
409
492
  }
410
493
  }
411
494
  onDeleteEvent(index, navService) {
412
- this.selectionService.selectedIndex = index;
495
+ this.selectionService.addToSelectedIndices(index);
413
496
  this.performAction('remove');
414
497
  const listboxItems = this.listboxItems.toArray();
415
498
  const setIndex = index + 1 === listboxItems.length ?
416
499
  { index: index - 1, tabindex: index - 1 } : { index, tabindex: index + 1 };
417
500
  navService.changeTabindex(null, listboxItems[setIndex['tabindex']]?.nativeElement);
418
- this.selectionChange.next({ index: setIndex['index'], prevIndex: null });
501
+ this.selectionChange.next({
502
+ selectedIndices: [setIndex['index']],
503
+ deselectedIndices: null
504
+ });
419
505
  navService.selectedListboxItemIndex = setIndex['index'];
420
506
  navService.focusedListboxItemIndex = setIndex['index'];
421
507
  navService.focusedListboxItem = setIndex['index'];
422
- this.selectionService.selectedIndex = setIndex['index'];
508
+ this.selectionService.selectedIndices = [setIndex['index']];
423
509
  }
424
510
  setToolbarClass(pos) {
425
511
  Object.keys(actionsClasses).forEach((className) => {
@@ -435,7 +521,7 @@ export class ListBoxComponent {
435
521
  this.renderer.addClass(this.hostElement.nativeElement, `k-listbox-${sizeClassMap[size]}`);
436
522
  }
437
523
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ListBoxComponent, deps: [{ token: i1.KeyboardNavigationService }, { token: i2.ListBoxSelectionService }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.NgZone }, { token: i3.LocalizationService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
438
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: ListBoxComponent, isStandalone: true, selector: "kendo-listbox", inputs: { textField: "textField", data: "data", size: "size", toolbar: "toolbar", listboxLabel: "listboxLabel", listboxToolbarLabel: "listboxToolbarLabel", itemDisabled: "itemDisabled" }, outputs: { selectionChange: "selectionChange", actionClick: "actionClick", getChildListbox: "getChildListbox" }, host: { properties: { "class.k-listbox": "this.listboxClassName", "attr.dir": "this.direction" } }, providers: [
524
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: ListBoxComponent, isStandalone: true, selector: "kendo-listbox", inputs: { textField: "textField", selectable: "selectable", data: "data", size: "size", toolbar: "toolbar", listboxLabel: "listboxLabel", listboxToolbarLabel: "listboxToolbarLabel", itemDisabled: "itemDisabled" }, outputs: { selectionChange: "selectionChange", action: "action", getChildListbox: "getChildListbox" }, host: { properties: { "class.k-listbox": "this.listboxClassName", "attr.dir": "this.direction" } }, providers: [
439
525
  ListBoxSelectionService,
440
526
  KeyboardNavigationService,
441
527
  LocalizationService,
@@ -502,16 +588,16 @@ export class ListBoxComponent {
502
588
  class="k-list-ul"
503
589
  role="listbox"
504
590
  [attr.aria-label]="listboxLabel"
505
- [attr.aria-multiselectable]="false"
591
+ [attr.aria-multiselectable]="selectable === 'multiple'"
506
592
  >
507
593
  <li
508
594
  #listboxItems
509
595
  *ngFor="let item of data; let i = index"
510
596
  kendoListBoxItemSelectable
511
597
  class="k-list-item"
512
- [attr.tabindex]="i === 0 ? '0' : '-1'"
598
+ [attr.tabindex]="i === keyboardNavigationService.focusedListboxItemIndex ? '0' : '-1'"
513
599
  role="option"
514
- [attr.aria-selected]="selectedIndex === i"
600
+ [attr.aria-selected]="selectedIndices.indexOf(i) >= 0"
515
601
  [index]="i"
516
602
  [class.k-disabled]="itemDisabled(item)"
517
603
  >
@@ -609,16 +695,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
609
695
  class="k-list-ul"
610
696
  role="listbox"
611
697
  [attr.aria-label]="listboxLabel"
612
- [attr.aria-multiselectable]="false"
698
+ [attr.aria-multiselectable]="selectable === 'multiple'"
613
699
  >
614
700
  <li
615
701
  #listboxItems
616
702
  *ngFor="let item of data; let i = index"
617
703
  kendoListBoxItemSelectable
618
704
  class="k-list-item"
619
- [attr.tabindex]="i === 0 ? '0' : '-1'"
705
+ [attr.tabindex]="i === keyboardNavigationService.focusedListboxItemIndex ? '0' : '-1'"
620
706
  role="option"
621
- [attr.aria-selected]="selectedIndex === i"
707
+ [attr.aria-selected]="selectedIndices.indexOf(i) >= 0"
622
708
  [index]="i"
623
709
  [class.k-disabled]="itemDisabled(item)"
624
710
  >
@@ -669,6 +755,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
669
755
  args: ['tools']
670
756
  }], textField: [{
671
757
  type: Input
758
+ }], selectable: [{
759
+ type: Input
672
760
  }], data: [{
673
761
  type: Input
674
762
  }], size: [{
@@ -683,7 +771,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
683
771
  type: Input
684
772
  }], selectionChange: [{
685
773
  type: Output
686
- }], actionClick: [{
774
+ }], action: [{
687
775
  type: Output
688
776
  }], getChildListbox: [{
689
777
  type: Output
@@ -10,7 +10,7 @@ export const packageMetadata = {
10
10
  productName: 'Kendo UI for Angular',
11
11
  productCode: 'KENDOUIANGULAR',
12
12
  productCodes: ['KENDOUIANGULAR'],
13
- publishDate: 1761910558,
14
- version: '21.0.0-develop.9',
13
+ publishDate: 1762953613,
14
+ version: '21.0.1-develop.1',
15
15
  licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/?utm_medium=product&utm_source=kendoangular&utm_campaign=kendo-ui-angular-purchase-license-keys-warning'
16
16
  };
@@ -0,0 +1,5 @@
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
+ export {};