Files
SteelBase/public/js/core/toast-manager.js

228 lines
7.3 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* ToastManager - Sistema de Notificações Visuais
* Gerencia notificações toast não-intrusivas para o usuário
*/
class ToastManager {
constructor() {
this.container = null;
this.toasts = new Map();
this.config = {
position: 'top-right',
duration: 5000,
maxToasts: 5,
animationDuration: 300
};
this.init();
}
init() {
this.createContainer();
console.log('🍞 ToastManager inicializado');
}
createContainer() {
// Remover container existente se houver
const existingContainer = document.querySelector('.toast-container');
if (existingContainer) {
existingContainer.remove();
}
// Criar novo container
this.container = document.createElement('div');
this.container.className = `toast-container toast-${this.config.position}`;
this.container.style.cssText = `
position: fixed;
z-index: 10000;
pointer-events: none;
`;
// Definir posição baseada na configuração
this.setContainerPosition();
document.body.appendChild(this.container);
}
setContainerPosition() {
if (!this.container) return;
const positions = {
'top-right': { top: '20px', right: '20px', bottom: 'auto', left: 'auto' },
'top-left': { top: '20px', left: '20px', bottom: 'auto', right: 'auto' },
'top-center': { top: '20px', left: '50%', transform: 'translateX(-50%)', bottom: 'auto', right: 'auto' },
'bottom-right': { bottom: '20px', right: '20px', top: 'auto', left: 'auto' },
'bottom-left': { bottom: '20px', left: '20px', top: 'auto', right: 'auto' },
'bottom-center': { bottom: '20px', left: '50%', transform: 'translateX(-50%)', top: 'auto', right: 'auto' }
};
const pos = positions[this.config.position] || positions['top-right'];
Object.assign(this.container.style, pos);
}
show(message, type = 'info', duration = null, options = {}) {
const toast = this.createToast(message, type, options);
const toastId = toast.dataset.toastId;
// Adicionar ao container
this.container.appendChild(toast);
// Armazenar referência
this.toasts.set(toastId, toast);
// Limitar número de toasts
this.limitToasts();
// Animar entrada
requestAnimationFrame(() => {
toast.classList.add('show');
});
// Configurar tempo de remoção
const autoHideDuration = duration !== null ? duration : this.config.duration;
if (autoHideDuration > 0) {
setTimeout(() => {
this.hide(toastId);
}, autoHideDuration);
}
return toastId;
}
createToast(message, type, options) {
const toast = document.createElement('div');
const toastId = 'toast_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
toast.dataset.toastId = toastId;
toast.className = `toast toast-${type}`;
toast.style.cssText = `
background: var(--toast-bg, #333);
color: var(--toast-color, #fff);
padding: 16px 20px;
margin-bottom: 10px;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
font-size: 14px;
line-height: 1.4;
max-width: 400px;
min-width: 300px;
opacity: 0;
transform: translateX(100%);
transition: all ${this.config.animationDuration}ms ease;
pointer-events: auto;
position: relative;
overflow: hidden;
`;
// Definir cores baseadas no tipo
const colors = {
success: { bg: '#22c55e', color: '#fff' },
error: { bg: '#ef4444', color: '#fff' },
warning: { bg: '#f59e0b', color: '#fff' },
info: { bg: '#3b82f6', color: '#fff' }
};
const colorConfig = colors[type] || colors.info;
toast.style.setProperty('--toast-bg', colorConfig.bg);
toast.style.setProperty('--toast-color', colorConfig.color);
// Adicionar ícone baseado no tipo
const icons = {
success: '✅',
error: '❌',
warning: '⚠️',
info: ''
};
const icon = options.icon || icons[type] || icons.info;
toast.innerHTML = `
<div style="display: flex; align-items: flex-start; gap: 12px;">
<span style="font-size: 16px; flex-shrink: 0;">${icon}</span>
<div style="flex: 1;">${message}</div>
<button onclick="toastManager.hide('${toastId}')" style="
background: none;
border: none;
color: inherit;
font-size: 18px;
cursor: pointer;
padding: 0;
margin-left: 8px;
opacity: 0.7;
transition: opacity 0.2s;
" onmouseover="this.style.opacity=1" onmouseout="this.style.opacity=0.7">×</button>
</div>
`;
return toast;
}
limitToasts() {
if (this.toasts.size <= this.config.maxToasts) return;
const toastsArray = Array.from(this.toasts.entries());
const toRemove = toastsArray.slice(0, toastsArray.length - this.config.maxToasts);
toRemove.forEach(([toastId]) => {
this.hide(toastId);
});
}
hide(toastId) {
const toast = this.toasts.get(toastId);
if (!toast) return;
toast.classList.remove('show');
setTimeout(() => {
if (toast.parentNode) {
toast.parentNode.removeChild(toast);
}
this.toasts.delete(toastId);
}, this.config.animationDuration);
}
hideAll() {
this.toasts.forEach((toast, toastId) => {
this.hide(toastId);
});
}
// Métodos de conveniência
success(message, duration, options) {
return this.show(message, 'success', duration, options);
}
error(message, duration, options) {
return this.show(message, 'error', duration, options);
}
warning(message, duration, options) {
return this.show(message, 'warning', duration, options);
}
info(message, duration, options) {
return this.show(message, 'info', duration, options);
}
// Configurar posição
setPosition(position) {
if (['top-right', 'top-left', 'top-center', 'bottom-right', 'bottom-left', 'bottom-center'].includes(position)) {
this.config.position = position;
this.createContainer();
}
}
// Obter estatísticas
getStats() {
return {
activeToasts: this.toasts.size,
maxToasts: this.config.maxToasts,
position: this.config.position,
duration: this.config.duration
};
}
}
// Tornar disponível globalmente
window.ToastManager = ToastManager;
window.toastManager = new ToastManager();