106 lines
3.9 KiB
JavaScript
106 lines
3.9 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
import { MozLitElement } from "chrome://global/content/lit-utils.mjs";
|
|
|
|
/**
|
|
* MozPanelWrappedElement bridges XULPanel's imperative API with a more
|
|
* Lit-friendly declarative option. Lit components whose display and positioning
|
|
* should be handled by a XUL panel can extend this class to control this behavior
|
|
* declaratively.
|
|
*
|
|
* The panel can be shown or hidden by changing this.panelState, and repositioned
|
|
* by changing this.panelAnchor.
|
|
*
|
|
* NOTE: This likely won't work correctly unless the class that inherits
|
|
* MozPanelWrappedElement is at the top of the Lit component stack, hence the need
|
|
* to extend this class instead of just wrapping the component tree with something.
|
|
*
|
|
* @property {string} panelID ID attribute to use for the panel element
|
|
* @property {"open"|"closed"} panelState controls whether panel is showing
|
|
* @property {HTMLElement} panelAnchor element that the panel should anchor to
|
|
* @property {boolean} noautofocus sets the panel's noautofocus attribute
|
|
* @property {boolean} norolluponanchor sets the panel's norolluponanchor attribute
|
|
* @property {boolean} rolluponmousewheel sets the panel's rolluponmousewheel attribute
|
|
* @property {boolean} consumeoutsideclicks sets the panel's consumeoutsideclicks attribute
|
|
* @property {boolean} level sets the panel's level attribute
|
|
*/
|
|
export class MozPanelWrappedElement extends MozLitElement {
|
|
static properties = {
|
|
panelID: { type: String },
|
|
panelState: { type: String },
|
|
panelAnchor: { type: HTMLElement },
|
|
noautofocus: { type: Boolean },
|
|
norolluponanchor: { type: Boolean },
|
|
rolluponmousewheel: { type: Boolean },
|
|
consumeoutsideclicks: { type: String },
|
|
level: { type: String },
|
|
};
|
|
|
|
/**
|
|
* Override this in a child class to do something when the popup is shown
|
|
*/
|
|
on_popupshown() {}
|
|
|
|
/**
|
|
* Override this in a child class to do something when the popup is hidden
|
|
*/
|
|
on_popuphidden() {}
|
|
|
|
createRenderRoot() {
|
|
if (!document.createXULElement) {
|
|
console.error(
|
|
"Unable to create panel: document.createXULElement is not available"
|
|
);
|
|
return super.createRenderRoot();
|
|
}
|
|
this.attachShadow({ mode: "open" });
|
|
this._panel = document.createXULElement("panel");
|
|
this._panel.setAttribute("id", "tabpreviewpanel");
|
|
this.syncPanelAttributes();
|
|
this._panel.addEventListener("popupshown", this.on_popupshown.bind(this));
|
|
this._panel.addEventListener("popuphidden", this.on_popuphidden.bind(this));
|
|
document.body.appendChild(this._panel);
|
|
this.shadowRoot.append(this._panel);
|
|
return this._panel;
|
|
}
|
|
|
|
syncPanelAttributes() {
|
|
this._panel.setAttribute("noautofocus", this.noautofocus);
|
|
this._panel.setAttribute("norolluponanchor", this.norolluponanchor);
|
|
this._panel.setAttribute(
|
|
"consumeoutsideclicks",
|
|
this.consumeoutsideclicks.toString()
|
|
);
|
|
this._panel.setAttribute("rolluponmousewheel", this.rolluponmousewheel);
|
|
this._panel.setAttribute("level", this.level);
|
|
}
|
|
|
|
updated(changedProperties) {
|
|
this.syncPanelAttributes();
|
|
if (changedProperties.has("panelState")) {
|
|
if (
|
|
this.panelState === "open" &&
|
|
!["open", "showing"].includes(this._panel.state)
|
|
) {
|
|
this._panel.openPopup(this.panelAnchor, {
|
|
position: "bottomleft topleft",
|
|
y: -2,
|
|
isContextMenu: false,
|
|
});
|
|
} else if (
|
|
this.panelState === "closed" &&
|
|
!["closed", "hiding"].includes(this._panel.state)
|
|
) {
|
|
this._panel.hidePopup();
|
|
}
|
|
} else if (
|
|
this.panelState === "open" &&
|
|
changedProperties.has("panelAnchor")
|
|
) {
|
|
this._panel.moveToAnchor(this.panelAnchor, "bottomleft topleft", 0, -2);
|
|
}
|
|
}
|
|
}
|