@progress/kendo-angular-listbox 21.1.1-develop.2 → 21.2.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.
@@ -30,23 +30,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
30
30
  exports.default = default_1;
31
31
  const utils_1 = require("../utils");
32
32
  const fs = __importStar(require("fs"));
33
- const index_1 = require("../template-transformer/index");
34
33
  function default_1(fileInfo, api) {
35
34
  const filePath = fileInfo.path;
35
+ // Handle HTML files and inline templates
36
+ const htmlResult = (0, utils_1.htmlTransformer)(fileInfo, api, (templateContent) => (0, utils_1.eventUpdate)(templateContent, 'kendo-listbox', 'actionClick', 'action'));
36
37
  if (filePath.endsWith('.html')) {
37
- if ((0, utils_1.hasKendoInTemplate)(fileInfo.source)) {
38
- let updatedContent = fileInfo.source;
39
- updatedContent = (0, utils_1.htmlEventTransformer)({ ...fileInfo, source: updatedContent }, 'kendo-listbox', 'actionClick', 'action');
40
- // Only write to file once after all transformations
41
- fs.writeFileSync(filePath, updatedContent, 'utf-8');
38
+ if (htmlResult && htmlResult !== fileInfo.source) {
39
+ fs.writeFileSync(filePath, htmlResult, 'utf-8');
40
+ return htmlResult;
42
41
  }
43
- return;
42
+ return fileInfo.source; // Return original source if no changes
44
43
  }
44
+ // Handle TypeScript property transformations
45
45
  const j = api.jscodeshift;
46
- const rootSource = j(fileInfo.source);
47
- (0, index_1.templateTransformer)(rootSource, j, (root) => {
48
- (0, utils_1.templateEventTransformer)(root, 'kendo-listbox', 'actionClick', 'action');
49
- });
50
- (0, utils_1.tsPropertyTransformer)(fileInfo.source, rootSource, j, 'ListBoxComponent', 'actionClick', 'action');
46
+ const rootSource = j(htmlResult || fileInfo.source);
47
+ (0, utils_1.tsPropertyTransformer)(fileInfo.source, rootSource, j, '@progress/kendo-angular-listbox', 'ListBoxComponent', 'actionClick', 'action');
51
48
  return rootSource.toSource();
52
49
  }
@@ -233,12 +233,24 @@ export class DataBindingDirective {
233
233
  if (!target || !source || source.data?.length === 0) {
234
234
  return;
235
235
  }
236
- const itemsToTransfer = source.data.splice(0, source.data.length);
236
+ const itemsToTransfer = source.data.filter((item) => !source.itemDisabled(item));
237
+ if (itemsToTransfer.length === 0) {
238
+ return;
239
+ }
240
+ source.data = source.data.filter((item) => source.itemDisabled(item));
237
241
  target.data.push(...itemsToTransfer);
238
242
  source.clearSelection();
239
243
  const sourceNavService = source.keyboardNavigationService;
240
244
  const sourceSelService = source.selectionService;
241
- this.updateListBoxIndices(sourceNavService, sourceSelService, 0);
245
+ if (source.data.length === 0) {
246
+ this.updateListBoxIndices(sourceNavService, sourceSelService, 0);
247
+ }
248
+ else {
249
+ sourceNavService.focusedListboxItemIndex = 0;
250
+ sourceNavService.selectedListboxItemIndex = -1;
251
+ sourceSelService.rangeSelectionAnchorIndex = null;
252
+ sourceSelService.lastSelectedOrUnselectedIndex = null;
253
+ }
242
254
  const targetIndex = target.data.length - 1;
243
255
  target.select([targetIndex]);
244
256
  const targetNavService = target.keyboardNavigationService;
@@ -5,7 +5,7 @@
5
5
  /* eslint-disable @typescript-eslint/no-inferrable-types */
6
6
  /* eslint-disable @typescript-eslint/no-explicit-any */
7
7
  import { EventEmitter, Injectable, NgZone, Renderer2 } from "@angular/core";
8
- import { Keys, normalizeNumpadKeys } from "@progress/kendo-angular-common";
8
+ import { Keys, normalizeKeys } from "@progress/kendo-angular-common";
9
9
  import { take } from "rxjs/operators";
10
10
  import * as i0 from "@angular/core";
11
11
  /**
@@ -30,7 +30,7 @@ export class KeyboardNavigationService {
30
30
  }
31
31
  onKeyDown(event, toolsRef, toolbar, childListbox, parentListbox, listboxItems, currentListbox) {
32
32
  const target = event.target;
33
- const keyCode = normalizeNumpadKeys(event);
33
+ const keyCode = normalizeKeys(event);
34
34
  const ctrlOrMetaKey = event.ctrlKey || event.metaKey;
35
35
  const parentListboxToolbar = parentListbox?.selectedTools;
36
36
  const tool = toolsRef.find(elem => elem.element === target);
@@ -114,6 +114,9 @@ export class KeyboardNavigationService {
114
114
  if (this.selectedListboxItemIndex !== this.focusedListboxItemIndex) {
115
115
  const previousItem = listboxItems[this.selectedListboxItemIndex]?.nativeElement;
116
116
  const currentItem = listboxItems[this.focusedListboxItemIndex]?.nativeElement;
117
+ if (this.isItemDisabled(currentItem)) {
118
+ return;
119
+ }
117
120
  this.changeTabindex(previousItem, currentItem);
118
121
  }
119
122
  this.onSelectionChange.emit({
@@ -144,8 +147,10 @@ export class KeyboardNavigationService {
144
147
  return;
145
148
  }
146
149
  dir === 'moveUp' ? this.onArrowUp(listboxItems) : this.onArrowDown(listboxItems);
147
- this.onSelectionChange.emit({ index: this.selectedListboxItemIndex, prevIndex: this.focusedListboxItemIndex });
148
- this.focusedListboxItemIndex = this.selectedListboxItemIndex;
150
+ if (this.selectedListboxItemIndex !== this.focusedListboxItemIndex) {
151
+ this.onSelectionChange.emit({ index: this.selectedListboxItemIndex, prevIndex: this.focusedListboxItemIndex });
152
+ this.focusedListboxItemIndex = this.selectedListboxItemIndex;
153
+ }
149
154
  }
150
155
  onArrowLeftOrRight(keyCode, parentListbox, childListbox, event, listboxItems, currentListbox) {
151
156
  event.preventDefault();
@@ -175,6 +180,9 @@ export class KeyboardNavigationService {
175
180
  else {
176
181
  previousItem = listboxItems[this.selectedListboxItemIndex]?.nativeElement;
177
182
  currentItem = listboxItems[this.focusedListboxItemIndex]?.nativeElement;
183
+ if (this.isItemDisabled(currentItem)) {
184
+ return;
185
+ }
178
186
  prevIndex = this.selectedListboxItemIndex;
179
187
  this.selectedListboxItemIndex = this.focusedListboxItemIndex;
180
188
  }
@@ -303,7 +311,17 @@ export class KeyboardNavigationService {
303
311
  }
304
312
  if (previousFocusIndex !== this.focusedListboxItemIndex) {
305
313
  const previousItem = listboxItems[previousFocusIndex]?.nativeElement;
306
- const currentItem = listboxItems[this.focusedListboxItemIndex]?.nativeElement;
314
+ let currentItem = listboxItems[this.focusedListboxItemIndex]?.nativeElement;
315
+ if (this.isItemDisabled(currentItem)) {
316
+ const step = dir === 'moveDown' ? 1 : -1;
317
+ const nextEnabledIndex = this.findNextEnabledIndex(this.focusedListboxItemIndex, listboxItems, step);
318
+ if (nextEnabledIndex === -1) {
319
+ this.focusedListboxItemIndex = previousFocusIndex;
320
+ return;
321
+ }
322
+ this.focusedListboxItemIndex = nextEnabledIndex;
323
+ currentItem = listboxItems[this.focusedListboxItemIndex]?.nativeElement;
324
+ }
307
325
  this.changeTabindex(previousItem, currentItem);
308
326
  this.onSelectionChange.emit({
309
327
  index: this.focusedListboxItemIndex,
@@ -317,7 +335,13 @@ export class KeyboardNavigationService {
317
335
  if (this.focusedListboxItemIndex < listboxItems.length - 1) {
318
336
  this.selectedListboxItemIndex = this.focusedListboxItemIndex + 1;
319
337
  const previousItem = listboxItems[this.focusedListboxItemIndex]?.nativeElement;
320
- const currentItem = listboxItems[this.selectedListboxItemIndex]?.nativeElement;
338
+ let currentItem = listboxItems[this.selectedListboxItemIndex]?.nativeElement;
339
+ if (this.isItemDisabled(currentItem)) {
340
+ currentItem = this.calculateNextActiveItem(listboxItems, 1);
341
+ if (!currentItem) {
342
+ return;
343
+ }
344
+ }
321
345
  this.changeTabindex(previousItem, currentItem);
322
346
  }
323
347
  }
@@ -325,10 +349,38 @@ export class KeyboardNavigationService {
325
349
  if (this.focusedListboxItemIndex > 0) {
326
350
  this.selectedListboxItemIndex = this.focusedListboxItemIndex - 1;
327
351
  const previousItem = listboxItems[this.focusedListboxItemIndex]?.nativeElement;
328
- const currentItem = listboxItems[this.selectedListboxItemIndex]?.nativeElement;
352
+ let currentItem = listboxItems[this.selectedListboxItemIndex]?.nativeElement;
353
+ if (this.isItemDisabled(currentItem)) {
354
+ currentItem = this.calculateNextActiveItem(listboxItems, -1);
355
+ if (!currentItem) {
356
+ return;
357
+ }
358
+ }
329
359
  this.changeTabindex(previousItem, currentItem);
330
360
  }
331
361
  }
362
+ isItemDisabled(item) {
363
+ return item.getAttribute('aria-disabled') === 'true';
364
+ }
365
+ findNextEnabledIndex(startIndex, listboxItems, step) {
366
+ let index = startIndex;
367
+ while (index >= 0 && index < listboxItems.length) {
368
+ const item = listboxItems[index]?.nativeElement;
369
+ if (!this.isItemDisabled(item)) {
370
+ return index;
371
+ }
372
+ index += step;
373
+ }
374
+ return -1;
375
+ }
376
+ calculateNextActiveItem(listboxItems, step) {
377
+ this.selectedListboxItemIndex = this.findNextEnabledIndex(this.selectedListboxItemIndex, listboxItems, step);
378
+ if (this.selectedListboxItemIndex === -1) {
379
+ this.selectedListboxItemIndex = this.focusedListboxItemIndex;
380
+ return null;
381
+ }
382
+ return listboxItems[this.selectedListboxItemIndex]?.nativeElement;
383
+ }
332
384
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: KeyboardNavigationService, deps: [{ token: i0.Renderer2 }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
333
385
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: KeyboardNavigationService });
334
386
  }
@@ -18,7 +18,6 @@ import { take } from 'rxjs/operators';
18
18
  import { L10N_PREFIX, LocalizationService } from '@progress/kendo-angular-l10n';
19
19
  import { caretAltLeftIcon, caretAltRightIcon } from '@progress/kendo-svg-icons';
20
20
  import { ItemSelectableDirective } from './item-selectable.directive';
21
- import { NgIf, NgFor } from '@angular/common';
22
21
  import { LocalizedMessagesDirective } from './localization/localized-messages.directive';
23
22
  import { isPresent, TemplateContextDirective } from '@progress/kendo-angular-common';
24
23
  import * as i0 from "@angular/core";
@@ -231,6 +230,9 @@ export class ListBoxComponent {
231
230
  this.setToolbarClass(DEFAULT_TOOLBAR_POSITION);
232
231
  this.setSizingClass(this.size);
233
232
  this.direction = localization.rtl ? 'rtl' : 'ltr';
233
+ this.selectionService.isItemDisabled = (index) => {
234
+ return this.itemDisabled(this.data[index]);
235
+ };
234
236
  }
235
237
  ngOnInit() {
236
238
  // This event emitter gives us the connectedWith value from the DataBinding directive
@@ -521,7 +523,7 @@ export class ListBoxComponent {
521
523
  this.renderer.addClass(this.hostElement.nativeElement, `k-listbox-${sizeClassMap[size]}`);
522
524
  }
523
525
  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 });
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: [
526
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.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: [
525
527
  ListBoxSelectionService,
526
528
  KeyboardNavigationService,
527
529
  LocalizationService,
@@ -531,41 +533,41 @@ export class ListBoxComponent {
531
533
  },
532
534
  ], queries: [{ propertyName: "itemTemplate", first: true, predicate: ItemTemplateDirective, descendants: true }], viewQueries: [{ propertyName: "listboxElement", first: true, predicate: ["listbox"], descendants: true }, { propertyName: "toolbarElement", first: true, predicate: ["toolbar"], descendants: true }, { propertyName: "listboxItems", predicate: ["listboxItems"], descendants: true }, { propertyName: "tools", predicate: ["tools"], descendants: true }], ngImport: i0, template: `
533
535
  <ng-container kendoListBoxLocalizedMessages
534
- i18n-moveUp="kendo.listbox.moveUp|The title of the Move Up button"
535
- moveUp="Move Up"
536
-
537
- i18n-moveDown="kendo.listbox.moveDown|The title of the Move Down button"
538
- moveDown="Move Down"
539
-
540
- i18n-transferTo="kendo.listbox.transferTo|The title of the Transfer To button"
541
- transferTo="Transfer To"
542
-
543
- i18n-transferAllTo="kendo.listbox.transferAllTo|The title of the Transfer All To button"
544
- transferAllTo="Transfer All To"
545
-
546
- i18n-transferFrom="kendo.listbox.transferFrom|The title of the Transfer From button"
547
- transferFrom="Transfer From"
548
-
549
- i18n-transferAllFrom="kendo.listbox.transferAllFrom|The title of the Transfer All From button"
550
- transferAllFrom="Transfer All From"
551
-
552
- i18n-remove="kendo.listbox.remove|The title of the Remove button"
553
- remove="Remove"
554
-
555
- i18n-noDataText="kendo.listbox.noDataText|The text displayed when there are no items"
556
- noDataText="No data found."
557
- >
536
+ i18n-moveUp="kendo.listbox.moveUp|The title of the Move Up button"
537
+ moveUp="Move Up"
538
+
539
+ i18n-moveDown="kendo.listbox.moveDown|The title of the Move Down button"
540
+ moveDown="Move Down"
541
+
542
+ i18n-transferTo="kendo.listbox.transferTo|The title of the Transfer To button"
543
+ transferTo="Transfer To"
544
+
545
+ i18n-transferAllTo="kendo.listbox.transferAllTo|The title of the Transfer All To button"
546
+ transferAllTo="Transfer All To"
547
+
548
+ i18n-transferFrom="kendo.listbox.transferFrom|The title of the Transfer From button"
549
+ transferFrom="Transfer From"
550
+
551
+ i18n-transferAllFrom="kendo.listbox.transferAllFrom|The title of the Transfer All From button"
552
+ transferAllFrom="Transfer All From"
553
+
554
+ i18n-remove="kendo.listbox.remove|The title of the Remove button"
555
+ remove="Remove"
556
+
557
+ i18n-noDataText="kendo.listbox.noDataText|The text displayed when there are no items"
558
+ noDataText="No data found."
559
+ >
558
560
  </ng-container>
559
- <div
561
+ @if (selectedTools.length > 0) {
562
+ <div
560
563
  #toolbar
561
564
  class="k-listbox-actions"
562
- *ngIf="selectedTools.length > 0"
563
565
  role="toolbar"
564
566
  [attr.aria-label]="listboxToolbarLabel"
565
- >
566
- <button
567
+ >
568
+ @for (tool of selectedTools; track tool; let i = $index) {
569
+ <button
567
570
  #tools
568
- *ngFor="let tool of selectedTools; let i = index"
569
571
  kendoButton
570
572
  [attr.tabindex]="i === 0 ? '0' : '-1'"
571
573
  [size]="this.size"
@@ -575,53 +577,59 @@ export class ListBoxComponent {
575
577
  (click)="performAction(tool.name)"
576
578
  role="button"
577
579
  type="button"
578
- ></button>
579
- </div>
580
+ ></button>
581
+ }
582
+ </div>
583
+ }
580
584
  <div class="k-list-scroller k-selectable">
581
- <div class="{{ listClasses }}">
582
- <div
583
- *ngIf="data.length > 0"
584
- class="k-list-content"
585
+ <div class="{{ listClasses }}">
586
+ @if (data.length > 0) {
587
+ <div
588
+ class="k-list-content"
585
589
  >
586
- <ul
587
- #listbox
588
- class="k-list-ul"
589
- role="listbox"
590
- [attr.aria-label]="listboxLabel"
591
- [attr.aria-multiselectable]="selectable === 'multiple'"
592
- >
593
- <li
594
- #listboxItems
595
- *ngFor="let item of data; let i = index"
596
- kendoListBoxItemSelectable
597
- class="k-list-item"
598
- [attr.tabindex]="i === keyboardNavigationService.focusedListboxItemIndex ? '0' : '-1'"
599
- role="option"
600
- [attr.aria-selected]="selectedIndices.indexOf(i) >= 0"
601
- [index]="i"
602
- [class.k-disabled]="itemDisabled(item)"
603
- >
604
- <ng-template
605
- *ngIf="itemTemplate; else defaultItemTemplate"
590
+ <ul
591
+ #listbox
592
+ class="k-list-ul"
593
+ role="listbox"
594
+ [attr.aria-label]="listboxLabel"
595
+ [attr.aria-multiselectable]="selectable === 'multiple'"
596
+ >
597
+ @for (item of data; track item; let i = $index) {
598
+ <li
599
+ #listboxItems
600
+ kendoListBoxItemSelectable
601
+ class="k-list-item"
602
+ [attr.tabindex]="i === keyboardNavigationService.focusedListboxItemIndex ? '0' : '-1'"
603
+ role="option"
604
+ [attr.aria-selected]="selectedIndices.indexOf(i) >= 0"
605
+ [index]="i"
606
+ [class.k-disabled]="itemDisabled(item)"
607
+ [attr.aria-disabled]="itemDisabled(item)"
608
+ >
609
+ @if (itemTemplate) {
610
+ <ng-template
606
611
  [templateContext]="{
607
612
  templateRef: itemTemplate.templateRef,
608
613
  $implicit: item
609
614
  }"
610
- >
611
- </ng-template>
612
- <ng-template #defaultItemTemplate>
613
- <span class="k-list-item-text">{{ getText(item) }}</span>
614
- </ng-template>
615
- </li>
616
- </ul>
617
- </div>
618
- <span
619
- *ngIf="data.length === 0"
620
- class="k-nodata"
621
- >{{ messageFor('noDataText') }}</span>
622
- </div>
615
+ >
616
+ </ng-template>
617
+ } @else {
618
+ <span class="k-list-item-text">{{ getText(item) }}</span>
619
+ }
620
+ </li>
621
+ }
622
+ </ul>
623
+ </div>
624
+ }
625
+ @if (data.length === 0) {
626
+ <span
627
+ class="k-nodata"
628
+ >{{ messageFor('noDataText') }}</span>
629
+ }
630
+ </div>
623
631
  </div>
624
- `, isInline: true, dependencies: [{ kind: "directive", type: LocalizedMessagesDirective, selector: "[kendoListBoxLocalizedMessages]" }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon", "primary", "look"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "directive", type: ItemSelectableDirective, selector: "[kendoListBoxItemSelectable]", inputs: ["index"] }, { kind: "directive", type: TemplateContextDirective, selector: "[templateContext]", inputs: ["templateContext"] }] });
632
+ `, isInline: true, dependencies: [{ kind: "directive", type: LocalizedMessagesDirective, selector: "[kendoListBoxLocalizedMessages]" }, { kind: "component", type: ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon", "primary", "look"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "directive", type: ItemSelectableDirective, selector: "[kendoListBoxItemSelectable]", inputs: ["index"] }, { kind: "directive", type: TemplateContextDirective, selector: "[templateContext]", inputs: ["templateContext"] }] });
625
633
  }
626
634
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ListBoxComponent, decorators: [{
627
635
  type: Component,
@@ -638,41 +646,41 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
638
646
  ],
639
647
  template: `
640
648
  <ng-container kendoListBoxLocalizedMessages
641
- i18n-moveUp="kendo.listbox.moveUp|The title of the Move Up button"
642
- moveUp="Move Up"
643
-
644
- i18n-moveDown="kendo.listbox.moveDown|The title of the Move Down button"
645
- moveDown="Move Down"
646
-
647
- i18n-transferTo="kendo.listbox.transferTo|The title of the Transfer To button"
648
- transferTo="Transfer To"
649
-
650
- i18n-transferAllTo="kendo.listbox.transferAllTo|The title of the Transfer All To button"
651
- transferAllTo="Transfer All To"
652
-
653
- i18n-transferFrom="kendo.listbox.transferFrom|The title of the Transfer From button"
654
- transferFrom="Transfer From"
655
-
656
- i18n-transferAllFrom="kendo.listbox.transferAllFrom|The title of the Transfer All From button"
657
- transferAllFrom="Transfer All From"
658
-
659
- i18n-remove="kendo.listbox.remove|The title of the Remove button"
660
- remove="Remove"
661
-
662
- i18n-noDataText="kendo.listbox.noDataText|The text displayed when there are no items"
663
- noDataText="No data found."
664
- >
649
+ i18n-moveUp="kendo.listbox.moveUp|The title of the Move Up button"
650
+ moveUp="Move Up"
651
+
652
+ i18n-moveDown="kendo.listbox.moveDown|The title of the Move Down button"
653
+ moveDown="Move Down"
654
+
655
+ i18n-transferTo="kendo.listbox.transferTo|The title of the Transfer To button"
656
+ transferTo="Transfer To"
657
+
658
+ i18n-transferAllTo="kendo.listbox.transferAllTo|The title of the Transfer All To button"
659
+ transferAllTo="Transfer All To"
660
+
661
+ i18n-transferFrom="kendo.listbox.transferFrom|The title of the Transfer From button"
662
+ transferFrom="Transfer From"
663
+
664
+ i18n-transferAllFrom="kendo.listbox.transferAllFrom|The title of the Transfer All From button"
665
+ transferAllFrom="Transfer All From"
666
+
667
+ i18n-remove="kendo.listbox.remove|The title of the Remove button"
668
+ remove="Remove"
669
+
670
+ i18n-noDataText="kendo.listbox.noDataText|The text displayed when there are no items"
671
+ noDataText="No data found."
672
+ >
665
673
  </ng-container>
666
- <div
674
+ @if (selectedTools.length > 0) {
675
+ <div
667
676
  #toolbar
668
677
  class="k-listbox-actions"
669
- *ngIf="selectedTools.length > 0"
670
678
  role="toolbar"
671
679
  [attr.aria-label]="listboxToolbarLabel"
672
- >
673
- <button
680
+ >
681
+ @for (tool of selectedTools; track tool; let i = $index) {
682
+ <button
674
683
  #tools
675
- *ngFor="let tool of selectedTools; let i = index"
676
684
  kendoButton
677
685
  [attr.tabindex]="i === 0 ? '0' : '-1'"
678
686
  [size]="this.size"
@@ -682,55 +690,61 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
682
690
  (click)="performAction(tool.name)"
683
691
  role="button"
684
692
  type="button"
685
- ></button>
686
- </div>
693
+ ></button>
694
+ }
695
+ </div>
696
+ }
687
697
  <div class="k-list-scroller k-selectable">
688
- <div class="{{ listClasses }}">
689
- <div
690
- *ngIf="data.length > 0"
691
- class="k-list-content"
698
+ <div class="{{ listClasses }}">
699
+ @if (data.length > 0) {
700
+ <div
701
+ class="k-list-content"
692
702
  >
693
- <ul
694
- #listbox
695
- class="k-list-ul"
696
- role="listbox"
697
- [attr.aria-label]="listboxLabel"
698
- [attr.aria-multiselectable]="selectable === 'multiple'"
699
- >
700
- <li
701
- #listboxItems
702
- *ngFor="let item of data; let i = index"
703
- kendoListBoxItemSelectable
704
- class="k-list-item"
705
- [attr.tabindex]="i === keyboardNavigationService.focusedListboxItemIndex ? '0' : '-1'"
706
- role="option"
707
- [attr.aria-selected]="selectedIndices.indexOf(i) >= 0"
708
- [index]="i"
709
- [class.k-disabled]="itemDisabled(item)"
710
- >
711
- <ng-template
712
- *ngIf="itemTemplate; else defaultItemTemplate"
703
+ <ul
704
+ #listbox
705
+ class="k-list-ul"
706
+ role="listbox"
707
+ [attr.aria-label]="listboxLabel"
708
+ [attr.aria-multiselectable]="selectable === 'multiple'"
709
+ >
710
+ @for (item of data; track item; let i = $index) {
711
+ <li
712
+ #listboxItems
713
+ kendoListBoxItemSelectable
714
+ class="k-list-item"
715
+ [attr.tabindex]="i === keyboardNavigationService.focusedListboxItemIndex ? '0' : '-1'"
716
+ role="option"
717
+ [attr.aria-selected]="selectedIndices.indexOf(i) >= 0"
718
+ [index]="i"
719
+ [class.k-disabled]="itemDisabled(item)"
720
+ [attr.aria-disabled]="itemDisabled(item)"
721
+ >
722
+ @if (itemTemplate) {
723
+ <ng-template
713
724
  [templateContext]="{
714
725
  templateRef: itemTemplate.templateRef,
715
726
  $implicit: item
716
727
  }"
717
- >
718
- </ng-template>
719
- <ng-template #defaultItemTemplate>
720
- <span class="k-list-item-text">{{ getText(item) }}</span>
721
- </ng-template>
722
- </li>
723
- </ul>
724
- </div>
725
- <span
726
- *ngIf="data.length === 0"
727
- class="k-nodata"
728
- >{{ messageFor('noDataText') }}</span>
729
- </div>
728
+ >
729
+ </ng-template>
730
+ } @else {
731
+ <span class="k-list-item-text">{{ getText(item) }}</span>
732
+ }
733
+ </li>
734
+ }
735
+ </ul>
736
+ </div>
737
+ }
738
+ @if (data.length === 0) {
739
+ <span
740
+ class="k-nodata"
741
+ >{{ messageFor('noDataText') }}</span>
742
+ }
743
+ </div>
730
744
  </div>
731
- `,
745
+ `,
732
746
  standalone: true,
733
- imports: [LocalizedMessagesDirective, NgIf, NgFor, ButtonComponent, ItemSelectableDirective, TemplateContextDirective]
747
+ imports: [LocalizedMessagesDirective, ButtonComponent, ItemSelectableDirective, TemplateContextDirective]
734
748
  }]
735
749
  }], ctorParameters: () => [{ type: i1.KeyboardNavigationService }, { type: i2.ListBoxSelectionService }, { type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.NgZone }, { type: i3.LocalizationService }, { type: i0.ChangeDetectorRef }], propDecorators: { listboxClassName: [{
736
750
  type: HostBinding,
@@ -10,7 +10,7 @@ export const packageMetadata = {
10
10
  productName: 'Kendo UI for Angular',
11
11
  productCode: 'KENDOUIANGULAR',
12
12
  productCodes: ['KENDOUIANGULAR'],
13
- publishDate: 1763729377,
14
- version: '21.1.1-develop.2',
13
+ publishDate: 1764593179,
14
+ version: '21.2.0-develop.10',
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
  };
@@ -13,8 +13,12 @@ export class ListBoxSelectionService {
13
13
  lastSelectedOrUnselectedIndex = null;
14
14
  rangeSelectionTargetIndex = null;
15
15
  rangeSelectionAnchorIndex = null;
16
+ isItemDisabled = () => false;
16
17
  onSelect = new EventEmitter();
17
18
  select(index, ctrlKey = false, shiftKey = false) {
19
+ if (this.isItemDisabled(index)) {
20
+ return;
21
+ }
18
22
  const previousSelection = [...this.selectedIndices];
19
23
  let selectedIndices = [];
20
24
  let deselectedIndices = null;
@@ -68,7 +72,9 @@ export class ListBoxSelectionService {
68
72
  const endIndex = Math.max(anchorIndex, index);
69
73
  this.selectedIndices = [];
70
74
  for (let i = startIndex; i <= endIndex; i++) {
71
- this.selectedIndices.push(i);
75
+ if (!this.isItemDisabled(i)) {
76
+ this.selectedIndices.push(i);
77
+ }
72
78
  }
73
79
  this.rangeSelectionTargetIndex = index;
74
80
  selectedIndices = this.selectedIndices.filter(i => !previousSelection.includes(i));
@@ -111,13 +117,18 @@ export class ListBoxSelectionService {
111
117
  const endIndex = Math.max(anchorIndex, targetIndex);
112
118
  this.selectedIndices = [];
113
119
  for (let i = startIndex; i <= endIndex; i++) {
114
- this.selectedIndices.push(i);
120
+ if (!this.isItemDisabled(i)) {
121
+ this.selectedIndices.push(i);
122
+ }
115
123
  }
116
124
  }
117
125
  setSelectedIndices(indices) {
118
- this.selectedIndices = [...indices];
126
+ this.selectedIndices = indices.filter(i => !this.isItemDisabled(i));
119
127
  }
120
128
  addToSelectedIndices(index) {
129
+ if (this.isItemDisabled(index)) {
130
+ return;
131
+ }
121
132
  if (this.selectionMode === 'single') {
122
133
  this.selectedIndices = [index];
123
134
  }
@@ -127,11 +138,17 @@ export class ListBoxSelectionService {
127
138
  }
128
139
  selectAll(totalItems) {
129
140
  if (this.selectionMode === 'multiple') {
130
- this.selectedIndices = Array.from({ length: totalItems }, (_, i) => i);
141
+ this.selectedIndices = [];
142
+ for (let i = 0; i < totalItems; i++) {
143
+ if (!this.isItemDisabled(i)) {
144
+ this.selectedIndices.push(i);
145
+ }
146
+ }
131
147
  }
132
148
  }
133
149
  areAllSelected(totalItems) {
134
- return this.selectedIndices.length === totalItems && totalItems > 0;
150
+ const allSelectableItems = Array.from({ length: totalItems }, (_, i) => i).filter(i => !this.isItemDisabled(i));
151
+ return this.selectedIndices.length === allSelectableItems.length && allSelectableItems.length > 0;
135
152
  }
136
153
  isSelected(index) {
137
154
  return this.selectedIndices.indexOf(index) !== -1;