tp-dialog/tp-dialog.js

172 lines
4.5 KiB
JavaScript
Raw Permalink Normal View History

2022-03-12 22:36:52 +01:00
/**
@license
Copyright (c) 2022 trading_peter
This program is available under Apache License Version 2.0
*/
import '@tp/tp-icon/tp-icon.js';
2022-03-12 23:39:27 +01:00
import { LitElement, html, css, svg } from 'lit';
2022-03-12 22:36:52 +01:00
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;
2022-03-12 22:36:52 +01:00
}
: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`
2022-03-17 11:47:07 +01:00
<dialog part="dialog">
2022-03-12 22:36:52 +01:00
${showClose ? html`
<div class="close-icon">
<tp-icon .icon=${this.icon ? this.icon : TpDialog.closeIcon} dialog-dismiss></tp-icon>
</div>
` : null}
<slot></slot>
</dialog>
`;
}
static get properties() {
return {
open: { type: Boolean, reflect: true },
showClose: { type: Boolean },
icon: { type: Object },
2024-11-22 10:54:57 +01:00
closeOnEsc: { type: Boolean },
closeOnOutsideClick: { type: Boolean },
2022-03-12 22:36:52 +01:00
};
}
static get closeIcon() {
return svg`<path fill="var(--tp-icon-color)" d="M20 6.91L17.09 4L12 9.09L6.91 4L4 6.91L9.09 12L4 17.09L6.91 20L12 14.91L17.09 20L20 17.09L14.91 12L20 6.91Z" />`;
}
get dialog() {
return this.shadowRoot.querySelector('dialog');
}
2024-11-22 10:54:57 +01:00
constructor() {
super();
this._handleEscKey = this._handleEscKey.bind(this);
}
2022-03-12 22:36:52 +01:00
connectedCallback() {
super.connectedCallback();
this.listen(this, 'click', '_onDialogClick');
2022-04-26 14:04:01 +02:00
this.listen(this, 'dialog-close', 'close');
2022-03-12 22:36:52 +01:00
}
disconnectedCallback() {
super.disconnectedCallback();
this.unlisten(this, 'click', '_onDialogClick');
2022-04-26 14:04:01 +02:00
this.unlisten(this, 'dialog-close', 'close');
2024-11-22 10:54:57 +01:00
if (this.closeOnEsc) {
document.removeEventListener('keydown', this._handleEscKey);
}
2022-03-12 22:36:52 +01:00
}
show() {
this.dialog.show();
this.open = true;
2024-11-22 10:54:57 +01:00
if (this.closeOnEsc) {
document.addEventListener('keydown', this._handleEscKey, { once: true });
}
2022-03-12 22:36:52 +01:00
}
showModal() {
this.dialog.showModal();
this.open = true;
2024-11-22 10:54:57 +01:00
if (this.closeOnEsc) {
document.addEventListener('keydown', this._handleEscKey, { once: true });
}
if (this.closeOnOutsideClick) {
this.addEventListener('click', this._handleOutsideClick, { once: true });
}
2022-03-12 22:36:52 +01:00
}
close() {
this.dialog.close();
2024-11-22 11:27:07 +01:00
this.dispatchEvent(new CustomEvent('closed', { detail: null, bubbles: true, composed: true }));
2022-03-12 22:36:52 +01:00
this.open = false;
}
_onDialogClick(event) {
2024-11-22 10:54:57 +01:00
if (this.closeOnOutsideClick) {
const path = event.composedPath();
if (!path.includes(this.dialog)) {
this.close();
event.stopPropagation();
return;
}
}
2022-03-12 22:36:52 +01:00
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;
}
}
2024-11-22 10:54:57 +01:00
_handleEscKey(event) {
if (event.key === 'Escape' && this.closeOnEsc) {
this.close();
}
}
2022-03-12 22:36:52 +01:00
}
window.customElements.define('tp-dialog', TpDialog);