@spectrum-web-components/menu 0.16.0 → 0.16.1

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 (109) hide show
  1. package/package.json +5 -5
  2. package/sp-menu-divider.dev.js +1 -0
  3. package/sp-menu-divider.dev.js.map +1 -1
  4. package/sp-menu-divider.js +1 -1
  5. package/sp-menu-divider.js.map +2 -2
  6. package/sp-menu-group.dev.js +1 -0
  7. package/sp-menu-group.dev.js.map +1 -1
  8. package/sp-menu-group.js +1 -1
  9. package/sp-menu-group.js.map +2 -2
  10. package/sp-menu-item.dev.js +1 -0
  11. package/sp-menu-item.dev.js.map +1 -1
  12. package/sp-menu-item.js +1 -1
  13. package/sp-menu-item.js.map +2 -2
  14. package/sp-menu.dev.js +1 -0
  15. package/sp-menu.dev.js.map +1 -1
  16. package/sp-menu.js +1 -1
  17. package/sp-menu.js.map +2 -2
  18. package/src/Menu.dev.js +51 -24
  19. package/src/Menu.dev.js.map +1 -1
  20. package/src/Menu.js +2 -2
  21. package/src/Menu.js.map +2 -2
  22. package/src/MenuDivider.dev.js +1 -0
  23. package/src/MenuDivider.dev.js.map +1 -1
  24. package/src/MenuDivider.js +1 -1
  25. package/src/MenuDivider.js.map +2 -2
  26. package/src/MenuGroup.dev.js +4 -3
  27. package/src/MenuGroup.dev.js.map +1 -1
  28. package/src/MenuGroup.js +2 -2
  29. package/src/MenuGroup.js.map +2 -2
  30. package/src/MenuItem.dev.js +34 -9
  31. package/src/MenuItem.dev.js.map +2 -2
  32. package/src/MenuItem.js +2 -2
  33. package/src/MenuItem.js.map +2 -2
  34. package/src/index.dev.js +1 -0
  35. package/src/index.dev.js.map +1 -1
  36. package/src/index.js +1 -1
  37. package/src/index.js.map +1 -1
  38. package/src/menu-divider.css.dev.js +1 -0
  39. package/src/menu-divider.css.dev.js.map +1 -1
  40. package/src/menu-divider.css.js +1 -1
  41. package/src/menu-divider.css.js.map +2 -2
  42. package/src/menu-group.css.dev.js +1 -0
  43. package/src/menu-group.css.dev.js.map +1 -1
  44. package/src/menu-group.css.js +1 -1
  45. package/src/menu-group.css.js.map +2 -2
  46. package/src/menu-item.css.dev.js +1 -0
  47. package/src/menu-item.css.dev.js.map +1 -1
  48. package/src/menu-item.css.js +1 -1
  49. package/src/menu-item.css.js.map +2 -2
  50. package/src/menu.css.dev.js +1 -0
  51. package/src/menu.css.dev.js.map +1 -1
  52. package/src/menu.css.js +1 -1
  53. package/src/menu.css.js.map +2 -2
  54. package/src/spectrum-checkmark.css.dev.js +1 -0
  55. package/src/spectrum-checkmark.css.dev.js.map +1 -1
  56. package/src/spectrum-checkmark.css.js +1 -1
  57. package/src/spectrum-checkmark.css.js.map +2 -2
  58. package/src/spectrum-chevron.css.dev.js +1 -0
  59. package/src/spectrum-chevron.css.dev.js.map +1 -1
  60. package/src/spectrum-chevron.css.js +1 -1
  61. package/src/spectrum-chevron.css.js.map +2 -2
  62. package/src/spectrum-itemLabel.css.dev.js +1 -0
  63. package/src/spectrum-itemLabel.css.dev.js.map +1 -1
  64. package/src/spectrum-itemLabel.css.js +1 -1
  65. package/src/spectrum-itemLabel.css.js.map +2 -2
  66. package/src/spectrum-menu-divider.css.dev.js +1 -0
  67. package/src/spectrum-menu-divider.css.dev.js.map +1 -1
  68. package/src/spectrum-menu-divider.css.js +1 -1
  69. package/src/spectrum-menu-divider.css.js.map +2 -2
  70. package/src/spectrum-menu-item.css.dev.js +1 -0
  71. package/src/spectrum-menu-item.css.dev.js.map +1 -1
  72. package/src/spectrum-menu-item.css.js +1 -1
  73. package/src/spectrum-menu-item.css.js.map +2 -2
  74. package/src/spectrum-menu-sectionHeading.css.dev.js +1 -0
  75. package/src/spectrum-menu-sectionHeading.css.dev.js.map +1 -1
  76. package/src/spectrum-menu-sectionHeading.css.js +1 -1
  77. package/src/spectrum-menu-sectionHeading.css.js.map +2 -2
  78. package/src/spectrum-menu.css.dev.js +1 -0
  79. package/src/spectrum-menu.css.dev.js.map +1 -1
  80. package/src/spectrum-menu.css.js +1 -1
  81. package/src/spectrum-menu.css.js.map +2 -2
  82. package/stories/menu-group.stories.js +61 -9
  83. package/stories/menu-group.stories.js.map +2 -2
  84. package/stories/menu-item.stories.js +25 -4
  85. package/stories/menu-item.stories.js.map +1 -1
  86. package/stories/menu.stories.js +47 -8
  87. package/stories/menu.stories.js.map +1 -1
  88. package/stories/submenu.stories.js +160 -16
  89. package/stories/submenu.stories.js.map +2 -2
  90. package/test/benchmark/test-basic.js +8 -1
  91. package/test/benchmark/test-basic.js.map +1 -1
  92. package/test/menu-group.test-vrt.js +4 -1
  93. package/test/menu-group.test-vrt.js.map +1 -1
  94. package/test/menu-group.test.js +257 -6
  95. package/test/menu-group.test.js.map +1 -1
  96. package/test/menu-item.test-vrt.js +4 -1
  97. package/test/menu-item.test-vrt.js.map +1 -1
  98. package/test/menu-item.test.js +121 -8
  99. package/test/menu-item.test.js.map +1 -1
  100. package/test/menu-selects.test.js +513 -5
  101. package/test/menu-selects.test.js.map +1 -1
  102. package/test/menu.test-vrt.js +4 -1
  103. package/test/menu.test-vrt.js.map +1 -1
  104. package/test/menu.test.js +337 -17
  105. package/test/menu.test.js.map +1 -1
  106. package/test/submenu.test-vrt.js +4 -1
  107. package/test/submenu.test-vrt.js.map +1 -1
  108. package/test/submenu.test.js +516 -21
  109. package/test/submenu.test.js.map +1 -1
@@ -1,14 +1,47 @@
1
- import"@spectrum-web-components/menu/sp-menu.js";import"@spectrum-web-components/menu/sp-menu-item.js";import{elementUpdated as d,expect as m,fixture as M,html as l,nextFrame as S,oneEvent as o}from"@open-wc/testing";import"@spectrum-web-components/theme/sp-theme.js";import"@spectrum-web-components/theme/src/themes.js";import{sendMouse as p}from"../../../test/plugins/browser.js";import{spy as h}from"sinon";import{sendKeys as y}from"@web/test-runner-commands";import"@spectrum-web-components/action-menu/sp-action-menu.js";import"@spectrum-web-components/menu/sp-menu-group.js";import"@spectrum-web-components/icons-workflow/icons/sp-icon-show-menu.js";async function r(t,n="ltr"){const e=await M(l`
2
- <sp-theme dir=${n} scale="medium" color="dark">${t}</sp-theme>
3
- `);return document.documentElement.dir=n,e.children[0]}describe("Submenu",()=>{it("selects - pointer",async()=>{const t=h(),n=h(),e=await r(l`
1
+ "use strict";
2
+ import "@spectrum-web-components/menu/sp-menu.js";
3
+ import "@spectrum-web-components/menu/sp-menu-item.js";
4
+ import {
5
+ elementUpdated,
6
+ expect,
7
+ fixture,
8
+ html,
9
+ nextFrame,
10
+ oneEvent
11
+ } from "@open-wc/testing";
12
+ import "@spectrum-web-components/theme/sp-theme.js";
13
+ import "@spectrum-web-components/theme/src/themes.js";
14
+ import { sendMouse } from "../../../test/plugins/browser.js";
15
+ import { spy } from "sinon";
16
+ import { sendKeys } from "@web/test-runner-commands";
17
+ import "@spectrum-web-components/action-menu/sp-action-menu.js";
18
+ import "@spectrum-web-components/menu/sp-menu-group.js";
19
+ import "@spectrum-web-components/icons-workflow/icons/sp-icon-show-menu.js";
20
+ async function styledFixture(story, dir = "ltr") {
21
+ const test = await fixture(html`
22
+ <sp-theme dir=${dir} scale="medium" color="dark">${story}</sp-theme>
23
+ `);
24
+ document.documentElement.dir = dir;
25
+ return test.children[0];
26
+ }
27
+ describe("Submenu", () => {
28
+ it("selects - pointer", async () => {
29
+ const rootChanged = spy();
30
+ const submenuChanged = spy();
31
+ const el = await styledFixture(
32
+ html`
4
33
  <sp-menu
5
- @change=${b=>{t(b.target.value)}}
34
+ @change=${(event) => {
35
+ rootChanged(event.target.value);
36
+ }}
6
37
  >
7
38
  <sp-menu-item class="root">
8
39
  Has submenu
9
40
  <sp-menu
10
41
  slot="submenu"
11
- @change=${b=>{n(b.target.value)}}
42
+ @change=${(event) => {
43
+ submenuChanged(event.target.value);
44
+ }}
12
45
  >
13
46
  <sp-menu-item class="submenu-item-1">
14
47
  One
@@ -22,15 +55,63 @@ import"@spectrum-web-components/menu/sp-menu.js";import"@spectrum-web-components
22
55
  </sp-menu>
23
56
  </sp-menu-item>
24
57
  </sp-menu>
25
- `);await d(e);const u=e.querySelector(".root"),s=u.getBoundingClientRect();m(u.open).to.be.false;const i=o(u,"sp-opened");p({steps:[{type:"move",position:[s.left+s.width/2,s.top+s.height/2]}]}),await i,m(u.open).to.be.true;const a=document.querySelector(".submenu-item-2").getBoundingClientRect(),w=o(u,"sp-closed");p({steps:[{type:"click",position:[a.left+a.width/2,a.top+a.height/2]}]}),await w,await S(),m(t.calledWith("Has submenu"),"root changed").to.be.true,m(n.calledWith("Two"),"submenu changed").to.be.true}),it("closes deep tree on selection",async()=>{const t=h(),n=h(),e=h(),u=await r(l`
58
+ `
59
+ );
60
+ await elementUpdated(el);
61
+ const rootItem = el.querySelector(".root");
62
+ const rootItemBoundingRect = rootItem.getBoundingClientRect();
63
+ expect(rootItem.open).to.be.false;
64
+ const opened = oneEvent(rootItem, "sp-opened");
65
+ sendMouse({
66
+ steps: [
67
+ {
68
+ type: "move",
69
+ position: [
70
+ rootItemBoundingRect.left + rootItemBoundingRect.width / 2,
71
+ rootItemBoundingRect.top + rootItemBoundingRect.height / 2
72
+ ]
73
+ }
74
+ ]
75
+ });
76
+ await opened;
77
+ expect(rootItem.open).to.be.true;
78
+ const item2 = document.querySelector(".submenu-item-2");
79
+ const item2BoundingRect = item2.getBoundingClientRect();
80
+ const closed = oneEvent(rootItem, "sp-closed");
81
+ sendMouse({
82
+ steps: [
83
+ {
84
+ type: "click",
85
+ position: [
86
+ item2BoundingRect.left + item2BoundingRect.width / 2,
87
+ item2BoundingRect.top + item2BoundingRect.height / 2
88
+ ]
89
+ }
90
+ ]
91
+ });
92
+ await closed;
93
+ await nextFrame();
94
+ expect(rootChanged.calledWith("Has submenu"), "root changed").to.be.true;
95
+ expect(submenuChanged.calledWith("Two"), "submenu changed").to.be.true;
96
+ });
97
+ it("closes deep tree on selection", async () => {
98
+ const rootChanged = spy();
99
+ const submenuChanged = spy();
100
+ const subSubmenuChanged = spy();
101
+ const el = await styledFixture(
102
+ html`
26
103
  <sp-menu
27
- @change=${g=>{t(g.target.value)}}
104
+ @change=${(event) => {
105
+ rootChanged(event.target.value);
106
+ }}
28
107
  >
29
108
  <sp-menu-item class="root">
30
109
  Has submenu
31
110
  <sp-menu
32
111
  slot="submenu"
33
- @change=${g=>{n(g.target.value)}}
112
+ @change=${(event) => {
113
+ submenuChanged(event.target.value);
114
+ }}
34
115
  >
35
116
  <sp-menu-item class="submenu-item-1">
36
117
  One
@@ -39,7 +120,9 @@ import"@spectrum-web-components/menu/sp-menu.js";import"@spectrum-web-components
39
120
  Two
40
121
  <sp-menu
41
122
  slot="submenu"
42
- @change=${g=>{e(g.target.value)}}
123
+ @change=${(event) => {
124
+ subSubmenuChanged(event.target.value);
125
+ }}
43
126
  >
44
127
  <sp-menu-item class="sub-submenu-item-1">
45
128
  A
@@ -58,15 +141,92 @@ import"@spectrum-web-components/menu/sp-menu.js";import"@spectrum-web-components
58
141
  </sp-menu>
59
142
  </sp-menu-item>
60
143
  </sp-menu>
61
- `);await d(u);const s=u.querySelector(".root"),i=s.getBoundingClientRect();m(s.open).to.be.false;const c=o(s,"sp-opened");p({steps:[{type:"move",position:[i.left+i.width/2,i.top+i.height/2]}]}),await c,m(s.open).to.be.true;const a=document.querySelector(".submenu-item-2"),w=a.getBoundingClientRect();let b=o(a,"sp-opened");p({steps:[{type:"click",position:[w.left+w.width/2,w.top+w.height/2]}]}),await b,await S(),m(a.open).to.be.true;const v=document.querySelector(".sub-submenu-item-3").getBoundingClientRect();b=o(s,"sp-closed"),p({steps:[{type:"click",position:[v.left+v.width/2,v.top+v.height/2]}]}),await b,await S(),m(t.calledWith("Has submenu"),"root changed").to.be.true,m(n.calledWith("Two"),"submenu changed").to.be.true,m(e.calledWith("C"),"sub submenu changed").to.be.true}),[{dir:"ltr",openKey:"ArrowRight",closeKey:"ArrowLeft"},{dir:"rtl",openKey:"ArrowLeft",closeKey:"ArrowRight"}].map(t=>{it(`selects - keyboard: ${t.dir}`,async()=>{const n=h(),e=h(),u=await r(l`
144
+ `
145
+ );
146
+ await elementUpdated(el);
147
+ const rootItem = el.querySelector(".root");
148
+ const rootItemBoundingRect = rootItem.getBoundingClientRect();
149
+ expect(rootItem.open).to.be.false;
150
+ const opened = oneEvent(rootItem, "sp-opened");
151
+ sendMouse({
152
+ steps: [
153
+ {
154
+ type: "move",
155
+ position: [
156
+ rootItemBoundingRect.left + rootItemBoundingRect.width / 2,
157
+ rootItemBoundingRect.top + rootItemBoundingRect.height / 2
158
+ ]
159
+ }
160
+ ]
161
+ });
162
+ await opened;
163
+ expect(rootItem.open).to.be.true;
164
+ const item2 = document.querySelector(".submenu-item-2");
165
+ const item2BoundingRect = item2.getBoundingClientRect();
166
+ let closed = oneEvent(item2, "sp-opened");
167
+ sendMouse({
168
+ steps: [
169
+ {
170
+ type: "click",
171
+ position: [
172
+ item2BoundingRect.left + item2BoundingRect.width / 2,
173
+ item2BoundingRect.top + item2BoundingRect.height / 2
174
+ ]
175
+ }
176
+ ]
177
+ });
178
+ await closed;
179
+ await nextFrame();
180
+ expect(item2.open).to.be.true;
181
+ const itemC = document.querySelector(".sub-submenu-item-3");
182
+ const itemCBoundingRect = itemC.getBoundingClientRect();
183
+ closed = oneEvent(rootItem, "sp-closed");
184
+ sendMouse({
185
+ steps: [
186
+ {
187
+ type: "click",
188
+ position: [
189
+ itemCBoundingRect.left + itemCBoundingRect.width / 2,
190
+ itemCBoundingRect.top + itemCBoundingRect.height / 2
191
+ ]
192
+ }
193
+ ]
194
+ });
195
+ await closed;
196
+ await nextFrame();
197
+ expect(rootChanged.calledWith("Has submenu"), "root changed").to.be.true;
198
+ expect(submenuChanged.calledWith("Two"), "submenu changed").to.be.true;
199
+ expect(subSubmenuChanged.calledWith("C"), "sub submenu changed").to.be.true;
200
+ });
201
+ [
202
+ {
203
+ dir: "ltr",
204
+ openKey: "ArrowRight",
205
+ closeKey: "ArrowLeft"
206
+ },
207
+ {
208
+ dir: "rtl",
209
+ openKey: "ArrowLeft",
210
+ closeKey: "ArrowRight"
211
+ }
212
+ ].map((testData) => {
213
+ it(`selects - keyboard: ${testData.dir}`, async () => {
214
+ const rootChanged = spy();
215
+ const submenuChanged = spy();
216
+ const el = await styledFixture(
217
+ html`
62
218
  <sp-menu
63
- @change=${a=>{n(a.target.value)}}
219
+ @change=${(event) => {
220
+ rootChanged(event.target.value);
221
+ }}
64
222
  >
65
223
  <sp-menu-item class="root">
66
224
  Has submenu
67
225
  <sp-menu
68
226
  slot="submenu"
69
- @change=${a=>{e(a.target.value)}}
227
+ @change=${(event) => {
228
+ submenuChanged(event.target.value);
229
+ }}
70
230
  >
71
231
  <sp-menu-item class="submenu-item-1">
72
232
  One
@@ -80,7 +240,47 @@ import"@spectrum-web-components/menu/sp-menu.js";import"@spectrum-web-components
80
240
  </sp-menu>
81
241
  </sp-menu-item>
82
242
  </sp-menu>
83
- `,t.dir);await d(u);const s=u.querySelector(".root");m(s.open).to.be.false,u.focus(),await d(u);let i=o(s,"sp-opened");y({press:t.openKey}),await i,m(s.open).to.be.true;let c=o(s,"sp-closed");y({press:t.closeKey}),await c,m(s.open).to.be.false,i=o(s,"sp-opened"),y({press:t.openKey}),await i,m(s.open).to.be.true,await y({press:"ArrowDown"}),c=o(s,"sp-closed"),y({press:"Enter"}),await c,m(n.calledWith("Has submenu"),"root changed").to.be.true,m(e.calledWith("Two"),"submenu changed").to.be.true})}),it("closes on `pointerleave`",async()=>{const t=await r(l`
243
+ `,
244
+ testData.dir
245
+ );
246
+ await elementUpdated(el);
247
+ const rootItem = el.querySelector(".root");
248
+ expect(rootItem.open).to.be.false;
249
+ el.focus();
250
+ await elementUpdated(el);
251
+ let opened = oneEvent(rootItem, "sp-opened");
252
+ sendKeys({
253
+ press: testData.openKey
254
+ });
255
+ await opened;
256
+ expect(rootItem.open).to.be.true;
257
+ let closed = oneEvent(rootItem, "sp-closed");
258
+ sendKeys({
259
+ press: testData.closeKey
260
+ });
261
+ await closed;
262
+ expect(rootItem.open).to.be.false;
263
+ opened = oneEvent(rootItem, "sp-opened");
264
+ sendKeys({
265
+ press: testData.openKey
266
+ });
267
+ await opened;
268
+ expect(rootItem.open).to.be.true;
269
+ await sendKeys({
270
+ press: "ArrowDown"
271
+ });
272
+ closed = oneEvent(rootItem, "sp-closed");
273
+ sendKeys({
274
+ press: "Enter"
275
+ });
276
+ await closed;
277
+ expect(rootChanged.calledWith("Has submenu"), "root changed").to.be.true;
278
+ expect(submenuChanged.calledWith("Two"), "submenu changed").to.be.true;
279
+ });
280
+ });
281
+ it("closes on `pointerleave`", async () => {
282
+ const el = await styledFixture(
283
+ html`
84
284
  <sp-menu>
85
285
  <sp-menu-item class="root">
86
286
  Has submenu
@@ -97,7 +297,44 @@ import"@spectrum-web-components/menu/sp-menu.js";import"@spectrum-web-components
97
297
  </sp-menu>
98
298
  </sp-menu-item>
99
299
  </sp-menu>
100
- `);await d(t);const n=t.querySelector(".root"),e=n.getBoundingClientRect();m(n.open).to.be.false;const u=o(n,"sp-opened");p({steps:[{type:"move",position:[e.left+e.width/2,e.top+e.height/2]}]}),await u,m(n.open).to.be.true;const s=o(n,"sp-closed");p({steps:[{type:"move",position:[e.left+e.width/2,e.top+e.height*2]}]}),await s,m(n.open).to.be.false}),it("stays open when mousing off menu item and back again",async()=>{const t=await r(l`
300
+ `
301
+ );
302
+ await elementUpdated(el);
303
+ const rootItem = el.querySelector(".root");
304
+ const rootItemBoundingRect = rootItem.getBoundingClientRect();
305
+ expect(rootItem.open).to.be.false;
306
+ const opened = oneEvent(rootItem, "sp-opened");
307
+ sendMouse({
308
+ steps: [
309
+ {
310
+ type: "move",
311
+ position: [
312
+ rootItemBoundingRect.left + rootItemBoundingRect.width / 2,
313
+ rootItemBoundingRect.top + rootItemBoundingRect.height / 2
314
+ ]
315
+ }
316
+ ]
317
+ });
318
+ await opened;
319
+ expect(rootItem.open).to.be.true;
320
+ const closed = oneEvent(rootItem, "sp-closed");
321
+ sendMouse({
322
+ steps: [
323
+ {
324
+ type: "move",
325
+ position: [
326
+ rootItemBoundingRect.left + rootItemBoundingRect.width / 2,
327
+ rootItemBoundingRect.top + rootItemBoundingRect.height * 2
328
+ ]
329
+ }
330
+ ]
331
+ });
332
+ await closed;
333
+ expect(rootItem.open).to.be.false;
334
+ });
335
+ it("stays open when mousing off menu item and back again", async () => {
336
+ const el = await styledFixture(
337
+ html`
101
338
  <sp-menu>
102
339
  <sp-menu-item class="root">
103
340
  Has submenu
@@ -114,7 +351,65 @@ import"@spectrum-web-components/menu/sp-menu.js";import"@spectrum-web-components
114
351
  </sp-menu>
115
352
  </sp-menu-item>
116
353
  </sp-menu>
117
- `);await d(t);const n=t.querySelector(".root"),e=n.getBoundingClientRect();m(n.open).to.be.false;const u=o(n,"sp-opened");await p({steps:[{type:"move",position:[e.left+e.width/2,e.top+e.height/2]}]}),await p({steps:[{type:"move",position:[e.left+e.width/2,e.top+e.height*2]}]}),await p({steps:[{type:"move",position:[e.left+e.width/2,e.top+e.height/2]}]}),await u,m(n.open).to.be.true;const s=o(n,"sp-closed");p({steps:[{type:"move",position:[e.left+e.width/2,e.top+e.height*2]}]}),await s}),it("stays open when mousing between menu item and submenu",async()=>{const t=await r(l`
354
+ `
355
+ );
356
+ await elementUpdated(el);
357
+ const rootItem = el.querySelector(".root");
358
+ const rootItemBoundingRect = rootItem.getBoundingClientRect();
359
+ expect(rootItem.open).to.be.false;
360
+ const opened = oneEvent(rootItem, "sp-opened");
361
+ await sendMouse({
362
+ steps: [
363
+ {
364
+ type: "move",
365
+ position: [
366
+ rootItemBoundingRect.left + rootItemBoundingRect.width / 2,
367
+ rootItemBoundingRect.top + rootItemBoundingRect.height / 2
368
+ ]
369
+ }
370
+ ]
371
+ });
372
+ await sendMouse({
373
+ steps: [
374
+ {
375
+ type: "move",
376
+ position: [
377
+ rootItemBoundingRect.left + rootItemBoundingRect.width / 2,
378
+ rootItemBoundingRect.top + rootItemBoundingRect.height * 2
379
+ ]
380
+ }
381
+ ]
382
+ });
383
+ await sendMouse({
384
+ steps: [
385
+ {
386
+ type: "move",
387
+ position: [
388
+ rootItemBoundingRect.left + rootItemBoundingRect.width / 2,
389
+ rootItemBoundingRect.top + rootItemBoundingRect.height / 2
390
+ ]
391
+ }
392
+ ]
393
+ });
394
+ await opened;
395
+ expect(rootItem.open).to.be.true;
396
+ const closed = oneEvent(rootItem, "sp-closed");
397
+ sendMouse({
398
+ steps: [
399
+ {
400
+ type: "move",
401
+ position: [
402
+ rootItemBoundingRect.left + rootItemBoundingRect.width / 2,
403
+ rootItemBoundingRect.top + rootItemBoundingRect.height * 2
404
+ ]
405
+ }
406
+ ]
407
+ });
408
+ await closed;
409
+ });
410
+ it("stays open when mousing between menu item and submenu", async () => {
411
+ const el = await styledFixture(
412
+ html`
118
413
  <sp-menu>
119
414
  <sp-menu-item class="root">
120
415
  Has submenu
@@ -131,7 +426,52 @@ import"@spectrum-web-components/menu/sp-menu.js";import"@spectrum-web-components
131
426
  </sp-menu>
132
427
  </sp-menu-item>
133
428
  </sp-menu>
134
- `);await d(t);const n=t.querySelector(".root"),e=n.getBoundingClientRect();m(n.open).to.be.false;const u=o(n,"sp-opened");await p({steps:[{type:"move",position:[e.left+e.width/2,e.top+e.height/2]}]}),await p({steps:[{type:"move",position:[e.left+e.width/2,e.top+e.height*2]}]}),await p({steps:[{type:"move",position:[e.left+e.width*1.5,e.top+e.height/2]}]}),await u,m(n.open).to.be.true}),it("not opens if disabled",async()=>{const t=await r(l`
429
+ `
430
+ );
431
+ await elementUpdated(el);
432
+ const rootItem = el.querySelector(".root");
433
+ const rootItemBoundingRect = rootItem.getBoundingClientRect();
434
+ expect(rootItem.open).to.be.false;
435
+ const opened = oneEvent(rootItem, "sp-opened");
436
+ await sendMouse({
437
+ steps: [
438
+ {
439
+ type: "move",
440
+ position: [
441
+ rootItemBoundingRect.left + rootItemBoundingRect.width / 2,
442
+ rootItemBoundingRect.top + rootItemBoundingRect.height / 2
443
+ ]
444
+ }
445
+ ]
446
+ });
447
+ await sendMouse({
448
+ steps: [
449
+ {
450
+ type: "move",
451
+ position: [
452
+ rootItemBoundingRect.left + rootItemBoundingRect.width / 2,
453
+ rootItemBoundingRect.top + rootItemBoundingRect.height * 2
454
+ ]
455
+ }
456
+ ]
457
+ });
458
+ await sendMouse({
459
+ steps: [
460
+ {
461
+ type: "move",
462
+ position: [
463
+ rootItemBoundingRect.left + rootItemBoundingRect.width * 1.5,
464
+ rootItemBoundingRect.top + rootItemBoundingRect.height / 2
465
+ ]
466
+ }
467
+ ]
468
+ });
469
+ await opened;
470
+ expect(rootItem.open).to.be.true;
471
+ });
472
+ it("not opens if disabled", async () => {
473
+ const el = await styledFixture(
474
+ html`
135
475
  <sp-menu>
136
476
  <sp-menu-item disabled class="root">
137
477
  Has submenu
@@ -148,7 +488,28 @@ import"@spectrum-web-components/menu/sp-menu.js";import"@spectrum-web-components
148
488
  </sp-menu>
149
489
  </sp-menu-item>
150
490
  </sp-menu>
151
- `);await d(t);const n=t.querySelector(".root"),e=n.getBoundingClientRect();m(n.open).to.be.false,p({steps:[{type:"move",position:[e.left+e.width/2,e.top+e.height/2]}]}),await new Promise(u=>setTimeout(u,200)),m(n.open).to.be.false}),it("closes all decendent submenus when closing a ancestor menu",async()=>{const t=await r(l`
491
+ `
492
+ );
493
+ await elementUpdated(el);
494
+ const rootItem = el.querySelector(".root");
495
+ const rootItemBoundingRect = rootItem.getBoundingClientRect();
496
+ expect(rootItem.open).to.be.false;
497
+ sendMouse({
498
+ steps: [
499
+ {
500
+ type: "move",
501
+ position: [
502
+ rootItemBoundingRect.left + rootItemBoundingRect.width / 2,
503
+ rootItemBoundingRect.top + rootItemBoundingRect.height / 2
504
+ ]
505
+ }
506
+ ]
507
+ });
508
+ await new Promise((r) => setTimeout(r, 200));
509
+ expect(rootItem.open).to.be.false;
510
+ });
511
+ it("closes all decendent submenus when closing a ancestor menu", async () => {
512
+ const el = await styledFixture(html`
152
513
  <sp-action-menu>
153
514
  <sp-icon-show-menu slot="icon"></sp-icon-show-menu>
154
515
  <sp-menu-group role="none">
@@ -186,7 +547,45 @@ import"@spectrum-web-components/menu/sp-menu.js";import"@spectrum-web-components
186
547
  </sp-menu-item>
187
548
  </sp-menu-group>
188
549
  </sp-action-menu>
189
- `),n=t.querySelector("#submenu-item-1"),e=t.querySelector("#submenu-item-3"),u=t.querySelector("#submenu-item-2");m(t.open).to.be.false;let s=o(t,"sp-opened");t.click(),await s,m(t.open).to.be.true;let i=document.querySelectorAll("active-overlay");m(i.length).to.equal(1),s=o(n,"sp-opened"),n.dispatchEvent(new PointerEvent("pointerenter",{bubbles:!0})),await s,i=document.querySelectorAll("active-overlay"),m(i.length).to.equal(2),s=o(u,"sp-opened"),u.dispatchEvent(new PointerEvent("pointerenter",{bubbles:!0})),await s,i=document.querySelectorAll("active-overlay"),m(i.length).to.equal(3);const c=Promise.all([o(u,"sp-closed"),o(n,"sp-closed"),o(e,"sp-opened")]);e.dispatchEvent(new PointerEvent("pointerenter",{bubbles:!0})),await c,i=document.querySelectorAll("active-overlay"),m(i.length).to.equal(2)}),it("closes back to the first overlay without a `root` when clicking away",async()=>{const t=await r(l`
550
+ `);
551
+ const rootMenu1 = el.querySelector("#submenu-item-1");
552
+ const rootMenu2 = el.querySelector("#submenu-item-3");
553
+ const childMenu2 = el.querySelector("#submenu-item-2");
554
+ expect(el.open).to.be.false;
555
+ let opened = oneEvent(el, "sp-opened");
556
+ el.click();
557
+ await opened;
558
+ expect(el.open).to.be.true;
559
+ let activeOverlays = document.querySelectorAll("active-overlay");
560
+ expect(activeOverlays.length).to.equal(1);
561
+ opened = oneEvent(rootMenu1, "sp-opened");
562
+ rootMenu1.dispatchEvent(
563
+ new PointerEvent("pointerenter", { bubbles: true })
564
+ );
565
+ await opened;
566
+ activeOverlays = document.querySelectorAll("active-overlay");
567
+ expect(activeOverlays.length).to.equal(2);
568
+ opened = oneEvent(childMenu2, "sp-opened");
569
+ childMenu2.dispatchEvent(
570
+ new PointerEvent("pointerenter", { bubbles: true })
571
+ );
572
+ await opened;
573
+ activeOverlays = document.querySelectorAll("active-overlay");
574
+ expect(activeOverlays.length).to.equal(3);
575
+ const overlaysManaged = Promise.all([
576
+ oneEvent(childMenu2, "sp-closed"),
577
+ oneEvent(rootMenu1, "sp-closed"),
578
+ oneEvent(rootMenu2, "sp-opened")
579
+ ]);
580
+ rootMenu2.dispatchEvent(
581
+ new PointerEvent("pointerenter", { bubbles: true })
582
+ );
583
+ await overlaysManaged;
584
+ activeOverlays = document.querySelectorAll("active-overlay");
585
+ expect(activeOverlays.length).to.equal(2);
586
+ });
587
+ it("closes back to the first overlay without a `root` when clicking away", async () => {
588
+ const el = await styledFixture(html`
190
589
  <sp-action-menu>
191
590
  <sp-icon-show-menu slot="icon"></sp-icon-show-menu>
192
591
  <sp-menu-group role="none">
@@ -224,7 +623,42 @@ import"@spectrum-web-components/menu/sp-menu.js";import"@spectrum-web-components
224
623
  </sp-menu-item>
225
624
  </sp-menu-group>
226
625
  </sp-action-menu>
227
- `),n=t.querySelector("#submenu-item-1"),e=t.querySelector("#submenu-item-2");m(t.open).to.be.false;let u=o(t,"sp-opened");t.click(),await u,m(t.open).to.be.true;let s=document.querySelectorAll("active-overlay");m(s.length).to.equal(1),u=o(n,"sp-opened"),n.dispatchEvent(new PointerEvent("pointerenter",{bubbles:!0})),await u,s=document.querySelectorAll("active-overlay"),m(s.length).to.equal(2),u=o(e,"sp-opened"),e.dispatchEvent(new PointerEvent("pointerenter",{bubbles:!0})),await u,s=document.querySelectorAll("active-overlay"),m(s.length).to.equal(3);const i=Promise.all([o(e,"sp-closed"),o(n,"sp-closed"),o(t,"sp-closed")]);document.body.click(),await i,s=document.querySelectorAll("active-overlay"),m(s.length).to.equal(0)}),it("closes decendent menus when Menu Item in ancestor without a submenu is pointerentered",async()=>{const t=await r(l`
626
+ `);
627
+ const rootMenu1 = el.querySelector("#submenu-item-1");
628
+ const childMenu2 = el.querySelector("#submenu-item-2");
629
+ expect(el.open).to.be.false;
630
+ let opened = oneEvent(el, "sp-opened");
631
+ el.click();
632
+ await opened;
633
+ expect(el.open).to.be.true;
634
+ let activeOverlays = document.querySelectorAll("active-overlay");
635
+ expect(activeOverlays.length).to.equal(1);
636
+ opened = oneEvent(rootMenu1, "sp-opened");
637
+ rootMenu1.dispatchEvent(
638
+ new PointerEvent("pointerenter", { bubbles: true })
639
+ );
640
+ await opened;
641
+ activeOverlays = document.querySelectorAll("active-overlay");
642
+ expect(activeOverlays.length).to.equal(2);
643
+ opened = oneEvent(childMenu2, "sp-opened");
644
+ childMenu2.dispatchEvent(
645
+ new PointerEvent("pointerenter", { bubbles: true })
646
+ );
647
+ await opened;
648
+ activeOverlays = document.querySelectorAll("active-overlay");
649
+ expect(activeOverlays.length).to.equal(3);
650
+ const closed = Promise.all([
651
+ oneEvent(childMenu2, "sp-closed"),
652
+ oneEvent(rootMenu1, "sp-closed"),
653
+ oneEvent(el, "sp-closed")
654
+ ]);
655
+ document.body.click();
656
+ await closed;
657
+ activeOverlays = document.querySelectorAll("active-overlay");
658
+ expect(activeOverlays.length).to.equal(0);
659
+ });
660
+ it("closes decendent menus when Menu Item in ancestor without a submenu is pointerentered", async () => {
661
+ const el = await styledFixture(html`
228
662
  <sp-action-menu>
229
663
  <sp-icon-show-menu slot="icon"></sp-icon-show-menu>
230
664
  <sp-menu-group role="none">
@@ -252,7 +686,33 @@ import"@spectrum-web-components/menu/sp-menu.js";import"@spectrum-web-components
252
686
  </sp-menu-item>
253
687
  </sp-menu-group>
254
688
  </sp-action-menu>
255
- `),n=t.querySelector("#submenu-item-1"),e=t.querySelector("#no-submenu");m(t.open).to.be.false;let u=o(t,"sp-opened");t.click(),await u,m(t.open).to.be.true;let s=document.querySelectorAll("active-overlay");m(s.length).to.equal(1),u=o(n,"sp-opened"),n.dispatchEvent(new PointerEvent("pointerenter",{bubbles:!0})),await u,s=document.querySelectorAll("active-overlay"),m(s.length).to.equal(2);const i=o(n,"sp-closed");e.dispatchEvent(new PointerEvent("pointerenter",{bubbles:!0})),await i,s=document.querySelectorAll("active-overlay"),m(s.length).to.equal(1)}),it("closes decendent menus when Menu Item in ancestor is clicked",async()=>{const t=await r(l`
689
+ `);
690
+ const rootMenu = el.querySelector("#submenu-item-1");
691
+ const noSubmenu = el.querySelector("#no-submenu");
692
+ expect(el.open).to.be.false;
693
+ let opened = oneEvent(el, "sp-opened");
694
+ el.click();
695
+ await opened;
696
+ expect(el.open).to.be.true;
697
+ let activeOverlays = document.querySelectorAll("active-overlay");
698
+ expect(activeOverlays.length).to.equal(1);
699
+ opened = oneEvent(rootMenu, "sp-opened");
700
+ rootMenu.dispatchEvent(
701
+ new PointerEvent("pointerenter", { bubbles: true })
702
+ );
703
+ await opened;
704
+ activeOverlays = document.querySelectorAll("active-overlay");
705
+ expect(activeOverlays.length).to.equal(2);
706
+ const closed = oneEvent(rootMenu, "sp-closed");
707
+ noSubmenu.dispatchEvent(
708
+ new PointerEvent("pointerenter", { bubbles: true })
709
+ );
710
+ await closed;
711
+ activeOverlays = document.querySelectorAll("active-overlay");
712
+ expect(activeOverlays.length).to.equal(1);
713
+ });
714
+ it("closes decendent menus when Menu Item in ancestor is clicked", async () => {
715
+ const el = await styledFixture(html`
256
716
  <sp-action-menu>
257
717
  <sp-icon-show-menu slot="icon"></sp-icon-show-menu>
258
718
  <sp-menu-group role="none">
@@ -292,5 +752,40 @@ import"@spectrum-web-components/menu/sp-menu.js";import"@spectrum-web-components
292
752
  </sp-menu-item>
293
753
  </sp-menu-group>
294
754
  </sp-action-menu>
295
- `),n=t.querySelector("#submenu-item-1"),e=t.querySelector("#submenu-item-2"),u=t.querySelector("#ancestor-item");m(t.open).to.be.false;let s=o(t,"sp-opened");t.click(),await s,m(t.open).to.be.true;let i=document.querySelectorAll("active-overlay");m(i.length).to.equal(1),s=o(n,"sp-opened"),n.dispatchEvent(new PointerEvent("pointerenter",{bubbles:!0})),await s,i=document.querySelectorAll("active-overlay"),m(i.length).to.equal(2),s=o(e,"sp-opened"),e.dispatchEvent(new PointerEvent("pointerenter",{bubbles:!0})),await s,i=document.querySelectorAll("active-overlay"),m(i.length).to.equal(3);const c=Promise.all([o(e,"sp-closed"),o(n,"sp-closed"),o(t,"sp-closed")]);u.click(),await c,i=document.querySelectorAll("active-overlay"),m(i.length).to.equal(0)})});
755
+ `);
756
+ const rootMenu1 = el.querySelector("#submenu-item-1");
757
+ const childMenu2 = el.querySelector("#submenu-item-2");
758
+ const ancestorItem = el.querySelector("#ancestor-item");
759
+ expect(el.open).to.be.false;
760
+ let opened = oneEvent(el, "sp-opened");
761
+ el.click();
762
+ await opened;
763
+ expect(el.open).to.be.true;
764
+ let activeOverlays = document.querySelectorAll("active-overlay");
765
+ expect(activeOverlays.length).to.equal(1);
766
+ opened = oneEvent(rootMenu1, "sp-opened");
767
+ rootMenu1.dispatchEvent(
768
+ new PointerEvent("pointerenter", { bubbles: true })
769
+ );
770
+ await opened;
771
+ activeOverlays = document.querySelectorAll("active-overlay");
772
+ expect(activeOverlays.length).to.equal(2);
773
+ opened = oneEvent(childMenu2, "sp-opened");
774
+ childMenu2.dispatchEvent(
775
+ new PointerEvent("pointerenter", { bubbles: true })
776
+ );
777
+ await opened;
778
+ activeOverlays = document.querySelectorAll("active-overlay");
779
+ expect(activeOverlays.length).to.equal(3);
780
+ const closed = Promise.all([
781
+ oneEvent(childMenu2, "sp-closed"),
782
+ oneEvent(rootMenu1, "sp-closed"),
783
+ oneEvent(el, "sp-closed")
784
+ ]);
785
+ ancestorItem.click();
786
+ await closed;
787
+ activeOverlays = document.querySelectorAll("active-overlay");
788
+ expect(activeOverlays.length).to.equal(0);
789
+ });
790
+ });
296
791
  //# sourceMappingURL=submenu.test.js.map