import { LightningElement, api } from "lwc"; import { normalizeBoolean } from "dxUtils/normalizers"; import { LightningSlotElement } from "typings/custom"; const CONTAINER_CLASS = "dx-modal-drawer_container"; const OVERLAY_CLASS = "dx-modal-drawer_overlay"; const modalStyle = "position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); display: grid; justify-content: center; align-items: center; z-index: 5000; height: 100%; width: 100%; pointer-events: none;"; const overlayStyle = "background-color: #195594; bottom: 0; height: 100%; left: 0; opacity: 0.62; position: fixed; right: 0; top: 0; width: 100%; z-index: calc(5000 - 1);"; export default class Modal extends LightningElement { private _open = false; @api get open() { return this._open; } set open(value) { this._open = normalizeBoolean(value); if (this._open) { this.openModal(); } else { this.closeModal(); } } private overlayClass = OVERLAY_CLASS; private modal: HTMLElement | null = null; private overlay: HTMLElement | null = null; private root: HTMLElement | null = null; private modalContent: HTMLElement | null = null; private keydownListener: Event | null = null; get containerClass(): string { return CONTAINER_CLASS; } private onSlotChange = (e: LightningSlotElement) => { // @ts-ignore this.modalContent = e.target.assignedElements()[0]; if (!this.modal && !this.overlay) { this.appendModalToHTML(); } }; connectedCallback(): void { document.addEventListener("keydown", this.handleKeyDown.bind(this)); } disconnectedCallback(): void { window.removeEventListener("keydown", this.handleKeyDown.bind(this)); this.modal?.remove(); this.overlay?.remove(); } private handleKeyDown(event: KeyboardEvent): void { if (event.key === "Escape") { this.closeModal(); } } private appendModalToHTML = () => { // @ts-ignore this.root = document.querySelector("html"); this.modal = this.template.querySelector(`.${CONTAINER_CLASS}`); this.overlay = this.template.querySelector(`.${OVERLAY_CLASS}`); if (this.overlay && this.modal && this.modalContent && this.root) { this.modal.setAttribute("style", modalStyle); this.overlay.setAttribute("style", overlayStyle); this.modal.querySelector("div")?.appendChild(this.modalContent); if (this.open) { this.openModal(); } } }; private onClickModal(e: any) { if (e?.target?.className === OVERLAY_CLASS) { this.closeModal(); } } private openModal() { if (this.overlay && this.modal) { this.root?.appendChild(this.modal); this.root?.appendChild(this.overlay); this.modal.querySelector("div")?.focus(); } } private closeModal = () => { if (this.modal && this.overlay) { this.modal.remove(); this.overlay.remove(); this.dispatchEvent(new CustomEvent("closemodal")); } }; }