@progress/kendo-angular-listbox 21.0.0-develop.2 → 21.0.0-develop.21
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 +6 -5
- package/esm2022/data-binding.directive.mjs +69 -31
- package/esm2022/item-selectable.directive.mjs +6 -1
- package/esm2022/keyboard-navigation.service.mjs +63 -13
- package/esm2022/listbox.component.mjs +131 -53
- 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 +395 -104
- package/index.d.ts +0 -1
- package/keyboard-navigation.service.d.ts +16 -2
- package/listbox.component.d.ts +24 -9
- 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
|
@@ -0,0 +1,52 @@
|
|
|
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
|
+
"use strict";
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
23
|
+
if (mod && mod.__esModule) return mod;
|
|
24
|
+
var result = {};
|
|
25
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
26
|
+
__setModuleDefault(result, mod);
|
|
27
|
+
return result;
|
|
28
|
+
};
|
|
29
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
+
exports.default = default_1;
|
|
31
|
+
const utils_1 = require("../utils");
|
|
32
|
+
const fs = __importStar(require("fs"));
|
|
33
|
+
const index_1 = require("../template-transformer/index");
|
|
34
|
+
function default_1(fileInfo, api) {
|
|
35
|
+
const filePath = fileInfo.path;
|
|
36
|
+
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');
|
|
42
|
+
}
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
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');
|
|
51
|
+
return rootSource.toSource();
|
|
52
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
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
|
+
"use strict";
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.default = default_1;
|
|
8
|
+
function default_1(fileInfo, api) {
|
|
9
|
+
const filePath = fileInfo.path;
|
|
10
|
+
if (filePath.endsWith('.html')) {
|
|
11
|
+
// HTML transformations not needed for this migration
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const j = api.jscodeshift;
|
|
15
|
+
const rootSource = j(fileInfo.source);
|
|
16
|
+
tsSelectedIndexTransformer(fileInfo.source, rootSource, j, 'ListBoxComponent');
|
|
17
|
+
return rootSource.toSource();
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Custom transformer to convert selectedIndex property access to selectedIndices[0]
|
|
21
|
+
* for ListBoxComponent instances
|
|
22
|
+
*/
|
|
23
|
+
const tsSelectedIndexTransformer = (source, root, j, componentType) => {
|
|
24
|
+
if (source.includes(componentType)) {
|
|
25
|
+
// Find all class properties that are of type ListBoxComponent
|
|
26
|
+
const properties = new Set();
|
|
27
|
+
// Find properties with type annotations
|
|
28
|
+
root.find(j.ClassProperty, {
|
|
29
|
+
typeAnnotation: {
|
|
30
|
+
typeAnnotation: {
|
|
31
|
+
typeName: {
|
|
32
|
+
name: componentType,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
}).forEach((path) => {
|
|
37
|
+
if (path.node.key.type === 'Identifier') {
|
|
38
|
+
properties.add(path.node.key.name);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
// Find function parameters of type componentType
|
|
42
|
+
const parameters = new Set();
|
|
43
|
+
root.find(j.FunctionDeclaration).forEach((path) => {
|
|
44
|
+
if (path.node.params) {
|
|
45
|
+
path.node.params.forEach((param) => {
|
|
46
|
+
if (param.type === 'Identifier' &&
|
|
47
|
+
param.typeAnnotation &&
|
|
48
|
+
param.typeAnnotation.typeAnnotation?.type === 'TSTypeReference' &&
|
|
49
|
+
param.typeAnnotation.typeAnnotation.typeName.type === 'Identifier' &&
|
|
50
|
+
param.typeAnnotation.typeAnnotation.typeName.name === componentType) {
|
|
51
|
+
parameters.add(param.name);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
// Also check method declarations in classes
|
|
57
|
+
root.find(j.ClassMethod).forEach((path) => {
|
|
58
|
+
if (path.node.params) {
|
|
59
|
+
path.node.params.forEach((param) => {
|
|
60
|
+
if (param.type === 'Identifier' &&
|
|
61
|
+
param.typeAnnotation &&
|
|
62
|
+
param.typeAnnotation.typeAnnotation?.type === 'TSTypeReference' &&
|
|
63
|
+
param.typeAnnotation.typeAnnotation.typeName.type === 'Identifier' &&
|
|
64
|
+
param.typeAnnotation.typeAnnotation.typeName.name === componentType) {
|
|
65
|
+
parameters.add(param.name);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
// Also check arrow functions
|
|
71
|
+
root.find(j.ArrowFunctionExpression).forEach((path) => {
|
|
72
|
+
if (path.node.params) {
|
|
73
|
+
path.node.params.forEach((param) => {
|
|
74
|
+
if (param.type === 'Identifier' &&
|
|
75
|
+
param.typeAnnotation &&
|
|
76
|
+
param.typeAnnotation.typeAnnotation?.type === 'TSTypeReference' &&
|
|
77
|
+
param.typeAnnotation.typeAnnotation.typeName.type === 'Identifier' &&
|
|
78
|
+
param.typeAnnotation.typeAnnotation.typeName.name === componentType) {
|
|
79
|
+
parameters.add(param.name);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
// Find local variable declarations of type componentType
|
|
85
|
+
const localVariables = new Set();
|
|
86
|
+
root.find(j.VariableDeclarator).forEach((path) => {
|
|
87
|
+
if (path.node.id.type === 'Identifier' &&
|
|
88
|
+
path.node.id.typeAnnotation &&
|
|
89
|
+
path.node.id.typeAnnotation.typeAnnotation?.type === 'TSTypeReference' &&
|
|
90
|
+
path.node.id.typeAnnotation.typeAnnotation.typeName.type === 'Identifier' &&
|
|
91
|
+
path.node.id.typeAnnotation.typeAnnotation.typeName.name === componentType) {
|
|
92
|
+
localVariables.add(path.node.id.name);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
// Find all member expressions where selectedIndex property is accessed on any ListBoxComponent instance
|
|
96
|
+
root.find(j.MemberExpression, {
|
|
97
|
+
property: {
|
|
98
|
+
type: 'Identifier',
|
|
99
|
+
name: 'selectedIndex',
|
|
100
|
+
},
|
|
101
|
+
})
|
|
102
|
+
.filter((path) => {
|
|
103
|
+
// Filter to only include accesses on properties that are ListBoxComponent instances
|
|
104
|
+
if (path.node.object.type === 'MemberExpression' && path.node.object.property.type === 'Identifier') {
|
|
105
|
+
// handle properties of this
|
|
106
|
+
if (path.node.object.object.type === 'ThisExpression' &&
|
|
107
|
+
properties.has(path.node.object.property.name)) {
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Handle function parameters and local variables
|
|
112
|
+
if (path.node.object.type === 'Identifier') {
|
|
113
|
+
return parameters.has(path.node.object.name) || localVariables.has(path.node.object.name);
|
|
114
|
+
}
|
|
115
|
+
return false;
|
|
116
|
+
})
|
|
117
|
+
.forEach((path) => {
|
|
118
|
+
// Replace selectedIndex with selectedIndices[0]
|
|
119
|
+
const memberExpression = j.memberExpression(j.memberExpression(path.node.object, j.identifier('selectedIndices')), j.numericLiteral(0), true // computed property access (uses brackets)
|
|
120
|
+
);
|
|
121
|
+
// Replace the entire member expression
|
|
122
|
+
j(path).replaceWith(memberExpression);
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
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
|
+
"use strict";
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.default = default_1;
|
|
8
|
+
const utils_1 = require("../utils");
|
|
9
|
+
function default_1(fileInfo, api) {
|
|
10
|
+
const j = api.jscodeshift;
|
|
11
|
+
const rootSource = j(fileInfo.source);
|
|
12
|
+
(0, utils_1.tsInterfaceTransformer)(fileInfo, rootSource, j, '@progress/kendo-angular-listbox', 'Toolbar', 'ListBoxToolbarConfig');
|
|
13
|
+
return rootSource.toSource();
|
|
14
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright © 2025 Progress Software Corporation. All rights reserved.
|
|
3
3
|
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
4
|
*-------------------------------------------------------------------------------------------*/
|
|
5
|
-
import { OnChanges, OnDestroy, SimpleChanges } from '@angular/core';
|
|
5
|
+
import { NgZone, OnChanges, OnDestroy, SimpleChanges } from '@angular/core';
|
|
6
6
|
import { ListBoxComponent } from './listbox.component';
|
|
7
7
|
import * as i0 from "@angular/core";
|
|
8
8
|
/**
|
|
@@ -29,16 +29,17 @@ import * as i0 from "@angular/core";
|
|
|
29
29
|
*/
|
|
30
30
|
export declare class DataBindingDirective implements OnChanges, OnDestroy {
|
|
31
31
|
private listbox;
|
|
32
|
+
private zone;
|
|
32
33
|
/**
|
|
33
34
|
* Specifies the `ListBoxComponent` instance with which the current ListBox connects.
|
|
34
35
|
* When you link two listboxes through this input, you can transfer items between them.
|
|
35
36
|
*/
|
|
36
37
|
connectedWith: ListBoxComponent;
|
|
37
|
-
private
|
|
38
|
+
private actionSub;
|
|
38
39
|
private selectedBoxSub;
|
|
39
40
|
private connectedWithSub;
|
|
40
41
|
private selectedBox;
|
|
41
|
-
constructor(listbox: ListBoxComponent);
|
|
42
|
+
constructor(listbox: ListBoxComponent, zone: NgZone);
|
|
42
43
|
/**
|
|
43
44
|
* @hidden
|
|
44
45
|
*/
|
|
@@ -48,8 +49,8 @@ export declare class DataBindingDirective implements OnChanges, OnDestroy {
|
|
|
48
49
|
*/
|
|
49
50
|
ngOnDestroy(): void;
|
|
50
51
|
private moveVertically;
|
|
51
|
-
private
|
|
52
|
-
private
|
|
52
|
+
private removeSelectedItems;
|
|
53
|
+
private transferSelectedItems;
|
|
53
54
|
private transferAll;
|
|
54
55
|
static ɵfac: i0.ɵɵFactoryDeclaration<DataBindingDirective, never>;
|
|
55
56
|
static ɵdir: i0.ɵɵDirectiveDeclaration<DataBindingDirective, "[kendoListBoxDataBinding]", never, { "connectedWith": { "alias": "connectedWith"; "required": false; }; }, {}, never, never, true, never>;
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
* Copyright © 2025 Progress Software Corporation. All rights reserved.
|
|
3
3
|
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
4
|
*-------------------------------------------------------------------------------------------*/
|
|
5
|
-
import { Directive, Input } from '@angular/core';
|
|
5
|
+
import { Directive, Input, NgZone } from '@angular/core';
|
|
6
6
|
import { isChanged } from '@progress/kendo-angular-common';
|
|
7
7
|
import { Subscription } from 'rxjs';
|
|
8
|
+
import { take } from 'rxjs/operators';
|
|
8
9
|
import { ListBoxComponent } from './listbox.component';
|
|
9
10
|
import { isPresent } from './util';
|
|
10
11
|
import * as i0 from "@angular/core";
|
|
@@ -33,22 +34,24 @@ import * as i1 from "./listbox.component";
|
|
|
33
34
|
*/
|
|
34
35
|
export class DataBindingDirective {
|
|
35
36
|
listbox;
|
|
37
|
+
zone;
|
|
36
38
|
/**
|
|
37
39
|
* Specifies the `ListBoxComponent` instance with which the current ListBox connects.
|
|
38
40
|
* When you link two listboxes through this input, you can transfer items between them.
|
|
39
41
|
*/
|
|
40
42
|
connectedWith;
|
|
41
|
-
|
|
43
|
+
actionSub = new Subscription();
|
|
42
44
|
selectedBoxSub = new Subscription();
|
|
43
45
|
connectedWithSub = new Subscription();
|
|
44
46
|
selectedBox;
|
|
45
|
-
constructor(listbox) {
|
|
47
|
+
constructor(listbox, zone) {
|
|
46
48
|
this.listbox = listbox;
|
|
49
|
+
this.zone = zone;
|
|
47
50
|
this.selectedBox = this.listbox;
|
|
48
51
|
this.connectedWithSub.add(this.listbox.getChildListbox.subscribe(() => {
|
|
49
52
|
this.listbox.childListbox = this.connectedWith;
|
|
50
53
|
}));
|
|
51
|
-
this.
|
|
54
|
+
this.actionSub.add(this.listbox.action.subscribe((actionName) => {
|
|
52
55
|
switch (actionName) {
|
|
53
56
|
case 'moveUp': {
|
|
54
57
|
this.moveVertically('up');
|
|
@@ -59,11 +62,11 @@ export class DataBindingDirective {
|
|
|
59
62
|
break;
|
|
60
63
|
}
|
|
61
64
|
case 'transferFrom': {
|
|
62
|
-
this.
|
|
65
|
+
this.transferSelectedItems(this.connectedWith, this.listbox);
|
|
63
66
|
break;
|
|
64
67
|
}
|
|
65
68
|
case 'transferTo': {
|
|
66
|
-
this.
|
|
69
|
+
this.transferSelectedItems(this.listbox, this.connectedWith);
|
|
67
70
|
break;
|
|
68
71
|
}
|
|
69
72
|
case 'transferAllTo': {
|
|
@@ -75,7 +78,7 @@ export class DataBindingDirective {
|
|
|
75
78
|
break;
|
|
76
79
|
}
|
|
77
80
|
case 'remove': {
|
|
78
|
-
this.
|
|
81
|
+
this.removeSelectedItems();
|
|
79
82
|
break;
|
|
80
83
|
}
|
|
81
84
|
default: {
|
|
@@ -107,9 +110,9 @@ export class DataBindingDirective {
|
|
|
107
110
|
* @hidden
|
|
108
111
|
*/
|
|
109
112
|
ngOnDestroy() {
|
|
110
|
-
if (this.
|
|
111
|
-
this.
|
|
112
|
-
this.
|
|
113
|
+
if (this.actionSub) {
|
|
114
|
+
this.actionSub.unsubscribe();
|
|
115
|
+
this.actionSub = null;
|
|
113
116
|
}
|
|
114
117
|
if (this.selectedBoxSub) {
|
|
115
118
|
this.selectedBoxSub.unsubscribe();
|
|
@@ -117,38 +120,73 @@ export class DataBindingDirective {
|
|
|
117
120
|
}
|
|
118
121
|
}
|
|
119
122
|
moveVertically(dir) {
|
|
120
|
-
const
|
|
121
|
-
if (!isPresent(
|
|
123
|
+
const selectedIndices = this.selectedBox.selectedIndices;
|
|
124
|
+
if (!isPresent(selectedIndices) || selectedIndices.length === 0) {
|
|
122
125
|
return;
|
|
123
126
|
}
|
|
124
|
-
const
|
|
125
|
-
const
|
|
127
|
+
const sortedIndices = [...selectedIndices].sort((a, b) => a - b);
|
|
128
|
+
const topIndex = sortedIndices[0];
|
|
129
|
+
const bottomIndex = sortedIndices[sortedIndices.length - 1];
|
|
130
|
+
const topReached = dir === 'up' && topIndex <= 0;
|
|
131
|
+
const bottomReached = dir === 'down' && bottomIndex >= this.selectedBox.data.length - 1;
|
|
126
132
|
if (topReached || bottomReached) {
|
|
127
133
|
return;
|
|
128
134
|
}
|
|
129
|
-
const
|
|
135
|
+
const data = this.selectedBox.data;
|
|
136
|
+
const newSelectedIndices = [];
|
|
137
|
+
if (dir === 'up') {
|
|
138
|
+
for (const index of sortedIndices) {
|
|
139
|
+
const newIndex = index - 1;
|
|
140
|
+
[data[newIndex], data[index]] = [data[index], data[newIndex]];
|
|
141
|
+
newSelectedIndices.push(newIndex);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
for (let i = sortedIndices.length - 1; i >= 0; i--) {
|
|
146
|
+
const index = sortedIndices[i];
|
|
147
|
+
const newIndex = index + 1;
|
|
148
|
+
[data[newIndex], data[index]] = [data[index], data[newIndex]];
|
|
149
|
+
newSelectedIndices.push(newIndex);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
newSelectedIndices.sort((a, b) => a - b);
|
|
153
|
+
this.selectedBox.selectionService.setSelectedIndices(newSelectedIndices);
|
|
130
154
|
const navigation = this.selectedBox.keyboardNavigationService;
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
155
|
+
const currentFocusedIndex = navigation.focusedListboxItemIndex;
|
|
156
|
+
const focusedItemIndexInSelection = sortedIndices.indexOf(currentFocusedIndex);
|
|
157
|
+
let newFocusIndex;
|
|
158
|
+
if (focusedItemIndexInSelection !== -1) {
|
|
159
|
+
newFocusIndex = newSelectedIndices[focusedItemIndexInSelection];
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
newFocusIndex = dir === 'up' ? topIndex - 1 : bottomIndex + 1;
|
|
163
|
+
}
|
|
164
|
+
this.zone.onStable.pipe(take(1)).subscribe(() => {
|
|
165
|
+
const listboxItems = this.selectedBox.listboxItems.toArray();
|
|
166
|
+
const previousItem = listboxItems[currentFocusedIndex]?.nativeElement;
|
|
167
|
+
const currentItem = listboxItems[newFocusIndex]?.nativeElement;
|
|
168
|
+
navigation.changeTabindex(previousItem, currentItem);
|
|
169
|
+
navigation.focusedListboxItemIndex = newFocusIndex;
|
|
170
|
+
navigation.selectedListboxItemIndex = newFocusIndex;
|
|
171
|
+
});
|
|
134
172
|
}
|
|
135
|
-
|
|
136
|
-
const
|
|
137
|
-
if (!isPresent(
|
|
173
|
+
removeSelectedItems() {
|
|
174
|
+
const itemIndices = this.selectedBox.selectedIndices;
|
|
175
|
+
if (!isPresent(itemIndices) || itemIndices.length === 0) {
|
|
138
176
|
return;
|
|
139
177
|
}
|
|
140
|
-
this.selectedBox.data.
|
|
178
|
+
this.selectedBox.data = this.selectedBox.data.filter((_, index) => !itemIndices.includes(index));
|
|
141
179
|
this.selectedBox.selectionService.clearSelection();
|
|
142
180
|
}
|
|
143
|
-
|
|
144
|
-
const
|
|
145
|
-
if (!
|
|
181
|
+
transferSelectedItems(source, target) {
|
|
182
|
+
const selectedIndices = source?.data && source?.selectedIndices;
|
|
183
|
+
if (!target || !source || !isPresent(selectedIndices) || selectedIndices.length === 0) {
|
|
146
184
|
return;
|
|
147
185
|
}
|
|
148
|
-
target.data.push(
|
|
149
|
-
source.data.
|
|
186
|
+
target.data.push(...selectedIndices.map(index => source.data[index]));
|
|
187
|
+
source.data = source.data.filter((_, index) => !selectedIndices.includes(index));
|
|
150
188
|
source.clearSelection();
|
|
151
|
-
target.
|
|
189
|
+
target.select([target.data.length - 1]);
|
|
152
190
|
this.selectedBox = target;
|
|
153
191
|
}
|
|
154
192
|
transferAll(source, target) {
|
|
@@ -156,10 +194,10 @@ export class DataBindingDirective {
|
|
|
156
194
|
return;
|
|
157
195
|
}
|
|
158
196
|
target.data.splice(target.data.length, 0, ...source.data.splice(0, source.data.length));
|
|
159
|
-
target.
|
|
197
|
+
target.select([target.data.length - 1]);
|
|
160
198
|
this.selectedBox = target;
|
|
161
199
|
}
|
|
162
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DataBindingDirective, deps: [{ token: i1.ListBoxComponent }], target: i0.ɵɵFactoryTarget.Directive });
|
|
200
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DataBindingDirective, deps: [{ token: i1.ListBoxComponent }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Directive });
|
|
163
201
|
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 });
|
|
164
202
|
}
|
|
165
203
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DataBindingDirective, decorators: [{
|
|
@@ -168,6 +206,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
168
206
|
selector: '[kendoListBoxDataBinding]',
|
|
169
207
|
standalone: true
|
|
170
208
|
}]
|
|
171
|
-
}], ctorParameters: () => [{ type: i1.ListBoxComponent }], propDecorators: { connectedWith: [{
|
|
209
|
+
}], ctorParameters: () => [{ type: i1.ListBoxComponent }, { type: i0.NgZone }], propDecorators: { connectedWith: [{
|
|
172
210
|
type: Input
|
|
173
211
|
}] } });
|
|
@@ -20,7 +20,12 @@ export class ItemSelectableDirective {
|
|
|
20
20
|
}
|
|
21
21
|
onClick(event) {
|
|
22
22
|
event.stopPropagation();
|
|
23
|
-
|
|
23
|
+
const ctrlKey = event.ctrlKey || event.metaKey;
|
|
24
|
+
const shiftKey = event.shiftKey;
|
|
25
|
+
if (shiftKey) {
|
|
26
|
+
event.preventDefault();
|
|
27
|
+
}
|
|
28
|
+
this.selectionService.select(this.index, ctrlKey, shiftKey);
|
|
24
29
|
}
|
|
25
30
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ItemSelectableDirective, deps: [{ token: i1.ListBoxSelectionService }], target: i0.ɵɵFactoryTarget.Directive });
|
|
26
31
|
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 });
|
|
@@ -22,6 +22,8 @@ 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;
|
|
@@ -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;
|
|
@@ -64,9 +77,7 @@ export class KeyboardNavigationService {
|
|
|
64
77
|
this.onSelectChange(event, listboxItems);
|
|
65
78
|
}
|
|
66
79
|
else if (keyCode === Keys.Space) {
|
|
67
|
-
|
|
68
|
-
this.onSpaceKey(event, listboxItems);
|
|
69
|
-
}
|
|
80
|
+
this.onSpaceKey(event, listboxItems);
|
|
70
81
|
}
|
|
71
82
|
}
|
|
72
83
|
}
|
|
@@ -90,18 +101,30 @@ 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)]
|
|
94
|
-
const currentItem = toolsRef[this.focusedToolIndex]
|
|
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
|
-
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
this.
|
|
104
|
-
|
|
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
|
+
});
|
|
125
|
+
if (!shiftKey) {
|
|
126
|
+
this.selectedListboxItemIndex = this.focusedListboxItemIndex;
|
|
127
|
+
}
|
|
105
128
|
}
|
|
106
129
|
onArrowUpOrDown(keyCode, ctrlOrMetaKey, event, activeToolbar, listboxItems) {
|
|
107
130
|
event.preventDefault();
|
|
@@ -118,6 +141,10 @@ export class KeyboardNavigationService {
|
|
|
118
141
|
this.changeFocusedItem(dir, listboxItems);
|
|
119
142
|
return;
|
|
120
143
|
}
|
|
144
|
+
if (event.shiftKey) {
|
|
145
|
+
this.onShiftArrow(dir, listboxItems);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
121
148
|
dir === 'moveUp' ? this.onArrowUp(listboxItems) : this.onArrowDown(listboxItems);
|
|
122
149
|
this.onSelectionChange.emit({ index: this.selectedListboxItemIndex, prevIndex: this.focusedListboxItemIndex });
|
|
123
150
|
this.focusedListboxItemIndex = this.selectedListboxItemIndex;
|
|
@@ -151,7 +178,8 @@ export class KeyboardNavigationService {
|
|
|
151
178
|
this.selectedListboxItemIndex = this.focusedListboxItemIndex;
|
|
152
179
|
}
|
|
153
180
|
this.changeTabindex(previousItem, currentItem, !!currentItem);
|
|
154
|
-
|
|
181
|
+
const ctrlKey = event.ctrlKey || event.metaKey;
|
|
182
|
+
this.onSelectionChange.emit({ index: this.selectedListboxItemIndex, prevIndex, ctrlKey });
|
|
155
183
|
}
|
|
156
184
|
onF10Key(tools) {
|
|
157
185
|
if (this.focusedToolIndex && this.focusedToolIndex > -1) {
|
|
@@ -253,14 +281,36 @@ export class KeyboardNavigationService {
|
|
|
253
281
|
});
|
|
254
282
|
}
|
|
255
283
|
changeFocusedItem(dir, listboxItems) {
|
|
256
|
-
|
|
284
|
+
const previousIndex = this.focusedListboxItemIndex;
|
|
285
|
+
const previousItem = listboxItems[previousIndex].nativeElement;
|
|
257
286
|
if (this.focusedListboxItemIndex > 0 && dir === 'moveUp') {
|
|
258
287
|
this.focusedListboxItemIndex -= 1;
|
|
259
288
|
}
|
|
260
289
|
else if (this.focusedListboxItemIndex < listboxItems.length - 1 && dir === 'moveDown') {
|
|
261
290
|
this.focusedListboxItemIndex += 1;
|
|
262
291
|
}
|
|
263
|
-
listboxItems[this.focusedListboxItemIndex].nativeElement
|
|
292
|
+
const currentItem = listboxItems[this.focusedListboxItemIndex].nativeElement;
|
|
293
|
+
this.changeTabindex(previousItem, currentItem);
|
|
294
|
+
}
|
|
295
|
+
onShiftArrow(dir, listboxItems) {
|
|
296
|
+
const previousFocusIndex = this.focusedListboxItemIndex;
|
|
297
|
+
if (dir === 'moveUp' && this.focusedListboxItemIndex > 0) {
|
|
298
|
+
this.focusedListboxItemIndex -= 1;
|
|
299
|
+
}
|
|
300
|
+
else if (dir === 'moveDown' && this.focusedListboxItemIndex < listboxItems.length - 1) {
|
|
301
|
+
this.focusedListboxItemIndex += 1;
|
|
302
|
+
}
|
|
303
|
+
if (previousFocusIndex !== this.focusedListboxItemIndex) {
|
|
304
|
+
const previousItem = listboxItems[previousFocusIndex]?.nativeElement;
|
|
305
|
+
const currentItem = listboxItems[this.focusedListboxItemIndex]?.nativeElement;
|
|
306
|
+
this.changeTabindex(previousItem, currentItem);
|
|
307
|
+
this.onSelectionChange.emit({
|
|
308
|
+
index: this.focusedListboxItemIndex,
|
|
309
|
+
prevIndex: this.selectedListboxItemIndex,
|
|
310
|
+
shiftKey: true
|
|
311
|
+
});
|
|
312
|
+
this.selectedListboxItemIndex = this.focusedListboxItemIndex;
|
|
313
|
+
}
|
|
264
314
|
}
|
|
265
315
|
onArrowDown(listboxItems) {
|
|
266
316
|
if (this.selectedListboxItemIndex < listboxItems.length - 1) {
|