/** @license Copyright (c) 2023 EDV Wasmeier */ import { EventHelpers } from '@tp/helpers/event-helpers.js'; import { LitElement, html, css, svg } from 'lit'; class TpToast extends EventHelpers(LitElement) { static get styles() { return [ css` :host { --tp-toast-info-icon-color: #fff; --tp-toast-success-icon-color: #fff; --tp-toast-error-icon-color: #fff; --tp-toast-warning-icon-color: #fff; transition: transform 0.5s, opacity 0.3s; will-change: transform, opacity; display: inline-block; border-radius: 2px; background: #FAFAFA; font-size: 0.8em; cursor: pointer; opacity: 1; 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); } .wrap { display: flex; flex-direction: row; } .icon { padding: 10px; border-right: 1px #fff; color: #ffffff; display: flex; flex-direction: row; align-items: center; justify-content: center; } :host([type="info"]) .icon { background: #039BE5; } :host([type="success"]) .icon { background: #558B2F; color: #fff; } :host([type="warning"]) .icon { background: #FFCA28; } :host([type="error"]) .icon { background: #B71C1C; } .content { padding: 10px 10px 10px 10px; line-height: 24px; } .dismiss { display: flex; align-items: center; justify-content: center; padding: 10px; } .dismiss tp-icon { --tp-icon-width: 18px; --tp-icon-height: 18px; } ` ]; } render() { const { sticky, dismissIcon, icon } = this; return html`
${!sticky ? html`
` : null}
`; } static get properties() { return { icon: { type: Object }, dismissIcon: { type: Object }, /** * Configures what kind of toast this is. * Comes with the variants `info`, `warning`, `error`, `success`. * Each type comes with a pre-defined icon, but via the `icon` property a custom icon can also be used. */ type: { type: String, reflect: true }, /** * Delay till the toast dismisses itself. * Set in milliseconds. */ delay: { type: Number }, /** * If true, the toast cant be dismissed manually. */ sticky: { type: Boolean }, isDismissed: { type: Boolean }, translateY: { type: Number }, }; } constructor() { super(); this.type = 'info'; this.delay = 5000; this.translateY = -150; this.dismiss = this.dismiss.bind(this); } static get defaultDismissIcon() { return svg``; } static get infoIcon() { return svg``; } static get successIcon() { return svg``; } static get errorIcon() { return svg``; } static get warningIcon() { return svg``; } connectedCallback() { super.connectedCallback(); this.listen(this, 'transitionend', '_afterTransitioned'); } shouldUpdate(changes) { if (changes.has('translateY')) { this._translateYChanged(); } return true; } /** * Dismiss the toast right now. */ dismiss() { this.isDismissed = true; this.style.transform = `translate3d(200px, ${this.translateY}px, 0px)`; this.style.opacity = '0'; } /** * Starts the delay timeout to dismiss the toast automatically. */ activateDelay() { if (this.delay > 0) { this.stopDelay(); this._delayJob = setTimeout(this.dismiss, this.delay); } } stopDelay() { if (this._delayJob) { clearTimeout(this._delayJob); this._delayJob = null; } } _afterTransitioned(e) { if (this.isDismissed) { if (e.propertyName === 'opacity') { this.dispatchEvent(new CustomEvent('toast-dismissed', { detail: { toast: this } , bubbles: true, composed: true })); } } } _translateYChanged() { if (this.isDismissed) { return; } this.style.transform = `translate3d(0px, ${this.translateY}px, 0px)`; } } window.customElements.define('tp-toast', TpToast);