@momentum-design/components 0.117.0 → 0.117.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/index.js +271 -275
- package/dist/browser/index.js.map +3 -3
- package/dist/components/option/option.component.js +4 -7
- package/dist/components/select/select.component.d.ts +39 -46
- package/dist/components/select/select.component.js +155 -156
- package/dist/components/toast/index.d.ts +0 -1
- package/dist/components/toast/index.js +0 -1
- package/dist/components/toast/toast.component.d.ts +2 -1
- package/dist/components/toast/toast.component.js +6 -4
- package/dist/custom-elements.json +3226 -3194
- package/dist/react/index.d.ts +3 -3
- package/dist/react/index.js +3 -3
- package/dist/react/select/index.d.ts +1 -0
- package/dist/react/select/index.js +1 -0
- package/dist/react/toast/index.d.ts +0 -1
- package/dist/react/toast/index.js +0 -1
- package/dist/utils/controllers/ElementStore.d.ts +1 -1
- package/dist/utils/mixins/ListNavigationMixin.js +2 -1
- package/package.json +1 -1
@@ -11,6 +11,7 @@ import { html, nothing } from 'lit';
|
|
11
11
|
import { property } from 'lit/decorators.js';
|
12
12
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
13
13
|
import { FormInternalsMixin } from '../../utils/mixins/FormInternalsMixin';
|
14
|
+
import { ROLE } from '../../utils/roles';
|
14
15
|
import ListItem from '../listitem/listitem.component';
|
15
16
|
import { LISTITEM_VARIANTS } from '../listitem/listitem.constants';
|
16
17
|
import { TYPE } from '../text/text.constants';
|
@@ -55,7 +56,7 @@ class Option extends FormInternalsMixin(ListItem) {
|
|
55
56
|
}
|
56
57
|
connectedCallback() {
|
57
58
|
super.connectedCallback();
|
58
|
-
this.role =
|
59
|
+
this.role = ROLE.OPTION;
|
59
60
|
this.variant = LISTITEM_VARIANTS.INSET_RECTANGLE;
|
60
61
|
this.setAttribute('aria-selected', `${this.selected}`);
|
61
62
|
this.setAttribute('aria-disabled', `${!!this.disabled}`);
|
@@ -80,9 +81,7 @@ class Option extends FormInternalsMixin(ListItem) {
|
|
80
81
|
`
|
81
82
|
: nothing;
|
82
83
|
const trailingContent = this.selected
|
83
|
-
? html `
|
84
|
-
<mdc-icon length-unit="rem" slot="trailing-controls" name="${SELECTED_ICON_NAME}"></mdc-icon>
|
85
|
-
`
|
84
|
+
? html ` <mdc-icon length-unit="rem" slot="trailing-controls" name="${SELECTED_ICON_NAME}"></mdc-icon> `
|
86
85
|
: nothing;
|
87
86
|
return html `
|
88
87
|
${prefixIconContent}
|
@@ -90,9 +89,7 @@ class Option extends FormInternalsMixin(ListItem) {
|
|
90
89
|
${this.getText('leading-text-primary-label', TYPE.BODY_MIDSIZE_REGULAR, this.label)}
|
91
90
|
${this.getText('leading-text-secondary-label', TYPE.BODY_SMALL_REGULAR, this.secondaryLabel)}
|
92
91
|
</div>
|
93
|
-
<div part="trailing">
|
94
|
-
${trailingContent}
|
95
|
-
</div>
|
92
|
+
<div part="trailing">${trailingContent}</div>
|
96
93
|
`;
|
97
94
|
}
|
98
95
|
}
|
@@ -3,8 +3,9 @@ import { CSSResult } from 'lit';
|
|
3
3
|
import { AssociatedFormControl } from '../../utils/mixins/FormInternalsMixin';
|
4
4
|
import FormfieldWrapper from '../formfieldwrapper/formfieldwrapper.component';
|
5
5
|
import type Option from '../option/option.component';
|
6
|
+
import type { PopoverStrategy } from '../popover/popover.types';
|
6
7
|
import type { Placement } from './select.types';
|
7
|
-
declare const Select_base: import("../../utils/mixins/index.types").Constructor<import("../../models/component/component.component").default & import("../../utils/mixins/AutoFocusOnMountMixin").AutoFocusOnMountMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/FormInternalsMixin").FormInternalsMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/DataAriaLabelMixin").DataAriaLabelMixinInterface> & typeof FormfieldWrapper;
|
8
|
+
declare const Select_base: import("../../utils/mixins/index.types").Constructor<import("../../models/component/component.component").default & import("../../utils/mixins/ListNavigationMixin").ListNavigationMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/lifecycle/CaptureDestroyEventForChildElement").CaptureDestroyEventForChildElementInterface> & import("../../utils/mixins/index.types").Constructor<import("../../models/component/component.component").default & import("../../utils/mixins/AutoFocusOnMountMixin").AutoFocusOnMountMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/FormInternalsMixin").FormInternalsMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/DataAriaLabelMixin").DataAriaLabelMixinInterface> & typeof FormfieldWrapper;
|
8
9
|
/**
|
9
10
|
* The mdc-select component is a dropdown selection control that allows users to pick an option from a predefined list.
|
10
11
|
* It is designed to work with `mdc-option` for individual options and `mdc-optgroup` for grouping related options.
|
@@ -12,6 +13,7 @@ declare const Select_base: import("../../utils/mixins/index.types").Constructor<
|
|
12
13
|
* Every mdc-option should have a `value` attribute set to ensure proper form submission.
|
13
14
|
*
|
14
15
|
* To set a default option, use the `selected` attribute on the `mdc-option` element.
|
16
|
+
* You can also set the `value` attribute on the `mdc-select` element to match the value of the desired option. The component will select the corresponding option automatically.
|
15
17
|
*
|
16
18
|
* **Note:** Make sure to add `mdc-selectlistbox` as a child of `mdc-select` and wrap options/optgroup in it to ensure proper accessibility functionality. Read more about it in SelectListBox documentation.
|
17
19
|
*
|
@@ -60,7 +62,13 @@ declare class Select extends Select_base implements AssociatedFormControl {
|
|
60
62
|
*/
|
61
63
|
readonly: boolean;
|
62
64
|
/**
|
63
|
-
* The
|
65
|
+
* The placement of the popover within Select component.
|
66
|
+
* This defines the position of the popover relative to the select input field.
|
67
|
+
*
|
68
|
+
* Possible values:
|
69
|
+
* - 'top-start'
|
70
|
+
* - 'bottom-start'
|
71
|
+
* @default 'bottom-start'
|
64
72
|
*/
|
65
73
|
placement: Placement;
|
66
74
|
/**
|
@@ -96,7 +104,7 @@ declare class Select extends Select_base implements AssociatedFormControl {
|
|
96
104
|
* @default absolute
|
97
105
|
* @see [Floating UI - strategy](https://floating-ui.com/docs/computePosition#strategy)
|
98
106
|
*/
|
99
|
-
strategy:
|
107
|
+
strategy: PopoverStrategy;
|
100
108
|
/**
|
101
109
|
* The z-index of the popover within Select.
|
102
110
|
*
|
@@ -111,8 +119,6 @@ declare class Select extends Select_base implements AssociatedFormControl {
|
|
111
119
|
*/
|
112
120
|
backdropAppendTo?: string;
|
113
121
|
/** @internal */
|
114
|
-
slottedListboxes: Array<HTMLElement>;
|
115
|
-
/** @internal */
|
116
122
|
private visualCombobox;
|
117
123
|
/** @internal */
|
118
124
|
selectedOption?: Option | null;
|
@@ -120,10 +126,35 @@ declare class Select extends Select_base implements AssociatedFormControl {
|
|
120
126
|
displayPopover: boolean;
|
121
127
|
/** @internal */
|
122
128
|
private initialSelectedOption;
|
123
|
-
|
124
|
-
private
|
125
|
-
|
129
|
+
/** @internal */
|
130
|
+
private itemsStore;
|
131
|
+
constructor();
|
132
|
+
connectedCallback(): void;
|
133
|
+
/** @internal */
|
134
|
+
get navItems(): Option[];
|
135
|
+
/**
|
136
|
+
* This function is called when the value attribute changes.
|
137
|
+
* It updates the selected option based on the value attribute.
|
138
|
+
*
|
139
|
+
* @param name - attribute name
|
140
|
+
* @param old - old value
|
141
|
+
* @param value - new value
|
142
|
+
*/
|
143
|
+
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
|
144
|
+
/** @internal */
|
145
|
+
private onStoreUpdate;
|
146
|
+
/** @internal */
|
147
|
+
private isValidItem;
|
148
|
+
/** @internal */
|
126
149
|
private getFirstSelectedOption;
|
150
|
+
/** @internal */
|
151
|
+
private getFirstOption;
|
152
|
+
/**
|
153
|
+
* Update the selected option when an option is modified.
|
154
|
+
*
|
155
|
+
* @internal
|
156
|
+
*/
|
157
|
+
private handleModifiedEvent;
|
127
158
|
/**
|
128
159
|
* Handles the first updated lifecycle event.
|
129
160
|
* If an option is selected, use that as the value.
|
@@ -131,15 +162,6 @@ declare class Select extends Select_base implements AssociatedFormControl {
|
|
131
162
|
*/
|
132
163
|
protected firstUpdated(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): Promise<void>;
|
133
164
|
updated(changedProperties: PropertyValues): void;
|
134
|
-
/**
|
135
|
-
* Modifies the listbox wrapper to ensure it has the correct attributes
|
136
|
-
* and IDs for accessibility.
|
137
|
-
*
|
138
|
-
* Once [ariaOwnsElements](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/ariaOwnsElements) is supported in browsers,
|
139
|
-
* this an be removed and mdc-option can be used directly in the select component with a listbox in a different
|
140
|
-
* shadow root and aria-owns attribute to connect them.
|
141
|
-
*/
|
142
|
-
private modifyListBoxWrapper;
|
143
165
|
/**
|
144
166
|
* A private method which is called when an option is clicked.
|
145
167
|
* It sets the selected option, removes selected from other options, updates the tabindex for all options,
|
@@ -157,13 +179,6 @@ declare class Select extends Select_base implements AssociatedFormControl {
|
|
157
179
|
* @param option - The option element in DOM which gets selected.
|
158
180
|
*/
|
159
181
|
private setSelectedOption;
|
160
|
-
/**
|
161
|
-
* Updates the tabindex of all options.
|
162
|
-
* Sets the tabindex of the selected option to '0' and others to '-1'.
|
163
|
-
*
|
164
|
-
* @param option - The option which tabIndex should be set to 0.
|
165
|
-
*/
|
166
|
-
private updateTabIndexForAllOptions;
|
167
182
|
/**
|
168
183
|
* Sets selected attribute on the selected option and removes it from all options
|
169
184
|
* @param selectedOption - The option which gets selected
|
@@ -212,21 +227,6 @@ declare class Select extends Select_base implements AssociatedFormControl {
|
|
212
227
|
* @param event - The keyboard event.
|
213
228
|
*/
|
214
229
|
private handleKeydownCombobox;
|
215
|
-
/**
|
216
|
-
* Handles the keydown event on the select element when the popover is open.
|
217
|
-
* The options are as follows:
|
218
|
-
* - HOME: Sets focus and tabindex on the first option.
|
219
|
-
* - END: Sets focus and tabindex on the last option.
|
220
|
-
* - ARROW_DOWN, ARROW_UP, PAGE_DOWN, PAGE_UP: Handles navigation between options.
|
221
|
-
* @param event - The keyboard event.
|
222
|
-
*/
|
223
|
-
private handlePopoverKeydown;
|
224
|
-
/**
|
225
|
-
* Focuses the given option and updates the tabindex for all options.
|
226
|
-
* @param option - The option to focus.
|
227
|
-
* @internal
|
228
|
-
*/
|
229
|
-
private focusAndUpdateTabIndexes;
|
230
230
|
/**
|
231
231
|
* If the native input is focused, it will focus the visual combobox.
|
232
232
|
* This is to ensure that the visual combobox is focused when the native input is focused.
|
@@ -236,13 +236,6 @@ declare class Select extends Select_base implements AssociatedFormControl {
|
|
236
236
|
* @internal
|
237
237
|
*/
|
238
238
|
private handleNativeInputFocus;
|
239
|
-
/**
|
240
|
-
* Updates the state of the select component.
|
241
|
-
* This public method should be fired when the selected on the option components is updated from the outside.
|
242
|
-
* It ensures that the selected attribute is set correctly on the options
|
243
|
-
* and that the aria-selected attribute is updated accordingly.
|
244
|
-
*/
|
245
|
-
updateState(): void;
|
246
239
|
render(): import("lit-html").TemplateResult<1>;
|
247
240
|
static styles: Array<CSSResult>;
|
248
241
|
}
|
@@ -8,17 +8,21 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
8
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
9
9
|
};
|
10
10
|
import { html, nothing } from 'lit';
|
11
|
-
import { property, query,
|
11
|
+
import { property, query, state } from 'lit/decorators.js';
|
12
12
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
13
|
+
import { ElementStore } from '../../utils/controllers/ElementStore';
|
13
14
|
import { KEYS } from '../../utils/keys';
|
14
|
-
import { DataAriaLabelMixin } from '../../utils/mixins/DataAriaLabelMixin';
|
15
15
|
import { AutoFocusOnMountMixin } from '../../utils/mixins/AutoFocusOnMountMixin';
|
16
|
+
import { DataAriaLabelMixin } from '../../utils/mixins/DataAriaLabelMixin';
|
16
17
|
import { FormInternalsMixin } from '../../utils/mixins/FormInternalsMixin';
|
18
|
+
import { CaptureDestroyEventForChildElement } from '../../utils/mixins/lifecycle/CaptureDestroyEventForChildElement';
|
19
|
+
import { LIFE_CYCLE_EVENTS } from '../../utils/mixins/lifecycle/lifecycle.contants';
|
20
|
+
import { ListNavigationMixin } from '../../utils/mixins/ListNavigationMixin';
|
17
21
|
import { ROLE } from '../../utils/roles';
|
18
22
|
import FormfieldWrapper from '../formfieldwrapper/formfieldwrapper.component';
|
19
23
|
import { DEFAULTS as FORMFIELD_DEFAULTS, VALIDATION } from '../formfieldwrapper/formfieldwrapper.constants';
|
20
24
|
import { TAG_NAME as OPTION_TAG_NAME } from '../option/option.constants';
|
21
|
-
import {
|
25
|
+
import { DEFAULTS as POPOVER_DEFAULTS, POPOVER_PLACEMENT } from '../popover/popover.constants';
|
22
26
|
import { TYPE, VALID_TEXT_TAGS } from '../text/text.constants';
|
23
27
|
import { ARROW_ICON, LISTBOX_ID, TRIGGER_ID } from './select.constants';
|
24
28
|
import styles from './select.styles';
|
@@ -29,6 +33,7 @@ import styles from './select.styles';
|
|
29
33
|
* Every mdc-option should have a `value` attribute set to ensure proper form submission.
|
30
34
|
*
|
31
35
|
* To set a default option, use the `selected` attribute on the `mdc-option` element.
|
36
|
+
* You can also set the `value` attribute on the `mdc-select` element to match the value of the desired option. The component will select the corresponding option automatically.
|
32
37
|
*
|
33
38
|
* **Note:** Make sure to add `mdc-selectlistbox` as a child of `mdc-select` and wrap options/optgroup in it to ensure proper accessibility functionality. Read more about it in SelectListBox documentation.
|
34
39
|
*
|
@@ -66,16 +71,22 @@ import styles from './select.styles';
|
|
66
71
|
* @cssproperty --mdc-select-listbox-height - The height of the listbox inside the select.
|
67
72
|
* @cssproperty --mdc-select-listbox-width - The width of the listbox inside the select (default: `--mdc-select-width`).
|
68
73
|
*/
|
69
|
-
class Select extends AutoFocusOnMountMixin(FormInternalsMixin(DataAriaLabelMixin(FormfieldWrapper))) {
|
74
|
+
class Select extends ListNavigationMixin(CaptureDestroyEventForChildElement(AutoFocusOnMountMixin(FormInternalsMixin(DataAriaLabelMixin(FormfieldWrapper))))) {
|
70
75
|
constructor() {
|
71
|
-
super(
|
76
|
+
super();
|
72
77
|
/**
|
73
78
|
* readonly attribute of the select field. If true, the select is read-only.
|
74
79
|
* @default false
|
75
80
|
*/
|
76
81
|
this.readonly = false;
|
77
82
|
/**
|
78
|
-
* The
|
83
|
+
* The placement of the popover within Select component.
|
84
|
+
* This defines the position of the popover relative to the select input field.
|
85
|
+
*
|
86
|
+
* Possible values:
|
87
|
+
* - 'top-start'
|
88
|
+
* - 'bottom-start'
|
89
|
+
* @default 'bottom-start'
|
79
90
|
*/
|
80
91
|
this.placement = POPOVER_PLACEMENT.BOTTOM_START;
|
81
92
|
/**
|
@@ -115,22 +126,141 @@ class Select extends AutoFocusOnMountMixin(FormInternalsMixin(DataAriaLabelMixin
|
|
115
126
|
this.displayPopover = false;
|
116
127
|
/** @internal */
|
117
128
|
this.initialSelectedOption = null;
|
129
|
+
/** @internal */
|
130
|
+
this.itemsStore = new ElementStore(this, {
|
131
|
+
isValidItem: this.isValidItem,
|
132
|
+
onStoreUpdate: this.onStoreUpdate,
|
133
|
+
});
|
134
|
+
this.addEventListener(LIFE_CYCLE_EVENTS.MODIFIED, this.handleModifiedEvent);
|
118
135
|
}
|
119
|
-
|
120
|
-
|
121
|
-
|
136
|
+
connectedCallback() {
|
137
|
+
super.connectedCallback();
|
138
|
+
this.loop = 'false';
|
139
|
+
this.initialFocus = 0;
|
122
140
|
}
|
123
|
-
|
141
|
+
/** @internal */
|
142
|
+
get navItems() {
|
143
|
+
return this.itemsStore.items;
|
144
|
+
}
|
145
|
+
/**
|
146
|
+
* This function is called when the value attribute changes.
|
147
|
+
* It updates the selected option based on the value attribute.
|
148
|
+
*
|
149
|
+
* @param name - attribute name
|
150
|
+
* @param old - old value
|
151
|
+
* @param value - new value
|
152
|
+
*/
|
153
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
124
154
|
var _a;
|
125
|
-
|
155
|
+
super.attributeChangedCallback(name, oldValue, newValue);
|
156
|
+
if (name === 'value' &&
|
157
|
+
newValue !== '' &&
|
158
|
+
newValue !== oldValue &&
|
159
|
+
newValue !== ((_a = this.selectedOption) === null || _a === void 0 ? void 0 : _a.value) &&
|
160
|
+
this.navItems.length) {
|
161
|
+
const firstSelectedOption = this.getFirstSelectedOption();
|
162
|
+
const firstValidOption = this.getFirstOption();
|
163
|
+
const valueBasedOption = this.navItems.find(option => option.value === newValue);
|
164
|
+
let optionToSelect = null;
|
165
|
+
if (valueBasedOption) {
|
166
|
+
optionToSelect = valueBasedOption;
|
167
|
+
}
|
168
|
+
else if (this.placeholder) {
|
169
|
+
optionToSelect = null;
|
170
|
+
}
|
171
|
+
else if (firstValidOption) {
|
172
|
+
optionToSelect = firstValidOption;
|
173
|
+
}
|
174
|
+
else if (firstSelectedOption) {
|
175
|
+
optionToSelect = firstSelectedOption;
|
176
|
+
}
|
177
|
+
else {
|
178
|
+
return;
|
179
|
+
}
|
180
|
+
this.updateComplete
|
181
|
+
.then(() => {
|
182
|
+
this.setSelectedOption(optionToSelect);
|
183
|
+
})
|
184
|
+
.catch(error => {
|
185
|
+
if (this.onerror) {
|
186
|
+
this.onerror(error);
|
187
|
+
}
|
188
|
+
});
|
189
|
+
}
|
126
190
|
}
|
127
|
-
|
128
|
-
|
129
|
-
|
191
|
+
/** @internal */
|
192
|
+
onStoreUpdate(option, changeType, index) {
|
193
|
+
switch (changeType) {
|
194
|
+
case 'added':
|
195
|
+
option.setAttribute('tabindex', '-1');
|
196
|
+
break;
|
197
|
+
case 'removed': {
|
198
|
+
if (index === -1 || option.tabIndex !== 0) {
|
199
|
+
return;
|
200
|
+
}
|
201
|
+
let newIndex = index + 1;
|
202
|
+
if (newIndex >= this.navItems.length) {
|
203
|
+
newIndex = index - 1;
|
204
|
+
}
|
205
|
+
if (newIndex === -1) {
|
206
|
+
this.displayPopover = false;
|
207
|
+
this.handleNativeInputFocus();
|
208
|
+
return;
|
209
|
+
}
|
210
|
+
this.resetTabIndexes(newIndex);
|
211
|
+
break;
|
212
|
+
}
|
213
|
+
default:
|
214
|
+
break;
|
215
|
+
}
|
216
|
+
}
|
217
|
+
/** @internal */
|
218
|
+
isValidItem(item) {
|
219
|
+
return item.matches(`${OPTION_TAG_NAME}:not([disabled])`);
|
130
220
|
}
|
221
|
+
/** @internal */
|
131
222
|
getFirstSelectedOption() {
|
132
|
-
|
133
|
-
|
223
|
+
return this.navItems.find(option => option.hasAttribute('selected'));
|
224
|
+
}
|
225
|
+
/** @internal */
|
226
|
+
getFirstOption() {
|
227
|
+
return this.navItems[0];
|
228
|
+
}
|
229
|
+
/**
|
230
|
+
* Update the selected option when an option is modified.
|
231
|
+
*
|
232
|
+
* @internal
|
233
|
+
*/
|
234
|
+
handleModifiedEvent(event) {
|
235
|
+
const option = event.target;
|
236
|
+
const firstSelectedOption = this.getFirstSelectedOption();
|
237
|
+
switch (event.detail.change) {
|
238
|
+
case 'selected': {
|
239
|
+
// when selected, check if there is any other option is a selected option,
|
240
|
+
// first preference should always be given to the `selected` attribute.
|
241
|
+
// if there is no selected option, then reset it to placeholder or first option
|
242
|
+
if (firstSelectedOption) {
|
243
|
+
this.setSelectedOption(firstSelectedOption);
|
244
|
+
}
|
245
|
+
else {
|
246
|
+
this.setSelectedOption(option);
|
247
|
+
}
|
248
|
+
break;
|
249
|
+
}
|
250
|
+
case 'unselected': {
|
251
|
+
// when unselected, check if there is any other option is a selected option,
|
252
|
+
// if there is no selected option, then reset it to placeholder or first option
|
253
|
+
if (firstSelectedOption) {
|
254
|
+
this.setSelectedOption(firstSelectedOption);
|
255
|
+
}
|
256
|
+
else {
|
257
|
+
this.setSelectedOption(this.placeholder ? null : this.getFirstOption());
|
258
|
+
}
|
259
|
+
break;
|
260
|
+
}
|
261
|
+
default:
|
262
|
+
break;
|
263
|
+
}
|
134
264
|
}
|
135
265
|
/**
|
136
266
|
* Handles the first updated lifecycle event.
|
@@ -139,7 +269,6 @@ class Select extends AutoFocusOnMountMixin(FormInternalsMixin(DataAriaLabelMixin
|
|
139
269
|
*/
|
140
270
|
async firstUpdated(_changedProperties) {
|
141
271
|
await this.updateComplete;
|
142
|
-
this.modifyListBoxWrapper();
|
143
272
|
const firstSelectedOption = this.getFirstSelectedOption();
|
144
273
|
if (firstSelectedOption) {
|
145
274
|
this.initialSelectedOption = firstSelectedOption;
|
@@ -148,7 +277,7 @@ class Select extends AutoFocusOnMountMixin(FormInternalsMixin(DataAriaLabelMixin
|
|
148
277
|
this.setSelectedOption(firstSelectedOption);
|
149
278
|
}
|
150
279
|
else if (!this.placeholder) {
|
151
|
-
const firstValidOption = this.
|
280
|
+
const firstValidOption = this.getFirstOption();
|
152
281
|
// We will show the first option as selected & fire
|
153
282
|
// and event since the selected option changed
|
154
283
|
this.setSelectedOption(firstValidOption);
|
@@ -178,26 +307,6 @@ class Select extends AutoFocusOnMountMixin(FormInternalsMixin(DataAriaLabelMixin
|
|
178
307
|
this.displayPopover = false;
|
179
308
|
}
|
180
309
|
}
|
181
|
-
if (changedProperties.has('dataAriaLabel')) {
|
182
|
-
this.modifyListBoxWrapper();
|
183
|
-
}
|
184
|
-
}
|
185
|
-
/**
|
186
|
-
* Modifies the listbox wrapper to ensure it has the correct attributes
|
187
|
-
* and IDs for accessibility.
|
188
|
-
*
|
189
|
-
* Once [ariaOwnsElements](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/ariaOwnsElements) is supported in browsers,
|
190
|
-
* this an be removed and mdc-option can be used directly in the select component with a listbox in a different
|
191
|
-
* shadow root and aria-owns attribute to connect them.
|
192
|
-
*/
|
193
|
-
modifyListBoxWrapper() {
|
194
|
-
const slottedListBox = this.slottedListboxes[0];
|
195
|
-
if (!slottedListBox) {
|
196
|
-
return;
|
197
|
-
}
|
198
|
-
slottedListBox.setAttribute('id', LISTBOX_ID);
|
199
|
-
slottedListBox.setAttribute('aria-label', this.dataAriaLabel || '');
|
200
|
-
slottedListBox.setAttribute('aria-labelledby', TRIGGER_ID);
|
201
310
|
}
|
202
311
|
/**
|
203
312
|
* A private method which is called when an option is clicked.
|
@@ -227,10 +336,13 @@ class Select extends AutoFocusOnMountMixin(FormInternalsMixin(DataAriaLabelMixin
|
|
227
336
|
*/
|
228
337
|
setSelectedOption(option) {
|
229
338
|
var _a, _b, _c;
|
339
|
+
// if the options is already selected, return
|
340
|
+
if (option === this.selectedOption)
|
341
|
+
return;
|
230
342
|
// set the attribute 'selected' on the option in HTML and remove it from others
|
231
343
|
this.updateSelectedInChildOptions(option);
|
232
344
|
// update the tabindex for all options
|
233
|
-
this.
|
345
|
+
this.resetTabIndexes(this.navItems.indexOf(option));
|
234
346
|
// set the selected option in the component state
|
235
347
|
this.selectedOption = option;
|
236
348
|
// update all form related values
|
@@ -239,27 +351,13 @@ class Select extends AutoFocusOnMountMixin(FormInternalsMixin(DataAriaLabelMixin
|
|
239
351
|
(_c = this.inputElement) === null || _c === void 0 ? void 0 : _c.setAttribute('value', this.value);
|
240
352
|
this.setInputValidity();
|
241
353
|
}
|
242
|
-
/**
|
243
|
-
* Updates the tabindex of all options.
|
244
|
-
* Sets the tabindex of the selected option to '0' and others to '-1'.
|
245
|
-
*
|
246
|
-
* @param option - The option which tabIndex should be set to 0.
|
247
|
-
*/
|
248
|
-
updateTabIndexForAllOptions(option) {
|
249
|
-
const options = this.getAllValidOptions();
|
250
|
-
const optionToGetTabIndex0 = option || options[0];
|
251
|
-
options.forEach(option => {
|
252
|
-
option.setAttribute('tabindex', option === optionToGetTabIndex0 ? '0' : '-1');
|
253
|
-
});
|
254
|
-
}
|
255
354
|
/**
|
256
355
|
* Sets selected attribute on the selected option and removes it from all options
|
257
356
|
* @param selectedOption - The option which gets selected
|
258
357
|
*/
|
259
358
|
updateSelectedInChildOptions(selectedOption) {
|
260
359
|
selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.setAttribute('selected', 'true');
|
261
|
-
|
262
|
-
options.forEach(option => {
|
360
|
+
this.navItems.forEach(option => {
|
263
361
|
if (option !== selectedOption) {
|
264
362
|
option.removeAttribute('selected');
|
265
363
|
}
|
@@ -309,7 +407,7 @@ class Select extends AutoFocusOnMountMixin(FormInternalsMixin(DataAriaLabelMixin
|
|
309
407
|
/** @internal */
|
310
408
|
formStateRestoreCallback(state) {
|
311
409
|
var _a;
|
312
|
-
const optionToRestoreTo = this.
|
410
|
+
const optionToRestoreTo = this.navItems.find(option => option.value === state || option.label === state);
|
313
411
|
if (((_a = this.selectedOption) === null || _a === void 0 ? void 0 : _a.value) !== (optionToRestoreTo === null || optionToRestoreTo === void 0 ? void 0 : optionToRestoreTo.value)) {
|
314
412
|
this.setSelectedOption(optionToRestoreTo || null);
|
315
413
|
// fire events to notify the change in case of restore
|
@@ -376,21 +474,13 @@ class Select extends AutoFocusOnMountMixin(FormInternalsMixin(DataAriaLabelMixin
|
|
376
474
|
break;
|
377
475
|
case KEYS.HOME: {
|
378
476
|
this.displayPopover = true;
|
379
|
-
|
380
|
-
if (firstOption) {
|
381
|
-
firstOption === null || firstOption === void 0 ? void 0 : firstOption.focus();
|
382
|
-
this.updateTabIndexForAllOptions(firstOption);
|
383
|
-
}
|
477
|
+
this.resetTabIndexAndSetFocus(0);
|
384
478
|
event.preventDefault();
|
385
479
|
break;
|
386
480
|
}
|
387
481
|
case KEYS.END: {
|
388
482
|
this.displayPopover = true;
|
389
|
-
|
390
|
-
if (lastOption) {
|
391
|
-
lastOption.focus();
|
392
|
-
this.updateTabIndexForAllOptions(lastOption);
|
393
|
-
}
|
483
|
+
this.resetTabIndexAndSetFocus(this.navItems.length - 1);
|
394
484
|
event.preventDefault();
|
395
485
|
break;
|
396
486
|
}
|
@@ -398,73 +488,6 @@ class Select extends AutoFocusOnMountMixin(FormInternalsMixin(DataAriaLabelMixin
|
|
398
488
|
break;
|
399
489
|
}
|
400
490
|
}
|
401
|
-
/**
|
402
|
-
* Handles the keydown event on the select element when the popover is open.
|
403
|
-
* The options are as follows:
|
404
|
-
* - HOME: Sets focus and tabindex on the first option.
|
405
|
-
* - END: Sets focus and tabindex on the last option.
|
406
|
-
* - ARROW_DOWN, ARROW_UP, PAGE_DOWN, PAGE_UP: Handles navigation between options.
|
407
|
-
* @param event - The keyboard event.
|
408
|
-
*/
|
409
|
-
handlePopoverKeydown(event) {
|
410
|
-
let optionToFocus = null;
|
411
|
-
switch (event.key) {
|
412
|
-
case KEYS.HOME: {
|
413
|
-
optionToFocus = this.getFirstValidOption();
|
414
|
-
break;
|
415
|
-
}
|
416
|
-
case KEYS.END: {
|
417
|
-
optionToFocus = this.getLastValidOption();
|
418
|
-
break;
|
419
|
-
}
|
420
|
-
case KEYS.ARROW_DOWN: {
|
421
|
-
const options = this.getAllValidOptions();
|
422
|
-
const currentIndex = options.findIndex(option => option === event.target);
|
423
|
-
const newIndex = Math.min(currentIndex + 1, options.length - 1);
|
424
|
-
optionToFocus = options[newIndex];
|
425
|
-
break;
|
426
|
-
}
|
427
|
-
case KEYS.ARROW_UP: {
|
428
|
-
const options = this.getAllValidOptions();
|
429
|
-
const currentIndex = options.findIndex(option => option === event.target);
|
430
|
-
const newIndex = Math.max(currentIndex - 1, 0);
|
431
|
-
optionToFocus = options[newIndex];
|
432
|
-
break;
|
433
|
-
}
|
434
|
-
case KEYS.PAGE_DOWN: {
|
435
|
-
const options = this.getAllValidOptions();
|
436
|
-
const currentIndex = options.findIndex(option => option === event.target);
|
437
|
-
const newIndex = Math.min(currentIndex + 10, options.length - 1);
|
438
|
-
optionToFocus = options[newIndex];
|
439
|
-
break;
|
440
|
-
}
|
441
|
-
case KEYS.PAGE_UP: {
|
442
|
-
const options = this.getAllValidOptions();
|
443
|
-
const currentIndex = options.findIndex(option => option === event.target);
|
444
|
-
const newIndex = Math.max(currentIndex - 10, 0);
|
445
|
-
optionToFocus = options[newIndex];
|
446
|
-
break;
|
447
|
-
}
|
448
|
-
default:
|
449
|
-
break;
|
450
|
-
}
|
451
|
-
if (optionToFocus) {
|
452
|
-
this.focusAndUpdateTabIndexes(optionToFocus);
|
453
|
-
event.preventDefault();
|
454
|
-
event.stopPropagation();
|
455
|
-
}
|
456
|
-
}
|
457
|
-
/**
|
458
|
-
* Focuses the given option and updates the tabindex for all options.
|
459
|
-
* @param option - The option to focus.
|
460
|
-
* @internal
|
461
|
-
*/
|
462
|
-
focusAndUpdateTabIndexes(option) {
|
463
|
-
if (option) {
|
464
|
-
option.focus();
|
465
|
-
this.updateTabIndexForAllOptions(option);
|
466
|
-
}
|
467
|
-
}
|
468
491
|
/**
|
469
492
|
* If the native input is focused, it will focus the visual combobox.
|
470
493
|
* This is to ensure that the visual combobox is focused when the native input is focused.
|
@@ -476,25 +499,6 @@ class Select extends AutoFocusOnMountMixin(FormInternalsMixin(DataAriaLabelMixin
|
|
476
499
|
handleNativeInputFocus() {
|
477
500
|
this.visualCombobox.focus();
|
478
501
|
}
|
479
|
-
/**
|
480
|
-
* Updates the state of the select component.
|
481
|
-
* This public method should be fired when the selected on the option components is updated from the outside.
|
482
|
-
* It ensures that the selected attribute is set correctly on the options
|
483
|
-
* and that the aria-selected attribute is updated accordingly.
|
484
|
-
*/
|
485
|
-
updateState() {
|
486
|
-
var _a;
|
487
|
-
const newSelectedOption = this.getFirstSelectedOption();
|
488
|
-
if (!this.inputElement) {
|
489
|
-
return;
|
490
|
-
}
|
491
|
-
if (!newSelectedOption) {
|
492
|
-
this.setSelectedOption(this.placeholder ? null : this.getFirstValidOption());
|
493
|
-
}
|
494
|
-
else if (((_a = this.selectedOption) === null || _a === void 0 ? void 0 : _a.value) !== newSelectedOption.value) {
|
495
|
-
this.setSelectedOption(newSelectedOption);
|
496
|
-
}
|
497
|
-
}
|
498
502
|
render() {
|
499
503
|
var _a, _b, _c, _d, _e, _f;
|
500
504
|
return html `
|
@@ -558,7 +562,6 @@ class Select extends AutoFocusOnMountMixin(FormInternalsMixin(DataAriaLabelMixin
|
|
558
562
|
<mdc-popover
|
559
563
|
trigger="manual"
|
560
564
|
triggerid="${TRIGGER_ID}"
|
561
|
-
@keydown="${this.handlePopoverKeydown}"
|
562
565
|
interactive
|
563
566
|
?visible="${this.displayPopover}"
|
564
567
|
role=""
|
@@ -621,10 +624,6 @@ __decorate([
|
|
621
624
|
property({ type: String, reflect: true, attribute: 'backdrop-append-to' }),
|
622
625
|
__metadata("design:type", String)
|
623
626
|
], Select.prototype, "backdropAppendTo", void 0);
|
624
|
-
__decorate([
|
625
|
-
queryAssignedElements({ selector: 'mdc-selectlistbox' }),
|
626
|
-
__metadata("design:type", Array)
|
627
|
-
], Select.prototype, "slottedListboxes", void 0);
|
628
627
|
__decorate([
|
629
628
|
query(`[id="${TRIGGER_ID}"]`),
|
630
629
|
__metadata("design:type", HTMLDivElement)
|
@@ -14,7 +14,6 @@ declare const Toast_base: import("../../utils/mixins/index.types").Constructor<i
|
|
14
14
|
* @dependency mdc-icon
|
15
15
|
* @dependency mdc-text
|
16
16
|
* @dependency mdc-button
|
17
|
-
* @dependency mdc-linkbutton
|
18
17
|
*
|
19
18
|
* @slot content-prefix - Slot for custom content before the icon (only for custom variant).
|
20
19
|
* @slot toast-body-normal - Slot for the main body content of the toast.
|
@@ -47,6 +46,8 @@ declare class Toast extends Toast_base {
|
|
47
46
|
/**
|
48
47
|
* Type of toast
|
49
48
|
* - Can be `custom`, `success`, `warning` or `error`.
|
49
|
+
*
|
50
|
+
* Note: When using the `custom` variant, provide your own icon via the `content-prefix` slot; otherwise, no icon will be shown.
|
50
51
|
* @default 'custom'
|
51
52
|
*/
|
52
53
|
variant: ToastVariant;
|