@angular/material 21.0.0-next.0 → 21.0.0-next.2

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