export enum ToastType { Default = 'default', Info = 'info', Success = 'success', Error = 'error', } export class Toast { type: ToastType message: string title: string duration: number | undefined creationTime = new Date() constructor(message = '', title = '', type = ToastType.Default) { this.type = type this.message = message this.title = title this.duration = 3000 } show() { container.cards.splice(0, 0, this) if (this.duration !== undefined) { setTimeout(() => this.dismiss(), this.duration) } } dismiss() { container.cards.splice(container.cards.indexOf(this), 1) } get element() { return dq(`.toast-card[key='${this.key}']`) } get key() { return this.creationTime.toISOString() } static get container() { return document.querySelector('.toast-card-container') } static createToastContainer() { if (!document.querySelector('.toast-card-container')) { document.body.insertAdjacentHTML('beforeend', /* html */` `) } } private static internalShow(message: string, title: string, duration: number | undefined, type: ToastType) { const toast = new Toast(message, title, type) toast.duration = duration toast.show() return toast } static show(message: string, title: string, duration: number | undefined) { return this.internalShow(message, title, duration, ToastType.Default) } static info(message: string, title: string, duration: number | undefined) { return this.internalShow(message, title, duration, ToastType.Info) } static success(message: string, title: string, duration: number | undefined) { return this.internalShow(message, title, duration, ToastType.Success) } static error(message: string, title: string, duration: number | undefined) { return this.internalShow(message, title, duration, ToastType.Error) } } resources.applyStyle('toastStyle') Vue.component('toast-card', { props: ['card'], template: /*html*/`

{{card.title}}

`, }) Toast.createToastContainer() const container = new Vue({ el: '.toast-card-container', data: { cards: [] as Toast[] }, }) export default { export: Toast }