diff --git a/.changeset/friendly-dolphins-give.md b/.changeset/friendly-dolphins-give.md new file mode 100644 index 000000000..161aa715b --- /dev/null +++ b/.changeset/friendly-dolphins-give.md @@ -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 diff --git a/package.json b/package.json index e2a033087..516f44c9a 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "build:docs": "wca analyze \"packages/tabs/**/*.js\"", "build:types": "tsc -p tsconfig.build.types.json", "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", "format": "npm run format:eslint && npm run format:prettier", "format:eslint": "eslint --ext .js,.html . --fix", @@ -48,7 +48,7 @@ "@storybook/addon-a11y": "~5.0.0", "@types/chai-dom": "^0.0.8", "@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-playwright": "^0.5.1", "@web/test-runner-puppeteer": "^0.6.1", diff --git a/packages/form-core/test-suites/ValidateMixin.suite.js b/packages/form-core/test-suites/ValidateMixin.suite.js index 785635196..4bc7ae2a1 100644 --- a/packages/form-core/test-suites/ValidateMixin.suite.js +++ b/packages/form-core/test-suites/ValidateMixin.suite.js @@ -721,7 +721,6 @@ export function runValidateMixinSuite(customConfig) { .modelValue=${''} >${lightDom} `)); - console.log(el._inputNode); expect(el._inputNode?.getAttribute('aria-required')).to.equal('true'); el.validators = []; expect(el._inputNode?.getAttribute('aria-required')).to.be.null; diff --git a/packages/form-integrations/docs/60-dialog-integration.md b/packages/form-integrations/docs/60-dialog-integration.md new file mode 100644 index 000000000..356256b1f --- /dev/null +++ b/packages/form-integrations/docs/60-dialog-integration.md @@ -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` + + +
+ + + Red + Hotpink + Teal + + + +
+
+`; +``` diff --git a/packages/input-datepicker/src/LionInputDatepicker.js b/packages/input-datepicker/src/LionInputDatepicker.js index 9b1d79563..d719ec807 100644 --- a/packages/input-datepicker/src/LionInputDatepicker.js +++ b/packages/input-datepicker/src/LionInputDatepicker.js @@ -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. * Important: do not change the name of this method. */ @@ -283,7 +283,7 @@ export class LionInputDatepicker extends ScopedElementsMixin(OverlayMixin(LionIn } async __openCalendarOverlay() { - this._overlayCtrl.show(); + await this._overlayCtrl.show(); await Promise.all([ this._overlayCtrl.contentNode.updateComplete, this._calendarNode.updateComplete, diff --git a/packages/input-datepicker/test/lion-input-datepicker.test.js b/packages/input-datepicker/test/lion-input-datepicker.test.js index 283b4de03..d4ef8c0c4 100644 --- a/packages/input-datepicker/test/lion-input-datepicker.test.js +++ b/packages/input-datepicker/test/lion-input-datepicker.test.js @@ -175,6 +175,7 @@ describe('', () => { const el = await fixture(html``); const elObj = new DatepickerInputObject(el); await elObj.openCalendar(); + await aTimeout(); expect(isSameDate(elObj.calendarEl.focusedDate, elObj.calendarEl.centralDate)).to.be.true; }); diff --git a/packages/overlays/src/OverlayController.js b/packages/overlays/src/OverlayController.js index 18a6a8650..b1ad9dc58 100644 --- a/packages/overlays/src/OverlayController.js +++ b/packages/overlays/src/OverlayController.js @@ -268,8 +268,8 @@ export class OverlayController { // } } - async _init({ cfgToAdd }) { - this.__initcontentWrapperNode({ cfgToAdd }); + _init({ cfgToAdd }) { + this.__initContentWrapperNode({ cfgToAdd }); this.__initConnectionTarget(); if (this.placementMode === 'local') { @@ -310,7 +310,7 @@ export class OverlayController { * @desc Cleanup ._contentWrapperNode. We do this, because creating a fresh wrapper * can lead to problems with event listeners... */ - __initcontentWrapperNode({ cfgToAdd }) { + __initContentWrapperNode({ cfgToAdd }) { if (this.config.contentWrapperNode && this.placementMode === 'local') { /** config [l2],[l3],[l4] */ this._contentWrapperNode = this.config.contentWrapperNode; @@ -568,7 +568,7 @@ export class OverlayController { * @param {object} config * @param {'init'|'show'|'hide'|'teardown'} config.phase */ - async _handleFeatures({ phase }) { + _handleFeatures({ phase }) { this._handleZIndex({ phase }); if (this.preventsScroll) { @@ -856,11 +856,15 @@ export class OverlayController { teardown() { this._handleFeatures({ phase: 'teardown' }); + if (this.placementMode === 'global' && this.__isContentNodeProjected) { + this.__originalContentParent.appendChild(this.contentNode); + } + // Remove the content node wrapper from the global rootnode - this._teardowncontentWrapperNode(); + this._teardownContentWrapperNode(); } - _teardowncontentWrapperNode() { + _teardownContentWrapperNode() { if ( this.placementMode === 'global' && this._contentWrapperNode && diff --git a/packages/overlays/src/OverlayMixin.js b/packages/overlays/src/OverlayMixin.js index 0a619bdb6..a007dba48 100644 --- a/packages/overlays/src/OverlayMixin.js +++ b/packages/overlays/src/OverlayMixin.js @@ -22,11 +22,8 @@ export const OverlayMixin = dedupeMixin( constructor() { super(); this.opened = false; + this.__needsSetup = true; this.config = {}; - - this._overlaySetupComplete = new Promise(resolve => { - this.__overlaySetupCompleteResolve = resolve; - }); } get config() { @@ -134,52 +131,24 @@ export const OverlayMixin = dedupeMixin( } connectedCallback() { - if (super.connectedCallback) { - super.connectedCallback(); - } - - // Wait for DOM to be ready before setting up the overlay, else extensions like rich select breaks + super.connectedCallback(); + // we do a setup after every connectedCallback as firstUpdated will only be called once + this.__needsSetup = true; this.updateComplete.then(() => { - if (!this.__isOverlaySetup) { + if (this.__needsSetup) { 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() { if (super.disconnectedCallback) { super.disconnectedCallback(); } - - if (!this._overlayCtrl) { - return; + if (this._overlayCtrl) { + this._teardownOverlayCtrl(); } - - 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(); - }) - .catch(() => {}); } get _overlayInvokerNode() { @@ -213,15 +182,12 @@ export const OverlayMixin = dedupeMixin( this.__syncToOverlayController(); this.__setupSyncFromOverlayController(); this._setupOpenCloseListeners(); - this.__overlaySetupCompleteResolve(); - this.__isOverlaySetup = true; } _teardownOverlayCtrl() { this._teardownOpenCloseListeners(); this.__teardownSyncFromOverlayController(); this._overlayCtrl.teardown(); - this.__isOverlaySetup = false; } /** diff --git a/packages/overlays/test-suites/OverlayMixin.suite.js b/packages/overlays/test-suites/OverlayMixin.suite.js index 9e18bb788..b9f1b0c96 100644 --- a/packages/overlays/test-suites/OverlayMixin.suite.js +++ b/packages/overlays/test-suites/OverlayMixin.suite.js @@ -195,10 +195,10 @@ export function runOverlayMixinSuite({ tagString, tag, suffix = '' }) { it('supports nested overlays', async () => { const el = await fixture(html` - <${tag}> + <${tag} id="main-dialog">
open nested overlay: - <${tag}> + <${tag} id="sub-dialog">
Nested content
@@ -222,6 +222,23 @@ export function runOverlayMixinSuite({ tagString, tag, suffix = '' }) { expect(nestedOverlayEl._overlayCtrl.contentNode).to.be.displayed; }); + it('[global] allows for moving of the element', async () => { + const el = await fixture(html` + <${tag}> +
content of the nested overlay
+ + + `); + if (el._overlayCtrl.placementMode === 'global') { + expect(getGlobalOverlayNodes().length).to.equal(1); + + const moveTarget = await fixture('
'); + 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 () => { const nestedEl = await fixture(html` <${tag} id="nest"> @@ -241,15 +258,12 @@ export function runOverlayMixinSuite({ tagString, tag, suffix = '' }) { `); 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 const overlayContainerNodes = getGlobalOverlayNodes(); 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 - expect(lastContentNodeInContainer.firstElementChild.innerText).to.equal( + expect(lastContentNodeInContainer.firstElementChild.firstChild.textContent).to.equal( 'content of the nested overlay', ); 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'); } }); - - it("doesn't tear down controller when dom nodes are being moved around", async () => { - const nestedEl = await fixture(html` - <${tag} id="nest"> -
content of the nested overlay
- - - `); - - const setupOverlayCtrlSpy = sinon.spy(nestedEl, '_setupOverlayCtrl'); - const teardownOverlayCtrlSpy = sinon.spy(nestedEl, '_teardownOverlayCtrl'); - - const el = await fixture(html` - <${tag} id="main"> -
- open nested overlay: - ${nestedEl} -
- - - `); - - // 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); - }); }); } diff --git a/packages/overlays/test/OverlayController.test.js b/packages/overlays/test/OverlayController.test.js index e4535bcc7..4411537ba 100644 --- a/packages/overlays/test/OverlayController.test.js +++ b/packages/overlays/test/OverlayController.test.js @@ -188,6 +188,42 @@ describe('OverlayController', () => { ctrl.teardown(); 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 = ` +
+ + +
+ `; + const contentNode = document.createElement('div'); + contentNode.slot = 'contentNode'; + shadowHost.appendChild(contentNode); + + const wrapper = await fixture('
'); + // Ensure the contentNode is connected to DOM + wrapper.appendChild(shadowHost); + + // has one child =
+ 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', () => { @@ -1372,7 +1408,7 @@ describe('OverlayController', () => { }).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'); shadowHost.attachShadow({ mode: 'open' }); shadowHost.shadowRoot.innerHTML = ` diff --git a/packages/select-rich/src/LionSelectRich.js b/packages/select-rich/src/LionSelectRich.js index 0557f374b..708b2a03e 100644 --- a/packages/select-rich/src/LionSelectRich.js +++ b/packages/select-rich/src/LionSelectRich.js @@ -195,10 +195,11 @@ export class LionSelectRich extends ScopedElementsMixin( } connectedCallback() { + // need to do this before anything else + this._listboxNode.registrationTarget = this; if (super.connectedCallback) { super.connectedCallback(); } - this._listboxNode.registrationTarget = this; this._invokerNode.selectedElement = this.formElements[this.checkedIndex]; this.__setupInvokerNode(); this.__setupListboxNode(); @@ -213,10 +214,6 @@ export class LionSelectRich extends ScopedElementsMixin( this.registrationComplete.then(() => { this.__initInteractionStates(); }); - - this._overlaySetupComplete.then(() => { - this.__setupOverlay(); - }); } disconnectedCallback() { @@ -226,6 +223,10 @@ export class LionSelectRich extends ScopedElementsMixin( if (this._labelNode) { this._labelNode.removeEventListener('click', this.__toggleChecked); } + this._scrollTargetNode.removeEventListener('keydown', this.__overlayOnHide); + this.__teardownInvokerNode(); + this.__teardownListboxNode(); + this.__teardownEventListeners(); } requestUpdateInternal(name, oldValue) { @@ -658,7 +659,8 @@ export class LionSelectRich extends ScopedElementsMixin( } } - __setupOverlay() { + _setupOverlayCtrl() { + super._setupOverlayCtrl(); this._initialInheritsReferenceWidth = this._overlayCtrl.inheritsReferenceWidth; this.__overlayBeforeShow = () => { if (this.hasNoDefaultSelected) { @@ -688,10 +690,6 @@ export class LionSelectRich extends ScopedElementsMixin( this._overlayCtrl.removeEventListener('show', this.__overlayOnShow); this._overlayCtrl.removeEventListener('before-show', this.__overlayBeforeShow); this._overlayCtrl.removeEventListener('hide', this.__overlayOnHide); - this._scrollTargetNode.removeEventListener('keydown', this.__overlayOnHide); - this.__teardownInvokerNode(); - this.__teardownListboxNode(); - this.__teardownEventListeners(); } __preventScrollingWithArrowKeys(ev) { diff --git a/packages/tooltip/src/LionTooltip.js b/packages/tooltip/src/LionTooltip.js index dcb69dd68..d4ce8f6dd 100644 --- a/packages/tooltip/src/LionTooltip.js +++ b/packages/tooltip/src/LionTooltip.js @@ -90,12 +90,6 @@ export class LionTooltip extends OverlayMixin(LitElement) { this.__setupRepositionCompletePromise(); } - connectedCallback() { - if (super.connectedCallback) { - super.connectedCallback(); - } - } - render() { return html` diff --git a/packages/tooltip/test/lion-tooltip.test.js b/packages/tooltip/test/lion-tooltip.test.js index f7d4111dd..111f92fe9 100644 --- a/packages/tooltip/test/lion-tooltip.test.js +++ b/packages/tooltip/test/lion-tooltip.test.js @@ -134,7 +134,6 @@ describe('lion-tooltip', () => { el.opened = true; await el.repositionComplete; - // Pretty sure we use flex for this now so that's why it fails /* expect(getComputedStyle(el.__arrowElement).getPropertyValue('top')).to.equal( '11px', diff --git a/scripts/screenshots/index.js b/scripts/screenshots/index.js index 5058b6372..ca1cb3bc4 100644 --- a/scripts/screenshots/index.js +++ b/scripts/screenshots/index.js @@ -1,3 +1,4 @@ +/* eslint-disable no-console */ /* eslint-disable import/no-extraneous-dependencies */ const { chromium } = require('playwright'); const looksSame = require('looks-same'); diff --git a/yarn.lock b/yarn.lock index 7928ea266..15d9c27e2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2513,10 +2513,10 @@ dependencies: semver "^7.3.2" -"@web/dev-server-core@^0.2.2", "@web/dev-server-core@^0.2.6": - version "0.2.6" - resolved "https://registry.yarnpkg.com/@web/dev-server-core/-/dev-server-core-0.2.6.tgz#522e524056e184d691138a76f0afa605b639160b" - integrity sha512-C04oUS5LijC5rLurH/+5uRkgRgD9EVAY9tHi+TZv/57a3QvvPME6ipKbA6MFvkLdeiSdYLKNTY/shjukGfNrcg== +"@web/dev-server-core@^0.2.2": + version "0.2.5" + resolved "https://registry.yarnpkg.com/@web/dev-server-core/-/dev-server-core-0.2.5.tgz#f05dd29c62f303b20589e439af6a838a831b060b" + integrity sha512-t1R1g3/CLwgVjag075dtyCqoX9KRY4gLIXn/12h05Y+wSzuEjFkezOxhZCyDt0qUzDd2eZ60mOuyq+r5SmV7OQ== dependencies: chokidar "^3.4.0" clone "^2.1.2" @@ -2532,7 +2532,28 @@ parse5 "^6.0.0" 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" 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== @@ -2553,14 +2574,14 @@ polyfills-loader "^1.6.1" valid-url "^1.0.9" -"@web/dev-server-rollup@^0.2.4": - version "0.2.4" - resolved "https://registry.yarnpkg.com/@web/dev-server-rollup/-/dev-server-rollup-0.2.4.tgz#45bb4595eee9af1b3f1b23ebd623ee7bc53922b2" - integrity sha512-NpW5BRkpzHZXtH73bH4JI/TqIuv4UHxo0LWjqN4V44xweC1mnTL6mzjYDy/HxfscrYs6pp1s2d+hJ2Lb5uldFQ== +"@web/dev-server-rollup@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@web/dev-server-rollup/-/dev-server-rollup-0.2.3.tgz#e95cc3090cb624084c90f5a7f31bb3fc85fd9b53" + integrity sha512-rR7jM4EW1fsTYb2/RksCNPWlDteJXdnoGq7OGAV6+qDk0JvO4GnsIRLcFcKuCEcjgK9oP2ZgqLdv9qMxkzc4ng== 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-core" "^0.7.5" + "@web/test-runner-core" "^0.7.4" chalk "^4.1.0" parse5 "^6.0.1" rollup "^2.20.0" @@ -2624,13 +2645,13 @@ dependencies: "@web/test-runner-core" "^0.7.4" -"@web/test-runner-core@^0.7.4", "@web/test-runner-core@^0.7.5": - version "0.7.5" - resolved "https://registry.yarnpkg.com/@web/test-runner-core/-/test-runner-core-0.7.5.tgz#8050d97a4e275be122a2dc46334f02c05b52b358" - integrity sha512-5V9gEYL8a6nxurXKFR/RigRQdYs67jO7Mo3Uj/XbGO54guZktOLCsCtkPCSsYGuNkerVUpyOAKX76ftuOTwblQ== +"@web/test-runner-core@^0.7.4": + version "0.7.4" + resolved "https://registry.yarnpkg.com/@web/test-runner-core/-/test-runner-core-0.7.4.tgz#ee8f031c893b32009ce29002f0de865e2aa718da" + integrity sha512-DS/BxZTjG64HGObybmSus7GRuWoPaNnPt44pTXSWpIxMvRB3nv/Q2I+wE0Nx66PhC/uM2L74o+CIT+g7qRWsdg== dependencies: "@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" debounce "^1.2.0" deepmerge "^4.2.2" @@ -2684,17 +2705,17 @@ "@web/test-runner-core" "^0.7.4" selenium-webdriver "^4.0.0-alpha.7" -"@web/test-runner@^0.7.3": - version "0.7.14" - resolved "https://registry.yarnpkg.com/@web/test-runner/-/test-runner-0.7.14.tgz#ac5840318d0f725a767b895fabeed83ae1e3fcbb" - integrity sha512-tbmEb/1H1KS1vgY6hRMhJgBtynRw+YRufptFkzwxsdAnMM6iHm6lCAGeFOBb96LawDBC+8IWauYtr/IHYLkhhg== +"@web/test-runner@^0.7.13": + version "0.7.13" + resolved "https://registry.yarnpkg.com/@web/test-runner/-/test-runner-0.7.13.tgz#8bfb9cd249e1bbd5fb5f0c2716689e137922f2ae" + integrity sha512-DOhWTQqKSxUVVq3e409sjCCmZEJo7k1kMv3DqRW8668bsD0KG+YR5SEIWIIg7BuUHDS40cnjWOmnLo4ttRJj7g== dependencies: "@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-cli" "^0.5.6" "@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" command-line-args "^5.1.1" deepmerge "^4.2.2" @@ -7430,7 +7451,7 @@ lit-element@^2.2.1, lit-element@^2.3.1, lit-element@~2.4.0: dependencies: 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" resolved "https://registry.yarnpkg.com/lit-html/-/lit-html-1.3.0.tgz#c80f3cc5793a6dea6c07172be90a70ab20e56034" integrity sha512-0Q1bwmaFH9O14vycPHw8C/IeHMk/uSDldVLIefu/kfbTBGIc44KGH6A8p1bDfxUfHdc8q6Ct7kQklWoHgr4t1Q==