UNPKG

toastjs-notifications

Version:

Una librería moderna, ligera y elegante para notificaciones toast en aplicaciones web. Incluye animaciones suaves, múltiples posiciones y diseño responsive.

266 lines (225 loc) 8.57 kB
/** * ToastJS Notifications * ========================================== * * La librería de notificaciones toast más elegante y minimalista para tu aplicación web. * Con animaciones suaves, diseño moderno y una experiencia de usuario excepcional. * * @version 1.11.14 * @author Urian Viera * @website https://www.urianviera.com * @youtube https://www.youtube.com/WebDeveloperUrianViera * @email urian1213viera@gmail.com * @donate https://www.paypal.com/donate/?hosted_button_id=4SV78MQJJH3VE * @license MIT * @copyright © 2025 Urian Viera. Todos los derechos reservados. */ (function (global) { "use strict"; const ANIMATION_DURATION = 10000; // 10 seconds // Constructor principal function ToastJS(options = {}) { this.options = { position: options.position || "top-right", duration: options.duration || 4000, maxToasts: options.maxToasts || 5, ...options, }; this.container = null; this.toastCount = 0; this.init(); } // Métodos del prototipo ToastJS.prototype = { init: function () { this.injectStyles(); this.createContainer(); }, // Inyectar CSS en el DOM injectStyles: function () { if (document.getElementById("toastjs-styles")) return; const link = document.createElement("link"); link.id = "toastjs-styles"; link.rel = "stylesheet"; // Detectar si estamos usando CDN const currentScript = document.currentScript || (function () { const scripts = document.getElementsByTagName("script"); return scripts[scripts.length - 1]; })(); const scriptSrc = currentScript?.src || ""; // Si es CDN, usar la ruta correcta if (scriptSrc.includes("cdn.jsdelivr.net/npm/toastjs-notifications")) { const version = scriptSrc.match(/@(\d+\.\d+\.\d+)/)?.[1] || "latest"; link.href = `https://cdn.jsdelivr.net/npm/toastjs-notifications@${version}/toast-notifications.min.css`; document.head.appendChild(link); return; } if (scriptSrc.includes("unpkg.com/toastjs-notifications")) { const version = scriptSrc.match(/@(\d+\.\d+\.\d+)/)?.[1] || "latest"; link.href = `https://unpkg.com/toastjs-notifications@${version}/toast-notifications.css`; document.head.appendChild(link); return; } // Para uso local if (scriptSrc.includes("toast-notifications.min.js")) { const basePath = scriptSrc.substring(0, scriptSrc.lastIndexOf("/")); // Extraer la parte del path antes de /js const baseDir = basePath.substring(0, basePath.lastIndexOf("/js")); const link = document.createElement("link"); link.rel = "stylesheet"; link.href = `${baseDir}/css/toast-notifications.css`; document.head.appendChild(link); return; } // Si no se cumple ninguna condición link.href = `${basePath}/toast-notifications.css`; document.head.appendChild(link); }, createContainer: function (position = this.options.position) { // Si el contenedor ya existe, actualizamos su clase if (this.container) { this.container.className = `toastjs-container ${position}`; return; } this.container = document.createElement("div"); this.container.className = `toastjs-container ${position}`; this.container.id = "toastjs-container"; document.body.appendChild(this.container); }, show: function (message, type = "info", options = {}) { if (this.toastCount >= this.options.maxToasts) { this.removeOldest(); } const config = { success: { icon: `<svg class="checkmark success" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52"> <circle class="checkmark__circle" cx="26" cy="26" r="25" fill="none" /> <path class="checkmark__check" fill="none" d="M14.1 27.2l7.1 7.2 16.7-16.8" /> </svg>`, class: "success", }, warning: { icon: `<svg class="checkmark warning" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52"> <circle class="checkmark__circle" cx="26" cy="26" r="25" fill="none" /> <line class="checkmark__check" x1="26" y1="16" x2="26" y2="30" /> <circle class="checkmark__dot" cx="26" cy="36" r="2" /> </svg>`, class: "warning", }, error: { icon: `<svg class="checkmark error" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52"> <circle class="checkmark__circle" cx="26" cy="26" r="25" fill="none" /> <line class="checkmark__check" x1="16" y1="16" x2="36" y2="36" /> <line class="checkmark__check" x1="36" y1="16" x2="16" y2="36" /> </svg>`, class: "error", }, info: { icon: `<svg class="checkmark info" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52"> <circle class="checkmark__circle" cx="26" cy="26" r="25" fill="none" /> <line class="checkmark__check" x1="26" y1="20" x2="26" y2="34" /> <circle class="checkmark__dot" cx="26" cy="16" r="2" /> </svg>`, class: "info", }, }; const toastConfig = config[type] || config.info; const duration = options.duration ?? this.options.duration; const position = options.position ?? this.options.position; // Actualiza el contenedor para la nueva posición this.createContainer(position); const toast = document.createElement("div"); toast.className = `my-toast ${toastConfig.class}`; toast.innerHTML = ` ${toastConfig.icon} <div class="toast-content">${message}</div> <span class="close-toast">×</span> <div class="toast-progress-bar"></div> `; const closeBtn = toast.querySelector(".close-toast"); closeBtn.addEventListener("click", () => this.remove(toast)); // Configurar la duración de la animación de la barra de progreso if (duration > 0) { // Aplicar la duración personalizada a la animación toast.style.setProperty("--progress-duration", `${duration}ms`); setTimeout(() => { if (toast.parentNode) this.remove(toast); }, duration); } // Insertar según la posición if (position.includes("bottom")) { this.container.appendChild(toast); } else { this.container.insertBefore(toast, this.container.firstChild); } this.toastCount++; return toast; }, remove: function (toast) { toast.classList.add("toastjs-fade-out"); setTimeout(() => { if (toast.parentNode) { toast.remove(); this.toastCount--; } }, ANIMATION_DURATION); }, removeOldest: function () { const oldestToast = this.container.querySelector(".my-toast"); if (oldestToast) { this.remove(oldestToast); } }, // Métodos de conveniencia info: function (message, options) { return this.show(message, "info", options); }, success: function (message, options) { return this.show(message, "success", options); }, warning: function (message, options) { return this.show(message, "warning", options); }, error: function (message, options) { return this.show(message, "error", options); }, }; // Crear instancia global por defecto const defaultToast = new ToastJS(); // API global const showToast = { // Crear nueva instancia create: function (options) { return new ToastJS(options); }, // Métodos de la instancia por defecto show: function (message, type, options) { return defaultToast.show(message, type, options); }, info: function (message, options) { return defaultToast.info(message, options); }, success: function (message, options) { return defaultToast.success(message, options); }, warning: function (message, options) { return defaultToast.warning(message, options); }, error: function (message, options) { return defaultToast.error(message, options); }, }; // Exportar para diferentes entornos if (typeof module !== "undefined" && module.exports) { module.exports = showToast; } else if (typeof define === "function" && define.amd) { define(function () { return showToast; }); } else { global.showToast = showToast; global.ToastJS = ToastJS; } })(typeof window !== "undefined" ? window : this);