import {css, html, ifDefined, LitElement, repeat, SlotMixin} from '@lion/core'; import {DialogButton, Et2Dialog} from "./Et2Dialog"; import {et2_template} from "../et2_widget_template"; import {Et2DialogContent} from "./Et2DialogContent"; /** * This handles the visible portion of the dialog, including the title & close button. * * Note we can't extend Et2Widget. If I try, something in the render / creation breaks and calling open() gives an * error with modal: true */ export class Et2DialogOverlay extends SlotMixin(LitElement) { protected buttons : DialogButton[]; protected _dialog : Et2Dialog; /** * I don't know what's going on with styles here, but if we define Et2DialogOverlay.styles it breaks * dialog display in Firefox. * The styles are added in render(), which is bad from a performance standpoint, but good in that it works. */ static get _styles() { return css` :host { display: inline-block; background: white; position: relative; border: 1px solid silver; box-shadow: -2px 1px 9px 3px #b4b4b4; min-width: 200px } :host([hidden]) { display: none; } .overlay { display: flex; flex-direction: column; } .overlay__header { display: flex; border-bottom: 1px inset; } .overlay__heading { margin: 0px; padding: 6px 10px 0px; flex: 1; font-size: 130%; font-weight: 400; } #overlay-content-node-wrapper { flex: 1 1 auto; padding: 10px; } .overlay__heading > .overlay__close-button { flex: none; } .overlay__close-button { min-width: 24px; min-height: 24px; border-width: 0; padding: 0; font-size: 24px; } #overlay-content-buttons { display: flex; flex-wrap: nowrap; justify-content: flex-start; align-items: stretch; gap: 5px; border-top: 1px solid silver; margin-top: 0.5em; padding: 5px; } /* Override style for legacy nextmatch action dialogs */ ::slotted([slot="content"]) { display: block !important; position: relative !important; inset: initial !important; } ::slotted([slot="buttons"]) { flex: 1 0 auto; } ::slotted([align="right"]) { margin-left: auto; order: 1; } `; } get properties() { return { // Allow to force size, otherwise it sizes to contents width: Number, height: Number, } } get slots() { return { ...super.slots, buttons: () => { return this._buttonsTemplate(); } } } constructor() { super(); this.buttons = []; } // Need to wait for Overlay async getUpdateComplete() { let result = await super.getUpdateComplete(); if(this._contentNode && this._contentNode instanceof LitElement) { await (this._contentNode).updateComplete; } return result; } connectedCallback() { super.connectedCallback(); // Need to wait for Overlay this.updateComplete .then(async() => { if(this._contentNode && this._contentNode instanceof LitElement) { // Re-do render to get proper images this._contentNode.requestUpdate(); await this._contentNode.updateComplete; } }); } egw() : IegwAppLocal { if(this._dialog) { return this._dialog.egw(); } else { return egw(); } } /** * Block until after the paint - This is needed to deal with children not fully "done" before the OverlayController * tries to do things with them * * @returns {Promise} */ async performUpdate() { await new Promise((resolve) => setTimeout(() => resolve())); return super.performUpdate(); } get _contentNode() : Et2DialogContent | et2_template { // @ts-ignore return this.querySelector("[slot='content']"); } /** @private */ __dispatchCloseEvent() { this.dispatchEvent(new Event('close-overlay')); } render() { // This style is just for this dialog let styles = [Et2DialogOverlay._styles]; if(this.width && Number.isInteger(this.width)) { styles.push(css`.overlay {width: ${this.width}px}`); } if(this.height && Number.isInteger(this.height)) { styles.push(css`.overlay {height: ${this.height}px}`); } return html`

`; } _buttonsTemplate() { if(!this.buttons) { return; } // Set button._parent here, otherwise button will have trouble finding our egw() return html`${repeat(this.buttons, (button : DialogButton) => button.id, (button, index) => { return html` ` })}`; } }