UNPKG

@progressive-development/pd-page

Version:

Progressive development page helper, teaser, menu, footer.

223 lines (205 loc) 6.56 kB
import { css, LitElement, html } from 'lit'; import { state, property } from 'lit/decorators.js'; import { localized, msg } from '@lit/localize'; import { pdIcons } from '@progressive-development/pd-icon'; import { toastBus } from '../toast-bus/toast-bus.js'; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __decorateClass = (decorators, target, key, kind) => { var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target; for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result; if (kind && result) __defProp(target, key, result); return result; }; const DEFAULT_DURATION = 6e3; const ANIMATION_DURATION = 300; let PdToast = class extends LitElement { constructor() { super(...arguments); this._message = ""; this.isError = false; this.isSuccess = false; // --------------------------------------------------------------------------- // Private // --------------------------------------------------------------------------- this._queue = []; this._isProcessing = false; this._boundHandleToast = this._handleToast.bind(this); } // --------------------------------------------------------------------------- // Lifecycle // --------------------------------------------------------------------------- connectedCallback() { super.connectedCallback(); this.setAttribute("aria-live", "polite"); toastBus.addEventListener("toast", this._boundHandleToast); } disconnectedCallback() { super.disconnectedCallback(); this._clearTimer(); toastBus.removeEventListener( "toast", this._boundHandleToast ); } // --------------------------------------------------------------------------- // Render // --------------------------------------------------------------------------- render() { return html` <div class="content" part="content">${this._message}</div> <pd-icon icon=${pdIcons.ICON_CLOSE} class="close-icon" tabindex="0" role="button" aria-label="${msg("Schließen", { id: "pdPage.toast.ariaClose" })}" @click=${this._close} @keydown=${this._onCloseKeyDown} ></pd-icon> `; } _onCloseKeyDown(e) { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); this._close(); } } // --------------------------------------------------------------------------- // Queue Processing // --------------------------------------------------------------------------- _handleToast(event) { const detail = event.detail; this._queue.push(detail); this._processQueue(); } _processQueue() { if (this._isProcessing || this._queue.length === 0) { return; } const item = this._queue.shift(); this._showToast(item); } _showToast(detail) { this._isProcessing = true; this._message = detail.message; this.isError = detail.type === "error"; this.isSuccess = detail.type === "success"; if (this.isError) { this.setAttribute("role", "alert"); } else { this.removeAttribute("role"); } this.classList.add("visible"); const duration = detail.duration ?? DEFAULT_DURATION; if (duration > 0) { this._autoCloseTimer = window.setTimeout(() => { this._close(); }, duration); } } _close() { this._clearTimer(); this.classList.remove("visible"); this._isProcessing = false; window.setTimeout(() => { this._processQueue(); }, ANIMATION_DURATION); } _clearTimer() { if (this._autoCloseTimer !== void 0) { window.clearTimeout(this._autoCloseTimer); this._autoCloseTimer = void 0; } } }; // --------------------------------------------------------------------------- // Styles // --------------------------------------------------------------------------- PdToast.styles = css` :host { --pd-icon-size: 1rem; --_toast-transition-duration: 300ms; /* Mobile first: smaller margins */ --_toast-margin: 12px; position: fixed; bottom: var(--pd-toast-bottom, var(--_toast-margin)); left: var(--pd-toast-left, var(--_toast-margin)); width: calc(100% - var(--_toast-margin) * 2); max-width: var(--pd-toast-max-width, 400px); z-index: var(--pd-toast-z-index, 105); background: var(--pd-toast-bg, var(--app-primary-color, #ebcf57)); color: var(--pd-toast-color, #0a3a48); padding: var(--pd-toast-padding, 0.6rem); padding-right: calc(var(--pd-toast-padding, 0.6rem) + 1.4rem); border-radius: var( --pd-toast-border-radius, var(--item-border-radius, 2px) ); box-shadow: var(--pd-toast-shadow, 3px 5px 5px 3px lightgrey); display: flex; align-items: center; gap: 0.5rem; transform: translateX(-150%); opacity: 0; transition: transform var(--_toast-transition-duration) ease-out, opacity var(--_toast-transition-duration) ease-out; pointer-events: none; } /* Tablet and up: more spacing */ @media (min-width: 768px) { :host { --_toast-margin: 30px; } } :host([isError]) { background: var(--pd-toast-error-bg, darkred); color: var(--pd-toast-error-color, #fff); } :host([isSuccess]) { background: var(--pd-toast-success-bg, green); color: var(--pd-toast-success-color, #fff); } :host(.visible) { transform: translateX(0); opacity: 1; pointer-events: auto; } .content { flex: 1; word-wrap: break-word; overflow-wrap: break-word; } .close-icon { position: absolute; cursor: pointer; right: var(--pd-spacing-sm, 0.5rem); top: var(--pd-spacing-sm, 0.5rem); } .close-icon:focus { outline: 2px solid currentColor; outline-offset: 2px; border-radius: var(--pd-radius-sm, 2px); } @media (prefers-reduced-motion: reduce) { :host { --_toast-transition-duration: 0ms; } } `; __decorateClass([ state() ], PdToast.prototype, "_message", 2); __decorateClass([ property({ type: Boolean, reflect: true }) ], PdToast.prototype, "isError", 2); __decorateClass([ property({ type: Boolean, reflect: true }) ], PdToast.prototype, "isSuccess", 2); PdToast = __decorateClass([ localized() ], PdToast); export { PdToast };