@angular/material 21.0.0-next.9 → 21.0.0-rc.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/core/tokens/_classes.scss +1 -1
- package/core/tokens/m2/_md-sys-color.scss +17 -17
- package/fesm2022/_animation-chunk.mjs +10 -16
- package/fesm2022/_animation-chunk.mjs.map +1 -1
- package/fesm2022/_date-formats-chunk.mjs +68 -164
- package/fesm2022/_date-formats-chunk.mjs.map +1 -1
- package/fesm2022/_date-range-input-harness-chunk.mjs +284 -463
- package/fesm2022/_date-range-input-harness-chunk.mjs.map +1 -1
- package/fesm2022/_error-options-chunk.mjs +56 -19
- package/fesm2022/_error-options-chunk.mjs.map +1 -1
- package/fesm2022/_error-state-chunk.mjs +24 -31
- package/fesm2022/_error-state-chunk.mjs.map +1 -1
- package/fesm2022/_form-field-chunk.mjs +1224 -1017
- package/fesm2022/_form-field-chunk.mjs.map +1 -1
- package/fesm2022/_icon-button-chunk.mjs +243 -187
- package/fesm2022/_icon-button-chunk.mjs.map +1 -1
- package/fesm2022/_icon-registry-chunk.mjs +350 -575
- package/fesm2022/_icon-registry-chunk.mjs.map +1 -1
- package/fesm2022/_input-harness-chunk.mjs +56 -107
- package/fesm2022/_input-harness-chunk.mjs.map +1 -1
- package/fesm2022/_input-value-accessor-chunk.mjs +0 -6
- package/fesm2022/_input-value-accessor-chunk.mjs.map +1 -1
- package/fesm2022/_internal-form-field-chunk.mjs +59 -19
- package/fesm2022/_internal-form-field-chunk.mjs.map +1 -1
- package/fesm2022/_line-chunk.mjs +83 -43
- package/fesm2022/_line-chunk.mjs.map +1 -1
- package/fesm2022/_option-chunk.mjs +348 -311
- package/fesm2022/_option-chunk.mjs.map +1 -1
- package/fesm2022/_option-harness-chunk.mjs +23 -39
- package/fesm2022/_option-harness-chunk.mjs.map +1 -1
- package/fesm2022/_option-module-chunk.mjs +36 -10
- package/fesm2022/_option-module-chunk.mjs.map +1 -1
- package/fesm2022/_pseudo-checkbox-chunk.mjs +79 -44
- package/fesm2022/_pseudo-checkbox-chunk.mjs.map +1 -1
- package/fesm2022/_pseudo-checkbox-module-chunk.mjs +36 -10
- package/fesm2022/_pseudo-checkbox-module-chunk.mjs.map +1 -1
- package/fesm2022/_public-api-chunk.mjs +71 -134
- package/fesm2022/_public-api-chunk.mjs.map +1 -1
- package/fesm2022/_ripple-chunk.mjs +504 -600
- package/fesm2022/_ripple-chunk.mjs.map +1 -1
- package/fesm2022/_ripple-loader-chunk.mjs +120 -138
- package/fesm2022/_ripple-loader-chunk.mjs.map +1 -1
- package/fesm2022/_ripple-module-chunk.mjs +36 -10
- package/fesm2022/_ripple-module-chunk.mjs.map +1 -1
- package/fesm2022/_structural-styles-chunk.mjs +37 -10
- package/fesm2022/_structural-styles-chunk.mjs.map +1 -1
- package/fesm2022/_tooltip-chunk.mjs +811 -888
- package/fesm2022/_tooltip-chunk.mjs.map +1 -1
- package/fesm2022/autocomplete-testing.mjs +62 -86
- package/fesm2022/autocomplete-testing.mjs.map +1 -1
- package/fesm2022/autocomplete.mjs +965 -1126
- package/fesm2022/autocomplete.mjs.map +1 -1
- package/fesm2022/badge-testing.mjs +38 -54
- package/fesm2022/badge-testing.mjs.map +1 -1
- package/fesm2022/badge.mjs +321 -272
- package/fesm2022/badge.mjs.map +1 -1
- package/fesm2022/bottom-sheet-testing.mjs +10 -24
- package/fesm2022/bottom-sheet-testing.mjs.map +1 -1
- package/fesm2022/bottom-sheet.mjs +349 -344
- package/fesm2022/bottom-sheet.mjs.map +1 -1
- package/fesm2022/button-testing.mjs +60 -94
- package/fesm2022/button-testing.mjs.map +1 -1
- package/fesm2022/button-toggle-testing.mjs +76 -125
- package/fesm2022/button-toggle-testing.mjs.map +1 -1
- package/fesm2022/button-toggle.mjs +752 -662
- package/fesm2022/button-toggle.mjs.map +1 -1
- package/fesm2022/button.mjs +263 -158
- package/fesm2022/button.mjs.map +1 -1
- package/fesm2022/card-testing.mjs +19 -33
- package/fesm2022/card-testing.mjs.map +1 -1
- package/fesm2022/card.mjs +576 -272
- package/fesm2022/card.mjs.map +1 -1
- package/fesm2022/checkbox-testing.mjs +71 -123
- package/fesm2022/checkbox-testing.mjs.map +1 -1
- package/fesm2022/checkbox.mjs +515 -477
- package/fesm2022/checkbox.mjs.map +1 -1
- package/fesm2022/chips-testing.mjs +201 -344
- package/fesm2022/chips-testing.mjs.map +1 -1
- package/fesm2022/chips.mjs +2552 -2289
- package/fesm2022/chips.mjs.map +1 -1
- package/fesm2022/core-testing.mjs +14 -28
- package/fesm2022/core-testing.mjs.map +1 -1
- package/fesm2022/core.mjs +357 -328
- package/fesm2022/core.mjs.map +1 -1
- package/fesm2022/datepicker-testing.mjs +15 -25
- package/fesm2022/datepicker-testing.mjs.map +1 -1
- package/fesm2022/datepicker.mjs +4826 -4563
- package/fesm2022/datepicker.mjs.map +1 -1
- package/fesm2022/dialog-testing.mjs +93 -129
- package/fesm2022/dialog-testing.mjs.map +1 -1
- package/fesm2022/dialog.mjs +810 -829
- package/fesm2022/dialog.mjs.map +1 -1
- package/fesm2022/divider-testing.mjs +10 -11
- package/fesm2022/divider-testing.mjs.map +1 -1
- package/fesm2022/divider.mjs +119 -43
- package/fesm2022/divider.mjs.map +1 -1
- package/fesm2022/expansion-testing.mjs +74 -130
- package/fesm2022/expansion-testing.mjs.map +1 -1
- package/fesm2022/expansion.mjs +703 -515
- package/fesm2022/expansion.mjs.map +1 -1
- package/fesm2022/form-field-testing-control.mjs +16 -33
- package/fesm2022/form-field-testing-control.mjs.map +1 -1
- package/fesm2022/form-field-testing.mjs +118 -179
- package/fesm2022/form-field-testing.mjs.map +1 -1
- package/fesm2022/form-field.mjs +36 -10
- package/fesm2022/form-field.mjs.map +1 -1
- package/fesm2022/grid-list-testing.mjs +65 -113
- package/fesm2022/grid-list-testing.mjs.map +1 -1
- package/fesm2022/grid-list.mjs +559 -494
- package/fesm2022/grid-list.mjs.map +1 -1
- package/fesm2022/icon-testing.mjs +148 -127
- package/fesm2022/icon-testing.mjs.map +1 -1
- package/fesm2022/icon.mjs +325 -351
- package/fesm2022/icon.mjs.map +1 -1
- package/fesm2022/input-testing.mjs +59 -99
- package/fesm2022/input-testing.mjs.map +1 -1
- package/fesm2022/input.mjs +457 -520
- package/fesm2022/input.mjs.map +1 -1
- package/fesm2022/list-testing.mjs +251 -434
- package/fesm2022/list-testing.mjs.map +1 -1
- package/fesm2022/list.mjs +1522 -1204
- package/fesm2022/list.mjs.map +1 -1
- package/fesm2022/material.mjs +0 -5
- package/fesm2022/material.mjs.map +1 -1
- package/fesm2022/menu-testing.mjs +159 -228
- package/fesm2022/menu-testing.mjs.map +1 -1
- package/fesm2022/menu.mjs +1338 -1343
- package/fesm2022/menu.mjs.map +1 -1
- package/fesm2022/paginator-testing.mjs +55 -79
- package/fesm2022/paginator-testing.mjs.map +1 -1
- package/fesm2022/paginator.mjs +381 -309
- package/fesm2022/paginator.mjs.map +1 -1
- package/fesm2022/progress-bar-testing.mjs +12 -21
- package/fesm2022/progress-bar-testing.mjs.map +1 -1
- package/fesm2022/progress-bar.mjs +224 -169
- package/fesm2022/progress-bar.mjs.map +1 -1
- package/fesm2022/progress-spinner-testing.mjs +13 -23
- package/fesm2022/progress-spinner-testing.mjs.map +1 -1
- package/fesm2022/progress-spinner.mjs +235 -160
- package/fesm2022/progress-spinner.mjs.map +1 -1
- package/fesm2022/radio-testing.mjs +133 -208
- package/fesm2022/radio-testing.mjs.map +1 -1
- package/fesm2022/radio.mjs +712 -679
- package/fesm2022/radio.mjs.map +1 -1
- package/fesm2022/select-testing.mjs +83 -117
- package/fesm2022/select-testing.mjs.map +1 -1
- package/fesm2022/select.mjs +1116 -1246
- package/fesm2022/select.mjs.map +1 -1
- package/fesm2022/sidenav-testing.mjs +54 -120
- package/fesm2022/sidenav-testing.mjs.map +1 -1
- package/fesm2022/sidenav.mjs +1078 -995
- package/fesm2022/sidenav.mjs.map +1 -1
- package/fesm2022/slide-toggle-testing.mjs +57 -92
- package/fesm2022/slide-toggle-testing.mjs.map +1 -1
- package/fesm2022/slide-toggle.mjs +369 -279
- package/fesm2022/slide-toggle.mjs.map +1 -1
- package/fesm2022/slider-testing.mjs +90 -138
- package/fesm2022/slider-testing.mjs.map +1 -1
- package/fesm2022/slider.mjs +1651 -1716
- package/fesm2022/slider.mjs.map +1 -1
- package/fesm2022/snack-bar-testing.mjs +40 -87
- package/fesm2022/snack-bar-testing.mjs.map +1 -1
- package/fesm2022/snack-bar.mjs +763 -714
- package/fesm2022/snack-bar.mjs.map +1 -1
- package/fesm2022/sort-testing.mjs +45 -66
- package/fesm2022/sort-testing.mjs.map +1 -1
- package/fesm2022/sort.mjs +419 -344
- package/fesm2022/sort.mjs.map +1 -1
- package/fesm2022/stepper-testing.mjs +78 -154
- package/fesm2022/stepper-testing.mjs.map +1 -1
- package/fesm2022/stepper.mjs +790 -498
- package/fesm2022/stepper.mjs.map +1 -1
- package/fesm2022/table-testing.mjs +120 -213
- package/fesm2022/table-testing.mjs.map +1 -1
- package/fesm2022/table.mjs +1026 -684
- package/fesm2022/table.mjs.map +1 -1
- package/fesm2022/tabs-testing.mjs +125 -197
- package/fesm2022/tabs-testing.mjs.map +1 -1
- package/fesm2022/tabs.mjs +2351 -2028
- package/fesm2022/tabs.mjs.map +1 -1
- package/fesm2022/timepicker-testing.mjs +113 -172
- package/fesm2022/timepicker-testing.mjs.map +1 -1
- package/fesm2022/timepicker.mjs +1019 -826
- package/fesm2022/timepicker.mjs.map +1 -1
- package/fesm2022/toolbar-testing.mjs +16 -27
- package/fesm2022/toolbar-testing.mjs.map +1 -1
- package/fesm2022/toolbar.mjs +163 -78
- package/fesm2022/toolbar.mjs.map +1 -1
- package/fesm2022/tooltip-testing.mjs +41 -52
- package/fesm2022/tooltip-testing.mjs.map +1 -1
- package/fesm2022/tooltip.mjs +36 -10
- package/fesm2022/tooltip.mjs.map +1 -1
- package/fesm2022/tree-testing.mjs +86 -162
- package/fesm2022/tree-testing.mjs.map +1 -1
- package/fesm2022/tree.mjs +638 -466
- package/fesm2022/tree.mjs.map +1 -1
- package/package.json +2 -2
- package/schematics/ng-add/index.js +1 -1
- package/types/expansion.d.ts +4 -2
- package/types/menu-testing.d.ts +2 -0
- package/types/select.d.ts +1 -1
- package/types/timepicker.d.ts +1 -0
package/fesm2022/select.mjs
CHANGED
|
@@ -11,6 +11,7 @@ import { Directionality, BidiModule } from '@angular/cdk/bidi';
|
|
|
11
11
|
import { SelectionModel } from '@angular/cdk/collections';
|
|
12
12
|
import { hasModifierKey, ENTER, SPACE, A, ESCAPE, DOWN_ARROW, UP_ARROW, LEFT_ARROW, RIGHT_ARROW } from '@angular/cdk/keycodes';
|
|
13
13
|
import { NgControl, Validators, NgForm, FormGroupDirective } from '@angular/forms';
|
|
14
|
+
import { _getEventTarget } from '@angular/cdk/platform';
|
|
14
15
|
import { Subject, defer, merge } from 'rxjs';
|
|
15
16
|
import { startWith, switchMap, filter, map, takeUntil, take } from 'rxjs/operators';
|
|
16
17
|
import { NgClass } from '@angular/common';
|
|
@@ -20,7 +21,6 @@ import { _ErrorStateTracker } from './_error-state-chunk.mjs';
|
|
|
20
21
|
import { MatOptionModule } from './_option-module-chunk.mjs';
|
|
21
22
|
import { MatFormFieldModule } from './form-field.mjs';
|
|
22
23
|
import './_ripple-chunk.mjs';
|
|
23
|
-
import '@angular/cdk/platform';
|
|
24
24
|
import '@angular/cdk/coercion';
|
|
25
25
|
import '@angular/cdk/private';
|
|
26
26
|
import './_pseudo-checkbox-chunk.mjs';
|
|
@@ -31,1281 +31,1151 @@ import './_ripple-module-chunk.mjs';
|
|
|
31
31
|
import './_pseudo-checkbox-module-chunk.mjs';
|
|
32
32
|
import '@angular/cdk/observers';
|
|
33
33
|
|
|
34
|
-
// Note that these have been copied over verbatim from
|
|
35
|
-
// `material/select` so that we don't have to expose them publicly.
|
|
36
|
-
/**
|
|
37
|
-
* Returns an exception to be thrown when attempting to change a select's `multiple` option
|
|
38
|
-
* after initialization.
|
|
39
|
-
* @docs-private
|
|
40
|
-
*/
|
|
41
34
|
function getMatSelectDynamicMultipleError() {
|
|
42
|
-
|
|
35
|
+
return Error('Cannot change `multiple` mode of select after initialization.');
|
|
43
36
|
}
|
|
44
|
-
/**
|
|
45
|
-
* Returns an exception to be thrown when attempting to assign a non-array value to a select
|
|
46
|
-
* in `multiple` mode. Note that `undefined` and `null` are still valid values to allow for
|
|
47
|
-
* resetting the value.
|
|
48
|
-
* @docs-private
|
|
49
|
-
*/
|
|
50
37
|
function getMatSelectNonArrayValueError() {
|
|
51
|
-
|
|
38
|
+
return Error('Value must be an array in multiple-selection mode.');
|
|
52
39
|
}
|
|
53
|
-
/**
|
|
54
|
-
* Returns an exception to be thrown when assigning a non-function value to the comparator
|
|
55
|
-
* used to determine if a value corresponds to an option. Note that whether the function
|
|
56
|
-
* actually takes two values and returns a boolean is not checked.
|
|
57
|
-
*/
|
|
58
40
|
function getMatSelectNonFunctionValueError() {
|
|
59
|
-
|
|
41
|
+
return Error('`compareWith` must be a function.');
|
|
60
42
|
}
|
|
61
43
|
|
|
62
|
-
/** Injection token that determines the scroll handling while a select is open. */
|
|
63
44
|
const MAT_SELECT_SCROLL_STRATEGY = new InjectionToken('mat-select-scroll-strategy', {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
45
|
+
providedIn: 'root',
|
|
46
|
+
factory: () => {
|
|
47
|
+
const injector = inject(Injector);
|
|
48
|
+
return () => createRepositionScrollStrategy(injector);
|
|
49
|
+
}
|
|
69
50
|
});
|
|
70
|
-
/** Injection token that can be used to provide the default options the select module. */
|
|
71
51
|
const MAT_SELECT_CONFIG = new InjectionToken('MAT_SELECT_CONFIG');
|
|
72
|
-
/**
|
|
73
|
-
* Injection token that can be used to reference instances of `MatSelectTrigger`. It serves as
|
|
74
|
-
* alternative token to the actual `MatSelectTrigger` class which could cause unnecessary
|
|
75
|
-
* retention of the class and its directive metadata.
|
|
76
|
-
*/
|
|
77
52
|
const MAT_SELECT_TRIGGER = new InjectionToken('MatSelectTrigger');
|
|
78
|
-
/** Change event object that is emitted when the select value has changed. */
|
|
79
53
|
class MatSelectChange {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
value) {
|
|
87
|
-
this.source = source;
|
|
88
|
-
this.value = value;
|
|
89
|
-
}
|
|
54
|
+
source;
|
|
55
|
+
value;
|
|
56
|
+
constructor(source, value) {
|
|
57
|
+
this.source = source;
|
|
58
|
+
this.value = value;
|
|
59
|
+
}
|
|
90
60
|
}
|
|
91
61
|
class MatSelect {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
return this._compareWith;
|
|
299
|
-
}
|
|
300
|
-
set compareWith(fn) {
|
|
301
|
-
if (typeof fn !== 'function' && (typeof ngDevMode === 'undefined' || ngDevMode)) {
|
|
302
|
-
throw getMatSelectNonFunctionValueError();
|
|
303
|
-
}
|
|
304
|
-
this._compareWith = fn;
|
|
305
|
-
if (this._selectionModel) {
|
|
306
|
-
// A different comparator means the selection could change.
|
|
307
|
-
this._initializeSelection();
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
/** Value of the select control. */
|
|
311
|
-
get value() {
|
|
312
|
-
return this._value;
|
|
313
|
-
}
|
|
314
|
-
set value(newValue) {
|
|
315
|
-
const hasAssigned = this._assignValue(newValue);
|
|
316
|
-
if (hasAssigned) {
|
|
317
|
-
this._onChange(newValue);
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
_value;
|
|
321
|
-
/** Aria label of the select. */
|
|
322
|
-
ariaLabel = '';
|
|
323
|
-
/** Input that can be used to specify the `aria-labelledby` attribute. */
|
|
324
|
-
ariaLabelledby;
|
|
325
|
-
/** Object used to control when error messages are shown. */
|
|
326
|
-
get errorStateMatcher() {
|
|
327
|
-
return this._errorStateTracker.matcher;
|
|
328
|
-
}
|
|
329
|
-
set errorStateMatcher(value) {
|
|
330
|
-
this._errorStateTracker.matcher = value;
|
|
331
|
-
}
|
|
332
|
-
/** Time to wait in milliseconds after the last keystroke before moving focus to an item. */
|
|
333
|
-
typeaheadDebounceInterval;
|
|
334
|
-
/**
|
|
335
|
-
* Function used to sort the values in a select in multiple mode.
|
|
336
|
-
* Follows the same logic as `Array.prototype.sort`.
|
|
337
|
-
*/
|
|
338
|
-
sortComparator;
|
|
339
|
-
/** Unique id of the element. */
|
|
340
|
-
get id() {
|
|
341
|
-
return this._id;
|
|
342
|
-
}
|
|
343
|
-
set id(value) {
|
|
344
|
-
this._id = value || this._uid;
|
|
345
|
-
this.stateChanges.next();
|
|
346
|
-
}
|
|
347
|
-
_id;
|
|
348
|
-
/** Whether the select is in an error state. */
|
|
349
|
-
get errorState() {
|
|
350
|
-
return this._errorStateTracker.errorState;
|
|
351
|
-
}
|
|
352
|
-
set errorState(value) {
|
|
353
|
-
this._errorStateTracker.errorState = value;
|
|
354
|
-
}
|
|
355
|
-
/**
|
|
356
|
-
* Width of the panel. If set to `auto`, the panel will match the trigger width.
|
|
357
|
-
* If set to null or an empty string, the panel will grow to match the longest option's text.
|
|
358
|
-
*/
|
|
359
|
-
panelWidth = this._defaultOptions && typeof this._defaultOptions.panelWidth !== 'undefined'
|
|
360
|
-
? this._defaultOptions.panelWidth
|
|
361
|
-
: 'auto';
|
|
362
|
-
/**
|
|
363
|
-
* By default selecting an option with a `null` or `undefined` value will reset the select's
|
|
364
|
-
* value. Enable this option if the reset behavior doesn't match your requirements and instead
|
|
365
|
-
* the nullable options should become selected. The value of this input can be controlled app-wide
|
|
366
|
-
* using the `MAT_SELECT_CONFIG` injection token.
|
|
367
|
-
*/
|
|
368
|
-
canSelectNullableOptions = this._defaultOptions?.canSelectNullableOptions ?? false;
|
|
369
|
-
/** Combined stream of all of the child options' change events. */
|
|
370
|
-
optionSelectionChanges = defer(() => {
|
|
371
|
-
const options = this.options;
|
|
372
|
-
if (options) {
|
|
373
|
-
return options.changes.pipe(startWith(options), switchMap(() => merge(...options.map(option => option.onSelectionChange))));
|
|
374
|
-
}
|
|
375
|
-
return this._initialized.pipe(switchMap(() => this.optionSelectionChanges));
|
|
62
|
+
_viewportRuler = inject(ViewportRuler);
|
|
63
|
+
_changeDetectorRef = inject(ChangeDetectorRef);
|
|
64
|
+
_elementRef = inject(ElementRef);
|
|
65
|
+
_dir = inject(Directionality, {
|
|
66
|
+
optional: true
|
|
67
|
+
});
|
|
68
|
+
_idGenerator = inject(_IdGenerator);
|
|
69
|
+
_renderer = inject(Renderer2);
|
|
70
|
+
_parentFormField = inject(MAT_FORM_FIELD, {
|
|
71
|
+
optional: true
|
|
72
|
+
});
|
|
73
|
+
ngControl = inject(NgControl, {
|
|
74
|
+
self: true,
|
|
75
|
+
optional: true
|
|
76
|
+
});
|
|
77
|
+
_liveAnnouncer = inject(LiveAnnouncer);
|
|
78
|
+
_defaultOptions = inject(MAT_SELECT_CONFIG, {
|
|
79
|
+
optional: true
|
|
80
|
+
});
|
|
81
|
+
_animationsDisabled = _animationsDisabled();
|
|
82
|
+
_initialized = new Subject();
|
|
83
|
+
_cleanupDetach;
|
|
84
|
+
options;
|
|
85
|
+
optionGroups;
|
|
86
|
+
customTrigger;
|
|
87
|
+
_positions = [{
|
|
88
|
+
originX: 'start',
|
|
89
|
+
originY: 'bottom',
|
|
90
|
+
overlayX: 'start',
|
|
91
|
+
overlayY: 'top'
|
|
92
|
+
}, {
|
|
93
|
+
originX: 'end',
|
|
94
|
+
originY: 'bottom',
|
|
95
|
+
overlayX: 'end',
|
|
96
|
+
overlayY: 'top'
|
|
97
|
+
}, {
|
|
98
|
+
originX: 'start',
|
|
99
|
+
originY: 'top',
|
|
100
|
+
overlayX: 'start',
|
|
101
|
+
overlayY: 'bottom',
|
|
102
|
+
panelClass: 'mat-mdc-select-panel-above'
|
|
103
|
+
}, {
|
|
104
|
+
originX: 'end',
|
|
105
|
+
originY: 'top',
|
|
106
|
+
overlayX: 'end',
|
|
107
|
+
overlayY: 'bottom',
|
|
108
|
+
panelClass: 'mat-mdc-select-panel-above'
|
|
109
|
+
}];
|
|
110
|
+
_scrollOptionIntoView(index) {
|
|
111
|
+
const option = this.options.toArray()[index];
|
|
112
|
+
if (option) {
|
|
113
|
+
const panel = this.panel.nativeElement;
|
|
114
|
+
const labelCount = _countGroupLabelsBeforeOption(index, this.options, this.optionGroups);
|
|
115
|
+
const element = option._getHostElement();
|
|
116
|
+
if (index === 0 && labelCount === 1) {
|
|
117
|
+
panel.scrollTop = 0;
|
|
118
|
+
} else {
|
|
119
|
+
panel.scrollTop = _getOptionScrollPosition(element.offsetTop, element.offsetHeight, panel.scrollTop, panel.offsetHeight);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
_positioningSettled() {
|
|
124
|
+
this._scrollOptionIntoView(this._keyManager.activeItemIndex || 0);
|
|
125
|
+
}
|
|
126
|
+
_getChangeEvent(value) {
|
|
127
|
+
return new MatSelectChange(this, value);
|
|
128
|
+
}
|
|
129
|
+
_scrollStrategyFactory = inject(MAT_SELECT_SCROLL_STRATEGY);
|
|
130
|
+
_panelOpen = false;
|
|
131
|
+
_compareWith = (o1, o2) => o1 === o2;
|
|
132
|
+
_uid = this._idGenerator.getId('mat-select-');
|
|
133
|
+
_triggerAriaLabelledBy = null;
|
|
134
|
+
_previousControl;
|
|
135
|
+
_destroy = new Subject();
|
|
136
|
+
_errorStateTracker;
|
|
137
|
+
stateChanges = new Subject();
|
|
138
|
+
disableAutomaticLabeling = true;
|
|
139
|
+
userAriaDescribedBy;
|
|
140
|
+
_selectionModel;
|
|
141
|
+
_keyManager;
|
|
142
|
+
_preferredOverlayOrigin;
|
|
143
|
+
_overlayWidth;
|
|
144
|
+
_onChange = () => {};
|
|
145
|
+
_onTouched = () => {};
|
|
146
|
+
_valueId = this._idGenerator.getId('mat-select-value-');
|
|
147
|
+
_scrollStrategy;
|
|
148
|
+
_overlayPanelClass = this._defaultOptions?.overlayPanelClass || '';
|
|
149
|
+
get focused() {
|
|
150
|
+
return this._focused || this._panelOpen;
|
|
151
|
+
}
|
|
152
|
+
_focused = false;
|
|
153
|
+
controlType = 'mat-select';
|
|
154
|
+
trigger;
|
|
155
|
+
panel;
|
|
156
|
+
_overlayDir;
|
|
157
|
+
panelClass;
|
|
158
|
+
disabled = false;
|
|
159
|
+
get disableRipple() {
|
|
160
|
+
return this._disableRipple();
|
|
161
|
+
}
|
|
162
|
+
set disableRipple(value) {
|
|
163
|
+
this._disableRipple.set(value);
|
|
164
|
+
}
|
|
165
|
+
_disableRipple = signal(false, ...(ngDevMode ? [{
|
|
166
|
+
debugName: "_disableRipple"
|
|
167
|
+
}] : []));
|
|
168
|
+
tabIndex = 0;
|
|
169
|
+
get hideSingleSelectionIndicator() {
|
|
170
|
+
return this._hideSingleSelectionIndicator;
|
|
171
|
+
}
|
|
172
|
+
set hideSingleSelectionIndicator(value) {
|
|
173
|
+
this._hideSingleSelectionIndicator = value;
|
|
174
|
+
this._syncParentProperties();
|
|
175
|
+
}
|
|
176
|
+
_hideSingleSelectionIndicator = this._defaultOptions?.hideSingleSelectionIndicator ?? false;
|
|
177
|
+
get placeholder() {
|
|
178
|
+
return this._placeholder;
|
|
179
|
+
}
|
|
180
|
+
set placeholder(value) {
|
|
181
|
+
this._placeholder = value;
|
|
182
|
+
this.stateChanges.next();
|
|
183
|
+
}
|
|
184
|
+
_placeholder;
|
|
185
|
+
get required() {
|
|
186
|
+
return this._required ?? this.ngControl?.control?.hasValidator(Validators.required) ?? false;
|
|
187
|
+
}
|
|
188
|
+
set required(value) {
|
|
189
|
+
this._required = value;
|
|
190
|
+
this.stateChanges.next();
|
|
191
|
+
}
|
|
192
|
+
_required;
|
|
193
|
+
get multiple() {
|
|
194
|
+
return this._multiple;
|
|
195
|
+
}
|
|
196
|
+
set multiple(value) {
|
|
197
|
+
if (this._selectionModel && (typeof ngDevMode === 'undefined' || ngDevMode)) {
|
|
198
|
+
throw getMatSelectDynamicMultipleError();
|
|
199
|
+
}
|
|
200
|
+
this._multiple = value;
|
|
201
|
+
}
|
|
202
|
+
_multiple = false;
|
|
203
|
+
disableOptionCentering = this._defaultOptions?.disableOptionCentering ?? false;
|
|
204
|
+
get compareWith() {
|
|
205
|
+
return this._compareWith;
|
|
206
|
+
}
|
|
207
|
+
set compareWith(fn) {
|
|
208
|
+
if (typeof fn !== 'function' && (typeof ngDevMode === 'undefined' || ngDevMode)) {
|
|
209
|
+
throw getMatSelectNonFunctionValueError();
|
|
210
|
+
}
|
|
211
|
+
this._compareWith = fn;
|
|
212
|
+
if (this._selectionModel) {
|
|
213
|
+
this._initializeSelection();
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
get value() {
|
|
217
|
+
return this._value;
|
|
218
|
+
}
|
|
219
|
+
set value(newValue) {
|
|
220
|
+
const hasAssigned = this._assignValue(newValue);
|
|
221
|
+
if (hasAssigned) {
|
|
222
|
+
this._onChange(newValue);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
_value;
|
|
226
|
+
ariaLabel = '';
|
|
227
|
+
ariaLabelledby;
|
|
228
|
+
get errorStateMatcher() {
|
|
229
|
+
return this._errorStateTracker.matcher;
|
|
230
|
+
}
|
|
231
|
+
set errorStateMatcher(value) {
|
|
232
|
+
this._errorStateTracker.matcher = value;
|
|
233
|
+
}
|
|
234
|
+
typeaheadDebounceInterval;
|
|
235
|
+
sortComparator;
|
|
236
|
+
get id() {
|
|
237
|
+
return this._id;
|
|
238
|
+
}
|
|
239
|
+
set id(value) {
|
|
240
|
+
this._id = value || this._uid;
|
|
241
|
+
this.stateChanges.next();
|
|
242
|
+
}
|
|
243
|
+
_id;
|
|
244
|
+
get errorState() {
|
|
245
|
+
return this._errorStateTracker.errorState;
|
|
246
|
+
}
|
|
247
|
+
set errorState(value) {
|
|
248
|
+
this._errorStateTracker.errorState = value;
|
|
249
|
+
}
|
|
250
|
+
panelWidth = this._defaultOptions && typeof this._defaultOptions.panelWidth !== 'undefined' ? this._defaultOptions.panelWidth : 'auto';
|
|
251
|
+
canSelectNullableOptions = this._defaultOptions?.canSelectNullableOptions ?? false;
|
|
252
|
+
optionSelectionChanges = defer(() => {
|
|
253
|
+
const options = this.options;
|
|
254
|
+
if (options) {
|
|
255
|
+
return options.changes.pipe(startWith(options), switchMap(() => merge(...options.map(option => option.onSelectionChange))));
|
|
256
|
+
}
|
|
257
|
+
return this._initialized.pipe(switchMap(() => this.optionSelectionChanges));
|
|
258
|
+
});
|
|
259
|
+
openedChange = new EventEmitter();
|
|
260
|
+
_openedStream = this.openedChange.pipe(filter(o => o), map(() => {}));
|
|
261
|
+
_closedStream = this.openedChange.pipe(filter(o => !o), map(() => {}));
|
|
262
|
+
selectionChange = new EventEmitter();
|
|
263
|
+
valueChange = new EventEmitter();
|
|
264
|
+
constructor() {
|
|
265
|
+
const defaultErrorStateMatcher = inject(ErrorStateMatcher);
|
|
266
|
+
const parentForm = inject(NgForm, {
|
|
267
|
+
optional: true
|
|
376
268
|
});
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
this.ngControl.valueAccessor = this;
|
|
400
|
-
}
|
|
401
|
-
// Note that we only want to set this when the defaults pass it in, otherwise it should
|
|
402
|
-
// stay as `undefined` so that it falls back to the default in the key manager.
|
|
403
|
-
if (this._defaultOptions?.typeaheadDebounceInterval != null) {
|
|
404
|
-
this.typeaheadDebounceInterval = this._defaultOptions.typeaheadDebounceInterval;
|
|
405
|
-
}
|
|
406
|
-
this._errorStateTracker = new _ErrorStateTracker(defaultErrorStateMatcher, this.ngControl, parentFormGroup, parentForm, this.stateChanges);
|
|
407
|
-
this._scrollStrategy = this._scrollStrategyFactory();
|
|
408
|
-
this.tabIndex = tabIndex == null ? 0 : parseInt(tabIndex) || 0;
|
|
409
|
-
// Force setter to be called in case id was not specified.
|
|
410
|
-
this.id = this.id;
|
|
411
|
-
}
|
|
412
|
-
ngOnInit() {
|
|
413
|
-
this._selectionModel = new SelectionModel(this.multiple);
|
|
414
|
-
this.stateChanges.next();
|
|
415
|
-
this._viewportRuler
|
|
416
|
-
.change()
|
|
417
|
-
.pipe(takeUntil(this._destroy))
|
|
418
|
-
.subscribe(() => {
|
|
419
|
-
if (this.panelOpen) {
|
|
420
|
-
this._overlayWidth = this._getOverlayWidth(this._preferredOverlayOrigin);
|
|
421
|
-
this._changeDetectorRef.detectChanges();
|
|
422
|
-
}
|
|
423
|
-
});
|
|
424
|
-
}
|
|
425
|
-
ngAfterContentInit() {
|
|
426
|
-
this._initialized.next();
|
|
427
|
-
this._initialized.complete();
|
|
428
|
-
this._initKeyManager();
|
|
429
|
-
this._selectionModel.changed.pipe(takeUntil(this._destroy)).subscribe(event => {
|
|
430
|
-
event.added.forEach(option => option.select());
|
|
431
|
-
event.removed.forEach(option => option.deselect());
|
|
432
|
-
});
|
|
433
|
-
this.options.changes.pipe(startWith(null), takeUntil(this._destroy)).subscribe(() => {
|
|
434
|
-
this._resetOptions();
|
|
435
|
-
this._initializeSelection();
|
|
436
|
-
});
|
|
437
|
-
}
|
|
438
|
-
ngDoCheck() {
|
|
439
|
-
const newAriaLabelledby = this._getTriggerAriaLabelledby();
|
|
440
|
-
const ngControl = this.ngControl;
|
|
441
|
-
// We have to manage setting the `aria-labelledby` ourselves, because part of its value
|
|
442
|
-
// is computed as a result of a content query which can cause this binding to trigger a
|
|
443
|
-
// "changed after checked" error.
|
|
444
|
-
if (newAriaLabelledby !== this._triggerAriaLabelledBy) {
|
|
445
|
-
const element = this._elementRef.nativeElement;
|
|
446
|
-
this._triggerAriaLabelledBy = newAriaLabelledby;
|
|
447
|
-
if (newAriaLabelledby) {
|
|
448
|
-
element.setAttribute('aria-labelledby', newAriaLabelledby);
|
|
449
|
-
}
|
|
450
|
-
else {
|
|
451
|
-
element.removeAttribute('aria-labelledby');
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
if (ngControl) {
|
|
455
|
-
// The disabled state might go out of sync if the form group is swapped out. See #17860.
|
|
456
|
-
if (this._previousControl !== ngControl.control) {
|
|
457
|
-
if (this._previousControl !== undefined &&
|
|
458
|
-
ngControl.disabled !== null &&
|
|
459
|
-
ngControl.disabled !== this.disabled) {
|
|
460
|
-
this.disabled = ngControl.disabled;
|
|
461
|
-
}
|
|
462
|
-
this._previousControl = ngControl.control;
|
|
463
|
-
}
|
|
464
|
-
this.updateErrorState();
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
ngOnChanges(changes) {
|
|
468
|
-
// Updating the disabled state is handled by the input, but we need to additionally let
|
|
469
|
-
// the parent form field know to run change detection when the disabled state changes.
|
|
470
|
-
if (changes['disabled'] || changes['userAriaDescribedBy']) {
|
|
471
|
-
this.stateChanges.next();
|
|
472
|
-
}
|
|
473
|
-
if (changes['typeaheadDebounceInterval'] && this._keyManager) {
|
|
474
|
-
this._keyManager.withTypeAhead(this.typeaheadDebounceInterval);
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
ngOnDestroy() {
|
|
478
|
-
this._cleanupDetach?.();
|
|
479
|
-
this._keyManager?.destroy();
|
|
480
|
-
this._destroy.next();
|
|
481
|
-
this._destroy.complete();
|
|
482
|
-
this.stateChanges.complete();
|
|
483
|
-
this._clearFromModal();
|
|
484
|
-
}
|
|
485
|
-
/** Toggles the overlay panel open or closed. */
|
|
486
|
-
toggle() {
|
|
487
|
-
this.panelOpen ? this.close() : this.open();
|
|
488
|
-
}
|
|
489
|
-
/** Opens the overlay panel. */
|
|
490
|
-
open() {
|
|
491
|
-
if (!this._canOpen()) {
|
|
492
|
-
return;
|
|
493
|
-
}
|
|
494
|
-
// It's important that we read this as late as possible, because doing so earlier will
|
|
495
|
-
// return a different element since it's based on queries in the form field which may
|
|
496
|
-
// not have run yet. Also this needs to be assigned before we measure the overlay width.
|
|
497
|
-
if (this._parentFormField) {
|
|
498
|
-
this._preferredOverlayOrigin = this._parentFormField.getConnectedOverlayOrigin();
|
|
499
|
-
}
|
|
500
|
-
this._cleanupDetach?.();
|
|
269
|
+
const parentFormGroup = inject(FormGroupDirective, {
|
|
270
|
+
optional: true
|
|
271
|
+
});
|
|
272
|
+
const tabIndex = inject(new HostAttributeToken('tabindex'), {
|
|
273
|
+
optional: true
|
|
274
|
+
});
|
|
275
|
+
if (this.ngControl) {
|
|
276
|
+
this.ngControl.valueAccessor = this;
|
|
277
|
+
}
|
|
278
|
+
if (this._defaultOptions?.typeaheadDebounceInterval != null) {
|
|
279
|
+
this.typeaheadDebounceInterval = this._defaultOptions.typeaheadDebounceInterval;
|
|
280
|
+
}
|
|
281
|
+
this._errorStateTracker = new _ErrorStateTracker(defaultErrorStateMatcher, this.ngControl, parentFormGroup, parentForm, this.stateChanges);
|
|
282
|
+
this._scrollStrategy = this._scrollStrategyFactory();
|
|
283
|
+
this.tabIndex = tabIndex == null ? 0 : parseInt(tabIndex) || 0;
|
|
284
|
+
this.id = this.id;
|
|
285
|
+
}
|
|
286
|
+
ngOnInit() {
|
|
287
|
+
this._selectionModel = new SelectionModel(this.multiple);
|
|
288
|
+
this.stateChanges.next();
|
|
289
|
+
this._viewportRuler.change().pipe(takeUntil(this._destroy)).subscribe(() => {
|
|
290
|
+
if (this.panelOpen) {
|
|
501
291
|
this._overlayWidth = this._getOverlayWidth(this._preferredOverlayOrigin);
|
|
502
|
-
this.
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
* We can work around this issue by applying `aria-owns` to the modal with the `id` of
|
|
536
|
-
* the options panel. This effectively communicates to assistive technology that the
|
|
537
|
-
* options panel is part of the same interaction as the modal.
|
|
538
|
-
*
|
|
539
|
-
* At time of this writing, this issue is present in VoiceOver.
|
|
540
|
-
* See https://github.com/angular/components/issues/20694
|
|
541
|
-
*/
|
|
542
|
-
_applyModalPanelOwnership() {
|
|
543
|
-
// TODO(http://github.com/angular/components/issues/26853): consider de-duplicating this with
|
|
544
|
-
// the `LiveAnnouncer` and any other usages.
|
|
545
|
-
//
|
|
546
|
-
// Note that the selector here is limited to CDK overlays at the moment in order to reduce the
|
|
547
|
-
// section of the DOM we need to look through. This should cover all the cases we support, but
|
|
548
|
-
// the selector can be expanded if it turns out to be too narrow.
|
|
549
|
-
const modal = this._elementRef.nativeElement.closest('body > .cdk-overlay-container [aria-modal="true"]');
|
|
550
|
-
if (!modal) {
|
|
551
|
-
// Most commonly, the autocomplete trigger is not inside a modal.
|
|
552
|
-
return;
|
|
553
|
-
}
|
|
554
|
-
const panelId = `${this.id}-panel`;
|
|
555
|
-
if (this._trackedModal) {
|
|
556
|
-
removeAriaReferencedId(this._trackedModal, 'aria-owns', panelId);
|
|
557
|
-
}
|
|
558
|
-
addAriaReferencedId(modal, 'aria-owns', panelId);
|
|
559
|
-
this._trackedModal = modal;
|
|
560
|
-
}
|
|
561
|
-
/** Clears the reference to the listbox overlay element from the modal it was added to. */
|
|
562
|
-
_clearFromModal() {
|
|
563
|
-
if (!this._trackedModal) {
|
|
564
|
-
// Most commonly, the autocomplete trigger is not used inside a modal.
|
|
565
|
-
return;
|
|
566
|
-
}
|
|
567
|
-
const panelId = `${this.id}-panel`;
|
|
568
|
-
removeAriaReferencedId(this._trackedModal, 'aria-owns', panelId);
|
|
569
|
-
this._trackedModal = null;
|
|
570
|
-
}
|
|
571
|
-
/** Closes the overlay panel and focuses the host element. */
|
|
572
|
-
close() {
|
|
573
|
-
if (this._panelOpen) {
|
|
574
|
-
this._panelOpen = false;
|
|
575
|
-
this._exitAndDetach();
|
|
576
|
-
this._keyManager.withHorizontalOrientation(this._isRtl() ? 'rtl' : 'ltr');
|
|
577
|
-
this._changeDetectorRef.markForCheck();
|
|
578
|
-
this._onTouched();
|
|
579
|
-
// Required for the MDC form field to pick up when the overlay has been closed.
|
|
580
|
-
this.stateChanges.next();
|
|
581
|
-
// Simulate the animation event before we moved away from `@angular/animations`.
|
|
582
|
-
Promise.resolve().then(() => this.openedChange.emit(false));
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
/** Triggers the exit animation and detaches the overlay at the end. */
|
|
586
|
-
_exitAndDetach() {
|
|
587
|
-
if (this._animationsDisabled || !this.panel) {
|
|
588
|
-
this._detachOverlay();
|
|
589
|
-
return;
|
|
292
|
+
this._changeDetectorRef.detectChanges();
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
ngAfterContentInit() {
|
|
297
|
+
this._initialized.next();
|
|
298
|
+
this._initialized.complete();
|
|
299
|
+
this._initKeyManager();
|
|
300
|
+
this._selectionModel.changed.pipe(takeUntil(this._destroy)).subscribe(event => {
|
|
301
|
+
event.added.forEach(option => option.select());
|
|
302
|
+
event.removed.forEach(option => option.deselect());
|
|
303
|
+
});
|
|
304
|
+
this.options.changes.pipe(startWith(null), takeUntil(this._destroy)).subscribe(() => {
|
|
305
|
+
this._resetOptions();
|
|
306
|
+
this._initializeSelection();
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
ngDoCheck() {
|
|
310
|
+
const newAriaLabelledby = this._getTriggerAriaLabelledby();
|
|
311
|
+
const ngControl = this.ngControl;
|
|
312
|
+
if (newAriaLabelledby !== this._triggerAriaLabelledBy) {
|
|
313
|
+
const element = this._elementRef.nativeElement;
|
|
314
|
+
this._triggerAriaLabelledBy = newAriaLabelledby;
|
|
315
|
+
if (newAriaLabelledby) {
|
|
316
|
+
element.setAttribute('aria-labelledby', newAriaLabelledby);
|
|
317
|
+
} else {
|
|
318
|
+
element.removeAttribute('aria-labelledby');
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
if (ngControl) {
|
|
322
|
+
if (this._previousControl !== ngControl.control) {
|
|
323
|
+
if (this._previousControl !== undefined && ngControl.disabled !== null && ngControl.disabled !== this.disabled) {
|
|
324
|
+
this.disabled = ngControl.disabled;
|
|
590
325
|
}
|
|
326
|
+
this._previousControl = ngControl.control;
|
|
327
|
+
}
|
|
328
|
+
this.updateErrorState();
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
ngOnChanges(changes) {
|
|
332
|
+
if (changes['disabled'] || changes['userAriaDescribedBy']) {
|
|
333
|
+
this.stateChanges.next();
|
|
334
|
+
}
|
|
335
|
+
if (changes['typeaheadDebounceInterval'] && this._keyManager) {
|
|
336
|
+
this._keyManager.withTypeAhead(this.typeaheadDebounceInterval);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
ngOnDestroy() {
|
|
340
|
+
this._cleanupDetach?.();
|
|
341
|
+
this._keyManager?.destroy();
|
|
342
|
+
this._destroy.next();
|
|
343
|
+
this._destroy.complete();
|
|
344
|
+
this.stateChanges.complete();
|
|
345
|
+
this._clearFromModal();
|
|
346
|
+
}
|
|
347
|
+
toggle() {
|
|
348
|
+
this.panelOpen ? this.close() : this.open();
|
|
349
|
+
}
|
|
350
|
+
open() {
|
|
351
|
+
if (!this._canOpen()) {
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
if (this._parentFormField) {
|
|
355
|
+
this._preferredOverlayOrigin = this._parentFormField.getConnectedOverlayOrigin();
|
|
356
|
+
}
|
|
357
|
+
this._cleanupDetach?.();
|
|
358
|
+
this._overlayWidth = this._getOverlayWidth(this._preferredOverlayOrigin);
|
|
359
|
+
this._applyModalPanelOwnership();
|
|
360
|
+
this._panelOpen = true;
|
|
361
|
+
this._overlayDir.positionChange.pipe(take(1)).subscribe(() => {
|
|
362
|
+
this._changeDetectorRef.detectChanges();
|
|
363
|
+
this._positioningSettled();
|
|
364
|
+
});
|
|
365
|
+
this._overlayDir.attachOverlay();
|
|
366
|
+
this._keyManager.withHorizontalOrientation(null);
|
|
367
|
+
this._highlightCorrectOption();
|
|
368
|
+
this._changeDetectorRef.markForCheck();
|
|
369
|
+
this.stateChanges.next();
|
|
370
|
+
Promise.resolve().then(() => this.openedChange.emit(true));
|
|
371
|
+
}
|
|
372
|
+
_trackedModal = null;
|
|
373
|
+
_applyModalPanelOwnership() {
|
|
374
|
+
const modal = this._elementRef.nativeElement.closest('body > .cdk-overlay-container [aria-modal="true"]');
|
|
375
|
+
if (!modal) {
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
const panelId = `${this.id}-panel`;
|
|
379
|
+
if (this._trackedModal) {
|
|
380
|
+
removeAriaReferencedId(this._trackedModal, 'aria-owns', panelId);
|
|
381
|
+
}
|
|
382
|
+
addAriaReferencedId(modal, 'aria-owns', panelId);
|
|
383
|
+
this._trackedModal = modal;
|
|
384
|
+
}
|
|
385
|
+
_clearFromModal() {
|
|
386
|
+
if (!this._trackedModal) {
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
const panelId = `${this.id}-panel`;
|
|
390
|
+
removeAriaReferencedId(this._trackedModal, 'aria-owns', panelId);
|
|
391
|
+
this._trackedModal = null;
|
|
392
|
+
}
|
|
393
|
+
close() {
|
|
394
|
+
if (this._panelOpen) {
|
|
395
|
+
this._panelOpen = false;
|
|
396
|
+
this._exitAndDetach();
|
|
397
|
+
this._keyManager.withHorizontalOrientation(this._isRtl() ? 'rtl' : 'ltr');
|
|
398
|
+
this._changeDetectorRef.markForCheck();
|
|
399
|
+
this._onTouched();
|
|
400
|
+
this.stateChanges.next();
|
|
401
|
+
Promise.resolve().then(() => this.openedChange.emit(false));
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
_exitAndDetach() {
|
|
405
|
+
if (this._animationsDisabled || !this.panel) {
|
|
406
|
+
this._detachOverlay();
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
this._cleanupDetach?.();
|
|
410
|
+
this._cleanupDetach = () => {
|
|
411
|
+
cleanupEvent();
|
|
412
|
+
clearTimeout(exitFallbackTimer);
|
|
413
|
+
this._cleanupDetach = undefined;
|
|
414
|
+
};
|
|
415
|
+
const panel = this.panel.nativeElement;
|
|
416
|
+
const cleanupEvent = this._renderer.listen(panel, 'animationend', event => {
|
|
417
|
+
if (event.animationName === '_mat-select-exit') {
|
|
591
418
|
this._cleanupDetach?.();
|
|
592
|
-
this.
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
updateErrorState() {
|
|
684
|
-
this._errorStateTracker.updateErrorState();
|
|
685
|
-
}
|
|
686
|
-
/** Whether the element is in RTL mode. */
|
|
687
|
-
_isRtl() {
|
|
688
|
-
return this._dir ? this._dir.value === 'rtl' : false;
|
|
689
|
-
}
|
|
690
|
-
/** Handles all keydown events on the select. */
|
|
691
|
-
_handleKeydown(event) {
|
|
692
|
-
if (!this.disabled) {
|
|
693
|
-
this.panelOpen ? this._handleOpenKeydown(event) : this._handleClosedKeydown(event);
|
|
694
|
-
}
|
|
695
|
-
}
|
|
696
|
-
/** Handles keyboard events while the select is closed. */
|
|
697
|
-
_handleClosedKeydown(event) {
|
|
698
|
-
const keyCode = event.keyCode;
|
|
699
|
-
const isArrowKey = keyCode === DOWN_ARROW ||
|
|
700
|
-
keyCode === UP_ARROW ||
|
|
701
|
-
keyCode === LEFT_ARROW ||
|
|
702
|
-
keyCode === RIGHT_ARROW;
|
|
703
|
-
const isOpenKey = keyCode === ENTER || keyCode === SPACE;
|
|
704
|
-
const manager = this._keyManager;
|
|
705
|
-
// Open the select on ALT + arrow key to match the native <select>
|
|
706
|
-
if ((!manager.isTyping() && isOpenKey && !hasModifierKey(event)) ||
|
|
707
|
-
((this.multiple || event.altKey) && isArrowKey)) {
|
|
708
|
-
event.preventDefault(); // prevents the page from scrolling down when pressing space
|
|
709
|
-
this.open();
|
|
710
|
-
}
|
|
711
|
-
else if (!this.multiple) {
|
|
712
|
-
const previouslySelectedOption = this.selected;
|
|
713
|
-
manager.onKeydown(event);
|
|
714
|
-
const selectedOption = this.selected;
|
|
715
|
-
// Since the value has changed, we need to announce it ourselves.
|
|
716
|
-
if (selectedOption && previouslySelectedOption !== selectedOption) {
|
|
717
|
-
// We set a duration on the live announcement, because we want the live element to be
|
|
718
|
-
// cleared after a while so that users can't navigate to it using the arrow keys.
|
|
719
|
-
this._liveAnnouncer.announce(selectedOption.viewValue, 10000);
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
}
|
|
723
|
-
/** Handles keyboard events when the selected is open. */
|
|
724
|
-
_handleOpenKeydown(event) {
|
|
725
|
-
const manager = this._keyManager;
|
|
726
|
-
const keyCode = event.keyCode;
|
|
727
|
-
const isArrowKey = keyCode === DOWN_ARROW || keyCode === UP_ARROW;
|
|
728
|
-
const isTyping = manager.isTyping();
|
|
729
|
-
if (isArrowKey && event.altKey) {
|
|
730
|
-
// Close the select on ALT + arrow key to match the native <select>
|
|
731
|
-
event.preventDefault();
|
|
732
|
-
this.close();
|
|
733
|
-
// Don't do anything in this case if the user is typing,
|
|
734
|
-
// because the typing sequence can include the space key.
|
|
735
|
-
}
|
|
736
|
-
else if (!isTyping &&
|
|
737
|
-
(keyCode === ENTER || keyCode === SPACE) &&
|
|
738
|
-
manager.activeItem &&
|
|
739
|
-
!hasModifierKey(event)) {
|
|
740
|
-
event.preventDefault();
|
|
741
|
-
manager.activeItem._selectViaInteraction();
|
|
742
|
-
}
|
|
743
|
-
else if (!isTyping && this._multiple && keyCode === A && event.ctrlKey) {
|
|
744
|
-
event.preventDefault();
|
|
745
|
-
const hasDeselectedOptions = this.options.some(opt => !opt.disabled && !opt.selected);
|
|
746
|
-
this.options.forEach(option => {
|
|
747
|
-
if (!option.disabled) {
|
|
748
|
-
hasDeselectedOptions ? option.select() : option.deselect();
|
|
749
|
-
}
|
|
750
|
-
});
|
|
751
|
-
}
|
|
752
|
-
else {
|
|
753
|
-
const previouslyFocusedIndex = manager.activeItemIndex;
|
|
754
|
-
manager.onKeydown(event);
|
|
755
|
-
if (this._multiple &&
|
|
756
|
-
isArrowKey &&
|
|
757
|
-
event.shiftKey &&
|
|
758
|
-
manager.activeItem &&
|
|
759
|
-
manager.activeItemIndex !== previouslyFocusedIndex) {
|
|
760
|
-
manager.activeItem._selectViaInteraction();
|
|
761
|
-
}
|
|
762
|
-
}
|
|
763
|
-
}
|
|
764
|
-
/** Handles keyboard events coming from the overlay. */
|
|
765
|
-
_handleOverlayKeydown(event) {
|
|
766
|
-
// TODO(crisbeto): prior to #30363 this was being handled inside the overlay directive, but we
|
|
767
|
-
// need control over the animation timing so we do it manually. We should remove the `keydown`
|
|
768
|
-
// listener from `.mat-mdc-select-panel` and handle all the events here. That may cause
|
|
769
|
-
// further test breakages so it's left for a follow-up.
|
|
770
|
-
if (event.keyCode === ESCAPE && !hasModifierKey(event)) {
|
|
771
|
-
event.preventDefault();
|
|
772
|
-
this.close();
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
_onFocus() {
|
|
776
|
-
if (!this.disabled) {
|
|
777
|
-
this._focused = true;
|
|
778
|
-
this.stateChanges.next();
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
/**
|
|
782
|
-
* Calls the touched callback only if the panel is closed. Otherwise, the trigger will
|
|
783
|
-
* "blur" to the panel when it opens, causing a false positive.
|
|
784
|
-
*/
|
|
785
|
-
_onBlur() {
|
|
786
|
-
this._focused = false;
|
|
787
|
-
this._keyManager?.cancelTypeahead();
|
|
788
|
-
if (!this.disabled && !this.panelOpen) {
|
|
789
|
-
this._onTouched();
|
|
790
|
-
this._changeDetectorRef.markForCheck();
|
|
791
|
-
this.stateChanges.next();
|
|
792
|
-
}
|
|
793
|
-
}
|
|
794
|
-
/** Returns the theme to be used on the panel. */
|
|
795
|
-
_getPanelTheme() {
|
|
796
|
-
return this._parentFormField ? `mat-${this._parentFormField.color}` : '';
|
|
797
|
-
}
|
|
798
|
-
/** Whether the select has a value. */
|
|
799
|
-
get empty() {
|
|
800
|
-
return !this._selectionModel || this._selectionModel.isEmpty();
|
|
801
|
-
}
|
|
802
|
-
_initializeSelection() {
|
|
803
|
-
// Defer setting the value in order to avoid the "Expression
|
|
804
|
-
// has changed after it was checked" errors from Angular.
|
|
805
|
-
Promise.resolve().then(() => {
|
|
806
|
-
if (this.ngControl) {
|
|
807
|
-
this._value = this.ngControl.value;
|
|
808
|
-
}
|
|
809
|
-
this._setSelectionByValue(this._value);
|
|
810
|
-
this.stateChanges.next();
|
|
811
|
-
});
|
|
812
|
-
}
|
|
813
|
-
/**
|
|
814
|
-
* Sets the selected option based on a value. If no option can be
|
|
815
|
-
* found with the designated value, the select trigger is cleared.
|
|
816
|
-
*/
|
|
817
|
-
_setSelectionByValue(value) {
|
|
818
|
-
this.options.forEach(option => option.setInactiveStyles());
|
|
819
|
-
this._selectionModel.clear();
|
|
820
|
-
if (this.multiple && value) {
|
|
821
|
-
if (!Array.isArray(value) && (typeof ngDevMode === 'undefined' || ngDevMode)) {
|
|
822
|
-
throw getMatSelectNonArrayValueError();
|
|
823
|
-
}
|
|
824
|
-
value.forEach((currentValue) => this._selectOptionByValue(currentValue));
|
|
825
|
-
this._sortValues();
|
|
826
|
-
}
|
|
827
|
-
else {
|
|
828
|
-
const correspondingOption = this._selectOptionByValue(value);
|
|
829
|
-
// Shift focus to the active item. Note that we shouldn't do this in multiple
|
|
830
|
-
// mode, because we don't know what option the user interacted with last.
|
|
831
|
-
if (correspondingOption) {
|
|
832
|
-
this._keyManager.updateActiveItem(correspondingOption);
|
|
833
|
-
}
|
|
834
|
-
else if (!this.panelOpen) {
|
|
835
|
-
// Otherwise reset the highlighted option. Note that we only want to do this while
|
|
836
|
-
// closed, because doing it while open can shift the user's focus unnecessarily.
|
|
837
|
-
this._keyManager.updateActiveItem(-1);
|
|
838
|
-
}
|
|
839
|
-
}
|
|
840
|
-
this._changeDetectorRef.markForCheck();
|
|
841
|
-
}
|
|
842
|
-
/**
|
|
843
|
-
* Finds and selects and option based on its value.
|
|
844
|
-
* @returns Option that has the corresponding value.
|
|
845
|
-
*/
|
|
846
|
-
_selectOptionByValue(value) {
|
|
847
|
-
const correspondingOption = this.options.find((option) => {
|
|
848
|
-
// Skip options that are already in the model. This allows us to handle cases
|
|
849
|
-
// where the same primitive value is selected multiple times.
|
|
850
|
-
if (this._selectionModel.isSelected(option)) {
|
|
851
|
-
return false;
|
|
852
|
-
}
|
|
853
|
-
try {
|
|
854
|
-
// Treat null as a special reset value.
|
|
855
|
-
return ((option.value != null || this.canSelectNullableOptions) &&
|
|
856
|
-
this._compareWith(option.value, value));
|
|
857
|
-
}
|
|
858
|
-
catch (error) {
|
|
859
|
-
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
860
|
-
// Notify developers of errors in their comparator.
|
|
861
|
-
console.warn(error);
|
|
862
|
-
}
|
|
863
|
-
return false;
|
|
864
|
-
}
|
|
865
|
-
});
|
|
866
|
-
if (correspondingOption) {
|
|
867
|
-
this._selectionModel.select(correspondingOption);
|
|
868
|
-
}
|
|
869
|
-
return correspondingOption;
|
|
870
|
-
}
|
|
871
|
-
/** Assigns a specific value to the select. Returns whether the value has changed. */
|
|
872
|
-
_assignValue(newValue) {
|
|
873
|
-
// Always re-assign an array, because it might have been mutated.
|
|
874
|
-
if (newValue !== this._value || (this._multiple && Array.isArray(newValue))) {
|
|
875
|
-
if (this.options) {
|
|
876
|
-
this._setSelectionByValue(newValue);
|
|
877
|
-
}
|
|
878
|
-
this._value = newValue;
|
|
879
|
-
return true;
|
|
419
|
+
this._detachOverlay();
|
|
420
|
+
}
|
|
421
|
+
});
|
|
422
|
+
const exitFallbackTimer = setTimeout(() => {
|
|
423
|
+
this._cleanupDetach?.();
|
|
424
|
+
this._detachOverlay();
|
|
425
|
+
}, 200);
|
|
426
|
+
panel.classList.add('mat-select-panel-exit');
|
|
427
|
+
}
|
|
428
|
+
_detachOverlay() {
|
|
429
|
+
this._overlayDir.detachOverlay();
|
|
430
|
+
this._changeDetectorRef.markForCheck();
|
|
431
|
+
}
|
|
432
|
+
writeValue(value) {
|
|
433
|
+
this._assignValue(value);
|
|
434
|
+
}
|
|
435
|
+
registerOnChange(fn) {
|
|
436
|
+
this._onChange = fn;
|
|
437
|
+
}
|
|
438
|
+
registerOnTouched(fn) {
|
|
439
|
+
this._onTouched = fn;
|
|
440
|
+
}
|
|
441
|
+
setDisabledState(isDisabled) {
|
|
442
|
+
this.disabled = isDisabled;
|
|
443
|
+
this._changeDetectorRef.markForCheck();
|
|
444
|
+
this.stateChanges.next();
|
|
445
|
+
}
|
|
446
|
+
get panelOpen() {
|
|
447
|
+
return this._panelOpen;
|
|
448
|
+
}
|
|
449
|
+
get selected() {
|
|
450
|
+
return this.multiple ? this._selectionModel?.selected || [] : this._selectionModel?.selected[0];
|
|
451
|
+
}
|
|
452
|
+
get triggerValue() {
|
|
453
|
+
if (this.empty) {
|
|
454
|
+
return '';
|
|
455
|
+
}
|
|
456
|
+
if (this._multiple) {
|
|
457
|
+
const selectedOptions = this._selectionModel.selected.map(option => option.viewValue);
|
|
458
|
+
if (this._isRtl()) {
|
|
459
|
+
selectedOptions.reverse();
|
|
460
|
+
}
|
|
461
|
+
return selectedOptions.join(', ');
|
|
462
|
+
}
|
|
463
|
+
return this._selectionModel.selected[0].viewValue;
|
|
464
|
+
}
|
|
465
|
+
updateErrorState() {
|
|
466
|
+
this._errorStateTracker.updateErrorState();
|
|
467
|
+
}
|
|
468
|
+
_isRtl() {
|
|
469
|
+
return this._dir ? this._dir.value === 'rtl' : false;
|
|
470
|
+
}
|
|
471
|
+
_handleKeydown(event) {
|
|
472
|
+
if (!this.disabled) {
|
|
473
|
+
this.panelOpen ? this._handleOpenKeydown(event) : this._handleClosedKeydown(event);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
_handleClosedKeydown(event) {
|
|
477
|
+
const keyCode = event.keyCode;
|
|
478
|
+
const isArrowKey = keyCode === DOWN_ARROW || keyCode === UP_ARROW || keyCode === LEFT_ARROW || keyCode === RIGHT_ARROW;
|
|
479
|
+
const isOpenKey = keyCode === ENTER || keyCode === SPACE;
|
|
480
|
+
const manager = this._keyManager;
|
|
481
|
+
if (!manager.isTyping() && isOpenKey && !hasModifierKey(event) || (this.multiple || event.altKey) && isArrowKey) {
|
|
482
|
+
event.preventDefault();
|
|
483
|
+
this.open();
|
|
484
|
+
} else if (!this.multiple) {
|
|
485
|
+
const previouslySelectedOption = this.selected;
|
|
486
|
+
manager.onKeydown(event);
|
|
487
|
+
const selectedOption = this.selected;
|
|
488
|
+
if (selectedOption && previouslySelectedOption !== selectedOption) {
|
|
489
|
+
this._liveAnnouncer.announce(selectedOption.viewValue, 10000);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
_handleOpenKeydown(event) {
|
|
494
|
+
const manager = this._keyManager;
|
|
495
|
+
const keyCode = event.keyCode;
|
|
496
|
+
const isArrowKey = keyCode === DOWN_ARROW || keyCode === UP_ARROW;
|
|
497
|
+
const isTyping = manager.isTyping();
|
|
498
|
+
if (isArrowKey && event.altKey) {
|
|
499
|
+
event.preventDefault();
|
|
500
|
+
this.close();
|
|
501
|
+
} else if (!isTyping && (keyCode === ENTER || keyCode === SPACE) && manager.activeItem && !hasModifierKey(event)) {
|
|
502
|
+
event.preventDefault();
|
|
503
|
+
manager.activeItem._selectViaInteraction();
|
|
504
|
+
} else if (!isTyping && this._multiple && keyCode === A && event.ctrlKey) {
|
|
505
|
+
event.preventDefault();
|
|
506
|
+
const hasDeselectedOptions = this.options.some(opt => !opt.disabled && !opt.selected);
|
|
507
|
+
this.options.forEach(option => {
|
|
508
|
+
if (!option.disabled) {
|
|
509
|
+
hasDeselectedOptions ? option.select() : option.deselect();
|
|
880
510
|
}
|
|
511
|
+
});
|
|
512
|
+
} else {
|
|
513
|
+
const previouslyFocusedIndex = manager.activeItemIndex;
|
|
514
|
+
manager.onKeydown(event);
|
|
515
|
+
if (this._multiple && isArrowKey && event.shiftKey && manager.activeItem && manager.activeItemIndex !== previouslyFocusedIndex) {
|
|
516
|
+
manager.activeItem._selectViaInteraction();
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
_handleOverlayKeydown(event) {
|
|
521
|
+
if (event.keyCode === ESCAPE && !hasModifierKey(event)) {
|
|
522
|
+
event.preventDefault();
|
|
523
|
+
this.close();
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
_onFocus() {
|
|
527
|
+
if (!this.disabled) {
|
|
528
|
+
this._focused = true;
|
|
529
|
+
this.stateChanges.next();
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
_onBlur() {
|
|
533
|
+
this._focused = false;
|
|
534
|
+
this._keyManager?.cancelTypeahead();
|
|
535
|
+
if (!this.disabled && !this.panelOpen) {
|
|
536
|
+
this._onTouched();
|
|
537
|
+
this._changeDetectorRef.markForCheck();
|
|
538
|
+
this.stateChanges.next();
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
_getPanelTheme() {
|
|
542
|
+
return this._parentFormField ? `mat-${this._parentFormField.color}` : '';
|
|
543
|
+
}
|
|
544
|
+
get empty() {
|
|
545
|
+
return !this._selectionModel || this._selectionModel.isEmpty();
|
|
546
|
+
}
|
|
547
|
+
_initializeSelection() {
|
|
548
|
+
Promise.resolve().then(() => {
|
|
549
|
+
if (this.ngControl) {
|
|
550
|
+
this._value = this.ngControl.value;
|
|
551
|
+
}
|
|
552
|
+
this._setSelectionByValue(this._value);
|
|
553
|
+
this.stateChanges.next();
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
_setSelectionByValue(value) {
|
|
557
|
+
this.options.forEach(option => option.setInactiveStyles());
|
|
558
|
+
this._selectionModel.clear();
|
|
559
|
+
if (this.multiple && value) {
|
|
560
|
+
if (!Array.isArray(value) && (typeof ngDevMode === 'undefined' || ngDevMode)) {
|
|
561
|
+
throw getMatSelectNonArrayValueError();
|
|
562
|
+
}
|
|
563
|
+
value.forEach(currentValue => this._selectOptionByValue(currentValue));
|
|
564
|
+
this._sortValues();
|
|
565
|
+
} else {
|
|
566
|
+
const correspondingOption = this._selectOptionByValue(value);
|
|
567
|
+
if (correspondingOption) {
|
|
568
|
+
this._keyManager.updateActiveItem(correspondingOption);
|
|
569
|
+
} else if (!this.panelOpen) {
|
|
570
|
+
this._keyManager.updateActiveItem(-1);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
this._changeDetectorRef.markForCheck();
|
|
574
|
+
}
|
|
575
|
+
_selectOptionByValue(value) {
|
|
576
|
+
const correspondingOption = this.options.find(option => {
|
|
577
|
+
if (this._selectionModel.isSelected(option)) {
|
|
881
578
|
return false;
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
// makes a few exceptions for compound widgets.
|
|
889
|
-
//
|
|
890
|
-
// From [Developing a Keyboard Interface](
|
|
891
|
-
// https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/):
|
|
892
|
-
// "For the following composite widget elements, keep them focusable when disabled: Options in a
|
|
893
|
-
// Listbox..."
|
|
894
|
-
//
|
|
895
|
-
// The user can focus disabled options using the keyboard, but the user cannot click disabled
|
|
896
|
-
// options.
|
|
897
|
-
_skipPredicate = (option) => {
|
|
898
|
-
if (this.panelOpen) {
|
|
899
|
-
// Support keyboard focusing disabled options in an ARIA listbox.
|
|
900
|
-
return false;
|
|
901
|
-
}
|
|
902
|
-
// When the panel is closed, skip over disabled options. Support options via the UP/DOWN arrow
|
|
903
|
-
// keys on a closed select. ARIA listbox interaction pattern is less relevant when the panel is
|
|
904
|
-
// closed.
|
|
905
|
-
return option.disabled;
|
|
906
|
-
};
|
|
907
|
-
/** Gets how wide the overlay panel should be. */
|
|
908
|
-
_getOverlayWidth(preferredOrigin) {
|
|
909
|
-
if (this.panelWidth === 'auto') {
|
|
910
|
-
const refToMeasure = preferredOrigin instanceof CdkOverlayOrigin
|
|
911
|
-
? preferredOrigin.elementRef
|
|
912
|
-
: preferredOrigin || this._elementRef;
|
|
913
|
-
return refToMeasure.nativeElement.getBoundingClientRect().width;
|
|
914
|
-
}
|
|
915
|
-
return this.panelWidth === null ? '' : this.panelWidth;
|
|
916
|
-
}
|
|
917
|
-
/** Syncs the parent state with the individual options. */
|
|
918
|
-
_syncParentProperties() {
|
|
919
|
-
if (this.options) {
|
|
920
|
-
for (const option of this.options) {
|
|
921
|
-
option._changeDetectorRef.markForCheck();
|
|
922
|
-
}
|
|
923
|
-
}
|
|
924
|
-
}
|
|
925
|
-
/** Sets up a key manager to listen to keyboard events on the overlay panel. */
|
|
926
|
-
_initKeyManager() {
|
|
927
|
-
this._keyManager = new ActiveDescendantKeyManager(this.options)
|
|
928
|
-
.withTypeAhead(this.typeaheadDebounceInterval)
|
|
929
|
-
.withVerticalOrientation()
|
|
930
|
-
.withHorizontalOrientation(this._isRtl() ? 'rtl' : 'ltr')
|
|
931
|
-
.withHomeAndEnd()
|
|
932
|
-
.withPageUpDown()
|
|
933
|
-
.withAllowedModifierKeys(['shiftKey'])
|
|
934
|
-
.skipPredicate(this._skipPredicate);
|
|
935
|
-
this._keyManager.tabOut.subscribe(() => {
|
|
936
|
-
if (this.panelOpen) {
|
|
937
|
-
// Select the active item when tabbing away. This is consistent with how the native
|
|
938
|
-
// select behaves. Note that we only want to do this in single selection mode.
|
|
939
|
-
if (!this.multiple && this._keyManager.activeItem) {
|
|
940
|
-
this._keyManager.activeItem._selectViaInteraction();
|
|
941
|
-
}
|
|
942
|
-
// Restore focus to the trigger before closing. Ensures that the focus
|
|
943
|
-
// position won't be lost if the user got focus into the overlay.
|
|
944
|
-
this.focus();
|
|
945
|
-
this.close();
|
|
946
|
-
}
|
|
947
|
-
});
|
|
948
|
-
this._keyManager.change.subscribe(() => {
|
|
949
|
-
if (this._panelOpen && this.panel) {
|
|
950
|
-
this._scrollOptionIntoView(this._keyManager.activeItemIndex || 0);
|
|
951
|
-
}
|
|
952
|
-
else if (!this._panelOpen && !this.multiple && this._keyManager.activeItem) {
|
|
953
|
-
this._keyManager.activeItem._selectViaInteraction();
|
|
954
|
-
}
|
|
955
|
-
});
|
|
956
|
-
}
|
|
957
|
-
/** Drops current option subscriptions and IDs and resets from scratch. */
|
|
958
|
-
_resetOptions() {
|
|
959
|
-
const changedOrDestroyed = merge(this.options.changes, this._destroy);
|
|
960
|
-
this.optionSelectionChanges.pipe(takeUntil(changedOrDestroyed)).subscribe(event => {
|
|
961
|
-
this._onSelect(event.source, event.isUserInput);
|
|
962
|
-
if (event.isUserInput && !this.multiple && this._panelOpen) {
|
|
963
|
-
this.close();
|
|
964
|
-
this.focus();
|
|
965
|
-
}
|
|
966
|
-
});
|
|
967
|
-
// Listen to changes in the internal state of the options and react accordingly.
|
|
968
|
-
// Handles cases like the labels of the selected options changing.
|
|
969
|
-
merge(...this.options.map(option => option._stateChanges))
|
|
970
|
-
.pipe(takeUntil(changedOrDestroyed))
|
|
971
|
-
.subscribe(() => {
|
|
972
|
-
// `_stateChanges` can fire as a result of a change in the label's DOM value which may
|
|
973
|
-
// be the result of an expression changing. We have to use `detectChanges` in order
|
|
974
|
-
// to avoid "changed after checked" errors (see #14793).
|
|
975
|
-
this._changeDetectorRef.detectChanges();
|
|
976
|
-
this.stateChanges.next();
|
|
977
|
-
});
|
|
978
|
-
}
|
|
979
|
-
/** Invoked when an option is clicked. */
|
|
980
|
-
_onSelect(option, isUserInput) {
|
|
981
|
-
const wasSelected = this._selectionModel.isSelected(option);
|
|
982
|
-
if (!this.canSelectNullableOptions && option.value == null && !this._multiple) {
|
|
983
|
-
option.deselect();
|
|
984
|
-
this._selectionModel.clear();
|
|
985
|
-
if (this.value != null) {
|
|
986
|
-
this._propagateChanges(option.value);
|
|
987
|
-
}
|
|
988
|
-
}
|
|
989
|
-
else {
|
|
990
|
-
if (wasSelected !== option.selected) {
|
|
991
|
-
option.selected
|
|
992
|
-
? this._selectionModel.select(option)
|
|
993
|
-
: this._selectionModel.deselect(option);
|
|
994
|
-
}
|
|
995
|
-
if (isUserInput) {
|
|
996
|
-
this._keyManager.setActiveItem(option);
|
|
997
|
-
}
|
|
998
|
-
if (this.multiple) {
|
|
999
|
-
this._sortValues();
|
|
1000
|
-
if (isUserInput) {
|
|
1001
|
-
// In case the user selected the option with their mouse, we
|
|
1002
|
-
// want to restore focus back to the trigger, in order to
|
|
1003
|
-
// prevent the select keyboard controls from clashing with
|
|
1004
|
-
// the ones from `mat-option`.
|
|
1005
|
-
this.focus();
|
|
1006
|
-
}
|
|
1007
|
-
}
|
|
579
|
+
}
|
|
580
|
+
try {
|
|
581
|
+
return (option.value != null || this.canSelectNullableOptions) && this._compareWith(option.value, value);
|
|
582
|
+
} catch (error) {
|
|
583
|
+
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
584
|
+
console.warn(error);
|
|
1008
585
|
}
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
const option = this.options.get(index);
|
|
1054
|
-
if (!option.disabled) {
|
|
1055
|
-
firstEnabledOptionIndex = index;
|
|
1056
|
-
break;
|
|
1057
|
-
}
|
|
1058
|
-
}
|
|
1059
|
-
this._keyManager.setActiveItem(firstEnabledOptionIndex);
|
|
1060
|
-
}
|
|
1061
|
-
else {
|
|
1062
|
-
this._keyManager.setActiveItem(this._selectionModel.selected[0]);
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
|
-
/** Whether the panel is allowed to open. */
|
|
1067
|
-
_canOpen() {
|
|
1068
|
-
return !this._panelOpen && !this.disabled && this.options?.length > 0 && !!this._overlayDir;
|
|
1069
|
-
}
|
|
1070
|
-
/** Focuses the select element. */
|
|
1071
|
-
focus(options) {
|
|
1072
|
-
this._elementRef.nativeElement.focus(options);
|
|
1073
|
-
}
|
|
1074
|
-
/** Gets the aria-labelledby for the select panel. */
|
|
1075
|
-
_getPanelAriaLabelledby() {
|
|
1076
|
-
if (this.ariaLabel) {
|
|
1077
|
-
return null;
|
|
1078
|
-
}
|
|
1079
|
-
const labelId = this._parentFormField?.getLabelId() || null;
|
|
1080
|
-
const labelExpression = labelId ? labelId + ' ' : '';
|
|
1081
|
-
return this.ariaLabelledby ? labelExpression + this.ariaLabelledby : labelId;
|
|
1082
|
-
}
|
|
1083
|
-
/** Determines the `aria-activedescendant` to be set on the host. */
|
|
1084
|
-
_getAriaActiveDescendant() {
|
|
1085
|
-
if (this.panelOpen && this._keyManager && this._keyManager.activeItem) {
|
|
1086
|
-
return this._keyManager.activeItem.id;
|
|
1087
|
-
}
|
|
1088
|
-
return null;
|
|
1089
|
-
}
|
|
1090
|
-
/** Gets the aria-labelledby of the select component trigger. */
|
|
1091
|
-
_getTriggerAriaLabelledby() {
|
|
1092
|
-
if (this.ariaLabel) {
|
|
1093
|
-
return null;
|
|
1094
|
-
}
|
|
1095
|
-
let value = this._parentFormField?.getLabelId() || '';
|
|
1096
|
-
if (this.ariaLabelledby) {
|
|
1097
|
-
value += ' ' + this.ariaLabelledby;
|
|
1098
|
-
}
|
|
1099
|
-
// The value should not be used for the trigger's aria-labelledby,
|
|
1100
|
-
// but this currently "breaks" accessibility tests since they complain
|
|
1101
|
-
// there is no aria-labelledby. This is because they are not setting an
|
|
1102
|
-
// appropriate label on the form field or select.
|
|
1103
|
-
// TODO: remove this conditional after fixing clients by ensuring their
|
|
1104
|
-
// selects have a label applied.
|
|
1105
|
-
if (!value) {
|
|
1106
|
-
value = this._valueId;
|
|
586
|
+
return false;
|
|
587
|
+
}
|
|
588
|
+
});
|
|
589
|
+
if (correspondingOption) {
|
|
590
|
+
this._selectionModel.select(correspondingOption);
|
|
591
|
+
}
|
|
592
|
+
return correspondingOption;
|
|
593
|
+
}
|
|
594
|
+
_assignValue(newValue) {
|
|
595
|
+
if (newValue !== this._value || this._multiple && Array.isArray(newValue)) {
|
|
596
|
+
if (this.options) {
|
|
597
|
+
this._setSelectionByValue(newValue);
|
|
598
|
+
}
|
|
599
|
+
this._value = newValue;
|
|
600
|
+
return true;
|
|
601
|
+
}
|
|
602
|
+
return false;
|
|
603
|
+
}
|
|
604
|
+
_skipPredicate = option => {
|
|
605
|
+
if (this.panelOpen) {
|
|
606
|
+
return false;
|
|
607
|
+
}
|
|
608
|
+
return option.disabled;
|
|
609
|
+
};
|
|
610
|
+
_getOverlayWidth(preferredOrigin) {
|
|
611
|
+
if (this.panelWidth === 'auto') {
|
|
612
|
+
const refToMeasure = preferredOrigin instanceof CdkOverlayOrigin ? preferredOrigin.elementRef : preferredOrigin || this._elementRef;
|
|
613
|
+
return refToMeasure.nativeElement.getBoundingClientRect().width;
|
|
614
|
+
}
|
|
615
|
+
return this.panelWidth === null ? '' : this.panelWidth;
|
|
616
|
+
}
|
|
617
|
+
_syncParentProperties() {
|
|
618
|
+
if (this.options) {
|
|
619
|
+
for (const option of this.options) {
|
|
620
|
+
option._changeDetectorRef.markForCheck();
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
_initKeyManager() {
|
|
625
|
+
this._keyManager = new ActiveDescendantKeyManager(this.options).withTypeAhead(this.typeaheadDebounceInterval).withVerticalOrientation().withHorizontalOrientation(this._isRtl() ? 'rtl' : 'ltr').withHomeAndEnd().withPageUpDown().withAllowedModifierKeys(['shiftKey']).skipPredicate(this._skipPredicate);
|
|
626
|
+
this._keyManager.tabOut.subscribe(() => {
|
|
627
|
+
if (this.panelOpen) {
|
|
628
|
+
if (!this.multiple && this._keyManager.activeItem) {
|
|
629
|
+
this._keyManager.activeItem._selectViaInteraction();
|
|
1107
630
|
}
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
}
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
631
|
+
this.focus();
|
|
632
|
+
this.close();
|
|
633
|
+
}
|
|
634
|
+
});
|
|
635
|
+
this._keyManager.change.subscribe(() => {
|
|
636
|
+
if (this._panelOpen && this.panel) {
|
|
637
|
+
this._scrollOptionIntoView(this._keyManager.activeItemIndex || 0);
|
|
638
|
+
} else if (!this._panelOpen && !this.multiple && this._keyManager.activeItem) {
|
|
639
|
+
this._keyManager.activeItem._selectViaInteraction();
|
|
640
|
+
}
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
_resetOptions() {
|
|
644
|
+
const changedOrDestroyed = merge(this.options.changes, this._destroy);
|
|
645
|
+
this.optionSelectionChanges.pipe(takeUntil(changedOrDestroyed)).subscribe(event => {
|
|
646
|
+
this._onSelect(event.source, event.isUserInput);
|
|
647
|
+
if (event.isUserInput && !this.multiple && this._panelOpen) {
|
|
648
|
+
this.close();
|
|
649
|
+
this.focus();
|
|
650
|
+
}
|
|
651
|
+
});
|
|
652
|
+
merge(...this.options.map(option => option._stateChanges)).pipe(takeUntil(changedOrDestroyed)).subscribe(() => {
|
|
653
|
+
this._changeDetectorRef.detectChanges();
|
|
654
|
+
this.stateChanges.next();
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
_onSelect(option, isUserInput) {
|
|
658
|
+
const wasSelected = this._selectionModel.isSelected(option);
|
|
659
|
+
if (!this.canSelectNullableOptions && option.value == null && !this._multiple) {
|
|
660
|
+
option.deselect();
|
|
661
|
+
this._selectionModel.clear();
|
|
662
|
+
if (this.value != null) {
|
|
663
|
+
this._propagateChanges(option.value);
|
|
664
|
+
}
|
|
665
|
+
} else {
|
|
666
|
+
if (wasSelected !== option.selected) {
|
|
667
|
+
option.selected ? this._selectionModel.select(option) : this._selectionModel.deselect(option);
|
|
668
|
+
}
|
|
669
|
+
if (isUserInput) {
|
|
670
|
+
this._keyManager.setActiveItem(option);
|
|
671
|
+
}
|
|
672
|
+
if (this.multiple) {
|
|
673
|
+
this._sortValues();
|
|
674
|
+
if (isUserInput) {
|
|
675
|
+
this.focus();
|
|
1126
676
|
}
|
|
1127
|
-
|
|
1128
|
-
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
if (wasSelected !== this._selectionModel.isSelected(option)) {
|
|
680
|
+
this._propagateChanges();
|
|
681
|
+
}
|
|
682
|
+
this.stateChanges.next();
|
|
683
|
+
}
|
|
684
|
+
_sortValues() {
|
|
685
|
+
if (this.multiple) {
|
|
686
|
+
const options = this.options.toArray();
|
|
687
|
+
this._selectionModel.sort((a, b) => {
|
|
688
|
+
return this.sortComparator ? this.sortComparator(a, b, options) : options.indexOf(a) - options.indexOf(b);
|
|
689
|
+
});
|
|
690
|
+
this.stateChanges.next();
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
_propagateChanges(fallbackValue) {
|
|
694
|
+
let valueToEmit;
|
|
695
|
+
if (this.multiple) {
|
|
696
|
+
valueToEmit = this.selected.map(option => option.value);
|
|
697
|
+
} else {
|
|
698
|
+
valueToEmit = this.selected ? this.selected.value : fallbackValue;
|
|
699
|
+
}
|
|
700
|
+
this._value = valueToEmit;
|
|
701
|
+
this.valueChange.emit(valueToEmit);
|
|
702
|
+
this._onChange(valueToEmit);
|
|
703
|
+
this.selectionChange.emit(this._getChangeEvent(valueToEmit));
|
|
704
|
+
this._changeDetectorRef.markForCheck();
|
|
705
|
+
}
|
|
706
|
+
_highlightCorrectOption() {
|
|
707
|
+
if (this._keyManager) {
|
|
708
|
+
if (this.empty) {
|
|
709
|
+
let firstEnabledOptionIndex = -1;
|
|
710
|
+
for (let index = 0; index < this.options.length; index++) {
|
|
711
|
+
const option = this.options.get(index);
|
|
712
|
+
if (!option.disabled) {
|
|
713
|
+
firstEnabledOptionIndex = index;
|
|
714
|
+
break;
|
|
715
|
+
}
|
|
1129
716
|
}
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
717
|
+
this._keyManager.setActiveItem(firstEnabledOptionIndex);
|
|
718
|
+
} else {
|
|
719
|
+
this._keyManager.setActiveItem(this._selectionModel.selected[0]);
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
_canOpen() {
|
|
724
|
+
return !this._panelOpen && !this.disabled && this.options?.length > 0 && !!this._overlayDir;
|
|
725
|
+
}
|
|
726
|
+
focus(options) {
|
|
727
|
+
this._elementRef.nativeElement.focus(options);
|
|
728
|
+
}
|
|
729
|
+
_getPanelAriaLabelledby() {
|
|
730
|
+
if (this.ariaLabel) {
|
|
731
|
+
return null;
|
|
732
|
+
}
|
|
733
|
+
const labelId = this._parentFormField?.getLabelId() || null;
|
|
734
|
+
const labelExpression = labelId ? labelId + ' ' : '';
|
|
735
|
+
return this.ariaLabelledby ? labelExpression + this.ariaLabelledby : labelId;
|
|
736
|
+
}
|
|
737
|
+
_getAriaActiveDescendant() {
|
|
738
|
+
if (this.panelOpen && this._keyManager && this._keyManager.activeItem) {
|
|
739
|
+
return this._keyManager.activeItem.id;
|
|
740
|
+
}
|
|
741
|
+
return null;
|
|
742
|
+
}
|
|
743
|
+
_getTriggerAriaLabelledby() {
|
|
744
|
+
if (this.ariaLabel) {
|
|
745
|
+
return null;
|
|
746
|
+
}
|
|
747
|
+
let value = this._parentFormField?.getLabelId() || '';
|
|
748
|
+
if (this.ariaLabelledby) {
|
|
749
|
+
value += ' ' + this.ariaLabelledby;
|
|
750
|
+
}
|
|
751
|
+
if (!value) {
|
|
752
|
+
value = this._valueId;
|
|
753
|
+
}
|
|
754
|
+
return value;
|
|
755
|
+
}
|
|
756
|
+
get describedByIds() {
|
|
757
|
+
const element = this._elementRef.nativeElement;
|
|
758
|
+
const existingDescribedBy = element.getAttribute('aria-describedby');
|
|
759
|
+
return existingDescribedBy?.split(' ') || [];
|
|
760
|
+
}
|
|
761
|
+
setDescribedByIds(ids) {
|
|
762
|
+
const element = this._elementRef.nativeElement;
|
|
763
|
+
if (ids.length) {
|
|
764
|
+
element.setAttribute('aria-describedby', ids.join(' '));
|
|
765
|
+
} else {
|
|
766
|
+
element.removeAttribute('aria-describedby');
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
onContainerClick(event) {
|
|
770
|
+
const target = _getEventTarget(event);
|
|
771
|
+
const overlayHost = this._overlayDir.overlayRef?.hostElement;
|
|
772
|
+
if (!target || !overlayHost || !overlayHost.contains(target)) {
|
|
773
|
+
this.focus();
|
|
774
|
+
this.open();
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
get shouldLabelFloat() {
|
|
778
|
+
return this.panelOpen || !this.empty || this.focused && !!this.placeholder;
|
|
779
|
+
}
|
|
780
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
781
|
+
minVersion: "12.0.0",
|
|
782
|
+
version: "20.2.0-next.2",
|
|
783
|
+
ngImport: i0,
|
|
784
|
+
type: MatSelect,
|
|
785
|
+
deps: [],
|
|
786
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
787
|
+
});
|
|
788
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({
|
|
789
|
+
minVersion: "17.0.0",
|
|
790
|
+
version: "20.2.0-next.2",
|
|
791
|
+
type: MatSelect,
|
|
792
|
+
isStandalone: true,
|
|
793
|
+
selector: "mat-select",
|
|
794
|
+
inputs: {
|
|
795
|
+
userAriaDescribedBy: ["aria-describedby", "userAriaDescribedBy"],
|
|
796
|
+
panelClass: "panelClass",
|
|
797
|
+
disabled: ["disabled", "disabled", booleanAttribute],
|
|
798
|
+
disableRipple: ["disableRipple", "disableRipple", booleanAttribute],
|
|
799
|
+
tabIndex: ["tabIndex", "tabIndex", value => value == null ? 0 : numberAttribute(value)],
|
|
800
|
+
hideSingleSelectionIndicator: ["hideSingleSelectionIndicator", "hideSingleSelectionIndicator", booleanAttribute],
|
|
801
|
+
placeholder: "placeholder",
|
|
802
|
+
required: ["required", "required", booleanAttribute],
|
|
803
|
+
multiple: ["multiple", "multiple", booleanAttribute],
|
|
804
|
+
disableOptionCentering: ["disableOptionCentering", "disableOptionCentering", booleanAttribute],
|
|
805
|
+
compareWith: "compareWith",
|
|
806
|
+
value: "value",
|
|
807
|
+
ariaLabel: ["aria-label", "ariaLabel"],
|
|
808
|
+
ariaLabelledby: ["aria-labelledby", "ariaLabelledby"],
|
|
809
|
+
errorStateMatcher: "errorStateMatcher",
|
|
810
|
+
typeaheadDebounceInterval: ["typeaheadDebounceInterval", "typeaheadDebounceInterval", numberAttribute],
|
|
811
|
+
sortComparator: "sortComparator",
|
|
812
|
+
id: "id",
|
|
813
|
+
panelWidth: "panelWidth",
|
|
814
|
+
canSelectNullableOptions: ["canSelectNullableOptions", "canSelectNullableOptions", booleanAttribute]
|
|
815
|
+
},
|
|
816
|
+
outputs: {
|
|
817
|
+
openedChange: "openedChange",
|
|
818
|
+
_openedStream: "opened",
|
|
819
|
+
_closedStream: "closed",
|
|
820
|
+
selectionChange: "selectionChange",
|
|
821
|
+
valueChange: "valueChange"
|
|
822
|
+
},
|
|
823
|
+
host: {
|
|
824
|
+
attributes: {
|
|
825
|
+
"role": "combobox",
|
|
826
|
+
"aria-haspopup": "listbox"
|
|
827
|
+
},
|
|
828
|
+
listeners: {
|
|
829
|
+
"keydown": "_handleKeydown($event)",
|
|
830
|
+
"focus": "_onFocus()",
|
|
831
|
+
"blur": "_onBlur()"
|
|
832
|
+
},
|
|
833
|
+
properties: {
|
|
834
|
+
"attr.id": "id",
|
|
835
|
+
"attr.tabindex": "disabled ? -1 : tabIndex",
|
|
836
|
+
"attr.aria-controls": "panelOpen ? id + \"-panel\" : null",
|
|
837
|
+
"attr.aria-expanded": "panelOpen",
|
|
838
|
+
"attr.aria-label": "ariaLabel || null",
|
|
839
|
+
"attr.aria-required": "required.toString()",
|
|
840
|
+
"attr.aria-disabled": "disabled.toString()",
|
|
841
|
+
"attr.aria-invalid": "errorState",
|
|
842
|
+
"attr.aria-activedescendant": "_getAriaActiveDescendant()",
|
|
843
|
+
"class.mat-mdc-select-disabled": "disabled",
|
|
844
|
+
"class.mat-mdc-select-invalid": "errorState",
|
|
845
|
+
"class.mat-mdc-select-required": "required",
|
|
846
|
+
"class.mat-mdc-select-empty": "empty",
|
|
847
|
+
"class.mat-mdc-select-multiple": "multiple",
|
|
848
|
+
"class.mat-select-open": "panelOpen"
|
|
849
|
+
},
|
|
850
|
+
classAttribute: "mat-mdc-select"
|
|
851
|
+
},
|
|
852
|
+
providers: [{
|
|
853
|
+
provide: MatFormFieldControl,
|
|
854
|
+
useExisting: MatSelect
|
|
855
|
+
}, {
|
|
856
|
+
provide: MAT_OPTION_PARENT_COMPONENT,
|
|
857
|
+
useExisting: MatSelect
|
|
858
|
+
}],
|
|
859
|
+
queries: [{
|
|
860
|
+
propertyName: "customTrigger",
|
|
861
|
+
first: true,
|
|
862
|
+
predicate: MAT_SELECT_TRIGGER,
|
|
863
|
+
descendants: true
|
|
864
|
+
}, {
|
|
865
|
+
propertyName: "options",
|
|
866
|
+
predicate: MatOption,
|
|
867
|
+
descendants: true
|
|
868
|
+
}, {
|
|
869
|
+
propertyName: "optionGroups",
|
|
870
|
+
predicate: MAT_OPTGROUP,
|
|
871
|
+
descendants: true
|
|
872
|
+
}],
|
|
873
|
+
viewQueries: [{
|
|
874
|
+
propertyName: "trigger",
|
|
875
|
+
first: true,
|
|
876
|
+
predicate: ["trigger"],
|
|
877
|
+
descendants: true
|
|
878
|
+
}, {
|
|
879
|
+
propertyName: "panel",
|
|
880
|
+
first: true,
|
|
881
|
+
predicate: ["panel"],
|
|
882
|
+
descendants: true
|
|
883
|
+
}, {
|
|
884
|
+
propertyName: "_overlayDir",
|
|
885
|
+
first: true,
|
|
886
|
+
predicate: CdkConnectedOverlay,
|
|
887
|
+
descendants: true
|
|
888
|
+
}],
|
|
889
|
+
exportAs: ["matSelect"],
|
|
890
|
+
usesOnChanges: true,
|
|
891
|
+
ngImport: i0,
|
|
892
|
+
template: "<div cdk-overlay-origin\n class=\"mat-mdc-select-trigger\"\n (click)=\"open()\"\n #fallbackOverlayOrigin=\"cdkOverlayOrigin\"\n #trigger>\n\n <div class=\"mat-mdc-select-value\" [attr.id]=\"_valueId\">\n @if (empty) {\n <span class=\"mat-mdc-select-placeholder mat-mdc-select-min-line\">{{placeholder}}</span>\n } @else {\n <span class=\"mat-mdc-select-value-text\">\n @if (customTrigger) {\n <ng-content select=\"mat-select-trigger\"></ng-content>\n } @else {\n <span class=\"mat-mdc-select-min-line\">{{triggerValue}}</span>\n }\n </span>\n }\n </div>\n\n <div class=\"mat-mdc-select-arrow-wrapper\">\n <div class=\"mat-mdc-select-arrow\">\n <!-- Use an inline SVG, because it works better than a CSS triangle in high contrast mode. -->\n <svg viewBox=\"0 0 24 24\" width=\"24px\" height=\"24px\" focusable=\"false\" aria-hidden=\"true\">\n <path d=\"M7 10l5 5 5-5z\"/>\n </svg>\n </div>\n </div>\n</div>\n\n<ng-template\n cdk-connected-overlay\n cdkConnectedOverlayLockPosition\n cdkConnectedOverlayHasBackdrop\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n [cdkConnectedOverlayDisableClose]=\"true\"\n [cdkConnectedOverlayPanelClass]=\"_overlayPanelClass\"\n [cdkConnectedOverlayScrollStrategy]=\"_scrollStrategy\"\n [cdkConnectedOverlayOrigin]=\"_preferredOverlayOrigin || fallbackOverlayOrigin\"\n [cdkConnectedOverlayPositions]=\"_positions\"\n [cdkConnectedOverlayWidth]=\"_overlayWidth\"\n [cdkConnectedOverlayFlexibleDimensions]=\"true\"\n (detach)=\"close()\"\n (backdropClick)=\"close()\"\n (overlayKeydown)=\"_handleOverlayKeydown($event)\">\n <div\n #panel\n role=\"listbox\"\n tabindex=\"-1\"\n class=\"mat-mdc-select-panel mdc-menu-surface mdc-menu-surface--open {{ _getPanelTheme() }}\"\n [class.mat-select-panel-animations-enabled]=\"!_animationsDisabled\"\n [attr.id]=\"id + '-panel'\"\n [attr.aria-multiselectable]=\"multiple\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.aria-labelledby]=\"_getPanelAriaLabelledby()\"\n [ngClass]=\"panelClass\"\n (keydown)=\"_handleKeydown($event)\">\n <ng-content></ng-content>\n </div>\n</ng-template>\n",
|
|
893
|
+
styles: ["@keyframes _mat-select-enter{from{opacity:0;transform:scaleY(0.8)}to{opacity:1;transform:none}}@keyframes _mat-select-exit{from{opacity:1}to{opacity:0}}.mat-mdc-select{display:inline-block;width:100%;outline:none;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;color:var(--mat-select-enabled-trigger-text-color, var(--mat-sys-on-surface));font-family:var(--mat-select-trigger-text-font, var(--mat-sys-body-large-font));line-height:var(--mat-select-trigger-text-line-height, var(--mat-sys-body-large-line-height));font-size:var(--mat-select-trigger-text-size, var(--mat-sys-body-large-size));font-weight:var(--mat-select-trigger-text-weight, var(--mat-sys-body-large-weight));letter-spacing:var(--mat-select-trigger-text-tracking, var(--mat-sys-body-large-tracking))}div.mat-mdc-select-panel{box-shadow:var(--mat-select-container-elevation-shadow, 0px 3px 1px -2px rgba(0, 0, 0, 0.2), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 1px 5px 0px rgba(0, 0, 0, 0.12))}.mat-mdc-select-disabled{color:var(--mat-select-disabled-trigger-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-mdc-select-disabled .mat-mdc-select-placeholder{color:var(--mat-select-disabled-trigger-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-mdc-select-trigger{display:inline-flex;align-items:center;cursor:pointer;position:relative;box-sizing:border-box;width:100%}.mat-mdc-select-disabled .mat-mdc-select-trigger{-webkit-user-select:none;user-select:none;cursor:default}.mat-mdc-select-value{width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mat-mdc-select-value-text{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mat-mdc-select-arrow-wrapper{height:24px;flex-shrink:0;display:inline-flex;align-items:center}.mat-form-field-appearance-fill .mdc-text-field--no-label .mat-mdc-select-arrow-wrapper{transform:none}.mat-mdc-form-field .mat-mdc-select.mat-mdc-select-invalid .mat-mdc-select-arrow,.mat-form-field-invalid:not(.mat-form-field-disabled) .mat-mdc-form-field-infix::after{color:var(--mat-select-invalid-arrow-color, var(--mat-sys-error))}.mat-mdc-select-arrow{width:10px;height:5px;position:relative;color:var(--mat-select-enabled-arrow-color, var(--mat-sys-on-surface-variant))}.mat-mdc-form-field.mat-focused .mat-mdc-select-arrow{color:var(--mat-select-focused-arrow-color, var(--mat-sys-primary))}.mat-mdc-form-field .mat-mdc-select.mat-mdc-select-disabled .mat-mdc-select-arrow{color:var(--mat-select-disabled-arrow-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-select-open .mat-mdc-select-arrow{transform:rotate(180deg)}.mat-form-field-animations-enabled .mat-mdc-select-arrow{transition:transform 80ms linear}.mat-mdc-select-arrow svg{fill:currentColor;position:absolute;top:50%;left:50%;transform:translate(-50%, -50%)}@media(forced-colors: active){.mat-mdc-select-arrow svg{fill:CanvasText}.mat-mdc-select-disabled .mat-mdc-select-arrow svg{fill:GrayText}}div.mat-mdc-select-panel{width:100%;max-height:275px;outline:0;overflow:auto;padding:8px 0;border-radius:4px;box-sizing:border-box;position:relative;background-color:var(--mat-select-panel-background-color, var(--mat-sys-surface-container))}@media(forced-colors: active){div.mat-mdc-select-panel{outline:solid 1px}}.cdk-overlay-pane:not(.mat-mdc-select-panel-above) div.mat-mdc-select-panel{border-top-left-radius:0;border-top-right-radius:0;transform-origin:top center}.mat-mdc-select-panel-above div.mat-mdc-select-panel{border-bottom-left-radius:0;border-bottom-right-radius:0;transform-origin:bottom center}.mat-select-panel-animations-enabled{animation:_mat-select-enter 120ms cubic-bezier(0, 0, 0.2, 1)}.mat-select-panel-animations-enabled.mat-select-panel-exit{animation:_mat-select-exit 100ms linear}.mat-mdc-select-placeholder{transition:color 400ms 133.3333333333ms cubic-bezier(0.25, 0.8, 0.25, 1);color:var(--mat-select-placeholder-text-color, var(--mat-sys-on-surface-variant))}.mat-mdc-form-field:not(.mat-form-field-animations-enabled) .mat-mdc-select-placeholder,._mat-animation-noopable .mat-mdc-select-placeholder{transition:none}.mat-form-field-hide-placeholder .mat-mdc-select-placeholder{color:rgba(0,0,0,0);-webkit-text-fill-color:rgba(0,0,0,0);transition:none;display:block}.mat-mdc-form-field-type-mat-select:not(.mat-form-field-disabled) .mat-mdc-text-field-wrapper{cursor:pointer}.mat-mdc-form-field-type-mat-select.mat-form-field-appearance-fill .mat-mdc-floating-label{max-width:calc(100% - 18px)}.mat-mdc-form-field-type-mat-select.mat-form-field-appearance-fill .mdc-floating-label--float-above{max-width:calc(100%/0.75 - 24px)}.mat-mdc-form-field-type-mat-select.mat-form-field-appearance-outline .mdc-notched-outline__notch{max-width:calc(100% - 60px)}.mat-mdc-form-field-type-mat-select.mat-form-field-appearance-outline .mdc-text-field--label-floating .mdc-notched-outline__notch{max-width:calc(100% - 24px)}.mat-mdc-select-min-line:empty::before{content:\" \";white-space:pre;width:1px;display:inline-block;visibility:hidden}.mat-form-field-appearance-fill .mat-mdc-select-arrow-wrapper{transform:var(--mat-select-arrow-transform, translateY(-8px))}\n"],
|
|
894
|
+
dependencies: [{
|
|
895
|
+
kind: "directive",
|
|
896
|
+
type: CdkOverlayOrigin,
|
|
897
|
+
selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]",
|
|
898
|
+
exportAs: ["cdkOverlayOrigin"]
|
|
899
|
+
}, {
|
|
900
|
+
kind: "directive",
|
|
901
|
+
type: CdkConnectedOverlay,
|
|
902
|
+
selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]",
|
|
903
|
+
inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"],
|
|
904
|
+
outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"],
|
|
905
|
+
exportAs: ["cdkConnectedOverlay"]
|
|
906
|
+
}, {
|
|
907
|
+
kind: "directive",
|
|
908
|
+
type: NgClass,
|
|
909
|
+
selector: "[ngClass]",
|
|
910
|
+
inputs: ["class", "ngClass"]
|
|
911
|
+
}],
|
|
912
|
+
changeDetection: i0.ChangeDetectionStrategy.OnPush,
|
|
913
|
+
encapsulation: i0.ViewEncapsulation.None
|
|
914
|
+
});
|
|
1153
915
|
}
|
|
1154
|
-
i0.ɵɵngDeclareClassMetadata({
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
916
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
917
|
+
minVersion: "12.0.0",
|
|
918
|
+
version: "20.2.0-next.2",
|
|
919
|
+
ngImport: i0,
|
|
920
|
+
type: MatSelect,
|
|
921
|
+
decorators: [{
|
|
922
|
+
type: Component,
|
|
923
|
+
args: [{
|
|
924
|
+
selector: 'mat-select',
|
|
925
|
+
exportAs: 'matSelect',
|
|
926
|
+
encapsulation: ViewEncapsulation.None,
|
|
927
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
928
|
+
host: {
|
|
929
|
+
'role': 'combobox',
|
|
930
|
+
'aria-haspopup': 'listbox',
|
|
931
|
+
'class': 'mat-mdc-select',
|
|
932
|
+
'[attr.id]': 'id',
|
|
933
|
+
'[attr.tabindex]': 'disabled ? -1 : tabIndex',
|
|
934
|
+
'[attr.aria-controls]': 'panelOpen ? id + "-panel" : null',
|
|
935
|
+
'[attr.aria-expanded]': 'panelOpen',
|
|
936
|
+
'[attr.aria-label]': 'ariaLabel || null',
|
|
937
|
+
'[attr.aria-required]': 'required.toString()',
|
|
938
|
+
'[attr.aria-disabled]': 'disabled.toString()',
|
|
939
|
+
'[attr.aria-invalid]': 'errorState',
|
|
940
|
+
'[attr.aria-activedescendant]': '_getAriaActiveDescendant()',
|
|
941
|
+
'[class.mat-mdc-select-disabled]': 'disabled',
|
|
942
|
+
'[class.mat-mdc-select-invalid]': 'errorState',
|
|
943
|
+
'[class.mat-mdc-select-required]': 'required',
|
|
944
|
+
'[class.mat-mdc-select-empty]': 'empty',
|
|
945
|
+
'[class.mat-mdc-select-multiple]': 'multiple',
|
|
946
|
+
'[class.mat-select-open]': 'panelOpen',
|
|
947
|
+
'(keydown)': '_handleKeydown($event)',
|
|
948
|
+
'(focus)': '_onFocus()',
|
|
949
|
+
'(blur)': '_onBlur()'
|
|
950
|
+
},
|
|
951
|
+
providers: [{
|
|
952
|
+
provide: MatFormFieldControl,
|
|
953
|
+
useExisting: MatSelect
|
|
954
|
+
}, {
|
|
955
|
+
provide: MAT_OPTION_PARENT_COMPONENT,
|
|
956
|
+
useExisting: MatSelect
|
|
957
|
+
}],
|
|
958
|
+
imports: [CdkOverlayOrigin, CdkConnectedOverlay, NgClass],
|
|
959
|
+
template: "<div cdk-overlay-origin\n class=\"mat-mdc-select-trigger\"\n (click)=\"open()\"\n #fallbackOverlayOrigin=\"cdkOverlayOrigin\"\n #trigger>\n\n <div class=\"mat-mdc-select-value\" [attr.id]=\"_valueId\">\n @if (empty) {\n <span class=\"mat-mdc-select-placeholder mat-mdc-select-min-line\">{{placeholder}}</span>\n } @else {\n <span class=\"mat-mdc-select-value-text\">\n @if (customTrigger) {\n <ng-content select=\"mat-select-trigger\"></ng-content>\n } @else {\n <span class=\"mat-mdc-select-min-line\">{{triggerValue}}</span>\n }\n </span>\n }\n </div>\n\n <div class=\"mat-mdc-select-arrow-wrapper\">\n <div class=\"mat-mdc-select-arrow\">\n <!-- Use an inline SVG, because it works better than a CSS triangle in high contrast mode. -->\n <svg viewBox=\"0 0 24 24\" width=\"24px\" height=\"24px\" focusable=\"false\" aria-hidden=\"true\">\n <path d=\"M7 10l5 5 5-5z\"/>\n </svg>\n </div>\n </div>\n</div>\n\n<ng-template\n cdk-connected-overlay\n cdkConnectedOverlayLockPosition\n cdkConnectedOverlayHasBackdrop\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n [cdkConnectedOverlayDisableClose]=\"true\"\n [cdkConnectedOverlayPanelClass]=\"_overlayPanelClass\"\n [cdkConnectedOverlayScrollStrategy]=\"_scrollStrategy\"\n [cdkConnectedOverlayOrigin]=\"_preferredOverlayOrigin || fallbackOverlayOrigin\"\n [cdkConnectedOverlayPositions]=\"_positions\"\n [cdkConnectedOverlayWidth]=\"_overlayWidth\"\n [cdkConnectedOverlayFlexibleDimensions]=\"true\"\n (detach)=\"close()\"\n (backdropClick)=\"close()\"\n (overlayKeydown)=\"_handleOverlayKeydown($event)\">\n <div\n #panel\n role=\"listbox\"\n tabindex=\"-1\"\n class=\"mat-mdc-select-panel mdc-menu-surface mdc-menu-surface--open {{ _getPanelTheme() }}\"\n [class.mat-select-panel-animations-enabled]=\"!_animationsDisabled\"\n [attr.id]=\"id + '-panel'\"\n [attr.aria-multiselectable]=\"multiple\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.aria-labelledby]=\"_getPanelAriaLabelledby()\"\n [ngClass]=\"panelClass\"\n (keydown)=\"_handleKeydown($event)\">\n <ng-content></ng-content>\n </div>\n</ng-template>\n",
|
|
960
|
+
styles: ["@keyframes _mat-select-enter{from{opacity:0;transform:scaleY(0.8)}to{opacity:1;transform:none}}@keyframes _mat-select-exit{from{opacity:1}to{opacity:0}}.mat-mdc-select{display:inline-block;width:100%;outline:none;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;color:var(--mat-select-enabled-trigger-text-color, var(--mat-sys-on-surface));font-family:var(--mat-select-trigger-text-font, var(--mat-sys-body-large-font));line-height:var(--mat-select-trigger-text-line-height, var(--mat-sys-body-large-line-height));font-size:var(--mat-select-trigger-text-size, var(--mat-sys-body-large-size));font-weight:var(--mat-select-trigger-text-weight, var(--mat-sys-body-large-weight));letter-spacing:var(--mat-select-trigger-text-tracking, var(--mat-sys-body-large-tracking))}div.mat-mdc-select-panel{box-shadow:var(--mat-select-container-elevation-shadow, 0px 3px 1px -2px rgba(0, 0, 0, 0.2), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 1px 5px 0px rgba(0, 0, 0, 0.12))}.mat-mdc-select-disabled{color:var(--mat-select-disabled-trigger-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-mdc-select-disabled .mat-mdc-select-placeholder{color:var(--mat-select-disabled-trigger-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-mdc-select-trigger{display:inline-flex;align-items:center;cursor:pointer;position:relative;box-sizing:border-box;width:100%}.mat-mdc-select-disabled .mat-mdc-select-trigger{-webkit-user-select:none;user-select:none;cursor:default}.mat-mdc-select-value{width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mat-mdc-select-value-text{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mat-mdc-select-arrow-wrapper{height:24px;flex-shrink:0;display:inline-flex;align-items:center}.mat-form-field-appearance-fill .mdc-text-field--no-label .mat-mdc-select-arrow-wrapper{transform:none}.mat-mdc-form-field .mat-mdc-select.mat-mdc-select-invalid .mat-mdc-select-arrow,.mat-form-field-invalid:not(.mat-form-field-disabled) .mat-mdc-form-field-infix::after{color:var(--mat-select-invalid-arrow-color, var(--mat-sys-error))}.mat-mdc-select-arrow{width:10px;height:5px;position:relative;color:var(--mat-select-enabled-arrow-color, var(--mat-sys-on-surface-variant))}.mat-mdc-form-field.mat-focused .mat-mdc-select-arrow{color:var(--mat-select-focused-arrow-color, var(--mat-sys-primary))}.mat-mdc-form-field .mat-mdc-select.mat-mdc-select-disabled .mat-mdc-select-arrow{color:var(--mat-select-disabled-arrow-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-select-open .mat-mdc-select-arrow{transform:rotate(180deg)}.mat-form-field-animations-enabled .mat-mdc-select-arrow{transition:transform 80ms linear}.mat-mdc-select-arrow svg{fill:currentColor;position:absolute;top:50%;left:50%;transform:translate(-50%, -50%)}@media(forced-colors: active){.mat-mdc-select-arrow svg{fill:CanvasText}.mat-mdc-select-disabled .mat-mdc-select-arrow svg{fill:GrayText}}div.mat-mdc-select-panel{width:100%;max-height:275px;outline:0;overflow:auto;padding:8px 0;border-radius:4px;box-sizing:border-box;position:relative;background-color:var(--mat-select-panel-background-color, var(--mat-sys-surface-container))}@media(forced-colors: active){div.mat-mdc-select-panel{outline:solid 1px}}.cdk-overlay-pane:not(.mat-mdc-select-panel-above) div.mat-mdc-select-panel{border-top-left-radius:0;border-top-right-radius:0;transform-origin:top center}.mat-mdc-select-panel-above div.mat-mdc-select-panel{border-bottom-left-radius:0;border-bottom-right-radius:0;transform-origin:bottom center}.mat-select-panel-animations-enabled{animation:_mat-select-enter 120ms cubic-bezier(0, 0, 0.2, 1)}.mat-select-panel-animations-enabled.mat-select-panel-exit{animation:_mat-select-exit 100ms linear}.mat-mdc-select-placeholder{transition:color 400ms 133.3333333333ms cubic-bezier(0.25, 0.8, 0.25, 1);color:var(--mat-select-placeholder-text-color, var(--mat-sys-on-surface-variant))}.mat-mdc-form-field:not(.mat-form-field-animations-enabled) .mat-mdc-select-placeholder,._mat-animation-noopable .mat-mdc-select-placeholder{transition:none}.mat-form-field-hide-placeholder .mat-mdc-select-placeholder{color:rgba(0,0,0,0);-webkit-text-fill-color:rgba(0,0,0,0);transition:none;display:block}.mat-mdc-form-field-type-mat-select:not(.mat-form-field-disabled) .mat-mdc-text-field-wrapper{cursor:pointer}.mat-mdc-form-field-type-mat-select.mat-form-field-appearance-fill .mat-mdc-floating-label{max-width:calc(100% - 18px)}.mat-mdc-form-field-type-mat-select.mat-form-field-appearance-fill .mdc-floating-label--float-above{max-width:calc(100%/0.75 - 24px)}.mat-mdc-form-field-type-mat-select.mat-form-field-appearance-outline .mdc-notched-outline__notch{max-width:calc(100% - 60px)}.mat-mdc-form-field-type-mat-select.mat-form-field-appearance-outline .mdc-text-field--label-floating .mdc-notched-outline__notch{max-width:calc(100% - 24px)}.mat-mdc-select-min-line:empty::before{content:\" \";white-space:pre;width:1px;display:inline-block;visibility:hidden}.mat-form-field-appearance-fill .mat-mdc-select-arrow-wrapper{transform:var(--mat-select-arrow-transform, translateY(-8px))}\n"]
|
|
961
|
+
}]
|
|
962
|
+
}],
|
|
963
|
+
ctorParameters: () => [],
|
|
964
|
+
propDecorators: {
|
|
965
|
+
options: [{
|
|
966
|
+
type: ContentChildren,
|
|
967
|
+
args: [MatOption, {
|
|
968
|
+
descendants: true
|
|
969
|
+
}]
|
|
970
|
+
}],
|
|
971
|
+
optionGroups: [{
|
|
972
|
+
type: ContentChildren,
|
|
973
|
+
args: [MAT_OPTGROUP, {
|
|
974
|
+
descendants: true
|
|
975
|
+
}]
|
|
976
|
+
}],
|
|
977
|
+
customTrigger: [{
|
|
978
|
+
type: ContentChild,
|
|
979
|
+
args: [MAT_SELECT_TRIGGER]
|
|
980
|
+
}],
|
|
981
|
+
userAriaDescribedBy: [{
|
|
982
|
+
type: Input,
|
|
983
|
+
args: ['aria-describedby']
|
|
984
|
+
}],
|
|
985
|
+
trigger: [{
|
|
986
|
+
type: ViewChild,
|
|
987
|
+
args: ['trigger']
|
|
988
|
+
}],
|
|
989
|
+
panel: [{
|
|
990
|
+
type: ViewChild,
|
|
991
|
+
args: ['panel']
|
|
992
|
+
}],
|
|
993
|
+
_overlayDir: [{
|
|
994
|
+
type: ViewChild,
|
|
995
|
+
args: [CdkConnectedOverlay]
|
|
996
|
+
}],
|
|
997
|
+
panelClass: [{
|
|
998
|
+
type: Input
|
|
999
|
+
}],
|
|
1000
|
+
disabled: [{
|
|
1001
|
+
type: Input,
|
|
1002
|
+
args: [{
|
|
1003
|
+
transform: booleanAttribute
|
|
1004
|
+
}]
|
|
1005
|
+
}],
|
|
1006
|
+
disableRipple: [{
|
|
1007
|
+
type: Input,
|
|
1008
|
+
args: [{
|
|
1009
|
+
transform: booleanAttribute
|
|
1010
|
+
}]
|
|
1011
|
+
}],
|
|
1012
|
+
tabIndex: [{
|
|
1013
|
+
type: Input,
|
|
1014
|
+
args: [{
|
|
1015
|
+
transform: value => value == null ? 0 : numberAttribute(value)
|
|
1016
|
+
}]
|
|
1017
|
+
}],
|
|
1018
|
+
hideSingleSelectionIndicator: [{
|
|
1019
|
+
type: Input,
|
|
1020
|
+
args: [{
|
|
1021
|
+
transform: booleanAttribute
|
|
1022
|
+
}]
|
|
1023
|
+
}],
|
|
1024
|
+
placeholder: [{
|
|
1025
|
+
type: Input
|
|
1026
|
+
}],
|
|
1027
|
+
required: [{
|
|
1028
|
+
type: Input,
|
|
1029
|
+
args: [{
|
|
1030
|
+
transform: booleanAttribute
|
|
1031
|
+
}]
|
|
1032
|
+
}],
|
|
1033
|
+
multiple: [{
|
|
1034
|
+
type: Input,
|
|
1035
|
+
args: [{
|
|
1036
|
+
transform: booleanAttribute
|
|
1037
|
+
}]
|
|
1038
|
+
}],
|
|
1039
|
+
disableOptionCentering: [{
|
|
1040
|
+
type: Input,
|
|
1041
|
+
args: [{
|
|
1042
|
+
transform: booleanAttribute
|
|
1043
|
+
}]
|
|
1044
|
+
}],
|
|
1045
|
+
compareWith: [{
|
|
1046
|
+
type: Input
|
|
1047
|
+
}],
|
|
1048
|
+
value: [{
|
|
1049
|
+
type: Input
|
|
1050
|
+
}],
|
|
1051
|
+
ariaLabel: [{
|
|
1052
|
+
type: Input,
|
|
1053
|
+
args: ['aria-label']
|
|
1054
|
+
}],
|
|
1055
|
+
ariaLabelledby: [{
|
|
1056
|
+
type: Input,
|
|
1057
|
+
args: ['aria-labelledby']
|
|
1058
|
+
}],
|
|
1059
|
+
errorStateMatcher: [{
|
|
1060
|
+
type: Input
|
|
1061
|
+
}],
|
|
1062
|
+
typeaheadDebounceInterval: [{
|
|
1063
|
+
type: Input,
|
|
1064
|
+
args: [{
|
|
1065
|
+
transform: numberAttribute
|
|
1066
|
+
}]
|
|
1067
|
+
}],
|
|
1068
|
+
sortComparator: [{
|
|
1069
|
+
type: Input
|
|
1070
|
+
}],
|
|
1071
|
+
id: [{
|
|
1072
|
+
type: Input
|
|
1073
|
+
}],
|
|
1074
|
+
panelWidth: [{
|
|
1075
|
+
type: Input
|
|
1076
|
+
}],
|
|
1077
|
+
canSelectNullableOptions: [{
|
|
1078
|
+
type: Input,
|
|
1079
|
+
args: [{
|
|
1080
|
+
transform: booleanAttribute
|
|
1081
|
+
}]
|
|
1082
|
+
}],
|
|
1083
|
+
openedChange: [{
|
|
1084
|
+
type: Output
|
|
1085
|
+
}],
|
|
1086
|
+
_openedStream: [{
|
|
1087
|
+
type: Output,
|
|
1088
|
+
args: ['opened']
|
|
1089
|
+
}],
|
|
1090
|
+
_closedStream: [{
|
|
1091
|
+
type: Output,
|
|
1092
|
+
args: ['closed']
|
|
1093
|
+
}],
|
|
1094
|
+
selectionChange: [{
|
|
1095
|
+
type: Output
|
|
1096
|
+
}],
|
|
1097
|
+
valueChange: [{
|
|
1098
|
+
type: Output
|
|
1099
|
+
}]
|
|
1100
|
+
}
|
|
1101
|
+
});
|
|
1270
1102
|
class MatSelectTrigger {
|
|
1271
|
-
|
|
1272
|
-
|
|
1103
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
1104
|
+
minVersion: "12.0.0",
|
|
1105
|
+
version: "20.2.0-next.2",
|
|
1106
|
+
ngImport: i0,
|
|
1107
|
+
type: MatSelectTrigger,
|
|
1108
|
+
deps: [],
|
|
1109
|
+
target: i0.ɵɵFactoryTarget.Directive
|
|
1110
|
+
});
|
|
1111
|
+
static ɵdir = i0.ɵɵngDeclareDirective({
|
|
1112
|
+
minVersion: "14.0.0",
|
|
1113
|
+
version: "20.2.0-next.2",
|
|
1114
|
+
type: MatSelectTrigger,
|
|
1115
|
+
isStandalone: true,
|
|
1116
|
+
selector: "mat-select-trigger",
|
|
1117
|
+
providers: [{
|
|
1118
|
+
provide: MAT_SELECT_TRIGGER,
|
|
1119
|
+
useExisting: MatSelectTrigger
|
|
1120
|
+
}],
|
|
1121
|
+
ngImport: i0
|
|
1122
|
+
});
|
|
1273
1123
|
}
|
|
1274
|
-
i0.ɵɵngDeclareClassMetadata({
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1124
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
1125
|
+
minVersion: "12.0.0",
|
|
1126
|
+
version: "20.2.0-next.2",
|
|
1127
|
+
ngImport: i0,
|
|
1128
|
+
type: MatSelectTrigger,
|
|
1129
|
+
decorators: [{
|
|
1130
|
+
type: Directive,
|
|
1131
|
+
args: [{
|
|
1132
|
+
selector: 'mat-select-trigger',
|
|
1133
|
+
providers: [{
|
|
1134
|
+
provide: MAT_SELECT_TRIGGER,
|
|
1135
|
+
useExisting: MatSelectTrigger
|
|
1136
|
+
}]
|
|
1137
|
+
}]
|
|
1138
|
+
}]
|
|
1139
|
+
});
|
|
1281
1140
|
|
|
1282
1141
|
class MatSelectModule {
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1142
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
1143
|
+
minVersion: "12.0.0",
|
|
1144
|
+
version: "20.2.0-next.2",
|
|
1145
|
+
ngImport: i0,
|
|
1146
|
+
type: MatSelectModule,
|
|
1147
|
+
deps: [],
|
|
1148
|
+
target: i0.ɵɵFactoryTarget.NgModule
|
|
1149
|
+
});
|
|
1150
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({
|
|
1151
|
+
minVersion: "14.0.0",
|
|
1152
|
+
version: "20.2.0-next.2",
|
|
1153
|
+
ngImport: i0,
|
|
1154
|
+
type: MatSelectModule,
|
|
1155
|
+
imports: [OverlayModule, MatOptionModule, MatSelect, MatSelectTrigger],
|
|
1156
|
+
exports: [BidiModule, CdkScrollableModule, MatFormFieldModule, MatSelect, MatSelectTrigger, MatOptionModule]
|
|
1157
|
+
});
|
|
1158
|
+
static ɵinj = i0.ɵɵngDeclareInjector({
|
|
1159
|
+
minVersion: "12.0.0",
|
|
1160
|
+
version: "20.2.0-next.2",
|
|
1161
|
+
ngImport: i0,
|
|
1162
|
+
type: MatSelectModule,
|
|
1163
|
+
imports: [OverlayModule, MatOptionModule, BidiModule, CdkScrollableModule, MatFormFieldModule, MatOptionModule]
|
|
1164
|
+
});
|
|
1294
1165
|
}
|
|
1295
|
-
i0.ɵɵngDeclareClassMetadata({
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
}] });
|
|
1166
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
1167
|
+
minVersion: "12.0.0",
|
|
1168
|
+
version: "20.2.0-next.2",
|
|
1169
|
+
ngImport: i0,
|
|
1170
|
+
type: MatSelectModule,
|
|
1171
|
+
decorators: [{
|
|
1172
|
+
type: NgModule,
|
|
1173
|
+
args: [{
|
|
1174
|
+
imports: [OverlayModule, MatOptionModule, MatSelect, MatSelectTrigger],
|
|
1175
|
+
exports: [BidiModule, CdkScrollableModule, MatFormFieldModule, MatSelect, MatSelectTrigger, MatOptionModule]
|
|
1176
|
+
}]
|
|
1177
|
+
}]
|
|
1178
|
+
});
|
|
1309
1179
|
|
|
1310
1180
|
export { MAT_SELECT_CONFIG, MAT_SELECT_SCROLL_STRATEGY, MAT_SELECT_TRIGGER, MatOption, MatSelect, MatSelectChange, MatSelectModule, MatSelectTrigger };
|
|
1311
1181
|
//# sourceMappingURL=select.mjs.map
|