import { createElement } from "../lib/skeleton/index.js"; import { ApplicationError } from "../lib/error.js"; import { animate, slideYIn, slideYOut } from "../lib/animate.js"; import { CSS } from "../helpers/loader.js"; const createNotification = async (msg, type) => createElement(`
${msg}
close
`); class NotificationComponent extends window.HTMLElement { buffer = []; constructor() { super(); } async trigger(message, type) { if (this.buffer.length > 20) this.buffer.pop(); // failsafe this.buffer.push({ message, type }); if (this.buffer.length !== 1) { const $close = this.querySelector(".close"); if ($close && typeof $close.onclick === "function") $close.onclick(); return; } await this.run(); } async run() { if (this.buffer.length === 0) return; const { message, type } = this.buffer[0]; const $notification = await createNotification(message, type); this.replaceChildren($notification); await animate($notification, { keyframes: slideYIn(50), time: 100, }); const ids = [] await Promise.race([ new Promise((done) => ids.push(window.setTimeout(done, this.buffer.length === 1 ? 8000 : 800))), new Promise((done) => ids.push(window.setTimeout(() => $notification.querySelector(".close").onclick = done, 1000))), ]); ids.forEach((id) => window.clearTimeout(id)); await animate($notification, { keyframes: slideYOut(10), time: 200, }); $notification.remove(); this.buffer.shift(); await this.run(); } } customElements.define("component-notification", NotificationComponent); function find() { const $dom = document.body.querySelector("component-notification"); if (!($dom instanceof NotificationComponent)) throw new ApplicationError("INTERNAL_ERROR", "assumption failed: wrong type notification component"); return $dom; } export default class Notification { static info(msg) { find().trigger(msg, "info"); } static success(msg) { find().trigger(msg, "success"); } static error(msg) { find().trigger(msg, "error"); } }