/** @license Copyright (c) 2022 trading_peter This program is available under Apache License Version 2.0 */ import './tp-toast.js'; import '@tp/helpers/debounce.js'; import '@tp/tp-icon/tp-icon.js'; import '@tp/tp-media-query/tp-media-query.js'; import { debounce } from '@tp/helpers/debounce.js'; import { closest } from '@tp/helpers/closest.js'; import { EventHelpers } from '@tp/helpers/event-helpers.js'; import { LitElement, html, css, svg } from 'lit'; export default class TpToaster extends EventHelpers(LitElement) { static get styles() { return [ css` :host { display: inline-block; position: fixed; top: 15px; left: 50%; width: 50%; z-index: 10000; transform: translateY(-60px); } :host [hidden] { display: none; } #infos { display: inline-block; font-size: 0.7em; border-radius: 4px; background: #FAFAFA; transition: transform 0.3s; will-change: transform; box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.14), 0 1px 8px 0 rgba(0, 0, 0, 0.12), 0 3px 3px -2px rgba(0, 0, 0, 0.4); } #infos .info-wrap { display: flex; flex-direction: row; align-items: center; } #infos[show-infos] { transform: translateY(60px); } #infos .info-wrap tp-icon { padding: 5px; --tp-icon-width: 18px; --tp-icon-height: 18px; } #infos .info-wrap > div { padding: 0 5px; } #wrap { transition: transform 0.3s; will-change: transform; transform: translateY(30px); } #wrap[show-infos] { transform: translateY(70px); } :host ::slotted(tp-toast) { position: absolute; } @media all and (min-width: 0) and (max-width: 480px) { :host { left: 2%; width: 96% } } ` ]; } render() { const { hiddenCount, dismissLabel, moreLabel } = this; const show = this.toasts.length > 1; return html`
${dismissLabel}
${hiddenCount} ${moreLabel}
`; } static get properties() { return { maxVisible: { type: Number }, count: { type: Number }, hiddenCount: { type: Number }, dismissLabel: { type: String }, moreLabel: { type: String }, }; } constructor() { super(); this.updateList = debounce(this.updateList.bind(this), 50); window.TpToaster = this; this.moreLabel = 'more'; this.hiddenCount = 0; this.maxVisible = 4; } static get clearAllIcon() { return svg``; } get toasts() { const slot = this.shadowRoot.querySelector('slot'); if (!slot) return []; return slot .assignedNodes({ flatten:true }) .filter(n => n.nodeType === Node.ELEMENT_NODE); } connectedCallback() { super.connectedCallback(); this.listen(this, 'click', 'onClick'); this.listen(this, 'toast-dismissed', 'onToastDismissed'); } /** * Adds a new toast. This can be a `tp-toast` element or a object with the properties: * ```json * { * "content": "The message to display", * "type": "warning", * "delay": "5000" * } * ``` * If the value of `content` starts with `i18n.`, the toaster tries to translate the string. * * @param toast */ add(toast) { toast = Object.assign({ content: '', type: 'info', delay: 5000 }, toast); const newContent = document.createElement('div'); newContent.textContent = toast.content; const newToast = document.createElement('tp-toast'); newToast.type = toast.type; newToast.delay = toast.delay; newToast.sticky = toast.sticky; newToast.icon = toast.icon; newToast.appendChild(newContent); this.appendChild(newToast); this.updateList(); } /** * Dismiss all non-sticky toasts. */ dismissAll() { this.toasts.forEach(toast => { if (!toast.sticky) { toast.dismiss(); } }); } /** * Dismiss all sticky toasts. */ dismissSticky() { this.toasts.forEach(toast => { if (toast.sticky) { toast.dismiss(); } }); } onClick(e) { const target = closest(e.target, 'tp-toast', true); if (target && !target.isDismissed) { target.parentNode.appendChild(target); setTimeout(() => { this.updateList(); }, 50); } } onToastDismissed(e) { this.removeChild(e.detail.toast); this.updateList(); } updateList() { const toasts = this.toasts; this.count = toasts.length; const hiddenToasts = toasts.slice(0, toasts.length - this.maxVisible); for (let i = 0, li = hiddenToasts.length; i < li; ++i) { hiddenToasts[i].translateY = -150; hiddenToasts[i].stopDelay(); } const visibleToasts = toasts.slice(Math.max(0, toasts.length - this.maxVisible)); for (let i = 0, li = visibleToasts.length; i < li; ++i) { visibleToasts[i].translateY = 30 * i; if (i === li - 1) { visibleToasts[i].activateDelay(); } else { visibleToasts[i].stopDelay(); } } this.hiddenCount = Math.max(0, this.count - this.maxVisible); } shouldShowMoreLabel(hiddenCount) { return hiddenCount > 0; } queryMatchChanged(e) { this.maxVisible = e.detail.value ? 1 : 4; if (this.isConnected) { this.updateList(); } } } window.customElements.define('tp-toaster', TpToaster);