99 lines
3.1 KiB
TypeScript
99 lines
3.1 KiB
TypeScript
/**
|
|
* Simple Toast Notification Utility
|
|
*/
|
|
export class Toast {
|
|
private static container: HTMLElement | null = null;
|
|
private static styleId = 'appdev-design-mode-toast-styles';
|
|
|
|
private static ensureContainer() {
|
|
if (this.container && document.body.contains(this.container)) return;
|
|
|
|
// Inject styles
|
|
if (!document.getElementById(this.styleId)) {
|
|
const style = document.createElement('style');
|
|
style.id = this.styleId;
|
|
style.textContent = `
|
|
.design-mode-toast-container {
|
|
position: fixed;
|
|
top: 20px;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
z-index: 10000;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 10px;
|
|
pointer-events: none;
|
|
}
|
|
.design-mode-toast {
|
|
background: white;
|
|
color: #333;
|
|
padding: 10px 20px;
|
|
border-radius: 6px;
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
font-family: system-ui, -apple-system, sans-serif;
|
|
font-size: 14px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
animation: design-mode-toast-in 0.3s ease-out forwards;
|
|
border: 1px solid #eee;
|
|
min-width: 200px;
|
|
max-width: 400px;
|
|
}
|
|
.design-mode-toast.error {
|
|
border-left: 4px solid #ef4444;
|
|
}
|
|
.design-mode-toast.success {
|
|
border-left: 4px solid #22c55e;
|
|
}
|
|
.design-mode-toast.info {
|
|
border-left: 4px solid #3b82f6;
|
|
}
|
|
@keyframes design-mode-toast-in {
|
|
from { opacity: 0; transform: translateY(-20px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
@keyframes design-mode-toast-out {
|
|
from { opacity: 1; transform: translateY(0); }
|
|
to { opacity: 0; transform: translateY(-20px); }
|
|
}
|
|
`;
|
|
document.head.appendChild(style);
|
|
}
|
|
|
|
// Create container
|
|
this.container = document.createElement('div');
|
|
this.container.className = 'design-mode-toast-container';
|
|
document.body.appendChild(this.container);
|
|
}
|
|
|
|
public static show(message: string, type: 'success' | 'error' | 'info' = 'info', duration = 3000) {
|
|
this.ensureContainer();
|
|
|
|
const toast = document.createElement('div');
|
|
toast.className = `design-mode-toast ${type}`;
|
|
toast.textContent = message;
|
|
|
|
this.container!.appendChild(toast);
|
|
|
|
setTimeout(() => {
|
|
toast.style.animation = 'design-mode-toast-out 0.3s ease-in forwards';
|
|
toast.addEventListener('animationend', () => {
|
|
toast.remove();
|
|
});
|
|
}, duration);
|
|
}
|
|
|
|
public static error(message: string, duration = 4000) {
|
|
this.show(message, 'error', duration);
|
|
}
|
|
|
|
public static success(message: string, duration = 3000) {
|
|
this.show(message, 'success', duration);
|
|
}
|
|
|
|
public static info(message: string, duration = 3000) {
|
|
this.show(message, 'info', duration);
|
|
}
|
|
}
|