Enhance DeesToast component with new features and improved demo
- Updated README to reflect new toast positions and convenience methods. - Expanded demo functionality to showcase various toast types, positions, and durations. - Added programmatic control for toast dismissal and multiple toast notifications. - Introduced new toast positions: top-center and bottom-center. - Implemented a progress bar for auto-dismiss functionality. - Improved styling and animations for better user experience.
This commit is contained in:
18
package.json
18
package.json
@ -16,7 +16,7 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@design.estate/dees-domtools": "^2.1.1",
|
||||
"@design.estate/dees-element": "^2.0.41",
|
||||
"@design.estate/dees-element": "^2.0.42",
|
||||
"@design.estate/dees-wcctools": "^1.0.90",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.7.2",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.7.2",
|
||||
@ -25,25 +25,25 @@
|
||||
"@push.rocks/smarti18n": "^1.0.4",
|
||||
"@push.rocks/smartpromise": "^4.2.0",
|
||||
"@push.rocks/smartstring": "^4.0.15",
|
||||
"@tsclass/tsclass": "^9.0.0",
|
||||
"@webcontainer/api": "1.2.0",
|
||||
"apexcharts": "^4.3.0",
|
||||
"@tsclass/tsclass": "^9.2.0",
|
||||
"@webcontainer/api": "1.6.1",
|
||||
"apexcharts": "^4.7.0",
|
||||
"highlight.js": "11.11.1",
|
||||
"ibantools": "^4.5.1",
|
||||
"lucide": "^0.501.0",
|
||||
"lucide": "^0.514.0",
|
||||
"monaco-editor": "^0.52.2",
|
||||
"pdfjs-dist": "^4.10.38",
|
||||
"xterm": "^5.3.0",
|
||||
"xterm-addon-fit": "^0.8.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@git.zone/tsbuild": "^2.1.84",
|
||||
"@git.zone/tsbuild": "^2.6.4",
|
||||
"@git.zone/tsbundle": "^2.0.15",
|
||||
"@git.zone/tstest": "^1.0.90",
|
||||
"@git.zone/tstest": "^2.3.1",
|
||||
"@git.zone/tswatch": "^2.0.37",
|
||||
"@push.rocks/projectinfo": "^5.0.2",
|
||||
"@push.rocks/tapbundle": "^5.5.6",
|
||||
"@types/node": "^22.14.1"
|
||||
"@push.rocks/tapbundle": "^6.0.3",
|
||||
"@types/node": "^24.0.0"
|
||||
},
|
||||
"files": [
|
||||
"ts/**/*",
|
||||
|
1959
pnpm-lock.yaml
generated
1959
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
33
readme.md
33
readme.md
@ -104,7 +104,7 @@ Loading indicator with customizable appearance.
|
||||
```
|
||||
|
||||
#### `DeesToast`
|
||||
Notification toast messages with various styles and auto-dismiss.
|
||||
Notification toast messages with various styles, positions, and auto-dismiss functionality.
|
||||
|
||||
```typescript
|
||||
// Programmatic usage
|
||||
@ -112,18 +112,43 @@ DeesToast.show({
|
||||
message: 'Operation successful',
|
||||
type: 'success', // Options: info, success, warning, error
|
||||
duration: 3000, // Time in milliseconds before auto-dismiss
|
||||
position: 'top-right' // Options: top-right, top-left, bottom-right, bottom-left
|
||||
position: 'top-right' // Options: top-right, top-left, bottom-right, bottom-left, top-center, bottom-center
|
||||
});
|
||||
|
||||
// Component usage
|
||||
// Convenience methods
|
||||
DeesToast.info('Information message');
|
||||
DeesToast.success('Success message');
|
||||
DeesToast.warning('Warning message');
|
||||
DeesToast.error('Error message');
|
||||
|
||||
// Advanced control
|
||||
const toast = await DeesToast.show({
|
||||
message: 'Processing...',
|
||||
type: 'info',
|
||||
duration: 0 // No auto-dismiss
|
||||
});
|
||||
|
||||
// Later dismiss programmatically
|
||||
toast.dismiss();
|
||||
|
||||
// Component usage (not typically used directly)
|
||||
<dees-toast
|
||||
message="Changes saved"
|
||||
type="success"
|
||||
autoClose
|
||||
duration="3000"
|
||||
></dees-toast>
|
||||
```
|
||||
|
||||
Key Features:
|
||||
- Multiple toast types with distinct icons and colors
|
||||
- 6 position options for flexible placement
|
||||
- Auto-dismiss with visual progress indicator
|
||||
- Manual dismiss by clicking
|
||||
- Smooth animations and transitions
|
||||
- Automatic stacking of multiple toasts
|
||||
- Theme-aware styling
|
||||
- Programmatic control
|
||||
|
||||
### Form Components
|
||||
|
||||
#### `DeesForm`
|
||||
|
@ -1,5 +1,262 @@
|
||||
import { html } from '@design.estate/dees-element';
|
||||
import { html, css, cssManager } from '@design.estate/dees-element';
|
||||
import { DeesToast } from './dees-toast.js';
|
||||
import './dees-button.js';
|
||||
|
||||
export const demoFunc = async () => {
|
||||
return html`<dees-toast></dees-toast>`;
|
||||
return html`
|
||||
<style>
|
||||
.demo-container {
|
||||
padding: 32px;
|
||||
min-height: 100vh;
|
||||
background: ${cssManager.bdTheme('#f8f9fa', '#0a0a0a')};
|
||||
}
|
||||
|
||||
.demo-section {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.demo-title {
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 16px;
|
||||
color: ${cssManager.bdTheme('#333', '#fff')};
|
||||
}
|
||||
|
||||
.demo-description {
|
||||
font-size: 14px;
|
||||
color: ${cssManager.bdTheme('#666', '#aaa')};
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.button-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 16px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.theme-toggle {
|
||||
position: fixed;
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
z-index: 100;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="demo-container">
|
||||
<dees-button class="theme-toggle" @clicked=${() => {
|
||||
document.body.classList.toggle('bright');
|
||||
}}>Toggle Theme</dees-button>
|
||||
|
||||
<div class="demo-section">
|
||||
<h2 class="demo-title">Toast Types</h2>
|
||||
<p class="demo-description">
|
||||
Different toast types for various notification scenarios. Click any button to show a toast.
|
||||
</p>
|
||||
<div class="button-grid">
|
||||
<dees-button @clicked=${() => {
|
||||
DeesToast.info('This is an informational message');
|
||||
}}>Info Toast</dees-button>
|
||||
|
||||
<dees-button type="highlighted" @clicked=${() => {
|
||||
DeesToast.success('Operation completed successfully!');
|
||||
}}>Success Toast</dees-button>
|
||||
|
||||
<dees-button @clicked=${() => {
|
||||
DeesToast.warning('Please review before proceeding');
|
||||
}}>Warning Toast</dees-button>
|
||||
|
||||
<dees-button @clicked=${() => {
|
||||
DeesToast.error('An error occurred while processing');
|
||||
}}>Error Toast</dees-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="demo-section">
|
||||
<h2 class="demo-title">Toast Positions</h2>
|
||||
<p class="demo-description">
|
||||
Toasts can appear in different positions on the screen.
|
||||
</p>
|
||||
<div class="button-grid">
|
||||
<dees-button @clicked=${() => {
|
||||
DeesToast.show({
|
||||
message: 'Top Right Position',
|
||||
type: 'info',
|
||||
position: 'top-right'
|
||||
});
|
||||
}}>Top Right</dees-button>
|
||||
|
||||
<dees-button @clicked=${() => {
|
||||
DeesToast.show({
|
||||
message: 'Top Left Position',
|
||||
type: 'info',
|
||||
position: 'top-left'
|
||||
});
|
||||
}}>Top Left</dees-button>
|
||||
|
||||
<dees-button @clicked=${() => {
|
||||
DeesToast.show({
|
||||
message: 'Bottom Right Position',
|
||||
type: 'info',
|
||||
position: 'bottom-right'
|
||||
});
|
||||
}}>Bottom Right</dees-button>
|
||||
|
||||
<dees-button @clicked=${() => {
|
||||
DeesToast.show({
|
||||
message: 'Bottom Left Position',
|
||||
type: 'info',
|
||||
position: 'bottom-left'
|
||||
});
|
||||
}}>Bottom Left</dees-button>
|
||||
|
||||
<dees-button @clicked=${() => {
|
||||
DeesToast.show({
|
||||
message: 'Top Center Position',
|
||||
type: 'info',
|
||||
position: 'top-center'
|
||||
});
|
||||
}}>Top Center</dees-button>
|
||||
|
||||
<dees-button @clicked=${() => {
|
||||
DeesToast.show({
|
||||
message: 'Bottom Center Position',
|
||||
type: 'info',
|
||||
position: 'bottom-center'
|
||||
});
|
||||
}}>Bottom Center</dees-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="demo-section">
|
||||
<h2 class="demo-title">Duration Options</h2>
|
||||
<p class="demo-description">
|
||||
Control how long toasts stay visible. Duration in milliseconds.
|
||||
</p>
|
||||
<div class="button-grid">
|
||||
<dees-button @clicked=${() => {
|
||||
DeesToast.show({
|
||||
message: 'Quick toast (1 second)',
|
||||
type: 'info',
|
||||
duration: 1000
|
||||
});
|
||||
}}>1 Second</dees-button>
|
||||
|
||||
<dees-button @clicked=${() => {
|
||||
DeesToast.show({
|
||||
message: 'Standard toast (3 seconds)',
|
||||
type: 'info',
|
||||
duration: 3000
|
||||
});
|
||||
}}>3 Seconds (Default)</dees-button>
|
||||
|
||||
<dees-button @clicked=${() => {
|
||||
DeesToast.show({
|
||||
message: 'Long toast (5 seconds)',
|
||||
type: 'info',
|
||||
duration: 5000
|
||||
});
|
||||
}}>5 Seconds</dees-button>
|
||||
|
||||
<dees-button @clicked=${() => {
|
||||
DeesToast.show({
|
||||
message: 'Manual dismiss only (click to close)',
|
||||
type: 'warning',
|
||||
duration: 0
|
||||
});
|
||||
}}>No Auto-Dismiss</dees-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="demo-section">
|
||||
<h2 class="demo-title">Multiple Toasts</h2>
|
||||
<p class="demo-description">
|
||||
Multiple toasts stack automatically. They maintain their order and animate smoothly.
|
||||
</p>
|
||||
<div class="button-grid">
|
||||
<dees-button @clicked=${() => {
|
||||
DeesToast.info('First notification');
|
||||
setTimeout(() => DeesToast.success('Second notification'), 200);
|
||||
setTimeout(() => DeesToast.warning('Third notification'), 400);
|
||||
setTimeout(() => DeesToast.error('Fourth notification'), 600);
|
||||
}}>Show Multiple</dees-button>
|
||||
|
||||
<dees-button @clicked=${() => {
|
||||
for (let i = 1; i <= 5; i++) {
|
||||
setTimeout(() => {
|
||||
DeesToast.show({
|
||||
message: `Notification #${i}`,
|
||||
type: i % 2 === 0 ? 'success' : 'info',
|
||||
duration: 2000 + (i * 500)
|
||||
});
|
||||
}, i * 100);
|
||||
}
|
||||
}}>Rapid Fire</dees-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="demo-section">
|
||||
<h2 class="demo-title">Real-World Examples</h2>
|
||||
<p class="demo-description">
|
||||
Common use cases for toast notifications in applications.
|
||||
</p>
|
||||
<div class="button-grid">
|
||||
<dees-button @clicked=${async () => {
|
||||
const toast = await DeesToast.show({
|
||||
message: 'Saving changes...',
|
||||
type: 'info',
|
||||
duration: 0
|
||||
});
|
||||
|
||||
// Simulate save operation
|
||||
setTimeout(() => {
|
||||
toast.dismiss();
|
||||
DeesToast.success('Changes saved successfully!');
|
||||
}, 2000);
|
||||
}}>Save Operation</dees-button>
|
||||
|
||||
<dees-button @clicked=${() => {
|
||||
DeesToast.error('Failed to connect to server. Please check your internet connection.');
|
||||
}}>Network Error</dees-button>
|
||||
|
||||
<dees-button @clicked=${() => {
|
||||
DeesToast.warning('Your session will expire in 5 minutes');
|
||||
}}>Session Warning</dees-button>
|
||||
|
||||
<dees-button @clicked=${() => {
|
||||
DeesToast.success('File uploaded successfully!');
|
||||
}}>Upload Complete</dees-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="demo-section">
|
||||
<h2 class="demo-title">Programmatic Control</h2>
|
||||
<p class="demo-description">
|
||||
Advanced control over toast behavior.
|
||||
</p>
|
||||
<div class="button-grid">
|
||||
<dees-button @clicked=${async () => {
|
||||
const toast = await DeesToast.show({
|
||||
message: 'This toast can be dismissed programmatically',
|
||||
type: 'info',
|
||||
duration: 0
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
toast.dismiss();
|
||||
DeesToast.success('Toast dismissed after 2 seconds');
|
||||
}, 2000);
|
||||
}}>Programmatic Dismiss</dees-button>
|
||||
|
||||
<dees-button @clicked=${() => {
|
||||
// Using the convenience methods
|
||||
DeesToast.info('Info message', 2000);
|
||||
setTimeout(() => DeesToast.success('Success message', 2000), 500);
|
||||
setTimeout(() => DeesToast.warning('Warning message', 2000), 1000);
|
||||
setTimeout(() => DeesToast.error('Error message', 2000), 1500);
|
||||
}}>Convenience Methods</dees-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
};
|
@ -1,4 +1,4 @@
|
||||
import { customElement, DeesElement, type TemplateResult, html, type CSSResult, } from '@design.estate/dees-element';
|
||||
import { customElement, DeesElement, type TemplateResult, html, css, property, cssManager } from '@design.estate/dees-element';
|
||||
|
||||
import * as domtools from '@design.estate/dees-domtools';
|
||||
import { demoFunc } from './dees-toast.demo.js';
|
||||
@ -9,20 +9,317 @@ declare global {
|
||||
}
|
||||
}
|
||||
|
||||
export type ToastType = 'info' | 'success' | 'warning' | 'error';
|
||||
export type ToastPosition = 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' | 'top-center' | 'bottom-center';
|
||||
|
||||
export interface IToastOptions {
|
||||
message: string;
|
||||
type?: ToastType;
|
||||
duration?: number;
|
||||
position?: ToastPosition;
|
||||
}
|
||||
|
||||
@customElement('dees-toast')
|
||||
export class DeesToast extends DeesElement {
|
||||
// STATIC
|
||||
public static demo = demoFunc;
|
||||
|
||||
private static toastContainers = new Map<ToastPosition, HTMLDivElement>();
|
||||
|
||||
private static getOrCreateContainer(position: ToastPosition): HTMLDivElement {
|
||||
if (!this.toastContainers.has(position)) {
|
||||
const container = document.createElement('div');
|
||||
container.className = `toast-container toast-container-${position}`;
|
||||
container.style.cssText = `
|
||||
position: fixed;
|
||||
z-index: 10000;
|
||||
pointer-events: none;
|
||||
padding: 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
`;
|
||||
|
||||
// Position the container
|
||||
switch (position) {
|
||||
case 'top-right':
|
||||
container.style.top = '0';
|
||||
container.style.right = '0';
|
||||
break;
|
||||
case 'top-left':
|
||||
container.style.top = '0';
|
||||
container.style.left = '0';
|
||||
break;
|
||||
case 'bottom-right':
|
||||
container.style.bottom = '0';
|
||||
container.style.right = '0';
|
||||
break;
|
||||
case 'bottom-left':
|
||||
container.style.bottom = '0';
|
||||
container.style.left = '0';
|
||||
break;
|
||||
case 'top-center':
|
||||
container.style.top = '0';
|
||||
container.style.left = '50%';
|
||||
container.style.transform = 'translateX(-50%)';
|
||||
break;
|
||||
case 'bottom-center':
|
||||
container.style.bottom = '0';
|
||||
container.style.left = '50%';
|
||||
container.style.transform = 'translateX(-50%)';
|
||||
break;
|
||||
}
|
||||
|
||||
document.body.appendChild(container);
|
||||
this.toastContainers.set(position, container);
|
||||
}
|
||||
return this.toastContainers.get(position)!;
|
||||
}
|
||||
|
||||
public static async show(options: IToastOptions | string) {
|
||||
const opts: IToastOptions = typeof options === 'string'
|
||||
? { message: options }
|
||||
: options;
|
||||
|
||||
const toast = new DeesToast();
|
||||
toast.message = opts.message;
|
||||
toast.type = opts.type || 'info';
|
||||
toast.duration = opts.duration || 3000;
|
||||
|
||||
const container = this.getOrCreateContainer(opts.position || 'top-right');
|
||||
container.appendChild(toast);
|
||||
|
||||
// Trigger animation
|
||||
await toast.updateComplete;
|
||||
requestAnimationFrame(() => {
|
||||
toast.isVisible = true;
|
||||
});
|
||||
|
||||
// Auto dismiss
|
||||
if (toast.duration > 0) {
|
||||
setTimeout(() => {
|
||||
toast.dismiss();
|
||||
}, toast.duration);
|
||||
}
|
||||
|
||||
return toast;
|
||||
}
|
||||
|
||||
// Convenience methods
|
||||
public static info(message: string, duration?: number) {
|
||||
return this.show({ message, type: 'info', duration });
|
||||
}
|
||||
|
||||
public static success(message: string, duration?: number) {
|
||||
return this.show({ message, type: 'success', duration });
|
||||
}
|
||||
|
||||
public static warning(message: string, duration?: number) {
|
||||
return this.show({ message, type: 'warning', duration });
|
||||
}
|
||||
|
||||
public static error(message: string, duration?: number) {
|
||||
return this.show({ message, type: 'error', duration });
|
||||
}
|
||||
|
||||
// INSTANCE
|
||||
@property({ type: String })
|
||||
public message: string = '';
|
||||
|
||||
@property({ type: String })
|
||||
public type: ToastType = 'info';
|
||||
|
||||
@property({ type: Number })
|
||||
public duration: number = 3000;
|
||||
|
||||
@property({ type: Boolean, reflect: true })
|
||||
public isVisible: boolean = false;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
domtools.elementBasic.setup();
|
||||
}
|
||||
|
||||
public render(): TemplateResult {
|
||||
return html`
|
||||
${domtools.elementBasic.styles}
|
||||
<style></style>
|
||||
public static styles = [
|
||||
cssManager.defaultStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
pointer-events: auto;
|
||||
font-family: 'Geist Sans', sans-serif;
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
:host([isvisible]) {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.toast {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 16px 20px;
|
||||
border-radius: 8px;
|
||||
background: ${cssManager.bdTheme('#fff', '#222')};
|
||||
border: 1px solid ${cssManager.bdTheme('#e0e0e0', '#333')};
|
||||
box-shadow: 0 4px 12px ${cssManager.bdTheme('rgba(0,0,0,0.1)', 'rgba(0,0,0,0.3)')};
|
||||
min-width: 300px;
|
||||
max-width: 500px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.toast:hover {
|
||||
transform: scale(1.02);
|
||||
}
|
||||
|
||||
.icon {
|
||||
flex-shrink: 0;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.icon svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.message {
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
color: ${cssManager.bdTheme('#333', '#fff')};
|
||||
}
|
||||
|
||||
.close {
|
||||
flex-shrink: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
opacity: 0.5;
|
||||
cursor: pointer;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.close:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.close svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
/* Type-specific styles */
|
||||
:host([type="info"]) .icon {
|
||||
color: #0084ff;
|
||||
}
|
||||
|
||||
:host([type="success"]) .icon {
|
||||
color: #22c55e;
|
||||
}
|
||||
|
||||
:host([type="warning"]) .icon {
|
||||
color: #f59e0b;
|
||||
}
|
||||
|
||||
:host([type="error"]) .icon {
|
||||
color: #ef4444;
|
||||
}
|
||||
|
||||
/* Progress bar */
|
||||
.progress {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 3px;
|
||||
background: currentColor;
|
||||
opacity: 0.2;
|
||||
border-radius: 0 0 8px 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
height: 100%;
|
||||
background: currentColor;
|
||||
opacity: 0.8;
|
||||
transform-origin: left;
|
||||
animation: progress linear forwards;
|
||||
}
|
||||
|
||||
@keyframes progress {
|
||||
from {
|
||||
transform: scaleX(1);
|
||||
}
|
||||
to {
|
||||
transform: scaleX(0);
|
||||
}
|
||||
}
|
||||
`
|
||||
];
|
||||
|
||||
public render(): TemplateResult {
|
||||
const icons = {
|
||||
info: html`<svg viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-11a1 1 0 10-2 0v2H7a1 1 0 100 2h2v2a1 1 0 102 0v-2h2a1 1 0 100-2h-2V7z" clip-rule="evenodd"/>
|
||||
</svg>`,
|
||||
success: html`<svg viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
|
||||
</svg>`,
|
||||
warning: html`<svg viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clip-rule="evenodd"/>
|
||||
</svg>`,
|
||||
error: html`<svg viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"/>
|
||||
</svg>`
|
||||
};
|
||||
|
||||
return html`
|
||||
<div class="toast" @click=${this.dismiss}>
|
||||
<div class="icon">
|
||||
${icons[this.type]}
|
||||
</div>
|
||||
<div class="message">${this.message}</div>
|
||||
<div class="close">
|
||||
<svg viewBox="0 0 16 16" fill="currentColor">
|
||||
<path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"/>
|
||||
</svg>
|
||||
</div>
|
||||
${this.duration > 0 ? html`
|
||||
<div class="progress">
|
||||
<div class="progress-bar" style="animation-duration: ${this.duration}ms"></div>
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
public async dismiss() {
|
||||
this.isVisible = false;
|
||||
await new Promise(resolve => setTimeout(resolve, 300));
|
||||
this.remove();
|
||||
|
||||
// Clean up empty containers
|
||||
const container = this.parentElement;
|
||||
if (container && container.children.length === 0) {
|
||||
container.remove();
|
||||
for (const [position, cont] of DeesToast.toastContainers.entries()) {
|
||||
if (cont === container) {
|
||||
DeesToast.toastContainers.delete(position);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public firstUpdated() {
|
||||
// Set the type attribute for CSS
|
||||
this.setAttribute('type', this.type);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user