@spectrum-web-components/menu 0.35.0 → 0.35.1-rc.24
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/package.json +9 -9
- package/src/Menu.d.ts +16 -6
- package/src/Menu.dev.js +162 -61
- package/src/Menu.dev.js.map +2 -2
- package/src/Menu.js +7 -3
- package/src/Menu.js.map +3 -3
- package/src/MenuGroup.d.ts +0 -2
- package/src/MenuGroup.dev.js +6 -10
- package/src/MenuGroup.dev.js.map +2 -2
- package/src/MenuGroup.js +3 -5
- package/src/MenuGroup.js.map +3 -3
- package/src/MenuItem.d.ts +26 -23
- package/src/MenuItem.dev.js +140 -185
- package/src/MenuItem.dev.js.map +3 -3
- package/src/MenuItem.js +35 -15
- package/src/MenuItem.js.map +3 -3
- package/src/menu-item.css.dev.js +1 -1
- package/src/menu-item.css.dev.js.map +1 -1
- package/src/menu-item.css.js +1 -1
- package/src/menu-item.css.js.map +1 -1
- package/src/menu.css.dev.js +1 -1
- package/src/menu.css.dev.js.map +1 -1
- package/src/menu.css.js +1 -1
- package/src/menu.css.js.map +1 -1
- package/stories/submenu.stories.js +107 -104
- package/stories/submenu.stories.js.map +3 -3
- package/test/menu-group.test.js +14 -1
- package/test/menu-group.test.js.map +2 -2
- package/test/menu-selects.test.js +3 -1
- package/test/menu-selects.test.js.map +2 -2
- package/test/menu.test.js +7 -0
- package/test/menu.test.js.map +2 -2
- package/test/submenu.test.js +206 -84
- package/test/submenu.test.js.map +2 -2
- package/custom-elements.json +0 -2252
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spectrum-web-components/menu",
|
|
3
|
-
"version": "0.35.
|
|
3
|
+
"version": "0.35.1-rc.24+e3649e123",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -85,13 +85,13 @@
|
|
|
85
85
|
],
|
|
86
86
|
"dependencies": {
|
|
87
87
|
"@lit-labs/observers": "^2.0.0",
|
|
88
|
-
"@spectrum-web-components/action-button": "^0.35.
|
|
89
|
-
"@spectrum-web-components/base": "^0.35.
|
|
90
|
-
"@spectrum-web-components/divider": "^0.35.
|
|
91
|
-
"@spectrum-web-components/icon": "^0.35.
|
|
92
|
-
"@spectrum-web-components/icons-ui": "^0.35.
|
|
93
|
-
"@spectrum-web-components/overlay": "^0.35.
|
|
94
|
-
"@spectrum-web-components/shared": "^0.35.
|
|
88
|
+
"@spectrum-web-components/action-button": "^0.35.1-rc.24+e3649e123",
|
|
89
|
+
"@spectrum-web-components/base": "^0.35.1-rc.24+e3649e123",
|
|
90
|
+
"@spectrum-web-components/divider": "^0.35.1-rc.24+e3649e123",
|
|
91
|
+
"@spectrum-web-components/icon": "^0.35.1-rc.24+e3649e123",
|
|
92
|
+
"@spectrum-web-components/icons-ui": "^0.35.1-rc.24+e3649e123",
|
|
93
|
+
"@spectrum-web-components/overlay": "^0.35.1-rc.24+e3649e123",
|
|
94
|
+
"@spectrum-web-components/shared": "^0.35.1-rc.24+e3649e123"
|
|
95
95
|
},
|
|
96
96
|
"devDependencies": {
|
|
97
97
|
"@spectrum-css/menu": "^4.0.48"
|
|
@@ -102,5 +102,5 @@
|
|
|
102
102
|
"./sp-*.js",
|
|
103
103
|
"./**/*.dev.js"
|
|
104
104
|
],
|
|
105
|
-
"gitHead": "
|
|
105
|
+
"gitHead": "e3649e1230ed727048988a452969c38ced5467ac"
|
|
106
106
|
}
|
package/src/Menu.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ export interface MenuChildItem {
|
|
|
22
22
|
*/
|
|
23
23
|
export declare class Menu extends SpectrumElement {
|
|
24
24
|
static get styles(): CSSResultArray;
|
|
25
|
-
isSubmenu
|
|
25
|
+
private get isSubmenu();
|
|
26
26
|
label: string;
|
|
27
27
|
ignore: boolean;
|
|
28
28
|
selects: undefined | 'inherit' | 'single' | 'multiple';
|
|
@@ -51,7 +51,7 @@ export declare class Menu extends SpectrumElement {
|
|
|
51
51
|
private resolvedRole?;
|
|
52
52
|
/**
|
|
53
53
|
* When a descendant `<sp-menu-item>` element is added or updated it will dispatch
|
|
54
|
-
* this event to announce its presence in the DOM. During the
|
|
54
|
+
* this event to announce its presence in the DOM. During the CAPTURE phase the first
|
|
55
55
|
* Menu based element that the event encounters will manage the focus state of the
|
|
56
56
|
* dispatching `<sp-menu-item>` element.
|
|
57
57
|
* @param event
|
|
@@ -59,7 +59,7 @@ export declare class Menu extends SpectrumElement {
|
|
|
59
59
|
private onFocusableItemAddedOrUpdated;
|
|
60
60
|
/**
|
|
61
61
|
* When a descendant `<sp-menu-item>` element is added or updated it will dispatch
|
|
62
|
-
* this event to announce its presence in the DOM. During the
|
|
62
|
+
* this event to announce its presence in the DOM. During the BUBBLE phase the first
|
|
63
63
|
* Menu based element that the event encounters that does not inherit selection will
|
|
64
64
|
* manage the selection state of the dispatching `<sp-menu-item>` element.
|
|
65
65
|
* @param event
|
|
@@ -69,24 +69,33 @@ export declare class Menu extends SpectrumElement {
|
|
|
69
69
|
private removeChildItem;
|
|
70
70
|
constructor();
|
|
71
71
|
focus({ preventScroll }?: FocusOptions): void;
|
|
72
|
-
private
|
|
72
|
+
private handleClick;
|
|
73
73
|
handleFocusin(event: FocusEvent): void;
|
|
74
74
|
startListeningToKeyboard(): void;
|
|
75
75
|
handleFocusout(event: FocusEvent): void;
|
|
76
76
|
stopListeningToKeyboard(): void;
|
|
77
|
+
private descendentOverlays;
|
|
78
|
+
protected handleDescendentOverlayOpened(event: Event): void;
|
|
79
|
+
protected handleDescendentOverlayClosed(event: Event): void;
|
|
80
|
+
handleSubmenuClosed: (event: Event) => void;
|
|
81
|
+
handleSubmenuOpened: (event: Event) => void;
|
|
77
82
|
selectOrToggleItem(targetItem: MenuItem): Promise<void>;
|
|
78
83
|
protected navigateWithinMenu(event: KeyboardEvent): void;
|
|
79
|
-
protected navigateBetweenRelatedMenus(
|
|
84
|
+
protected navigateBetweenRelatedMenus(event: KeyboardEvent): void;
|
|
80
85
|
handleKeydown(event: KeyboardEvent): void;
|
|
81
86
|
focusMenuItemByOffset(offset: number): MenuItem;
|
|
82
87
|
private prepareToCleanUp;
|
|
88
|
+
private _hasUpdatedSelectedItemIndex;
|
|
83
89
|
updateSelectedItemIndex(): void;
|
|
84
90
|
private _willUpdateItems;
|
|
85
91
|
private handleItemsChanged;
|
|
92
|
+
private updateCache;
|
|
86
93
|
private updateItemFocus;
|
|
94
|
+
closeDescendentOverlays(): void;
|
|
87
95
|
private forwardFocusVisibleToItem;
|
|
96
|
+
private handleSlotchange;
|
|
97
|
+
protected renderMenuItemSlot(): TemplateResult;
|
|
88
98
|
render(): TemplateResult;
|
|
89
|
-
private _notFirstUpdated;
|
|
90
99
|
protected firstUpdated(changed: PropertyValues): void;
|
|
91
100
|
protected updated(changes: PropertyValues<this>): void;
|
|
92
101
|
protected selectsChanged(): void;
|
|
@@ -94,5 +103,6 @@ export declare class Menu extends SpectrumElement {
|
|
|
94
103
|
disconnectedCallback(): void;
|
|
95
104
|
protected childItemsUpdated: Promise<unknown[]>;
|
|
96
105
|
protected cacheUpdated: Promise<void>;
|
|
106
|
+
protected resolveCacheUpdated: () => void;
|
|
97
107
|
protected getUpdateComplete(): Promise<boolean>;
|
|
98
108
|
}
|
package/src/Menu.dev.js
CHANGED
|
@@ -26,7 +26,6 @@ function elementIsOrContains(el, isOrContains) {
|
|
|
26
26
|
export class Menu extends SpectrumElement {
|
|
27
27
|
constructor() {
|
|
28
28
|
super();
|
|
29
|
-
this.isSubmenu = false;
|
|
30
29
|
this.label = "";
|
|
31
30
|
this.ignore = false;
|
|
32
31
|
this.value = "";
|
|
@@ -37,9 +36,44 @@ export class Menu extends SpectrumElement {
|
|
|
37
36
|
this.focusedItemIndex = 0;
|
|
38
37
|
this.focusInItemIndex = 0;
|
|
39
38
|
this.selectedItemsMap = /* @__PURE__ */ new Map();
|
|
39
|
+
this.descendentOverlays = /* @__PURE__ */ new Map();
|
|
40
|
+
this.handleSubmenuClosed = (event) => {
|
|
41
|
+
event.stopPropagation();
|
|
42
|
+
const target = event.composedPath()[0];
|
|
43
|
+
target.dispatchEvent(
|
|
44
|
+
new Event("sp-menu-submenu-closed", {
|
|
45
|
+
bubbles: true,
|
|
46
|
+
composed: true
|
|
47
|
+
})
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
this.handleSubmenuOpened = (event) => {
|
|
51
|
+
event.stopPropagation();
|
|
52
|
+
const target = event.composedPath()[0];
|
|
53
|
+
target.dispatchEvent(
|
|
54
|
+
new Event("sp-menu-submenu-opened", {
|
|
55
|
+
bubbles: true,
|
|
56
|
+
composed: true
|
|
57
|
+
})
|
|
58
|
+
);
|
|
59
|
+
const focusedItem = this.childItems[this.focusedItemIndex];
|
|
60
|
+
if (focusedItem) {
|
|
61
|
+
focusedItem.focused = false;
|
|
62
|
+
}
|
|
63
|
+
const openedItem = event.composedPath().find((el) => this.childItemSet.has(el));
|
|
64
|
+
if (!openedItem)
|
|
65
|
+
return;
|
|
66
|
+
const openedItemIndex = this.childItems.indexOf(openedItem);
|
|
67
|
+
this.focusedItemIndex = openedItemIndex;
|
|
68
|
+
this.focusInItemIndex = openedItemIndex;
|
|
69
|
+
};
|
|
70
|
+
this._hasUpdatedSelectedItemIndex = false;
|
|
40
71
|
this._willUpdateItems = false;
|
|
41
|
-
this._notFirstUpdated = false;
|
|
42
72
|
this.cacheUpdated = Promise.resolve();
|
|
73
|
+
/* c8 ignore next 3 */
|
|
74
|
+
this.resolveCacheUpdated = () => {
|
|
75
|
+
return;
|
|
76
|
+
};
|
|
43
77
|
this.addEventListener(
|
|
44
78
|
"sp-menu-item-added-or-updated",
|
|
45
79
|
this.onSelectableItemAddedOrUpdated
|
|
@@ -51,13 +85,18 @@ export class Menu extends SpectrumElement {
|
|
|
51
85
|
capture: true
|
|
52
86
|
}
|
|
53
87
|
);
|
|
54
|
-
this.addEventListener("
|
|
55
|
-
this.addEventListener("click", this.onClick);
|
|
88
|
+
this.addEventListener("click", this.handleClick);
|
|
56
89
|
this.addEventListener("focusin", this.handleFocusin);
|
|
90
|
+
this.addEventListener("focusout", this.handleFocusout);
|
|
91
|
+
this.addEventListener("sp-opened", this.handleSubmenuOpened);
|
|
92
|
+
this.addEventListener("sp-closed", this.handleSubmenuClosed);
|
|
57
93
|
}
|
|
58
94
|
static get styles() {
|
|
59
95
|
return [menuStyles];
|
|
60
96
|
}
|
|
97
|
+
get isSubmenu() {
|
|
98
|
+
return this.slot === "submenu";
|
|
99
|
+
}
|
|
61
100
|
get childItems() {
|
|
62
101
|
if (!this.cachedChildItems) {
|
|
63
102
|
this.cachedChildItems = this.updateCachedMenuItems();
|
|
@@ -102,17 +141,37 @@ export class Menu extends SpectrumElement {
|
|
|
102
141
|
}
|
|
103
142
|
/**
|
|
104
143
|
* When a descendant `<sp-menu-item>` element is added or updated it will dispatch
|
|
105
|
-
* this event to announce its presence in the DOM. During the
|
|
144
|
+
* this event to announce its presence in the DOM. During the CAPTURE phase the first
|
|
106
145
|
* Menu based element that the event encounters will manage the focus state of the
|
|
107
146
|
* dispatching `<sp-menu-item>` element.
|
|
108
147
|
* @param event
|
|
109
148
|
*/
|
|
110
149
|
onFocusableItemAddedOrUpdated(event) {
|
|
150
|
+
event.menuCascade.set(this, {
|
|
151
|
+
hadFocusRoot: !!event.item.menuData.focusRoot,
|
|
152
|
+
ancestorWithSelects: event.currentAncestorWithSelects
|
|
153
|
+
});
|
|
154
|
+
if (this.selects) {
|
|
155
|
+
event.currentAncestorWithSelects = this;
|
|
156
|
+
}
|
|
157
|
+
event.item.menuData.focusRoot = event.item.menuData.focusRoot || this;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* When a descendant `<sp-menu-item>` element is added or updated it will dispatch
|
|
161
|
+
* this event to announce its presence in the DOM. During the BUBBLE phase the first
|
|
162
|
+
* Menu based element that the event encounters that does not inherit selection will
|
|
163
|
+
* manage the selection state of the dispatching `<sp-menu-item>` element.
|
|
164
|
+
* @param event
|
|
165
|
+
*/
|
|
166
|
+
onSelectableItemAddedOrUpdated(event) {
|
|
111
167
|
var _a, _b;
|
|
112
|
-
|
|
168
|
+
const cascadeData = event.menuCascade.get(this);
|
|
169
|
+
if (!cascadeData)
|
|
170
|
+
return;
|
|
171
|
+
event.item.menuData.parentMenu = event.item.menuData.parentMenu || this;
|
|
172
|
+
if (cascadeData.hadFocusRoot && !this.ignore) {
|
|
113
173
|
this.tabIndex = -1;
|
|
114
174
|
}
|
|
115
|
-
event.focusRoot = this;
|
|
116
175
|
this.addChildItem(event.item);
|
|
117
176
|
if (this.selects === "inherit") {
|
|
118
177
|
this.resolvedSelects = "inherit";
|
|
@@ -121,34 +180,33 @@ export class Menu extends SpectrumElement {
|
|
|
121
180
|
} else if (this.selects) {
|
|
122
181
|
this.resolvedRole = this.ignore ? "none" : this.getAttribute("role") || void 0;
|
|
123
182
|
this.resolvedSelects = this.selects;
|
|
124
|
-
event.currentAncestorWithSelects = this;
|
|
125
183
|
} else {
|
|
126
184
|
this.resolvedRole = this.ignore ? "none" : this.getAttribute("role") || void 0;
|
|
127
185
|
this.resolvedSelects = this.resolvedRole === "none" ? "ignore" : "none";
|
|
128
186
|
}
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* When a descendant `<sp-menu-item>` element is added or updated it will dispatch
|
|
132
|
-
* this event to announce its presence in the DOM. During the bubble phase the first
|
|
133
|
-
* Menu based element that the event encounters that does not inherit selection will
|
|
134
|
-
* manage the selection state of the dispatching `<sp-menu-item>` element.
|
|
135
|
-
* @param event
|
|
136
|
-
*/
|
|
137
|
-
onSelectableItemAddedOrUpdated(event) {
|
|
138
187
|
const selects = this.resolvedSelects === "single" || this.resolvedSelects === "multiple";
|
|
188
|
+
event.item.menuData.cleanupSteps.push(
|
|
189
|
+
(item) => this.removeChildItem(item)
|
|
190
|
+
);
|
|
139
191
|
if ((selects || !this.selects && this.resolvedSelects !== "ignore") && !event.item.menuData.selectionRoot) {
|
|
140
192
|
event.item.setRole(this.childRole);
|
|
141
|
-
event.selectionRoot = this;
|
|
193
|
+
event.item.menuData.selectionRoot = event.item.menuData.selectionRoot || this;
|
|
194
|
+
if (event.item.selected) {
|
|
195
|
+
this.selectedItemsMap.set(event.item, true);
|
|
196
|
+
this.selectedItems = [...this.selectedItems, event.item];
|
|
197
|
+
this.selected = [...this.selected, event.item.value];
|
|
198
|
+
this.value = this.selected.join(this.valueSeparator);
|
|
199
|
+
}
|
|
142
200
|
}
|
|
143
201
|
}
|
|
144
202
|
addChildItem(item) {
|
|
145
203
|
this.childItemSet.add(item);
|
|
146
204
|
this.handleItemsChanged();
|
|
147
205
|
}
|
|
148
|
-
async removeChildItem(
|
|
149
|
-
this.childItemSet.delete(
|
|
206
|
+
async removeChildItem(item) {
|
|
207
|
+
this.childItemSet.delete(item);
|
|
150
208
|
this.cachedChildItems = void 0;
|
|
151
|
-
if (
|
|
209
|
+
if (item.focused) {
|
|
152
210
|
this.handleItemsChanged();
|
|
153
211
|
await this.updateComplete;
|
|
154
212
|
this.focus();
|
|
@@ -166,12 +224,12 @@ export class Menu extends SpectrumElement {
|
|
|
166
224
|
}
|
|
167
225
|
this.focusMenuItemByOffset(0);
|
|
168
226
|
super.focus({ preventScroll });
|
|
169
|
-
const selectedItem = this.
|
|
227
|
+
const selectedItem = this.selectedItems[0];
|
|
170
228
|
if (selectedItem && !preventScroll) {
|
|
171
229
|
selectedItem.scrollIntoView({ block: "nearest" });
|
|
172
230
|
}
|
|
173
231
|
}
|
|
174
|
-
|
|
232
|
+
handleClick(event) {
|
|
175
233
|
if (event.defaultPrevented) {
|
|
176
234
|
return;
|
|
177
235
|
}
|
|
@@ -203,18 +261,18 @@ export class Menu extends SpectrumElement {
|
|
|
203
261
|
}
|
|
204
262
|
handleFocusin(event) {
|
|
205
263
|
var _a;
|
|
206
|
-
const
|
|
264
|
+
const wasOrContainedRelatedTarget = elementIsOrContains(
|
|
207
265
|
this,
|
|
208
266
|
event.relatedTarget
|
|
209
267
|
);
|
|
210
|
-
if (
|
|
268
|
+
if (this.childItems.some(
|
|
211
269
|
(childItem) => childItem.menuData.focusRoot !== this
|
|
212
270
|
)) {
|
|
213
271
|
return;
|
|
214
272
|
}
|
|
215
273
|
const activeElement = this.getRootNode().activeElement;
|
|
216
274
|
const selectionRoot = ((_a = this.childItems[this.focusedItemIndex]) == null ? void 0 : _a.menuData.selectionRoot) || this;
|
|
217
|
-
if (activeElement !== selectionRoot || !
|
|
275
|
+
if (activeElement !== selectionRoot || !wasOrContainedRelatedTarget && event.target !== this) {
|
|
218
276
|
selectionRoot.focus({ preventScroll: true });
|
|
219
277
|
if (activeElement && this.focusedItemIndex === 0) {
|
|
220
278
|
const offset = this.childItems.findIndex(
|
|
@@ -229,27 +287,32 @@ export class Menu extends SpectrumElement {
|
|
|
229
287
|
}
|
|
230
288
|
startListeningToKeyboard() {
|
|
231
289
|
this.addEventListener("keydown", this.handleKeydown);
|
|
232
|
-
this.addEventListener("focusout", this.handleFocusout);
|
|
233
290
|
}
|
|
234
291
|
handleFocusout(event) {
|
|
235
292
|
if (elementIsOrContains(this, event.relatedTarget)) {
|
|
236
|
-
event.composedPath()[0].focused = false;
|
|
237
293
|
return;
|
|
238
294
|
}
|
|
239
295
|
this.stopListeningToKeyboard();
|
|
240
|
-
|
|
241
|
-
(childItem) => childItem.menuData.focusRoot === this
|
|
242
|
-
)) {
|
|
243
|
-
const focusedItem = this.childItems[this.focusedItemIndex];
|
|
244
|
-
if (focusedItem) {
|
|
245
|
-
focusedItem.focused = false;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
296
|
+
this.childItems.forEach((child) => child.focused = false);
|
|
248
297
|
this.removeAttribute("aria-activedescendant");
|
|
249
298
|
}
|
|
250
299
|
stopListeningToKeyboard() {
|
|
251
300
|
this.removeEventListener("keydown", this.handleKeydown);
|
|
252
|
-
|
|
301
|
+
}
|
|
302
|
+
handleDescendentOverlayOpened(event) {
|
|
303
|
+
const target = event.composedPath()[0];
|
|
304
|
+
if (!target.overlayElement)
|
|
305
|
+
return;
|
|
306
|
+
this.descendentOverlays.set(
|
|
307
|
+
target.overlayElement,
|
|
308
|
+
target.overlayElement
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
handleDescendentOverlayClosed(event) {
|
|
312
|
+
const target = event.composedPath()[0];
|
|
313
|
+
if (!target.overlayElement)
|
|
314
|
+
return;
|
|
315
|
+
this.descendentOverlays.delete(target.overlayElement);
|
|
253
316
|
}
|
|
254
317
|
async selectOrToggleItem(targetItem) {
|
|
255
318
|
const resolvedSelects = this.resolvedSelects;
|
|
@@ -258,6 +321,7 @@ export class Menu extends SpectrumElement {
|
|
|
258
321
|
const oldSelectedItems = this.selectedItems.slice();
|
|
259
322
|
const oldValue = this.value;
|
|
260
323
|
this.childItems[this.focusedItemIndex].focused = false;
|
|
324
|
+
this.childItems[this.focusedItemIndex].active = false;
|
|
261
325
|
this.focusedItemIndex = this.childItems.indexOf(targetItem);
|
|
262
326
|
this.forwardFocusVisibleToItem(targetItem);
|
|
263
327
|
if (resolvedSelects === "multiple") {
|
|
@@ -321,23 +385,31 @@ export class Menu extends SpectrumElement {
|
|
|
321
385
|
return;
|
|
322
386
|
}
|
|
323
387
|
event.preventDefault();
|
|
388
|
+
event.stopPropagation();
|
|
324
389
|
itemToFocus.scrollIntoView({ block: "nearest" });
|
|
325
390
|
}
|
|
326
|
-
navigateBetweenRelatedMenus(
|
|
391
|
+
navigateBetweenRelatedMenus(event) {
|
|
392
|
+
const { code } = event;
|
|
327
393
|
const shouldOpenSubmenu = this.isLTR && code === "ArrowRight" || !this.isLTR && code === "ArrowLeft";
|
|
328
394
|
const shouldCloseSelfAsSubmenu = this.isLTR && code === "ArrowLeft" || !this.isLTR && code === "ArrowRight";
|
|
329
395
|
if (shouldOpenSubmenu) {
|
|
396
|
+
event.stopPropagation();
|
|
330
397
|
const lastFocusedItem = this.childItems[this.focusedItemIndex];
|
|
331
398
|
if (lastFocusedItem == null ? void 0 : lastFocusedItem.hasSubmenu) {
|
|
332
|
-
this.blur();
|
|
333
399
|
lastFocusedItem.openOverlay();
|
|
334
400
|
}
|
|
335
401
|
} else if (shouldCloseSelfAsSubmenu && this.isSubmenu) {
|
|
402
|
+
event.stopPropagation();
|
|
336
403
|
this.dispatchEvent(new Event("close", { bubbles: true }));
|
|
404
|
+
this.updateSelectedItemIndex();
|
|
337
405
|
}
|
|
338
406
|
}
|
|
339
407
|
handleKeydown(event) {
|
|
340
408
|
var _a;
|
|
409
|
+
const isNotThisOrDirectChild = event.target !== this && this !== event.target.parentElement;
|
|
410
|
+
if (isNotThisOrDirectChild || event.defaultPrevented) {
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
341
413
|
const { code } = event;
|
|
342
414
|
if (code === "Tab") {
|
|
343
415
|
this.prepareToCleanUp();
|
|
@@ -346,7 +418,6 @@ export class Menu extends SpectrumElement {
|
|
|
346
418
|
if (code === "Space") {
|
|
347
419
|
const lastFocusedItem = this.childItems[this.focusedItemIndex];
|
|
348
420
|
if (lastFocusedItem == null ? void 0 : lastFocusedItem.hasSubmenu) {
|
|
349
|
-
this.blur();
|
|
350
421
|
lastFocusedItem.openOverlay();
|
|
351
422
|
return;
|
|
352
423
|
}
|
|
@@ -359,12 +430,15 @@ export class Menu extends SpectrumElement {
|
|
|
359
430
|
this.navigateWithinMenu(event);
|
|
360
431
|
return;
|
|
361
432
|
}
|
|
362
|
-
this.navigateBetweenRelatedMenus(
|
|
433
|
+
this.navigateBetweenRelatedMenus(event);
|
|
363
434
|
}
|
|
364
435
|
focusMenuItemByOffset(offset) {
|
|
365
436
|
const step = offset || 1;
|
|
366
437
|
const focusedItem = this.childItems[this.focusedItemIndex];
|
|
367
|
-
focusedItem
|
|
438
|
+
if (focusedItem) {
|
|
439
|
+
focusedItem.focused = false;
|
|
440
|
+
focusedItem.active = false;
|
|
441
|
+
}
|
|
368
442
|
this.focusedItemIndex = (this.childItems.length + this.focusedItemIndex + offset) % this.childItems.length;
|
|
369
443
|
let itemToFocus = this.childItems[this.focusedItemIndex];
|
|
370
444
|
let availableItems = this.childItems.length;
|
|
@@ -403,7 +477,7 @@ export class Menu extends SpectrumElement {
|
|
|
403
477
|
itemIndex -= 1;
|
|
404
478
|
const childItem = this.childItems[itemIndex];
|
|
405
479
|
if (childItem.menuData.selectionRoot === this) {
|
|
406
|
-
if (childItem.selected) {
|
|
480
|
+
if (childItem.selected || !this._hasUpdatedSelectedItemIndex && this.selected.includes(childItem.value)) {
|
|
407
481
|
firstOrFirstSelectedIndex = itemIndex;
|
|
408
482
|
selectedItemsMap.set(childItem, true);
|
|
409
483
|
selected.unshift(childItem.value);
|
|
@@ -429,21 +503,18 @@ export class Menu extends SpectrumElement {
|
|
|
429
503
|
handleItemsChanged() {
|
|
430
504
|
this.cachedChildItems = void 0;
|
|
431
505
|
if (!this._willUpdateItems) {
|
|
432
|
-
let resolve = () => {
|
|
433
|
-
return;
|
|
434
|
-
};
|
|
435
|
-
this.cacheUpdated = new Promise((res) => resolve = res);
|
|
436
506
|
this._willUpdateItems = true;
|
|
437
|
-
|
|
438
|
-
if (this.cachedChildItems === void 0) {
|
|
439
|
-
this.updateSelectedItemIndex();
|
|
440
|
-
this.updateItemFocus();
|
|
441
|
-
}
|
|
442
|
-
this._willUpdateItems = false;
|
|
443
|
-
resolve();
|
|
444
|
-
});
|
|
507
|
+
this.cacheUpdated = this.updateCache();
|
|
445
508
|
}
|
|
446
509
|
}
|
|
510
|
+
async updateCache() {
|
|
511
|
+
await new Promise((res) => requestAnimationFrame(() => res(true)));
|
|
512
|
+
if (this.cachedChildItems === void 0) {
|
|
513
|
+
this.updateSelectedItemIndex();
|
|
514
|
+
this.updateItemFocus();
|
|
515
|
+
}
|
|
516
|
+
this._willUpdateItems = false;
|
|
517
|
+
}
|
|
447
518
|
updateItemFocus() {
|
|
448
519
|
if (this.childItems.length == 0) {
|
|
449
520
|
return;
|
|
@@ -453,21 +524,52 @@ export class Menu extends SpectrumElement {
|
|
|
453
524
|
this.forwardFocusVisibleToItem(focusInItem);
|
|
454
525
|
}
|
|
455
526
|
}
|
|
527
|
+
closeDescendentOverlays() {
|
|
528
|
+
this.descendentOverlays.forEach((overlay) => {
|
|
529
|
+
overlay.open = false;
|
|
530
|
+
});
|
|
531
|
+
this.descendentOverlays = /* @__PURE__ */ new Map();
|
|
532
|
+
}
|
|
456
533
|
forwardFocusVisibleToItem(item) {
|
|
457
534
|
if (item.menuData.focusRoot !== this) {
|
|
458
535
|
return;
|
|
459
536
|
}
|
|
460
|
-
|
|
537
|
+
this.closeDescendentOverlays();
|
|
538
|
+
const focused = this.hasVisibleFocusInTree() || !!this.childItems.find((child) => {
|
|
539
|
+
return child.hasVisibleFocusInTree();
|
|
540
|
+
});
|
|
541
|
+
item.focused = focused;
|
|
461
542
|
this.setAttribute("aria-activedescendant", item.id);
|
|
462
543
|
if (item.menuData.selectionRoot && item.menuData.selectionRoot !== this) {
|
|
463
544
|
item.menuData.selectionRoot.focus();
|
|
464
545
|
}
|
|
465
546
|
}
|
|
466
|
-
|
|
547
|
+
handleSlotchange({
|
|
548
|
+
target
|
|
549
|
+
}) {
|
|
550
|
+
const assignedElement = target.assignedElements({
|
|
551
|
+
flatten: true
|
|
552
|
+
});
|
|
553
|
+
if (this.childItems.length !== assignedElement.length) {
|
|
554
|
+
assignedElement.forEach((item) => {
|
|
555
|
+
if (typeof item.triggerUpdate !== "undefined") {
|
|
556
|
+
item.triggerUpdate();
|
|
557
|
+
}
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
renderMenuItemSlot() {
|
|
467
562
|
return html`
|
|
468
|
-
<slot
|
|
563
|
+
<slot
|
|
564
|
+
@sp-menu-submenu-opened=${this.handleDescendentOverlayOpened}
|
|
565
|
+
@sp-menu-submenu-closed=${this.handleDescendentOverlayClosed}
|
|
566
|
+
@slotchange=${this.handleSlotchange}
|
|
567
|
+
></slot>
|
|
469
568
|
`;
|
|
470
569
|
}
|
|
570
|
+
render() {
|
|
571
|
+
return this.renderMenuItemSlot();
|
|
572
|
+
}
|
|
471
573
|
firstUpdated(changed) {
|
|
472
574
|
super.firstUpdated(changed);
|
|
473
575
|
if (!this.hasAttribute("tabindex") && !this.ignore) {
|
|
@@ -490,17 +592,16 @@ export class Menu extends SpectrumElement {
|
|
|
490
592
|
}
|
|
491
593
|
updated(changes) {
|
|
492
594
|
super.updated(changes);
|
|
493
|
-
if (changes.has("selects") && this.
|
|
595
|
+
if (changes.has("selects") && this.hasUpdated) {
|
|
494
596
|
this.selectsChanged();
|
|
495
597
|
}
|
|
496
|
-
if (changes.has("label")) {
|
|
598
|
+
if (changes.has("label") && (this.label || typeof changes.get("label") !== "undefined")) {
|
|
497
599
|
if (this.label) {
|
|
498
600
|
this.setAttribute("aria-label", this.label);
|
|
499
601
|
} else {
|
|
500
602
|
this.removeAttribute("aria-label");
|
|
501
603
|
}
|
|
502
604
|
}
|
|
503
|
-
this._notFirstUpdated = true;
|
|
504
605
|
}
|
|
505
606
|
selectsChanged() {
|
|
506
607
|
const updates = [
|