dl-notificator
Version:
Componente contruido en js para mostrarle informacion al usuario mediante notificaciones temporales
253 lines (239 loc) • 8.95 kB
JavaScript
import { mergeObjects, setNewProperty } from 'functionallibrary';
class Notification {
/*
* @params {object} opts - opciones
* @params {number} opts.duration - duración animación. por defecto 4000 (ms)
* @params {object} opts.errorOptions - opciones de configuración para notificación de error
* @params {object} opts.infoOptions - opciones de configuración para notificación de información
* @params {boolean} opts.left - lado por el que aparece la notificación. Por defecto false porque se muestra por la derecha
* @params {object} opts.success - opciones de configuración para notificación de éxito
* @params {number} opts.top - valor de desfase de la primera notificación respecto a la ventana del navegador. Por defecto es 1 (rem);
* @params {object} opts.warning - opciones de configuración para notificación de advertencia
*/
constructor(opts = {}) {
const { duration, errorOptions, infoOptions, left, successOptions, top, warningOptions, zIndex } = opts;
const { backgroundColor: errorBg, color: errorColor, duration: errorTime, closeBtn: errorClose } = errorOptions || {};
const { backgroundColor: infoBg, color: infoColor, duration: infoTime, closeBtn: infoClose } = infoOptions || {};
const { backgroundColor: successBg, color: successColor, duration: successTime, closeBtn: successClose } = successOptions || {};
const { backgroundColor: warningBg, color: warningColor, duration: warningTime, closeBtn: warningClose } = warningOptions || {};
/**
* Identificador único de cada instancia generada
*/
this.uuid = Math.random().toString(32).slice(2);
this.top = top;
/**
* contenedor principal agregado en el body
*/
const mainNotificationContainer = document.createElement('div');
mainNotificationContainer.classList.add(`notification-container-${this.uuid}`);
const [body] = document.getElementsByTagName('body');
body.appendChild(mainNotificationContainer);
/**
* Configurar y agregar estilos en el head
*/
const showingSide = left ? 'left:0' : 'right:0'
var style = document.createElement('style');
style.innerHTML = `
.notification-container-${this.uuid} {
position: fixed;
${showingSide};
top: ${this.top || 10}px;
width: fit-content;
z-index: ${zIndex || 999}
}
.notification-${this.uuid} {
animation-name: entering-${this.uuid};
border-radius: 5px;
color: white;
margin: 0.5rem 1rem;
max-width: 15rem;
min-width: 12rem;
padding: 1rem;
position: relative;
}
entering-${this.uuid} {
0% {
transform: translateX(${left ? -150 : 150}%);
}
50% {
transform: translateX(${left ? 15 : -15}%);
}
100% {
transform: translateX(${left ? 1 : -1}%);
}
}
active-${this.uuid} {
from {
transform: translateX(${left ? 1 : -1}%);
}
to {
transform: translateX(${left ? 1 : -1}%);
}
}
outgoing-${this.uuid} {
0% {
transform: translateX(${left ? 1 : -1}%);
}
50% {
transform: translateX(${left ? 15 : -15}%);
}
100% {
transform: translateX(${left ? -150 : 150}%);
}
}
.close-btn-${this.uuid} {
background-color: transparent;
border: none;
cursor: pointer;
padding: 0.25rem;
position: absolute;
right: .1rem;
top: 0;
transition-duration: 150ms;
}
.close-btn-${this.uuid}:focus {
outline: none;
}
.close-btn-${this.uuid}:hover {
transform: scale(1.5);
}
`;
document.head.appendChild(style);
this.container = mainNotificationContainer;
this.enteringDuration = 250;
this.outgoingDuration = 350;
this.duration = duration || (4000 - 250 - 350);
this.errorOpts = {
backgroundColor: errorBg || '#EC0B43',
color: errorColor || 'white',
closeBtn: !!errorClose,
duration: errorTime || this.duration,
},
this.infoOpts = {
backgroundColor: infoBg || '#06f',
color: infoColor || 'white',
closeBtn: !!infoClose,
duration: infoTime || this.duration,
};
this.successOpts = {
backgroundColor: successBg || '#2EDC76',
color: successColor || 'white',
closeBtn: !!successClose,
duration: successTime || this.duration,
};
this.warningOpts = {
backgroundColor: warningBg || '#FFBC42',
color: warningColor || 'white',
closeBtn: !!warningClose,
duration: warningTime || this.duration,
};
}
/**
*
* @param {string} message - Mensaje a mostrar en la notificación
* @param {string} color - Color a usar en la notificación
* @param {time} time - Tiempo de duración de la notificación
*/
add(notiOptions, cb) {
const { firstChild } = this.container;
const div = this.createNotificationElement(notiOptions, cb);
this.container.insertBefore(div, firstChild);
}
createNotificationElement(notiOptions, cb) {
const { backgroundColor, closeBtn, color, message, duration } = notiOptions;
const newDuration = duration - (this.enteringDuration + this.outgoingDuration);
const div = document.createElement('div');
div.addEventListener('animationend', (ev) => {
const animationName = ev.detail || ev.animationName;
if (animationName === `entering-${this.uuid}`) {
div.style.animationName = `active-${this.uuid}`;
div.style.animationDuration = `${newDuration}ms`;
} else if (animationName === `active-${this.uuid}`) {
div.style.animationName = `outgoing-${this.uuid}`;
div.style.animationDuration = `${this.outgoingDuration}ms`;
} else if (animationName === `outgoing-${this.uuid}`) {
this.removeNotification.call(this, div, cb);
}
});
div.style.animationDuration = `${this.enteringDuration}ms`;
div.style.backgroundColor = backgroundColor;
div.style.color = color;
div.innerText = message;
div.classList.add(`notification-${this.uuid}`);
if (closeBtn) {
const closeButton = this.createCloseButton.call(this, div, color);
div.appendChild(closeButton);
}
return div;
}
createCloseButton(notificationEl, color) {
const button = document.createElement('button');
button.addEventListener(
'click',
this.removeActiveAnimation.bind(this, notificationEl),
);
button.innerHTML = '\u2715';
button.style.color = color;
button.classList.add(`close-btn-${this.uuid}`);
return button;
}
/**
*
* @param {string} message - Mensaje de error a mostrar.
* @param {string | null} errorColor - Color de la notificación. Si no existe se usa el color por defecto.
* @param {number} time - tiempo de duración de la notificación. Si no existe se usa la duración por defecto.
*/
error(errorOptions = {}, cb) {
const errorOpt = typeof errorOptions === 'string'
? setNewProperty('message', errorOptions, this.errorOpts)
: mergeObjects(this.errorOpts, errorOptions);
this.add(errorOpt, cb);
}
/**
*
* @param {string} message - Mensaje de información a mostrar.
* @param {string | null} infoColor - Color de la notificación. Si no existe se usa el color por defecto.
* @param {number} time - tiempo de duración de la notificación. Si no existe se usa la duración por defecto.
*/
info(infoOptions = {}, cb) {
const infoOpt = typeof infoOptions === 'string'
? setNewProperty('message', infoOptions, this.infoOpts)
: mergeObjects(this.infoOpts, infoOptions);
this.add(infoOpt, cb);
}
removeActiveAnimation(notificationEl) {
const animationEnd = new CustomEvent('animationend', { detail: `active-${this.uuid}` });
notificationEl.dispatchEvent(animationEnd);
}
removeNotification(el, cb) {
this.container.removeChild(el);
if (cb && typeof cb === 'function') {
cb();
}
}
/**
*
* @param {string} message - Mensaje de éxito a mostrar.
* @param {string | null} successColor - Color de la notificación. Si no existe se usa el color por defecto.
* @param {number} time - tiempo de duración en `ms` de la notificación. Si no existe se usa la duración por defecto.
*/
success(successOptions = {}, cb) {
const successOpt = typeof successOptions === 'string'
? setNewProperty('message', successOptions, this.successOpts)
: mergeObjects(this.successOpts, successOptions);
this.add(successOpt, cb);
}
/**
*
* @param {string} message - Mensaje de advertencia a mostrar.
* @param {string | null} infoColor - Color de la notificación. Si no existe se usa el color por defecto.
* @param {number} time - tiempo de duración de la notificación. Si no existe se usa la duración por defecto.
*/
warning(warningOptions = {}, cb) {
const warningOpt = typeof warningOptions === 'string'
? setNewProperty('message', warningOptions, this.warningOpts)
: mergeObjects(this.warningOpts, warningOptions);
this.add(warningOpt, cb);
}
}
export default Notification;