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