@spectrum-web-components/menu 0.35.1-rc.43 → 0.36.0

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