toastify-pro 1.3.0 → 1.4.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 +115 -57
- package/dist/toastify-pro.esm.js +427 -72
- package/dist/toastify-pro.esm.js.map +1 -1
- package/dist/toastify-pro.umd.js +427 -72
- package/dist/toastify-pro.umd.js.map +1 -1
- package/dist/toastify-pro.umd.min.js +5 -2
- package/dist/toastify-pro.umd.min.js.map +1 -1
- package/package.json +2 -2
- package/src/toastify-pro.js +427 -72
package/dist/toastify-pro.umd.js
CHANGED
|
@@ -20,11 +20,18 @@
|
|
|
20
20
|
* - Confirmation dialogs with customizable buttons and callbacks
|
|
21
21
|
* - Center position support for enhanced focus
|
|
22
22
|
* - Independent positioning for confirmations
|
|
23
|
+
* - Loading states for async operations
|
|
24
|
+
* - Custom gradient colors with primaryColor/secondaryColor
|
|
25
|
+
* - Single instance mode with shake animation
|
|
23
26
|
*
|
|
24
|
-
* @version 1.
|
|
27
|
+
* @version 1.4.0
|
|
25
28
|
* @author ToastifyPro Team
|
|
26
29
|
* @license MIT
|
|
27
30
|
*/
|
|
31
|
+
|
|
32
|
+
// Global active confirmation tracker (shared across all instances)
|
|
33
|
+
let globalActiveConfirmation = null;
|
|
34
|
+
|
|
28
35
|
class ToastifyPro {
|
|
29
36
|
/**
|
|
30
37
|
* Creates a new ToastifyPro instance
|
|
@@ -304,6 +311,26 @@
|
|
|
304
311
|
100% { transform: translateX(100%); }
|
|
305
312
|
}
|
|
306
313
|
|
|
314
|
+
@keyframes shake {
|
|
315
|
+
0%, 100% { transform: translate(0, 0); }
|
|
316
|
+
10%, 30%, 50%, 70%, 90% { transform: translate(-10px, 0); }
|
|
317
|
+
20%, 40%, 60%, 80% { transform: translate(10px, 0); }
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
@keyframes shakeCenter {
|
|
321
|
+
0%, 100% { transform: scale(1) translateX(0); }
|
|
322
|
+
10%, 30%, 50%, 70%, 90% { transform: scale(1) translateX(-10px); }
|
|
323
|
+
20%, 40%, 60%, 80% { transform: scale(1) translateX(10px); }
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
.toastify-pro.shake {
|
|
327
|
+
animation: shake 0.6s cubic-bezier(0.36, 0.07, 0.19, 0.97) !important;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
.toastify-pro-container.center .toastify-pro.shake {
|
|
331
|
+
animation: shakeCenter 0.6s cubic-bezier(0.36, 0.07, 0.19, 0.97) !important;
|
|
332
|
+
}
|
|
333
|
+
|
|
307
334
|
.toastify-pro.show {
|
|
308
335
|
opacity: 1;
|
|
309
336
|
transform: scale(1);
|
|
@@ -406,6 +433,11 @@
|
|
|
406
433
|
opacity: 0;
|
|
407
434
|
}
|
|
408
435
|
}
|
|
436
|
+
|
|
437
|
+
@keyframes spin {
|
|
438
|
+
0% { transform: rotate(0deg); }
|
|
439
|
+
100% { transform: rotate(360deg); }
|
|
440
|
+
}
|
|
409
441
|
|
|
410
442
|
.toastify-pro .toast-icon svg {
|
|
411
443
|
width: 18px;
|
|
@@ -486,15 +518,23 @@
|
|
|
486
518
|
.toastify-pro-container.bottom-right { right: 16px; }
|
|
487
519
|
}
|
|
488
520
|
|
|
489
|
-
/* Confirmation Toast Styles */
|
|
521
|
+
/* Confirmation Toast Styles - Enhanced Modern Design */
|
|
490
522
|
.toastify-pro.confirmation {
|
|
491
|
-
min-width:
|
|
492
|
-
max-width:
|
|
493
|
-
padding:
|
|
523
|
+
min-width: 380px;
|
|
524
|
+
max-width: 500px;
|
|
525
|
+
padding: 32px 28px 28px;
|
|
494
526
|
flex-direction: column;
|
|
495
527
|
align-items: stretch;
|
|
496
|
-
gap:
|
|
528
|
+
gap: 24px;
|
|
497
529
|
position: relative;
|
|
530
|
+
backdrop-filter: blur(24px) saturate(180%);
|
|
531
|
+
box-shadow:
|
|
532
|
+
0 24px 48px -12px rgba(0, 0, 0, 0.25),
|
|
533
|
+
0 12px 24px -8px rgba(0, 0, 0, 0.15),
|
|
534
|
+
0 0 0 1px rgba(255, 255, 255, 0.08),
|
|
535
|
+
inset 0 1px 0 0 rgba(255, 255, 255, 0.1);
|
|
536
|
+
border: 1.5px solid rgba(255, 255, 255, 0.15);
|
|
537
|
+
border-radius: 20px;
|
|
498
538
|
}
|
|
499
539
|
|
|
500
540
|
/* Hide progress bar for confirmation toasts */
|
|
@@ -502,62 +542,94 @@
|
|
|
502
542
|
display: none;
|
|
503
543
|
}
|
|
504
544
|
|
|
545
|
+
/* Shimmer effect for confirmation toasts */
|
|
546
|
+
.toastify-pro.confirmation::before {
|
|
547
|
+
opacity: 0.5;
|
|
548
|
+
}
|
|
549
|
+
|
|
505
550
|
/* Close button for confirmation dialogs */
|
|
506
551
|
.toastify-pro.confirmation .conf-close-btn {
|
|
507
552
|
position: absolute;
|
|
508
|
-
top:
|
|
509
|
-
right:
|
|
553
|
+
top: 14px;
|
|
554
|
+
right: 14px;
|
|
510
555
|
cursor: pointer;
|
|
511
|
-
font-size:
|
|
556
|
+
font-size: 20px;
|
|
512
557
|
color: inherit;
|
|
513
|
-
opacity: 0.
|
|
514
|
-
padding:
|
|
515
|
-
border-radius:
|
|
516
|
-
transition: all 0.
|
|
517
|
-
width:
|
|
518
|
-
height:
|
|
558
|
+
opacity: 0.5;
|
|
559
|
+
padding: 6px;
|
|
560
|
+
border-radius: 8px;
|
|
561
|
+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
562
|
+
width: 32px;
|
|
563
|
+
height: 32px;
|
|
519
564
|
display: flex;
|
|
520
565
|
align-items: center;
|
|
521
566
|
justify-content: center;
|
|
522
|
-
background: rgba(255, 255, 255, 0.
|
|
567
|
+
background: rgba(255, 255, 255, 0.08);
|
|
523
568
|
backdrop-filter: blur(10px);
|
|
524
569
|
font-weight: 300;
|
|
525
570
|
line-height: 1;
|
|
526
|
-
border: 1px solid rgba(255, 255, 255, 0.
|
|
571
|
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
527
572
|
}
|
|
528
573
|
|
|
529
574
|
.toastify-pro.confirmation .conf-close-btn:hover {
|
|
530
|
-
opacity:
|
|
531
|
-
background: rgba(255, 255, 255, 0.
|
|
532
|
-
transform: scale(1.1);
|
|
533
|
-
border-color: rgba(255, 255, 255, 0.
|
|
575
|
+
opacity: 0.9;
|
|
576
|
+
background: rgba(255, 255, 255, 0.15);
|
|
577
|
+
transform: scale(1.1) rotate(90deg);
|
|
578
|
+
border-color: rgba(255, 255, 255, 0.25);
|
|
534
579
|
}
|
|
535
580
|
|
|
536
581
|
.toastify-pro.confirmation.light .conf-close-btn {
|
|
537
|
-
background: rgba(15, 23, 42, 0.
|
|
538
|
-
border-color: rgba(15, 23, 42, 0.
|
|
582
|
+
background: rgba(15, 23, 42, 0.06);
|
|
583
|
+
border-color: rgba(15, 23, 42, 0.12);
|
|
584
|
+
opacity: 0.6;
|
|
539
585
|
}
|
|
540
586
|
|
|
541
587
|
.toastify-pro.confirmation.light .conf-close-btn:hover {
|
|
542
|
-
background: rgba(15, 23, 42, 0.
|
|
588
|
+
background: rgba(15, 23, 42, 0.12);
|
|
543
589
|
border-color: rgba(15, 23, 42, 0.2);
|
|
590
|
+
opacity: 1;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
/* Icon styling for confirmation */
|
|
594
|
+
.toastify-pro.confirmation .toast-icon {
|
|
595
|
+
width: 56px;
|
|
596
|
+
height: 56px;
|
|
597
|
+
margin: 0 auto 8px;
|
|
598
|
+
background: rgba(255, 255, 255, 0.15);
|
|
599
|
+
backdrop-filter: blur(12px);
|
|
600
|
+
border: 2px solid rgba(255, 255, 255, 0.2);
|
|
601
|
+
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.15);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
.toastify-pro.confirmation .toast-icon svg {
|
|
605
|
+
width: 28px;
|
|
606
|
+
height: 28px;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
.toastify-pro.confirmation.light .toast-icon {
|
|
610
|
+
background: rgba(15, 23, 42, 0.08);
|
|
611
|
+
border-color: rgba(15, 23, 42, 0.15);
|
|
544
612
|
}
|
|
545
613
|
|
|
546
614
|
.toastify-pro.confirmation .toast-content {
|
|
547
615
|
text-align: center;
|
|
548
|
-
margin-bottom:
|
|
616
|
+
margin-bottom: 4px;
|
|
549
617
|
}
|
|
550
618
|
|
|
551
619
|
.toastify-pro.confirmation .toast-message {
|
|
552
|
-
font-weight:
|
|
553
|
-
font-size:
|
|
554
|
-
margin-bottom:
|
|
620
|
+
font-weight: 700;
|
|
621
|
+
font-size: 20px;
|
|
622
|
+
margin-bottom: 8px;
|
|
623
|
+
letter-spacing: -0.02em;
|
|
624
|
+
line-height: 1.3;
|
|
555
625
|
}
|
|
556
626
|
|
|
557
627
|
.toastify-pro.confirmation .toast-description {
|
|
558
|
-
font-size:
|
|
559
|
-
opacity: 0.
|
|
560
|
-
margin-top:
|
|
628
|
+
font-size: 15px;
|
|
629
|
+
opacity: 0.85;
|
|
630
|
+
margin-top: 8px;
|
|
631
|
+
line-height: 1.5;
|
|
632
|
+
font-weight: 400;
|
|
561
633
|
}
|
|
562
634
|
|
|
563
635
|
/* Fix text visibility for dark/light variants */
|
|
@@ -573,54 +645,80 @@
|
|
|
573
645
|
|
|
574
646
|
.toast-actions {
|
|
575
647
|
display: flex;
|
|
576
|
-
gap:
|
|
577
|
-
margin-top:
|
|
648
|
+
gap: 14px;
|
|
649
|
+
margin-top: 4px;
|
|
578
650
|
}
|
|
579
651
|
|
|
580
652
|
.toast-btn {
|
|
581
653
|
flex: 1;
|
|
582
|
-
padding:
|
|
654
|
+
padding: 14px 20px;
|
|
583
655
|
border: none;
|
|
584
|
-
border-radius:
|
|
656
|
+
border-radius: 12px;
|
|
585
657
|
font-weight: 600;
|
|
586
|
-
font-size:
|
|
658
|
+
font-size: 15px;
|
|
587
659
|
cursor: pointer;
|
|
588
|
-
transition: all 0.
|
|
660
|
+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
589
661
|
backdrop-filter: blur(10px);
|
|
590
|
-
|
|
662
|
+
position: relative;
|
|
663
|
+
overflow: hidden;
|
|
664
|
+
letter-spacing: 0.01em;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
.toast-btn::after {
|
|
668
|
+
content: '';
|
|
669
|
+
position: absolute;
|
|
670
|
+
top: 50%;
|
|
671
|
+
left: 50%;
|
|
672
|
+
width: 0;
|
|
673
|
+
height: 0;
|
|
674
|
+
border-radius: 50%;
|
|
675
|
+
background: rgba(255, 255, 255, 0.3);
|
|
676
|
+
transform: translate(-50%, -50%);
|
|
677
|
+
transition: width 0.6s, height 0.6s;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
.toast-btn:hover::after {
|
|
681
|
+
width: 300px;
|
|
682
|
+
height: 300px;
|
|
591
683
|
}
|
|
592
684
|
|
|
593
685
|
.toast-btn:hover {
|
|
594
|
-
transform: translateY(-
|
|
595
|
-
box-shadow: 0
|
|
686
|
+
transform: translateY(-2px);
|
|
687
|
+
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
|
|
596
688
|
}
|
|
597
689
|
|
|
598
690
|
.toast-btn:active {
|
|
599
691
|
transform: translateY(0);
|
|
692
|
+
transition: all 0.1s;
|
|
600
693
|
}
|
|
601
694
|
|
|
602
695
|
.toast-btn-cancel {
|
|
603
696
|
background: rgba(255, 255, 255, 0.1);
|
|
604
|
-
color: rgba(255, 255, 255, 0.
|
|
605
|
-
border:
|
|
606
|
-
font-weight:
|
|
697
|
+
color: rgba(255, 255, 255, 0.9);
|
|
698
|
+
border: 1.5px solid rgba(255, 255, 255, 0.25);
|
|
699
|
+
font-weight: 600;
|
|
607
700
|
}
|
|
608
701
|
|
|
609
702
|
.toast-btn-cancel:hover {
|
|
610
703
|
background: rgba(255, 255, 255, 0.15);
|
|
611
|
-
color:
|
|
612
|
-
border-color: rgba(255, 255, 255, 0.
|
|
704
|
+
color: white;
|
|
705
|
+
border-color: rgba(255, 255, 255, 0.35);
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
.toast-btn-cancel:disabled {
|
|
709
|
+
opacity: 0.5;
|
|
710
|
+
cursor: not-allowed;
|
|
711
|
+
pointer-events: none;
|
|
613
712
|
}
|
|
614
713
|
|
|
615
714
|
.toast-btn-confirm {
|
|
616
715
|
color: white;
|
|
617
716
|
font-weight: 700;
|
|
618
|
-
border: 2px solid rgba(255, 255, 255, 0.
|
|
619
|
-
box-shadow: 0
|
|
717
|
+
border: 2px solid rgba(255, 255, 255, 0.4);
|
|
718
|
+
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25);
|
|
620
719
|
position: relative;
|
|
621
720
|
overflow: hidden;
|
|
622
|
-
background: linear-gradient(135deg, rgba(15, 23, 42, 0.
|
|
623
|
-
border-color: rgba(148, 163, 184, 0.5);
|
|
721
|
+
background: linear-gradient(135deg, rgba(15, 23, 42, 0.95), rgba(30, 41, 59, 0.95));
|
|
624
722
|
}
|
|
625
723
|
|
|
626
724
|
.toast-btn-confirm::before {
|
|
@@ -630,8 +728,8 @@
|
|
|
630
728
|
left: -100%;
|
|
631
729
|
width: 100%;
|
|
632
730
|
height: 100%;
|
|
633
|
-
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.
|
|
634
|
-
transition: left 0.
|
|
731
|
+
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.25), transparent);
|
|
732
|
+
transition: left 0.6s;
|
|
635
733
|
}
|
|
636
734
|
|
|
637
735
|
.toast-btn-confirm:hover::before {
|
|
@@ -640,13 +738,38 @@
|
|
|
640
738
|
|
|
641
739
|
.toast-btn-confirm:hover {
|
|
642
740
|
background: linear-gradient(135deg, rgba(15, 23, 42, 1), rgba(30, 41, 59, 1));
|
|
643
|
-
border-color: rgba(
|
|
644
|
-
box-shadow: 0
|
|
741
|
+
border-color: rgba(255, 255, 255, 0.5);
|
|
742
|
+
box-shadow: 0 8px 28px rgba(15, 23, 42, 0.5);
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
.toast-btn-confirm.loading {
|
|
746
|
+
opacity: 0.7;
|
|
747
|
+
cursor: not-allowed;
|
|
748
|
+
pointer-events: none;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
.toast-btn-confirm .btn-spinner {
|
|
752
|
+
display: none;
|
|
753
|
+
width: 16px;
|
|
754
|
+
height: 16px;
|
|
755
|
+
border: 2px solid rgba(255, 255, 255, 0.3);
|
|
756
|
+
border-top-color: white;
|
|
757
|
+
border-radius: 50%;
|
|
758
|
+
animation: spin 0.6s linear infinite;
|
|
759
|
+
margin-right: 8px;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
.toast-btn-confirm.loading .btn-spinner {
|
|
763
|
+
display: inline-block;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
.toast-btn-confirm.loading .btn-text {
|
|
767
|
+
opacity: 0.7;
|
|
645
768
|
}
|
|
646
769
|
|
|
647
770
|
.toastify-pro.light .toast-btn-cancel {
|
|
648
771
|
background: rgba(15, 23, 42, 0.08);
|
|
649
|
-
color: rgba(15, 23, 42, 0.
|
|
772
|
+
color: rgba(15, 23, 42, 0.85);
|
|
650
773
|
border-color: rgba(15, 23, 42, 0.2);
|
|
651
774
|
}
|
|
652
775
|
|
|
@@ -658,15 +781,15 @@
|
|
|
658
781
|
|
|
659
782
|
/* Enhanced light theme confirm buttons */
|
|
660
783
|
.toastify-pro.light .toast-btn-confirm {
|
|
661
|
-
border-color: rgba(15, 23, 42, 0.
|
|
662
|
-
background: linear-gradient(135deg,
|
|
663
|
-
color:
|
|
784
|
+
border-color: rgba(15, 23, 42, 0.35);
|
|
785
|
+
background: linear-gradient(135deg, #1e293b 0%, #334155 100%);
|
|
786
|
+
color: white;
|
|
664
787
|
}
|
|
665
788
|
|
|
666
789
|
.toastify-pro.light .toast-btn-confirm:hover {
|
|
667
|
-
background: linear-gradient(135deg,
|
|
668
|
-
border-color: rgba(15, 23, 42, 0.
|
|
669
|
-
box-shadow: 0
|
|
790
|
+
background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
|
|
791
|
+
border-color: rgba(15, 23, 42, 0.5);
|
|
792
|
+
box-shadow: 0 8px 28px rgba(15, 23, 42, 0.3);
|
|
670
793
|
}
|
|
671
794
|
|
|
672
795
|
@media (max-width: 640px) {
|
|
@@ -923,6 +1046,25 @@
|
|
|
923
1046
|
* @param {Function} callback - Callback function (if description provided)
|
|
924
1047
|
*/
|
|
925
1048
|
conf(message, descriptionOrCallback, callback) {
|
|
1049
|
+
// Check if there's already an active confirmation (GLOBAL CHECK)
|
|
1050
|
+
if (globalActiveConfirmation && globalActiveConfirmation.element && globalActiveConfirmation.element.parentNode) {
|
|
1051
|
+
// Trigger shake animation on existing confirmation toast element
|
|
1052
|
+
const existingToast = globalActiveConfirmation.element;
|
|
1053
|
+
existingToast.classList.remove('shake');
|
|
1054
|
+
// Force reflow to restart animation
|
|
1055
|
+
void existingToast.offsetWidth;
|
|
1056
|
+
existingToast.classList.add('shake');
|
|
1057
|
+
|
|
1058
|
+
// Remove shake class after animation completes
|
|
1059
|
+
setTimeout(() => {
|
|
1060
|
+
if (existingToast && existingToast.parentNode) {
|
|
1061
|
+
existingToast.classList.remove('shake');
|
|
1062
|
+
}
|
|
1063
|
+
}, 600);
|
|
1064
|
+
|
|
1065
|
+
return globalActiveConfirmation;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
926
1068
|
// Parse arguments to support multiple usage patterns
|
|
927
1069
|
let description = '';
|
|
928
1070
|
let options = {};
|
|
@@ -966,6 +1108,9 @@
|
|
|
966
1108
|
cancelText: options.cancelText || 'Cancel',
|
|
967
1109
|
theme: options.theme || options.color || 'dark', // Support both theme and color for backward compatibility
|
|
968
1110
|
position: options.position || 'center', // Default to center for confirmations
|
|
1111
|
+
primaryColor: options.primaryColor || null,
|
|
1112
|
+
secondaryColor: options.secondaryColor || null,
|
|
1113
|
+
loading: options.loading || false, // Support external loading state (for React/Vue)
|
|
969
1114
|
...options
|
|
970
1115
|
};
|
|
971
1116
|
|
|
@@ -976,6 +1121,23 @@
|
|
|
976
1121
|
confirmOptions.theme = 'dark'; // Default to dark for all other values
|
|
977
1122
|
}
|
|
978
1123
|
|
|
1124
|
+
// Helper function to determine if a color is light or dark
|
|
1125
|
+
const isLightColor = (color) => {
|
|
1126
|
+
if (!color) return false;
|
|
1127
|
+
const hex = color.replace('#', '');
|
|
1128
|
+
const r = parseInt(hex.substr(0, 2), 16);
|
|
1129
|
+
const g = parseInt(hex.substr(2, 2), 16);
|
|
1130
|
+
const b = parseInt(hex.substr(4, 2), 16);
|
|
1131
|
+
const brightness = ((r * 299) + (g * 587) + (b * 114)) / 1000;
|
|
1132
|
+
return brightness > 155;
|
|
1133
|
+
};
|
|
1134
|
+
|
|
1135
|
+
// Determine text color based on background
|
|
1136
|
+
let textColor = confirmOptions.theme === 'light' ? '#1e293b' : 'white';
|
|
1137
|
+
if (confirmOptions.primaryColor) {
|
|
1138
|
+
textColor = isLightColor(confirmOptions.primaryColor) ? '#1e293b' : 'white';
|
|
1139
|
+
}
|
|
1140
|
+
|
|
979
1141
|
// Validate position for confirmation toast
|
|
980
1142
|
const validPositions = ['top-left', 'top-right', 'bottom-left', 'bottom-right', 'top-center', 'bottom-center', 'center'];
|
|
981
1143
|
if (!validPositions.includes(confirmOptions.position)) {
|
|
@@ -997,26 +1159,108 @@
|
|
|
997
1159
|
}
|
|
998
1160
|
}
|
|
999
1161
|
|
|
1162
|
+
// Create control functions for loading state
|
|
1163
|
+
let confirmBtnElement = null;
|
|
1164
|
+
let cancelBtnElement = null;
|
|
1165
|
+
let closeBtnElement = null;
|
|
1166
|
+
let isLoading = false;
|
|
1167
|
+
let useLoading = false; // Track if user wants loading behavior
|
|
1168
|
+
let toastElement = null; // Reference to toast element
|
|
1169
|
+
|
|
1170
|
+
const setLoading = (loading) => {
|
|
1171
|
+
useLoading = true; // User is manually controlling loading
|
|
1172
|
+
isLoading = loading;
|
|
1173
|
+
if (confirmBtnElement) {
|
|
1174
|
+
if (loading) {
|
|
1175
|
+
confirmBtnElement.classList.add('loading');
|
|
1176
|
+
confirmBtnElement.disabled = true;
|
|
1177
|
+
} else {
|
|
1178
|
+
confirmBtnElement.classList.remove('loading');
|
|
1179
|
+
confirmBtnElement.disabled = false;
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
// Disable/enable cancel and close buttons during loading
|
|
1183
|
+
if (cancelBtnElement) {
|
|
1184
|
+
cancelBtnElement.disabled = loading;
|
|
1185
|
+
cancelBtnElement.style.opacity = loading ? '0.5' : '1';
|
|
1186
|
+
cancelBtnElement.style.cursor = loading ? 'not-allowed' : 'pointer';
|
|
1187
|
+
}
|
|
1188
|
+
if (closeBtnElement) {
|
|
1189
|
+
closeBtnElement.style.opacity = loading ? '0.3' : '0.5';
|
|
1190
|
+
closeBtnElement.style.cursor = loading ? 'not-allowed' : 'pointer';
|
|
1191
|
+
closeBtnElement.style.pointerEvents = loading ? 'none' : 'auto';
|
|
1192
|
+
}
|
|
1193
|
+
};
|
|
1194
|
+
|
|
1195
|
+
const closeConfirmation = () => {
|
|
1196
|
+
if (toastElement && toastElement.parentNode) {
|
|
1197
|
+
globalActiveConfirmation = null;
|
|
1198
|
+
this.removeToast(toastElement);
|
|
1199
|
+
}
|
|
1200
|
+
};
|
|
1201
|
+
|
|
1000
1202
|
// Helper function to handle confirmation result
|
|
1001
|
-
const handleConfirmation = (confirmed) => {
|
|
1203
|
+
const handleConfirmation = async (confirmed) => {
|
|
1002
1204
|
if (confirmed) {
|
|
1003
1205
|
// Call onConfirm if provided
|
|
1004
1206
|
if (options.onConfirm && typeof options.onConfirm === 'function') {
|
|
1005
1207
|
try {
|
|
1006
|
-
options.onConfirm();
|
|
1208
|
+
const result = options.onConfirm({ setLoading, close: closeConfirmation });
|
|
1209
|
+
// Check if it's a promise
|
|
1210
|
+
if (result && typeof result.then === 'function') {
|
|
1211
|
+
// If user didn't manually set loading, auto-set it
|
|
1212
|
+
if (!useLoading) {
|
|
1213
|
+
setLoading(true);
|
|
1214
|
+
}
|
|
1215
|
+
await result;
|
|
1216
|
+
// Auto-close after promise resolves if user didn't manually close
|
|
1217
|
+
if (toastElement && toastElement.parentNode) {
|
|
1218
|
+
setLoading(false);
|
|
1219
|
+
closeConfirmation();
|
|
1220
|
+
}
|
|
1221
|
+
} else {
|
|
1222
|
+
// Synchronous callback - only close if user didn't start loading
|
|
1223
|
+
if (!useLoading) {
|
|
1224
|
+
closeConfirmation();
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1007
1227
|
} catch (error) {
|
|
1008
1228
|
console.error('ToastifyPro: Error in onConfirm callback:', error);
|
|
1229
|
+
setLoading(false);
|
|
1230
|
+
closeConfirmation();
|
|
1009
1231
|
}
|
|
1010
1232
|
}
|
|
1011
1233
|
// Call unified callback if provided
|
|
1012
|
-
if (resultCallback && typeof resultCallback === 'function') {
|
|
1234
|
+
else if (resultCallback && typeof resultCallback === 'function') {
|
|
1013
1235
|
try {
|
|
1014
|
-
resultCallback(true);
|
|
1236
|
+
const result = resultCallback(true, { setLoading, close: closeConfirmation });
|
|
1237
|
+
if (result && typeof result.then === 'function') {
|
|
1238
|
+
if (!useLoading) {
|
|
1239
|
+
setLoading(true);
|
|
1240
|
+
}
|
|
1241
|
+
await result;
|
|
1242
|
+
if (toastElement && toastElement.parentNode) {
|
|
1243
|
+
setLoading(false);
|
|
1244
|
+
closeConfirmation();
|
|
1245
|
+
}
|
|
1246
|
+
} else {
|
|
1247
|
+
if (!useLoading) {
|
|
1248
|
+
closeConfirmation();
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1015
1251
|
} catch (error) {
|
|
1016
1252
|
console.error('ToastifyPro: Error in confirmation callback:', error);
|
|
1253
|
+
setLoading(false);
|
|
1254
|
+
closeConfirmation();
|
|
1017
1255
|
}
|
|
1256
|
+
} else {
|
|
1257
|
+
// No callback - just close
|
|
1258
|
+
closeConfirmation();
|
|
1018
1259
|
}
|
|
1019
1260
|
} else {
|
|
1261
|
+
// Cancel - no loading needed, check if not currently loading
|
|
1262
|
+
if (isLoading) return; // Don't allow cancel while loading
|
|
1263
|
+
|
|
1020
1264
|
// Call onCancel if provided
|
|
1021
1265
|
if (options.onCancel && typeof options.onCancel === 'function') {
|
|
1022
1266
|
try {
|
|
@@ -1033,6 +1277,7 @@
|
|
|
1033
1277
|
console.error('ToastifyPro: Error in confirmation callback:', error);
|
|
1034
1278
|
}
|
|
1035
1279
|
}
|
|
1280
|
+
closeConfirmation();
|
|
1036
1281
|
}
|
|
1037
1282
|
};
|
|
1038
1283
|
|
|
@@ -1040,6 +1285,30 @@
|
|
|
1040
1285
|
// Create confirmation toast element
|
|
1041
1286
|
const toast = document.createElement("div");
|
|
1042
1287
|
toast.className = `toastify-pro confirmation ${confirmOptions.theme}`;
|
|
1288
|
+
|
|
1289
|
+
// Store reference to toast element
|
|
1290
|
+
toastElement = toast;
|
|
1291
|
+
|
|
1292
|
+
// Apply custom colors if provided
|
|
1293
|
+
if (confirmOptions.primaryColor) {
|
|
1294
|
+
const primary = confirmOptions.primaryColor;
|
|
1295
|
+
const secondary = confirmOptions.secondaryColor;
|
|
1296
|
+
|
|
1297
|
+
if (secondary) {
|
|
1298
|
+
// Both colors provided - create gradient
|
|
1299
|
+
toast.style.background = `linear-gradient(135deg, ${primary} 0%, ${secondary} 100%)`;
|
|
1300
|
+
} else {
|
|
1301
|
+
// Only primary color - solid with slight transparency
|
|
1302
|
+
toast.style.background = primary;
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
// Set text color based on background brightness
|
|
1306
|
+
toast.style.color = textColor;
|
|
1307
|
+
|
|
1308
|
+
// Adjust border color to match
|
|
1309
|
+
const borderOpacity = isLightColor(primary) ? '0.2' : '0.15';
|
|
1310
|
+
toast.style.borderColor = `rgba(255, 255, 255, ${borderOpacity})`;
|
|
1311
|
+
}
|
|
1043
1312
|
|
|
1044
1313
|
// Create close button for confirmation
|
|
1045
1314
|
const closeBtn = document.createElement("span");
|
|
@@ -1047,15 +1316,23 @@
|
|
|
1047
1316
|
closeBtn.innerHTML = "×";
|
|
1048
1317
|
closeBtn.setAttribute('aria-label', 'Cancel confirmation');
|
|
1049
1318
|
closeBtn.onclick = () => {
|
|
1050
|
-
|
|
1051
|
-
|
|
1319
|
+
if (!isLoading) {
|
|
1320
|
+
handleConfirmation(false);
|
|
1321
|
+
}
|
|
1052
1322
|
};
|
|
1323
|
+
if (confirmOptions.primaryColor) {
|
|
1324
|
+
closeBtn.style.color = textColor;
|
|
1325
|
+
}
|
|
1326
|
+
closeBtnElement = closeBtn;
|
|
1053
1327
|
toast.appendChild(closeBtn);
|
|
1054
1328
|
|
|
1055
1329
|
// Create icon wrapper
|
|
1056
1330
|
const iconWrapper = document.createElement("div");
|
|
1057
1331
|
iconWrapper.className = "toast-icon";
|
|
1058
1332
|
iconWrapper.innerHTML = this.getIconSVG('info'); // Default to info icon
|
|
1333
|
+
if (confirmOptions.primaryColor) {
|
|
1334
|
+
iconWrapper.style.color = textColor;
|
|
1335
|
+
}
|
|
1059
1336
|
toast.appendChild(iconWrapper);
|
|
1060
1337
|
|
|
1061
1338
|
// Create content wrapper
|
|
@@ -1066,6 +1343,9 @@
|
|
|
1066
1343
|
const messageElement = document.createElement("div");
|
|
1067
1344
|
messageElement.className = "toast-message";
|
|
1068
1345
|
messageElement.textContent = message.substring(0, this.defaultOptions.maxLength);
|
|
1346
|
+
if (confirmOptions.primaryColor) {
|
|
1347
|
+
messageElement.style.color = textColor;
|
|
1348
|
+
}
|
|
1069
1349
|
contentWrapper.appendChild(messageElement);
|
|
1070
1350
|
|
|
1071
1351
|
// Optional description
|
|
@@ -1073,6 +1353,9 @@
|
|
|
1073
1353
|
const descriptionElement = document.createElement("div");
|
|
1074
1354
|
descriptionElement.className = "toast-description";
|
|
1075
1355
|
descriptionElement.textContent = description.substring(0, this.defaultOptions.maxLength * 2);
|
|
1356
|
+
if (confirmOptions.primaryColor) {
|
|
1357
|
+
descriptionElement.style.color = textColor;
|
|
1358
|
+
}
|
|
1076
1359
|
contentWrapper.appendChild(descriptionElement);
|
|
1077
1360
|
}
|
|
1078
1361
|
|
|
@@ -1087,18 +1370,64 @@
|
|
|
1087
1370
|
cancelBtn.className = "toast-btn toast-btn-cancel";
|
|
1088
1371
|
cancelBtn.textContent = confirmOptions.cancelText;
|
|
1089
1372
|
cancelBtn.onclick = () => {
|
|
1090
|
-
|
|
1091
|
-
|
|
1373
|
+
if (!isLoading) {
|
|
1374
|
+
handleConfirmation(false);
|
|
1375
|
+
}
|
|
1092
1376
|
};
|
|
1377
|
+
|
|
1378
|
+
// Store cancel button reference
|
|
1379
|
+
cancelBtnElement = cancelBtn;
|
|
1380
|
+
|
|
1381
|
+
// Style cancel button with custom colors
|
|
1382
|
+
if (confirmOptions.primaryColor) {
|
|
1383
|
+
const isLight = isLightColor(confirmOptions.primaryColor);
|
|
1384
|
+
cancelBtn.style.background = isLight ? 'rgba(15, 23, 42, 0.08)' : 'rgba(255, 255, 255, 0.1)';
|
|
1385
|
+
cancelBtn.style.color = textColor;
|
|
1386
|
+
cancelBtn.style.borderColor = isLight ? 'rgba(15, 23, 42, 0.2)' : 'rgba(255, 255, 255, 0.25)';
|
|
1387
|
+
}
|
|
1093
1388
|
|
|
1094
1389
|
// Confirm button
|
|
1095
1390
|
const confirmBtn = document.createElement("button");
|
|
1096
1391
|
confirmBtn.className = `toast-btn toast-btn-confirm`;
|
|
1097
|
-
|
|
1392
|
+
|
|
1393
|
+
// Create spinner element
|
|
1394
|
+
const spinner = document.createElement("span");
|
|
1395
|
+
spinner.className = "btn-spinner";
|
|
1396
|
+
confirmBtn.appendChild(spinner);
|
|
1397
|
+
|
|
1398
|
+
// Create text wrapper
|
|
1399
|
+
const textWrapper = document.createElement("span");
|
|
1400
|
+
textWrapper.className = "btn-text";
|
|
1401
|
+
textWrapper.textContent = confirmOptions.confirmText;
|
|
1402
|
+
confirmBtn.appendChild(textWrapper);
|
|
1403
|
+
|
|
1098
1404
|
confirmBtn.onclick = () => {
|
|
1099
|
-
|
|
1100
|
-
|
|
1405
|
+
if (!isLoading) {
|
|
1406
|
+
handleConfirmation(true);
|
|
1407
|
+
}
|
|
1101
1408
|
};
|
|
1409
|
+
|
|
1410
|
+
// Store reference for loading state control
|
|
1411
|
+
confirmBtnElement = confirmBtn;
|
|
1412
|
+
|
|
1413
|
+
// Style confirm button with custom colors
|
|
1414
|
+
if (confirmOptions.primaryColor) {
|
|
1415
|
+
const primary = confirmOptions.primaryColor;
|
|
1416
|
+
const secondary = confirmOptions.secondaryColor;
|
|
1417
|
+
const isLight = isLightColor(primary);
|
|
1418
|
+
|
|
1419
|
+
if (secondary) {
|
|
1420
|
+
// Gradient confirm button
|
|
1421
|
+
confirmBtn.style.background = `linear-gradient(135deg, ${primary} 0%, ${secondary} 100%)`;
|
|
1422
|
+
} else {
|
|
1423
|
+
// Solid color confirm button with enhanced styling
|
|
1424
|
+
confirmBtn.style.background = primary;
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1427
|
+
// Determine button text color (always use contrasting color for readability)
|
|
1428
|
+
confirmBtn.style.color = isLight ? '#1e293b' : 'white';
|
|
1429
|
+
confirmBtn.style.borderColor = isLight ? 'rgba(15, 23, 42, 0.3)' : 'rgba(255, 255, 255, 0.4)';
|
|
1430
|
+
}
|
|
1102
1431
|
|
|
1103
1432
|
actionsWrapper.appendChild(cancelBtn);
|
|
1104
1433
|
actionsWrapper.appendChild(confirmBtn);
|
|
@@ -1106,6 +1435,21 @@
|
|
|
1106
1435
|
|
|
1107
1436
|
// Add toast to the specified container (not default container)
|
|
1108
1437
|
confirmContainer.appendChild(toast);
|
|
1438
|
+
|
|
1439
|
+
// Create control object
|
|
1440
|
+
const controlObject = {
|
|
1441
|
+
element: toast,
|
|
1442
|
+
setLoading: setLoading,
|
|
1443
|
+
close: closeConfirmation
|
|
1444
|
+
};
|
|
1445
|
+
|
|
1446
|
+
// Store as global active confirmation (with control object)
|
|
1447
|
+
globalActiveConfirmation = controlObject;
|
|
1448
|
+
|
|
1449
|
+
// Apply initial loading state if provided (for React/Vue)
|
|
1450
|
+
if (confirmOptions.loading) {
|
|
1451
|
+
setLoading(true);
|
|
1452
|
+
}
|
|
1109
1453
|
|
|
1110
1454
|
// Entrance animation
|
|
1111
1455
|
setTimeout(() => {
|
|
@@ -1116,11 +1460,22 @@
|
|
|
1116
1460
|
}
|
|
1117
1461
|
}, 10);
|
|
1118
1462
|
|
|
1119
|
-
|
|
1463
|
+
// Return control object with toast element and control functions
|
|
1464
|
+
return controlObject;
|
|
1120
1465
|
} catch (error) {
|
|
1121
1466
|
console.error('ToastifyPro: Failed to create confirmation toast:', error);
|
|
1122
1467
|
}
|
|
1123
1468
|
}
|
|
1469
|
+
|
|
1470
|
+
/**
|
|
1471
|
+
* Alias for conf() method - shows a confirmation toast
|
|
1472
|
+
* @param {string} message - Main confirmation question
|
|
1473
|
+
* @param {string|Function|Object} descriptionOrCallback - Description text, callback function, or options object
|
|
1474
|
+
* @param {Function} callback - Callback function (if description provided)
|
|
1475
|
+
*/
|
|
1476
|
+
confirm(message, descriptionOrCallback, callback) {
|
|
1477
|
+
return this.conf(message, descriptionOrCallback, callback);
|
|
1478
|
+
}
|
|
1124
1479
|
}
|
|
1125
1480
|
|
|
1126
1481
|
/**
|