/** @license Copyright (c) 2022 trading_peter This program is available under Apache License Version 2.0 */ import '@tp/tp-icon/tp-icon.js'; import { LitElement, html, css, svg } from 'lit'; import { EventHelpers } from '@tp/helpers/event-helpers.js'; import { closest } from '@tp/helpers/closest.js'; class TpDialog extends EventHelpers(LitElement) { static get styles() { return [ css` :host { display: flex; justify-content: center; align-items: center; position: fixed; inset: 0px; pointer-events: none; overflow: auto; z-index: 900; } :host([open]) { pointer-events: all; } dialog { position: relative; border-radius: var(--tp-dialog-border-radius); background-color: var(--tp-dialog-bg); color: var(--text); border: var(--tp-dialog-border); padding: var(--tp-dialog-padding); } .close-icon { position: absolute; right: 4px; top: 5px; --tp-icon-width: 18px; --tp-icon-height: 18px; } ` ]; } render() { const { showClose } = this; return html` ${showClose ? html`
` : null}
`; } static get properties() { return { open: { type: Boolean, reflect: true }, showClose: { type: Boolean }, icon: { type: Object }, closeOnEsc: { type: Boolean }, closeOnOutsideClick: { type: Boolean }, }; } static get closeIcon() { return svg``; } get dialog() { return this.shadowRoot.querySelector('dialog'); } constructor() { super(); this._handleEscKey = this._handleEscKey.bind(this); } connectedCallback() { super.connectedCallback(); this.listen(this, 'click', '_onDialogClick'); this.listen(this, 'dialog-close', 'close'); } disconnectedCallback() { super.disconnectedCallback(); this.unlisten(this, 'click', '_onDialogClick'); this.unlisten(this, 'dialog-close', 'close'); if (this.closeOnEsc) { document.removeEventListener('keydown', this._handleEscKey); } } show() { this.dialog.show(); this.open = true; if (this.closeOnEsc) { document.addEventListener('keydown', this._handleEscKey, { once: true }); } } showModal() { this.dialog.showModal(); this.open = true; if (this.closeOnEsc) { document.addEventListener('keydown', this._handleEscKey, { once: true }); } if (this.closeOnOutsideClick) { this.addEventListener('click', this._handleOutsideClick, { once: true }); } } close() { this.dialog.close(); this.dispatchEvent(new CustomEvent('closed', { detail: null, bubbles: true, composed: true })); this.open = false; } _onDialogClick(event) { if (this.closeOnOutsideClick) { const path = event.composedPath(); if (!path.includes(this.dialog)) { this.close(); event.stopPropagation(); return; } } var rootTarget = event.composedPath()[0]; var target = closest(rootTarget, '[dialog-dismiss]', true) || closest(rootTarget, '[dialog-confirm]', true); while (target && target !== this) { if (target.hasAttribute) { if (target.hasAttribute('dialog-dismiss')) { var reason = target.getAttribute('dialog-dismiss'); this.dispatchEvent(new CustomEvent('dismissed', { detail: reason.length > 0 ? reason : true, bubbles: true, composed: true })); this.close(); event.stopPropagation(); break; } else if (target.hasAttribute('dialog-confirm')) { var reason = target.getAttribute('dialog-confirm'); this.dispatchEvent(new CustomEvent('confirmed', { detail: reason.length > 0 ? reason : true, bubbles: true, composed: true })); this.close(); event.stopPropagation(); break; } } target = target.parentNode; } } _handleEscKey(event) { if (event.key === 'Escape' && this.closeOnEsc) { this.close(); } } } window.customElements.define('tp-dialog', TpDialog);