@angular/cdk-experimental 14.0.3 → 14.1.0-next.2
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/esm2020/listbox/listbox.mjs +565 -314
- package/esm2020/version.mjs +1 -1
- package/fesm2015/cdk-experimental.mjs +1 -1
- package/fesm2015/cdk-experimental.mjs.map +1 -1
- package/fesm2015/listbox.mjs +569 -321
- package/fesm2015/listbox.mjs.map +1 -1
- package/fesm2020/cdk-experimental.mjs +1 -1
- package/fesm2020/cdk-experimental.mjs.map +1 -1
- package/fesm2020/listbox.mjs +566 -314
- package/fesm2020/listbox.mjs.map +1 -1
- package/listbox/index.d.ts +267 -131
- package/package.json +2 -2
package/fesm2020/listbox.mjs
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import {
|
|
2
|
+
import { inject, ElementRef, Directive, Input, ChangeDetectorRef, InjectFlags, forwardRef, Output, ContentChildren, NgModule } from '@angular/core';
|
|
3
3
|
import { ActiveDescendantKeyManager } from '@angular/cdk/a11y';
|
|
4
4
|
import { SPACE, ENTER, UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW } from '@angular/cdk/keycodes';
|
|
5
5
|
import { coerceBooleanProperty, coerceArray } from '@angular/cdk/coercion';
|
|
6
6
|
import { SelectionModel } from '@angular/cdk/collections';
|
|
7
|
-
import { defer, merge,
|
|
8
|
-
import { startWith, switchMap, takeUntil } from 'rxjs/operators';
|
|
9
|
-
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import { CDK_COMBOBOX } from '@angular/cdk-experimental/combobox';
|
|
7
|
+
import { Subject, BehaviorSubject, defer, merge, combineLatest } from 'rxjs';
|
|
8
|
+
import { startWith, switchMap, mapTo, takeUntil, filter, take } from 'rxjs/operators';
|
|
9
|
+
import { Validators, NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms';
|
|
10
|
+
import { Directionality } from '@angular/cdk/bidi';
|
|
11
|
+
import { CdkCombobox } from '@angular/cdk-experimental/combobox';
|
|
13
12
|
|
|
14
13
|
/**
|
|
15
14
|
* @license
|
|
@@ -18,115 +17,116 @@ import { CDK_COMBOBOX } from '@angular/cdk-experimental/combobox';
|
|
|
18
17
|
* Use of this source code is governed by an MIT-style license that can be
|
|
19
18
|
* found in the LICENSE file at https://angular.io/license
|
|
20
19
|
*/
|
|
20
|
+
/** The next id to use for creating unique DOM IDs. */
|
|
21
21
|
let nextId = 0;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
multi: true,
|
|
27
|
-
};
|
|
22
|
+
// TODO(mmalerba):
|
|
23
|
+
// - should listbox wrap be configurable?
|
|
24
|
+
// - should skipping disabled options be configurable?
|
|
25
|
+
/** A selectable option in a listbox. */
|
|
28
26
|
class CdkOption {
|
|
29
|
-
constructor(
|
|
30
|
-
this.
|
|
31
|
-
this.listbox = listbox;
|
|
32
|
-
this._selected = false;
|
|
27
|
+
constructor() {
|
|
28
|
+
this._generatedId = `cdk-option-${nextId++}`;
|
|
33
29
|
this._disabled = false;
|
|
30
|
+
/** The option's host element */
|
|
31
|
+
this.element = inject(ElementRef).nativeElement;
|
|
32
|
+
/** The parent listbox this option belongs to. */
|
|
33
|
+
this.listbox = inject(CdkListbox);
|
|
34
|
+
/** Emits when the option is destroyed. */
|
|
35
|
+
this.destroyed = new Subject();
|
|
36
|
+
/** Emits when the option is clicked. */
|
|
37
|
+
this._clicked = new Subject();
|
|
38
|
+
/** Whether the option is currently active. */
|
|
34
39
|
this._active = false;
|
|
35
|
-
/** The id of the option, set to a uniqueid if the user does not provide one. */
|
|
36
|
-
this.id = `cdk-option-${nextId++}`;
|
|
37
|
-
this.selectionChange = new EventEmitter();
|
|
38
40
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
/** The id of the option's host element. */
|
|
42
|
+
get id() {
|
|
43
|
+
return this._id || this._generatedId;
|
|
41
44
|
}
|
|
42
|
-
set
|
|
43
|
-
|
|
44
|
-
this._selected = coerceBooleanProperty(value);
|
|
45
|
-
}
|
|
45
|
+
set id(value) {
|
|
46
|
+
this._id = value;
|
|
46
47
|
}
|
|
48
|
+
/** Whether this option is disabled. */
|
|
47
49
|
get disabled() {
|
|
48
|
-
return this._disabled;
|
|
50
|
+
return this.listbox.disabled || this._disabled;
|
|
49
51
|
}
|
|
50
52
|
set disabled(value) {
|
|
51
53
|
this._disabled = coerceBooleanProperty(value);
|
|
52
54
|
}
|
|
53
|
-
/** The
|
|
54
|
-
get
|
|
55
|
-
return this.
|
|
55
|
+
/** The tabindex of the option when it is enabled. */
|
|
56
|
+
get enabledTabIndex() {
|
|
57
|
+
return this._enabledTabIndex === undefined
|
|
58
|
+
? this.listbox.enabledTabIndex
|
|
59
|
+
: this._enabledTabIndex;
|
|
56
60
|
}
|
|
57
|
-
set
|
|
58
|
-
|
|
59
|
-
this.deselect();
|
|
60
|
-
}
|
|
61
|
-
this._value = value;
|
|
61
|
+
set enabledTabIndex(value) {
|
|
62
|
+
this._enabledTabIndex = value;
|
|
62
63
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
this.selected = !this.selected;
|
|
67
|
-
this._emitSelectionChange(true);
|
|
68
|
-
}
|
|
64
|
+
ngOnDestroy() {
|
|
65
|
+
this.destroyed.next();
|
|
66
|
+
this.destroyed.complete();
|
|
69
67
|
}
|
|
70
|
-
/**
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
this._active = true;
|
|
74
|
-
}
|
|
68
|
+
/** Whether this option is selected. */
|
|
69
|
+
isSelected() {
|
|
70
|
+
return this.listbox.isSelected(this.value);
|
|
75
71
|
}
|
|
76
|
-
/**
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
this._active = false;
|
|
80
|
-
}
|
|
72
|
+
/** Whether this option is active. */
|
|
73
|
+
isActive() {
|
|
74
|
+
return this._active;
|
|
81
75
|
}
|
|
82
|
-
/**
|
|
76
|
+
/** Toggle the selected state of this option. */
|
|
77
|
+
toggle() {
|
|
78
|
+
this.listbox.toggle(this);
|
|
79
|
+
}
|
|
80
|
+
/** Select this option if it is not selected. */
|
|
83
81
|
select() {
|
|
84
|
-
|
|
85
|
-
this.selected = true;
|
|
86
|
-
this._emitSelectionChange();
|
|
87
|
-
}
|
|
82
|
+
this.listbox.select(this);
|
|
88
83
|
}
|
|
89
|
-
/**
|
|
84
|
+
/** Deselect this option if it is selected. */
|
|
90
85
|
deselect() {
|
|
91
|
-
|
|
92
|
-
this.selected = false;
|
|
93
|
-
this._emitSelectionChange();
|
|
94
|
-
}
|
|
86
|
+
this.listbox.deselect(this);
|
|
95
87
|
}
|
|
96
|
-
/**
|
|
88
|
+
/** Focus this option. */
|
|
97
89
|
focus() {
|
|
98
|
-
this.
|
|
99
|
-
}
|
|
100
|
-
/** Returns true if the option or listbox are disabled, and false otherwise. */
|
|
101
|
-
_isInteractionDisabled() {
|
|
102
|
-
return this.listbox.disabled || this._disabled;
|
|
103
|
-
}
|
|
104
|
-
/** Emits a change event extending the Option Selection Change Event interface. */
|
|
105
|
-
_emitSelectionChange(isUserInput = false) {
|
|
106
|
-
this.selectionChange.emit({
|
|
107
|
-
source: this,
|
|
108
|
-
isUserInput: isUserInput,
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
/** Returns the tab index which depends on the disabled property. */
|
|
112
|
-
_getTabIndex() {
|
|
113
|
-
return this._isInteractionDisabled() ? null : '-1';
|
|
90
|
+
this.element.focus();
|
|
114
91
|
}
|
|
115
92
|
/** Get the label for this element which is required by the FocusableOption interface. */
|
|
116
93
|
getLabel() {
|
|
117
|
-
return (this.
|
|
94
|
+
return (this.typeaheadLabel ?? this.element.textContent?.trim()) || '';
|
|
118
95
|
}
|
|
119
|
-
/**
|
|
96
|
+
/**
|
|
97
|
+
* Set the option as active.
|
|
98
|
+
* @docs-private
|
|
99
|
+
*/
|
|
120
100
|
setActiveStyles() {
|
|
121
101
|
this._active = true;
|
|
122
102
|
}
|
|
123
|
-
/**
|
|
103
|
+
/**
|
|
104
|
+
* Set the option as inactive.
|
|
105
|
+
* @docs-private
|
|
106
|
+
*/
|
|
124
107
|
setInactiveStyles() {
|
|
125
108
|
this._active = false;
|
|
126
109
|
}
|
|
110
|
+
/** Handle focus events on the option. */
|
|
111
|
+
_handleFocus() {
|
|
112
|
+
// Options can wind up getting focused in active descendant mode if the user clicks on them.
|
|
113
|
+
// In this case, we push focus back to the parent listbox to prevent an extra tab stop when
|
|
114
|
+
// the user performs a shift+tab.
|
|
115
|
+
if (this.listbox.useActiveDescendant) {
|
|
116
|
+
this.listbox._setActiveOption(this);
|
|
117
|
+
this.listbox.focus();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/** Get the tabindex for this option. */
|
|
121
|
+
_getTabIndex() {
|
|
122
|
+
if (this.listbox.useActiveDescendant || this.disabled) {
|
|
123
|
+
return -1;
|
|
124
|
+
}
|
|
125
|
+
return this.isActive() ? this.enabledTabIndex : -1;
|
|
126
|
+
}
|
|
127
127
|
}
|
|
128
|
-
CdkOption.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: CdkOption, deps: [
|
|
129
|
-
CdkOption.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.1", type: CdkOption, selector: "[cdkOption]", inputs: { id: "id",
|
|
128
|
+
CdkOption.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: CdkOption, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
129
|
+
CdkOption.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.1", type: CdkOption, selector: "[cdkOption]", inputs: { id: "id", value: ["cdkOption", "value"], typeaheadLabel: ["cdkOptionTypeaheadLabel", "typeaheadLabel"], disabled: ["cdkOptionDisabled", "disabled"], enabledTabIndex: ["tabindex", "enabledTabIndex"] }, host: { attributes: { "role": "option" }, listeners: { "click": "_clicked.next()", "focus": "_handleFocus()" }, properties: { "id": "id", "attr.aria-selected": "isSelected() || null", "attr.tabindex": "_getTabIndex()", "attr.aria-disabled": "disabled", "class.cdk-option-disabled": "disabled", "class.cdk-option-active": "isActive()", "class.cdk-option-selected": "isSelected()" }, classAttribute: "cdk-option" }, exportAs: ["cdkOption"], ngImport: i0 });
|
|
130
130
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: CdkOption, decorators: [{
|
|
131
131
|
type: Directive,
|
|
132
132
|
args: [{
|
|
@@ -135,70 +135,134 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImpor
|
|
|
135
135
|
host: {
|
|
136
136
|
'role': 'option',
|
|
137
137
|
'class': 'cdk-option',
|
|
138
|
-
'(click)': 'toggle()',
|
|
139
|
-
'(focus)': 'activate()',
|
|
140
|
-
'(blur)': 'deactivate()',
|
|
141
138
|
'[id]': 'id',
|
|
142
|
-
'[attr.aria-selected]': '
|
|
139
|
+
'[attr.aria-selected]': 'isSelected() || null',
|
|
143
140
|
'[attr.tabindex]': '_getTabIndex()',
|
|
144
|
-
'[attr.aria-disabled]': '
|
|
145
|
-
'[class.cdk-option-disabled]': '
|
|
146
|
-
'[class.cdk-option-active]': '
|
|
147
|
-
'[class.cdk-option-selected]': '
|
|
141
|
+
'[attr.aria-disabled]': 'disabled',
|
|
142
|
+
'[class.cdk-option-disabled]': 'disabled',
|
|
143
|
+
'[class.cdk-option-active]': 'isActive()',
|
|
144
|
+
'[class.cdk-option-selected]': 'isSelected()',
|
|
145
|
+
'(click)': '_clicked.next()',
|
|
146
|
+
'(focus)': '_handleFocus()',
|
|
148
147
|
},
|
|
149
148
|
}]
|
|
150
|
-
}],
|
|
151
|
-
type: Inject,
|
|
152
|
-
args: [forwardRef(() => CdkListbox)]
|
|
153
|
-
}] }]; }, propDecorators: { id: [{
|
|
154
|
-
type: Input
|
|
155
|
-
}], selected: [{
|
|
156
|
-
type: Input
|
|
157
|
-
}], disabled: [{
|
|
149
|
+
}], propDecorators: { id: [{
|
|
158
150
|
type: Input
|
|
159
151
|
}], value: [{
|
|
160
|
-
type: Input
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
152
|
+
type: Input,
|
|
153
|
+
args: ['cdkOption']
|
|
154
|
+
}], typeaheadLabel: [{
|
|
155
|
+
type: Input,
|
|
156
|
+
args: ['cdkOptionTypeaheadLabel']
|
|
157
|
+
}], disabled: [{
|
|
158
|
+
type: Input,
|
|
159
|
+
args: ['cdkOptionDisabled']
|
|
160
|
+
}], enabledTabIndex: [{
|
|
161
|
+
type: Input,
|
|
162
|
+
args: ['tabindex']
|
|
165
163
|
}] } });
|
|
166
164
|
class CdkListbox {
|
|
167
|
-
constructor(
|
|
168
|
-
this.
|
|
169
|
-
this._dir = _dir;
|
|
170
|
-
this._tabIndex = 0;
|
|
171
|
-
/** `View -> model callback called when select has been touched` */
|
|
172
|
-
this._onTouched = () => { };
|
|
173
|
-
/** `View -> model callback called when value changes` */
|
|
174
|
-
this._onChange = () => { };
|
|
175
|
-
this.optionSelectionChanges = defer(() => {
|
|
176
|
-
const options = this._options;
|
|
177
|
-
return options.changes.pipe(startWith(options), switchMap(() => merge(...options.map(option => option.selectionChange))));
|
|
178
|
-
});
|
|
179
|
-
this._disabled = false;
|
|
165
|
+
constructor() {
|
|
166
|
+
this._generatedId = `cdk-listbox-${nextId++}`;
|
|
180
167
|
this._multiple = false;
|
|
168
|
+
this._disabled = false;
|
|
181
169
|
this._useActiveDescendant = false;
|
|
182
|
-
|
|
183
|
-
this._destroyed = new Subject();
|
|
184
|
-
this.selectionChange = new EventEmitter();
|
|
185
|
-
this.id = `cdk-listbox-${listboxId++}`;
|
|
186
|
-
/** Determines the orientation for the list key manager. Affects keyboard interaction. */
|
|
170
|
+
/** The orientation of the listbox. Only affects keyboard interaction, not visual layout. */
|
|
187
171
|
this.orientation = 'vertical';
|
|
188
|
-
|
|
172
|
+
/** Emits when the selected value(s) in the listbox change. */
|
|
173
|
+
this.valueChange = new Subject();
|
|
174
|
+
// TODO(mmalerba): Refactor SelectionModel so that its not necessary to create new instances
|
|
175
|
+
/** The selection model used by the listbox. */
|
|
176
|
+
this.selectionModelSubject = new BehaviorSubject(new SelectionModel(this.multiple, [], true, this._compareWith));
|
|
177
|
+
/** Emits when the listbox is destroyed. */
|
|
178
|
+
this.destroyed = new Subject();
|
|
179
|
+
/** The host element of the listbox. */
|
|
180
|
+
this.element = inject(ElementRef).nativeElement;
|
|
181
|
+
/** The change detector for this listbox. */
|
|
182
|
+
this.changeDetectorRef = inject(ChangeDetectorRef);
|
|
183
|
+
/** Callback called when the listbox has been touched */
|
|
184
|
+
this._onTouched = () => { };
|
|
185
|
+
/** Callback called when the listbox value changes */
|
|
186
|
+
this._onChange = () => { };
|
|
187
|
+
/** Callback called when the form validator changes. */
|
|
188
|
+
this._onValidatorChange = () => { };
|
|
189
|
+
/** Emits when an option has been clicked. */
|
|
190
|
+
this._optionClicked = defer(() => this.options.changes.pipe(startWith(this.options), switchMap(options => merge(...options.map(option => option._clicked.pipe(mapTo(option)))))));
|
|
191
|
+
/** The directionality of the page. */
|
|
192
|
+
this._dir = inject(Directionality, InjectFlags.Optional);
|
|
193
|
+
// TODO(mmalerba): Should not depend on combobox
|
|
194
|
+
this._combobox = inject(CdkCombobox, InjectFlags.Optional);
|
|
195
|
+
/**
|
|
196
|
+
* Validator that produces an error if multiple values are selected in a single selection
|
|
197
|
+
* listbox.
|
|
198
|
+
* @param control The control to validate
|
|
199
|
+
* @return A validation error or null
|
|
200
|
+
*/
|
|
201
|
+
this._validateMultipleValues = (control) => {
|
|
202
|
+
const controlValue = this._coerceValue(control.value);
|
|
203
|
+
if (!this.multiple && controlValue.length > 1) {
|
|
204
|
+
return { 'cdkListboxMultipleValues': true };
|
|
205
|
+
}
|
|
206
|
+
return null;
|
|
207
|
+
};
|
|
208
|
+
/**
|
|
209
|
+
* Validator that produces an error if any selected values are not valid options for this listbox.
|
|
210
|
+
* @param control The control to validate
|
|
211
|
+
* @return A validation error or null
|
|
212
|
+
*/
|
|
213
|
+
this._validateInvalidValues = (control) => {
|
|
214
|
+
const controlValue = this._coerceValue(control.value);
|
|
215
|
+
const invalidValues = this._getValuesWithValidity(controlValue, false);
|
|
216
|
+
if (invalidValues.length) {
|
|
217
|
+
return { 'cdkListboxInvalidValues': { 'values': invalidValues } };
|
|
218
|
+
}
|
|
219
|
+
return null;
|
|
220
|
+
};
|
|
221
|
+
/** The combined set of validators for this listbox. */
|
|
222
|
+
this._validators = Validators.compose([
|
|
223
|
+
this._validateMultipleValues,
|
|
224
|
+
this._validateInvalidValues,
|
|
225
|
+
]);
|
|
226
|
+
this.selectionModelSubject
|
|
227
|
+
.pipe(switchMap(selectionModel => selectionModel.changed), takeUntil(this.destroyed))
|
|
228
|
+
.subscribe(() => {
|
|
229
|
+
this._updateInternalValue();
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
/** The id of the option's host element. */
|
|
233
|
+
get id() {
|
|
234
|
+
return this._id || this._generatedId;
|
|
235
|
+
}
|
|
236
|
+
set id(value) {
|
|
237
|
+
this._id = value;
|
|
238
|
+
}
|
|
239
|
+
/** The tabindex to use when the listbox is enabled. */
|
|
240
|
+
get enabledTabIndex() {
|
|
241
|
+
return this._enabledTabIndex === undefined ? 0 : this._enabledTabIndex;
|
|
242
|
+
}
|
|
243
|
+
set enabledTabIndex(value) {
|
|
244
|
+
this._enabledTabIndex = value;
|
|
245
|
+
}
|
|
246
|
+
/** The value selected in the listbox, represented as an array of option values. */
|
|
247
|
+
get value() {
|
|
248
|
+
return this.selectionModel().selected;
|
|
249
|
+
}
|
|
250
|
+
set value(value) {
|
|
251
|
+
this._setSelection(value);
|
|
189
252
|
}
|
|
190
253
|
/**
|
|
191
|
-
* Whether the listbox allows multiple options to be selected.
|
|
192
|
-
*
|
|
254
|
+
* Whether the listbox allows multiple options to be selected. If the value switches from `true`
|
|
255
|
+
* to `false`, and more than one option is selected, all options are deselected.
|
|
193
256
|
*/
|
|
194
257
|
get multiple() {
|
|
195
258
|
return this._multiple;
|
|
196
259
|
}
|
|
197
260
|
set multiple(value) {
|
|
198
|
-
|
|
199
|
-
this.
|
|
200
|
-
this.
|
|
261
|
+
this._multiple = coerceBooleanProperty(value);
|
|
262
|
+
this._updateSelectionModel();
|
|
263
|
+
this._onValidatorChange();
|
|
201
264
|
}
|
|
265
|
+
/** Whether the listbox is disabled. */
|
|
202
266
|
get disabled() {
|
|
203
267
|
return this._disabled;
|
|
204
268
|
}
|
|
@@ -212,226 +276,400 @@ class CdkListbox {
|
|
|
212
276
|
set useActiveDescendant(shouldUseActiveDescendant) {
|
|
213
277
|
this._useActiveDescendant = coerceBooleanProperty(shouldUseActiveDescendant);
|
|
214
278
|
}
|
|
215
|
-
/**
|
|
216
|
-
get
|
|
217
|
-
return this.
|
|
279
|
+
/** The function used to compare option values. */
|
|
280
|
+
get compareWith() {
|
|
281
|
+
return this._compareWith;
|
|
218
282
|
}
|
|
219
|
-
set
|
|
220
|
-
this.
|
|
221
|
-
|
|
222
|
-
ngOnInit() {
|
|
223
|
-
this._selectionModel = new SelectionModel(this.multiple);
|
|
283
|
+
set compareWith(fn) {
|
|
284
|
+
this._compareWith = fn;
|
|
285
|
+
this._updateSelectionModel();
|
|
224
286
|
}
|
|
225
287
|
ngAfterContentInit() {
|
|
288
|
+
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
289
|
+
this._verifyNoOptionValueCollisions();
|
|
290
|
+
}
|
|
226
291
|
this._initKeyManager();
|
|
227
|
-
this._initSelectionModel();
|
|
228
292
|
this._combobox?._registerContent(this.id, 'listbox');
|
|
229
|
-
this.
|
|
230
|
-
this.
|
|
231
|
-
this.
|
|
232
|
-
this.setActiveOption(event.source);
|
|
233
|
-
this._updatePanelForSelection(event.source);
|
|
293
|
+
this.options.changes.pipe(takeUntil(this.destroyed)).subscribe(() => {
|
|
294
|
+
this._updateInternalValue();
|
|
295
|
+
this._onValidatorChange();
|
|
234
296
|
});
|
|
297
|
+
this._optionClicked
|
|
298
|
+
.pipe(filter(option => !option.disabled), takeUntil(this.destroyed))
|
|
299
|
+
.subscribe(option => this._handleOptionClicked(option));
|
|
235
300
|
}
|
|
236
301
|
ngOnDestroy() {
|
|
237
|
-
this.
|
|
238
|
-
this.
|
|
239
|
-
this.
|
|
302
|
+
this.listKeyManager.change.complete();
|
|
303
|
+
this.destroyed.next();
|
|
304
|
+
this.destroyed.complete();
|
|
240
305
|
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
306
|
+
/**
|
|
307
|
+
* Toggle the selected state of the given option.
|
|
308
|
+
* @param option The option to toggle
|
|
309
|
+
*/
|
|
310
|
+
toggle(option) {
|
|
311
|
+
this.toggleValue(option.value);
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Toggle the selected state of the given value.
|
|
315
|
+
* @param value The value to toggle
|
|
316
|
+
*/
|
|
317
|
+
toggleValue(value) {
|
|
318
|
+
this.selectionModel().toggle(value);
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Select the given option.
|
|
322
|
+
* @param option The option to select
|
|
323
|
+
*/
|
|
324
|
+
select(option) {
|
|
325
|
+
this.selectValue(option.value);
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Select the given value.
|
|
329
|
+
* @param value The value to select
|
|
330
|
+
*/
|
|
331
|
+
selectValue(value) {
|
|
332
|
+
this.selectionModel().select(value);
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Deselect the given option.
|
|
336
|
+
* @param option The option to deselect
|
|
337
|
+
*/
|
|
338
|
+
deselect(option) {
|
|
339
|
+
this.deselectValue(option.value);
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Deselect the given value.
|
|
343
|
+
* @param value The value to deselect
|
|
344
|
+
*/
|
|
345
|
+
deselectValue(value) {
|
|
346
|
+
this.selectionModel().deselect(value);
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Set the selected state of all options.
|
|
350
|
+
* @param isSelected The new selected state to set
|
|
351
|
+
*/
|
|
352
|
+
setAllSelected(isSelected) {
|
|
353
|
+
if (!isSelected) {
|
|
354
|
+
this.selectionModel().clear();
|
|
249
355
|
}
|
|
250
356
|
else {
|
|
251
|
-
this.
|
|
357
|
+
this.selectionModel().select(...this.options.toArray().map(option => option.value));
|
|
252
358
|
}
|
|
253
|
-
this._listKeyManager.change.pipe(takeUntil(this._destroyed)).subscribe(() => {
|
|
254
|
-
this._updateActiveOption();
|
|
255
|
-
});
|
|
256
359
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
360
|
+
/**
|
|
361
|
+
* Get whether the given option is selected.
|
|
362
|
+
* @param option The option to get the selected state of
|
|
363
|
+
*/
|
|
364
|
+
isSelected(option) {
|
|
365
|
+
return this.selectionModel().isSelected(option instanceof CdkOption ? option.value : option);
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Registers a callback to be invoked when the listbox's value changes from user input.
|
|
369
|
+
* @param fn The callback to register
|
|
370
|
+
* @docs-private
|
|
371
|
+
*/
|
|
372
|
+
registerOnChange(fn) {
|
|
373
|
+
this._onChange = fn;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Registers a callback to be invoked when the listbox is blurred by the user.
|
|
377
|
+
* @param fn The callback to register
|
|
378
|
+
* @docs-private
|
|
379
|
+
*/
|
|
380
|
+
registerOnTouched(fn) {
|
|
381
|
+
this._onTouched = fn;
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Sets the listbox's value.
|
|
385
|
+
* @param value The new value of the listbox
|
|
386
|
+
* @docs-private
|
|
387
|
+
*/
|
|
388
|
+
writeValue(value) {
|
|
389
|
+
this._setSelection(value);
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Sets the disabled state of the listbox.
|
|
393
|
+
* @param isDisabled The new disabled state
|
|
394
|
+
* @docs-private
|
|
395
|
+
*/
|
|
396
|
+
setDisabledState(isDisabled) {
|
|
397
|
+
this.disabled = isDisabled;
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Validate the given control
|
|
401
|
+
* @docs-private
|
|
402
|
+
*/
|
|
403
|
+
validate(control) {
|
|
404
|
+
return this._validators(control);
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Registers a callback to be called when the form validator changes.
|
|
408
|
+
* @param fn The callback to call
|
|
409
|
+
* @docs-private
|
|
410
|
+
*/
|
|
411
|
+
registerOnValidatorChange(fn) {
|
|
412
|
+
this._onValidatorChange = fn;
|
|
413
|
+
}
|
|
414
|
+
/** Focus the listbox's host element. */
|
|
415
|
+
focus() {
|
|
416
|
+
this.element.focus();
|
|
417
|
+
}
|
|
418
|
+
/** The selection model used to track the listbox's value. */
|
|
419
|
+
selectionModel() {
|
|
420
|
+
return this.selectionModelSubject.value;
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Triggers the given option in response to user interaction.
|
|
424
|
+
* - In single selection mode: selects the option and deselects any other selected option.
|
|
425
|
+
* - In multi selection mode: toggles the selected state of the option.
|
|
426
|
+
* @param option The option to trigger
|
|
427
|
+
*/
|
|
428
|
+
triggerOption(option) {
|
|
429
|
+
if (option && !option.disabled) {
|
|
430
|
+
let changed = false;
|
|
431
|
+
this.selectionModel()
|
|
432
|
+
.changed.pipe(take(1), takeUntil(this.destroyed))
|
|
433
|
+
.subscribe(() => (changed = true));
|
|
434
|
+
if (this.multiple) {
|
|
435
|
+
this.toggle(option);
|
|
263
436
|
}
|
|
264
|
-
|
|
265
|
-
option
|
|
437
|
+
else {
|
|
438
|
+
this.select(option);
|
|
266
439
|
}
|
|
267
|
-
|
|
440
|
+
if (changed) {
|
|
441
|
+
this._onChange(this.value);
|
|
442
|
+
this.valueChange.next({
|
|
443
|
+
value: this.value,
|
|
444
|
+
listbox: this,
|
|
445
|
+
option: option,
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Sets the given option as active.
|
|
452
|
+
* @param option The option to make active
|
|
453
|
+
*/
|
|
454
|
+
_setActiveOption(option) {
|
|
455
|
+
this.listKeyManager.setActiveItem(option);
|
|
268
456
|
}
|
|
269
|
-
|
|
457
|
+
/** Called when the listbox receives focus. */
|
|
458
|
+
_handleFocus() {
|
|
459
|
+
if (!this.useActiveDescendant) {
|
|
460
|
+
this.listKeyManager.setNextItemActive();
|
|
461
|
+
this._focusActiveOption();
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
/** Called when the user presses keydown on the listbox. */
|
|
465
|
+
_handleKeydown(event) {
|
|
270
466
|
if (this._disabled) {
|
|
271
467
|
return;
|
|
272
468
|
}
|
|
273
|
-
const manager = this._listKeyManager;
|
|
274
469
|
const { keyCode } = event;
|
|
275
|
-
const previousActiveIndex =
|
|
470
|
+
const previousActiveIndex = this.listKeyManager.activeItemIndex;
|
|
276
471
|
if (keyCode === SPACE || keyCode === ENTER) {
|
|
277
|
-
|
|
278
|
-
this._toggleActiveOption();
|
|
279
|
-
}
|
|
472
|
+
this.triggerOption(this.listKeyManager.activeItem);
|
|
280
473
|
event.preventDefault();
|
|
281
474
|
}
|
|
282
475
|
else {
|
|
283
|
-
|
|
476
|
+
this.listKeyManager.onKeydown(event);
|
|
284
477
|
}
|
|
285
478
|
/** Will select an option if shift was pressed while navigating to the option */
|
|
286
479
|
const isArrow = keyCode === UP_ARROW ||
|
|
287
480
|
keyCode === DOWN_ARROW ||
|
|
288
481
|
keyCode === LEFT_ARROW ||
|
|
289
482
|
keyCode === RIGHT_ARROW;
|
|
290
|
-
if (isArrow && event.shiftKey && previousActiveIndex !== this.
|
|
291
|
-
this.
|
|
483
|
+
if (isArrow && event.shiftKey && previousActiveIndex !== this.listKeyManager.activeItemIndex) {
|
|
484
|
+
this.triggerOption(this.listKeyManager.activeItem);
|
|
292
485
|
}
|
|
293
486
|
}
|
|
294
|
-
/**
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
487
|
+
/**
|
|
488
|
+
* Called when the focus leaves an element in the listbox.
|
|
489
|
+
* @param event The focusout event
|
|
490
|
+
*/
|
|
491
|
+
_handleFocusOut(event) {
|
|
492
|
+
const otherElement = event.relatedTarget;
|
|
493
|
+
if (this.element !== otherElement && !this.element.contains(otherElement)) {
|
|
494
|
+
this._onTouched();
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
/** Get the id of the active option if active descendant is being used. */
|
|
498
|
+
_getAriaActiveDescendant() {
|
|
499
|
+
return this._useActiveDescendant ? this.listKeyManager?.activeItem?.id : null;
|
|
300
500
|
}
|
|
301
|
-
/**
|
|
302
|
-
|
|
303
|
-
if (
|
|
304
|
-
|
|
305
|
-
|
|
501
|
+
/** Get the tabindex for the listbox. */
|
|
502
|
+
_getTabIndex() {
|
|
503
|
+
if (this.disabled) {
|
|
504
|
+
return -1;
|
|
505
|
+
}
|
|
506
|
+
return this.useActiveDescendant || !this.listKeyManager.activeItem ? this.enabledTabIndex : -1;
|
|
507
|
+
}
|
|
508
|
+
/** Initialize the key manager. */
|
|
509
|
+
_initKeyManager() {
|
|
510
|
+
this.listKeyManager = new ActiveDescendantKeyManager(this.options)
|
|
511
|
+
.withWrap()
|
|
512
|
+
.withTypeAhead()
|
|
513
|
+
.withHomeAndEnd()
|
|
514
|
+
.withAllowedModifierKeys(['shiftKey']);
|
|
515
|
+
if (this.orientation === 'vertical') {
|
|
516
|
+
this.listKeyManager.withVerticalOrientation();
|
|
517
|
+
}
|
|
518
|
+
else {
|
|
519
|
+
this.listKeyManager.withHorizontalOrientation(this._dir?.value || 'ltr');
|
|
306
520
|
}
|
|
307
|
-
|
|
521
|
+
this.listKeyManager.change
|
|
522
|
+
.pipe(takeUntil(this.destroyed))
|
|
523
|
+
.subscribe(() => this._focusActiveOption());
|
|
308
524
|
}
|
|
525
|
+
// TODO(mmalerba): Should not depend on combobox.
|
|
309
526
|
_updatePanelForSelection(option) {
|
|
310
527
|
if (this._combobox) {
|
|
311
528
|
if (!this.multiple) {
|
|
312
|
-
this._combobox.updateAndClose(option.
|
|
529
|
+
this._combobox.updateAndClose(option.isSelected() ? option.value : []);
|
|
313
530
|
}
|
|
314
531
|
else {
|
|
315
|
-
this._combobox.updateAndClose(this.
|
|
532
|
+
this._combobox.updateAndClose(this.value);
|
|
316
533
|
}
|
|
317
534
|
}
|
|
318
535
|
}
|
|
319
|
-
/**
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
if (activeOption && !activeOption.disabled) {
|
|
323
|
-
activeOption.toggle();
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
/** Returns the id of the active option if active descendant is being used. */
|
|
327
|
-
_getAriaActiveDescendant() {
|
|
328
|
-
return this._useActiveDescendant ? this._listKeyManager?.activeItem?.id : null;
|
|
329
|
-
}
|
|
330
|
-
/** Updates the activeOption and the active and focus properties of the option. */
|
|
331
|
-
_updateActiveOption() {
|
|
332
|
-
if (!this._listKeyManager.activeItem) {
|
|
333
|
-
return;
|
|
334
|
-
}
|
|
335
|
-
this._activeOption?.deactivate();
|
|
336
|
-
this._activeOption = this._listKeyManager.activeItem;
|
|
337
|
-
this._activeOption.activate();
|
|
338
|
-
if (!this.useActiveDescendant) {
|
|
339
|
-
this._activeOption.focus();
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
/** Updates selection states of options when the 'multiple' property changes. */
|
|
343
|
-
_updateSelectionOnMultiSelectionChange(value) {
|
|
344
|
-
if (this.multiple && !value) {
|
|
345
|
-
// Deselect all options instead of arbitrarily keeping one of the selected options.
|
|
346
|
-
this.setAllSelected(false);
|
|
347
|
-
}
|
|
348
|
-
else if (!this.multiple && value) {
|
|
349
|
-
this._selectionModel = new SelectionModel(value, this._selectionModel?.selected);
|
|
350
|
-
}
|
|
536
|
+
/** Update the selection mode when the 'multiple' property changes. */
|
|
537
|
+
_updateSelectionModel() {
|
|
538
|
+
this.selectionModelSubject.next(new SelectionModel(this.multiple, !this.multiple && this.value.length > 1 ? [] : this.value.slice(), true, this._compareWith));
|
|
351
539
|
}
|
|
540
|
+
/** Focus the active option. */
|
|
352
541
|
_focusActiveOption() {
|
|
353
|
-
if (!this.
|
|
354
|
-
|
|
355
|
-
}
|
|
356
|
-
if (this._listKeyManager.activeItem) {
|
|
357
|
-
this.setActiveOption(this._listKeyManager.activeItem);
|
|
358
|
-
}
|
|
359
|
-
else if (this._options.first) {
|
|
360
|
-
this.setActiveOption(this._options.first);
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
/** Selects the given option if the option and listbox aren't disabled. */
|
|
364
|
-
select(option) {
|
|
365
|
-
if (!this.disabled && !option.disabled) {
|
|
366
|
-
option.select();
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
/** Deselects the given option if the option and listbox aren't disabled. */
|
|
370
|
-
deselect(option) {
|
|
371
|
-
if (!this.disabled && !option.disabled) {
|
|
372
|
-
option.deselect();
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
/** Sets the selected state of all options to be the given value. */
|
|
376
|
-
setAllSelected(isSelected) {
|
|
377
|
-
for (const option of this._options.toArray()) {
|
|
378
|
-
isSelected ? this.select(option) : this.deselect(option);
|
|
542
|
+
if (!this.useActiveDescendant) {
|
|
543
|
+
this.listKeyManager.activeItem?.focus();
|
|
379
544
|
}
|
|
380
|
-
|
|
381
|
-
/** Updates the key manager's active item to the given option. */
|
|
382
|
-
setActiveOption(option) {
|
|
383
|
-
this._listKeyManager.updateActiveItem(option);
|
|
384
|
-
this._updateActiveOption();
|
|
545
|
+
this.changeDetectorRef.markForCheck();
|
|
385
546
|
}
|
|
386
547
|
/**
|
|
387
|
-
*
|
|
388
|
-
*
|
|
548
|
+
* Set the selected values.
|
|
549
|
+
* @param value The list of new selected values.
|
|
389
550
|
*/
|
|
390
|
-
|
|
391
|
-
|
|
551
|
+
_setSelection(value) {
|
|
552
|
+
const coercedValue = this._coerceValue(value);
|
|
553
|
+
this.selectionModel().setSelection(...(!this.multiple && coercedValue.length > 1
|
|
554
|
+
? []
|
|
555
|
+
: this._getValuesWithValidity(coercedValue, true)));
|
|
556
|
+
}
|
|
557
|
+
/** Update the internal value of the listbox based on the selection model. */
|
|
558
|
+
_updateInternalValue() {
|
|
559
|
+
const indexCache = new Map();
|
|
560
|
+
// Check if we need to remove any values due to them becoming invalid
|
|
561
|
+
// (e.g. if the option was removed from the DOM.)
|
|
562
|
+
const selected = this.selectionModel().selected;
|
|
563
|
+
const validSelected = this._getValuesWithValidity(selected, true);
|
|
564
|
+
if (validSelected.length != selected.length) {
|
|
565
|
+
this.selectionModel().setSelection(...validSelected);
|
|
566
|
+
}
|
|
567
|
+
this.selectionModel().sort((a, b) => {
|
|
568
|
+
const aIndex = this._getIndexForValue(indexCache, a);
|
|
569
|
+
const bIndex = this._getIndexForValue(indexCache, b);
|
|
570
|
+
return aIndex - bIndex;
|
|
571
|
+
});
|
|
572
|
+
this.changeDetectorRef.markForCheck();
|
|
392
573
|
}
|
|
393
574
|
/**
|
|
394
|
-
*
|
|
395
|
-
*
|
|
575
|
+
* Gets the index of the given value in the given list of options.
|
|
576
|
+
* @param cache The cache of indices found so far
|
|
577
|
+
* @param value The value to find
|
|
578
|
+
* @return The index of the value in the options list
|
|
396
579
|
*/
|
|
397
|
-
|
|
398
|
-
this.
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
580
|
+
_getIndexForValue(cache, value) {
|
|
581
|
+
const isEqual = this.compareWith || Object.is;
|
|
582
|
+
if (!cache.has(value)) {
|
|
583
|
+
let index = -1;
|
|
584
|
+
for (let i = 0; i < this.options.length; i++) {
|
|
585
|
+
if (isEqual(value, this.options.get(i).value)) {
|
|
586
|
+
index = i;
|
|
587
|
+
break;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
cache.set(value, index);
|
|
404
591
|
}
|
|
592
|
+
return cache.get(value);
|
|
405
593
|
}
|
|
406
|
-
/**
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
const
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
this.
|
|
426
|
-
|
|
594
|
+
/**
|
|
595
|
+
* Handle the user clicking an option.
|
|
596
|
+
* @param option The option that was clicked.
|
|
597
|
+
*/
|
|
598
|
+
_handleOptionClicked(option) {
|
|
599
|
+
this.listKeyManager.setActiveItem(option);
|
|
600
|
+
this.triggerOption(option);
|
|
601
|
+
this._updatePanelForSelection(option);
|
|
602
|
+
}
|
|
603
|
+
/** Verifies that no two options represent the same value under the compareWith function. */
|
|
604
|
+
_verifyNoOptionValueCollisions() {
|
|
605
|
+
combineLatest([
|
|
606
|
+
this.selectionModelSubject,
|
|
607
|
+
this.options.changes.pipe(startWith(this.options)),
|
|
608
|
+
]).subscribe(() => {
|
|
609
|
+
const isEqual = this.compareWith ?? Object.is;
|
|
610
|
+
for (let i = 0; i < this.options.length; i++) {
|
|
611
|
+
const option = this.options.get(i);
|
|
612
|
+
let duplicate = null;
|
|
613
|
+
for (let j = i + 1; j < this.options.length; j++) {
|
|
614
|
+
const other = this.options.get(j);
|
|
615
|
+
if (isEqual(option.value, other.value)) {
|
|
616
|
+
duplicate = other;
|
|
617
|
+
break;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
if (duplicate) {
|
|
621
|
+
// TODO(mmalerba): Link to docs about this.
|
|
622
|
+
if (this.compareWith) {
|
|
623
|
+
console.warn(`Found multiple CdkOption representing the same value under the given compareWith function`, {
|
|
624
|
+
option1: option.element,
|
|
625
|
+
option2: duplicate.element,
|
|
626
|
+
compareWith: this.compareWith,
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
else {
|
|
630
|
+
console.warn(`Found multiple CdkOption with the same value`, {
|
|
631
|
+
option1: option.element,
|
|
632
|
+
option2: duplicate.element,
|
|
633
|
+
});
|
|
634
|
+
}
|
|
427
635
|
return;
|
|
428
636
|
}
|
|
429
637
|
}
|
|
430
|
-
}
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* Coerces a value into an array representing a listbox selection.
|
|
642
|
+
* @param value The value to coerce
|
|
643
|
+
* @return An array
|
|
644
|
+
*/
|
|
645
|
+
_coerceValue(value) {
|
|
646
|
+
return value == null ? [] : coerceArray(value);
|
|
647
|
+
}
|
|
648
|
+
/**
|
|
649
|
+
* Get the sublist of values with the given validity.
|
|
650
|
+
* @param values The list of values
|
|
651
|
+
* @param valid Whether to get valid values
|
|
652
|
+
* @return The sublist of values with the requested validity
|
|
653
|
+
*/
|
|
654
|
+
_getValuesWithValidity(values, valid) {
|
|
655
|
+
const isEqual = this.compareWith || Object.is;
|
|
656
|
+
const validValues = (this.options || []).map(option => option.value);
|
|
657
|
+
return values.filter(value => valid === validValues.some(validValue => isEqual(value, validValue)));
|
|
431
658
|
}
|
|
432
659
|
}
|
|
433
|
-
CdkListbox.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: CdkListbox, deps: [
|
|
434
|
-
CdkListbox.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.1", type: CdkListbox, selector: "[cdkListbox]", inputs: { id: "id", multiple: "multiple", disabled: "disabled", useActiveDescendant: "
|
|
660
|
+
CdkListbox.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: CdkListbox, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
661
|
+
CdkListbox.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.1", type: CdkListbox, selector: "[cdkListbox]", inputs: { id: "id", enabledTabIndex: ["tabindex", "enabledTabIndex"], value: ["cdkListboxValue", "value"], multiple: ["cdkListboxMultiple", "multiple"], disabled: ["cdkListboxDisabled", "disabled"], useActiveDescendant: ["cdkListboxUseActiveDescendant", "useActiveDescendant"], orientation: ["cdkListboxOrientation", "orientation"], compareWith: ["cdkListboxCompareWith", "compareWith"] }, outputs: { valueChange: "cdkListboxValueChange" }, host: { attributes: { "role": "listbox" }, listeners: { "focus": "_handleFocus()", "keydown": "_handleKeydown($event)", "focusout": "_handleFocusOut($event)" }, properties: { "id": "id", "attr.tabindex": "_getTabIndex()", "attr.aria-disabled": "disabled", "attr.aria-multiselectable": "multiple", "attr.aria-activedescendant": "_getAriaActiveDescendant()", "attr.aria-orientation": "orientation" }, classAttribute: "cdk-listbox" }, providers: [
|
|
662
|
+
{
|
|
663
|
+
provide: NG_VALUE_ACCESSOR,
|
|
664
|
+
useExisting: forwardRef(() => CdkListbox),
|
|
665
|
+
multi: true,
|
|
666
|
+
},
|
|
667
|
+
{
|
|
668
|
+
provide: NG_VALIDATORS,
|
|
669
|
+
useExisting: forwardRef(() => CdkListbox),
|
|
670
|
+
multi: true,
|
|
671
|
+
},
|
|
672
|
+
], queries: [{ propertyName: "options", predicate: CdkOption, descendants: true }], exportAs: ["cdkListbox"], ngImport: i0 });
|
|
435
673
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: CdkListbox, decorators: [{
|
|
436
674
|
type: Directive,
|
|
437
675
|
args: [{
|
|
@@ -441,43 +679,57 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImpor
|
|
|
441
679
|
'role': 'listbox',
|
|
442
680
|
'class': 'cdk-listbox',
|
|
443
681
|
'[id]': 'id',
|
|
444
|
-
'
|
|
445
|
-
'(keydown)': '_keydown($event)',
|
|
446
|
-
'[attr.tabindex]': '_tabIndex',
|
|
682
|
+
'[attr.tabindex]': '_getTabIndex()',
|
|
447
683
|
'[attr.aria-disabled]': 'disabled',
|
|
448
684
|
'[attr.aria-multiselectable]': 'multiple',
|
|
449
685
|
'[attr.aria-activedescendant]': '_getAriaActiveDescendant()',
|
|
450
686
|
'[attr.aria-orientation]': 'orientation',
|
|
687
|
+
'(focus)': '_handleFocus()',
|
|
688
|
+
'(keydown)': '_handleKeydown($event)',
|
|
689
|
+
'(focusout)': '_handleFocusOut($event)',
|
|
451
690
|
},
|
|
452
|
-
providers: [
|
|
691
|
+
providers: [
|
|
692
|
+
{
|
|
693
|
+
provide: NG_VALUE_ACCESSOR,
|
|
694
|
+
useExisting: forwardRef(() => CdkListbox),
|
|
695
|
+
multi: true,
|
|
696
|
+
},
|
|
697
|
+
{
|
|
698
|
+
provide: NG_VALIDATORS,
|
|
699
|
+
useExisting: forwardRef(() => CdkListbox),
|
|
700
|
+
multi: true,
|
|
701
|
+
},
|
|
702
|
+
],
|
|
453
703
|
}]
|
|
454
|
-
}], ctorParameters: function () { return [
|
|
455
|
-
type: Optional
|
|
456
|
-
}, {
|
|
457
|
-
type: Inject,
|
|
458
|
-
args: [CDK_COMBOBOX]
|
|
459
|
-
}] }, { type: i1.Directionality, decorators: [{
|
|
460
|
-
type: Optional
|
|
461
|
-
}] }]; }, propDecorators: { _options: [{
|
|
462
|
-
type: ContentChildren,
|
|
463
|
-
args: [CdkOption, { descendants: true }]
|
|
464
|
-
}], selectionChange: [{
|
|
465
|
-
type: Output
|
|
466
|
-
}], id: [{
|
|
704
|
+
}], ctorParameters: function () { return []; }, propDecorators: { id: [{
|
|
467
705
|
type: Input
|
|
706
|
+
}], enabledTabIndex: [{
|
|
707
|
+
type: Input,
|
|
708
|
+
args: ['tabindex']
|
|
709
|
+
}], value: [{
|
|
710
|
+
type: Input,
|
|
711
|
+
args: ['cdkListboxValue']
|
|
468
712
|
}], multiple: [{
|
|
469
|
-
type: Input
|
|
713
|
+
type: Input,
|
|
714
|
+
args: ['cdkListboxMultiple']
|
|
470
715
|
}], disabled: [{
|
|
471
|
-
type: Input
|
|
716
|
+
type: Input,
|
|
717
|
+
args: ['cdkListboxDisabled']
|
|
472
718
|
}], useActiveDescendant: [{
|
|
473
|
-
type: Input
|
|
474
|
-
|
|
475
|
-
type: Input
|
|
719
|
+
type: Input,
|
|
720
|
+
args: ['cdkListboxUseActiveDescendant']
|
|
476
721
|
}], orientation: [{
|
|
477
722
|
type: Input,
|
|
478
|
-
args: ['
|
|
723
|
+
args: ['cdkListboxOrientation']
|
|
479
724
|
}], compareWith: [{
|
|
480
|
-
type: Input
|
|
725
|
+
type: Input,
|
|
726
|
+
args: ['cdkListboxCompareWith']
|
|
727
|
+
}], valueChange: [{
|
|
728
|
+
type: Output,
|
|
729
|
+
args: ['cdkListboxValueChange']
|
|
730
|
+
}], options: [{
|
|
731
|
+
type: ContentChildren,
|
|
732
|
+
args: [CdkOption, { descendants: true }]
|
|
481
733
|
}] } });
|
|
482
734
|
|
|
483
735
|
/**
|
|
@@ -521,5 +773,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImpor
|
|
|
521
773
|
* Generated bundle index. Do not edit.
|
|
522
774
|
*/
|
|
523
775
|
|
|
524
|
-
export {
|
|
776
|
+
export { CdkListbox, CdkListboxModule, CdkOption };
|
|
525
777
|
//# sourceMappingURL=listbox.mjs.map
|