@spectrum-web-components/menu 0.14.4 → 0.15.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 (110) hide show
  1. package/custom-elements.json +59 -59
  2. package/package.json +53 -19
  3. package/sp-menu-divider.dev.js +3 -0
  4. package/sp-menu-divider.dev.js.map +7 -0
  5. package/sp-menu-divider.js +3 -14
  6. package/sp-menu-divider.js.map +7 -1
  7. package/sp-menu-group.dev.js +3 -0
  8. package/sp-menu-group.dev.js.map +7 -0
  9. package/sp-menu-group.js +3 -14
  10. package/sp-menu-group.js.map +7 -1
  11. package/sp-menu-item.dev.js +3 -0
  12. package/sp-menu-item.dev.js.map +7 -0
  13. package/sp-menu-item.js +3 -14
  14. package/sp-menu-item.js.map +7 -1
  15. package/sp-menu.dev.js +3 -0
  16. package/sp-menu.dev.js.map +7 -0
  17. package/sp-menu.js +3 -14
  18. package/sp-menu.js.map +7 -1
  19. package/src/Menu.dev.js +495 -0
  20. package/src/Menu.dev.js.map +7 -0
  21. package/src/Menu.js +487 -574
  22. package/src/Menu.js.map +7 -1
  23. package/src/MenuDivider.dev.js +13 -0
  24. package/src/MenuDivider.dev.js.map +7 -0
  25. package/src/MenuDivider.js +11 -25
  26. package/src/MenuDivider.js.map +7 -1
  27. package/src/MenuGroup.dev.js +82 -0
  28. package/src/MenuGroup.dev.js.map +7 -0
  29. package/src/MenuGroup.js +67 -71
  30. package/src/MenuGroup.js.map +7 -1
  31. package/src/MenuItem.dev.js +424 -0
  32. package/src/MenuItem.dev.js.map +7 -0
  33. package/src/MenuItem.js +397 -432
  34. package/src/MenuItem.js.map +7 -1
  35. package/src/index.dev.js +5 -0
  36. package/src/index.dev.js.map +7 -0
  37. package/src/index.js +5 -16
  38. package/src/index.js.map +7 -1
  39. package/src/menu-divider.css.dev.js +6 -0
  40. package/src/menu-divider.css.dev.js.map +7 -0
  41. package/src/menu-divider.css.js +3 -14
  42. package/src/menu-divider.css.js.map +7 -1
  43. package/src/menu-group.css.dev.js +8 -0
  44. package/src/menu-group.css.dev.js.map +7 -0
  45. package/src/menu-group.css.js +3 -14
  46. package/src/menu-group.css.js.map +7 -1
  47. package/src/menu-item.css.dev.js +73 -0
  48. package/src/menu-item.css.dev.js.map +7 -0
  49. package/src/menu-item.css.js +3 -14
  50. package/src/menu-item.css.js.map +7 -1
  51. package/src/menu.css.dev.js +61 -0
  52. package/src/menu.css.dev.js.map +7 -0
  53. package/src/menu.css.js +3 -14
  54. package/src/menu.css.js.map +7 -1
  55. package/src/spectrum-checkmark.css.dev.js +10 -0
  56. package/src/spectrum-checkmark.css.dev.js.map +7 -0
  57. package/src/spectrum-checkmark.css.js +3 -14
  58. package/src/spectrum-checkmark.css.js.map +7 -1
  59. package/src/spectrum-chevron.css.dev.js +10 -0
  60. package/src/spectrum-chevron.css.dev.js.map +7 -0
  61. package/src/spectrum-chevron.css.js +3 -14
  62. package/src/spectrum-chevron.css.js.map +7 -1
  63. package/src/spectrum-itemLabel.css.dev.js +6 -0
  64. package/src/spectrum-itemLabel.css.dev.js.map +7 -0
  65. package/src/spectrum-itemLabel.css.js +3 -14
  66. package/src/spectrum-itemLabel.css.js.map +7 -1
  67. package/src/spectrum-menu-divider.css.dev.js +6 -0
  68. package/src/spectrum-menu-divider.css.dev.js.map +7 -0
  69. package/src/spectrum-menu-divider.css.js +3 -14
  70. package/src/spectrum-menu-divider.css.js.map +7 -1
  71. package/src/spectrum-menu-item.css.dev.js +65 -0
  72. package/src/spectrum-menu-item.css.dev.js.map +7 -0
  73. package/src/spectrum-menu-item.css.js +3 -14
  74. package/src/spectrum-menu-item.css.js.map +7 -1
  75. package/src/spectrum-menu-sectionHeading.css.dev.js +8 -0
  76. package/src/spectrum-menu-sectionHeading.css.dev.js.map +7 -0
  77. package/src/spectrum-menu-sectionHeading.css.js +3 -14
  78. package/src/spectrum-menu-sectionHeading.css.js.map +7 -1
  79. package/src/spectrum-menu.css.dev.js +61 -0
  80. package/src/spectrum-menu.css.dev.js.map +7 -0
  81. package/src/spectrum-menu.css.js +3 -14
  82. package/src/spectrum-menu.css.js.map +7 -1
  83. package/stories/menu-group.stories.js +51 -58
  84. package/stories/menu-group.stories.js.map +7 -1
  85. package/stories/menu-item.stories.js +12 -32
  86. package/stories/menu-item.stories.js.map +7 -1
  87. package/stories/menu.stories.js +22 -35
  88. package/stories/menu.stories.js.map +7 -1
  89. package/stories/submenu.stories.js +125 -136
  90. package/stories/submenu.stories.js.map +7 -1
  91. package/test/benchmark/test-basic.js +8 -19
  92. package/test/benchmark/test-basic.js.map +7 -1
  93. package/test/menu-group.test-vrt.js +4 -15
  94. package/test/menu-group.test-vrt.js.map +7 -1
  95. package/test/menu-group.test.js +178 -168
  96. package/test/menu-group.test.js.map +7 -1
  97. package/test/menu-item.test-vrt.js +4 -15
  98. package/test/menu-item.test-vrt.js.map +7 -1
  99. package/test/menu-item.test.js +93 -99
  100. package/test/menu-item.test.js.map +7 -1
  101. package/test/menu-selects.test.js +488 -494
  102. package/test/menu-selects.test.js.map +7 -1
  103. package/test/menu.test-vrt.js +4 -15
  104. package/test/menu.test-vrt.js.map +7 -1
  105. package/test/menu.test.js +248 -257
  106. package/test/menu.test.js.map +7 -1
  107. package/test/submenu.test-vrt.js +4 -15
  108. package/test/submenu.test-vrt.js.map +7 -1
  109. package/test/submenu.test.js +452 -486
  110. package/test/submenu.test.js.map +7 -1
package/src/MenuItem.js CHANGED
@@ -1,459 +1,424 @@
1
- /*
2
- Copyright 2020 Adobe. All rights reserved.
3
- This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
- you may not use this file except in compliance with the License. You may obtain a copy
5
- of the License at http://www.apache.org/licenses/LICENSE-2.0
6
-
7
- Unless required by applicable law or agreed to in writing, software distributed under
8
- the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
- OF ANY KIND, either express or implied. See the License for the specific language
10
- governing permissions and limitations under the License.
11
- */
12
- import { __decorate } from "tslib";
13
- import { html, } from '@spectrum-web-components/base';
14
- import { property, query, } from '@spectrum-web-components/base/src/decorators.js';
15
- import '@spectrum-web-components/icons-ui/icons/sp-icon-checkmark100.js';
16
- import { LikeAnchor } from '@spectrum-web-components/shared/src/like-anchor.js';
17
- import { Focusable } from '@spectrum-web-components/shared/src/focusable.js';
18
- import '@spectrum-web-components/icons-ui/icons/sp-icon-chevron100.js';
19
- import chevronStyles from '@spectrum-web-components/icon/src/spectrum-icon-chevron.css.js';
20
- import { openOverlay } from '@spectrum-web-components/overlay/src/loader.js';
21
- import { OverlayCloseEvent } from '@spectrum-web-components/overlay/src/overlay-events.js';
22
- import menuItemStyles from './menu-item.css.js';
23
- import checkmarkStyles from '@spectrum-web-components/icon/src/spectrum-icon-checkmark.css.js';
24
- import { reparentChildren } from '@spectrum-web-components/shared/src/reparent-children.js';
25
- import { MutationController } from '@lit-labs/observers/mutation_controller.js';
26
- /**
27
- * Duration during which a pointing device can leave an `<sp-menu-item>` element
28
- * and return to it or to the submenu opened from it before closing that submenu.
29
- **/
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __decorateClass = (decorators, target, key, kind) => {
4
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
5
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
6
+ if (decorator = decorators[i])
7
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
8
+ if (kind && result)
9
+ __defProp(target, key, result);
10
+ return result;
11
+ };
12
+ import {
13
+ html
14
+ } from "@spectrum-web-components/base";
15
+ import {
16
+ property,
17
+ query
18
+ } from "@spectrum-web-components/base/src/decorators.js";
19
+ import "@spectrum-web-components/icons-ui/icons/sp-icon-checkmark100.js";
20
+ import { LikeAnchor } from "@spectrum-web-components/shared/src/like-anchor.js";
21
+ import { Focusable } from "@spectrum-web-components/shared/src/focusable.js";
22
+ import "@spectrum-web-components/icons-ui/icons/sp-icon-chevron100.js";
23
+ import chevronStyles from "@spectrum-web-components/icon/src/spectrum-icon-chevron.css.js";
24
+ import { openOverlay } from "@spectrum-web-components/overlay/src/loader.js";
25
+ import { OverlayCloseEvent } from "@spectrum-web-components/overlay/src/overlay-events.js";
26
+ import menuItemStyles from "./menu-item.css.js";
27
+ import checkmarkStyles from "@spectrum-web-components/icon/src/spectrum-icon-checkmark.css.js";
28
+ import { reparentChildren } from "@spectrum-web-components/shared/src/reparent-children.js";
29
+ import { MutationController } from "@lit-labs/observers/mutation_controller.js";
30
30
  const POINTERLEAVE_TIMEOUT = 100;
31
31
  export class MenuItemRemovedEvent extends Event {
32
- constructor() {
33
- super('sp-menu-item-removed', {
34
- bubbles: true,
35
- composed: true,
36
- });
37
- this.focused = false;
38
- }
39
- get item() {
40
- return this._item;
41
- }
42
- reset(item) {
43
- this._item = item;
44
- }
32
+ constructor() {
33
+ super("sp-menu-item-removed", {
34
+ bubbles: true,
35
+ composed: true
36
+ });
37
+ this.focused = false;
38
+ }
39
+ get item() {
40
+ return this._item;
41
+ }
42
+ reset(item) {
43
+ this._item = item;
44
+ }
45
45
  }
46
46
  export class MenuItemAddedOrUpdatedEvent extends Event {
47
- constructor() {
48
- super('sp-menu-item-added-or-updated', {
49
- bubbles: true,
50
- composed: true,
51
- });
52
- }
53
- set focusRoot(root) {
54
- this.item.menuData.focusRoot = this.item.menuData.focusRoot || root;
55
- }
56
- set selectionRoot(root) {
57
- this.item.menuData.selectionRoot =
58
- this.item.menuData.selectionRoot || root;
59
- }
60
- get item() {
61
- return this._item;
62
- }
63
- set currentAncestorWithSelects(ancestor) {
64
- this._currentAncestorWithSelects = ancestor;
65
- }
66
- get currentAncestorWithSelects() {
67
- return this._currentAncestorWithSelects;
68
- }
69
- reset(item) {
70
- this._item = item;
71
- this._currentAncestorWithSelects = undefined;
72
- item.menuData = {
73
- focusRoot: undefined,
74
- selectionRoot: undefined,
75
- };
76
- }
47
+ constructor() {
48
+ super("sp-menu-item-added-or-updated", {
49
+ bubbles: true,
50
+ composed: true
51
+ });
52
+ }
53
+ set focusRoot(root) {
54
+ this.item.menuData.focusRoot = this.item.menuData.focusRoot || root;
55
+ }
56
+ set selectionRoot(root) {
57
+ this.item.menuData.selectionRoot = this.item.menuData.selectionRoot || root;
58
+ }
59
+ get item() {
60
+ return this._item;
61
+ }
62
+ set currentAncestorWithSelects(ancestor) {
63
+ this._currentAncestorWithSelects = ancestor;
64
+ }
65
+ get currentAncestorWithSelects() {
66
+ return this._currentAncestorWithSelects;
67
+ }
68
+ reset(item) {
69
+ this._item = item;
70
+ this._currentAncestorWithSelects = void 0;
71
+ item.menuData = {
72
+ focusRoot: void 0,
73
+ selectionRoot: void 0
74
+ };
75
+ }
77
76
  }
78
77
  const addOrUpdateEvent = new MenuItemAddedOrUpdatedEvent();
79
78
  const removeEvent = new MenuItemRemovedEvent();
80
- /**
81
- * @element sp-menu-item
82
- *
83
- * @slot - text content to display within the Menu Item
84
- * @slot icon - icon element to be placed at the start of the Menu Item
85
- * @slot value - content placed at the end of the Menu Item like values, keyboard shortcuts, etc.
86
- * @fires sp-menu-item-added - announces the item has been added so a parent menu can take ownerships
87
- * @fires sp-menu-item-removed - announces when removed from the DOM so the parent menu can remove ownership and update selected state
88
- */
89
- export class MenuItem extends LikeAnchor(Focusable) {
90
- constructor() {
91
- super();
92
- this.isInSubmenu = false;
93
- this.active = false;
94
- this.focused = false;
95
- this.selected = false;
96
- this._value = '';
97
- this.hasSubmenu = false;
98
- this.noWrap = false;
99
- this.open = false;
100
- /**
101
- * When there is a `change` event in the submenu for this item
102
- * then we "click" this item to cascade the selection up the
103
- * menu tree allowing all submenus between the initial selection
104
- * and the root of the tree to have their selection changes and
105
- * be closed.
106
- */
107
- this.handleSubmenuChange = () => {
108
- var _a;
109
- (_a = this.menuData.selectionRoot) === null || _a === void 0 ? void 0 : _a.selectOrToggleItem(this);
110
- };
111
- this.handleSubmenuPointerenter = () => {
112
- if (this.leaveTimeout) {
113
- clearTimeout(this.leaveTimeout);
114
- delete this.leaveTimeout;
115
- }
116
- };
117
- this.menuData = {
118
- focusRoot: undefined,
119
- selectionRoot: undefined,
120
- };
121
- this.proxyFocus = this.proxyFocus.bind(this);
122
- this.addEventListener('click', this.handleClickCapture, {
123
- capture: true,
124
- });
125
- new MutationController(this, {
126
- config: {
127
- characterData: true,
128
- childList: true,
129
- subtree: true,
130
- },
131
- callback: () => {
132
- this.breakItemChildrenCache();
133
- },
134
- });
135
- }
136
- static get styles() {
137
- return [menuItemStyles, checkmarkStyles, chevronStyles];
138
- }
139
- get value() {
140
- return this._value || this.itemText;
141
- }
142
- set value(value) {
143
- if (value === this._value) {
144
- return;
145
- }
146
- this._value = value || '';
147
- if (this._value) {
148
- this.setAttribute('value', this._value);
149
- }
150
- else {
151
- this.removeAttribute('value');
152
- }
153
- }
154
- /**
155
- * @private
156
- */
157
- get itemText() {
158
- return this.itemChildren.content.reduce((acc, node) => acc + (node.textContent || '').trim(), '');
159
- }
160
- get focusElement() {
161
- return this;
162
- }
163
- get itemChildren() {
164
- if (this._itemChildren) {
165
- return this._itemChildren;
166
- }
167
- const iconSlot = this.shadowRoot.querySelector('slot[name="icon"]');
168
- const icon = !iconSlot
169
- ? []
170
- : 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 contentSlot = this.shadowRoot.querySelector('slot:not([name])');
177
- const content = !contentSlot
178
- ? []
179
- : contentSlot.assignedNodes().map((node) => node.cloneNode(true));
180
- this._itemChildren = { icon, content };
181
- return this._itemChildren;
182
- }
183
- click() {
184
- if (this.disabled) {
185
- return;
186
- }
187
- if (this.shouldProxyClick()) {
188
- return;
189
- }
190
- super.click();
191
- }
192
- handleClickCapture(event) {
193
- if (this.disabled) {
194
- event.preventDefault();
195
- event.stopImmediatePropagation();
196
- event.stopPropagation();
197
- return false;
198
- }
199
- }
200
- proxyFocus() {
201
- this.focus();
202
- }
203
- shouldProxyClick() {
204
- let handled = false;
205
- if (this.anchorElement) {
206
- this.anchorElement.click();
207
- handled = true;
208
- }
209
- return handled;
210
- }
211
- breakItemChildrenCache() {
212
- this._itemChildren = undefined;
213
- this.triggerUpdate();
214
- }
215
- render() {
216
- return html `
79
+ const _MenuItem = class extends LikeAnchor(Focusable) {
80
+ constructor() {
81
+ super();
82
+ this.isInSubmenu = false;
83
+ this.active = false;
84
+ this.focused = false;
85
+ this.selected = false;
86
+ this._value = "";
87
+ this.hasSubmenu = false;
88
+ this.noWrap = false;
89
+ this.open = false;
90
+ this.handleSubmenuChange = () => {
91
+ var _a;
92
+ (_a = this.menuData.selectionRoot) == null ? void 0 : _a.selectOrToggleItem(this);
93
+ };
94
+ this.handleSubmenuPointerenter = () => {
95
+ if (this.leaveTimeout) {
96
+ clearTimeout(this.leaveTimeout);
97
+ delete this.leaveTimeout;
98
+ }
99
+ };
100
+ this.menuData = {
101
+ focusRoot: void 0,
102
+ selectionRoot: void 0
103
+ };
104
+ this.proxyFocus = this.proxyFocus.bind(this);
105
+ this.addEventListener("click", this.handleClickCapture, {
106
+ capture: true
107
+ });
108
+ new MutationController(this, {
109
+ config: {
110
+ characterData: true,
111
+ childList: true,
112
+ subtree: true
113
+ },
114
+ callback: () => {
115
+ this.breakItemChildrenCache();
116
+ }
117
+ });
118
+ }
119
+ static get styles() {
120
+ return [menuItemStyles, checkmarkStyles, chevronStyles];
121
+ }
122
+ get value() {
123
+ return this._value || this.itemText;
124
+ }
125
+ set value(value) {
126
+ if (value === this._value) {
127
+ return;
128
+ }
129
+ this._value = value || "";
130
+ if (this._value) {
131
+ this.setAttribute("value", this._value);
132
+ } else {
133
+ this.removeAttribute("value");
134
+ }
135
+ }
136
+ get itemText() {
137
+ return this.itemChildren.content.reduce((acc, node) => acc + (node.textContent || "").trim(), "");
138
+ }
139
+ get focusElement() {
140
+ return this;
141
+ }
142
+ get itemChildren() {
143
+ if (this._itemChildren) {
144
+ return this._itemChildren;
145
+ }
146
+ const iconSlot = this.shadowRoot.querySelector('slot[name="icon"]');
147
+ const icon = !iconSlot ? [] : iconSlot.assignedElements().map((element) => {
148
+ const newElement = element.cloneNode(true);
149
+ newElement.removeAttribute("slot");
150
+ newElement.classList.toggle("icon");
151
+ return newElement;
152
+ });
153
+ const contentSlot = this.shadowRoot.querySelector("slot:not([name])");
154
+ const content = !contentSlot ? [] : contentSlot.assignedNodes().map((node) => node.cloneNode(true));
155
+ this._itemChildren = { icon, content };
156
+ return this._itemChildren;
157
+ }
158
+ click() {
159
+ if (this.disabled) {
160
+ return;
161
+ }
162
+ if (this.shouldProxyClick()) {
163
+ return;
164
+ }
165
+ super.click();
166
+ }
167
+ handleClickCapture(event) {
168
+ if (this.disabled) {
169
+ event.preventDefault();
170
+ event.stopImmediatePropagation();
171
+ event.stopPropagation();
172
+ return false;
173
+ }
174
+ }
175
+ proxyFocus() {
176
+ this.focus();
177
+ }
178
+ shouldProxyClick() {
179
+ let handled = false;
180
+ if (this.anchorElement) {
181
+ this.anchorElement.click();
182
+ handled = true;
183
+ }
184
+ return handled;
185
+ }
186
+ breakItemChildrenCache() {
187
+ this._itemChildren = void 0;
188
+ this.triggerUpdate();
189
+ }
190
+ render() {
191
+ return html`
217
192
  <slot name="icon"></slot>
218
193
  <div id="label">
219
194
  <slot id="slot"></slot>
220
195
  </div>
221
196
  <slot name="value"></slot>
222
- ${this.selected
223
- ? html `
197
+ ${this.selected ? html`
224
198
  <sp-icon-checkmark100
225
199
  id="selected"
226
200
  class="spectrum-UIIcon-Checkmark100 icon checkmark"
227
201
  ></sp-icon-checkmark100>
228
- `
229
- : html ``}
230
- ${this.href && this.href.length > 0
231
- ? super.renderAnchor({
232
- id: 'button',
233
- ariaHidden: true,
234
- className: 'button anchor hidden',
235
- })
236
- : html ``}
202
+ ` : html``}
203
+ ${this.href && this.href.length > 0 ? super.renderAnchor({
204
+ id: "button",
205
+ ariaHidden: true,
206
+ className: "button anchor hidden"
207
+ }) : html``}
237
208
  <slot
238
209
  hidden
239
210
  name="submenu"
240
211
  @slotchange=${this.manageSubmenu}
241
212
  ></slot>
242
- ${this.hasSubmenu
243
- ? html `
213
+ ${this.hasSubmenu ? html`
244
214
  <sp-icon-chevron100
245
215
  class="spectrum-UIIcon-ChevronRight100 chevron icon"
246
216
  ></sp-icon-chevron100>
247
- `
248
- : html ``}
217
+ ` : html``}
249
218
  `;
250
- }
251
- manageSubmenu(event) {
252
- const assignedElements = event.target.assignedElements({
253
- flatten: true,
254
- });
255
- this.hasSubmenu = this.open || !!assignedElements.length;
256
- }
257
- handleRemoveActive(event) {
258
- if ((event.type === 'pointerleave' && this.hasSubmenu) ||
259
- this.hasSubmenu ||
260
- this.open) {
261
- return;
262
- }
263
- this.active = false;
264
- }
265
- handlePointerdown() {
266
- this.active = true;
267
- }
268
- firstUpdated(changes) {
269
- super.firstUpdated(changes);
270
- this.setAttribute('tabindex', '-1');
271
- this.addEventListener('pointerdown', this.handlePointerdown);
272
- if (!this.hasAttribute('id')) {
273
- this.id = `sp-menu-item-${MenuItem.instanceCount++}`;
274
- }
275
- this.addEventListener('pointerenter', this.closeOverlaysForRoot);
276
- }
277
- closeOverlaysForRoot() {
278
- if (this.open)
279
- return;
280
- const overalyCloseEvent = new OverlayCloseEvent({
281
- root: this.menuData.focusRoot,
282
- });
283
- this.dispatchEvent(overalyCloseEvent);
284
- }
285
- handleSubmenuClick() {
286
- this.openOverlay();
287
- }
288
- handlePointerenter() {
289
- if (this.leaveTimeout) {
290
- clearTimeout(this.leaveTimeout);
291
- delete this.leaveTimeout;
292
- return;
293
- }
294
- this.openOverlay();
295
- }
296
- handlePointerleave() {
297
- if (this.hasSubmenu && this.open) {
298
- this.leaveTimeout = setTimeout(() => {
299
- delete this.leaveTimeout;
300
- if (this.closeOverlay)
301
- this.closeOverlay();
302
- }, POINTERLEAVE_TIMEOUT);
303
- }
304
- }
305
- async openOverlay() {
306
- if (!this.hasSubmenu || this.open || this.disabled) {
307
- return;
308
- }
309
- this.open = true;
310
- this.active = true;
311
- const submenu = this.shadowRoot.querySelector('slot[name="submenu"]').assignedElements()[0];
312
- submenu.addEventListener('pointerenter', this.handleSubmenuPointerenter);
313
- submenu.addEventListener('change', this.handleSubmenuChange);
314
- const popover = document.createElement('sp-popover');
315
- const returnSubmenu = reparentChildren([submenu], popover, {
316
- position: 'beforeend',
317
- prepareCallback: (el) => {
318
- const slotName = el.slot;
319
- el.tabIndex = 0;
320
- el.removeAttribute('slot');
321
- el.isSubmenu = true;
322
- return (el) => {
323
- el.tabIndex = -1;
324
- el.slot = slotName;
325
- el.isSubmenu = false;
326
- };
327
- },
328
- });
329
- const closeOverlay = openOverlay(this, 'click', popover, {
330
- placement: this.isLTR ? 'right-start' : 'left-start',
331
- receivesFocus: 'auto',
332
- root: this.menuData.focusRoot,
333
- });
334
- const closeSubmenu = async () => {
335
- delete this.closeOverlay;
336
- (await closeOverlay)();
337
- };
338
- this.closeOverlay = closeSubmenu;
339
- const cleanup = (event) => {
340
- event.stopPropagation();
341
- delete this.closeOverlay;
342
- returnSubmenu();
343
- this.open = false;
344
- this.active = false;
219
+ }
220
+ manageSubmenu(event) {
221
+ const assignedElements = event.target.assignedElements({
222
+ flatten: true
223
+ });
224
+ this.hasSubmenu = this.open || !!assignedElements.length;
225
+ }
226
+ handleRemoveActive(event) {
227
+ if (event.type === "pointerleave" && this.hasSubmenu || this.hasSubmenu || this.open) {
228
+ return;
229
+ }
230
+ this.active = false;
231
+ }
232
+ handlePointerdown() {
233
+ this.active = true;
234
+ }
235
+ firstUpdated(changes) {
236
+ super.firstUpdated(changes);
237
+ this.setAttribute("tabindex", "-1");
238
+ this.addEventListener("pointerdown", this.handlePointerdown);
239
+ if (!this.hasAttribute("id")) {
240
+ this.id = `sp-menu-item-${_MenuItem.instanceCount++}`;
241
+ }
242
+ this.addEventListener("pointerenter", this.closeOverlaysForRoot);
243
+ }
244
+ closeOverlaysForRoot() {
245
+ if (this.open)
246
+ return;
247
+ const overalyCloseEvent = new OverlayCloseEvent({
248
+ root: this.menuData.focusRoot
249
+ });
250
+ this.dispatchEvent(overalyCloseEvent);
251
+ }
252
+ handleSubmenuClick() {
253
+ this.openOverlay();
254
+ }
255
+ handlePointerenter() {
256
+ if (this.leaveTimeout) {
257
+ clearTimeout(this.leaveTimeout);
258
+ delete this.leaveTimeout;
259
+ return;
260
+ }
261
+ this.openOverlay();
262
+ }
263
+ handlePointerleave() {
264
+ if (this.hasSubmenu && this.open) {
265
+ this.leaveTimeout = setTimeout(() => {
266
+ delete this.leaveTimeout;
267
+ if (this.closeOverlay)
268
+ this.closeOverlay();
269
+ }, POINTERLEAVE_TIMEOUT);
270
+ }
271
+ }
272
+ async openOverlay() {
273
+ if (!this.hasSubmenu || this.open || this.disabled) {
274
+ return;
275
+ }
276
+ this.open = true;
277
+ this.active = true;
278
+ const submenu = this.shadowRoot.querySelector('slot[name="submenu"]').assignedElements()[0];
279
+ submenu.addEventListener("pointerenter", this.handleSubmenuPointerenter);
280
+ submenu.addEventListener("change", this.handleSubmenuChange);
281
+ const popover = document.createElement("sp-popover");
282
+ const returnSubmenu = reparentChildren([submenu], popover, {
283
+ position: "beforeend",
284
+ prepareCallback: (el) => {
285
+ const slotName = el.slot;
286
+ el.tabIndex = 0;
287
+ el.removeAttribute("slot");
288
+ el.isSubmenu = true;
289
+ return (el2) => {
290
+ el2.tabIndex = -1;
291
+ el2.slot = slotName;
292
+ el2.isSubmenu = false;
345
293
  };
346
- this.addEventListener('sp-closed', cleanup, {
347
- once: true,
348
- });
349
- popover.addEventListener('change', closeSubmenu);
350
- }
351
- updateAriaSelected() {
352
- const role = this.getAttribute('role');
353
- if (role === 'option') {
354
- this.setAttribute('aria-selected', this.selected ? 'true' : 'false');
355
- }
356
- else if (role === 'menuitemcheckbox' || role === 'menuitemradio') {
357
- this.setAttribute('aria-checked', this.selected ? 'true' : 'false');
358
- }
359
- }
360
- setRole(role) {
361
- this.setAttribute('role', role);
362
- this.updateAriaSelected();
363
- }
364
- updated(changes) {
365
- super.updated(changes);
366
- if (changes.has('label')) {
367
- this.setAttribute('aria-label', this.label || '');
368
- }
369
- if (changes.has('active')) {
370
- if (this.active) {
371
- this.addEventListener('pointerup', this.handleRemoveActive);
372
- this.addEventListener('pointerleave', this.handleRemoveActive);
373
- }
374
- else {
375
- this.removeEventListener('pointerup', this.handleRemoveActive);
376
- this.removeEventListener('pointerleave', this.handleRemoveActive);
377
- }
378
- }
379
- if (this.anchorElement) {
380
- this.anchorElement.addEventListener('focus', this.proxyFocus);
381
- this.anchorElement.tabIndex = -1;
382
- }
383
- if (changes.has('selected')) {
384
- this.updateAriaSelected();
385
- }
386
- if (changes.has('hasSubmenu')) {
387
- if (this.hasSubmenu) {
388
- this.addEventListener('click', this.handleSubmenuClick);
389
- this.addEventListener('pointerenter', this.handlePointerenter);
390
- this.addEventListener('pointerleave', this.handlePointerleave);
391
- }
392
- else if (!this.closeOverlay) {
393
- this.removeEventListener('click', this.handleSubmenuClick);
394
- this.removeEventListener('pointerenter', this.handlePointerenter);
395
- this.removeEventListener('pointerleave', this.handlePointerleave);
396
- }
397
- }
398
- }
399
- connectedCallback() {
400
- super.connectedCallback();
401
- this.isInSubmenu = !!this.closest('[slot="submenu"]');
402
- if (this.isInSubmenu) {
403
- return;
404
- }
405
- addOrUpdateEvent.reset(this);
406
- this.dispatchEvent(addOrUpdateEvent);
407
- this._parentElement = this.parentElement;
408
- }
409
- disconnectedCallback() {
410
- var _a;
411
- removeEvent.reset(this);
412
- if (!this.isInSubmenu) {
413
- (_a = this._parentElement) === null || _a === void 0 ? void 0 : _a.dispatchEvent(removeEvent);
414
- }
415
- this.isInSubmenu = false;
416
- super.disconnectedCallback();
417
- }
418
- async triggerUpdate() {
419
- if (this.isInSubmenu) {
420
- return;
421
- }
422
- await new Promise((ready) => requestAnimationFrame(ready));
423
- addOrUpdateEvent.reset(this);
424
- this.dispatchEvent(addOrUpdateEvent);
425
- }
426
- }
294
+ }
295
+ });
296
+ const closeOverlay = openOverlay(this, "click", popover, {
297
+ placement: this.isLTR ? "right-start" : "left-start",
298
+ receivesFocus: "auto",
299
+ root: this.menuData.focusRoot
300
+ });
301
+ const closeSubmenu = async () => {
302
+ delete this.closeOverlay;
303
+ (await closeOverlay)();
304
+ };
305
+ this.closeOverlay = closeSubmenu;
306
+ const cleanup = (event) => {
307
+ event.stopPropagation();
308
+ delete this.closeOverlay;
309
+ returnSubmenu();
310
+ this.open = false;
311
+ this.active = false;
312
+ };
313
+ this.addEventListener("sp-closed", cleanup, {
314
+ once: true
315
+ });
316
+ popover.addEventListener("change", closeSubmenu);
317
+ }
318
+ updateAriaSelected() {
319
+ const role = this.getAttribute("role");
320
+ if (role === "option") {
321
+ this.setAttribute("aria-selected", this.selected ? "true" : "false");
322
+ } else if (role === "menuitemcheckbox" || role === "menuitemradio") {
323
+ this.setAttribute("aria-checked", this.selected ? "true" : "false");
324
+ }
325
+ }
326
+ setRole(role) {
327
+ this.setAttribute("role", role);
328
+ this.updateAriaSelected();
329
+ }
330
+ updated(changes) {
331
+ super.updated(changes);
332
+ if (changes.has("label")) {
333
+ this.setAttribute("aria-label", this.label || "");
334
+ }
335
+ if (changes.has("active")) {
336
+ if (this.active) {
337
+ this.addEventListener("pointerup", this.handleRemoveActive);
338
+ this.addEventListener("pointerleave", this.handleRemoveActive);
339
+ } else {
340
+ this.removeEventListener("pointerup", this.handleRemoveActive);
341
+ this.removeEventListener("pointerleave", this.handleRemoveActive);
342
+ }
343
+ }
344
+ if (this.anchorElement) {
345
+ this.anchorElement.addEventListener("focus", this.proxyFocus);
346
+ this.anchorElement.tabIndex = -1;
347
+ }
348
+ if (changes.has("selected")) {
349
+ this.updateAriaSelected();
350
+ }
351
+ if (changes.has("hasSubmenu")) {
352
+ if (this.hasSubmenu) {
353
+ this.addEventListener("click", this.handleSubmenuClick);
354
+ this.addEventListener("pointerenter", this.handlePointerenter);
355
+ this.addEventListener("pointerleave", this.handlePointerleave);
356
+ } else if (!this.closeOverlay) {
357
+ this.removeEventListener("click", this.handleSubmenuClick);
358
+ this.removeEventListener("pointerenter", this.handlePointerenter);
359
+ this.removeEventListener("pointerleave", this.handlePointerleave);
360
+ }
361
+ }
362
+ }
363
+ connectedCallback() {
364
+ super.connectedCallback();
365
+ this.isInSubmenu = !!this.closest('[slot="submenu"]');
366
+ if (this.isInSubmenu) {
367
+ return;
368
+ }
369
+ addOrUpdateEvent.reset(this);
370
+ this.dispatchEvent(addOrUpdateEvent);
371
+ this._parentElement = this.parentElement;
372
+ }
373
+ disconnectedCallback() {
374
+ var _a;
375
+ removeEvent.reset(this);
376
+ if (!this.isInSubmenu) {
377
+ (_a = this._parentElement) == null ? void 0 : _a.dispatchEvent(removeEvent);
378
+ }
379
+ this.isInSubmenu = false;
380
+ super.disconnectedCallback();
381
+ }
382
+ async triggerUpdate() {
383
+ if (this.isInSubmenu) {
384
+ return;
385
+ }
386
+ await new Promise((ready) => requestAnimationFrame(ready));
387
+ addOrUpdateEvent.reset(this);
388
+ this.dispatchEvent(addOrUpdateEvent);
389
+ }
390
+ };
391
+ export let MenuItem = _MenuItem;
427
392
  MenuItem.instanceCount = 0;
428
- __decorate([
429
- property({ type: Boolean, reflect: true })
430
- ], MenuItem.prototype, "active", void 0);
431
- __decorate([
432
- property({ type: Boolean, reflect: true })
433
- ], MenuItem.prototype, "focused", void 0);
434
- __decorate([
435
- property({ type: Boolean, reflect: true })
436
- ], MenuItem.prototype, "selected", void 0);
437
- __decorate([
438
- property({ type: String })
439
- ], MenuItem.prototype, "value", null);
440
- __decorate([
441
- property({ type: Boolean })
442
- ], MenuItem.prototype, "hasSubmenu", void 0);
443
- __decorate([
444
- property({
445
- type: Boolean,
446
- reflect: true,
447
- attribute: 'no-wrap',
448
- hasChanged() {
449
- return false;
450
- },
451
- })
452
- ], MenuItem.prototype, "noWrap", void 0);
453
- __decorate([
454
- query('.anchor')
455
- ], MenuItem.prototype, "anchorElement", void 0);
456
- __decorate([
457
- property({ type: Boolean })
458
- ], MenuItem.prototype, "open", void 0);
459
- //# sourceMappingURL=MenuItem.js.map
393
+ __decorateClass([
394
+ property({ type: Boolean, reflect: true })
395
+ ], MenuItem.prototype, "active", 2);
396
+ __decorateClass([
397
+ property({ type: Boolean, reflect: true })
398
+ ], MenuItem.prototype, "focused", 2);
399
+ __decorateClass([
400
+ property({ type: Boolean, reflect: true })
401
+ ], MenuItem.prototype, "selected", 2);
402
+ __decorateClass([
403
+ property({ type: String })
404
+ ], MenuItem.prototype, "value", 1);
405
+ __decorateClass([
406
+ property({ type: Boolean })
407
+ ], MenuItem.prototype, "hasSubmenu", 2);
408
+ __decorateClass([
409
+ property({
410
+ type: Boolean,
411
+ reflect: true,
412
+ attribute: "no-wrap",
413
+ hasChanged() {
414
+ return false;
415
+ }
416
+ })
417
+ ], MenuItem.prototype, "noWrap", 2);
418
+ __decorateClass([
419
+ query(".anchor")
420
+ ], MenuItem.prototype, "anchorElement", 2);
421
+ __decorateClass([
422
+ property({ type: Boolean })
423
+ ], MenuItem.prototype, "open", 2);
424
+ //# sourceMappingURL=MenuItem.js.map