125 lines
4.0 KiB
JavaScript
125 lines
4.0 KiB
JavaScript
|
|
/**
|
||
|
|
* @fileoverview Toast Notification Component for Rantii
|
||
|
|
* @author retoor <retoor@molodetz.nl>
|
||
|
|
* @description Non-intrusive notification messages for user feedback
|
||
|
|
* @keywords toast, notification, alert, message, feedback
|
||
|
|
*/
|
||
|
|
|
||
|
|
import { BaseComponent } from './base-component.js';
|
||
|
|
|
||
|
|
class ToastNotification extends BaseComponent {
|
||
|
|
static get observedAttributes() {
|
||
|
|
return ['type', 'message', 'duration'];
|
||
|
|
}
|
||
|
|
|
||
|
|
init() {
|
||
|
|
this.autoHideTimer = null;
|
||
|
|
this.render();
|
||
|
|
}
|
||
|
|
|
||
|
|
render() {
|
||
|
|
const type = this.getAttr('type') || 'info';
|
||
|
|
const message = this.getAttr('message') || '';
|
||
|
|
|
||
|
|
this.addClass('toast', `toast-${type}`);
|
||
|
|
|
||
|
|
this.setHtml(`
|
||
|
|
<div class="toast-content">
|
||
|
|
<span class="toast-icon">${this.getIcon(type)}</span>
|
||
|
|
<span class="toast-message">${message}</span>
|
||
|
|
<button class="toast-close" aria-label="Close">
|
||
|
|
<svg viewBox="0 0 24 24" width="18" height="18">
|
||
|
|
<path fill="currentColor" d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
|
||
|
|
</svg>
|
||
|
|
</button>
|
||
|
|
</div>
|
||
|
|
`);
|
||
|
|
|
||
|
|
this.bindEvents();
|
||
|
|
this.startAutoHide();
|
||
|
|
}
|
||
|
|
|
||
|
|
getIcon(type) {
|
||
|
|
const icons = {
|
||
|
|
success: `<svg viewBox="0 0 24 24" width="20" height="20"><path fill="currentColor" d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>`,
|
||
|
|
error: `<svg viewBox="0 0 24 24" width="20" height="20"><path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/></svg>`,
|
||
|
|
warning: `<svg viewBox="0 0 24 24" width="20" height="20"><path fill="currentColor" d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/></svg>`,
|
||
|
|
info: `<svg viewBox="0 0 24 24" width="20" height="20"><path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/></svg>`
|
||
|
|
};
|
||
|
|
return icons[type] || icons.info;
|
||
|
|
}
|
||
|
|
|
||
|
|
bindEvents() {
|
||
|
|
const closeBtn = this.$('.toast-close');
|
||
|
|
if (closeBtn) {
|
||
|
|
this.on(closeBtn, 'click', () => this.dismiss());
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
startAutoHide() {
|
||
|
|
const duration = parseInt(this.getAttr('duration') || '4000', 10);
|
||
|
|
if (duration > 0) {
|
||
|
|
this.autoHideTimer = setTimeout(() => this.dismiss(), duration);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
dismiss() {
|
||
|
|
if (this.autoHideTimer) {
|
||
|
|
clearTimeout(this.autoHideTimer);
|
||
|
|
}
|
||
|
|
this.addClass('toast-hiding');
|
||
|
|
setTimeout(() => {
|
||
|
|
this.emit('toast-dismissed');
|
||
|
|
this.remove();
|
||
|
|
}, 300);
|
||
|
|
}
|
||
|
|
|
||
|
|
show(message, type = 'info', duration = 4000) {
|
||
|
|
this.setAttr('message', message);
|
||
|
|
this.setAttr('type', type);
|
||
|
|
this.setAttr('duration', duration.toString());
|
||
|
|
this.render();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
customElements.define('toast-notification', ToastNotification);
|
||
|
|
|
||
|
|
class ToastContainer extends BaseComponent {
|
||
|
|
init() {
|
||
|
|
this.addClass('toast-container');
|
||
|
|
}
|
||
|
|
|
||
|
|
show(message, type = 'info', duration = 4000) {
|
||
|
|
const toast = document.createElement('toast-notification');
|
||
|
|
toast.setAttribute('message', message);
|
||
|
|
toast.setAttribute('type', type);
|
||
|
|
toast.setAttribute('duration', duration.toString());
|
||
|
|
this.appendChild(toast);
|
||
|
|
return toast;
|
||
|
|
}
|
||
|
|
|
||
|
|
success(message, duration = 4000) {
|
||
|
|
return this.show(message, 'success', duration);
|
||
|
|
}
|
||
|
|
|
||
|
|
error(message, duration = 5000) {
|
||
|
|
return this.show(message, 'error', duration);
|
||
|
|
}
|
||
|
|
|
||
|
|
warning(message, duration = 4000) {
|
||
|
|
return this.show(message, 'warning', duration);
|
||
|
|
}
|
||
|
|
|
||
|
|
info(message, duration = 4000) {
|
||
|
|
return this.show(message, 'info', duration);
|
||
|
|
}
|
||
|
|
|
||
|
|
clearAll() {
|
||
|
|
this.innerHTML = '';
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
customElements.define('toast-container', ToastContainer);
|
||
|
|
|
||
|
|
export { ToastNotification, ToastContainer };
|