@lion/ui 0.22.0 → 0.23.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.
- package/README.md +35 -0
- package/components/combobox/src/LionCombobox.js +10 -2
- package/components/combobox/test/lion-combobox.test.js +31 -0
- package/components/form-core/src/choice-group/ChoiceGroupMixin.js +7 -0
- package/components/form-core/types/choice-group/ChoiceGroupMixinTypes.ts +5 -0
- package/components/input-amount/src/LionInputAmount.js +17 -6
- package/components/input-amount/src/formatters.js +5 -3
- package/components/input-amount/test/formatters.test.js +88 -74
- package/components/input-amount/test/lion-input-amount.test.js +51 -36
- package/components/input-tel/test/validators.test.js +9 -0
- package/components/listbox/src/ListboxMixin.js +19 -3
- package/components/listbox/types/ListboxMixinTypes.ts +7 -1
- package/components/menu/README.md +360 -0
- package/components/menu/src/InteractiveListMixin.js +867 -0
- package/components/menu/src/LionMenu.js +436 -0
- package/components/menu/src/MoreButtonMenuMixin.js +295 -0
- package/components/menu/src/MultiLevelListMixin.js +312 -0
- package/components/menu/src/utils/isInView.js +26 -0
- package/components/menu/src/utils/listItemInteractions.js +124 -0
- package/components/menu/test/InteractiveListMixin.test.js +3 -0
- package/components/menu/test/MoreButtonMenuMixin.test.js +4 -0
- package/components/menu/test/MultiLevelListMixin.test.js +3 -0
- package/components/menu/test/lion-menu-interactions.test.js +3 -0
- package/components/menu/test/lion-menu.test.js +14 -0
- package/components/menu/test-helpers/mimicKeyPress.js +9 -0
- package/components/menu/test-suites/InteractiveListMixin.suite.js +537 -0
- package/components/menu/test-suites/LionMenu.suite.js +114 -0
- package/components/menu/test-suites/LionMenuInteractions.suite.js +583 -0
- package/components/menu/test-suites/MoreButtonMenuMixin.suite.js +372 -0
- package/components/menu/test-suites/MultiLevelListMixin.suite.js +309 -0
- package/components/menu/types/InteractiveListMixinTypes.ts +126 -0
- package/components/menu/types/MoreButtonMenuMixinTypes.ts +51 -0
- package/components/menu/types/MultiLevelListMixinTypes.ts +28 -0
- package/components/menu/types/OverlayWithListInvokerMixinTypes.ts +61 -0
- package/components/overlays/NEXT.md +49 -0
- package/components/overlays/src/OverlayController.js +304 -125
- package/components/overlays/src/OverlayMixin.js +81 -17
- package/components/overlays/src/utils/adopt-styles.js +1 -1
- package/components/overlays/src/utils/is-equal-config.js +15 -6
- package/components/overlays/test/OverlayController.test.js +223 -25
- package/components/overlays/test-suites/OverlayMixin.suite.js +8 -8
- package/components/overlays/types/ArrowMixinTypes.ts +1 -3
- package/components/overlays/types/OverlayConfig.ts +20 -5
- package/components/overlays/types/OverlayMixinTypes.ts +2 -0
- package/components/select-rich/src/LionSelectRich.js +12 -0
- package/components/select-rich/test/lion-select-rich-interaction.test.js +53 -0
- package/components/select-rich/test/lion-select-rich-upgrade.test.js +30 -0
- package/custom-elements.json +3120 -149
- package/dist-types/components/combobox/src/LionCombobox.d.ts +1 -1
- package/dist-types/components/combobox/src/LionCombobox.d.ts.map +1 -1
- package/dist-types/components/dialog/src/LionDialog.d.ts +6 -2
- package/dist-types/components/dialog/src/LionDialog.d.ts.map +1 -1
- package/dist-types/components/form-core/src/choice-group/ChoiceGroupMixin.d.ts.map +1 -1
- package/dist-types/components/form-core/types/choice-group/ChoiceGroupMixinTypes.d.ts +5 -0
- package/dist-types/components/form-core/types/choice-group/ChoiceGroupMixinTypes.d.ts.map +1 -1
- package/dist-types/components/input-amount/src/LionInputAmount.d.ts +3 -1
- package/dist-types/components/input-amount/src/LionInputAmount.d.ts.map +1 -1
- package/dist-types/components/input-amount/src/formatters.d.ts +6 -4
- package/dist-types/components/input-amount/src/formatters.d.ts.map +1 -1
- package/dist-types/components/input-datepicker/src/LionInputDatepicker.d.ts +1 -1
- package/dist-types/components/listbox/src/ListboxMixin.d.ts.map +1 -1
- package/dist-types/components/listbox/types/ListboxMixinTypes.d.ts +7 -1
- package/dist-types/components/listbox/types/ListboxMixinTypes.d.ts.map +1 -1
- package/dist-types/components/menu/src/InteractiveListMixin.d.ts +35 -0
- package/dist-types/components/menu/src/InteractiveListMixin.d.ts.map +1 -0
- package/dist-types/components/menu/src/LionMenu.d.ts +129 -0
- package/dist-types/components/menu/src/LionMenu.d.ts.map +1 -0
- package/dist-types/components/menu/src/MoreButtonMenuMixin.d.ts +8 -0
- package/dist-types/components/menu/src/MoreButtonMenuMixin.d.ts.map +1 -0
- package/dist-types/components/menu/src/MultiLevelListMixin.d.ts +7 -0
- package/dist-types/components/menu/src/MultiLevelListMixin.d.ts.map +1 -0
- package/dist-types/components/menu/src/utils/isInView.d.ts +9 -0
- package/dist-types/components/menu/src/utils/isInView.d.ts.map +1 -0
- package/dist-types/components/menu/src/utils/listItemInteractions.d.ts +48 -0
- package/dist-types/components/menu/src/utils/listItemInteractions.d.ts.map +1 -0
- package/dist-types/components/menu/test/InteractiveListMixin.test.d.ts +2 -0
- package/dist-types/components/menu/test/InteractiveListMixin.test.d.ts.map +1 -0
- package/dist-types/components/menu/test/MoreButtonMenuMixin.test.d.ts +2 -0
- package/dist-types/components/menu/test/MoreButtonMenuMixin.test.d.ts.map +1 -0
- package/dist-types/components/menu/test/MultiLevelListMixin.test.d.ts +2 -0
- package/dist-types/components/menu/test/MultiLevelListMixin.test.d.ts.map +1 -0
- package/dist-types/components/menu/test/lion-menu-interactions.test.d.ts +2 -0
- package/dist-types/components/menu/test/lion-menu-interactions.test.d.ts.map +1 -0
- package/dist-types/components/menu/test/lion-menu.test.d.ts +2 -0
- package/dist-types/components/menu/test/lion-menu.test.d.ts.map +1 -0
- package/dist-types/components/menu/test-helpers/mimicKeyPress.d.ts +7 -0
- package/dist-types/components/menu/test-helpers/mimicKeyPress.d.ts.map +1 -0
- package/dist-types/components/menu/test-suites/InteractiveListMixin.suite.d.ts +11 -0
- package/dist-types/components/menu/test-suites/InteractiveListMixin.suite.d.ts.map +1 -0
- package/dist-types/components/menu/test-suites/LionMenu.suite.d.ts +9 -0
- package/dist-types/components/menu/test-suites/LionMenu.suite.d.ts.map +1 -0
- package/dist-types/components/menu/test-suites/LionMenuInteractions.suite.d.ts +5 -0
- package/dist-types/components/menu/test-suites/LionMenuInteractions.suite.d.ts.map +1 -0
- package/dist-types/components/menu/test-suites/MoreButtonMenuMixin.suite.d.ts +11 -0
- package/dist-types/components/menu/test-suites/MoreButtonMenuMixin.suite.d.ts.map +1 -0
- package/dist-types/components/menu/test-suites/MultiLevelListMixin.suite.d.ts +11 -0
- package/dist-types/components/menu/test-suites/MultiLevelListMixin.suite.d.ts.map +1 -0
- package/dist-types/components/menu/types/InteractiveListMixinTypes.d.ts +72 -0
- package/dist-types/components/menu/types/InteractiveListMixinTypes.d.ts.map +1 -0
- package/dist-types/components/menu/types/MoreButtonMenuMixinTypes.d.ts +30 -0
- package/dist-types/components/menu/types/MoreButtonMenuMixinTypes.d.ts.map +1 -0
- package/dist-types/components/menu/types/MultiLevelListMixinTypes.d.ts +16 -0
- package/dist-types/components/menu/types/MultiLevelListMixinTypes.d.ts.map +1 -0
- package/dist-types/components/menu/types/OverlayWithListInvokerMixinTypes.d.ts +35 -0
- package/dist-types/components/menu/types/OverlayWithListInvokerMixinTypes.d.ts.map +1 -0
- package/dist-types/components/overlays/src/OverlayController.d.ts +22 -5
- package/dist-types/components/overlays/src/OverlayController.d.ts.map +1 -1
- package/dist-types/components/overlays/src/OverlayMixin.d.ts.map +1 -1
- package/dist-types/components/overlays/src/utils/is-equal-config.d.ts.map +1 -1
- package/dist-types/components/overlays/types/ArrowMixinTypes.d.ts.map +1 -1
- package/dist-types/components/overlays/types/OverlayConfig.d.ts +12 -2
- package/dist-types/components/overlays/types/OverlayConfig.d.ts.map +1 -1
- package/dist-types/components/overlays/types/OverlayMixinTypes.d.ts +1 -0
- package/dist-types/components/overlays/types/OverlayMixinTypes.d.ts.map +1 -1
- package/dist-types/components/select-rich/src/LionSelectRich.d.ts +13 -2
- package/dist-types/components/select-rich/src/LionSelectRich.d.ts.map +1 -1
- package/dist-types/components/select-rich/test/lion-select-rich-interaction.test.d.ts.map +1 -1
- package/dist-types/components/select-rich/test/lion-select-rich-upgrade.test.d.ts +2 -0
- package/dist-types/components/select-rich/test/lion-select-rich-upgrade.test.d.ts.map +1 -0
- package/dist-types/components/tooltip/src/LionTooltip.d.ts +1 -1
- package/dist-types/exports/define/lion-item.d.ts +2 -0
- package/dist-types/exports/define/lion-item.d.ts.map +1 -0
- package/dist-types/exports/define/lion-menu.d.ts +2 -0
- package/dist-types/exports/define/lion-menu.d.ts.map +1 -0
- package/dist-types/exports/define/lion-menuitem.d.ts +2 -0
- package/dist-types/exports/define/lion-menuitem.d.ts.map +1 -0
- package/dist-types/exports/menu-test-suites.d.ts +4 -0
- package/dist-types/exports/menu-test-suites.d.ts.map +1 -0
- package/dist-types/exports/menu.d.ts +3 -0
- package/dist-types/exports/menu.d.ts.map +1 -0
- package/dist-types/exports/overlays.d.ts +6 -0
- package/dist-types/exports/overlays.d.ts.map +1 -1
- package/dist-types/tsconfig.tsbuildinfo +1 -1
- package/docs/components/checkbox-group/overview.md +2 -2
- package/docs/components/collapsible/overview.md +1 -1
- package/docs/components/combobox/api-table.md +53 -39
- package/docs/components/combobox/overview.md +1 -1
- package/docs/components/combobox/use-cases.md +1 -1
- package/docs/components/dialog/api-table.md +32 -6
- package/docs/components/dialog/overview.md +1 -1
- package/docs/components/fieldset/overview.md +5 -5
- package/docs/components/form/overview.md +3 -3
- package/docs/components/form/use-cases.md +2 -2
- package/docs/components/icon/use-cases.md +1 -1
- package/docs/components/input/overview.md +1 -1
- package/docs/components/input-amount/api-table.md +9 -7
- package/docs/components/input-amount/overview.md +3 -3
- package/docs/components/input-amount/use-cases.md +15 -4
- package/docs/components/input-amount-dropdown/api-table.md +2 -0
- package/docs/components/input-date/overview.md +3 -3
- package/docs/components/input-datepicker/api-table.md +63 -45
- package/docs/components/input-datepicker/overview.md +5 -5
- package/docs/components/input-email/overview.md +2 -2
- package/docs/components/input-file/overview.md +1 -1
- package/docs/components/input-iban/overview.md +2 -2
- package/docs/components/input-range/overview.md +2 -2
- package/docs/components/input-stepper/overview.md +1 -1
- package/docs/components/input-tel/overview.md +1 -1
- package/docs/components/input-tel/use-cases.md +6 -6
- package/docs/components/input-tel-dropdown/overview.md +1 -1
- package/docs/components/listbox/use-cases.md +1 -1
- package/docs/components/menu/api-table.md +44 -0
- package/docs/components/menu/applyMenuDemoStyles.js +173 -0
- package/docs/components/menu/extensions.md +262 -0
- package/docs/components/menu/index.md +13 -0
- package/docs/components/menu/migration.md +129 -0
- package/docs/components/menu/overview.md +448 -0
- package/docs/components/menu/src/DemoNavigationBar.js +441 -0
- package/docs/components/menu/src/DemoSpinButton.js +215 -0
- package/docs/components/menu/src/DemoToolbar.js +101 -0
- package/docs/components/menu/src/DemoTree.js +55 -0
- package/docs/components/menu/src/navigation-bar-types.js +41 -0
- package/docs/components/menu/use-cases.md +74 -0
- package/docs/components/radio-group/overview.md +3 -3
- package/docs/components/select/use-cases.md +1 -1
- package/docs/components/select-rich/api-table.md +51 -33
- package/docs/components/select-rich/use-cases.md +2 -2
- package/docs/components/tabs/examples.md +1 -1
- package/docs/components/tooltip/api-table.md +33 -7
- package/docs/fundamentals/index.md +4 -4
- package/docs/fundamentals/node-tools/providence-analytics/overview.md +1 -1
- package/docs/fundamentals/node-tools/publish-docs/overview.md +3 -3
- package/docs/fundamentals/node-tools/rocket-preset-extend-lion-docs/overview.md +2 -2
- package/docs/fundamentals/rationales/accessibility.md +1 -1
- package/docs/fundamentals/systems/core/SlotMixin.md +1 -1
- package/docs/fundamentals/systems/core/overview.md +1 -1
- package/docs/fundamentals/systems/form/formatting-and-parsing.md +4 -4
- package/docs/fundamentals/systems/form/model-value.md +1 -1
- package/docs/fundamentals/systems/form/overview.md +28 -28
- package/docs/fundamentals/systems/form/validate.md +2 -2
- package/docs/fundamentals/systems/localize/overview.md +4 -4
- package/docs/fundamentals/systems/overlays/api-table.md +46 -43
- package/docs/fundamentals/systems/overlays/configuration.md +2 -2
- package/docs/fundamentals/systems/overlays/overview.md +5 -5
- package/docs/fundamentals/systems/overlays/use-cases.md +2 -2
- package/docs/fundamentals/tools/helpers/overview.md +1 -1
- package/docs/fundamentals/tools/singleton-manager/overview.md +4 -4
- package/docs/guides/how-to/create-a-custom-field.md +5 -5
- package/docs/guides/how-to/create-a-form.md +4 -4
- package/docs/guides/how-to/extend-a-native-input.md +2 -2
- package/docs/guides/how-to/index.md +1 -1
- package/docs/guides/index.md +8 -8
- package/docs/guides/principles/index.md +5 -5
- package/docs/guides/principles/styling.md +1 -1
- package/exports/define/lion-item.js +3 -0
- package/exports/define/lion-menu.js +3 -0
- package/exports/define/lion-menuitem.js +3 -0
- package/exports/menu-test-suites.js +4 -0
- package/exports/menu.js +3 -0
- package/exports/overlays.js +6 -0
- package/menu-test-suites.js +4 -0
- package/menu.js +3 -0
- package/overlays.js +6 -0
- package/package.json +11 -4
- package/vendor/README.md +61 -0
- package/vendor/awesome-phonenumber-7.9.0-tlouisse.libphonenumber-9.0.41.tgz +0 -0
- package/vscode.html-custom-data.json +76 -8
- package/web-types.json +202 -17
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { dedupeMixin } from '@open-wc/dedupe-mixin';
|
|
2
2
|
import { OverlayController } from './OverlayController.js';
|
|
3
|
-
import { isEqualConfig } from './utils/is-equal-config.js';
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* @typedef {<T>(ingOverlayHost:T) => void} PostProcessor
|
|
@@ -28,14 +27,12 @@ export function _addOverlayMixinPostProcessor(postProcessor) {
|
|
|
28
27
|
* @type {OverlayMixin}
|
|
29
28
|
* @param {import('@open-wc/dedupe-mixin').Constructor<import('lit').LitElement>} superclass
|
|
30
29
|
*/
|
|
30
|
+
// @ts-ignore https://github.com/microsoft/TypeScript/issues/36821#issuecomment-588375051
|
|
31
31
|
export const OverlayMixinImplementation = superclass => {
|
|
32
32
|
class OverlayMixin extends superclass {
|
|
33
33
|
static get properties() {
|
|
34
34
|
return {
|
|
35
|
-
opened: {
|
|
36
|
-
type: Boolean,
|
|
37
|
-
reflect: true,
|
|
38
|
-
},
|
|
35
|
+
opened: { type: Boolean, reflect: true },
|
|
39
36
|
};
|
|
40
37
|
}
|
|
41
38
|
|
|
@@ -69,13 +66,13 @@ export const OverlayMixinImplementation = superclass => {
|
|
|
69
66
|
|
|
70
67
|
/** @param {OverlayConfig} value */
|
|
71
68
|
set config(value) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if (this._overlayCtrl
|
|
69
|
+
// The OverlayController already guards against redundant updates
|
|
70
|
+
// (see OverlayController#updateConfig), so we delegate unconditionally here.
|
|
71
|
+
if (this._overlayCtrl) {
|
|
75
72
|
this._overlayCtrl.updateConfig(value);
|
|
76
73
|
}
|
|
77
74
|
this.__config = value;
|
|
78
|
-
if (this._overlayCtrl
|
|
75
|
+
if (this._overlayCtrl) {
|
|
79
76
|
this.__syncToOverlayController();
|
|
80
77
|
}
|
|
81
78
|
}
|
|
@@ -160,6 +157,8 @@ export const OverlayMixinImplementation = superclass => {
|
|
|
160
157
|
*/
|
|
161
158
|
// eslint-disable-next-line class-methods-use-this
|
|
162
159
|
_setupOpenCloseListeners() {
|
|
160
|
+
// Keeps the close-overlay event private for the controller.
|
|
161
|
+
// (we already have )
|
|
163
162
|
/**
|
|
164
163
|
* @param {{ stopPropagation: () => void; }} ev
|
|
165
164
|
*/
|
|
@@ -217,12 +216,6 @@ export const OverlayMixinImplementation = superclass => {
|
|
|
217
216
|
// @ts-expect-error
|
|
218
217
|
static enabledWarnings = super.enabledWarnings?.filter(w => w !== 'change-in-update') || [];
|
|
219
218
|
|
|
220
|
-
get _overlayInvokerNode() {
|
|
221
|
-
return /** @type {HTMLElement | undefined} */ (
|
|
222
|
-
Array.from(this.children).find(child => child.slot === 'invoker')
|
|
223
|
-
);
|
|
224
|
-
}
|
|
225
|
-
|
|
226
219
|
/**
|
|
227
220
|
* @overridable
|
|
228
221
|
*/
|
|
@@ -255,13 +248,81 @@ export const OverlayMixinImplementation = superclass => {
|
|
|
255
248
|
);
|
|
256
249
|
}
|
|
257
250
|
|
|
251
|
+
/**
|
|
252
|
+
* Returns the element that can actually receive focus inside the passed
|
|
253
|
+
* invoker (wrapper) element: the element itself when it is focusable,
|
|
254
|
+
* otherwise the first focusable descendant.
|
|
255
|
+
* @param {Element|null|undefined} focusableElOrWrapper
|
|
256
|
+
* @returns {Element|null}
|
|
257
|
+
*/
|
|
258
|
+
/**
|
|
259
|
+
* @param {Element | null | undefined} focusableElOrWrapper
|
|
260
|
+
* @returns {Element | null}
|
|
261
|
+
*/
|
|
262
|
+
static _getFocusableInvokerEl(focusableElOrWrapper) {
|
|
263
|
+
if (!focusableElOrWrapper) return null;
|
|
264
|
+
const focusableSelector = '[tabindex], button, a[href], [role=button]';
|
|
265
|
+
return focusableElOrWrapper.matches(focusableSelector)
|
|
266
|
+
? focusableElOrWrapper
|
|
267
|
+
: focusableElOrWrapper.querySelector(focusableSelector);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* The node that opens/closes this overlay.
|
|
272
|
+
*
|
|
273
|
+
* Resolved in a stable, declarative way (independent of the exact DOM order)
|
|
274
|
+
* by looking, in order, for:
|
|
275
|
+
* 1. a child with `[slot="invoker"]`
|
|
276
|
+
* 2. any element in the same root that opts in via `[data-invoker]` and
|
|
277
|
+
* references this host by id (`for="<id>"`)
|
|
278
|
+
* 3. a preceding sibling that opts in via `[data-invoker]`
|
|
279
|
+
* @protected
|
|
280
|
+
*/
|
|
281
|
+
get _overlayInvokerNode() {
|
|
282
|
+
if (!this.__invokerNode) {
|
|
283
|
+
this.__invokerNode = this._getInvokerNode();
|
|
284
|
+
}
|
|
285
|
+
return this.__invokerNode;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* @protected
|
|
290
|
+
* @returns {Element|null}
|
|
291
|
+
*/
|
|
292
|
+
_getInvokerNode() {
|
|
293
|
+
const ctor = /** @type {typeof OverlayMixin} */ (this.constructor);
|
|
294
|
+
|
|
295
|
+
const slottedNode = Array.from(this.children).find(child => child.slot === 'invoker');
|
|
296
|
+
if (slottedNode) {
|
|
297
|
+
return ctor._getFocusableInvokerEl(slottedNode);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (this.id) {
|
|
301
|
+
// Reference the invoker declaratively: `<button data-invoker for="my-menu">`
|
|
302
|
+
const root = /** @type {Document|ShadowRoot} */ (this.getRootNode());
|
|
303
|
+
const explicitInvoker = root.querySelector?.(`[data-invoker][for="${this.id}"]`);
|
|
304
|
+
if (explicitInvoker) {
|
|
305
|
+
return ctor._getFocusableInvokerEl(explicitInvoker);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Fall back to a preceding sibling that opted in via [data-invoker]
|
|
310
|
+
const { previousElementSibling } = this;
|
|
311
|
+
return previousElementSibling && previousElementSibling.hasAttribute('data-invoker')
|
|
312
|
+
? ctor._getFocusableInvokerEl(previousElementSibling)
|
|
313
|
+
: null;
|
|
314
|
+
}
|
|
315
|
+
|
|
258
316
|
/** @protected */
|
|
259
317
|
_setupOverlayCtrl() {
|
|
260
318
|
if (this.#hasSetup) return;
|
|
319
|
+
|
|
320
|
+
const invokerNode = this._overlayInvokerNode;
|
|
321
|
+
|
|
261
322
|
const config = {
|
|
262
323
|
contentNode: this._overlayContentNode,
|
|
263
324
|
contentWrapperNode: this._overlayContentWrapperNode,
|
|
264
|
-
invokerNode:
|
|
325
|
+
invokerNode: invokerNode && invokerNode instanceof HTMLElement ? invokerNode : undefined,
|
|
265
326
|
referenceNode: this._overlayReferenceNode,
|
|
266
327
|
backdropNode: this._overlayBackdropNode,
|
|
267
328
|
};
|
|
@@ -282,6 +343,8 @@ export const OverlayMixinImplementation = superclass => {
|
|
|
282
343
|
|
|
283
344
|
/** @protected */
|
|
284
345
|
_teardownOverlayCtrl() {
|
|
346
|
+
// Make sure that dynamic behavior (e.g. responsive) is possible by allowing multiple setups and teardowns of the overlay controller.
|
|
347
|
+
this.#hasSetup = false;
|
|
285
348
|
if (!this._overlayCtrl) return;
|
|
286
349
|
|
|
287
350
|
this._teardownOpenCloseListeners();
|
|
@@ -434,6 +497,7 @@ export const OverlayMixinImplementation = superclass => {
|
|
|
434
497
|
for (const postProcessor of overlayMixinPostProcessors) {
|
|
435
498
|
postProcessor(OverlayMixin);
|
|
436
499
|
}
|
|
437
|
-
|
|
500
|
+
// @ts-ignore https://github.com/microsoft/TypeScript/issues/36821#issuecomment-588375051
|
|
501
|
+
return OverlayMixin;
|
|
438
502
|
};
|
|
439
503
|
export const OverlayMixin = dedupeMixin(OverlayMixinImplementation);
|
|
@@ -124,7 +124,7 @@ export function adoptStyle(renderRoot, style, { teardown = false } = {}) {
|
|
|
124
124
|
if (!teardown) {
|
|
125
125
|
// @ts-ignore
|
|
126
126
|
// eslint-disable-next-line no-param-reassign
|
|
127
|
-
renderRoot.adoptedStyleSheets = [...renderRoot.adoptedStyleSheets, sheet];
|
|
127
|
+
renderRoot.adoptedStyleSheets = [...(renderRoot.adoptedStyleSheets || []), sheet];
|
|
128
128
|
} else if (renderRoot.adoptedStyleSheets.includes(sheet)) {
|
|
129
129
|
// @ts-ignore
|
|
130
130
|
// eslint-disable-next-line no-param-reassign
|
|
@@ -12,15 +12,24 @@
|
|
|
12
12
|
*/
|
|
13
13
|
export function isEqualConfig(a, b) {
|
|
14
14
|
if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) {
|
|
15
|
+
if (typeof a === 'function' && typeof b === 'function') {
|
|
16
|
+
return /** @type {Function} */ (a).toString() === /** @type {Function} */ (b).toString();
|
|
17
|
+
}
|
|
15
18
|
return a === b;
|
|
16
19
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
if (a instanceof Node && b instanceof Node) {
|
|
21
|
+
return a === b;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const aProps = Object.keys(a);
|
|
25
|
+
const bProps = Object.keys(b);
|
|
21
26
|
if (aProps.length !== bProps.length) {
|
|
22
27
|
return false;
|
|
23
28
|
}
|
|
24
|
-
|
|
25
|
-
|
|
29
|
+
return aProps.every(
|
|
30
|
+
prop =>
|
|
31
|
+
Object.prototype.hasOwnProperty.call(b, prop) &&
|
|
32
|
+
// @ts-ignore - dynamic property access
|
|
33
|
+
isEqualConfig(a[prop], b[prop]),
|
|
34
|
+
);
|
|
26
35
|
}
|
|
@@ -115,26 +115,35 @@ const withLocalTestConfig = () =>
|
|
|
115
115
|
*/
|
|
116
116
|
async function createNestedEscControllers(parentContent) {
|
|
117
117
|
const childContent = /** @type {HTMLDivElement} */ (parentContent.querySelector('div[id]'));
|
|
118
|
-
// Assert valid fixure
|
|
119
|
-
const isValidFixture =
|
|
120
|
-
(parentContent.id.startsWith('parent-overlay--hidesOnEsc') ||
|
|
121
|
-
parentContent.id.startsWith('parent-overlay--hidesOnOutsideEsc')) &&
|
|
122
|
-
(childContent.id.startsWith('child-overlay--hidesOnEsc') ||
|
|
123
|
-
childContent.id.startsWith('child-overlay--hidesOnOutsideEsc'));
|
|
124
|
-
if (!isValidFixture) {
|
|
125
|
-
throw new Error('Provide a valid fixture');
|
|
126
|
-
}
|
|
127
118
|
|
|
128
119
|
if (parentContent.hasAttribute('data-convert-to-shadow-root')) {
|
|
129
120
|
const shadowRootParent = parentContent.attachShadow({ mode: 'open' });
|
|
130
121
|
shadowRootParent.appendChild(childContent);
|
|
131
122
|
}
|
|
132
123
|
|
|
124
|
+
const parentConfig = {};
|
|
125
|
+
const childConfig = {};
|
|
126
|
+
|
|
133
127
|
const parentHasOutsideOnEsc = parentContent.id.startsWith('parent-overlay--hidesOnOutsideEsc');
|
|
134
128
|
const childHasOutsideOnEsc = childContent.id.startsWith('child-overlay--hidesOnOutsideEsc');
|
|
135
129
|
|
|
136
|
-
|
|
137
|
-
|
|
130
|
+
if (parentHasOutsideOnEsc) {
|
|
131
|
+
parentConfig.hidesOnOutsideEsc = true;
|
|
132
|
+
} else {
|
|
133
|
+
parentConfig.hidesOnEsc = true;
|
|
134
|
+
}
|
|
135
|
+
if (childHasOutsideOnEsc) {
|
|
136
|
+
childConfig.hidesOnOutsideEsc = true;
|
|
137
|
+
} else {
|
|
138
|
+
childConfig.hidesOnEsc = true;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const parentHasSyncChildrenCloseState =
|
|
142
|
+
parentContent.dataset.syncChildrenCloseState !== undefined;
|
|
143
|
+
|
|
144
|
+
if (parentHasSyncChildrenCloseState) {
|
|
145
|
+
parentConfig.syncChildrenCloseState = true;
|
|
146
|
+
}
|
|
138
147
|
|
|
139
148
|
const parentOverlay = new OverlayController({
|
|
140
149
|
...withGlobalTestConfig(),
|
|
@@ -283,8 +292,9 @@ describe('OverlayController', () => {
|
|
|
283
292
|
contentNode,
|
|
284
293
|
});
|
|
285
294
|
};
|
|
295
|
+
|
|
286
296
|
expect(createOverlayController).to.throw(
|
|
287
|
-
'[OverlayController] Could not find a render target,
|
|
297
|
+
'[OverlayController] Could not find a render target, makes sure contentNode has a parent element (or contentWrapperNode is connected)',
|
|
288
298
|
);
|
|
289
299
|
});
|
|
290
300
|
|
|
@@ -346,6 +356,21 @@ describe('OverlayController', () => {
|
|
|
346
356
|
await ctrl.hide();
|
|
347
357
|
expect(ctrl.isShown).to.be.false;
|
|
348
358
|
});
|
|
359
|
+
|
|
360
|
+
it('cleans up the dom structure it created', async () => {
|
|
361
|
+
const contentNode = /** @type {HTMLElement} */ (fixtureSync(html`<div>my content</div>`));
|
|
362
|
+
const ctrl = new OverlayController({
|
|
363
|
+
placementMode: 'global',
|
|
364
|
+
contentNode,
|
|
365
|
+
});
|
|
366
|
+
await ctrl.show();
|
|
367
|
+
expect(ctrl.contentWrapperNode).to.exist;
|
|
368
|
+
expect(ctrl.__wrappingDialogNode).to.exist;
|
|
369
|
+
|
|
370
|
+
await ctrl.teardown();
|
|
371
|
+
expect(ctrl.contentWrapperNode).to.not.exist;
|
|
372
|
+
expect(ctrl.__wrappingDialogNode).to.not.exist;
|
|
373
|
+
});
|
|
349
374
|
});
|
|
350
375
|
|
|
351
376
|
describe('Node Configuration', () => {
|
|
@@ -403,7 +428,7 @@ describe('OverlayController', () => {
|
|
|
403
428
|
{ ignoreAttributes: ['closedby'] },
|
|
404
429
|
);
|
|
405
430
|
|
|
406
|
-
expect(el).lightDom.to.equal(`<div slot="content">projected</div>`);
|
|
431
|
+
expect(el).lightDom.to.equal(`<div data-content="" slot="content">projected</div>`);
|
|
407
432
|
});
|
|
408
433
|
});
|
|
409
434
|
|
|
@@ -425,7 +450,7 @@ describe('OverlayController', () => {
|
|
|
425
450
|
`
|
|
426
451
|
<dialog data-overlay-outer-wrapper="" open="" role="none" style="${wrappingDialogNodeStyle}">
|
|
427
452
|
<div data-id="content-wrapper">
|
|
428
|
-
<div id="content">non projected</div>
|
|
453
|
+
<div data-content="" id="content">non projected</div>
|
|
429
454
|
</div>
|
|
430
455
|
</dialog>
|
|
431
456
|
`,
|
|
@@ -434,6 +459,84 @@ describe('OverlayController', () => {
|
|
|
434
459
|
});
|
|
435
460
|
});
|
|
436
461
|
|
|
462
|
+
describe('When .contentWrapperNode is provided in a host that is not connected yet', () => {
|
|
463
|
+
/** @param {{ nested?: boolean }} [opts] */
|
|
464
|
+
function createDisconnectedHost({ nested = false } = {}) {
|
|
465
|
+
const host = document.createElement('div');
|
|
466
|
+
const shadowRoot = host.attachShadow({ mode: 'open' });
|
|
467
|
+
const wrapper = document.createElement('div');
|
|
468
|
+
wrapper.setAttribute('data-id', 'content-wrapper');
|
|
469
|
+
wrapper.innerHTML = '<slot name="content"></slot>';
|
|
470
|
+
if (nested) {
|
|
471
|
+
const section = document.createElement('section');
|
|
472
|
+
section.appendChild(wrapper);
|
|
473
|
+
shadowRoot.appendChild(section);
|
|
474
|
+
} else {
|
|
475
|
+
shadowRoot.appendChild(wrapper);
|
|
476
|
+
}
|
|
477
|
+
const content = document.createElement('div');
|
|
478
|
+
content.slot = 'content';
|
|
479
|
+
content.textContent = 'projected';
|
|
480
|
+
host.appendChild(content);
|
|
481
|
+
return { host, shadowRoot, wrapper, content };
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
it('does not throw and keeps the projected slot inside the wrapper', async () => {
|
|
485
|
+
const { host, shadowRoot, wrapper, content } = createDisconnectedHost();
|
|
486
|
+
expect(wrapper.isConnected).to.be.false;
|
|
487
|
+
const slot = /** @type {HTMLSlotElement} */ (content.assignedSlot);
|
|
488
|
+
|
|
489
|
+
const ctrl = new OverlayController({
|
|
490
|
+
...withGlobalTestConfig(),
|
|
491
|
+
contentNode: content,
|
|
492
|
+
contentWrapperNode: wrapper,
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
expect(ctrl.contentWrapperNode).to.equal(wrapper);
|
|
496
|
+
expect(wrapper.parentElement?.tagName).to.equal('DIALOG');
|
|
497
|
+
expect(slot.parentElement).to.equal(wrapper);
|
|
498
|
+
expect(content.parentElement).to.equal(host);
|
|
499
|
+
expect(shadowRoot.querySelectorAll('slot').length).to.equal(1);
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
it('restores the same relocated slot at its original position on teardown', async () => {
|
|
503
|
+
const { host, shadowRoot, wrapper, content } = createDisconnectedHost({ nested: true });
|
|
504
|
+
const section = /** @type {HTMLElement} */ (shadowRoot.querySelector('section'));
|
|
505
|
+
const slot = /** @type {HTMLSlotElement} */ (content.assignedSlot);
|
|
506
|
+
const ctrl = new OverlayController({
|
|
507
|
+
...withGlobalTestConfig(),
|
|
508
|
+
contentNode: content,
|
|
509
|
+
contentWrapperNode: wrapper,
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
ctrl.teardown();
|
|
513
|
+
|
|
514
|
+
expect(content.parentElement).to.equal(host);
|
|
515
|
+
expect(wrapper.parentElement).to.equal(section);
|
|
516
|
+
expect(slot.parentElement).to.equal(wrapper);
|
|
517
|
+
expect(shadowRoot.querySelector('dialog')).to.be.null;
|
|
518
|
+
expect(shadowRoot.querySelector('slot')).to.equal(slot);
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
it('survives repeated updateConfig calls and keeps slot ownership', async () => {
|
|
522
|
+
const { host, shadowRoot, wrapper, content } = createDisconnectedHost();
|
|
523
|
+
const slot = /** @type {HTMLSlotElement} */ (content.assignedSlot);
|
|
524
|
+
const ctrl = new OverlayController({
|
|
525
|
+
...withGlobalTestConfig(),
|
|
526
|
+
contentNode: content,
|
|
527
|
+
contentWrapperNode: wrapper,
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
expect(() => ctrl.updateConfig({ trapsKeyboardFocus: true })).to.not.throw();
|
|
531
|
+
expect(() => ctrl.updateConfig({ trapsKeyboardFocus: false })).to.not.throw();
|
|
532
|
+
|
|
533
|
+
expect(content.parentElement).to.equal(host);
|
|
534
|
+
expect(shadowRoot.querySelectorAll('slot').length).to.equal(1);
|
|
535
|
+
expect(shadowRoot.querySelector('slot')).to.equal(slot);
|
|
536
|
+
expect(wrapper.contains(slot)).to.be.true;
|
|
537
|
+
});
|
|
538
|
+
});
|
|
539
|
+
|
|
437
540
|
describe('When .contenWrapperNode provided', async () => {
|
|
438
541
|
it('keeps the .contentWrapperNode for style application and wraps a <dialog role="none"> for top layer paints', async () => {
|
|
439
542
|
const tagString = defineCE(
|
|
@@ -620,6 +723,7 @@ describe('OverlayController', () => {
|
|
|
620
723
|
});
|
|
621
724
|
});
|
|
622
725
|
|
|
726
|
+
// TODO: make features modular (so they can be treeshaken) and test their lifecycle within this desrcibe
|
|
623
727
|
describe('Feature Configuration', () => {
|
|
624
728
|
describe('trapsKeyboardFocus', () => {
|
|
625
729
|
it('focuses the overlay on show', async () => {
|
|
@@ -854,7 +958,7 @@ describe('OverlayController', () => {
|
|
|
854
958
|
)
|
|
855
959
|
);
|
|
856
960
|
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
857
|
-
mimicEscapePress(childOverlay.contentNode);
|
|
961
|
+
await mimicEscapePress(childOverlay.contentNode);
|
|
858
962
|
|
|
859
963
|
expect(parentOverlay.isShown).to.be.true;
|
|
860
964
|
expect(childOverlay.isShown).to.be.true;
|
|
@@ -863,10 +967,7 @@ describe('OverlayController', () => {
|
|
|
863
967
|
|
|
864
968
|
describe('Nested hidesOnEsc / hidesOnOutsideEsc', () => {
|
|
865
969
|
describe('Parent has hidesOnEsc and child has hidesOnOutsideEsc', () => {
|
|
866
|
-
|
|
867
|
-
// is not staying shown after the parent overlay is hidden. The failing line
|
|
868
|
-
// is highlighted below.
|
|
869
|
-
it.skip('on [Escape] press in child overlay: parent hides, child stays shown', async () => {
|
|
970
|
+
it('on [Escape] press in child overlay: parent hides, child stays shown', async () => {
|
|
870
971
|
const parentContent = /** @type {HTMLDivElement} */ (
|
|
871
972
|
await fixture(
|
|
872
973
|
html` <!-- -->
|
|
@@ -877,12 +978,16 @@ describe('OverlayController', () => {
|
|
|
877
978
|
);
|
|
878
979
|
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
879
980
|
await mimicEscapePress(childOverlay.contentNode);
|
|
880
|
-
await
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
981
|
+
await childOverlay._showComplete;
|
|
982
|
+
await parentOverlay._showComplete;
|
|
983
|
+
await childOverlay._hideComplete;
|
|
984
|
+
await parentOverlay._hideComplete;
|
|
985
|
+
if (!childOverlay.isShown) {
|
|
986
|
+
await waitUntil(() => childOverlay.isShown);
|
|
987
|
+
}
|
|
988
|
+
if (parentOverlay.isShown) {
|
|
989
|
+
await waitUntil(() => !parentOverlay.isShown);
|
|
990
|
+
}
|
|
886
991
|
await childOverlay.teardown();
|
|
887
992
|
await parentOverlay.teardown();
|
|
888
993
|
});
|
|
@@ -988,6 +1093,7 @@ describe('OverlayController', () => {
|
|
|
988
1093
|
});
|
|
989
1094
|
});
|
|
990
1095
|
});
|
|
1096
|
+
|
|
991
1097
|
describe('hidesOnOutsideClick', () => {
|
|
992
1098
|
it('hides on outside click', async () => {
|
|
993
1099
|
const contentNode = /** @type {HTMLElement} */ (await fixture('<div>Content</div>'));
|
|
@@ -1708,6 +1814,97 @@ describe('OverlayController', () => {
|
|
|
1708
1814
|
expect(ctrl1.hasActiveBackdrop).to.be.true;
|
|
1709
1815
|
});
|
|
1710
1816
|
});
|
|
1817
|
+
|
|
1818
|
+
describe('elementToFocusOnShow', () => {
|
|
1819
|
+
it('adds tabindex="-1" to the content node when elementToFocusOnShow is true', async () => {
|
|
1820
|
+
const ctrl = new OverlayController({
|
|
1821
|
+
...withGlobalTestConfig(),
|
|
1822
|
+
isBlocking: false,
|
|
1823
|
+
elementToFocusOnShow: true,
|
|
1824
|
+
});
|
|
1825
|
+
const contentNode = /** @type {HTMLElement} */ (await fixture('<div>Content</div>'));
|
|
1826
|
+
ctrl.updateConfig({ contentNode });
|
|
1827
|
+
await ctrl.show();
|
|
1828
|
+
expect(contentNode.getAttribute('tabindex')).to.equal('-1');
|
|
1829
|
+
});
|
|
1830
|
+
|
|
1831
|
+
it('makes contentNode the root of "next tab flow"', async () => {
|
|
1832
|
+
const ctrl = new OverlayController({
|
|
1833
|
+
...withGlobalTestConfig(),
|
|
1834
|
+
isBlocking: false,
|
|
1835
|
+
elementToFocusOnShow: true,
|
|
1836
|
+
});
|
|
1837
|
+
const contentNode = /** @type {HTMLElement} */ (
|
|
1838
|
+
await fixture('<div><button>Button</button></div>')
|
|
1839
|
+
);
|
|
1840
|
+
ctrl.updateConfig({ contentNode });
|
|
1841
|
+
await ctrl.show();
|
|
1842
|
+
const button = /** @type {HTMLButtonElement} */ (contentNode.querySelector('button'));
|
|
1843
|
+
button.focus();
|
|
1844
|
+
expect(isActiveElement(button)).to.be.true;
|
|
1845
|
+
});
|
|
1846
|
+
});
|
|
1847
|
+
|
|
1848
|
+
describe('syncChildrenCloseState', () => {
|
|
1849
|
+
it('does not close all children of nested controllers when syncChildrenCloseState is false', async () => {
|
|
1850
|
+
const parentContent = /** @type {HTMLDivElement} */ (
|
|
1851
|
+
await fixture(
|
|
1852
|
+
html` <!-- -->
|
|
1853
|
+
<div data-sync-children-close-state id="parent-overlay">
|
|
1854
|
+
<div id="child-overlay">we open our child and it will close when parent does</div>
|
|
1855
|
+
</div>`,
|
|
1856
|
+
)
|
|
1857
|
+
);
|
|
1858
|
+
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
1859
|
+
expect(parentOverlay.isShown).to.be.true;
|
|
1860
|
+
expect(childOverlay.isShown).to.be.true;
|
|
1861
|
+
|
|
1862
|
+
await parentOverlay.hide();
|
|
1863
|
+
await childOverlay._hideComplete;
|
|
1864
|
+
expect(parentOverlay.isShown).to.be.false;
|
|
1865
|
+
expect(childOverlay.isShown).to.be.false;
|
|
1866
|
+
});
|
|
1867
|
+
|
|
1868
|
+
it('does not close all children of nested controllers when syncChildrenCloseState is false', async () => {
|
|
1869
|
+
const parentContent = /** @type {HTMLDivElement} */ (
|
|
1870
|
+
await fixture(
|
|
1871
|
+
html` <!-- -->
|
|
1872
|
+
<div id="parent-overlay">
|
|
1873
|
+
<div id="child-overlay">
|
|
1874
|
+
we open our child and it will not close when parent does
|
|
1875
|
+
</div>
|
|
1876
|
+
</div>`,
|
|
1877
|
+
)
|
|
1878
|
+
);
|
|
1879
|
+
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
1880
|
+
expect(parentOverlay.isShown).to.be.true;
|
|
1881
|
+
expect(childOverlay.isShown).to.be.true;
|
|
1882
|
+
|
|
1883
|
+
await parentOverlay.hide();
|
|
1884
|
+
expect(parentOverlay.isShown).to.be.false;
|
|
1885
|
+
expect(childOverlay.isShown).to.be.true;
|
|
1886
|
+
});
|
|
1887
|
+
});
|
|
1888
|
+
|
|
1889
|
+
describe('isActivated', () => {
|
|
1890
|
+
it('allows to conditionally disable overlay/openable functionality (for responsive context like nav menus, accordions/collapsibles vs plain headings/content etc.)', async () => {
|
|
1891
|
+
const ctrl = new OverlayController({
|
|
1892
|
+
...withGlobalTestConfig(),
|
|
1893
|
+
isActivated: false,
|
|
1894
|
+
});
|
|
1895
|
+
expect(ctrl.__hasSetup).to.be.false;
|
|
1896
|
+
ctrl.updateConfig({
|
|
1897
|
+
isActivated: true,
|
|
1898
|
+
});
|
|
1899
|
+
expect(ctrl.__hasSetup).to.be.true;
|
|
1900
|
+
});
|
|
1901
|
+
});
|
|
1902
|
+
|
|
1903
|
+
// TODO
|
|
1904
|
+
describe('hideVisually', () => {});
|
|
1905
|
+
|
|
1906
|
+
// TODO
|
|
1907
|
+
describe('requireConnectedNodes', () => {});
|
|
1711
1908
|
});
|
|
1712
1909
|
|
|
1713
1910
|
describe('Show / Hide / Toggle', () => {
|
|
@@ -2298,6 +2495,7 @@ describe('OverlayController', () => {
|
|
|
2298
2495
|
});
|
|
2299
2496
|
|
|
2300
2497
|
it('should run with scroll prevention', async () => {
|
|
2498
|
+
await overlayControllerPreventsScroll.hide();
|
|
2301
2499
|
await overlayControllerPreventsScroll.show();
|
|
2302
2500
|
|
|
2303
2501
|
expect(
|
|
@@ -540,13 +540,13 @@ export function runOverlayMixinSuite({ tagString, tag, suffix = '' }) {
|
|
|
540
540
|
it('works with cache directive when reconnected', async () => {
|
|
541
541
|
class CachingContext extends LitElement {
|
|
542
542
|
static properties = {
|
|
543
|
-
|
|
543
|
+
showOverlay: { type: Boolean },
|
|
544
544
|
};
|
|
545
545
|
|
|
546
546
|
constructor() {
|
|
547
547
|
super();
|
|
548
548
|
|
|
549
|
-
this.
|
|
549
|
+
this.showOverlay = true;
|
|
550
550
|
}
|
|
551
551
|
|
|
552
552
|
get overlayEl() {
|
|
@@ -555,12 +555,12 @@ export function runOverlayMixinSuite({ tagString, tag, suffix = '' }) {
|
|
|
555
555
|
|
|
556
556
|
render() {
|
|
557
557
|
return html`${cache(
|
|
558
|
-
this.
|
|
559
|
-
? html
|
|
560
|
-
: html`<${tag} id="myOverlay">
|
|
558
|
+
this.showOverlay
|
|
559
|
+
? html`<${tag} id="myOverlay">
|
|
561
560
|
<div slot="content">content b</div>
|
|
562
561
|
<button slot="invoker">invoker button b</button>
|
|
563
|
-
</${tag}
|
|
562
|
+
</${tag}>`
|
|
563
|
+
: html`something else`,
|
|
564
564
|
)}`;
|
|
565
565
|
}
|
|
566
566
|
}
|
|
@@ -581,7 +581,7 @@ export function runOverlayMixinSuite({ tagString, tag, suffix = '' }) {
|
|
|
581
581
|
// @ts-expect-error [allow-protected] in tests
|
|
582
582
|
const setupSpy = sinon.spy(el.overlayEl, '_setupOverlayCtrl');
|
|
583
583
|
|
|
584
|
-
el.
|
|
584
|
+
el.showOverlay = false;
|
|
585
585
|
// render the new content
|
|
586
586
|
await el.updateComplete;
|
|
587
587
|
// wait for the teardown to complete
|
|
@@ -591,7 +591,7 @@ export function runOverlayMixinSuite({ tagString, tag, suffix = '' }) {
|
|
|
591
591
|
expect(teardownSpy.callCount).to.equal(1);
|
|
592
592
|
expect(setupSpy.callCount).to.equal(0);
|
|
593
593
|
|
|
594
|
-
el.
|
|
594
|
+
el.showOverlay = true;
|
|
595
595
|
await el.updateComplete;
|
|
596
596
|
expect(setupSpy.callCount).to.equal(1);
|
|
597
597
|
|
|
@@ -26,9 +26,7 @@ export declare class ArrowHost {
|
|
|
26
26
|
|
|
27
27
|
protected _defineOverlayConfig(): OverlayConfig;
|
|
28
28
|
|
|
29
|
-
protected _getPopperArrowConfig(
|
|
30
|
-
popperConfigToExtendFrom: Partial<PopperOptions>,
|
|
31
|
-
): Partial<PopperOptions>;
|
|
29
|
+
protected _getPopperArrowConfig(popperConfigToExtendFrom: Partial<PopperOptions>): Partial<PopperOptions>;
|
|
32
30
|
|
|
33
31
|
private __setupRepositionCompletePromise(): void;
|
|
34
32
|
|
|
@@ -21,7 +21,6 @@ export type OverlayPhase =
|
|
|
21
21
|
| 'add'
|
|
22
22
|
| 'remove';
|
|
23
23
|
|
|
24
|
-
|
|
25
24
|
export interface ViewportConfig {
|
|
26
25
|
placement: ViewportPlacement;
|
|
27
26
|
}
|
|
@@ -97,14 +96,30 @@ export interface OverlayConfig {
|
|
|
97
96
|
/** By default, the tooltip content is a 'description' for the invoker (uses aria-describedby) Setting this property to 'label' makes the content function as a label (via aria-labelledby) */
|
|
98
97
|
invokerRelation?: 'label' | 'description';
|
|
99
98
|
|
|
100
|
-
/** render a div instead of dialog */
|
|
101
|
-
_noDialogEl?: Boolean;
|
|
102
|
-
|
|
103
99
|
/**
|
|
104
100
|
* Determines the conditions hiding/showing should be based on. It gets the OverlayController as input and returns an object with
|
|
105
101
|
* functions with Overlay phases as keys
|
|
106
102
|
*/
|
|
107
103
|
visibilityTriggerFunction?: Function;
|
|
108
|
-
}
|
|
109
104
|
|
|
105
|
+
/**
|
|
106
|
+
* Whether the overlay content should receive focus when shown.
|
|
107
|
+
*/
|
|
108
|
+
elementToFocusOnShow?: boolean;
|
|
109
|
+
|
|
110
|
+
/*
|
|
111
|
+
* By default, we function either as overlay or disclosure. In some cases, this should be dynamically set (think of responsive changes).
|
|
112
|
+
* or it depends on the context (a top level menu is not openable (unless it's a context menu), its children menus are).
|
|
113
|
+
*/
|
|
114
|
+
isActivated?: boolean;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* By default, an error is thrown when contentNode is not connected to the DOM.
|
|
118
|
+
* This allows to prepare nodes and later connect them to dom.
|
|
119
|
+
*/
|
|
120
|
+
requireConnectedNodes?: boolean;
|
|
121
|
+
|
|
122
|
+
syncChildrenCloseState?: boolean;
|
|
110
123
|
|
|
124
|
+
_shouldTeardownDomStructure?: boolean;
|
|
125
|
+
}
|
|
@@ -17,6 +17,8 @@ export interface DefineOverlayConfig {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export declare class OverlayHost {
|
|
20
|
+
static _getFocusableInvokerEl(focusableElOrWrapper: Element | null | undefined): Element | null;
|
|
21
|
+
|
|
20
22
|
opened: Boolean;
|
|
21
23
|
get config(): Partial<OverlayConfig>;
|
|
22
24
|
set config(value: Partial<OverlayConfig>);
|