import type { PropertyValues } from 'lit' import { css, html } from 'lit' import { property, query, state } from 'lit/decorators.js' import { when } from 'lit/directives/when.js' import { classMap } from 'lit/directives/class-map.js' import { styleMap } from 'lit/directives/style-map.js' import { UsBaseElement } from '../base/UsBaseElement' import { customElementIfNotExist } from '../../utils/customElementIfNotExist' import { dispatchCustomEvent } from '../../utils/dispatchCustomEvent' import { EnumModalHeaderTypes } from '../modalHeader/model/IModalHeaderProps' import type { IPopupPositions, IPopupProps } from './model/IPopupProps' import UsPopup_css from './popup.pcss' import vars_css from './vars.pcss' import '../../layouts/scrollLayout/ScrollLayout' import '../modalHeader/UsModalHeader' import '../header/UsHeader' import '../button/UsButton' declare global { interface HTMLElementTagNameMap { 'us-popup': UsPopup } } @customElementIfNotExist('us-popup') export class UsPopup extends UsBaseElement implements IPopupProps { static styles = [ UsBaseElement.styles, css([vars_css] as TemplateStringsArray | any), css([UsPopup_css] as TemplateStringsArray | any), ] @property({ type: String }) width = '256px' @property({ type: String }) maxWidth = 'none' @property({ type: String }) height = 'auto' @property({ type: String }) maxHeight = 'none' @property({ type: String }) name!: string @property({ type: Boolean }) boxShadow = false @property({ type: Boolean }) overlay = false @property({ type: Boolean }) show = false @property({ type: Boolean }) alternativeHeader = false @property({ type: Boolean }) scrollable = false @property({ type: Boolean }) hideCloseButton = false @property({ type: Boolean }) notFullWidth = false @property({ type: Boolean }) noContentPadding = false @property({ type: String }) beforeTitleIcon: EnumModalHeaderTypes = EnumModalHeaderTypes.DEFAULT @property({ type: Boolean }) readonly = false // if you need open the modal over another one @property({ type: Boolean }) openOver = false @property({ type: String }) position: IPopupPositions = 'center' @property({ type: String }) variant: IPopupProps['variant'] = 'default' @property({ type: String, attribute: 'data-testid', reflect: true }) dataTestId = 'popup' @property({ type: Boolean }) transparent = false @state() innerShow!: boolean @query('.us-popup') _popupContainer: HTMLDivElement | undefined connectedCallback() { super.connectedCallback() this.addEventListener('keyup', this.onKeypress) } disconnectedCallback() { this.removeEventListener('keyup', this.onKeypress) super.disconnectedCallback() } firstUpdated(_changedProperties: PropertyValues) { this.focusContainer() super.firstUpdated(_changedProperties) } async updated(changeProperties: PropertyValues) { await super.updated(changeProperties) if (changeProperties.has('show')) this.innerShow = this.show } render() { const defaultHeader = html` ${when(!this.hideCloseButton, () => html` `)} ${when(this.beforeTitleIcon, () => html` `)} ` const alternativeHeader = html` ` const popup = html`
${when(this.variant === 'default', () => defaultHeader)} ${when(this.variant === 'preview', () => alternativeHeader)}
${when(this.variant === 'secondary', () => defaultHeader)} ${when(this.innerShow, () => html``)}
` return html`${when(this.show, () => popup, () => '')}` } focusContainer() { setTimeout(() => this._popupContainer?.focus()) } closeModal(e?: Event) { if (e) { if (e.target !== e.currentTarget) return e.preventDefault() } this.show = false dispatchCustomEvent('close', true, this, false, false) } handleCloseByEnter(e: KeyboardEvent) { if (e.key === 'Enter') { this.show = false dispatchCustomEvent('close', true, this, false, false) } } emitBackEvent(e?: Event) { if (e) e.preventDefault() dispatchCustomEvent('back', true, this, false, false) } private onKeypress(e: KeyboardEvent) { if (e.key === 'Escape') { if (this.alternativeHeader) this.emitBackEvent() else this.closeModal() } } private getContentClasses() { return classMap({ 'us-popup__content': true, 'us-popup__content_no-padding': this.noContentPadding, }) } private getContainerClasses() { return classMap({ 'us-popup__container': true, 'us-popup__container_boxshadow': this.boxShadow, 'us-popup__container_overflow-hidden': this.position === 'center', }) } private getMainClasses() { return classMap({ 'us-popup': true, 'us-popup_open-over': this.openOver, 'us-popup_preview': this.variant === 'preview', 'us-popup_secondary': this.variant === 'secondary', 'us-popup_full': !this.notFullWidth, 'us-popup_right': this.position === 'right', 'us-popup_left': this.position === 'left', 'us-popup_center': this.position === 'center', 'us-popup_overlay': this.overlay, 'us-popup_transparent': this.transparent, }) } private getContainerStyles() { return styleMap({ 'width': this.width, 'height': this.height, 'max-height': this.maxHeight, 'max-width': this.maxWidth, }) } }