toastify-pro 1.1.0 → 1.3.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.
@@ -1,165 +1,1155 @@
1
- (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
1
+ (function (factory) {
3
2
  typeof define === 'function' && define.amd ? define(factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.ToastifyPro = factory());
5
- })(this, (function () { 'use strict';
3
+ factory();
4
+ })((function () { 'use strict';
6
5
 
6
+ /**
7
+ * ToastifyPro - Modern Toast Notification Library
8
+ * A beautiful, customizable toast notification library with glassmorphism design,
9
+ * Apple AirDrop-style animations, and car swipe exit effects.
10
+ *
11
+ * Features:
12
+ * - Glassmorphism design with backdrop-filter effects
13
+ * - Apple AirDrop-style entrance animations
14
+ * - Position-aware car swipe exit animations
15
+ * - Description support for enhanced messaging
16
+ * - Six theme variants (success, error, info, warning, dark, light)
17
+ * - Progress bar with shimmer effects
18
+ * - Responsive design for mobile devices
19
+ * - Framework agnostic (works with React, Vue, Angular, etc.)
20
+ * - Confirmation dialogs with customizable buttons and callbacks
21
+ * - Center position support for enhanced focus
22
+ * - Independent positioning for confirmations
23
+ *
24
+ * @version 1.3.0
25
+ * @author ToastifyPro Team
26
+ * @license MIT
27
+ */
7
28
  class ToastifyPro {
29
+ /**
30
+ * Creates a new ToastifyPro instance
31
+ * @param {Object} options - Configuration options
32
+ * @param {string} options.position - Toast position (top-left, top-right, bottom-left, bottom-right, top-center, bottom-center, center)
33
+ * @param {number} options.timeout - Auto-dismiss timeout in milliseconds (0 to disable)
34
+ * @param {boolean} options.allowClose - Whether to show close button
35
+ * @param {number} options.maxLength - Maximum message length
36
+ */
8
37
  constructor(options = {}) {
38
+ // Validate options parameter
39
+ if (typeof options !== 'object' || options === null) {
40
+ console.warn('ToastifyPro: Invalid options parameter. Using defaults.');
41
+ options = {};
42
+ }
43
+
44
+ // Merge with default options
9
45
  this.defaultOptions = {
10
- position: options.position || "bottom-center", // top-left, top-right, bottom-left, bottom-right, top-center, bottom-center
46
+ position: options.position || "bottom-center", // top-left, top-right, bottom-left, bottom-right, top-center, bottom-center, center
11
47
  timeout: options.timeout || 3000,
12
48
  allowClose: options.allowClose !== false, // default true
13
49
  maxLength: options.maxLength || 100,
14
50
  };
15
51
 
16
- // create container only once
52
+ // Validate position
53
+ const validPositions = ['top-left', 'top-right', 'bottom-left', 'bottom-right', 'top-center', 'bottom-center', 'center'];
54
+ if (!validPositions.includes(this.defaultOptions.position)) {
55
+ console.warn(`ToastifyPro: Invalid position "${this.defaultOptions.position}". Using "bottom-center".`);
56
+ this.defaultOptions.position = "bottom-center";
57
+ }
58
+
59
+ // Check if we're in a browser environment
60
+ if (typeof document === 'undefined') {
61
+ throw new Error('ToastifyPro: This library requires a DOM environment (browser).');
62
+ }
63
+
64
+ // Create or reuse container for this position
17
65
  const existing = document.querySelector(
18
66
  `.toastify-pro-container.${this.defaultOptions.position}`
19
67
  );
68
+
20
69
  if (existing) {
21
70
  this.container = existing;
22
71
  } else {
23
- this.container = document.createElement("div");
24
- this.container.className = `toastify-pro-container ${this.defaultOptions.position}`;
25
- document.body.appendChild(this.container);
72
+ try {
73
+ this.container = document.createElement("div");
74
+ this.container.className = `toastify-pro-container ${this.defaultOptions.position}`;
75
+ document.body.appendChild(this.container);
76
+ } catch (error) {
77
+ throw new Error('ToastifyPro: Failed to create container element. DOM may not be ready.');
78
+ }
26
79
  }
27
80
 
81
+ // Inject styles once
28
82
  this.injectStyles();
29
83
  }
30
84
 
85
+ /**
86
+ * Returns the SVG icon for a given toast type
87
+ * @param {string} type - Toast type (success, error, info, warning, dark, light)
88
+ * @returns {string} SVG icon markup
89
+ */
90
+ getIconSVG(type) {
91
+ // Validate type parameter
92
+ if (typeof type !== 'string') {
93
+ console.warn('ToastifyPro: Invalid icon type. Using default info icon.');
94
+ type = 'info';
95
+ }
96
+
97
+ const icons = {
98
+ success: `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
99
+ <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"/>
100
+ </svg>`,
101
+ error: `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
102
+ <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"/>
103
+ </svg>`,
104
+ info: `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
105
+ <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"/>
106
+ </svg>`,
107
+ warning: `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
108
+ <path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z" fill="currentColor"/>
109
+ </svg>`,
110
+ dark: `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
111
+ <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"/>
112
+ </svg>`,
113
+ light: `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
114
+ <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"/>
115
+ </svg>`
116
+ };
117
+
118
+ return icons[type] || icons.info;
119
+ }
120
+
121
+ /**
122
+ * Injects the CSS styles into the document head
123
+ * Styles include glassmorphism design, animations, and responsive layout
124
+ */
31
125
  injectStyles() {
32
- if (document.getElementById("toastify-pro-styles")) return; // load once
33
- const style = document.createElement("style");
34
- style.id = "toastify-pro-styles";
35
- style.textContent = `
126
+ // Prevent duplicate style injection
127
+ if (document.getElementById("toastify-pro-styles")) return;
128
+
129
+ try {
130
+ const style = document.createElement("style");
131
+ style.id = "toastify-pro-styles";
132
+ style.textContent = `
133
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap');
134
+
36
135
  .toastify-pro-container {
37
136
  position: fixed;
38
137
  z-index: 9999;
39
138
  display: flex;
40
139
  flex-direction: column;
41
- gap: 10px;
140
+ gap: 16px;
42
141
  pointer-events: none;
43
142
  }
44
- .toastify-pro-container.top-left { top: 20px; left: 20px; align-items: flex-start; }
45
- .toastify-pro-container.top-right { top: 20px; right: 20px; align-items: flex-end; }
46
- .toastify-pro-container.bottom-left { bottom: 20px; left: 20px; align-items: flex-start; }
47
- .toastify-pro-container.bottom-right { bottom: 20px; right: 20px; align-items: flex-end; }
48
- .toastify-pro-container.top-center { top: 20px; left: 50%; transform: translateX(-50%); }
49
- .toastify-pro-container.bottom-center { bottom: 150px; left: 50%; transform: translateX(-50%); }
143
+ .toastify-pro-container.top-left { top: 50px; left: 24px; align-items: flex-start; }
144
+ .toastify-pro-container.top-right { top: 50px; right: 24px; align-items: flex-end; }
145
+ .toastify-pro-container.bottom-left { bottom: 50px; left: 24px; align-items: flex-start; }
146
+ .toastify-pro-container.bottom-right { bottom: 50px; right: 24px; align-items: flex-end; }
147
+ .toastify-pro-container.top-center { top: 50px; left: 50%; transform: translateX(-50%); }
148
+ .toastify-pro-container.bottom-center { bottom: 50px; left: 50%; transform: translateX(-50%); }
149
+ .toastify-pro-container.center { top: 50%; left: 50%; transform: translate(-50%, -50%); }
50
150
 
51
151
  .toastify-pro {
52
- min-width: 220px;
53
- max-width: 320px;
54
- padding: 12px 18px;
55
- border-radius: 20px;
56
- font-size: 14px;
57
- font-family: sans-serif;
152
+ min-width: 280px;
153
+ max-width: 400px;
154
+ padding: 20px 24px;
155
+ border-radius: 16px;
156
+ font-size: 15px;
157
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
158
+ font-weight: 500;
58
159
  color: white;
59
160
  opacity: 0;
60
- transform: translateY(20px);
61
- transition: all 0.3s ease;
161
+ transform: scale(0.3);
162
+ transition: all 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);
62
163
  pointer-events: auto;
63
164
  position: relative;
64
165
  display: flex;
65
166
  align-items: center;
66
- justify-content: space-between;
67
- gap: 12px;
167
+ gap: 16px;
168
+ backdrop-filter: blur(20px);
169
+ border: 1px solid rgba(255, 255, 255, 0.1);
170
+ box-shadow:
171
+ 0 20px 25px -5px rgba(0, 0, 0, 0.1),
172
+ 0 10px 10px -5px rgba(0, 0, 0, 0.04),
173
+ 0 0 0 1px rgba(255, 255, 255, 0.05);
174
+ overflow: hidden;
175
+ }
176
+
177
+ .toastify-pro::before {
178
+ content: '';
179
+ position: absolute;
180
+ top: 0;
181
+ left: 0;
182
+ right: 0;
183
+ height: 3px;
184
+ background: linear-gradient(90deg,
185
+ rgba(255, 255, 255, 0.8) 0%,
186
+ rgba(255, 255, 255, 0.4) 50%,
187
+ rgba(255, 255, 255, 0.8) 100%);
188
+ animation: shimmer 2s infinite;
189
+ transition: opacity 0.8s ease;
190
+ }
191
+
192
+ .toastify-pro::after {
193
+ content: '';
194
+ position: absolute;
195
+ bottom: 0;
196
+ left: 0;
197
+ height: 3px;
198
+ background: rgba(255, 255, 255, 0.6);
199
+ animation: progress var(--duration, 5s) linear;
200
+ border-radius: 0 0 16px 16px;
201
+ }
202
+
203
+ @keyframes airdropPop {
204
+ 0% {
205
+ opacity: 0;
206
+ transform: scale(0.3) rotateY(-20deg);
207
+ }
208
+ 30% {
209
+ opacity: 0.8;
210
+ transform: scale(1.1) rotateY(10deg);
211
+ }
212
+ 60% {
213
+ opacity: 1;
214
+ transform: scale(0.98) rotateY(-3deg);
215
+ }
216
+ 100% {
217
+ opacity: 1;
218
+ transform: scale(1) rotateY(0deg);
219
+ }
220
+ }
221
+
222
+ @keyframes carSwipeBottom {
223
+ 0% {
224
+ opacity: 1;
225
+ transform: scale(1) translateY(0);
226
+ }
227
+ 15% {
228
+ opacity: 1;
229
+ transform: scale(1.02) translateY(-8px);
230
+ }
231
+ 100% {
232
+ opacity: 0;
233
+ transform: scale(0.8) translateY(200px);
234
+ }
235
+ }
236
+
237
+ @keyframes carSwipeTop {
238
+ 0% {
239
+ opacity: 1;
240
+ transform: scale(1) translateY(0);
241
+ }
242
+ 15% {
243
+ opacity: 1;
244
+ transform: scale(1.02) translateY(8px);
245
+ }
246
+ 100% {
247
+ opacity: 0;
248
+ transform: scale(0.8) translateY(-200px);
249
+ }
250
+ }
251
+
252
+ @keyframes carSwipeLeft {
253
+ 0% {
254
+ opacity: 1;
255
+ transform: scale(1) translateX(0);
256
+ }
257
+ 15% {
258
+ opacity: 1;
259
+ transform: scale(1.02) translateX(8px);
260
+ }
261
+ 100% {
262
+ opacity: 0;
263
+ transform: scale(0.8) translateX(-300px);
264
+ }
265
+ }
266
+
267
+ @keyframes carSwipeRight {
268
+ 0% {
269
+ opacity: 1;
270
+ transform: scale(1) translateX(0);
271
+ }
272
+ 15% {
273
+ opacity: 1;
274
+ transform: scale(1.02) translateX(-8px);
275
+ }
276
+ 100% {
277
+ opacity: 0;
278
+ transform: scale(0.8) translateX(300px);
279
+ }
280
+ }
281
+
282
+ @keyframes carSwipeCenter {
283
+ 0% {
284
+ opacity: 1;
285
+ transform: scale(1) translateY(0);
286
+ }
287
+ 15% {
288
+ opacity: 1;
289
+ transform: scale(1.02) translateY(-5px);
290
+ }
291
+ 100% {
292
+ opacity: 0;
293
+ transform: scale(0.6) translateY(150px);
294
+ }
295
+ }
296
+
297
+ @keyframes progress {
298
+ 0% { width: 100%; }
299
+ 100% { width: 0%; }
300
+ }
301
+
302
+ @keyframes shimmer {
303
+ 0% { transform: translateX(-100%); }
304
+ 100% { transform: translateX(100%); }
305
+ }
306
+
307
+ .toastify-pro.show {
308
+ opacity: 1;
309
+ transform: scale(1);
310
+ animation: airdropPop 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);
311
+ }
312
+
313
+ .toastify-pro.success {
314
+ background: linear-gradient(135deg,
315
+ rgba(34, 197, 94, 0.9) 0%,
316
+ rgba(21, 128, 61, 0.9) 100%);
317
+ border-color: rgba(34, 197, 94, 0.3);
318
+ }
319
+
320
+ .toastify-pro.error {
321
+ background: linear-gradient(135deg,
322
+ rgba(239, 68, 68, 0.9) 0%,
323
+ rgba(185, 28, 28, 0.9) 100%);
324
+ border-color: rgba(239, 68, 68, 0.3);
325
+ }
326
+
327
+ .toastify-pro.info {
328
+ background: linear-gradient(135deg,
329
+ rgba(59, 130, 246, 0.9) 0%,
330
+ rgba(29, 78, 216, 0.9) 100%);
331
+ border-color: rgba(59, 130, 246, 0.3);
332
+ }
333
+
334
+ .toastify-pro.warning {
335
+ background: linear-gradient(135deg,
336
+ rgba(245, 158, 11, 0.9) 0%,
337
+ rgba(217, 119, 6, 0.9) 100%);
338
+ border-color: rgba(245, 158, 11, 0.3);
339
+ }
340
+
341
+ .toastify-pro.dark {
342
+ background: linear-gradient(135deg,
343
+ rgba(15, 23, 42, 0.95) 0%,
344
+ rgba(30, 41, 59, 0.95) 100%);
345
+ border-color: rgba(148, 163, 184, 0.2);
346
+ }
347
+
348
+ .toastify-pro.light {
349
+ background: linear-gradient(135deg,
350
+ rgba(255, 255, 255, 0.95) 0%,
351
+ rgba(248, 250, 252, 0.95) 100%);
352
+ color: #1e293b;
353
+ border-color: rgba(226, 232, 240, 0.8);
354
+ box-shadow:
355
+ 0 20px 25px -5px rgba(0, 0, 0, 0.08),
356
+ 0 10px 10px -5px rgba(0, 0, 0, 0.03);
357
+ }
358
+
359
+ .toastify-pro.light::before {
360
+ background: linear-gradient(90deg,
361
+ rgba(30, 41, 59, 0.8) 0%,
362
+ rgba(30, 41, 59, 0.4) 50%,
363
+ rgba(30, 41, 59, 0.8) 100%);
364
+ }
365
+
366
+ .toastify-pro.light::after {
367
+ background: rgba(30, 41, 59, 0.6);
368
+ }
369
+
370
+ .toastify-pro .toast-icon {
371
+ flex-shrink: 0;
372
+ display: flex;
373
+ align-items: center;
374
+ justify-content: center;
375
+ width: 28px;
376
+ height: 28px;
377
+ border-radius: 50%;
378
+ background: rgba(255, 255, 255, 0.2);
379
+ backdrop-filter: blur(10px);
380
+ animation: iconPulse 2s infinite;
381
+ }
382
+
383
+ @keyframes iconPulse {
384
+ 0%, 100% { transform: scale(1); }
385
+ 50% { transform: scale(1.05); }
386
+ }
387
+
388
+ @keyframes iconBounce {
389
+ 0% { transform: scale(0.2) rotate(-15deg); }
390
+ 40% { transform: scale(1.2) rotate(8deg); }
391
+ 70% { transform: scale(0.95) rotate(-3deg); }
392
+ 100% { transform: scale(1) rotate(0deg); }
393
+ }
394
+
395
+ @keyframes iconCarExit {
396
+ 0% {
397
+ transform: scale(1) rotate(0deg);
398
+ opacity: 1;
399
+ }
400
+ 20% {
401
+ transform: scale(1.1) rotate(-10deg);
402
+ opacity: 0.9;
403
+ }
404
+ 100% {
405
+ transform: scale(0.3) rotate(180deg);
406
+ opacity: 0;
407
+ }
408
+ }
409
+
410
+ .toastify-pro .toast-icon svg {
411
+ width: 18px;
412
+ height: 18px;
413
+ color: inherit;
414
+ filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1));
415
+ }
416
+
417
+ .toastify-pro.light .toast-icon {
418
+ background: rgba(15, 23, 42, 0.1);
68
419
  }
69
- .toastify-pro.show { opacity: 1; transform: translateY(0); }
70
- .toastify-pro.success { background: rgba(76, 175, 80, 0.9); }
71
- .toastify-pro.error { background: rgba(244, 67, 54, 0.9); }
72
- .toastify-pro.info { background: rgba(33, 150, 243, 0.9); }
73
- .toastify-pro.warning { background: rgba(255, 152, 0, 0.9); }
74
- .toastify-pro.dark { background: rgba(0,0,0,0.85); }
75
- .toastify-pro.light { background: rgba(255,255,255,0.9); color: #000; }
76
420
 
77
421
  .toastify-pro .toast-content {
78
422
  flex: 1;
79
- padding-right: 8px;
423
+ line-height: 1.5;
424
+ font-weight: 500;
425
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
426
+ }
427
+
428
+ .toastify-pro .toast-message {
429
+ font-size: 15px;
430
+ font-weight: 500;
431
+ margin-bottom: 0;
432
+ }
433
+
434
+ .toastify-pro .toast-description {
435
+ font-size: 13px;
436
+ font-weight: 400;
437
+ opacity: 0.85;
438
+ margin-top: 4px;
80
439
  line-height: 1.4;
81
440
  }
82
441
 
83
442
  .toastify-pro .close-btn {
84
443
  cursor: pointer;
85
- font-size: 18px;
444
+ font-size: 20px;
86
445
  color: inherit;
87
- opacity: 0.8;
88
- padding: 2px 4px;
89
- border-radius: 3px;
90
- transition: opacity 0.2s ease, background-color 0.2s ease;
446
+ opacity: 0.7;
447
+ padding: 8px;
448
+ border-radius: 50%;
449
+ transition: all 0.2s ease;
91
450
  flex-shrink: 0;
92
- min-width: 20px;
93
- text-align: center;
451
+ width: 32px;
452
+ height: 32px;
453
+ display: flex;
454
+ align-items: center;
455
+ justify-content: center;
456
+ background: rgba(255, 255, 255, 0.1);
457
+ backdrop-filter: blur(10px);
458
+ font-weight: 300;
94
459
  line-height: 1;
95
460
  }
461
+
96
462
  .toastify-pro .close-btn:hover {
97
463
  opacity: 1;
98
- background-color: rgba(0,0,0,0.1);
464
+ background: rgba(255, 255, 255, 0.2);
465
+ transform: scale(1.1);
466
+ }
467
+
468
+ .toastify-pro.light .close-btn {
469
+ background: rgba(15, 23, 42, 0.08);
99
470
  }
471
+
100
472
  .toastify-pro.light .close-btn:hover {
101
- background-color: rgba(0,0,0,0.05);
473
+ background: rgba(15, 23, 42, 0.15);
474
+ }
475
+
476
+ @media (max-width: 640px) {
477
+ .toastify-pro {
478
+ min-width: 260px;
479
+ max-width: calc(100vw - 48px);
480
+ margin: 0 8px;
481
+ }
482
+
483
+ .toastify-pro-container.top-left,
484
+ .toastify-pro-container.bottom-left { left: 16px; }
485
+ .toastify-pro-container.top-right,
486
+ .toastify-pro-container.bottom-right { right: 16px; }
487
+ }
488
+
489
+ /* Confirmation Toast Styles */
490
+ .toastify-pro.confirmation {
491
+ min-width: 320px;
492
+ max-width: 450px;
493
+ padding: 24px;
494
+ flex-direction: column;
495
+ align-items: stretch;
496
+ gap: 20px;
497
+ position: relative;
498
+ }
499
+
500
+ /* Hide progress bar for confirmation toasts */
501
+ .toastify-pro.confirmation::after {
502
+ display: none;
503
+ }
504
+
505
+ /* Close button for confirmation dialogs */
506
+ .toastify-pro.confirmation .conf-close-btn {
507
+ position: absolute;
508
+ top: 12px;
509
+ right: 12px;
510
+ cursor: pointer;
511
+ font-size: 18px;
512
+ color: inherit;
513
+ opacity: 0.6;
514
+ padding: 4px;
515
+ border-radius: 50%;
516
+ transition: all 0.2s ease;
517
+ width: 24px;
518
+ height: 24px;
519
+ display: flex;
520
+ align-items: center;
521
+ justify-content: center;
522
+ background: rgba(255, 255, 255, 0.1);
523
+ backdrop-filter: blur(10px);
524
+ font-weight: 300;
525
+ line-height: 1;
526
+ border: 1px solid rgba(255, 255, 255, 0.1);
527
+ }
528
+
529
+ .toastify-pro.confirmation .conf-close-btn:hover {
530
+ opacity: 1;
531
+ background: rgba(255, 255, 255, 0.2);
532
+ transform: scale(1.1);
533
+ border-color: rgba(255, 255, 255, 0.2);
534
+ }
535
+
536
+ .toastify-pro.confirmation.light .conf-close-btn {
537
+ background: rgba(15, 23, 42, 0.08);
538
+ border-color: rgba(15, 23, 42, 0.1);
539
+ }
540
+
541
+ .toastify-pro.confirmation.light .conf-close-btn:hover {
542
+ background: rgba(15, 23, 42, 0.15);
543
+ border-color: rgba(15, 23, 42, 0.2);
544
+ }
545
+
546
+ .toastify-pro.confirmation .toast-content {
547
+ text-align: center;
548
+ margin-bottom: 8px;
549
+ }
550
+
551
+ .toastify-pro.confirmation .toast-message {
552
+ font-weight: 600;
553
+ font-size: 16px;
554
+ margin-bottom: 6px;
555
+ }
556
+
557
+ .toastify-pro.confirmation .toast-description {
558
+ font-size: 14px;
559
+ opacity: 0.9;
560
+ margin-top: 6px;
561
+ }
562
+
563
+ /* Fix text visibility for dark/light variants */
564
+ .toastify-pro.confirmation.dark .toast-message,
565
+ .toastify-pro.confirmation.dark .toast-description {
566
+ color: white;
567
+ }
568
+
569
+ .toastify-pro.confirmation.light .toast-message,
570
+ .toastify-pro.confirmation.light .toast-description {
571
+ color: #1e293b;
572
+ }
573
+
574
+ .toast-actions {
575
+ display: flex;
576
+ gap: 12px;
577
+ margin-top: 8px;
578
+ }
579
+
580
+ .toast-btn {
581
+ flex: 1;
582
+ padding: 10px 16px;
583
+ border: none;
584
+ border-radius: 8px;
585
+ font-weight: 600;
586
+ font-size: 14px;
587
+ cursor: pointer;
588
+ transition: all 0.2s ease;
589
+ backdrop-filter: blur(10px);
590
+ border: 1px solid rgba(255, 255, 255, 0.2);
591
+ }
592
+
593
+ .toast-btn:hover {
594
+ transform: translateY(-1px);
595
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
596
+ }
597
+
598
+ .toast-btn:active {
599
+ transform: translateY(0);
600
+ }
601
+
602
+ .toast-btn-cancel {
603
+ background: rgba(255, 255, 255, 0.1);
604
+ color: rgba(255, 255, 255, 0.8);
605
+ border: 1px solid rgba(255, 255, 255, 0.3);
606
+ font-weight: 500;
607
+ }
608
+
609
+ .toast-btn-cancel:hover {
610
+ background: rgba(255, 255, 255, 0.15);
611
+ color: rgba(255, 255, 255, 0.9);
612
+ border-color: rgba(255, 255, 255, 0.4);
613
+ }
614
+
615
+ .toast-btn-confirm {
616
+ color: white;
617
+ font-weight: 700;
618
+ border: 2px solid rgba(255, 255, 255, 0.3);
619
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
620
+ position: relative;
621
+ overflow: hidden;
622
+ background: linear-gradient(135deg, rgba(15, 23, 42, 0.9), rgba(30, 41, 59, 0.9));
623
+ border-color: rgba(148, 163, 184, 0.5);
624
+ }
625
+
626
+ .toast-btn-confirm::before {
627
+ content: '';
628
+ position: absolute;
629
+ top: 0;
630
+ left: -100%;
631
+ width: 100%;
632
+ height: 100%;
633
+ background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
634
+ transition: left 0.5s;
635
+ }
636
+
637
+ .toast-btn-confirm:hover::before {
638
+ left: 100%;
639
+ }
640
+
641
+ .toast-btn-confirm:hover {
642
+ background: linear-gradient(135deg, rgba(15, 23, 42, 1), rgba(30, 41, 59, 1));
643
+ border-color: rgba(148, 163, 184, 0.7);
644
+ box-shadow: 0 6px 20px rgba(15, 23, 42, 0.4);
645
+ }
646
+
647
+ .toastify-pro.light .toast-btn-cancel {
648
+ background: rgba(15, 23, 42, 0.08);
649
+ color: rgba(15, 23, 42, 0.8);
650
+ border-color: rgba(15, 23, 42, 0.2);
651
+ }
652
+
653
+ .toastify-pro.light .toast-btn-cancel:hover {
654
+ background: rgba(15, 23, 42, 0.12);
655
+ color: rgba(15, 23, 42, 1);
656
+ border-color: rgba(15, 23, 42, 0.3);
657
+ }
658
+
659
+ /* Enhanced light theme confirm buttons */
660
+ .toastify-pro.light .toast-btn-confirm {
661
+ border-color: rgba(15, 23, 42, 0.3);
662
+ background: linear-gradient(135deg, rgba(255, 255, 255, 0.9), rgba(248, 250, 252, 0.9));
663
+ color: #1e293b;
664
+ }
665
+
666
+ .toastify-pro.light .toast-btn-confirm:hover {
667
+ background: linear-gradient(135deg, rgba(255, 255, 255, 1), rgba(248, 250, 252, 1));
668
+ border-color: rgba(15, 23, 42, 0.4);
669
+ box-shadow: 0 6px 20px rgba(15, 23, 42, 0.2);
670
+ }
671
+
672
+ @media (max-width: 640px) {
673
+ .toastify-pro.confirmation {
674
+ min-width: 280px;
675
+ max-width: calc(100vw - 32px);
676
+ }
102
677
  }
103
678
  `;
104
- document.head.appendChild(style);
679
+ document.head.appendChild(style);
680
+ } catch (error) {
681
+ console.error('ToastifyPro: Failed to inject styles:', error);
682
+ }
105
683
  }
106
684
 
685
+ /**
686
+ * Creates and displays a toast notification
687
+ * @param {string} message - Main message text
688
+ * @param {string} type - Toast type (success, error, info, warning, dark, light)
689
+ * @param {Object} opts - Additional options
690
+ * @param {string} opts.description - Optional description text
691
+ * @param {number} opts.timeout - Override default timeout
692
+ * @param {boolean} opts.allowClose - Override close button setting
693
+ * @param {number} opts.maxLength - Override max message length
694
+ */
107
695
  show(message, type = "dark", opts = {}) {
108
- const options = { ...this.defaultOptions, ...opts };
696
+ // Input validation
697
+ if (typeof message !== 'string') {
698
+ console.warn('ToastifyPro: Message must be a string. Converting to string.');
699
+ message = String(message);
700
+ }
109
701
 
110
- const toast = document.createElement("div");
111
- toast.className = `toastify-pro ${type}`;
702
+ if (!message.trim()) {
703
+ console.warn('ToastifyPro: Empty message provided.');
704
+ return;
705
+ }
112
706
 
113
- // Create content wrapper for the message
114
- const contentWrapper = document.createElement("div");
115
- contentWrapper.className = "toast-content";
116
- contentWrapper.textContent = message.substring(0, options.maxLength);
117
- toast.appendChild(contentWrapper);
707
+ // Validate type
708
+ const validTypes = ['success', 'error', 'info', 'warning', 'dark', 'light'];
709
+ if (!validTypes.includes(type)) {
710
+ console.warn(`ToastifyPro: Invalid type "${type}". Using "dark".`);
711
+ type = 'dark';
712
+ }
118
713
 
119
- if (options.allowClose) {
120
- const closeBtn = document.createElement("span");
121
- closeBtn.className = "close-btn";
122
- closeBtn.innerHTML = "&times;";
123
- closeBtn.onclick = () => this.removeToast(toast);
124
- toast.appendChild(closeBtn);
714
+ // Validate and merge options
715
+ if (typeof opts !== 'object' || opts === null) {
716
+ console.warn('ToastifyPro: Invalid options parameter. Using defaults.');
717
+ opts = {};
125
718
  }
126
719
 
127
- this.container.appendChild(toast);
720
+ const options = { ...this.defaultOptions, ...opts };
721
+
722
+ try {
723
+ // Create toast element
724
+ const toast = document.createElement("div");
725
+ toast.className = `toastify-pro ${type}`;
726
+
727
+ // Set duration for progress bar animation
728
+ if (options.timeout > 0) {
729
+ toast.style.setProperty('--duration', `${options.timeout}ms`);
730
+ }
731
+
732
+ // Create icon wrapper
733
+ const iconWrapper = document.createElement("div");
734
+ iconWrapper.className = "toast-icon";
735
+ iconWrapper.innerHTML = this.getIconSVG(type);
736
+ toast.appendChild(iconWrapper);
737
+
738
+ // Create content wrapper for the message and description
739
+ const contentWrapper = document.createElement("div");
740
+ contentWrapper.className = "toast-content";
741
+
742
+ // Main message
743
+ const messageElement = document.createElement("div");
744
+ messageElement.className = "toast-message";
745
+ messageElement.textContent = message.substring(0, options.maxLength);
746
+ contentWrapper.appendChild(messageElement);
747
+
748
+ // Optional description (if provided)
749
+ if (options.description && typeof options.description === 'string') {
750
+ const descriptionElement = document.createElement("div");
751
+ descriptionElement.className = "toast-description";
752
+ descriptionElement.textContent = options.description.substring(0, options.maxLength * 2);
753
+ contentWrapper.appendChild(descriptionElement);
754
+ }
755
+
756
+ toast.appendChild(contentWrapper);
757
+
758
+ // Add close button if enabled
759
+ if (options.allowClose) {
760
+ const closeBtn = document.createElement("span");
761
+ closeBtn.className = "close-btn";
762
+ closeBtn.innerHTML = "&times;";
763
+ closeBtn.setAttribute('aria-label', 'Close notification');
764
+ closeBtn.onclick = () => this.removeToast(toast);
765
+ toast.appendChild(closeBtn);
766
+ }
767
+
768
+ // Add toast to container
769
+ this.container.appendChild(toast);
128
770
 
129
- // show animation
130
- setTimeout(() => toast.classList.add("show"), 50);
771
+ // Apple AirDrop-style entrance animation
772
+ setTimeout(() => {
773
+ toast.classList.add("show");
774
+ // Add icon bounce effect with Apple-style timing
775
+ const icon = toast.querySelector('.toast-icon');
776
+ if (icon) {
777
+ icon.style.animation = 'iconBounce 0.8s cubic-bezier(0.175, 0.885, 0.32, 1.275)';
778
+ }
779
+ }, 10);
131
780
 
132
- // auto remove
133
- if (options.timeout > 0) {
134
- setTimeout(() => this.removeToast(toast), options.timeout);
781
+ // Auto-remove after timeout
782
+ if (options.timeout > 0) {
783
+ setTimeout(() => this.removeToast(toast), options.timeout);
784
+ }
785
+
786
+ return toast; // Return element for potential future manipulation
787
+ } catch (error) {
788
+ console.error('ToastifyPro: Failed to create toast:', error);
135
789
  }
136
790
  }
137
791
 
792
+ /**
793
+ * Removes a toast with position-aware car swipe animation
794
+ * @param {HTMLElement} toast - Toast element to remove
795
+ */
138
796
  removeToast(toast) {
139
- toast.classList.remove("show");
140
- setTimeout(() => toast.remove(), 300);
797
+ if (!toast || !toast.parentNode) {
798
+ console.warn('ToastifyPro: Invalid toast element for removal.');
799
+ return;
800
+ }
801
+
802
+ try {
803
+ // Detect position to choose the right swipe direction
804
+ const container = toast.parentNode;
805
+ const position = container.className.split(' ')[1]; // get position class
806
+
807
+ let swipeAnimation = 'carSwipeBottom'; // default fallback
808
+
809
+ // Choose animation based on position - car swipes away from screen edge
810
+ if (position.includes('bottom')) {
811
+ swipeAnimation = 'carSwipeBottom'; // swipe down off screen
812
+ } else if (position.includes('top')) {
813
+ swipeAnimation = 'carSwipeTop'; // swipe up off screen
814
+ } else if (position.includes('left')) {
815
+ swipeAnimation = 'carSwipeLeft'; // swipe left off screen
816
+ } else if (position.includes('right')) {
817
+ swipeAnimation = 'carSwipeRight'; // swipe right off screen
818
+ } else if (position.includes('center')) {
819
+ swipeAnimation = 'carSwipeCenter'; // swipe down for center
820
+ }
821
+
822
+ // Apply fast car swipe animation with improved easing
823
+ toast.style.animation = `${swipeAnimation} 0.4s cubic-bezier(0.4, 0.0, 1, 1) forwards`;
824
+
825
+ // Add spinning icon animation for extra polish
826
+ const icon = toast.querySelector('.toast-icon');
827
+ if (icon) {
828
+ icon.style.animation = 'iconCarExit 0.4s cubic-bezier(0.4, 0.0, 1, 1) forwards';
829
+ }
830
+
831
+ // Remove element after animation completes
832
+ setTimeout(() => {
833
+ if (toast.parentNode) {
834
+ toast.remove();
835
+ }
836
+ }, 400);
837
+ } catch (error) {
838
+ console.error('ToastifyPro: Error removing toast:', error);
839
+ // Fallback: remove immediately if animation fails
840
+ if (toast.parentNode) {
841
+ toast.remove();
842
+ }
843
+ }
141
844
  }
142
845
 
846
+ /**
847
+ * Shows a success toast notification
848
+ * @param {string} msg - Main message
849
+ * @param {string|Object} opts - Description string or options object
850
+ */
143
851
  success(msg, opts) {
852
+ // Handle both (message) and (message, description) formats
853
+ if (typeof opts === 'string') {
854
+ opts = { description: opts };
855
+ }
144
856
  this.show(msg, "success", opts);
145
857
  }
858
+
859
+ /**
860
+ * Shows an error toast notification
861
+ * @param {string} msg - Main message
862
+ * @param {string|Object} opts - Description string or options object
863
+ */
146
864
  error(msg, opts) {
865
+ if (typeof opts === 'string') {
866
+ opts = { description: opts };
867
+ }
147
868
  this.show(msg, "error", opts);
148
869
  }
870
+
871
+ /**
872
+ * Shows an info toast notification
873
+ * @param {string} msg - Main message
874
+ * @param {string|Object} opts - Description string or options object
875
+ */
149
876
  info(msg, opts) {
877
+ if (typeof opts === 'string') {
878
+ opts = { description: opts };
879
+ }
150
880
  this.show(msg, "info", opts);
151
881
  }
882
+
883
+ /**
884
+ * Shows a warning toast notification
885
+ * @param {string} msg - Main message
886
+ * @param {string|Object} opts - Description string or options object
887
+ */
152
888
  warning(msg, opts) {
889
+ if (typeof opts === 'string') {
890
+ opts = { description: opts };
891
+ }
153
892
  this.show(msg, "warning", opts);
154
893
  }
894
+
895
+ /**
896
+ * Shows a dark-themed toast notification
897
+ * @param {string} msg - Main message
898
+ * @param {string|Object} opts - Description string or options object
899
+ */
155
900
  dark(msg, opts) {
901
+ if (typeof opts === 'string') {
902
+ opts = { description: opts };
903
+ }
156
904
  this.show(msg, "dark", opts);
157
905
  }
906
+
907
+ /**
908
+ * Shows a light-themed toast notification
909
+ * @param {string} msg - Main message
910
+ * @param {string|Object} opts - Description string or options object
911
+ */
158
912
  light(msg, opts) {
913
+ if (typeof opts === 'string') {
914
+ opts = { description: opts };
915
+ }
159
916
  this.show(msg, "light", opts);
160
917
  }
918
+
919
+ /**
920
+ * Shows a confirmation toast with confirm/cancel buttons
921
+ * @param {string} message - Main confirmation question
922
+ * @param {string|Function|Object} descriptionOrCallback - Description text, callback function, or options object
923
+ * @param {Function} callback - Callback function (if description provided)
924
+ */
925
+ conf(message, descriptionOrCallback, callback) {
926
+ // Parse arguments to support multiple usage patterns
927
+ let description = '';
928
+ let options = {};
929
+ let resultCallback = null;
930
+
931
+ // Pattern 1: conf('message', callback)
932
+ if (typeof descriptionOrCallback === 'function' && !callback) {
933
+ resultCallback = descriptionOrCallback;
934
+ }
935
+ // Pattern 2: conf('message', 'description', callback)
936
+ else if (typeof descriptionOrCallback === 'string' && typeof callback === 'function') {
937
+ description = descriptionOrCallback;
938
+ resultCallback = callback;
939
+ }
940
+ // Pattern 3: conf('message', options) with onConfirm/onCancel
941
+ else if (typeof descriptionOrCallback === 'object' && descriptionOrCallback !== null) {
942
+ options = descriptionOrCallback;
943
+ description = options.description || '';
944
+
945
+ // Use onConfirm/onCancel if provided, otherwise use callback parameter
946
+ if (options.onConfirm || options.onCancel) {
947
+ // Don't use the callback parameter if onConfirm/onCancel are provided
948
+ resultCallback = null;
949
+ } else if (typeof callback === 'function') {
950
+ resultCallback = callback;
951
+ }
952
+ }
953
+ // Pattern 4: conf('message', 'description', options) - legacy support
954
+ else if (typeof descriptionOrCallback === 'string' && typeof callback === 'object') {
955
+ description = descriptionOrCallback;
956
+ options = callback || {};
957
+ // In this case, no unified callback, rely on onConfirm/onCancel
958
+ resultCallback = null;
959
+ }
960
+
961
+ // Default options for confirmation
962
+ const confirmOptions = {
963
+ timeout: 0, // No auto-dismiss for confirmations
964
+ allowClose: false, // No close button, must choose
965
+ confirmText: options.confirmText || 'Confirm',
966
+ cancelText: options.cancelText || 'Cancel',
967
+ theme: options.theme || options.color || 'dark', // Support both theme and color for backward compatibility
968
+ position: options.position || 'center', // Default to center for confirmations
969
+ ...options
970
+ };
971
+
972
+ // Validate and set theme to only dark or light
973
+ if (confirmOptions.theme === 'light' || confirmOptions.theme === 'white') {
974
+ confirmOptions.theme = 'light';
975
+ } else {
976
+ confirmOptions.theme = 'dark'; // Default to dark for all other values
977
+ }
978
+
979
+ // Validate position for confirmation toast
980
+ const validPositions = ['top-left', 'top-right', 'bottom-left', 'bottom-right', 'top-center', 'bottom-center', 'center'];
981
+ if (!validPositions.includes(confirmOptions.position)) {
982
+ console.warn(`ToastifyPro: Invalid confirmation position "${confirmOptions.position}". Using default position.`);
983
+ confirmOptions.position = this.defaultOptions.position;
984
+ }
985
+
986
+ // Get or create container for the specified position
987
+ let confirmContainer = document.querySelector(`.toastify-pro-container.${confirmOptions.position}`);
988
+
989
+ if (!confirmContainer) {
990
+ try {
991
+ confirmContainer = document.createElement("div");
992
+ confirmContainer.className = `toastify-pro-container ${confirmOptions.position}`;
993
+ document.body.appendChild(confirmContainer);
994
+ } catch (error) {
995
+ console.warn('ToastifyPro: Failed to create confirmation container. Using default container.');
996
+ confirmContainer = this.container;
997
+ }
998
+ }
999
+
1000
+ // Helper function to handle confirmation result
1001
+ const handleConfirmation = (confirmed) => {
1002
+ if (confirmed) {
1003
+ // Call onConfirm if provided
1004
+ if (options.onConfirm && typeof options.onConfirm === 'function') {
1005
+ try {
1006
+ options.onConfirm();
1007
+ } catch (error) {
1008
+ console.error('ToastifyPro: Error in onConfirm callback:', error);
1009
+ }
1010
+ }
1011
+ // Call unified callback if provided
1012
+ if (resultCallback && typeof resultCallback === 'function') {
1013
+ try {
1014
+ resultCallback(true);
1015
+ } catch (error) {
1016
+ console.error('ToastifyPro: Error in confirmation callback:', error);
1017
+ }
1018
+ }
1019
+ } else {
1020
+ // Call onCancel if provided
1021
+ if (options.onCancel && typeof options.onCancel === 'function') {
1022
+ try {
1023
+ options.onCancel();
1024
+ } catch (error) {
1025
+ console.error('ToastifyPro: Error in onCancel callback:', error);
1026
+ }
1027
+ }
1028
+ // Call unified callback if provided
1029
+ if (resultCallback && typeof resultCallback === 'function') {
1030
+ try {
1031
+ resultCallback(false);
1032
+ } catch (error) {
1033
+ console.error('ToastifyPro: Error in confirmation callback:', error);
1034
+ }
1035
+ }
1036
+ }
1037
+ };
1038
+
1039
+ try {
1040
+ // Create confirmation toast element
1041
+ const toast = document.createElement("div");
1042
+ toast.className = `toastify-pro confirmation ${confirmOptions.theme}`;
1043
+
1044
+ // Create close button for confirmation
1045
+ const closeBtn = document.createElement("span");
1046
+ closeBtn.className = "conf-close-btn";
1047
+ closeBtn.innerHTML = "&times;";
1048
+ closeBtn.setAttribute('aria-label', 'Cancel confirmation');
1049
+ closeBtn.onclick = () => {
1050
+ handleConfirmation(false);
1051
+ this.removeToast(toast);
1052
+ };
1053
+ toast.appendChild(closeBtn);
1054
+
1055
+ // Create icon wrapper
1056
+ const iconWrapper = document.createElement("div");
1057
+ iconWrapper.className = "toast-icon";
1058
+ iconWrapper.innerHTML = this.getIconSVG('info'); // Default to info icon
1059
+ toast.appendChild(iconWrapper);
1060
+
1061
+ // Create content wrapper
1062
+ const contentWrapper = document.createElement("div");
1063
+ contentWrapper.className = "toast-content";
1064
+
1065
+ // Main message
1066
+ const messageElement = document.createElement("div");
1067
+ messageElement.className = "toast-message";
1068
+ messageElement.textContent = message.substring(0, this.defaultOptions.maxLength);
1069
+ contentWrapper.appendChild(messageElement);
1070
+
1071
+ // Optional description
1072
+ if (description) {
1073
+ const descriptionElement = document.createElement("div");
1074
+ descriptionElement.className = "toast-description";
1075
+ descriptionElement.textContent = description.substring(0, this.defaultOptions.maxLength * 2);
1076
+ contentWrapper.appendChild(descriptionElement);
1077
+ }
1078
+
1079
+ toast.appendChild(contentWrapper);
1080
+
1081
+ // Create action buttons container
1082
+ const actionsWrapper = document.createElement("div");
1083
+ actionsWrapper.className = "toast-actions";
1084
+
1085
+ // Cancel button
1086
+ const cancelBtn = document.createElement("button");
1087
+ cancelBtn.className = "toast-btn toast-btn-cancel";
1088
+ cancelBtn.textContent = confirmOptions.cancelText;
1089
+ cancelBtn.onclick = () => {
1090
+ handleConfirmation(false);
1091
+ this.removeToast(toast);
1092
+ };
1093
+
1094
+ // Confirm button
1095
+ const confirmBtn = document.createElement("button");
1096
+ confirmBtn.className = `toast-btn toast-btn-confirm`;
1097
+ confirmBtn.textContent = confirmOptions.confirmText;
1098
+ confirmBtn.onclick = () => {
1099
+ handleConfirmation(true);
1100
+ this.removeToast(toast);
1101
+ };
1102
+
1103
+ actionsWrapper.appendChild(cancelBtn);
1104
+ actionsWrapper.appendChild(confirmBtn);
1105
+ toast.appendChild(actionsWrapper);
1106
+
1107
+ // Add toast to the specified container (not default container)
1108
+ confirmContainer.appendChild(toast);
1109
+
1110
+ // Entrance animation
1111
+ setTimeout(() => {
1112
+ toast.classList.add("show");
1113
+ const icon = toast.querySelector('.toast-icon');
1114
+ if (icon) {
1115
+ icon.style.animation = 'iconBounce 0.8s cubic-bezier(0.175, 0.885, 0.32, 1.275)';
1116
+ }
1117
+ }, 10);
1118
+
1119
+ return toast;
1120
+ } catch (error) {
1121
+ console.error('ToastifyPro: Failed to create confirmation toast:', error);
1122
+ }
1123
+ }
1124
+ }
1125
+
1126
+ /**
1127
+ * Export for different environments
1128
+ * Supports CommonJS (Node.js), AMD, and browser globals
1129
+ */
1130
+
1131
+ // CommonJS export (Node.js/npm)
1132
+ if (typeof module !== 'undefined' && module.exports) {
1133
+ module.exports = ToastifyPro;
1134
+ }
1135
+
1136
+ // ES6 module export
1137
+ if (typeof exports !== 'undefined') {
1138
+ exports.ToastifyPro = ToastifyPro;
1139
+ exports.default = ToastifyPro;
1140
+ }
1141
+
1142
+ // AMD export (RequireJS)
1143
+ if (typeof define === 'function' && define.amd) {
1144
+ define(function() {
1145
+ return ToastifyPro;
1146
+ });
1147
+ }
1148
+
1149
+ // Browser global
1150
+ if (typeof window !== 'undefined') {
1151
+ window.ToastifyPro = ToastifyPro;
161
1152
  }
162
1153
 
163
- return ToastifyPro;
164
-
165
1154
  }));
1155
+ //# sourceMappingURL=toastify-pro.umd.js.map