(() => {
const TOAST_STACK_ID = 'installer-toast-stack';
const DEFAULT_TIMEOUT = 5000;
const MAX_TOASTS = 3;
const ICONS = {
error: '',
close: ''
};
const getStack = () => document.getElementById(TOAST_STACK_ID);
const dismissToast = (toast) => {
if (!toast) return;
if (toast.classList.contains('is-leaving')) return;
toast.classList.add('is-leaving');
const remove = () => toast.remove();
toast.addEventListener('transitionend', remove, { once: true });
setTimeout(remove, 450);
};
const showToast = ({
title = '',
description = '',
status = 'error',
dismissible = true,
timeout = DEFAULT_TIMEOUT
} = {}) => {
const stack = getStack();
if (!stack) return;
const visibleToasts = Array.from(
stack.querySelectorAll('.installer-toast:not(.is-leaving)')
);
if (visibleToasts.length >= MAX_TOASTS) {
dismissToast(visibleToasts[0]);
}
const toast = document.createElement('div');
toast.className = 'installer-toast is-entering';
toast.dataset.status = status;
toast.setAttribute('role', status === 'error' ? 'alert' : 'status');
const content = document.createElement('div');
content.className = 'installer-toast-content';
const icon = document.createElement('span');
icon.className = 'installer-toast-icon';
icon.dataset.status = status;
icon.innerHTML = ICONS.error;
content.appendChild(icon);
const body = document.createElement('section');
body.className = 'installer-toast-body';
if (title) {
const titleNode = document.createElement('p');
titleNode.className = 'installer-toast-title typography-text-m-500';
titleNode.textContent = title;
body.appendChild(titleNode);
}
if (description) {
const descNode = document.createElement('p');
descNode.className = 'installer-toast-description typography-text-m-400';
descNode.textContent = description;
body.appendChild(descNode);
}
content.appendChild(body);
toast.appendChild(content);
if (dismissible) {
const close = document.createElement('button');
close.type = 'button';
close.className = 'installer-toast-close';
close.setAttribute('aria-label', 'Dismiss notification');
close.innerHTML = ICONS.close;
close.addEventListener('click', () => dismissToast(toast));
toast.appendChild(close);
}
stack.appendChild(toast);
toast.getBoundingClientRect();
requestAnimationFrame(() => {
toast.classList.remove('is-entering');
});
if (timeout > 0) {
setTimeout(() => dismissToast(toast), timeout);
}
};
window.InstallerToast = Object.freeze({
showToast
});
})();