esp/assets/js/toast.js

71 lines
2.4 KiB
JavaScript

// Toast util sin dependencias (compatible con Tailwind)
(function(global){
function ensureContainer(){
const id = 'toast-container';
let el = document.getElementById(id);
if (!el) {
el = document.createElement('div');
el.id = id;
el.className = 'fixed bottom-4 right-4 z-50 space-y-2';
document.body.appendChild(el);
}
return el;
}
function getStyles(type){
// Mapear tipo -> clases Tailwind
switch ((type||'').toLowerCase()) {
case 'success': return 'bg-emerald-600 text-white';
case 'danger':
case 'error': return 'bg-red-600 text-white';
case 'warning': return 'bg-amber-500 text-white';
default: return 'bg-gray-900 text-white'; // info
}
}
function mostrarToast(mensaje, options){
try {
const container = ensureContainer();
const delay = (options && options.delay) || 4000;
const type = (options && options.type) || (options && options.variant) || 'info';
const cls = getStyles(type);
const toastEl = document.createElement('div');
toastEl.className = 'pointer-events-auto shadow-lg rounded px-4 py-3 text-sm flex items-start gap-3 transition transform translate-y-2 opacity-0 ' + cls;
toastEl.setAttribute('role', 'status');
toastEl.innerHTML = `
<div class="flex-1">${mensaje}</div>
<button type="button" aria-label="Cerrar" class="ml-2 text-white/80 hover:text-white" data-close-toast>✕</button>
`;
container.appendChild(toastEl);
// Animar entrada
requestAnimationFrame(() => {
toastEl.classList.remove('translate-y-2','opacity-0');
toastEl.classList.add('translate-y-0','opacity-100');
});
// Cierre manual
toastEl.querySelector('[data-close-toast]')?.addEventListener('click', () => removeToast(toastEl));
// Auto-cierre
const timer = setTimeout(() => removeToast(toastEl), delay);
// Si el mouse entra, pausar auto-cierre
toastEl.addEventListener('mouseenter', () => clearTimeout(timer), { once: true });
function removeToast(node){
try {
node.classList.remove('translate-y-0','opacity-100');
node.classList.add('translate-y-2','opacity-0');
setTimeout(() => node.remove(), 200);
} catch {}
}
} catch (e) {
console.warn('mostrarToast fallback:', e);
alert(mensaje);
}
}
global.mostrarToast = mostrarToast;
})(window);