@lion/ui 0.18.0-menu-system.0 → 0.18.0-menu-system.2
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/components/menu/src/MoreButtonMenuMixin.js +11 -7
- package/components/overlays/src/OverlayController.js +49 -14
- package/components/overlays/test/OverlayController.test.js +122 -11
- package/components/overlays/types/ArrowMixinTypes.ts +3 -1
- package/components/overlays/types/OverlayConfig.ts +5 -1
- package/custom-elements.json +82 -40
- package/dist-types/components/dialog/src/LionDialog.d.ts +3 -1
- package/dist-types/components/dialog/src/LionDialog.d.ts.map +1 -1
- package/dist-types/components/menu/src/LionMenuOverlay.d.ts +3 -1
- package/dist-types/components/menu/src/LionMenuOverlay.d.ts.map +1 -1
- package/dist-types/components/menu/src/MoreButtonMenuMixin.d.ts.map +1 -1
- package/dist-types/components/overlays/src/OverlayController.d.ts +16 -0
- package/dist-types/components/overlays/src/OverlayController.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 +3 -1
- package/dist-types/components/overlays/types/OverlayConfig.d.ts.map +1 -1
- package/dist-types/components/select-rich/src/LionSelectRich.d.ts +3 -1
- package/dist-types/components/select-rich/src/LionSelectRich.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/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-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/radio-group/overview.md +3 -3
- package/docs/components/select/use-cases.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 +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 +36 -34
- 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/menu.js +1 -0
- package/menu.js +1 -0
- package/package.json +1 -1
|
@@ -182,7 +182,13 @@ export const MoreButtonMenuMixin = superclass =>
|
|
|
182
182
|
}
|
|
183
183
|
|
|
184
184
|
doItemsFit() {
|
|
185
|
-
|
|
185
|
+
this.style.display = 'none';
|
|
186
|
+
const parentWidth = this.parentElement.clientWidth;
|
|
187
|
+
this.style.display = '';
|
|
188
|
+
return (
|
|
189
|
+
this._listNode.scrollWidth === this._listNode.clientWidth &&
|
|
190
|
+
this._listNode.scrollWidth <= parentWidth
|
|
191
|
+
);
|
|
186
192
|
}
|
|
187
193
|
|
|
188
194
|
getListItems() {
|
|
@@ -210,16 +216,11 @@ export const MoreButtonMenuMixin = superclass =>
|
|
|
210
216
|
|
|
211
217
|
const nextNodes = [];
|
|
212
218
|
let { nextSibling } = listItem;
|
|
213
|
-
let includeOneMoreAfterComment = false;
|
|
214
219
|
while (nextSibling) {
|
|
215
220
|
nextNodes.push(nextSibling);
|
|
216
221
|
|
|
217
|
-
if (includeOneMoreAfterComment) {
|
|
218
|
-
break;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
222
|
if (isMarkerComment(nextSibling)) {
|
|
222
|
-
|
|
223
|
+
break;
|
|
223
224
|
}
|
|
224
225
|
|
|
225
226
|
({ nextSibling } = nextSibling);
|
|
@@ -285,12 +286,15 @@ export const MoreButtonMenuMixin = superclass =>
|
|
|
285
286
|
this.hideMoreButton();
|
|
286
287
|
|
|
287
288
|
if (this.doItemsFit()) {
|
|
289
|
+
this.style.visibility = '';
|
|
288
290
|
return;
|
|
289
291
|
}
|
|
290
292
|
|
|
293
|
+
this.style.visibility = 'hidden';
|
|
291
294
|
this.displayMoreButton();
|
|
292
295
|
const hiddenItemsCount = this.hideItemsOneByOneInMainMenuUntilTheyFit();
|
|
293
296
|
this.moveHiddenItemsFromMainMenuToMoreButtonMenu(hiddenItemsCount);
|
|
297
|
+
this.style.visibility = '';
|
|
294
298
|
}, 50);
|
|
295
299
|
}
|
|
296
300
|
};
|
|
@@ -237,8 +237,7 @@ export class OverlayController extends EventTarget {
|
|
|
237
237
|
placement: 'center',
|
|
238
238
|
},
|
|
239
239
|
zIndex: 9999,
|
|
240
|
-
|
|
241
|
-
isOpenable: true,
|
|
240
|
+
isActivated: true,
|
|
242
241
|
focusContentOnOpen: false,
|
|
243
242
|
// This means that content will have visually-hidden / sr-only styles. This is handy for:
|
|
244
243
|
// - hidden menus that should be "indexable" by screen readers (like the Links list in VO: https://support.apple.com/en-gb/guide/voiceover/mchlp2719/mac)
|
|
@@ -247,6 +246,11 @@ export class OverlayController extends EventTarget {
|
|
|
247
246
|
// @ts-ignore - hideVisually is an extension property
|
|
248
247
|
hideVisually: false,
|
|
249
248
|
requireConnectedNodes: true,
|
|
249
|
+
|
|
250
|
+
// hides children overlays when parent is closed...
|
|
251
|
+
syncChildrenCloseState: false,
|
|
252
|
+
// // In next major, we remove this prop. Now we disable it for backwards compatibility and enable it in the places we need it internally
|
|
253
|
+
// _shouldTeardownDomStructure: false,
|
|
250
254
|
};
|
|
251
255
|
|
|
252
256
|
/** @protected */
|
|
@@ -272,7 +276,7 @@ export class OverlayController extends EventTarget {
|
|
|
272
276
|
this.__escKeyHandlerCalled = false;
|
|
273
277
|
}
|
|
274
278
|
|
|
275
|
-
|
|
279
|
+
__hasSetup = false;
|
|
276
280
|
|
|
277
281
|
/**
|
|
278
282
|
* The invokerNode
|
|
@@ -540,7 +544,7 @@ export class OverlayController extends EventTarget {
|
|
|
540
544
|
},
|
|
541
545
|
};
|
|
542
546
|
|
|
543
|
-
const shouldUpdate = !this
|
|
547
|
+
const shouldUpdate = !this.__hasSetup || !isEqualConfig(prevConfig, newConfig);
|
|
544
548
|
if (!shouldUpdate) return;
|
|
545
549
|
// Teardown all previous configs
|
|
546
550
|
|
|
@@ -592,7 +596,7 @@ export class OverlayController extends EventTarget {
|
|
|
592
596
|
* @protected
|
|
593
597
|
*/
|
|
594
598
|
_init() {
|
|
595
|
-
if (!this.config.
|
|
599
|
+
if (!this.config.isActivated) return;
|
|
596
600
|
|
|
597
601
|
// TODO: should not be behind a flag when we are fully tearing down...
|
|
598
602
|
// TODO 2: When we move away from dialog (use popover to paint to top layer)
|
|
@@ -627,7 +631,7 @@ export class OverlayController extends EventTarget {
|
|
|
627
631
|
// Use event delegation to listen for clicks on close buttons...
|
|
628
632
|
this.contentNode.addEventListener('click', this.#hideOnCloseButtonClick);
|
|
629
633
|
|
|
630
|
-
this
|
|
634
|
+
this.__hasSetup = true;
|
|
631
635
|
}
|
|
632
636
|
|
|
633
637
|
#hideOnCloseButtonClick = (/** @type {{ target: any; }} */ ev) => {
|
|
@@ -981,7 +985,7 @@ export class OverlayController extends EventTarget {
|
|
|
981
985
|
*/
|
|
982
986
|
async hide() {
|
|
983
987
|
// Function like a no-op for dynamic edge cases...
|
|
984
|
-
if (!this.config.
|
|
988
|
+
if (!this.config.isActivated) return;
|
|
985
989
|
|
|
986
990
|
this._hideComplete = new Promise(resolve => {
|
|
987
991
|
this._hideResolve = resolve;
|
|
@@ -1135,24 +1139,53 @@ export class OverlayController extends EventTarget {
|
|
|
1135
1139
|
if (this.visibilityTriggerFunction) {
|
|
1136
1140
|
this._handleVisibilityTriggers({ phase });
|
|
1137
1141
|
}
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
this.contentNode?.setAttribute('tabindex', '-1');
|
|
1142
|
+
if (this.config.syncChildrenCloseState) {
|
|
1143
|
+
this._handleSyncChildrenCloseState({ phase });
|
|
1141
1144
|
}
|
|
1145
|
+
if (this.config.focusContentOnOpen) {
|
|
1146
|
+
this._handleFocusContentOnOpen({ phase });
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1142
1149
|
|
|
1143
|
-
|
|
1150
|
+
/**
|
|
1151
|
+
* @param {{phase: OverlayPhase}} opts
|
|
1152
|
+
* @returns {void}
|
|
1153
|
+
*/
|
|
1154
|
+
_handleFocusContentOnOpen({ phase }) {
|
|
1155
|
+
if (phase === 'init') {
|
|
1156
|
+
this.contentNode?.setAttribute('tabindex', '-1');
|
|
1157
|
+
} else if (phase === 'teardown') {
|
|
1144
1158
|
// TODO: capture initial attr, use Resettable mechanism of VisibilityToggleCtrl in whole Controller
|
|
1145
1159
|
this.contentNode?.removeAttribute('tabindex');
|
|
1146
1160
|
}
|
|
1147
1161
|
}
|
|
1148
1162
|
|
|
1163
|
+
/**
|
|
1164
|
+
* @param {{phase: OverlayPhase}} opts
|
|
1165
|
+
* @returns {void}
|
|
1166
|
+
*/
|
|
1167
|
+
_handleSyncChildrenCloseState({ phase }) {
|
|
1168
|
+
if (phase !== 'hide') return;
|
|
1169
|
+
|
|
1170
|
+
const visibleChildren = this.manager.shownList.filter(
|
|
1171
|
+
ctrl => ctrl !== this && deepContains(this.contentNode, ctrl.contentNode),
|
|
1172
|
+
);
|
|
1173
|
+
visibleChildren.forEach(ctrl => ctrl.hide());
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1149
1176
|
/**
|
|
1150
1177
|
* @param {{ phase: OverlayPhase }} config
|
|
1151
1178
|
*/
|
|
1152
1179
|
_handleVisibilityTriggers({ phase }) {
|
|
1153
1180
|
if (typeof this.visibilityTriggerFunction !== 'function') return;
|
|
1154
1181
|
|
|
1155
|
-
|
|
1182
|
+
// Here we initialize the __visibilityTriggerHandler of our invokerNode. It's important that we ONLY do this on init,
|
|
1183
|
+
// otherwise we risk not being able to properly clean up listeners...
|
|
1184
|
+
if (phase === 'init') {
|
|
1185
|
+
this.__visibilityTriggerHandler = this.visibilityTriggerFunction({ controller: this });
|
|
1186
|
+
}
|
|
1187
|
+
// Here we run the appropriate lifecycle, if defined in our handler
|
|
1188
|
+
this.__visibilityTriggerHandler[phase]?.();
|
|
1156
1189
|
}
|
|
1157
1190
|
|
|
1158
1191
|
/**
|
|
@@ -1562,7 +1595,7 @@ export class OverlayController extends EventTarget {
|
|
|
1562
1595
|
}
|
|
1563
1596
|
|
|
1564
1597
|
teardown() {
|
|
1565
|
-
if (!this
|
|
1598
|
+
if (!this.__hasSetup) return;
|
|
1566
1599
|
this.__handleOverlayStyles({ phase: 'teardown' });
|
|
1567
1600
|
if (this.isShown) {
|
|
1568
1601
|
this._keepBodySize({ phase: 'teardown' });
|
|
@@ -1574,10 +1607,12 @@ export class OverlayController extends EventTarget {
|
|
|
1574
1607
|
|
|
1575
1608
|
this.contentNode?.removeEventListener('click', this.#hideOnCloseButtonClick);
|
|
1576
1609
|
|
|
1610
|
+
// if (this.config._shouldTeardownDomStructure) {
|
|
1577
1611
|
this.__rearrangeNodesCleanup?.();
|
|
1612
|
+
// }
|
|
1578
1613
|
this.__teardownVisibility();
|
|
1579
1614
|
|
|
1580
|
-
this
|
|
1615
|
+
this.__hasSetup = false;
|
|
1581
1616
|
}
|
|
1582
1617
|
|
|
1583
1618
|
/** @private */
|
|
@@ -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(),
|
|
@@ -347,6 +356,21 @@ describe('OverlayController', () => {
|
|
|
347
356
|
await ctrl.hide();
|
|
348
357
|
expect(ctrl.isShown).to.be.false;
|
|
349
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
|
+
// });
|
|
350
374
|
});
|
|
351
375
|
|
|
352
376
|
describe('Node Configuration', () => {
|
|
@@ -621,6 +645,7 @@ describe('OverlayController', () => {
|
|
|
621
645
|
});
|
|
622
646
|
});
|
|
623
647
|
|
|
648
|
+
// TODO: make features modular (so they can be treeshaken) and test their lifecycle within this desrcibe
|
|
624
649
|
describe('Feature Configuration', () => {
|
|
625
650
|
describe('trapsKeyboardFocus', () => {
|
|
626
651
|
it('focuses the overlay on show', async () => {
|
|
@@ -983,6 +1008,7 @@ describe('OverlayController', () => {
|
|
|
983
1008
|
});
|
|
984
1009
|
});
|
|
985
1010
|
});
|
|
1011
|
+
|
|
986
1012
|
describe('hidesOnOutsideClick', () => {
|
|
987
1013
|
it('hides on outside click', async () => {
|
|
988
1014
|
const contentNode = /** @type {HTMLElement} */ (await fixture('<div>Content</div>'));
|
|
@@ -1703,6 +1729,91 @@ describe('OverlayController', () => {
|
|
|
1703
1729
|
expect(ctrl1.hasActiveBackdrop).to.be.true;
|
|
1704
1730
|
});
|
|
1705
1731
|
});
|
|
1732
|
+
|
|
1733
|
+
describe('focusContentOnOpen', () => {
|
|
1734
|
+
it('adds tabindex="-1" to the content node when focusContentOnOpen is true', async () => {
|
|
1735
|
+
const ctrl = new OverlayController({
|
|
1736
|
+
...withGlobalTestConfig(),
|
|
1737
|
+
isBlocking: false,
|
|
1738
|
+
focusContentOnOpen: true,
|
|
1739
|
+
});
|
|
1740
|
+
const contentNode = /** @type {HTMLElement} */ (await fixture('<div>Content</div>'));
|
|
1741
|
+
ctrl.updateConfig({ contentNode });
|
|
1742
|
+
await ctrl.show();
|
|
1743
|
+
expect(contentNode.getAttribute('tabindex')).to.equal('-1');
|
|
1744
|
+
});
|
|
1745
|
+
|
|
1746
|
+
it('makes contentNode the root of "next tab flow"', async () => {
|
|
1747
|
+
const ctrl = new OverlayController({
|
|
1748
|
+
...withGlobalTestConfig(),
|
|
1749
|
+
isBlocking: false,
|
|
1750
|
+
focusContentOnOpen: true,
|
|
1751
|
+
});
|
|
1752
|
+
const contentNode = /** @type {HTMLElement} */ (
|
|
1753
|
+
await fixture('<div><button>Button</button></div>')
|
|
1754
|
+
);
|
|
1755
|
+
ctrl.updateConfig({ contentNode });
|
|
1756
|
+
await ctrl.show();
|
|
1757
|
+
const button = /** @type {HTMLButtonElement} */ (contentNode.querySelector('button'));
|
|
1758
|
+
button.focus();
|
|
1759
|
+
expect(isActiveElement(button)).to.be.true;
|
|
1760
|
+
});
|
|
1761
|
+
});
|
|
1762
|
+
|
|
1763
|
+
describe('syncChildrenCloseState', () => {
|
|
1764
|
+
it('does not close all children of nested controllers when syncChildrenCloseState is false', async () => {
|
|
1765
|
+
const parentContent = /** @type {HTMLDivElement} */ (
|
|
1766
|
+
await fixture(
|
|
1767
|
+
html` <!-- -->
|
|
1768
|
+
<div data-sync-children-close-state id="parent-overlay">
|
|
1769
|
+
<div id="child-overlay">we open our child and it will close when parent does</div>
|
|
1770
|
+
</div>`,
|
|
1771
|
+
)
|
|
1772
|
+
);
|
|
1773
|
+
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
1774
|
+
expect(parentOverlay.isShown).to.be.true;
|
|
1775
|
+
expect(childOverlay.isShown).to.be.true;
|
|
1776
|
+
|
|
1777
|
+
await parentOverlay.hide();
|
|
1778
|
+
await childOverlay._hideComplete;
|
|
1779
|
+
expect(parentOverlay.isShown).to.be.false;
|
|
1780
|
+
expect(childOverlay.isShown).to.be.false;
|
|
1781
|
+
});
|
|
1782
|
+
|
|
1783
|
+
it('does not close all children of nested controllers when syncChildrenCloseState is false', async () => {
|
|
1784
|
+
const parentContent = /** @type {HTMLDivElement} */ (
|
|
1785
|
+
await fixture(
|
|
1786
|
+
html` <!-- -->
|
|
1787
|
+
<div id="parent-overlay">
|
|
1788
|
+
<div id="child-overlay">
|
|
1789
|
+
we open our child and it will not close when parent does
|
|
1790
|
+
</div>
|
|
1791
|
+
</div>`,
|
|
1792
|
+
)
|
|
1793
|
+
);
|
|
1794
|
+
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
1795
|
+
expect(parentOverlay.isShown).to.be.true;
|
|
1796
|
+
expect(childOverlay.isShown).to.be.true;
|
|
1797
|
+
|
|
1798
|
+
await parentOverlay.hide();
|
|
1799
|
+
expect(parentOverlay.isShown).to.be.false;
|
|
1800
|
+
expect(childOverlay.isShown).to.be.true;
|
|
1801
|
+
});
|
|
1802
|
+
});
|
|
1803
|
+
|
|
1804
|
+
describe('isActivated', () => {
|
|
1805
|
+
it('allows to conditionally disable overlay/openable functionality (for responsive context like nav menus, accordions/collapsibles vs plain headings/content etc.)', async () => {
|
|
1806
|
+
const ctrl = new OverlayController({
|
|
1807
|
+
...withGlobalTestConfig(),
|
|
1808
|
+
isActivated: false,
|
|
1809
|
+
});
|
|
1810
|
+
expect(ctrl.__hasSetup).to.be.false;
|
|
1811
|
+
ctrl.updateConfig({
|
|
1812
|
+
isActivated: true,
|
|
1813
|
+
});
|
|
1814
|
+
expect(ctrl.__hasSetup).to.be.true;
|
|
1815
|
+
});
|
|
1816
|
+
});
|
|
1706
1817
|
});
|
|
1707
1818
|
|
|
1708
1819
|
describe('Show / Hide / Toggle', () => {
|
|
@@ -26,7 +26,9 @@ export declare class ArrowHost {
|
|
|
26
26
|
|
|
27
27
|
protected _defineOverlayConfig(): OverlayConfig;
|
|
28
28
|
|
|
29
|
-
protected _getPopperArrowConfig(
|
|
29
|
+
protected _getPopperArrowConfig(
|
|
30
|
+
popperConfigToExtendFrom: Partial<PopperOptions>,
|
|
31
|
+
): Partial<PopperOptions>;
|
|
30
32
|
|
|
31
33
|
private __setupRepositionCompletePromise(): void;
|
|
32
34
|
|
|
@@ -111,11 +111,15 @@ export interface OverlayConfig {
|
|
|
111
111
|
* By default, we function either as overlay or disclosure. In some cases, this should be dynamically set (think of responsive changes).
|
|
112
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
113
|
*/
|
|
114
|
-
|
|
114
|
+
isActivated?: boolean;
|
|
115
115
|
|
|
116
116
|
/**
|
|
117
117
|
* By default, an error is thrown when contentNode is not connected to the DOM.
|
|
118
118
|
* This allows to prepare nodes and later connect them to dom.
|
|
119
119
|
*/
|
|
120
120
|
requireConnectedNodes?: boolean;
|
|
121
|
+
|
|
122
|
+
syncChildrenCloseState?: boolean;
|
|
123
|
+
|
|
124
|
+
_shouldTeardownDomStructure?: boolean;
|
|
121
125
|
}
|
package/custom-elements.json
CHANGED
|
@@ -2252,36 +2252,6 @@
|
|
|
2252
2252
|
}
|
|
2253
2253
|
]
|
|
2254
2254
|
},
|
|
2255
|
-
{
|
|
2256
|
-
"kind": "javascript-module",
|
|
2257
|
-
"path": "exports/define-helpers/sb-action-logger.js",
|
|
2258
|
-
"declarations": [],
|
|
2259
|
-
"exports": [
|
|
2260
|
-
{
|
|
2261
|
-
"kind": "custom-element-definition",
|
|
2262
|
-
"name": "sb-action-logger",
|
|
2263
|
-
"declaration": {
|
|
2264
|
-
"name": "SbActionLogger",
|
|
2265
|
-
"module": "/exports/helpers.js"
|
|
2266
|
-
}
|
|
2267
|
-
}
|
|
2268
|
-
]
|
|
2269
|
-
},
|
|
2270
|
-
{
|
|
2271
|
-
"kind": "javascript-module",
|
|
2272
|
-
"path": "exports/define-helpers/sb-locale-switcher.js",
|
|
2273
|
-
"declarations": [],
|
|
2274
|
-
"exports": [
|
|
2275
|
-
{
|
|
2276
|
-
"kind": "custom-element-definition",
|
|
2277
|
-
"name": "sb-locale-switcher",
|
|
2278
|
-
"declaration": {
|
|
2279
|
-
"name": "SbLocaleSwitcher",
|
|
2280
|
-
"module": "/exports/helpers.js"
|
|
2281
|
-
}
|
|
2282
|
-
}
|
|
2283
|
-
]
|
|
2284
|
-
},
|
|
2285
2255
|
{
|
|
2286
2256
|
"kind": "javascript-module",
|
|
2287
2257
|
"path": "exports/define/lion-accordion.js",
|
|
@@ -3077,6 +3047,36 @@
|
|
|
3077
3047
|
}
|
|
3078
3048
|
]
|
|
3079
3049
|
},
|
|
3050
|
+
{
|
|
3051
|
+
"kind": "javascript-module",
|
|
3052
|
+
"path": "exports/define-helpers/sb-action-logger.js",
|
|
3053
|
+
"declarations": [],
|
|
3054
|
+
"exports": [
|
|
3055
|
+
{
|
|
3056
|
+
"kind": "custom-element-definition",
|
|
3057
|
+
"name": "sb-action-logger",
|
|
3058
|
+
"declaration": {
|
|
3059
|
+
"name": "SbActionLogger",
|
|
3060
|
+
"module": "/exports/helpers.js"
|
|
3061
|
+
}
|
|
3062
|
+
}
|
|
3063
|
+
]
|
|
3064
|
+
},
|
|
3065
|
+
{
|
|
3066
|
+
"kind": "javascript-module",
|
|
3067
|
+
"path": "exports/define-helpers/sb-locale-switcher.js",
|
|
3068
|
+
"declarations": [],
|
|
3069
|
+
"exports": [
|
|
3070
|
+
{
|
|
3071
|
+
"kind": "custom-element-definition",
|
|
3072
|
+
"name": "sb-locale-switcher",
|
|
3073
|
+
"declaration": {
|
|
3074
|
+
"name": "SbLocaleSwitcher",
|
|
3075
|
+
"module": "/exports/helpers.js"
|
|
3076
|
+
}
|
|
3077
|
+
}
|
|
3078
|
+
]
|
|
3079
|
+
},
|
|
3080
3080
|
{
|
|
3081
3081
|
"kind": "javascript-module",
|
|
3082
3082
|
"path": "components/accordion/src/LionAccordion.js",
|
|
@@ -131886,15 +131886,6 @@
|
|
|
131886
131886
|
}
|
|
131887
131887
|
}
|
|
131888
131888
|
},
|
|
131889
|
-
{
|
|
131890
|
-
"kind": "field",
|
|
131891
|
-
"name": "#hasSetup",
|
|
131892
|
-
"privacy": "private",
|
|
131893
|
-
"type": {
|
|
131894
|
-
"text": "boolean"
|
|
131895
|
-
},
|
|
131896
|
-
"default": "false"
|
|
131897
|
-
},
|
|
131898
131889
|
{
|
|
131899
131890
|
"kind": "field",
|
|
131900
131891
|
"name": "#hideOnCloseButtonClick",
|
|
@@ -132378,7 +132369,7 @@
|
|
|
132378
132369
|
"text": "OverlayConfig"
|
|
132379
132370
|
},
|
|
132380
132371
|
"privacy": "protected",
|
|
132381
|
-
"default": "{ placementMode: undefined, contentNode: config.contentNode, contentWrapperNode: config.contentWrapperNode, invokerNode: config.invokerNode, backdropNode: config.backdropNode, referenceNode: undefined, elementToFocusAfterHide: config.invokerNode, inheritsReferenceWidth: 'none', hasBackdrop: false, isBlocking: false, preventsScroll: false, trapsKeyboardFocus: false, hidesOnEsc: false, hidesOnOutsideEsc: false, hidesOnOutsideClick: false, isTooltip: false, isAlertDialog: false, invokerRelation: 'description', visibilityTriggerFunction: undefined, handlesAccessibility: false, popperConfig: { placement: 'top', strategy: 'fixed', modifiers: [ { name: 'preventOverflow', enabled: true, options: { boundariesElement: 'viewport', padding: 8, // viewport-margin for shifting/sliding }, }, { name: 'flip', options: { boundariesElement: 'viewport', padding: 16, // viewport-margin for flipping }, }, { name: 'offset', enabled: true, options: { offset: [0, 8], // horizontal and vertical margin (distance between popper and referenceElement) }, }, { name: 'arrow', enabled: false, }, ], }, viewportConfig: { placement: 'center', }, zIndex: 9999,
|
|
132372
|
+
"default": "{ placementMode: undefined, contentNode: config.contentNode, contentWrapperNode: config.contentWrapperNode, invokerNode: config.invokerNode, backdropNode: config.backdropNode, referenceNode: undefined, elementToFocusAfterHide: config.invokerNode, inheritsReferenceWidth: 'none', hasBackdrop: false, isBlocking: false, preventsScroll: false, trapsKeyboardFocus: false, hidesOnEsc: false, hidesOnOutsideEsc: false, hidesOnOutsideClick: false, isTooltip: false, isAlertDialog: false, invokerRelation: 'description', visibilityTriggerFunction: undefined, handlesAccessibility: false, popperConfig: { placement: 'top', strategy: 'fixed', modifiers: [ { name: 'preventOverflow', enabled: true, options: { boundariesElement: 'viewport', padding: 8, // viewport-margin for shifting/sliding }, }, { name: 'flip', options: { boundariesElement: 'viewport', padding: 16, // viewport-margin for flipping }, }, { name: 'offset', enabled: true, options: { offset: [0, 8], // horizontal and vertical margin (distance between popper and referenceElement) }, }, { name: 'arrow', enabled: false, }, ], }, viewportConfig: { placement: 'center', }, zIndex: 9999, isActivated: true, focusContentOnOpen: false, // This means that content will have visually-hidden / sr-only styles. This is handy for: // - hidden menus that should be \"indexable\" by screen readers (like the Links list in VO: https://support.apple.com/en-gb/guide/voiceover/mchlp2719/mac) // - \"more\" menus that put content in a dropdown that do not fit in the current row // - menus that should generally open on tab. // @ts-ignore - hideVisually is an extension property hideVisually: false, requireConnectedNodes: true, // hides children overlays when parent is closed... syncChildrenCloseState: false, // // In next major, we remove this prop. Now we disable it for backwards compatibility and enable it in the places we need it internally // _shouldTeardownDomStructure: false, }"
|
|
132382
132373
|
},
|
|
132383
132374
|
{
|
|
132384
132375
|
"kind": "method",
|
|
@@ -132446,6 +132437,27 @@
|
|
|
132446
132437
|
"description": "All features are handled here.",
|
|
132447
132438
|
"privacy": "protected"
|
|
132448
132439
|
},
|
|
132440
|
+
{
|
|
132441
|
+
"kind": "method",
|
|
132442
|
+
"name": "_handleFocusContentOnOpen",
|
|
132443
|
+
"parameters": [
|
|
132444
|
+
{
|
|
132445
|
+
"name": "{ phase }"
|
|
132446
|
+
},
|
|
132447
|
+
{
|
|
132448
|
+
"name": "opts",
|
|
132449
|
+
"type": {
|
|
132450
|
+
"text": "{phase: OverlayPhase}"
|
|
132451
|
+
}
|
|
132452
|
+
}
|
|
132453
|
+
],
|
|
132454
|
+
"return": {
|
|
132455
|
+
"type": {
|
|
132456
|
+
"text": "void"
|
|
132457
|
+
}
|
|
132458
|
+
},
|
|
132459
|
+
"privacy": "protected"
|
|
132460
|
+
},
|
|
132449
132461
|
{
|
|
132450
132462
|
"kind": "method",
|
|
132451
132463
|
"name": "_handleHidesOnEsc",
|
|
@@ -132531,6 +132543,27 @@
|
|
|
132531
132543
|
],
|
|
132532
132544
|
"privacy": "protected"
|
|
132533
132545
|
},
|
|
132546
|
+
{
|
|
132547
|
+
"kind": "method",
|
|
132548
|
+
"name": "_handleSyncChildrenCloseState",
|
|
132549
|
+
"parameters": [
|
|
132550
|
+
{
|
|
132551
|
+
"name": "{ phase }"
|
|
132552
|
+
},
|
|
132553
|
+
{
|
|
132554
|
+
"name": "opts",
|
|
132555
|
+
"type": {
|
|
132556
|
+
"text": "{phase: OverlayPhase}"
|
|
132557
|
+
}
|
|
132558
|
+
}
|
|
132559
|
+
],
|
|
132560
|
+
"return": {
|
|
132561
|
+
"type": {
|
|
132562
|
+
"text": "void"
|
|
132563
|
+
}
|
|
132564
|
+
},
|
|
132565
|
+
"privacy": "protected"
|
|
132566
|
+
},
|
|
132534
132567
|
{
|
|
132535
132568
|
"kind": "method",
|
|
132536
132569
|
"name": "_handleTrapsKeyboardFocus",
|
|
@@ -132747,6 +132780,15 @@
|
|
|
132747
132780
|
"privacy": "private",
|
|
132748
132781
|
"default": "true"
|
|
132749
132782
|
},
|
|
132783
|
+
{
|
|
132784
|
+
"kind": "field",
|
|
132785
|
+
"name": "__hasSetup",
|
|
132786
|
+
"type": {
|
|
132787
|
+
"text": "boolean"
|
|
132788
|
+
},
|
|
132789
|
+
"default": "false",
|
|
132790
|
+
"privacy": "private"
|
|
132791
|
+
},
|
|
132750
132792
|
{
|
|
132751
132793
|
"kind": "method",
|
|
132752
132794
|
"name": "__initContentDomStructure",
|
|
@@ -34,8 +34,10 @@ export class LionDialog extends LionDialog_base {
|
|
|
34
34
|
invokerRelation?: "label" | "description" | undefined;
|
|
35
35
|
visibilityTriggerFunction?: Function | undefined;
|
|
36
36
|
focusContentOnOpen?: boolean | undefined;
|
|
37
|
-
|
|
37
|
+
isActivated?: boolean | undefined;
|
|
38
38
|
requireConnectedNodes?: boolean | undefined;
|
|
39
|
+
syncChildrenCloseState?: boolean | undefined;
|
|
40
|
+
_shouldTeardownDomStructure?: boolean | undefined;
|
|
39
41
|
};
|
|
40
42
|
render(): import("lit-html").TemplateResult<1>;
|
|
41
43
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LionDialog.d.ts","sourceRoot":"","sources":["../../../../components/dialog/src/LionDialog.js"],"names":[],"mappings":";AAGA;;GAEG;AACH;IACE,kBAAkB;IAClB,6BAIC;IAIC,uBAA0B;IAG5B;;OAEG;IAEH
|
|
1
|
+
{"version":3,"file":"LionDialog.d.ts","sourceRoot":"","sources":["../../../../components/dialog/src/LionDialog.js"],"names":[],"mappings":";AAGA;;GAEG;AACH;IACE,kBAAkB;IAClB,6BAIC;IAIC,uBAA0B;IAG5B;;OAEG;IAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAKC;IAED,+CAOC;CACF"}
|
|
@@ -992,8 +992,10 @@ export class LionMenuOverlay extends LionMenuOverlay_base {
|
|
|
992
992
|
invokerRelation?: "label" | "description" | undefined;
|
|
993
993
|
visibilityTriggerFunction?: Function | undefined;
|
|
994
994
|
focusContentOnOpen?: boolean | undefined;
|
|
995
|
-
|
|
995
|
+
isActivated?: boolean | undefined;
|
|
996
996
|
requireConnectedNodes?: boolean | undefined;
|
|
997
|
+
syncChildrenCloseState?: boolean | undefined;
|
|
998
|
+
_shouldTeardownDomStructure?: boolean | undefined;
|
|
997
999
|
};
|
|
998
1000
|
/**
|
|
999
1001
|
* @enhance InteractiveListMixin
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LionMenuOverlay.d.ts","sourceRoot":"","sources":["../../../../components/menu/src/LionMenuOverlay.js"],"names":[],"mappings":"AASA;;;;;;;;GAQG;AACH,wDAFW,OAAO,uBAAuB,EAAE,WAAW,CAAC,OAAO,KAAK,EAAE,UAAU,CAAC;;;;QA0B5E;;WAEG;;QAWH;;WAEG;;QAWH;;WAEG;;QAMH;;WAEG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAKJ;;;;;QAzCC;;WAEG;;QAWH;;WAEG;;QAWH;;WAEG;;QAMH;;WAEG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQP;IAaE
|
|
1
|
+
{"version":3,"file":"LionMenuOverlay.d.ts","sourceRoot":"","sources":["../../../../components/menu/src/LionMenuOverlay.js"],"names":[],"mappings":"AASA;;;;;;;;GAQG;AACH,wDAFW,OAAO,uBAAuB,EAAE,WAAW,CAAC,OAAO,KAAK,EAAE,UAAU,CAAC;;;;QA0B5E;;WAEG;;QAWH;;WAEG;;QAWH;;WAEG;;QAMH;;WAEG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAKJ;;;;;QAzCC;;WAEG;;QAWH;;WAEG;;QAWH;;WAEG;;QAMH;;WAEG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQP;IAaE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAkCC;IAED;;OAEG;IACH;;OAEG;IACH,4BAYC;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MoreButtonMenuMixin.d.ts","sourceRoot":"","sources":["../../../../components/menu/src/MoreButtonMenuMixin.js"],"names":[],"mappings":"AA6DO;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"MoreButtonMenuMixin.d.ts","sourceRoot":"","sources":["../../../../components/menu/src/MoreButtonMenuMixin.js"],"names":[],"mappings":"AA6DO;;;;;;;;;;;;;;;;;;QAyIH;;WAEG;iDADQ,IAAI;;;;;;;;EAoGhB"}
|
|
@@ -50,6 +50,7 @@ export class OverlayController extends EventTarget {
|
|
|
50
50
|
* @private
|
|
51
51
|
*/
|
|
52
52
|
private __escKeyHandlerCalled;
|
|
53
|
+
__hasSetup: boolean;
|
|
53
54
|
/**
|
|
54
55
|
* The invokerNode
|
|
55
56
|
* @type {HTMLElement | undefined}
|
|
@@ -350,12 +351,27 @@ export class OverlayController extends EventTarget {
|
|
|
350
351
|
protected _handleFeatures({ phase }: {
|
|
351
352
|
phase: OverlayPhase;
|
|
352
353
|
}): void;
|
|
354
|
+
/**
|
|
355
|
+
* @param {{phase: OverlayPhase}} opts
|
|
356
|
+
* @returns {void}
|
|
357
|
+
*/
|
|
358
|
+
_handleFocusContentOnOpen({ phase }: {
|
|
359
|
+
phase: OverlayPhase;
|
|
360
|
+
}): void;
|
|
361
|
+
/**
|
|
362
|
+
* @param {{phase: OverlayPhase}} opts
|
|
363
|
+
* @returns {void}
|
|
364
|
+
*/
|
|
365
|
+
_handleSyncChildrenCloseState({ phase }: {
|
|
366
|
+
phase: OverlayPhase;
|
|
367
|
+
}): void;
|
|
353
368
|
/**
|
|
354
369
|
* @param {{ phase: OverlayPhase }} config
|
|
355
370
|
*/
|
|
356
371
|
_handleVisibilityTriggers({ phase }: {
|
|
357
372
|
phase: OverlayPhase;
|
|
358
373
|
}): void;
|
|
374
|
+
__visibilityTriggerHandler: any;
|
|
359
375
|
/**
|
|
360
376
|
* @param {{ phase: OverlayPhase }} config
|
|
361
377
|
* @protected
|