71 lines
2.4 KiB
JavaScript
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);
|