Merge pull request #911 from ing-bank/feat/syncOverlays
feat(overlays): make OverlayController constructor tasks sync
This commit is contained in:
commit
c7b0709e98
15 changed files with 189 additions and 139 deletions
15
.changeset/friendly-dolphins-give.md
Normal file
15
.changeset/friendly-dolphins-give.md
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
---
|
||||||
|
'@lion/overlays': minor
|
||||||
|
'@lion/select-rich': minor
|
||||||
|
'@lion/dialog': minor
|
||||||
|
'@lion/input-datepicker': minor
|
||||||
|
'@lion/tooltip': minor
|
||||||
|
'@lion/form-integrations': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
- Make the OverlayController constructor phase synchronous.
|
||||||
|
- Trigger a setup of the OverlayController on every connectedCallback
|
||||||
|
- Execute a new OverlayController after (shadowDom) rendering of the element is done
|
||||||
|
- Teardown the OverlayController on every disconnectedCallback
|
||||||
|
- This means moving a dialog triggers teardown in the old location and setup in the new location
|
||||||
|
- Restore the original light dom (if needed) in the teardown phase of the OverlayController
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
"build:docs": "wca analyze \"packages/tabs/**/*.js\"",
|
"build:docs": "wca analyze \"packages/tabs/**/*.js\"",
|
||||||
"build:types": "tsc -p tsconfig.build.types.json",
|
"build:types": "tsc -p tsconfig.build.types.json",
|
||||||
"bundlesize": "rollup -c bundlesize/rollup.config.js && bundlesize",
|
"bundlesize": "rollup -c bundlesize/rollup.config.js && bundlesize",
|
||||||
"debug": "web-test-runner \"packages/dialog/test/**/*.test.js\" --watch",
|
"debug": "web-test-runner \"packages/input-datepicker/test/**/*.test.js\" --watch",
|
||||||
"dev-server": "es-dev-server",
|
"dev-server": "es-dev-server",
|
||||||
"format": "npm run format:eslint && npm run format:prettier",
|
"format": "npm run format:eslint && npm run format:prettier",
|
||||||
"format:eslint": "eslint --ext .js,.html . --fix",
|
"format:eslint": "eslint --ext .js,.html . --fix",
|
||||||
|
|
@ -48,7 +48,7 @@
|
||||||
"@storybook/addon-a11y": "~5.0.0",
|
"@storybook/addon-a11y": "~5.0.0",
|
||||||
"@types/chai-dom": "^0.0.8",
|
"@types/chai-dom": "^0.0.8",
|
||||||
"@web/dev-server-legacy": "^0.1.1",
|
"@web/dev-server-legacy": "^0.1.1",
|
||||||
"@web/test-runner": "^0.7.3",
|
"@web/test-runner": "^0.7.13",
|
||||||
"@web/test-runner-browserstack": "^0.1.1",
|
"@web/test-runner-browserstack": "^0.1.1",
|
||||||
"@web/test-runner-playwright": "^0.5.1",
|
"@web/test-runner-playwright": "^0.5.1",
|
||||||
"@web/test-runner-puppeteer": "^0.6.1",
|
"@web/test-runner-puppeteer": "^0.6.1",
|
||||||
|
|
|
||||||
|
|
@ -721,7 +721,6 @@ export function runValidateMixinSuite(customConfig) {
|
||||||
.modelValue=${''}
|
.modelValue=${''}
|
||||||
>${lightDom}</${tag}>
|
>${lightDom}</${tag}>
|
||||||
`));
|
`));
|
||||||
console.log(el._inputNode);
|
|
||||||
expect(el._inputNode?.getAttribute('aria-required')).to.equal('true');
|
expect(el._inputNode?.getAttribute('aria-required')).to.equal('true');
|
||||||
el.validators = [];
|
el.validators = [];
|
||||||
expect(el._inputNode?.getAttribute('aria-required')).to.be.null;
|
expect(el._inputNode?.getAttribute('aria-required')).to.be.null;
|
||||||
|
|
|
||||||
40
packages/form-integrations/docs/60-dialog-integration.md
Normal file
40
packages/form-integrations/docs/60-dialog-integration.md
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
[//]: # 'AUTO INSERT HEADER PREPUBLISH'
|
||||||
|
|
||||||
|
# Forms in a dialog
|
||||||
|
|
||||||
|
```js script
|
||||||
|
import { html } from 'lit-html';
|
||||||
|
import '@lion/dialog/lion-dialog.js';
|
||||||
|
import '@lion/select-rich/lion-select-rich.js';
|
||||||
|
import '@lion/select-rich/lion-options.js';
|
||||||
|
import '@lion/select-rich/lion-option.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: 'Forms/System/Dialog integrations',
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Opening a Rich Select inside a dialog
|
||||||
|
|
||||||
|
```js story
|
||||||
|
export const main = () => html`
|
||||||
|
<lion-dialog>
|
||||||
|
<button slot="invoker">Open Dialog</button>
|
||||||
|
<div slot="content">
|
||||||
|
<lion-select-rich name="favoriteColor" label="Favorite color">
|
||||||
|
<lion-options slot="input">
|
||||||
|
<lion-option .choiceValue=${'red'}>Red</lion-option>
|
||||||
|
<lion-option .choiceValue=${'hotpink'} checked>Hotpink</lion-option>
|
||||||
|
<lion-option .choiceValue=${'teal'}>Teal</lion-option>
|
||||||
|
</lion-options>
|
||||||
|
</lion-select-rich>
|
||||||
|
<button
|
||||||
|
class="close-button"
|
||||||
|
@click=${e => e.target.dispatchEvent(new Event('close-overlay', { bubbles: true }))}
|
||||||
|
>
|
||||||
|
⨯
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</lion-dialog>
|
||||||
|
`;
|
||||||
|
```
|
||||||
|
|
@ -207,7 +207,7 @@ export class LionInputDatepicker extends ScopedElementsMixin(OverlayMixin(LionIn
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defining this overlay as a templates lets OverlayInteraceMixin
|
* Defining this overlay as a templates from OverlayMixin
|
||||||
* this is our source to give as .contentNode to OverlayController.
|
* this is our source to give as .contentNode to OverlayController.
|
||||||
* Important: do not change the name of this method.
|
* Important: do not change the name of this method.
|
||||||
*/
|
*/
|
||||||
|
|
@ -283,7 +283,7 @@ export class LionInputDatepicker extends ScopedElementsMixin(OverlayMixin(LionIn
|
||||||
}
|
}
|
||||||
|
|
||||||
async __openCalendarOverlay() {
|
async __openCalendarOverlay() {
|
||||||
this._overlayCtrl.show();
|
await this._overlayCtrl.show();
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this._overlayCtrl.contentNode.updateComplete,
|
this._overlayCtrl.contentNode.updateComplete,
|
||||||
this._calendarNode.updateComplete,
|
this._calendarNode.updateComplete,
|
||||||
|
|
|
||||||
|
|
@ -175,6 +175,7 @@ describe('<lion-input-datepicker>', () => {
|
||||||
const el = await fixture(html`<lion-input-datepicker></lion-input-datepicker>`);
|
const el = await fixture(html`<lion-input-datepicker></lion-input-datepicker>`);
|
||||||
const elObj = new DatepickerInputObject(el);
|
const elObj = new DatepickerInputObject(el);
|
||||||
await elObj.openCalendar();
|
await elObj.openCalendar();
|
||||||
|
await aTimeout();
|
||||||
expect(isSameDate(elObj.calendarEl.focusedDate, elObj.calendarEl.centralDate)).to.be.true;
|
expect(isSameDate(elObj.calendarEl.focusedDate, elObj.calendarEl.centralDate)).to.be.true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -268,8 +268,8 @@ export class OverlayController {
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
async _init({ cfgToAdd }) {
|
_init({ cfgToAdd }) {
|
||||||
this.__initcontentWrapperNode({ cfgToAdd });
|
this.__initContentWrapperNode({ cfgToAdd });
|
||||||
this.__initConnectionTarget();
|
this.__initConnectionTarget();
|
||||||
|
|
||||||
if (this.placementMode === 'local') {
|
if (this.placementMode === 'local') {
|
||||||
|
|
@ -310,7 +310,7 @@ export class OverlayController {
|
||||||
* @desc Cleanup ._contentWrapperNode. We do this, because creating a fresh wrapper
|
* @desc Cleanup ._contentWrapperNode. We do this, because creating a fresh wrapper
|
||||||
* can lead to problems with event listeners...
|
* can lead to problems with event listeners...
|
||||||
*/
|
*/
|
||||||
__initcontentWrapperNode({ cfgToAdd }) {
|
__initContentWrapperNode({ cfgToAdd }) {
|
||||||
if (this.config.contentWrapperNode && this.placementMode === 'local') {
|
if (this.config.contentWrapperNode && this.placementMode === 'local') {
|
||||||
/** config [l2],[l3],[l4] */
|
/** config [l2],[l3],[l4] */
|
||||||
this._contentWrapperNode = this.config.contentWrapperNode;
|
this._contentWrapperNode = this.config.contentWrapperNode;
|
||||||
|
|
@ -568,7 +568,7 @@ export class OverlayController {
|
||||||
* @param {object} config
|
* @param {object} config
|
||||||
* @param {'init'|'show'|'hide'|'teardown'} config.phase
|
* @param {'init'|'show'|'hide'|'teardown'} config.phase
|
||||||
*/
|
*/
|
||||||
async _handleFeatures({ phase }) {
|
_handleFeatures({ phase }) {
|
||||||
this._handleZIndex({ phase });
|
this._handleZIndex({ phase });
|
||||||
|
|
||||||
if (this.preventsScroll) {
|
if (this.preventsScroll) {
|
||||||
|
|
@ -856,11 +856,15 @@ export class OverlayController {
|
||||||
teardown() {
|
teardown() {
|
||||||
this._handleFeatures({ phase: 'teardown' });
|
this._handleFeatures({ phase: 'teardown' });
|
||||||
|
|
||||||
// Remove the content node wrapper from the global rootnode
|
if (this.placementMode === 'global' && this.__isContentNodeProjected) {
|
||||||
this._teardowncontentWrapperNode();
|
this.__originalContentParent.appendChild(this.contentNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
_teardowncontentWrapperNode() {
|
// Remove the content node wrapper from the global rootnode
|
||||||
|
this._teardownContentWrapperNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
_teardownContentWrapperNode() {
|
||||||
if (
|
if (
|
||||||
this.placementMode === 'global' &&
|
this.placementMode === 'global' &&
|
||||||
this._contentWrapperNode &&
|
this._contentWrapperNode &&
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,8 @@ export const OverlayMixin = dedupeMixin(
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.opened = false;
|
this.opened = false;
|
||||||
|
this.__needsSetup = true;
|
||||||
this.config = {};
|
this.config = {};
|
||||||
|
|
||||||
this._overlaySetupComplete = new Promise(resolve => {
|
|
||||||
this.__overlaySetupCompleteResolve = resolve;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get config() {
|
get config() {
|
||||||
|
|
@ -134,52 +131,24 @@ export const OverlayMixin = dedupeMixin(
|
||||||
}
|
}
|
||||||
|
|
||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
if (super.connectedCallback) {
|
|
||||||
super.connectedCallback();
|
super.connectedCallback();
|
||||||
}
|
// we do a setup after every connectedCallback as firstUpdated will only be called once
|
||||||
|
this.__needsSetup = true;
|
||||||
// Wait for DOM to be ready before setting up the overlay, else extensions like rich select breaks
|
|
||||||
this.updateComplete.then(() => {
|
this.updateComplete.then(() => {
|
||||||
if (!this.__isOverlaySetup) {
|
if (this.__needsSetup) {
|
||||||
this._setupOverlayCtrl();
|
this._setupOverlayCtrl();
|
||||||
}
|
}
|
||||||
|
this.__needsSetup = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
// When dom nodes are being moved around (meaning connected/disconnected are being fired
|
|
||||||
// repeatedly), we need to delay the teardown until we find a 'permanent disconnect'
|
|
||||||
if (this.__rejectOverlayDisconnectComplete) {
|
|
||||||
// makes sure _overlayDisconnectComplete never resolves: we don't want a teardown
|
|
||||||
this.__rejectOverlayDisconnectComplete();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnectedCallback() {
|
disconnectedCallback() {
|
||||||
if (super.disconnectedCallback) {
|
if (super.disconnectedCallback) {
|
||||||
super.disconnectedCallback();
|
super.disconnectedCallback();
|
||||||
}
|
}
|
||||||
|
if (this._overlayCtrl) {
|
||||||
if (!this._overlayCtrl) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._overlayDisconnectComplete = new Promise((resolve, reject) => {
|
|
||||||
this.__resolveOverlayDisconnectComplete = resolve;
|
|
||||||
this.__rejectOverlayDisconnectComplete = reject;
|
|
||||||
});
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
// we start the teardown below
|
|
||||||
this.__resolveOverlayDisconnectComplete();
|
|
||||||
});
|
|
||||||
|
|
||||||
// We need to prevent that we create a setup/teardown cycle during startup, where it
|
|
||||||
// is common that the overlay system moves around nodes. Therefore, we make the
|
|
||||||
// teardown async, so that it only happens when we are permanently disconnecting from dom
|
|
||||||
this._overlayDisconnectComplete
|
|
||||||
.then(() => {
|
|
||||||
this._teardownOverlayCtrl();
|
this._teardownOverlayCtrl();
|
||||||
})
|
}
|
||||||
.catch(() => {});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get _overlayInvokerNode() {
|
get _overlayInvokerNode() {
|
||||||
|
|
@ -213,15 +182,12 @@ export const OverlayMixin = dedupeMixin(
|
||||||
this.__syncToOverlayController();
|
this.__syncToOverlayController();
|
||||||
this.__setupSyncFromOverlayController();
|
this.__setupSyncFromOverlayController();
|
||||||
this._setupOpenCloseListeners();
|
this._setupOpenCloseListeners();
|
||||||
this.__overlaySetupCompleteResolve();
|
|
||||||
this.__isOverlaySetup = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_teardownOverlayCtrl() {
|
_teardownOverlayCtrl() {
|
||||||
this._teardownOpenCloseListeners();
|
this._teardownOpenCloseListeners();
|
||||||
this.__teardownSyncFromOverlayController();
|
this.__teardownSyncFromOverlayController();
|
||||||
this._overlayCtrl.teardown();
|
this._overlayCtrl.teardown();
|
||||||
this.__isOverlaySetup = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -195,10 +195,10 @@ export function runOverlayMixinSuite({ tagString, tag, suffix = '' }) {
|
||||||
|
|
||||||
it('supports nested overlays', async () => {
|
it('supports nested overlays', async () => {
|
||||||
const el = await fixture(html`
|
const el = await fixture(html`
|
||||||
<${tag}>
|
<${tag} id="main-dialog">
|
||||||
<div slot="content" id="mainContent">
|
<div slot="content" id="mainContent">
|
||||||
open nested overlay:
|
open nested overlay:
|
||||||
<${tag}>
|
<${tag} id="sub-dialog">
|
||||||
<div slot="content" id="nestedContent">
|
<div slot="content" id="nestedContent">
|
||||||
Nested content
|
Nested content
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -222,6 +222,23 @@ export function runOverlayMixinSuite({ tagString, tag, suffix = '' }) {
|
||||||
expect(nestedOverlayEl._overlayCtrl.contentNode).to.be.displayed;
|
expect(nestedOverlayEl._overlayCtrl.contentNode).to.be.displayed;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('[global] allows for moving of the element', async () => {
|
||||||
|
const el = await fixture(html`
|
||||||
|
<${tag}>
|
||||||
|
<div slot="content" id="nestedContent">content of the nested overlay</div>
|
||||||
|
<button slot="invoker">invoker nested</button>
|
||||||
|
</${tag}>
|
||||||
|
`);
|
||||||
|
if (el._overlayCtrl.placementMode === 'global') {
|
||||||
|
expect(getGlobalOverlayNodes().length).to.equal(1);
|
||||||
|
|
||||||
|
const moveTarget = await fixture('<div id="target"></div>');
|
||||||
|
moveTarget.appendChild(el);
|
||||||
|
await el.updateComplete;
|
||||||
|
expect(getGlobalOverlayNodes().length).to.equal(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it('reconstructs the overlay when disconnected and reconnected to DOM (support for nested overlay nodes)', async () => {
|
it('reconstructs the overlay when disconnected and reconnected to DOM (support for nested overlay nodes)', async () => {
|
||||||
const nestedEl = await fixture(html`
|
const nestedEl = await fixture(html`
|
||||||
<${tag} id="nest">
|
<${tag} id="nest">
|
||||||
|
|
@ -241,15 +258,12 @@ export function runOverlayMixinSuite({ tagString, tag, suffix = '' }) {
|
||||||
`);
|
`);
|
||||||
|
|
||||||
if (el._overlayCtrl.placementMode === 'global') {
|
if (el._overlayCtrl.placementMode === 'global') {
|
||||||
// Specifically checking the output in global root node, because the _contentOverlayNode still references
|
|
||||||
// the node that was removed in the teardown but hasn't been garbage collected due to reference to it still existing..
|
|
||||||
|
|
||||||
// Find the outlets that are not backdrop outlets
|
// Find the outlets that are not backdrop outlets
|
||||||
const overlayContainerNodes = getGlobalOverlayNodes();
|
const overlayContainerNodes = getGlobalOverlayNodes();
|
||||||
expect(overlayContainerNodes.length).to.equal(2);
|
expect(overlayContainerNodes.length).to.equal(2);
|
||||||
const lastContentNodeInContainer = overlayContainerNodes[0];
|
const lastContentNodeInContainer = overlayContainerNodes[1];
|
||||||
// Check that the last container is the nested one with the intended content
|
// Check that the last container is the nested one with the intended content
|
||||||
expect(lastContentNodeInContainer.firstElementChild.innerText).to.equal(
|
expect(lastContentNodeInContainer.firstElementChild.firstChild.textContent).to.equal(
|
||||||
'content of the nested overlay',
|
'content of the nested overlay',
|
||||||
);
|
);
|
||||||
expect(lastContentNodeInContainer.firstElementChild.slot).to.equal('content');
|
expect(lastContentNodeInContainer.firstElementChild.slot).to.equal('content');
|
||||||
|
|
@ -259,43 +273,5 @@ export function runOverlayMixinSuite({ tagString, tag, suffix = '' }) {
|
||||||
expect(contentNode.innerText).to.equal('content of the nested overlay');
|
expect(contentNode.innerText).to.equal('content of the nested overlay');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it("doesn't tear down controller when dom nodes are being moved around", async () => {
|
|
||||||
const nestedEl = await fixture(html`
|
|
||||||
<${tag} id="nest">
|
|
||||||
<div slot="content" id="nestedContent">content of the nested overlay</div>
|
|
||||||
<button slot="invoker">invoker nested</button>
|
|
||||||
</${tag}>
|
|
||||||
`);
|
|
||||||
|
|
||||||
const setupOverlayCtrlSpy = sinon.spy(nestedEl, '_setupOverlayCtrl');
|
|
||||||
const teardownOverlayCtrlSpy = sinon.spy(nestedEl, '_teardownOverlayCtrl');
|
|
||||||
|
|
||||||
const el = await fixture(html`
|
|
||||||
<${tag} id="main">
|
|
||||||
<div slot="content" id="mainContent">
|
|
||||||
open nested overlay:
|
|
||||||
${nestedEl}
|
|
||||||
</div>
|
|
||||||
<button slot="invoker">invoker button</button>
|
|
||||||
</${tag}>
|
|
||||||
`);
|
|
||||||
|
|
||||||
// Even though many connected/disconnected calls take place,
|
|
||||||
// we detect we are in the middle of a 'move'
|
|
||||||
expect(teardownOverlayCtrlSpy).to.not.have.been.called;
|
|
||||||
expect(setupOverlayCtrlSpy).to.not.have.been.called;
|
|
||||||
|
|
||||||
// Now move nestedEl to an offline node
|
|
||||||
const offlineNode = document.createElement('div');
|
|
||||||
offlineNode.appendChild(nestedEl);
|
|
||||||
await aTimeout();
|
|
||||||
// And we detect this time the disconnect was 'permanent'
|
|
||||||
expect(teardownOverlayCtrlSpy.callCount).to.equal(1);
|
|
||||||
|
|
||||||
el._overlayContentNode.appendChild(nestedEl);
|
|
||||||
await aTimeout();
|
|
||||||
expect(setupOverlayCtrlSpy.callCount).to.equal(1);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -188,6 +188,42 @@ describe('OverlayController', () => {
|
||||||
ctrl.teardown();
|
ctrl.teardown();
|
||||||
expect(ctrl.manager.globalRootNode.children.length).to.equal(0);
|
expect(ctrl.manager.globalRootNode.children.length).to.equal(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('[global] restores contentNode if it was/is a projected node', async () => {
|
||||||
|
const shadowHost = document.createElement('div');
|
||||||
|
shadowHost.id = 'shadowHost';
|
||||||
|
shadowHost.attachShadow({ mode: 'open' });
|
||||||
|
shadowHost.shadowRoot.innerHTML = `
|
||||||
|
<div id="contentWrapperNode">
|
||||||
|
<slot name="contentNode"></slot>
|
||||||
|
<my-arrow></my-arrow>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
const contentNode = document.createElement('div');
|
||||||
|
contentNode.slot = 'contentNode';
|
||||||
|
shadowHost.appendChild(contentNode);
|
||||||
|
|
||||||
|
const wrapper = await fixture('<div id="wrapper"></div>');
|
||||||
|
// Ensure the contentNode is connected to DOM
|
||||||
|
wrapper.appendChild(shadowHost);
|
||||||
|
|
||||||
|
// has one child = <div slot="contentNode"></div>
|
||||||
|
expect(shadowHost.children.length).to.equal(1);
|
||||||
|
|
||||||
|
const ctrl = new OverlayController({
|
||||||
|
...withLocalTestConfig(),
|
||||||
|
placementMode: 'global',
|
||||||
|
contentNode,
|
||||||
|
contentWrapperNode: shadowHost,
|
||||||
|
});
|
||||||
|
|
||||||
|
// has no children as content gets moved to the body
|
||||||
|
expect(shadowHost.children.length).to.equal(0);
|
||||||
|
ctrl.teardown();
|
||||||
|
|
||||||
|
// restores original light dom in teardown
|
||||||
|
expect(shadowHost.children.length).to.equal(1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Node Configuration', () => {
|
describe('Node Configuration', () => {
|
||||||
|
|
@ -1372,7 +1408,7 @@ describe('OverlayController', () => {
|
||||||
}).to.throw('[OverlayController] You need to provide a .contentNode');
|
}).to.throw('[OverlayController] You need to provide a .contentNode');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('throws if contentNodewrapper is not provided for projected contentNode', async () => {
|
it('throws if contentNodeWrapper is not provided for projected contentNode', async () => {
|
||||||
const shadowHost = document.createElement('div');
|
const shadowHost = document.createElement('div');
|
||||||
shadowHost.attachShadow({ mode: 'open' });
|
shadowHost.attachShadow({ mode: 'open' });
|
||||||
shadowHost.shadowRoot.innerHTML = `
|
shadowHost.shadowRoot.innerHTML = `
|
||||||
|
|
|
||||||
|
|
@ -195,10 +195,11 @@ export class LionSelectRich extends ScopedElementsMixin(
|
||||||
}
|
}
|
||||||
|
|
||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
|
// need to do this before anything else
|
||||||
|
this._listboxNode.registrationTarget = this;
|
||||||
if (super.connectedCallback) {
|
if (super.connectedCallback) {
|
||||||
super.connectedCallback();
|
super.connectedCallback();
|
||||||
}
|
}
|
||||||
this._listboxNode.registrationTarget = this;
|
|
||||||
this._invokerNode.selectedElement = this.formElements[this.checkedIndex];
|
this._invokerNode.selectedElement = this.formElements[this.checkedIndex];
|
||||||
this.__setupInvokerNode();
|
this.__setupInvokerNode();
|
||||||
this.__setupListboxNode();
|
this.__setupListboxNode();
|
||||||
|
|
@ -213,10 +214,6 @@ export class LionSelectRich extends ScopedElementsMixin(
|
||||||
this.registrationComplete.then(() => {
|
this.registrationComplete.then(() => {
|
||||||
this.__initInteractionStates();
|
this.__initInteractionStates();
|
||||||
});
|
});
|
||||||
|
|
||||||
this._overlaySetupComplete.then(() => {
|
|
||||||
this.__setupOverlay();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnectedCallback() {
|
disconnectedCallback() {
|
||||||
|
|
@ -226,6 +223,10 @@ export class LionSelectRich extends ScopedElementsMixin(
|
||||||
if (this._labelNode) {
|
if (this._labelNode) {
|
||||||
this._labelNode.removeEventListener('click', this.__toggleChecked);
|
this._labelNode.removeEventListener('click', this.__toggleChecked);
|
||||||
}
|
}
|
||||||
|
this._scrollTargetNode.removeEventListener('keydown', this.__overlayOnHide);
|
||||||
|
this.__teardownInvokerNode();
|
||||||
|
this.__teardownListboxNode();
|
||||||
|
this.__teardownEventListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
requestUpdateInternal(name, oldValue) {
|
requestUpdateInternal(name, oldValue) {
|
||||||
|
|
@ -658,7 +659,8 @@ export class LionSelectRich extends ScopedElementsMixin(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__setupOverlay() {
|
_setupOverlayCtrl() {
|
||||||
|
super._setupOverlayCtrl();
|
||||||
this._initialInheritsReferenceWidth = this._overlayCtrl.inheritsReferenceWidth;
|
this._initialInheritsReferenceWidth = this._overlayCtrl.inheritsReferenceWidth;
|
||||||
this.__overlayBeforeShow = () => {
|
this.__overlayBeforeShow = () => {
|
||||||
if (this.hasNoDefaultSelected) {
|
if (this.hasNoDefaultSelected) {
|
||||||
|
|
@ -688,10 +690,6 @@ export class LionSelectRich extends ScopedElementsMixin(
|
||||||
this._overlayCtrl.removeEventListener('show', this.__overlayOnShow);
|
this._overlayCtrl.removeEventListener('show', this.__overlayOnShow);
|
||||||
this._overlayCtrl.removeEventListener('before-show', this.__overlayBeforeShow);
|
this._overlayCtrl.removeEventListener('before-show', this.__overlayBeforeShow);
|
||||||
this._overlayCtrl.removeEventListener('hide', this.__overlayOnHide);
|
this._overlayCtrl.removeEventListener('hide', this.__overlayOnHide);
|
||||||
this._scrollTargetNode.removeEventListener('keydown', this.__overlayOnHide);
|
|
||||||
this.__teardownInvokerNode();
|
|
||||||
this.__teardownListboxNode();
|
|
||||||
this.__teardownEventListeners();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__preventScrollingWithArrowKeys(ev) {
|
__preventScrollingWithArrowKeys(ev) {
|
||||||
|
|
|
||||||
|
|
@ -90,12 +90,6 @@ export class LionTooltip extends OverlayMixin(LitElement) {
|
||||||
this.__setupRepositionCompletePromise();
|
this.__setupRepositionCompletePromise();
|
||||||
}
|
}
|
||||||
|
|
||||||
connectedCallback() {
|
|
||||||
if (super.connectedCallback) {
|
|
||||||
super.connectedCallback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return html`
|
return html`
|
||||||
<slot name="invoker"></slot>
|
<slot name="invoker"></slot>
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,6 @@ describe('lion-tooltip', () => {
|
||||||
el.opened = true;
|
el.opened = true;
|
||||||
|
|
||||||
await el.repositionComplete;
|
await el.repositionComplete;
|
||||||
|
|
||||||
// Pretty sure we use flex for this now so that's why it fails
|
// Pretty sure we use flex for this now so that's why it fails
|
||||||
/* expect(getComputedStyle(el.__arrowElement).getPropertyValue('top')).to.equal(
|
/* expect(getComputedStyle(el.__arrowElement).getPropertyValue('top')).to.equal(
|
||||||
'11px',
|
'11px',
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* eslint-disable no-console */
|
||||||
/* eslint-disable import/no-extraneous-dependencies */
|
/* eslint-disable import/no-extraneous-dependencies */
|
||||||
const { chromium } = require('playwright');
|
const { chromium } = require('playwright');
|
||||||
const looksSame = require('looks-same');
|
const looksSame = require('looks-same');
|
||||||
|
|
|
||||||
67
yarn.lock
67
yarn.lock
|
|
@ -2513,10 +2513,10 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
semver "^7.3.2"
|
semver "^7.3.2"
|
||||||
|
|
||||||
"@web/dev-server-core@^0.2.2", "@web/dev-server-core@^0.2.6":
|
"@web/dev-server-core@^0.2.2":
|
||||||
version "0.2.6"
|
version "0.2.5"
|
||||||
resolved "https://registry.yarnpkg.com/@web/dev-server-core/-/dev-server-core-0.2.6.tgz#522e524056e184d691138a76f0afa605b639160b"
|
resolved "https://registry.yarnpkg.com/@web/dev-server-core/-/dev-server-core-0.2.5.tgz#f05dd29c62f303b20589e439af6a838a831b060b"
|
||||||
integrity sha512-C04oUS5LijC5rLurH/+5uRkgRgD9EVAY9tHi+TZv/57a3QvvPME6ipKbA6MFvkLdeiSdYLKNTY/shjukGfNrcg==
|
integrity sha512-t1R1g3/CLwgVjag075dtyCqoX9KRY4gLIXn/12h05Y+wSzuEjFkezOxhZCyDt0qUzDd2eZ60mOuyq+r5SmV7OQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
chokidar "^3.4.0"
|
chokidar "^3.4.0"
|
||||||
clone "^2.1.2"
|
clone "^2.1.2"
|
||||||
|
|
@ -2532,7 +2532,28 @@
|
||||||
parse5 "^6.0.0"
|
parse5 "^6.0.0"
|
||||||
picomatch "^2.2.2"
|
picomatch "^2.2.2"
|
||||||
|
|
||||||
"@web/dev-server-legacy@^0.1.1", "@web/dev-server-legacy@^0.1.2":
|
"@web/dev-server-legacy@^0.1.1":
|
||||||
|
version "0.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@web/dev-server-legacy/-/dev-server-legacy-0.1.1.tgz#1f719610710aaf5608b952defa901c8590173201"
|
||||||
|
integrity sha512-mf/p35fOtT05PTdFQsJy8B69lhXn7JfOaGJTg0bijm1QH7NTkT50ECAL3l76B9bk5ExmYWRSIqLKhq3iFTJOCA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/core" "^7.10.5"
|
||||||
|
"@babel/plugin-proposal-dynamic-import" "^7.10.4"
|
||||||
|
"@babel/plugin-syntax-class-properties" "^7.10.4"
|
||||||
|
"@babel/plugin-syntax-import-meta" "^7.10.4"
|
||||||
|
"@babel/plugin-syntax-numeric-separator" "^7.10.4"
|
||||||
|
"@babel/plugin-transform-modules-systemjs" "^7.10.5"
|
||||||
|
"@babel/plugin-transform-template-literals" "^7.10.5"
|
||||||
|
"@babel/preset-env" "^7.10.4"
|
||||||
|
"@web/dev-server-core" "^0.2.1"
|
||||||
|
browserslist "^4.13.0"
|
||||||
|
browserslist-useragent "^3.0.3"
|
||||||
|
caniuse-api "^3.0.0"
|
||||||
|
parse5 "^6.0.0"
|
||||||
|
polyfills-loader "^1.6.1"
|
||||||
|
valid-url "^1.0.9"
|
||||||
|
|
||||||
|
"@web/dev-server-legacy@^0.1.2":
|
||||||
version "0.1.3"
|
version "0.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/@web/dev-server-legacy/-/dev-server-legacy-0.1.3.tgz#3b508062b14b502a1b8621802875ba01b234d690"
|
resolved "https://registry.yarnpkg.com/@web/dev-server-legacy/-/dev-server-legacy-0.1.3.tgz#3b508062b14b502a1b8621802875ba01b234d690"
|
||||||
integrity sha512-PbsDnRKfiCtN5hSrxVpT1EOZofpEl009oF72m30YOu/m+cIef6rAPyk+MgKNXsiq3iob+u/zYqTKj0F5/jVj1A==
|
integrity sha512-PbsDnRKfiCtN5hSrxVpT1EOZofpEl009oF72m30YOu/m+cIef6rAPyk+MgKNXsiq3iob+u/zYqTKj0F5/jVj1A==
|
||||||
|
|
@ -2553,14 +2574,14 @@
|
||||||
polyfills-loader "^1.6.1"
|
polyfills-loader "^1.6.1"
|
||||||
valid-url "^1.0.9"
|
valid-url "^1.0.9"
|
||||||
|
|
||||||
"@web/dev-server-rollup@^0.2.4":
|
"@web/dev-server-rollup@^0.2.3":
|
||||||
version "0.2.4"
|
version "0.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/@web/dev-server-rollup/-/dev-server-rollup-0.2.4.tgz#45bb4595eee9af1b3f1b23ebd623ee7bc53922b2"
|
resolved "https://registry.yarnpkg.com/@web/dev-server-rollup/-/dev-server-rollup-0.2.3.tgz#e95cc3090cb624084c90f5a7f31bb3fc85fd9b53"
|
||||||
integrity sha512-NpW5BRkpzHZXtH73bH4JI/TqIuv4UHxo0LWjqN4V44xweC1mnTL6mzjYDy/HxfscrYs6pp1s2d+hJ2Lb5uldFQ==
|
integrity sha512-rR7jM4EW1fsTYb2/RksCNPWlDteJXdnoGq7OGAV6+qDk0JvO4GnsIRLcFcKuCEcjgK9oP2ZgqLdv9qMxkzc4ng==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@web/dev-server-core" "^0.2.6"
|
"@web/dev-server-core" "^0.2.2"
|
||||||
"@web/test-runner-chrome" "^0.6.4"
|
"@web/test-runner-chrome" "^0.6.4"
|
||||||
"@web/test-runner-core" "^0.7.5"
|
"@web/test-runner-core" "^0.7.4"
|
||||||
chalk "^4.1.0"
|
chalk "^4.1.0"
|
||||||
parse5 "^6.0.1"
|
parse5 "^6.0.1"
|
||||||
rollup "^2.20.0"
|
rollup "^2.20.0"
|
||||||
|
|
@ -2624,13 +2645,13 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@web/test-runner-core" "^0.7.4"
|
"@web/test-runner-core" "^0.7.4"
|
||||||
|
|
||||||
"@web/test-runner-core@^0.7.4", "@web/test-runner-core@^0.7.5":
|
"@web/test-runner-core@^0.7.4":
|
||||||
version "0.7.5"
|
version "0.7.4"
|
||||||
resolved "https://registry.yarnpkg.com/@web/test-runner-core/-/test-runner-core-0.7.5.tgz#8050d97a4e275be122a2dc46334f02c05b52b358"
|
resolved "https://registry.yarnpkg.com/@web/test-runner-core/-/test-runner-core-0.7.4.tgz#ee8f031c893b32009ce29002f0de865e2aa718da"
|
||||||
integrity sha512-5V9gEYL8a6nxurXKFR/RigRQdYs67jO7Mo3Uj/XbGO54guZktOLCsCtkPCSsYGuNkerVUpyOAKX76ftuOTwblQ==
|
integrity sha512-DS/BxZTjG64HGObybmSus7GRuWoPaNnPt44pTXSWpIxMvRB3nv/Q2I+wE0Nx66PhC/uM2L74o+CIT+g7qRWsdg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/code-frame" "^7.10.4"
|
"@babel/code-frame" "^7.10.4"
|
||||||
"@web/dev-server-core" "^0.2.6"
|
"@web/dev-server-core" "^0.2.2"
|
||||||
co-body "^6.0.0"
|
co-body "^6.0.0"
|
||||||
debounce "^1.2.0"
|
debounce "^1.2.0"
|
||||||
deepmerge "^4.2.2"
|
deepmerge "^4.2.2"
|
||||||
|
|
@ -2684,17 +2705,17 @@
|
||||||
"@web/test-runner-core" "^0.7.4"
|
"@web/test-runner-core" "^0.7.4"
|
||||||
selenium-webdriver "^4.0.0-alpha.7"
|
selenium-webdriver "^4.0.0-alpha.7"
|
||||||
|
|
||||||
"@web/test-runner@^0.7.3":
|
"@web/test-runner@^0.7.13":
|
||||||
version "0.7.14"
|
version "0.7.13"
|
||||||
resolved "https://registry.yarnpkg.com/@web/test-runner/-/test-runner-0.7.14.tgz#ac5840318d0f725a767b895fabeed83ae1e3fcbb"
|
resolved "https://registry.yarnpkg.com/@web/test-runner/-/test-runner-0.7.13.tgz#8bfb9cd249e1bbd5fb5f0c2716689e137922f2ae"
|
||||||
integrity sha512-tbmEb/1H1KS1vgY6hRMhJgBtynRw+YRufptFkzwxsdAnMM6iHm6lCAGeFOBb96LawDBC+8IWauYtr/IHYLkhhg==
|
integrity sha512-DOhWTQqKSxUVVq3e409sjCCmZEJo7k1kMv3DqRW8668bsD0KG+YR5SEIWIIg7BuUHDS40cnjWOmnLo4ttRJj7g==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@rollup/plugin-node-resolve" "^8.1.0"
|
"@rollup/plugin-node-resolve" "^8.1.0"
|
||||||
"@web/dev-server-rollup" "^0.2.4"
|
"@web/dev-server-rollup" "^0.2.3"
|
||||||
"@web/test-runner-chrome" "^0.6.4"
|
"@web/test-runner-chrome" "^0.6.4"
|
||||||
"@web/test-runner-cli" "^0.5.6"
|
"@web/test-runner-cli" "^0.5.6"
|
||||||
"@web/test-runner-commands" "^0.1.3"
|
"@web/test-runner-commands" "^0.1.3"
|
||||||
"@web/test-runner-core" "^0.7.5"
|
"@web/test-runner-core" "^0.7.4"
|
||||||
"@web/test-runner-mocha" "^0.3.3"
|
"@web/test-runner-mocha" "^0.3.3"
|
||||||
command-line-args "^5.1.1"
|
command-line-args "^5.1.1"
|
||||||
deepmerge "^4.2.2"
|
deepmerge "^4.2.2"
|
||||||
|
|
@ -7430,7 +7451,7 @@ lit-element@^2.2.1, lit-element@^2.3.1, lit-element@~2.4.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
lit-html "^1.1.1"
|
lit-html "^1.1.1"
|
||||||
|
|
||||||
lit-html@^1.0.0, lit-html@^1.1.1, lit-html@^1.2.1:
|
lit-html@^1.0.0, lit-html@^1.1.1, lit-html@^1.2.1, lit-html@^1.3.0:
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/lit-html/-/lit-html-1.3.0.tgz#c80f3cc5793a6dea6c07172be90a70ab20e56034"
|
resolved "https://registry.yarnpkg.com/lit-html/-/lit-html-1.3.0.tgz#c80f3cc5793a6dea6c07172be90a70ab20e56034"
|
||||||
integrity sha512-0Q1bwmaFH9O14vycPHw8C/IeHMk/uSDldVLIefu/kfbTBGIc44KGH6A8p1bDfxUfHdc8q6Ct7kQklWoHgr4t1Q==
|
integrity sha512-0Q1bwmaFH9O14vycPHw8C/IeHMk/uSDldVLIefu/kfbTBGIc44KGH6A8p1bDfxUfHdc8q6Ct7kQklWoHgr4t1Q==
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue