toastify-pro 1.0.3 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +164 -37
- package/assets/site/site.webmanifest +1 -1
- package/dist/toastify-pro.esm.js +658 -67
- package/dist/toastify-pro.esm.js.map +1 -0
- package/dist/toastify-pro.umd.js +661 -71
- package/dist/toastify-pro.umd.js.map +1 -0
- package/dist/toastify-pro.umd.min.js +21 -1
- package/dist/toastify-pro.umd.min.js.map +1 -0
- package/package.json +46 -5
- package/src/toastify-pro.js +656 -66
package/src/toastify-pro.js
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ToastifyPro - Modern Toast Notification Library
|
|
3
|
+
* A beautiful, customizable toast notification library with glassmorphism design,
|
|
4
|
+
* Apple AirDrop-style animations, and car swipe exit effects.
|
|
5
|
+
*
|
|
6
|
+
* Features:
|
|
7
|
+
* - Glassmorphism design with backdrop-filter effects
|
|
8
|
+
* - Apple AirDrop-style entrance animations
|
|
9
|
+
* - Position-aware car swipe exit animations
|
|
10
|
+
* - Description support for enhanced messaging
|
|
11
|
+
* - Six theme variants (success, error, info, warning, dark, light)
|
|
12
|
+
* - Progress bar with shimmer effects
|
|
13
|
+
* - Responsive design for mobile devices
|
|
14
|
+
* - Framework agnostic (works with React, Vue, Angular, etc.)
|
|
15
|
+
*
|
|
16
|
+
* @version 1.2.0
|
|
17
|
+
* @author ToastifyPro Team
|
|
18
|
+
* @license MIT
|
|
19
|
+
*/
|
|
1
20
|
class ToastifyPro {
|
|
21
|
+
/**
|
|
22
|
+
* Creates a new ToastifyPro instance
|
|
23
|
+
* @param {Object} options - Configuration options
|
|
24
|
+
* @param {string} options.position - Toast position (top-left, top-right, bottom-left, bottom-right, top-center, bottom-center)
|
|
25
|
+
* @param {number} options.timeout - Auto-dismiss timeout in milliseconds (0 to disable)
|
|
26
|
+
* @param {boolean} options.allowClose - Whether to show close button
|
|
27
|
+
* @param {number} options.maxLength - Maximum message length
|
|
28
|
+
*/
|
|
2
29
|
constructor(options = {}) {
|
|
30
|
+
// Validate options parameter
|
|
31
|
+
if (typeof options !== 'object' || options === null) {
|
|
32
|
+
console.warn('ToastifyPro: Invalid options parameter. Using defaults.');
|
|
33
|
+
options = {};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Merge with default options
|
|
3
37
|
this.defaultOptions = {
|
|
4
38
|
position: options.position || "bottom-center", // top-left, top-right, bottom-left, bottom-right, top-center, bottom-center
|
|
5
39
|
timeout: options.timeout || 3000,
|
|
@@ -7,151 +41,707 @@ class ToastifyPro {
|
|
|
7
41
|
maxLength: options.maxLength || 100,
|
|
8
42
|
};
|
|
9
43
|
|
|
10
|
-
//
|
|
44
|
+
// Validate position
|
|
45
|
+
const validPositions = ['top-left', 'top-right', 'bottom-left', 'bottom-right', 'top-center', 'bottom-center'];
|
|
46
|
+
if (!validPositions.includes(this.defaultOptions.position)) {
|
|
47
|
+
console.warn(`ToastifyPro: Invalid position "${this.defaultOptions.position}". Using "bottom-center".`);
|
|
48
|
+
this.defaultOptions.position = "bottom-center";
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Check if we're in a browser environment
|
|
52
|
+
if (typeof document === 'undefined') {
|
|
53
|
+
throw new Error('ToastifyPro: This library requires a DOM environment (browser).');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Create or reuse container for this position
|
|
11
57
|
const existing = document.querySelector(
|
|
12
58
|
`.toastify-pro-container.${this.defaultOptions.position}`
|
|
13
59
|
);
|
|
60
|
+
|
|
14
61
|
if (existing) {
|
|
15
62
|
this.container = existing;
|
|
16
63
|
} else {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
64
|
+
try {
|
|
65
|
+
this.container = document.createElement("div");
|
|
66
|
+
this.container.className = `toastify-pro-container ${this.defaultOptions.position}`;
|
|
67
|
+
document.body.appendChild(this.container);
|
|
68
|
+
} catch (error) {
|
|
69
|
+
throw new Error('ToastifyPro: Failed to create container element. DOM may not be ready.');
|
|
70
|
+
}
|
|
20
71
|
}
|
|
21
72
|
|
|
73
|
+
// Inject styles once
|
|
22
74
|
this.injectStyles();
|
|
23
75
|
}
|
|
24
76
|
|
|
77
|
+
/**
|
|
78
|
+
* Returns the SVG icon for a given toast type
|
|
79
|
+
* @param {string} type - Toast type (success, error, info, warning, dark, light)
|
|
80
|
+
* @returns {string} SVG icon markup
|
|
81
|
+
*/
|
|
82
|
+
getIconSVG(type) {
|
|
83
|
+
// Validate type parameter
|
|
84
|
+
if (typeof type !== 'string') {
|
|
85
|
+
console.warn('ToastifyPro: Invalid icon type. Using default info icon.');
|
|
86
|
+
type = 'info';
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const icons = {
|
|
90
|
+
success: `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
91
|
+
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" fill="currentColor"/>
|
|
92
|
+
</svg>`,
|
|
93
|
+
error: `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
94
|
+
<path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z" fill="currentColor"/>
|
|
95
|
+
</svg>`,
|
|
96
|
+
info: `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
97
|
+
<path 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" fill="currentColor"/>
|
|
98
|
+
</svg>`,
|
|
99
|
+
warning: `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
100
|
+
<path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z" fill="currentColor"/>
|
|
101
|
+
</svg>`,
|
|
102
|
+
dark: `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
103
|
+
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" fill="currentColor"/>
|
|
104
|
+
</svg>`,
|
|
105
|
+
light: `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
106
|
+
<path d="M9 11H7v6h2v-6zm4 0h-2v6h2v-6zm4 0h-2v6h2v-6zm2.5-9H19V1h-2v1H7V1H5v1H4.5C3.11 2 2 3.11 2 4.5v14C2 19.89 3.11 21 4.5 21h15c1.39 0 2.5-1.11 2.5-2.5v-14C22 3.11 20.89 2 19.5 2zm0 16h-15v-11h15v11z" fill="currentColor"/>
|
|
107
|
+
</svg>`
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
return icons[type] || icons.info;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Injects the CSS styles into the document head
|
|
115
|
+
* Styles include glassmorphism design, animations, and responsive layout
|
|
116
|
+
*/
|
|
25
117
|
injectStyles() {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
118
|
+
// Prevent duplicate style injection
|
|
119
|
+
if (document.getElementById("toastify-pro-styles")) return;
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
const style = document.createElement("style");
|
|
123
|
+
style.id = "toastify-pro-styles";
|
|
124
|
+
style.textContent = `
|
|
125
|
+
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap');
|
|
126
|
+
|
|
30
127
|
.toastify-pro-container {
|
|
31
128
|
position: fixed;
|
|
32
129
|
z-index: 9999;
|
|
33
130
|
display: flex;
|
|
34
131
|
flex-direction: column;
|
|
35
|
-
gap:
|
|
132
|
+
gap: 16px;
|
|
36
133
|
pointer-events: none;
|
|
37
134
|
}
|
|
38
|
-
.toastify-pro-container.top-left { top:
|
|
39
|
-
.toastify-pro-container.top-right { top:
|
|
40
|
-
.toastify-pro-container.bottom-left { bottom:
|
|
41
|
-
.toastify-pro-container.bottom-right { bottom:
|
|
42
|
-
.toastify-pro-container.top-center { top:
|
|
43
|
-
.toastify-pro-container.bottom-center { bottom:
|
|
135
|
+
.toastify-pro-container.top-left { top: 50px; left: 24px; align-items: flex-start; }
|
|
136
|
+
.toastify-pro-container.top-right { top: 50px; right: 24px; align-items: flex-end; }
|
|
137
|
+
.toastify-pro-container.bottom-left { bottom: 50px; left: 24px; align-items: flex-start; }
|
|
138
|
+
.toastify-pro-container.bottom-right { bottom: 50px; right: 24px; align-items: flex-end; }
|
|
139
|
+
.toastify-pro-container.top-center { top: 50px; left: 50%; transform: translateX(-50%); }
|
|
140
|
+
.toastify-pro-container.bottom-center { bottom: 50px; left: 50%; transform: translateX(-50%); }
|
|
44
141
|
|
|
45
142
|
.toastify-pro {
|
|
46
|
-
min-width:
|
|
47
|
-
max-width:
|
|
48
|
-
padding:
|
|
49
|
-
border-radius:
|
|
50
|
-
font-size:
|
|
51
|
-
font-family: sans-serif;
|
|
143
|
+
min-width: 280px;
|
|
144
|
+
max-width: 400px;
|
|
145
|
+
padding: 20px 24px;
|
|
146
|
+
border-radius: 16px;
|
|
147
|
+
font-size: 15px;
|
|
148
|
+
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
149
|
+
font-weight: 500;
|
|
52
150
|
color: white;
|
|
53
151
|
opacity: 0;
|
|
54
|
-
transform:
|
|
55
|
-
transition: all 0.
|
|
152
|
+
transform: scale(0.3);
|
|
153
|
+
transition: all 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
|
56
154
|
pointer-events: auto;
|
|
57
155
|
position: relative;
|
|
58
156
|
display: flex;
|
|
59
157
|
align-items: center;
|
|
60
|
-
|
|
61
|
-
|
|
158
|
+
gap: 16px;
|
|
159
|
+
backdrop-filter: blur(20px);
|
|
160
|
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
161
|
+
box-shadow:
|
|
162
|
+
0 20px 25px -5px rgba(0, 0, 0, 0.1),
|
|
163
|
+
0 10px 10px -5px rgba(0, 0, 0, 0.04),
|
|
164
|
+
0 0 0 1px rgba(255, 255, 255, 0.05);
|
|
165
|
+
overflow: hidden;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.toastify-pro::before {
|
|
169
|
+
content: '';
|
|
170
|
+
position: absolute;
|
|
171
|
+
top: 0;
|
|
172
|
+
left: 0;
|
|
173
|
+
right: 0;
|
|
174
|
+
height: 3px;
|
|
175
|
+
background: linear-gradient(90deg,
|
|
176
|
+
rgba(255, 255, 255, 0.8) 0%,
|
|
177
|
+
rgba(255, 255, 255, 0.4) 50%,
|
|
178
|
+
rgba(255, 255, 255, 0.8) 100%);
|
|
179
|
+
animation: shimmer 2s infinite;
|
|
180
|
+
transition: opacity 0.8s ease;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.toastify-pro::after {
|
|
184
|
+
content: '';
|
|
185
|
+
position: absolute;
|
|
186
|
+
bottom: 0;
|
|
187
|
+
left: 0;
|
|
188
|
+
height: 3px;
|
|
189
|
+
background: rgba(255, 255, 255, 0.6);
|
|
190
|
+
animation: progress var(--duration, 5s) linear;
|
|
191
|
+
border-radius: 0 0 16px 16px;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
@keyframes airdropPop {
|
|
195
|
+
0% {
|
|
196
|
+
opacity: 0;
|
|
197
|
+
transform: scale(0.3) rotateY(-20deg);
|
|
198
|
+
}
|
|
199
|
+
30% {
|
|
200
|
+
opacity: 0.8;
|
|
201
|
+
transform: scale(1.1) rotateY(10deg);
|
|
202
|
+
}
|
|
203
|
+
60% {
|
|
204
|
+
opacity: 1;
|
|
205
|
+
transform: scale(0.98) rotateY(-3deg);
|
|
206
|
+
}
|
|
207
|
+
100% {
|
|
208
|
+
opacity: 1;
|
|
209
|
+
transform: scale(1) rotateY(0deg);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
@keyframes carSwipeBottom {
|
|
214
|
+
0% {
|
|
215
|
+
opacity: 1;
|
|
216
|
+
transform: scale(1) translateY(0);
|
|
217
|
+
}
|
|
218
|
+
15% {
|
|
219
|
+
opacity: 1;
|
|
220
|
+
transform: scale(1.02) translateY(-8px);
|
|
221
|
+
}
|
|
222
|
+
100% {
|
|
223
|
+
opacity: 0;
|
|
224
|
+
transform: scale(0.8) translateY(200px);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
@keyframes carSwipeTop {
|
|
229
|
+
0% {
|
|
230
|
+
opacity: 1;
|
|
231
|
+
transform: scale(1) translateY(0);
|
|
232
|
+
}
|
|
233
|
+
15% {
|
|
234
|
+
opacity: 1;
|
|
235
|
+
transform: scale(1.02) translateY(8px);
|
|
236
|
+
}
|
|
237
|
+
100% {
|
|
238
|
+
opacity: 0;
|
|
239
|
+
transform: scale(0.8) translateY(-200px);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
@keyframes carSwipeLeft {
|
|
244
|
+
0% {
|
|
245
|
+
opacity: 1;
|
|
246
|
+
transform: scale(1) translateX(0);
|
|
247
|
+
}
|
|
248
|
+
15% {
|
|
249
|
+
opacity: 1;
|
|
250
|
+
transform: scale(1.02) translateX(8px);
|
|
251
|
+
}
|
|
252
|
+
100% {
|
|
253
|
+
opacity: 0;
|
|
254
|
+
transform: scale(0.8) translateX(-300px);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
@keyframes carSwipeRight {
|
|
259
|
+
0% {
|
|
260
|
+
opacity: 1;
|
|
261
|
+
transform: scale(1) translateX(0);
|
|
262
|
+
}
|
|
263
|
+
15% {
|
|
264
|
+
opacity: 1;
|
|
265
|
+
transform: scale(1.02) translateX(-8px);
|
|
266
|
+
}
|
|
267
|
+
100% {
|
|
268
|
+
opacity: 0;
|
|
269
|
+
transform: scale(0.8) translateX(300px);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
@keyframes carSwipeCenter {
|
|
274
|
+
0% {
|
|
275
|
+
opacity: 1;
|
|
276
|
+
transform: scale(1) translateY(0);
|
|
277
|
+
}
|
|
278
|
+
15% {
|
|
279
|
+
opacity: 1;
|
|
280
|
+
transform: scale(1.02) translateY(-5px);
|
|
281
|
+
}
|
|
282
|
+
100% {
|
|
283
|
+
opacity: 0;
|
|
284
|
+
transform: scale(0.6) translateY(150px);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
@keyframes progress {
|
|
289
|
+
0% { width: 100%; }
|
|
290
|
+
100% { width: 0%; }
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
@keyframes shimmer {
|
|
294
|
+
0% { transform: translateX(-100%); }
|
|
295
|
+
100% { transform: translateX(100%); }
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.toastify-pro.show {
|
|
299
|
+
opacity: 1;
|
|
300
|
+
transform: scale(1);
|
|
301
|
+
animation: airdropPop 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.toastify-pro.success {
|
|
305
|
+
background: linear-gradient(135deg,
|
|
306
|
+
rgba(34, 197, 94, 0.9) 0%,
|
|
307
|
+
rgba(21, 128, 61, 0.9) 100%);
|
|
308
|
+
border-color: rgba(34, 197, 94, 0.3);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
.toastify-pro.error {
|
|
312
|
+
background: linear-gradient(135deg,
|
|
313
|
+
rgba(239, 68, 68, 0.9) 0%,
|
|
314
|
+
rgba(185, 28, 28, 0.9) 100%);
|
|
315
|
+
border-color: rgba(239, 68, 68, 0.3);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
.toastify-pro.info {
|
|
319
|
+
background: linear-gradient(135deg,
|
|
320
|
+
rgba(59, 130, 246, 0.9) 0%,
|
|
321
|
+
rgba(29, 78, 216, 0.9) 100%);
|
|
322
|
+
border-color: rgba(59, 130, 246, 0.3);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.toastify-pro.warning {
|
|
326
|
+
background: linear-gradient(135deg,
|
|
327
|
+
rgba(245, 158, 11, 0.9) 0%,
|
|
328
|
+
rgba(217, 119, 6, 0.9) 100%);
|
|
329
|
+
border-color: rgba(245, 158, 11, 0.3);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
.toastify-pro.dark {
|
|
333
|
+
background: linear-gradient(135deg,
|
|
334
|
+
rgba(15, 23, 42, 0.95) 0%,
|
|
335
|
+
rgba(30, 41, 59, 0.95) 100%);
|
|
336
|
+
border-color: rgba(148, 163, 184, 0.2);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
.toastify-pro.light {
|
|
340
|
+
background: linear-gradient(135deg,
|
|
341
|
+
rgba(255, 255, 255, 0.95) 0%,
|
|
342
|
+
rgba(248, 250, 252, 0.95) 100%);
|
|
343
|
+
color: #1e293b;
|
|
344
|
+
border-color: rgba(226, 232, 240, 0.8);
|
|
345
|
+
box-shadow:
|
|
346
|
+
0 20px 25px -5px rgba(0, 0, 0, 0.08),
|
|
347
|
+
0 10px 10px -5px rgba(0, 0, 0, 0.03);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
.toastify-pro.light::before {
|
|
351
|
+
background: linear-gradient(90deg,
|
|
352
|
+
rgba(30, 41, 59, 0.8) 0%,
|
|
353
|
+
rgba(30, 41, 59, 0.4) 50%,
|
|
354
|
+
rgba(30, 41, 59, 0.8) 100%);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.toastify-pro.light::after {
|
|
358
|
+
background: rgba(30, 41, 59, 0.6);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
.toastify-pro .toast-icon {
|
|
362
|
+
flex-shrink: 0;
|
|
363
|
+
display: flex;
|
|
364
|
+
align-items: center;
|
|
365
|
+
justify-content: center;
|
|
366
|
+
width: 28px;
|
|
367
|
+
height: 28px;
|
|
368
|
+
border-radius: 50%;
|
|
369
|
+
background: rgba(255, 255, 255, 0.2);
|
|
370
|
+
backdrop-filter: blur(10px);
|
|
371
|
+
animation: iconPulse 2s infinite;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
@keyframes iconPulse {
|
|
375
|
+
0%, 100% { transform: scale(1); }
|
|
376
|
+
50% { transform: scale(1.05); }
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
@keyframes iconBounce {
|
|
380
|
+
0% { transform: scale(0.2) rotate(-15deg); }
|
|
381
|
+
40% { transform: scale(1.2) rotate(8deg); }
|
|
382
|
+
70% { transform: scale(0.95) rotate(-3deg); }
|
|
383
|
+
100% { transform: scale(1) rotate(0deg); }
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
@keyframes iconCarExit {
|
|
387
|
+
0% {
|
|
388
|
+
transform: scale(1) rotate(0deg);
|
|
389
|
+
opacity: 1;
|
|
390
|
+
}
|
|
391
|
+
20% {
|
|
392
|
+
transform: scale(1.1) rotate(-10deg);
|
|
393
|
+
opacity: 0.9;
|
|
394
|
+
}
|
|
395
|
+
100% {
|
|
396
|
+
transform: scale(0.3) rotate(180deg);
|
|
397
|
+
opacity: 0;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
.toastify-pro .toast-icon svg {
|
|
402
|
+
width: 18px;
|
|
403
|
+
height: 18px;
|
|
404
|
+
color: inherit;
|
|
405
|
+
filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1));
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
.toastify-pro.light .toast-icon {
|
|
409
|
+
background: rgba(15, 23, 42, 0.1);
|
|
62
410
|
}
|
|
63
|
-
.toastify-pro.show { opacity: 1; transform: translateY(0); }
|
|
64
|
-
.toastify-pro.success { background: rgba(76, 175, 80, 0.9); }
|
|
65
|
-
.toastify-pro.error { background: rgba(244, 67, 54, 0.9); }
|
|
66
|
-
.toastify-pro.info { background: rgba(33, 150, 243, 0.9); }
|
|
67
|
-
.toastify-pro.warning { background: rgba(255, 152, 0, 0.9); }
|
|
68
|
-
.toastify-pro.dark { background: rgba(0,0,0,0.85); }
|
|
69
|
-
.toastify-pro.light { background: rgba(255,255,255,0.9); color: #000; }
|
|
70
411
|
|
|
71
412
|
.toastify-pro .toast-content {
|
|
72
413
|
flex: 1;
|
|
73
|
-
|
|
414
|
+
line-height: 1.5;
|
|
415
|
+
font-weight: 500;
|
|
416
|
+
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
.toastify-pro .toast-message {
|
|
420
|
+
font-size: 15px;
|
|
421
|
+
font-weight: 500;
|
|
422
|
+
margin-bottom: 0;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
.toastify-pro .toast-description {
|
|
426
|
+
font-size: 13px;
|
|
427
|
+
font-weight: 400;
|
|
428
|
+
opacity: 0.85;
|
|
429
|
+
margin-top: 4px;
|
|
74
430
|
line-height: 1.4;
|
|
75
431
|
}
|
|
76
432
|
|
|
77
433
|
.toastify-pro .close-btn {
|
|
78
434
|
cursor: pointer;
|
|
79
|
-
font-size:
|
|
435
|
+
font-size: 20px;
|
|
80
436
|
color: inherit;
|
|
81
|
-
opacity: 0.
|
|
82
|
-
padding:
|
|
83
|
-
border-radius:
|
|
84
|
-
transition:
|
|
437
|
+
opacity: 0.7;
|
|
438
|
+
padding: 8px;
|
|
439
|
+
border-radius: 50%;
|
|
440
|
+
transition: all 0.2s ease;
|
|
85
441
|
flex-shrink: 0;
|
|
86
|
-
|
|
87
|
-
|
|
442
|
+
width: 32px;
|
|
443
|
+
height: 32px;
|
|
444
|
+
display: flex;
|
|
445
|
+
align-items: center;
|
|
446
|
+
justify-content: center;
|
|
447
|
+
background: rgba(255, 255, 255, 0.1);
|
|
448
|
+
backdrop-filter: blur(10px);
|
|
449
|
+
font-weight: 300;
|
|
88
450
|
line-height: 1;
|
|
89
451
|
}
|
|
452
|
+
|
|
90
453
|
.toastify-pro .close-btn:hover {
|
|
91
454
|
opacity: 1;
|
|
92
|
-
background
|
|
455
|
+
background: rgba(255, 255, 255, 0.2);
|
|
456
|
+
transform: scale(1.1);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
.toastify-pro.light .close-btn {
|
|
460
|
+
background: rgba(15, 23, 42, 0.08);
|
|
93
461
|
}
|
|
462
|
+
|
|
94
463
|
.toastify-pro.light .close-btn:hover {
|
|
95
|
-
background
|
|
464
|
+
background: rgba(15, 23, 42, 0.15);
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
@media (max-width: 640px) {
|
|
468
|
+
.toastify-pro {
|
|
469
|
+
min-width: 260px;
|
|
470
|
+
max-width: calc(100vw - 48px);
|
|
471
|
+
margin: 0 8px;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
.toastify-pro-container.top-left,
|
|
475
|
+
.toastify-pro-container.bottom-left { left: 16px; }
|
|
476
|
+
.toastify-pro-container.top-right,
|
|
477
|
+
.toastify-pro-container.bottom-right { right: 16px; }
|
|
96
478
|
}
|
|
97
479
|
`;
|
|
98
|
-
|
|
480
|
+
document.head.appendChild(style);
|
|
481
|
+
} catch (error) {
|
|
482
|
+
console.error('ToastifyPro: Failed to inject styles:', error);
|
|
483
|
+
}
|
|
99
484
|
}
|
|
100
485
|
|
|
486
|
+
/**
|
|
487
|
+
* Creates and displays a toast notification
|
|
488
|
+
* @param {string} message - Main message text
|
|
489
|
+
* @param {string} type - Toast type (success, error, info, warning, dark, light)
|
|
490
|
+
* @param {Object} opts - Additional options
|
|
491
|
+
* @param {string} opts.description - Optional description text
|
|
492
|
+
* @param {number} opts.timeout - Override default timeout
|
|
493
|
+
* @param {boolean} opts.allowClose - Override close button setting
|
|
494
|
+
* @param {number} opts.maxLength - Override max message length
|
|
495
|
+
*/
|
|
101
496
|
show(message, type = "dark", opts = {}) {
|
|
102
|
-
|
|
497
|
+
// Input validation
|
|
498
|
+
if (typeof message !== 'string') {
|
|
499
|
+
console.warn('ToastifyPro: Message must be a string. Converting to string.');
|
|
500
|
+
message = String(message);
|
|
501
|
+
}
|
|
103
502
|
|
|
104
|
-
|
|
105
|
-
|
|
503
|
+
if (!message.trim()) {
|
|
504
|
+
console.warn('ToastifyPro: Empty message provided.');
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
106
507
|
|
|
107
|
-
//
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
508
|
+
// Validate type
|
|
509
|
+
const validTypes = ['success', 'error', 'info', 'warning', 'dark', 'light'];
|
|
510
|
+
if (!validTypes.includes(type)) {
|
|
511
|
+
console.warn(`ToastifyPro: Invalid type "${type}". Using "dark".`);
|
|
512
|
+
type = 'dark';
|
|
513
|
+
}
|
|
112
514
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
closeBtn.onclick = () => this.removeToast(toast);
|
|
118
|
-
toast.appendChild(closeBtn);
|
|
515
|
+
// Validate and merge options
|
|
516
|
+
if (typeof opts !== 'object' || opts === null) {
|
|
517
|
+
console.warn('ToastifyPro: Invalid options parameter. Using defaults.');
|
|
518
|
+
opts = {};
|
|
119
519
|
}
|
|
120
520
|
|
|
121
|
-
this.
|
|
521
|
+
const options = { ...this.defaultOptions, ...opts };
|
|
522
|
+
|
|
523
|
+
try {
|
|
524
|
+
// Create toast element
|
|
525
|
+
const toast = document.createElement("div");
|
|
526
|
+
toast.className = `toastify-pro ${type}`;
|
|
527
|
+
|
|
528
|
+
// Set duration for progress bar animation
|
|
529
|
+
if (options.timeout > 0) {
|
|
530
|
+
toast.style.setProperty('--duration', `${options.timeout}ms`);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// Create icon wrapper
|
|
534
|
+
const iconWrapper = document.createElement("div");
|
|
535
|
+
iconWrapper.className = "toast-icon";
|
|
536
|
+
iconWrapper.innerHTML = this.getIconSVG(type);
|
|
537
|
+
toast.appendChild(iconWrapper);
|
|
122
538
|
|
|
123
|
-
|
|
124
|
-
|
|
539
|
+
// Create content wrapper for the message and description
|
|
540
|
+
const contentWrapper = document.createElement("div");
|
|
541
|
+
contentWrapper.className = "toast-content";
|
|
542
|
+
|
|
543
|
+
// Main message
|
|
544
|
+
const messageElement = document.createElement("div");
|
|
545
|
+
messageElement.className = "toast-message";
|
|
546
|
+
messageElement.textContent = message.substring(0, options.maxLength);
|
|
547
|
+
contentWrapper.appendChild(messageElement);
|
|
548
|
+
|
|
549
|
+
// Optional description (if provided)
|
|
550
|
+
if (options.description && typeof options.description === 'string') {
|
|
551
|
+
const descriptionElement = document.createElement("div");
|
|
552
|
+
descriptionElement.className = "toast-description";
|
|
553
|
+
descriptionElement.textContent = options.description.substring(0, options.maxLength * 2);
|
|
554
|
+
contentWrapper.appendChild(descriptionElement);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
toast.appendChild(contentWrapper);
|
|
125
558
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
559
|
+
// Add close button if enabled
|
|
560
|
+
if (options.allowClose) {
|
|
561
|
+
const closeBtn = document.createElement("span");
|
|
562
|
+
closeBtn.className = "close-btn";
|
|
563
|
+
closeBtn.innerHTML = "×";
|
|
564
|
+
closeBtn.setAttribute('aria-label', 'Close notification');
|
|
565
|
+
closeBtn.onclick = () => this.removeToast(toast);
|
|
566
|
+
toast.appendChild(closeBtn);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
// Add toast to container
|
|
570
|
+
this.container.appendChild(toast);
|
|
571
|
+
|
|
572
|
+
// Apple AirDrop-style entrance animation
|
|
573
|
+
setTimeout(() => {
|
|
574
|
+
toast.classList.add("show");
|
|
575
|
+
// Add icon bounce effect with Apple-style timing
|
|
576
|
+
const icon = toast.querySelector('.toast-icon');
|
|
577
|
+
if (icon) {
|
|
578
|
+
icon.style.animation = 'iconBounce 0.8s cubic-bezier(0.175, 0.885, 0.32, 1.275)';
|
|
579
|
+
}
|
|
580
|
+
}, 10);
|
|
581
|
+
|
|
582
|
+
// Auto-remove after timeout
|
|
583
|
+
if (options.timeout > 0) {
|
|
584
|
+
setTimeout(() => this.removeToast(toast), options.timeout);
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
return toast; // Return element for potential future manipulation
|
|
588
|
+
} catch (error) {
|
|
589
|
+
console.error('ToastifyPro: Failed to create toast:', error);
|
|
129
590
|
}
|
|
130
591
|
}
|
|
131
592
|
|
|
593
|
+
/**
|
|
594
|
+
* Removes a toast with position-aware car swipe animation
|
|
595
|
+
* @param {HTMLElement} toast - Toast element to remove
|
|
596
|
+
*/
|
|
132
597
|
removeToast(toast) {
|
|
133
|
-
toast.
|
|
134
|
-
|
|
598
|
+
if (!toast || !toast.parentNode) {
|
|
599
|
+
console.warn('ToastifyPro: Invalid toast element for removal.');
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
try {
|
|
604
|
+
// Detect position to choose the right swipe direction
|
|
605
|
+
const container = toast.parentNode;
|
|
606
|
+
const position = container.className.split(' ')[1]; // get position class
|
|
607
|
+
|
|
608
|
+
let swipeAnimation = 'carSwipeBottom'; // default fallback
|
|
609
|
+
|
|
610
|
+
// Choose animation based on position - car swipes away from screen edge
|
|
611
|
+
if (position.includes('bottom')) {
|
|
612
|
+
swipeAnimation = 'carSwipeBottom'; // swipe down off screen
|
|
613
|
+
} else if (position.includes('top')) {
|
|
614
|
+
swipeAnimation = 'carSwipeTop'; // swipe up off screen
|
|
615
|
+
} else if (position.includes('left')) {
|
|
616
|
+
swipeAnimation = 'carSwipeLeft'; // swipe left off screen
|
|
617
|
+
} else if (position.includes('right')) {
|
|
618
|
+
swipeAnimation = 'carSwipeRight'; // swipe right off screen
|
|
619
|
+
} else if (position.includes('center')) {
|
|
620
|
+
swipeAnimation = 'carSwipeCenter'; // swipe down for center
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
// Apply fast car swipe animation with improved easing
|
|
624
|
+
toast.style.animation = `${swipeAnimation} 0.4s cubic-bezier(0.4, 0.0, 1, 1) forwards`;
|
|
625
|
+
|
|
626
|
+
// Add spinning icon animation for extra polish
|
|
627
|
+
const icon = toast.querySelector('.toast-icon');
|
|
628
|
+
if (icon) {
|
|
629
|
+
icon.style.animation = 'iconCarExit 0.4s cubic-bezier(0.4, 0.0, 1, 1) forwards';
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
// Remove element after animation completes
|
|
633
|
+
setTimeout(() => {
|
|
634
|
+
if (toast.parentNode) {
|
|
635
|
+
toast.remove();
|
|
636
|
+
}
|
|
637
|
+
}, 400);
|
|
638
|
+
} catch (error) {
|
|
639
|
+
console.error('ToastifyPro: Error removing toast:', error);
|
|
640
|
+
// Fallback: remove immediately if animation fails
|
|
641
|
+
if (toast.parentNode) {
|
|
642
|
+
toast.remove();
|
|
643
|
+
}
|
|
644
|
+
}
|
|
135
645
|
}
|
|
136
646
|
|
|
647
|
+
/**
|
|
648
|
+
* Shows a success toast notification
|
|
649
|
+
* @param {string} msg - Main message
|
|
650
|
+
* @param {string|Object} opts - Description string or options object
|
|
651
|
+
*/
|
|
137
652
|
success(msg, opts) {
|
|
653
|
+
// Handle both (message) and (message, description) formats
|
|
654
|
+
if (typeof opts === 'string') {
|
|
655
|
+
opts = { description: opts };
|
|
656
|
+
}
|
|
138
657
|
this.show(msg, "success", opts);
|
|
139
658
|
}
|
|
659
|
+
|
|
660
|
+
/**
|
|
661
|
+
* Shows an error toast notification
|
|
662
|
+
* @param {string} msg - Main message
|
|
663
|
+
* @param {string|Object} opts - Description string or options object
|
|
664
|
+
*/
|
|
140
665
|
error(msg, opts) {
|
|
666
|
+
if (typeof opts === 'string') {
|
|
667
|
+
opts = { description: opts };
|
|
668
|
+
}
|
|
141
669
|
this.show(msg, "error", opts);
|
|
142
670
|
}
|
|
671
|
+
|
|
672
|
+
/**
|
|
673
|
+
* Shows an info toast notification
|
|
674
|
+
* @param {string} msg - Main message
|
|
675
|
+
* @param {string|Object} opts - Description string or options object
|
|
676
|
+
*/
|
|
143
677
|
info(msg, opts) {
|
|
678
|
+
if (typeof opts === 'string') {
|
|
679
|
+
opts = { description: opts };
|
|
680
|
+
}
|
|
144
681
|
this.show(msg, "info", opts);
|
|
145
682
|
}
|
|
683
|
+
|
|
684
|
+
/**
|
|
685
|
+
* Shows a warning toast notification
|
|
686
|
+
* @param {string} msg - Main message
|
|
687
|
+
* @param {string|Object} opts - Description string or options object
|
|
688
|
+
*/
|
|
146
689
|
warning(msg, opts) {
|
|
690
|
+
if (typeof opts === 'string') {
|
|
691
|
+
opts = { description: opts };
|
|
692
|
+
}
|
|
147
693
|
this.show(msg, "warning", opts);
|
|
148
694
|
}
|
|
695
|
+
|
|
696
|
+
/**
|
|
697
|
+
* Shows a dark-themed toast notification
|
|
698
|
+
* @param {string} msg - Main message
|
|
699
|
+
* @param {string|Object} opts - Description string or options object
|
|
700
|
+
*/
|
|
149
701
|
dark(msg, opts) {
|
|
702
|
+
if (typeof opts === 'string') {
|
|
703
|
+
opts = { description: opts };
|
|
704
|
+
}
|
|
150
705
|
this.show(msg, "dark", opts);
|
|
151
706
|
}
|
|
707
|
+
|
|
708
|
+
/**
|
|
709
|
+
* Shows a light-themed toast notification
|
|
710
|
+
* @param {string} msg - Main message
|
|
711
|
+
* @param {string|Object} opts - Description string or options object
|
|
712
|
+
*/
|
|
152
713
|
light(msg, opts) {
|
|
714
|
+
if (typeof opts === 'string') {
|
|
715
|
+
opts = { description: opts };
|
|
716
|
+
}
|
|
153
717
|
this.show(msg, "light", opts);
|
|
154
718
|
}
|
|
155
719
|
}
|
|
156
720
|
|
|
157
|
-
|
|
721
|
+
/**
|
|
722
|
+
* Export for different environments
|
|
723
|
+
* Supports CommonJS (Node.js), AMD, and browser globals
|
|
724
|
+
*/
|
|
725
|
+
|
|
726
|
+
// CommonJS export (Node.js/npm)
|
|
727
|
+
if (typeof module !== 'undefined' && module.exports) {
|
|
728
|
+
module.exports = ToastifyPro;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
// ES6 module export
|
|
732
|
+
if (typeof exports !== 'undefined') {
|
|
733
|
+
exports.ToastifyPro = ToastifyPro;
|
|
734
|
+
exports.default = ToastifyPro;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
// AMD export (RequireJS)
|
|
738
|
+
if (typeof define === 'function' && define.amd) {
|
|
739
|
+
define(function() {
|
|
740
|
+
return ToastifyPro;
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
// Browser global
|
|
745
|
+
if (typeof window !== 'undefined') {
|
|
746
|
+
window.ToastifyPro = ToastifyPro;
|
|
747
|
+
}
|