@spectrum-web-components/menu 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. package/package.json +12 -12
  2. package/sp-menu-divider.d.ts +6 -0
  3. package/sp-menu-divider.dev.js +5 -0
  4. package/sp-menu-divider.dev.js.map +7 -0
  5. package/sp-menu-divider.js +2 -0
  6. package/sp-menu-divider.js.map +7 -0
  7. package/sp-menu-group.d.ts +6 -0
  8. package/sp-menu-group.dev.js +5 -0
  9. package/sp-menu-group.dev.js.map +7 -0
  10. package/sp-menu-group.js +2 -0
  11. package/sp-menu-group.js.map +7 -0
  12. package/sp-menu-item.d.ts +6 -0
  13. package/sp-menu-item.dev.js +5 -0
  14. package/sp-menu-item.dev.js.map +7 -0
  15. package/sp-menu-item.js +2 -0
  16. package/sp-menu-item.js.map +7 -0
  17. package/sp-menu.d.ts +6 -0
  18. package/sp-menu.dev.js +5 -0
  19. package/sp-menu.dev.js.map +7 -0
  20. package/sp-menu.js +2 -0
  21. package/sp-menu.js.map +7 -0
  22. package/src/Menu.d.ts +118 -0
  23. package/src/Menu.dev.js +740 -0
  24. package/src/Menu.dev.js.map +7 -0
  25. package/src/Menu.js +8 -0
  26. package/src/Menu.js.map +7 -0
  27. package/src/MenuDivider.d.ts +13 -0
  28. package/src/MenuDivider.dev.js +19 -0
  29. package/src/MenuDivider.dev.js.map +7 -0
  30. package/src/MenuDivider.js +2 -0
  31. package/src/MenuDivider.js.map +7 -0
  32. package/src/MenuGroup.d.ts +18 -0
  33. package/src/MenuGroup.dev.js +78 -0
  34. package/src/MenuGroup.dev.js.map +7 -0
  35. package/src/MenuGroup.js +7 -0
  36. package/src/MenuGroup.js.map +7 -0
  37. package/src/MenuItem.d.ts +125 -0
  38. package/src/MenuItem.dev.js +518 -0
  39. package/src/MenuItem.dev.js.map +7 -0
  40. package/src/MenuItem.js +50 -0
  41. package/src/MenuItem.js.map +7 -0
  42. package/src/checkmark-overrides.css.d.ts +2 -0
  43. package/src/checkmark-overrides.css.dev.js +7 -0
  44. package/src/checkmark-overrides.css.dev.js.map +7 -0
  45. package/src/checkmark-overrides.css.js +4 -0
  46. package/src/checkmark-overrides.css.js.map +7 -0
  47. package/src/chevron-overrides.css.d.ts +2 -0
  48. package/src/chevron-overrides.css.dev.js +7 -0
  49. package/src/chevron-overrides.css.dev.js.map +7 -0
  50. package/src/chevron-overrides.css.js +4 -0
  51. package/src/chevron-overrides.css.js.map +7 -0
  52. package/src/index.d.ts +4 -0
  53. package/src/index.dev.js +6 -0
  54. package/src/index.dev.js.map +7 -0
  55. package/src/index.js +2 -0
  56. package/src/index.js.map +7 -0
  57. package/src/menu-divider-overrides.css.d.ts +2 -0
  58. package/src/menu-divider-overrides.css.dev.js +7 -0
  59. package/src/menu-divider-overrides.css.dev.js.map +7 -0
  60. package/src/menu-divider-overrides.css.js +4 -0
  61. package/src/menu-divider-overrides.css.js.map +7 -0
  62. package/src/menu-divider.css.d.ts +2 -0
  63. package/src/menu-divider.css.dev.js +7 -0
  64. package/src/menu-divider.css.dev.js.map +7 -0
  65. package/src/menu-divider.css.js +4 -0
  66. package/src/menu-divider.css.js.map +7 -0
  67. package/src/menu-group.css.d.ts +2 -0
  68. package/src/menu-group.css.dev.js +7 -0
  69. package/src/menu-group.css.dev.js.map +7 -0
  70. package/src/menu-group.css.js +4 -0
  71. package/src/menu-group.css.js.map +7 -0
  72. package/src/menu-item-overrides.css.d.ts +2 -0
  73. package/src/menu-item-overrides.css.dev.js +7 -0
  74. package/src/menu-item-overrides.css.dev.js.map +7 -0
  75. package/src/menu-item-overrides.css.js +4 -0
  76. package/src/menu-item-overrides.css.js.map +7 -0
  77. package/src/menu-item.css.d.ts +2 -0
  78. package/src/menu-item.css.dev.js +7 -0
  79. package/src/menu-item.css.dev.js.map +7 -0
  80. package/src/menu-item.css.js +4 -0
  81. package/src/menu-item.css.js.map +7 -0
  82. package/src/menu-overrides.css.d.ts +2 -0
  83. package/src/menu-overrides.css.dev.js +7 -0
  84. package/src/menu-overrides.css.dev.js.map +7 -0
  85. package/src/menu-overrides.css.js +4 -0
  86. package/src/menu-overrides.css.js.map +7 -0
  87. package/src/menu-sectionHeading-overrides.css.d.ts +2 -0
  88. package/src/menu-sectionHeading-overrides.css.dev.js +7 -0
  89. package/src/menu-sectionHeading-overrides.css.dev.js.map +7 -0
  90. package/src/menu-sectionHeading-overrides.css.js +4 -0
  91. package/src/menu-sectionHeading-overrides.css.js.map +7 -0
  92. package/src/menu.css.d.ts +2 -0
  93. package/src/menu.css.dev.js +7 -0
  94. package/src/menu.css.dev.js.map +7 -0
  95. package/src/menu.css.js +4 -0
  96. package/src/menu.css.js.map +7 -0
  97. package/src/spectrum-checkmark.css.d.ts +2 -0
  98. package/src/spectrum-checkmark.css.dev.js +7 -0
  99. package/src/spectrum-checkmark.css.dev.js.map +7 -0
  100. package/src/spectrum-checkmark.css.js +4 -0
  101. package/src/spectrum-checkmark.css.js.map +7 -0
  102. package/src/spectrum-chevron.css.d.ts +2 -0
  103. package/src/spectrum-chevron.css.dev.js +7 -0
  104. package/src/spectrum-chevron.css.dev.js.map +7 -0
  105. package/src/spectrum-chevron.css.js +4 -0
  106. package/src/spectrum-chevron.css.js.map +7 -0
  107. package/src/spectrum-menu-divider.css.d.ts +2 -0
  108. package/src/spectrum-menu-divider.css.dev.js +7 -0
  109. package/src/spectrum-menu-divider.css.dev.js.map +7 -0
  110. package/src/spectrum-menu-divider.css.js +4 -0
  111. package/src/spectrum-menu-divider.css.js.map +7 -0
  112. package/src/spectrum-menu-item.css.d.ts +2 -0
  113. package/src/spectrum-menu-item.css.dev.js +7 -0
  114. package/src/spectrum-menu-item.css.dev.js.map +7 -0
  115. package/src/spectrum-menu-item.css.js +4 -0
  116. package/src/spectrum-menu-item.css.js.map +7 -0
  117. package/src/spectrum-menu-sectionHeading.css.d.ts +2 -0
  118. package/src/spectrum-menu-sectionHeading.css.dev.js +7 -0
  119. package/src/spectrum-menu-sectionHeading.css.dev.js.map +7 -0
  120. package/src/spectrum-menu-sectionHeading.css.js +4 -0
  121. package/src/spectrum-menu-sectionHeading.css.js.map +7 -0
  122. package/src/spectrum-menu.css.d.ts +2 -0
  123. package/src/spectrum-menu.css.dev.js +7 -0
  124. package/src/spectrum-menu.css.dev.js.map +7 -0
  125. package/src/spectrum-menu.css.js +4 -0
  126. package/src/spectrum-menu.css.js.map +7 -0
  127. package/stories/index.js +82 -0
  128. package/stories/index.js.map +7 -0
  129. package/stories/menu-divider.stories.js +32 -0
  130. package/stories/menu-divider.stories.js.map +7 -0
  131. package/stories/menu-group.stories.js +144 -0
  132. package/stories/menu-group.stories.js.map +7 -0
  133. package/stories/menu-item.disconnected.stories.js +178 -0
  134. package/stories/menu-item.disconnected.stories.js.map +7 -0
  135. package/stories/menu-item.stories.js +73 -0
  136. package/stories/menu-item.stories.js.map +7 -0
  137. package/stories/menu-sizes.stories.js +11 -0
  138. package/stories/menu-sizes.stories.js.map +7 -0
  139. package/stories/menu.stories.js +407 -0
  140. package/stories/menu.stories.js.map +7 -0
  141. package/stories/submenu.stories.js +346 -0
  142. package/stories/submenu.stories.js.map +7 -0
  143. package/test/benchmark/test-basic.js +24 -0
  144. package/test/benchmark/test-basic.js.map +7 -0
  145. package/test/menu-divider.test-vrt.js +5 -0
  146. package/test/menu-divider.test-vrt.js.map +7 -0
  147. package/test/menu-group.test-vrt.js +5 -0
  148. package/test/menu-group.test-vrt.js.map +7 -0
  149. package/test/menu-group.test.js +405 -0
  150. package/test/menu-group.test.js.map +7 -0
  151. package/test/menu-item.disconnected.test-vrt.js +5 -0
  152. package/test/menu-item.disconnected.test-vrt.js.map +7 -0
  153. package/test/menu-item.test-vrt.js +5 -0
  154. package/test/menu-item.test-vrt.js.map +7 -0
  155. package/test/menu-item.test.js +189 -0
  156. package/test/menu-item.test.js.map +7 -0
  157. package/test/menu-memory.test.js +5 -0
  158. package/test/menu-memory.test.js.map +7 -0
  159. package/test/menu-selects.test.js +530 -0
  160. package/test/menu-selects.test.js.map +7 -0
  161. package/test/menu-sizes.test-vrt.js +5 -0
  162. package/test/menu-sizes.test-vrt.js.map +7 -0
  163. package/test/menu.test-vrt.js +5 -0
  164. package/test/menu.test-vrt.js.map +7 -0
  165. package/test/menu.test.js +559 -0
  166. package/test/menu.test.js.map +7 -0
  167. package/test/submenu.test-vrt.js +5 -0
  168. package/test/submenu.test-vrt.js.map +7 -0
  169. package/test/submenu.test.js +970 -0
  170. package/test/submenu.test.js.map +7 -0
@@ -0,0 +1,125 @@
1
+ import { CSSResultArray, PropertyValues, TemplateResult } from '@spectrum-web-components/base';
2
+ import '@spectrum-web-components/icons-ui/icons/sp-icon-checkmark100.js';
3
+ import { Focusable } from '@spectrum-web-components/shared/src/focusable.js';
4
+ import '@spectrum-web-components/icons-ui/icons/sp-icon-chevron100.js';
5
+ import type { Menu } from './Menu.js';
6
+ import type { Overlay } from '@spectrum-web-components/overlay';
7
+ type MenuCascadeItem = {
8
+ hadFocusRoot: boolean;
9
+ ancestorWithSelects?: HTMLElement;
10
+ };
11
+ export declare class MenuItemAddedOrUpdatedEvent extends Event {
12
+ constructor(item: MenuItem);
13
+ clear(item: MenuItem): void;
14
+ menuCascade: WeakMap<HTMLElement, MenuCascadeItem>;
15
+ get item(): MenuItem;
16
+ private _item;
17
+ currentAncestorWithSelects?: Menu;
18
+ }
19
+ export type MenuItemChildren = {
20
+ icon: Element[];
21
+ content: Node[];
22
+ };
23
+ declare const MenuItem_base: typeof Focusable & {
24
+ new (...args: any[]): import("@spectrum-web-components/shared").SlotPresenceObservingInterface;
25
+ prototype: import("@spectrum-web-components/shared").SlotPresenceObservingInterface;
26
+ } & {
27
+ new (...args: any[]): import("@spectrum-web-components/shared").SlotTextObservingInterface;
28
+ prototype: import("@spectrum-web-components/shared").SlotTextObservingInterface;
29
+ } & {
30
+ new (...args: any[]): import("@spectrum-web-components/shared").LikeAnchorInterface;
31
+ prototype: import("@spectrum-web-components/shared").LikeAnchorInterface;
32
+ };
33
+ /**
34
+ * @element sp-menu-item
35
+ *
36
+ * @slot - text content to display within the Menu Item
37
+ * @slot description - description to be placed below the label of the Menu Item
38
+ * @slot icon - icon element to be placed at the start of the Menu Item
39
+ * @slot value - content placed at the end of the Menu Item like values, keyboard shortcuts, etc.
40
+ * @slot submenu - content placed in a submenu
41
+ * @fires sp-menu-item-added - announces the item has been added so a parent menu can take ownerships
42
+ */
43
+ export declare class MenuItem extends MenuItem_base {
44
+ static get styles(): CSSResultArray;
45
+ abortControllerSubmenu: AbortController;
46
+ active: boolean;
47
+ private dependencyManager;
48
+ focused: boolean;
49
+ selected: boolean;
50
+ get value(): string;
51
+ set value(value: string);
52
+ private _value;
53
+ /**
54
+ * @private
55
+ */
56
+ get itemText(): string;
57
+ hasSubmenu: boolean;
58
+ contentSlot: HTMLSlotElement;
59
+ iconSlot: HTMLSlotElement;
60
+ noWrap: boolean;
61
+ private anchorElement;
62
+ overlayElement: Overlay;
63
+ private submenuElement?;
64
+ get focusElement(): HTMLElement;
65
+ protected get hasIcon(): boolean;
66
+ get itemChildren(): MenuItemChildren;
67
+ private _itemChildren?;
68
+ constructor();
69
+ open: boolean;
70
+ click(): void;
71
+ private handleClickCapture;
72
+ private handleSlottableRequest;
73
+ private proxyFocus;
74
+ private shouldProxyClick;
75
+ protected breakItemChildrenCache(): void;
76
+ protected renderSubmenu(): TemplateResult;
77
+ protected render(): TemplateResult;
78
+ protected manageSubmenu(event: Event & {
79
+ target: HTMLSlotElement;
80
+ }): void;
81
+ private handlePointerdown;
82
+ protected firstUpdated(changes: PropertyValues): void;
83
+ protected closeOverlaysForRoot(): void;
84
+ protected handleSubmenuClick(event: Event): void;
85
+ protected handleSubmenuFocus(): void;
86
+ protected handleBeforetoggle: (event: Event) => void;
87
+ protected handlePointerenter(): void;
88
+ protected leaveTimeout?: ReturnType<typeof setTimeout>;
89
+ protected recentlyLeftChild: boolean;
90
+ protected handlePointerleave(): void;
91
+ /**
92
+ * When there is a `change` event in the submenu for this item
93
+ * then we "click" this item to cascade the selection up the
94
+ * menu tree allowing all submenus between the initial selection
95
+ * and the root of the tree to have their selection changes and
96
+ * be closed.
97
+ */
98
+ protected handleSubmenuChange(event: Event): void;
99
+ protected handleSubmenuPointerenter(): void;
100
+ protected handleSubmenuPointerleave(): Promise<void>;
101
+ protected handleSubmenuOpen(event: Event): void;
102
+ protected cleanup(): void;
103
+ openOverlay(): Promise<void>;
104
+ updateAriaSelected(): void;
105
+ setRole(role: string): void;
106
+ protected updated(changes: PropertyValues<this>): void;
107
+ connectedCallback(): void;
108
+ _parentElement: HTMLElement;
109
+ disconnectedCallback(): void;
110
+ private willDispatchUpdate;
111
+ triggerUpdate(): Promise<void>;
112
+ dispatchUpdate(): void;
113
+ menuData: {
114
+ focusRoot?: Menu;
115
+ parentMenu?: Menu;
116
+ selectionRoot?: Menu;
117
+ cleanupSteps: ((item: MenuItem) => void)[];
118
+ };
119
+ }
120
+ declare global {
121
+ interface GlobalEventHandlersEventMap {
122
+ 'sp-menu-item-added-or-updated': MenuItemAddedOrUpdatedEvent;
123
+ }
124
+ }
125
+ export {};
@@ -0,0 +1,518 @@
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
+ nothing
15
+ } from "@spectrum-web-components/base";
16
+ import {
17
+ ObserveSlotPresence,
18
+ ObserveSlotText,
19
+ randomID
20
+ } from "@spectrum-web-components/shared";
21
+ import {
22
+ property,
23
+ query
24
+ } from "@spectrum-web-components/base/src/decorators.js";
25
+ import "@spectrum-web-components/icons-ui/icons/sp-icon-checkmark100.js";
26
+ import { LikeAnchor } from "@spectrum-web-components/shared/src/like-anchor.js";
27
+ import { Focusable } from "@spectrum-web-components/shared/src/focusable.js";
28
+ import "@spectrum-web-components/icons-ui/icons/sp-icon-chevron100.js";
29
+ import chevronStyles from "@spectrum-web-components/icon/src/spectrum-icon-chevron.css.js";
30
+ import chevronIconOverrides from "@spectrum-web-components/icon/src/icon-chevron-overrides.css.js";
31
+ import { DependencyManagerController } from "@spectrum-web-components/reactive-controllers/src/DependencyManger.js";
32
+ import menuItemStyles from "./menu-item.css.js";
33
+ import checkmarkStyles from "@spectrum-web-components/icon/src/spectrum-icon-checkmark.css.js";
34
+ import checkmarkSmallOverrides from "@spectrum-web-components/icon/src/icon-checkmark-overrides.css.js";
35
+ import { MutationController } from "@lit-labs/observers/mutation-controller.js";
36
+ import { SlottableRequestEvent } from "@spectrum-web-components/overlay/src/slottable-request-event.js";
37
+ const POINTERLEAVE_TIMEOUT = 100;
38
+ export class MenuItemAddedOrUpdatedEvent extends Event {
39
+ constructor(item) {
40
+ super("sp-menu-item-added-or-updated", {
41
+ bubbles: true,
42
+ composed: true
43
+ });
44
+ this.menuCascade = /* @__PURE__ */ new WeakMap();
45
+ this.clear(item);
46
+ }
47
+ clear(item) {
48
+ this._item = item;
49
+ this.currentAncestorWithSelects = void 0;
50
+ item.menuData = {
51
+ cleanupSteps: [],
52
+ focusRoot: void 0,
53
+ selectionRoot: void 0,
54
+ parentMenu: void 0
55
+ };
56
+ this.menuCascade = /* @__PURE__ */ new WeakMap();
57
+ }
58
+ get item() {
59
+ return this._item;
60
+ }
61
+ }
62
+ export class MenuItem extends LikeAnchor(
63
+ ObserveSlotText(ObserveSlotPresence(Focusable, '[slot="icon"]'))
64
+ ) {
65
+ constructor() {
66
+ super();
67
+ this.active = false;
68
+ this.dependencyManager = new DependencyManagerController(this);
69
+ this.focused = false;
70
+ this.selected = false;
71
+ this._value = "";
72
+ this.hasSubmenu = false;
73
+ this.noWrap = false;
74
+ this.open = false;
75
+ this.handleSlottableRequest = (event) => {
76
+ var _a;
77
+ (_a = this.submenuElement) == null ? void 0 : _a.dispatchEvent(
78
+ new SlottableRequestEvent(event.name, event.data)
79
+ );
80
+ };
81
+ this.proxyFocus = () => {
82
+ this.focus();
83
+ };
84
+ this.handleBeforetoggle = (event) => {
85
+ if (event.newState === "closed") {
86
+ this.open = true;
87
+ this.overlayElement.manuallyKeepOpen();
88
+ this.overlayElement.removeEventListener(
89
+ "beforetoggle",
90
+ this.handleBeforetoggle
91
+ );
92
+ }
93
+ };
94
+ this.recentlyLeftChild = false;
95
+ this.willDispatchUpdate = false;
96
+ this.menuData = {
97
+ focusRoot: void 0,
98
+ parentMenu: void 0,
99
+ selectionRoot: void 0,
100
+ cleanupSteps: []
101
+ };
102
+ this.addEventListener("click", this.handleClickCapture, {
103
+ capture: true
104
+ });
105
+ new MutationController(this, {
106
+ config: {
107
+ characterData: true,
108
+ childList: true,
109
+ subtree: true
110
+ },
111
+ callback: (mutations) => {
112
+ const isSubmenu = mutations.every(
113
+ (mutation) => mutation.target.slot === "submenu"
114
+ );
115
+ if (isSubmenu) {
116
+ return;
117
+ }
118
+ this.breakItemChildrenCache();
119
+ }
120
+ });
121
+ }
122
+ static get styles() {
123
+ return [
124
+ menuItemStyles,
125
+ checkmarkStyles,
126
+ checkmarkSmallOverrides,
127
+ chevronStyles,
128
+ chevronIconOverrides
129
+ ];
130
+ }
131
+ get value() {
132
+ return this._value || this.itemText;
133
+ }
134
+ set value(value) {
135
+ if (value === this._value) {
136
+ return;
137
+ }
138
+ this._value = value || "";
139
+ if (this._value) {
140
+ this.setAttribute("value", this._value);
141
+ } else {
142
+ this.removeAttribute("value");
143
+ }
144
+ }
145
+ /**
146
+ * @private
147
+ */
148
+ get itemText() {
149
+ return this.itemChildren.content.reduce(
150
+ (acc, node) => acc + (node.textContent || "").trim(),
151
+ ""
152
+ );
153
+ }
154
+ get focusElement() {
155
+ return this;
156
+ }
157
+ get hasIcon() {
158
+ return this.slotContentIsPresent;
159
+ }
160
+ get itemChildren() {
161
+ if (!this.iconSlot || !this.contentSlot) {
162
+ return {
163
+ icon: [],
164
+ content: []
165
+ };
166
+ }
167
+ if (this._itemChildren) {
168
+ return this._itemChildren;
169
+ }
170
+ const icon = this.iconSlot.assignedElements().map((element) => {
171
+ const newElement = element.cloneNode(true);
172
+ newElement.removeAttribute("slot");
173
+ newElement.classList.toggle("icon");
174
+ return newElement;
175
+ });
176
+ const content = this.contentSlot.assignedNodes().map((node) => node.cloneNode(true));
177
+ this._itemChildren = { icon, content };
178
+ return this._itemChildren;
179
+ }
180
+ click() {
181
+ if (this.disabled) {
182
+ return;
183
+ }
184
+ if (this.shouldProxyClick()) {
185
+ return;
186
+ }
187
+ super.click();
188
+ }
189
+ handleClickCapture(event) {
190
+ if (this.disabled) {
191
+ event.preventDefault();
192
+ event.stopImmediatePropagation();
193
+ event.stopPropagation();
194
+ return false;
195
+ }
196
+ }
197
+ shouldProxyClick() {
198
+ let handled = false;
199
+ if (this.anchorElement) {
200
+ this.anchorElement.click();
201
+ handled = true;
202
+ }
203
+ return handled;
204
+ }
205
+ breakItemChildrenCache() {
206
+ this._itemChildren = void 0;
207
+ this.triggerUpdate();
208
+ }
209
+ renderSubmenu() {
210
+ const slot = html`
211
+ <slot
212
+ name="submenu"
213
+ @slotchange=${this.manageSubmenu}
214
+ @sp-menu-item-added-or-updated=${{
215
+ handleEvent: (event) => {
216
+ event.clear(event.item);
217
+ },
218
+ capture: true
219
+ }}
220
+ @focusin=${(event) => event.stopPropagation()}
221
+ ></slot>
222
+ `;
223
+ if (!this.hasSubmenu) {
224
+ return slot;
225
+ }
226
+ this.dependencyManager.add("sp-overlay");
227
+ this.dependencyManager.add("sp-popover");
228
+ import("@spectrum-web-components/overlay/sp-overlay.js");
229
+ import("@spectrum-web-components/popover/sp-popover.js");
230
+ return html`
231
+ <sp-overlay
232
+ .triggerElement=${this}
233
+ ?disabled=${!this.hasSubmenu}
234
+ ?open=${this.hasSubmenu && this.open && this.dependencyManager.loaded}
235
+ .placement=${this.isLTR ? "right-start" : "left-start"}
236
+ .offset=${[-10, -5]}
237
+ .type=${"auto"}
238
+ @close=${(event) => event.stopPropagation()}
239
+ @slottable-request=${this.handleSlottableRequest}
240
+ >
241
+ <sp-popover
242
+ @change=${(event) => {
243
+ this.handleSubmenuChange(event);
244
+ this.open = false;
245
+ }}
246
+ @pointerenter=${this.handleSubmenuPointerenter}
247
+ @pointerleave=${this.handleSubmenuPointerleave}
248
+ @sp-menu-item-added-or-updated=${(event) => event.stopPropagation()}
249
+ >
250
+ ${slot}
251
+ </sp-popover>
252
+ </sp-overlay>
253
+ <sp-icon-chevron100
254
+ class="spectrum-UIIcon-ChevronRight100 chevron icon"
255
+ ></sp-icon-chevron100>
256
+ `;
257
+ }
258
+ render() {
259
+ return html`
260
+ ${this.selected ? html`
261
+ <sp-icon-checkmark100
262
+ id="selected"
263
+ class="spectrum-UIIcon-Checkmark100
264
+ icon
265
+ checkmark
266
+ ${this.hasIcon ? "checkmark--withAdjacentIcon" : ""}"
267
+ ></sp-icon-checkmark100>
268
+ ` : nothing}
269
+ <slot name="icon"></slot>
270
+ <div id="label">
271
+ <slot id="slot"></slot>
272
+ </div>
273
+ <slot name="description"></slot>
274
+ <slot name="value"></slot>
275
+ ${this.href && this.href.length > 0 ? super.renderAnchor({
276
+ id: "button",
277
+ ariaHidden: true,
278
+ className: "button anchor hidden"
279
+ }) : nothing}
280
+ ${this.renderSubmenu()}
281
+ `;
282
+ }
283
+ manageSubmenu(event) {
284
+ this.submenuElement = event.target.assignedElements({
285
+ flatten: true
286
+ })[0];
287
+ this.hasSubmenu = !!this.submenuElement;
288
+ if (this.hasSubmenu) {
289
+ this.setAttribute("aria-haspopup", "true");
290
+ }
291
+ }
292
+ handlePointerdown(event) {
293
+ if (event.target === this && this.hasSubmenu && this.open) {
294
+ this.addEventListener("focus", this.handleSubmenuFocus, {
295
+ once: true
296
+ });
297
+ this.overlayElement.addEventListener(
298
+ "beforetoggle",
299
+ this.handleBeforetoggle
300
+ );
301
+ }
302
+ }
303
+ firstUpdated(changes) {
304
+ super.firstUpdated(changes);
305
+ this.setAttribute("tabindex", "-1");
306
+ this.addEventListener("pointerdown", this.handlePointerdown);
307
+ this.addEventListener("pointerenter", this.closeOverlaysForRoot);
308
+ if (!this.hasAttribute("id")) {
309
+ this.id = `sp-menu-item-${randomID()}`;
310
+ }
311
+ }
312
+ closeOverlaysForRoot() {
313
+ var _a;
314
+ if (this.open) return;
315
+ (_a = this.menuData.parentMenu) == null ? void 0 : _a.closeDescendentOverlays();
316
+ }
317
+ handleSubmenuClick(event) {
318
+ if (event.composedPath().includes(this.overlayElement)) {
319
+ return;
320
+ }
321
+ this.openOverlay();
322
+ }
323
+ handleSubmenuFocus() {
324
+ requestAnimationFrame(() => {
325
+ this.overlayElement.open = this.open;
326
+ });
327
+ }
328
+ handlePointerenter() {
329
+ if (this.leaveTimeout) {
330
+ clearTimeout(this.leaveTimeout);
331
+ delete this.leaveTimeout;
332
+ return;
333
+ }
334
+ this.openOverlay();
335
+ }
336
+ handlePointerleave() {
337
+ if (this.open && !this.recentlyLeftChild) {
338
+ this.leaveTimeout = setTimeout(() => {
339
+ delete this.leaveTimeout;
340
+ this.open = false;
341
+ }, POINTERLEAVE_TIMEOUT);
342
+ }
343
+ }
344
+ /**
345
+ * When there is a `change` event in the submenu for this item
346
+ * then we "click" this item to cascade the selection up the
347
+ * menu tree allowing all submenus between the initial selection
348
+ * and the root of the tree to have their selection changes and
349
+ * be closed.
350
+ */
351
+ handleSubmenuChange(event) {
352
+ var _a;
353
+ event.stopPropagation();
354
+ (_a = this.menuData.selectionRoot) == null ? void 0 : _a.selectOrToggleItem(this);
355
+ }
356
+ handleSubmenuPointerenter() {
357
+ this.recentlyLeftChild = true;
358
+ }
359
+ async handleSubmenuPointerleave() {
360
+ requestAnimationFrame(() => {
361
+ this.recentlyLeftChild = false;
362
+ });
363
+ }
364
+ handleSubmenuOpen(event) {
365
+ this.focused = false;
366
+ const parentOverlay = event.composedPath().find((el) => {
367
+ return el !== this.overlayElement && el.localName === "sp-overlay";
368
+ });
369
+ this.overlayElement.parentOverlayToForceClose = parentOverlay;
370
+ }
371
+ cleanup() {
372
+ this.open = false;
373
+ this.active = false;
374
+ }
375
+ async openOverlay() {
376
+ if (!this.hasSubmenu || this.open || this.disabled) {
377
+ return;
378
+ }
379
+ this.open = true;
380
+ this.active = true;
381
+ this.setAttribute("aria-expanded", "true");
382
+ this.addEventListener("sp-closed", this.cleanup, {
383
+ once: true
384
+ });
385
+ }
386
+ updateAriaSelected() {
387
+ const role = this.getAttribute("role");
388
+ if (role === "option") {
389
+ this.setAttribute(
390
+ "aria-selected",
391
+ this.selected ? "true" : "false"
392
+ );
393
+ } else if (role === "menuitemcheckbox" || role === "menuitemradio") {
394
+ this.setAttribute("aria-checked", this.selected ? "true" : "false");
395
+ }
396
+ }
397
+ setRole(role) {
398
+ this.setAttribute("role", role);
399
+ this.updateAriaSelected();
400
+ }
401
+ updated(changes) {
402
+ var _a, _b;
403
+ super.updated(changes);
404
+ if (changes.has("label") && (this.label || typeof changes.get("label") !== "undefined")) {
405
+ this.setAttribute("aria-label", this.label || "");
406
+ }
407
+ if (changes.has("active") && (this.active || typeof changes.get("active") !== "undefined")) {
408
+ if (this.active) {
409
+ (_a = this.menuData.selectionRoot) == null ? void 0 : _a.closeDescendentOverlays();
410
+ }
411
+ }
412
+ if (this.anchorElement) {
413
+ this.anchorElement.addEventListener("focus", this.proxyFocus);
414
+ this.anchorElement.tabIndex = -1;
415
+ }
416
+ if (changes.has("selected")) {
417
+ this.updateAriaSelected();
418
+ }
419
+ if (changes.has("hasSubmenu") && (this.hasSubmenu || typeof changes.get("hasSubmenu") !== "undefined")) {
420
+ if (this.hasSubmenu) {
421
+ this.abortControllerSubmenu = new AbortController();
422
+ const options = { signal: this.abortControllerSubmenu.signal };
423
+ this.addEventListener(
424
+ "click",
425
+ this.handleSubmenuClick,
426
+ options
427
+ );
428
+ this.addEventListener(
429
+ "pointerenter",
430
+ this.handlePointerenter,
431
+ options
432
+ );
433
+ this.addEventListener(
434
+ "pointerleave",
435
+ this.handlePointerleave,
436
+ options
437
+ );
438
+ this.addEventListener(
439
+ "sp-opened",
440
+ this.handleSubmenuOpen,
441
+ options
442
+ );
443
+ } else {
444
+ (_b = this.abortControllerSubmenu) == null ? void 0 : _b.abort();
445
+ }
446
+ }
447
+ }
448
+ connectedCallback() {
449
+ super.connectedCallback();
450
+ this.triggerUpdate();
451
+ }
452
+ disconnectedCallback() {
453
+ this.menuData.cleanupSteps.forEach((removal) => removal(this));
454
+ this.menuData = {
455
+ focusRoot: void 0,
456
+ parentMenu: void 0,
457
+ selectionRoot: void 0,
458
+ cleanupSteps: []
459
+ };
460
+ super.disconnectedCallback();
461
+ }
462
+ async triggerUpdate() {
463
+ if (this.willDispatchUpdate) {
464
+ return;
465
+ }
466
+ this.willDispatchUpdate = true;
467
+ await new Promise((ready) => requestAnimationFrame(ready));
468
+ this.dispatchUpdate();
469
+ }
470
+ dispatchUpdate() {
471
+ if (!this.isConnected) {
472
+ return;
473
+ }
474
+ this.dispatchEvent(new MenuItemAddedOrUpdatedEvent(this));
475
+ this.willDispatchUpdate = false;
476
+ }
477
+ }
478
+ __decorateClass([
479
+ property({ type: Boolean, reflect: true })
480
+ ], MenuItem.prototype, "active", 2);
481
+ __decorateClass([
482
+ property({ type: Boolean, reflect: true })
483
+ ], MenuItem.prototype, "focused", 2);
484
+ __decorateClass([
485
+ property({ type: Boolean, reflect: true })
486
+ ], MenuItem.prototype, "selected", 2);
487
+ __decorateClass([
488
+ property({ type: String })
489
+ ], MenuItem.prototype, "value", 1);
490
+ __decorateClass([
491
+ property({ type: Boolean, reflect: true, attribute: "has-submenu" })
492
+ ], MenuItem.prototype, "hasSubmenu", 2);
493
+ __decorateClass([
494
+ query("slot:not([name])")
495
+ ], MenuItem.prototype, "contentSlot", 2);
496
+ __decorateClass([
497
+ query('slot[name="icon"]')
498
+ ], MenuItem.prototype, "iconSlot", 2);
499
+ __decorateClass([
500
+ property({
501
+ type: Boolean,
502
+ reflect: true,
503
+ attribute: "no-wrap",
504
+ hasChanged() {
505
+ return false;
506
+ }
507
+ })
508
+ ], MenuItem.prototype, "noWrap", 2);
509
+ __decorateClass([
510
+ query(".anchor")
511
+ ], MenuItem.prototype, "anchorElement", 2);
512
+ __decorateClass([
513
+ query("sp-overlay")
514
+ ], MenuItem.prototype, "overlayElement", 2);
515
+ __decorateClass([
516
+ property({ type: Boolean, reflect: true })
517
+ ], MenuItem.prototype, "open", 2);
518
+ //# sourceMappingURL=MenuItem.dev.js.map