Improve combobox overlay observer (#14463)

This commit is contained in:
Paul Bottein 2022-11-28 16:53:35 +01:00 committed by GitHub
parent aec0eb3c78
commit 4846fa1a74
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -9,14 +9,7 @@ import type {
ComboBoxLightValueChangedEvent, ComboBoxLightValueChangedEvent,
} from "@vaadin/combo-box/vaadin-combo-box-light"; } from "@vaadin/combo-box/vaadin-combo-box-light";
import { registerStyles } from "@vaadin/vaadin-themable-mixin/register-styles"; import { registerStyles } from "@vaadin/vaadin-themable-mixin/register-styles";
import { import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
css,
CSSResultGroup,
html,
LitElement,
PropertyValues,
TemplateResult,
} from "lit";
import { customElement, property, query } from "lit/decorators"; import { customElement, property, query } from "lit/decorators";
import { ifDefined } from "lit/directives/if-defined"; import { ifDefined } from "lit/directives/if-defined";
import { fireEvent } from "../common/dom/fire_event"; import { fireEvent } from "../common/dom/fire_event";
@ -113,6 +106,8 @@ export class HaComboBox extends LitElement {
private _overlayMutationObserver?: MutationObserver; private _overlayMutationObserver?: MutationObserver;
private _bodyMutationObserver?: MutationObserver;
public async open() { public async open() {
await this.updateComplete; await this.updateComplete;
this._comboBox?.open(); this._comboBox?.open();
@ -130,6 +125,10 @@ export class HaComboBox extends LitElement {
this._overlayMutationObserver.disconnect(); this._overlayMutationObserver.disconnect();
this._overlayMutationObserver = undefined; this._overlayMutationObserver = undefined;
} }
if (this._bodyMutationObserver) {
this._bodyMutationObserver.disconnect();
this._bodyMutationObserver = undefined;
}
} }
public get selectedItem() { public get selectedItem() {
@ -227,7 +226,7 @@ export class HaComboBox extends LitElement {
private _openedChanged(ev: ComboBoxLightOpenedChangedEvent) { private _openedChanged(ev: ComboBoxLightOpenedChangedEvent) {
const opened = ev.detail.value; const opened = ev.detail.value;
// delay this so we can handle click event before setting _opened // delay this so we can handle click event for toggle button before setting _opened
setTimeout(() => { setTimeout(() => {
this.opened = opened; this.opened = opened;
}, 0); }, 0);
@ -235,36 +234,61 @@ export class HaComboBox extends LitElement {
fireEvent(this, ev.type, ev.detail); fireEvent(this, ev.type, ev.detail);
if (opened) { if (opened) {
this.removeInertOnOverlay();
}
}
private removeInertOnOverlay() {
if ("MutationObserver" in window && !this._overlayMutationObserver) {
const overlay = document.querySelector<HTMLElement>( const overlay = document.querySelector<HTMLElement>(
"vaadin-combo-box-overlay" "vaadin-combo-box-overlay"
); );
if (!overlay) { if (overlay) {
return; this._removeInert(overlay);
}
this._observeBody();
} else {
this._bodyMutationObserver?.disconnect();
this._bodyMutationObserver = undefined;
}
} }
this._overlayMutationObserver = new MutationObserver((mutations) => { private _observeBody() {
if ("MutationObserver" in window && !this._bodyMutationObserver) {
this._bodyMutationObserver = new MutationObserver((mutations) => {
mutations.forEach((mutation) => { mutations.forEach((mutation) => {
if ( mutation.addedNodes.forEach((node) => {
mutation.type === "attributes" && if (node.nodeName === "VAADIN-COMBO-BOX-OVERLAY") {
mutation.attributeName === "inert" this._removeInert(node as HTMLElement);
) { }
this._overlayMutationObserver?.disconnect(); });
this._overlayMutationObserver = undefined;
overlay.inert = false;
} else if (mutation.type === "childList") {
mutation.removedNodes.forEach((node) => { mutation.removedNodes.forEach((node) => {
if (node.nodeName === "VAADIN-COMBO-BOX-OVERLAY") { if (node.nodeName === "VAADIN-COMBO-BOX-OVERLAY") {
this._overlayMutationObserver?.disconnect(); this._overlayMutationObserver?.disconnect();
this._overlayMutationObserver = undefined; this._overlayMutationObserver = undefined;
} }
}); });
});
});
this._bodyMutationObserver.observe(document.body, {
childList: true,
});
}
}
private _removeInert(overlay: HTMLElement) {
if (overlay.inert) {
overlay.inert = false;
this._overlayMutationObserver?.disconnect();
this._overlayMutationObserver = undefined;
return;
}
if ("MutationObserver" in window && !this._overlayMutationObserver) {
this._overlayMutationObserver = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.attributeName === "inert") {
const target = mutation.target as HTMLElement;
if (target.inert) {
this._overlayMutationObserver?.disconnect();
this._overlayMutationObserver = undefined;
target.inert = false;
}
} }
}); });
}); });
@ -272,19 +296,6 @@ export class HaComboBox extends LitElement {
this._overlayMutationObserver.observe(overlay, { this._overlayMutationObserver.observe(overlay, {
attributes: true, attributes: true,
}); });
this._overlayMutationObserver.observe(document.body, {
childList: true,
});
}
}
updated(changedProps: PropertyValues) {
super.updated(changedProps);
if (
changedProps.has("filteredItems") ||
(changedProps.has("items") && this.opened)
) {
this.removeInertOnOverlay();
} }
} }