(function () { const DEFAULT_DURATION = 6200; const VARIANTS = ["info", "warning", "error"]; const GENERIC_ERROR_MESSAGE = "Something went wrong on this page. Please try again in a moment."; window.Warpbox = window.Warpbox || {}; let lastGlobalErrorAt = 0; function ensureRegion() { let region = document.querySelector("[data-warpbox-popups]"); if (region) { return region; } region = document.createElement("div"); region.className = "warpbox-popups"; region.setAttribute("data-warpbox-popups", ""); region.setAttribute("aria-live", "polite"); region.setAttribute("aria-atomic", "false"); document.body.append(region); return region; } function normalizeOptions(options, message) { if (typeof options === "string") { options = { message: options }; } else { options = options || {}; } if (message) { options.message = message; } const variant = VARIANTS.includes(options.variant) ? options.variant : "info"; return { variant, title: options.title || defaultTitle(variant), message: options.message || "", duration: Number.isFinite(options.duration) ? options.duration : DEFAULT_DURATION, actions: Array.isArray(options.actions) ? options.actions : [], }; } function defaultTitle(variant) { if (variant === "error") { return "Error"; } if (variant === "warning") { return "Warning"; } return "Info"; } function notify(options, message) { const config = normalizeOptions(options, message); const region = ensureRegion(); const popup = document.createElement("section"); popup.className = "warpbox-popup warpbox-popup-" + config.variant; popup.setAttribute("role", config.variant === "error" ? "alert" : "status"); const chrome = document.createElement("div"); chrome.className = "warpbox-popup-chrome"; const icon = document.createElement("span"); icon.className = "warpbox-popup-icon"; icon.setAttribute("aria-hidden", "true"); icon.textContent = config.variant === "error" ? "!" : config.variant === "warning" ? "?" : "i"; const body = document.createElement("div"); body.className = "warpbox-popup-body"; const title = document.createElement("strong"); title.className = "warpbox-popup-title"; title.textContent = config.title; const text = document.createElement("p"); text.className = "warpbox-popup-message"; text.textContent = config.message; body.append(title, text); const close = document.createElement("button"); close.type = "button"; close.className = "warpbox-popup-close"; close.setAttribute("aria-label", "Dismiss notification"); close.textContent = "x"; close.addEventListener("click", () => dismiss(popup)); chrome.append(icon, body, close); popup.append(chrome); if (config.actions.length > 0) { const actions = document.createElement("div"); actions.className = "warpbox-popup-actions"; config.actions.forEach((action) => { const button = document.createElement("button"); button.type = "button"; button.className = "button " + (action.kind === "primary" ? "button-primary" : "button-outline"); button.textContent = action.label || "Action"; button.addEventListener("click", () => { if (typeof action.onClick === "function") { action.onClick(); } if (action.dismiss !== false) { dismiss(popup); } }); actions.append(button); }); popup.append(actions); } region.append(popup); window.requestAnimationFrame(() => popup.classList.add("is-visible")); let timer = null; if (config.duration > 0) { timer = window.setTimeout(() => dismiss(popup), config.duration); } return { element: popup, close: function closePopup() { if (timer) { window.clearTimeout(timer); } dismiss(popup); }, }; } function dismiss(popup) { if (!popup || popup.dataset.closing === "true") { return; } popup.dataset.closing = "true"; popup.classList.remove("is-visible"); window.setTimeout(() => popup.remove(), 180); } window.Warpbox.notify = notify; window.Warpbox.info = function info(message, options) { return notify({ ...(options || {}), variant: "info", message }); }; window.Warpbox.warning = function warning(message, options) { return notify({ ...(options || {}), variant: "warning", message }); }; window.Warpbox.error = function error(message, options) { return notify({ ...(options || {}), variant: "error", message }); }; function showGlobalError() { const now = Date.now(); if (now - lastGlobalErrorAt < 2500) { return; } lastGlobalErrorAt = now; notify({ variant: "error", title: "Page error", message: GENERIC_ERROR_MESSAGE, duration: 9000, }); } window.addEventListener("error", function (event) { if (event && event.target && event.target !== window) { return; } showGlobalError(); }); window.addEventListener("unhandledrejection", function () { showGlobalError(); }); })();