@spectrum-web-components/overlay 0.36.0 → 0.37.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 (156) hide show
  1. package/README.md +266 -149
  2. package/custom-elements.json +1678 -553
  3. package/package.json +49 -22
  4. package/sp-overlay.d.ts +6 -0
  5. package/sp-overlay.dev.js +5 -0
  6. package/{active-overlay.dev.js.map → sp-overlay.dev.js.map} +3 -3
  7. package/sp-overlay.js +2 -0
  8. package/{active-overlay.js.map → sp-overlay.js.map} +4 -4
  9. package/src/AbstractOverlay.d.ts +58 -0
  10. package/src/AbstractOverlay.dev.js +211 -0
  11. package/src/AbstractOverlay.dev.js.map +7 -0
  12. package/src/AbstractOverlay.js +2 -0
  13. package/src/AbstractOverlay.js.map +7 -0
  14. package/src/Overlay.d.ts +163 -0
  15. package/src/Overlay.dev.js +792 -0
  16. package/src/Overlay.dev.js.map +7 -0
  17. package/src/Overlay.js +33 -0
  18. package/src/Overlay.js.map +7 -0
  19. package/src/OverlayDialog.d.ts +4 -0
  20. package/src/OverlayDialog.dev.js +135 -0
  21. package/src/OverlayDialog.dev.js.map +7 -0
  22. package/src/OverlayDialog.js +2 -0
  23. package/src/OverlayDialog.js.map +7 -0
  24. package/src/OverlayNoPopover.d.ts +4 -0
  25. package/src/OverlayNoPopover.dev.js +109 -0
  26. package/src/OverlayNoPopover.dev.js.map +7 -0
  27. package/src/OverlayNoPopover.js +2 -0
  28. package/src/OverlayNoPopover.js.map +7 -0
  29. package/src/OverlayPopover.d.ts +4 -0
  30. package/src/OverlayPopover.dev.js +169 -0
  31. package/src/OverlayPopover.dev.js.map +7 -0
  32. package/src/OverlayPopover.js +2 -0
  33. package/src/OverlayPopover.js.map +7 -0
  34. package/src/OverlayStack.d.ts +43 -0
  35. package/src/OverlayStack.dev.js +150 -0
  36. package/src/OverlayStack.dev.js.map +7 -0
  37. package/src/OverlayStack.js +2 -0
  38. package/src/OverlayStack.js.map +7 -0
  39. package/src/OverlayTrigger.d.ts +26 -42
  40. package/src/OverlayTrigger.dev.js +172 -296
  41. package/src/OverlayTrigger.dev.js.map +3 -3
  42. package/src/OverlayTrigger.js +49 -25
  43. package/src/OverlayTrigger.js.map +3 -3
  44. package/src/PlacementController.d.ts +38 -0
  45. package/src/PlacementController.dev.js +199 -0
  46. package/src/PlacementController.dev.js.map +7 -0
  47. package/src/PlacementController.js +2 -0
  48. package/src/PlacementController.js.map +7 -0
  49. package/src/VirtualTrigger.dev.js +2 -1
  50. package/src/VirtualTrigger.dev.js.map +2 -2
  51. package/src/VirtualTrigger.js +1 -1
  52. package/src/VirtualTrigger.js.map +2 -2
  53. package/src/fullSizePlugin.d.ts +12 -0
  54. package/src/fullSizePlugin.dev.js +39 -0
  55. package/src/fullSizePlugin.dev.js.map +7 -0
  56. package/src/fullSizePlugin.js +2 -0
  57. package/src/fullSizePlugin.js.map +7 -0
  58. package/src/index.d.ts +2 -3
  59. package/src/index.dev.js +2 -3
  60. package/src/index.dev.js.map +2 -2
  61. package/src/index.js +1 -1
  62. package/src/index.js.map +2 -2
  63. package/src/loader.d.ts +1 -2
  64. package/src/loader.dev.js +2 -19
  65. package/src/loader.dev.js.map +2 -2
  66. package/src/loader.js +1 -1
  67. package/src/loader.js.map +3 -3
  68. package/src/overlay-timer.dev.js.map +2 -2
  69. package/src/overlay-timer.js.map +2 -2
  70. package/src/overlay-trigger.css.dev.js +1 -1
  71. package/src/overlay-trigger.css.dev.js.map +1 -1
  72. package/src/overlay-trigger.css.js +3 -3
  73. package/src/overlay-trigger.css.js.map +1 -1
  74. package/src/overlay-types.d.ts +25 -31
  75. package/src/overlay-types.dev.js +1 -0
  76. package/src/overlay-types.dev.js.map +3 -3
  77. package/src/overlay-types.js +1 -1
  78. package/src/overlay-types.js.map +3 -3
  79. package/src/overlay.css.dev.js +9 -0
  80. package/src/overlay.css.dev.js.map +7 -0
  81. package/src/overlay.css.js +6 -0
  82. package/src/overlay.css.js.map +7 -0
  83. package/src/topLayerOverTransforms.d.ts +2 -0
  84. package/src/topLayerOverTransforms.dev.js +91 -0
  85. package/src/topLayerOverTransforms.dev.js.map +7 -0
  86. package/src/topLayerOverTransforms.js +2 -0
  87. package/src/topLayerOverTransforms.js.map +7 -0
  88. package/stories/overlay-element.stories.js +476 -0
  89. package/stories/overlay-element.stories.js.map +7 -0
  90. package/stories/overlay-story-components.js +9 -8
  91. package/stories/overlay-story-components.js.map +2 -2
  92. package/stories/overlay.stories.js +824 -680
  93. package/stories/overlay.stories.js.map +2 -2
  94. package/sync/overlay-trigger.d.ts +5 -0
  95. package/sync/overlay-trigger.dev.js +2 -4
  96. package/sync/overlay-trigger.dev.js.map +2 -2
  97. package/sync/overlay-trigger.js +1 -1
  98. package/sync/overlay-trigger.js.map +3 -3
  99. package/test/benchmark/basic-test.js +2 -2
  100. package/test/benchmark/basic-test.js.map +1 -1
  101. package/test/index.js +414 -377
  102. package/test/index.js.map +3 -3
  103. package/test/overlay-element.test-vrt.js +5 -0
  104. package/test/overlay-element.test-vrt.js.map +7 -0
  105. package/test/overlay-element.test.js +682 -0
  106. package/test/overlay-element.test.js.map +7 -0
  107. package/test/overlay-lifecycle.test.js +36 -106
  108. package/test/overlay-lifecycle.test.js.map +2 -2
  109. package/test/overlay-trigger-click.test.js +11 -5
  110. package/test/overlay-trigger-click.test.js.map +2 -2
  111. package/test/overlay-trigger-extended.test.js +46 -36
  112. package/test/overlay-trigger-extended.test.js.map +2 -2
  113. package/test/overlay-trigger-hover-click.test.js +38 -25
  114. package/test/overlay-trigger-hover-click.test.js.map +2 -2
  115. package/test/overlay-trigger-hover.test.js +41 -35
  116. package/test/overlay-trigger-hover.test.js.map +2 -2
  117. package/test/overlay-trigger-longpress.test.js +211 -82
  118. package/test/overlay-trigger-longpress.test.js.map +2 -2
  119. package/test/overlay-trigger-sync.test.js +1 -1
  120. package/test/overlay-trigger-sync.test.js.map +2 -2
  121. package/test/overlay-trigger.test.js +1 -1
  122. package/test/overlay-trigger.test.js.map +2 -2
  123. package/test/overlay-update.test.js +5 -5
  124. package/test/overlay-update.test.js.map +2 -2
  125. package/test/overlay-v1.test.js +547 -0
  126. package/test/overlay-v1.test.js.map +7 -0
  127. package/test/overlay.test.js +385 -269
  128. package/test/overlay.test.js.map +3 -3
  129. package/active-overlay.d.ts +0 -6
  130. package/active-overlay.dev.js +0 -5
  131. package/active-overlay.js +0 -2
  132. package/src/ActiveOverlay.d.ts +0 -84
  133. package/src/ActiveOverlay.dev.js +0 -517
  134. package/src/ActiveOverlay.dev.js.map +0 -7
  135. package/src/ActiveOverlay.js +0 -16
  136. package/src/ActiveOverlay.js.map +0 -7
  137. package/src/active-overlay.css.dev.js +0 -13
  138. package/src/active-overlay.css.dev.js.map +0 -7
  139. package/src/active-overlay.css.js +0 -10
  140. package/src/active-overlay.css.js.map +0 -7
  141. package/src/overlay-stack.d.ts +0 -50
  142. package/src/overlay-stack.dev.js +0 -515
  143. package/src/overlay-stack.dev.js.map +0 -7
  144. package/src/overlay-stack.js +0 -34
  145. package/src/overlay-stack.js.map +0 -7
  146. package/src/overlay-utils.d.ts +0 -3
  147. package/src/overlay-utils.dev.js +0 -31
  148. package/src/overlay-utils.dev.js.map +0 -7
  149. package/src/overlay-utils.js +0 -2
  150. package/src/overlay-utils.js.map +0 -7
  151. package/src/overlay.d.ts +0 -59
  152. package/src/overlay.dev.js +0 -127
  153. package/src/overlay.dev.js.map +0 -7
  154. package/src/overlay.js +0 -2
  155. package/src/overlay.js.map +0 -7
  156. /package/src/{active-overlay.css.d.ts → overlay.css.d.ts} +0 -0
@@ -1,20 +1,21 @@
1
1
  "use strict";
2
2
  import "@spectrum-web-components/button/sp-button.js";
3
3
  import "@spectrum-web-components/dialog/sp-dialog.js";
4
+ import "@spectrum-web-components/overlay/sp-overlay.js";
5
+ import "@spectrum-web-components/overlay/overlay-trigger.js";
6
+ import "@spectrum-web-components/tooltip/sp-tooltip.js";
4
7
  import "@spectrum-web-components/popover/sp-popover.js";
5
8
  import { setViewport } from "@web/test-runner-commands";
6
9
  import {
7
- Overlay
10
+ Overlay,
11
+ VirtualTrigger
8
12
  } from "@spectrum-web-components/overlay";
9
- import { isVisible } from "../../../test/testing-helpers.js";
10
13
  import {
11
14
  elementUpdated,
12
15
  expect,
13
- fixture,
14
16
  html,
15
17
  nextFrame,
16
- oneEvent,
17
- waitUntil
18
+ oneEvent
18
19
  } from "@open-wc/testing";
19
20
  import { sendKeys } from "@web/test-runner-commands";
20
21
  import {
@@ -22,11 +23,28 @@ import {
22
23
  virtualElement
23
24
  } from "../stories/overlay.stories";
24
25
  import { sendMouse } from "../../../test/plugins/browser.js";
26
+ import { spy } from "sinon";
27
+ import "@spectrum-web-components/theme/sp-theme.js";
28
+ import "@spectrum-web-components/theme/src/themes.js";
29
+ import { render } from "@spectrum-web-components/base";
30
+ import {
31
+ fixture,
32
+ isInteractive,
33
+ isOnTopLayer
34
+ } from "../../../test/testing-helpers.js";
35
+ async function styledFixture(story) {
36
+ const test = await fixture(html`
37
+ <sp-theme theme="spectrum" scale="medium" color="dark">
38
+ ${story}
39
+ </sp-theme>
40
+ `);
41
+ return test.children[0];
42
+ }
25
43
  describe("Overlays", () => {
26
44
  let testDiv;
27
45
  let openOverlays = [];
28
46
  beforeEach(async () => {
29
- testDiv = await fixture(
47
+ testDiv = await styledFixture(
30
48
  html`
31
49
  <div id="top">
32
50
  <style>
@@ -48,31 +66,28 @@ describe("Overlays", () => {
48
66
  display: none;
49
67
  }
50
68
  </style>
51
- <sp-button
52
- id="first-button"
53
- variant="primary"
54
- slot="trigger"
55
- >
69
+ <sp-button id="first-button" variant="primary">
56
70
  Show Popover
57
71
  </sp-button>
58
72
  <div id="overlay-content">
59
- <sp-popover
60
- id="outer-popover"
61
- slot="click-content"
62
- direction="bottom"
63
- tip
64
- open
65
- >
66
- <sp-dialog class="options-popover-content">
67
- A popover message
73
+ <sp-popover id="outer-popover" direction="bottom" tip>
74
+ <sp-dialog no-divider>
75
+ <div class="options-popover-content">
76
+ A popover message
77
+ </div>
78
+ <sp-button id="outer-focus-target">
79
+ Test 1
80
+ </sp-button>
81
+ <sp-button>Test 2</sp-button>
82
+ <sp-button>Test 3</sp-button>
68
83
  </sp-dialog>
69
84
  </sp-popover>
70
- <div id="hover-1" class="hover-content">
85
+ <sp-tooltip id="hover-1" class="hover-content">
71
86
  Hover message
72
- </div>
73
- <div id="hover-2" class="hover-content">
87
+ </sp-tooltip>
88
+ <sp-tooltip id="hover-2" class="hover-content">
74
89
  Other hover message
75
- </div>
90
+ </sp-tooltip>
76
91
  </div>
77
92
  </div>
78
93
  `
@@ -80,7 +95,7 @@ describe("Overlays", () => {
80
95
  await elementUpdated(testDiv);
81
96
  });
82
97
  afterEach(() => {
83
- openOverlays.map((close) => close());
98
+ openOverlays.map((overlay) => overlay.open = false);
84
99
  openOverlays = [];
85
100
  });
86
101
  [
@@ -95,88 +110,126 @@ describe("Overlays", () => {
95
110
  "left-end",
96
111
  "right",
97
112
  "right-start",
98
- "right-end",
99
- "none"
113
+ "right-end"
100
114
  ].map((direction) => {
101
115
  const placement = direction;
102
116
  it(`opens a popover - ${placement}`, async () => {
117
+ const clickSpy = spy();
103
118
  const button = testDiv.querySelector(
104
119
  "#first-button"
105
120
  );
106
121
  const outerPopover = testDiv.querySelector(
107
122
  "#outer-popover"
108
123
  );
109
- expect(outerPopover.parentElement).to.exist;
110
- if (outerPopover.parentElement) {
111
- expect(outerPopover.parentElement.id).to.equal(
112
- "overlay-content"
113
- );
114
- }
115
- expect(isVisible(outerPopover)).to.be.false;
124
+ outerPopover.addEventListener("click", () => {
125
+ clickSpy();
126
+ });
127
+ expect(await isInteractive(outerPopover)).to.be.false;
116
128
  expect(button).to.exist;
117
- const opened = oneEvent(button, "sp-opened");
129
+ const opened = oneEvent(outerPopover, "sp-opened");
118
130
  openOverlays.push(
119
- await Overlay.open(button, "click", outerPopover, {
131
+ await Overlay.open(outerPopover, {
132
+ trigger: button,
133
+ type: "auto",
120
134
  delayed: false,
121
135
  placement,
122
136
  offset: 10
123
137
  })
124
138
  );
139
+ button.insertAdjacentElement(
140
+ "afterend",
141
+ openOverlays.at(-1)
142
+ );
125
143
  await opened;
126
- expect(outerPopover.parentElement).to.exist;
127
- if (outerPopover.parentElement) {
128
- expect(outerPopover.parentElement.id).not.to.equal(
129
- "overlay-content"
130
- );
131
- }
132
- expect(isVisible(outerPopover)).to.be.true;
144
+ expect(await isInteractive(outerPopover)).to.be.true;
133
145
  });
134
146
  });
147
+ it(`opens a modal dialog`, async () => {
148
+ const button = testDiv.querySelector("#first-button");
149
+ const outerPopover = testDiv.querySelector("#outer-popover");
150
+ expect(await isInteractive(outerPopover)).to.be.false;
151
+ expect(button).to.exist;
152
+ const opened = oneEvent(outerPopover, "sp-opened");
153
+ openOverlays.push(
154
+ await Overlay.open(outerPopover, {
155
+ trigger: button
156
+ })
157
+ );
158
+ button.insertAdjacentElement(
159
+ "afterend",
160
+ openOverlays.at(-1)
161
+ );
162
+ await opened;
163
+ const firstFocused = outerPopover.querySelector(
164
+ "#outer-focus-target"
165
+ );
166
+ expect(document.activeElement === firstFocused).to.be.true;
167
+ await sendKeys({
168
+ press: "Tab"
169
+ });
170
+ expect(document.activeElement === button).to.be.false;
171
+ await sendKeys({
172
+ press: "Tab"
173
+ });
174
+ expect(document.activeElement === button).to.be.false;
175
+ await sendKeys({
176
+ press: "Shift+Tab"
177
+ });
178
+ expect(document.activeElement === button).to.be.false;
179
+ await sendKeys({
180
+ press: "Shift+Tab"
181
+ });
182
+ expect(document.activeElement === button).to.be.false;
183
+ await sendKeys({
184
+ press: "Shift+Tab"
185
+ });
186
+ expect(document.activeElement === button).to.be.false;
187
+ });
135
188
  it(`updates a popover`, async () => {
136
189
  const button = testDiv.querySelector("#first-button");
137
190
  const outerPopover = testDiv.querySelector("#outer-popover");
138
- expect(outerPopover.parentElement).to.exist;
139
- if (outerPopover.parentElement) {
140
- expect(outerPopover.parentElement.id).to.equal("overlay-content");
141
- }
142
- expect(isVisible(outerPopover)).to.be.false;
191
+ expect(await isInteractive(outerPopover)).to.be.false;
143
192
  expect(button).to.exist;
144
- const opened = oneEvent(button, "sp-opened");
193
+ const opened = oneEvent(outerPopover, "sp-opened");
145
194
  openOverlays.push(
146
- await Overlay.open(button, "click", outerPopover, {
147
- delayed: false,
195
+ await Overlay.open(outerPopover, {
196
+ trigger: button,
197
+ type: "auto",
148
198
  offset: 10
149
199
  })
150
200
  );
201
+ button.insertAdjacentElement(
202
+ "afterend",
203
+ openOverlays.at(-1)
204
+ );
151
205
  await opened;
152
- expect(isVisible(outerPopover)).to.be.true;
206
+ expect(await isInteractive(outerPopover)).to.be.true;
153
207
  Overlay.update();
154
- expect(isVisible(outerPopover)).to.be.true;
208
+ expect(await isInteractive(outerPopover)).to.be.true;
155
209
  });
156
210
  it(`opens a popover w/ delay`, async () => {
157
211
  const button = testDiv.querySelector("#first-button");
158
212
  const outerPopover = testDiv.querySelector("#outer-popover");
159
- expect(outerPopover.parentElement).to.exist;
160
- if (outerPopover.parentElement) {
161
- expect(outerPopover.parentElement.id).to.equal("overlay-content");
162
- }
163
- expect(isVisible(outerPopover)).to.be.false;
213
+ expect(await isInteractive(outerPopover)).to.be.false;
164
214
  expect(button).to.exist;
165
- const opened = oneEvent(button, "sp-opened");
215
+ const opened = oneEvent(outerPopover, "sp-opened");
216
+ const start = performance.now();
166
217
  openOverlays.push(
167
- await Overlay.open(button, "click", outerPopover, {
218
+ await Overlay.open(outerPopover, {
219
+ trigger: button,
220
+ type: "auto",
168
221
  delayed: true,
169
222
  offset: 10
170
223
  })
171
224
  );
225
+ button.insertAdjacentElement(
226
+ "afterend",
227
+ openOverlays.at(-1)
228
+ );
172
229
  await opened;
173
- expect(outerPopover.parentElement).to.exist;
174
- if (outerPopover.parentElement) {
175
- expect(outerPopover.parentElement.id).not.to.equal(
176
- "overlay-content"
177
- );
178
- }
179
- expect(isVisible(outerPopover)).to.be.true;
230
+ const end = performance.now();
231
+ expect(await isInteractive(outerPopover)).to.be.true;
232
+ expect(end - start).to.be.greaterThan(1e3);
180
233
  });
181
234
  it("opens hover overlay", async () => {
182
235
  const button = testDiv.querySelector("#first-button");
@@ -184,38 +237,44 @@ describe("Overlays", () => {
184
237
  const clickOverlay = testDiv.querySelector(
185
238
  "#outer-popover"
186
239
  );
187
- expect(isVisible(hoverOverlay)).to.be.false;
188
- expect(isVisible(clickOverlay)).to.be.false;
189
- let opened = oneEvent(button, "sp-opened");
240
+ expect(await isOnTopLayer(hoverOverlay)).to.be.false;
241
+ expect(await isOnTopLayer(clickOverlay)).to.be.false;
242
+ let opened = oneEvent(hoverOverlay, "sp-opened");
190
243
  openOverlays.push(
191
- await Overlay.open(button, "hover", hoverOverlay, {
192
- delayed: false,
244
+ await Overlay.open(hoverOverlay, {
245
+ trigger: button,
246
+ type: "hint",
193
247
  placement: "top",
194
248
  offset: 10
195
249
  })
196
250
  );
251
+ button.insertAdjacentElement(
252
+ "afterend",
253
+ openOverlays.at(-1)
254
+ );
197
255
  await opened;
198
- expect(hoverOverlay.parentElement).to.exist;
199
- if (hoverOverlay.parentElement) {
200
- expect(hoverOverlay.parentElement.id).not.to.equal(
201
- "overlay-content"
202
- );
203
- }
204
- expect(isVisible(hoverOverlay)).to.be.true;
205
- opened = oneEvent(button, "sp-opened");
256
+ expect(await isOnTopLayer(hoverOverlay)).to.be.true;
257
+ opened = oneEvent(clickOverlay, "sp-opened");
258
+ const closed = oneEvent(hoverOverlay, "sp-closed");
206
259
  openOverlays.push(
207
- await Overlay.open(button, "click", clickOverlay, {
208
- delayed: false,
260
+ await Overlay.open(clickOverlay, {
261
+ trigger: button,
262
+ type: "auto",
209
263
  placement: "bottom",
210
264
  offset: 10
211
265
  })
212
266
  );
267
+ button.insertAdjacentElement(
268
+ "afterend",
269
+ openOverlays.at(-1)
270
+ );
213
271
  await opened;
214
- if (hoverOverlay.parentElement) {
215
- expect(hoverOverlay.parentElement.id).to.equal("overlay-content");
216
- }
217
- expect(isVisible(hoverOverlay)).to.be.false;
218
- expect(isVisible(clickOverlay)).to.be.true;
272
+ await closed;
273
+ expect(
274
+ await isInteractive(clickOverlay),
275
+ "click overlay not interactive"
276
+ ).to.be.true;
277
+ expect(await isOnTopLayer(hoverOverlay), "hover overlay interactive").to.be.false;
219
278
  });
220
279
  it("opens custom overlay", async () => {
221
280
  const button = testDiv.querySelector("#first-button");
@@ -225,94 +284,148 @@ describe("Overlays", () => {
225
284
  );
226
285
  expect(button).to.exist;
227
286
  expect(customOverlay).to.exist;
228
- expect(isVisible(customOverlay)).to.be.false;
229
- expect(isVisible(clickOverlay)).to.be.false;
230
- let opened = oneEvent(button, "sp-opened");
287
+ expect(await isOnTopLayer(customOverlay)).to.be.false;
288
+ expect(await isOnTopLayer(clickOverlay)).to.be.false;
289
+ let opened = oneEvent(customOverlay, "sp-opened");
231
290
  openOverlays.push(
232
- await Overlay.open(button, "custom", customOverlay, {
233
- delayed: false,
291
+ await Overlay.open(customOverlay, {
292
+ trigger: button,
293
+ type: "auto",
234
294
  placement: "top",
235
295
  offset: 10
236
296
  })
237
297
  );
298
+ button.insertAdjacentElement(
299
+ "afterend",
300
+ openOverlays.at(-1)
301
+ );
238
302
  await opened;
239
- expect(customOverlay.parentElement).to.exist;
240
- if (customOverlay.parentElement) {
241
- expect(customOverlay.parentElement.id).not.to.equal(
242
- "overlay-content"
243
- );
244
- }
245
- expect(isVisible(customOverlay)).to.be.true;
246
- opened = oneEvent(button, "sp-opened");
303
+ expect(await isOnTopLayer(customOverlay)).to.be.true;
304
+ opened = oneEvent(clickOverlay, "sp-opened");
247
305
  openOverlays.push(
248
- await Overlay.open(button, "click", clickOverlay, {
249
- delayed: false,
306
+ await Overlay.open(clickOverlay, {
307
+ trigger: button,
308
+ type: "auto",
250
309
  placement: "bottom",
251
310
  offset: 10
252
311
  })
253
312
  );
313
+ button.insertAdjacentElement(
314
+ "afterend",
315
+ openOverlays.at(-1)
316
+ );
254
317
  await opened;
255
- expect(isVisible(customOverlay)).to.be.true;
256
- expect(isVisible(clickOverlay)).to.be.true;
318
+ expect(await isOnTopLayer(clickOverlay), "click content open").to.be.true;
257
319
  });
258
320
  it("closes via events", async () => {
259
- const el = await fixture(html`
260
- <div id="root">
261
- <sp-dialog dismissable></sp-dialog>
321
+ const test = await fixture(html`
322
+ <div>
323
+ <sp-popover id="root">
324
+ <sp-dialog dismissable>
325
+ Some Content for the Dialog.
326
+ </sp-dialog>
327
+ </sp-popover>
262
328
  </div>
263
329
  `);
330
+ const el = test.querySelector("sp-popover");
264
331
  const dialog = el.querySelector("sp-dialog");
265
332
  const opened = oneEvent(el, "sp-opened");
266
333
  openOverlays.push(
267
- await Overlay.open(el, "click", dialog, {
268
- delayed: false,
334
+ await Overlay.open(el, {
335
+ trigger: test,
336
+ type: "auto",
269
337
  placement: "bottom",
270
338
  offset: 10
271
339
  })
272
340
  );
341
+ test.insertAdjacentElement(
342
+ "afterend",
343
+ openOverlays.at(-1)
344
+ );
273
345
  await opened;
346
+ expect(await isInteractive(el)).to.be.true;
347
+ const closed = oneEvent(el, "sp-closed");
274
348
  dialog.close();
275
- await waitUntil(
276
- () => !!dialog.parentElement && dialog.parentElement.tagName !== "ACTIVE-OVERLAY",
277
- "content is returned"
349
+ await closed;
350
+ expect(await isInteractive(el)).to.be.false;
351
+ });
352
+ it("positions with a VirtualTrigger", async () => {
353
+ const test = await fixture(html`
354
+ <div>
355
+ <sp-popover id="root" placement="right">
356
+ <sp-dialog dismissable>
357
+ Some Content for the Dialog.
358
+ </sp-dialog>
359
+ </sp-popover>
360
+ </div>
361
+ `);
362
+ const el = test.querySelector("sp-popover");
363
+ const trigger = new VirtualTrigger(100, 100);
364
+ const opened = oneEvent(el, "sp-opened");
365
+ openOverlays.push(
366
+ await Overlay.open(el, {
367
+ trigger,
368
+ type: "auto",
369
+ placement: "right",
370
+ offset: 10
371
+ })
278
372
  );
373
+ test.insertAdjacentElement(
374
+ "afterend",
375
+ openOverlays.at(-1)
376
+ );
377
+ await opened;
378
+ expect(await isInteractive(el)).to.be.true;
379
+ const initial = el.getBoundingClientRect();
380
+ trigger.updateBoundingClientRect(500, 500);
381
+ await nextFrame();
382
+ await nextFrame();
383
+ const final = el.getBoundingClientRect();
384
+ expect(initial.x).to.not.equal(8);
385
+ expect(initial.y).to.not.equal(8);
386
+ expect(initial.x).to.not.equal(final.x);
387
+ expect(initial.y).to.not.equal(final.y);
279
388
  });
280
389
  it("closes an inline overlay when tabbing past the content", async () => {
281
390
  const el = await fixture(html`
282
391
  <div>
283
392
  <sp-button class="trigger">Trigger</sp-button>
284
- <div class="content">
393
+ <sp-popover class="content">
285
394
  <input />
286
- </div>
395
+ </sp-popover>
287
396
  <input value="After" id="after" />
288
397
  </div>
289
398
  `);
290
399
  const trigger = el.querySelector(".trigger");
291
400
  const content = el.querySelector(".content");
292
401
  const input = el.querySelector("input");
293
- const after = el.querySelector("#after");
294
- openOverlays.push(await Overlay.open(trigger, "inline", content, {}));
295
- trigger.focus();
296
- await sendKeys({
297
- press: "Tab"
298
- });
402
+ const after2 = el.querySelector("#after");
403
+ const opened = oneEvent(content, "sp-opened");
404
+ openOverlays.push(
405
+ await Overlay.open(content, {
406
+ trigger,
407
+ type: "auto",
408
+ receivesFocus: "auto"
409
+ })
410
+ );
411
+ trigger.insertAdjacentElement(
412
+ "afterend",
413
+ openOverlays.at(-1)
414
+ );
415
+ await opened;
416
+ expect(await isInteractive(content)).to.be.true;
299
417
  expect(document.activeElement).to.equal(input);
300
- expect(input.closest("active-overlay") !== null);
418
+ const closed = oneEvent(content, "sp-closed");
301
419
  await sendKeys({
302
420
  press: "Shift+Tab"
303
421
  });
422
+ await closed;
304
423
  expect(document.activeElement).to.equal(trigger);
305
424
  await sendKeys({
306
425
  press: "Tab"
307
426
  });
308
- expect(document.activeElement).to.equal(input);
309
- await sendKeys({
310
- press: "Tab"
311
- });
312
- expect(document.activeElement).to.equal(after);
313
- await waitUntil(
314
- () => document.querySelector("active-overlay") === null
315
- );
427
+ expect(document.activeElement).to.equal(after2);
428
+ expect(await isInteractive(content)).to.be.false;
316
429
  });
317
430
  it("closes an inline overlay when tabbing before the trigger", async () => {
318
431
  const el = await fixture(html`
@@ -330,14 +443,20 @@ describe("Overlays", () => {
330
443
  const trigger = el.querySelector(".trigger");
331
444
  const content = el.querySelector(".content");
332
445
  const input = el.querySelector(".content input");
333
- const before = el.querySelector("#before");
334
- openOverlays.push(await Overlay.open(trigger, "inline", content, {}));
335
- trigger.focus();
336
- await sendKeys({
337
- press: "Tab"
338
- });
446
+ const before2 = el.querySelector("#before");
447
+ const open = oneEvent(trigger, "sp-opened");
448
+ openOverlays.push(
449
+ await Overlay.open(content, {
450
+ trigger,
451
+ type: "auto"
452
+ })
453
+ );
454
+ trigger.insertAdjacentElement(
455
+ "afterend",
456
+ openOverlays.at(-1)
457
+ );
458
+ await open;
339
459
  expect(document.activeElement).to.equal(input);
340
- expect(input.closest("active-overlay") !== null);
341
460
  await sendKeys({
342
461
  press: "Shift+Tab"
343
462
  });
@@ -345,10 +464,7 @@ describe("Overlays", () => {
345
464
  await sendKeys({
346
465
  press: "Shift+Tab"
347
466
  });
348
- expect(document.activeElement).to.equal(before);
349
- await waitUntil(
350
- () => document.querySelector("active-overlay") === null
351
- );
467
+ expect(document.activeElement).to.equal(before2);
352
468
  });
353
469
  it("opens detached content", async () => {
354
470
  const textContent = "This is a detached element that has been overlaid";
@@ -357,118 +473,130 @@ describe("Overlays", () => {
357
473
  <button>Trigger</button>
358
474
  `
359
475
  );
360
- const content = document.createElement("div");
476
+ const content = document.createElement("sp-popover");
361
477
  content.textContent = textContent;
362
- const opened = oneEvent(el, "sp-opened");
363
- const closeOverlay = await Overlay.open(el, "click", content, {
478
+ const opened = oneEvent(content, "sp-opened");
479
+ const overlay = await Overlay.open(content, {
480
+ trigger: el,
481
+ type: "auto",
364
482
  placement: "bottom"
365
483
  });
484
+ el.insertAdjacentElement("afterend", overlay);
366
485
  await opened;
367
- let activeOverlay = document.querySelector("active-overlay");
368
- if (activeOverlay) {
369
- expect(activeOverlay.textContent).to.equal(textContent);
370
- } else {
371
- expect(activeOverlay).to.not.be.null;
372
- }
373
- const closed = oneEvent(el, "sp-closed");
374
- closeOverlay();
486
+ expect(await isInteractive(content)).to.be.true;
487
+ const closed = oneEvent(content, "sp-closed");
488
+ overlay.open = false;
375
489
  await closed;
376
- activeOverlay = document.querySelector("active-overlay");
377
- expect(activeOverlay).to.be.null;
490
+ expect(await isInteractive(content)).to.be.false;
378
491
  content.remove();
379
492
  });
380
493
  });
381
494
  describe('Overlay - type="modal"', () => {
382
- it("closes on `contextmenu` and passes that to the underlying page", async () => {
383
- await fixture(html`
384
- ${virtualElement({
385
- ...virtualElement.args,
386
- offset: 6
387
- })}
388
- `);
389
- const width = window.innerWidth;
390
- const height = window.innerHeight;
391
- let opened = oneEvent(document, "sp-opened");
392
- sendMouse({
393
- steps: [
394
- {
395
- type: "move",
396
- position: [width / 2 + 50, height / 2]
397
- },
398
- {
399
- type: "click",
400
- options: {
401
- button: "right"
402
- },
403
- position: [width / 2 + 50, height / 2]
404
- }
405
- ]
495
+ describe("handle multiple separate `contextmenu` events", async () => {
496
+ let width = 0;
497
+ let height = 0;
498
+ let firstMenu;
499
+ let firstRect;
500
+ let secondMenu;
501
+ let secondRect;
502
+ before(async () => {
503
+ render(
504
+ html`
505
+ <sp-theme color="light" scale="large">
506
+ ${virtualElement({
507
+ ...virtualElement.args,
508
+ offset: 6
509
+ })}
510
+ </sp-theme>
511
+ `,
512
+ document.body
513
+ );
514
+ width = window.innerWidth;
515
+ height = window.innerHeight;
406
516
  });
407
- await opened;
408
- const firstOverlay = document.querySelector(
409
- "active-overlay"
410
- );
411
- const firstHeadline = firstOverlay.querySelector(
412
- '[slot="header"]'
413
- );
414
- expect(firstOverlay, "first overlay").to.not.be.null;
415
- expect(firstOverlay.isConnected).to.be.true;
416
- expect(firstHeadline.textContent).to.equal("Menu source: end");
417
- let closed = oneEvent(document, "sp-closed");
418
- opened = oneEvent(document, "sp-opened");
419
- sendMouse({
420
- steps: [
421
- {
422
- type: "move",
423
- position: [width / 4, height / 4]
424
- },
425
- {
426
- type: "click",
427
- options: {
428
- button: "right"
517
+ after(() => {
518
+ var _a;
519
+ (_a = document.querySelector("sp-theme")) == null ? void 0 : _a.remove();
520
+ });
521
+ it('opens the first "contextmenu" overlay', async () => {
522
+ const opened = oneEvent(document, "sp-opened");
523
+ await sendMouse({
524
+ steps: [
525
+ {
526
+ type: "move",
527
+ position: [width / 2 + 50, height / 2]
429
528
  },
430
- position: [width / 4, height / 4]
431
- }
432
- ]
529
+ {
530
+ type: "click",
531
+ options: {
532
+ button: "right"
533
+ },
534
+ position: [width / 2 + 50, height / 2]
535
+ }
536
+ ]
537
+ });
538
+ await opened;
539
+ firstMenu = document.querySelector("sp-popover");
540
+ expect(firstMenu.textContent).to.include("Menu source: end");
541
+ firstRect = firstMenu.getBoundingClientRect();
542
+ expect(firstMenu).to.not.be.null;
433
543
  });
434
- await closed;
435
- await opened;
436
- const secondOverlay = document.querySelector(
437
- "active-overlay"
438
- );
439
- const secondHeadline = secondOverlay.querySelector(
440
- '[slot="header"]'
441
- );
442
- expect(secondOverlay, "second overlay").to.not.be.null;
443
- expect(secondOverlay).to.not.equal(firstOverlay);
444
- expect(firstOverlay.isConnected).to.be.false;
445
- expect(secondOverlay.isConnected).to.be.true;
446
- expect(secondHeadline.textContent).to.equal("Menu source: start");
447
- closed = oneEvent(document, "sp-closed");
448
- sendMouse({
449
- steps: [
450
- {
451
- type: "move",
452
- position: [width / 8, height / 8]
453
- },
454
- {
455
- type: "click",
456
- position: [width / 8, height / 8]
457
- }
458
- ]
544
+ it('closes the first "contextmenu" when opening a second', async () => {
545
+ var _a, _b, _c, _d;
546
+ const closed = oneEvent(document, "sp-closed");
547
+ const opened = oneEvent(document, "sp-opened");
548
+ const trigger = document.querySelector(
549
+ "start-end-contextmenu"
550
+ );
551
+ (_b = (_a = trigger.shadowRoot) == null ? void 0 : _a.querySelector("#start")) == null ? void 0 : _b.dispatchEvent(
552
+ new Event("contextmenu", {
553
+ composed: true
554
+ })
555
+ );
556
+ await nextFrame();
557
+ (_d = (_c = trigger.shadowRoot) == null ? void 0 : _c.querySelector("#start")) == null ? void 0 : _d.dispatchEvent(
558
+ new Event("pointerup", {
559
+ composed: true,
560
+ bubbles: true
561
+ })
562
+ );
563
+ await closed;
564
+ await opened;
565
+ secondMenu = document.querySelector("sp-popover");
566
+ expect(secondMenu.textContent).to.include("Menu source: start");
567
+ secondRect = secondMenu.getBoundingClientRect();
568
+ expect(secondMenu).to.not.be.null;
569
+ });
570
+ it('closes the second "contextmenu" when clicking away', async () => {
571
+ const closed = oneEvent(document, "sp-closed");
572
+ sendMouse({
573
+ steps: [
574
+ {
575
+ type: "click",
576
+ position: [width - width / 8, height - height / 8]
577
+ }
578
+ ]
579
+ });
580
+ await closed;
581
+ expect(firstRect.top).to.not.equal(secondRect.top);
582
+ expect(firstRect.left).to.not.equal(secondRect.left);
459
583
  });
460
- await closed;
461
- await nextFrame();
462
584
  });
463
585
  it("does not open content off of the viewport", async () => {
586
+ before(async () => {
587
+ await setViewport({ width: 360, height: 640 });
588
+ await nextFrame();
589
+ });
590
+ after(async () => {
591
+ await setViewport({ width: 800, height: 600 });
592
+ await nextFrame();
593
+ });
464
594
  await fixture(html`
465
595
  ${virtualElement({
466
596
  ...virtualElement.args,
467
597
  offset: 6
468
598
  })}
469
599
  `);
470
- await setViewport({ width: 360, height: 640 });
471
- await nextFrame();
472
600
  const opened = oneEvent(document, "sp-opened");
473
601
  sendMouse({
474
602
  steps: [
@@ -486,19 +614,15 @@ describe('Overlay - type="modal"', () => {
486
614
  ]
487
615
  });
488
616
  await opened;
489
- const activeOverlay = document.querySelector(
490
- "active-overlay"
491
- );
492
- expect(activeOverlay.placement).to.equal("right-start");
493
- expect(activeOverlay.getAttribute("actual-placement")).to.equal(
494
- "bottom"
495
- );
617
+ const firstMenu = document.querySelector("sp-menu");
618
+ expect(firstMenu).to.not.be.null;
619
+ expect(await isInteractive(firstMenu)).to.be.true;
496
620
  const closed = oneEvent(document, "sp-closed");
497
621
  sendKeys({
498
622
  press: "Escape"
499
623
  });
500
624
  await closed;
501
- await nextFrame();
625
+ expect(await isInteractive(firstMenu)).to.be.false;
502
626
  });
503
627
  it("opens children in the modal stack through shadow roots", async () => {
504
628
  const el = await fixture(definedOverlayElement());
@@ -508,51 +632,47 @@ describe('Overlay - type="modal"', () => {
508
632
  let open = oneEvent(el, "sp-opened");
509
633
  trigger.click();
510
634
  await open;
635
+ expect(el.open).to.equal("click");
511
636
  const content = document.querySelector(
512
637
  "popover-content"
513
638
  );
514
639
  open = oneEvent(content, "sp-opened");
515
640
  content.button.click();
516
641
  await open;
517
- const activeOverlays = document.querySelectorAll("active-overlay");
518
- activeOverlays.forEach((overlay) => {
519
- expect(overlay.slot).to.equal("open");
520
- });
642
+ expect(content.trigger.open).to.equal("click");
521
643
  let close = oneEvent(content, "sp-closed");
522
644
  content.trigger.removeAttribute("open");
523
645
  await close;
646
+ expect(content.trigger.open).to.be.null;
524
647
  close = oneEvent(el, "sp-closed");
525
648
  el.removeAttribute("open");
526
649
  await close;
650
+ expect(el.open).to.be.null;
527
651
  });
528
652
  });
529
653
  describe("Overlay - timing", () => {
530
654
  it("manages multiple modals in a row without preventing them from closing", async () => {
531
655
  const test = await fixture(html`
532
656
  <div>
533
- <overlay-trigger>
657
+ <overlay-trigger id="test-1" placement="right">
534
658
  <sp-button slot="trigger">Trigger 1</sp-button>
535
659
  <sp-popover slot="hover-content">
536
660
  <p>Hover contentent for "Trigger 1".</p>
537
661
  </sp-popover>
538
662
  </overlay-trigger>
539
- <overlay-trigger>
663
+ <overlay-trigger id="test-2" placement="right">
540
664
  <sp-button slot="trigger">Trigger 2</sp-button>
541
- <sp-popover slot="hover-content">
542
- <p>Hover contentent for "Trigger 2".</p>
543
- </sp-popover>
544
665
  <sp-popover slot="click-content">
545
666
  <p>Click contentent for "Trigger 2".</p>
546
667
  </sp-popover>
668
+ <sp-popover slot="hover-content">
669
+ <p>Hover contentent for "Trigger 2".</p>
670
+ </sp-popover>
547
671
  </overlay-trigger>
548
672
  </div>
549
673
  `);
550
- const overlayTrigger1 = test.querySelector(
551
- "overlay-trigger:first-child"
552
- );
553
- const overlayTrigger2 = test.querySelector(
554
- "overlay-trigger:last-child"
555
- );
674
+ const overlayTrigger1 = test.querySelector("#test-1");
675
+ const overlayTrigger2 = test.querySelector("#test-2");
556
676
  const trigger1 = overlayTrigger1.querySelector(
557
677
  '[slot="trigger"]'
558
678
  );
@@ -565,17 +685,13 @@ describe("Overlay - timing", () => {
565
685
  boundingRectTrigger1.left + boundingRectTrigger1.width / 2,
566
686
  boundingRectTrigger1.top + boundingRectTrigger1.height / 2
567
687
  ];
568
- const outsideTrigger1 = [
569
- boundingRectTrigger1.left + boundingRectTrigger1.width * 2,
570
- boundingRectTrigger1.top + boundingRectTrigger1.height * 2
688
+ const outsideTriggers = [
689
+ boundingRectTrigger1.left + boundingRectTrigger1.width / 2,
690
+ 300
571
691
  ];
572
692
  const trigger2Position = [
573
693
  boundingRectTrigger2.left + boundingRectTrigger2.width / 2,
574
- boundingRectTrigger2.top + boundingRectTrigger2.height / 2
575
- ];
576
- const outsideTrigger2 = [
577
- boundingRectTrigger2.left + boundingRectTrigger2.width * 2,
578
- boundingRectTrigger2.top + boundingRectTrigger2.height / 2
694
+ boundingRectTrigger2.top + boundingRectTrigger2.height / 4
579
695
  ];
580
696
  await sendMouse({
581
697
  steps: [
@@ -591,7 +707,7 @@ describe("Overlay - timing", () => {
591
707
  steps: [
592
708
  {
593
709
  type: "move",
594
- position: outsideTrigger1
710
+ position: outsideTriggers
595
711
  }
596
712
  ]
597
713
  });
@@ -608,7 +724,7 @@ describe("Overlay - timing", () => {
608
724
  await nextFrame();
609
725
  await nextFrame();
610
726
  const opened = oneEvent(trigger2, "sp-opened");
611
- sendMouse({
727
+ await sendMouse({
612
728
  steps: [
613
729
  {
614
730
  type: "click",
@@ -617,23 +733,23 @@ describe("Overlay - timing", () => {
617
733
  ]
618
734
  });
619
735
  await opened;
736
+ await nextFrame();
737
+ await nextFrame();
620
738
  expect(overlayTrigger1.hasAttribute("open")).to.be.false;
621
739
  expect(overlayTrigger2.hasAttribute("open")).to.be.true;
622
740
  expect(overlayTrigger2.getAttribute("open")).to.equal("click");
623
741
  const closed = oneEvent(overlayTrigger2, "sp-closed");
624
- sendMouse({
742
+ await sendMouse({
625
743
  steps: [
626
744
  {
627
745
  type: "click",
628
- position: outsideTrigger2
746
+ position: outsideTriggers
629
747
  }
630
748
  ]
631
749
  });
632
750
  await closed;
633
- for (let i = 0; i < 3; i++)
634
- await nextFrame();
635
751
  expect(overlayTrigger1.hasAttribute("open")).to.be.false;
636
- expect(overlayTrigger2.hasAttribute("open"), overlayTrigger2.open).to.be.false;
752
+ expect(overlayTrigger2.hasAttribute("open")).to.be.false;
637
753
  });
638
754
  });
639
755
  //# sourceMappingURL=overlay.test.js.map