@spectrum-web-components/menu 1.1.0-beta.9 → 1.1.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 (165) hide show
  1. package/package.json +12 -12
  2. package/sp-menu-divider.d.ts +0 -6
  3. package/sp-menu-divider.dev.js +0 -5
  4. package/sp-menu-divider.dev.js.map +0 -7
  5. package/sp-menu-divider.js +0 -2
  6. package/sp-menu-divider.js.map +0 -7
  7. package/sp-menu-group.d.ts +0 -6
  8. package/sp-menu-group.dev.js +0 -5
  9. package/sp-menu-group.dev.js.map +0 -7
  10. package/sp-menu-group.js +0 -2
  11. package/sp-menu-group.js.map +0 -7
  12. package/sp-menu-item.d.ts +0 -6
  13. package/sp-menu-item.dev.js +0 -5
  14. package/sp-menu-item.dev.js.map +0 -7
  15. package/sp-menu-item.js +0 -2
  16. package/sp-menu-item.js.map +0 -7
  17. package/sp-menu.d.ts +0 -6
  18. package/sp-menu.dev.js +0 -5
  19. package/sp-menu.dev.js.map +0 -7
  20. package/sp-menu.js +0 -2
  21. package/sp-menu.js.map +0 -7
  22. package/src/Menu.d.ts +0 -118
  23. package/src/Menu.dev.js +0 -740
  24. package/src/Menu.dev.js.map +0 -7
  25. package/src/Menu.js +0 -8
  26. package/src/Menu.js.map +0 -7
  27. package/src/MenuDivider.d.ts +0 -13
  28. package/src/MenuDivider.dev.js +0 -19
  29. package/src/MenuDivider.dev.js.map +0 -7
  30. package/src/MenuDivider.js +0 -2
  31. package/src/MenuDivider.js.map +0 -7
  32. package/src/MenuGroup.d.ts +0 -18
  33. package/src/MenuGroup.dev.js +0 -78
  34. package/src/MenuGroup.dev.js.map +0 -7
  35. package/src/MenuGroup.js +0 -7
  36. package/src/MenuGroup.js.map +0 -7
  37. package/src/MenuItem.d.ts +0 -125
  38. package/src/MenuItem.dev.js +0 -518
  39. package/src/MenuItem.dev.js.map +0 -7
  40. package/src/MenuItem.js +0 -50
  41. package/src/MenuItem.js.map +0 -7
  42. package/src/checkmark-overrides.css.d.ts +0 -2
  43. package/src/checkmark-overrides.css.dev.js +0 -7
  44. package/src/checkmark-overrides.css.dev.js.map +0 -7
  45. package/src/checkmark-overrides.css.js +0 -4
  46. package/src/checkmark-overrides.css.js.map +0 -7
  47. package/src/chevron-overrides.css.d.ts +0 -2
  48. package/src/chevron-overrides.css.dev.js +0 -7
  49. package/src/chevron-overrides.css.dev.js.map +0 -7
  50. package/src/chevron-overrides.css.js +0 -4
  51. package/src/chevron-overrides.css.js.map +0 -7
  52. package/src/index.d.ts +0 -4
  53. package/src/index.dev.js +0 -6
  54. package/src/index.dev.js.map +0 -7
  55. package/src/index.js +0 -2
  56. package/src/index.js.map +0 -7
  57. package/src/menu-divider-overrides.css.d.ts +0 -2
  58. package/src/menu-divider-overrides.css.dev.js +0 -7
  59. package/src/menu-divider-overrides.css.dev.js.map +0 -7
  60. package/src/menu-divider-overrides.css.js +0 -4
  61. package/src/menu-divider-overrides.css.js.map +0 -7
  62. package/src/menu-divider.css.d.ts +0 -2
  63. package/src/menu-divider.css.dev.js +0 -7
  64. package/src/menu-divider.css.dev.js.map +0 -7
  65. package/src/menu-divider.css.js +0 -4
  66. package/src/menu-divider.css.js.map +0 -7
  67. package/src/menu-group.css.d.ts +0 -2
  68. package/src/menu-group.css.dev.js +0 -7
  69. package/src/menu-group.css.dev.js.map +0 -7
  70. package/src/menu-group.css.js +0 -4
  71. package/src/menu-group.css.js.map +0 -7
  72. package/src/menu-item-overrides.css.d.ts +0 -2
  73. package/src/menu-item-overrides.css.dev.js +0 -7
  74. package/src/menu-item-overrides.css.dev.js.map +0 -7
  75. package/src/menu-item-overrides.css.js +0 -4
  76. package/src/menu-item-overrides.css.js.map +0 -7
  77. package/src/menu-item.css.d.ts +0 -2
  78. package/src/menu-item.css.dev.js +0 -7
  79. package/src/menu-item.css.dev.js.map +0 -7
  80. package/src/menu-item.css.js +0 -4
  81. package/src/menu-item.css.js.map +0 -7
  82. package/src/menu-overrides.css.d.ts +0 -2
  83. package/src/menu-overrides.css.dev.js +0 -7
  84. package/src/menu-overrides.css.dev.js.map +0 -7
  85. package/src/menu-overrides.css.js +0 -4
  86. package/src/menu-overrides.css.js.map +0 -7
  87. package/src/menu.css.d.ts +0 -2
  88. package/src/menu.css.dev.js +0 -7
  89. package/src/menu.css.dev.js.map +0 -7
  90. package/src/menu.css.js +0 -4
  91. package/src/menu.css.js.map +0 -7
  92. package/src/spectrum-checkmark.css.d.ts +0 -2
  93. package/src/spectrum-checkmark.css.dev.js +0 -7
  94. package/src/spectrum-checkmark.css.dev.js.map +0 -7
  95. package/src/spectrum-checkmark.css.js +0 -4
  96. package/src/spectrum-checkmark.css.js.map +0 -7
  97. package/src/spectrum-chevron.css.d.ts +0 -2
  98. package/src/spectrum-chevron.css.dev.js +0 -7
  99. package/src/spectrum-chevron.css.dev.js.map +0 -7
  100. package/src/spectrum-chevron.css.js +0 -4
  101. package/src/spectrum-chevron.css.js.map +0 -7
  102. package/src/spectrum-menu-divider.css.d.ts +0 -2
  103. package/src/spectrum-menu-divider.css.dev.js +0 -7
  104. package/src/spectrum-menu-divider.css.dev.js.map +0 -7
  105. package/src/spectrum-menu-divider.css.js +0 -4
  106. package/src/spectrum-menu-divider.css.js.map +0 -7
  107. package/src/spectrum-menu-item.css.d.ts +0 -2
  108. package/src/spectrum-menu-item.css.dev.js +0 -7
  109. package/src/spectrum-menu-item.css.dev.js.map +0 -7
  110. package/src/spectrum-menu-item.css.js +0 -4
  111. package/src/spectrum-menu-item.css.js.map +0 -7
  112. package/src/spectrum-menu-sectionHeading.css.d.ts +0 -2
  113. package/src/spectrum-menu-sectionHeading.css.dev.js +0 -7
  114. package/src/spectrum-menu-sectionHeading.css.dev.js.map +0 -7
  115. package/src/spectrum-menu-sectionHeading.css.js +0 -4
  116. package/src/spectrum-menu-sectionHeading.css.js.map +0 -7
  117. package/src/spectrum-menu.css.d.ts +0 -2
  118. package/src/spectrum-menu.css.dev.js +0 -7
  119. package/src/spectrum-menu.css.dev.js.map +0 -7
  120. package/src/spectrum-menu.css.js +0 -4
  121. package/src/spectrum-menu.css.js.map +0 -7
  122. package/stories/index.js +0 -82
  123. package/stories/index.js.map +0 -7
  124. package/stories/menu-divider.stories.js +0 -32
  125. package/stories/menu-divider.stories.js.map +0 -7
  126. package/stories/menu-group.stories.js +0 -144
  127. package/stories/menu-group.stories.js.map +0 -7
  128. package/stories/menu-item.disconnected.stories.js +0 -176
  129. package/stories/menu-item.disconnected.stories.js.map +0 -7
  130. package/stories/menu-item.stories.js +0 -73
  131. package/stories/menu-item.stories.js.map +0 -7
  132. package/stories/menu-sizes.stories.js +0 -11
  133. package/stories/menu-sizes.stories.js.map +0 -7
  134. package/stories/menu.stories.js +0 -403
  135. package/stories/menu.stories.js.map +0 -7
  136. package/stories/submenu.stories.js +0 -346
  137. package/stories/submenu.stories.js.map +0 -7
  138. package/test/benchmark/test-basic.js +0 -24
  139. package/test/benchmark/test-basic.js.map +0 -7
  140. package/test/menu-divider.test-vrt.js +0 -5
  141. package/test/menu-divider.test-vrt.js.map +0 -7
  142. package/test/menu-group.test-vrt.js +0 -5
  143. package/test/menu-group.test-vrt.js.map +0 -7
  144. package/test/menu-group.test.js +0 -405
  145. package/test/menu-group.test.js.map +0 -7
  146. package/test/menu-item.disconnected.test-vrt.js +0 -5
  147. package/test/menu-item.disconnected.test-vrt.js.map +0 -7
  148. package/test/menu-item.test-vrt.js +0 -5
  149. package/test/menu-item.test-vrt.js.map +0 -7
  150. package/test/menu-item.test.js +0 -180
  151. package/test/menu-item.test.js.map +0 -7
  152. package/test/menu-memory.test.js +0 -5
  153. package/test/menu-memory.test.js.map +0 -7
  154. package/test/menu-selects.test.js +0 -530
  155. package/test/menu-selects.test.js.map +0 -7
  156. package/test/menu-sizes.test-vrt.js +0 -5
  157. package/test/menu-sizes.test-vrt.js.map +0 -7
  158. package/test/menu.test-vrt.js +0 -5
  159. package/test/menu.test-vrt.js.map +0 -7
  160. package/test/menu.test.js +0 -559
  161. package/test/menu.test.js.map +0 -7
  162. package/test/submenu.test-vrt.js +0 -5
  163. package/test/submenu.test-vrt.js.map +0 -7
  164. package/test/submenu.test.js +0 -970
  165. package/test/submenu.test.js.map +0 -7
package/src/Menu.dev.js DELETED
@@ -1,740 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __decorateClass = (decorators, target, key, kind) => {
5
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
6
- for (var i = decorators.length - 1, decorator; i >= 0; i--)
7
- if (decorator = decorators[i])
8
- result = (kind ? decorator(target, key, result) : decorator(result)) || result;
9
- if (kind && result) __defProp(target, key, result);
10
- return result;
11
- };
12
- import {
13
- html,
14
- SizedMixin,
15
- SpectrumElement
16
- } from "@spectrum-web-components/base";
17
- import {
18
- property,
19
- query
20
- } from "@spectrum-web-components/base/src/decorators.js";
21
- import menuStyles from "./menu.css.js";
22
- function elementIsOrContains(el, isOrContains) {
23
- return !!isOrContains && (el === isOrContains || el.contains(isOrContains));
24
- }
25
- export class Menu extends SizedMixin(SpectrumElement, { noDefaultSize: true }) {
26
- constructor() {
27
- super();
28
- this.label = "";
29
- this.ignore = false;
30
- this.value = "";
31
- this.valueSeparator = ",";
32
- this._selected = [];
33
- this.selectedItems = [];
34
- this.childItemSet = /* @__PURE__ */ new Set();
35
- this.focusedItemIndex = 0;
36
- this.focusInItemIndex = 0;
37
- this.selectedItemsMap = /* @__PURE__ */ new Map();
38
- // if the click and pointerup events are on the same target, we should not
39
- // handle the click event.
40
- this.pointerUpTarget = null;
41
- this.descendentOverlays = /* @__PURE__ */ new Map();
42
- this.handleSubmenuClosed = (event) => {
43
- event.stopPropagation();
44
- const target = event.composedPath()[0];
45
- target.dispatchEvent(
46
- new Event("sp-menu-submenu-closed", {
47
- bubbles: true,
48
- composed: true
49
- })
50
- );
51
- };
52
- this.handleSubmenuOpened = (event) => {
53
- event.stopPropagation();
54
- const target = event.composedPath()[0];
55
- target.dispatchEvent(
56
- new Event("sp-menu-submenu-opened", {
57
- bubbles: true,
58
- composed: true
59
- })
60
- );
61
- const focusedItem = this.childItems[this.focusedItemIndex];
62
- if (focusedItem) {
63
- focusedItem.focused = false;
64
- }
65
- const openedItem = event.composedPath().find((el) => this.childItemSet.has(el));
66
- if (!openedItem) return;
67
- const openedItemIndex = this.childItems.indexOf(openedItem);
68
- this.focusedItemIndex = openedItemIndex;
69
- this.focusInItemIndex = openedItemIndex;
70
- };
71
- this._hasUpdatedSelectedItemIndex = false;
72
- this._willUpdateItems = false;
73
- this.cacheUpdated = Promise.resolve();
74
- /* c8 ignore next 3 */
75
- this.resolveCacheUpdated = () => {
76
- return;
77
- };
78
- this.addEventListener(
79
- "sp-menu-item-added-or-updated",
80
- this.onSelectableItemAddedOrUpdated
81
- );
82
- this.addEventListener(
83
- "sp-menu-item-added-or-updated",
84
- this.onFocusableItemAddedOrUpdated,
85
- {
86
- capture: true
87
- }
88
- );
89
- this.addEventListener("click", this.handleClick);
90
- this.addEventListener("pointerup", this.handlePointerup);
91
- this.addEventListener("focusin", this.handleFocusin);
92
- this.addEventListener("blur", this.handleBlur);
93
- this.addEventListener("sp-opened", this.handleSubmenuOpened);
94
- this.addEventListener("sp-closed", this.handleSubmenuClosed);
95
- }
96
- static get styles() {
97
- return [menuStyles];
98
- }
99
- get isSubmenu() {
100
- return this.slot === "submenu";
101
- }
102
- get selected() {
103
- return this._selected;
104
- }
105
- set selected(selected) {
106
- if (selected === this.selected) {
107
- return;
108
- }
109
- const old = this.selected;
110
- this._selected = selected;
111
- this.selectedItems = [];
112
- this.selectedItemsMap.clear();
113
- this.childItems.forEach((item) => {
114
- if (this !== item.menuData.selectionRoot) {
115
- return;
116
- }
117
- item.selected = this.selected.includes(item.value);
118
- if (item.selected) {
119
- this.selectedItems.push(item);
120
- this.selectedItemsMap.set(item, true);
121
- }
122
- });
123
- this.requestUpdate("selected", old);
124
- }
125
- get childItems() {
126
- if (!this.cachedChildItems) {
127
- this.cachedChildItems = this.updateCachedMenuItems();
128
- }
129
- return this.cachedChildItems;
130
- }
131
- updateCachedMenuItems() {
132
- this.cachedChildItems = [];
133
- if (!this.menuSlot) {
134
- return [];
135
- }
136
- const slottedElements = this.menuSlot.assignedElements({
137
- flatten: true
138
- });
139
- for (const [i, slottedElement] of slottedElements.entries()) {
140
- if (this.childItemSet.has(slottedElement)) {
141
- this.cachedChildItems.push(slottedElement);
142
- continue;
143
- }
144
- const isHTMLSlotElement = slottedElement.localName === "slot";
145
- const flattenedChildren = isHTMLSlotElement ? slottedElement.assignedElements({
146
- flatten: true
147
- }) : [...slottedElement.querySelectorAll(`:scope > *`)];
148
- slottedElements.splice(
149
- i,
150
- 1,
151
- slottedElement,
152
- ...flattenedChildren
153
- );
154
- }
155
- return this.cachedChildItems;
156
- }
157
- /**
158
- * Hide this getter from web-component-analyzer until
159
- * https://github.com/runem/web-component-analyzer/issues/131
160
- * has been addressed.
161
- *
162
- * @private
163
- */
164
- get childRole() {
165
- if (this.resolvedRole === "listbox") {
166
- return "option";
167
- }
168
- switch (this.resolvedSelects) {
169
- case "single":
170
- return "menuitemradio";
171
- case "multiple":
172
- return "menuitemcheckbox";
173
- default:
174
- return "menuitem";
175
- }
176
- }
177
- get ownRole() {
178
- return "menu";
179
- }
180
- /**
181
- * When a descendant `<sp-menu-item>` element is added or updated it will dispatch
182
- * this event to announce its presence in the DOM. During the CAPTURE phase the first
183
- * Menu based element that the event encounters will manage the focus state of the
184
- * dispatching `<sp-menu-item>` element.
185
- * @param event
186
- */
187
- onFocusableItemAddedOrUpdated(event) {
188
- event.menuCascade.set(this, {
189
- hadFocusRoot: !!event.item.menuData.focusRoot,
190
- ancestorWithSelects: event.currentAncestorWithSelects
191
- });
192
- if (this.selects) {
193
- event.currentAncestorWithSelects = this;
194
- }
195
- event.item.menuData.focusRoot = event.item.menuData.focusRoot || this;
196
- }
197
- /**
198
- * When a descendant `<sp-menu-item>` element is added or updated it will dispatch
199
- * this event to announce its presence in the DOM. During the BUBBLE phase the first
200
- * Menu based element that the event encounters that does not inherit selection will
201
- * manage the selection state of the dispatching `<sp-menu-item>` element.
202
- * @param event
203
- */
204
- onSelectableItemAddedOrUpdated(event) {
205
- var _a, _b;
206
- const cascadeData = event.menuCascade.get(this);
207
- if (!cascadeData) return;
208
- event.item.menuData.parentMenu = event.item.menuData.parentMenu || this;
209
- if (cascadeData.hadFocusRoot && !this.ignore) {
210
- this.tabIndex = -1;
211
- }
212
- this.addChildItem(event.item);
213
- if (this.selects === "inherit") {
214
- this.resolvedSelects = "inherit";
215
- const ignoreMenu = (_a = event.currentAncestorWithSelects) == null ? void 0 : _a.ignore;
216
- this.resolvedRole = ignoreMenu ? "none" : ((_b = event.currentAncestorWithSelects) == null ? void 0 : _b.getAttribute("role")) || this.getAttribute("role") || void 0;
217
- } else if (this.selects) {
218
- this.resolvedRole = this.ignore ? "none" : this.getAttribute("role") || void 0;
219
- this.resolvedSelects = this.selects;
220
- } else {
221
- this.resolvedRole = this.ignore ? "none" : this.getAttribute("role") || void 0;
222
- this.resolvedSelects = this.resolvedRole === "none" ? "ignore" : "none";
223
- }
224
- const selects = this.resolvedSelects === "single" || this.resolvedSelects === "multiple";
225
- event.item.menuData.cleanupSteps.push(
226
- (item) => this.removeChildItem(item)
227
- );
228
- if ((selects || !this.selects && this.resolvedSelects !== "ignore") && !event.item.menuData.selectionRoot) {
229
- event.item.setRole(this.childRole);
230
- event.item.menuData.selectionRoot = event.item.menuData.selectionRoot || this;
231
- if (event.item.selected) {
232
- this.selectedItemsMap.set(event.item, true);
233
- this.selectedItems = [...this.selectedItems, event.item];
234
- this._selected = [...this.selected, event.item.value];
235
- this.value = this.selected.join(this.valueSeparator);
236
- }
237
- }
238
- }
239
- addChildItem(item) {
240
- this.childItemSet.add(item);
241
- this.handleItemsChanged();
242
- }
243
- async removeChildItem(item) {
244
- this.childItemSet.delete(item);
245
- this.cachedChildItems = void 0;
246
- if (item.focused) {
247
- this.handleItemsChanged();
248
- await this.updateComplete;
249
- this.focus();
250
- }
251
- }
252
- focus({ preventScroll } = {}) {
253
- if (!this.childItems.length || this.childItems.every((childItem) => childItem.disabled)) {
254
- return;
255
- }
256
- if (this.childItems.some(
257
- (childItem) => childItem.menuData.focusRoot !== this
258
- )) {
259
- super.focus({ preventScroll });
260
- return;
261
- }
262
- this.focusMenuItemByOffset(0);
263
- super.focus({ preventScroll });
264
- const selectedItem = this.selectedItems[0];
265
- if (selectedItem && !preventScroll) {
266
- selectedItem.scrollIntoView({ block: "nearest" });
267
- }
268
- }
269
- handleClick(event) {
270
- if (this.pointerUpTarget === event.target) {
271
- this.pointerUpTarget = null;
272
- return;
273
- }
274
- this.handlePointerBasedSelection(event);
275
- }
276
- handlePointerup(event) {
277
- this.pointerUpTarget = event.target;
278
- this.handlePointerBasedSelection(event);
279
- }
280
- handlePointerBasedSelection(event) {
281
- var _a, _b;
282
- if (event instanceof MouseEvent && event.button !== 0) {
283
- return;
284
- }
285
- const path = event.composedPath();
286
- const target = path.find((el) => {
287
- if (!(el instanceof Element)) {
288
- return false;
289
- }
290
- return el.getAttribute("role") === this.childRole;
291
- });
292
- if (event.defaultPrevented) {
293
- const index = this.childItems.indexOf(target);
294
- if (((_a = target == null ? void 0 : target.menuData) == null ? void 0 : _a.focusRoot) === this && index > -1) {
295
- this.focusedItemIndex = index;
296
- }
297
- return;
298
- }
299
- if ((target == null ? void 0 : target.href) && target.href.length) {
300
- this.dispatchEvent(
301
- new Event("change", {
302
- bubbles: true,
303
- composed: true
304
- })
305
- );
306
- return;
307
- } else if (((_b = target == null ? void 0 : target.menuData) == null ? void 0 : _b.selectionRoot) === this && this.childItems.length) {
308
- event.preventDefault();
309
- if (target.hasSubmenu || target.open) {
310
- return;
311
- }
312
- this.selectOrToggleItem(target);
313
- } else {
314
- return;
315
- }
316
- this.prepareToCleanUp();
317
- }
318
- handleFocusin(event) {
319
- var _a;
320
- if (this.childItems.some(
321
- (childItem) => childItem.menuData.focusRoot !== this
322
- )) {
323
- return;
324
- }
325
- const activeElement = this.getRootNode().activeElement;
326
- const selectionRoot = ((_a = this.childItems[this.focusedItemIndex]) == null ? void 0 : _a.menuData.selectionRoot) || this;
327
- if (activeElement !== selectionRoot || event.target !== this) {
328
- selectionRoot.focus({ preventScroll: true });
329
- if (activeElement && this.focusedItemIndex === 0) {
330
- const offset = this.childItems.findIndex(
331
- (childItem) => childItem === activeElement
332
- );
333
- this.focusMenuItemByOffset(Math.max(offset, 0));
334
- }
335
- }
336
- this.startListeningToKeyboard();
337
- }
338
- startListeningToKeyboard() {
339
- this.addEventListener("keydown", this.handleKeydown);
340
- }
341
- handleBlur(event) {
342
- if (elementIsOrContains(this, event.relatedTarget)) {
343
- return;
344
- }
345
- this.stopListeningToKeyboard();
346
- this.childItems.forEach((child) => child.focused = false);
347
- this.removeAttribute("aria-activedescendant");
348
- }
349
- stopListeningToKeyboard() {
350
- this.removeEventListener("keydown", this.handleKeydown);
351
- }
352
- handleDescendentOverlayOpened(event) {
353
- const target = event.composedPath()[0];
354
- if (!target.overlayElement) return;
355
- this.descendentOverlays.set(
356
- target.overlayElement,
357
- target.overlayElement
358
- );
359
- }
360
- handleDescendentOverlayClosed(event) {
361
- const target = event.composedPath()[0];
362
- if (!target.overlayElement) return;
363
- this.descendentOverlays.delete(target.overlayElement);
364
- }
365
- async selectOrToggleItem(targetItem) {
366
- const resolvedSelects = this.resolvedSelects;
367
- const oldSelectedItemsMap = new Map(this.selectedItemsMap);
368
- const oldSelected = this.selected.slice();
369
- const oldSelectedItems = this.selectedItems.slice();
370
- const oldValue = this.value;
371
- const focusedChild = this.childItems[this.focusedItemIndex];
372
- if (focusedChild) {
373
- focusedChild.focused = false;
374
- focusedChild.active = false;
375
- }
376
- this.focusedItemIndex = this.childItems.indexOf(targetItem);
377
- this.forwardFocusVisibleToItem(targetItem);
378
- if (resolvedSelects === "multiple") {
379
- if (this.selectedItemsMap.has(targetItem)) {
380
- this.selectedItemsMap.delete(targetItem);
381
- } else {
382
- this.selectedItemsMap.set(targetItem, true);
383
- }
384
- const selected = [];
385
- const selectedItems = [];
386
- this.childItemSet.forEach((childItem) => {
387
- if (childItem.menuData.selectionRoot !== this) return;
388
- if (this.selectedItemsMap.has(childItem)) {
389
- selected.push(childItem.value);
390
- selectedItems.push(childItem);
391
- }
392
- });
393
- this._selected = selected;
394
- this.selectedItems = selectedItems;
395
- this.value = this.selected.join(this.valueSeparator);
396
- } else {
397
- this.selectedItemsMap.clear();
398
- this.selectedItemsMap.set(targetItem, true);
399
- this.value = targetItem.value;
400
- this._selected = [targetItem.value];
401
- this.selectedItems = [targetItem];
402
- }
403
- const applyDefault = this.dispatchEvent(
404
- new Event("change", {
405
- cancelable: true,
406
- bubbles: true,
407
- composed: true
408
- })
409
- );
410
- if (!applyDefault) {
411
- this._selected = oldSelected;
412
- this.selectedItems = oldSelectedItems;
413
- this.selectedItemsMap = oldSelectedItemsMap;
414
- this.value = oldValue;
415
- return;
416
- }
417
- if (resolvedSelects === "single") {
418
- for (const oldItem of oldSelectedItemsMap.keys()) {
419
- if (oldItem !== targetItem) {
420
- oldItem.selected = false;
421
- }
422
- }
423
- targetItem.selected = true;
424
- } else if (resolvedSelects === "multiple") {
425
- targetItem.selected = !targetItem.selected;
426
- }
427
- }
428
- navigateWithinMenu(event) {
429
- const { key } = event;
430
- const lastFocusedItem = this.childItems[this.focusedItemIndex];
431
- const direction = key === "ArrowDown" ? 1 : -1;
432
- const itemToFocus = this.focusMenuItemByOffset(direction);
433
- if (itemToFocus === lastFocusedItem) {
434
- return;
435
- }
436
- event.preventDefault();
437
- event.stopPropagation();
438
- itemToFocus.scrollIntoView({ block: "nearest" });
439
- }
440
- navigateBetweenRelatedMenus(event) {
441
- const { key } = event;
442
- event.stopPropagation();
443
- const shouldOpenSubmenu = this.isLTR && key === "ArrowRight" || !this.isLTR && key === "ArrowLeft";
444
- const shouldCloseSelfAsSubmenu = this.isLTR && key === "ArrowLeft" || !this.isLTR && key === "ArrowRight";
445
- if (shouldOpenSubmenu) {
446
- const lastFocusedItem = this.childItems[this.focusedItemIndex];
447
- if (lastFocusedItem == null ? void 0 : lastFocusedItem.hasSubmenu) {
448
- lastFocusedItem.openOverlay();
449
- }
450
- } else if (shouldCloseSelfAsSubmenu && this.isSubmenu) {
451
- this.dispatchEvent(new Event("close", { bubbles: true }));
452
- this.updateSelectedItemIndex();
453
- }
454
- }
455
- handleKeydown(event) {
456
- if (event.defaultPrevented) {
457
- return;
458
- }
459
- const lastFocusedItem = this.childItems[this.focusedItemIndex];
460
- if (lastFocusedItem) {
461
- lastFocusedItem.focused = true;
462
- }
463
- const { key } = event;
464
- if (event.shiftKey && event.target !== this && this.hasAttribute("tabindex")) {
465
- this.removeAttribute("tabindex");
466
- const replaceTabindex = (event2) => {
467
- if (!event2.shiftKey && !this.hasAttribute("tabindex")) {
468
- this.tabIndex = 0;
469
- document.removeEventListener("keyup", replaceTabindex);
470
- this.removeEventListener("focusout", replaceTabindex);
471
- }
472
- };
473
- document.addEventListener("keyup", replaceTabindex);
474
- this.addEventListener("focusout", replaceTabindex);
475
- }
476
- if (key === "Tab") {
477
- this.prepareToCleanUp();
478
- return;
479
- }
480
- if (key === " ") {
481
- if (lastFocusedItem == null ? void 0 : lastFocusedItem.hasSubmenu) {
482
- lastFocusedItem.openOverlay();
483
- return;
484
- }
485
- }
486
- if (key === " " || key === "Enter") {
487
- const childItem = this.childItems[this.focusedItemIndex];
488
- if (childItem && childItem.menuData.selectionRoot === event.target) {
489
- event.preventDefault();
490
- childItem.click();
491
- }
492
- return;
493
- }
494
- if (key === "ArrowDown" || key === "ArrowUp") {
495
- const childItem = this.childItems[this.focusedItemIndex];
496
- if (childItem && childItem.menuData.selectionRoot === event.target) {
497
- this.navigateWithinMenu(event);
498
- }
499
- return;
500
- }
501
- this.navigateBetweenRelatedMenus(event);
502
- }
503
- focusMenuItemByOffset(offset) {
504
- const step = offset || 1;
505
- const focusedItem = this.childItems[this.focusedItemIndex];
506
- if (focusedItem) {
507
- focusedItem.focused = false;
508
- focusedItem.active = focusedItem.open;
509
- }
510
- this.focusedItemIndex = (this.childItems.length + this.focusedItemIndex + offset) % this.childItems.length;
511
- let itemToFocus = this.childItems[this.focusedItemIndex];
512
- let availableItems = this.childItems.length;
513
- while ((itemToFocus == null ? void 0 : itemToFocus.disabled) && availableItems) {
514
- availableItems -= 1;
515
- this.focusedItemIndex = (this.childItems.length + this.focusedItemIndex + step) % this.childItems.length;
516
- itemToFocus = this.childItems[this.focusedItemIndex];
517
- }
518
- if (!(itemToFocus == null ? void 0 : itemToFocus.disabled)) {
519
- this.forwardFocusVisibleToItem(itemToFocus);
520
- }
521
- return itemToFocus;
522
- }
523
- prepareToCleanUp() {
524
- document.addEventListener(
525
- "focusout",
526
- () => {
527
- requestAnimationFrame(() => {
528
- const focusedItem = this.childItems[this.focusedItemIndex];
529
- if (focusedItem) {
530
- focusedItem.focused = false;
531
- this.updateSelectedItemIndex();
532
- }
533
- });
534
- },
535
- { once: true }
536
- );
537
- }
538
- updateSelectedItemIndex() {
539
- let firstOrFirstSelectedIndex = 0;
540
- const selectedItemsMap = /* @__PURE__ */ new Map();
541
- const selected = [];
542
- const selectedItems = [];
543
- let itemIndex = this.childItems.length;
544
- while (itemIndex) {
545
- itemIndex -= 1;
546
- const childItem = this.childItems[itemIndex];
547
- if (childItem.menuData.selectionRoot === this) {
548
- if (childItem.selected || !this._hasUpdatedSelectedItemIndex && this.selected.includes(childItem.value)) {
549
- firstOrFirstSelectedIndex = itemIndex;
550
- selectedItemsMap.set(childItem, true);
551
- selected.unshift(childItem.value);
552
- selectedItems.unshift(childItem);
553
- }
554
- if (itemIndex !== firstOrFirstSelectedIndex) {
555
- childItem.focused = false;
556
- }
557
- }
558
- }
559
- selectedItems.map((item, i) => {
560
- if (i > 0) {
561
- item.focused = false;
562
- }
563
- });
564
- this.selectedItemsMap = selectedItemsMap;
565
- this._selected = selected;
566
- this.selectedItems = selectedItems;
567
- this.value = this.selected.join(this.valueSeparator);
568
- this.focusedItemIndex = firstOrFirstSelectedIndex;
569
- this.focusInItemIndex = firstOrFirstSelectedIndex;
570
- }
571
- handleItemsChanged() {
572
- this.cachedChildItems = void 0;
573
- if (!this._willUpdateItems) {
574
- this._willUpdateItems = true;
575
- this.cacheUpdated = this.updateCache();
576
- }
577
- }
578
- async updateCache() {
579
- if (!this.hasUpdated) {
580
- await Promise.all([
581
- new Promise((res) => requestAnimationFrame(() => res(true))),
582
- this.updateComplete
583
- ]);
584
- } else {
585
- await new Promise((res) => requestAnimationFrame(() => res(true)));
586
- }
587
- if (this.cachedChildItems === void 0) {
588
- this.updateSelectedItemIndex();
589
- this.updateItemFocus();
590
- }
591
- this._willUpdateItems = false;
592
- }
593
- updateItemFocus() {
594
- if (this.childItems.length == 0) {
595
- return;
596
- }
597
- const focusInItem = this.childItems[this.focusInItemIndex];
598
- if (this.getRootNode().activeElement === focusInItem.menuData.focusRoot) {
599
- this.forwardFocusVisibleToItem(focusInItem);
600
- }
601
- }
602
- closeDescendentOverlays() {
603
- this.descendentOverlays.forEach((overlay) => {
604
- overlay.open = false;
605
- });
606
- this.descendentOverlays = /* @__PURE__ */ new Map();
607
- }
608
- forwardFocusVisibleToItem(item) {
609
- if (!item || item.menuData.focusRoot !== this) {
610
- return;
611
- }
612
- this.closeDescendentOverlays();
613
- const focused = this.hasVisibleFocusInTree() || !!this.childItems.find((child) => {
614
- return child.hasVisibleFocusInTree();
615
- });
616
- item.focused = focused;
617
- this.setAttribute("aria-activedescendant", item.id);
618
- if (item.menuData.selectionRoot && item.menuData.selectionRoot !== this) {
619
- item.menuData.selectionRoot.focus();
620
- }
621
- }
622
- handleSlotchange({
623
- target
624
- }) {
625
- const assignedElements = target.assignedElements({
626
- flatten: true
627
- });
628
- if (this.childItems.length !== assignedElements.length) {
629
- assignedElements.forEach((item) => {
630
- if (typeof item.triggerUpdate !== "undefined") {
631
- item.triggerUpdate();
632
- } else if (typeof item.childItems !== "undefined") {
633
- item.childItems.forEach((child) => {
634
- child.triggerUpdate();
635
- });
636
- }
637
- });
638
- }
639
- }
640
- renderMenuItemSlot() {
641
- return html`
642
- <slot
643
- @sp-menu-submenu-opened=${this.handleDescendentOverlayOpened}
644
- @sp-menu-submenu-closed=${this.handleDescendentOverlayClosed}
645
- @slotchange=${this.handleSlotchange}
646
- ></slot>
647
- `;
648
- }
649
- render() {
650
- return this.renderMenuItemSlot();
651
- }
652
- firstUpdated(changed) {
653
- super.firstUpdated(changed);
654
- if (!this.hasAttribute("tabindex") && !this.ignore) {
655
- const role = this.getAttribute("role");
656
- if (role === "group") {
657
- this.tabIndex = -1;
658
- } else {
659
- this.tabIndex = 0;
660
- }
661
- }
662
- const updates = [
663
- new Promise((res) => requestAnimationFrame(() => res(true)))
664
- ];
665
- [...this.children].forEach((item) => {
666
- if (item.localName === "sp-menu-item") {
667
- updates.push(item.updateComplete);
668
- }
669
- });
670
- this.childItemsUpdated = Promise.all(updates);
671
- }
672
- updated(changes) {
673
- super.updated(changes);
674
- if (changes.has("selects") && this.hasUpdated) {
675
- this.selectsChanged();
676
- }
677
- if (changes.has("label") && (this.label || typeof changes.get("label") !== "undefined")) {
678
- if (this.label) {
679
- this.setAttribute("aria-label", this.label);
680
- } else {
681
- this.removeAttribute("aria-label");
682
- }
683
- }
684
- }
685
- selectsChanged() {
686
- const updates = [
687
- new Promise((res) => requestAnimationFrame(() => res(true)))
688
- ];
689
- this.childItemSet.forEach((childItem) => {
690
- updates.push(childItem.triggerUpdate());
691
- });
692
- this.childItemsUpdated = Promise.all(updates);
693
- }
694
- connectedCallback() {
695
- super.connectedCallback();
696
- if (!this.hasAttribute("role") && !this.ignore) {
697
- this.setAttribute("role", this.ownRole);
698
- }
699
- this.updateComplete.then(() => this.updateItemFocus());
700
- }
701
- disconnectedCallback() {
702
- this.cachedChildItems = void 0;
703
- this.selectedItems = [];
704
- this.selectedItemsMap.clear();
705
- this.childItemSet.clear();
706
- this.descendentOverlays = /* @__PURE__ */ new Map();
707
- super.disconnectedCallback();
708
- }
709
- async getUpdateComplete() {
710
- const complete = await super.getUpdateComplete();
711
- await this.childItemsUpdated;
712
- await this.cacheUpdated;
713
- return complete;
714
- }
715
- }
716
- __decorateClass([
717
- property({ type: String, reflect: true })
718
- ], Menu.prototype, "label", 2);
719
- __decorateClass([
720
- property({ type: Boolean, reflect: true })
721
- ], Menu.prototype, "ignore", 2);
722
- __decorateClass([
723
- property({ type: String, reflect: true })
724
- ], Menu.prototype, "selects", 2);
725
- __decorateClass([
726
- property({ type: String })
727
- ], Menu.prototype, "value", 2);
728
- __decorateClass([
729
- property({ type: String, attribute: "value-separator" })
730
- ], Menu.prototype, "valueSeparator", 2);
731
- __decorateClass([
732
- property({ attribute: false })
733
- ], Menu.prototype, "selected", 1);
734
- __decorateClass([
735
- property({ attribute: false })
736
- ], Menu.prototype, "selectedItems", 2);
737
- __decorateClass([
738
- query("slot:not([name])")
739
- ], Menu.prototype, "menuSlot", 2);
740
- //# sourceMappingURL=Menu.dev.js.map