@lion/ui 0.0.9 → 0.0.11

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 (158) hide show
  1. package/components/accordion/src/LionAccordion.js +2 -2
  2. package/components/core/src/SlotMixin.js +2 -1
  3. package/components/dialog/src/LionDialog.js +0 -28
  4. package/components/dialog/test/lion-dialog.test.js +11 -10
  5. package/components/form-integrations/test/form-group-methods.test.js +6 -4
  6. package/components/form-integrations/test/form-integrations.test.js +10 -5
  7. package/components/form-integrations/test/helpers/umbrella-form.js +10 -0
  8. package/components/form-integrations/test/model-value-consistency.test.js +29 -20
  9. package/components/input-datepicker/src/LionInputDatepicker.js +66 -104
  10. package/components/input-datepicker/src/localizeNamespaceLoader.js +188 -0
  11. package/components/input-datepicker/test/lion-input-datepicker.test.js +15 -20
  12. package/components/input-datepicker/test-helpers/DatepickerInputObject.js +3 -3
  13. package/components/input-tel/src/parsers.js +1 -1
  14. package/components/listbox/test-suites/ListboxMixin.suite.js +3 -3
  15. package/components/localize/src/singleton.js +1 -1
  16. package/components/localize/test/number/formatNumber.test.js +2 -6
  17. package/components/overlays/src/OverlayController.js +292 -291
  18. package/components/overlays/src/OverlayMixin.js +17 -18
  19. package/components/overlays/src/OverlaysManager.js +28 -53
  20. package/components/overlays/src/configurations/visibility-trigger-partials/withClickInteraction.js +32 -0
  21. package/components/overlays/src/configurations/visibility-trigger-partials/withHoverInteraction.js +76 -0
  22. package/components/overlays/src/configurations/withBottomSheetConfig.js +3 -0
  23. package/components/overlays/src/configurations/withDropdownConfig.js +3 -0
  24. package/components/overlays/src/configurations/withModalDialogConfig.js +3 -0
  25. package/components/overlays/src/configurations/withTooltipConfig.js +29 -0
  26. package/components/overlays/src/overlayDocumentStyle.js +24 -0
  27. package/components/overlays/src/overlayShadowDomStyle.js +138 -0
  28. package/components/overlays/src/singleton.js +3 -1
  29. package/components/overlays/test/ArrowMixin.test.js +0 -1
  30. package/components/overlays/test/OverlayController.test.js +372 -274
  31. package/components/overlays/test/OverlaysManager.test.js +23 -32
  32. package/components/overlays/test/global-positioning.test.js +4 -15
  33. package/components/overlays/test/local-positioning.test.js +65 -38
  34. package/components/overlays/test-suites/OverlayMixin.suite.js +18 -26
  35. package/components/overlays/types/OverlayConfig.ts +38 -11
  36. package/components/overlays/types/OverlayMixinTypes.ts +2 -2
  37. package/components/select-rich/src/LionSelectInvoker.js +2 -3
  38. package/components/select-rich/src/LionSelectRich.js +22 -20
  39. package/components/select-rich/test/lion-select-rich.test.js +5 -7
  40. package/components/tooltip/src/LionTooltip.js +3 -90
  41. package/components/tooltip/test/lion-tooltip.test.js +52 -20
  42. package/custom-elements.json +535 -503
  43. package/dist-types/components/core/src/SlotMixin.d.ts.map +1 -1
  44. package/dist-types/components/dialog/src/LionDialog.d.ts +0 -2
  45. package/dist-types/components/dialog/src/LionDialog.d.ts.map +1 -1
  46. package/dist-types/components/form-integrations/test/helpers/umbrella-form.d.ts +4 -0
  47. package/dist-types/components/form-integrations/test/helpers/umbrella-form.d.ts.map +1 -1
  48. package/dist-types/components/form-integrations/test/model-value-consistency.test.d.ts.map +1 -1
  49. package/dist-types/components/input-datepicker/src/LionInputDatepicker.d.ts +3 -3
  50. package/dist-types/components/input-datepicker/src/LionInputDatepicker.d.ts.map +1 -1
  51. package/dist-types/components/input-datepicker/src/localizeNamespaceLoader.d.ts +4 -0
  52. package/dist-types/components/input-datepicker/src/localizeNamespaceLoader.d.ts.map +1 -0
  53. package/dist-types/components/overlays/src/OverlayController.d.ts +56 -101
  54. package/dist-types/components/overlays/src/OverlayController.d.ts.map +1 -1
  55. package/dist-types/components/overlays/src/OverlayMixin.d.ts.map +1 -1
  56. package/dist-types/components/overlays/src/OverlaysManager.d.ts +0 -7
  57. package/dist-types/components/overlays/src/OverlaysManager.d.ts.map +1 -1
  58. package/dist-types/components/overlays/src/configurations/visibility-trigger-partials/withClickInteraction.d.ts +12 -0
  59. package/dist-types/components/overlays/src/configurations/visibility-trigger-partials/withClickInteraction.d.ts.map +1 -0
  60. package/dist-types/components/overlays/src/configurations/visibility-trigger-partials/withHoverInteraction.d.ts +18 -0
  61. package/dist-types/components/overlays/src/configurations/visibility-trigger-partials/withHoverInteraction.d.ts.map +1 -0
  62. package/dist-types/components/overlays/src/configurations/withBottomSheetConfig.d.ts.map +1 -1
  63. package/dist-types/components/overlays/src/configurations/withDropdownConfig.d.ts.map +1 -1
  64. package/dist-types/components/overlays/src/configurations/withModalDialogConfig.d.ts.map +1 -1
  65. package/dist-types/components/overlays/src/configurations/withTooltipConfig.d.ts +8 -0
  66. package/dist-types/components/overlays/src/configurations/withTooltipConfig.d.ts.map +1 -0
  67. package/dist-types/components/overlays/src/overlayDocumentStyle.d.ts +2 -0
  68. package/dist-types/components/overlays/src/overlayDocumentStyle.d.ts.map +1 -0
  69. package/dist-types/components/overlays/src/overlayShadowDomStyle.d.ts +2 -0
  70. package/dist-types/components/overlays/src/overlayShadowDomStyle.d.ts.map +1 -0
  71. package/dist-types/components/overlays/src/singleton.d.ts +2 -1
  72. package/dist-types/components/overlays/src/singleton.d.ts.map +1 -1
  73. package/dist-types/components/overlays/test-suites/OverlayMixin.suite.d.ts.map +1 -1
  74. package/dist-types/components/overlays/types/OverlayConfig.d.ts +19 -10
  75. package/dist-types/components/overlays/types/OverlayConfig.d.ts.map +1 -1
  76. package/dist-types/components/overlays/types/OverlayMixinTypes.d.ts +2 -2
  77. package/dist-types/components/overlays/types/OverlayMixinTypes.d.ts.map +1 -1
  78. package/dist-types/components/select-rich/src/LionSelectInvoker.d.ts +3 -27
  79. package/dist-types/components/select-rich/src/LionSelectInvoker.d.ts.map +1 -1
  80. package/dist-types/components/select-rich/src/LionSelectRich.d.ts.map +1 -1
  81. package/dist-types/components/select-rich/test/lion-select-rich.test.d.ts.map +1 -1
  82. package/dist-types/components/tooltip/src/LionTooltip.d.ts +4 -20
  83. package/dist-types/components/tooltip/src/LionTooltip.d.ts.map +1 -1
  84. package/dist-types/components/tooltip/test/lion-tooltip.test.d.ts.map +1 -1
  85. package/dist-types/exports/input-datepicker.d.ts +0 -1
  86. package/dist-types/exports/overlays.d.ts +1 -1
  87. package/dist-types/exports/types/overlays.d.ts +1 -0
  88. package/dist-types/exports/types/overlays.d.ts.map +1 -1
  89. package/dist-types/tsconfig.tsbuildinfo +1 -1
  90. package/docs/components/checkbox-group/overview.md +2 -2
  91. package/docs/components/collapsible/overview.md +1 -1
  92. package/docs/components/combobox/overview.md +1 -1
  93. package/docs/components/combobox/use-cases.md +1 -1
  94. package/docs/components/dialog/overview.md +5 -9
  95. package/docs/components/dialog/use-cases.md +43 -87
  96. package/docs/components/fieldset/overview.md +5 -5
  97. package/docs/components/form/overview.md +3 -3
  98. package/docs/components/icon/use-cases.md +1 -1
  99. package/docs/components/input/overview.md +1 -1
  100. package/docs/components/input-amount/overview.md +3 -3
  101. package/docs/components/input-date/overview.md +3 -3
  102. package/docs/components/input-datepicker/overview.md +5 -5
  103. package/docs/components/input-email/overview.md +2 -2
  104. package/docs/components/input-iban/overview.md +2 -2
  105. package/docs/components/input-range/overview.md +2 -2
  106. package/docs/components/input-stepper/overview.md +1 -1
  107. package/docs/components/input-tel/overview.md +1 -1
  108. package/docs/components/input-tel/use-cases.md +6 -6
  109. package/docs/components/input-tel-dropdown/overview.md +1 -1
  110. package/docs/components/radio-group/overview.md +3 -3
  111. package/docs/components/select-rich/use-cases.md +1 -1
  112. package/docs/components/tabs/examples.md +1 -1
  113. package/docs/fundamentals/index.md +4 -4
  114. package/docs/fundamentals/node-tools/providence-analytics/LocalConfiguration.md +1 -1
  115. package/docs/fundamentals/node-tools/providence-analytics/QueryResult.md +1 -1
  116. package/docs/fundamentals/node-tools/providence-analytics/analyzer.md +1 -1
  117. package/docs/fundamentals/node-tools/providence-analytics/dashboard.md +1 -1
  118. package/docs/fundamentals/node-tools/providence-analytics/overview.md +3 -3
  119. package/docs/fundamentals/node-tools/publish-docs/overview.md +3 -3
  120. package/docs/fundamentals/node-tools/rocket-preset-extend-lion-docs/overview.md +2 -2
  121. package/docs/fundamentals/systems/core/overview.md +1 -1
  122. package/docs/fundamentals/systems/form/formatting-and-parsing.md +4 -4
  123. package/docs/fundamentals/systems/form/model-value.md +1 -1
  124. package/docs/fundamentals/systems/form/overview.md +28 -28
  125. package/docs/fundamentals/systems/form/use-cases.md +4 -0
  126. package/docs/fundamentals/systems/form/validate.md +1 -1
  127. package/docs/fundamentals/systems/localize/overview.md +4 -4
  128. package/docs/fundamentals/systems/overlays/assets/{applyDemoOverlayStyles.js → applyDemoOverlayStyles.mjs} +2 -1
  129. package/docs/fundamentals/systems/overlays/assets/demo-el-using-overlaymixin.mjs +119 -0
  130. package/docs/fundamentals/systems/overlays/assets/{demo-overlay-backdrop.js → demo-overlay-backdrop.mjs} +3 -4
  131. package/docs/fundamentals/systems/overlays/assets/demo-overlay-positioning.mjs +537 -0
  132. package/docs/fundamentals/systems/overlays/assets/umbrella-form.js +9 -2
  133. package/docs/fundamentals/systems/overlays/configuration.md +56 -54
  134. package/docs/fundamentals/systems/overlays/overview.md +5 -5
  135. package/docs/fundamentals/systems/overlays/use-cases.md +83 -77
  136. package/docs/fundamentals/tools/helpers/overview.md +1 -1
  137. package/docs/fundamentals/tools/singleton-manager/overview.md +4 -4
  138. package/docs/guides/how-to/create-a-custom-field.md +6 -6
  139. package/docs/guides/how-to/extend-a-native-input.md +3 -3
  140. package/docs/guides/index.md +8 -8
  141. package/docs/guides/principles/index.md +5 -5
  142. package/docs/guides/principles/styling.md +1 -1
  143. package/exports/input-datepicker.js +0 -1
  144. package/exports/overlays.js +1 -1
  145. package/exports/types/overlays.ts +1 -0
  146. package/package.json +2 -1
  147. package/components/input-datepicker/src/LionCalendarOverlayFrame.js +0 -125
  148. package/components/overlays/src/globalOverlaysStyle.js +0 -139
  149. package/dist-types/components/input-datepicker/src/LionCalendarOverlayFrame.d.ts +0 -10
  150. package/dist-types/components/input-datepicker/src/LionCalendarOverlayFrame.d.ts.map +0 -1
  151. package/dist-types/components/overlays/src/globalOverlaysStyle.d.ts +0 -2
  152. package/dist-types/components/overlays/src/globalOverlaysStyle.d.ts.map +0 -1
  153. package/dist-types/exports/define/lion-calendar-overlay-frame.d.ts +0 -2
  154. package/dist-types/exports/define/lion-calendar-overlay-frame.d.ts.map +0 -1
  155. package/docs/fundamentals/systems/overlays/assets/demo-overlay-system.js +0 -42
  156. package/docs/fundamentals/systems/overlays/form-integration.md +0 -65
  157. package/docs/fundamentals/systems/overlays/scope.md +0 -176
  158. package/exports/define/lion-calendar-overlay-frame.js +0 -3
@@ -11,7 +11,7 @@ import {
11
11
  import sinon from 'sinon';
12
12
  import { OverlayController, overlays } from '@lion/ui/overlays.js';
13
13
  import { mimicClick } from '@lion/ui/overlays-test-helpers.js';
14
-
14
+ import { overlayShadowDomStyle } from '../src/overlayShadowDomStyle.js';
15
15
  import { keyCodes } from '../src/utils/key-codes.js';
16
16
  import { simulateTab } from '../src/utils/simulate-tab.js';
17
17
 
@@ -20,6 +20,33 @@ import { simulateTab } from '../src/utils/simulate-tab.js';
20
20
  * @typedef {import('../types/OverlayConfig.js').ViewportPlacement} ViewportPlacement
21
21
  */
22
22
 
23
+ const wrappingDialogNodeStyle = 'display: none; z-index: 9999;';
24
+
25
+ /**
26
+ * Returns element that adopts stylesheet
27
+ * @param {Element} shadowOrBodyEl
28
+ * @returns {ShadowRoot}
29
+ */
30
+ function getRootNodeOrBodyElThatAdoptsStylesheet(shadowOrBodyEl) {
31
+ const rootNode = /** @type {* & DocumentOrShadowRoot} */ (shadowOrBodyEl.getRootNode());
32
+ if (rootNode === document) {
33
+ // @ts-ignore
34
+ return document.body;
35
+ }
36
+ return rootNode;
37
+ }
38
+
39
+ /**
40
+ * Make sure that all browsers serialize html in a similar way
41
+ * (Firefox tends to output empty style attrs)
42
+ * @param {HTMLElement} node
43
+ */
44
+ function normalizeOverlayContentWapper(node) {
45
+ if (node.hasAttribute('style') && !node.style.cssText) {
46
+ node.removeAttribute('style');
47
+ }
48
+ }
49
+
23
50
  /**
24
51
  * @param {OverlayController} overlayControllerEl
25
52
  */
@@ -66,7 +93,56 @@ describe('OverlayController', () => {
66
93
  ...withGlobalTestConfig(),
67
94
  });
68
95
  expect(ctrl.content).not.to.be.undefined;
69
- expect(ctrl.contentNode.parentElement).to.equal(ctrl.content);
96
+ expect(ctrl.contentNode.parentElement).to.equal(ctrl.contentWrapperNode);
97
+ });
98
+
99
+ describe('Stylesheets', () => {
100
+ it('adds a stylesheet to the body when contentWrapper is located there', async () => {
101
+ new OverlayController({
102
+ ...withLocalTestConfig(),
103
+ });
104
+ // @ts-ignore
105
+ if (document.body.adoptedStyleSheets) {
106
+ // @ts-ignore
107
+ expect(document.body.adoptedStyleSheets).to.include(overlayShadowDomStyle.styleSheet);
108
+ }
109
+ });
110
+
111
+ it('adds a stylesheet to the shadowRoot when contentWrappeNode is located there', async () => {
112
+ const contentNode = /** @type {HTMLElement} */ (await fixture('<div>contentful</div>'));
113
+ const shadowHost = document.createElement('div');
114
+ shadowHost.attachShadow({ mode: 'open' });
115
+ /** @type {ShadowRoot} */ (shadowHost.shadowRoot).innerHTML = `<slot></slot>`;
116
+ shadowHost.appendChild(contentNode);
117
+ document.body.appendChild(shadowHost);
118
+ const ctrl = new OverlayController({
119
+ ...withLocalTestConfig(),
120
+ contentNode,
121
+ });
122
+
123
+ const rootNodeOrBody = getRootNodeOrBodyElThatAdoptsStylesheet(ctrl.contentWrapperNode);
124
+ expect(rootNodeOrBody).to.not.equal(document.body);
125
+
126
+ if (rootNodeOrBody.adoptedStyleSheets) {
127
+ expect(rootNodeOrBody.adoptedStyleSheets).to.include(overlayShadowDomStyle.styleSheet);
128
+ }
129
+ document.body.removeChild(shadowHost);
130
+ });
131
+
132
+ it('does not add same stylesheet twice', async () => {
133
+ // @ts-ignore
134
+ if (!document.body.adoptedStyleSheets) {
135
+ return;
136
+ }
137
+
138
+ new OverlayController({ ...withLocalTestConfig() });
139
+ // @ts-ignore
140
+ const amountOfStylesheetsAfterOneInit = document.body.adoptedStyleSheets.length;
141
+
142
+ new OverlayController({ ...withLocalTestConfig() });
143
+ // @ts-ignore
144
+ expect(document.body.adoptedStyleSheets.length).to.equal(amountOfStylesheetsAfterOneInit);
145
+ });
70
146
  });
71
147
 
72
148
  describe('Z-index on local overlays', () => {
@@ -106,17 +182,21 @@ describe('OverlayController', () => {
106
182
  contentNode: await createZNode('auto', { mode: 'global' }),
107
183
  });
108
184
  await ctrl.show();
109
- expect(ctrl.content.style.zIndex).to.equal('1');
185
+ // @ts-expect-error find out why config would/could be undfined
186
+ expect(ctrl.content.style.zIndex).to.equal(`${ctrl.config.zIndex + 1}`);
110
187
  ctrl.updateConfig({ contentNode: await createZNode('auto', { mode: 'inline' }) });
111
188
  await ctrl.show();
112
- expect(ctrl.content.style.zIndex).to.equal('1');
189
+ // @ts-expect-error find out why config would/could be undfined
190
+ expect(ctrl.content.style.zIndex).to.equal(`${ctrl.config.zIndex + 1}`);
113
191
 
114
192
  ctrl.updateConfig({ contentNode: await createZNode('0', { mode: 'global' }) });
115
193
  await ctrl.show();
116
- expect(ctrl.content.style.zIndex).to.equal('1');
194
+ // @ts-expect-error find out why config would/could be undfined
195
+ expect(ctrl.content.style.zIndex).to.equal(`${ctrl.config.zIndex + 1}`);
117
196
  ctrl.updateConfig({ contentNode: await createZNode('0', { mode: 'inline' }) });
118
197
  await ctrl.show();
119
- expect(ctrl.content.style.zIndex).to.equal('1');
198
+ // @ts-expect-error find out why config would/could be undfined
199
+ expect(ctrl.content.style.zIndex).to.equal(`${ctrl.config.zIndex + 1}`);
120
200
  });
121
201
 
122
202
  it.skip("doesn't set a z-index when contentNode already has >= 1", async () => {
@@ -147,42 +227,7 @@ describe('OverlayController', () => {
147
227
  });
148
228
  });
149
229
 
150
- describe('Render target', () => {
151
- it('creates global target for placement mode "global"', async () => {
152
- const ctrl = new OverlayController({
153
- ...withGlobalTestConfig(),
154
- });
155
- const { renderTarget } = getProtectedMembers(ctrl);
156
- expect(renderTarget).to.equal(overlays.globalRootNode);
157
- });
158
-
159
- it.skip('creates local target next to sibling for placement mode "local"', async () => {
160
- const ctrl = new OverlayController({
161
- ...withLocalTestConfig(),
162
- invokerNode: /** @type {HTMLElement} */ (await fixture(html`<button>Invoker</button>`)),
163
- });
164
- const { renderTarget } = getProtectedMembers(ctrl);
165
- expect(renderTarget).to.be.undefined;
166
- expect(ctrl.content).to.equal(ctrl.invokerNode?.nextElementSibling);
167
- });
168
-
169
- it('keeps local target for placement mode "local" when already connected', async () => {
170
- const parentNode = /** @type {HTMLElement} */ (
171
- await fixture(html`
172
- <div id="parent">
173
- <div id="content">Content</div>
174
- </div>
175
- `)
176
- );
177
- const contentNode = /** @type {HTMLElement} */ (parentNode.querySelector('#content'));
178
- const ctrl = new OverlayController({
179
- ...withLocalTestConfig(),
180
- contentNode,
181
- });
182
- const { renderTarget } = getProtectedMembers(ctrl);
183
- expect(renderTarget).to.equal(parentNode);
184
- });
185
-
230
+ describe('Offline content', () => {
186
231
  it('throws when passing a content node that was created "offline"', async () => {
187
232
  const contentNode = document.createElement('div');
188
233
  const createOverlayController = () => {
@@ -197,113 +242,250 @@ describe('OverlayController', () => {
197
242
  });
198
243
 
199
244
  it('succeeds when passing a content node that was created "online"', async () => {
200
- const contentNode = document.createElement('div');
201
- document.body.appendChild(contentNode);
245
+ const contentNode = /** @type {HTMLElement} */ (fixtureSync('<div>'));
202
246
  const overlay = new OverlayController({
203
247
  ...withLocalTestConfig(),
204
248
  contentNode,
205
249
  });
206
- const { renderTarget } = getProtectedMembers(overlay);
207
-
208
250
  expect(overlay.contentNode.isConnected).to.be.true;
209
- expect(renderTarget).to.not.be.undefined;
210
251
  });
211
252
  });
212
253
  });
213
254
 
214
255
  // TODO: Add teardown feature tests
215
- describe('Teardown', () => {
216
- it('removes the contentWrapperNode from global rootnode upon teardown', async () => {
217
- const ctrl = new OverlayController({
218
- ...withGlobalTestConfig(),
219
- });
220
-
221
- expect(ctrl.manager.globalRootNode.children.length).to.equal(1);
222
- ctrl.teardown();
223
- expect(ctrl.manager.globalRootNode.children.length).to.equal(0);
224
- });
256
+ describe('Teardown', () => {});
225
257
 
226
- it('[global] restores contentNode if it was/is a projected node', async () => {
227
- const shadowHost = document.createElement('div');
228
- shadowHost.id = 'shadowHost';
229
- shadowHost.attachShadow({ mode: 'open' });
230
- /** @type {ShadowRoot} */
231
- (shadowHost.shadowRoot).innerHTML = `
232
- <div id="contentWrapperNode">
233
- <slot name="contentNode"></slot>
234
- <my-arrow></my-arrow>
235
- </div>
236
- `;
237
- const contentNode = document.createElement('div');
238
- contentNode.slot = 'contentNode';
239
- shadowHost.appendChild(contentNode);
258
+ describe('Node Configuration', () => {
259
+ describe('Content', async () => {
260
+ it('accepts a .contentNode for displaying content of the overlay', async () => {
261
+ const myContentNode = /** @type {HTMLElement} */ (fixtureSync('<p>direct node</p>'));
262
+ const ctrl = new OverlayController({
263
+ ...withGlobalTestConfig(),
264
+ contentNode: myContentNode,
265
+ });
266
+ expect(ctrl.contentNode).to.have.trimmed.text('direct node');
267
+ expect(ctrl.contentNode).to.equal(myContentNode);
268
+ });
269
+
270
+ describe('Embedded dom structure', async () => {
271
+ describe('When projected in shadow dom', async () => {
272
+ it('wraps a .contentWrapperNode for style application and a <dialog role="none"> for top layer paints', async () => {
273
+ const tagString = defineCE(
274
+ class extends HTMLElement {
275
+ constructor() {
276
+ super();
277
+ this.attachShadow({ mode: 'open' });
278
+ }
279
+
280
+ connectedCallback() {
281
+ /** @type {ShadowRoot} */
282
+ (this.shadowRoot).innerHTML = '<slot name="content"></slot>';
283
+ this.innerHTML = '<div slot="content">projected</div>';
284
+ }
285
+ },
286
+ );
287
+
288
+ const el = /** @type {HTMLElement} */ (fixtureSync(`<${tagString}></${tagString}>`));
289
+ const myContentNode = /** @type {HTMLElement} */ (el.querySelector('[slot=content]'));
290
+ const ctrl = new OverlayController({
291
+ ...withGlobalTestConfig(),
292
+ contentNode: myContentNode,
293
+ });
294
+
295
+ expect(ctrl.contentNode.assignedSlot?.parentElement).to.equal(ctrl.contentWrapperNode);
296
+ expect(ctrl.contentWrapperNode.parentElement?.tagName).to.equal('DIALOG');
297
+
298
+ normalizeOverlayContentWapper(ctrl.contentWrapperNode);
299
+
300
+ // The total dom structure created...
301
+ expect(el).shadowDom.to.equal(`
302
+ <dialog data-overlay-outer-wrapper="" open="" role="none" style="${wrappingDialogNodeStyle}">
303
+ <div data-id="content-wrapper">
304
+ <slot name="content">
305
+ </slot>
306
+ </div>
307
+ </dialog>
308
+ `);
309
+
310
+ expect(el).lightDom.to.equal(`<div slot="content">projected</div>`);
311
+ });
312
+ });
240
313
 
241
- const wrapper = /** @type {HTMLElement} */ (await fixture('<div id="wrapper"></div>'));
242
- // Ensure the contentNode is connected to DOM
243
- wrapper.appendChild(shadowHost);
314
+ describe('When in light dom', async () => {
315
+ it('wraps a .contentWrapperNode for style application and a <dialog role="none"> for top layer paints', async () => {
316
+ const el = fixtureSync('<section><div id="content">non projected</div></section>');
317
+ const myContentNode = /** @type {HTMLElement} */ (el.querySelector('#content'));
318
+ const ctrl = new OverlayController({
319
+ ...withGlobalTestConfig(),
320
+ contentNode: myContentNode,
321
+ });
322
+ expect(ctrl.contentNode.parentElement).to.equal(ctrl.contentWrapperNode);
323
+ expect(ctrl.contentWrapperNode.parentElement?.tagName).to.equal('DIALOG');
324
+
325
+ normalizeOverlayContentWapper(ctrl.contentWrapperNode);
326
+
327
+ // The total dom structure created...
328
+ expect(el).lightDom.to.equal(`
329
+ <dialog data-overlay-outer-wrapper="" open="" role="none" style="${wrappingDialogNodeStyle}">
330
+ <div data-id="content-wrapper">
331
+ <div id="content">non projected</div>
332
+ </div>
333
+ </dialog>
334
+ `);
335
+ });
336
+ });
244
337
 
245
- // has one child = <div slot="contentNode"></div>
246
- expect(shadowHost.children.length).to.equal(1);
338
+ describe('When .contenWrapperNode provided', async () => {
339
+ it('keeps the .contentWrapperNode for style application and wraps a <dialog role="none"> for top layer paints', async () => {
340
+ const tagString = defineCE(
341
+ class extends HTMLElement {
342
+ constructor() {
343
+ super();
344
+ this.attachShadow({ mode: 'open' });
345
+ }
346
+
347
+ connectedCallback() {
348
+ /** @type {ShadowRoot} */
349
+ (this.shadowRoot).innerHTML = '<div><slot name="content"></slot></div>';
350
+ this.innerHTML = '<div slot="content">projected</div>';
351
+ }
352
+ },
353
+ );
354
+
355
+ const el = /** @type {HTMLElement} */ (fixtureSync(`<${tagString}></${tagString}>`));
356
+ const myContentNode = /** @type {HTMLElement} */ (el.querySelector('[slot=content]'));
357
+ const myContentWrapper = /** @type {HTMLElement} */ (
358
+ el.shadowRoot?.querySelector('div')
359
+ );
360
+ const ctrl = new OverlayController({
361
+ ...withGlobalTestConfig(),
362
+ contentNode: myContentNode,
363
+ contentWrapperNode: myContentWrapper,
364
+ });
365
+
366
+ normalizeOverlayContentWapper(ctrl.contentWrapperNode);
367
+
368
+ // The total dom structure created...
369
+ expect(el).shadowDom.to.equal(`
370
+ <dialog data-overlay-outer-wrapper="" open="" role="none" style="${wrappingDialogNodeStyle}">
371
+ <div data-id="content-wrapper">
372
+ <slot name="content"></slot>
373
+ </div>
374
+ </dialog>
375
+ `);
376
+ });
247
377
 
248
- const ctrl = new OverlayController({
249
- ...withLocalTestConfig(),
250
- placementMode: 'global',
251
- contentNode,
252
- contentWrapperNode: shadowHost,
378
+ it("uses the .contentWrapperNode as container for Popper's arrow", async () => {
379
+ const tagString = defineCE(
380
+ class extends HTMLElement {
381
+ constructor() {
382
+ super();
383
+ this.attachShadow({ mode: 'open' });
384
+ }
385
+
386
+ connectedCallback() {
387
+ /** @type {ShadowRoot} */
388
+ (this.shadowRoot).innerHTML = `
389
+ <div>
390
+ <div id="arrow"></div>
391
+ <slot name="content"></slot>
392
+ </div>`;
393
+ this.innerHTML = '<div slot="content">projected</div>';
394
+ }
395
+ },
396
+ );
397
+
398
+ const el = /** @type {HTMLElement} */ (fixtureSync(`<${tagString}></${tagString}>`));
399
+ const myContentNode = /** @type {HTMLElement} */ (el.querySelector('[slot=content]'));
400
+ const myContentWrapper = /** @type {HTMLElement} */ (
401
+ el.shadowRoot?.querySelector('div')
402
+ );
403
+ const ctrl = new OverlayController({
404
+ ...withLocalTestConfig(),
405
+ contentNode: myContentNode,
406
+ contentWrapperNode: myContentWrapper,
407
+ });
408
+
409
+ normalizeOverlayContentWapper(ctrl.contentWrapperNode);
410
+
411
+ // The total dom structure created...
412
+ expect(el).shadowDom.to.equal(`
413
+ <dialog data-overlay-outer-wrapper="" open="" role="none" style="${wrappingDialogNodeStyle}">
414
+ <div data-id="content-wrapper">
415
+ <div id="arrow"></div>
416
+ <slot name="content"></slot>
417
+ </div>
418
+ </dialog>
419
+ `);
420
+ });
421
+ });
253
422
  });
254
-
255
- // has no children as content gets moved to the body
256
- expect(shadowHost.children.length).to.equal(0);
257
- ctrl.teardown();
258
-
259
- // restores original light dom in teardown
260
- expect(shadowHost.children.length).to.equal(1);
261
423
  });
262
- });
263
424
 
264
- describe('Node Configuration', () => {
265
- it('accepts an .contentNode<Node> to directly set content', async () => {
266
- const ctrl = new OverlayController({
267
- ...withGlobalTestConfig(),
268
- contentNode: /** @type {HTMLElement} */ (await fixture('<p>direct node</p>')),
425
+ describe('Invoker / Reference', async () => {
426
+ it('accepts a .invokerNode to directly set invoker', async () => {
427
+ const myInvokerNode = /** @type {HTMLElement} */ (fixtureSync('<button>invoke</button>'));
428
+ const ctrl = new OverlayController({
429
+ ...withGlobalTestConfig(),
430
+ invokerNode: myInvokerNode,
431
+ });
432
+ expect(ctrl.invokerNode).to.equal(myInvokerNode);
433
+ expect(ctrl.referenceNode).to.equal(undefined);
269
434
  });
270
- expect(ctrl.contentNode).to.have.trimmed.text('direct node');
271
- });
272
435
 
273
- it('accepts an .invokerNode<Node> to directly set invoker', async () => {
274
- const ctrl = new OverlayController({
275
- ...withGlobalTestConfig(),
276
- invokerNode: /** @type {HTMLElement} */ (await fixture('<button>invoke</button>')),
436
+ it('accepts a .referenceNode as positioning anchor different from .invokerNode', async () => {
437
+ const myInvokerNode = /** @type {HTMLElement} */ (fixtureSync('<button>invoke</button>'));
438
+ const myReferenceNode = /** @type {HTMLElement} */ (fixtureSync('<div>anchor</div>'));
439
+ const ctrl = new OverlayController({
440
+ ...withGlobalTestConfig(),
441
+ invokerNode: myInvokerNode,
442
+ referenceNode: myReferenceNode,
443
+ });
444
+ expect(ctrl.referenceNode).to.equal(myReferenceNode);
445
+ expect(ctrl.invokerNode).to.not.equal(ctrl.referenceNode);
277
446
  });
278
- expect(ctrl.invokerNode).to.have.trimmed.text('invoke');
279
447
  });
280
448
 
281
- describe('When contentWrapperNode projects contentNode', () => {
282
- it('recognizes projected contentNode', async () => {
283
- const shadowHost = document.createElement('div');
284
- shadowHost.attachShadow({ mode: 'open' });
285
- /** @type {ShadowRoot} */ (shadowHost.shadowRoot).innerHTML = `
286
- <div id="contentWrapperNode">
287
- <slot name="contentNode"></slot>
288
- <my-arrow></my-arrow>
289
- </div>
290
- `;
291
- const contentNode = document.createElement('div');
292
- contentNode.slot = 'contentNode';
293
- shadowHost.appendChild(contentNode);
449
+ describe('Backdrop', () => {
450
+ it('creates a .backdropNode inside <dialog> for guaranteed top layer paints and positioning opportunities', async () => {
451
+ const tagString = defineCE(
452
+ class extends HTMLElement {
453
+ constructor() {
454
+ super();
455
+ this.attachShadow({ mode: 'open' });
456
+ }
294
457
 
295
- // Ensure the contentNode is connected to DOM
296
- document.body.appendChild(shadowHost);
458
+ connectedCallback() {
459
+ /** @type {ShadowRoot} */
460
+ (this.shadowRoot).innerHTML = '<slot name="content"></slot>';
461
+ this.innerHTML = '<div slot="content">projected</div>';
462
+ }
463
+ },
464
+ );
465
+
466
+ const el = /** @type {HTMLElement} */ (fixtureSync(`<${tagString}></${tagString}>`));
467
+ const myContentNode = /** @type {HTMLElement} */ (el.querySelector('[slot=content]'));
297
468
 
298
469
  const ctrl = new OverlayController({
299
- ...withLocalTestConfig(),
300
- contentNode,
301
- contentWrapperNode: /** @type {HTMLElement} */ (
302
- /** @type {ShadowRoot} */ (shadowHost.shadowRoot).getElementById('contentWrapperNode')
303
- ),
470
+ ...withGlobalTestConfig(),
471
+ contentNode: myContentNode,
472
+ hasBackdrop: true,
304
473
  });
305
474
 
306
- expect(ctrl.__isContentNodeProjected).to.be.true;
475
+ normalizeOverlayContentWapper(ctrl.contentWrapperNode);
476
+
477
+ // The total dom structure created...
478
+ expect(el).shadowDom.to.equal(
479
+ `
480
+ <dialog data-overlay-outer-wrapper="" open="" role="none" style="${wrappingDialogNodeStyle}">
481
+ <div class="overlays__backdrop"></div>
482
+ <div data-id="content-wrapper">
483
+ <slot name="content">
484
+ </slot>
485
+ </div>
486
+ </dialog>
487
+ `,
488
+ );
307
489
  });
308
490
  });
309
491
 
@@ -446,6 +628,18 @@ describe('OverlayController', () => {
446
628
  document.dispatchEvent(new KeyboardEvent('keyup', { key: 'Escape' }));
447
629
  expect(ctrl.isShown).to.be.true;
448
630
  });
631
+
632
+ it('does not hide when [escape] is pressed with modal <dialog> and "hidesOnEsc" is false', async () => {
633
+ const ctrl = new OverlayController({
634
+ ...withGlobalTestConfig(),
635
+ trapsKeyboardFocus: true,
636
+ hidesOnEsc: false,
637
+ });
638
+ await ctrl.show();
639
+ ctrl.contentNode.dispatchEvent(new KeyboardEvent('keyup', { key: 'Escape' }));
640
+ await aTimeout(0);
641
+ expect(ctrl.isShown).to.be.true;
642
+ });
449
643
  });
450
644
 
451
645
  describe('hidesOnOutsideEsc', () => {
@@ -760,6 +954,35 @@ describe('OverlayController', () => {
760
954
  expect(document.activeElement).to.equal(input);
761
955
  });
762
956
 
957
+ it('supports elementToFocusAfterHide option when shadowRoot involved involved', async () => {
958
+ const input = /** @type {HTMLElement} */ (await fixture('<input />'));
959
+ const contentNode = /** @type {HTMLElement} */ (
960
+ await fixture('<div><textarea></textarea></div>')
961
+ );
962
+
963
+ const shadowHost = document.createElement('div');
964
+ shadowHost.attachShadow({ mode: 'open' });
965
+ /** @type {ShadowRoot} */ (shadowHost.shadowRoot).innerHTML = `<slot></slot>`;
966
+ shadowHost.appendChild(contentNode);
967
+ document.body.appendChild(shadowHost);
968
+
969
+ const ctrl = new OverlayController({
970
+ ...withGlobalTestConfig(),
971
+ elementToFocusAfterHide: input,
972
+ contentNode,
973
+ });
974
+
975
+ await ctrl.show();
976
+ const textarea = /** @type {HTMLTextAreaElement} */ (contentNode.querySelector('textarea'));
977
+ textarea.focus();
978
+ expect(document.activeElement).to.equal(textarea);
979
+
980
+ await ctrl.hide();
981
+ expect(document.activeElement).to.equal(input);
982
+
983
+ document.body.removeChild(shadowHost);
984
+ });
985
+
763
986
  it(`only sets focus when outside world didn't take over already`, async () => {
764
987
  const input = /** @type {HTMLElement} */ (await fixture('<input />'));
765
988
  const outsideButton = /** @type {HTMLButtonElement} */ (await fixture('<button></button>'));
@@ -810,10 +1033,10 @@ describe('OverlayController', () => {
810
1033
  });
811
1034
 
812
1035
  await ctrl.show();
813
- expect(getComputedStyle(document.body).overflow).to.equal('hidden');
1036
+ expect(Array.from(document.body.classList)).to.contain('overlays-scroll-lock');
814
1037
 
815
1038
  await ctrl.hide();
816
- expect(getComputedStyle(document.body).overflow).to.equal('visible');
1039
+ expect(Array.from(document.body.classList)).to.not.contain('overlays-scroll-lock');
817
1040
  });
818
1041
 
819
1042
  it('keeps preventing of scrolling when multiple overlays are opened and closed', async () => {
@@ -829,7 +1052,7 @@ describe('OverlayController', () => {
829
1052
  await ctrl0.show();
830
1053
  await ctrl1.show();
831
1054
  await ctrl1.hide();
832
- expect(getComputedStyle(document.body).overflow).to.equal('hidden');
1055
+ expect(Array.from(document.body.classList)).to.contain('overlays-scroll-lock');
833
1056
  });
834
1057
  });
835
1058
 
@@ -856,7 +1079,7 @@ describe('OverlayController', () => {
856
1079
  hasBackdrop: true,
857
1080
  });
858
1081
  await controllerWithBackdrop.show();
859
- expect(controllerWithBackdrop.backdropNode).to.have.class('global-overlays__backdrop');
1082
+ expect(controllerWithBackdrop.backdropNode).to.have.class('overlays__backdrop');
860
1083
  });
861
1084
 
862
1085
  it('reenables the backdrop when shown/hidden/shown', async () => {
@@ -865,10 +1088,10 @@ describe('OverlayController', () => {
865
1088
  hasBackdrop: true,
866
1089
  });
867
1090
  await ctrl.show();
868
- expect(ctrl.backdropNode).to.have.class('global-overlays__backdrop');
1091
+ expect(ctrl.backdropNode).to.have.class('overlays__backdrop');
869
1092
  await ctrl.hide();
870
1093
  await ctrl.show();
871
- expect(ctrl.backdropNode).to.have.class('global-overlays__backdrop');
1094
+ expect(ctrl.backdropNode).to.have.class('overlays__backdrop');
872
1095
  });
873
1096
 
874
1097
  it('adds and stacks backdrops if .hasBackdrop is enabled', async () => {
@@ -877,14 +1100,14 @@ describe('OverlayController', () => {
877
1100
  hasBackdrop: true,
878
1101
  });
879
1102
  await ctrl0.show();
880
- expect(ctrl0.backdropNode).to.have.class('global-overlays__backdrop');
1103
+ expect(ctrl0.backdropNode).to.have.class('overlays__backdrop');
881
1104
 
882
1105
  const ctrl1 = new OverlayController({
883
1106
  ...withGlobalTestConfig(),
884
1107
  hasBackdrop: false,
885
1108
  });
886
1109
  await ctrl1.show();
887
- expect(ctrl0.backdropNode).to.have.class('global-overlays__backdrop');
1110
+ expect(ctrl0.backdropNode).to.have.class('overlays__backdrop');
888
1111
  expect(ctrl1.backdropNode).to.be.undefined;
889
1112
 
890
1113
  const ctrl2 = new OverlayController({
@@ -893,9 +1116,9 @@ describe('OverlayController', () => {
893
1116
  });
894
1117
  await ctrl2.show();
895
1118
 
896
- expect(ctrl0.backdropNode).to.have.class('global-overlays__backdrop');
1119
+ expect(ctrl0.backdropNode).to.have.class('overlays__backdrop');
897
1120
  expect(ctrl1.backdropNode).to.be.undefined;
898
- expect(ctrl2.backdropNode).to.have.class('global-overlays__backdrop');
1121
+ expect(ctrl2.backdropNode).to.have.class('overlays__backdrop');
899
1122
  });
900
1123
  });
901
1124
 
@@ -1003,24 +1226,24 @@ describe('OverlayController', () => {
1003
1226
  await ctrl0.show();
1004
1227
  await ctrl1.show();
1005
1228
  await ctrl2.show(); // blocking
1006
- expect(ctrl0.content).to.not.be.displayed;
1007
- expect(ctrl1.content).to.not.be.displayed;
1008
- expect(ctrl2.content).to.be.displayed;
1229
+ expect(ctrl0.__wrappingDialogNode).to.not.be.displayed;
1230
+ expect(ctrl1.__wrappingDialogNode).to.not.be.displayed;
1231
+ expect(ctrl2.__wrappingDialogNode).to.be.displayed;
1009
1232
 
1010
1233
  await ctrl3.show();
1011
1234
  await ctrl3._showComplete;
1012
- expect(ctrl3.content).to.be.displayed;
1235
+ expect(ctrl3.__wrappingDialogNode).to.be.displayed;
1013
1236
 
1014
1237
  await ctrl2.hide();
1015
1238
  await ctrl2._hideComplete;
1016
- expect(ctrl0.content).to.be.displayed;
1017
- expect(ctrl1.content).to.be.displayed;
1239
+ expect(ctrl0.__wrappingDialogNode).to.be.displayed;
1240
+ expect(ctrl1.__wrappingDialogNode).to.be.displayed;
1018
1241
 
1019
1242
  await ctrl2.show(); // blocking
1020
- expect(ctrl0.content).to.not.be.displayed;
1021
- expect(ctrl1.content).to.not.be.displayed;
1022
- expect(ctrl2.content).to.be.displayed;
1023
- expect(ctrl3.content).to.not.be.displayed;
1243
+ expect(ctrl0.__wrappingDialogNode).to.not.be.displayed;
1244
+ expect(ctrl1.__wrappingDialogNode).to.not.be.displayed;
1245
+ expect(ctrl2.__wrappingDialogNode).to.be.displayed;
1246
+ expect(ctrl3.__wrappingDialogNode).to.not.be.displayed;
1024
1247
  });
1025
1248
 
1026
1249
  it('keeps backdrop status when used in combination with blocking', async () => {
@@ -1197,11 +1420,11 @@ describe('OverlayController', () => {
1197
1420
 
1198
1421
  ctrl.hide();
1199
1422
 
1200
- expect(getComputedStyle(ctrl.contentWrapperNode).display).to.equal('block');
1423
+ expect(getComputedStyle(ctrl.content).display).to.equal('block');
1201
1424
  setTimeout(() => {
1202
1425
  hideTransitionFinished();
1203
1426
  setTimeout(() => {
1204
- expect(getComputedStyle(ctrl.contentWrapperNode).display).to.equal('none');
1427
+ expect(getComputedStyle(ctrl.content).display).to.equal('none');
1205
1428
  done();
1206
1429
  }, 0);
1207
1430
  }, 0);
@@ -1285,15 +1508,11 @@ describe('OverlayController', () => {
1285
1508
  });
1286
1509
 
1287
1510
  ctrl.show();
1288
- expect(
1289
- ctrl.contentWrapperNode.classList.contains('global-overlays__overlay-container--center'),
1290
- );
1511
+ expect(ctrl.contentWrapperNode.classList.contains('overlays__overlay-container--center'));
1291
1512
  expect(ctrl.isShown).to.be.true;
1292
1513
 
1293
1514
  ctrl.updateConfig({ viewportConfig: { placement: 'top-right' } });
1294
- expect(
1295
- ctrl.contentWrapperNode.classList.contains('global-overlays__overlay-container--top-right'),
1296
- );
1515
+ expect(ctrl.contentWrapperNode.classList.contains('overlays__overlay-container--top-right'));
1297
1516
  expect(ctrl.isShown).to.be.true;
1298
1517
  });
1299
1518
  });
@@ -1379,89 +1598,9 @@ describe('OverlayController', () => {
1379
1598
  expect(properlyInstantiated).to.be.true;
1380
1599
  });
1381
1600
 
1382
- it('adds attributes inert and aria-hidden="true" on all siblings of rootNode if an overlay is shown', async () => {
1383
- const ctrl = new OverlayController({
1384
- ...withGlobalTestConfig(),
1385
- trapsKeyboardFocus: true,
1386
- });
1387
-
1388
- const sibling1 = document.createElement('div');
1389
- const sibling2 = document.createElement('div');
1390
- document.body.insertBefore(sibling1, ctrl.manager.globalRootNode);
1391
- document.body.appendChild(sibling2);
1392
-
1393
- await ctrl.show();
1394
-
1395
- [sibling1, sibling2].forEach(sibling => {
1396
- expect(sibling).to.have.attribute('aria-hidden', 'true');
1397
- expect(sibling).to.have.attribute('inert');
1398
- });
1399
- expect(ctrl.content.hasAttribute('aria-hidden')).to.be.false;
1400
- expect(ctrl.content.hasAttribute('inert')).to.be.false;
1401
-
1402
- await ctrl.hide();
1403
-
1404
- [sibling1, sibling2].forEach(sibling => {
1405
- expect(sibling).to.not.have.attribute('aria-hidden');
1406
- expect(sibling).to.not.have.attribute('inert');
1407
- });
1408
-
1409
- // cleanup
1410
- document.body.removeChild(sibling1);
1411
- document.body.removeChild(sibling2);
1412
- });
1413
-
1414
- /**
1415
- * style.userSelect:
1416
- * - chrome: 'none'
1417
- * - rest: undefined
1418
- *
1419
- * style.pointerEvents:
1420
- * - chrome: auto
1421
- * - IE11: visiblePainted
1422
- */
1423
- it('disables pointer events and selection on inert elements', async () => {
1424
- const ctrl = new OverlayController({
1425
- ...withGlobalTestConfig(),
1426
- trapsKeyboardFocus: true,
1427
- });
1428
-
1429
- // show+hide are needed to create a root node
1430
- await ctrl.show();
1431
- await ctrl.hide();
1432
-
1433
- const sibling1 = document.createElement('div');
1434
- const sibling2 = document.createElement('div');
1435
- document.body.insertBefore(sibling1, ctrl.manager.globalRootNode);
1436
- document.body.appendChild(sibling2);
1437
-
1438
- await ctrl.show();
1439
-
1440
- [sibling1, sibling2].forEach(sibling => {
1441
- expect(window.getComputedStyle(sibling).userSelect).to.be.oneOf(['none', undefined]);
1442
- expect(window.getComputedStyle(sibling).pointerEvents).to.equal('none');
1443
- });
1444
-
1445
- expect(window.getComputedStyle(ctrl.contentNode).userSelect).to.be.oneOf(['auto', undefined]);
1446
- expect(window.getComputedStyle(ctrl.contentNode).pointerEvents).to.be.oneOf([
1447
- 'auto',
1448
- 'visiblePainted',
1449
- ]);
1450
-
1451
- await ctrl.hide();
1452
-
1453
- [sibling1, sibling2].forEach(sibling => {
1454
- expect(window.getComputedStyle(sibling).userSelect).to.be.oneOf(['auto', undefined]);
1455
- expect(window.getComputedStyle(sibling).pointerEvents).to.be.oneOf([
1456
- 'auto',
1457
- 'visiblePainted',
1458
- ]);
1459
- });
1460
-
1461
- // cleanup
1462
- document.body.removeChild(sibling1);
1463
- document.body.removeChild(sibling2);
1464
- });
1601
+ // TODO: check if we covered all functionality. "Inertness" should be handled by the platform with a modal overlay...
1602
+ it.skip('adds attributes inert and aria-hidden="true" on all siblings of rootNode if an overlay is shown', async () => {});
1603
+ it.skip('disables pointer events and selection on inert elements', async () => {});
1465
1604
 
1466
1605
  describe('Tooltip', () => {
1467
1606
  it('adds [aria-describedby] on invoker', async () => {
@@ -1616,47 +1755,6 @@ describe('OverlayController', () => {
1616
1755
  }).to.throw('[OverlayController] You need to provide a .contentNode');
1617
1756
  });
1618
1757
 
1619
- it('throws if contentNodeWrapper is not provided for projected contentNode', async () => {
1620
- const shadowHost = document.createElement('div');
1621
- shadowHost.attachShadow({ mode: 'open' });
1622
- /** @type {ShadowRoot} */ (shadowHost.shadowRoot).innerHTML = `
1623
- <div id="contentWrapperNode">
1624
- <slot name="contentNode"></slot>
1625
- <my-arrow></my-arrow>
1626
- </div>
1627
- `;
1628
- const contentNode = document.createElement('div');
1629
- contentNode.slot = 'contentNode';
1630
- shadowHost.appendChild(contentNode);
1631
-
1632
- // Ensure the contentNode is connected to DOM
1633
- document.body.appendChild(shadowHost);
1634
-
1635
- expect(() => {
1636
- new OverlayController({
1637
- ...withLocalTestConfig(),
1638
- contentNode,
1639
- });
1640
- }).to.throw(
1641
- '[OverlayController] You need to provide a .contentWrapperNode when .contentNode is projected',
1642
- );
1643
- });
1644
-
1645
- it('throws if placementMode is global for a tooltip', async () => {
1646
- const contentNode = document.createElement('div');
1647
- document.body.appendChild(contentNode);
1648
- expect(() => {
1649
- new OverlayController({
1650
- placementMode: 'global',
1651
- contentNode,
1652
- isTooltip: true,
1653
- handlesAccessibility: true,
1654
- });
1655
- }).to.throw(
1656
- '[OverlayController] .isTooltip should be configured with .placementMode "local"',
1657
- );
1658
- });
1659
-
1660
1758
  it('throws if handlesAccessibility is false for a tooltip', async () => {
1661
1759
  const contentNode = document.createElement('div');
1662
1760
  document.body.appendChild(contentNode);