@lion/ui 0.16.0 → 0.17.0-menu-system.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/collapsible.js +1 -0
- package/components/button/src/LionButton.js +5 -0
- package/components/button/test-suites/LionButton.suite.js +1 -0
- package/components/calendar/src/LionCalendar.js +2 -0
- package/components/collapsible/src/DisclosureMixin.js +313 -0
- package/components/collapsible/types/DisclosureMixinTypes.ts +48 -0
- package/components/combobox/src/utils/makeMatchingTextBold.js +3 -1
- package/components/combobox/test/lion-combobox.test.js +105 -0
- package/components/form-core/src/form-group/FormGroupMixin.js +7 -0
- package/components/form-core/src/registration/FormRegistrarMixin.js +11 -0
- package/components/form-core/test/FormControlMixin.test.js +1 -0
- package/components/form-core/test/validate/Validator.test.js +2 -0
- package/components/form-core/test-suites/ValidateMixin.suite.js +2 -0
- package/components/form-core/test-suites/ValidateMixinFeedbackPart.suite.js +1 -0
- package/components/input-datepicker/src/LionInputDatepicker.js +6 -2
- package/components/input-datepicker/src/localizeNamespaceLoader.js +1 -0
- package/components/input-datepicker/test/lion-input-datepicker.test.js +17 -2
- package/components/input-datepicker/translations/bg.js +1 -1
- package/components/input-datepicker/translations/cs.js +1 -1
- package/components/input-datepicker/translations/de.js +1 -1
- package/components/input-datepicker/translations/en.js +1 -1
- package/components/input-datepicker/translations/es.js +1 -1
- package/components/input-datepicker/translations/fr.js +1 -1
- package/components/input-datepicker/translations/hu.js +1 -1
- package/components/input-datepicker/translations/it.js +1 -1
- package/components/input-datepicker/translations/nl.js +1 -1
- package/components/input-datepicker/translations/pl.js +1 -1
- package/components/input-datepicker/translations/ro.js +1 -1
- package/components/input-datepicker/translations/ru.js +1 -1
- package/components/input-datepicker/translations/sk.js +1 -1
- package/components/input-datepicker/translations/tr.js +1 -1
- package/components/input-datepicker/translations/uk.js +1 -1
- package/components/input-datepicker/translations/zh.js +1 -1
- package/components/input-stepper/src/LionInputStepper.js +15 -7
- package/components/input-stepper/test-suites/lion-input-stepper.suite.js +28 -4
- package/components/localize/test/date/formatDate.test.js +1 -0
- package/components/menu/CHANGELOG.md +37 -0
- package/components/menu/README.md +335 -0
- package/components/menu/index.js +2 -0
- package/components/menu/lion-menu-overlay.js +3 -0
- package/components/menu/lion-menu.js +3 -0
- package/components/menu/lion-spinbutton.js +3 -0
- package/components/menu/lion-toolbar.js +3 -0
- package/components/menu/lion-tree.js +3 -0
- package/components/menu/package.json +46 -0
- package/components/menu/requirements.temp.md +12 -0
- package/components/menu/src/InteractiveListMixin.js +796 -0
- package/components/menu/src/LionMenu.js +250 -0
- package/components/menu/src/LionMenuHybrid.js +46 -0
- package/components/menu/src/LionMenuOverlay.js +155 -0
- package/components/menu/src/LionSpinbutton.js +213 -0
- package/components/menu/src/LionToolbar.js +94 -0
- package/components/menu/src/LionTree.js +52 -0
- package/components/menu/src/MultiLevelListMixin.js +275 -0
- package/components/menu/src/utils/isInView.js +26 -0
- package/components/menu/src/utils/listItemInteractions.js +104 -0
- package/components/menu/src/utils/uuid.js +3 -0
- package/components/menu/test/lion-menu.test.js +3 -0
- package/components/menu/test-suites/InteractiveListMixin.suite.js +142 -0
- package/components/menu/types/InteractiveListMixinTypes.d.ts +82 -0
- package/components/navigation-bar/README.md +1 -0
- package/components/navigation-bar/src/LionNavigationBar.js +449 -0
- package/components/navigation-bar/src/types.js +41 -0
- package/components/overlays/NEXT.md +49 -0
- package/components/overlays/src/OverlayController.js +165 -115
- package/components/overlays/src/OverlayMixin.js +75 -12
- package/components/overlays/src/OverlaysManager.js +102 -4
- package/components/overlays/src/overlayShadowDomStyle.js +2 -2
- package/components/overlays/src/utils/adopt-styles.js +2 -1
- package/components/overlays/src/utils/get-focusable-elements.js +4 -0
- package/components/overlays/src/utils/is-equal-config.js +4 -1
- package/components/overlays/test/OverlayController.test.js +117 -6
- package/components/overlays/test/OverlaysManager.test.js +1 -1
- package/components/overlays/types/OverlayConfig.ts +19 -4
- package/components/select-rich/test/lion-select-rich.test.js +3 -0
- package/custom-elements.json +12958 -2510
- package/dist-types/components/button/src/LionButton.d.ts +1 -0
- package/dist-types/components/button/src/LionButton.d.ts.map +1 -1
- package/dist-types/components/button/test-suites/LionButton.suite.d.ts.map +1 -1
- package/dist-types/components/calendar/src/LionCalendar.d.ts.map +1 -1
- package/dist-types/components/collapsible/src/DisclosureMixin.d.ts +3 -0
- package/dist-types/components/collapsible/src/DisclosureMixin.d.ts.map +1 -0
- package/dist-types/components/collapsible/types/DisclosureMixinTypes.d.ts +24 -0
- package/dist-types/components/collapsible/types/DisclosureMixinTypes.d.ts.map +1 -0
- package/dist-types/components/combobox/src/utils/makeMatchingTextBold.d.ts.map +1 -1
- package/dist-types/components/dialog/src/LionDialog.d.ts +2 -1
- package/dist-types/components/dialog/src/LionDialog.d.ts.map +1 -1
- package/dist-types/components/form-core/src/form-group/FormGroupMixin.d.ts.map +1 -1
- package/dist-types/components/form-core/src/registration/FormRegistrarMixin.d.ts.map +1 -1
- package/dist-types/components/form-core/test-suites/ValidateMixin.suite.d.ts.map +1 -1
- package/dist-types/components/form-core/test-suites/ValidateMixinFeedbackPart.suite.d.ts.map +1 -1
- package/dist-types/components/input-datepicker/src/LionInputDatepicker.d.ts.map +1 -1
- package/dist-types/components/input-datepicker/src/localizeNamespaceLoader.d.ts.map +1 -1
- package/dist-types/components/input-stepper/src/LionInputStepper.d.ts +4 -2
- package/dist-types/components/input-stepper/src/LionInputStepper.d.ts.map +1 -1
- package/dist-types/components/input-stepper/test-suites/lion-input-stepper.suite.d.ts.map +1 -1
- package/dist-types/components/menu/index.d.ts +3 -0
- package/dist-types/components/menu/index.d.ts.map +1 -0
- package/dist-types/components/menu/lion-menu-overlay.d.ts +2 -0
- package/dist-types/components/menu/lion-menu-overlay.d.ts.map +1 -0
- package/dist-types/components/menu/lion-menu.d.ts +2 -0
- package/dist-types/components/menu/lion-menu.d.ts.map +1 -0
- package/dist-types/components/menu/lion-spinbutton.d.ts +2 -0
- package/dist-types/components/menu/lion-spinbutton.d.ts.map +1 -0
- package/dist-types/components/menu/lion-toolbar.d.ts +2 -0
- package/dist-types/components/menu/lion-toolbar.d.ts.map +1 -0
- package/dist-types/components/menu/lion-tree.d.ts +2 -0
- package/dist-types/components/menu/lion-tree.d.ts.map +1 -0
- package/dist-types/components/menu/src/InteractiveListMixin.d.ts +611 -0
- package/dist-types/components/menu/src/InteractiveListMixin.d.ts.map +1 -0
- package/dist-types/components/menu/src/LionMenu.d.ts +563 -0
- package/dist-types/components/menu/src/LionMenu.d.ts.map +1 -0
- package/dist-types/components/menu/src/LionMenuHybrid.d.ts +19 -0
- package/dist-types/components/menu/src/LionMenuHybrid.d.ts.map +1 -0
- package/dist-types/components/menu/src/LionMenuOverlay.d.ts +1006 -0
- package/dist-types/components/menu/src/LionMenuOverlay.d.ts.map +1 -0
- package/dist-types/components/menu/src/LionSpinbutton.d.ts +58 -0
- package/dist-types/components/menu/src/LionSpinbutton.d.ts.map +1 -0
- package/dist-types/components/menu/src/LionToolbar.d.ts +8 -0
- package/dist-types/components/menu/src/LionToolbar.d.ts.map +1 -0
- package/dist-types/components/menu/src/LionTree.d.ts +445 -0
- package/dist-types/components/menu/src/LionTree.d.ts.map +1 -0
- package/dist-types/components/menu/src/MultiLevelListMixin.d.ts +493 -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 +42 -0
- package/dist-types/components/menu/src/utils/listItemInteractions.d.ts.map +1 -0
- package/dist-types/components/menu/src/utils/uuid.d.ts +2 -0
- package/dist-types/components/menu/src/utils/uuid.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-suites/InteractiveListMixin.suite.d.ts +13 -0
- package/dist-types/components/menu/test-suites/InteractiveListMixin.suite.d.ts.map +1 -0
- package/dist-types/components/navigation-bar/src/LionNavigationBar.d.ts +226 -0
- package/dist-types/components/navigation-bar/src/LionNavigationBar.d.ts.map +1 -0
- package/dist-types/components/navigation-bar/src/types.d.ts +85 -0
- package/dist-types/components/navigation-bar/src/types.d.ts.map +1 -0
- package/dist-types/components/overlays/src/OverlayController.d.ts +7 -13
- package/dist-types/components/overlays/src/OverlayController.d.ts.map +1 -1
- package/dist-types/components/overlays/src/OverlayMixin.d.ts +3 -0
- package/dist-types/components/overlays/src/OverlayMixin.d.ts.map +1 -1
- package/dist-types/components/overlays/src/OverlaysManager.d.ts +33 -2
- package/dist-types/components/overlays/src/OverlaysManager.d.ts.map +1 -1
- package/dist-types/components/overlays/src/utils/get-focusable-elements.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/OverlayConfig.d.ts +6 -2
- package/dist-types/components/overlays/types/OverlayConfig.d.ts.map +1 -1
- package/dist-types/components/select-rich/src/LionSelectRich.d.ts +11 -2
- package/dist-types/components/select-rich/src/LionSelectRich.d.ts.map +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-overlay.d.ts +2 -0
- package/dist-types/exports/define/lion-menu-overlay.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-navigation-bar.d.ts +2 -0
- package/dist-types/exports/define/lion-navigation-bar.d.ts.map +1 -0
- package/dist-types/exports/define/lion-toolbar.d.ts +2 -0
- package/dist-types/exports/define/lion-toolbar.d.ts.map +1 -0
- package/dist-types/exports/define/lion-tree.d.ts +2 -0
- package/dist-types/exports/define/lion-tree.d.ts.map +1 -0
- package/dist-types/exports/menu.d.ts +7 -0
- package/dist-types/exports/menu.d.ts.map +1 -0
- package/dist-types/exports/navigation-bar.d.ts +2 -0
- package/dist-types/exports/navigation-bar.d.ts.map +1 -0
- package/dist-types/exports/overlays.d.ts +2 -0
- package/dist-types/exports/types/overlays.d.ts +1 -0
- package/dist-types/exports/types/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/overview.md +1 -1
- package/docs/components/combobox/use-cases.md +1 -1
- 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/index.md +1 -1
- package/docs/components/input/overview.md +1 -1
- package/docs/components/input-amount/overview.md +3 -3
- package/docs/components/input-date/overview.md +3 -3
- package/docs/components/input-datepicker/overview.md +5 -5
- package/docs/components/input-datepicker/use-cases.md +16 -1
- 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/api-table.md +1 -1
- package/docs/components/input-range/overview.md +2 -2
- package/docs/components/input-stepper/api-table.md +2 -2
- package/docs/components/input-stepper/overview.md +1 -1
- package/docs/components/input-stepper/use-cases.md +26 -0
- 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 +450 -0
- package/docs/components/menu/applyMenuDemoStyles.js +173 -0
- package/docs/components/menu/extensions.md +216 -0
- package/docs/components/menu/index.md +13 -0
- package/docs/components/menu/overview.md +422 -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 +1 -1
- package/docs/components/select-rich/use-cases.md +2 -2
- package/docs/components/tabs/examples.md +1 -1
- package/docs/fundamentals/index.md +4 -4
- 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 +18 -18
- 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/interaction-states.md +0 -1
- 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/localize/text.md +1 -1
- package/docs/fundamentals/systems/overlays/api-table.md +98 -50
- 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 +14 -0
- package/docs/guides/index.md +8 -8
- package/docs/guides/principles/index.md +5 -5
- package/docs/guides/principles/styling.md +1 -2
- package/exports/collapsible.js +1 -0
- package/exports/define/lion-item.js +3 -0
- package/exports/define/lion-menu-overlay.js +3 -0
- package/exports/define/lion-menu.js +3 -0
- package/exports/define/lion-navigation-bar.js +3 -0
- package/exports/define/lion-toolbar.js +3 -0
- package/exports/define/lion-tree.js +3 -0
- package/exports/menu.js +6 -0
- package/exports/navigation-bar.js +1 -0
- package/exports/overlays.js +2 -0
- package/exports/types/overlays.ts +1 -0
- package/menu.js +6 -0
- package/navigation-bar.js +1 -0
- package/overlays.js +2 -0
- package/package.json +1 -1
|
@@ -3,6 +3,7 @@ import { browserDetection } from '@lion/ui/core.js';
|
|
|
3
3
|
/**
|
|
4
4
|
* @typedef {import('lit').CSSResult} CSSResult
|
|
5
5
|
* @typedef {import('./OverlayController.js').OverlayController} OverlayController
|
|
6
|
+
* @typedef {import('@lion/ui/types/overlays.js').OverlayPhase} OverlayPhase
|
|
6
7
|
*/
|
|
7
8
|
|
|
8
9
|
import { overlayDocumentStyle } from './overlayDocumentStyle.js';
|
|
@@ -46,13 +47,38 @@ export class OverlaysManager {
|
|
|
46
47
|
* @private
|
|
47
48
|
*/
|
|
48
49
|
this.__shownList = [];
|
|
49
|
-
/** @
|
|
50
|
-
this.
|
|
50
|
+
/** @protected */
|
|
51
|
+
this._siblingsInert = false;
|
|
51
52
|
/**
|
|
52
53
|
* @type {WeakMap<OverlayController, OverlayController[]>}
|
|
53
54
|
* @private
|
|
54
55
|
*/
|
|
55
56
|
this.__blockingMap = new WeakMap();
|
|
57
|
+
/**
|
|
58
|
+
* @private
|
|
59
|
+
* @type {{
|
|
60
|
+
* preventScrollCount: number;
|
|
61
|
+
* clientWidth: number | undefined;
|
|
62
|
+
* clientHeight: number | undefined;
|
|
63
|
+
* marginRightInline: string | undefined;
|
|
64
|
+
* marginBottomInline: string | undefined;
|
|
65
|
+
* marginRight: number | undefined;
|
|
66
|
+
* marginBottom: number | undefined;
|
|
67
|
+
* }}
|
|
68
|
+
*/
|
|
69
|
+
this.__bodySizeVars = {
|
|
70
|
+
preventScrollCount: 0,
|
|
71
|
+
clientWidth: undefined,
|
|
72
|
+
clientHeight: undefined,
|
|
73
|
+
marginRightInline: undefined,
|
|
74
|
+
marginBottomInline: undefined,
|
|
75
|
+
marginRight: undefined,
|
|
76
|
+
marginBottom: undefined,
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
this.__forTesting = {
|
|
80
|
+
bodySizeVars: this.__bodySizeVars,
|
|
81
|
+
};
|
|
56
82
|
|
|
57
83
|
if (!OverlaysManager.__globalStyleNode) {
|
|
58
84
|
OverlaysManager.__globalStyleNode = OverlaysManager.__createGlobalStyleNode();
|
|
@@ -118,7 +144,14 @@ export class OverlaysManager {
|
|
|
118
144
|
|
|
119
145
|
this.__list = [];
|
|
120
146
|
this.__shownList = [];
|
|
121
|
-
this.
|
|
147
|
+
this._siblingsInert = false;
|
|
148
|
+
this.__bodySizeVars.preventScrollCount = 0;
|
|
149
|
+
this.__bodySizeVars.clientWidth = undefined;
|
|
150
|
+
this.__bodySizeVars.clientHeight = undefined;
|
|
151
|
+
this.__bodySizeVars.marginRightInline = undefined;
|
|
152
|
+
this.__bodySizeVars.marginBottomInline = undefined;
|
|
153
|
+
this.__bodySizeVars.marginRight = undefined;
|
|
154
|
+
this.__bodySizeVars.marginBottom = undefined;
|
|
122
155
|
|
|
123
156
|
if (OverlaysManager.__globalStyleNode) {
|
|
124
157
|
document.head.removeChild(
|
|
@@ -131,11 +164,76 @@ export class OverlaysManager {
|
|
|
131
164
|
/** Features right now only for Global Overlay Manager */
|
|
132
165
|
|
|
133
166
|
get siblingsInert() {
|
|
134
|
-
return this.
|
|
167
|
+
return this._siblingsInert;
|
|
135
168
|
}
|
|
136
169
|
|
|
137
170
|
/** PreventsScroll */
|
|
138
171
|
|
|
172
|
+
/**
|
|
173
|
+
* @param {{ phase: OverlayPhase }} config
|
|
174
|
+
*/
|
|
175
|
+
requestToKeepBodySize({ phase }) {
|
|
176
|
+
switch (phase) {
|
|
177
|
+
case 'before-show':
|
|
178
|
+
// Tracks the amount of active preventsScroll overlays.
|
|
179
|
+
// Only the first overlay captures body metrics and only the last one restores them.
|
|
180
|
+
if (this.__bodySizeVars.preventScrollCount === 0) {
|
|
181
|
+
this.__bodySizeVars.clientWidth = document.body.clientWidth;
|
|
182
|
+
this.__bodySizeVars.clientHeight = document.body.clientHeight;
|
|
183
|
+
this.__bodySizeVars.marginRightInline = document.body.style.marginRight;
|
|
184
|
+
this.__bodySizeVars.marginBottomInline = document.body.style.marginBottom;
|
|
185
|
+
}
|
|
186
|
+
this.__bodySizeVars.preventScrollCount += 1;
|
|
187
|
+
break;
|
|
188
|
+
case 'show': {
|
|
189
|
+
if (this.__bodySizeVars.preventScrollCount === 1) {
|
|
190
|
+
if (window.getComputedStyle) {
|
|
191
|
+
const bodyStyle = window.getComputedStyle(document.body);
|
|
192
|
+
this.__bodySizeVars.marginRight = parseInt(
|
|
193
|
+
bodyStyle.getPropertyValue('margin-right'),
|
|
194
|
+
10,
|
|
195
|
+
);
|
|
196
|
+
this.__bodySizeVars.marginBottom = parseInt(
|
|
197
|
+
bodyStyle.getPropertyValue('margin-bottom'),
|
|
198
|
+
10,
|
|
199
|
+
);
|
|
200
|
+
} else {
|
|
201
|
+
this.__bodySizeVars.marginRight = 0;
|
|
202
|
+
this.__bodySizeVars.marginBottom = 0;
|
|
203
|
+
}
|
|
204
|
+
const scrollbarWidth =
|
|
205
|
+
document.body.clientWidth - /** @type {number} */ (this.__bodySizeVars.clientWidth);
|
|
206
|
+
const scrollbarHeight =
|
|
207
|
+
document.body.clientHeight - /** @type {number} */ (this.__bodySizeVars.clientHeight);
|
|
208
|
+
const newMarginRight = this.__bodySizeVars.marginRight + scrollbarWidth;
|
|
209
|
+
const newMarginBottom = this.__bodySizeVars.marginBottom + scrollbarHeight;
|
|
210
|
+
// @ts-expect-error [external]: CSS not yet typed
|
|
211
|
+
if (window.CSS?.number && document.body.attributeStyleMap?.set) {
|
|
212
|
+
// @ts-ignore - CSS Typed OM not fully typed
|
|
213
|
+
document.body.attributeStyleMap.set('margin-right', CSS.px(newMarginRight));
|
|
214
|
+
// @ts-ignore - CSS Typed OM not fully typed
|
|
215
|
+
document.body.attributeStyleMap.set('margin-bottom', CSS.px(newMarginBottom));
|
|
216
|
+
} else {
|
|
217
|
+
document.body.style.marginRight = `${newMarginRight}px`;
|
|
218
|
+
document.body.style.marginBottom = `${newMarginBottom}px`;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
case 'hide':
|
|
224
|
+
case 'teardown':
|
|
225
|
+
if (this.__bodySizeVars.preventScrollCount > 0) {
|
|
226
|
+
this.__bodySizeVars.preventScrollCount -= 1;
|
|
227
|
+
if (this.__bodySizeVars.preventScrollCount === 0) {
|
|
228
|
+
document.body.style.marginRight = this.__bodySizeVars.marginRightInline || '';
|
|
229
|
+
document.body.style.marginBottom = this.__bodySizeVars.marginBottomInline || '';
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
break;
|
|
233
|
+
/* no default */
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
139
237
|
// eslint-disable-next-line class-methods-use-this
|
|
140
238
|
requestToPreventScroll() {
|
|
141
239
|
const { isIOS, isMacSafari } = browserDetection;
|
|
@@ -113,11 +113,11 @@ export const overlayShadowDomStyle = css`
|
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
@media screen and (prefers-reduced-motion: reduce) {
|
|
116
|
-
.
|
|
116
|
+
.overlays__backdrop--animation-in {
|
|
117
117
|
animation: overlays-backdrop-fade-in 1ms;
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
.
|
|
120
|
+
.overlays__backdrop--animation-out {
|
|
121
121
|
animation: overlays-backdrop-fade-out 1ms;
|
|
122
122
|
}
|
|
123
123
|
}
|
|
@@ -56,7 +56,8 @@ function adoptStyleWhenAdoptedStylesheetsNotSupported(
|
|
|
56
56
|
const styleEl = document.createElement('style');
|
|
57
57
|
// keep notation, so it's not renamed in minification/build
|
|
58
58
|
// eslint-disable-next-line dot-notation
|
|
59
|
-
|
|
59
|
+
// @ts-ignore - litNonce is a custom property
|
|
60
|
+
const nonce = window.litNonce;
|
|
60
61
|
if (nonce !== undefined) {
|
|
61
62
|
styleEl.setAttribute('nonce', nonce);
|
|
62
63
|
}
|
|
@@ -8,6 +8,7 @@ import { isVisible } from './is-visible.js';
|
|
|
8
8
|
import { sortByTabIndex } from './sort-by-tabindex.js';
|
|
9
9
|
|
|
10
10
|
// IE11 supports matches as 'msMatchesSelector'
|
|
11
|
+
/** @type {'matches' | 'msMatchesSelector'} */
|
|
11
12
|
const matchesFunc = 'matches' in Element.prototype ? 'matches' : 'msMatchesSelector';
|
|
12
13
|
|
|
13
14
|
/**
|
|
@@ -16,11 +17,14 @@ const matchesFunc = 'matches' in Element.prototype ? 'matches' : 'msMatchesSelec
|
|
|
16
17
|
*/
|
|
17
18
|
function isFocusable(element) {
|
|
18
19
|
// Elements that cannot be focused if they have [disabled] attribute.
|
|
20
|
+
// @ts-ignore - msMatchesSelector is legacy
|
|
19
21
|
if (element[matchesFunc]('input, select, textarea, button, object')) {
|
|
22
|
+
// @ts-ignore
|
|
20
23
|
return element[matchesFunc](':not([disabled])');
|
|
21
24
|
}
|
|
22
25
|
|
|
23
26
|
// Elements that can be focused even if they have [disabled] attribute.
|
|
27
|
+
// @ts-ignore
|
|
24
28
|
return element[matchesFunc]('a[href], area[href], iframe, [tabindex], [contentEditable]');
|
|
25
29
|
}
|
|
26
30
|
|
|
@@ -19,6 +19,9 @@ export function isEqualConfig(a, b) {
|
|
|
19
19
|
if (aProps.length !== bProps.length) {
|
|
20
20
|
return false;
|
|
21
21
|
}
|
|
22
|
-
const isEqual =
|
|
22
|
+
const isEqual =
|
|
23
|
+
/** @param {string} prop */
|
|
24
|
+
// @ts-ignore - dynamic property access
|
|
25
|
+
prop => isEqualConfig(a[prop], b[prop]);
|
|
23
26
|
return aProps.every(isEqual);
|
|
24
27
|
}
|
|
@@ -403,7 +403,7 @@ describe('OverlayController', () => {
|
|
|
403
403
|
{ ignoreAttributes: ['closedby'] },
|
|
404
404
|
);
|
|
405
405
|
|
|
406
|
-
expect(el).lightDom.to.equal(`<div slot="content">projected</div>`);
|
|
406
|
+
expect(el).lightDom.to.equal(`<div data-content="" slot="content">projected</div>`);
|
|
407
407
|
});
|
|
408
408
|
});
|
|
409
409
|
|
|
@@ -425,7 +425,7 @@ describe('OverlayController', () => {
|
|
|
425
425
|
`
|
|
426
426
|
<dialog data-overlay-outer-wrapper="" open="" role="none" style="${wrappingDialogNodeStyle}">
|
|
427
427
|
<div data-id="content-wrapper">
|
|
428
|
-
<div id="content">non projected</div>
|
|
428
|
+
<div data-content="" id="content">non projected</div>
|
|
429
429
|
</div>
|
|
430
430
|
</dialog>
|
|
431
431
|
`,
|
|
@@ -1384,6 +1384,109 @@ describe('OverlayController', () => {
|
|
|
1384
1384
|
await ctrl1.hide();
|
|
1385
1385
|
expect(Array.from(document.body.classList)).to.contain('overlays-scroll-lock');
|
|
1386
1386
|
});
|
|
1387
|
+
|
|
1388
|
+
it('does not accumulate body margins when nested overlays have preventsScroll', async () => {
|
|
1389
|
+
const ctrl0 = new OverlayController({
|
|
1390
|
+
...withGlobalTestConfig(),
|
|
1391
|
+
preventsScroll: true,
|
|
1392
|
+
});
|
|
1393
|
+
const ctrl1 = new OverlayController({
|
|
1394
|
+
...withGlobalTestConfig(),
|
|
1395
|
+
preventsScroll: true,
|
|
1396
|
+
});
|
|
1397
|
+
|
|
1398
|
+
const originalMarginRight = document.body.style.marginRight;
|
|
1399
|
+
|
|
1400
|
+
await ctrl0.show();
|
|
1401
|
+
const marginAfterFirst = document.body.style.marginRight;
|
|
1402
|
+
|
|
1403
|
+
await ctrl1.show();
|
|
1404
|
+
const marginAfterSecond = document.body.style.marginRight;
|
|
1405
|
+
|
|
1406
|
+
// The margin should NOT increase further when second overlay opens
|
|
1407
|
+
expect(marginAfterSecond).to.equal(marginAfterFirst);
|
|
1408
|
+
|
|
1409
|
+
await ctrl1.hide();
|
|
1410
|
+
// After hiding second, first still prevents scroll — margin stays
|
|
1411
|
+
expect(document.body.style.marginRight).to.equal(marginAfterFirst);
|
|
1412
|
+
|
|
1413
|
+
await ctrl0.hide();
|
|
1414
|
+
// After hiding all, original margin is restored
|
|
1415
|
+
expect(document.body.style.marginRight).to.equal(originalMarginRight);
|
|
1416
|
+
});
|
|
1417
|
+
|
|
1418
|
+
it('restores body margin when overlay with preventsScroll is torn down while shown', async () => {
|
|
1419
|
+
const ctrl = new OverlayController({
|
|
1420
|
+
...withGlobalTestConfig(),
|
|
1421
|
+
preventsScroll: true,
|
|
1422
|
+
});
|
|
1423
|
+
|
|
1424
|
+
const originalMarginRight = document.body.style.marginRight;
|
|
1425
|
+
|
|
1426
|
+
await ctrl.show();
|
|
1427
|
+
const marginAfterShow = document.body.style.marginRight;
|
|
1428
|
+
// Margin should be set after show
|
|
1429
|
+
expect(marginAfterShow).to.not.equal(originalMarginRight);
|
|
1430
|
+
|
|
1431
|
+
ctrl.teardown();
|
|
1432
|
+
// Margin should be restored after teardown
|
|
1433
|
+
expect(document.body.style.marginRight).to.equal(originalMarginRight);
|
|
1434
|
+
});
|
|
1435
|
+
|
|
1436
|
+
it('does not break body margin when teardown() is called on a hidden overlay', async () => {
|
|
1437
|
+
const ctrl0 = new OverlayController({
|
|
1438
|
+
...withGlobalTestConfig(),
|
|
1439
|
+
preventsScroll: true,
|
|
1440
|
+
});
|
|
1441
|
+
const ctrl1 = new OverlayController({
|
|
1442
|
+
...withGlobalTestConfig(),
|
|
1443
|
+
preventsScroll: true,
|
|
1444
|
+
});
|
|
1445
|
+
|
|
1446
|
+
const originalMarginRight = document.body.style.marginRight;
|
|
1447
|
+
|
|
1448
|
+
// Show first overlay
|
|
1449
|
+
await ctrl0.show();
|
|
1450
|
+
const marginAfterFirst = document.body.style.marginRight;
|
|
1451
|
+
expect(marginAfterFirst).to.not.equal(originalMarginRight);
|
|
1452
|
+
|
|
1453
|
+
// Teardown second overlay that was never shown
|
|
1454
|
+
ctrl1.teardown();
|
|
1455
|
+
// Margin should still be set by first overlay
|
|
1456
|
+
expect(document.body.style.marginRight).to.equal(marginAfterFirst);
|
|
1457
|
+
|
|
1458
|
+
// Hide first overlay
|
|
1459
|
+
await ctrl0.hide();
|
|
1460
|
+
// Now margin should be restored
|
|
1461
|
+
expect(document.body.style.marginRight).to.equal(originalMarginRight);
|
|
1462
|
+
});
|
|
1463
|
+
|
|
1464
|
+
it('does not break body margin when updateConfig() is called on a hidden overlay', async () => {
|
|
1465
|
+
const ctrl = new OverlayController({
|
|
1466
|
+
...withGlobalTestConfig(),
|
|
1467
|
+
preventsScroll: true,
|
|
1468
|
+
});
|
|
1469
|
+
|
|
1470
|
+
const originalMarginRight = document.body.style.marginRight;
|
|
1471
|
+
|
|
1472
|
+
// updateConfig calls teardown internally
|
|
1473
|
+
ctrl.updateConfig({
|
|
1474
|
+
...withGlobalTestConfig(),
|
|
1475
|
+
preventsScroll: true,
|
|
1476
|
+
});
|
|
1477
|
+
|
|
1478
|
+
// Margin should not be affected
|
|
1479
|
+
expect(document.body.style.marginRight).to.equal(originalMarginRight);
|
|
1480
|
+
|
|
1481
|
+
// Show after updateConfig
|
|
1482
|
+
await ctrl.show();
|
|
1483
|
+
const marginAfterShow = document.body.style.marginRight;
|
|
1484
|
+
expect(marginAfterShow).to.not.equal(originalMarginRight);
|
|
1485
|
+
|
|
1486
|
+
// Hide should restore
|
|
1487
|
+
await ctrl.hide();
|
|
1488
|
+
expect(document.body.style.marginRight).to.equal(originalMarginRight);
|
|
1489
|
+
});
|
|
1387
1490
|
});
|
|
1388
1491
|
|
|
1389
1492
|
describe('hasBackdrop', () => {
|
|
@@ -2180,15 +2283,23 @@ describe('OverlayController', () => {
|
|
|
2180
2283
|
it('should not run with scroll prevention', async () => {
|
|
2181
2284
|
await overlayControllerNoPrevent.show();
|
|
2182
2285
|
|
|
2183
|
-
expect(
|
|
2184
|
-
|
|
2286
|
+
expect(
|
|
2287
|
+
overlayControllerNoPrevent.manager.__forTesting.bodySizeVars.marginRightInline,
|
|
2288
|
+
).to.equal(undefined);
|
|
2289
|
+
expect(overlayControllerNoPrevent.manager.__forTesting.bodySizeVars.marginRight).to.equal(
|
|
2290
|
+
undefined,
|
|
2291
|
+
);
|
|
2185
2292
|
});
|
|
2186
2293
|
|
|
2187
2294
|
it('should run with scroll prevention', async () => {
|
|
2188
2295
|
await overlayControllerPreventsScroll.show();
|
|
2189
2296
|
|
|
2190
|
-
expect(
|
|
2191
|
-
|
|
2297
|
+
expect(
|
|
2298
|
+
overlayControllerPreventsScroll.manager.__forTesting.bodySizeVars.marginRightInline,
|
|
2299
|
+
).to.not.equal(undefined);
|
|
2300
|
+
expect(
|
|
2301
|
+
overlayControllerPreventsScroll.manager.__forTesting.bodySizeVars.marginRight,
|
|
2302
|
+
).to.not.equal(undefined);
|
|
2192
2303
|
});
|
|
2193
2304
|
});
|
|
2194
2305
|
});
|
|
@@ -46,7 +46,7 @@ describe('OverlaysManager', () => {
|
|
|
46
46
|
// @ts-ignore [allow-private-in-test]
|
|
47
47
|
expect(mngr.__shownList).to.be.empty;
|
|
48
48
|
// @ts-ignore [allow-private-in-test]
|
|
49
|
-
expect(mngr.
|
|
49
|
+
expect(mngr._siblingsInert).to.be.false;
|
|
50
50
|
});
|
|
51
51
|
|
|
52
52
|
it('can add/remove controllers', () => {
|
|
@@ -11,6 +11,15 @@ export type ViewportPlacement =
|
|
|
11
11
|
| 'bottom-left'
|
|
12
12
|
| 'left';
|
|
13
13
|
|
|
14
|
+
export type OverlayPhase =
|
|
15
|
+
| 'setup'
|
|
16
|
+
| 'init'
|
|
17
|
+
| 'teardown'
|
|
18
|
+
| 'before-show'
|
|
19
|
+
| 'show'
|
|
20
|
+
| 'hide'
|
|
21
|
+
| 'add'
|
|
22
|
+
| 'remove';
|
|
14
23
|
|
|
15
24
|
export interface ViewportConfig {
|
|
16
25
|
placement: ViewportPlacement;
|
|
@@ -87,14 +96,20 @@ export interface OverlayConfig {
|
|
|
87
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) */
|
|
88
97
|
invokerRelation?: 'label' | 'description';
|
|
89
98
|
|
|
90
|
-
/** render a div instead of dialog */
|
|
91
|
-
_noDialogEl?: Boolean;
|
|
92
|
-
|
|
93
99
|
/**
|
|
94
100
|
* Determines the conditions hiding/showing should be based on. It gets the OverlayController as input and returns an object with
|
|
95
101
|
* functions with Overlay phases as keys
|
|
96
102
|
*/
|
|
97
103
|
visibilityTriggerFunction?: Function;
|
|
98
|
-
}
|
|
99
104
|
|
|
105
|
+
/**
|
|
106
|
+
* Whether the overlay content should receive focus when shown.
|
|
107
|
+
*/
|
|
108
|
+
focusContentOnOpen?: boolean;
|
|
100
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
|
+
isOpenable?: boolean;
|
|
115
|
+
}
|
|
@@ -832,6 +832,7 @@ describe('lion-select-rich', () => {
|
|
|
832
832
|
await waitUntil(isSelectRichRendered);
|
|
833
833
|
getInvoker()?.click();
|
|
834
834
|
await waitUntil(isDialogVisible);
|
|
835
|
+
// @ts-ignore - NodeList array access
|
|
835
836
|
const optionBlue = /** @type { HTMLElement | undefined } */ (
|
|
836
837
|
wrapperElementShadowRoot?.querySelectorAll('lion-option')
|
|
837
838
|
)?.[1];
|
|
@@ -955,6 +956,7 @@ describe('lion-select-rich', () => {
|
|
|
955
956
|
await waitUntil(isSelectRichRendered);
|
|
956
957
|
getInvoker()?.click();
|
|
957
958
|
await waitUntil(isDialogVisible);
|
|
959
|
+
// @ts-ignore - NodeList array access
|
|
958
960
|
const optionBlue = /** @type { HTMLElement | undefined } */ (
|
|
959
961
|
wrapperElementShadowRoot?.querySelectorAll('lion-option')
|
|
960
962
|
)?.[1];
|
|
@@ -1082,6 +1084,7 @@ describe('lion-select-rich', () => {
|
|
|
1082
1084
|
await waitUntil(isSelectRichRendered);
|
|
1083
1085
|
getInvoker()?.click();
|
|
1084
1086
|
await waitUntil(isDialogVisible);
|
|
1087
|
+
// @ts-ignore - NodeList array access
|
|
1085
1088
|
const optionBlue = /** @type { HTMLElement | undefined } */ (
|
|
1086
1089
|
wrapperElementShadowRoot?.querySelectorAll('lion-option')
|
|
1087
1090
|
)?.[1];
|