@lion/overlays
Advanced tools
Comparing version 0.22.4 to 0.22.5
# Change Log | ||
## 0.22.5 | ||
### Patch Changes | ||
- 83359ac2: Only set inert when placementMode is global, otherwise events are broken inside local overlay content | ||
- 7709d7c2: Fix deep contains util to properly check multiple nested shadow roots, and do not set containsTarget to false when children deepContains returns false. This would undo a found target in another child somewhere that was found in an earlier recursion. | ||
- 2eeace23: Keep transitionShow and transitionHide as user hooks | ||
## 0.22.4 | ||
@@ -4,0 +12,0 @@ |
{ | ||
"name": "@lion/overlays", | ||
"version": "0.22.4", | ||
"version": "0.22.5", | ||
"description": "Overlays System using lit-html for rendering", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
@@ -378,2 +378,4 @@ /** | ||
/** | ||
* Method to be overriden by subclassers | ||
* | ||
* @param {{backdropNode:HTMLElement, contentNode:HTMLElement}} hideConfig | ||
@@ -385,4 +387,13 @@ */ | ||
}): Promise<void>; | ||
/** | ||
* @param {{backdropNode:HTMLElement, contentNode:HTMLElement}} hideConfig | ||
*/ | ||
_transitionHide(hideConfig: { | ||
backdropNode: HTMLElement; | ||
contentNode: HTMLElement; | ||
}): Promise<void>; | ||
__backdropAnimation: Promise<any> | undefined; | ||
/** | ||
* To be overridden by subclassers | ||
* | ||
* @param {{backdropNode:HTMLElement, contentNode:HTMLElement}} showConfig | ||
@@ -394,2 +405,9 @@ */ | ||
}): Promise<void>; | ||
/** | ||
* @param {{backdropNode:HTMLElement, contentNode:HTMLElement}} showConfig | ||
*/ | ||
_transitionShow(showConfig: { | ||
backdropNode: HTMLElement; | ||
contentNode: HTMLElement; | ||
}): Promise<void>; | ||
_restoreFocus(): void; | ||
@@ -396,0 +414,0 @@ toggle(): Promise<void>; |
@@ -684,3 +684,6 @@ import '@lion/core/src/differentKeyEventNamesShimIE.js'; | ||
this.dispatchEvent(new Event('show')); | ||
await this.transitionShow({ backdropNode: this.backdropNode, contentNode: this.contentNode }); | ||
await this._transitionShow({ | ||
backdropNode: this.backdropNode, | ||
contentNode: this.contentNode, | ||
}); | ||
} | ||
@@ -791,3 +794,7 @@ /** @type {function} */ | ||
if (!event.defaultPrevented) { | ||
await this.transitionHide({ backdropNode: this.backdropNode, contentNode: this.contentNode }); | ||
await this._transitionHide({ | ||
backdropNode: this.backdropNode, | ||
contentNode: this.contentNode, | ||
}); | ||
this.contentWrapperNode.style.display = 'none'; | ||
@@ -803,6 +810,17 @@ this._handleFeatures({ phase: 'hide' }); | ||
/** | ||
* Method to be overriden by subclassers | ||
* | ||
* @param {{backdropNode:HTMLElement, contentNode:HTMLElement}} hideConfig | ||
*/ | ||
// eslint-disable-next-line class-methods-use-this, no-empty-function, no-unused-vars | ||
async transitionHide(hideConfig) { | ||
async transitionHide(hideConfig) {} | ||
/** | ||
* @param {{backdropNode:HTMLElement, contentNode:HTMLElement}} hideConfig | ||
*/ | ||
// eslint-disable-next-line class-methods-use-this, no-empty-function, no-unused-vars | ||
async _transitionHide(hideConfig) { | ||
// `this.transitionHide` is a hook for our users | ||
await this.transitionHide({ backdropNode: this.backdropNode, contentNode: this.contentNode }); | ||
if (hideConfig.backdropNode) { | ||
@@ -837,6 +855,17 @@ hideConfig.backdropNode.classList.remove( | ||
/** | ||
* To be overridden by subclassers | ||
* | ||
* @param {{backdropNode:HTMLElement, contentNode:HTMLElement}} showConfig | ||
*/ | ||
// eslint-disable-next-line class-methods-use-this, no-empty-function, no-unused-vars | ||
async transitionShow(showConfig) { | ||
async transitionShow(showConfig) {} | ||
/** | ||
* @param {{backdropNode:HTMLElement, contentNode:HTMLElement}} showConfig | ||
*/ | ||
// eslint-disable-next-line class-methods-use-this, no-empty-function, no-unused-vars | ||
async _transitionShow(showConfig) { | ||
// `this.transitionShow` is a hook for our users | ||
await this.transitionShow({ backdropNode: this.backdropNode, contentNode: this.contentNode }); | ||
if (showConfig.backdropNode) { | ||
@@ -1020,3 +1049,3 @@ showConfig.backdropNode.classList.add( | ||
if (this.manager) { | ||
this.manager.informTrapsKeyboardFocusGotEnabled(); | ||
this.manager.informTrapsKeyboardFocusGotEnabled(this.placementMode); | ||
} | ||
@@ -1023,0 +1052,0 @@ } |
@@ -51,3 +51,6 @@ /** | ||
disableTrapsKeyboardFocusForAll(): void; | ||
informTrapsKeyboardFocusGotEnabled(): void; | ||
/** | ||
* @param {'local' | 'global' | undefined} placementMode | ||
*/ | ||
informTrapsKeyboardFocusGotEnabled(placementMode: 'local' | 'global' | undefined): void; | ||
informTrapsKeyboardFocusGotDisabled({ disabledCtrl, findNewTrap }?: { | ||
@@ -54,0 +57,0 @@ disabledCtrl: any; |
@@ -156,4 +156,7 @@ import { unsetSiblingsInert, setSiblingsInert } from './utils/inert-siblings.js'; | ||
informTrapsKeyboardFocusGotEnabled() { | ||
if (this.siblingsInert === false) { | ||
/** | ||
* @param {'local' | 'global' | undefined} placementMode | ||
*/ | ||
informTrapsKeyboardFocusGotEnabled(placementMode) { | ||
if (this.siblingsInert === false && placementMode === 'global') { | ||
if (OverlaysManager.__globalRootNode) { | ||
@@ -160,0 +163,0 @@ setSiblingsInert(this.globalRootNode); |
@@ -13,11 +13,9 @@ /** | ||
/** @param {HTMLElement} elem */ | ||
/** @param {HTMLElement|ShadowRoot} elem */ | ||
function checkChildren(elem) { | ||
for (let i = 0; i < elem.children.length; i += 1) { | ||
const child = /** @type {HTMLElement} */ (elem.children[i]); | ||
if (child.shadowRoot) { | ||
containsTarget = deepContains(child.shadowRoot, targetEl); | ||
if (containsTarget) { | ||
break; | ||
} | ||
if (child.shadowRoot && deepContains(child.shadowRoot, targetEl)) { | ||
containsTarget = true; | ||
break; | ||
} | ||
@@ -31,12 +29,10 @@ if (child.children.length > 0) { | ||
// If element is not shadowRoot itself | ||
if (el instanceof HTMLElement) { | ||
if (el.shadowRoot) { | ||
containsTarget = deepContains(el.shadowRoot, targetEl); | ||
if (containsTarget) { | ||
return true; | ||
} | ||
if (el instanceof HTMLElement && el.shadowRoot) { | ||
containsTarget = deepContains(el.shadowRoot, targetEl); | ||
if (containsTarget) { | ||
return true; | ||
} | ||
checkChildren(el); | ||
} | ||
checkChildren(el); | ||
return containsTarget; | ||
} |
@@ -22,10 +22,16 @@ import { expect, fixture } from '@open-wc/testing'; | ||
`)); | ||
const lightEl = /** @type {HTMLElement} */ (element.querySelector('#light-el-1')); | ||
const lightChildEl = /** @type {HTMLElement} */ (element.querySelector('#light-el-1')); | ||
expect(deepContains(element, element)).to.be.true; | ||
expect(deepContains(element, shadowElement)).to.be.true; | ||
expect(deepContains(element, shadowElementChild)).to.be.true; | ||
expect(deepContains(element, lightEl)).to.be.true; | ||
expect(deepContains(element, lightChildEl)).to.be.true; | ||
expect(deepContains(shadowElement, shadowElement)).to.be.true; | ||
expect(deepContains(shadowElement, shadowElementChild)).to.be.true; | ||
expect(deepContains(shadowRoot, shadowElementChild)).to.be.true; | ||
// Siblings | ||
expect(deepContains(element.firstElementChild, element.lastElementChild)).to.be.false; | ||
// Unrelated | ||
expect(deepContains(lightChildEl, shadowElementChild)).to.be.false; | ||
}); | ||
@@ -67,2 +73,40 @@ | ||
}); | ||
it('can detect containing elements inside multiple nested shadow roots', async () => { | ||
const shadowNestedElement = await fixture('<div id="shadow-nested"></div>'); | ||
const shadowNestedRoot = shadowNestedElement.attachShadow({ mode: 'open' }); | ||
shadowNestedRoot.innerHTML = ` | ||
<button id="nested-el-1">Button</button> | ||
<a id="nested-el-2" href="#foo">Href</a> | ||
<input id="nested-el-3"> | ||
`; | ||
const shadowElement = /** @type {HTMLElement} */ (await fixture('<div id="shadow"></div>')); | ||
const shadowRoot = shadowElement.attachShadow({ mode: 'open' }); | ||
shadowRoot.innerHTML = ` | ||
<button id="el-1">Button</button> | ||
<input id="el-3"> | ||
`; | ||
shadowRoot.insertBefore(shadowNestedElement, shadowRoot.lastElementChild); | ||
const element = /** @type {HTMLElement} */ (await fixture(html` | ||
<div id="light"> | ||
${shadowElement} | ||
<button id="light-el-1"></button> | ||
</div> | ||
`)); | ||
expect(deepContains(element, element.firstElementChild)).to.be.true; | ||
expect(deepContains(element, element.firstElementChild.shadowRoot)).to.be.true; | ||
expect(deepContains(element, element.firstElementChild.shadowRoot.children[1])).to.be.true; | ||
expect(deepContains(element, element.firstElementChild.shadowRoot.children[1].shadowRoot)).to.be | ||
.true; | ||
expect( | ||
deepContains( | ||
element, | ||
element.firstElementChild.shadowRoot.children[1].shadowRoot.lastElementChild, | ||
), | ||
).to.be.true; | ||
}); | ||
}); |
315973
6262