@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.
- package/codemods/template-transformer/index.js +93 -0
- package/codemods/utils.js +711 -0
- package/codemods/v21/listbox-actionclick.js +52 -0
- package/codemods/v21/listbox-selectedindex.js +125 -0
- package/codemods/v21/listbox-toolbar.js +14 -0
- package/data-binding.directive.d.ts +7 -5
- package/esm2022/data-binding.directive.mjs +128 -33
- package/esm2022/item-selectable.directive.mjs +6 -1
- package/esm2022/keyboard-navigation.service.mjs +73 -24
- package/esm2022/listbox.component.mjs +139 -51
- package/esm2022/package-metadata.mjs +2 -2
- package/esm2022/selection-mode.mjs +5 -0
- package/esm2022/selection.service.mjs +127 -6
- package/fesm2022/progress-kendo-angular-listbox.mjs +473 -116
- package/index.d.ts +0 -1
- package/keyboard-navigation.service.d.ts +17 -3
- package/listbox.component.d.ts +24 -8
- package/package.json +33 -7
- package/schematics/ngAdd/index.js +4 -4
- package/selection-mode.d.ts +12 -0
- package/selection.service.d.ts +18 -6
- package/toolbar.d.ts +1 -10
|
@@ -9,7 +9,7 @@ import { Subscription } from 'rxjs';
|
|
|
9
9
|
import { getter } from '@progress/kendo-common';
|
|
10
10
|
import { caretAltUpIcon, caretAltDownIcon, caretAltRightIcon, caretAltLeftIcon, caretDoubleAltRightIcon, caretDoubleAltLeftIcon, xIcon } from '@progress/kendo-svg-icons';
|
|
11
11
|
import { ButtonComponent } from '@progress/kendo-angular-buttons';
|
|
12
|
-
import { normalizeNumpadKeys, Keys, TemplateContextDirective, isChanged, ResizeBatchService } from '@progress/kendo-angular-common';
|
|
12
|
+
import { normalizeNumpadKeys, Keys, isPresent as isPresent$1, TemplateContextDirective, isChanged, ResizeBatchService } from '@progress/kendo-angular-common';
|
|
13
13
|
import { take } from 'rxjs/operators';
|
|
14
14
|
import * as i1 from '@progress/kendo-angular-l10n';
|
|
15
15
|
import { ComponentMessages, LocalizationService, L10N_PREFIX } from '@progress/kendo-angular-l10n';
|
|
@@ -25,8 +25,8 @@ const packageMetadata = {
|
|
|
25
25
|
productName: 'Kendo UI for Angular',
|
|
26
26
|
productCode: 'KENDOUIANGULAR',
|
|
27
27
|
productCodes: ['KENDOUIANGULAR'],
|
|
28
|
-
publishDate:
|
|
29
|
-
version: '21.0.
|
|
28
|
+
publishDate: 1762953613,
|
|
29
|
+
version: '21.0.1-develop.1',
|
|
30
30
|
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'
|
|
31
31
|
};
|
|
32
32
|
|
|
@@ -34,17 +34,138 @@ const packageMetadata = {
|
|
|
34
34
|
* @hidden
|
|
35
35
|
*/
|
|
36
36
|
class ListBoxSelectionService {
|
|
37
|
+
selectedIndices = [];
|
|
38
|
+
selectionMode = 'single';
|
|
39
|
+
lastSelectedOrUnselectedIndex = null;
|
|
40
|
+
rangeSelectionTargetIndex = null;
|
|
41
|
+
rangeSelectionAnchorIndex = null;
|
|
37
42
|
onSelect = new EventEmitter();
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
43
|
+
select(index, ctrlKey = false, shiftKey = false) {
|
|
44
|
+
const previousSelection = [...this.selectedIndices];
|
|
45
|
+
let selectedIndices = [];
|
|
46
|
+
let deselectedIndices = null;
|
|
47
|
+
const previousTargetIndex = this.rangeSelectionTargetIndex;
|
|
48
|
+
if (this.selectionMode === 'single') {
|
|
49
|
+
if (ctrlKey) {
|
|
50
|
+
const isSelected = this.isSelected(index);
|
|
51
|
+
if (isSelected) {
|
|
52
|
+
this.selectedIndices = [];
|
|
53
|
+
deselectedIndices = [index];
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
this.selectedIndices = [index];
|
|
57
|
+
selectedIndices = [index];
|
|
58
|
+
if (previousSelection.length > 0) {
|
|
59
|
+
deselectedIndices = previousSelection;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
this.lastSelectedOrUnselectedIndex = index;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
this.selectedIndices = [index];
|
|
66
|
+
selectedIndices = [index];
|
|
67
|
+
this.lastSelectedOrUnselectedIndex = index;
|
|
68
|
+
this.rangeSelectionAnchorIndex = index;
|
|
69
|
+
if (previousSelection.length > 0 && previousSelection[0] !== index) {
|
|
70
|
+
deselectedIndices = previousSelection;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else if (this.selectionMode === 'multiple') {
|
|
75
|
+
if (shiftKey) {
|
|
76
|
+
let anchorIndex = this.rangeSelectionAnchorIndex ?? this.lastSelectedOrUnselectedIndex ?? 0;
|
|
77
|
+
if (index === anchorIndex) {
|
|
78
|
+
this.selectedIndices = [anchorIndex];
|
|
79
|
+
this.rangeSelectionTargetIndex = index;
|
|
80
|
+
selectedIndices = this.selectedIndices.filter(i => !previousSelection.includes(i));
|
|
81
|
+
const nowDeselected = previousSelection.filter(i => !this.selectedIndices.includes(i));
|
|
82
|
+
deselectedIndices = nowDeselected.length > 0 ? nowDeselected : null;
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
if (previousTargetIndex !== null && previousTargetIndex !== anchorIndex) {
|
|
86
|
+
const previousDirection = previousTargetIndex > anchorIndex ? 'down' : 'up';
|
|
87
|
+
const currentDirection = index > anchorIndex ? 'down' : 'up';
|
|
88
|
+
if (previousDirection !== currentDirection) {
|
|
89
|
+
this.rangeSelectionAnchorIndex = previousTargetIndex;
|
|
90
|
+
anchorIndex = previousTargetIndex;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const startIndex = Math.min(anchorIndex, index);
|
|
94
|
+
const endIndex = Math.max(anchorIndex, index);
|
|
95
|
+
this.selectedIndices = [];
|
|
96
|
+
for (let i = startIndex; i <= endIndex; i++) {
|
|
97
|
+
this.selectedIndices.push(i);
|
|
98
|
+
}
|
|
99
|
+
this.rangeSelectionTargetIndex = index;
|
|
100
|
+
selectedIndices = this.selectedIndices.filter(i => !previousSelection.includes(i));
|
|
101
|
+
const nowDeselected = previousSelection.filter(i => !this.selectedIndices.includes(i));
|
|
102
|
+
deselectedIndices = nowDeselected.length > 0 ? nowDeselected : null;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
else if (ctrlKey) {
|
|
106
|
+
const indexInSelection = this.selectedIndices.indexOf(index);
|
|
107
|
+
if (indexInSelection === -1) {
|
|
108
|
+
this.selectedIndices.push(index);
|
|
109
|
+
selectedIndices = [index];
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
this.selectedIndices.splice(indexInSelection, 1);
|
|
113
|
+
deselectedIndices = [index];
|
|
114
|
+
}
|
|
115
|
+
this.lastSelectedOrUnselectedIndex = index;
|
|
116
|
+
this.rangeSelectionAnchorIndex = index;
|
|
117
|
+
this.rangeSelectionTargetIndex = index;
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
this.selectedIndices = [index];
|
|
121
|
+
selectedIndices = [index];
|
|
122
|
+
this.lastSelectedOrUnselectedIndex = index;
|
|
123
|
+
this.rangeSelectionAnchorIndex = index;
|
|
124
|
+
this.rangeSelectionTargetIndex = index;
|
|
125
|
+
const nowDeselected = previousSelection.filter(i => i !== index);
|
|
126
|
+
deselectedIndices = nowDeselected.length > 0 ? nowDeselected : null;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
this.onSelect.next({
|
|
130
|
+
selectedIndices: selectedIndices.length > 0 ? selectedIndices : null,
|
|
131
|
+
deselectedIndices
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
selectRange(targetIndex) {
|
|
135
|
+
const anchorIndex = this.lastSelectedOrUnselectedIndex ?? 0;
|
|
136
|
+
const startIndex = Math.min(anchorIndex, targetIndex);
|
|
137
|
+
const endIndex = Math.max(anchorIndex, targetIndex);
|
|
138
|
+
this.selectedIndices = [];
|
|
139
|
+
for (let i = startIndex; i <= endIndex; i++) {
|
|
140
|
+
this.selectedIndices.push(i);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
setSelectedIndices(indices) {
|
|
144
|
+
this.selectedIndices = [...indices];
|
|
145
|
+
}
|
|
146
|
+
addToSelectedIndices(index) {
|
|
147
|
+
if (this.selectionMode === 'single') {
|
|
148
|
+
this.selectedIndices = [index];
|
|
149
|
+
}
|
|
150
|
+
else if (this.selectedIndices.indexOf(index) === -1) {
|
|
151
|
+
this.selectedIndices = [...this.selectedIndices, index];
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
selectAll(totalItems) {
|
|
155
|
+
if (this.selectionMode === 'multiple') {
|
|
156
|
+
this.selectedIndices = Array.from({ length: totalItems }, (_, i) => i);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
areAllSelected(totalItems) {
|
|
160
|
+
return this.selectedIndices.length === totalItems && totalItems > 0;
|
|
42
161
|
}
|
|
43
162
|
isSelected(index) {
|
|
44
|
-
return index
|
|
163
|
+
return this.selectedIndices.indexOf(index) !== -1;
|
|
45
164
|
}
|
|
46
165
|
clearSelection() {
|
|
47
|
-
this.
|
|
166
|
+
this.selectedIndices = [];
|
|
167
|
+
this.lastSelectedOrUnselectedIndex = null;
|
|
168
|
+
this.rangeSelectionAnchorIndex = null;
|
|
48
169
|
}
|
|
49
170
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ListBoxSelectionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
50
171
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ListBoxSelectionService });
|
|
@@ -208,11 +329,13 @@ class KeyboardNavigationService {
|
|
|
208
329
|
onTransferAllEvent = new EventEmitter();
|
|
209
330
|
onShiftSelectedItem = new EventEmitter();
|
|
210
331
|
onSelectionChange = new EventEmitter();
|
|
332
|
+
onSelectAll = new EventEmitter();
|
|
333
|
+
onSelectToEnd = new EventEmitter();
|
|
211
334
|
constructor(renderer, zone) {
|
|
212
335
|
this.renderer = renderer;
|
|
213
336
|
this.zone = zone;
|
|
214
337
|
}
|
|
215
|
-
onKeyDown(event, toolsRef, toolbar, childListbox, parentListbox, listboxItems) {
|
|
338
|
+
onKeyDown(event, toolsRef, toolbar, childListbox, parentListbox, listboxItems, currentListbox) {
|
|
216
339
|
const target = event.target;
|
|
217
340
|
const keyCode = normalizeNumpadKeys(event);
|
|
218
341
|
const ctrlOrMetaKey = event.ctrlKey || event.metaKey;
|
|
@@ -234,6 +357,17 @@ class KeyboardNavigationService {
|
|
|
234
357
|
this.onDeleteEvent.emit(this.selectedListboxItemIndex);
|
|
235
358
|
}
|
|
236
359
|
}
|
|
360
|
+
if (ctrlOrMetaKey && (event.key === 'a' || event.key === 'A')) {
|
|
361
|
+
event.preventDefault();
|
|
362
|
+
this.onSelectAll.emit();
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
if (ctrlOrMetaKey && event.shiftKey && (keyCode === Keys.Home || keyCode === Keys.End)) {
|
|
366
|
+
event.preventDefault();
|
|
367
|
+
const direction = keyCode === Keys.Home ? 'home' : 'end';
|
|
368
|
+
this.onSelectToEnd.emit({ direction });
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
237
371
|
const isTargetListboxItem = listboxItems.find(elem => elem.nativeElement === target);
|
|
238
372
|
if (isTargetListboxItem) {
|
|
239
373
|
let isTransferToolVisible;
|
|
@@ -241,7 +375,7 @@ class KeyboardNavigationService {
|
|
|
241
375
|
isTransferToolVisible = activeToolbar.some(tool => tool.name.startsWith('transfer'));
|
|
242
376
|
}
|
|
243
377
|
if ((keyCode === Keys.ArrowRight || keyCode === Keys.ArrowLeft) && ctrlOrMetaKey && isTransferToolVisible) {
|
|
244
|
-
this.onArrowLeftOrRight(keyCode, parentListbox, childListbox, event, listboxItems);
|
|
378
|
+
this.onArrowLeftOrRight(keyCode, parentListbox, childListbox, event, listboxItems, currentListbox);
|
|
245
379
|
}
|
|
246
380
|
else if ((keyCode === Keys.ArrowUp || keyCode === Keys.ArrowDown)) {
|
|
247
381
|
this.onArrowUpOrDown(keyCode, ctrlOrMetaKey, event, activeToolbar, listboxItems);
|
|
@@ -250,9 +384,7 @@ class KeyboardNavigationService {
|
|
|
250
384
|
this.onSelectChange(event, listboxItems);
|
|
251
385
|
}
|
|
252
386
|
else if (keyCode === Keys.Space) {
|
|
253
|
-
|
|
254
|
-
this.onSpaceKey(event, listboxItems);
|
|
255
|
-
}
|
|
387
|
+
this.onSpaceKey(event, listboxItems);
|
|
256
388
|
}
|
|
257
389
|
}
|
|
258
390
|
}
|
|
@@ -276,17 +408,27 @@ class KeyboardNavigationService {
|
|
|
276
408
|
}
|
|
277
409
|
const offset = dir === 'up' ? -1 : 1;
|
|
278
410
|
this.focusedToolIndex += offset;
|
|
279
|
-
const prevItem = toolsRef[this.focusedToolIndex + (offset * -1)]
|
|
280
|
-
const currentItem = toolsRef[this.focusedToolIndex]
|
|
411
|
+
const prevItem = toolsRef[this.focusedToolIndex + (offset * -1)]?.element;
|
|
412
|
+
const currentItem = toolsRef[this.focusedToolIndex]?.element;
|
|
281
413
|
this.changeTabindex(prevItem, currentItem);
|
|
282
414
|
}
|
|
283
415
|
onSpaceKey(event, listboxItems) {
|
|
284
416
|
event.stopImmediatePropagation();
|
|
285
417
|
event.preventDefault();
|
|
286
|
-
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
this.
|
|
418
|
+
event.stopPropagation();
|
|
419
|
+
const ctrlKey = event.ctrlKey || event.metaKey;
|
|
420
|
+
const shiftKey = event.shiftKey;
|
|
421
|
+
if (this.selectedListboxItemIndex !== this.focusedListboxItemIndex) {
|
|
422
|
+
const previousItem = listboxItems[this.selectedListboxItemIndex]?.nativeElement;
|
|
423
|
+
const currentItem = listboxItems[this.focusedListboxItemIndex]?.nativeElement;
|
|
424
|
+
this.changeTabindex(previousItem, currentItem);
|
|
425
|
+
}
|
|
426
|
+
this.onSelectionChange.emit({
|
|
427
|
+
index: this.focusedListboxItemIndex,
|
|
428
|
+
prevIndex: this.selectedListboxItemIndex,
|
|
429
|
+
ctrlKey,
|
|
430
|
+
shiftKey
|
|
431
|
+
});
|
|
290
432
|
this.selectedListboxItemIndex = this.focusedListboxItemIndex;
|
|
291
433
|
}
|
|
292
434
|
onArrowUpOrDown(keyCode, ctrlOrMetaKey, event, activeToolbar, listboxItems) {
|
|
@@ -304,17 +446,24 @@ class KeyboardNavigationService {
|
|
|
304
446
|
this.changeFocusedItem(dir, listboxItems);
|
|
305
447
|
return;
|
|
306
448
|
}
|
|
449
|
+
if (event.shiftKey) {
|
|
450
|
+
this.onShiftArrow(dir, listboxItems);
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
307
453
|
dir === 'moveUp' ? this.onArrowUp(listboxItems) : this.onArrowDown(listboxItems);
|
|
308
454
|
this.onSelectionChange.emit({ index: this.selectedListboxItemIndex, prevIndex: this.focusedListboxItemIndex });
|
|
309
455
|
this.focusedListboxItemIndex = this.selectedListboxItemIndex;
|
|
310
456
|
}
|
|
311
|
-
onArrowLeftOrRight(keyCode, parentListbox, childListbox, event, listboxItems) {
|
|
457
|
+
onArrowLeftOrRight(keyCode, parentListbox, childListbox, event, listboxItems, currentListbox) {
|
|
312
458
|
event.preventDefault();
|
|
313
459
|
if (event.shiftKey) {
|
|
314
460
|
this.transferAllItems(keyCode, childListbox, parentListbox);
|
|
315
461
|
return;
|
|
316
462
|
}
|
|
317
|
-
|
|
463
|
+
const isArrowRight = keyCode === Keys.ArrowRight;
|
|
464
|
+
const sourceListbox = isArrowRight ? currentListbox : childListbox || parentListbox?.childListbox;
|
|
465
|
+
const hasSelection = sourceListbox?.selectedIndices && sourceListbox.selectedIndices.length > 0;
|
|
466
|
+
if (hasSelection) {
|
|
318
467
|
this.transferItem(keyCode, childListbox, parentListbox, listboxItems);
|
|
319
468
|
}
|
|
320
469
|
}
|
|
@@ -337,7 +486,8 @@ class KeyboardNavigationService {
|
|
|
337
486
|
this.selectedListboxItemIndex = this.focusedListboxItemIndex;
|
|
338
487
|
}
|
|
339
488
|
this.changeTabindex(previousItem, currentItem, !!currentItem);
|
|
340
|
-
|
|
489
|
+
const ctrlKey = event.ctrlKey || event.metaKey;
|
|
490
|
+
this.onSelectionChange.emit({ index: this.selectedListboxItemIndex, prevIndex, ctrlKey });
|
|
341
491
|
}
|
|
342
492
|
onF10Key(tools) {
|
|
343
493
|
if (this.focusedToolIndex && this.focusedToolIndex > -1) {
|
|
@@ -439,29 +589,49 @@ class KeyboardNavigationService {
|
|
|
439
589
|
});
|
|
440
590
|
}
|
|
441
591
|
changeFocusedItem(dir, listboxItems) {
|
|
442
|
-
|
|
592
|
+
const previousIndex = this.focusedListboxItemIndex;
|
|
593
|
+
const previousItem = listboxItems[previousIndex].nativeElement;
|
|
443
594
|
if (this.focusedListboxItemIndex > 0 && dir === 'moveUp') {
|
|
444
595
|
this.focusedListboxItemIndex -= 1;
|
|
445
596
|
}
|
|
446
597
|
else if (this.focusedListboxItemIndex < listboxItems.length - 1 && dir === 'moveDown') {
|
|
447
598
|
this.focusedListboxItemIndex += 1;
|
|
448
599
|
}
|
|
449
|
-
listboxItems[this.focusedListboxItemIndex].nativeElement
|
|
600
|
+
const currentItem = listboxItems[this.focusedListboxItemIndex].nativeElement;
|
|
601
|
+
this.changeTabindex(previousItem, currentItem);
|
|
602
|
+
}
|
|
603
|
+
onShiftArrow(dir, listboxItems) {
|
|
604
|
+
const previousFocusIndex = this.focusedListboxItemIndex;
|
|
605
|
+
if (dir === 'moveUp' && this.focusedListboxItemIndex > 0) {
|
|
606
|
+
this.focusedListboxItemIndex -= 1;
|
|
607
|
+
}
|
|
608
|
+
else if (dir === 'moveDown' && this.focusedListboxItemIndex < listboxItems.length - 1) {
|
|
609
|
+
this.focusedListboxItemIndex += 1;
|
|
610
|
+
}
|
|
611
|
+
if (previousFocusIndex !== this.focusedListboxItemIndex) {
|
|
612
|
+
const previousItem = listboxItems[previousFocusIndex]?.nativeElement;
|
|
613
|
+
const currentItem = listboxItems[this.focusedListboxItemIndex]?.nativeElement;
|
|
614
|
+
this.changeTabindex(previousItem, currentItem);
|
|
615
|
+
this.onSelectionChange.emit({
|
|
616
|
+
index: this.focusedListboxItemIndex,
|
|
617
|
+
prevIndex: this.selectedListboxItemIndex,
|
|
618
|
+
shiftKey: true
|
|
619
|
+
});
|
|
620
|
+
this.selectedListboxItemIndex = this.focusedListboxItemIndex;
|
|
621
|
+
}
|
|
450
622
|
}
|
|
451
623
|
onArrowDown(listboxItems) {
|
|
452
|
-
if (this.
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
const previousItem = listboxItems[this.selectedListboxItemIndex - 1]?.nativeElement;
|
|
624
|
+
if (this.focusedListboxItemIndex < listboxItems.length - 1) {
|
|
625
|
+
this.selectedListboxItemIndex = this.focusedListboxItemIndex + 1;
|
|
626
|
+
const previousItem = listboxItems[this.focusedListboxItemIndex]?.nativeElement;
|
|
456
627
|
const currentItem = listboxItems[this.selectedListboxItemIndex]?.nativeElement;
|
|
457
628
|
this.changeTabindex(previousItem, currentItem);
|
|
458
629
|
}
|
|
459
630
|
}
|
|
460
631
|
onArrowUp(listboxItems) {
|
|
461
|
-
if (this.
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
const previousItem = listboxItems[this.selectedListboxItemIndex + 1]?.nativeElement;
|
|
632
|
+
if (this.focusedListboxItemIndex > 0) {
|
|
633
|
+
this.selectedListboxItemIndex = this.focusedListboxItemIndex - 1;
|
|
634
|
+
const previousItem = listboxItems[this.focusedListboxItemIndex]?.nativeElement;
|
|
465
635
|
const currentItem = listboxItems[this.selectedListboxItemIndex]?.nativeElement;
|
|
466
636
|
this.changeTabindex(previousItem, currentItem);
|
|
467
637
|
}
|
|
@@ -487,7 +657,12 @@ class ItemSelectableDirective {
|
|
|
487
657
|
}
|
|
488
658
|
onClick(event) {
|
|
489
659
|
event.stopPropagation();
|
|
490
|
-
|
|
660
|
+
const ctrlKey = event.ctrlKey || event.metaKey;
|
|
661
|
+
const shiftKey = event.shiftKey;
|
|
662
|
+
if (shiftKey) {
|
|
663
|
+
event.preventDefault();
|
|
664
|
+
}
|
|
665
|
+
this.selectionService.select(this.index, ctrlKey, shiftKey);
|
|
491
666
|
}
|
|
492
667
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ItemSelectableDirective, deps: [{ token: ListBoxSelectionService }], target: i0.ɵɵFactoryTarget.Directive });
|
|
493
668
|
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.14", type: ItemSelectableDirective, isStandalone: true, selector: "[kendoListBoxItemSelectable]", inputs: { index: "index" }, host: { listeners: { "mousedown": "onClick($event)" }, properties: { "class.k-selected": "this.selectedClassName" } }, ngImport: i0 });
|
|
@@ -637,7 +812,7 @@ class ListBoxComponent {
|
|
|
637
812
|
renderer;
|
|
638
813
|
zone;
|
|
639
814
|
localization;
|
|
640
|
-
|
|
815
|
+
cdr;
|
|
641
816
|
/**
|
|
642
817
|
* @hidden
|
|
643
818
|
*/
|
|
@@ -670,6 +845,18 @@ class ListBoxComponent {
|
|
|
670
845
|
* Specifies the field of the data item that provides the text content of the nodes.
|
|
671
846
|
*/
|
|
672
847
|
textField;
|
|
848
|
+
/**
|
|
849
|
+
* Sets the selection mode of the ListBox.
|
|
850
|
+
*
|
|
851
|
+
* @default 'single'
|
|
852
|
+
*/
|
|
853
|
+
set selectable(mode) {
|
|
854
|
+
this._selectable = mode;
|
|
855
|
+
this.selectionService.selectionMode = mode;
|
|
856
|
+
}
|
|
857
|
+
get selectable() {
|
|
858
|
+
return this._selectable;
|
|
859
|
+
}
|
|
673
860
|
/**
|
|
674
861
|
* Specifies the data that the ListBox displays.
|
|
675
862
|
*
|
|
@@ -692,6 +879,8 @@ class ListBoxComponent {
|
|
|
692
879
|
/**
|
|
693
880
|
* Configures the toolbar of the ListBox.
|
|
694
881
|
* Specifies whether to display a toolbar and which tools and position to use.
|
|
882
|
+
*
|
|
883
|
+
* @default false
|
|
695
884
|
*/
|
|
696
885
|
set toolbar(config) {
|
|
697
886
|
let position = DEFAULT_TOOLBAR_POSITION;
|
|
@@ -730,7 +919,7 @@ class ListBoxComponent {
|
|
|
730
919
|
/**
|
|
731
920
|
* Fires when you click a ListBox item.
|
|
732
921
|
*/
|
|
733
|
-
|
|
922
|
+
action = new EventEmitter();
|
|
734
923
|
/**
|
|
735
924
|
* @hidden
|
|
736
925
|
*/
|
|
@@ -750,7 +939,7 @@ class ListBoxComponent {
|
|
|
750
939
|
/**
|
|
751
940
|
* @hidden
|
|
752
941
|
*/
|
|
753
|
-
selectedTools =
|
|
942
|
+
selectedTools = [];
|
|
754
943
|
/**
|
|
755
944
|
* @hidden
|
|
756
945
|
*/
|
|
@@ -778,15 +967,16 @@ class ListBoxComponent {
|
|
|
778
967
|
localizationSubscription;
|
|
779
968
|
_size = DEFAULT_SIZE;
|
|
780
969
|
subs = new Subscription();
|
|
781
|
-
shouldFireFocusIn =
|
|
782
|
-
|
|
970
|
+
shouldFireFocusIn = false;
|
|
971
|
+
_selectable = 'single';
|
|
972
|
+
constructor(keyboardNavigationService, selectionService, hostElement, renderer, zone, localization, cdr) {
|
|
783
973
|
this.keyboardNavigationService = keyboardNavigationService;
|
|
784
974
|
this.selectionService = selectionService;
|
|
785
975
|
this.hostElement = hostElement;
|
|
786
976
|
this.renderer = renderer;
|
|
787
977
|
this.zone = zone;
|
|
788
978
|
this.localization = localization;
|
|
789
|
-
this.
|
|
979
|
+
this.cdr = cdr;
|
|
790
980
|
validatePackage(packageMetadata);
|
|
791
981
|
this.setToolbarClass(DEFAULT_TOOLBAR_POSITION);
|
|
792
982
|
this.setSizingClass(this.size);
|
|
@@ -799,9 +989,6 @@ class ListBoxComponent {
|
|
|
799
989
|
// This allows us to know to which parent Listbox the child Listbox is connected to
|
|
800
990
|
this.childListbox.parentListbox = this;
|
|
801
991
|
}
|
|
802
|
-
if (this.selectedIndex) {
|
|
803
|
-
this.keyboardNavigationService.focusedToolIndex = this.selectedIndex;
|
|
804
|
-
}
|
|
805
992
|
this.localizationSubscription = this.localization.changes.subscribe(({ rtl }) => {
|
|
806
993
|
this.direction = rtl ? 'rtl' : 'ltr';
|
|
807
994
|
});
|
|
@@ -825,11 +1012,12 @@ class ListBoxComponent {
|
|
|
825
1012
|
const isListboxChild = this.parentListbox && !this.childListbox;
|
|
826
1013
|
const isListboxParentAndChild = !!(this.parentListbox && this.childListbox);
|
|
827
1014
|
const isListboxParent = !!(this.childListbox || (!this.childListbox && !this.parentListbox));
|
|
1015
|
+
this.shouldFireFocusIn = false;
|
|
828
1016
|
if (isListboxChild || (isListboxParentAndChild && isActionTransferFrom)) {
|
|
829
|
-
this.parentListbox.
|
|
1017
|
+
this.parentListbox.action.next(actionName);
|
|
830
1018
|
}
|
|
831
1019
|
else if (isListboxParent || (isListboxParentAndChild && !isActionTransferFrom)) {
|
|
832
|
-
this.
|
|
1020
|
+
this.action.next(actionName);
|
|
833
1021
|
}
|
|
834
1022
|
const toolsRef = this.tools.toArray() || this.parentListbox.tools.toArray();
|
|
835
1023
|
const focusedToolIndex = toolsRef.findIndex(elem => elem.nativeElement === document.activeElement);
|
|
@@ -841,12 +1029,27 @@ class ListBoxComponent {
|
|
|
841
1029
|
const currentTool = toolsRef[navService.focusedToolIndex]?.element;
|
|
842
1030
|
navService.changeTabindex(prevTool, currentTool);
|
|
843
1031
|
}
|
|
1032
|
+
this.cdr.markForCheck();
|
|
1033
|
+
this.zone.runOutsideAngular(() => setTimeout(() => {
|
|
1034
|
+
this.shouldFireFocusIn = true;
|
|
1035
|
+
}));
|
|
1036
|
+
}
|
|
1037
|
+
/**
|
|
1038
|
+
* Selects multiple ListBox nodes programmatically.
|
|
1039
|
+
*/
|
|
1040
|
+
select(indices) {
|
|
1041
|
+
const validIndices = indices.filter(index => index >= 0 && index < this.data.length);
|
|
1042
|
+
this.selectionService.setSelectedIndices(validIndices);
|
|
844
1043
|
}
|
|
845
1044
|
/**
|
|
846
1045
|
* Selects a ListBox node programmatically.
|
|
1046
|
+
*
|
|
1047
|
+
* @hidden
|
|
847
1048
|
*/
|
|
848
1049
|
selectItem(index) {
|
|
849
|
-
this.
|
|
1050
|
+
if (index >= 0 && index < this.data.length) {
|
|
1051
|
+
this.select([index]);
|
|
1052
|
+
}
|
|
850
1053
|
}
|
|
851
1054
|
/**
|
|
852
1055
|
* Clears the ListBox selection programmatically.
|
|
@@ -855,10 +1058,10 @@ class ListBoxComponent {
|
|
|
855
1058
|
this.selectionService.clearSelection();
|
|
856
1059
|
}
|
|
857
1060
|
/**
|
|
858
|
-
* Gets the
|
|
1061
|
+
* Gets the indexes of the currently selected items in the ListBox.
|
|
859
1062
|
*/
|
|
860
|
-
get
|
|
861
|
-
return this.selectionService.
|
|
1063
|
+
get selectedIndices() {
|
|
1064
|
+
return this.selectionService.selectedIndices;
|
|
862
1065
|
}
|
|
863
1066
|
/**
|
|
864
1067
|
* @hidden
|
|
@@ -901,36 +1104,84 @@ class ListBoxComponent {
|
|
|
901
1104
|
this.caretAltLeftIcon :
|
|
902
1105
|
icon;
|
|
903
1106
|
}
|
|
904
|
-
onClickEvent(prevIndex, index) {
|
|
905
|
-
this.shouldFireFocusIn = false;
|
|
906
|
-
this.selectionChange.next({ index, prevIndex: this.keyboardNavigationService.selectedListboxItemIndex });
|
|
907
|
-
this.keyboardNavigationService.selectedListboxItemIndex = index;
|
|
908
|
-
this.keyboardNavigationService.focusedListboxItemIndex = index;
|
|
909
|
-
this.zone.onStable.pipe(take(1)).subscribe(() => {
|
|
910
|
-
const listboxItems = this.listboxItems.toArray();
|
|
911
|
-
const previousItem = prevIndex ? listboxItems[prevIndex].nativeElement : listboxItems[0].nativeElement;
|
|
912
|
-
const currentItem = listboxItems[index].nativeElement;
|
|
913
|
-
this.keyboardNavigationService.changeTabindex(previousItem, currentItem);
|
|
914
|
-
});
|
|
915
|
-
this.zone.onStable.pipe(take(1)).subscribe(() => {
|
|
916
|
-
this.shouldFireFocusIn = true;
|
|
917
|
-
});
|
|
918
|
-
}
|
|
919
1107
|
initSubscriptions(navService, hostEl, toolsRef) {
|
|
920
1108
|
this.subs.add(navService.onShiftSelectedItem.subscribe((actionToPerform) => this.performAction(actionToPerform)));
|
|
921
1109
|
this.subs.add(navService.onTransferAllEvent.subscribe((actionToPerform) => this.performAction(actionToPerform)));
|
|
922
|
-
this.subs.add(this.selectionService.onSelect.subscribe((
|
|
1110
|
+
this.subs.add(this.selectionService.onSelect.subscribe((event) => {
|
|
1111
|
+
this.shouldFireFocusIn = false;
|
|
1112
|
+
this.selectionChange.next(event);
|
|
1113
|
+
const newFocusIndex = isPresent$1(this.selectionService.rangeSelectionTargetIndex)
|
|
1114
|
+
? this.selectionService.rangeSelectionTargetIndex
|
|
1115
|
+
: this.selectionService.lastSelectedOrUnselectedIndex;
|
|
1116
|
+
if (isPresent$1(newFocusIndex)) {
|
|
1117
|
+
const listboxItems = this.listboxItems.toArray();
|
|
1118
|
+
const previousItem = listboxItems[navService.focusedListboxItemIndex]?.nativeElement;
|
|
1119
|
+
const currentItem = listboxItems[newFocusIndex]?.nativeElement;
|
|
1120
|
+
if (previousItem && currentItem) {
|
|
1121
|
+
navService.changeTabindex(previousItem, currentItem, false);
|
|
1122
|
+
navService.focusedListboxItemIndex = newFocusIndex;
|
|
1123
|
+
navService.selectedListboxItemIndex = newFocusIndex;
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
this.cdr.markForCheck();
|
|
1127
|
+
this.zone.runOutsideAngular(() => setTimeout(() => {
|
|
1128
|
+
this.shouldFireFocusIn = true;
|
|
1129
|
+
}));
|
|
1130
|
+
}));
|
|
923
1131
|
this.subs.add(navService.onDeleteEvent.subscribe((index) => this.onDeleteEvent(index, navService)));
|
|
924
1132
|
this.subs.add(navService.onMoveSelectedItem.subscribe((dir) => this.performAction(dir)));
|
|
1133
|
+
this.subs.add(navService.onSelectAll.subscribe(() => {
|
|
1134
|
+
if (this.selectable === 'multiple') {
|
|
1135
|
+
const previousSelection = [...this.selectionService.selectedIndices];
|
|
1136
|
+
const allSelected = this.selectionService.areAllSelected(this.data.length);
|
|
1137
|
+
if (allSelected) {
|
|
1138
|
+
this.selectionService.clearSelection();
|
|
1139
|
+
this.selectionChange.next({
|
|
1140
|
+
selectedIndices: null,
|
|
1141
|
+
deselectedIndices: previousSelection.length > 0 ? previousSelection : null
|
|
1142
|
+
});
|
|
1143
|
+
}
|
|
1144
|
+
else {
|
|
1145
|
+
this.selectionService.selectAll(this.data.length);
|
|
1146
|
+
const selectedIndices = this.selectionService.selectedIndices.filter(i => !previousSelection.includes(i));
|
|
1147
|
+
this.selectionChange.next({
|
|
1148
|
+
selectedIndices: selectedIndices.length > 0 ? selectedIndices : null,
|
|
1149
|
+
deselectedIndices: null
|
|
1150
|
+
});
|
|
1151
|
+
}
|
|
1152
|
+
this.cdr.markForCheck();
|
|
1153
|
+
}
|
|
1154
|
+
}));
|
|
1155
|
+
this.subs.add(navService.onSelectToEnd.subscribe(({ direction }) => {
|
|
1156
|
+
if (this.selectable === 'multiple') {
|
|
1157
|
+
this.shouldFireFocusIn = false;
|
|
1158
|
+
const previousSelection = [...this.selectionService.selectedIndices];
|
|
1159
|
+
const targetIndex = direction === 'home' ? 0 : this.data.length - 1;
|
|
1160
|
+
this.selectionService.selectRange(targetIndex);
|
|
1161
|
+
const selectedIndices = this.selectionService.selectedIndices.filter(i => !previousSelection.includes(i));
|
|
1162
|
+
const deselectedIndices = previousSelection.filter(i => !this.selectionService.selectedIndices.includes(i));
|
|
1163
|
+
this.selectionChange.next({
|
|
1164
|
+
selectedIndices: selectedIndices.length > 0 ? selectedIndices : null,
|
|
1165
|
+
deselectedIndices: deselectedIndices.length > 0 ? deselectedIndices : null
|
|
1166
|
+
});
|
|
1167
|
+
const listboxItems = this.listboxItems.toArray();
|
|
1168
|
+
const currentItem = listboxItems[navService.focusedListboxItemIndex]?.nativeElement;
|
|
1169
|
+
const targetItem = listboxItems[targetIndex]?.nativeElement;
|
|
1170
|
+
navService.changeTabindex(currentItem, targetItem);
|
|
1171
|
+
navService.focusedListboxItemIndex = targetIndex;
|
|
1172
|
+
this.cdr.markForCheck();
|
|
1173
|
+
this.zone.runOutsideAngular(() => setTimeout(() => {
|
|
1174
|
+
this.shouldFireFocusIn = true;
|
|
1175
|
+
}));
|
|
1176
|
+
}
|
|
1177
|
+
}));
|
|
925
1178
|
if (this.listboxElement) {
|
|
926
1179
|
this.subs.add(this.renderer.listen(this.listboxElement.nativeElement, 'focusin', (event) => this.onFocusIn(event)));
|
|
927
1180
|
}
|
|
928
|
-
this.subs.add(this.renderer.listen(hostEl, 'keydown', (event) => navService.onKeyDown(event, toolsRef, this.selectedTools, this.childListbox, this.parentListbox, this.listboxItems.toArray())));
|
|
929
|
-
this.subs.add(navService.onSelectionChange.subscribe((
|
|
930
|
-
const {
|
|
931
|
-
this.selectionService.
|
|
932
|
-
this.selectionChange.next({ index, prevIndex });
|
|
933
|
-
this.changeDetector.markForCheck();
|
|
1181
|
+
this.subs.add(this.renderer.listen(hostEl, 'keydown', (event) => navService.onKeyDown(event, toolsRef, this.selectedTools, this.childListbox, this.parentListbox, this.listboxItems.toArray(), this)));
|
|
1182
|
+
this.subs.add(navService.onSelectionChange.subscribe((event) => {
|
|
1183
|
+
const { index, ctrlKey, shiftKey } = event;
|
|
1184
|
+
this.selectionService.select(index, ctrlKey, shiftKey);
|
|
934
1185
|
}));
|
|
935
1186
|
}
|
|
936
1187
|
onFocusIn(event) {
|
|
@@ -941,8 +1192,15 @@ class ListBoxComponent {
|
|
|
941
1192
|
if (index === -1) {
|
|
942
1193
|
return;
|
|
943
1194
|
}
|
|
944
|
-
this.selectionService.
|
|
945
|
-
this.
|
|
1195
|
+
const previousSelection = [...this.selectionService.selectedIndices];
|
|
1196
|
+
this.selectionService.addToSelectedIndices(index);
|
|
1197
|
+
navService.focusedListboxItemIndex = index;
|
|
1198
|
+
navService.selectedListboxItemIndex = index;
|
|
1199
|
+
const deselected = previousSelection.filter(i => i !== index);
|
|
1200
|
+
this.selectionChange.next({
|
|
1201
|
+
selectedIndices: [index],
|
|
1202
|
+
deselectedIndices: deselected.length > 0 ? deselected : null
|
|
1203
|
+
});
|
|
946
1204
|
const previousItem = items[navService.selectedListboxItemIndex]?.nativeElement;
|
|
947
1205
|
const currentItem = items[index]?.nativeElement;
|
|
948
1206
|
this.renderer.setAttribute(previousItem, 'tabindex', '-1');
|
|
@@ -984,17 +1242,20 @@ class ListBoxComponent {
|
|
|
984
1242
|
}
|
|
985
1243
|
}
|
|
986
1244
|
onDeleteEvent(index, navService) {
|
|
987
|
-
this.selectionService.
|
|
1245
|
+
this.selectionService.addToSelectedIndices(index);
|
|
988
1246
|
this.performAction('remove');
|
|
989
1247
|
const listboxItems = this.listboxItems.toArray();
|
|
990
1248
|
const setIndex = index + 1 === listboxItems.length ?
|
|
991
1249
|
{ index: index - 1, tabindex: index - 1 } : { index, tabindex: index + 1 };
|
|
992
1250
|
navService.changeTabindex(null, listboxItems[setIndex['tabindex']]?.nativeElement);
|
|
993
|
-
this.selectionChange.next({
|
|
1251
|
+
this.selectionChange.next({
|
|
1252
|
+
selectedIndices: [setIndex['index']],
|
|
1253
|
+
deselectedIndices: null
|
|
1254
|
+
});
|
|
994
1255
|
navService.selectedListboxItemIndex = setIndex['index'];
|
|
995
1256
|
navService.focusedListboxItemIndex = setIndex['index'];
|
|
996
1257
|
navService.focusedListboxItem = setIndex['index'];
|
|
997
|
-
this.selectionService.
|
|
1258
|
+
this.selectionService.selectedIndices = [setIndex['index']];
|
|
998
1259
|
}
|
|
999
1260
|
setToolbarClass(pos) {
|
|
1000
1261
|
Object.keys(actionsClasses).forEach((className) => {
|
|
@@ -1010,7 +1271,7 @@ class ListBoxComponent {
|
|
|
1010
1271
|
this.renderer.addClass(this.hostElement.nativeElement, `k-listbox-${sizeClassMap[size]}`);
|
|
1011
1272
|
}
|
|
1012
1273
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ListBoxComponent, deps: [{ token: KeyboardNavigationService }, { token: ListBoxSelectionService }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.NgZone }, { token: i1.LocalizationService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
1013
|
-
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",
|
|
1274
|
+
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: [
|
|
1014
1275
|
ListBoxSelectionService,
|
|
1015
1276
|
KeyboardNavigationService,
|
|
1016
1277
|
LocalizationService,
|
|
@@ -1077,16 +1338,16 @@ class ListBoxComponent {
|
|
|
1077
1338
|
class="k-list-ul"
|
|
1078
1339
|
role="listbox"
|
|
1079
1340
|
[attr.aria-label]="listboxLabel"
|
|
1080
|
-
[attr.aria-multiselectable]="
|
|
1341
|
+
[attr.aria-multiselectable]="selectable === 'multiple'"
|
|
1081
1342
|
>
|
|
1082
1343
|
<li
|
|
1083
1344
|
#listboxItems
|
|
1084
1345
|
*ngFor="let item of data; let i = index"
|
|
1085
1346
|
kendoListBoxItemSelectable
|
|
1086
1347
|
class="k-list-item"
|
|
1087
|
-
[attr.tabindex]="i ===
|
|
1348
|
+
[attr.tabindex]="i === keyboardNavigationService.focusedListboxItemIndex ? '0' : '-1'"
|
|
1088
1349
|
role="option"
|
|
1089
|
-
[attr.aria-selected]="
|
|
1350
|
+
[attr.aria-selected]="selectedIndices.indexOf(i) >= 0"
|
|
1090
1351
|
[index]="i"
|
|
1091
1352
|
[class.k-disabled]="itemDisabled(item)"
|
|
1092
1353
|
>
|
|
@@ -1184,16 +1445,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
1184
1445
|
class="k-list-ul"
|
|
1185
1446
|
role="listbox"
|
|
1186
1447
|
[attr.aria-label]="listboxLabel"
|
|
1187
|
-
[attr.aria-multiselectable]="
|
|
1448
|
+
[attr.aria-multiselectable]="selectable === 'multiple'"
|
|
1188
1449
|
>
|
|
1189
1450
|
<li
|
|
1190
1451
|
#listboxItems
|
|
1191
1452
|
*ngFor="let item of data; let i = index"
|
|
1192
1453
|
kendoListBoxItemSelectable
|
|
1193
1454
|
class="k-list-item"
|
|
1194
|
-
[attr.tabindex]="i ===
|
|
1455
|
+
[attr.tabindex]="i === keyboardNavigationService.focusedListboxItemIndex ? '0' : '-1'"
|
|
1195
1456
|
role="option"
|
|
1196
|
-
[attr.aria-selected]="
|
|
1457
|
+
[attr.aria-selected]="selectedIndices.indexOf(i) >= 0"
|
|
1197
1458
|
[index]="i"
|
|
1198
1459
|
[class.k-disabled]="itemDisabled(item)"
|
|
1199
1460
|
>
|
|
@@ -1244,6 +1505,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
1244
1505
|
args: ['tools']
|
|
1245
1506
|
}], textField: [{
|
|
1246
1507
|
type: Input
|
|
1508
|
+
}], selectable: [{
|
|
1509
|
+
type: Input
|
|
1247
1510
|
}], data: [{
|
|
1248
1511
|
type: Input
|
|
1249
1512
|
}], size: [{
|
|
@@ -1258,7 +1521,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
1258
1521
|
type: Input
|
|
1259
1522
|
}], selectionChange: [{
|
|
1260
1523
|
type: Output
|
|
1261
|
-
}],
|
|
1524
|
+
}], action: [{
|
|
1262
1525
|
type: Output
|
|
1263
1526
|
}], getChildListbox: [{
|
|
1264
1527
|
type: Output
|
|
@@ -1288,22 +1551,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
1288
1551
|
*/
|
|
1289
1552
|
class DataBindingDirective {
|
|
1290
1553
|
listbox;
|
|
1554
|
+
zone;
|
|
1291
1555
|
/**
|
|
1292
1556
|
* Specifies the `ListBoxComponent` instance with which the current ListBox connects.
|
|
1293
1557
|
* When you link two listboxes through this input, you can transfer items between them.
|
|
1294
1558
|
*/
|
|
1295
1559
|
connectedWith;
|
|
1296
|
-
|
|
1560
|
+
actionSub = new Subscription();
|
|
1297
1561
|
selectedBoxSub = new Subscription();
|
|
1298
1562
|
connectedWithSub = new Subscription();
|
|
1299
1563
|
selectedBox;
|
|
1300
|
-
constructor(listbox) {
|
|
1564
|
+
constructor(listbox, zone) {
|
|
1301
1565
|
this.listbox = listbox;
|
|
1566
|
+
this.zone = zone;
|
|
1302
1567
|
this.selectedBox = this.listbox;
|
|
1303
1568
|
this.connectedWithSub.add(this.listbox.getChildListbox.subscribe(() => {
|
|
1304
1569
|
this.listbox.childListbox = this.connectedWith;
|
|
1305
1570
|
}));
|
|
1306
|
-
this.
|
|
1571
|
+
this.actionSub.add(this.listbox.action.subscribe((actionName) => {
|
|
1307
1572
|
switch (actionName) {
|
|
1308
1573
|
case 'moveUp': {
|
|
1309
1574
|
this.moveVertically('up');
|
|
@@ -1314,11 +1579,11 @@ class DataBindingDirective {
|
|
|
1314
1579
|
break;
|
|
1315
1580
|
}
|
|
1316
1581
|
case 'transferFrom': {
|
|
1317
|
-
this.
|
|
1582
|
+
this.transferSelectedItems(this.connectedWith, this.listbox);
|
|
1318
1583
|
break;
|
|
1319
1584
|
}
|
|
1320
1585
|
case 'transferTo': {
|
|
1321
|
-
this.
|
|
1586
|
+
this.transferSelectedItems(this.listbox, this.connectedWith);
|
|
1322
1587
|
break;
|
|
1323
1588
|
}
|
|
1324
1589
|
case 'transferAllTo': {
|
|
@@ -1330,7 +1595,7 @@ class DataBindingDirective {
|
|
|
1330
1595
|
break;
|
|
1331
1596
|
}
|
|
1332
1597
|
case 'remove': {
|
|
1333
|
-
this.
|
|
1598
|
+
this.removeSelectedItems();
|
|
1334
1599
|
break;
|
|
1335
1600
|
}
|
|
1336
1601
|
default: {
|
|
@@ -1350,11 +1615,37 @@ class DataBindingDirective {
|
|
|
1350
1615
|
}
|
|
1351
1616
|
this.selectedBoxSub.add(this.listbox.selectionChange.subscribe(() => {
|
|
1352
1617
|
this.selectedBox = this.listbox;
|
|
1618
|
+
const connectedNavService = this.connectedWith.keyboardNavigationService;
|
|
1619
|
+
const connectedSelService = this.connectedWith.selectionService;
|
|
1620
|
+
let lastSelectedIndex = 0;
|
|
1621
|
+
if (connectedSelService.selectedIndices.length > 0) {
|
|
1622
|
+
lastSelectedIndex = connectedSelService.rangeSelectionTargetIndex ?? connectedSelService.lastSelectedOrUnselectedIndex ?? 0;
|
|
1623
|
+
}
|
|
1353
1624
|
this.connectedWith.clearSelection();
|
|
1625
|
+
if (this.connectedWith.data?.length > 0) {
|
|
1626
|
+
const validIndex = Math.min(lastSelectedIndex, this.connectedWith.data.length - 1);
|
|
1627
|
+
this.updateListBoxIndices(connectedNavService, connectedSelService, validIndex, false);
|
|
1628
|
+
}
|
|
1629
|
+
else {
|
|
1630
|
+
this.updateListBoxIndices(connectedNavService, connectedSelService, 0, false);
|
|
1631
|
+
}
|
|
1354
1632
|
}));
|
|
1355
1633
|
this.selectedBoxSub.add(this.connectedWith.selectionChange.subscribe(() => {
|
|
1356
1634
|
this.selectedBox = this.connectedWith;
|
|
1635
|
+
const listboxNavService = this.listbox.keyboardNavigationService;
|
|
1636
|
+
const listboxSelService = this.listbox.selectionService;
|
|
1637
|
+
let lastSelectedIndex = 0;
|
|
1638
|
+
if (listboxSelService.selectedIndices.length > 0) {
|
|
1639
|
+
lastSelectedIndex = listboxSelService.rangeSelectionTargetIndex ?? listboxSelService.lastSelectedOrUnselectedIndex ?? 0;
|
|
1640
|
+
}
|
|
1357
1641
|
this.listbox.clearSelection();
|
|
1642
|
+
if (this.listbox.data?.length > 0) {
|
|
1643
|
+
const validIndex = Math.min(lastSelectedIndex, this.listbox.data.length - 1);
|
|
1644
|
+
this.updateListBoxIndices(listboxNavService, listboxSelService, validIndex, false);
|
|
1645
|
+
}
|
|
1646
|
+
else {
|
|
1647
|
+
this.updateListBoxIndices(listboxNavService, listboxSelService, 0, false);
|
|
1648
|
+
}
|
|
1358
1649
|
}));
|
|
1359
1650
|
}
|
|
1360
1651
|
}
|
|
@@ -1362,9 +1653,9 @@ class DataBindingDirective {
|
|
|
1362
1653
|
* @hidden
|
|
1363
1654
|
*/
|
|
1364
1655
|
ngOnDestroy() {
|
|
1365
|
-
if (this.
|
|
1366
|
-
this.
|
|
1367
|
-
this.
|
|
1656
|
+
if (this.actionSub) {
|
|
1657
|
+
this.actionSub.unsubscribe();
|
|
1658
|
+
this.actionSub = null;
|
|
1368
1659
|
}
|
|
1369
1660
|
if (this.selectedBoxSub) {
|
|
1370
1661
|
this.selectedBoxSub.unsubscribe();
|
|
@@ -1372,49 +1663,115 @@ class DataBindingDirective {
|
|
|
1372
1663
|
}
|
|
1373
1664
|
}
|
|
1374
1665
|
moveVertically(dir) {
|
|
1375
|
-
const
|
|
1376
|
-
if (!isPresent(
|
|
1666
|
+
const selectedIndices = this.selectedBox.selectedIndices;
|
|
1667
|
+
if (!isPresent(selectedIndices) || selectedIndices.length === 0) {
|
|
1377
1668
|
return;
|
|
1378
1669
|
}
|
|
1379
|
-
const
|
|
1380
|
-
const
|
|
1670
|
+
const sortedIndices = [...selectedIndices].sort((a, b) => a - b);
|
|
1671
|
+
const topIndex = sortedIndices[0];
|
|
1672
|
+
const bottomIndex = sortedIndices[sortedIndices.length - 1];
|
|
1673
|
+
const topReached = dir === 'up' && topIndex <= 0;
|
|
1674
|
+
const bottomReached = dir === 'down' && bottomIndex >= this.selectedBox.data.length - 1;
|
|
1381
1675
|
if (topReached || bottomReached) {
|
|
1382
1676
|
return;
|
|
1383
1677
|
}
|
|
1384
|
-
const
|
|
1678
|
+
const data = this.selectedBox.data;
|
|
1679
|
+
const newSelectedIndices = [];
|
|
1680
|
+
if (dir === 'up') {
|
|
1681
|
+
for (const index of sortedIndices) {
|
|
1682
|
+
const newIndex = index - 1;
|
|
1683
|
+
[data[newIndex], data[index]] = [data[index], data[newIndex]];
|
|
1684
|
+
newSelectedIndices.push(newIndex);
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1687
|
+
else {
|
|
1688
|
+
for (let i = sortedIndices.length - 1; i >= 0; i--) {
|
|
1689
|
+
const index = sortedIndices[i];
|
|
1690
|
+
const newIndex = index + 1;
|
|
1691
|
+
[data[newIndex], data[index]] = [data[index], data[newIndex]];
|
|
1692
|
+
newSelectedIndices.push(newIndex);
|
|
1693
|
+
}
|
|
1694
|
+
}
|
|
1695
|
+
newSelectedIndices.sort((a, b) => a - b);
|
|
1696
|
+
this.selectedBox.selectionService.setSelectedIndices(newSelectedIndices);
|
|
1385
1697
|
const navigation = this.selectedBox.keyboardNavigationService;
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1698
|
+
const currentFocusedIndex = navigation.focusedListboxItemIndex;
|
|
1699
|
+
const focusedItemIndexInSelection = sortedIndices.indexOf(currentFocusedIndex);
|
|
1700
|
+
let newFocusIndex;
|
|
1701
|
+
if (focusedItemIndexInSelection !== -1) {
|
|
1702
|
+
newFocusIndex = newSelectedIndices[focusedItemIndexInSelection];
|
|
1703
|
+
}
|
|
1704
|
+
else {
|
|
1705
|
+
newFocusIndex = dir === 'up' ? topIndex - 1 : bottomIndex + 1;
|
|
1706
|
+
}
|
|
1707
|
+
this.zone.onStable.pipe(take(1)).subscribe(() => {
|
|
1708
|
+
const listboxItems = this.selectedBox.listboxItems.toArray();
|
|
1709
|
+
const previousItem = listboxItems[currentFocusedIndex]?.nativeElement;
|
|
1710
|
+
const currentItem = listboxItems[newFocusIndex]?.nativeElement;
|
|
1711
|
+
navigation.changeTabindex(previousItem, currentItem);
|
|
1712
|
+
navigation.focusedListboxItemIndex = newFocusIndex;
|
|
1713
|
+
navigation.selectedListboxItemIndex = newFocusIndex;
|
|
1714
|
+
});
|
|
1389
1715
|
}
|
|
1390
|
-
|
|
1391
|
-
const
|
|
1392
|
-
if (!isPresent(
|
|
1716
|
+
removeSelectedItems() {
|
|
1717
|
+
const itemIndices = this.selectedBox.selectedIndices;
|
|
1718
|
+
if (!isPresent(itemIndices) || itemIndices.length === 0) {
|
|
1393
1719
|
return;
|
|
1394
1720
|
}
|
|
1395
|
-
this.selectedBox.data.
|
|
1721
|
+
this.selectedBox.data = this.selectedBox.data.filter((_, index) => !itemIndices.includes(index));
|
|
1396
1722
|
this.selectedBox.selectionService.clearSelection();
|
|
1397
1723
|
}
|
|
1398
|
-
|
|
1399
|
-
const
|
|
1400
|
-
if (!
|
|
1724
|
+
transferSelectedItems(source, target) {
|
|
1725
|
+
const selectedIndices = source?.data && source?.selectedIndices;
|
|
1726
|
+
if (!target || !source || !isPresent(selectedIndices) || selectedIndices.length === 0) {
|
|
1401
1727
|
return;
|
|
1402
1728
|
}
|
|
1403
|
-
|
|
1404
|
-
|
|
1729
|
+
const sourceLastIndex = source.selectionService.rangeSelectionTargetIndex ??
|
|
1730
|
+
source.selectionService.lastSelectedOrUnselectedIndex ??
|
|
1731
|
+
0;
|
|
1732
|
+
target.data.push(...selectedIndices.map(index => source.data[index]));
|
|
1733
|
+
source.data = source.data.filter((_, index) => !selectedIndices.includes(index));
|
|
1405
1734
|
source.clearSelection();
|
|
1406
|
-
|
|
1735
|
+
const removedBeforeAnchor = selectedIndices.filter(i => i < sourceLastIndex).length;
|
|
1736
|
+
const adjustedAnchorIndex = Math.max(0, Math.min(sourceLastIndex - removedBeforeAnchor, source.data.length - 1));
|
|
1737
|
+
const sourceNavService = source.keyboardNavigationService;
|
|
1738
|
+
const sourceSelService = source.selectionService;
|
|
1739
|
+
if (source.data.length > 0) {
|
|
1740
|
+
this.updateListBoxIndices(sourceNavService, sourceSelService, adjustedAnchorIndex);
|
|
1741
|
+
}
|
|
1742
|
+
const targetIndex = target.data.length - 1;
|
|
1743
|
+
target.select([targetIndex]);
|
|
1744
|
+
const targetNavService = target.keyboardNavigationService;
|
|
1745
|
+
const targetSelService = target.selectionService;
|
|
1746
|
+
this.updateListBoxIndices(targetNavService, targetSelService, targetIndex);
|
|
1407
1747
|
this.selectedBox = target;
|
|
1408
1748
|
}
|
|
1409
1749
|
transferAll(source, target) {
|
|
1410
|
-
if (!target || !source) {
|
|
1750
|
+
if (!target || !source || source.data?.length === 0) {
|
|
1411
1751
|
return;
|
|
1412
1752
|
}
|
|
1413
|
-
|
|
1414
|
-
target.
|
|
1753
|
+
const itemsToTransfer = source.data.splice(0, source.data.length);
|
|
1754
|
+
target.data.push(...itemsToTransfer);
|
|
1755
|
+
source.clearSelection();
|
|
1756
|
+
const sourceNavService = source.keyboardNavigationService;
|
|
1757
|
+
const sourceSelService = source.selectionService;
|
|
1758
|
+
this.updateListBoxIndices(sourceNavService, sourceSelService, 0);
|
|
1759
|
+
const targetIndex = target.data.length - 1;
|
|
1760
|
+
target.select([targetIndex]);
|
|
1761
|
+
const targetNavService = target.keyboardNavigationService;
|
|
1762
|
+
const targetSelService = target.selectionService;
|
|
1763
|
+
this.updateListBoxIndices(targetNavService, targetSelService, targetIndex);
|
|
1415
1764
|
this.selectedBox = target;
|
|
1416
1765
|
}
|
|
1417
|
-
|
|
1766
|
+
updateListBoxIndices = (keyboardNavService, selectionService, index, setFocusedIndex = true) => {
|
|
1767
|
+
if (setFocusedIndex) {
|
|
1768
|
+
keyboardNavService.focusedListboxItemIndex = index;
|
|
1769
|
+
}
|
|
1770
|
+
keyboardNavService.selectedListboxItemIndex = index;
|
|
1771
|
+
selectionService.rangeSelectionAnchorIndex = index;
|
|
1772
|
+
selectionService.lastSelectedOrUnselectedIndex = index;
|
|
1773
|
+
};
|
|
1774
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DataBindingDirective, deps: [{ token: ListBoxComponent }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Directive });
|
|
1418
1775
|
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.14", type: DataBindingDirective, isStandalone: true, selector: "[kendoListBoxDataBinding]", inputs: { connectedWith: "connectedWith" }, usesOnChanges: true, ngImport: i0 });
|
|
1419
1776
|
}
|
|
1420
1777
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DataBindingDirective, decorators: [{
|
|
@@ -1423,7 +1780,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
1423
1780
|
selector: '[kendoListBoxDataBinding]',
|
|
1424
1781
|
standalone: true
|
|
1425
1782
|
}]
|
|
1426
|
-
}], ctorParameters: () => [{ type: ListBoxComponent }], propDecorators: { connectedWith: [{
|
|
1783
|
+
}], ctorParameters: () => [{ type: ListBoxComponent }, { type: i0.NgZone }], propDecorators: { connectedWith: [{
|
|
1427
1784
|
type: Input
|
|
1428
1785
|
}] } });
|
|
1429
1786
|
|